source: git/Singular/LIB/primdec.lib @ 237b18f

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