source: git/Singular/LIB/primdec.lib @ 7835f61

spielwiese
Last change on this file since 7835f61 was 7835f61, checked in by Jakob Kröker <kroeker@…>, 10 years ago
used Hans routine hasGlobalOrdering instead of my hasGlobalMonomialOrdering
  • Property mode set to 100644
File size: 221.0 KB
Line 
1////////////////////////////////////////////////////////////////////////////
2version="version primdec.lib 4.0.0.0 Jun_2013 "; // $Id$
3category="Commutative Algebra";
4info="
5LIBRARY: primdec.lib   Primary Decomposition and Radical of Ideals
6AUTHORS:  Gerhard Pfister, pfister@mathematik.uni-kl.de (GTZ)@*
7          Wolfram Decker, decker@math.uni-sb.de         (SY)@*
8          Hans Schoenemann, hannes@mathematik.uni-kl.de (SY)@*
9          Santiago Laplagne, slaplagn@dm.uba.ar         (GTZ)
10
11OVERVIEW:
12    Algorithms for primary decomposition based on the ideas of
13    Gianni, Trager and Zacharias (implementation by Gerhard Pfister),
14    respectively based on the ideas of Shimoyama and Yokoyama (implementation
15    by Wolfram Decker and Hans Schoenemann).@*
16    The procedures are implemented to be used in characteristic 0.@*
17    They also work in positive characteristic >> 0.@*
18    In small characteristic and for algebraic extensions, primdecGTZ
19    may not terminate.@*
20    Algorithms for the computation of the radical based on the ideas of
21    Krick, Logar, Laplagne and Kemper (implementation by Gerhard Pfister and Santiago Laplagne).
22    They work in any characteristic.@*
23    Baserings must have a global ordering and no quotient ideal.
24    Exceptions: primdecGTZ, absPrimdecGTZ, minAssGTZ, primdecSY, minAssChar, radical accept non-global ordering.
25
26
27PROCEDURES:
28 Ann(M);           annihilator of R^n/M, R=basering, M in R^n
29 primdecGTZ(I);    complete primary decomposition via Gianni,Trager,Zacharias
30 primdecSY(I...);  complete primary decomposition via Shimoyama-Yokoyama
31 minAssGTZ(I);     the minimal associated primes via Gianni,Trager,Zacharias (with modifications by Laplagne)
32 minAssChar(I...); the minimal associated primes using characteristic sets
33 testPrimary(L,k); tests the result of the primary decomposition
34 radical(I);       computes the radical of I via Krick/Logar (with modifications by Laplagne) and Kemper
35 radicalEHV(I);    computes the radical of I via Eisenbud,Huneke,Vasconcelos
36 equiRadical(I);   the radical of the equidimensional part of the ideal I
37 prepareAss(I);    list of radicals of the equidimensional components of I
38 equidim(I);       weak equidimensional decomposition of I
39 equidimMax(I);    equidimensional locus of I
40 equidimMaxEHV(I); equidimensional locus of I via Eisenbud,Huneke,Vasconcelos
41 zerodec(I);       zerodimensional decomposition via Monico
42 absPrimdecGTZ(I); the absolute prime components of I
43 sep(f,k);         the separabel part of f as polynomial in Fp(t1,...,tm)
44";
45
46LIB "general.lib";
47LIB "elim.lib";
48LIB "poly.lib";
49LIB "random.lib";
50LIB "inout.lib";
51LIB "matrix.lib";
52LIB "triang.lib";
53LIB "absfact.lib";
54LIB "ring.lib";
55///////////////////////////////////////////////////////////////////////////////
56//
57//                      Gianni/Trager/Zacharias
58//
59///////////////////////////////////////////////////////////////////////////////
60
61static proc sat1 (ideal id, poly p)
62"USAGE:   sat1(id,j);  id ideal, j polynomial
63RETURN:  saturation of id with respect to j (= union_(k=1...) of id:j^k)
64NOTE:    result is a std basis in the basering
65"
66{
67  ASSUME(0, not isQuotientRing(basering) ) ;
68  ASSUME(0, hasGlobalOrdering(basering) ) ;
69
70  int @k;
71  ideal inew=std(id);
72  ideal iold;
73  intvec op=option(get);
74  option(returnSB);
75  while(specialIdealsEqual(iold,inew)==0 )
76  {
77    iold=inew;
78    inew=quotient(iold,p);
79    @k++;
80  }
81  @k--;
82  option(set,op);
83  list L =inew,p^@k;
84  return (L);
85}
86
87///////////////////////////////////////////////////////////////////////////////
88
89static proc sat2 (ideal id, ideal h)
90"USAGE:   sat2(id,j);  id ideal, j polynomial
91RETURN:  saturation of id with respect to j (= union_(k=1...) of id:j^k)
92NOTE:    result is a std basis in the basering
93"
94{
95  ASSUME(0, not isQuotientRing(basering) ) ;
96  ASSUME(0, hasGlobalOrdering(basering) ) ;
97  int @k,@i;
98  def @P= basering;
99  if(ordstr(basering)[1,2]!="dp")
100  {
101    execute("ring @Phelp=("+charstr(@P)+"),("+varstr(@P)+"),(C,dp);");
102    ideal inew=std(imap(@P,id));
103    ideal  @h=imap(@P,h);
104  }
105  else
106  {
107    ideal @h=h;
108    ideal inew=std(id);
109  }
110  ideal fac;
111
112  for(@i=1;@i<=ncols(@h);@i++)
113  {
114    if(deg(@h[@i])>0)
115    {
116      fac=fac+factorize(@h[@i],1);
117    }
118  }
119  fac=simplify(fac,6);
120  poly @f=1;
121  if(deg(fac[1])>0)
122  {
123    ideal iold;
124    for(@i=1;@i<=size(fac);@i++)
125    {
126      @f=@f*fac[@i];
127    }
128    intvec op = option(get);
129    option(returnSB);
130    while(specialIdealsEqual(iold,inew)==0 )
131    {
132      iold=inew;
133      if(deg(iold[size(iold)])!=1)
134      {
135        inew=quotient(iold,@f);
136      }
137      else
138      {
139        inew=iold;
140      }
141      @k++;
142    }
143    option(set,op);
144    @k--;
145  }
146
147  if(ordstr(@P)[1,2]!="dp")
148  {
149    setring @P;
150    ideal inew=std(imap(@Phelp,inew));
151    poly @f=imap(@Phelp,@f);
152  }
153  list L =inew,@f^@k;
154  return (L);
155}
156
157///////////////////////////////////////////////////////////////////////////////
158
159
160proc minSat(ideal inew, ideal h)
161{
162  ASSUME(0, not isQuotientRing(basering) ) ;
163  ASSUME(0, hasGlobalOrdering(basering) ) ;
164  int i,k;
165  poly f=1;
166  ideal iold,fac;
167  list quotM,l;
168
169  for(i=1;i<=ncols(h);i++)
170  {
171    if(deg(h[i])>0)
172    {
173      fac=fac+factorize(h[i],1);
174    }
175  }
176  fac=simplify(fac,6);
177  if(size(fac)==0)
178  {
179    l=inew,1;
180    return(l);
181  }
182  fac=sort(fac)[1];
183  for(i=1;i<=size(fac);i++)
184  {
185    f=f*fac[i];
186  }
187  quotM[1]=inew;
188  quotM[2]=fac;
189  quotM[3]=f;
190  f=1;
191  intvec op = option(get);
192  option(returnSB);
193  while(specialIdealsEqual(iold,quotM[1])==0)
194  {
195    if(k>0)
196    {
197      f=f*quotM[3];
198    }
199    iold=quotM[1];
200    quotM=quotMin(quotM);
201    k++;
202  }
203  option(set,op);
204  l=quotM[1],f;
205  return(l);
206}
207
208static proc quotMin(list tsil)
209{
210  ASSUME(0, not isQuotientRing(basering) ) ;
211  ASSUME(0, hasGlobalOrdering(basering) ) ;
212  int i,j,k,action;
213  ideal verg;
214  list l;
215  poly g;
216
217  ideal laedi=tsil[1];
218  ideal fac=tsil[2];
219  poly f=tsil[3];
220
221  ideal star=quotient(laedi,f);
222
223  if(specialIdealsEqual(star,laedi))
224  {
225    l=star,fac,f;
226    return(l);
227  }
228
229  action=1;
230
231  while(action==1)
232  {
233    if(size(fac)==1)
234    {
235      action=0;
236      break;
237    }
238    for(i=1;i<=size(fac);i++)
239    {
240      g=1;
241      verg=laedi;
242      for(j=1;j<=size(fac);j++)
243      {
244        if(i!=j)
245        {
246          g=g*fac[j];
247        }
248      }
249      verg=quotient(laedi,g);
250
251      if(specialIdealsEqual(verg,star)==1)
252      {
253        f=g;
254        fac[i]=0;
255        fac=simplify(fac,2);
256        break;
257      }
258      if(i==size(fac))
259      {
260        action=0;
261      }
262    }
263  }
264  l=star,fac,f;
265  return(l);
266}
267
268///////////////////////////////////////////////////////////////////////////////
269
270static proc testFactor(list act,poly p)
271{
272  ASSUME(0, not isQuotientRing(basering) ) ;
273  ASSUME(0, hasGlobalOrdering(basering) ) ;
274  poly keep=p;
275
276  int i;
277  poly q=act[1][1]^act[2][1];
278  for(i=2;i<=size(act[1]);i++)
279  {
280    q=q*act[1][i]^act[2][i];
281  }
282  q=1/leadcoef(q)*q;
283  p=1/leadcoef(p)*p;
284  if(p-q!=0)
285  {
286    "ERROR IN FACTOR, please inform the authors";
287  }
288}
289///////////////////////////////////////////////////////////////////////////////
290
291static proc factor(poly p)
292"USAGE:   factor(p) p poly
293RETURN:  list=;
294NOTE:
295EXAMPLE: example factor; shows an example
296"
297{
298  ASSUME(0, not isQuotientRing(basering) ) ;
299  ASSUME(0, hasGlobalOrdering(basering) ) ;
300  ideal @i;
301  list @l;
302  intvec @v,@w;
303  int @j,@k,@n;
304
305  @l=factorize(p);
306    for(@j=1;@j<=size(@l[1]);@j++)
307    {
308      if(leadcoef(@l[1][@j])==@l[1][@j])
309      {
310        @n++;
311      }
312    }
313    if(@n>0)
314    {
315      if(@n==size(@l[1]))
316      {
317        @l[1]=ideal(1);
318        @v=1;
319        @l[2]=@v;
320      }
321      else
322      {
323        @k=0;
324        int pleh;
325        for(@j=1;@j<=size(@l[1]);@j++)
326        {
327          if(leadcoef(@l[1][@j])!=@l[1][@j])
328          {
329            @k++;
330            @i=@i+ideal(@l[1][@j]);
331            if(size(@i)==pleh)
332            {
333              "//factorization error";
334              @l;
335              @k--;
336              @v[@k]=@v[@k]+@l[2][@j];
337            }
338            else
339            {
340              pleh++;
341              @v[@k]=@l[2][@j];
342            }
343          }
344        }
345        @l[1]=@i;
346        @l[2]=@v;
347      }
348    }
349    // }
350  return(@l);
351}
352example
353{ "EXAMPLE:"; echo = 2;
354   ring  r = 0,(x,y,z),lp;
355   poly  p = (x+y)^2*(y-z)^3;
356   list  l = factor(p);
357   l;
358   ring r1 =(0,b,d,f,g),(a,c,e),lp;
359   poly p  =(1*d)*e^2+(1*d*f^2*g);
360   list  l = factor(p);
361   l;
362   ring r2 =(0,b,f,g),(a,c,e,d),lp;
363   poly p  =(1*d)*e^2+(1*d*f^2*g);
364   list  l = factor(p);
365   l;
366}
367
368///////////////////////////////////////////////////////////////////////////////
369
370proc idealsEqual( ideal k, ideal j)
371{
372  return(stdIdealsEqual(std(k),std(j)));
373}
374
375static proc specialIdealsEqual( ideal k1, ideal k2)
376{
377  int j;
378
379  if(size(k1)==size(k2))
380  {
381    for(j=1;j<=size(k1);j++)
382    {
383      if(leadexp(k1[j])!=leadexp(k2[j]))
384      {
385        return(0);
386      }
387    }
388    return(1);
389  }
390  return(0);
391}
392
393static proc stdIdealsEqual( ideal k1, ideal k2)
394{
395  int j;
396
397  if(size(k1)==size(k2))
398  {
399    for(j=1;j<=size(k1);j++)
400    {
401      if(leadexp(k1[j])!=leadexp(k2[j]))
402      {
403        return(0);
404      }
405    }
406    attrib(k2,"isSB",1);
407    if(size(reduce(k1,k2,1))==0)
408    {
409      return(1);
410    }
411  }
412  return(0);
413}
414///////////////////////////////////////////////////////////////////////////////
415
416proc primaryTest (ideal i, poly p)
417{
418  ASSUME(0, not isQuotientRing(basering) ) ;
419  ASSUME(0, hasGlobalOrdering(basering) ) ;
420  int m=1;
421  int n=nvars(basering);
422  int e,f;
423  poly t;
424  ideal h;
425  list act;
426
427  ideal prm=p;
428  attrib(prm,"isSB",1);
429
430  while (n>1)
431  {
432    n--;
433    m++;
434
435    //search for i[m] which has a power of var(n) as leading term
436    if (n==1)
437    {
438      m=size(i);
439    }
440    else
441    {
442      while (lead(i[m])/var(n-1)==0)
443      {
444        m++;
445      }
446      m--;
447    }
448    //check whether i[m] =(c*var(n)+h)^e modulo prm for some
449    //h in K[var(n+1),...,var(nvars(basering))], c in K
450    //if not (0) is returned, else var(n)+h is added to prm
451
452    e=deg(lead(i[m]));
453    if(char(basering)!=0)
454    {
455      f=1;
456      if(e mod char(basering)==0)
457      {
458        if ( voice >=15 )
459        {
460          "// WARNING: The characteristic is perhaps too small to use";
461          "// the algorithm of Gianni/Trager/Zacharias.";
462          "// This may result in an infinte loop";
463          "// loop in primaryTest, voice:",voice;"";
464        }
465        while(e mod char(basering)==0)
466        {
467          f=f*char(basering);
468          e=e div char(basering);
469        }
470      }
471      t=leadcoef(i[m])*e*var(n)^f+(i[m]-lead(i[m]))/var(n)^((e-1)*f);
472      i[m]=poly(e)^e*leadcoef(i[m])^(e-1)*i[m];
473      if (reduce(i[m]-t^e,prm,1) !=0)
474      {
475        return(ideal(0));
476      }
477      if(f>1)
478      {
479        act=factorize(t);
480        if(size(act[1])>2)
481        {
482          return(ideal(0));
483        }
484        if(deg(act[1][2])>1)
485        {
486          return(ideal(0));
487        }
488        t=act[1][2];
489      }
490    }
491    else
492    {
493      t=leadcoef(i[m])*e*var(n)+(i[m]-lead(i[m]))/var(n)^(e-1);
494      i[m]=poly(e)^e*leadcoef(i[m])^(e-1)*i[m];
495      if (reduce(i[m]-t^e,prm,1) !=0)
496      {
497        return(ideal(0));
498      }
499    }
500
501    h=interred(t);
502    t=h[1];
503
504    prm = prm,t;
505    attrib(prm,"isSB",1);
506  }
507  return(prm);
508}
509
510///////////////////////////////////////////////////////////////////////////////
511proc gcdTest(ideal act)
512{
513  ASSUME(0, not isQuotientRing(basering) ) ;
514  ASSUME(0, hasGlobalOrdering(basering) ) ;
515  int i,j;
516  if(size(act)<=1)
517  {
518    return(0);
519  }
520  for (i=1;i<=size(act)-1;i++)
521  {
522    for(j=i+1;j<=size(act);j++)
523    {
524      if(deg(std(ideal(act[i],act[j]))[1])>0)
525      {
526        return(0);
527      }
528    }
529  }
530  return(1);
531}
532
533///////////////////////////////////////////////////////////////////////////////
534static proc splitPrimary(list l,ideal ser,int @wr,list sact)
535{
536  ASSUME(0, not isQuotientRing(basering) ) ;
537  ASSUME(0, hasGlobalOrdering(basering) ) ;
538  int i,j,k,s,r,w;
539  list keepresult,act,keepprime;
540  poly @f;
541  int sl=size(l);
542  for(i=1;i<=sl div 2;i++)
543  {
544    if(sact[2][i]>1)
545    {
546      keepprime[i]=l[2*i-1]+ideal(sact[1][i]);
547    }
548    else
549    {
550      keepprime[i]=l[2*i-1];
551    }
552  }
553  i=0;
554  while(i<size(l) div 2)
555  {
556    i++;
557    if((size(ser)>0)&&(size(reduce(ser,l[2*i-1],1))==0))
558    {
559      l[2*i-1]=ideal(1);
560      l[2*i]=ideal(1);
561      continue;
562    }
563
564    if(size(l[2*i])==0)
565    {
566      if(homog(l[2*i-1])==1)
567      {
568        l[2*i]=maxideal(1);
569        continue;
570      }
571      j=0;
572/*
573      if(i<=sl div 2)
574      {
575        j=1;
576      }
577*/
578      while(j<size(l[2*i-1]))
579      {
580        j++;
581        act=factor(l[2*i-1][j]);
582        r=size(act[1]);
583        attrib(l[2*i-1],"isSB",1);
584        if((r==1)&&(vdim(l[2*i-1])==deg(l[2*i-1][j])))
585        {
586          l[2*i]=std(l[2*i-1],act[1][1]);
587          break;
588        }
589        if((r==1)&&(act[2][1]>1))
590        {
591          keepprime[i]=interred(keepprime[i]+ideal(act[1][1]));
592          if(homog(keepprime[i])==1)
593          {
594            l[2*i]=maxideal(1);
595            break;
596          }
597        }
598        if(gcdTest(act[1])==1)
599        {
600          for(k=2;k<=r;k++)
601          {
602            keepprime[size(l) div 2+k-1]=interred(keepprime[i]+ideal(act[1][k]));
603          }
604          keepprime[i]=interred(keepprime[i]+ideal(act[1][1]));
605          for(k=1;k<=r;k++)
606          {
607            if(@wr==0)
608            {
609              keepresult[k]=std(l[2*i-1],act[1][k]^act[2][k]);
610            }
611            else
612            {
613              keepresult[k]=std(l[2*i-1],act[1][k]);
614            }
615          }
616          l[2*i-1]=keepresult[1];
617          if(vdim(keepresult[1])==deg(act[1][1]))
618          {
619            l[2*i]=keepresult[1];
620          }
621          if((homog(keepresult[1])==1)||(homog(keepprime[i])==1))
622          {
623            l[2*i]=maxideal(1);
624          }
625          s=size(l)-2;
626          for(k=2;k<=r;k++)
627          {
628            l[s+2*k-1]=keepresult[k];
629            keepprime[s div 2+k]=interred(keepresult[k]+ideal(act[1][k]));
630            if(vdim(keepresult[k])==deg(act[1][k]))
631            {
632              l[s+2*k]=keepresult[k];
633            }
634            else
635            {
636              l[s+2*k]=ideal(0);
637            }
638            if((homog(keepresult[k])==1)||(homog(keepprime[s div 2+k])==1))
639            {
640              l[s+2*k]=maxideal(1);
641            }
642          }
643          i--;
644          break;
645        }
646        if(r>=2)
647        {
648          s=size(l);
649          @f=act[1][1];
650          act=sat1(l[2*i-1],act[1][1]);
651          if(deg(act[1][1])>0)
652          {
653            l[s+1]=std(l[2*i-1],act[2]);
654            if(homog(l[s+1])==1)
655            {
656              l[s+2]=maxideal(1);
657            }
658            else
659            {
660              l[s+2]=ideal(0);
661            }
662            keepprime[s div 2+1]=interred(keepprime[i]+ideal(@f));
663            if(homog(keepprime[s div 2+1])==1)
664            {
665              l[s+2]=maxideal(1);
666            }
667            keepprime[i]=act[1];
668            l[2*i-1]=act[1];
669            attrib(l[2*i-1],"isSB",1);
670            if(homog(l[2*i-1])==1)
671            {
672              l[2*i]=maxideal(1);
673            }
674            i--;
675            break;
676          }
677        }
678      }
679    }
680  }
681  if(sl==size(l))
682  {
683    return(l);
684  }
685  for(i=1;i<=size(l) div 2;i++)
686  {
687    attrib(l[2*i-1],"isSB",1);
688
689    if((size(ser)>0)&&(size(reduce(ser,l[2*i-1],1))==0)&&(deg(l[2*i-1][1])>0))
690    {
691      "Achtung in split";
692
693      l[2*i-1]=ideal(1);
694      l[2*i]=ideal(1);
695    }
696    if((size(l[2*i])==0)&&(specialIdealsEqual(keepprime[i],l[2*i-1])!=1))
697    {
698      keepprime[i]=std(keepprime[i]);
699      if(homog(keepprime[i])==1)
700      {
701        l[2*i]=maxideal(1);
702      }
703      else
704      {
705        act=zero_decomp(keepprime[i],ideal(0),@wr,1);
706        if(size(act)==2)
707        {
708          l[2*i]=act[2];
709        }
710      }
711    }
712  }
713  return(l);
714}
715example
716{ "EXAMPLE:"; echo=2;
717   ring  r = 32003,(x,y,z),lp;
718   ideal i1=x*(x+1),yz,(z+1)*(z-1);
719   ideal i2=xy,yz,(x-2)*(x+3);
720   list l=i1,ideal(0),i2,ideal(0),i2,ideal(1);
721   list l1=splitPrimary(l,ideal(0),0);
722   l1;
723}
724///////////////////////////////////////////////////////////////////////////////
725static proc splitCharp(list l)
726{
727  ASSUME(0, not isQuotientRing(basering) ) ;
728  ASSUME(0, hasGlobalOrdering(basering) ) ;
729  if((char(basering)==0)||(npars(basering)>0))
730  {
731    return(l);
732  }
733  def op = option(get);
734  def P=basering;
735  int i,j,k,m,q,d,o;
736  int n = nvars(basering);
737  ideal s,t,u,sact;
738  poly ni;
739  string minp,gnir,va;
740  list sa,keep,rp,keep1;
741  for(i=1;i<=size(l) div 2;i++)
742  {
743    if(size(l[2*i])==0)
744    {
745      if(deg(l[2*i-1][1])==vdim(l[2*i-1]))
746      {
747        l[2*i]=l[2*i-1];
748      }
749    }
750  }
751  for(i=1;i<=size(l) div 2;i++)
752  {
753    if(size(l[2*i])==0)
754    {
755      s=factorize(l[2*i-1][1],1);   //vermeiden!!!
756      t=l[2*i-1];
757      m=size(t);
758      ni=s[1];
759      if(deg(ni)>1)
760      {
761        va=varstr(P);
762        j=size(va);
763        while(va[j]!=","){j--;}
764        va=va[1..j-1];
765        gnir="ring RL=("+string(char(P))+","+string(var(n))+"),("+va+"),lp;";
766        execute(gnir);
767        minpoly=leadcoef(imap(P,ni));
768        ideal act;
769        ideal t=imap(P,t);
770
771        for(k=2;k<=m;k++)
772        {
773          act=factorize(t[k],1);
774          if(size(act)>1){break;}
775        }
776        setring P;
777        sact=imap(RL,act);
778
779        if(size(sact)>1)
780        {
781          sa=sat1(l[2*i-1],sact[1]);
782          keep[size(keep)+1]=std(l[2*i-1],sa[2]);
783          if(sa[1][1]==l[2*i-1][1])
784          {
785             l[2*i-1]=std(sa[1]);
786             l[2*i]=primaryTest(sa[1],s[1]);
787          }
788          else
789          {
790             l[2*i-1]=std(sa[1]);
791             l[2*i]=primaryTest(sa[1],factorize(sa[1][1],1)[1]);
792          }
793        }
794        if((size(sact)==1)&&(m==2))
795        {
796          l[2*i]=l[2*i-1];
797          attrib(l[2*i],"isSB",1);
798        }
799        if((size(sact)==1)&&(m>2))
800        {
801          setring RL;
802
803          option(redSB);
804          t=std(t);
805
806          list sp=zero_decomp(t,0,0);
807
808          setring P;
809          rp=imap(RL,sp);
810          for(o=1;o<=size(rp);o++)
811          {
812            rp[o]=interred(simplify(rp[o],1)+ideal(ni));
813          }
814          l[2*i-1]=rp[1];
815          l[2*i]=rp[2];
816          rp=delete(rp,1);
817          rp=delete(rp,1);
818          keep1=keep1+rp;
819
820          option(noredSB);
821        }
822        kill RL;
823      }
824    }
825  }
826  if(size(keep)>0)
827  {
828    for(i=1;i<=size(keep);i++)
829    {
830      if(deg(keep[i][1])>0)
831      {
832        l[size(l)+1]=keep[i];
833        l[size(l)+1]=primaryTest(keep[i],factorize(keep[i][1],1)[1]);
834      }
835    }
836  }
837  l=l+keep1;
838  option(set,op);
839  return(l);
840}
841
842///////////////////////////////////////////////////////////////////////////////
843
844proc zero_decomp (ideal j,ideal ser,int @wr,list #)
845"USAGE:   zero_decomp(j,ser,@wr); j,ser ideals, @wr=0 or 1
846         (@wr=0 for primary decomposition, @wr=1 for computation of associated
847         primes)
848RETURN:  list = list of primary ideals and their radicals (at even positions
849         in the list) if the input is zero-dimensional and a standardbases
850         with respect to lex-ordering
851         If ser!=(0) and ser is contained in j or if j is not zero-dimen-
852         sional then ideal(1),ideal(1) is returned
853NOTE:    Algorithm of Gianni/Trager/Zacharias
854EXAMPLE: example zero_decomp; shows an example
855"
856{
857  ASSUME(0, not isQuotientRing(basering) ) ;
858  ASSUME(0, hasGlobalOrdering(basering) ) ;
859
860  def   @P = basering;
861  int uytrewq;
862  int nva = nvars(basering);
863  int @k,@s,@n,@k1,zz;
864  list primary,lres0,lres1,act,@lh,@wh;
865  map phi,psi,phi1,psi1;
866  ideal jmap,jmap1,jmap2,helpprim,@qh,@qht,ser1;
867  intvec @vh,@hilb;
868  string @ri;
869  poly @f;
870  if (dim(j)>0)
871  {
872    primary[1]=ideal(1);
873    primary[2]=ideal(1);
874    return(primary);
875  }
876  intvec save=option(get);
877  option(redSB);
878  j=interred(j);
879
880  attrib(j,"isSB",1);
881
882  if(vdim(j)==deg(j[1]))
883  {
884    act=factor(j[1]);
885    for(@k=1;@k<=size(act[1]);@k++)
886    {
887      @qh=j;
888      if(@wr==0)
889      {
890        @qh[1]=act[1][@k]^act[2][@k];
891      }
892      else
893      {
894        @qh[1]=act[1][@k];
895      }
896      primary[2*@k-1]=interred(@qh);
897      @qh=j;
898      @qh[1]=act[1][@k];
899      primary[2*@k]=interred(@qh);
900      attrib( primary[2*@k-1],"isSB",1);
901
902      if((size(ser)>0)&&(size(reduce(ser,primary[2*@k-1],1))==0))
903      {
904        primary[2*@k-1]=ideal(1);
905        primary[2*@k]=ideal(1);
906      }
907    }
908    option(set,save);
909    return(primary);
910  }
911
912  option(set,save);
913  if(homog(j)==1)
914  {
915    primary[1]=j;
916    if((size(ser)>0)&&(size(reduce(ser,j,1))==0))
917    {
918      primary[1]=ideal(1);
919      primary[2]=ideal(1);
920      return(primary);
921    }
922    if(dim(j)==-1)
923    {
924      primary[1]=ideal(1);
925      primary[2]=ideal(1);
926    }
927    else
928    {
929      primary[2]=maxideal(1);
930    }
931    return(primary);
932  }
933
934//the first element in the standardbase is factorized
935  if(deg(j[1])>0)
936  {
937    act=factor(j[1]);
938    testFactor(act,j[1]);
939  }
940  else
941  {
942    primary[1]=ideal(1);
943    primary[2]=ideal(1);
944    return(primary);
945  }
946
947//with the factors new ideals (hopefully the primary decomposition)
948//are created
949  if(size(act[1])>1)
950  {
951    if(size(#)>1)
952    {
953      primary[1]=ideal(1);
954      primary[2]=ideal(1);
955      primary[3]=ideal(1);
956      primary[4]=ideal(1);
957      return(primary);
958    }
959    for(@k=1;@k<=size(act[1]);@k++)
960    {
961      if(@wr==0)
962      {
963        primary[2*@k-1]=std(j,act[1][@k]^act[2][@k]);
964      }
965      else
966      {
967        primary[2*@k-1]=std(j,act[1][@k]);
968      }
969      if((act[2][@k]==1)&&(vdim(primary[2*@k-1])==deg(act[1][@k])))
970      {
971        primary[2*@k]   = primary[2*@k-1];
972      }
973      else
974      {
975        primary[2*@k]   = primaryTest(primary[2*@k-1],act[1][@k]);
976      }
977    }
978  }
979  else
980  {
981    primary[1]=j;
982    if((size(#)>0)&&(act[2][1]>1))
983    {
984      act[2]=1;
985      primary[1]=std(primary[1],act[1][1]);
986    }
987    if(@wr!=0)
988    {
989      primary[1]=std(j,act[1][1]);
990    }
991    if((act[2][1]==1)&&(vdim(primary[1])==deg(act[1][1])))
992    {
993      primary[2]=primary[1];
994    }
995    else
996    {
997      primary[2]=primaryTest(primary[1],act[1][1]);
998    }
999  }
1000
1001  if(size(#)==0)
1002  {
1003    primary=splitPrimary(primary,ser,@wr,act);
1004  }
1005
1006  if((voice>=6)&&(char(basering)<=181))
1007  {
1008    primary=splitCharp(primary);
1009  }
1010
1011  if((@wr==2)&&(npars(basering)>0)&&(voice>=6)&&(char(basering)>0))
1012  {
1013  //the prime decomposition of Yokoyama in characteristic p
1014    list ke,ek;
1015    @k=0;
1016    while(@k<size(primary) div 2)
1017    {
1018      @k++;
1019      if(size(primary[2*@k])==0)
1020      {
1021        ek=insepDecomp(primary[2*@k-1]);
1022        primary=delete(primary,2*@k);
1023        primary=delete(primary,2*@k-1);
1024        @k--;
1025      }
1026      ke=ke+ek;
1027    }
1028    for(@k=1;@k<=size(ke);@k++)
1029    {
1030      primary[size(primary)+1]=ke[@k];
1031      primary[size(primary)+1]=ke[@k];
1032    }
1033  }
1034
1035  if(voice>=8){primary=extF(primary);};
1036
1037//test whether all ideals in the decomposition are primary and
1038//in general position
1039//if not after a random coordinate transformation of the last
1040//variable the corresponding ideal is decomposed again.
1041  if((npars(basering)>0)&&(voice>=8))
1042  {
1043    poly randp;
1044    for(zz=1;zz<nvars(basering);zz++)
1045    {
1046      randp=randp
1047              +(random(0,5)*par(1)^2+random(0,5)*par(1)+random(0,5))*var(zz);
1048    }
1049    randp=randp+var(nvars(basering));
1050  }
1051  @k=0;
1052  while(@k<(size(primary) div 2))
1053  {
1054    @k++;
1055    if (size(primary[2*@k])==0)
1056    {
1057      for(zz=1;zz<size(primary[2*@k-1])-1;zz++)
1058      {
1059        attrib(primary[2*@k-1],"isSB",1);
1060        if(vdim(primary[2*@k-1])==deg(primary[2*@k-1][zz]))
1061        {
1062          primary[2*@k]=primary[2*@k-1];
1063        }
1064      }
1065    }
1066  }
1067
1068  @k=0;
1069  ideal keep;
1070  while(@k<(size(primary) div 2))
1071  {
1072    @k++;
1073    if (size(primary[2*@k])==0)
1074    {
1075      jmap=randomLast(100);
1076      jmap1=maxideal(1);
1077      jmap2=maxideal(1);
1078      @qht=primary[2*@k-1];
1079      if((npars(basering)>0)&&(voice>=10))
1080      {
1081        jmap[size(jmap)]=randp;
1082      }
1083
1084      for(@n=2;@n<=size(primary[2*@k-1]);@n++)
1085      {
1086        if(deg(lead(primary[2*@k-1][@n]))==1)
1087        {
1088          for(zz=1;zz<=nva;zz++)
1089          {
1090            if(lead(primary[2*@k-1][@n])/var(zz)!=0)
1091            {
1092              jmap1[zz]=-1/leadcoef(primary[2*@k-1][@n])*primary[2*@k-1][@n]
1093                   +2/leadcoef(primary[2*@k-1][@n])*lead(primary[2*@k-1][@n]);
1094              jmap2[zz]=primary[2*@k-1][@n];
1095              @qht[@n]=var(zz);
1096            }
1097          }
1098          jmap[nva]=subst(jmap[nva],lead(primary[2*@k-1][@n]),0);
1099        }
1100      }
1101      if(size(subst(jmap[nva],var(1),0)-var(nva))!=0)
1102      {
1103        // jmap[nva]=subst(jmap[nva],var(1),0);
1104        //hier geaendert +untersuchen!!!!!!!!!!!!!!
1105      }
1106      phi1=@P,jmap1;
1107      phi=@P,jmap;
1108      for(@n=1;@n<=nva;@n++)
1109      {
1110        jmap[@n]=-(jmap[@n]-2*var(@n));
1111      }
1112      psi=@P,jmap;
1113      psi1=@P,jmap2;
1114      @qh=phi(@qht);
1115
1116//=================== the new part ============================
1117
1118      if (npars(basering)>1) { @qh=groebner(@qh,"par2var"); }
1119      else                   { @qh=groebner(@qh); }
1120
1121//=============================================================
1122//       if(npars(@P)>0)
1123//       {
1124//          @ri= "ring @Phelp ="
1125//                  +string(char(@P))+",
1126//                   ("+varstr(@P)+","+parstr(@P)+",@t),(C,dp);";
1127//       }
1128//       else
1129//       {
1130//          @ri= "ring @Phelp ="
1131//                  +string(char(@P))+",("+varstr(@P)+",@t),(C,dp);";
1132//       }
1133//       execute(@ri);
1134//       ideal @qh=homog(imap(@P,@qht),@t);
1135//
1136//       ideal @qh1=std(@qh);
1137//       @hilb=hilb(@qh1,1);
1138//       @ri= "ring @Phelp1 ="
1139//                  +string(char(@P))+",("+varstr(@Phelp)+"),(C,lp);";
1140//       execute(@ri);
1141//       ideal @qh=homog(imap(@P,@qh),@t);
1142//       kill @Phelp;
1143//       @qh=std(@qh,@hilb);
1144//       @qh=subst(@qh,@t,1);
1145//       setring @P;
1146//       @qh=imap(@Phelp1,@qh);
1147//       kill @Phelp1;
1148//       @qh=clearSB(@qh);
1149//       attrib(@qh,"isSB",1);
1150//=============================================================
1151
1152      ser1=phi1(ser);
1153      @lh=zero_decomp (@qh,phi(ser1),@wr);
1154
1155      kill lres0;
1156      list lres0;
1157      if(size(@lh)==2)
1158      {
1159        helpprim=@lh[2];
1160        lres0[1]=primary[2*@k-1];
1161        ser1=psi(helpprim);
1162        lres0[2]=psi1(ser1);
1163        if(size(reduce(lres0[2],lres0[1],1))==0)
1164        {
1165          primary[2*@k]=primary[2*@k-1];
1166          continue;
1167        }
1168      }
1169      else
1170      {
1171        lres1=psi(@lh);
1172        lres0=psi1(lres1);
1173      }
1174
1175//=================== the new part ============================
1176
1177      primary=delete(primary,2*@k-1);
1178      primary=delete(primary,2*@k-1);
1179      @k--;
1180      if(size(lres0)==2)
1181      {
1182        lres0[2]=groebner(lres0[2]);
1183      }
1184      else
1185      {
1186        for(@n=1;@n<=size(lres0) div 2;@n++)
1187        {
1188          if(specialIdealsEqual(lres0[2*@n-1],lres0[2*@n])==1)
1189          {
1190            lres0[2*@n-1]=groebner(lres0[2*@n-1]);
1191            lres0[2*@n]=lres0[2*@n-1];
1192            attrib(lres0[2*@n],"isSB",1);
1193          }
1194          else
1195          {
1196            lres0[2*@n-1]=groebner(lres0[2*@n-1]);
1197            lres0[2*@n]=groebner(lres0[2*@n]);
1198          }
1199        }
1200      }
1201      primary=primary+lres0;
1202
1203//=============================================================
1204//       if(npars(@P)>0)
1205//       {
1206//          @ri= "ring @Phelp ="
1207//                  +string(char(@P))+",
1208//                   ("+varstr(@P)+","+parstr(@P)+",@t),(C,dp);";
1209//       }
1210//       else
1211//       {
1212//          @ri= "ring @Phelp ="
1213//                  +string(char(@P))+",("+varstr(@P)+",@t),(C,dp);";
1214//       }
1215//       execute(@ri);
1216//       list @lvec;
1217//       list @lr=imap(@P,lres0);
1218//       ideal @lr1;
1219//
1220//       if(size(@lr)==2)
1221//       {
1222//          @lr[2]=homog(@lr[2],@t);
1223//          @lr1=std(@lr[2]);
1224//          @lvec[2]=hilb(@lr1,1);
1225//       }
1226//       else
1227//       {
1228//          for(@n=1;@n<=size(@lr) div 2;@n++)
1229//          {
1230//             if(specialIdealsEqual(@lr[2*@n-1],@lr[2*@n])==1)
1231//             {
1232//                @lr[2*@n-1]=homog(@lr[2*@n-1],@t);
1233//                @lr1=std(@lr[2*@n-1]);
1234//                @lvec[2*@n-1]=hilb(@lr1,1);
1235//                @lvec[2*@n]=@lvec[2*@n-1];
1236//             }
1237//             else
1238//             {
1239//                @lr[2*@n-1]=homog(@lr[2*@n-1],@t);
1240//                @lr1=std(@lr[2*@n-1]);
1241//                @lvec[2*@n-1]=hilb(@lr1,1);
1242//                @lr[2*@n]=homog(@lr[2*@n],@t);
1243//                @lr1=std(@lr[2*@n]);
1244//                @lvec[2*@n]=hilb(@lr1,1);
1245//
1246//             }
1247//         }
1248//       }
1249//       @ri= "ring @Phelp1 ="
1250//                  +string(char(@P))+",("+varstr(@Phelp)+"),(C,lp);";
1251//       execute(@ri);
1252//       list @lr=imap(@Phelp,@lr);
1253//
1254//       kill @Phelp;
1255//       if(size(@lr)==2)
1256//      {
1257//          @lr[2]=std(@lr[2],@lvec[2]);
1258//          @lr[2]=subst(@lr[2],@t,1);
1259//       }
1260//       else
1261//       {
1262//          for(@n=1;@n<=size(@lr) div 2;@n++)
1263//          {
1264//             if(specialIdealsEqual(@lr[2*@n-1],@lr[2*@n])==1)
1265//             {
1266//                @lr[2*@n-1]=std(@lr[2*@n-1],@lvec[2*@n-1]);
1267//                @lr[2*@n-1]=subst(@lr[2*@n-1],@t,1);
1268//                @lr[2*@n]=@lr[2*@n-1];
1269//                attrib(@lr[2*@n],"isSB",1);
1270//             }
1271//             else
1272//             {
1273//                @lr[2*@n-1]=std(@lr[2*@n-1],@lvec[2*@n-1]);
1274//                @lr[2*@n-1]=subst(@lr[2*@n-1],@t,1);
1275//                @lr[2*@n]=std(@lr[2*@n],@lvec[2*@n]);
1276//                @lr[2*@n]=subst(@lr[2*@n],@t,1);
1277//             }
1278//          }
1279//       }
1280//       kill @lvec;
1281//       setring @P;
1282//       lres0=imap(@Phelp1,@lr);
1283//       kill @Phelp1;
1284//       for(@n=1;@n<=size(lres0);@n++)
1285//       {
1286//          lres0[@n]=clearSB(lres0[@n]);
1287//          attrib(lres0[@n],"isSB",1);
1288//       }
1289//
1290//       primary[2*@k-1]=lres0[1];
1291//       primary[2*@k]=lres0[2];
1292//       @s=size(primary) div 2;
1293//       for(@n=1;@n<=size(lres0) div 2-1;@n++)
1294//       {
1295//         primary[2*@s+2*@n-1]=lres0[2*@n+1];
1296//         primary[2*@s+2*@n]=lres0[2*@n+2];
1297//       }
1298//       @k--;
1299//=============================================================
1300    }
1301  }
1302  return(primary);
1303}
1304example
1305{ "EXAMPLE:"; echo = 2;
1306   ring  r = 0,(x,y,z),lp;
1307   poly  p = z2+1;
1308   poly  q = z4+2;
1309   ideal i = p^2*q^3,(y-z3)^3,(x-yz+z4)^4;
1310   i=std(i);
1311   list  pr= zero_decomp(i,ideal(0),0);
1312   pr;
1313}
1314///////////////////////////////////////////////////////////////////////////////
1315proc extF(list l,list #)
1316{
1317  ASSUME(0, not isQuotientRing(basering) ) ;
1318  ASSUME(0, hasGlobalOrdering(basering) ) ;
1319//zero_dimensional primary decomposition after finite field extension
1320  def R=basering;
1321  int p=char(R);
1322
1323  if((p==0)||(p>13)||(npars(R)>0)){return(l);}
1324
1325  int ex=3;
1326  if(size(#)>0){ex=#[1];}
1327
1328  list peek,peek1;
1329  while(size(l)>0)
1330  {
1331    if(size(l[2])==0)
1332    {
1333      peek[size(peek)+1]=l[1];
1334    }
1335    else
1336    {
1337      peek1[size(peek1)+1]=l[1];
1338      peek1[size(peek1)+1]=l[2];
1339    }
1340    l=delete(l,1);
1341    l=delete(l,1);
1342  }
1343  if(size(peek)==0){return(peek1);}
1344
1345  string gnir="ring RH=("+string(p)+"^"+string(ex)+",a),("+varstr(R)+"),lp;";
1346  execute(gnir);
1347  string mp="minpoly="+string(minpoly)+";";
1348  gnir="ring RL=("+string(p)+",a),("+varstr(R)+"),lp;";
1349  execute(gnir);
1350  execute(mp);
1351  list L=imap(R,peek);
1352  list pr, keep;
1353  int i;
1354  for(i=1;i<=size(L);i++)
1355  {
1356    attrib(L[i],"isSB",1);
1357    pr=zero_decomp(L[i],0,0);
1358    keep=keep+pr;
1359  }
1360  for(i=1;i<=size(keep);i++)
1361  {
1362    keep[i]=simplify(keep[i],1);
1363  }
1364  mp="poly pp="+string(minpoly)+";";
1365
1366  string gnir1="ring RS="+string(p)+",("+varstr(R)+",a),lp;";
1367  execute(gnir1);
1368  execute(mp);
1369  list L=imap(RL,keep);
1370
1371  for(i=1;i<=size(L);i++)
1372  {
1373    L[i]=eliminate(L[i]+ideal(pp),a);
1374  }
1375  i=0;
1376  int j;
1377  while(i<size(L) div 2-1)
1378  {
1379    i++;
1380    j=i;
1381    while(j<size(L) div 2)
1382    {
1383      j++;
1384      if(idealsEqual(L[2*i-1],L[2*j-1]))
1385      {
1386        L=delete(L,2*j-1);
1387        L=delete(L,2*j-1);
1388        j--;
1389      }
1390    }
1391  }
1392  setring R;
1393  list re=imap(RS,L);
1394  re=re+peek1;
1395
1396  return(extF(re,ex+1));
1397}
1398
1399///////////////////////////////////////////////////////////////////////////////
1400proc zeroSp(ideal i)
1401{
1402//preparation for the separable closure
1403//decomposition into ideals of special type
1404//i.e. the minimal polynomials of every variable mod i are irreducible
1405//returns a list of 2 lists: rr=pe,qe
1406//the ideals in pe[l] are special, their special elements are in qe[l]
1407//pe[l] is a dp-Groebnerbasis
1408//the radical of the intersection of the pe[l] is equal to the radical of i
1409
1410  ASSUME(0, not isQuotientRing(basering) ) ;
1411  ASSUME(0, hasGlobalOrdering(basering) ) ;
1412  def R=basering;
1413
1414  //i has to be a reduced groebner basis
1415  ASSUME(1, dim(i)==0);
1416  ideal F=finduni(i);
1417
1418  int j,k,l,ready;
1419  list fa;
1420  fa[1]=factorize(F[1],1);
1421  poly te,ti;
1422  ideal tj;
1423  //avoid factorization of the same polynomial
1424  for(j=2;j<=size(F);j++)
1425  {
1426    for(k=1;k<=j-1;k++)
1427    {
1428      ti=F[k];
1429      te=subst(ti,var(k),var(j));
1430      if(te==F[j])
1431      {
1432        tj=fa[k];
1433        fa[j]=subst(tj,var(k),var(j));
1434        ready=1;
1435        break;
1436      }
1437    }
1438    if(!ready)
1439    {
1440      fa[j]=factorize(F[j],1);
1441    }
1442    ready=0;
1443  }
1444  execute( "ring P=("+charstr(R)+"),("+varstr(R)+"),(C,dp);");
1445  ideal i=imap(R,i);
1446  if(npars(basering)==0)
1447  {
1448    ideal J=fglm(R,i);
1449  }
1450  else
1451  {
1452    ideal J=groebner(i);
1453  }
1454  list fa=imap(R,fa);
1455  list qe=J;          //collects a dp-Groebnerbasis of the special ideals
1456  list keep=ideal(0); //collects the special elements
1457
1458  list re,em,ke;
1459  ideal K,L;
1460
1461  for(j=1;j<=nvars(basering);j++)
1462  {
1463    for(l=1;l<=size(qe);l++)
1464    {
1465      for(k=1;k<=size(fa[j]);k++)
1466      {
1467        L=std(qe[l],fa[j][k]);
1468        K=keep[l],fa[j][k];
1469        if(deg(L[1])>0)
1470        {
1471          re[size(re)+1]=L;
1472          ke[size(ke)+1]=K;
1473        }
1474      }
1475    }
1476    qe=re;
1477    re=em;
1478    keep=ke;
1479    ke=em;
1480  }
1481
1482  setring R;
1483  list qe=imap(P,keep);
1484  list pe=imap(P,qe);
1485  for(l=1;l<=size(qe);l++)
1486  {
1487    qe[l]=simplify(qe[l],2);
1488  }
1489  list rr=pe,qe;
1490  return(rr);
1491}
1492///////////////////////////////////////////////////////////////////////////////
1493
1494proc zeroSepClos(ideal I,ideal F)
1495{
1496//computes the separable closure of the special ideal I
1497//F is the set of special elements of I
1498//returns the separable closure sc(I) of I and an intvec v
1499//such that sc(I)=preimage(frobenius definde by v)
1500//i.e. var(i)----->var(i)^(p^v[i])
1501
1502  ASSUME(0, not isQuotientRing(basering) ) ;
1503  ASSUME(0, hasGlobalOrdering(basering) ) ;
1504  if(homog(I)==1){return(maxideal(1));}
1505
1506  //assume F[i] irreducible in I and depending only on var(i)
1507
1508  def R=basering;
1509  int n=nvars(R);
1510  int p=char(R);
1511  intvec v;
1512  v[n]=0;
1513  int i,k;
1514  list l;
1515
1516  for(i=1;i<=n;i++)
1517  {
1518    l[i]=sep(F[i],i);
1519    F[i]=l[i][1];
1520    if(l[i][2]>k){k=l[i][2];}
1521  }
1522
1523  if(k==0){return(list(I,v));}        //the separable case
1524  ideal m;
1525
1526  for(i=1;i<=n;i++)
1527  {
1528    m[i]=var(i)^(p^l[i][2]);
1529    v[i]=l[i][2];
1530  }
1531  map phi=R,m;
1532  ideal J=preimage(R,phi,I);
1533  return(list(J,v));
1534}
1535///////////////////////////////////////////////////////////////////////////////
1536
1537proc insepDecomp(ideal i)
1538{
1539//decomposes i into special ideals
1540//computes the prime decomposition of the special ideals
1541//and transforms it back to a decomposition of i
1542 
1543  ASSUME(0, not isQuotientRing(basering) ) ;
1544  ASSUME(0, hasGlobalOrdering(basering) ) ;
1545  def R=basering;
1546  list pr=zeroSp(i);
1547  int l,k;
1548  list re,wo,qr;
1549  ideal m=maxideal(1);
1550  ideal K;
1551  map phi=R,m;
1552  int p=char(R);
1553  intvec op=option(get);
1554
1555  for(l=1;l<=size(pr[1]);l++)
1556  {
1557    wo=zeroSepClos(pr[1][l],pr[2][l]);
1558    for(k=1;k<=nvars(basering);k++)
1559    {
1560      m[k]=var(k)^(p^wo[2][k]);
1561    }
1562    phi=R,m;
1563    qr=decomp(wo[1],2);
1564
1565    option(redSB);
1566    for(k=1;k<=size(qr) div 2;k++)
1567    {
1568      K=qr[2*k];
1569      K=phi(K);
1570      K=groebner(K);
1571      re[size(re)+1]=zeroRad(K);
1572    }
1573    option(noredSB);
1574  }
1575  option(set,op);
1576  return(re);
1577}
1578
1579
1580///////////////////////////////////////////////////////////////////////////////
1581
1582static proc clearSB (ideal i,list #)
1583"USAGE:   clearSB(i); i ideal which is SB ordered by monomial ordering
1584RETURN:  ideal = minimal SB
1585NOTE:
1586EXAMPLE: example clearSB; shows an example
1587"
1588{
1589  ASSUME(0, not isQuotientRing(basering) ) ;
1590  ASSUME(0, hasGlobalOrdering(basering) ) ;
1591  int k,j;
1592  poly m;
1593  int c=size(i);
1594
1595  if(size(#)==0)
1596  {
1597    for(j=1;j<c;j++)
1598    {
1599      if(deg(i[j])==0)
1600      {
1601        i=ideal(1);
1602        return(i);
1603      }
1604      if(deg(i[j])>0)
1605      {
1606        m=lead(i[j]);
1607        for(k=j+1;k<=c;k++)
1608        {
1609          if(size(lead(i[k])/m)>0)
1610          {
1611            i[k]=0;
1612          }
1613        }
1614      }
1615    }
1616  }
1617  else
1618  {
1619    j=0;
1620    while(j<c-1)
1621    {
1622      j++;
1623      if(deg(i[j])==0)
1624      {
1625        i=ideal(1);
1626        return(i);
1627      }
1628      if(deg(i[j])>0)
1629      {
1630        m=lead(i[j]);
1631        for(k=j+1;k<=c;k++)
1632        {
1633          if(size(lead(i[k])/m)>0)
1634          {
1635            if((leadexp(m)!=leadexp(i[k]))||(#[j]<=#[k]))
1636            {
1637              i[k]=0;
1638            }
1639            else
1640            {
1641              i[j]=0;
1642              break;
1643            }
1644          }
1645        }
1646      }
1647    }
1648  }
1649  return(simplify(i,2));
1650}
1651example
1652{ "EXAMPLE:"; echo = 2;
1653   ring  r = (0,a,b),(x,y,z),dp;
1654   ideal i=ax2+y,a2x+y,bx;
1655   list l=1,2,1;
1656   ideal j=clearSB(i,l);
1657   j;
1658}
1659
1660///////////////////////////////////////////////////////////////////////////////
1661static proc clearSBNeu (ideal i,list #)
1662"USAGE:   clearSB(i); i ideal which is SB ordered by monomial ordering
1663RETURN:  ideal = minimal SB
1664NOTE:
1665EXAMPLE: example clearSB; shows an example
1666"
1667{
1668 ASSUME(0, not isQuotientRing(basering) ) ;
1669  ASSUME(0, hasGlobalOrdering(basering) ) ;
1670 int k,j;
1671 intvec m,n,v,w;
1672 int c=size(i);
1673 w=leadexp(0);
1674 v[size(i)]=0;
1675
1676 j=0;
1677 while(j<c-1)
1678 {
1679   j++;
1680   if(deg(i[j])>=0)
1681   {
1682      m=leadexp(i[j]);
1683      for(k=j+1;k<=c;k++)
1684      {
1685        n=leadexp(i[k]);
1686        if(n!=w)
1687        {
1688           if(((m==n)&&(#[j]>#[k]))||((teilt(n,m))&&(n!=m)))
1689           {
1690             i[j]=0;
1691             v[j]=1;
1692             break;
1693           }
1694           if(((m==n)&&(#[j]<=#[k]))||((teilt(m,n))&&(n!=m)))
1695           {
1696             i[k]=0;
1697             v[k]=1;
1698           }
1699        }
1700      }
1701    }
1702  }
1703  return(v);
1704}
1705
1706static proc teilt(intvec a, intvec b)
1707{
1708  int i;
1709  for(i=1;i<=size(a);i++)
1710  {
1711    if(a[i]>b[i]){return(0);}
1712  }
1713  return(1);
1714}
1715///////////////////////////////////////////////////////////////////////////////
1716
1717static proc independSet (ideal j)
1718"USAGE:   independentSet(i); i ideal
1719RETURN:  list = new varstring with the independent set at the end,
1720                ordstring with the corresponding block ordering,
1721                the integer where the independent set starts in the varstring
1722NOTE:
1723EXAMPLE: example independentSet; shows an example
1724"
1725{
1726  int n,k,di;
1727  list resu,hilf;
1728  string var1,var2;
1729  list v=indepSet(j,1);
1730
1731  for(n=1;n<=size(v);n++)
1732  {
1733    di=0;
1734    var1="";
1735    var2="";
1736    for(k=1;k<=size(v[n]);k++)
1737    {
1738      if(v[n][k]!=0)
1739      {
1740        di++;
1741        var2=var2+"var("+string(k)+"),";
1742      }
1743      else
1744      {
1745        var1=var1+"var("+string(k)+"),";
1746      }
1747    }
1748    if(di>0)
1749    {
1750      var1=var1+var2;
1751      var1=var1[1..size(var1)-1];
1752      hilf[1]=var1;
1753      hilf[2]="lp";
1754      //"lp("+string(nvars(basering)-di)+"),dp("+string(di)+")";
1755      hilf[3]=di;
1756      resu[n]=hilf;
1757    }
1758    else
1759    {
1760      resu[n]=varstr(basering),ordstr(basering),0;
1761    }
1762  }
1763  return(resu);
1764}
1765example
1766{ "EXAMPLE:"; echo = 2;
1767   ring s1=(0,x,y),(a,b,c,d,e,f,g),lp;
1768   ideal i=ea-fbg,fa+be,ec-fdg,fc+de;
1769   i=std(i);
1770   list  l=independSet(i);
1771   l;
1772   i=i,g;
1773   l=independSet(i);
1774   l;
1775
1776   ring s=0,(x,y,z),lp;
1777   ideal i=z,yx;
1778   list l=independSet(i);
1779   l;
1780
1781
1782}
1783///////////////////////////////////////////////////////////////////////////////
1784
1785static proc maxIndependSet (ideal j)
1786"USAGE:   maxIndependentSet(i); i ideal
1787RETURN:  list = new varstring with the maximal independent set at the end,
1788                ordstring with the corresponding block ordering,
1789                the integer where the independent set starts in the varstring
1790NOTE:
1791EXAMPLE: example maxIndependentSet; shows an example
1792"
1793{
1794  ASSUME(0, not isQuotientRing(basering) ) ;
1795  ASSUME(0, hasGlobalOrdering(basering) ) ;
1796  int n,k,di;
1797  list resu,hilf;
1798  string var1,var2;
1799  list v=indepSet(j,0);
1800
1801  for(n=1;n<=size(v);n++)
1802  {
1803    di=0;
1804    var1="";
1805    var2="";
1806    for(k=1;k<=size(v[n]);k++)
1807    {
1808      if(v[n][k]!=0)
1809      {
1810        di++;
1811        var2=var2+"var("+string(k)+"),";
1812      }
1813      else
1814      {
1815        var1=var1+"var("+string(k)+"),";
1816      }
1817    }
1818    if(di>0)
1819    {
1820      var1=var1+var2;
1821      var1=var1[1..size(var1)-1];
1822      hilf[1]=var1;
1823      hilf[2]="lp";
1824      hilf[3]=di;
1825      resu[n]=hilf;
1826    }
1827    else
1828    {
1829      resu[n]=varstr(basering),ordstr(basering),0;
1830    }
1831  }
1832  return(resu);
1833}
1834example
1835{ "EXAMPLE:"; echo = 2;
1836   ring s1=(0,x,y),(a,b,c,d,e,f,g),lp;
1837   ideal i=ea-fbg,fa+be,ec-fdg,fc+de;
1838   i=std(i);
1839   list  l=maxIndependSet(i);
1840   l;
1841   i=i,g;
1842   l=maxIndependSet(i);
1843   l;
1844
1845   ring s=0,(x,y,z),lp;
1846   ideal i=z,yx;
1847   list l=maxIndependSet(i);
1848   l;
1849
1850
1851}
1852
1853///////////////////////////////////////////////////////////////////////////////
1854
1855static proc prepareQuotientring (int nnp)
1856"USAGE:   prepareQuotientring(nnp); nnp int
1857RETURN:  string = to define Kvar(nnp+1),...,var(nvars)[..rest ]
1858NOTE:
1859EXAMPLE: example independentSet; shows an example
1860"
1861{
1862  ASSUME(0, not isQuotientRing(basering) ) ;
1863  ASSUME(0, hasGlobalOrdering(basering) ) ;
1864  ideal @ih,@jh;
1865  int npar=npars(basering);
1866  int @n;
1867
1868  string quotring= "ring quring = ("+charstr(basering);
1869  for(@n=nnp+1;@n<=nvars(basering);@n++)
1870  {
1871     quotring=quotring+",var("+string(@n)+")";
1872     @ih=@ih+var(@n);
1873  }
1874
1875  quotring=quotring+"),(var(1)";
1876  @jh=@jh+var(1);
1877  for(@n=2;@n<=nnp;@n++)
1878  {
1879    quotring=quotring+",var("+string(@n)+")";
1880    @jh=@jh+var(@n);
1881  }
1882  quotring=quotring+"),(C,lp);";
1883
1884  return(quotring);
1885
1886}
1887example
1888{ "EXAMPLE:"; echo = 2;
1889   ring s1=(0,x),(a,b,c,d,e,f,g),lp;
1890   def @Q=basering;
1891   list l= prepareQuotientring(3);
1892   l;
1893   execute(l[1]);
1894   execute(l[2]);
1895   basering;
1896   phi;
1897   setring @Q;
1898
1899}
1900
1901///////////////////////////////////////////////////////////////////////////////
1902static proc cleanPrimary(list l)
1903{
1904   int i,j;
1905   list lh;
1906   for(i=1;i<=size(l) div 2;i++)
1907   {
1908      if(deg(l[2*i-1][1])>0)
1909      {
1910         j++;
1911         lh[j]=l[2*i-1];
1912         j++;
1913         lh[j]=l[2*i];
1914      }
1915   }
1916   return(lh);
1917}
1918///////////////////////////////////////////////////////////////////////////////
1919
1920
1921proc minAssPrimesold(ideal i, list #)
1922"USAGE:   minAssPrimes(i); i ideal
1923         minAssPrimes(i,1); i ideal  (to use also the factorizing Groebner)
1924RETURN:  list = the minimal associated prime ideals of i
1925EXAMPLE: example minAssPrimes; shows an example
1926"
1927{
1928   ASSUME(0, not isQuotientRing(basering) ) ;
1929  ASSUME(0, hasGlobalOrdering(basering) ) ;
1930   def @P=basering;
1931   if(size(i)==0){return(list(ideal(0)));}
1932   list qr=simplifyIdeal(i);
1933   map phi=@P,qr[2];
1934   i=qr[1];
1935
1936   execute ("ring gnir = ("+charstr(basering)+"),("+varstr(basering)+"),("
1937             +ordstr(basering)+");");
1938
1939
1940   ideal i=fetch(@P,i);
1941   if(size(#)==0)
1942   {
1943      int @wr;
1944      list tluser,@res;
1945      list primary=decomp(i,2);
1946
1947      @res[1]=primary;
1948
1949      tluser=union(@res);
1950      setring @P;
1951      list @res=imap(gnir,tluser);
1952      return(phi(@res));
1953   }
1954   list @res,empty;
1955   ideal ser;
1956   def op = option( get );
1957   option( redSB );
1958   list @pr=facstd(i);
1959   //if(size(@pr)==1)
1960//   {
1961//      attrib(@pr[1],"isSB",1);
1962//      if((dim(@pr[1])==0)&&(homog(@pr[1])==1))
1963//      {
1964//         setring @P;
1965//         list @res=maxideal(1);
1966//         return(phi(@res));
1967//      }
1968//      if(dim(@pr[1])>1)
1969//      {
1970//         setring @P;
1971//        // kill gnir;
1972//         execute ("ring gnir1 = ("+charstr(basering)+"),
1973//                              ("+varstr(basering)+"),(C,lp);");
1974//         ideal i=fetch(@P,i);
1975//         list @pr=facstd(i);
1976//        // ideal ser;
1977//         setring gnir;
1978//         @pr=fetch(gnir1,@pr);
1979//         kill gnir1;
1980//      }
1981//   }
1982   // option( noredSB );
1983   option( set, op );
1984   int j,k,odim,ndim,count;
1985   attrib(@pr[1],"isSB",1);
1986   if(#[1]==77)
1987   {
1988     odim=dim(@pr[1]);
1989     count=1;
1990     intvec pos;
1991     pos[size(@pr)]=0;
1992     for(j=2;j<=size(@pr);j++)
1993     {
1994        attrib(@pr[j],"isSB",1);
1995        ndim=dim(@pr[j]);
1996        if(ndim>odim)
1997        {
1998           for(k=count;k<=j-1;k++)
1999           {
2000              pos[k]=1;
2001           }
2002           count=j;
2003           odim=ndim;
2004        }
2005        if(ndim<odim)
2006        {
2007           pos[j]=1;
2008        }
2009     }
2010     for(j=1;j<=size(@pr);j++)
2011     {
2012        if(pos[j]!=1)
2013        {
2014            @res[j]=decomp(@pr[j],2);
2015        }
2016        else
2017        {
2018           @res[j]=empty;
2019        }
2020     }
2021   }
2022   else
2023   {
2024     ser=ideal(1);
2025     for(j=1;j<=size(@pr);j++)
2026     {
2027//@pr[j];
2028//pause();
2029        @res[j]=decomp(@pr[j],2);
2030//       @res[j]=decomp(@pr[j],2,@pr[j],ser);
2031//       for(k=1;k<=size(@res[j]);k++)
2032//       {
2033//          ser=intersect(ser,@res[j][k]);
2034//       }
2035     }
2036   }
2037
2038   @res=union(@res);
2039   setring @P;
2040   list @res=imap(gnir,@res);
2041   return(phi(@res));
2042}
2043example
2044{ "EXAMPLE:"; echo = 2;
2045   ring  r = 32003,(x,y,z),lp;
2046   poly  p = z2+1;
2047   poly  q = z4+2;
2048   ideal i = p^2*q^3,(y-z3)^3,(x-yz+z4)^4;
2049   list pr= minAssPrimes(i);  pr;
2050
2051   minAssPrimes(i,1);
2052}
2053
2054static proc primT(ideal i)
2055{
2056   ASSUME(0, not isQuotientRing(basering) ) ;
2057  ASSUME(0, hasGlobalOrdering(basering) ) ;
2058
2059   //assumes that all generators of i are irreducible
2060   //i is standard basis
2061
2062   attrib(i,"isSB",1);
2063   int j=size(i);
2064   int k;
2065   while(j>0)
2066   {
2067     if(deg(i[j])>1){break;}
2068     j--;
2069   }
2070   if(j==0){return(1);}
2071   if(deg(i[j])==vdim(i)){return(1);}
2072   return(0);
2073}
2074
2075static proc minAssPrimes(ideal i, list #)
2076"USAGE:   minAssPrimes(i); i ideal
2077      Optional parameters in list #: (can be entered in any order)
2078      0, "facstd"   ->   uses facstd to first decompose the ideal
2079      1, "noFacstd" ->  does not use facstd (default)
2080      "SL" ->     the new algorithm is used (default)
2081      "GTZ" ->     the old algorithm is used
2082RETURN:  list = the minimal associated prime ideals of i
2083EXAMPLE: example minAssPrimes; shows an example
2084"
2085{
2086  ASSUME(0, not isQuotientRing(basering) ) ;
2087  ASSUME(0, hasGlobalOrdering(basering) ) ;
2088
2089  if(size(i) == 0){return(list(ideal(0)));}
2090  string algorithm;    // Algorithm to be used
2091  string facstdOption;    // To uses proc facstd
2092  int j;          // Counter
2093  def P0 = basering;
2094  list Pl=ringlist(P0);
2095  intvec dp_w;
2096  for(j=nvars(P0);j>0;j--) {dp_w[j]=1;}
2097  Pl[3]=list(list("dp",dp_w),list("C",0));
2098  def P=ring(Pl);
2099  setring P;
2100  ideal i=imap(P0,i);
2101
2102  // Set input parameters
2103  algorithm = "SL";         // Default: SL algorithm
2104  facstdOption = "Facstd";    // Default: facstd is not used
2105  if(size(#) > 0)
2106  {
2107    int valid;
2108    for(j = 1; j <= size(#); j++)
2109    {
2110      valid = 0;
2111      if((typeof(#[j]) == "int") or (typeof(#[j]) == "number"))
2112      {
2113        if (#[j] == 0) {facstdOption = "noFacstd"; valid = 1;}    // If #[j] == 0, facstd is not used.
2114        if (#[j] == 1) {facstdOption = "facstd";   valid = 1;}    // If #[j] == 1, facstd is used.
2115      }
2116      if(typeof(#[j]) == "string")
2117      {
2118        if(#[j] == "GTZ" || #[j] == "SL")
2119        {
2120          algorithm = #[j];
2121          valid = 1;
2122        }
2123        if(#[j] == "noFacstd" || #[j] == "facstd")
2124        {
2125          facstdOption = #[j];
2126          valid = 1;
2127        }
2128      }
2129      if(valid == 0)
2130      {
2131        dbprint(1, "Warning! The following input parameter was not recognized:", #[j]);
2132      }
2133    }
2134  }
2135
2136  list q = simplifyIdeal(i);
2137  list re = maxideal(1);
2138  int a, k;
2139  intvec op = option(get);
2140  map phi = P,q[2];
2141
2142  list result;
2143
2144  if(npars(P) == 0){option(redSB);}
2145
2146  if(attrib(i,"isSB")!=1)
2147  {
2148    i=groebner(q[1]);
2149  }
2150  else
2151  {
2152    for(j=1;j<=nvars(basering);j++)
2153    {
2154      if(q[2][j]!=var(j)){k=1;break;}
2155    }
2156    if(k)
2157    {
2158      i=groebner(q[1]);
2159    }
2160  }
2161
2162  if( dim(i) == -1 )
2163  {
2164    option( set,op );
2165    setring P0;
2166    return( ideal(1) );
2167  }
2168  if( (dim(i) == 0 ) && ( npars(P) == 0) )
2169  {
2170    int di = vdim(i);
2171    execute ("ring gnir=("+charstr(P)+"),("+varstr(P)+"),lp;");
2172    ideal J = std(imap(P,i));
2173    attrib(J, "isSB", 1);
2174    if(vdim(J) != di)
2175    {
2176      J = fglm(P, i);
2177    }
2178//    list pr = triangMH(J,2); HIER KOENNEN verschiedene Mengen zu gleichen
2179//                             asoziierten Primidealen fuehren
2180// Aenderung
2181    list pr = triangMH(J,2);
2182    list qr, re;
2183    for(k = 1; k <= size(pr); k++)
2184    {
2185      if(primT(pr[k])&&(0))
2186      {
2187        re[size(re) + 1] = pr[k];
2188      }
2189      else
2190      {
2191        attrib(pr[k], "isSB", 1);
2192        // Lines changed
2193        if (algorithm == "GTZ")
2194        {
2195          qr = decomp(pr[k], 2);
2196        }
2197        else
2198        {
2199          qr = minAssSL(pr[k]);
2200        }
2201        for(j = 1; j <= size(qr) div 2; j++)
2202        {
2203          re[size(re) + 1] = std(qr[2 * j]);
2204        }
2205      }
2206    }
2207    setring P;
2208    re = imap(gnir, re);
2209    re=phi(re);
2210    option(set, op);
2211    setring(P0);
2212    list re=imap(P,re);
2213    return(re);
2214  }
2215
2216  // Lines changed
2217  if ((facstdOption == "noFacstd") || (dim(i) == 0))
2218  {
2219    if (algorithm == "GTZ")
2220    {
2221      re[1] = decomp(i, 2);
2222    }
2223    else
2224    {
2225      re[1] = minAssSL(i);
2226    }
2227    re = union(re);
2228    option(set, op);
2229    re=phi(re);
2230    setring(P0);
2231    list re=imap(P,re);
2232    return(re);
2233  }
2234  q = facstd(i);
2235
2236/*
2237  if((size(q) == 1) && (dim(i) > 1))
2238  {
2239    execute ("ring gnir=("+charstr(P)+"),("+varstr(P)+"),lp;");
2240    list p = facstd(fetch(P, i));
2241    if(size(p) > 1)
2242    {
2243      a = 1;
2244      setring P;
2245      q = fetch(gnir,p);
2246    }
2247    else
2248    {
2249      setring P;
2250    }
2251    kill gnir;
2252  }
2253*/
2254  option(set,op);
2255  // Debug
2256  dbprint(printlevel - voice, "Components returned by facstd", size(q), q);
2257  for(j = 1; j <= size(q); j++)
2258  {
2259    if(a == 0){attrib(q[j], "isSB", 1);}
2260    // Debug
2261    dbprint(printlevel - voice, "We compute the decomp of component", j);
2262    // Lines changed
2263    if (algorithm == "GTZ")
2264    {
2265      re[j] = decomp(q[j], 2);
2266    }
2267    else
2268    {
2269      re[j] = minAssSL(q[j]);
2270    }
2271    // Debug
2272    dbprint(printlevel - voice, "Number of components obtained for this component:", size(re[j]) div 2);
2273    dbprint(printlevel - voice, "re[j]:", re[j]);
2274  }
2275  re = union(re);
2276  re=phi(re);
2277  setring(P0);
2278  list re=imap(P,re);
2279  return(re);
2280}
2281example
2282{ "EXAMPLE:"; echo = 2;
2283   ring  r = 32003,(x,y,z),lp;
2284   poly  p = z2+1;
2285   poly  q = z4+2;
2286   ideal i = p^2*q^3,(y-z3)^3,(x-yz+z4)^4;
2287   list pr= minAssPrimes(i);  pr;
2288
2289   minAssPrimes(i,1);
2290}
2291
2292static proc union(list li)
2293{
2294  int i,j,k;
2295
2296  def P=basering;
2297
2298  execute("ring ir = ("+charstr(basering)+"),("+varstr(basering)+"),(C,lp);");
2299  list l=fetch(P,li);
2300  list @erg;
2301
2302  for(k=1;k<=size(l);k++)
2303  {
2304     for(j=1;j<=size(l[k]) div 2;j++)
2305     {
2306        if(deg(l[k][2*j][1])!=0)
2307        {
2308           i++;
2309           @erg[i]=l[k][2*j];
2310        }
2311     }
2312  }
2313
2314  list @wos;
2315  i=0;
2316  ideal i1,i2;
2317  while(i<size(@erg)-1)
2318  {
2319     i++;
2320     k=i+1;
2321     i1=lead(@erg[i]);
2322      attrib(i1,"isSB",1);
2323      attrib(@erg[i],"isSB",1);
2324
2325     while(k<=size(@erg))
2326     {
2327        if(deg(@erg[i][1])==0)
2328        {
2329           break;
2330        }
2331        i2=lead(@erg[k]);
2332        attrib(@erg[k],"isSB",1);
2333        attrib(i2,"isSB",1);
2334
2335        if(size(reduce(i1,i2,1))==0)
2336        {
2337           if(size(reduce(@erg[i],@erg[k],1))==0)
2338           {
2339              @erg[k]=ideal(1);
2340              i2=ideal(1);
2341           }
2342        }
2343        if(size(reduce(i2,i1,1))==0)
2344        {
2345           if(size(reduce(@erg[k],@erg[i],1))==0)
2346           {
2347              break;
2348           }
2349        }
2350        k++;
2351        if(k>size(@erg))
2352        {
2353           @wos[size(@wos)+1]=@erg[i];
2354        }
2355     }
2356  }
2357  if(deg(@erg[size(@erg)][1])!=0)
2358  {
2359     @wos[size(@wos)+1]=@erg[size(@erg)];
2360  }
2361  setring P;
2362  list @ser=fetch(ir,@wos);
2363  return(@ser);
2364}
2365///////////////////////////////////////////////////////////////////////////////
2366proc equidim(ideal i,list #)
2367"USAGE:  equidim(i) or equidim(i,1) ; i ideal
2368RETURN: list of equidimensional ideals a[1],...,a[s] with:
2369        - a[s] the equidimensional locus of i, i.e. the intersection
2370          of the primary ideals of dimension of i
2371        - a[1],...,a[s-1] the lower dimensional equidimensional loci.
2372NOTE:    An embedded component q (primary ideal) of i can be replaced in the
2373         decomposition by a primary ideal q1 with the same radical as q. @*
2374         @code{equidim(i,1)} uses the algorithm of Eisenbud/Huneke/Vasconcelos.
2375
2376EXAMPLE:example equidim; shows an example
2377"
2378{
2379
2380  ASSUME(0, not isQuotientRing(basering) ) ;
2381  if(attrib(basering,"global")!=1)
2382  {
2383      ERROR(
2384      "// Not implemented for this ordering, please change to global ordering."
2385      );
2386  }
2387  ASSUME(0, hasGlobalOrdering(basering) ) ;
2388
2389  intvec op ;
2390  def  P = basering;
2391  list eq;
2392  intvec w;
2393  int n,m;
2394  int g=size(i);
2395  int a=attrib(i,"isSB");
2396  int homo=homog(i);
2397  if(size(#)!=0)
2398  {
2399     m=1;
2400  }
2401
2402  if(((homo==1)||(a==1))&&(find(ordstr(basering),"l")==0)
2403                                &&(find(ordstr(basering),"s")==0))
2404  {
2405     execute("ring gnir = ("+charstr(basering)+"),("+varstr(basering)+"),("
2406                              +ordstr(basering)+");");
2407     ideal i=imap(P,i);
2408     ideal j=i;
2409     if(a==1)
2410     {
2411       attrib(j,"isSB",1);
2412     }
2413     else
2414     {
2415       j=groebner(i);
2416     }
2417  }
2418  else
2419  {
2420     execute("ring gnir = ("+charstr(basering)+"),("+varstr(basering)+"),dp;");
2421     ideal i=imap(P,i);
2422     ideal j=groebner(i);
2423  }
2424  if(homo==1)
2425  {
2426     for(n=1;n<=nvars(basering);n++)
2427     {
2428        w[n]=ord(var(n));
2429     }
2430     intvec hil=hilb(j,1,w);
2431  }
2432
2433  if ((dim(j)==-1)||(size(j)==0)||(nvars(basering)==1)
2434                  ||(dim(j)==0)||(dim(j)+g==nvars(basering)))
2435  {
2436    setring P;
2437    eq[1]=i;
2438    return(eq);
2439  }
2440
2441  if(m==0)
2442  {
2443     ideal k=equidimMax(j);
2444  }
2445  else
2446  {
2447     ideal k=equidimMaxEHV(j);
2448  }
2449  if(size(reduce(k,j,1))==0)
2450  {
2451    setring P;
2452    eq[1]=i;
2453    kill gnir;
2454    return(eq);
2455  }
2456  op=option(get);
2457  option(returnSB);
2458  j=quotient(j,k);
2459  option(set,op);
2460
2461  list equi=equidim(j);
2462  if(deg(equi[size(equi)][1])<=0)
2463  {
2464      equi[size(equi)]=k;
2465  }
2466  else
2467  {
2468    equi[size(equi)+1]=k;
2469  }
2470  setring P;
2471  eq=imap(gnir,equi);
2472  kill gnir;
2473  return(eq);
2474}
2475example
2476{ "EXAMPLE:"; echo = 2;
2477   ring  r = 32003,(x,y,z),dp;
2478   ideal i = intersect(ideal(z),ideal(x,y),ideal(x2,z2),ideal(x5,y5,z5));
2479   equidim(i);
2480}
2481
2482///////////////////////////////////////////////////////////////////////////////
2483proc equidimMax(ideal i)
2484"USAGE:  equidimMax(i); i ideal
2485RETURN:  ideal of equidimensional locus (of maximal dimension) of i.
2486EXAMPLE: example equidimMax; shows an example
2487"
2488{
2489  ASSUME(0, not isQuotientRing(basering) ) ;
2490  if(attrib(basering,"global")!=1)
2491  {
2492      ERROR(
2493      "// Not implemented for this ordering, please change to global ordering."
2494      );
2495  }
2496  ASSUME(0, hasGlobalOrdering(basering) ) ;
2497
2498  def  P = basering;
2499  ideal eq;
2500  intvec w;
2501  int n;
2502  int g=size(i);
2503  int a=attrib(i,"isSB");
2504  int homo=homog(i);
2505
2506  if(((homo==1)||(a==1))&&(find(ordstr(basering),"l")==0)
2507                                &&(find(ordstr(basering),"s")==0))
2508  {
2509     execute("ring gnir = ("+charstr(basering)+"),("+varstr(basering)+"),("
2510                              +ordstr(basering)+");");
2511     ideal i=imap(P,i);
2512     ideal j=i;
2513     if(a==1)
2514     {
2515       attrib(j,"isSB",1);
2516     }
2517     else
2518     {
2519       j=groebner(i);
2520     }
2521  }
2522  else
2523  {
2524     execute("ring gnir = ("+charstr(basering)+"),("+varstr(basering)+"),dp;");
2525     ideal i=imap(P,i);
2526     ideal j=groebner(i);
2527  }
2528  list indep;
2529  ideal equ,equi;
2530  if(homo==1)
2531  {
2532     for(n=1;n<=nvars(basering);n++)
2533     {
2534        w[n]=ord(var(n));
2535     }
2536     intvec hil=hilb(j,1,w);
2537  }
2538  if ((dim(j)==-1)||(size(j)==0)||(nvars(basering)==1)
2539                  ||(dim(j)==0)||(dim(j)+g==nvars(basering)))
2540  {
2541    setring P;
2542    return(i);
2543  }
2544
2545  indep=maxIndependSet(j);
2546
2547  execute("ring gnir1 = ("+charstr(basering)+"),("+indep[1][1]+"),("
2548                              +indep[1][2]+");");
2549  if(homo==1)
2550  {
2551     ideal j=std(imap(gnir,j),hil,w);
2552  }
2553  else
2554  {
2555     ideal j=groebner(imap(gnir,j));
2556  }
2557  string quotring=prepareQuotientring(nvars(basering)-indep[1][3]);
2558  execute(quotring);
2559  ideal j=imap(gnir1,j);
2560  kill gnir1;
2561  j=clearSB(j);
2562  ideal h;
2563  for(n=1;n<=size(j);n++)
2564  {
2565     h[n]=leadcoef(j[n]);
2566  }
2567  setring gnir;
2568  ideal h=imap(quring,h);
2569  kill quring;
2570
2571  list l=minSat(j,h);
2572
2573  if(deg(l[2])>0)
2574  {
2575    equ=l[1];
2576    attrib(equ,"isSB",1);
2577    j=std(j,l[2]);
2578
2579    if(dim(equ)==dim(j))
2580    {
2581      equi=equidimMax(j);
2582      equ=interred(intersect(equ,equi));
2583    }
2584  }
2585  else
2586  {
2587    equ=i;
2588  }
2589
2590  setring P;
2591  eq=imap(gnir,equ);
2592  kill gnir;
2593  return(eq);
2594}
2595example
2596{ "EXAMPLE:"; echo = 2;
2597   ring  r = 32003,(x,y,z),dp;
2598   ideal i = intersect(ideal(z),ideal(x,y),ideal(x2,z2),ideal(x5,y5,z5));
2599   equidimMax(i);
2600}
2601///////////////////////////////////////////////////////////////////////////////
2602static proc islp()
2603{
2604   string s=ordstr(basering);
2605   int n=find(s,"lp");
2606   if(!n){return(0);}
2607   int k=find(s,",");
2608   string t=s[k+1..size(s)];
2609   int l=find(t,",");
2610   t=s[1..k-1];
2611   int m=find(t,",");
2612   if(l+m){return(0);}
2613   return(1);
2614}
2615///////////////////////////////////////////////////////////////////////////////
2616
2617proc algeDeco(ideal i, int w)
2618{
2619   ASSUME(0, not isQuotientRing(basering) ) ;
2620  ASSUME(0, hasGlobalOrdering(basering) ) ;
2621
2622//reduces primery decomposition over algebraic extensions to
2623//the other cases
2624   def R=basering;
2625   int n=nvars(R);
2626
2627   def op = option(get);
2628
2629//---Anfang Provisorium
2630   if((size(i)==2) && (w==2))
2631   {
2632      option( redSB );
2633      ideal J = std(i);
2634      option( noredSB );
2635      if ((size(J)==2)&&(deg(J[1])==1))
2636      {
2637         ideal keep;
2638         poly f;
2639         int j;
2640         for(j=1;j<=nvars(basering);j++)
2641         {
2642           f=J[2];
2643           while((f/var(j))*var(j)-f==0)
2644           {
2645             f=f/var(j);
2646             keep=keep,var(j);
2647           }
2648           J[2]=f;
2649         }
2650         ideal K=factorize(J[2],1);
2651         if(deg(K[1])==0){K=0;}
2652         K=K+std(keep);
2653         ideal L;
2654         list resu;
2655         for(j=1;j<=size(K);j++)
2656         {
2657            L=J[1],K[j];
2658            resu[j]=L;
2659         }
2660         option( set, op );
2661         return(resu);
2662      }
2663   }
2664//---Ende Provisorium
2665   string mp="poly p="+string(minpoly)+";";
2666   string gnir="ring RH="+string(char(R))+",("+varstr(R)+","+string(par(1))
2667                +"),dp;";
2668   execute(gnir);
2669   execute(mp);
2670   ideal i=imap(R,i);
2671   ideal I=subst(i,var(nvars(basering)),0);
2672   int j;
2673   for(j=1;j<=ncols(i);j++)
2674   {
2675     if(i[j]!=I[j]){break;}
2676   }
2677   if((j>ncols(i))&&(deg(p)==1))
2678   {
2679     setring R;
2680     kill RH;
2681     kill gnir;
2682     string gnir="ring RH="+string(char(R))+",("+varstr(R)+"),dp;";
2683     execute(gnir);
2684     ideal i=imap(R,i);
2685     ideal J;
2686   }
2687   else
2688   {
2689      i=i,p;
2690   }
2691   list pr;
2692
2693   if(w==0)
2694   {
2695      pr=decomp(i);
2696   }
2697   if(w==1)
2698   {
2699      pr=prim_dec(i,1);
2700      pr=reconvList(pr);
2701   }
2702   if(w==2)
2703   {
2704      pr=minAssPrimes(i);
2705   }
2706   if(n<nvars(basering))
2707   {
2708      gnir="ring RS="+string(char(R))+",("+varstr(RH)
2709                +"),(dp("+string(n)+"),lp);";
2710      execute(gnir);
2711      list pr=imap(RH,pr);
2712      ideal K;
2713      for(j=1;j<=size(pr);j++)
2714      {
2715         K=groebner(pr[j]);
2716         K=K[2..size(K)];
2717         pr[j]=K;
2718      }
2719      setring R;
2720      list pr=imap(RS,pr);
2721   }
2722   else
2723   {
2724      setring R;
2725      list pr=imap(RH,pr);
2726   }
2727   list re;
2728   if(w==2)
2729   {
2730      re=pr;
2731   }
2732   else
2733   {
2734      re=convList(pr);
2735   }
2736   option( set, op );
2737   return( re );
2738}
2739///////////////////////////////////////////////////////////////////////////////
2740static proc prepare_absprimdec(list primary)
2741{
2742  ASSUME(0, not isQuotientRing(basering) ) ;
2743  ASSUME(0, hasGlobalOrdering(basering) ) ;
2744
2745  list resu,tempo;
2746  string absotto;
2747  resu[size(primary) div 2]=list();
2748  for(int ab=1;ab<=size(primary) div 2;ab++)
2749  {
2750    absotto= absFactorize(primary[2*ab][1],77);
2751    tempo=primary[2*ab-1],primary[2*ab],absotto,string(var(nvars(basering)));
2752    resu[ab]=tempo;
2753  }
2754  return(resu);
2755}
2756///////////////////////////////////////////////////////////////////////////////
2757static proc decomp(ideal i,list #)
2758"USAGE:  decomp(i); i ideal  (for primary decomposition)   (resp.
2759         decomp(i,1);        (for the associated primes of dimension of i) )
2760         decomp(i,2);        (for the minimal associated primes) )
2761         decomp(i,3);        (for the absolute primary decomposition) )
2762RETURN:  list = list of primary ideals and their associated primes
2763         (at even positions in the list)
2764         (resp. a list of the minimal associated primes)
2765NOTE:    Algorithm of Gianni/Trager/Zacharias
2766EXAMPLE: example decomp; shows an example
2767"
2768{
2769  ASSUME(0, not isQuotientRing(basering) ) ;
2770  ASSUME(0, hasGlobalOrdering(basering) ) ;
2771
2772  intvec op,@vv;
2773  def  @P = basering;
2774  list primary,indep,ltras;
2775  intvec @vh,isat,@w;
2776  int @wr,@k,@n,@m,@n1,@n2,@n3,homo,seri,keepdi,abspri,ab,nn;
2777  ideal peek=i;
2778  ideal ser,tras;
2779  int isS=(attrib(i,"isSB")==1);
2780
2781
2782  if(size(#)>0)
2783  {
2784    if((#[1]==1)||(#[1]==2)||(#[1]==3))
2785    {
2786      @wr=#[1];
2787      if(@wr==3){abspri=1;@wr=0;}
2788      if(size(#)>1)
2789      {
2790        seri=1;
2791        peek=#[2];
2792        ser=#[3];
2793      }
2794    }
2795    else
2796    {
2797      seri=1;
2798      peek=#[1];
2799      ser=#[2];
2800    }
2801  }
2802  if(abspri)
2803  {
2804    list absprimary,abskeep,absprimarytmp,abskeeptmp;
2805  }
2806  homo=homog(i);
2807  if(homo==1)
2808  {
2809    if(attrib(i,"isSB")!=1)
2810    {
2811      //ltras=mstd(i);
2812      tras=groebner(i);
2813      ltras=tras,tras;
2814      attrib(ltras[1],"isSB",1);
2815    }
2816    else
2817    {
2818      ltras=i,i;
2819      attrib(ltras[1],"isSB",1);
2820    }
2821    tras=ltras[1];
2822    attrib(tras,"isSB",1);
2823    if((dim(tras)==0) && (!abspri))
2824    {
2825      primary[1]=ltras[2];
2826      primary[2]=maxideal(1);
2827      if(@wr>0)
2828      {
2829        list l;
2830        l[1]=maxideal(1);
2831        l[2]=maxideal(1);
2832        return(l);
2833      }
2834      return(primary);
2835    }
2836    for(@n=1;@n<=nvars(basering);@n++)
2837    {
2838      @w[@n]=ord(var(@n));
2839    }
2840    intvec @hilb=hilb(tras,1,@w);
2841    intvec keephilb=@hilb;
2842  }
2843
2844  //----------------------------------------------------------------
2845  //i is the zero-ideal
2846  //----------------------------------------------------------------
2847
2848  if(size(i)==0)
2849  {
2850    primary=ideal(0),ideal(0);
2851    if (abspri) { return(prepare_absprimdec(primary));}
2852    return(primary);
2853  }
2854
2855  //----------------------------------------------------------------
2856  //pass to the lexicographical ordering and compute a standardbasis
2857  //----------------------------------------------------------------
2858
2859  int lp=islp();
2860
2861  execute("ring gnir = ("+charstr(basering)+"),("+varstr(basering)+"),(C,lp);");
2862  op=option(get);
2863  option(redSB);
2864
2865  ideal ser=fetch(@P,ser);
2866
2867  if(homo==1)
2868  {
2869    if(!lp)
2870    {
2871      ideal @j=std(fetch(@P,i),@hilb,@w);
2872    }
2873    else
2874    {
2875      ideal @j=fetch(@P,tras);
2876      attrib(@j,"isSB",1);
2877    }
2878  }
2879  else
2880  {
2881    if(lp&&isS)
2882    {
2883      ideal @j=fetch(@P,i);
2884      attrib(@j,"isSB",1);
2885    }
2886    else
2887    {
2888      ideal @j=groebner(fetch(@P,i));
2889    }
2890  }
2891  option(set,op);
2892  if(seri==1)
2893  {
2894    ideal peek=fetch(@P,peek);
2895    attrib(peek,"isSB",1);
2896  }
2897  else
2898  {
2899    ideal peek=@j;
2900  }
2901  if((size(ser)==0)&&(!abspri))
2902  {
2903    ideal fried;
2904    @n=size(@j);
2905    for(@k=1;@k<=@n;@k++)
2906    {
2907      if(deg(lead(@j[@k]))==1)
2908      {
2909        fried[size(fried)+1]=@j[@k];
2910        @j[@k]=0;
2911      }
2912    }
2913    if(size(fried)==nvars(basering))
2914    {
2915      setring @P;
2916      primary[1]=i;
2917      primary[2]=i;
2918      if (abspri) { return(prepare_absprimdec(primary));}
2919      return(primary);
2920    }
2921    if(size(fried)>0)
2922    {
2923      string newva;
2924      string newma;
2925      poly f;
2926      for(@k=1;@k<=nvars(basering);@k++)
2927      {
2928        @n1=0;
2929        for(@n=1;@n<=size(fried);@n++)
2930        {
2931          if(leadmonom(fried[@n])==var(@k))
2932          {
2933            @n1=1;
2934            break;
2935          }
2936        }
2937        if(@n1==0)
2938        {
2939          newva=newva+string(var(@k))+",";
2940          newma=newma+string(var(@k))+",";
2941        }
2942        else
2943        {
2944          newma=newma+string(0)+",";
2945          fried[@n]=fried[@n]/leadcoef(fried[@n]);
2946          f=fried[@n]-lead(fried[@n]);
2947          @j=subst(@j,var(@k),-f);
2948        }
2949      }
2950      newva[size(newva)]=")";
2951      newma[size(newma)]=";";
2952      execute("ring @deirf=("+charstr(gnir)+"),("+newva+",lp;");
2953      execute("map @kappa=gnir,"+newma);
2954      ideal @j= @kappa(@j);
2955      @j=std(@j);
2956
2957      list pr=decomp(@j);
2958      setring gnir;
2959      list pr=imap(@deirf,pr);
2960      for(@k=1;@k<=size(pr);@k++)
2961      {
2962        @j=pr[@k]+fried;
2963        pr[@k]=@j;
2964      }
2965      setring @P;
2966      primary=imap(gnir,pr);
2967      if (abspri) { return(prepare_absprimdec(primary));}
2968      return(primary);
2969    }
2970  }
2971  //----------------------------------------------------------------
2972  //j is the ring
2973  //----------------------------------------------------------------
2974
2975  if (dim(@j)==-1)
2976  {
2977    setring @P;
2978    primary=ideal(1),ideal(1);
2979    if (abspri) { return(prepare_absprimdec(primary));}
2980    return(primary);
2981  }
2982
2983  //----------------------------------------------------------------
2984  //  the case of one variable
2985  //----------------------------------------------------------------
2986
2987  if(nvars(basering)==1)
2988  {
2989    list fac=factor(@j[1]);
2990    list gprimary;
2991    for(@k=1;@k<=size(fac[1]);@k++)
2992    {
2993      if(@wr==0)
2994      {
2995        gprimary[2*@k-1]=ideal(fac[1][@k]^fac[2][@k]);
2996        gprimary[2*@k]=ideal(fac[1][@k]);
2997      }
2998      else
2999      {
3000        gprimary[2*@k-1]=ideal(fac[1][@k]);
3001        gprimary[2*@k]=ideal(fac[1][@k]);
3002      }
3003    }
3004    setring @P;
3005    primary=fetch(gnir,gprimary);
3006
3007//HIER
3008    if (abspri) { return(prepare_absprimdec(primary));}
3009    return(primary);
3010  }
3011
3012 //------------------------------------------------------------------
3013 //the zero-dimensional case
3014 //------------------------------------------------------------------
3015  if (dim(@j)==0)
3016  {
3017    op=option(get);
3018    option(redSB);
3019    list gprimary= zero_decomp(@j,ser,@wr);
3020
3021    setring @P;
3022    primary=fetch(gnir,gprimary);
3023
3024    if(size(ser)>0)
3025    {
3026      primary=cleanPrimary(primary);
3027    }
3028//HIER
3029    if(abspri)
3030    {
3031      setring gnir;
3032      list primary=imap(@P,primary);
3033      list resu,tempo;
3034      string absotto;
3035      map sigma,invsigma;
3036      ideal II,jmap;
3037      nn=nvars(basering);
3038      for(ab=1;ab<=size(primary) div 2;ab++)
3039      {
3040        II=primary[2*ab];
3041        attrib(II,"isSB",1);
3042        if(deg(II[1])==vdim(II))
3043        {
3044          absotto= absFactorize(primary[2*ab][1],77);
3045          tempo=
3046            primary[2*ab-1],primary[2*ab],absotto,string(var(nvars(basering)));
3047        }
3048        else
3049        {
3050          invsigma=basering,maxideal(1);
3051          jmap=randomLast(50);
3052          sigma=basering,jmap;
3053          jmap[nn]=2*var(nn)-jmap[nn];
3054          invsigma=basering,jmap;
3055          II=groebner(sigma(II));
3056          absotto = absFactorize(II[1],77);
3057          II=var(nn);
3058          tempo= primary[2*ab-1],primary[2*ab],absotto,string(invsigma(II));
3059        }
3060        resu[ab]=tempo;
3061      }
3062      primary=resu;
3063      setring @P;
3064      primary=imap(gnir,primary);
3065    }
3066    option(set,op);
3067    return(primary);
3068  }
3069
3070  poly @gs,@gh,@p;
3071  string @va,quotring;
3072  list quprimary,htprimary,collectprimary,lsau,lnew,allindep,restindep;
3073  ideal @h;
3074  int jdim=dim(@j);
3075  list fett;
3076  int lauf,di,newtest;
3077  //------------------------------------------------------------------
3078  //search for a maximal independent set indep,i.e.
3079  //look for subring such that the intersection with the ideal is zero
3080  //j intersected with K[var(indep[3]+1),...,var(nvar] is zero,
3081  //indep[1] is the new varstring and indep[2] the string for block-ordering
3082  //------------------------------------------------------------------
3083  if(@wr!=1)
3084  {
3085    allindep=independSet(@j);
3086    for(@m=1;@m<=size(allindep);@m++)
3087    {
3088      if(allindep[@m][3]==jdim)
3089      {
3090        di++;
3091        indep[di]=allindep[@m];
3092      }
3093      else
3094      {
3095        lauf++;
3096        restindep[lauf]=allindep[@m];
3097      }
3098    }
3099  }
3100  else
3101  {
3102    indep=maxIndependSet(@j);
3103  }
3104
3105  ideal jkeep=@j;
3106  if(ordstr(@P)[1]=="w")
3107  {
3108    execute("ring @Phelp=("+charstr(gnir)+"),("+varstr(gnir)+"),("+ordstr(@P)+");");
3109  }
3110  else
3111  {
3112    execute( "ring @Phelp=("+charstr(gnir)+"),("+varstr(gnir)+"),(C,dp);");
3113  }
3114
3115  if(homo==1)
3116  {
3117    if((ordstr(@P)[3]=="d")||(ordstr(@P)[1]=="d")||(ordstr(@P)[1]=="w")
3118       ||(ordstr(@P)[3]=="w"))
3119    {
3120      ideal jwork=imap(@P,tras);
3121      attrib(jwork,"isSB",1);
3122    }
3123    else
3124    {
3125      ideal jwork=std(imap(gnir,@j),@hilb,@w);
3126    }
3127  }
3128  else
3129  {
3130    ideal jwork=groebner(imap(gnir,@j));
3131  }
3132  list hquprimary;
3133  poly @p,@q;
3134  ideal @h,fac,ser;
3135  ideal @Ptest=1;
3136  di=dim(jwork);
3137  keepdi=di;
3138
3139  setring gnir;
3140  for(@m=1;@m<=size(indep);@m++)
3141  {
3142    isat=0;
3143    @n2=0;
3144    if((indep[@m][1]==varstr(basering))&&(@m==1))
3145    //this is the good case, nothing to do, just to have the same notations
3146    //change the ring
3147    {
3148      execute("ring gnir1 = ("+charstr(basering)+"),("+varstr(basering)+"),("
3149                              +ordstr(basering)+");");
3150      ideal @j=fetch(gnir,@j);
3151      attrib(@j,"isSB",1);
3152      ideal ser=fetch(gnir,ser);
3153    }
3154    else
3155    {
3156      @va=string(maxideal(1));
3157      if(@m==1)
3158      {
3159        @j=fetch(@P,i);
3160      }
3161      execute("ring gnir1 = ("+charstr(basering)+"),("+indep[@m][1]+"),("
3162                              +indep[@m][2]+");");
3163      execute("map phi=gnir,"+@va+";");
3164      op=option(get);
3165      option(redSB);
3166      if(homo==1)
3167      {
3168        ideal @j=std(phi(@j),@hilb,@w);
3169      }
3170      else
3171      {
3172        ideal @j=groebner(phi(@j));
3173      }
3174      ideal ser=phi(ser);
3175
3176      option(set,op);
3177    }
3178    if((deg(@j[1])==0)||(dim(@j)<jdim))
3179    {
3180      setring gnir;
3181      break;
3182    }
3183    for (lauf=1;lauf<=size(@j);lauf++)
3184    {
3185      fett[lauf]=size(@j[lauf]);
3186    }
3187    //------------------------------------------------------------------------
3188    //we have now the following situation:
3189    //j intersected with K[var(nnp+1),..,var(nva)] is zero so we may pass
3190    //to this quotientring, j is their still a standardbasis, the
3191    //leading coefficients of the polynomials  there (polynomials in
3192    //K[var(nnp+1),..,var(nva)]) are collected in the list h,
3193    //we need their ggt, gh, because of the following: let
3194    //(j:gh^n)=(j:gh^infinity) then j*K(var(nnp+1),..,var(nva))[..the rest..]
3195    //intersected with K[var(1),...,var(nva)] is (j:gh^n)
3196    //on the other hand j=(j,gh^n) intersected with (j:gh^n)
3197
3198    //------------------------------------------------------------------------
3199
3200    //arrangement for quotientring K(var(nnp+1),..,var(nva))[..the rest..] and
3201    //map phi:K[var(1),...,var(nva)] --->K(var(nnpr+1),..,var(nva))[..rest..]
3202    //------------------------------------------------------------------------
3203
3204    quotring=prepareQuotientring(nvars(basering)-indep[@m][3]);
3205
3206    //---------------------------------------------------------------------
3207    //we pass to the quotientring   K(var(nnp+1),..,var(nva))[..the rest..]
3208    //---------------------------------------------------------------------
3209
3210    ideal @jj=lead(@j);               //!! vorn vereinbaren
3211    execute(quotring);
3212
3213    ideal @jj=imap(gnir1,@jj);
3214    @vv=clearSBNeu(@jj,fett);  //!! vorn vereinbaren
3215    setring gnir1;
3216    @k=size(@j);
3217    for (lauf=1;lauf<=@k;lauf++)
3218    {
3219      if(@vv[lauf]==1)
3220      {
3221        @j[lauf]=0;
3222      }
3223    }
3224    @j=simplify(@j,2);
3225    setring quring;
3226    // @j considered in the quotientring
3227    ideal @j=imap(gnir1,@j);
3228
3229    ideal ser=imap(gnir1,ser);
3230
3231    kill gnir1;
3232
3233    //j is a standardbasis in the quotientring but usually not minimal
3234    //here it becomes minimal
3235
3236    attrib(@j,"isSB",1);
3237
3238    //we need later ggt(h[1],...)=gh for saturation
3239    ideal @h;
3240    if(deg(@j[1])>0)
3241    {
3242      for(@n=1;@n<=size(@j);@n++)
3243      {
3244        @h[@n]=leadcoef(@j[@n]);
3245      }
3246      //the primary decomposition of j*K(var(nnp+1),..,var(nva))[..the rest..]
3247      op=option(get);
3248      option(redSB);
3249
3250      list uprimary= zero_decomp(@j,ser,@wr);
3251//HIER
3252      if(abspri)
3253      {
3254        ideal II;
3255        ideal jmap;
3256        map sigma;
3257        nn=nvars(basering);
3258        map invsigma=basering,maxideal(1);
3259        for(ab=1;ab<=size(uprimary) div 2;ab++)
3260        {
3261          II=uprimary[2*ab];
3262          attrib(II,"isSB",1);
3263          if(deg(II[1])!=vdim(II))
3264          {
3265            jmap=randomLast(50);
3266            sigma=basering,jmap;
3267            jmap[nn]=2*var(nn)-jmap[nn];
3268            invsigma=basering,jmap;
3269            II=groebner(sigma(II));
3270          }
3271          absprimarytmp[ab]= absFactorize(II[1],77);
3272          II=var(nn);
3273          abskeeptmp[ab]=string(invsigma(II));
3274          invsigma=basering,maxideal(1);
3275        }
3276      }
3277      option(set,op);
3278    }
3279    else
3280    {
3281      list uprimary;
3282      uprimary[1]=ideal(1);
3283      uprimary[2]=ideal(1);
3284    }
3285    //we need the intersection of the ideals in the list quprimary with the
3286    //polynomialring, i.e. let q=(f1,...,fr) in the quotientring such an ideal
3287    //but fi polynomials, then the intersection of q with the polynomialring
3288    //is the saturation of the ideal generated by f1,...,fr with respect to
3289    //h which is the lcm of the leading coefficients of the fi considered in
3290    //in the quotientring: this is coded in saturn
3291
3292    list saturn;
3293    ideal hpl;
3294
3295    for(@n=1;@n<=size(uprimary);@n++)
3296    {
3297      uprimary[@n]=interred(uprimary[@n]); // temporary fix
3298      hpl=0;
3299      for(@n1=1;@n1<=size(uprimary[@n]);@n1++)
3300      {
3301        hpl=hpl,leadcoef(uprimary[@n][@n1]);
3302      }
3303      saturn[@n]=hpl;
3304    }
3305
3306    //--------------------------------------------------------------------
3307    //we leave  the quotientring   K(var(nnp+1),..,var(nva))[..the rest..]
3308    //back to the polynomialring
3309    //---------------------------------------------------------------------
3310    setring gnir;
3311
3312    collectprimary=imap(quring,uprimary);
3313    lsau=imap(quring,saturn);
3314    @h=imap(quring,@h);
3315
3316    kill quring;
3317
3318    @n2=size(quprimary);
3319    @n3=@n2;
3320
3321    for(@n1=1;@n1<=size(collectprimary) div 2;@n1++)
3322    {
3323      if(deg(collectprimary[2*@n1][1])>0)
3324      {
3325        @n2++;
3326        quprimary[@n2]=collectprimary[2*@n1-1];
3327        lnew[@n2]=lsau[2*@n1-1];
3328        @n2++;
3329        lnew[@n2]=lsau[2*@n1];
3330        quprimary[@n2]=collectprimary[2*@n1];
3331        if(abspri)
3332        {
3333          absprimary[@n2 div 2]=absprimarytmp[@n1];
3334          abskeep[@n2 div 2]=abskeeptmp[@n1];
3335        }
3336      }
3337    }
3338    //here the intersection with the polynomialring
3339    //mentioned above is really computed
3340    for(@n=@n3 div 2+1;@n<=@n2 div 2;@n++)
3341    {
3342      if(specialIdealsEqual(quprimary[2*@n-1],quprimary[2*@n]))
3343      {
3344        quprimary[2*@n-1]=sat2(quprimary[2*@n-1],lnew[2*@n-1])[1];
3345        quprimary[2*@n]=quprimary[2*@n-1];
3346      }
3347      else
3348      {
3349        if(@wr==0)
3350        {
3351          quprimary[2*@n-1]=sat2(quprimary[2*@n-1],lnew[2*@n-1])[1];
3352        }
3353        quprimary[2*@n]=sat2(quprimary[2*@n],lnew[2*@n])[1];
3354      }
3355    }
3356
3357    if(size(@h)>0)
3358    {
3359      //---------------------------------------------------------------
3360      //we change to @Phelp to have the ordering dp for saturation
3361      //---------------------------------------------------------------
3362      setring @Phelp;
3363      @h=imap(gnir,@h);
3364      if(@wr!=1)
3365      {
3366        if(defined(@LL)){kill @LL;}
3367        list @LL=minSat(jwork,@h);
3368        @Ptest=intersect(@Ptest,@LL[1]);
3369        @q=@LL[2];
3370      }
3371      else
3372      {
3373        fac=ideal(0);
3374        for(lauf=1;lauf<=ncols(@h);lauf++)
3375        {
3376          if(deg(@h[lauf])>0)
3377          {
3378            fac=fac+factorize(@h[lauf],1);
3379          }
3380        }
3381        fac=simplify(fac,6);
3382        @q=1;
3383        for(lauf=1;lauf<=size(fac);lauf++)
3384        {
3385          @q=@q*fac[lauf];
3386        }
3387      }
3388      jwork=std(jwork,@q);
3389      keepdi=dim(jwork);
3390      if(keepdi<di)
3391      {
3392        setring gnir;
3393        @j=imap(@Phelp,jwork);
3394        break;
3395      }
3396      if(homo==1)
3397      {
3398        @hilb=hilb(jwork,1,@w);
3399      }
3400
3401      setring gnir;
3402      @j=imap(@Phelp,jwork);
3403    }
3404  }
3405
3406  if((size(quprimary)==0)&&(@wr==1))
3407  {
3408    @j=ideal(1);
3409    quprimary[1]=ideal(1);
3410    quprimary[2]=ideal(1);
3411  }
3412  if((size(quprimary)==0))
3413  {
3414    keepdi=di-1;
3415    quprimary[1]=ideal(1);
3416    quprimary[2]=ideal(1);
3417  }
3418  //---------------------------------------------------------------
3419  //notice that j=sat(j,gh) intersected with (j,gh^n)
3420  //we finished with sat(j,gh) and have to start with (j,gh^n)
3421  //---------------------------------------------------------------
3422  if((deg(@j[1])!=0)&&(@wr!=1))
3423  {
3424    if(size(quprimary)>0)
3425    {
3426      setring @Phelp;
3427      ser=imap(gnir,ser);
3428      hquprimary=imap(gnir,quprimary);
3429      if(@wr==0)
3430      {
3431        //HIER STATT DURCHSCHNITT SATURIEREN!
3432        ideal htest=@Ptest;
3433      }
3434      else
3435      {
3436        ideal htest=hquprimary[2];
3437
3438        for (@n1=2;@n1<=size(hquprimary) div 2;@n1++)
3439        {
3440          htest=intersect(htest,hquprimary[2*@n1]);
3441        }
3442      }
3443
3444      if(size(ser)>0)
3445      {
3446        ser=intersect(htest,ser);
3447      }
3448      else
3449      {
3450        ser=htest;
3451      }
3452      setring gnir;
3453      ser=imap(@Phelp,ser);
3454    }
3455    if(size(reduce(ser,peek,1))!=0)
3456    {
3457      for(@m=1;@m<=size(restindep);@m++)
3458      {
3459        // if(restindep[@m][3]>=keepdi)
3460        // {
3461        isat=0;
3462        @n2=0;
3463
3464        if(restindep[@m][1]==varstr(basering))
3465           //the good case, nothing to do, just to have the same notations
3466           //change the ring
3467        {
3468          execute("ring gnir1 = ("+charstr(basering)+"),("+
3469               varstr(basering)+"),("+ordstr(basering)+");");
3470          ideal @j=fetch(gnir,jkeep);
3471          attrib(@j,"isSB",1);
3472        }
3473        else
3474        {
3475          @va=string(maxideal(1));
3476          execute("ring gnir1 = ("+charstr(basering)+"),("+
3477                      restindep[@m][1]+"),(" +restindep[@m][2]+");");
3478          execute("map phi=gnir,"+@va+";");
3479          op=option(get);
3480          option(redSB);
3481          if(homo==1)
3482          {
3483            ideal @j=std(phi(jkeep),keephilb,@w);
3484          }
3485          else
3486          {
3487            ideal @j=groebner(phi(jkeep));
3488          }
3489          ideal ser=phi(ser);
3490          option(set,op);
3491        }
3492
3493        for (lauf=1;lauf<=size(@j);lauf++)
3494        {
3495          fett[lauf]=size(@j[lauf]);
3496        }
3497        //------------------------------------------------------------------
3498        //we have now the following situation:
3499        //j intersected with K[var(nnp+1),..,var(nva)] is zero so we may
3500        //pass to this quotientring, j is their still a standardbasis, the
3501        //leading coefficients of the polynomials  there (polynomials in
3502        //K[var(nnp+1),..,var(nva)]) are collected in the list h,
3503        //we need their ggt, gh, because of the following:
3504        //let (j:gh^n)=(j:gh^infinity) then
3505        //j*K(var(nnp+1),..,var(nva))[..the rest..]
3506        //intersected with K[var(1),...,var(nva)] is (j:gh^n)
3507        //on the other hand j=(j,gh^n) intersected with (j:gh^n)
3508
3509        //------------------------------------------------------------------
3510
3511        //the arrangement for the quotientring
3512        // K(var(nnp+1),..,var(nva))[..the rest..]
3513        //and the map phi:K[var(1),...,var(nva)] ---->
3514        //--->K(var(nnpr+1),..,var(nva))[..the rest..]
3515        //------------------------------------------------------------------
3516
3517        quotring=prepareQuotientring(nvars(basering)-restindep[@m][3]);
3518
3519        //------------------------------------------------------------------
3520        //we pass to the quotientring  K(var(nnp+1),..,var(nva))[..rest..]
3521        //------------------------------------------------------------------
3522
3523        execute(quotring);
3524
3525        // @j considered in the quotientring
3526        ideal @j=imap(gnir1,@j);
3527        ideal ser=imap(gnir1,ser);
3528
3529        kill gnir1;
3530
3531        //j is a standardbasis in the quotientring but usually not minimal
3532        //here it becomes minimal
3533        @j=clearSB(@j,fett);
3534        attrib(@j,"isSB",1);
3535
3536        //we need later ggt(h[1],...)=gh for saturation
3537        ideal @h;
3538
3539        for(@n=1;@n<=size(@j);@n++)
3540        {
3541          @h[@n]=leadcoef(@j[@n]);
3542        }
3543        //the primary decomposition of j*K(var(nnp+1),..,var(nva))[..rest..]
3544
3545        op=option(get);
3546        option(redSB);
3547        list uprimary= zero_decomp(@j,ser,@wr);
3548//HIER
3549        if(abspri)
3550        {
3551          ideal II;
3552          ideal jmap;
3553          map sigma;
3554          nn=nvars(basering);
3555          map invsigma=basering,maxideal(1);
3556          for(ab=1;ab<=size(uprimary) div 2;ab++)
3557          {
3558            II=uprimary[2*ab];
3559            attrib(II,"isSB",1);
3560            if(deg(II[1])!=vdim(II))
3561            {
3562              jmap=randomLast(50);
3563              sigma=basering,jmap;
3564              jmap[nn]=2*var(nn)-jmap[nn];
3565              invsigma=basering,jmap;
3566              II=groebner(sigma(II));
3567            }
3568            absprimarytmp[ab]= absFactorize(II[1],77);
3569            II=var(nn);
3570            abskeeptmp[ab]=string(invsigma(II));
3571            invsigma=basering,maxideal(1);
3572          }
3573        }
3574        option(set,op);
3575
3576        //we need the intersection of the ideals in the list quprimary with
3577        //the polynomialring, i.e. let q=(f1,...,fr) in the quotientring
3578        //such an ideal but fi polynomials, then the intersection of q with
3579        //the polynomialring is the saturation of the ideal generated by
3580        //f1,...,fr with respect toh which is the lcm of the leading
3581        //coefficients of the fi considered in the quotientring:
3582        //this is coded in saturn
3583
3584        list saturn;
3585        ideal hpl;
3586
3587        for(@n=1;@n<=size(uprimary);@n++)
3588        {
3589          hpl=0;
3590          for(@n1=1;@n1<=size(uprimary[@n]);@n1++)
3591          {
3592            hpl=hpl,leadcoef(uprimary[@n][@n1]);
3593          }
3594          saturn[@n]=hpl;
3595        }
3596        //------------------------------------------------------------------
3597        //we leave  the quotientring   K(var(nnp+1),..,var(nva))[..rest..]
3598        //back to the polynomialring
3599        //------------------------------------------------------------------
3600        setring gnir;
3601        collectprimary=imap(quring,uprimary);
3602        lsau=imap(quring,saturn);
3603        @h=imap(quring,@h);
3604
3605        kill quring;
3606
3607        @n2=size(quprimary);
3608        @n3=@n2;
3609
3610        for(@n1=1;@n1<=size(collectprimary) div 2;@n1++)
3611        {
3612          if(deg(collectprimary[2*@n1][1])>0)
3613          {
3614            @n2++;
3615            quprimary[@n2]=collectprimary[2*@n1-1];
3616            lnew[@n2]=lsau[2*@n1-1];
3617            @n2++;
3618            lnew[@n2]=lsau[2*@n1];
3619            quprimary[@n2]=collectprimary[2*@n1];
3620            if(abspri)
3621            {
3622              absprimary[@n2 div 2]=absprimarytmp[@n1];
3623              abskeep[@n2 div 2]=abskeeptmp[@n1];
3624            }
3625          }
3626        }
3627
3628
3629        //here the intersection with the polynomialring
3630        //mentioned above is really computed
3631
3632        for(@n=@n3 div 2+1;@n<=@n2 div 2;@n++)
3633        {
3634          if(specialIdealsEqual(quprimary[2*@n-1],quprimary[2*@n]))
3635          {
3636            quprimary[2*@n-1]=sat2(quprimary[2*@n-1],lnew[2*@n-1])[1];
3637            quprimary[2*@n]=quprimary[2*@n-1];
3638          }
3639          else
3640          {
3641            if(@wr==0)
3642            {
3643              quprimary[2*@n-1]=sat2(quprimary[2*@n-1],lnew[2*@n-1])[1];
3644            }
3645            quprimary[2*@n]=sat2(quprimary[2*@n],lnew[2*@n])[1];
3646          }
3647        }
3648        if(@n2>=@n3+2)
3649        {
3650          setring @Phelp;
3651          ser=imap(gnir,ser);
3652          hquprimary=imap(gnir,quprimary);
3653          for(@n=@n3 div 2+1;@n<=@n2 div 2;@n++)
3654          {
3655            if(@wr==0)
3656            {
3657              ser=intersect(ser,hquprimary[2*@n-1]);
3658            }
3659            else
3660            {
3661              ser=intersect(ser,hquprimary[2*@n]);
3662            }
3663          }
3664          setring gnir;
3665          ser=imap(@Phelp,ser);
3666        }
3667
3668         // }
3669      }
3670//HIER
3671      if(abspri)
3672      {
3673        list resu,tempo;
3674        for(ab=1;ab<=size(quprimary) div 2;ab++)
3675        {
3676          if (deg(quprimary[2*ab][1])!=0)
3677          {
3678            tempo=quprimary[2*ab-1],quprimary[2*ab],
3679                         absprimary[ab],abskeep[ab];
3680            resu[ab]=tempo;
3681          }
3682        }
3683        quprimary=resu;
3684        @wr=3;
3685      }
3686      if(size(reduce(ser,peek,1))!=0)
3687      {
3688        if(@wr>0)
3689        {
3690          htprimary=decomp(@j,@wr,peek,ser);
3691        }
3692        else
3693        {
3694          htprimary=decomp(@j,peek,ser);
3695        }
3696        // here we collect now both results primary(sat(j,gh))
3697        // and primary(j,gh^n)
3698        @n=size(quprimary);
3699        for (@k=1;@k<=size(htprimary);@k++)
3700        {
3701          quprimary[@n+@k]=htprimary[@k];
3702        }
3703      }
3704    }
3705  }
3706  else
3707  {
3708    if(abspri)
3709    {
3710      list resu,tempo;
3711      for(ab=1;ab<=size(quprimary) div 2;ab++)
3712      {
3713        tempo=quprimary[2*ab-1],quprimary[2*ab],
3714                   absprimary[ab],abskeep[ab];
3715        resu[ab]=tempo;
3716      }
3717      quprimary=resu;
3718    }
3719  }
3720  //---------------------------------------------------------------------------
3721  //back to the ring we started with
3722  //the final result: primary
3723  //---------------------------------------------------------------------------
3724  setring @P;
3725  primary=imap(gnir,quprimary);
3726  if(!abspri)
3727  {
3728    primary=cleanPrimary(primary);
3729  }
3730  if (abspri && (typeof(primary[1][1])=="poly"))
3731  { return(prepare_absprimdec(primary));}
3732  return(primary);
3733}
3734
3735
3736example
3737{ "EXAMPLE:"; echo = 2;
3738   ring  r = 32003,(x,y,z),lp;
3739   poly  p = z2+1;
3740   poly  q = z4+2;
3741   ideal i = p^2*q^3,(y-z3)^3,(x-yz+z4)^4;
3742   list pr= decomp(i);
3743   pr;
3744   testPrimary( pr, i);
3745}
3746
3747///////////////////////////////////////////////////////////////////////////////
3748static proc powerCoeffs(poly f,int e)
3749//computes a polynomial with the same monomials as f but coefficients
3750//the p^e th power of the coefficients of f
3751{
3752   ASSUME(0, not isQuotientRing(basering) ) ;
3753  ASSUME(0, hasGlobalOrdering(basering) ) ;
3754
3755   int i;
3756   poly g;
3757   int ex=char(basering)^e;
3758   for(i=1;i<=size(f);i++)
3759   {
3760      g=g+leadcoef(f[i])^ex*leadmonom(f[i]);
3761   }
3762   return(g);
3763}
3764///////////////////////////////////////////////////////////////////////////////
3765
3766proc sep(poly f,int i, list #)
3767"USAGE:  input: a polynomial f depending on the i-th variable and optional
3768         an integer k considering the polynomial f defined over Fp(t1,...,tm)
3769         as polynomial over Fp(t(1)^(p^-k),...,t(m)^(p^-k))
3770 RETURN: the separabel part of f as polynomial in Fp(t1,...,tm)
3771        and an integer k to indicate that f should be considerd
3772        as polynomial over Fp(t(1)^(p^-k),...,t(m)^(p^-k))
3773 EXAMPLE: example sep; shows an example
3774{
3775   ASSUME(0, not isQuotientRing(basering) ) ;
3776  ASSUME(0, hasGlobalOrdering(basering) ) ;
3777
3778   def R=basering;
3779   int k;
3780   if(size(#)>0){k=#[1];}
3781
3782
3783   poly h=gcd(f,diff(f,var(i)));
3784   if((reduce(f,std(h))!=0)||(reduce(diff(f,var(i)),std(h))!=0))
3785   {
3786      ERROR("FEHLER IN GCD");
3787   }
3788   poly g1=lift(h,f)[1][1];    //  f/h
3789   poly h1;
3790
3791   while(h!=h1)
3792   {
3793      h1=h;
3794      h=gcd(h,diff(h,var(i)));
3795   }
3796
3797   if(deg(h1)==0){return(list(g1,k));} //in characteristic 0 we return here
3798
3799   k++;
3800
3801   ideal ma=maxideal(1);
3802   ma[i]=var(i)^char(R);
3803   map phi=R,ma;
3804   ideal hh=h;    //this is technical because preimage works only for ideals
3805
3806   poly u=preimage(R,phi,hh)[1]; //h=u(x(i)^p)
3807
3808   list g2=sep(u,i,k);           //we consider u(t(1)^(p^-1),...,t(m)^(p^-1))
3809   g1=powerCoeffs(g1,g2[2]-k+1); //to have g1 over the same field as g2[1]
3810
3811   list g3=sep(g1*g2[1],i,g2[2]);
3812   return(g3);
3813}
3814example
3815{ "EXAMPLE:"; echo = 2;
3816   ring R=(5,t,s),(x,y,z),dp;
3817   poly f=(x^25-t*x^5+t)*(x^3+s);
3818   sep(f,1);
3819}
3820
3821///////////////////////////////////////////////////////////////////////////////
3822 proc zeroRad(ideal I,list #)
3823"USAGE:  zeroRad(I) , I a zero-dimensional ideal
3824 RETURN: the radical of I
3825 NOTE:  Algorithm of Kemper
3826 EXAMPLE: example zeroRad; shows an example
3827{
3828   ASSUME(0, not isQuotientRing(basering) ) ;
3829  ASSUME(0, hasGlobalOrdering(basering) ) ;
3830
3831   if(homog(I)==1){return(maxideal(1));}
3832   //I needs to be a reduced standard basis
3833   def R=basering;
3834   int m=npars(R);
3835   int n=nvars(R);
3836   int p=char(R);
3837   int d=vdim(I);
3838   int i,k;
3839   list l;
3840   if(((p==0)||(p>d))&&(d==deg(I[1])))
3841   {
3842     intvec e=leadexp(I[1]);
3843     for(i=1;i<=nvars(basering);i++)
3844     {
3845       if(e[i]!=0) break;
3846     }
3847     I[1]=sep(I[1],i)[1];
3848     return(interred(I));
3849   }
3850   intvec op=option(get);
3851
3852   option(redSB);
3853   ASSUME(1, dim(I)==0);
3854   ideal F=finduni(I);//F[i] generates I intersected with K[var(i)]
3855
3856   option(set,op);
3857   if(size(#)>0){I=#[1];}
3858
3859   for(i=1;i<=n;i++)
3860   {
3861      l[i]=sep(F[i],i);
3862      F[i]=l[i][1];
3863      if(l[i][2]>k){k=l[i][2];}  //computation of the maximal k
3864   }
3865
3866   if((k==0)||(m==0)) //the separable case
3867   {
3868    intvec save=option(get);option(redSB);
3869    I=interred(I+F);option(set,save);return(I);
3870   }
3871   //I=simplify(I,1);
3872
3873   for(i=1;i<=n;i++)             //consider all polynomials over
3874   {                             //Fp(t(1)^(p^-k),...,t(m)^(p^-k))
3875      F[i]=powerCoeffs(F[i],k-l[i][2]);
3876   }
3877
3878   string cR="ring @R="+string(p)+",("+parstr(R)+","+varstr(R)+"),dp;";
3879   execute(cR);
3880   ideal F=imap(R,F);
3881
3882   string nR1="ring @S1="+string(p)+",("+varstr(R)+","+parstr(R)+",@y(1..m)),dp;";
3883   execute(nR1);
3884   list lR=ringlist(@S1)[2];
3885   lR=lR[(size(lR)-m+1)..(size(lR))];
3886
3887   string nR="ring @S="+string(p)+",("+string(lR)+","+varstr(R)+","+parstr(R)+"),dp;";
3888   execute(nR);
3889
3890   ideal G=fetch(@R,F);    //G[i](t(1)^(p^-k),...,t(m)^(p^-k),x(i))=sep(F[i])
3891
3892   ideal I=imap(R,I);
3893   ideal J=I+G;
3894   poly el=1;
3895   k=p^k;
3896   for(i=1;i<=m;i++)
3897   {
3898      J=J,var(i)^k-var(m+n+i);
3899      el=el*var(i);
3900   }
3901
3902   J=eliminate(J,el);
3903   setring R;
3904   ideal J=imap(@S,J);
3905   return(J);
3906}
3907example
3908{ "EXAMPLE:"; echo = 2;
3909   ring R=(5,t),(x,y),dp;
3910   ideal I=x^5-t,y^5-t;
3911   zeroRad(I);
3912}
3913
3914///////////////////////////////////////////////////////////////////////////////
3915
3916proc radicalEHV(ideal i)
3917"USAGE:   radicalEHV(i); i ideal.
3918RETURN:  ideal, the radical of i.
3919NOTE:    Uses the algorithm of Eisenbud/Huneke/Vasconcelos, which
3920         reduces the computation to the complete intersection case,
3921         by taking, in the general case, a generic linear combination
3922         of the input.
3923         Works only in characteristic 0 or p large.
3924EXAMPLE: example radicalEHV; shows an example
3925"
3926{
3927   ASSUME(0, not isQuotientRing(basering) ) ;
3928   if(attrib(basering,"global")!=1)
3929   {
3930      ERROR(
3931      "// Not implemented for this ordering, please change to global ordering."
3932      );
3933   }
3934   ASSUME(0, hasGlobalOrdering(basering) ) ;
3935
3936   if((char(basering)<100)&&(char(basering)!=0))
3937   {
3938      "WARNING: The characteristic is too small, the result may be wrong";
3939   }
3940   if ( size(i)==0 ) { return(ideal(0)); }
3941
3942   ideal J,I,I0,radI0,L,radI1,I2,radI2;
3943   int l,n;
3944   intvec op=option(get);
3945   matrix M;
3946
3947   option(redSB);
3948   list m=mstd(i);
3949        I=m[2];
3950   option(set,op);
3951
3952   if ( dim(m[1])<0 ) { return(ideal(1)); }
3953
3954   int cod=nvars(basering)-dim(m[1]);
3955   //-------------------complete intersection case:----------------------
3956   if(cod==size(m[2]))
3957   {
3958     J=minor(jacob(I),cod);
3959     return(quotient(I,J));
3960   }
3961   //-----first codim elements of I are a complete intersection:---------
3962   for(l=1;l<=cod;l++)
3963   {
3964      I0[l]=I[l];
3965   }
3966   n=dim(std(I0))+cod-nvars(basering);
3967   //-----last codim elements of I are a complete intersection:----------
3968   if(n!=0)
3969   {
3970      for(l=1;l<=cod;l++)
3971      {
3972         I0[l]=I[size(I)-l+1];
3973      }
3974      n=dim(std(I0))+cod-nvars(basering);
3975   }
3976   //-----taking a generic linear combination of the input:--------------
3977   if(n!=0)
3978   {
3979      M=transpose(sparsetriag(size(m[2]),cod,95,1));
3980      I0=ideal(M*transpose(I));
3981      n=dim(std(I0))+cod-nvars(basering);
3982   }
3983   //-----taking a more generic linear combination of the input:---------
3984   if(n!=0)
3985   {
3986      M=transpose(sparsetriag(size(m[2]),cod,0,100));
3987      I0=ideal(M*transpose(I));
3988      n=dim(std(I0))+cod-nvars(basering);
3989   }
3990   if(n==0)
3991   {
3992      J=minor(jacob(I0),cod);
3993      radI0=quotient(I0,J);
3994      L=quotient(radI0,I);
3995      radI1=quotient(radI0,L);
3996
3997      if(size(reduce(radI1,m[1],1))==0)
3998      {
3999         return(I);
4000      }
4001
4002      I2=sat(I,radI1)[1];
4003
4004      if(deg(I2[1])<=0)
4005      {
4006         return(radI1);
4007      }
4008      return(intersect(radI1,radicalEHV(I2)));
4009   }
4010   //---------------------general case-------------------------------------
4011   return(radical(I));
4012}
4013example
4014{ "EXAMPLE:";  echo = 2;
4015   ring  r = 0,(x,y,z),dp;
4016   poly  p = z2+1;
4017   poly  q = z3+2;
4018   ideal i = p*q^2,y-z2;
4019   ideal pr= radicalEHV(i);
4020   pr;
4021}
4022
4023///////////////////////////////////////////////////////////////////////////////
4024
4025proc Ann(module M)
4026"USAGE:   Ann(M);  M module
4027RETURN:  ideal, the annihilator of coker(M)
4028NOTE:    The output is the ideal of all elements a of the basering R such that
4029         a * R^m is contained in M  (m=number of rows of M).
4030EXAMPLE: example Ann; shows an example
4031"
4032{
4033
4034  M=prune(M);  //to obtain a small embedding
4035  ideal ann=quotient1(M,freemodule(nrows(M)));
4036  return(ann);
4037}
4038example
4039{ "EXAMPLE:"; echo = 2;
4040   ring  r = 0,(x,y,z),lp;
4041   module M = x2-y2,z3;
4042   Ann(M);
4043   M = [1,x2],[y,x];
4044   Ann(M);
4045   qring Q=std(xy-1);
4046   module M=imap(r,M);
4047   Ann(M);
4048}
4049
4050///////////////////////////////////////////////////////////////////////////////
4051
4052//computes the equidimensional part of the ideal i of codimension e
4053static proc int_ass_primary_e(ideal i, int e)
4054{
4055  ASSUME(0, not isQuotientRing(basering) ) ;
4056  ASSUME(0, hasGlobalOrdering(basering) ) ;
4057
4058  if(homog(i)!=1)
4059  {
4060     i=std(i);
4061  }
4062  list re=sres(i,0);                   //the resolution
4063  re=minres(re);                       //minimized resolution
4064  ideal ann=AnnExt_R(e,re);
4065  if(nvars(basering)-dim(std(ann))!=e)
4066  {
4067    return(ideal(1));
4068  }
4069  return(ann);
4070}
4071
4072///////////////////////////////////////////////////////////////////////////////
4073
4074//computes the annihilator of Ext^n(R/i,R) with given resolution re
4075//n is not necessarily the number of variables
4076static proc AnnExt_R(int n,list re)
4077{
4078
4079  if(n<nvars(basering))
4080  {
4081    if(size(re[n+1])>0)
4082    {
4083        matrix f=transpose(re[n+1]);      //Hom(_,R)
4084        module k=nres(f,2)[2];            //the kernel
4085        matrix g=transpose(re[n]);        //the image of Hom(_,R)
4086
4087        ideal ann=quotient1(g,k);         //the anihilator
4088        return(ann);
4089    }
4090  }
4091  // remaining case: re[n+1] is trivial
4092  // either n is at least number of variables or
4093  // resolution happens to be shorter
4094  ideal ann=Ann(transpose(re[n]));
4095  return(ann);
4096}
4097///////////////////////////////////////////////////////////////////////////////
4098
4099static proc analyze(list pr)
4100{
4101   ASSUME(0, not isQuotientRing(basering) ) ;
4102  ASSUME(0, hasGlobalOrdering(basering) ) ;
4103
4104   int ii,jj;
4105   for(ii=1;ii<=size(pr) div 2;ii++)
4106   {
4107      dim(std(pr[2*ii]));
4108      idealsEqual(pr[2*ii-1],pr[2*ii]);
4109      "===========================";
4110   }
4111
4112   for(ii=size(pr) div 2;ii>1;ii--)
4113   {
4114      for(jj=1;jj<ii;jj++)
4115      {
4116         if(size(reduce(pr[2*jj],std(pr[2*ii],1)))==0)
4117         {
4118            "eingebette Komponente";
4119            jj;
4120            ii;
4121         }
4122      }
4123   }
4124}
4125
4126///////////////////////////////////////////////////////////////////////////////
4127//
4128//                  Shimoyama-Yokoyama
4129//
4130///////////////////////////////////////////////////////////////////////////////
4131
4132static proc simplifyIdeal(ideal i)
4133{
4134  ASSUME(0, not isQuotientRing(basering) ) ;
4135  ASSUME(0, hasGlobalOrdering(basering) ) ;
4136
4137  def r=basering;
4138
4139  int j,k;
4140  map phi;
4141  poly p;
4142
4143  ideal iwork=i;
4144  ideal imap1=maxideal(1);
4145  ideal imap2=maxideal(1);
4146
4147
4148  for(j=1;j<=nvars(basering);j++)
4149  {
4150    for(k=1;k<=size(i);k++)
4151    {
4152      if(deg(iwork[k]/var(j))==0)
4153      {
4154        p=-1/leadcoef(iwork[k]/var(j))*iwork[k];
4155        imap1[j]=p+2*var(j);
4156        phi=r,imap1;
4157        iwork=phi(iwork);
4158        iwork=subst(iwork,var(j),0);
4159        iwork[k]=var(j);
4160        imap1=maxideal(1);
4161        imap2[j]=-p;
4162        break;
4163      }
4164    }
4165  }
4166  return(iwork,imap2);
4167}
4168
4169
4170///////////////////////////////////////////////////////
4171// ini_mod
4172// input: a polynomial p
4173// output: the initial term of p as needed
4174// in the context of characteristic sets
4175//////////////////////////////////////////////////////
4176
4177static proc ini_mod(poly p)
4178{
4179  if (p==0)
4180  {
4181    return(0);
4182  }
4183  int n; matrix m;
4184  for( n=nvars(basering); n>0; n--)
4185  {
4186    m=coef(p,var(n));
4187    if(m[1,1]!=1)
4188    {
4189      p=m[2,1];
4190      break;
4191    }
4192  }
4193  if(deg(p)==0)
4194  {
4195    p=0;
4196  }
4197  return(p);
4198}
4199///////////////////////////////////////////////////////
4200// min_ass_prim_charsets
4201// input: generators of an ideal PS and an integer cho
4202// If cho=0, the given ordering of the variables is used.
4203// Otherwise, the system tries to find an "optimal ordering",
4204// which in some cases may considerably speed up the algorithm
4205// output: the minimal associated primes of PS
4206// algorithm: via characteriostic sets
4207//////////////////////////////////////////////////////
4208
4209
4210static proc min_ass_prim_charsets (ideal PS, int cho)
4211{
4212  if((cho<0) and (cho>1))
4213  {
4214    ERROR("<int> must be 0 or 1");
4215  }
4216  intvec saveopt=option(get);
4217  option(notWarnSB);
4218  list L;
4219  if(cho==0)
4220  {
4221    L=min_ass_prim_charsets0(PS);
4222  }
4223  else
4224  {
4225    L=min_ass_prim_charsets1(PS);
4226  }
4227  option(set,saveopt);
4228  return(L);
4229}
4230///////////////////////////////////////////////////////
4231// min_ass_prim_charsets0
4232// input: generators of an ideal PS
4233// output: the minimal associated primes of PS
4234// algorithm: via characteristic sets
4235// the given ordering of the variables is used
4236//////////////////////////////////////////////////////
4237
4238
4239static proc min_ass_prim_charsets0 (ideal PS)
4240{
4241  ASSUME(0, not isQuotientRing(basering) ) ;
4242  ASSUME(0, hasGlobalOrdering(basering) ) ;
4243
4244  intvec op;
4245  matrix m=char_series(PS);  // We compute an irreducible
4246                             // characteristic series
4247  if ((nrows(m)==1)
4248  && (ncols(m)==1)
4249  && (m[1,1]==1)) // in case of an empty series: min_ass_prim_charsets1
4250  {
4251    return min_ass_prim_charsets1(PS);
4252  }
4253  int i,j,k;
4254  list PSI;
4255  list PHI;  // the ideals given by the characteristic series
4256  for(i=nrows(m);i>=1; i--)
4257  {
4258    PHI[i]=ideal(m[i,1..ncols(m)]);
4259  }
4260  // We compute the radical of each ideal in PHI
4261  ideal I,JS,II;
4262  int sizeJS, sizeII;
4263  for(i=size(PHI);i>=1; i--)
4264  {
4265    I=0;
4266    for(j=size(PHI[i]);j>0;j--)
4267    {
4268      I=I+ini_mod(PHI[i][j]);
4269    }
4270    JS=std(PHI[i]);
4271    sizeJS=size(JS);
4272    for(j=size(I);j>0;j--)
4273    {
4274      II=0;
4275      sizeII=0;
4276      k=0;
4277      while(k<=sizeII)                  // successive saturation
4278      {
4279        op=option(get);
4280        option(returnSB);
4281        II=quotient(JS,I[j]);
4282        option(set,op);
4283        sizeII=size(II);
4284        if(sizeII==sizeJS)
4285        {
4286          for(k=1;k<=sizeII;k++)
4287          {
4288            if(leadexp(II[k])!=leadexp(JS[k])) break;
4289          }
4290        }
4291        JS=II;
4292        sizeJS=sizeII;
4293      }
4294    }
4295    PSI=insert(PSI,JS);
4296  }
4297  int sizePSI=size(PSI);
4298  // We eliminate redundant ideals
4299  for(i=1;i<sizePSI;i++)
4300  {
4301    for(j=i+1;j<=sizePSI;j++)
4302    {
4303      if(size(PSI[i])!=0)
4304      {
4305        if(size(PSI[j])!=0)
4306        {
4307          if(size(NF(PSI[i],PSI[j],1))==0)
4308          {
4309            PSI[j]=ideal(0);
4310          }
4311          else
4312          {
4313            if(size(NF(PSI[j],PSI[i],1))==0)
4314            {
4315              PSI[i]=ideal(0);
4316            }
4317          }
4318        }
4319      }
4320    }
4321  }
4322  for(i=sizePSI;i>=1;i--)
4323  {
4324    if(size(PSI[i])==0)
4325    {
4326      PSI=delete(PSI,i);
4327    }
4328  }
4329  return (PSI);
4330}
4331
4332///////////////////////////////////////////////////////
4333// min_ass_prim_charsets1
4334// input: generators of an ideal PS
4335// output: the minimal associated primes of PS
4336// algorithm: via characteristic sets
4337// input: generators of an ideal PS and an integer i
4338// The system tries to find an "optimal ordering" of
4339// the variables
4340//////////////////////////////////////////////////////
4341
4342
4343static proc min_ass_prim_charsets1 (ideal PS)
4344{
4345  ASSUME(0, not isQuotientRing(basering) ) ;
4346  ASSUME(0, hasGlobalOrdering(basering) ) ;
4347
4348  intvec op;
4349  def oldring=basering;
4350  string n=system("neworder",PS);
4351  execute("ring r=("+charstr(oldring)+"),("+n+"),dp;");
4352  ideal PS=imap(oldring,PS);
4353  matrix m=char_series(PS);  // We compute an irreducible
4354                             // characteristic series
4355                             // this series may be empty (1x1: 1)
4356  int i,j,k,cnt;
4357  while ((cnt<nvars(oldring))
4358  && (nrows(m)==1)
4359  && (ncols(m)==1)
4360  && (m[1,1]==1)) // in case of an empty series: permute the variables
4361  {
4362    cnt++;
4363    n=string(var(nvars(oldring)));
4364    for(i=1;i<nvars(oldring);i++) { n=n+","+string(var(i)); }
4365    kill r;
4366    execute("ring r=("+charstr(oldring)+"),("+n+"),dp;");
4367    ideal PS=imap(oldring,PS);
4368    matrix m=char_series(PS);
4369  }
4370  ideal I;
4371  list PSI;
4372  list PHI;    // the ideals given by the characteristic series
4373  list ITPHI;  // their initial terms
4374  for(i=nrows(m);i>=1; i--)
4375  {
4376    PHI[i]=ideal(m[i,1..ncols(m)]);
4377    I=0;
4378    for(j=size(PHI[i]);j>0;j=j-1)
4379    {
4380      I=I,ini_mod(PHI[i][j]);
4381    }
4382    I=I[2..ncols(I)];
4383    ITPHI[i]=I;
4384  }
4385  setring oldring;
4386  matrix m=imap(r,m);
4387  list PHI=imap(r,PHI);
4388  list ITPHI=imap(r,ITPHI);
4389  // We compute the radical of each ideal in PHI
4390  ideal I,JS,II;
4391  int sizeJS, sizeII;
4392  for(i=size(PHI);i>=1; i--)
4393  {
4394    I=0;
4395    for(j=size(PHI[i]);j>0;j--)
4396    {
4397      I=I+ITPHI[i][j];
4398    }
4399    JS=std(PHI[i]);
4400    sizeJS=size(JS);
4401    for(j=size(I);j>0;j--)
4402    {
4403      II=0;
4404      sizeII=0;
4405      k=0;
4406      while(k<=sizeII)                  // successive iteration
4407      {
4408        op=option(get);
4409        option(returnSB);
4410        II=quotient(JS,I[j]);
4411        option(set,op);
4412//std
4413//         II=std(II);
4414        sizeII=size(II);
4415        if(sizeII==sizeJS)
4416        {
4417          for(k=1;k<=sizeII;k++)
4418          {
4419            if(leadexp(II[k])!=leadexp(JS[k])) break;
4420          }
4421        }
4422        JS=II;
4423        sizeJS=sizeII;
4424      }
4425    }
4426    PSI=insert(PSI,JS);
4427  }
4428  int sizePSI=size(PSI);
4429  // We eliminate redundant ideals
4430  for(i=1;i<sizePSI;i++)
4431  {
4432    for(j=i+1;j<=sizePSI;j++)
4433    {
4434      if(size(PSI[i])!=0)
4435      {
4436        if(size(PSI[j])!=0)
4437        {
4438          if(size(NF(PSI[i],PSI[j],1))==0)
4439          {
4440            PSI[j]=ideal(0);
4441          }
4442          else
4443          {
4444            if(size(NF(PSI[j],PSI[i],1))==0)
4445            {
4446              PSI[i]=ideal(0);
4447            }
4448          }
4449        }
4450      }
4451    }
4452  }
4453  for(i=sizePSI;i>=1;i--)
4454  {
4455    if(size(PSI[i])==0)
4456    {
4457      PSI=delete(PSI,i);
4458    }
4459  }
4460  return (PSI);
4461}
4462
4463
4464/////////////////////////////////////////////////////
4465// proc prim_dec
4466// input:  generators of an ideal I and an integer choose
4467// If choose=0, min_ass_prim_charsets with the given
4468// ordering of the variables is used.
4469// If choose=1, min_ass_prim_charsets with the "optimized"
4470// ordering of the variables is used.
4471// If choose=2, minAssPrimes from primdec.lib is used
4472// If choose=3, minAssPrimes+factorizing Buchberger from primdec.lib is used
4473// output: a primary decomposition of I, i.e., a list
4474// of pairs consisting of a standard basis of a primary component
4475// of I and a standard basis of the corresponding associated prime.
4476// To compute the minimal associated primes of a given ideal
4477// min_ass_prim_l is called, i.e., the minimal associated primes
4478// are computed via characteristic sets.
4479// In the homogeneous case, the performance of the procedure
4480// will be improved if I is already given by a minimal set of
4481// generators. Apply minbase if necessary.
4482//////////////////////////////////////////////////////////
4483
4484
4485static proc prim_dec(ideal I, int choose)
4486{
4487  ASSUME(0, not isQuotientRing(basering) ) ;
4488  ASSUME(0, hasGlobalOrdering(basering) ) ;
4489
4490  if((choose<0) or (choose>3))
4491  {
4492    ERROR("ERROR: <int> must be 0 or 1 or 2 or 3");
4493  }
4494  ideal H=1; // The intersection of the primary components
4495  list U;    // the leaves of the decomposition tree, i.e.,
4496             // pairs consisting of a primary component of I
4497             // and the corresponding associated prime
4498  list W;    // the non-leaf vertices in the decomposition tree.
4499             // every entry has 6 components:
4500                // 1- the vertex itself , i.e., a standard bais of the
4501                //    given ideal I (type 1), or a standard basis of a
4502                //    pseudo-primary component arising from
4503                //    pseudo-primary decomposition (type 2), or a
4504                //    standard basis of a remaining component arising from
4505                //    pseudo-primary decomposition or extraction (type 3)
4506                // 2- the type of the vertex as indicated above
4507                // 3- the weighted_tree_depth of the vertex
4508                // 4- the tester of the vertex
4509                // 5- a standard basis of the associated prime
4510                //    of a vertex of type 2, or 0 otherwise
4511                // 6- a list of pairs consisting of a standard
4512                //    basis of a minimal associated prime ideal
4513                //    of the father of the vertex and the
4514                //    irreducible factors of the "minimal
4515                //    divisor" of the seperator or extractor
4516                //    corresponding to the prime ideal
4517                //    as computed by the procedure minsat,
4518                //    if the vertex is of type 3, or
4519                //    the empty list otherwise
4520  ideal SI=std(I);
4521  if(SI[1]==1)  // primdecSY(ideal(1))
4522  {
4523    return(list());
4524  }
4525  intvec save=option(get);
4526  option(notWarnSB);
4527  int ncolsSI=ncols(SI);
4528  int ncolsH=1;
4529  W[1]=list(I,1,0,poly(1),ideal(0),list()); // The root of the tree
4530  int weighted_tree_depth;
4531  int i,j;
4532  int check;
4533  list V;  // current vertex
4534  list VV; // new vertex
4535  list QQ;
4536  list WI;
4537  ideal Qi,SQ,SRest,fac;
4538  poly tester;
4539
4540  while(1)
4541  {
4542    i=1;
4543    while(1)
4544    {
4545      while(i<=size(W)) // find vertex V of smallest weighted tree-depth
4546      {
4547        if (W[i][3]<=weighted_tree_depth) break;
4548        i++;
4549      }
4550      if (i<=size(W)) break;
4551      i=1;
4552      weighted_tree_depth++;
4553    }
4554    V=W[i];
4555    W=delete(W,i); // delete V from W
4556
4557    // now proceed by type of vertex V
4558
4559    if (V[2]==2)  // extraction needed
4560    {
4561      SQ,SRest,fac=extraction(V[1],V[5]);
4562                        // standard basis of primary component,
4563                        // standard basis of remaining component,
4564                        // irreducible factors of
4565                        // the "minimal divisor" of the extractor
4566                        // as computed by the procedure minsat,
4567      check=0;
4568      for(j=1;j<=ncolsH;j++)
4569      {
4570        if (NF(H[j],SQ,1)!=0) // Q is not redundant
4571        {
4572          check=1;
4573          break;
4574        }
4575      }
4576      if(check==1)             // Q is not redundant
4577      {
4578        QQ=list();
4579        QQ[1]=list(SQ,V[5]);  // primary component, associated prime,
4580                              // i.e., standard bases thereof
4581        U=U+QQ;
4582        H=intersect(H,SQ);
4583        H=std(H);
4584        ncolsH=ncols(H);
4585        check=0;
4586        if(ncolsH==ncolsSI)
4587        {
4588          for(j=1;j<=ncolsSI;j++)
4589          {
4590            if(leadexp(H[j])!=leadexp(SI[j]))
4591            {
4592              check=1;
4593              break;
4594            }
4595          }
4596        }
4597        else
4598        {
4599          check=1;
4600        }
4601        if(check==0) // H==I => U is a primary decomposition
4602        {
4603          option(set,save);
4604          return(U);
4605        }
4606      }
4607      if (SRest[1]!=1)        // the remaining component is not
4608                              // the whole ring
4609      {
4610        if (rad_con(V[4],SRest)==0) // the new vertex is not the
4611                                    // root of a redundant subtree
4612        {
4613          VV[1]=SRest;     // remaining component
4614          VV[2]=3;         // pseudoprimdec_special
4615          VV[3]=V[3]+1;    // weighted depth
4616          VV[4]=V[4];      // the tester did not change
4617          VV[5]=ideal(0);
4618          VV[6]=list(list(V[5],fac));
4619          W=insert(W,VV,size(W));
4620        }
4621      }
4622    }
4623    else
4624    {
4625      if (V[2]==3) // pseudo_prim_dec_special is needed
4626      {
4627        QQ,SRest=pseudo_prim_dec_special_charsets(V[1],V[6],choose);
4628                         // QQ = quadruples:
4629                         // standard basis of pseudo-primary component,
4630                         // standard basis of corresponding prime,
4631                         // seperator, irreducible factors of
4632                         // the "minimal divisor" of the seperator
4633                         // as computed by the procedure minsat,
4634                         // SRest=standard basis of remaining component
4635      }
4636      else     // V is the root, pseudo_prim_dec is needed
4637      {
4638        QQ,SRest=pseudo_prim_dec_charsets(I,SI,choose);
4639                         // QQ = quadruples:
4640                         // standard basis of pseudo-primary component,
4641                         // standard basis of corresponding prime,
4642                         // seperator, irreducible factors of
4643                         // the "minimal divisor" of the seperator
4644                         // as computed by the procedure minsat,
4645                         // SRest=standard basis of remaining component
4646      }
4647      //check
4648      for(i=size(QQ);i>=1;i--)
4649      //for(i=1;i<=size(QQ);i++)
4650      {
4651        tester=QQ[i][3]*V[4];
4652        Qi=QQ[i][2];
4653        if(NF(tester,Qi,1)!=0)  // the new vertex is not the
4654                                // root of a redundant subtree
4655        {
4656          VV[1]=QQ[i][1];
4657          VV[2]=2;
4658          VV[3]=V[3]+1;
4659          VV[4]=tester;      // the new tester as computed above
4660          VV[5]=Qi;          // QQ[i][2];
4661          VV[6]=list();
4662          W=insert(W,VV,size(W));
4663        }
4664      }
4665      if (SRest[1]!=1)        // the remaining component is not
4666                              // the whole ring
4667      {
4668        if (rad_con(V[4],SRest)==0) // the vertex is not the root
4669                                    // of a redundant subtree
4670        {
4671          VV[1]=SRest;
4672          VV[2]=3;
4673          VV[3]=V[3]+2;
4674          VV[4]=V[4];      // the tester did not change
4675          VV[5]=ideal(0);
4676          WI=list();
4677          for(i=1;i<=size(QQ);i++)
4678          {
4679            WI=insert(WI,list(QQ[i][2],QQ[i][4]));
4680          }
4681          VV[6]=WI;
4682          W=insert(W,VV,size(W));
4683        }
4684      }
4685    }
4686  }
4687  option(set,save);
4688}
4689
4690//////////////////////////////////////////////////////////////////////////
4691// proc pseudo_prim_dec_charsets
4692// input: Generators of an arbitrary ideal I, a standard basis SI of I,
4693// and an integer choo
4694// If choo=0, min_ass_prim_charsets with the given
4695// ordering of the variables is used.
4696// If choo=1, min_ass_prim_charsets with the "optimized"
4697// ordering of the variables is used.
4698// If choo=2, minAssPrimes from primdec.lib is used
4699// If choo=3, minAssPrimes+factorizing Buchberger from primdec.lib is used
4700// output: a pseudo primary decomposition of I, i.e., a list
4701// of pseudo primary components together with a standard basis of the
4702// remaining component. Each pseudo primary component is
4703// represented by a quadrupel: A standard basis of the component,
4704// a standard basis of the corresponding associated prime, the
4705// seperator of the component, and the irreducible factors of the
4706// "minimal divisor" of the seperator as computed by the procedure minsat,
4707// calls  proc pseudo_prim_dec_i
4708//////////////////////////////////////////////////////////////////////////
4709
4710
4711static proc pseudo_prim_dec_charsets (ideal I, ideal SI, int choo)
4712{
4713  ASSUME(0, not isQuotientRing(basering) ) ;
4714  ASSUME(0, hasGlobalOrdering(basering) ) ;
4715
4716  list L;          // The list of minimal associated primes,
4717                   // each one given by a standard basis
4718  if((choo==0) or (choo==1))
4719  {
4720    L=min_ass_prim_charsets(I,choo);
4721  }
4722  else
4723  {
4724    if(choo==2)
4725    {
4726      L=minAssPrimes(I);
4727    }
4728    else
4729    {
4730      L=minAssPrimes(I,1);
4731    }
4732    for(int i=size(L);i>=1;i--)
4733    {
4734      L[i]=std(L[i]);
4735    }
4736  }
4737  return (pseudo_prim_dec_i(SI,L));
4738}
4739
4740////////////////////////////////////////////////////////////////
4741// proc pseudo_prim_dec_special_charsets
4742// input: a standard basis of an ideal I whose radical is the
4743// intersection of the radicals of ideals generated by one prime ideal
4744// P_i together with one polynomial f_i, the list V6 must be the list of
4745// pairs (standard basis of P_i, irreducible factors of f_i),
4746// and an integer choo
4747// If choo=0, min_ass_prim_charsets with the given
4748// ordering of the variables is used.
4749// If choo=1, min_ass_prim_charsets with the "optimized"
4750// ordering of the variables is used.
4751// If choo=2, minAssPrimes from primdec.lib is used
4752// If choo=3, minAssPrimes+factorizing Buchberger from primdec.lib is used
4753// output: a pseudo primary decomposition of I, i.e., a list
4754// of pseudo primary components together with a standard basis of the
4755// remaining component. Each pseudo primary component is
4756// represented by a quadrupel: A standard basis of the component,
4757// a standard basis of the corresponding associated prime, the
4758// seperator of the component, and the irreducible factors of the
4759// "minimal divisor" of the seperator as computed by the procedure minsat,
4760// calls  proc pseudo_prim_dec_i
4761////////////////////////////////////////////////////////////////
4762
4763
4764static proc pseudo_prim_dec_special_charsets (ideal SI,list V6, int choo)
4765{
4766  ASSUME(0, not isQuotientRing(basering) ) ;
4767  ASSUME(0, hasGlobalOrdering(basering) ) ;
4768
4769  int i,j,l;
4770  list m;
4771  list L;
4772  int sizeL;
4773  ideal P,SP; ideal fac;
4774  int dimSP;
4775  for(l=size(V6);l>=1;l--)   // creates a list of associated primes
4776                             // of I, possibly redundant
4777  {
4778    P=V6[l][1];
4779    fac=V6[l][2];
4780    for(i=ncols(fac);i>=1;i--)
4781    {
4782      SP=P+fac[i];
4783      SP=std(SP);
4784      if(SP[1]!=1)
4785      {
4786        if((choo==0) or (choo==1))
4787        {
4788          m=min_ass_prim_charsets(SP,choo);  // a list of SB
4789        }
4790        else
4791        {
4792          if(choo==2)
4793          {
4794            m=minAssPrimes(SP);
4795          }
4796          else
4797          {
4798            m=minAssPrimes(SP,1);
4799          }
4800          for(j=size(m);j>=1;j=j-1)
4801            {
4802              m[j]=std(m[j]);
4803            }
4804        }
4805        dimSP=dim(SP);
4806        for(j=size(m);j>=1; j--)
4807        {
4808          if(dim(m[j])==dimSP)
4809          {
4810            L=insert(L,m[j],size(L));
4811          }
4812        }
4813      }
4814    }
4815  }
4816  sizeL=size(L);
4817  for(i=1;i<sizeL;i++)     // get rid of redundant primes
4818  {
4819    for(j=i+1;j<=sizeL;j++)
4820    {
4821      if(size(L[i])!=0)
4822      {
4823        if(size(L[j])!=0)
4824        {
4825          if(size(NF(L[i],L[j],1))==0)
4826          {
4827            L[j]=ideal(0);
4828          }
4829          else
4830          {
4831            if(size(NF(L[j],L[i],1))==0)
4832            {
4833              L[i]=ideal(0);
4834            }
4835          }
4836        }
4837      }
4838    }
4839  }
4840  for(i=sizeL;i>=1;i--)
4841  {
4842    if(size(L[i])==0)
4843    {
4844      L=delete(L,i);
4845    }
4846  }
4847  return (pseudo_prim_dec_i(SI,L));
4848}
4849
4850
4851////////////////////////////////////////////////////////////////
4852// proc pseudo_prim_dec_i
4853// input: A standard basis of an arbitrary ideal I, and standard bases
4854// of the minimal associated primes of I
4855// output: a pseudo primary decomposition of I, i.e., a list
4856// of pseudo primary components together with a standard basis of the
4857// remaining component. Each pseudo primary component is
4858// represented by a quadrupel: A standard basis of the component Q_i,
4859// a standard basis of the corresponding associated prime P_i, the
4860// seperator of the component, and the irreducible factors of the
4861// "minimal divisor" of the seperator as computed by the procedure minsat,
4862////////////////////////////////////////////////////////////////
4863
4864
4865static proc pseudo_prim_dec_i (ideal SI, list L)
4866{
4867  ASSUME(0, not isQuotientRing(basering) ) ;
4868  ASSUME(0, hasGlobalOrdering(basering) ) ;
4869
4870  list Q;
4871  if (size(L)==1)               // one minimal associated prime only
4872                                // the ideal is already pseudo primary
4873  {
4874    Q=SI,L[1],1;
4875    list QQ;
4876    QQ[1]=Q;
4877    return (QQ,ideal(1));
4878  }
4879
4880  poly f0,f,g;
4881  ideal fac;
4882  int i,j,k,l;
4883  ideal SQi;
4884  ideal I'=SI;
4885  list QP;
4886  int sizeL=size(L);
4887  for(i=1;i<=sizeL;i++)
4888  {
4889    fac=0;
4890    for(j=1;j<=sizeL;j++)           // compute the seperator sep_i
4891                                    // of the i-th component
4892    {
4893      if (i!=j)                       // search g not in L[i], but L[j]
4894      {
4895        for(k=1;k<=ncols(L[j]);k++)
4896        {
4897          if(NF(L[j][k],L[i],1)!=0)
4898          {
4899            break;
4900          }
4901        }
4902        fac=fac+L[j][k];
4903      }
4904    }
4905    // delete superfluous polynomials
4906    fac=simplify(fac,8+2);
4907    // saturation
4908    SQi,f0,f,fac=minsat_ppd(SI,fac);
4909    I'=I',f;
4910    QP=SQi,L[i],f0,fac;
4911             // the quadrupel:
4912             // a standard basis of Q_i,
4913             // a standard basis of P_i,
4914             // sep_i,
4915             // irreducible factors of
4916             // the "minimal divisor" of the seperator
4917             //  as computed by the procedure minsat,
4918    Q[i]=QP;
4919  }
4920  I'=std(I');
4921  return (Q, I');
4922                   // I' = remaining component
4923}
4924
4925
4926////////////////////////////////////////////////////////////////
4927// proc extraction
4928// input: A standard basis of a pseudo primary ideal I, and a standard
4929// basis of the unique minimal associated prime P of I
4930// output: an extraction of I, i.e., a standard basis of the primary
4931// component Q of I with associated prime P, a standard basis of the
4932// remaining component, and the irreducible factors of the
4933// "minimal divisor" of the extractor as computed by the procedure minsat
4934////////////////////////////////////////////////////////////////
4935
4936
4937static proc extraction (ideal SI, ideal SP)
4938{
4939  ASSUME(0, not isQuotientRing(basering) ) ;
4940  ASSUME(0, hasGlobalOrdering(basering) ) ;
4941
4942  list indsets=indepSet(SP,0);
4943  poly f;
4944  if(size(indsets)!=0)      //check, whether dim P != 0
4945  {
4946    intvec v;               // a maximal independent set of variables
4947                            // modulo P
4948    string U;               // the independent variables
4949    string A;               // the dependent variables
4950    int j,k;
4951    int a;                  //  the size of A
4952    int degf;
4953    ideal g;
4954    list polys;
4955    int sizepolys;
4956    list newpoly;
4957    def R=basering;
4958    //intvec hv=hilb(SI,1);
4959    for (k=1;k<=size(indsets);k++)
4960    {
4961      v=indsets[k];
4962      for (j=1;j<=nvars(R);j++)
4963      {
4964        if (v[j]==1)
4965        {
4966          U=U+varstr(j)+",";
4967        }
4968        else
4969        {
4970          A=A+varstr(j)+",";
4971          a++;
4972        }
4973      }
4974
4975      U[size(U)]=")";           // we compute the extractor of I (w.r.t. U)
4976      execute("ring RAU=("+charstr(basering)+"),("+A+U+",(dp("+string(a)+"),dp);");
4977      ideal I=imap(R,SI);
4978      //I=std(I,hv);            // the standard basis in (R[U])[A]
4979      I=std(I);            // the standard basis in (R[U])[A]
4980      A[size(A)]=")";
4981      execute("ring Rloc=("+charstr(basering)+","+U+",("+A+",dp;");
4982      ideal I=imap(RAU,I);
4983      //"std in lokalisierung:"+newline,I;
4984      ideal h;
4985      for(j=ncols(I);j>=1;j--)
4986      {
4987        h[j]=leadcoef(I[j]);  // consider I in (R(U))[A]
4988      }
4989      setring R;
4990      g=imap(Rloc,h);
4991      kill RAU,Rloc;
4992      U="";
4993      A="";
4994      a=0;
4995      f=lcm(g);
4996      newpoly[1]=f;
4997      polys=polys+newpoly;
4998      newpoly=list();
4999    }
5000    f=polys[1];
5001    degf=deg(f);
5002    sizepolys=size(polys);
5003    for (k=2;k<=sizepolys;k++)
5004    {
5005      if (deg(polys[k])<degf)
5006      {
5007        f=polys[k];
5008        degf=deg(f);
5009      }
5010    }
5011  }
5012  else
5013  {
5014    f=1;
5015  }
5016  poly f0,h0; ideal SQ; ideal fac;
5017  if(f!=1)
5018  {
5019    SQ,f0,h0,fac=minsat(SI,f);
5020    return(SQ,std(SI+h0),fac);
5021             // the tripel
5022             // a standard basis of Q,
5023             // a standard basis of remaining component,
5024             // irreducible factors of
5025             // the "minimal divisor" of the extractor
5026             // as computed by the procedure minsat
5027  }
5028  else
5029  {
5030    return(SI,ideal(1),ideal(1));
5031  }
5032}
5033
5034/////////////////////////////////////////////////////
5035// proc minsat
5036// input:  a standard basis of an ideal I and a polynomial p
5037// output: a standard basis IS of the saturation of I w.r. to p,
5038// the maximal squarefree factor f0 of p,
5039// the "minimal divisor" f of f0 such that the saturation of
5040// I w.r. to f equals the saturation of I w.r. to f0 (which is IS),
5041// the irreducible factors of f
5042//////////////////////////////////////////////////////////
5043
5044
5045static proc minsat(ideal SI, poly p)
5046{
5047  ASSUME(0, not isQuotientRing(basering) ) ;
5048  ASSUME(0, hasGlobalOrdering(basering) ) ;
5049
5050  ideal fac=factorize(p,1);       //the irreducible factors of p
5051  fac=sort(fac)[1];
5052  int i,k;
5053  poly f0=1;
5054  for(i=ncols(fac);i>=1;i--)
5055  {
5056    f0=f0*fac[i];
5057  }
5058  poly f=1;
5059  ideal iold;
5060  list quotM;
5061  quotM[1]=SI;
5062  quotM[2]=fac;
5063  quotM[3]=f0;
5064  // we deal seperately with the first quotient;
5065  // factors, which do not contribute to this one,
5066  // are omitted
5067  iold=quotM[1];
5068  quotM=minquot(quotM);
5069  fac=quotM[2];
5070  if(quotM[3]==1)
5071    {
5072      return(quotM[1],f0,f,fac);
5073    }
5074  while(special_ideals_equal(iold,quotM[1])==0)
5075    {
5076      f=f*quotM[3];
5077      iold=quotM[1];
5078      quotM=minquot(quotM);
5079    }
5080  return(quotM[1],f0,f,fac);           // the quadrupel ((I:p),f0,f, irr. factors of f)
5081}
5082
5083/////////////////////////////////////////////////////
5084// proc minsat_ppd
5085// input:  a standard basis of an ideal I and a polynomial p
5086// output: a standard basis IS of the saturation of I w.r. to p,
5087// the maximal squarefree factor f0 of p,
5088// the "minimal divisor" f of f0 such that the saturation of
5089// I w.r. to f equals the saturation of I w.r. to f0 (which is IS),
5090// the irreducible factors of f
5091//////////////////////////////////////////////////////////
5092
5093
5094static proc minsat_ppd(ideal SI, ideal fac)
5095{
5096  ASSUME(0, not isQuotientRing(basering) ) ;
5097  ASSUME(0, hasGlobalOrdering(basering) ) ;
5098
5099  fac=sort(fac)[1];
5100  int i,k;
5101  poly f0=1;
5102  for(i=ncols(fac);i>=1;i--)
5103  {
5104    f0=f0*fac[i];
5105  }
5106  poly f=1;
5107  ideal iold;
5108  list quotM;
5109  quotM[1]=SI;
5110  quotM[2]=fac;
5111  quotM[3]=f0;
5112  // we deal seperately with the first quotient;
5113  // factors, which do not contribute to this one,
5114  // are omitted
5115  iold=quotM[1];
5116  quotM=minquot(quotM);
5117  fac=quotM[2];
5118  if(quotM[3]==1)
5119    {
5120      return(quotM[1],f0,f,fac);
5121    }
5122  while(special_ideals_equal(iold,quotM[1])==0)
5123  {
5124    f=f*quotM[3];
5125    iold=quotM[1];
5126    quotM=minquot(quotM);
5127    k++;
5128  }
5129  return(quotM[1],f0,f,fac);           // the quadrupel ((I:p),f0,f, irr. factors of f)
5130}
5131/////////////////////////////////////////////////////////////////
5132// proc minquot
5133// input: a list with 3 components: a standard basis
5134// of an ideal I, a set of irreducible polynomials, and
5135// there product f0
5136// output: a standard basis of the ideal (I:f0), the irreducible
5137// factors of the "minimal divisor" f of f0 with (I:f0) = (I:f),
5138// the "minimal divisor" f
5139/////////////////////////////////////////////////////////////////
5140
5141static proc minquot(list tsil)
5142{
5143   ASSUME(0, not isQuotientRing(basering) ) ;
5144  ASSUME(0, hasGlobalOrdering(basering) ) ;
5145
5146   intvec op;
5147   int i,j,k,action;
5148   ideal verg;
5149   list l;
5150   poly g;
5151   ideal laedi=tsil[1];
5152   ideal fac=tsil[2];
5153   poly f=tsil[3];
5154
5155//std
5156//   ideal star=quotient(laedi,f);
5157//   star=std(star);
5158   op=option(get);
5159   option(returnSB);
5160   ideal star=quotient(laedi,f);
5161   option(set,op);
5162   if(special_ideals_equal(laedi,star)==1)
5163     {
5164       return(laedi,ideal(1),1);
5165     }
5166   action=1;
5167   while(action==1)
5168   {
5169      if(size(fac)==1)
5170      {
5171         action=0;
5172         break;
5173      }
5174      for(i=1;i<=size(fac);i++)
5175      {
5176        g=1;
5177         for(j=1;j<=size(fac);j++)
5178         {
5179            if(i!=j)
5180            {
5181               g=g*fac[j];
5182            }
5183         }
5184//std
5185//         verg=quotient(laedi,g);
5186//         verg=std(verg);
5187         op=option(get);
5188         option(returnSB);
5189         verg=quotient(laedi,g);
5190         option(set,op);
5191         if(special_ideals_equal(verg,star)==1)
5192         {
5193            f=g;
5194            fac[i]=0;
5195            fac=simplify(fac,2);
5196            break;
5197         }
5198         if(i==size(fac))
5199         {
5200            action=0;
5201         }
5202      }
5203   }
5204   l=star,fac,f;
5205   return(l);
5206}
5207/////////////////////////////////////////////////
5208// proc special_ideals_equal
5209// input: standard bases of ideal k1 and k2 such that
5210// k1 is contained in k2, or k2 is contained ink1
5211// output: 1, if k1 equals k2, 0 otherwise
5212//////////////////////////////////////////////////
5213
5214static proc special_ideals_equal( ideal k1, ideal k2)
5215{
5216   ASSUME(0, not isQuotientRing(basering) ) ;
5217  ASSUME(0, hasGlobalOrdering(basering) ) ;
5218
5219   int j;
5220   if(size(k1)==size(k2))
5221   {
5222      for(j=1;j<=size(k1);j++)
5223      {
5224         if(leadexp(k1[j])!=leadexp(k2[j]))
5225         {
5226            return(0);
5227         }
5228      }
5229      return(1);
5230   }
5231   return(0);
5232}
5233
5234
5235///////////////////////////////////////////////////////////////////////////////
5236
5237static proc convList(list l)
5238{
5239   int i;
5240   list re,he;
5241   for(i=1;i<=size(l) div 2;i++)
5242   {
5243      he=l[2*i-1],l[2*i];
5244      re[i]=he;
5245   }
5246   return(re);
5247}
5248///////////////////////////////////////////////////////////////////////////////
5249
5250static proc reconvList(list l)
5251{
5252   int i;
5253   list re;
5254   for(i=1;i<=size(l);i++)
5255   {
5256      re[2*i-1]=l[i][1];
5257      re[2*i]=l[i][2];
5258   }
5259   return(re);
5260}
5261
5262///////////////////////////////////////////////////////////////////////////////
5263//
5264//     The main procedures
5265//
5266///////////////////////////////////////////////////////////////////////////////
5267
5268proc primdecGTZ(ideal i, list #)
5269"USAGE:   primdecGTZ(i); i ideal
5270RETURN:  a list pr of primary ideals and their associated primes:
5271@format
5272   pr[i][1]   the i-th primary component,
5273   pr[i][2]   the i-th prime component.
5274@end format
5275NOTE:    - Algorithm of Gianni/Trager/Zacharias.
5276         - Designed for characteristic 0, works also in char k > 0, if it
5277           terminates (may result in an infinite loop in small characteristic!)
5278         - For local orderings, the result is considered in the localization
5279           of the polynomial ring, not in the power series ring
5280         - For local and mixed orderings, the decomposition in the
5281           corresponding global ring is returned if the string 'global'
5282           is specified as second argument
5283EXAMPLE: example primdecGTZ; shows an example
5284"
5285{
5286   ASSUME(0, not isQuotientRing(basering) ) ;
5287   if(size(#)>0)
5288   {
5289      int keep_comp=1;
5290   }
5291   if(attrib(basering,"global")!=1)
5292   {
5293// algorithms only work in global case!
5294// pass to appropriate global ring
5295      def r=basering;
5296      def s=changeord(list(list("dp",1:nvars(basering))));
5297      setring s;
5298      ideal i=imap(r,i);
5299// decompose and go back
5300      list li=primdecGTZ(i);
5301      setring r;
5302      def li=imap(s,li);
5303// clean up
5304      if(!defined(keep_comp))
5305      {
5306         for(int k=size(li);k>=1;k--)
5307         {
5308            if(mindeg(std(lead(li[k][2]))[1])==0)
5309            {
5310// 1 contained in ideal, i.e. component does not meet origin in local ordering
5311               li=delete(li,k);
5312            }
5313         }
5314      }
5315      return(li);
5316   }
5317
5318   if(minpoly!=0)
5319   {
5320      return(algeDeco(i,0));
5321      ERROR(
5322      "// Not implemented yet for algebraic extensions.Simulate the ring extension by adding the minpoly to the ideal"
5323      );
5324   }
5325  return(convList(decomp(i)));
5326}
5327example
5328{ "EXAMPLE:";  echo = 2;
5329   ring  r = 0,(x,y,z),lp;
5330   poly  p = z2+1;
5331   poly  q = z3+2;
5332   ideal i = p*q^2,y-z2;
5333   list pr = primdecGTZ(i);
5334   pr;
5335}
5336///////////////////////////////////////////////////////////////////////////////
5337proc absPrimdecGTZ(ideal I, list #)
5338"USAGE:   absPrimdecGTZ(I); I ideal
5339ASSUME:  Ground field has characteristic 0.
5340RETURN:  a ring containing two lists: @code{absolute_primes}, the absolute
5341         prime components of I, and @code{primary_decomp}, the output of
5342         @code{primdecGTZ(I)}.
5343         The list absolute_primes has to be interpreted as follows:
5344         each entry describes a class of conjugated absolute primes,
5345@format
5346   absolute_primes[i][1]   the absolute prime component,
5347   absolute_primes[i][2]   the number of conjugates.
5348@end format
5349         The first entry of @code{absolute_primes[i][1]} is the minimal
5350         polynomial of a minimal finite field extension over which the
5351         absolute prime component is defined.
5352         For local orderings, the result is considered in the localization
5353         of the polynomial ring, not in the power series ring.
5354         For local and mixed orderings, the decomposition in the
5355         corresponding global ring is returned if the string 'global'
5356         is specified as second argument
5357NOTE:    Algorithm of Gianni/Trager/Zacharias combined with the
5358         @code{absFactorize} command.
5359SEE ALSO: primdecGTZ; absFactorize
5360EXAMPLE: example absPrimdecGTZ; shows an example
5361"
5362{
5363  ASSUME(0, not isQuotientRing(basering) ) ;
5364  if (char(basering) != 0)
5365  {
5366    ERROR("primdec.lib::absPrimdecGTZ is only implemented for "+
5367           +"characteristic 0");
5368  }
5369
5370  if(size(#)>0)
5371  {
5372     int keep_comp=1;
5373  }
5374
5375  if(attrib(basering,"global")!=1)
5376  {
5377// algorithm automatically passes to the global case
5378// hence prepare to go back to an appropriate new ring
5379      def r=basering;
5380      ideal max_of_r=maxideal(1);
5381      def s=changeord(list(list("dp",1:nvars(basering))));
5382      setring s;
5383      def I=imap(r,I);
5384      def S=absPrimdecGTZ(I);
5385      setring S;
5386      ring r1=char(basering),var(nvars(r)+1),dp;
5387      def rS=r+r1;
5388// move objects to appropriate ring and clean up
5389      setring rS;
5390      def max_of_r=imap(r,max_of_r);
5391      attrib(max_of_r,"isSB",1);
5392      def absolute_primes=imap(S,absolute_primes);
5393      def primary_decomp=imap(S,primary_decomp);
5394      if(!defined(keep_comp))
5395      {
5396         ideal tempid;
5397         for(int k=size(absolute_primes);k>=1;k--)
5398         {
5399            tempid=absolute_primes[k][1];
5400            tempid[1]=0;                  // ignore minimal polynomial
5401            if(size(reduce(lead(tempid),max_of_r))!=0)
5402            {
5403// 1 contained in ideal, i.e. component does not meet origin in local ordering
5404               absolute_primes=delete(absolute_primes,k);
5405            }
5406         }
5407         for(k=size(primary_decomp);k>=1;k--)
5408         {
5409            if(mindeg(std(lead(primary_decomp[k][2]))[1])==0)
5410            {
5411// 1 contained in ideal, i.e. component does not meet origin in local ordering
5412               primary_decomp=delete(primary_decomp,k);
5413            }
5414         }
5415         kill tempid;
5416      }
5417      export(primary_decomp);
5418      export(absolute_primes);
5419      return(rS);
5420  }
5421  if(minpoly!=0)
5422  {
5423    //return(algeDeco(i,0));
5424    ERROR(
5425      "// Not implemented yet for algebraic extensions.Simulate the ring extension by adding the minpoly to the ideal"
5426    );
5427  }
5428  def R=basering;
5429  int n=nvars(R);
5430  list L=decomp(I,3);
5431  string newvar=L[1][3];
5432  int k=find(newvar,",",find(newvar,",")+1);
5433  newvar=newvar[k+1..size(newvar)];
5434  list lR=ringlist(R);
5435  int i,de,ii;
5436  intvec vv=1:n;
5437  //for(i=1;i<=n;i++){vv[i]=1;}
5438
5439  list orst;
5440  orst[1]=list("dp",vv);
5441  orst[2]=list("dp",intvec(1));
5442  orst[3]=list("C",0);
5443  lR[3]=orst;
5444  lR[2][n+1] = newvar;
5445  def Rz = ring(lR);
5446  setring Rz;
5447  list L=imap(R,L);
5448  list absolute_primes,primary_decomp;
5449  ideal I,M,N,K;
5450  M=maxideal(1);
5451  N=maxideal(1);
5452  poly p,q,f,g;
5453  map phi,psi;
5454  string tvar;
5455  for(i=1;i<=size(L);i++)
5456  {
5457    tvar=L[i][4];
5458    ii=find(tvar,"+");
5459    while(ii)
5460    {
5461      tvar=tvar[ii+1..size(tvar)];
5462      ii=find(tvar,"+");
5463    }
5464    for(ii=1;ii<=nvars(basering);ii++)
5465    {
5466      if(tvar==string(var(ii))) break;
5467    }
5468    I=L[i][2];
5469    execute("K="+L[i][3]+";");
5470    p=K[1];
5471    q=K[2];
5472    execute("f="+L[i][4]+";");
5473    g=2*var(ii)-f;
5474    M[ii]=f;
5475    N[ii]=g;
5476    de=deg(p);
5477    psi=Rz,M;
5478    phi=Rz,N;
5479    I=phi(I),p,q;
5480    I=std(I);
5481    absolute_primes[i]=list(psi(I),de);
5482    primary_decomp[i]=list(L[i][1],L[i][2]);
5483  }
5484  export(primary_decomp);
5485  export(absolute_primes);
5486  setring R;
5487  dbprint( printlevel-voice+3,"
5488// 'absPrimdecGTZ' created a ring, in which two lists absolute_primes (the
5489// absolute prime components) and primary_decomp (the primary and prime
5490// components over the current basering) are stored.
5491// To access the list of absolute prime components, type (if the name S was
5492// assigned to the return value):
5493        setring S; absolute_primes; ");
5494
5495  return(Rz);
5496}
5497example
5498{ "EXAMPLE:";  echo = 2;
5499   ring  r = 0,(x,y,z),lp;
5500   poly  p = z2+1;
5501   poly  q = z3+2;
5502   ideal i = p*q^2,y-z2;
5503   def S = absPrimdecGTZ(i);
5504   setring S;
5505   absolute_primes;
5506}
5507
5508///////////////////////////////////////////////////////////////////////////////
5509
5510proc primdecSY(ideal i, list #)
5511"USAGE:   primdecSY(I, c); I ideal, c int (optional)
5512RETURN:  a list pr of primary ideals and their associated primes:
5513@format
5514   pr[i][1]   the i-th primary component,
5515   pr[i][2]   the i-th prime component.
5516@end format
5517NOTE:    Algorithm of Shimoyama/Yokoyama.
5518@format
5519   if c=0,  the given ordering of the variables is used,
5520   if c=1,  minAssChar tries to use an optimal ordering (default),
5521   if c=2,  minAssGTZ is used,
5522   if c=3,  minAssGTZ and facstd are used.
5523@end format
5524         For local orderings, the result is considered in the localization
5525         of the polynomial ring, not in the power series ring.
5526         For local and mixed orderings, the decomposition in the
5527         corresponding global ring is returned if the string 'global'
5528         is specified as third argument
5529EXAMPLE: example primdecSY; shows an example
5530"
5531{
5532   ASSUME(0, not isQuotientRing(basering) ) ;
5533   if(size(#)>1)
5534   {
5535      int keep_comp=1;
5536   }
5537   if(attrib(basering,"global")!=1)
5538   {
5539// algorithms only work in global case!
5540// pass to appropriate global ring
5541      def r=basering;
5542      def s=changeord(list(list("dp",1:nvars(basering))));
5543      setring s;
5544      ideal i=imap(r,i);
5545// decompose and go back
5546      list li=primdecSY(i);
5547      setring r;
5548      def li=imap(s,li);
5549// clean up
5550      if(!defined(keep_comp))
5551      {
5552         for(int k=size(li);k>=1;k--)
5553         {
5554            if(mindeg(std(lead(li[k][2]))[1])==0)
5555            {
5556// 1 contained in ideal, i.e. component does not meet origin in local ordering
5557               li=delete(li,k);
5558            }
5559         }
5560      }
5561      return(li);
5562   }
5563   i=simplify(i,2);
5564   if ((i[1]==0)||(i[1]==1))
5565   {
5566     list L=list(ideal(i[1]),ideal(i[1]));
5567     return(list(L));
5568   }
5569
5570   if(minpoly!=0)
5571   {
5572      return(algeDeco(i,1));
5573   }
5574   if (size(#)!=0)
5575   { return(prim_dec(i,#[1])); }
5576   else
5577   { return(prim_dec(i,1)); }
5578}
5579example
5580{ "EXAMPLE:";  echo = 2;
5581   ring  r = 0,(x,y,z),lp;
5582   poly  p = z2+1;
5583   poly  q = z3+2;
5584   ideal i = p*q^2,y-z2;
5585   list pr = primdecSY(i);
5586   pr;
5587}
5588///////////////////////////////////////////////////////////////////////////////
5589proc minAssGTZ(ideal i,list #)
5590"USAGE:    minAssGTZ(I[, l]); I ideal, l list (optional)
5591   @* Optional parameters in list l (can be entered in any order):
5592   @* 0, \"facstd\" -> uses facstd to first decompose the ideal (default)
5593   @* 1, \"noFacstd\" -> does not use facstd
5594   @* \"GTZ\" -> the original algorithm by Gianni, Trager and Zacharias is used
5595   @* \"SL\" -> GTZ algorithm with modificiations by Laplagne is used (default)
5596
5597RETURN:  a list, the minimal associated prime ideals of I.
5598NOTE:    - Designed for characteristic 0, works also in char k > 0 based
5599           on an algorithm of Yokoyama
5600         - For local orderings, the result is considered in the localization
5601           of the polynomial ring, not in the power series ring
5602         - For local and mixed orderings, the decomposition in the
5603           corresponding global ring is returned if the string 'global'
5604           is specified as second argument
5605EXAMPLE: example minAssGTZ; shows an example
5606"
5607{
5608   ASSUME(0, not isQuotientRing(basering) ) ;
5609   if(size(#)>0)
5610   {
5611      int keep_comp=1;
5612   }
5613
5614  if(attrib(basering,"global")!=1)
5615  {
5616  // algorithms only work in global case!
5617// pass to appropriate global ring
5618      def r=basering;
5619      def s=changeord(list(list("dp",1:nvars(basering))));
5620      setring s;
5621      ideal i=imap(r,i);
5622// decompose and go back
5623      list li=minAssGTZ(i);
5624      setring r;
5625      def li=imap(s,li);
5626// clean up
5627      if(!defined(keep_comp))
5628      {
5629         for(int k=size(li);k>=1;k--)
5630         {
5631            if(mindeg(std(lead(li[k]))[1])==0)
5632            {
5633// 1 contained in ideal, i.e. component does not meet origin in local ordering
5634               li=delete(li,k);
5635            }
5636         }
5637      }
5638      return(li);
5639  }
5640
5641  int j;
5642  string algorithm;
5643  string facstdOption;
5644  int useFac;
5645
5646  // Set input parameters
5647  algorithm = "SL";         // Default: SL algorithm
5648  facstdOption = "facstd";
5649  if(size(#) > 0)
5650  {
5651    int valid;
5652    for(j = 1; j <= size(#); j++)
5653    {
5654      valid = 0;
5655      if((typeof(#[j]) == "int") or (typeof(#[j]) == "number"))
5656      {
5657        if (#[j] == 1) {facstdOption = "noFacstd"; valid = 1;}    // If #[j] == 1, facstd is not used.
5658        if (#[j] == 0) {facstdOption = "facstd";   valid = 1;}    // If #[j] == 0, facstd is used.
5659      }
5660      if(typeof(#[j]) == "string")
5661      {
5662        if((#[j] == "GTZ") || (#[j] == "SL"))
5663        {
5664          algorithm = #[j];
5665          valid = 1;
5666        }
5667        if((#[j] == "noFacstd") || (#[j] == "facstd"))
5668        {
5669          facstdOption = #[j];
5670          valid = 1;
5671        }
5672      }
5673      if(valid == 0)
5674      {
5675        dbprint(1, "Warning! The following input parameter was not recognized:", #[j]);
5676      }
5677    }
5678  }
5679
5680  if(minpoly!=0)
5681  {
5682    return(algeDeco(i,2));
5683  }
5684
5685  list result = minAssPrimes(i, facstdOption, algorithm);
5686  return(result);
5687}
5688example
5689{ "EXAMPLE:";  echo = 2;
5690   ring  r = 0,(x,y,z),dp;
5691   poly  p = z2+1;
5692   poly  q = z3+2;
5693   ideal i = p*q^2,y-z2;
5694   list pr = minAssGTZ(i);
5695   pr;
5696}
5697
5698///////////////////////////////////////////////////////////////////////////////
5699proc minAssChar(ideal i, list #)
5700"USAGE:   minAssChar(I[,c]); i ideal, c int (optional).
5701RETURN:  list, the minimal associated prime ideals of i.
5702NOTE:    If c=0, the given ordering of the variables is used. @*
5703         Otherwise, the system tries to find an optimal ordering,
5704         which in some cases may considerably speed up the algorithm. @*
5705         For local orderings, the result is considered in the localization
5706         of the polynomial ring, not in the power series ring
5707         For local and mixed orderings, the decomposition in the
5708         corresponding global ring is returned if the string 'global'
5709         is specified as third argument
5710EXAMPLE: example minAssChar; shows an example
5711"
5712{
5713   ASSUME(0, not isQuotientRing(basering) ) ;
5714   if(size(#)>1)
5715   {
5716      int keep_comp=1;
5717   }
5718   if(attrib(basering,"global")!=1)
5719   {
5720// algorithms only work in global case!
5721// pass to appropriate global ring
5722      def r=basering;
5723      def s=changeord(list(list("dp",1:nvars(basering))));
5724      setring s;
5725      ideal i=imap(r,i);
5726// decompose and go back
5727      list li=minAssChar(i);
5728      setring r;
5729      def li=imap(s,li);
5730// clean up
5731      if(!defined(keep_comp))
5732      {
5733         for(int k=size(li);k>=1;k--)
5734         {
5735            if(mindeg(std(lead(li[k]))[1])==0)
5736            {
5737// 1 contained in ideal, i.e. component does not meet origin in local ordering
5738               li=delete(li,k);
5739            }
5740         }
5741      }
5742      return(li);
5743   }
5744   if (size(#)>0)
5745   { return(min_ass_prim_charsets(i,#[1])); }
5746   else
5747   { return(min_ass_prim_charsets(i,1)); }
5748}
5749example
5750{ "EXAMPLE:";  echo = 2;
5751   ring  r = 0,(x,y,z),dp;
5752   poly  p = z2+1;
5753   poly  q = z3+2;
5754   ideal i = p*q^2,y-z2;
5755   list pr = minAssChar(i);
5756   pr;
5757}
5758///////////////////////////////////////////////////////////////////////////////
5759proc equiRadical(ideal i)
5760"USAGE:   equiRadical(I); I ideal
5761RETURN:  ideal, intersection of associated primes of I of maximal dimension.
5762NOTE:    A combination of the algorithms of Krick/Logar (with modifications by Laplagne) and Kemper is used.
5763         Works also in positive characteristic (Kempers algorithm).
5764EXAMPLE: example equiRadical; shows an example
5765"
5766{
5767  ASSUME(0, not isQuotientRing(basering) ) ;
5768  if(attrib(basering,"global")!=1)
5769  {
5770     ERROR(
5771     "// Not implemented for this ordering, please change to global ordering."
5772     );
5773  }
5774  ASSUME(0, hasGlobalOrdering(basering) ) ;
5775
5776  return(radical(i, 1));
5777}
5778example
5779{ "EXAMPLE:";  echo = 2;
5780   ring  r = 0,(x,y,z),dp;
5781   poly  p = z2+1;
5782   poly  q = z3+2;
5783   ideal i = p*q^2,y-z2;
5784   ideal pr= equiRadical(i);
5785   pr;
5786}
5787
5788///////////////////////////////////////////////////////////////////////////////
5789proc radical(ideal i, list #)
5790"USAGE: radical(I[, l]); I ideal, l list (optional)
5791 @*  Optional parameters in list l (can be entered in any order):
5792 @*  0, \"fullRad\" -> full radical is computed (default)
5793 @*  1, \"equiRad\" -> equiRadical is computed
5794 @*  \"KL\" -> Krick/Logar algorithm is used
5795 @*  \"SL\" -> modifications by Laplagne are used (default)
5796 @*  \"facstd\" -> uses facstd to first decompose the ideal (default for non homogeneous ideals)
5797 @*  \"noFacstd\" -> does not use facstd (default for homogeneous ideals)
5798RETURN:  ideal, the radical of I (or the equiradical if required in the input parameters)
5799NOTE:    A combination of the algorithms of Krick/Logar (with modifications by Laplagne) and Kemper is used.
5800         Works also in positive characteristic (Kempers algorithm).
5801EXAMPLE: example radical; shows an example
5802"
5803{
5804  ASSUME(0, not isQuotientRing(basering) ) ;
5805  dbprint(printlevel - voice, "Radical, version 2006.05.08");
5806  if(attrib(basering,"global")!=1)
5807  {
5808// algorithms only work in global case!
5809// pass to appropriate global ring
5810      def r=basering;
5811      def s=changeord(list(list("dp",1:nvars(basering))));
5812      setring s;
5813      ideal i=imap(r,i);
5814// compute radical and go back
5815      def j=radical(i);
5816      setring r;
5817      def j=imap(s,j);
5818      return(j);
5819  }
5820  if(size(i) == 0){return(ideal(0));}
5821  int j;
5822  def P0 = basering;
5823  list Pl=ringlist(P0);
5824  intvec dp_w;
5825  for(j=nvars(P0);j>0;j--) {dp_w[j]=1;}
5826  Pl[3]=list(list("dp",dp_w),list("C",0));
5827  def @P=ring(Pl);
5828  setring @P;
5829  ideal i=imap(P0,i);
5830
5831  int il;
5832  string algorithm;
5833  int useFac;
5834
5835  // Set input parameters
5836  algorithm = "SL";                                 // Default: SL algorithm
5837  il = 0;                                           // Default: Full radical (not only equiRadical)
5838  if (homog(i) == 1)
5839  {   // Default: facStd is used, except if the ideal is homogeneous.
5840    useFac = 0;
5841  }
5842  else
5843  {
5844    useFac = 1;
5845  }
5846  if(size(#) > 0)
5847  {
5848    int valid;
5849    for(j = 1; j <= size(#); j++)
5850    {
5851      valid = 0;
5852      if((typeof(#[j]) == "int") or (typeof(#[j]) == "number"))
5853      {
5854        il = #[j];          // If il == 1, equiRadical is computed
5855        valid = 1;
5856      }
5857      if(typeof(#[j]) == "string")
5858      {
5859        if(#[j] == "KL")
5860        {
5861          algorithm = "KL";
5862          valid = 1;
5863        }
5864        if(#[j] == "SL")
5865        {
5866          algorithm = "SL";
5867          valid = 1;
5868        }
5869        if(#[j] == "noFacstd")
5870        {
5871          useFac = 0;
5872          valid = 1;
5873        }
5874        if(#[j] == "facstd")
5875        {
5876          useFac = 1;
5877          valid = 1;
5878        }
5879        if(#[j] == "equiRad")
5880        {
5881          il = 1;
5882          valid = 1;
5883        }
5884        if(#[j] == "fullRad")
5885        {
5886          il = 0;
5887          valid = 1;
5888        }
5889      }
5890      if(valid == 0)
5891      {
5892        dbprint(1, "Warning! The following input parameter was not recognized:", #[j]);
5893      }
5894    }
5895  }
5896
5897  ideal rad = 1;
5898  intvec op = option(get);
5899  list qr = simplifyIdeal(i);
5900  map phi = @P, qr[2];
5901
5902  option(redSB);
5903  i = groebner(qr[1]);
5904  option(set, op);
5905  int di = dim(i);
5906
5907  if(di == 0)
5908  {
5909    i = zeroRad(i, qr[1]);
5910    option(redSB);
5911    i=interred(phi(i));
5912    option(set, op);
5913    setring(P0);
5914    i=imap(@P,i);
5915    return(i);
5916  }
5917
5918  option(redSB);
5919  list pr;
5920  if(useFac == 1)
5921  {
5922    pr = facstd(i);
5923  }
5924  else
5925  {
5926    pr = i;
5927  }
5928  option(set, op);
5929  int s = size(pr);
5930  if(useFac == 1)
5931  {
5932    dbprint(printlevel - voice, "Number of components returned by facstd: ", s);
5933  }
5934  for(j = 1; j <= s; j++)
5935  {
5936    attrib(pr[s + 1 - j], "isSB", 1);
5937    if((size(reduce(rad, pr[s + 1 - j], 1)) != 0) && ((dim(pr[s + 1 - j]) == di) || !il))
5938    {
5939      // SL Debug messages
5940      dbprint(printlevel-voice, "We shall compute the radical of ", pr[s + 1 - j]);
5941      dbprint(printlevel-voice, "The dimension is: ", dim(pr[s+1-j]));
5942
5943      if(algorithm == "KL")
5944      {
5945        rad = intersect(rad, radicalKL(pr[s + 1 - j], rad, il));
5946      }
5947      if(algorithm == "SL")
5948      {
5949        rad = intersect(rad, radicalSL(pr[s + 1 - j], il));
5950      }
5951    }
5952    else
5953    {
5954      // SL Debug
5955      dbprint(printlevel-voice, "The radical of this component is not needed.");
5956      dbprint(printlevel-voice, "size(reduce(rad, pr[s + 1 - j], 1))",
5957              size(reduce(rad, pr[s + 1 - j], 1)));
5958      dbprint(printlevel-voice, "dim(pr[s + 1 - j])", dim(pr[s + 1 - j]));
5959      dbprint(printlevel-voice, "il", il);
5960    }
5961  }
5962  rad=interred(phi(rad));
5963  setring(P0);
5964  i=imap(@P,rad);
5965  return(i);
5966}
5967example
5968{ "EXAMPLE:";  echo = 2;
5969   ring  r = 0,(x,y,z),dp;
5970   poly  p = z2+1;
5971   poly  q = z3+2;
5972   ideal i = p*q^2,y-z2;
5973   ideal pr = radical(i);
5974   pr;
5975}
5976
5977///////////////////////////////////////////////////////////////////////////////
5978//
5979// Computes the radical of I using KL algorithm.
5980// The only difference with the previous implementation of KL algorithm is
5981// that now it uses block dp instead of lp ordering for the reduction to the
5982// zerodimensional case.
5983// The reduction step has been moved to the new routine radicalReduction, so that it can be
5984// used also by radicalSL procedure.
5985//
5986static proc radicalKL(ideal I, ideal ser, list #)
5987{
5988   ASSUME(0, not isQuotientRing(basering) ) ;
5989  ASSUME(0, hasGlobalOrdering(basering) ) ;
5990
5991// ideal I     The ideal for which the radical is computed
5992// ideal ser   Used to reduce components already obtained
5993// list #      If #[1] = 1, equiradical is computed.
5994
5995  // I needs to be a Groebner basis.
5996  if (attrib(I, "isSB") != 1)
5997  {
5998    I = groebner(I);
5999  }
6000
6001  ideal rad;                                // The radical
6002  int allIndep = 1;                // All max independent sets are used
6003
6004  list result = radicalReduction(I, ser, allIndep, #);
6005  int done = result[3];
6006  rad = result[1];
6007  if (done == 0)
6008  {
6009    rad = intersect(rad, radicalKL(result[2], ideal(1), #));
6010  }
6011  return(rad);
6012}
6013
6014
6015///////////////////////////////////////////////////////////////////////////////
6016//
6017// Computes the radical of I via Laplagne algorithm, using zerodimensional radical in
6018// the zero dimensional case.
6019// For the reduction to the zerodimensional case, it uses the procedure
6020// radical, with some modifications to avoid the recursion.
6021//
6022static proc radicalSL(ideal I, list #)
6023// Input = I, ideal
6024//         #, list. If #[1] = 1, then computes only the equiradical.
6025// Output = (P, primaryDec) where P = rad(I) and primaryDec is the list of the radicals
6026// obtained in intermediate steps.
6027{
6028  ASSUME(0, not isQuotientRing(basering) ) ;
6029  ASSUME(0, hasGlobalOrdering(basering) ) ;
6030
6031  ideal rad = 1;
6032  ideal equiRad = 1;
6033  list primes;
6034  int k;                        // Counter
6035  int il;                 // If il = 1, only the equiradical is required.
6036  int iDim;                // The dimension of I
6037  int stop = 0;   // Checks if the radical has been obtained
6038
6039  if (attrib(I, "isSB") != 1)
6040  {
6041    I = groebner(I);
6042  }
6043  iDim = dim(I);
6044
6045  // Checks if only equiradical is required
6046  if (size(#) > 0)
6047  {
6048    il = #[1];
6049  }
6050
6051  while(stop == 0)
6052  {
6053    dbprint (printlevel-voice, "// We call radLoopR to find new prime ideals.");
6054    primes = radicalSLIteration(I, rad);                         // A list of primes or intersections of primes, not included in P
6055    dbprint (printlevel - voice, "// Output of Iteration Step:");
6056    dbprint (printlevel - voice, primes);
6057    if (size(primes) > 0)
6058    {
6059      dbprint (printlevel - voice, "// We intersect P with the ideal just obtained.");
6060      for(k = 1; k <= size(primes); k++)
6061      {
6062        rad = intersect(rad, primes[k]);
6063        if (il == 1)
6064        {
6065          if (attrib(primes[k], "isSB") != 1)
6066          {
6067            primes[k] = groebner(primes[k]);
6068          }
6069          if (iDim == dim(primes[k]))
6070          {
6071            equiRad = intersect(equiRad, primes[k]);
6072          }
6073        }
6074      }
6075    }
6076    else
6077    {
6078      stop = 1;
6079    }
6080  }
6081  if (il == 0)
6082  {
6083    return(rad);
6084  }
6085  else
6086  {
6087    return(equiRad);
6088  }
6089}
6090
6091//////////////////////////////////////////////////////////////////////////
6092// Based on radicalKL.
6093// It contains all of old version of proc radicalKL except the recursion call.
6094//
6095// Output:
6096// #1 -> output ideal, the part of the radical that has been computed
6097// #2 -> complementary ideal, the part of the ideal I whose radical remains to be computed
6098//       = (I, h) in KL algorithm
6099//       This is not used in the new algorithm. It is part of KL algorithm
6100// #3 -> done, 1: output = radical, there is no need to continue
6101//                   0: radical = output \cap \sqrt{complementary ideal}
6102//       This is not used in the new algorithm. It is part of KL algorithm
6103
6104static proc radicalReduction(ideal I, ideal ser, int allIndep, list #)
6105{
6106// allMaximal      1 -> Indicates that the reduction to the zerodim case
6107//                    must be done for all indep set of the leading terms ideal
6108//                 0 -> Otherwise
6109// ideal ser       Only for radicalKL. (Same as in radicalKL)
6110// list #          Only for radicalKL (If #[1] = 1,
6111//                    only equiradical is required.
6112//                    It is used to set the value of done.)
6113  ASSUME(0, not isQuotientRing(basering) ) ;
6114  ASSUME(0, hasGlobalOrdering(basering) ) ;
6115
6116  attrib(I, "isSB", 1);   // I needs to be a reduced standard basis
6117  list indep, fett;
6118  intvec @w, @hilb, op;
6119  int @wr, @n, @m, lauf, di;
6120  ideal fac, @h, collectrad, lsau;
6121  poly @q;
6122  string @va, quotring;
6123
6124  def @P = basering;
6125  int jdim = dim(I);               // Computes the dimension of I
6126  int  homo = homog(I);            // Finds out if I is homogeneous
6127  ideal rad = ideal(1);            // The unit ideal
6128  ideal te = ser;
6129  if(size(#) > 0)
6130  {
6131    @wr = #[1];
6132  }
6133  if(homo == 1)
6134  {
6135    for(@n = 1; @n <= nvars(basering); @n++)
6136    {
6137      @w[@n] = ord(var(@n));
6138    }
6139    @hilb = hilb(I, 1, @w);
6140  }
6141
6142  // SL 2006.04.11 1 Debug messages
6143  dbprint(printlevel-voice, "//Computes the radical of the ideal:", I);
6144  // SL 2006.04.11 2 Debug messages
6145
6146  //---------------------------------------------------------------------------
6147  //j is the ring
6148  //---------------------------------------------------------------------------
6149
6150  if (jdim==-1)
6151  {
6152    return(ideal(1), ideal(1), 1);
6153  }
6154
6155  //---------------------------------------------------------------------------
6156  //the zero-dimensional case
6157  //---------------------------------------------------------------------------
6158
6159  if (jdim==0)
6160  {
6161    return(zeroRad(I), ideal(1), 1);
6162  }
6163
6164  //-------------------------------------------------------------------------
6165  //search for a maximal independent set indep,i.e.
6166  //look for subring such that the intersection with the ideal is zero
6167  //j intersected with K[var(indep[3]+1),...,var(nvar)] is zero,
6168  //indep[1] is the new varstring, indep[2] the string for the block-ordering
6169  //-------------------------------------------------------------------------
6170
6171  // SL 2006-04-24 1   If allIndep = 0, then it only computes one maximal
6172  //                     independent set.
6173  //                     This looks better for the new algorithm but not for KL
6174  //                     algorithm
6175  list parameters = allIndep;
6176  indep = newMaxIndependSetDp(I, parameters);
6177  // SL 2006-04-24 2
6178
6179  for(@m = 1; @m <= size(indep); @m++)
6180  {
6181    if((indep[@m][1] == varstr(basering)) && (@m == 1))
6182    //this is the good case, nothing to do, just to have the same notations
6183    //change the ring
6184    {
6185      execute("ring gnir1 = ("+charstr(basering)+"),("+varstr(basering)+"),("
6186                              +ordstr(basering)+");");
6187      ideal @j = fetch(@P, I);
6188      attrib(@j, "isSB", 1);
6189    }
6190    else
6191    {
6192      @va = string(maxideal(1));
6193
6194      execute("ring gnir1 = (" + charstr(basering) + "), (" + indep[@m][1] + "),("
6195                              + indep[@m][2] + ");");
6196      execute("map phi = @P," + @va + ";");
6197      if(homo == 1)
6198      {
6199        ideal @j = std(phi(I), @hilb, @w);
6200      }
6201      else
6202      {
6203        ideal @j = groebner(phi(I));
6204      }
6205    }
6206    if((deg(@j[1]) == 0) || (dim(@j) < jdim))
6207    {
6208      setring @P;
6209      break;
6210    }
6211    for (lauf = 1; lauf <= size(@j); lauf++)
6212    {
6213      fett[lauf] = size(@j[lauf]);
6214    }
6215    //------------------------------------------------------------------------
6216    // We have now the following situation:
6217    // j intersected with K[var(nnp+1),..,var(nva)] is zero so we may pass
6218    // to this quotientring, j is there still a standardbasis, the
6219    // leading coefficients of the polynomials there (polynomials in
6220    // K[var(nnp+1),..,var(nva)]) are collected in the list h,
6221    // we need their LCM, gh, because of the following:
6222    // let (j:gh^n)=(j:gh^infinity) then j*K(var(nnp+1),..,var(nva))[..rest..]
6223    // intersected with K[var(1),...,var(nva)] is (j:gh^n)
6224    // on the other hand j = ((j, gh^n) intersected with (j : gh^n))
6225
6226    //------------------------------------------------------------------------
6227    // The arrangement for the quotientring K(var(nnp+1),..,var(nva))[..rest..]
6228    // and the map phi:K[var(1),...,var(nva)] ----->
6229    // K(var(nnpr+1),..,var(nva))[..the rest..]
6230    //------------------------------------------------------------------------
6231    quotring = prepareQuotientRingDp(nvars(basering) - indep[@m][3]);
6232    //------------------------------------------------------------------------
6233    // We pass to the quotientring   K(var(nnp+1),..,var(nva))[..the rest..]
6234    //------------------------------------------------------------------------
6235
6236    execute(quotring);
6237
6238    // @j considered in the quotientring
6239    ideal @j = imap(gnir1, @j);
6240
6241    kill gnir1;
6242
6243    // j is a standardbasis in the quotientring but usually not minimal
6244    // here it becomes minimal
6245
6246    @j = clearSB(@j, fett);
6247
6248    // We need later LCM(h[1],...) = gh for saturation
6249    ideal @h;
6250    if(deg(@j[1]) > 0)
6251    {
6252      for(@n = 1; @n <= size(@j); @n++)
6253      {
6254        @h[@n] = leadcoef(@j[@n]);
6255      }
6256      op = option(get);
6257      option(redSB);
6258      @j = std(@j);  //to obtain a reduced standardbasis
6259      option(set, op);
6260
6261      // SL 1 Debug messages
6262      dbprint(printlevel - voice, "zero_rad", basering, @j, dim(groebner(@j)));
6263      ideal zero_rad = zeroRad(@j);
6264      dbprint(printlevel - voice, "zero_rad passed");
6265      // SL 2
6266    }
6267    else
6268    {
6269      ideal zero_rad = ideal(1);
6270    }
6271
6272    // We need the intersection of the ideals in the list quprimary with the
6273    // polynomialring, i.e. let q=(f1,...,fr) in the quotientring such an ideal
6274    // but fi polynomials, then the intersection of q with the polynomialring
6275    // is the saturation of the ideal generated by f1,...,fr with respect to
6276    // h which is the lcm of the leading coefficients of the fi considered in
6277    // the quotientring: this is coded in saturn
6278
6279    zero_rad = std(zero_rad);
6280
6281    ideal hpl;
6282
6283    for(@n = 1; @n <= size(zero_rad); @n++)
6284    {
6285      hpl = hpl, leadcoef(zero_rad[@n]);
6286    }
6287
6288    //------------------------------------------------------------------------
6289    // We leave  the quotientring   K(var(nnp+1),..,var(nva))[..the rest..]
6290    // back to the polynomialring
6291    //------------------------------------------------------------------------
6292    setring @P;
6293
6294    collectrad = imap(quring, zero_rad);
6295    lsau = simplify(imap(quring, hpl), 2);
6296    @h = imap(quring, @h);
6297
6298    kill quring;
6299
6300    // Here the intersection with the polynomialring
6301    // mentioned above is really computed
6302
6303    collectrad = sat2(collectrad, lsau)[1];
6304    if(deg(@h[1])>=0)
6305    {
6306      fac = ideal(0);
6307      for(lauf = 1; lauf <= ncols(@h); lauf++)
6308      {
6309        if(deg(@h[lauf]) > 0)
6310        {
6311          fac = fac + factorize(@h[lauf], 1);
6312        }
6313      }
6314      fac = simplify(fac, 6);
6315      @q = 1;
6316      for(lauf = 1; lauf <= size(fac); lauf++)
6317      {
6318        @q = @q * fac[lauf];
6319      }
6320      op = option(get);
6321      option(returnSB);
6322      option(redSB);
6323      I = quotient(I + ideal(@q), rad);
6324      attrib(I, "isSB", 1);
6325      option(set, op);
6326    }
6327    if((deg(rad[1]) > 0) && (deg(collectrad[1]) > 0))
6328    {
6329      rad = intersect(rad, collectrad);
6330      te = intersect(te, collectrad);
6331      te = simplify(reduce(te, I, 1), 2);
6332    }
6333    else
6334    {
6335      if(deg(collectrad[1]) > 0)
6336      {
6337        rad = collectrad;
6338        te = intersect(te, collectrad);
6339        te = simplify(reduce(te, I, 1), 2);
6340      }
6341    }
6342
6343    if((dim(I) < jdim)||(size(te) == 0))
6344    {
6345      break;
6346    }
6347    if(homo==1)
6348    {
6349      @hilb = hilb(I, 1, @w);
6350    }
6351  }
6352
6353  // SL 2006.04.11 1 Debug messages
6354  dbprint (printlevel-voice, "// Part of the Radical already computed:", rad);
6355  dbprint (printlevel-voice, "// Dimension:", dim(groebner(rad)));
6356  // SL 2006.04.11 2 Debug messages
6357
6358  // SL 2006.04.21 1    New variable "done".
6359  //                      It tells if the radical is already computed or
6360  //                      if it still has to be computed the radical of the new ideal I
6361  int done;
6362  if(((@wr == 1) && (dim(I)<jdim)) || (deg(I[1])==0) || (size(te) == 0))
6363  {
6364    done = 1;
6365  }
6366  else
6367  {
6368    done = 0;
6369  }
6370  // SL 2006.04.21 2
6371
6372  // SL 2006.04.21 1     See details of the output at the beginning of this proc.
6373  list result = rad, I, done;
6374  return(result);
6375  // SL 2006.04.21 2
6376}
6377
6378///////////////////////////////////////////////////////////////////////////////
6379// Given an ideal I and an ideal P (intersection of some minimal prime ideals
6380// associated to I), it calculates the intersection of new minimal prime ideals
6381// associated to I which where not used to calculate P.
6382// This version uses ZD Radical in the zerodimensional case.
6383static proc radicalSLIteration (ideal I, ideal P);
6384// Input: I, ideal. The ideal from which new prime components will be obtained.
6385//        P, ideal. Intersection of some prime ideals of I.
6386// Output: ideal. Intersection of some primes of I different from the ones in P.
6387{
6388  ASSUME(0, not isQuotientRing(basering) ) ;
6389  ASSUME(0, hasGlobalOrdering(basering) ) ;
6390
6391  int k = 1;                     // Counter
6392  int good  = 0;                 // Checks if an element of P is in rad(I)
6393
6394  dbprint (printlevel-voice, "// We search for an element in P - sqrt(I).");
6395  while ((k <= size(P)) and (good == 0))
6396  {
6397    dbprint (printlevel-voice, "// We try with:", P[k]);
6398    good = 1 - rad_con(P[k], I);
6399    k++;
6400  }
6401  k--;
6402  if (good == 0)
6403  {
6404    dbprint (printlevel-voice, "// No element was found, P = sqrt(I).");
6405    list emptyList = list();
6406    return (emptyList);
6407  }
6408  dbprint(printlevel - voice, "// That one was good!");
6409  dbprint(printlevel - voice, "// We saturate I with respect to this element.");
6410  if (P[k] != 1)
6411  {
6412    intvec oo=option(get);
6413    option(redSB);
6414    ideal J = sat(I, P[k])[1];
6415    option(set,oo);
6416
6417  }
6418  else
6419  {
6420    dbprint(printlevel - voice, "// The polynomial is 1, the saturation in not actually computed.");
6421    ideal J = I;
6422  }
6423
6424  // We now call proc radicalNew;
6425  dbprint(printlevel - voice, "// We do the reduction to the zerodimensional case, via radical.");
6426  dbprint(printlevel - voice, "// The ideal is ", J);
6427  dbprint(printlevel - voice, "// The dimension is ", dim(groebner(J)));
6428
6429  int allMaximal = 0;   // Compute the zerodim reduction for only one indep set.
6430  ideal re = 1;         // No reduction is need,
6431                        //    there are not redundant components.
6432  list emptyList = list();   // Look for primes of any dimension,
6433                             //   not only of max dimension.
6434  list result = radicalReduction(J, re, allMaximal, emptyList);
6435
6436  return(result[1]);
6437}
6438
6439///////////////////////////////////////////////////////////////////////////////////
6440// Based on maxIndependSet
6441// Added list # as parameter
6442// If the first element of # is 0, the output is only 1 max indep set.
6443// If no list is specified or #[1] = 1, the output is all the max indep set of the
6444// leading terms ideal. This is the original output of maxIndependSet
6445
6446// The ordering given in the output has been changed to block dp instead of lp.
6447
6448proc newMaxIndependSetDp(ideal j, list #)
6449"USAGE:   newMaxIndependentSetDp(I); I ideal (returns all maximal independent sets of the corresponding leading terms ideal)
6450          newMaxIndependentSetDp(I, 0); I ideal (returns only one maximal independent set)
6451RETURN:  list = #1. new varstring with the maximal independent set at the end,
6452                #2. ordstring with the corresponding dp block ordering,
6453                #3. the number of independent variables
6454NOTE:
6455EXAMPLE: example newMaxIndependentSetDp; shows an example
6456"
6457{
6458  ASSUME(0, not isQuotientRing(basering) ) ;
6459  ASSUME(0, hasGlobalOrdering(basering) ) ;
6460
6461  int n, k, di;
6462  list resu, hilf;
6463  string var1, var2;
6464  list v = indepSet(j, 0);
6465
6466  // SL 2006.04.21 1 Lines modified to use only one independent Set
6467  int allMaximal;
6468  if (size(#) > 0)
6469  {
6470    allMaximal = #[1];
6471  }
6472  else
6473  {
6474    allMaximal = 1;
6475  }
6476
6477  int nMax;
6478  if (allMaximal == 1)
6479  {
6480    nMax = size(v);
6481  }
6482  else
6483  {
6484    nMax = 1;
6485  }
6486
6487  for(n = 1; n <= nMax; n++)
6488  // SL 2006.04.21 2
6489  {
6490    di = 0;
6491    var1 = "";
6492    var2 = "";
6493    for(k = 1; k <= size(v[n]); k++)
6494    {
6495     if(v[n][k] != 0)
6496      {
6497        di++;
6498        var2 = var2 + "var(" + string(k) + "), ";
6499      }
6500      else
6501      {
6502        var1 = var1 + "var(" + string(k) + "), ";
6503      }
6504    }
6505    if(di > 0)
6506    {
6507      var1 = var1 + var2;
6508      var1 = var1[1..size(var1) - 2];                         // The "- 2" removes the trailer comma
6509      hilf[1] = var1;
6510      // SL 2006.21.04 1 The order is now block dp instead of lp
6511      hilf[2] = "dp(" + string(nvars(basering) - di) + "), dp(" + string(di) + ")";
6512      // SL 2006.21.04 2
6513      hilf[3] = di;
6514      resu[n] = hilf;
6515    }
6516    else
6517    {
6518      resu[n] = varstr(basering), ordstr(basering), 0;
6519    }
6520  }
6521  return(resu);
6522}
6523example
6524{ "EXAMPLE:"; echo = 2;
6525   ring s1 = (0, x, y), (a, b, c, d, e, f, g), lp;
6526   ideal i = ea - fbg, fa + be, ec - fdg, fc + de;
6527   i = std(i);
6528   list l = newMaxIndependSetDp(i);
6529   l;
6530   i = i, g;
6531   l = newMaxIndependSetDp(i);
6532   l;
6533
6534   ring s = 0, (x, y, z), lp;
6535   ideal i = z, yx;
6536   list l = newMaxIndependSetDp(i);
6537   l;
6538}
6539
6540
6541///////////////////////////////////////////////////////////////////////////////
6542// based on prepareQuotientring
6543// The order returned is now (C, dp) instead of (C, lp)
6544
6545static proc prepareQuotientRingDp (int nnp)
6546"USAGE:   prepareQuotientRingDp(nnp); nnp int
6547RETURN:  string = to define Kvar(nnp+1),...,var(nvars)[..rest ]
6548NOTE:
6549EXAMPLE: example prepareQuotientRingDp; shows an example
6550"
6551{
6552  ASSUME(0, not isQuotientRing(basering) ) ;
6553  ASSUME(0, hasGlobalOrdering(basering) ) ;
6554
6555  ideal @ih,@jh;
6556  int npar=npars(basering);
6557  int @n;
6558
6559  string quotring= "ring quring = ("+charstr(basering);
6560  for(@n = nnp + 1; @n <= nvars(basering); @n++)
6561  {
6562     quotring = quotring + ", var(" + string(@n) + ")";
6563     @ih = @ih + var(@n);
6564  }
6565
6566  quotring = quotring+"),(var(1)";
6567  @jh = @jh + var(1);
6568  for(@n = 2; @n <= nnp; @n++)
6569  {
6570    quotring = quotring + ", var(" + string(@n) + ")";
6571    @jh = @jh + var(@n);
6572  }
6573  // SL 2006-04-21 1 The order returned is now (C, dp) instead of (C, lp)
6574  quotring = quotring + "), (C, dp);";
6575  // SL 2006-04-21 2
6576
6577  return(quotring);
6578}
6579example
6580{ "EXAMPLE:"; echo = 2;
6581   ring s1=(0,x),(a,b,c,d,e,f,g),lp;
6582   def @Q=basering;
6583   list l= prepareQuotientRingDp(3);
6584   l;
6585   execute(l[1]);
6586   execute(l[2]);
6587   basering;
6588   phi;
6589   setring @Q;
6590
6591}
6592
6593///////////////////////////////////////////////////////////////////////////////
6594proc prepareAss(ideal i)
6595"USAGE:   prepareAss(I); I ideal
6596RETURN:  list, the radicals of the maximal dimensional components of I.
6597NOTE:    Uses algorithm of Eisenbud/Huneke/Vasconcelos.
6598EXAMPLE: example prepareAss; shows an example
6599"
6600{
6601  ASSUME(0, not isQuotientRing(basering) ) ;
6602  if(attrib(basering,"global")!=1)
6603  {
6604      ERROR(
6605      "// Not implemented for this ordering, please change to global ordering."
6606      );
6607  }
6608  ASSUME(0, hasGlobalOrdering(basering) ) ;
6609
6610  ideal j=std(i);
6611  int cod=nvars(basering)-dim(j);
6612  int e;
6613  list er;
6614  ideal ann;
6615  if(homog(i)==1)
6616  {
6617     list re=sres(j,0);                   //the resolution
6618     re=minres(re);                       //minimized resolution
6619  }
6620  else
6621  {
6622    list re=mres(i,0);
6623  }
6624  for(e=cod;e<=nvars(basering);e++)
6625  {
6626     ann=AnnExt_R(e,re);
6627
6628     if(nvars(basering)-dim(std(ann))==e)
6629     {
6630        er[size(er)+1]=equiRadical(ann);
6631     }
6632  }
6633  return(er);
6634}
6635example
6636{ "EXAMPLE:";  echo = 2;
6637   ring  r = 0,(x,y,z),dp;
6638   poly  p = z2+1;
6639   poly  q = z3+2;
6640   ideal i = p*q^2,y-z2;
6641   list pr = prepareAss(i);
6642   pr;
6643}
6644///////////////////////////////////////////////////////////////////////////////
6645proc equidimMaxEHV(ideal i)
6646"USAGE:  equidimMaxEHV(I); I ideal
6647RETURN:  ideal, the equidimensional component (of maximal dimension) of I.
6648NOTE:    Uses algorithm of Eisenbud, Huneke and Vasconcelos.
6649EXAMPLE: example equidimMaxEHV; shows an example
6650"
6651{
6652  ASSUME(0, not isQuotientRing(basering) ) ;
6653  if(attrib(basering,"global")!=1)
6654  {
6655      ERROR(
6656      "// Not implemented for this ordering, please change to global ordering."
6657      );
6658  }
6659  ASSUME(0, hasGlobalOrdering(basering) ) ;
6660
6661  ideal j=groebner(i);
6662  int cod=nvars(basering)-dim(j);
6663  int e;
6664  ideal ann;
6665  if(homog(i)==1)
6666  {
6667     list re=sres(j,0);                   //the resolution
6668     re=minres(re);                       //minimized resolution
6669  }
6670  else
6671  {
6672    list re=mres(i,0);
6673  }
6674  ann=AnnExt_R(cod,re);
6675  return(ann);
6676}
6677example
6678{ "EXAMPLE:";  echo = 2;
6679   ring  r = 0,(x,y,z),dp;
6680   ideal i=intersect(ideal(z),ideal(x,y),ideal(x2,z2),ideal(x5,y5,z5));
6681   equidimMaxEHV(i);
6682}
6683
6684proc testPrimary(list pr, ideal k)
6685"USAGE:   testPrimary(pr,k); pr a list, k an ideal.
6686ASSUME:  pr is the result of primdecGTZ(k) or primdecSY(k).
6687RETURN:  int, 1 if the intersection of the ideals in pr is k, 0 if not
6688EXAMPLE: example testPrimary; shows an example
6689"
6690{
6691   ASSUME(0, not isQuotientRing(basering) ) ;
6692  ASSUME(0, hasGlobalOrdering(basering) ) ;
6693
6694   int i;
6695   pr=reconvList(pr);
6696   ideal j=pr[1];
6697   for (i=2;i<=size(pr) div 2;i++)
6698   {
6699       j=intersect(j,pr[2*i-1]);
6700   }
6701   return(idealsEqual(j,k));
6702}
6703example
6704{ "EXAMPLE:";  echo = 2;
6705   ring  r = 32003,(x,y,z),dp;
6706   poly  p = z2+1;
6707   poly  q = z4+2;
6708   ideal i = p^2*q^3,(y-z3)^3,(x-yz+z4)^4;
6709   list pr = primdecGTZ(i);
6710   testPrimary(pr,i);
6711}
6712
6713///////////////////////////////////////////////////////////////////////////////
6714proc zerodec(ideal I)
6715"USAGE:   zerodec(I); I ideal
6716ASSUME:  I is zero-dimensional, the characteristic of the ground field is 0
6717RETURN:  list of primary ideals, the zero-dimensional decomposition of I
6718NOTE:    The algorithm (of Monico), works well only for a small total number
6719         of solutions (@code{vdim(std(I))} should be < 100) and without
6720         parameters. In practice, it works also in large characteristic p>0
6721         but may fail for small p.
6722@*       If printlevel > 0 (default = 0) additional information is displayed.
6723EXAMPLE: example zerodec; shows an example
6724"
6725{
6726  ASSUME(0, not isQuotientRing(basering) ) ;
6727  if(attrib(basering,"global")!=1)
6728  {
6729    ERROR(
6730    "// Not implemented for this ordering, please change to global ordering."
6731    );
6732  }
6733  ASSUME(0, hasGlobalOrdering(basering) ) ;
6734
6735  def R=basering;
6736  poly q;
6737  int j,time;
6738  matrix m;
6739  list re;
6740  poly va=var(1);
6741  ideal J=groebner(I);
6742  ideal ba=kbase(J);
6743  int d=vdim(J);
6744  dbprint(printlevel-voice+2,"// multiplicity of ideal : "+ string(d));
6745//------ compute matrix of multiplication on R/I with generic element p -----
6746  int e=nvars(basering);
6747  poly p=randomLast(100)[e]+random(-50,50);     //the generic element
6748  matrix n[d][d];
6749  time = timer;
6750  for(j=2;j<=e;j++)
6751  {
6752    va=va*var(j);
6753  }
6754  for(j=1;j<=d;j++)
6755  {
6756    q=reduce(p*ba[j],J);
6757    m=coeffs(q,ba,va);
6758    n[j,1..d]=m[1..d,1];
6759  }
6760  dbprint(printlevel-voice+2,
6761    "// time for computing multiplication matrix (with generic element) : "+
6762    string(timer-time));
6763//---------------- compute characteristic polynomial of matrix --------------
6764  execute("ring P1=("+charstr(R)+"),T,dp;");
6765  matrix n=imap(R,n);
6766  time = timer;
6767  poly charpol=det(n-T*freemodule(d));
6768  dbprint(printlevel-voice+2,"// time for computing char poly: "+
6769         string(timer-time));
6770//------------------- factorize characteristic polynomial -------------------
6771//check first if constant term of charpoly is != 0 (which is true for
6772//sufficiently generic element)
6773  if(charpol[size(charpol)]!=0)
6774  {
6775    time = timer;
6776    list fac=factor(charpol);
6777    testFactor(fac,charpol);
6778    dbprint(printlevel-voice+2,"// time for factorizing char poly: "+
6779            string(timer-time));
6780    int f=size(fac[1]);
6781//--------------------------- the irreducible case --------------------------
6782    if(f==1)
6783    {
6784      setring R;
6785      re=I;
6786      return(re);
6787    }
6788//---------------------------- the reducible case ---------------------------
6789//if f_i are the irreducible factors of charpoly, mult=ri, then <I,g_i^ri>
6790//are the primary components where g_i = f_i(p). However, substituting p in
6791//f_i may result in a huge object although the final result may be small.
6792//Hence it is better to simultaneously reduce with I. For this we need a new
6793//ring.
6794    execute("ring P=("+charstr(R)+"),(T,"+varstr(R)+"),(dp(1),dp);");
6795    list rfac=imap(P1,fac);
6796    intvec ov=option(get);;
6797    option(redSB);
6798    list re1;
6799    ideal new = T-imap(R,p),imap(R,J);
6800    attrib(new, "isSB",1);    //we know that new is a standard basis
6801    for(j=1;j<=f;j++)
6802    {
6803      re1[j]=reduce(rfac[1][j]^rfac[2][j],new);
6804    }
6805    setring R;
6806    re = imap(P,re1);
6807    for(j=1;j<=f;j++)
6808    {
6809      J=I,re[j];
6810      re[j]=interred(J);
6811    }
6812    option(set,ov);
6813    return(re);
6814  }
6815  else
6816//------------------- choice of generic element failed -------------------
6817  {
6818    dbprint(printlevel-voice+2,"// try new generic element!");
6819    setring R;
6820    return(zerodec(I));
6821  }
6822}
6823example
6824{ "EXAMPLE:";  echo = 2;
6825   ring r  = 0,(x,y),dp;
6826   ideal i = x2-2,y2-2;
6827   list pr = zerodec(i);
6828   pr;
6829}
6830///////////////////////////////////////////////////////////////////////////////
6831static proc newDecompStep(ideal i, list #)
6832"USAGE:  newDecompStep(i); i ideal  (for primary decomposition)
6833         newDecompStep(i,1);        (for the associated primes of dimension of i)
6834         newDecompStep(i,2);        (for the minimal associated primes)
6835         newDecompStep(i,3);        (for the absolute primary decomposition (not tested!))
6836         "oneIndep";        (for using only one max indep set)
6837         "intersect";        (returns alse the intersection of the components founded)
6838
6839RETURN:  list = list of primary ideals and their associated primes
6840         (at even positions in the list)
6841         (resp. a list of the minimal associated primes)
6842NOTE:    Algorithm of Gianni/Trager/Zacharias
6843EXAMPLE: example newDecompStep; shows an example
6844"
6845{
6846  ASSUME(0, not isQuotientRing(basering) ) ;
6847  ASSUME(0, hasGlobalOrdering(basering) ) ;
6848
6849  intvec op,@vv;
6850  def  @P = basering;
6851  list primary,indep,ltras;
6852  intvec @vh,isat,@w;
6853  int @wr,@k,@n,@m,@n1,@n2,@n3,homo,seri,keepdi,abspri,ab,nn;
6854  ideal peek=i;
6855  ideal ser,tras;
6856  list data;
6857  list result;
6858  intvec @hilb;
6859  int isS=(attrib(i,"isSB")==1);
6860
6861  // Debug
6862  dbprint(printlevel - voice, "newDecompStep, v2.0");
6863
6864  string indepOption = "allIndep";
6865  string intersectOption = "noIntersect";
6866
6867  if(size(#)>0)
6868  {
6869    int count = 1;
6870    if(typeof(#[count]) == "string")
6871    {
6872      if ((#[count] == "oneIndep") or (#[count] == "allIndep"))
6873      {
6874        indepOption = #[count];
6875        count++;
6876      }
6877    }
6878    if(typeof(#[count]) == "string")
6879    {
6880      if ((#[count] == "intersect") or (#[count] == "noIntersect"))
6881      {
6882        intersectOption = #[count];
6883        count++;
6884      }
6885    }
6886    if((typeof(#[count]) == "int") or (typeof(#[count]) == "number"))
6887    {
6888      if ((#[count]==1)||(#[count]==2)||(#[count]==3))
6889      {
6890        @wr=#[count];
6891        if(@wr==3){abspri = 1; @wr = 0;}
6892        count++;
6893      }
6894    }
6895    if(size(#)>count)
6896    {
6897      seri=1;
6898      peek=#[count + 1];
6899      ser=#[count + 2];
6900    }
6901  }
6902  if(abspri)
6903  {
6904    list absprimary,abskeep,absprimarytmp,abskeeptmp;
6905  }
6906  homo=homog(i);
6907  if(homo==1)
6908  {
6909    if(attrib(i,"isSB")!=1)
6910    {
6911      //ltras=mstd(i);
6912      tras=groebner(i);
6913      ltras=tras,tras;
6914      attrib(ltras[1],"isSB",1);
6915    }
6916    else
6917    {
6918      ltras=i,i;
6919      attrib(ltras[1],"isSB",1);
6920    }
6921    tras = ltras[1];
6922    attrib(tras,"isSB",1);
6923    if(dim(tras)==0)
6924    {
6925      primary[1]=ltras[2];
6926      primary[2]=maxideal(1);
6927      if(@wr>0)
6928      {
6929        list l;
6930        l[2]=maxideal(1);
6931        l[1]=maxideal(1);
6932        if (intersectOption == "intersect")
6933        {
6934          return(list(l, maxideal(1)));
6935        }
6936        else
6937        {
6938          return(l);
6939        }
6940      }
6941      if (intersectOption == "intersect")
6942      {
6943        return(list(primary, primary[1]));
6944      }
6945      else
6946      {
6947        return(primary);
6948      }
6949    }
6950    for(@n=1;@n<=nvars(basering);@n++)
6951    {
6952      @w[@n]=ord(var(@n));
6953    }
6954    @hilb=hilb(tras,1,@w);
6955    intvec keephilb=@hilb;
6956  }
6957
6958  //----------------------------------------------------------------
6959  //i is the zero-ideal
6960  //----------------------------------------------------------------
6961
6962  if(size(i)==0)
6963  {
6964    primary=i,i;
6965    if (intersectOption == "intersect")
6966    {
6967      return(list(primary, i));
6968    }
6969    else
6970    {
6971      return(primary);
6972    }
6973  }
6974
6975  //----------------------------------------------------------------
6976  //pass to the lexicographical ordering and compute a standardbasis
6977  //----------------------------------------------------------------
6978
6979  int lp=islp();
6980
6981  execute("ring gnir = ("+charstr(basering)+"),("+varstr(basering)+"),(C,lp);");
6982  op=option(get);
6983  option(redSB);
6984
6985  ideal ser=fetch(@P,ser);
6986  if(homo==1)
6987  {
6988    if(!lp)
6989    {
6990      ideal @j=std(fetch(@P,i),@hilb,@w);
6991    }
6992    else
6993    {
6994      ideal @j=fetch(@P,tras);
6995      attrib(@j,"isSB",1);
6996    }
6997  }
6998  else
6999  {
7000    if(lp&&isS)
7001    {
7002      ideal @j=fetch(@P,i);
7003      attrib(@j,"isSB",1);
7004    }
7005    else
7006    {
7007      ideal @j=groebner(fetch(@P,i));
7008    }
7009  }
7010  option(set,op);
7011  if(seri==1)
7012  {
7013    ideal peek=fetch(@P,peek);
7014    attrib(peek,"isSB",1);
7015  }
7016  else
7017  {
7018    ideal peek=@j;
7019  }
7020  if((size(ser)==0)&&(!abspri))
7021  {
7022    ideal fried;
7023    @n=size(@j);
7024    for(@k=1;@k<=@n;@k++)
7025    {
7026      if(deg(lead(@j[@k]))==1)
7027      {
7028        fried[size(fried)+1]=@j[@k];
7029        @j[@k]=0;
7030      }
7031    }
7032    if(size(fried)==nvars(basering))
7033    {
7034      setring @P;
7035      primary[1]=i;
7036      primary[2]=i;
7037      if (intersectOption == "intersect")
7038      {
7039        return(list(primary, i));
7040      }
7041      else
7042      {
7043        return(primary);
7044      }
7045    }
7046    if(size(fried)>0)
7047    {
7048      string newva;
7049      string newma;
7050      for(@k=1;@k<=nvars(basering);@k++)
7051      {
7052        @n1=0;
7053        for(@n=1;@n<=size(fried);@n++)
7054        {
7055          if(leadmonom(fried[@n])==var(@k))
7056          {
7057            @n1=1;
7058            break;
7059          }
7060        }
7061        if(@n1==0)
7062        {
7063          newva=newva+string(var(@k))+",";
7064          newma=newma+string(var(@k))+",";
7065        }
7066        else
7067        {
7068          newma=newma+string(0)+",";
7069        }
7070      }
7071      newva[size(newva)]=")";
7072      newma[size(newma)]=";";
7073      execute("ring @deirf=("+charstr(gnir)+"),("+newva+",lp;");
7074      execute("map @kappa=gnir,"+newma);
7075      ideal @j= @kappa(@j);
7076      @j=simplify(@j, 2);
7077      attrib(@j,"isSB",1);
7078      result = newDecompStep(@j, indepOption, intersectOption, @wr);
7079      if (intersectOption == "intersect")
7080      {
7081       list pr = result[1];
7082       ideal intersection = result[2];
7083      }
7084      else
7085      {
7086        list pr = result;
7087      }
7088
7089      setring gnir;
7090      list pr=imap(@deirf,pr);
7091      for(@k=1;@k<=size(pr);@k++)
7092      {
7093        @j=pr[@k]+fried;
7094        pr[@k]=@j;
7095      }
7096      if (intersectOption == "intersect")
7097      {
7098        ideal intersection = imap(@deirf, intersection);
7099        @j = intersection + fried;
7100        intersection = @j;
7101      }
7102      setring @P;
7103      if (intersectOption == "intersect")
7104      {
7105        return(list(imap(gnir,pr), imap(gnir,intersection)));
7106      }
7107      else
7108      {
7109        return(imap(gnir,pr));
7110      }
7111    }
7112  }
7113  //----------------------------------------------------------------
7114  //j is the ring
7115  //----------------------------------------------------------------
7116
7117  if (dim(@j)==-1)
7118  {
7119    setring @P;
7120    primary=ideal(1),ideal(1);
7121    if (intersectOption == "intersect")
7122    {
7123      return(list(primary, ideal(1)));
7124    }
7125    else
7126    {
7127      return(primary);
7128    }
7129  }
7130
7131  //----------------------------------------------------------------
7132  //  the case of one variable
7133  //----------------------------------------------------------------
7134
7135  if(nvars(basering)==1)
7136  {
7137    list fac=factor(@j[1]);
7138    list gprimary;
7139    poly generator;
7140    ideal gIntersection;
7141    for(@k=1;@k<=size(fac[1]);@k++)
7142    {
7143      if(@wr==0)
7144      {
7145        gprimary[2*@k-1]=ideal(fac[1][@k]^fac[2][@k]);
7146        gprimary[2*@k]=ideal(fac[1][@k]);
7147      }
7148      else
7149      {
7150        gprimary[2*@k-1]=ideal(fac[1][@k]);
7151        gprimary[2*@k]=ideal(fac[1][@k]);
7152      }
7153      if (intersectOption == "intersect")
7154      {
7155        generator = generator * fac[1][@k];
7156      }
7157    }
7158    if (intersectOption == "intersect")
7159    {
7160      gIntersection = generator;
7161    }
7162    setring @P;
7163    primary=fetch(gnir,gprimary);
7164    if (intersectOption == "intersect")
7165    {
7166      ideal intersection = fetch(gnir,gIntersection);
7167    }
7168
7169//HIER
7170    if(abspri)
7171    {
7172      list resu,tempo;
7173      string absotto;
7174      for(ab=1;ab<=size(primary) div 2;ab++)
7175      {
7176        absotto= absFactorize(primary[2*ab][1],77);
7177        tempo=primary[2*ab-1],primary[2*ab],absotto,string(var(nvars(basering)));
7178        resu[ab]=tempo;
7179      }
7180      primary=resu;
7181      intersection = 1;
7182      for(ab=1;ab<=size(primary);ab++)
7183      {
7184        intersection = intersect(intersection, primary[ab][2]);
7185      }
7186    }
7187    if (intersectOption == "intersect")
7188    {
7189      return(list(primary, intersection));
7190    }
7191    else
7192    {
7193      return(primary);
7194    }
7195  }
7196
7197 //------------------------------------------------------------------
7198 //the zero-dimensional case
7199 //------------------------------------------------------------------
7200  if (dim(@j)==0)
7201  {
7202    op=option(get);
7203    option(redSB);
7204    list gprimary= newZero_decomp(@j,ser,@wr);
7205
7206    setring @P;
7207    primary=fetch(gnir,gprimary);
7208
7209    if(size(ser)>0)
7210    {
7211      primary=cleanPrimary(primary);
7212    }
7213//HIER
7214    if(abspri)
7215    {
7216      list resu,tempo;
7217      string absotto;
7218      for(ab=1;ab<=size(primary) div 2;ab++)
7219      {
7220        absotto= absFactorize(primary[2*ab][1],77);
7221        tempo=primary[2*ab-1],primary[2*ab],absotto,string(var(nvars(basering)));
7222        resu[ab]=tempo;
7223      }
7224      primary=resu;
7225    }
7226    option(set,op);
7227    if (intersectOption == "intersect")
7228    {
7229      return(list(primary, fetch(gnir,@j)));
7230    }
7231    else
7232    {
7233      return(primary);
7234    }
7235  }
7236
7237  poly @gs,@gh,@p;
7238  string @va,quotring;
7239  list quprimary,htprimary,collectprimary,lsau,lnew,allindep,restindep;
7240  ideal @h;
7241  int jdim=dim(@j);
7242  list fett;
7243  int lauf,di,newtest;
7244  //------------------------------------------------------------------
7245  //search for a maximal independent set indep,i.e.
7246  //look for subring such that the intersection with the ideal is zero
7247  //j intersected with K[var(indep[3]+1),...,var(nvar] is zero,
7248  //indep[1] is the new varstring and indep[2] the string for block-ordering
7249  //------------------------------------------------------------------
7250  if(@wr!=1)
7251  {
7252    allindep = newMaxIndependSetLp(@j, indepOption);
7253    for(@m=1;@m<=size(allindep);@m++)
7254    {
7255      if(allindep[@m][3]==jdim)
7256      {
7257        di++;
7258        indep[di]=allindep[@m];
7259      }
7260      else
7261      {
7262        lauf++;
7263        restindep[lauf]=allindep[@m];
7264      }
7265    }
7266  }
7267  else
7268  {
7269    indep = newMaxIndependSetLp(@j, indepOption);
7270  }
7271
7272  ideal jkeep=@j;
7273  if(ordstr(@P)[1]=="w")
7274  {
7275    execute("ring @Phelp=("+charstr(gnir)+"),("+varstr(gnir)+"),("+ordstr(@P)+");");
7276  }
7277  else
7278  {
7279    execute( "ring @Phelp=("+charstr(gnir)+"),("+varstr(gnir)+"),(C,dp);");
7280  }
7281
7282  if(homo==1)
7283  {
7284    if((ordstr(@P)[3]=="d")||(ordstr(@P)[1]=="d")||(ordstr(@P)[1]=="w")
7285       ||(ordstr(@P)[3]=="w"))
7286    {
7287      ideal jwork=imap(@P,tras);
7288      attrib(jwork,"isSB",1);
7289    }
7290    else
7291    {
7292      ideal jwork=std(imap(gnir,@j),@hilb,@w);
7293    }
7294  }
7295  else
7296  {
7297    ideal jwork=groebner(imap(gnir,@j));
7298  }
7299  list hquprimary;
7300  poly @p,@q;
7301  ideal @h,fac,ser;
7302//Aenderung================
7303  ideal @Ptest=1;
7304//=========================
7305  di=dim(jwork);
7306  keepdi=di;
7307
7308  ser = 1;
7309
7310  setring gnir;
7311  for(@m=1; @m<=size(indep); @m++)
7312  {
7313    data[1] = indep[@m];
7314    result = newReduction(@j, ser, @hilb, @w, jdim, abspri, @wr, data);
7315    quprimary = quprimary + result[1];
7316    if(abspri)
7317    {
7318      absprimary = absprimary + result[2];
7319      abskeep = abskeep + result[3];
7320    }
7321    @h = result[5];
7322    ser = result[4];
7323    if(size(@h)>0)
7324    {
7325      //---------------------------------------------------------------
7326      //we change to @Phelp to have the ordering dp for saturation
7327      //---------------------------------------------------------------
7328
7329      setring @Phelp;
7330      @h=imap(gnir,@h);
7331//Aenderung==================================
7332      if(defined(@LL)){kill @LL;}
7333      list @LL=minSat(jwork,@h);
7334      @Ptest=intersect(@Ptest,@LL[1]);
7335      ser = intersect(ser, @LL[1]);
7336//===========================================
7337
7338      if(@wr!=1)
7339      {
7340//Aenderung==================================
7341        @q=@LL[2];
7342//===========================================
7343        //@q=minSat(jwork,@h)[2];
7344      }
7345      else
7346      {
7347        fac=ideal(0);
7348        for(lauf=1;lauf<=ncols(@h);lauf++)
7349        {
7350          if(deg(@h[lauf])>0)
7351          {
7352            fac=fac+factorize(@h[lauf],1);
7353          }
7354        }
7355        fac=simplify(fac,6);
7356        @q=1;
7357        for(lauf=1;lauf<=size(fac);lauf++)
7358        {
7359          @q=@q*fac[lauf];
7360        }
7361      }
7362      jwork = std(jwork,@q);
7363      keepdi = dim(jwork);
7364      if(keepdi < di)
7365      {
7366        setring gnir;
7367        @j = imap(@Phelp, jwork);
7368        ser = imap(@Phelp, ser);
7369        break;
7370      }
7371      if(homo == 1)
7372      {
7373        @hilb = hilb(jwork, 1, @w);
7374      }
7375
7376      setring gnir;
7377      ser = imap(@Phelp, ser);
7378      @j = imap(@Phelp, jwork);
7379    }
7380  }
7381
7382  if((size(quprimary)==0)&&(@wr==1))
7383  {
7384     @j=ideal(1);
7385     quprimary[1]=ideal(1);
7386     quprimary[2]=ideal(1);
7387  }
7388  if((size(quprimary)==0))
7389  {
7390    keepdi = di - 1;
7391    quprimary[1]=ideal(1);
7392    quprimary[2]=ideal(1);
7393  }
7394  //---------------------------------------------------------------
7395  //notice that j=sat(j,gh) intersected with (j,gh^n)
7396  //we finished with sat(j,gh) and have to start with (j,gh^n)
7397  //---------------------------------------------------------------
7398  if((deg(@j[1])!=0)&&(@wr!=1))
7399  {
7400     if(size(quprimary)>0)
7401     {
7402        setring @Phelp;
7403        ser=imap(gnir,ser);
7404
7405        hquprimary=imap(gnir,quprimary);
7406        if(@wr==0)
7407        {
7408//Aenderung====================================================
7409//HIER STATT DURCHSCHNITT SATURIEREN!
7410           ideal htest=@Ptest;
7411/*
7412           ideal htest=hquprimary[1];
7413           for (@n1=2;@n1<=size(hquprimary) div 2;@n1++)
7414           {
7415              htest=intersect(htest,hquprimary[2*@n1-1]);
7416           }
7417*/
7418//=============================================================
7419        }
7420        else
7421        {
7422           ideal htest=hquprimary[2];
7423
7424           for (@n1=2;@n1<=size(hquprimary) div 2;@n1++)
7425           {
7426              htest=intersect(htest,hquprimary[2*@n1]);
7427           }
7428        }
7429
7430        if(size(ser)>0)
7431        {
7432           ser=intersect(htest,ser);
7433        }
7434        else
7435        {
7436          ser=htest;
7437        }
7438        setring gnir;
7439        ser=imap(@Phelp,ser);
7440     }
7441     if(size(reduce(ser,peek,1))!=0)
7442     {
7443        for(@m=1;@m<=size(restindep);@m++)
7444        {
7445         // if(restindep[@m][3]>=keepdi)
7446         // {
7447           isat=0;
7448           @n2=0;
7449
7450           if(restindep[@m][1]==varstr(basering))
7451           //the good case, nothing to do, just to have the same notations
7452           //change the ring
7453           {
7454              execute("ring gnir1 = ("+charstr(basering)+"),("+
7455                varstr(basering)+"),("+ordstr(basering)+");");
7456              ideal @j=fetch(gnir,jkeep);
7457              attrib(@j,"isSB",1);
7458           }
7459           else
7460           {
7461              @va=string(maxideal(1));
7462              execute("ring gnir1 = ("+charstr(basering)+"),("+
7463                      restindep[@m][1]+"),(" +restindep[@m][2]+");");
7464              execute("map phi=gnir,"+@va+";");
7465              op=option(get);
7466              option(redSB);
7467              if(homo==1)
7468              {
7469                 ideal @j=std(phi(jkeep),keephilb,@w);
7470              }
7471              else
7472              {
7473                ideal @j=groebner(phi(jkeep));
7474              }
7475              ideal ser=phi(ser);
7476              option(set,op);
7477           }
7478
7479           for (lauf=1;lauf<=size(@j);lauf++)
7480           {
7481              fett[lauf]=size(@j[lauf]);
7482           }
7483           //------------------------------------------------------------------
7484           //we have now the following situation:
7485           //j intersected with K[var(nnp+1),..,var(nva)] is zero so we may
7486           //pass to this quotientring, j is their still a standardbasis, the
7487           //leading coefficients of the polynomials  there (polynomials in
7488           //K[var(nnp+1),..,var(nva)]) are collected in the list h,
7489           //we need their ggt, gh, because of the following:
7490           //let (j:gh^n)=(j:gh^infinity) then
7491           //j*K(var(nnp+1),..,var(nva))[..the rest..]
7492           //intersected with K[var(1),...,var(nva)] is (j:gh^n)
7493           //on the other hand j=(j,gh^n) intersected with (j:gh^n)
7494
7495           //------------------------------------------------------------------
7496
7497           //the arrangement for the quotientring
7498           // K(var(nnp+1),..,var(nva))[..the rest..]
7499           //and the map phi:K[var(1),...,var(nva)] ---->
7500           //--->K(var(nnpr+1),..,var(nva))[..the rest..]
7501           //------------------------------------------------------------------
7502
7503           quotring=prepareQuotientring(nvars(basering)-restindep[@m][3]);
7504
7505           //------------------------------------------------------------------
7506           //we pass to the quotientring  K(var(nnp+1),..,var(nva))[..rest..]
7507           //------------------------------------------------------------------
7508
7509           execute(quotring);
7510
7511           // @j considered in the quotientring
7512           ideal @j=imap(gnir1,@j);
7513           ideal ser=imap(gnir1,ser);
7514
7515           kill gnir1;
7516
7517           //j is a standardbasis in the quotientring but usually not minimal
7518           //here it becomes minimal
7519           @j=clearSB(@j,fett);
7520           attrib(@j,"isSB",1);
7521
7522           //we need later ggt(h[1],...)=gh for saturation
7523           ideal @h;
7524
7525           for(@n=1;@n<=size(@j);@n++)
7526           {
7527              @h[@n]=leadcoef(@j[@n]);
7528           }
7529           //the primary decomposition of j*K(var(nnp+1),..,var(nva))[..rest..]
7530
7531           op=option(get);
7532           option(redSB);
7533           list uprimary= newZero_decomp(@j,ser,@wr);
7534//HIER
7535           if(abspri)
7536           {
7537              ideal II;
7538              ideal jmap;
7539              map sigma;
7540              nn=nvars(basering);
7541              map invsigma=basering,maxideal(1);
7542              for(ab=1;ab<=size(uprimary) div 2;ab++)
7543              {
7544                 II=uprimary[2*ab];
7545                 attrib(II,"isSB",1);
7546                 if(deg(II[1])!=vdim(II))
7547                 {
7548                    jmap=randomLast(50);
7549                    sigma=basering,jmap;
7550                    jmap[nn]=2*var(nn)-jmap[nn];
7551                    invsigma=basering,jmap;
7552                    II=groebner(sigma(II));
7553                  }
7554                  absprimarytmp[ab]= absFactorize(II[1],77);
7555                  II=var(nn);
7556                  abskeeptmp[ab]=string(invsigma(II));
7557                  invsigma=basering,maxideal(1);
7558              }
7559           }
7560           option(set,op);
7561
7562           //we need the intersection of the ideals in the list quprimary with
7563           //the polynomialring, i.e. let q=(f1,...,fr) in the quotientring
7564           //such an ideal but fi polynomials, then the intersection of q with
7565           //the polynomialring is the saturation of the ideal generated by
7566           //f1,...,fr with respect toh which is the lcm of the leading
7567           //coefficients of the fi considered in the quotientring:
7568           //this is coded in saturn
7569
7570           list saturn;
7571           ideal hpl;
7572
7573           for(@n=1;@n<=size(uprimary);@n++)
7574           {
7575              hpl=0;
7576              for(@n1=1;@n1<=size(uprimary[@n]);@n1++)
7577              {
7578                 hpl=hpl,leadcoef(uprimary[@n][@n1]);
7579              }
7580              saturn[@n]=hpl;
7581           }
7582           //------------------------------------------------------------------
7583           //we leave  the quotientring   K(var(nnp+1),..,var(nva))[..rest..]
7584           //back to the polynomialring
7585           //------------------------------------------------------------------
7586           setring gnir;
7587           collectprimary=imap(quring,uprimary);
7588           lsau=imap(quring,saturn);
7589           @h=imap(quring,@h);
7590
7591           kill quring;
7592
7593
7594           @n2=size(quprimary);
7595//================NEU=========================================
7596           if(deg(quprimary[1][1])<=0){ @n2=0; }
7597//============================================================
7598
7599           @n3=@n2;
7600
7601           for(@n1=1;@n1<=size(collectprimary) div 2;@n1++)
7602           {
7603              if(deg(collectprimary[2*@n1][1])>0)
7604              {
7605                 @n2++;
7606                 quprimary[@n2]=collectprimary[2*@n1-1];
7607                 lnew[@n2]=lsau[2*@n1-1];
7608                 @n2++;
7609                 lnew[@n2]=lsau[2*@n1];
7610                 quprimary[@n2]=collectprimary[2*@n1];
7611                 if(abspri)
7612                 {
7613                   absprimary[@n2 div 2]=absprimarytmp[@n1];
7614                   abskeep[@n2 div 2]=abskeeptmp[@n1];
7615                 }
7616              }
7617           }
7618
7619
7620           //here the intersection with the polynomialring
7621           //mentioned above is really computed
7622
7623           for(@n=@n3 div 2+1;@n<=@n2 div 2;@n++)
7624           {
7625              if(specialIdealsEqual(quprimary[2*@n-1],quprimary[2*@n]))
7626              {
7627                 quprimary[2*@n-1]=sat2(quprimary[2*@n-1],lnew[2*@n-1])[1];
7628                 quprimary[2*@n]=quprimary[2*@n-1];
7629              }
7630              else
7631              {
7632                 if(@wr==0)
7633                 {
7634                    quprimary[2*@n-1]=sat2(quprimary[2*@n-1],lnew[2*@n-1])[1];
7635                 }
7636                 quprimary[2*@n]=sat2(quprimary[2*@n],lnew[2*@n])[1];
7637              }
7638           }
7639           if(@n2>=@n3+2)
7640           {
7641              setring @Phelp;
7642              ser=imap(gnir,ser);
7643              hquprimary=imap(gnir,quprimary);
7644              for(@n=@n3 div 2+1;@n<=@n2 div 2;@n++)
7645              {
7646                if(@wr==0)
7647                {
7648                   ser=intersect(ser,hquprimary[2*@n-1]);
7649                }
7650                else
7651                {
7652                   ser=intersect(ser,hquprimary[2*@n]);
7653                }
7654              }
7655              setring gnir;
7656              ser=imap(@Phelp,ser);
7657           }
7658
7659         // }
7660        }
7661//HIER
7662        if(abspri)
7663        {
7664          list resu,tempo;
7665          for(ab=1;ab<=size(quprimary) div 2;ab++)
7666          {
7667             if (deg(quprimary[2*ab][1])!=0)
7668             {
7669               tempo=quprimary[2*ab-1],quprimary[2*ab],
7670                         absprimary[ab],abskeep[ab];
7671               resu[ab]=tempo;
7672             }
7673          }
7674          quprimary=resu;
7675          @wr=3;
7676        }
7677        if(size(reduce(ser,peek,1))!=0)
7678        {
7679           if(@wr>0)
7680           {
7681              // The following line was dropped to avoid the recursion step:
7682              //htprimary=newDecompStep(@j,@wr,peek,ser);
7683              htprimary = list();
7684           }
7685           else
7686           {
7687              // The following line was dropped to avoid the recursion step:
7688              //htprimary=newDecompStep(@j,peek,ser);
7689              htprimary = list();
7690           }
7691           // here we collect now both results primary(sat(j,gh))
7692           // and primary(j,gh^n)
7693           @n=size(quprimary);
7694           if (deg(quprimary[1][1])<=0) { @n=0; }
7695           for (@k=1;@k<=size(htprimary);@k++)
7696           {
7697              quprimary[@n+@k]=htprimary[@k];
7698           }
7699        }
7700     }
7701   }
7702   else
7703   {
7704      if(abspri)
7705      {
7706        list resu,tempo;
7707        for(ab=1;ab<=size(quprimary) div 2;ab++)
7708        {
7709           tempo=quprimary[2*ab-1],quprimary[2*ab],
7710                   absprimary[ab],abskeep[ab];
7711           resu[ab]=tempo;
7712        }
7713        quprimary=resu;
7714      }
7715   }
7716  //---------------------------------------------------------------------------
7717  //back to the ring we started with
7718  //the final result: primary
7719  //---------------------------------------------------------------------------
7720
7721  setring @P;
7722  primary=imap(gnir,quprimary);
7723
7724  if (intersectOption == "intersect")
7725  {
7726     return(list(primary, imap(gnir, ser)));
7727  }
7728  else
7729  {
7730    return(primary);
7731  }
7732}
7733example
7734{ "EXAMPLE:"; echo = 2;
7735   ring  r = 32003,(x,y,z),lp;
7736   poly  p = z2+1;
7737   poly  q = z4+2;
7738   ideal i = p^2*q^3,(y-z3)^3,(x-yz+z4)^4;
7739   list pr= newDecompStep(i);
7740   pr;
7741   testPrimary( pr, i);
7742}
7743
7744// This was part of proc decomp.
7745// In proc newDecompStep, used for the computation of the minimal associated primes,
7746// this part was separated as a soubrutine to make the code more clear.
7747// Also, since the reduction is performed twice in proc newDecompStep, it should use both times this routine.
7748// This is not yet implemented, since the reduction is not exactly the same and some changes should be made.
7749static proc newReduction(ideal @j, ideal ser, intvec @hilb, intvec @w, int jdim, int abspri, int @wr, list data)
7750{
7751   ASSUME(0, not isQuotientRing(basering) ) ;
7752  ASSUME(0, hasGlobalOrdering(basering) ) ;
7753
7754
7755   string @va;
7756   string quotring;
7757   intvec op;
7758   intvec @vv;
7759   def gnir = basering;
7760   ideal isat=0;
7761   int @n;
7762   int @n1 = 0;
7763   int @n2 = 0;
7764   int @n3 = 0;
7765   int homo = homog(@j);
7766   int lauf;
7767   int @k;
7768   list fett;
7769   int keepdi;
7770   list collectprimary;
7771   list lsau;
7772   list lnew;
7773   ideal @h;
7774
7775   list indepInfo = data[1];
7776   list quprimary = list();
7777
7778   //if(abspri)
7779   //{
7780     int ab;
7781     list absprimarytmp,abskeeptmp;
7782     list absprimary, abskeep;
7783   //}
7784   // Debug
7785   dbprint(printlevel - voice, "newReduction, v2.0");
7786
7787   if((indepInfo[1]==varstr(basering)))  // &&(@m==1)
7788   //this is the good case, nothing to do, just to have the same notations
7789   //change the ring
7790   {
7791     execute("ring gnir1 = ("+charstr(basering)+"),("+varstr(basering)+"),("
7792                              +ordstr(basering)+");");
7793     ideal @j = fetch(gnir, @j);
7794     attrib(@j,"isSB",1);
7795     ideal ser = fetch(gnir, ser);
7796   }
7797   else
7798   {
7799     @va=string(maxideal(1));
7800//Aenderung==============
7801     //if(@m==1)
7802     //{
7803     //  @j=fetch(@P,i);
7804     //}
7805//=======================
7806     execute("ring gnir1 = ("+charstr(basering)+"),("+indepInfo[1]+"),("
7807                              +indepInfo[2]+");");
7808     execute("map phi=gnir,"+@va+";");
7809     op=option(get);
7810     option(redSB);
7811     if(homo==1)
7812     {
7813       ideal @j=std(phi(@j),@hilb,@w);
7814     }
7815     else
7816     {
7817       ideal @j=groebner(phi(@j));
7818     }
7819     ideal ser=phi(ser);
7820
7821     option(set,op);
7822   }
7823   if((deg(@j[1])==0)||(dim(@j)<jdim))
7824   {
7825     setring gnir;
7826     break;
7827   }
7828   for (lauf=1;lauf<=size(@j);lauf++)
7829   {
7830     fett[lauf]=size(@j[lauf]);
7831   }
7832   //------------------------------------------------------------------------
7833   //we have now the following situation:
7834   //j intersected with K[var(nnp+1),..,var(nva)] is zero so we may pass
7835   //to this quotientring, j is their still a standardbasis, the
7836   //leading coefficients of the polynomials  there (polynomials in
7837   //K[var(nnp+1),..,var(nva)]) are collected in the list h,
7838   //we need their ggt, gh, because of the following: let
7839   //(j:gh^n)=(j:gh^infinity) then j*K(var(nnp+1),..,var(nva))[..the rest..]
7840   //intersected with K[var(1),...,var(nva)] is (j:gh^n)
7841   //on the other hand j=(j,gh^n) intersected with (j:gh^n)
7842
7843   //------------------------------------------------------------------------
7844
7845   //arrangement for quotientring K(var(nnp+1),..,var(nva))[..the rest..] and
7846   //map phi:K[var(1),...,var(nva)] --->K(var(nnpr+1),..,var(nva))[..rest..]
7847   //------------------------------------------------------------------------
7848
7849   quotring=prepareQuotientring(nvars(basering)-indepInfo[3]);
7850
7851   //---------------------------------------------------------------------
7852   //we pass to the quotientring   K(var(nnp+1),..,var(nva))[..the rest..]
7853   //---------------------------------------------------------------------
7854
7855   ideal @jj=lead(@j);               //!! vorn vereinbaren
7856   execute(quotring);
7857
7858   ideal @jj=imap(gnir1,@jj);
7859   @vv=clearSBNeu(@jj,fett);  //!! vorn vereinbaren
7860   setring gnir1;
7861   @k=size(@j);
7862   for (lauf=1;lauf<=@k;lauf++)
7863   {
7864     if(@vv[lauf]==1)
7865     {
7866       @j[lauf]=0;
7867     }
7868   }
7869   @j=simplify(@j,2);
7870   setring quring;
7871   // @j considered in the quotientring
7872   ideal @j=imap(gnir1,@j);
7873
7874   ideal ser=imap(gnir1,ser);
7875
7876   kill gnir1;
7877
7878   //j is a standardbasis in the quotientring but usually not minimal
7879   //here it becomes minimal
7880
7881   attrib(@j,"isSB",1);
7882
7883   //we need later ggt(h[1],...)=gh for saturation
7884   ideal @h;
7885   if(deg(@j[1])>0)
7886   {
7887     for(@n=1;@n<=size(@j);@n++)
7888     {
7889       @h[@n]=leadcoef(@j[@n]);
7890     }
7891     //the primary decomposition of j*K(var(nnp+1),..,var(nva))[..the rest..]
7892     op=option(get);
7893     option(redSB);
7894
7895     int zeroMinAss = @wr;
7896     if (@wr == 2) {zeroMinAss = 1;}
7897     list uprimary= newZero_decomp(@j, ser, zeroMinAss);
7898
7899//HIER
7900     if(abspri)
7901     {
7902       ideal II;
7903       ideal jmap;
7904       map sigma;
7905       nn=nvars(basering);
7906       map invsigma=basering,maxideal(1);
7907       for(ab=1;ab<=size(uprimary) div 2;ab++)
7908       {
7909         II=uprimary[2*ab];
7910         attrib(II,"isSB",1);
7911         if(deg(II[1])!=vdim(II))
7912         {
7913           jmap=randomLast(50);
7914           sigma=basering,jmap;
7915           jmap[nn]=2*var(nn)-jmap[nn];
7916           invsigma=basering,jmap;
7917           II=groebner(sigma(II));
7918         }
7919         absprimarytmp[ab]= absFactorize(II[1],77);
7920         II=var(nn);
7921         abskeeptmp[ab]=string(invsigma(II));
7922         invsigma=basering,maxideal(1);
7923       }
7924     }
7925     option(set,op);
7926   }
7927   else
7928   {
7929     list uprimary;
7930     uprimary[1]=ideal(1);
7931     uprimary[2]=ideal(1);
7932   }
7933   //we need the intersection of the ideals in the list quprimary with the
7934   //polynomialring, i.e. let q=(f1,...,fr) in the quotientring such an ideal
7935   //but fi polynomials, then the intersection of q with the polynomialring
7936   //is the saturation of the ideal generated by f1,...,fr with respect to
7937   //h which is the lcm of the leading coefficients of the fi considered in
7938   //in the quotientring: this is coded in saturn
7939
7940   list saturn;
7941   ideal hpl;
7942
7943   for(@n=1;@n<=size(uprimary);@n++)
7944   {
7945     uprimary[@n]=interred(uprimary[@n]); // temporary fix
7946     hpl=0;
7947     for(@n1=1;@n1<=size(uprimary[@n]);@n1++)
7948     {
7949       hpl=hpl,leadcoef(uprimary[@n][@n1]);
7950     }
7951     saturn[@n]=hpl;
7952   }
7953
7954   //--------------------------------------------------------------------
7955   //we leave  the quotientring   K(var(nnp+1),..,var(nva))[..the rest..]
7956   //back to the polynomialring
7957   //---------------------------------------------------------------------
7958   setring gnir;
7959
7960   collectprimary=imap(quring,uprimary);
7961   lsau=imap(quring,saturn);
7962   @h=imap(quring,@h);
7963
7964   kill quring;
7965
7966   @n2=size(quprimary);
7967   @n3=@n2;
7968
7969   for(@n1=1;@n1<=size(collectprimary) div 2;@n1++)
7970   {
7971     if(deg(collectprimary[2*@n1][1])>0)
7972     {
7973       @n2++;
7974       quprimary[@n2]=collectprimary[2*@n1-1];
7975       lnew[@n2]=lsau[2*@n1-1];
7976       @n2++;
7977       lnew[@n2]=lsau[2*@n1];
7978       quprimary[@n2]=collectprimary[2*@n1];
7979       if(abspri)
7980       {
7981         absprimary[@n2 div 2]=absprimarytmp[@n1];
7982         abskeep[@n2 div 2]=abskeeptmp[@n1];
7983       }
7984     }
7985   }
7986
7987   //here the intersection with the polynomialring
7988   //mentioned above is really computed
7989   for(@n=@n3 div 2+1;@n<=@n2 div 2;@n++)
7990   {
7991     if(specialIdealsEqual(quprimary[2*@n-1],quprimary[2*@n]))
7992     {
7993       quprimary[2*@n-1]=sat2(quprimary[2*@n-1],lnew[2*@n-1])[1];
7994       quprimary[2*@n]=quprimary[2*@n-1];
7995     }
7996     else
7997     {
7998       if(@wr==0)
7999       {
8000         quprimary[2*@n-1]=sat2(quprimary[2*@n-1],lnew[2*@n-1])[1];
8001       }
8002       quprimary[2*@n]=sat2(quprimary[2*@n],lnew[2*@n])[1];
8003     }
8004   }
8005
8006   return(quprimary, absprimary, abskeep, ser, @h);
8007}
8008
8009
8010////////////////////////////////////////////////////////////////////////////
8011
8012
8013
8014
8015///////////////////////////////////////////////////////////////////////////////
8016// Based on minAssGTZ
8017
8018proc minAss(ideal i,list #)
8019"USAGE:   minAss(I[, l]); i ideal, l list (optional) of parameters, same as minAssGTZ
8020RETURN:  a list, the minimal associated prime ideals of I.
8021NOTE:    Designed for characteristic 0, works also in char k > 0 based
8022         on an algorithm of Yokoyama
8023EXAMPLE: example minAss; shows an example
8024"
8025{
8026  return(minAssGTZ(i,#));
8027}
8028example
8029{ "EXAMPLE:";  echo = 2;
8030   ring  r = 0, (x, y, z), dp;
8031   poly  p = z2 + 1;
8032   poly  q = z3 + 2;
8033   ideal i = p * q^2, y - z2;
8034   list pr = minAss(i);
8035   pr;
8036}
8037
8038
8039///////////////////////////////////////////////////////////////////////////////
8040//
8041// Computes the minimal associated primes of I via Laplagne algorithm,
8042// using primary decomposition in the zero dimensional case.
8043// For reduction to the zerodimensional case, it uses the procedure
8044// decomp, with some modifications to avoid the recursion.
8045//
8046
8047static proc minAssSL(ideal I)
8048// Input = I, ideal
8049// Output = primaryDec where primaryDec is the list of the minimal
8050// associated primes and the primary components corresponding to these primes.
8051{
8052  ASSUME(0, not isQuotientRing(basering) ) ;
8053  ASSUME(0, hasGlobalOrdering(basering) ) ;
8054
8055  ideal P = 1;
8056  list pd = list();
8057  int k;
8058  int stop = 0;
8059  list primaryDec = list();
8060
8061  while (stop == 0)
8062  {
8063    // Debug
8064    dbprint(printlevel - voice, "// We call minAssSLIteration to find new prime ideals!");
8065    pd = minAssSLIteration(I, P);
8066    // Debug
8067    dbprint(printlevel - voice, "// Output of minAssSLIteration:");
8068    dbprint(printlevel - voice, pd);
8069    if (size(pd[1]) > 0)
8070    {
8071      primaryDec = primaryDec + pd[1];
8072      // Debug
8073      dbprint(printlevel - voice, "// We intersect the prime ideals obtained.");
8074      P = intersect(P, pd[2]);
8075      // Debug
8076      dbprint(printlevel - voice, "// Intersection finished.");
8077    }
8078    else
8079    {
8080      stop = 1;
8081    }
8082  }
8083
8084  // Returns only the primary components, not the radical.
8085  return(primaryDec);
8086}
8087
8088///////////////////////////////////////////////////////////////////////////////
8089// Given an ideal I and an ideal P (intersection of some minimal prime ideals
8090// associated to I), it calculates new minimal prime ideals associated to I
8091// which were not used to calculate P.
8092// This version uses Primary Decomposition in the zerodimensional case.
8093static proc minAssSLIteration(ideal I, ideal P);
8094{
8095  ASSUME(0, not isQuotientRing(basering) ) ;
8096  ASSUME(0, hasGlobalOrdering(basering) ) ;
8097
8098  int k = 1;
8099  int good  = 0;
8100  list primaryDec = list();
8101  // Debug
8102  dbprint (printlevel-voice, "// We search for an element in P - sqrt(I).");
8103  while ((k <= size(P)) and (good == 0))
8104  {
8105    good = 1 - rad_con(P[k], I);
8106    k++;
8107  }
8108  k--;
8109  if (good == 0)
8110  {
8111    // Debug
8112    dbprint (printlevel - voice, "// No element was found, P = sqrt(I).");
8113    return (list(primaryDec, ideal(0)));
8114  }
8115  // Debug
8116  dbprint (printlevel - voice, "// We found h = ", P[k]);
8117  dbprint (printlevel - voice, "// We calculate the saturation of I with respect to the element just founded.");
8118  ideal J = sat(I, P[k])[1];
8119
8120  // Uses decomp from primdec, modified to avoid the recursion.
8121  // Debug
8122  dbprint(printlevel - voice, "// We do the reduction to the zerodimensional case, via decomp.");
8123
8124  primaryDec = newDecompStep(J, "oneIndep", "intersect", 2);
8125  // Debug
8126  dbprint(printlevel - voice, "// Proc decomp has found", size(primaryDec) div 2, "new primary components.");
8127
8128  return(primaryDec);
8129}
8130
8131
8132
8133///////////////////////////////////////////////////////////////////////////////////
8134// Based on maxIndependSet
8135// Added list # as parameter
8136// If the first element of # is 0, the output is only 1 max indep set.
8137// If no list is specified or #[1] = 1, the output is all the max indep set of the
8138// leading terms ideal. This is the original output of maxIndependSet
8139
8140proc newMaxIndependSetLp(ideal j, list #)
8141"USAGE:   newMaxIndependentSetLp(i); i ideal (returns all maximal independent sets of the corresponding leading terms ideal)
8142          newMaxIndependentSetLp(i, 0); i ideal (returns only one maximal independent set)
8143RETURN:  list = #1. new varstring with the maximal independent set at the end,
8144                #2. ordstring with the lp ordering,
8145                #3. the number of independent variables
8146NOTE:
8147EXAMPLE: example newMaxIndependentSetLp; shows an example
8148"
8149{
8150  ASSUME(0, not isQuotientRing(basering) ) ;
8151  ASSUME(0, hasGlobalOrdering(basering) ) ;
8152
8153  int n, k, di;
8154  list resu, hilf;
8155  string var1, var2;
8156  list v = indepSet(j, 0);
8157
8158  // SL 2006.04.21 1 Lines modified to use only one independent Set
8159  string indepOption;
8160  if (size(#) > 0)
8161  {
8162    indepOption = #[1];
8163  }
8164  else
8165  {
8166    indepOption = "allIndep";
8167  }
8168
8169  int nMax;
8170  if (indepOption == "allIndep")
8171  {
8172    nMax = size(v);
8173  }
8174  else
8175  {
8176    nMax = 1;
8177  }
8178
8179  for(n = 1; n <= nMax; n++)
8180  // SL 2006.04.21 2
8181  {
8182    di = 0;
8183    var1 = "";
8184    var2 = "";
8185    for(k = 1; k <= size(v[n]); k++)
8186    {
8187      if(v[n][k] != 0)
8188      {
8189        di++;
8190        var2 = var2 + "var(" + string(k) + "), ";
8191      }
8192      else
8193      {
8194        var1 = var1 + "var(" + string(k) + "), ";
8195      }
8196    }
8197    if(di > 0)
8198    {
8199      var1 = var1 + var2;
8200      var1 = var1[1..size(var1) - 2];       // The "- 2" removes the trailer comma
8201      hilf[1] = var1;
8202      // SL 2006.21.04 1 The order is now block dp instead of lp
8203      //hilf[2] = "dp(" + string(nvars(basering) - di) + "), dp(" + string(di) + ")";
8204      // SL 2006.21.04 2
8205      // For decomp, lp ordering is needed. Nothing is changed.
8206      hilf[2] = "lp";
8207      hilf[3] = di;
8208      resu[n] = hilf;
8209    }
8210    else
8211    {
8212      resu[n] = varstr(basering), ordstr(basering), 0;
8213    }
8214  }
8215  return(resu);
8216}
8217example
8218{ "EXAMPLE:"; echo = 2;
8219   ring s1 = (0, x, y), (a, b, c, d, e, f, g), lp;
8220   ideal i = ea - fbg, fa + be, ec - fdg, fc + de;
8221   i = std(i);
8222   list l = newMaxIndependSetLp(i);
8223   l;
8224   i = i, g;
8225   l = newMaxIndependSetLp(i);
8226   l;
8227
8228   ring s = 0, (x, y, z), lp;
8229   ideal i = z, yx;
8230   list l = newMaxIndependSetLp(i);
8231   l;
8232}
8233
8234
8235///////////////////////////////////////////////////////////////////////////////
8236
8237proc newZero_decomp (ideal j, ideal ser, int @wr, list #)
8238"USAGE:   newZero_decomp(j,ser,@wr); j,ser ideals, @wr=0 or 1
8239         (@wr=0 for primary decomposition, @wr=1 for computation of associated
8240         primes)
8241         if #[1] = "nest", then #[2] indicates the nest level (number of recursive calls)
8242         When the nest level is high it indicates that the computation is difficult,
8243         and different methods are applied.
8244RETURN:  list = list of primary ideals and their radicals (at even positions
8245         in the list) if the input is zero-dimensional and a standardbases
8246         with respect to lex-ordering
8247         If ser!=(0) and ser is contained in j or if j is not zero-dimen-
8248         sional then ideal(1),ideal(1) is returned
8249NOTE:    Algorithm of Gianni/Trager/Zacharias
8250EXAMPLE: example newZero_decomp; shows an example
8251"
8252{
8253  ASSUME(0, not isQuotientRing(basering) ) ;
8254  ASSUME(0, hasGlobalOrdering(basering) ) ;
8255
8256  def   @P = basering;
8257  int uytrewq;
8258  int nva = nvars(basering);
8259  int @k,@s,@n,@k1,zz;
8260  list primary,lres0,lres1,act,@lh,@wh;
8261  map phi,psi,phi1,psi1;
8262  ideal jmap,jmap1,jmap2,helpprim,@qh,@qht,ser1;
8263  intvec @vh,@hilb;
8264  string @ri;
8265  poly @f;
8266
8267  // Debug
8268  dbprint(printlevel - voice, "proc newZero_decomp");
8269
8270  if (dim(j)>0)
8271  {
8272    primary[1]=ideal(1);
8273    primary[2]=ideal(1);
8274    return(primary);
8275  }
8276  j=interred(j);
8277
8278  attrib(j,"isSB",1);
8279
8280  int nestLevel = 0;
8281  if (size(#) > 0)
8282  {
8283    if (typeof(#[1]) == "string")
8284    {
8285      if (#[1] == "nest")
8286      {
8287        nestLevel = #[2];
8288      }
8289      # = list();
8290    }
8291  }
8292
8293  if(vdim(j)==deg(j[1]))
8294  {
8295    act=factor(j[1]);
8296    for(@k=1;@k<=size(act[1]);@k++)
8297    {
8298      @qh=j;
8299      if(@wr==0)
8300      {
8301        @qh[1]=act[1][@k]^act[2][@k];
8302      }
8303      else
8304      {
8305        @qh[1]=act[1][@k];
8306      }
8307      primary[2*@k-1]=interred(@qh);
8308      @qh=j;
8309      @qh[1]=act[1][@k];
8310      primary[2*@k]=interred(@qh);
8311      attrib( primary[2*@k-1],"isSB",1);
8312
8313      if((size(ser)>0)&&(size(reduce(ser,primary[2*@k-1],1))==0))
8314      {
8315        primary[2*@k-1]=ideal(1);
8316        primary[2*@k]=ideal(1);
8317      }
8318    }
8319    return(primary);
8320  }
8321
8322  if(homog(j)==1)
8323  {
8324    primary[1]=j;
8325    if((size(ser)>0)&&(size(reduce(ser,j,1))==0))
8326    {
8327      primary[1]=ideal(1);
8328      primary[2]=ideal(1);
8329      return(primary);
8330    }
8331    if(dim(j)==-1)
8332    {
8333      primary[1]=ideal(1);
8334      primary[2]=ideal(1);
8335    }
8336    else
8337    {
8338      primary[2]=maxideal(1);
8339    }
8340    return(primary);
8341  }
8342
8343//the first element in the standardbase is factorized
8344  if(deg(j[1])>0)
8345  {
8346    act=factor(j[1]);
8347    testFactor(act,j[1]);
8348  }
8349  else
8350  {
8351    primary[1]=ideal(1);
8352    primary[2]=ideal(1);
8353    return(primary);
8354  }
8355
8356//with the factors new ideals (hopefully the primary decomposition)
8357//are created
8358  if(size(act[1])>1)
8359  {
8360    if(size(#)>1)
8361    {
8362      primary[1]=ideal(1);
8363      primary[2]=ideal(1);
8364      primary[3]=ideal(1);
8365      primary[4]=ideal(1);
8366      return(primary);
8367    }
8368    for(@k=1;@k<=size(act[1]);@k++)
8369    {
8370      if(@wr==0)
8371      {
8372        primary[2*@k-1]=std(j,act[1][@k]^act[2][@k]);
8373      }
8374      else
8375      {
8376        primary[2*@k-1]=std(j,act[1][@k]);
8377      }
8378      if((act[2][@k]==1)&&(vdim(primary[2*@k-1])==deg(act[1][@k])))
8379      {
8380        primary[2*@k]   = primary[2*@k-1];
8381      }
8382      else
8383      {
8384        primary[2*@k]   = primaryTest(primary[2*@k-1],act[1][@k]);
8385      }
8386    }
8387  }
8388  else
8389  {
8390    primary[1]=j;
8391    if((size(#)>0)&&(act[2][1]>1))
8392    {
8393      act[2]=1;
8394      primary[1]=std(primary[1],act[1][1]);
8395    }
8396    if(@wr!=0)
8397    {
8398      primary[1]=std(j,act[1][1]);
8399    }
8400    if((act[2][1]==1)&&(vdim(primary[1])==deg(act[1][1])))
8401    {
8402      primary[2]=primary[1];
8403    }
8404    else
8405    {
8406      primary[2]=primaryTest(primary[1],act[1][1]);
8407    }
8408  }
8409
8410  if(size(#)==0)
8411  {
8412    primary=splitPrimary(primary,ser,@wr,act);
8413  }
8414
8415  if((voice>=6)&&(char(basering)<=181))
8416  {
8417    primary=splitCharp(primary);
8418  }
8419
8420  if((@wr==2)&&(npars(basering)>0)&&(voice>=6)&&(char(basering)>0))
8421  {
8422  //the prime decomposition of Yokoyama in characteristic p
8423    list ke,ek;
8424    @k=0;
8425    while(@k<size(primary) div 2)
8426    {
8427      @k++;
8428      if(size(primary[2*@k])==0)
8429      {
8430        ek=insepDecomp(primary[2*@k-1]);
8431        primary=delete(primary,2*@k);
8432        primary=delete(primary,2*@k-1);
8433        @k--;
8434      }
8435      ke=ke+ek;
8436    }
8437    for(@k=1;@k<=size(ke);@k++)
8438    {
8439      primary[size(primary)+1]=ke[@k];
8440      primary[size(primary)+1]=ke[@k];
8441    }
8442  }
8443
8444  if(nestLevel > 1){primary=extF(primary);}
8445
8446//test whether all ideals in the decomposition are primary and
8447//in general position
8448//if not after a random coordinate transformation of the last
8449//variable the corresponding ideal is decomposed again.
8450  if((npars(basering)>0)&&(nestLevel > 1))
8451  {
8452    poly randp;
8453    for(zz=1;zz<nvars(basering);zz++)
8454    {
8455      randp=randp
8456              +(random(0,5)*par(1)^2+random(0,5)*par(1)+random(0,5))*var(zz);
8457    }
8458    randp=randp+var(nvars(basering));
8459  }
8460  @k=0;
8461  while(@k<(size(primary) div 2))
8462  {
8463    @k++;
8464    if (size(primary[2*@k])==0)
8465    {
8466      for(zz=1;zz<size(primary[2*@k-1])-1;zz++)
8467      {
8468        attrib(primary[2*@k-1],"isSB",1);
8469        if(vdim(primary[2*@k-1])==deg(primary[2*@k-1][zz]))
8470        {
8471          primary[2*@k]=primary[2*@k-1];
8472        }
8473      }
8474    }
8475  }
8476
8477  @k=0;
8478  ideal keep;
8479  while(@k<(size(primary) div 2))
8480  {
8481    @k++;
8482    if (size(primary[2*@k])==0)
8483    {
8484      jmap=randomLast(100);
8485      jmap1=maxideal(1);
8486      jmap2=maxideal(1);
8487      @qht=primary[2*@k-1];
8488      if((npars(basering)>0)&&(nestLevel > 1))
8489      {
8490        jmap[size(jmap)]=randp;
8491      }
8492
8493      for(@n=2;@n<=size(primary[2*@k-1]);@n++)
8494      {
8495        if(deg(lead(primary[2*@k-1][@n]))==1)
8496        {
8497          for(zz=1;zz<=nva;zz++)
8498          {
8499            if(lead(primary[2*@k-1][@n])/var(zz)!=0)
8500            {
8501              jmap1[zz]=-1/leadcoef(primary[2*@k-1][@n])*primary[2*@k-1][@n]
8502                   +2/leadcoef(primary[2*@k-1][@n])*lead(primary[2*@k-1][@n]);
8503              jmap2[zz]=primary[2*@k-1][@n];
8504              @qht[@n]=var(zz);
8505            }
8506          }
8507          jmap[nva]=subst(jmap[nva],lead(primary[2*@k-1][@n]),0);
8508        }
8509      }
8510      if(size(subst(jmap[nva],var(1),0)-var(nva))!=0)
8511      {
8512        // jmap[nva]=subst(jmap[nva],var(1),0);
8513        //hier geaendert +untersuchen!!!!!!!!!!!!!!
8514      }
8515      phi1=@P,jmap1;
8516      phi=@P,jmap;
8517      for(@n=1;@n<=nva;@n++)
8518      {
8519        jmap[@n]=-(jmap[@n]-2*var(@n));
8520      }
8521      psi=@P,jmap;
8522      psi1=@P,jmap2;
8523      @qh=phi(@qht);
8524
8525//=================== the new part ============================
8526
8527      if (npars(basering)>1) { @qh=groebner(@qh,"par2var"); }
8528      else                   { @qh=groebner(@qh); }
8529
8530//=============================================================
8531//       if(npars(@P)>0)
8532//       {
8533//          @ri= "ring @Phelp ="
8534//                  +string(char(@P))+",
8535//                   ("+varstr(@P)+","+parstr(@P)+",@t),(C,dp);";
8536//       }
8537//       else
8538//       {
8539//          @ri= "ring @Phelp ="
8540//                  +string(char(@P))+",("+varstr(@P)+",@t),(C,dp);";
8541//       }
8542//       execute(@ri);
8543//       ideal @qh=homog(imap(@P,@qht),@t);
8544//
8545//       ideal @qh1=std(@qh);
8546//       @hilb=hilb(@qh1,1);
8547//       @ri= "ring @Phelp1 ="
8548//                  +string(char(@P))+",("+varstr(@Phelp)+"),(C,lp);";
8549//       execute(@ri);
8550//       ideal @qh=homog(imap(@P,@qh),@t);
8551//       kill @Phelp;
8552//       @qh=std(@qh,@hilb);
8553//       @qh=subst(@qh,@t,1);
8554//       setring @P;
8555//       @qh=imap(@Phelp1,@qh);
8556//       kill @Phelp1;
8557//       @qh=clearSB(@qh);
8558//       attrib(@qh,"isSB",1);
8559//=============================================================
8560
8561      ser1=phi1(ser);
8562      @lh=newZero_decomp (@qh,phi(ser1),@wr, list("nest", nestLevel + 1));
8563
8564      kill lres0;
8565      list lres0;
8566      if(size(@lh)==2)
8567      {
8568        helpprim=@lh[2];
8569        lres0[1]=primary[2*@k-1];
8570        ser1=psi(helpprim);
8571        lres0[2]=psi1(ser1);
8572        if(size(reduce(lres0[2],lres0[1],1))==0)
8573        {
8574          primary[2*@k]=primary[2*@k-1];
8575          continue;
8576        }
8577      }
8578      else
8579      {
8580        lres1=psi(@lh);
8581        lres0=psi1(lres1);
8582      }
8583
8584//=================== the new part ============================
8585
8586      primary=delete(primary,2*@k-1);
8587      primary=delete(primary,2*@k-1);
8588      @k--;
8589      if(size(lres0)==2)
8590      {
8591        if (npars(basering)>1) { lres0[2]=groebner(lres0[2],"par2var"); }
8592        else                   { lres0[2]=groebner(lres0[2]); }
8593      }
8594      else
8595      {
8596        for(@n=1;@n<=size(lres0) div 2;@n++)
8597        {
8598          if(specialIdealsEqual(lres0[2*@n-1],lres0[2*@n])==1)
8599          {
8600            lres0[2*@n-1]=groebner(lres0[2*@n-1]);
8601            lres0[2*@n]=lres0[2*@n-1];
8602            attrib(lres0[2*@n],"isSB",1);
8603          }
8604          else
8605          {
8606            lres0[2*@n-1]=groebner(lres0[2*@n-1]);
8607            lres0[2*@n]=groebner(lres0[2*@n]);
8608          }
8609        }
8610      }
8611      primary=primary+lres0;
8612
8613//=============================================================
8614//       if(npars(@P)>0)
8615//       {
8616//          @ri= "ring @Phelp ="
8617//                  +string(char(@P))+",
8618//                   ("+varstr(@P)+","+parstr(@P)+",@t),(C,dp);";
8619//       }
8620//       else
8621//       {
8622//          @ri= "ring @Phelp ="
8623//                  +string(char(@P))+",("+varstr(@P)+",@t),(C,dp);";
8624//       }
8625//       execute(@ri);
8626//       list @lvec;
8627//       list @lr=imap(@P,lres0);
8628//       ideal @lr1;
8629//
8630//       if(size(@lr)==2)
8631//       {
8632//          @lr[2]=homog(@lr[2],@t);
8633//          @lr1=std(@lr[2]);
8634//          @lvec[2]=hilb(@lr1,1);
8635//       }
8636//       else
8637//       {
8638//          for(@n=1;@n<=size(@lr) div 2;@n++)
8639//          {
8640//             if(specialIdealsEqual(@lr[2*@n-1],@lr[2*@n])==1)
8641//             {
8642//                @lr[2*@n-1]=homog(@lr[2*@n-1],@t);
8643//                @lr1=std(@lr[2*@n-1]);
8644//                @lvec[2*@n-1]=hilb(@lr1,1);
8645//                @lvec[2*@n]=@lvec[2*@n-1];
8646//             }
8647//             else
8648//             {
8649//                @lr[2*@n-1]=homog(@lr[2*@n-1],@t);
8650//                @lr1=std(@lr[2*@n-1]);
8651//                @lvec[2*@n-1]=hilb(@lr1,1);
8652//                @lr[2*@n]=homog(@lr[2*@n],@t);
8653//                @lr1=std(@lr[2*@n]);
8654//                @lvec[2*@n]=hilb(@lr1,1);
8655//
8656//             }
8657//         }
8658//       }
8659//       @ri= "ring @Phelp1 ="
8660//                  +string(char(@P))+",("+varstr(@Phelp)+"),(C,lp);";
8661//       execute(@ri);
8662//       list @lr=imap(@Phelp,@lr);
8663//
8664//       kill @Phelp;
8665//       if(size(@lr)==2)
8666//      {
8667//          @lr[2]=std(@lr[2],@lvec[2]);
8668//          @lr[2]=subst(@lr[2],@t,1);
8669//
8670//       }
8671//       else
8672//       {
8673//          for(@n=1;@n<=size(@lr) div 2;@n++)
8674//          {
8675//             if(specialIdealsEqual(@lr[2*@n-1],@lr[2*@n])==1)
8676//             {
8677//                @lr[2*@n-1]=std(@lr[2*@n-1],@lvec[2*@n-1]);
8678//                @lr[2*@n-1]=subst(@lr[2*@n-1],@t,1);
8679//                @lr[2*@n]=@lr[2*@n-1];
8680//                attrib(@lr[2*@n],"isSB",1);
8681//             }
8682//             else
8683//             {
8684//                @lr[2*@n-1]=std(@lr[2*@n-1],@lvec[2*@n-1]);
8685//                @lr[2*@n-1]=subst(@lr[2*@n-1],@t,1);
8686//                @lr[2*@n]=std(@lr[2*@n],@lvec[2*@n]);
8687//                @lr[2*@n]=subst(@lr[2*@n],@t,1);
8688//             }
8689//          }
8690//       }
8691//       kill @lvec;
8692//       setring @P;
8693//       lres0=imap(@Phelp1,@lr);
8694//       kill @Phelp1;
8695//       for(@n=1;@n<=size(lres0);@n++)
8696//       {
8697//          lres0[@n]=clearSB(lres0[@n]);
8698//          attrib(lres0[@n],"isSB",1);
8699//       }
8700//
8701//       primary[2*@k-1]=lres0[1];
8702//       primary[2*@k]=lres0[2];
8703//       @s=size(primary) div 2;
8704//       for(@n=1;@n<=size(lres0) div 2-1;@n++)
8705//       {
8706//         primary[2*@s+2*@n-1]=lres0[2*@n+1];
8707//         primary[2*@s+2*@n]=lres0[2*@n+2];
8708//       }
8709//       @k--;
8710//=============================================================
8711    }
8712  }
8713  return(primary);
8714}
8715example
8716{ "EXAMPLE:"; echo = 2;
8717   ring  r = 0,(x,y,z),lp;
8718   poly  p = z2+1;
8719   poly  q = z4+2;
8720   ideal i = p^2*q^3,(y-z3)^3,(x-yz+z4)^4;
8721   i=std(i);
8722   list  pr= newZero_decomp(i,ideal(0),0);
8723   pr;
8724}
8725///////////////////////////////////////////////////////////////////////////////
8726
8727////////////////////////////////////////////////////////////////////////////
8728/*
8729//Beispiele Wenk-Dipl (in ~/Texfiles/Diplom/Wenk/Examples/)
8730//Zeiten: Singular/Singular/Singular -r123456789 -v :wilde13 (PentiumPro200)
8731//Singular for HPUX-9 version 1-3-8  (2000060214)  Jun  2 2000 15:31:26
8732//(wilde13)
8733
8734//1. vdim=20, 3  Komponenten
8735//zerodec-time:2(1)  (matrix:1 charpoly:0 factor:1)
8736//primdecGTZ-time: 1(0)
8737ring rs= 0,(a,b,c),dp;
8738poly f1= a^2*b*c + a*b^2*c + a*b*c^2 + a*b*c + a*b + a*c + b*c;
8739poly f2= a^2*b^2*c + a*b^2*c^2 + a^2*b*c + a*b*c + b*c + a + c;
8740poly f3= a^2*b^2*c^2 + a^2*b^2*c + a*b^2*c + a*b*c + a*c + c + 1;
8741ideal gls=f1,f2,f3;
8742int time=timer;
8743printlevel =1;
8744time=timer; list pr1=zerodec(gls); timer-time;size(pr1);
8745time=timer; list pr =primdecGTZ(gls); timer-time;size(pr);
8746time=timer; ideal ra =radical(gls); timer-time;size(pr);
8747
8748//2.cyclic5  vdim=70, 20 Komponenten
8749//zerodec-time:36(28)  (matrix:1(0) charpoly:18(19) factor:17(9)
8750//primdecGTZ-time: 28(5)
8751//radical : 0
8752ring rs= 0,(a,b,c,d,e),dp;
8753poly f0= a + b + c + d + e + 1;
8754poly f1= a + b + c + d + e;
8755poly f2= a*b + b*c + c*d + a*e + d*e;
8756poly f3= a*b*c + b*c*d + a*b*e + a*d*e + c*d*e;
8757poly f4= a*b*c*d + a*b*c*e + a*b*d*e + a*c*d*e + b*c*d*e;
8758poly f5= a*b*c*d*e - 1;
8759ideal gls= f1,f2,f3,f4,f5;
8760
8761//3. random vdim=40, 1 Komponente
8762//zerodec-time:126(304)  (matrix:1 charpoly:115(298) factor:10(5))
8763//primdecGTZ-time:17 (11)
8764ring rs=0,(x,y,z),dp;
8765poly f1=2*x^2 + 4*x + 3*y^2 + 7*x*z + 9*y*z + 5*z^2;
8766poly f2=7*x^3 + 8*x*y + 12*y^2 + 18*x*z + 3*y^4*z + 10*z^3 + 12;
8767poly f3=3*x^4 + 1*x*y*z + 6*y^3 + 3*x*z^2 + 2*y*z^2 + 4*z^2 + 5;
8768ideal gls=f1,f2,f3;
8769
8770//4. introduction into resultants, sturmfels, vdim=28, 1 Komponente
8771//zerodec-time:4  (matrix:0 charpoly:0 factor:4)
8772//primdecGTZ-time:1
8773ring rs=0,(x,y),dp;
8774poly f1= x4+y4-1;
8775poly f2= x5y2-4x3y3+x2y5-1;
8776ideal gls=f1,f2;
8777
8778//5. 3 quadratic equations with random coeffs, vdim=8, 1 Komponente
8779//zerodec-time:0(0)  (matrix:0 charpoly:0 factor:0)
8780//primdecGTZ-time:1(0)
8781ring rs=0,(x,y,z),dp;
8782poly f1=2*x^2 + 4*x*y + 3*y^2 + 7*x*z + 9*y*z + 5*z^2 + 2;
8783poly f2=7*x^2 + 8*x*y + 12*y^2 + 18*x*z + 3*y*z + 10*z^2 + 12;
8784poly f3=3*x^2 + 1*x*y + 6*y^2 + 3*x*z + 2*y*z + 4*z^2 + 5;
8785ideal gls=f1,f2,f3;
8786
8787//6. 3 polys    vdim=24, 1 Komponente
8788// run("ex14",2);
8789//zerodec-time:5(4)  (matrix:0 charpoly:3(3) factor:2(1))
8790//primdecGTZ-time:4 (2)
8791ring rs=0,(x1,x2,x3,x4),dp;
8792poly f1=16*x1^2 + 3*x2^2 + 5*x3^4 - 1 - 4*x4 + x4^3;
8793poly f2=5*x1^3 + 3*x2^2 + 4*x3^2*x4 + 2*x1*x4 - 1 + x4 + 4*x1 + x2 + x3 + x4;
8794poly f3=-4*x1^2 + x2^2 + x3^2 - 3 + x4^2 + 4*x1 + x2 + x3 + x4;
8795poly f4=-4*x1 + x2 + x3 + x4;
8796ideal gls=f1,f2,f3,f4;
8797
8798//7. ex43, PoSSo, caprasse   vdim=56, 16 Komponenten
8799//zerodec-time:23(15)  (matrix:0 charpoly:16(13) factor:3(2))
8800//primdecGTZ-time:3 (2)
8801ring rs= 0,(y,z,x,t),dp;
8802ideal gls=y^2*z+2*y*x*t-z-2*x,
88034*y^2*z*x-z*x^3+2*y^3*t+4*y*x^2*t-10*y^2+4*z*x+4*x^2-10*y*t+2,
88042*y*z*t+x*t^2-2*z-x,
8805-z^3*x+4*y*z^2*t+4*z*x*t^2+2*y*t^3+4*z^2+4*z*x-10*y*t-10*t^2+2;
8806
8807//8. Arnborg-System, n=6 (II),    vdim=156, 90 Komponenten
8808//zerodec-time (char32003):127(45)(matrix:2(0) charpoly:106(37) factor:16(7))
8809//primdecGTZ-time(char32003) :81 (18)
8810//ring rs= 0,(a,b,c,d,x,f),dp;
8811ring rs= 32003,(a,b,c,d,x,f),dp;
8812ideal gls=a+b+c+d+x+f, ab+bc+cd+dx+xf+af, abc+bcd+cdx+d*xf+axf+abf,
8813abcd+bcdx+cd*xf+ad*xf+abxf+abcf, abcdx+bcd*xf+acd*xf+abd*xf+abcxf+abcdf,
8814abcd*xf-1;
8815
8816//9. ex42, PoSSo, Methan6_1, vdim=27, 2 Komponenten
8817//zerodec-time:610  (matrix:10 charpoly:557 factor:26)
8818//primdecGTZ-time: 118
8819//zerodec-time(char32003):2
8820//primdecGTZ-time(char32003):4
8821//ring rs= 0,(x1,x2,x3,x4,x5,x6,x7,x8,x9,x10),dp;
8822ring rs= 32003,(x1,x2,x3,x4,x5,x6,x7,x8,x9,x10),dp;
8823ideal gls=64*x2*x7-10*x1*x8+10*x7*x9+11*x7*x10-320000*x1,
8824-32*x2*x7-5*x2*x8-5*x2*x10+160000*x1-5000*x2,
8825-x3*x8+x6*x8+x9*x10+210*x6+1300000,
8826-x4*x8+700000,
8827x10^2-2*x5,
8828-x6*x8+x7*x9-210*x6,
8829-64*x2*x7-10*x7*x9-11*x7*x10+320000*x1-16*x7+7000000,
8830-10*x1*x8-10*x2*x8-10*x3*x8-10*x4*x8-10*x6*x8+10*x2*x10+11*x7*x10
8831    +20000*x2+14*x5,
8832x4*x8-x7*x9-x9*x10-410*x9,
883310*x2*x8+10*x3*x8+10*x6*x8+10*x7*x9-10*x2*x10-11*x7*x10-10*x9*x10
8834    -10*x10^2+1400*x6-4200*x10;
8835
8836//10. ex33, walk-s7, Diplomarbeit von Tim, vdim=114
8837//zerfaellt in unterschiedlich viele Komponenten in versch. Charkteristiken:
8838//char32003:30, char0:3(2xdeg1,1xdeg112!), char181:4(2xdeg1,1xdeg28,1xdeg84)
8839//char 0: zerodec-time:10075 (ca 3h) (matrix:3 charpoly:9367, factor:680
8840//        + 24 sec fuer Normalform (anstatt einsetzen), total [29623k])
8841//        primdecGTZ-time: 214
8842//char 32003:zerodec-time:197(68) (matrix:2(1) charpoly:173(60) factor:15(6))
8843//        primdecGTZ-time:14 (5)
8844//char 181:zerodec-time:(87) (matrix:(1) charpoly:(58) factor:(25))
8845//        primdecGTZ-time:(2)
8846//in char181 stimmen Ergebnisse von zerodec und primdecGTZ ueberein (gecheckt)
8847
8848//ring rs= 0,(a,b,c,d,e,f,g),dp;
8849ring rs= 32003,(a,b,c,d,e,f,g),dp;
8850poly f1= 2gb + 2fc + 2ed + a2 + a;
8851poly f2= 2gc + 2fd + e2 + 2ba + b;
8852poly f3= 2gd + 2fe + 2ca + c + b2;
8853poly f4= 2ge + f2 + 2da + d + 2cb;
8854poly f5= 2fg + 2ea + e + 2db + c2;
8855poly f6= g2 + 2fa + f + 2eb + 2dc;
8856poly f7= 2ga + g + 2fb + 2ec + d2;
8857ideal gls= f1,f2,f3,f4,f5,f6,f7;
8858
8859~/Singular/Singular/Singular -r123456789 -v
8860LIB"./primdec.lib";
8861timer=1;
8862int time=timer;
8863printlevel =1;
8864option(prot,mem);
8865time=timer; list pr1=zerodec(gls); timer-time;
8866
8867time=timer; list pr =primdecGTZ(gls); timer-time;
8868time=timer; list pr =primdecSY(gls); timer-time;
8869time=timer; ideal ra =radical(gls); timer-time;size(pr);
8870LIB"all.lib";
8871
8872ring R=0,(a,b,c,d,e,f),dp;
8873ideal I=cyclic(6);
8874minAssGTZ(I);
8875
8876
8877ring S=(2,a,b),(x,y),lp;
8878ideal I=x8-b,y4+a;
8879minAssGTZ(I);
8880
8881ring S1=2,(x,y,a,b),lp;
8882ideal I=x8-b,y4+a;
8883minAssGTZ(I);
8884
8885
8886ring S2=(2,z),(x,y),dp;
8887minpoly=z2+z+1;
8888ideal I=y3+y+1,x4+x+1;
8889primdecGTZ(I);
8890minAssGTZ(I);
8891
8892ring S3=2,(x,y,z),dp;
8893ideal I=y3+y+1,x4+x+1,z2+z+1;
8894primdecGTZ(I);
8895minAssGTZ(I);
8896
8897
8898ring R1=2,(x,y,z),lp;
8899ideal I=y6+y5+y3+y2+1,x4+x+1,z2+z+1;
8900primdecGTZ(I);
8901minAssGTZ(I);
8902
8903
8904ring R2=(2,z),(x,y),lp;
8905minpoly=z3+z+1;
8906ideal I=y2+y+(z2+z+1),x4+x+1;
8907primdecGTZ(I);
8908minAssGTZ(I);
8909
8910*/
Note: See TracBrowser for help on using the repository browser.