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

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