source: git/Singular/LIB/primdec.lib @ 584649e

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