/* $OpenXM: OpenXM_contrib2/asir2018/lib/primdec_mod,v 1.2 2021/02/18 05:35:01 noro Exp $ */ extern First_Component,Minipoly_SBA,NDGR$ extern Hom,GBTime$ extern DIVLIST,INTIDEAL,ORIGINAL,ORIGINALDIMENSION,STOP,Trials,REM$ extern T_GRF,T_INT,T_PD,T_MP$ extern BuchbergerMinipoly,PartialDecompByLex,ParallelMinipoly$ extern B_Win,D_Win$ extern COMMONCHECK_SF,CID_SF$ if (!module_definedp("fff")) load("fff"); else $ if (!module_definedp("gr")) load("gr"); else $ module primdec_mod $ /* Empty for now. It will be used in a future. */ endmodule $ /*==============================================*/ /* prime decomposition of ideals over */ /* finite fields */ /* part 1 */ /* radical computation */ /* 28/12/2002 for Basic Small Finite Field */ /* 4/1/2003 for Arbitary Small Finite Field */ /*==============================================*/ /*==============================================*/ /* radical computation of ideals over */ /* finite fields by Matsumoto's algorithm */ /* */ /* The radical of I is computed as the */ /* kernel of a power of Frobenius map. */ /* */ /* radical */ /* Input: a list P of polynomials */ /* Output: a list P1 of polynomials */ /* such that =rad(

) */ /* */ /* frobeniuskernel_main{2} */ /* Input: a list of polynomials P, */ /* a list of variables VSet, */ /* and a list of other variables WSet */ /* Output: a list of polynomials Q */ /* such that Q is the kernel of */ /* single Frobenius map: x--> x^q */ /* where q is the characteristic. */ /* version 2 uses successive kernel */ /* computation suggested by Matsumoto */ /* */ /* coefficientfrobeniuskernel */ /* Input: a list of polynomials P, */ /* Output: a list of polynomials Q */ /* such that Q is the kernel of */ /* single coefficient Frobenius */ /* map: a in GF(q) --> a^q */ /* where q is the characteristic. */ /* */ /* elimination */ /* Input: a list P of polynomials */ /* a list V of variables */ /* Output: a list P1 of polynomials */ /* such that P1={f\in P | */ /* vars(f)\cap V =\emptyset} */ /* */ /* checkequality */ /* Input: a list P of polynomials */ /* a list Q of polynomials */ /* Output: 1 if

= */ /* 0 otherwise */ /* */ /* */ /* */ /*==============================================*/ def radicalideal(P,Choice,VSet) { GBTime=0; Ord=0; /* VSet=vars(P);*/ WSet=makecounterpart(VSet); T000=time()[0]; P1=dp_gr_f_main(P,VSet,Hom,Ord); T001=time()[0]; GBTime +=T001-T000; if ( Choice == 3 ) { P2=frobeniuskernel_main3(P1,VSet,WSet); } else if ( Choice == 2 ) { P2=frobeniuskernel_main2(P1,VSet,WSet); } else if ( Choice == 4 ) { P2=frobeniuskernel_main4(P1,VSet,WSet); } else { P2=frobeniuskernel_main(P1,VSet,WSet); } M=checkequality(P1,P2,VSet); while ( M !=1 ) { P1=P2; P2=frobeniuskernel_main2(P2,VSet,WSet); M=checkequality(P1,P2,VSet); } return P1; } def frobeniuskernel_main(P,VSet,WSet) { NV=length(VSet); NewP=coefficientfrobeniuskernel(P); NW=length(NewP); TempP=NewP; for (K=NW-1;K>=0;K--) { Poly=TempP[K]; for (J=0;J=0;I--) { Poly=PW[I]; for (J=0;J=0;K--) { Poly=PW[K]; for (J=0;J=0;K--) { Poly=TempP[K]; for (J=0;J=0;K--) { Poly=PW[K]; for (J=0;J=0;K--) { Poly=PW[K]; Poly=subst(Poly,WSet[I],VSet[I]); NewP=cons(Poly,NewP); } } return NewP; } def coefficientfrobeniuskernel(P) { if ( setmod_ff()[1] == 0 ) { return P; } NP=length(P); ANS=[]; for (I=0;I=0;I--) { VSet=vars(G[I]); DIFF=setminus(VSet,V); if ( DIFF ==[] ) { ANS=cons(G[I],ANS); } } return ANS; } def setminus(A,B) { NA=length(A); NB=length(B); ANS=[]; for (I=0;I=0;I--) { T=strtov(A+rtostr(I)); ANS=cons(T,ANS); } return ANS; } def checkequality(P,Q,VSet) { QQ=dp_gr_f_main(Q,VSet,Hom,Ord); PP=dp_gr_f_main(P,VSet,Hom,Ord); NP=length(PP); NQ=length(QQ); VarsP=vars(P); VarsQ=vars(Q); if ( NP != NQ || VarsP !=VarsQ ) { return 0; } for (I=0;I Defaultsize ) { Index=I; } Defaultsize= Targetsize; } return Index; } def headtermset(P,V,Ord) { ANS=[]; NP=length(P); for ( I=NP-1;I>=0;I--) { Head=headterm(P[I],V,Ord); ANS=cons(Head,ANS); } return ANS; } def headterm(P,V,Ord) { dp_ord(Ord); Q=dp_ptod(P,V); Headdp=dp_hm(Q); Head=dp_dtop(Headdp,V); return Head; } def findmsi_main(TermsetIndex,MSIsetIndex,Int,N) { ANS=[]; BNS=[]; TempMSIsetIndex=MSIsetIndex; if (Int == 0) { for ( I=0;I */ /* [subprocedure] */ /* o --gr_fctr_sf (mplex2) */ /* o --primedecomposition */ /* Remark: if F = 1, we empoly Early Termination */ /* */ /* */ /* primedecomposition(P,V,Ord,C,F) */ /* Input: a list P of polynomials */ /* a list V of variables */ /* a term order Ord */ /* a level C of recursive call */ /* a flag F on Early Termination */ /* Output: 0 */ /* DVILIST: the set of prime divisors of

^ec */ /* [subprocedure] */ /* o --idealdimension (part2) */ /* o --setminus (part1) */ /* o --zeroprimedecomposition */ /* o --extcont */ /* o --checkadd2 */ /* o --ideal_intersection_sfrat */ /* o --radical_equality */ /* */ /* zeroprimedecomposition(P,V,W) */ /* Input: a list P of polynomials */ /* lists V,W of variables */ /* such that

is 0-dimensional */ /* in K[V] and W is the original set */ /* of variables */ /* Output: the set of prime/primary */ /* divisors of

*/ /* (P is a GB w.r.t. DRL) */ /* [subprocedure] */ /* o --partical_decomp (mplex2) */ /* o --checkgeneric */ /* o --separableclosure */ /* o --zerogenericprimedecomposition */ /* o --zeroseparableprimedecomposition */ /* o --convertdivisor */ /* o --contraction */ /* o --radicalideal (part1) */ /* */ /* extcont(P,V,Ord) */ /* Input: a list P of polynomials */ /* a set V of variables */ /* Output: a polynomial f */ /* such that \sqrt

^c=\sqrt(P:f) */ /* Then \sqrt

=\sqrt(P:f)\cap \sqrt(P+) */ /* */ /* separableclosure([P,MP],V,W) */ /* Input: a pair [P,MP] of a list P of */ /* polynomials and a list MP of */ /* minimal polynomials of variables */ /* list V,W of variables */ /* such that

is 0-dimensional */ /* in K[V] and W is the original set */ /* of variables */ /* Output: [Q,E], a list Q of polynomials */ /* an exponent vector E */ /* such that is the separable */ /* closure of

*/ /* [subprocedure] */ /* o --makecounterpart(part1) */ /* o --elimination(part1) */ /* o --checkseparable */ /* */ /* zeroseparableprimedecomposition(P,V,W) */ /* Input: a list P of polynomials */ /* lists V,W of variables */ /* such that

is 0-dimensional */ /* and all minimal polynomial */ /* are irreducible (i.e.

is an */ /* intermediate ideal in the paper */ /* or the output of partial_decomp) */ /* in K[V] and W is the original set */ /* of variables */ /* Output: the set of prime/primary */ /* divisors of

*/ /* [subprocedure] */ /* o --findgeneric */ /* o --elimination(part1) */ /* */ /* zerogenericprimedecomposition([P,MP],M,V,W) */ /* Input: a pair [P,MP] of a list P of */ /* polynomials and a list MP of */ /* minimal polynomials of variables */ /* such that

is 0-dimensional */ /* and M is a minimal poly of a */ /* variable in generic position */ /* in K[V] and W is the original */ /* set of variables */ /* Output: the set of prime/primary */ /* divisors of

*/ /* [subprocedure] */ /* */ /* convertdivisor(P,V,W,E) */ /* Input: a list P of polynomials */ /* list V,W of variables */ /* such that

is a primary/prime */ /* 0-dimensional ideal in K[V] and */ /* W is the original set */ /* of variables */ /* the exponent vector E */ /* Output: the corresponding prime ideal */ /* in K[W] */ /* [subprocedure] */ /* o --elimination(part1) */ /* */ /* contraction(P,V,W) */ /* Input: a list P of polynomials */ /* list V,W of variables */ /* such that

is a primary/prime */ /* 0-dimensional ideal in K[V] and */ /* W is the original set */ /* of variables */ /* Output: the contraction

^c in K[W] */ /* */ /* findgeneric(P,V) */ /* Input: a list P of polynomials */ /* a list V of variables */ /* such that

is a separable */ /* 0-dimensional ideal in K[V] */ /* Output: [F,Min,X], a polynomial F in */ /* generic position, its minimal */ /* polynomial Min in a new variable */ /* X */ /* [subprocedure] */ /* o --lineardimension */ /* o --makemagic */ /* o --minipoly_sf (mplex2) */ /* */ /*======================================================*/ def primedec_mod(P,VSet,Ord,Mod,Strategy) { First_Component = getopt(first); if ( type(First_Component) == -1 ) First_Component = 0; Minipoly_SBA = getopt(sba); if ( type(Minipoly_SBA) == -1 ) Minipoly_SBA = 0; NDGR = getopt(ndgr); if ( type(NDGR) == -1 ) NDGR = 0; for ( Q = Mod, E = 1; Q < 2^14; Q *= Mod, E++ ); Q /= Mod; E--; if ( !(E%2) ) { Q /= Mod; E--; } setmod_ff(Mod,E); Pq = map(simp_ff,P); primedec_sf(Pq,VSet,Ord,Strategy); R = convsf(DIVLIST,VSet,0,1); return R; } def primedec_sf(P,VSet,Ord,Strategy) { /* DIVLIST = the set of all computed candidates for iredundant divisors */ /* INTIDEAL = the intersection of all computed candidates */ /* ORIGINAL = a Groebner basis of the input ideal

w.r.t. Ord */ /* ORIGINALDIMENSION = the dimension of the input ideal

*/ /* STOP = the flag on termination */ /* REM = the list of remaining ideals */ T0 = time(); T_GRF=0; T_INT=0; T_PD=0; T_MP=0; DIVLIST=[]; INTIDEAL=[]; STOP=0; B_Win=0; D_Win=0; ORIGINAL=dp_gr_f_main(P,VSet,Hom,Ord); Dimeset=idealdimension(ORIGINAL,VSet,Ord); ORIGINALDIMENSION=Dimeset[0]; /* REM0=newvect(ORIGINALDIMENSION+1);*/ REM=newvect(ORIGINALDIMENSION+1); for (I=0;I TESTDIM ) { continue; } if ( setminus(TESTLIST,ADD) == [] ) { return 1; } if ( inclusion_test(TESTLIST,ADD,VSet,Ord) == 1 ) { return 1; } } return 0; } def checkadd3(ADD,TESTADDLIST,VSet) { /* This function will be used for eliminating redundant divisors */ NTESTADDLIST=length(TESTADDLIST); for (I=0;I w.r.t. Ord */ /* ORIGINALDIMENSION = the dimension of the input ideal

*/ RP=P; GP=dp_gr_f_main(RP,VSet,Hom,Ord); /* First we compute the MSI and the dimension of the */ /* ideal

in K[Vset], where K is the ground field. */ Dimeset=idealdimension(GP,VSet,Ord); Dimension=Dimeset[0]; MSI=Dimeset[1]; if ( dp_gr_print() ) { print("The dimension of the ideal is ",2); print(Dimension,2); print("."); } TargetVSet=setminus(VSet,MSI); NewGP=dp_gr_f_main(GP,TargetVSet,Hom,Ord); if ( vars(NewGP) == [] ) { return []; } /* Then the ideal is 0-dimension in K[TargetVSet]. */ if ( dp_gr_print() ) { print("We enter Zero-dimension Prime Decomposition. ",2); } QP=zeroprimedecomposition(NewGP,TargetVSet,VSet); ANS=[]; NQP=length(QP); if ( dp_gr_print() ) { print("The number of the newly found component is ",2); print(NQP,2);print(". ",2); } for (I=0;I by recursive call. */ if ( Strategy == 1 ) { CHECK=radical_equality(INTIDEAL,ORIGINAL,VSet,Ord); if (CHECK==1) { if ( dp_gr_print() ) { print("We already obtain all divisor. "); } STOP = 1; return 0; } } if ( Dimension == 0 ) { return 0; } Ord1 = [[0,length(TargetVSet)],[0,length(MSI)]]; GP1 = dp_gr_f_main(GP,append(TargetVSet,MSI),Hom,Ord1); ExtpolyFactor=extcont_factor(GP1,TargetVSet,0); COUNTER=COUNTER+1; for ( Tmp = ExtpolyFactor; Tmp != []; Tmp = cdr(Tmp) ) { AddPoly=car(Tmp); NewGP=cons(AddPoly,GP); GP1 = dp_gr_f_main(cons(AddPoly,GP),VSet,Hom,Ord); if ( Strategy == 1 ) { CHECKADD=radical_equality(INTIDEAL,NewGP,VSet,Ord); if ( CHECKADD != 0 ) { if ( dp_gr_print() ) { print("Avoid unnecessary computation. ",2); } continue; } } DimI=idealdimension(GP1,VSet,Ord)[0]; if ( REM[ORIGINALDIMENSION-DimI] !=[] ) { REM[ORIGINALDIMENSION-DimI]=cons(GP1,REM[ORIGINALDIMENSION-DimI]); } else { REM[ORIGINALDIMENSION-DimI]=[GP1]; } /* primedecomposition(GP1,VSet,Ord,COUNTER,Strategy); if ( STOP == 1) { return 0; }*/ } return 0; } /* returns 1 if Poly is a subset of Id(GB) */ /* we assume GB is a gb wrt (V,Ord) */ def inclusion_test(Poly,GB,V,Ord) { Len = length(GB); PS = newvect(Len); dp_ord(Ord); for ( J = 0, T = GB; T != []; T = cdr(T), J++ ) PS[J] = dp_ptod(car(T),V); for ( J = Len-1, Ind = []; J >= 0; J-- ) Ind = cons(J,Ind); for ( T = Poly; T != []; T = cdr(T) ) if ( nf_sfrat(Ind,dp_ptod(car(T),V),1,PS)[0] ) return 0; return 1; } def zeroprimedecomposition(P,TargetVSet,VSet) { /* We compute prime decomposition for an ideal

*/ /* such that

is 0-dimensional in K[TargetVSet]. */ PD=partial_decomp(P,TargetVSet); /* each ideal in PD is an intermediate ideal, */ /* i.e., all minimal polynomials are irreducible. */ /* Thus, each ideal is very likely a prime ideal. */ /* PD=[[P,MP],...], where P is a GB w.r.t. DRL and */ /* MP is the set of all minimal polynomials. */ NPD=length(PD); ANS=[]; for (I=0;I by using minimal polynomails.*/ /* separableclosure outputs */ /* [a GB Q of separable closure, the exponent vector]. */ /* If

is already separable, then the exponent vector is 0. */ Sep=separableclosure(COMP,TargetVSet,VSet); /* Then, we compute prime divisors of the separable closure by using */ /* generic position. */ /* If Sep[1]=0, COMP[0] is already separable ideal, and hence, */ /* we do not apply radicalideal to its divisors. */ if ( Sep[1] != 0 ) { if ( dp_gr_print() ) { print("The ideal is inseparable. ",2); } CHECK2=checkgeneric2(Sep[2]); } else { if ( dp_gr_print() ) { print("The ideal is already separable. ",2); } } if ( Sep[1] !=0 && CHECK2 == 1 ) { if ( dp_gr_print() ) { print("The separable closure is of generic type. ",2); print("So, the intermediate ideal is prime or primary. ",2); } PDiv=convertdivisor(Sep[0],TargetVSet,VSet,Sep[1]); if ( TargetVSet != VSet ) { PDiv=contraction(PDiv,TargetVSet,VSet)[0]; } Divisor=radicalideal(PDiv,2,VSet); ZDecomp=[Divisor]; } else { #if 0 ZSDecomp=zeroseparableprimedecomposition(Sep[0],TargetVSet,VSet); #else ZSDecomp=zerosepdec(Sep[0],TargetVSet,VSet,Ord); #endif /* We convert a prime separable ideal in K[TargetVSet] to its */ /* corresponding prime ideal in K[VSet]. */ NComp=length(ZSDecomp); ZDecomp=[]; for (J=0;J in K[TargetVSet] by using */ /* generic position. */ ANS=[]; Ord=0; NVSet=length(TargetVSet); /* The P is already a GB w.r.t. DRL. So, the following */ /* must be replaced with NewP=P. */ /* NewGP=dp_gr_f_main(P,TargetVSet,Hom,Ord); */ NewGP = P; /* We search a polynomial f in generic position. */ /* Generic=[f, minimal polynomial of f in newt, newt], */ /* where newt (X) is a newly introduced variable. */ if ( dp_gr_print() ) { print("We search for a linear sum of variables in generic position. ",2); } Generic=findgeneric(NewGP,TargetVSet,VSet); X=Generic[2]; /* newly introduced variable */ Factors=sffctr(Generic[1]); NFactors=length(Factors); /* irreducible case */ if ( NFactors == 2 && Factors[1][1] == 1 ) return [NewGP]; #if 0 for (J=1;J= 0; I-- ) Ind = cons(I,Ind); Ind = reverse(Ind); YSet = setminus(VSet,TargetVSet); NYSet = length(YSet); ElimVSet = append(TargetVSet,YSet); ElimOrd = [[Ord,NVSet],[0,NYSet]]; for ( J = 1; J < NFactors; J++ ) { dp_ord([[0,1],[Ord,NVSet]]); Factor = dp_dtop(nf_sfrat(Ind,dp_ptod(Factors[J][0],XVSet),1,PS)[0],XVSet); #if 0 Q = dp_gr_f_main(cons(Factor,NewGP),ElimVSet,Hom,ElimOrd); #else if ( NDGR ) { Q0 = nd_gr(cons(Factor,NewGP),ElimVSet,-1,0); Q = nd_gr(Q0,ElimVSet,-1,ElimOrd); Q = nd_gr(Q,TargetVSet,-1,Ord); dp_ord(0); } else { Q0 = dp_gr_f_main(cons(Factor,NewGP),ElimVSet,Hom,0); Q = dp_gr_f_main(Q0,ElimVSet,Hom,ElimOrd); Q = dp_gr_f_main(Q,TargetVSet,Hom,Ord); } #endif ANS = cons(Q,ANS); } #endif return ANS; } /* partial decomposition by sums of variables -> zeroseparableprimedecomposition */ #if 0 def zerosepdec(P,W,V,Ord) { /* P is GB wrt (W,Ord) */ dp_ord(Ord); DIM = length(dp_mbase(map(dp_ptod,P,W))); /* preprocessing */ N = length(W); C = newvect(N); C[0] = 1; Vt = ttttt; do { for ( I = 0, LF = 0; I < N; I++ ) if ( C[I] ) LF += W[I]; LF = simp_ff(LF); MP = minipoly_sf(P,W,Ord,LF,Vt); Factors = map(first,cdr(sffctr(MP))); if ( deg(MP,Vt) == DIM ) { if ( length(Factors) == 1 ) return [P]; else return zerosepdec_main(P,W,V,Ord,map(subst,Factors,Vt,LF)); } else if ( length(Factors) > 1 ) { R = zerosepdec_main(P,W,V,Ord,map(subst,Factors,Vt,LF)); S = []; for ( TR = R; TR != []; TR = cdr(TR) ) S = append(zerosepdec(car(TR),W,V,Ord),S); return S; } } while ( !nextchoice(C) ); /* we could not find any useful combination */ R = zeroseparableprimedecomposition(P,W,V); return R; } #else /* we only search for useful poly among v[i]+v[j] */ def zerosepdec(P,W,V,Ord) { /* P is GB wrt (W,Ord) */ dp_ord(Ord); DIM = length(dp_mbase(map(dp_ptod,P,W))); /* preprocessing */ N = length(W); C = newvect(N); C[0] = 1; Vt = ttttt; for ( I1 = 0; I1 < N; I1++ ) for ( I2 = I1+1; I2 < N; I2++ ) { LF = simp_ff(W[I1]+W[I2]); MP = minipoly_sf(P,W,Ord,LF,Vt); Factors = map(first,cdr(sffctr(MP))); if ( deg(MP,Vt) == DIM ) { if ( length(Factors) == 1 ) return [P]; else return zerosepdec_main(P,W,V,Ord,map(subst,Factors,Vt,LF)); } else if ( length(Factors) > 1 ) { R = zerosepdec_main(P,W,V,Ord,map(subst,Factors,Vt,LF)); S = []; for ( TR = R; TR != []; TR = cdr(TR) ) S = append(zerosepdec(car(TR),W,V,Ord),S); return S; } } /* we could not find any useful combination */ R = zeroseparableprimedecomposition(P,W,V); return R; } #endif def zerosepdec_main(P,W,V,Ord,Factors) { dp_ord(Ord); N = length(P); NFactors = length(Factors); PS = newvect(length(P),map(dp_ptod,P,W)); for ( I = length(P)-1, Ind = [];I >= 0; I-- ) Ind = cons(I,Ind); Y= setminus(V,W); NW = length(W); NY = length(Y); ElimV = append(W,Y); ElimOrd = [[Ord,NW],[0,NY]]; ANS = []; for ( J = 0; J < NFactors; J++ ) { Factor = dp_dtop(nf_sfrat(Ind,dp_ptod(Factors[J],W),1,PS)[0],W); if ( NDGR ) { Q = nd_gr(cons(Factor,P),ElimV,-1,ElimOrd); Q = nd_gr(Q,W,-1,Ord); dp_ord(0); } else { Q = dp_gr_f_main(cons(Factor,P),ElimV,Hom,ElimOrd); Q = dp_gr_f_main(Q,W,Hom,Ord); } ANS = cons(Q,ANS); if ( First_Component ) break; } return ANS; } def nextchoice(C) { N = size(C)[0]; for ( I = N-1, Carry = 1; I >= 0; I-- ) { if ( C[I] ) { C[I] = !Carry; Carry = !C[I]; } else { C[I] = Carry; Carry = 0; } } return Carry; } def separableclosure(CP,TargetVSet,VSet) { /* We compute a separable ideal from

by */ /* computing inverse Frobenius map. */ Ord=0; NVSet=length(TargetVSet); IndexVector=newvect(NVSet); /* First we check if

is already separable. */ /* CHECK == 1 if

is already separable, */ /* Otherwise, CHECK is the list of pairs of */ /* the separable closure sc(m) of the minimal polynomial*/ /* m and the exponent e, i.e. m=sc(m)(t^(q^e)). */ CHECK=checkseparable(CP,TargetVSet,VSet); if ( CHECK == 1 ) { if ( dp_gr_print() ) { print("This is already a separable ideal.", 2); } return [CP[0],0]; } if ( dp_gr_print() ) { print("This is not a separable ideal, so we make its separable closure.", 2); } WSet=makecounterpart(TargetVSet); Char=characteristic_ff(); NewP=CP[0]; EXPVECTOR=newvect(NVSet); CHECKEXPVECTOR=newvect(NVSet); for (I=0;I=0;I--) { Poly=Q[I]; for (J=0;J from

by */ /* computing Frobenius map. */ if (ExVector == 0 ) { return P; } NVSet=length(TargetVSet); WSet=makecounterpart(TargetVSet); Char=characteristic_ff(); Ord=0; NewP=P; for (I=0;I=0;I--) { Poly=Q[I]; for (J=0;J}=\sqrt{

+}\cap \sqrt{(

)^{ec}} */ /* by B.W. Proposition 8.96. */ /* Remark: The square free part of f is also OK. */ dp_ord(Ord); HC = map(dp_hc,map(dp_ptod,P,V)); LCM = car(HC); for ( T = cdr(HC); T != []; T = cdr(T) ) LCM = lcm_sfrat(LCM,car(T)); return LCM; } def first(A) { return A[0]; } def set_union(A,B) { for ( T = A; T != []; T = cdr(T) ) B = insert_element(car(T),B); return B; } def insert_element(E,A) { for ( T = A; T != []; T = cdr(T) ) if ( E == car(T) ) break; if ( T == [] ) return cons(E,A); else return A; } def extcont_factor(P,V,Ord) { /* We assume P is a Groebner Basis w.r.t. Ord. */ /* We compute a polynomial f such that */ /* \sqrt{

}=\sqrt{

+}\cap \sqrt{(

)^{ec}} */ /* by B.W. Proposition 8.96. */ /* Remark: The square free part of f is also OK. */ dp_ord(Ord); HC = map(dp_hc,map(dp_ptod,P,V)); F = []; for ( T = HC; T != []; T = cdr(T) ) { F1 = map(first,cdr(sffctr(car(T)))); F = set_union(F1,F); } return F; } def contraction(P,V,W) { /* We assume P is a Groebner Basis w.r.t. Ord. */ /* We compute the contraction

^{c} by */ /*

^c=(:f^\infty) */ /* by B.W. Proposition 8.91. */ /* This procedure is called by zeroprimedecomposition. */ /* So, P is supposed to be a GB w.r.t. DRL. */ Ord0 = dp_ord(); Ord=0; YSet=setminus(W,V); Ord1 = [[Ord,length(V)],[0,length(YSet)]]; W1 = append(V,YSet); GP1 = dp_gr_f_main(P,W1,Hom,Ord1); Factor = extcont_factor(GP1,V,Ord); for ( F = 1, T = Factor; T != []; T = cdr(T) ) F *= car(T); Vt = newt; G = dp_gr_f_main(cons(1-Vt*F,P),cons(Vt,W),0,[[0,1],[Ord,length(W)]]); R = []; for ( T = G; T != []; T = cdr(T) ) if ( !member(Vt,vars(car(T))) ) R = cons(car(T),R); dp_ord(Ord0); return [R,F]; } def checkgeneric2(LIST) { NList=size(LIST)[0]; FLAG=0; for (I=0;I 1 ) { FLAG=FLAG+1; } } if (FLAG < 2 ) { return 1; } return 0; } #if 0 def checkseparablepoly(P,V) { TestP=P; CHECK=diff(TestP,V); Count=0; while ( CHECK !=0 ) { if ( deg(TestP,V) != 0 ) { break; } TestP=pdivide(TestP); CHECK=diff(TestP,V); Count=Count+1; } return [TestP,Count]; } def pdivide(F,V) { Char=characteristic_ff(); TestP=P; Deg=ideg(TestP,V); DegP=idiv(Deg,Char); if ( irem(Deg,Char) != 0 ) { error; } ANS=0; for (I=O;I= P ) error("invalid coef"); } def mapsf_first(D) { return [ptosfp(D[0]),D[1]]; } def partial_decomp(B,V) { T0 = time(); if ( ParallelMinipoly ) { map(ox_cmo_rpc,ParallelMinipoly,"setmod_ff",characteristic_ff(),extdeg_ff()); map(ox_pop_cmo,ParallelMinipoly); } B = map(simp_ff,B); B = dp_gr_f_main(B,V,0,0); R = partial_decomp0(B,V,length(V)-1); if ( PartialDecompByLex ) { R0 = []; for ( TR = R; TR != []; TR = cdr(TR) ) { T = car(TR); S = dp_gr_f_main(T[0],V,0,0); R0 = cons([S,T[1]],R0); } R = reverse(R0); } T_PD += time()[3]-T0[3]; return R; } def setintersection(A,B) { for ( L = []; A != []; A = cdr(A) ) if ( member(car(A),B) ) L = cons(car(A),L); return L; } /* returns [[Plist,Mlist],...] */ def partial_decomp0(B,V,I) { N = length(V); if ( I < 0 ) return [[B,[]]]; Ord = PartialDecompByLex ? [[0,I],[2,N-I]] : 0; #if 0 if ( setminus(vars(B),V) == [] ) B = fglm_sf_0dim(B,V,Ord0,Ord); else #endif B = dp_gr_f_main(B,V,0,Ord); if ( type(B[0]) == 1 ) return []; if ( !zero_dim(B,V,Ord) ) error("non zero-dimensional ideal"); /* XXX */ Vt = ttttt; VI = V[I]; if ( PartialDecompByLex ) { for ( J = 0, W = V; J < I; J++ ) W = cdr(W); VW = setminus(V,W); for ( Bw = [], T = B; T != []; T = cdr(T) ) if ( setintersection(vars(car(T)),VW) == [] ) Bw = cons(car(T),Bw); MI = minipoly_sf(Bw,W,2,VI,Vt); } else MI = minipoly_sf(B,V,0,VI,Vt); MIF = sffctr(MI); /* if MI is irreducible, then process the next variable */ if ( length(MIF) == 2 && MIF[1][1] == 1 ) { L = partial_decomp0(B,V,I-1); R = []; for ( S = L; S != []; S = cdr(S) ) { L = car(S); R = cons([L[0],cons(subst(MI,Vt,VI),L[1])],R); } return R; } /* for nf computation */ Ord1 = PartialDecompByLex ? 2 : [[0,1],[0,N]]; Len = length(B); PS = newvect(Len+1); dp_ord(Ord1); XV = cons(Vt,V); for ( J = 0, T = cons(Vt-VI,B); T != []; T = cdr(T), J++ ) PS[J] = dp_ptod(car(T),XV); for ( J = 0, GI = []; J <= Len; J++ ) GI = cons(J,GI); if ( PartialDecompByLex ) GI = reverse(GI); R = []; for ( T = MIF; T != []; T = cdr(T) ) { Mt = car(car(T)); if ( type(Mt) == 1 ) continue; dp_ord(Ord1); NfMt = dp_dtop(nf_sfrat(GI,dp_ptod(Mt,XV),1,PS)[0],XV); if ( NfMt ) B1 = dp_gr_f_main(cons(NfMt,B),V,0,Ord); else B1 = B; Rt = partial_decomp0(B1,V,I-1); for ( S = Rt; S != []; S = cdr(S) ) { L = car(S); R = cons([L[0],cons(subst(Mt,Vt,VI),L[1])],R); } } return R; } /* G is a gb wrt (V,O) */ def minipoly_sf(G,V,O,F,V0) { T0 = time(); Vc = cons(V0,setminus(vars(G),V)); if ( ParallelMinipoly ) { Proc0 = ParallelMinipoly[0]; Proc1 = ParallelMinipoly[1]; if ( length(Vc) == 1 ) { ox_rpc(Proc0,"minipoly_sf_by_buchberger",G,V,O,F,V0,1); ox_rpc(Proc1,"minipoly_sf_0dim",G,V,O,F,V0,1); map(ox_get,ParallelMinipoly); /* 258=SM_popSerializedLocalObject */ map(ox_push_cmd,ParallelMinipoly,258); F = ox_select(ParallelMinipoly); MP = ox_get(F[0]); if ( F[0] == Proc0 ) { if ( length(F) == 1 ) B_Win++; else ox_get(Proc1); } else { if ( length(F) == 1 ) D_Win++; else ox_get(Proc0); } ox_reset(Proc0); ox_reset(Proc1); } else if ( length(Vc) == 2 ) { ox_rpc(Proc0,"minipoly_sf_by_buchberger",G,V,O,F,V0,1); ox_rpc(Proc1,"minipoly_sfrat",G,V,O,F,V0,1); map(ox_get,ParallelMinipoly); /* 258=SM_popSerializedLocalObject */ map(ox_push_cmd,ParallelMinipoly,258); F = ox_select(ParallelMinipoly); MP = ox_get(F[0]); if ( F[0] == Proc0 ) { if ( length(F) == 1 ) B_Win++; else ox_get(Proc1); } else { if ( length(F) == 1 ) D_Win++; else ox_get(Proc0); } ox_reset(Proc0); ox_reset(Proc1); } else MP = minipoly_sf_by_buchberger(G,V,O,F,V0,0); } else if ( BuchbergerMinipoly ) MP = minipoly_sf_by_buchberger(G,V,O,F,V0,0); else { if ( length(Vc) == 1 ) MP = minipoly_sf_0dim(G,V,O,F,V0,0); else if ( length(Vc) == 2 ) MP = minipoly_sfrat(G,V,O,F,V0,0); else MP = minipoly_sf_by_buchberger(G,V,O,F,V0,0); } T_MP += time()[3]-T0[3]; return MP; } def minipoly_sf_by_buchberger(G,V,O,F,V0,Server) { if ( Server ) ox_sync(0); Vc = cons(V0,setminus(vars(G),V)); Gf = cons(simp_ff(V0-F),G); Vf = append(V,Vc); Gelim = dp_gr_f_main(Gf,Vf,1,[[0,length(V)],[0,length(Vc)]]); for ( Gc = [], T = Gelim; T != []; T = cdr(T) ) { Vt = setminus(vars(car(T)),Vc); if ( Vt == [] ) Gc = cons(car(T),Gc); } Gt = dp_gr_f_main(Gc,Vc,1,[[0,1],[0,length(Vc)-1]]); Pmin = car(Gt); Dmin = deg(Pmin,V0); for ( T = cdr(Gt); T != []; T = cdr(T) ) { Dt = deg(car(T),V0); if ( Dt < Dmin ) { Pmin = car(T); Dmin = Dt; } } Cont = sfcont(Pmin,V0); return sdiv(Pmin,Cont); } def minipoly_sf_0dim(G,V,O,F,V0,Server) { if ( Server ) ox_sync(0); if ( Minipoly_SBA ) { G1 = cons(simp_ff(V0-F),G); V1 = append(V,[V0]); G2 = nd_sba(G1,V1,-1,[[0,length(V)],[0,1]]|sba_modord=[[],0]); dp_ord(0); for ( T = G2; T != []; T = cdr(T) ) if ( vars(car(T)) == [V0] ) break; if ( T == [] ) error("minipoly does not exit"); return car(T); } N = length(V); Len = length(G); dp_ord(O); PS = newvect(Len); for ( I = 0, T = G; T != []; T = cdr(T), I++ ) PS[I] = dp_ptod(car(T),V); for ( I = Len-1, HL = []; I >= 0; I-- ) HL = cons(dp_ht(PS[I]),HL); for ( I = Len - 1, GI = []; I >= 0; I-- ) GI = cons(I,GI); MB = dp_mbase(HL); DIM = length(MB); UT = newvect(DIM); U = dp_ptod(simp_ff(F),V); U = dp_nf_f(GI,U,PS,1); for ( I = 0; I < DIM; I++ ) UT[I] = [MB[I],dp_nf_f(GI,U*MB[I],PS,1)]; T = dp_ptod(simp_ff(1),[V0]); TT = dp_ptod(simp_ff(1),V); G = H = [[TT,T]]; for ( I = 1; ; I++ ) { if ( dp_gr_print() ) print(".",2); T = dp_ptod(simp_ff(V0^I),[V0]); TT = dp_nf_tab_f(H[0][0],UT); H = cons([TT,T],H); L = dp_lnf_f([TT,T],G); if ( !L[0] ) { if ( dp_gr_print() ) print(""); return dp_dtop(L[1],[V0]); /* XXX */ } else G = insert(G,L); } } #if 1 def minipoly_sf_rat(G,V,F,V0) { Vc = setminus(vars(G),V); Gf = cons(V0-F,G); Vf = append(V,[V0]); G3 = dp_gr_f_main(map(simp_ff,Gf),Vf,0,3); for ( T = G3; T != []; T = cdr(T) ) { Vt = setminus(vars(car(T)),Vc); if ( Vt == [V0] ) return car(T); } } def minipoly_mod(G,V,Mod,F,V0) { Vc = setminus(vars(G),V); Gf = cons(V0-F,G); Vf = append(V,[V0]); G3 = dp_gr_mod_main(Gf,Vf,1,Mod,3); for ( T = G3; T != []; T = cdr(T) ) { Vt = setminus(vars(car(T)),Vc); if ( Vt == [V0] ) return car(T); } } #endif /* find N/D s.t. F = N/D mod V^(2M), deg(N),deg(D)= DMP ) { DMP = D; for ( TL = [], MPT = 0, J = 0; J <= D; J++ ) { TL = cons(V0^J,TL); MPT += car(TL); } NF = gennf_sfrat(G1,TL,V1,O1,V0,1)[0]; R = tolex_sfrat_main(V1,O1,NF,[MPT],Vc,Eval,MB); if ( R ) return sdiv(R[0],sfcont(R[0],V0)); } } next_eval_sfrat(Eval); } } def next_eval_sfrat(Eval) { N = size(Eval)[0]; for ( I = N-1; I >= 0; I-- ) if ( Eval[I] ) break; if ( I < 0 ) Eval[N-1] = 1; else if ( I == 0 ) { T = Eval[0]; Eval[0] = 0; Eval[N-1] = T+1; } else { Eval[I-1]++; T = Eval[I]; for ( J = I; J < N-1; J++ ) Eval[J] = 0; Eval[N-1] = T-1; } } def eval_sfrat(F,V,Eval) { for ( I = 0; V != []; V = cdr(V), I++ ) F = subst(F,car(V),ptosfp(Eval[I])); return F; } def valid_modulus_sfrat(HL,Vc,Eval) { for ( T = HL; T != []; T = cdr(T) ) { C = car(T); for ( S = Vc, I = 0; S != []; S = cdr(S), I++ ) C = subst(C,car(S),ptosfp(Eval[I])); if ( !C ) break; } return T == [] ? 1 : 0; } def gennf_sfrat(G,TL,V,O,V0,FLAG) { N = length(V); Len = length(G); dp_ord(O); PS = newvect(Len); for ( I = 0, T = G, HL = []; T != []; T = cdr(T), I++ ) { PS[I] = dp_ptod(car(T),V); HL = cons(dp_ht(PS[I]),HL); } for ( I = 0, DTL = []; TL != []; TL = cdr(TL) ) DTL = cons(dp_ptod(car(TL),V),DTL); for ( I = Len - 1, GI = []; I >= 0; I-- ) GI = cons(I,GI); T = car(DTL); DTL = cdr(DTL); H = [nf_sfrat(GI,T,T,PS)]; USE_TAB = (FLAG != 0); if ( USE_TAB ) { T0 = time()[0]; MB = dp_mbase(HL); DIM = length(MB); U = dp_ptod(V0,V); UTAB = newvect(DIM); for ( I = 0; I < DIM; I++ ) { UTAB[I] = [MB[I],remove_cont_sfrat(nf_sfrat(GI,U*MB[I],1,PS))]; if ( dp_gr_print() ) print(".",2); } if ( dp_gr_print() ) print(""); TTAB = time()[0]-T0; } T0 = time()[0]; for ( LCM = 1; DTL != []; ) { if ( dp_gr_print() ) print(".",2); T = car(DTL); DTL = cdr(DTL); if ( L = search_redble(T,H) ) { DD = dp_subd(T,L[1]); if ( USE_TAB && (DD == U) ) { NF = nf_tab_sfrat(L[0],UTAB); NF = [NF[0],dp_hc(L[1])*NF[1]*T]; } else NF = nf_sfrat(GI,L[0]*dp_subd(T,L[1]),dp_hc(L[1])*T,PS); } else NF = nf_sfrat(GI,T,T,PS); NF = remove_cont_sfrat(NF); H = cons(NF,H); LCM = lcm_sfrat(LCM,dp_hc(NF[1])); } TNF = time()[0]-T0; if ( dp_gr_print() ) print("gennf(TAB="+rtostr(TTAB)+" NF="+rtostr(TNF)+")"); return [[map(adj_dn_sfrat,H,LCM),LCM],PS,GI]; } def lcm_sfrat(A,B) { G = sfgcd(A,B); return sdiv(A,G)*B; } #define REDCONT(f) ((f)/sfcont(f)) def remove_cont_sfrat(L) { if ( type(L[1]) <= 2 ) { T = remove_cont_sfrat([L[0],L[1]*<<0>>]); return [T[0],dp_hc(T[1])]; } else if ( !L[0] ) return [0,REDCONT(L[1])]; else if ( !L[1] ) return [REDCONT(L[0]),0]; else { A0 = REDCONT(L[0]); A1 = REDCONT(L[1]); C0 = sdiv(dp_hc(L[0]),dp_hc(A0)); C1 = sdiv(dp_hc(L[1]),dp_hc(A1)); GCD = sfgcd(C0,C1); M0 = sdiv(C0,GCD); M1 = sdiv(C1,GCD); return [M0*A0,M1*A1]; } } def nf_sfrat(B,G,M,PS) { for ( D = 0; G; ) { for ( U = 0, L = B; L != []; L = cdr(L) ) { if ( dp_redble(G,R=PS[car(L)]) > 0 ) { GCD = sfgcd(dp_hc(G),dp_hc(R)); CG = sdiv(dp_hc(R),GCD); CR = sdiv(dp_hc(G),GCD); U = CG*G-dp_subd(G,R)*CR*R; if ( !U ) return [D,M]; D *= CG; M *= CG; break; } } if ( U ) G = U; else { D += dp_hm(G); G = dp_rest(G); } } return [D,M]; } def nf_tab_sfrat(F,TAB) { for ( NM = 0, DN = 1, I = 0; F; F = dp_rest(F) ) { T = dp_ht(F); for ( ; TAB[I][0] != T; I++); NF = TAB[I][1]; N = NF[0]; D = NF[1]; G = sfgcd(DN,D); DN1 = sdiv(DN,G); D1 = sdiv(D,G); NM = D1*NM + DN1*dp_hc(F)*N; DN *= D1; } return [NM,DN]; } def adj_dn_sfrat(P,D) { return [(sdiv(D,dp_hc(P[1])))*P[0],dp_ht(P[1])]; } def tolex_sfrat_main(V,O,NF,GM,Vc,Eval,MB) { if ( MB ) { PosDim = 0; DIM = length(MB); DV = newvect(DIM); } else PosDim = 1; for ( T = GM, SL = [], LCM = 1; T != []; T = cdr(T) ) { S = p_terms(car(T),V,2); if ( PosDim ) { MB = gather_nf_terms(S,NF,V,O); DV = newvect(length(MB)); } dp_ord(O); RHS = termstomat_sfrat(NF,map(dp_ptod,cdr(S),V),MB,Vc,Eval); dp_ord(O); NHT = nf_tab_gsl_sfrat(dp_ptod(LCM*car(S),V),NF); dptov(NHT[0],DV,MB); dp_ord(O); B = hen_ttob_gsl_sfrat([DV,NHT[1]],RHS,cdr(S),Vc,Eval); if ( !B ) return 0; Len = length(S); LCM *= B[1]; for ( U = LCM*car(S), I = 1; I < Len; I++ ) U += B[0][I-1]*S[I]; SL = cons(U,SL); if ( dp_gr_print() ) print(["DN",B[1]]); } return SL; } def termstomat_sfrat(NF,TERMS,MB,Vc,Eval) { DN = NF[1]; NF = NF[0]; N = length(MB); M = length(TERMS); MAT = newmat(N,M); W = newvect(N); Len = length(NF); for ( I = 0; I < M; I++ ) { T = TERMS[I]; for ( K = 0; K < Len; K++ ) if ( T == NF[K][1] ) break; dptov(NF[K][0],W,MB); for ( J = 0; J < N; J++ ) MAT[J][I] = W[J]; } return [henleq_prep_sfrat(MAT,Vc,Eval),DN]; } def henleq_prep_sfrat(A,Vc,Eval) { SIZE = size(A); ROW = SIZE[0]; COL = SIZE[1]; L = geninv_sf_swap(map(eval_sfrat,A,Vc,Eval)); INV = L[0]; INDEX = L[1]; AA = newmat(COL,COL); for ( I = 0; I < COL; I++ ) for ( J = 0, T = AA[I], S = A[INDEX[I]]; J < COL; J++ ) T[J] = S[J]; if ( COL != ROW ) { RESTA = newmat(ROW-COL,COL); for ( ; I < ROW; I++ ) for ( J = 0, T = RESTA[I-COL], S = A[INDEX[I]]; J < COL; J++ ) T[J] = S[J]; } else RESTA = 0; return [[A,AA,RESTA],L]; } def hen_ttob_gsl_sfrat(LHS,RHS,TERMS,Vc,Eval) { LDN = LHS[1]; RDN = RHS[1]; LCM = lcm_sfrat(LDN,RDN); L1 = sdiv(LCM,LDN); R1 = sdiv(LCM,RDN); T0 = time()[0]; S = henleq_gsl_sfrat(RHS[0],LHS[0]*L1,Vc,Eval); if ( dp_gr_print() ) print(["henleq_gsl_sfrat",time()[0]-T0]); if ( !S ) return 0; N = length(TERMS); return [S[0],S[1]*R1]; } def nf_tab_gsl_sfrat(A,NF) { DN = NF[1]; NF = NF[0]; TLen = length(NF); for ( R = 0; A; A = dp_rest(A) ) { HM = dp_hm(A); C = dp_hc(HM); T = dp_ht(HM); for ( I = 0; I < TLen; I++ ) if ( NF[I][1] == T ) break; R += C*NF[I][0]; } return remove_cont_sfrat([R,DN]); } def henleq_gsl_sfrat(L,B,Vc,Eval) { Nc = length(Vc); if ( Nc > 1 ) return henleq_gsl_sfrat_higher(L,B,Vc,Eval); V0 = Vc[0]; E0 = ptosfp(Eval[0]); AL = L[0]; INVL = L[1]; A = AL[0]; AA = AL[1]; RESTA = AL[2]; INV = INVL[0]; INDEX = INVL[1]; SIZE = size(A); ROW = SIZE[0]; COL = SIZE[1]; BB = newvect(COL); for ( I = 0; I < COL; I++ ) BB[I] = B[INDEX[I]]; if ( COL != ROW ) { RESTB = newvect(ROW-COL); for ( ; I < ROW; I++ ) RESTB[I-COL] = B[INDEX[I]]; } else RESTB = 0; COUNT = 2; if ( !COUNT ) COUNT = 2; X = newvect(size(AA)[0]); for ( I = 0, C = BB, CCC = 0, ITOR_FAIL = -1; ; I++ ) { if ( zerovector(C) ) { X = map(subst,X,V0,V0-E0); if ( zerovector(RESTA*X+RESTB) ) { if ( dp_gr_print() ) print("end",0); return [X,simp_ff(1)]; } else return 0; } else if ( COUNT == CCC ) { CCC = 0; ND = polyvtoratv(X,V0,I); if ( ND ) { F = map(subst,ND[0],V0,V0-E0); LCM = subst(ND[1],V0,V0-E0); T = AA*F+LCM*BB; if ( zerovector(T) ) { T = RESTA*F+LCM*RESTB; if ( zerovector(T) ) { if ( dp_gr_print() ) print("end",0); return [F,LCM]; } else return 0; } } else { } } else { if ( dp_gr_print() ) print(".",2); CCC++; } XT = -INV*map(subst,C,V0,E0); X += XT*V0^I; C += AA*XT; C = map(sdiv,C,V0-E0); } } def henleq_gsl_sfrat_higher(L,B,Vc,Eval) { Nc = length(Vc); E = map(ptosfp,Eval); AL = L[0]; INVL = L[1]; A = AL[0]; AA0 = AL[1]; RESTA = AL[2]; INV = INVL[0]; INDEX = INVL[1]; SIZE = size(A); ROW = SIZE[0]; COL = SIZE[1]; AA = map(mshift,AA0,Vc,E,1); BB = newvect(COL); for ( I = 0; I < COL; I++ ) BB[I] = mshift(B[INDEX[I]],Vc,E,1); if ( COL != ROW ) { RESTB = newvect(ROW-COL); for ( ; I < ROW; I++ ) RESTB[I-COL] = B[INDEX[I]]; } else RESTB = 0; COUNT = 2; if ( !COUNT ) COUNT = 2; X = newvect(size(AA)[0]); for ( I = 0, R = BB, CCC = 0, ITOR_FAIL = -1; ; I++ ) { if ( zerovector(R) ) { X = map(mshift,X,Vc,E,-1); if ( zerovector(RESTA*X+RESTB) ) { if ( dp_gr_print() ) print("end",0); return [X,simp_ff(1)]; } else return 0; } else if ( COUNT == CCC ) { CCC = 0; ND = polyvtoratv_higher(X,Vc,I); if ( ND ) { F = map(mshift,ND[0],Vc,E,-1); LCM = mshift(ND[1],Vc,E,-1); T = AA*F+LCM*BB; if ( zerovector(T) ) { T = RESTA*F+LCM*RESTB; if ( zerovector(T) ) { if ( dp_gr_print() ) print("end",0); return [F,LCM]; } else return 0; } } else { } } else { if ( dp_gr_print() ) print(".",2); CCC++; } RK = map(mtrunc,R,I+1); XT = -INV*RK; X += XT; R += AA*XT; } } /* V -> V+Sgn*E */ def mshift(F,V,E,Sgn) { N = length(V); for ( I = 0; I < N; I++ ) F = subst(F,V[I],V[I]+Sgn*E[I]); return F; } /* truncate terms whose degree are higher than or equal to D */ def mtrunc(F,D) { if ( type(F) <= 1 ) return F; else { R = 0; V = var(F); while ( F ) { K = deg(F,V); C = coef(F,K,V); if ( K < D ) R += mtrunc(C,D-K)*V^K; F -= C*V^K; } return R; } } /* for 1-dim case */ def polyvtoratv(Vect,V,K) { N = size(Vect)[0]; R = newvect(N); K2 = idiv(K,2); Mat = newmat(K2,K2); for ( I = 0; I < N; I++ ) { T = polytorat(Vect[I],V,Mat,K2); if ( T ) R[I] = T; else return 0; } LCM = R[0][1]; for ( I = 1; I < N; I++ ) LCM = lcm_sfrat(LCM,R[I][1]); for ( I = 0; I < N; I++ ) R[I] = R[I][0]*sdiv(LCM,R[I][1]); return [R,LCM]; } /* for higher dim case */ def polyvtoratv_higher(Vect,Vc,K) { N = size(Vect)[0]; R = newvect(N); K2 = idiv(K,2); for ( I = 0; I < N; I++ ) { T = polytorat_higher(Vect[I],Vc,K2); if ( T ) R[I] = T; else return 0; } LCM = R[0][1]; for ( I = 1; I < N; I++ ) LCM = lcm_sfrat(LCM,R[I][1]); for ( I = 0; I < N; I++ ) R[I] = R[I][0]*sdiv(LCM,R[I][1]); return [R,LCM]; } /* find F = N/D mod V^(2K), deg(N), deg(D) < K */ def polytorat_gcd(F,V,K) { if ( deg(F,V) < K ) return [F,simp_ff(1)]; F1 = Mod^(K*2); F2 = F; B1 = 0; B2 = 1; while ( 1 ) { Q = sdiv(F1,F2); F3 = F1-F2*Q; B3 = B1-B2*Q; if ( deg(F3,V) < K ) { if ( deg(B3,V) < K ) return [F3,B3]; else return 0; } F1 = F2; F2 = F3; B1 = B2; B2 = B3; } } /* * for 1-dim case * * solve * * [fk ... f1][ a0 ] * [f(k+1) ... f2][ a1 ] = 0 * [ ... ][ ... ] * [f(2k-1) ... fk][a(k-1)] */ def polytorat(F,V,Mat,K) { if ( deg(F,V) < K ) return [F,simp_ff(1)]; for ( I = 0; I < K; I++ ) for ( J = 0; J < K; J++ ) Mat[I][J] = coef(F,I+K-J); S = nullspace_ff(Mat); MT = S[0]; IND = S[1]; for ( I = 0; I < K; I++ ) if ( IND[I] ) break; if ( I == K ) return 0; D = null_to_poly_ff(MT,IND,V)[0]; N = trunc(F*D,K-1); return [N,D]; } /* find N,D s.t. tdeg(N), tdeg(D) < K, F = N/D mod ^(2K) */ def polytorat_higher(F,V,K) { if ( K < 2 ) return 0; if ( homogeneous_deg(F) < K ) return [F,simp_ff(1)]; D = create_icpoly(V,K); C = extract_coef(D*F,V,K,2*K); Vc = vars(C); G = dp_gr_f_main(C,Vc,0,2); PS = newvect(length(G),map(dp_ptod,G,Vc)); for ( I = length(G)-1, Ind = [];I >= 0; I-- ) Ind = cons(I,Ind); D = dp_dtop(nf_sfrat(Ind,dp_ptod(D,Vc),1,PS)[0],Vc); if ( !D ) return 0; Vp = setminus(vars(D),V); D = subst(D,car(Vp),1); for ( T = cdr(Vp); T != []; T = cdr(T) ) D = subst(D,car(T),0); N = mtrunc(F*D,K); return [N,D]; } def create_icpoly(V,K) { if ( V == [] ) return uc(); R = 0; for ( I = 0; I < K; I++ ) R += create_icpoly(cdr(V),K-I)*V[0]^I; return R; } /* extract terms whose degrees are in [From,To) */ def extract_coef(F,V,From,To) { if ( V == [] ) { if ( From == 0 ) return [F]; else return []; } R = []; V0 = V[0]; for ( I = 0; I < To; I++ ) { C = coef(F,I,V0); if ( C ) { C = extract_coef(C,cdr(V),From>=I?From-I:0,To-I); R = append(C,R); } } return R; } def saturation_sfrat(F,G,V,Ord) { Vt = ttttt; G0 = dp_gr_f_main(cons(Vt*F-1,G),cons(Vt,V),0,[[0,1],[Ord,length(V)]]); return elimination(G0,V); } def ideal_list_intersection_sfrat(L,V) { R = car(L); for ( TL = cdr(L); TL != []; TL = cdr(TL) ) R = ideal_intersection_sfrat(R,car(TL),V); return R; } def ideal_intersection_sfrat(A,B,V) { T0 = time(); Vt = ttttt; C = []; for ( T = A; T != []; T = cdr(T) ) C = cons(car(T)*Vt,C); for ( T = B; T != []; T = cdr(T) ) C = cons(car(T)*(1-Vt),C); Ord = [[0,1],[0,length(V)]]; #if 0 G0 = dp_gr_f_main(C,cons(Vt,V),0,0); G = dp_gr_f_main(G0,cons(Vt,V),0,Ord); #else G = dp_gr_f_main(C,cons(Vt,V),0,Ord); #endif T_INT += time()[3]-T0[3]; return elimination(G,V); } /* Shimoyama's gr_fctr */ def idealsqfr_sf(G) { for(LL=[],I=length(G)-1;I>=0;I--) { for(A=1,L=sfsqfr(G[I]),J=1;J 2 || N > 1) { TLL = []; for (J = 1; J < L; J++) { W = cons(FL[J][0],G); NG = dp_gr_f_main(W,VL,0,Ord); TNG = idealsqfr_sf(NG); if ( !gb_comp_old(NG,TNG) ) NG = dp_gr_f_main(TNG,VL,0,Ord); if ( !inclusion_test(CID_SF,NG,VL,Ord) ) { DG = gr_fctr_sub_sf(NG,VL,Ord); RL = append(RL,DG); if ( J <= L-2 && !inclusion_test(CID_SF,NG,VL,Ord) && COMMONCHECK_SF ) { CID_SF=ideal_intersection_sfrat(CID_SF,NG,VL); } } } break; } } if (I == length(G)) RL = append([G],RL); return RL; } def gb_comp_old(A,B) { LA = length(A); LB = length(B); if ( LA != LB ) return 0; A = newvect(LA,A); B = newvect(LB,B); A1 = qsort(A); B1 = qsort(B); for ( I = 0; I < LA; I++ ) if ( A1[I] != B1[I] && A1[I] != -B1[I] ) break; return I == LA ? 1 : 0; } end$