source: git/Singular/LIB/primdec.lib @ 92550d

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