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

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