source: git/Singular/LIB/primdec.lib @ f1741f

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