source: git/Singular/LIB/primdec.lib @ 3ea5cee

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