source: git/Singular/LIB/primdec.lib @ 7c9d6f

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