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

fieker-DuValspielwiese
Last change on this file since f54c83 was f54c83, checked in by Hans Schönemann <hannes@…>, 18 years ago
*hannes: std -> groebner in finvar.lib *pfister: imap changes in primdec.lib git-svn-id: file:///usr/local/Singular/svn/trunk@9021 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 144.8 KB
RevLine 
[091424]1///////////////////////////////////////////////////////////////////////////////
[f54c83]2version="$Id: primdec.lib,v 1.111 2006-03-16 15:50:39 Singular Exp $";
[0ae4ce]3category="Commutative Algebra";
[5480da]4info="
[8942a5]5LIBRARY: primdec.lib   Primary Decomposition and Radical of Ideals
[07c623]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)
[f34c37c]9
[b9b906]10OVERVIEW:
[07c623]11    Algorithms for primary decomposition based on the ideas of
[367e88]12    Gianni, Trager and Zacharias (implementation by Gerhard Pfister),
13    respectively based on the ideas of Shimoyama and Yokoyama (implementation
[7b3971]14    by Wolfram Decker and Hans Schoenemann).
15 @* The procedures are implemented to be used in characteristic 0.
16 @* They also work in positive characteristic >> 0.
[24f458]17 @* In small characteristic and for algebraic extensions, primdecGTZ
18    may not terminate.
[b9b906]19    Algorithms for the computation of the radical based on the ideas of
[7b3971]20    Krick, Logar and Kemper (implementation by Gerhard Pfister).
[8942a5]21
[f34c37c]22PROCEDURES:
[24f458]23 Ann(M);           annihilator of R^n/M, R=basering, M in R^n
[8942a5]24 primdecGTZ(I);    complete primary decomposition via Gianni,Trager,Zacharias
25 primdecSY(I...);  complete primary decomposition via Shimoyama-Yokoyama
26 minAssGTZ(I);     the minimal associated primes via Gianni,Trager,Zacharias
27 minAssChar(I...); the minimal associated primes using characteristic sets
28 testPrimary(L,k); tests the result of the primary decomposition
[07c623]29 radical(I);       computes the radical of I via  Krick/Logar and Kemper
30 radicalEHV(I);    computes the radical of I via  Eisenbud,Huneke,Vasconcelos
[8942a5]31 equiRadical(I);   the radical of the equidimensional part of the ideal I
32 prepareAss(I);    list of radicals of the equidimensional components of I
33 equidim(I);       weak equidimensional decomposition of I
34 equidimMax(I);    equidimensional locus of I
35 equidimMaxEHV(I); equidimensional locus of I via Eisenbud,Huneke,Vasconcelos
36 zerodec(I);       zerodimensional decomposition via Monico
[326dba]37 absPrimdecGTZ(I); the absolute prime components of I
[8942a5]38";
[e801fe]39
40LIB "general.lib";
[67bd4c]41LIB "elim.lib";
[e801fe]42LIB "poly.lib";
43LIB "random.lib";
[8afd58]44LIB "inout.lib";
[7f24dd7]45LIB "matrix.lib";
[24f458]46LIB "triang.lib";
[6fa3af]47LIB "absfact.lib";
[d6db1f2]48///////////////////////////////////////////////////////////////////////////////
[ebecf83]49//
[091424]50//                      Gianni/Trager/Zacharias
[ebecf83]51//
52///////////////////////////////////////////////////////////////////////////////
53
[07c623]54static proc sat1 (ideal id, poly p)
[d2b2a7]55"USAGE:   sat1(id,j);  id ideal, j polynomial
[d6db1f2]56RETURN:  saturation of id with respect to j (= union_(k=1...) of id:j^k)
57NOTE:    result is a std basis in the basering
[d2b2a7]58"
[d6db1f2]59{
60   int @k;
61   ideal inew=std(id);
62   ideal iold;
[02335e]63   intvec op=option(get);
[d6db1f2]64   option(returnSB);
65   while(specialIdealsEqual(iold,inew)==0 )
66   {
67      iold=inew;
68      inew=quotient(iold,p);
69      @k++;
70   }
71   @k--;
[02335e]72   option(set,op);
[d6db1f2]73   list L =inew,p^@k;
74   return (L);
75}
76
77///////////////////////////////////////////////////////////////////////////////
78
[07c623]79static proc sat2 (ideal id, ideal h)
[d2b2a7]80"USAGE:   sat2(id,j);  id ideal, j polynomial
[d6db1f2]81RETURN:  saturation of id with respect to j (= union_(k=1...) of id:j^k)
82NOTE:    result is a std basis in the basering
[d2b2a7]83"
[d6db1f2]84{
[466f80]85   int @k,@i;
[d6db1f2]86   def @P= basering;
87   if(ordstr(basering)[1,2]!="dp")
88   {
[2d2cad9]89      execute("ring @Phelp=("+charstr(@P)+"),("+varstr(@P)+"),(C,dp);");
[d6db1f2]90      ideal inew=std(imap(@P,id));
91      ideal  @h=imap(@P,h);
92   }
93   else
94   {
95      ideal @h=h;
96      ideal inew=std(id);
97   }
98   ideal fac;
99
100   for(@i=1;@i<=ncols(@h);@i++)
101   {
102     if(deg(@h[@i])>0)
103     {
[18dd47]104        fac=fac+factorize(@h[@i],1);
[d6db1f2]105     }
106   }
107   fac=simplify(fac,4);
108   poly @f=1;
109   if(deg(fac[1])>0)
110   {
[18dd47]111      ideal iold;
[d6db1f2]112      for(@i=1;@i<=size(fac);@i++)
113      {
114        @f=@f*fac[@i];
[466f80]115     }
116     intvec op = option(get);
117     option(returnSB);
118     while(specialIdealsEqual(iold,inew)==0 )
119     {
[d6db1f2]120         iold=inew;
121         if(deg(iold[size(iold)])!=1)
122         {
123            inew=quotient(iold,@f);
124         }
125         else
126         {
127            inew=iold;
128         }
129         @k++;
130      }
[02335e]131      option(set,op);
[d6db1f2]132      @k--;
133   }
134
135   if(ordstr(@P)[1,2]!="dp")
136   {
137      setring @P;
138      ideal inew=std(imap(@Phelp,inew));
139      poly @f=imap(@Phelp,@f);
140   }
141   list L =inew,@f^@k;
142   return (L);
143}
144
145///////////////////////////////////////////////////////////////////////////////
146
[24f458]147
148proc minSat(ideal inew, ideal h)
[d6db1f2]149{
150   int i,k;
151   poly f=1;
152   ideal iold,fac;
153   list quotM,l;
154
155   for(i=1;i<=ncols(h);i++)
156   {
157      if(deg(h[i])>0)
158      {
[18dd47]159         fac=fac+factorize(h[i],1);
[d6db1f2]160      }
161   }
162   fac=simplify(fac,4);
163   if(size(fac)==0)
164   {
165      l=inew,1;
[18dd47]166      return(l);
[d6db1f2]167   }
168   fac=sort(fac)[1];
169   for(i=1;i<=size(fac);i++)
170   {
171      f=f*fac[i];
172   }
[18dd47]173   quotM[1]=inew;
[d6db1f2]174   quotM[2]=fac;
175   quotM[3]=f;
176   f=1;
[466f80]177   intvec op = option(get);
[18dd47]178   option(returnSB);
[d6db1f2]179   while(specialIdealsEqual(iold,quotM[1])==0)
180   {
181      if(k>0)
182      {
183         f=f*quotM[3];
184      }
185      iold=quotM[1];
186      quotM=quotMin(quotM);
187      k++;
188   }
[02335e]189   option(set,op);
[d6db1f2]190   l=quotM[1],f;
191   return(l);
[18dd47]192}
[d6db1f2]193
[07c623]194static proc quotMin(list tsil)
[d6db1f2]195{
196   int i,j,k,action;
197   ideal verg;
198   list l;
199   poly g;
200
201   ideal laedi=tsil[1];
202   ideal fac=tsil[2];
203   poly f=tsil[3];
[3939bc]204
[d6db1f2]205   ideal star=quotient(laedi,f);
[b1d1e8c]206
207   if(specialIdealsEqual(star,laedi))
208   {
209      l=star,fac,f;
[b9b906]210      return(l);
[b1d1e8c]211   }
[b9b906]212
[d6db1f2]213   action=1;
[18dd47]214
[d6db1f2]215   while(action==1)
216   {
217      if(size(fac)==1)
218      {
219         action=0;
220         break;
221      }
222      for(i=1;i<=size(fac);i++)
223      {
224        g=1;
[e801fe]225        verg=laedi;
[3939bc]226
[d6db1f2]227         for(j=1;j<=size(fac);j++)
228         {
229            if(i!=j)
[18dd47]230            {
[d6db1f2]231               g=g*fac[j];
[18dd47]232            }
[d6db1f2]233         }
[b1d1e8c]234
[d6db1f2]235         verg=quotient(laedi,g);
[3939bc]236
[d6db1f2]237         if(specialIdealsEqual(verg,star)==1)
238         {
[18dd47]239            f=g;
[d6db1f2]240            fac[i]=0;
241            fac=simplify(fac,2);
242            break;
243         }
244         if(i==size(fac))
245         {
246            action=0;
247         }
248      }
249   }
[3939bc]250   l=star,fac,f;
[18dd47]251   return(l);
[d6db1f2]252}
253
[091424]254///////////////////////////////////////////////////////////////////////////////
255
[07c623]256static proc testFactor(list act,poly p)
[d6db1f2]257{
[e801fe]258  poly keep=p;
[3939bc]259
[d6db1f2]260   int i;
261   poly q=act[1][1]^act[2][1];
262   for(i=2;i<=size(act[1]);i++)
263   {
264      q=q*act[1][i]^act[2][i];
265   }
266   q=1/leadcoef(q)*q;
267   p=1/leadcoef(p)*p;
268   if(p-q!=0)
269   {
[07c623]270      "ERROR IN FACTOR, please inform the authors";
[d6db1f2]271   }
272}
[091424]273///////////////////////////////////////////////////////////////////////////////
[d6db1f2]274
[07c623]275static proc factor(poly p)
[d2b2a7]276"USAGE:   factor(p) p poly
[d6db1f2]277RETURN:  list=;
[18dd47]278NOTE:
[d6db1f2]279EXAMPLE: example factor; shows an example
[d2b2a7]280"
[d6db1f2]281{
[18dd47]282
[d6db1f2]283  ideal @i;
284  list @l;
285  intvec @v,@w;
286  int @j,@k,@n;
287
288  if(deg(p)<=1)
289  {
290     @i=ideal(p);
291     @v=1;
292     @l[1]=@i;
293     @l[2]=@v;
294     return(@l);
295  }
296  if (size(p)==1)
297  {
298     @w=leadexp(p);
299     for(@j=1;@j<=nvars(basering);@j++)
300     {
301        if(@w[@j]!=0)
302        {
303           @k++;
304           @v[@k]=@w[@j];
305           @i=@i+ideal(var(@j));
306        }
307     }
308     @l[1]=@i;
309     @l[2]=@v;
310     return(@l);
311  }
[091424]312  //  @l=factorize(p,2);
[e801fe]313  @l=factorize(p);
314  // if(npars(basering)>0)
315  // {
[d6db1f2]316     for(@j=1;@j<=size(@l[1]);@j++)
317     {
318        if(deg(@l[1][@j])==0)
319        {
320           @n++;
321        }
322     }
323     if(@n>0)
324     {
325        if(@n==size(@l[1]))
326        {
327           @l[1]=ideal(1);
328           @v=1;
329           @l[2]=@v;
330        }
331        else
332        {
333           @k=0;
334           int pleh;
335           for(@j=1;@j<=size(@l[1]);@j++)
336           {
337              if(deg(@l[1][@j])!=0)
338              {
339                 @k++;
340                 @i=@i+ideal(@l[1][@j]);
341                 if(size(@i)==pleh)
342                 {
[091424]343                   "//factorization error";
344                   @l;
[d6db1f2]345                    @k--;
346                    @v[@k]=@v[@k]+@l[2][@j];
347                 }
348                 else
349                 {
350                    pleh++;
351                    @v[@k]=@l[2][@j];
352                 }
353              }
354           }
355           @l[1]=@i;
356           @l[2]=@v;
357        }
358     }
[e801fe]359     // }
[d6db1f2]360  return(@l);
361}
362example
363{ "EXAMPLE:"; echo = 2;
364   ring  r = 0,(x,y,z),lp;
365   poly  p = (x+y)^2*(y-z)^3;
366   list  l = factor(p);
367   l;
368   ring r1 =(0,b,d,f,g),(a,c,e),lp;
369   poly p  =(1*d)*e^2+(1*d*f^2*g);
370   list  l = factor(p);
371   l;
372   ring r2 =(0,b,f,g),(a,c,e,d),lp;
373   poly p  =(1*d)*e^2+(1*d*f^2*g);
374   list  l = factor(p);
375   l;
376}
377
[091424]378///////////////////////////////////////////////////////////////////////////////
[d6db1f2]379
[50cbdc]380proc idealsEqual( ideal k, ideal j)
[18dd47]381{
[d6db1f2]382   return(stdIdealsEqual(std(k),std(j)));
383}
384
[07c623]385static proc specialIdealsEqual( ideal k1, ideal k2)
[d6db1f2]386{
387   int j;
388
389   if(size(k1)==size(k2))
390   {
[87fba93]391      for(j=1;j<=size(k1);j++)
[d6db1f2]392      {
393         if(leadexp(k1[j])!=leadexp(k2[j]))
394         {
395            return(0);
396         }
397      }
398      return(1);
399   }
400   return(0);
401}
402
[07c623]403static proc stdIdealsEqual( ideal k1, ideal k2)
[d6db1f2]404{
405   int j;
406
407   if(size(k1)==size(k2))
408   {
[87fba93]409      for(j=1;j<=size(k1);j++)
[d6db1f2]410      {
411         if(leadexp(k1[j])!=leadexp(k2[j]))
412         {
413            return(0);
414         }
415      }
416      attrib(k2,"isSB",1);
[e801fe]417      if(size(reduce(k1,k2,1))==0)
[d6db1f2]418      {
419         return(1);
420      }
421   }
422   return(0);
423}
[091424]424///////////////////////////////////////////////////////////////////////////////
[d6db1f2]425
[50cbdc]426proc primaryTest (ideal i, poly p)
[d6db1f2]427{
428   int m=1;
429   int n=nvars(basering);
[6ffa84]430   int e,f;
[d6db1f2]431   poly t;
432   ideal h;
[6ffa84]433   list act;
[d6db1f2]434
[18dd47]435   ideal prm=p;
[d6db1f2]436   attrib(prm,"isSB",1);
437
438   while (n>1)
439   {
440      n=n-1;
441      m=m+1;
442
443      //search for i[m] which has a power of var(n) as leading term
444      if (n==1)
445      {
446         m=size(i);
447      }
448      else
449      {
[a3432c]450        while (lead(i[m])/var(n-1)==0)
[d6db1f2]451        {
[a3432c]452          m=m+1;
453        }
454        m=m-1;
[d6db1f2]455      }
[3939bc]456      //check whether i[m] =(c*var(n)+h)^e modulo prm for some
[d6db1f2]457      //h in K[var(n+1),...,var(nvars(basering))], c in K
458      //if not (0) is returned, else var(n)+h is added to prm
[18dd47]459
[a3432c]460      e=deg(lead(i[m]));
[6ffa84]461      if(char(basering)!=0)
462      {
463         f=1;
464         if(e mod char(basering)==0)
465         {
466           if ( voice >=15 )
[b9b906]467           {
[6ffa84]468              "// WARNING: The characteristic is perhaps too small to use";
469              "// the algorithm of Gianni/Trager/Zacharias.";
470              "// This may result in an infinte loop";
471              "// loop in primaryTest, voice:",voice;"";
472           }
473           while(e mod char(basering)==0)
474           {
475              f=f*char(basering);
[b9b906]476              e=e/char(basering);
[6ffa84]477           }
[b9b906]478
[6ffa84]479         }
480         t=leadcoef(i[m])*e*var(n)^f+(i[m]-lead(i[m]))/var(n)^((e-1)*f);
481         i[m]=poly(e)^e*leadcoef(i[m])^(e-1)*i[m];
482         if (reduce(i[m]-t^e,prm,1) !=0)
483         {
484           return(ideal(0));
485         }
486         if(f>1)
[b9b906]487         {
[6ffa84]488            act=factorize(t);
489            if(size(act[1])>2)
490            {
[b9b906]491              return(ideal(0));
[6ffa84]492            }
[afe6cf]493            if(deg(act[1][2])>1)
494            {
[b9b906]495              return(ideal(0));
[afe6cf]496            }
[6ffa84]497            t=act[1][2];
498         }
[971ba6f]499      }
[6ffa84]500      else
[a3432c]501      {
[6ffa84]502         t=leadcoef(i[m])*e*var(n)+(i[m]-lead(i[m]))/var(n)^(e-1);
503         i[m]=poly(e)^e*leadcoef(i[m])^(e-1)*i[m];
504         if (reduce(i[m]-t^e,prm,1) !=0)
505         {
506           return(ideal(0));
507         }
[a3432c]508      }
[6ffa84]509
[a3432c]510      h=interred(t);
511      t=h[1];
[d6db1f2]512
513      prm = prm,t;
514      attrib(prm,"isSB",1);
515   }
516   return(prm);
517}
518
[d12f079]519///////////////////////////////////////////////////////////////////////////////
520proc gcdTest(ideal act)
521{
522  int i,j;
523  if(size(act)<=1)
524  {
525     return(0);
526  }
527  for (i=1;i<=size(act)-1;i++)
528  {
529     for(j=i+1;j<=size(act);j++)
530     {
531        if(deg(std(ideal(act[i],act[j]))[1])>0)
532        {
533           return(0);
534        }
535     }
536  }
537  return(1);
538}
[d6db1f2]539
540///////////////////////////////////////////////////////////////////////////////
[07c623]541static proc splitPrimary(list l,ideal ser,int @wr,list sact)
[d6db1f2]542{
543   int i,j,k,s,r,w;
544   list keepresult,act,keepprime;
545   poly @f;
546   int sl=size(l);
[67bd4c]547   for(i=1;i<=sl/2;i++)
[d6db1f2]548   {
549      if(sact[2][i]>1)
550      {
551         keepprime[i]=l[2*i-1]+ideal(sact[1][i]);
552      }
553      else
554      {
555         keepprime[i]=l[2*i-1];
556      }
[67bd4c]557  }
[d6db1f2]558   i=0;
[67bd4c]559   while(i<size(l)/2)
[d6db1f2]560   {
561      i++;
[e801fe]562      if((size(ser)>0)&&(size(reduce(ser,l[2*i-1],1))==0))
[d6db1f2]563      {
564         l[2*i-1]=ideal(1);
565         l[2*i]=ideal(1);
566         continue;
567      }
568
569      if(size(l[2*i])==0)
570      {
571         if(homog(l[2*i-1])==1)
572         {
573            l[2*i]=maxideal(1);
574            continue;
575         }
576         j=0;
[67bd4c]577         if(i<=sl/2)
[d6db1f2]578         {
579            j=1;
580         }
581         while(j<size(l[2*i-1]))
582         {
583            j++;
584            act=factor(l[2*i-1][j]);
585            r=size(act[1]);
586            attrib(l[2*i-1],"isSB",1);
587            if((r==1)&&(vdim(l[2*i-1])==deg(l[2*i-1][j])))
588            {
589              l[2*i]=std(l[2*i-1],act[1][1]);
590              break;
591            }
592            if((r==1)&&(act[2][1]>1))
593            {
594               keepprime[i]=interred(keepprime[i]+ideal(act[1][1]));
595               if(homog(keepprime[i])==1)
596               {
597                  l[2*i]=maxideal(1);
598                  break;
599               }
600            }
601            if(gcdTest(act[1])==1)
[18dd47]602            {
[d6db1f2]603               for(k=2;k<=r;k++)
604               {
[80b3cd]605                  keepprime[size(l)/2+k-1]=interred(keepprime[i]+ideal(act[1][k]));
[d6db1f2]606               }
607               keepprime[i]=interred(keepprime[i]+ideal(act[1][1]));
608               for(k=1;k<=r;k++)
609               {
610                  if(@wr==0)
611                  {
612                     keepresult[k]=std(l[2*i-1],act[1][k]^act[2][k]);
613                  }
614                  else
615                  {
616                     keepresult[k]=std(l[2*i-1],act[1][k]);
617                  }
618               }
619               l[2*i-1]=keepresult[1];
620               if(vdim(keepresult[1])==deg(act[1][1]))
621               {
622                  l[2*i]=keepresult[1];
623               }
624               if((homog(keepresult[1])==1)||(homog(keepprime[i])==1))
625               {
626                  l[2*i]=maxideal(1);
627               }
628               s=size(l)-2;
629               for(k=2;k<=r;k++)
630               {
631                  l[s+2*k-1]=keepresult[k];
[67bd4c]632                  keepprime[s/2+k]=interred(keepresult[k]+ideal(act[1][k]));
[d6db1f2]633                  if(vdim(keepresult[k])==deg(act[1][k]))
634                  {
635                     l[s+2*k]=keepresult[k];
636                  }
637                  else
638                  {
639                     l[s+2*k]=ideal(0);
640                  }
[67bd4c]641                  if((homog(keepresult[k])==1)||(homog(keepprime[s/2+k])==1))
[d6db1f2]642                  {
643                    l[s+2*k]=maxideal(1);
644                  }
645               }
646               i--;
[18dd47]647               break;
[d6db1f2]648            }
649            if(r>=2)
650            {
651               s=size(l);
652               @f=act[1][1];
653               act=sat1(l[2*i-1],act[1][1]);
654               if(deg(act[1][1])>0)
655               {
656                  l[s+1]=std(l[2*i-1],act[2]);
657                  if(homog(l[s+1])==1)
658                  {
659                     l[s+2]=maxideal(1);
660                  }
661                  else
662                  {
[18dd47]663                     l[s+2]=ideal(0);
[d6db1f2]664                  }
[67bd4c]665                  keepprime[s/2+1]=interred(keepprime[i]+ideal(@f));
666                  if(homog(keepprime[s/2+1])==1)
[d6db1f2]667                  {
668                     l[s+2]=maxideal(1);
669                  }
[18dd47]670                  keepprime[i]=act[1];
[d6db1f2]671                  l[2*i-1]=act[1];
672                  attrib(l[2*i-1],"isSB",1);
673                  if(homog(l[2*i-1])==1)
674                  {
675                     l[2*i]=maxideal(1);
676                  }
[18dd47]677
[d6db1f2]678                  i--;
679                  break;
680               }
681            }
682         }
683      }
684   }
685   if(sl==size(l))
686   {
687      return(l);
688   }
[67bd4c]689   for(i=1;i<=size(l)/2;i++)
[d6db1f2]690   {
[e801fe]691     attrib(l[2*i-1],"isSB",1);
[3939bc]692
[e801fe]693     if((size(ser)>0)&&(size(reduce(ser,l[2*i-1],1))==0)&&(deg(l[2*i-1][1])>0))
694     {
695       "Achtung in split";
[3939bc]696
[e801fe]697         l[2*i-1]=ideal(1);
698         l[2*i]=ideal(1);
699     }
700     if((size(l[2*i])==0)&&(specialIdealsEqual(keepprime[i],l[2*i-1])!=1))
[d6db1f2]701      {
[18dd47]702         keepprime[i]=std(keepprime[i]);
[d6db1f2]703         if(homog(keepprime[i])==1)
[18dd47]704         {
[d6db1f2]705             l[2*i]=maxideal(1);
706         }
707         else
708         {
709            act=zero_decomp(keepprime[i],ideal(0),@wr,1);
710            if(size(act)==2)
711            {
712               l[2*i]=act[2];
713            }
714         }
715      }
716   }
717   return(l);
718}
719example
720{ "EXAMPLE:"; echo=2;
721   ring  r = 32003,(x,y,z),lp;
722   ideal i1=x*(x+1),yz,(z+1)*(z-1);
723   ideal i2=xy,yz,(x-2)*(x+3);
724   list l=i1,ideal(0),i2,ideal(0),i2,ideal(1);
725   list l1=splitPrimary(l,ideal(0),0);
726   l1;
727}
[651953]728///////////////////////////////////////////////////////////////////////////////
[07c623]729static proc splitCharp(list l)
[651953]730{
731  if((char(basering)==0)||(npars(basering)>0))
732  {
733     return(l);
734  }
735  def P=basering;
[24f458]736  int i,j,k,m,q,d,o;
[651953]737  int n=nvars(basering);
738  ideal s,t,u,sact;
739  poly ni;
740  string minp,gnir,va;
[24f458]741  list sa,keep,rp,keep1;
[651953]742  for(i=1;i<=size(l)/2;i++)
743  {
744    if(size(l[2*i])==0)
745    {
746       if(deg(l[2*i-1][1])==vdim(l[2*i-1]))
747       {
748          l[2*i]=l[2*i-1];
749       }
750    }
751  }
752  for(i=1;i<=size(l)/2;i++)
753  {
754    if(size(l[2*i])==0)
755    {
[24f458]756      s=factorize(l[2*i-1][1],1);   //vermeiden!!!
[651953]757      t=l[2*i-1];
758      m=size(t);
759      ni=s[1];
760      if(deg(ni)>1)
761      {
762        va=varstr(P);
763        j=size(va);
764        while(va[j]!=","){j--;}
765        va=va[1..j-1];
[24f458]766        gnir="ring RL=("+string(char(P))+","+string(var(n))+"),("+va+"),lp;";
[651953]767        execute(gnir);
768        minpoly=leadcoef(imap(P,ni));
769        ideal act;
770        ideal t=imap(P,t);
[24f458]771
[651953]772        for(k=2;k<=m;k++)
[b9b906]773        {
[651953]774           act=factorize(t[k],1);
[24f458]775           if(size(act)>1){break;}
[651953]776        }
777        setring P;
778        sact=imap(RL,act);
[24f458]779
[651953]780        if(size(sact)>1)
781        {
782           sa=sat1(l[2*i-1],sact[1]);
783           keep[size(keep)+1]=std(l[2*i-1],sa[2]);
784           l[2*i-1]=std(sa[1]);
785           l[2*i]=primaryTest(sa[1],sa[1][1]);
786        }
[24f458]787        if((size(sact)==1)&&(m==2))
788        {
789           l[2*i]=l[2*i-1];
790           attrib(l[2*i],"isSB",1);
791        }
792        if((size(sact)==1)&&(m>2))
793        {
794           setring RL;
795           option(redSB);
796           t=std(t);
797
798           list sp=zero_decomp(t,0,0);
799
800           setring P;
801           rp=imap(RL,sp);
802           for(o=1;o<=size(rp);o++)
803           {
804              rp[o]=interred(simplify(rp[o],1)+ideal(ni));
805           }
806           l[2*i-1]=rp[1];
807           l[2*i]=rp[2];
808           rp=delete(rp,1);
809           rp=delete(rp,1);
810           keep1=keep1+rp;
811           option(noredSB);
812        }
813        kill RL;
[651953]814      }
815    }
816  }
817  if(size(keep)>0)
818  {
819    for(i=1;i<=size(keep);i++)
820    {
[50cbdc]821       if(deg(keep[i][1])>0)
822       {
823          l[size(l)+1]=keep[i];
824          l[size(l)+1]=primaryTest(keep[i],keep[i][1]);
825       }
[651953]826    }
827  }
[24f458]828  l=l+keep1;
[651953]829  return(l);
830}
[d6db1f2]831
[091424]832///////////////////////////////////////////////////////////////////////////////
[d6db1f2]833
[24f458]834proc zero_decomp (ideal j,ideal ser,int @wr,list #)
[d2b2a7]835"USAGE:   zero_decomp(j,ser,@wr); j,ser ideals, @wr=0 or 1
[d6db1f2]836         (@wr=0 for primary decomposition, @wr=1 for computaion of associated
837         primes)
838RETURN:  list = list of primary ideals and their radicals (at even positions
839         in the list) if the input is zero-dimensional and a standardbases
840         with respect to lex-ordering
841         If ser!=(0) and ser is contained in j or if j is not zero-dimen-
842         sional then ideal(1),ideal(1) is returned
[7b3971]843NOTE:    Algorithm of Gianni/Trager/Zacharias
[d6db1f2]844EXAMPLE: example zero_decomp; shows an example
[d2b2a7]845"
[d6db1f2]846{
847  def   @P = basering;
[20057b]848  int uytrewq;
[d6db1f2]849  int nva = nvars(basering);
[e801fe]850  int @k,@s,@n,@k1,zz;
[a39a07]851  list primary,lres0,lres1,act,@lh,@wh;
[e801fe]852  map phi,psi,phi1,psi1;
853  ideal jmap,jmap1,jmap2,helpprim,@qh,@qht,ser1;
[d6db1f2]854  intvec @vh,@hilb;
855  string @ri;
856  poly @f;
857  if (dim(j)>0)
858  {
859     primary[1]=ideal(1);
860     primary[2]=ideal(1);
861     return(primary);
862  }
[3939bc]863  j=interred(j);
[0bcebab]864
[d6db1f2]865  attrib(j,"isSB",1);
[24f458]866
[d6db1f2]867  if(vdim(j)==deg(j[1]))
[3939bc]868  {
[d6db1f2]869     act=factor(j[1]);
870     for(@k=1;@k<=size(act[1]);@k++)
871     {
872       @qh=j;
873       if(@wr==0)
874       {
875          @qh[1]=act[1][@k]^act[2][@k];
876       }
877       else
878       {
[18dd47]879          @qh[1]=act[1][@k];
[d6db1f2]880       }
881       primary[2*@k-1]=interred(@qh);
882       @qh=j;
883       @qh[1]=act[1][@k];
884       primary[2*@k]=interred(@qh);
[e801fe]885       attrib( primary[2*@k-1],"isSB",1);
[3939bc]886
[e801fe]887       if((size(ser)>0)&&(size(reduce(ser,primary[2*@k-1],1))==0))
888       {
889          primary[2*@k-1]=ideal(1);
[3939bc]890          primary[2*@k]=ideal(1);
[e801fe]891       }
[d6db1f2]892     }
[e801fe]893     return(primary);
[d6db1f2]894  }
895
896  if(homog(j)==1)
897  {
898     primary[1]=j;
[e801fe]899     if((size(ser)>0)&&(size(reduce(ser,j,1))==0))
[d6db1f2]900     {
901          primary[1]=ideal(1);
902          primary[2]=ideal(1);
903          return(primary);
904     }
905     if(dim(j)==-1)
[18dd47]906     {
[d6db1f2]907        primary[1]=ideal(1);
908        primary[2]=ideal(1);
909     }
910     else
911     {
912        primary[2]=maxideal(1);
913     }
914     return(primary);
915  }
[18dd47]916
[d6db1f2]917//the first element in the standardbase is factorized
918  if(deg(j[1])>0)
919  {
920    act=factor(j[1]);
921    testFactor(act,j[1]);
922  }
923  else
924  {
925     primary[1]=ideal(1);
926     primary[2]=ideal(1);
927     return(primary);
928  }
929
[9050ca]930//with the factors new ideals (hopefully the primary decomposition)
[d6db1f2]931//are created
932  if(size(act[1])>1)
933  {
934     if(size(#)>1)
935     {
936        primary[1]=ideal(1);
937        primary[2]=ideal(1);
938        primary[3]=ideal(1);
939        primary[4]=ideal(1);
940        return(primary);
941     }
942     for(@k=1;@k<=size(act[1]);@k++)
943     {
944        if(@wr==0)
945        {
946           primary[2*@k-1]=std(j,act[1][@k]^act[2][@k]);
[24f458]947
[d6db1f2]948        }
949        else
950        {
951           primary[2*@k-1]=std(j,act[1][@k]);
952        }
953        if((act[2][@k]==1)&&(vdim(primary[2*@k-1])==deg(act[1][@k])))
954        {
955           primary[2*@k]   = primary[2*@k-1];
956        }
957        else
958        {
[24f458]959
[d6db1f2]960           primary[2*@k]   = primaryTest(primary[2*@k-1],act[1][@k]);
[24f458]961
[d6db1f2]962        }
963     }
964  }
965  else
[3939bc]966  {
[d6db1f2]967     primary[1]=j;
968     if((size(#)>0)&&(act[2][1]>1))
969     {
970        act[2]=1;
971        primary[1]=std(primary[1],act[1][1]);
972     }
[18dd47]973
[d6db1f2]974     if((act[2][1]==1)&&(vdim(primary[1])==deg(act[1][1])))
975     {
976        primary[2]=primary[1];
977     }
978     else
979     {
980        primary[2]=primaryTest(primary[1],act[1][1]);
981     }
982  }
[50cbdc]983
[d6db1f2]984  if(size(#)==0)
985  {
986     primary=splitPrimary(primary,ser,@wr,act);
987  }
[24f458]988
989  if((voice>=6)&&(char(basering)<=181))
990  {
991     primary=splitCharp(primary);
992  }
993
994  if((@wr==2)&&(npars(basering)>0)&&(voice>=6)&&(char(basering)>0))
995  {
996  //the prime decomposition of Yokoyama in characteristic p
997     list ke,ek;
998     @k=0;
999     while(@k<size(primary)/2)
1000     {
1001        @k++;
1002        if(size(primary[2*@k])==0)
1003        {
1004           ek=insepDecomp(primary[2*@k-1]);
1005           primary=delete(primary,2*@k);
1006           primary=delete(primary,2*@k-1);
1007           @k--;
1008        }
1009        ke=ke+ek;
1010     }
1011     for(@k=1;@k<=size(ke);@k++)
1012     {
1013        primary[size(primary)+1]=ke[@k];
1014        primary[size(primary)+1]=ke[@k];
1015     }
1016  }
1017
1018  if(voice>=8){primary=extF(primary)};
1019
[d6db1f2]1020//test whether all ideals in the decomposition are primary and
1021//in general position
1022//if not after a random coordinate transformation of the last
1023//variable the corresponding ideal is decomposed again.
[24f458]1024  if((npars(basering)>0)&&(voice>=8))
1025  {
1026     poly randp;
1027     for(zz=1;zz<nvars(basering);zz++)
1028     {
1029        randp=randp
1030              +(random(0,5)*par(1)^2+random(0,5)*par(1)+random(0,5))*var(zz);
1031     }
1032     randp=randp+var(nvars(basering));
1033  }
[d6db1f2]1034  @k=0;
[67bd4c]1035  while(@k<(size(primary)/2))
[d6db1f2]1036  {
1037    @k++;
1038    if (size(primary[2*@k])==0)
1039    {
[67bd4c]1040       for(zz=1;zz<size(primary[2*@k-1])-1;zz++)
1041       {
[24f458]1042          attrib(primary[2*@k-1],"isSB",1);
[67bd4c]1043          if(vdim(primary[2*@k-1])==deg(primary[2*@k-1][zz]))
1044          {
1045             primary[2*@k]=primary[2*@k-1];
1046          }
1047       }
1048    }
1049  }
[3939bc]1050
[67bd4c]1051  @k=0;
[e801fe]1052  ideal keep;
[67bd4c]1053  while(@k<(size(primary)/2))
1054  {
1055    @k++;
1056    if (size(primary[2*@k])==0)
1057    {
1058
[d6db1f2]1059       jmap=randomLast(100);
[e801fe]1060       jmap1=maxideal(1);
1061       jmap2=maxideal(1);
1062       @qht=primary[2*@k-1];
[24f458]1063       if((npars(basering)>0)&&(voice>=10))
1064       {
1065          jmap[size(jmap)]=randp;
1066       }
[e801fe]1067
[d6db1f2]1068       for(@n=2;@n<=size(primary[2*@k-1]);@n++)
1069       {
1070          if(deg(lead(primary[2*@k-1][@n]))==1)
1071          {
[e801fe]1072             for(zz=1;zz<=nva;zz++)
1073             {
1074                if(lead(primary[2*@k-1][@n])/var(zz)!=0)
1075                {
[07c623]1076                 jmap1[zz]=-1/leadcoef(primary[2*@k-1][@n])*primary[2*@k-1][@n]
[e801fe]1077                   +2/leadcoef(primary[2*@k-1][@n])*lead(primary[2*@k-1][@n]);
1078                    jmap2[zz]=primary[2*@k-1][@n];
1079                    @qht[@n]=var(zz);
[3939bc]1080
[e801fe]1081                }
1082             }
[d6db1f2]1083             jmap[nva]=subst(jmap[nva],lead(primary[2*@k-1][@n]),0);
1084          }
1085       }
[e801fe]1086       if(size(subst(jmap[nva],var(1),0)-var(nva))!=0)
1087       {
[ac54d4]1088         // jmap[nva]=subst(jmap[nva],var(1),0);
1089         //hier geaendert +untersuchen!!!!!!!!!!!!!!
[e801fe]1090       }
1091       phi1=@P,jmap1;
[d6db1f2]1092       phi=@P,jmap;
[e801fe]1093       for(@n=1;@n<=nva;@n++)
1094       {
1095          jmap[@n]=-(jmap[@n]-2*var(@n));
1096       }
[18dd47]1097       psi=@P,jmap;
[e801fe]1098       psi1=@P,jmap2;
[d6db1f2]1099       @qh=phi(@qht);
[24f458]1100
1101//=================== the new part ============================
1102
1103       @qh=groebner(@qh);
1104
1105//=============================================================
1106//       if(npars(@P)>0)
1107//       {
1108//          @ri= "ring @Phelp ="
1109//                  +string(char(@P))+",
1110//                   ("+varstr(@P)+","+parstr(@P)+",@t),(C,dp);";
1111//       }
1112//       else
1113//       {
1114//          @ri= "ring @Phelp ="
1115//                  +string(char(@P))+",("+varstr(@P)+",@t),(C,dp);";
1116//       }
1117//       execute(@ri);
1118//       ideal @qh=homog(imap(@P,@qht),@t);
1119//
1120//       ideal @qh1=std(@qh);
1121//       @hilb=hilb(@qh1,1);
1122//       @ri= "ring @Phelp1 ="
1123//                  +string(char(@P))+",("+varstr(@Phelp)+"),(C,lp);";
1124//       execute(@ri);
1125//       ideal @qh=homog(imap(@P,@qh),@t);
1126//       kill @Phelp;
1127//       @qh=std(@qh,@hilb);
1128//       @qh=subst(@qh,@t,1);
1129//       setring @P;
1130//       @qh=imap(@Phelp1,@qh);
1131//       kill @Phelp1;
1132//       @qh=clearSB(@qh);
1133//       attrib(@qh,"isSB",1);
1134//=============================================================
1135
[e801fe]1136       ser1=phi1(ser);
1137       @lh=zero_decomp (@qh,phi(ser1),@wr);
[24f458]1138
[a39a07]1139       kill lres0;
1140       list lres0;
[d6db1f2]1141       if(size(@lh)==2)
1142       {
1143          helpprim=@lh[2];
[a39a07]1144          lres0[1]=primary[2*@k-1];
[e801fe]1145          ser1=psi(helpprim);
[a39a07]1146          lres0[2]=psi1(ser1);
1147          if(size(reduce(lres0[2],lres0[1],1))==0)
[d6db1f2]1148          {
1149             primary[2*@k]=primary[2*@k-1];
1150             continue;
1151          }
1152       }
1153       else
1154       {
[18dd47]1155
[24f458]1156          lres1=psi(@lh);
1157          lres0=psi1(lres1);
[d6db1f2]1158       }
1159
[24f458]1160//=================== the new part ============================
[d6db1f2]1161
[24f458]1162       primary=delete(primary,2*@k-1);
1163       primary=delete(primary,2*@k-1);
1164       @k--;
1165       if(size(lres0)==2)
[d6db1f2]1166       {
[24f458]1167          lres0[2]=groebner(lres0[2]);
[d6db1f2]1168       }
1169       else
1170       {
[24f458]1171          for(@n=1;@n<=size(lres0)/2;@n++)
[d6db1f2]1172          {
[24f458]1173             if(specialIdealsEqual(lres0[2*@n-1],lres0[2*@n])==1)
[d6db1f2]1174             {
[24f458]1175                lres0[2*@n-1]=groebner(lres0[2*@n-1]);
1176                lres0[2*@n]=lres0[2*@n-1];
1177                attrib(lres0[2*@n],"isSB",1);
[d6db1f2]1178             }
1179             else
1180             {
[24f458]1181                lres0[2*@n-1]=groebner(lres0[2*@n-1]);
1182                lres0[2*@n]=groebner(lres0[2*@n]);
[d6db1f2]1183             }
1184          }
1185       }
[24f458]1186       primary=primary+lres0;
[18dd47]1187
[24f458]1188//=============================================================
1189//       if(npars(@P)>0)
1190//       {
1191//          @ri= "ring @Phelp ="
1192//                  +string(char(@P))+",
1193//                   ("+varstr(@P)+","+parstr(@P)+",@t),(C,dp);";
1194//       }
1195//       else
1196//       {
1197//          @ri= "ring @Phelp ="
1198//                  +string(char(@P))+",("+varstr(@P)+",@t),(C,dp);";
1199//       }
1200//       execute(@ri);
1201//       list @lvec;
1202//       list @lr=imap(@P,lres0);
1203//       ideal @lr1;
1204//
1205//       if(size(@lr)==2)
1206//       {
1207//          @lr[2]=homog(@lr[2],@t);
1208//          @lr1=std(@lr[2]);
1209//          @lvec[2]=hilb(@lr1,1);
1210//       }
1211//       else
1212//       {
1213//          for(@n=1;@n<=size(@lr)/2;@n++)
1214//          {
1215//             if(specialIdealsEqual(@lr[2*@n-1],@lr[2*@n])==1)
1216//             {
1217//                @lr[2*@n-1]=homog(@lr[2*@n-1],@t);
1218//                @lr1=std(@lr[2*@n-1]);
1219//                @lvec[2*@n-1]=hilb(@lr1,1);
1220//                @lvec[2*@n]=@lvec[2*@n-1];
1221//             }
1222//             else
1223//             {
1224//                @lr[2*@n-1]=homog(@lr[2*@n-1],@t);
1225//                @lr1=std(@lr[2*@n-1]);
1226//                @lvec[2*@n-1]=hilb(@lr1,1);
1227//                @lr[2*@n]=homog(@lr[2*@n],@t);
1228//                @lr1=std(@lr[2*@n]);
1229//                @lvec[2*@n]=hilb(@lr1,1);
1230//
1231//             }
1232//         }
1233//       }
1234//       @ri= "ring @Phelp1 ="
1235//                  +string(char(@P))+",("+varstr(@Phelp)+"),(C,lp);";
1236//       execute(@ri);
1237//       list @lr=imap(@Phelp,@lr);
1238//
1239//       kill @Phelp;
1240//       if(size(@lr)==2)
1241//      {
1242//          @lr[2]=std(@lr[2],@lvec[2]);
1243//          @lr[2]=subst(@lr[2],@t,1);
1244//
1245//       }
1246//       else
1247//       {
1248//          for(@n=1;@n<=size(@lr)/2;@n++)
1249//          {
1250//             if(specialIdealsEqual(@lr[2*@n-1],@lr[2*@n])==1)
1251//             {
1252//                @lr[2*@n-1]=std(@lr[2*@n-1],@lvec[2*@n-1]);
1253//                @lr[2*@n-1]=subst(@lr[2*@n-1],@t,1);
1254//                @lr[2*@n]=@lr[2*@n-1];
1255//                attrib(@lr[2*@n],"isSB",1);
1256//             }
1257//             else
1258//             {
1259//                @lr[2*@n-1]=std(@lr[2*@n-1],@lvec[2*@n-1]);
1260//                @lr[2*@n-1]=subst(@lr[2*@n-1],@t,1);
1261//                @lr[2*@n]=std(@lr[2*@n],@lvec[2*@n]);
1262//                @lr[2*@n]=subst(@lr[2*@n],@t,1);
1263//             }
1264//          }
1265//       }
1266//       kill @lvec;
1267//       setring @P;
1268//       lres0=imap(@Phelp1,@lr);
1269//       kill @Phelp1;
1270//       for(@n=1;@n<=size(lres0);@n++)
1271//       {
1272//          lres0[@n]=clearSB(lres0[@n]);
1273//          attrib(lres0[@n],"isSB",1);
1274//       }
1275//
1276//       primary[2*@k-1]=lres0[1];
1277//       primary[2*@k]=lres0[2];
1278//       @s=size(primary)/2;
1279//       for(@n=1;@n<=size(lres0)/2-1;@n++)
1280//       {
1281//         primary[2*@s+2*@n-1]=lres0[2*@n+1];
1282//         primary[2*@s+2*@n]=lres0[2*@n+2];
1283//       }
1284//       @k--;
1285//=============================================================
[d6db1f2]1286     }
1287  }
1288  return(primary);
1289}
1290example
1291{ "EXAMPLE:"; echo = 2;
1292   ring  r = 0,(x,y,z),lp;
1293   poly  p = z2+1;
1294   poly  q = z4+2;
1295   ideal i = p^2*q^3,(y-z3)^3,(x-yz+z4)^4;
1296   i=std(i);
1297   list  pr= zero_decomp(i,ideal(0),0);
1298   pr;
1299}
[24f458]1300///////////////////////////////////////////////////////////////////////////////
1301proc extF(list l,list #)
1302{
1303//zero_dimensional primary decomposition after finite field extension
1304   def R=basering;
1305   int p=char(R);
1306
1307   if((p==0)||(p>13)||(npars(R)>0)){return(l);}
1308
1309   int ex=3;
1310   if(size(#)>0){ex=#[1];}
1311
1312   list peek,peek1;
1313   while(size(l)>0)
1314   {
1315      if(size(l[2])==0)
1316      {
1317         peek[size(peek)+1]=l[1];
1318      }
1319      else
1320      {
1321         peek1[size(peek1)+1]=l[1];
1322         peek1[size(peek1)+1]=l[2];
1323      }
1324      l=delete(l,1);
1325      l=delete(l,1);
1326   }
1327   if(size(peek)==0){return(peek1);}
1328
1329   string gnir="ring RH=("+string(p)+"^"+string(ex)+",a),("+varstr(R)+"),lp;";
1330   execute(gnir);
1331   string mp="minpoly="+string(minpoly)+";";
1332   gnir="ring RL=("+string(p)+",a),("+varstr(R)+"),lp;";
1333   execute(gnir);
1334   execute(mp);
1335   list L=imap(R,peek);
1336   list pr, keep;
1337   int i;
1338   for(i=1;i<=size(L);i++)
1339   {
1340      attrib(L[i],"isSB",1);
1341      pr=zero_decomp(L[i],0,0);
1342      keep=keep+pr;
1343   }
1344   for(i=1;i<=size(keep);i++)
1345   {
1346      keep[i]=simplify(keep[i],1);
1347   }
1348   mp="poly pp="+string(minpoly)+";";
1349
1350   string gnir1="ring RS="+string(p)+",("+varstr(R)+",a),lp;";
1351   execute(gnir1);
1352   execute(mp);
1353   list L=imap(RL,keep);
1354
1355   for(i=1;i<=size(L);i++)
1356   {
1357      L[i]=eliminate(L[i]+ideal(pp),a);
1358   }
1359   i=0;
1360   int j;
1361   while(i<size(L)/2-1)
1362   {
1363      i++;
1364      j=i;
1365      while(j<size(L)/2)
1366      {
1367         j++;
1368         if(idealsEqual(L[2*i-1],L[2*j-1]))
1369         {
1370            L=delete(L,2*j-1);
1371            L=delete(L,2*j-1);
1372            j--;
1373         }
1374      }
1375   }
1376   setring R;
1377   list re=imap(RS,L);
1378   re=re+peek1;
1379
1380   return(extF(re,ex+1));
1381}
1382
1383///////////////////////////////////////////////////////////////////////////////
1384proc zeroSp(ideal i)
1385{
1386//preparation for the separable closure
1387//decomposition into ideals of special type
1388//i.e. the minimal polynomials of every variable mod i are irreducible
1389//returns a list of 2 lists: rr=pe,qe
1390//the ideals in pe[l] are special, their special elements are in qe[l]
1391//pe[l] is a dp-Groebnerbasis
1392//the radical of the intersection of the pe[l] is equal to the radical of i
1393
1394   def R=basering;
1395
1396   //i has to be a reduced groebner basis
1397   ideal F=finduni(i);
1398
1399   int j,k,l,ready;
1400   list fa;
1401   fa[1]=factorize(F[1],1);
1402   poly te,ti;
1403   ideal tj;
1404   //avoid factorization of the same polynomial
1405   for(j=2;j<=size(F);j++)
1406   {
1407      for(k=1;k<=j-1;k++)
1408      {
1409         ti=F[k];
1410         te=subst(ti,var(k),var(j));
1411         if(te==F[j])
1412         {
1413            tj=fa[k];
1414            fa[j]=subst(tj,var(k),var(j));
1415            ready=1;
1416            break;
1417         }
1418      }
1419      if(!ready)
1420      {
1421         fa[j]=factorize(F[j],1);
1422      }
1423      ready=0;
1424   }
1425   execute( "ring P=("+charstr(R)+"),("+varstr(R)+"),(C,dp);");
1426   ideal i=imap(R,i);
1427   if(npars(basering)==0)
1428   {
1429      ideal J=fglm(R,i);
1430   }
1431   else
1432   {
1433      ideal J=groebner(i);
1434   }
1435   list fa=imap(R,fa);
1436   list qe=J;          //collects a dp-Groebnerbasis of the special ideals
1437   list keep=ideal(0); //collects the special elements
1438
1439   list re,em,ke;
1440   ideal K,L;
1441
1442   for(j=1;j<=nvars(basering);j++)
1443   {
1444      for(l=1;l<=size(qe);l++)
1445      {
1446         for(k=1;k<=size(fa[j]);k++)
1447         {
1448            L=std(qe[l],fa[j][k]);
1449            K=keep[l],fa[j][k];
1450            if(deg(L[1])>0)
1451            {
1452               re[size(re)+1]=L;
1453               ke[size(ke)+1]=K;
1454            }
1455         }
1456      }
1457      qe=re;
1458      re=em;
1459      keep=ke;
1460      ke=em;
1461   }
1462
1463   setring R;
1464   list qe=imap(P,keep);
1465   list pe=imap(P,qe);
1466   for(l=1;l<=size(qe);l++)
1467   {
1468      qe[l]=simplify(qe[l],2);
1469    }
1470    list rr=pe,qe;
1471    return(rr);
1472}
1473///////////////////////////////////////////////////////////////////////////////
1474
1475proc zeroSepClos(ideal I,ideal F)
1476{
1477//computes the separable closure of the special ideal I
1478//F is the set of special elements of I
1479//returns the separable closure sc(I) of I and an intvec v
1480//such that sc(I)=preimage(frobenius definde by v)
1481//i.e. var(i)----->var(i)^(p^v[i])
1482
1483   if(homog(I)==1){return(maxideal(1));}
1484
1485   //assume F[i] irreducible in I and depending only on var(i)
1486
1487   def R=basering;
1488   int n=nvars(R);
1489   int p=char(R);
1490   intvec v;
1491   v[n]=0;
1492   int i,k;
1493   list l;
1494
1495   for(i=1;i<=n;i++)
1496   {
1497      l[i]=sep(F[i],i);
1498      F[i]=l[i][1];
1499      if(l[i][2]>k){k=l[i][2];}
1500   }
1501
1502   if(k==0){return(list(I,v));}        //the separable case
1503   ideal m;
1504
1505   for(i=1;i<=n;i++)
1506   {
1507      m[i]=var(i)^(p^l[i][2]);
1508      v[i]=l[i][2];
1509   }
1510   map phi=R,m;
1511   ideal J=preimage(R,phi,I);
1512   return(list(J,v));
1513}
1514///////////////////////////////////////////////////////////////////////////////
1515
1516proc insepDecomp(ideal i)
1517{
1518//decomposes i into special ideals
1519//computes the prime decomposition of the special ideals
1520//and transforms it back to a decomposition of i
1521
1522   def R=basering;
1523   list pr=zeroSp(i);
1524   int l,k;
1525   list re,wo,qr;
1526   ideal m=maxideal(1);
1527   ideal K;
1528   map phi=R,m;
1529   int p=char(R);
1530   intvec op=option(get);
1531
1532   for(l=1;l<=size(pr[1]);l++)
1533   {
1534      wo=zeroSepClos(pr[1][l],pr[2][l]);
1535      for(k=1;k<=nvars(basering);k++)
1536      {
1537         m[k]=var(k)^(p^wo[2][k]);
1538      }
1539      phi=R,m;
1540      qr=decomp(wo[1],2);
1541
1542      option(redSB);
1543      for(k=1;k<=size(qr)/2;k++)
1544      {
1545         K=qr[2*k];
1546         K=phi(K);
1547         K=groebner(K);
1548         re[size(re)+1]=zeroRad(K);
1549      }
1550      option(noredSB);
1551   }
1552   option(set,op);
1553   return(re);
1554}
1555
1556
[67bd4c]1557///////////////////////////////////////////////////////////////////////////////
1558
[07c623]1559static proc clearSB (ideal i,list #)
[d2b2a7]1560"USAGE:   clearSB(i); i ideal which is SB ordered by monomial ordering
[d6db1f2]1561RETURN:  ideal = minimal SB
[18dd47]1562NOTE:
[d6db1f2]1563EXAMPLE: example clearSB; shows an example
[d2b2a7]1564"
[d6db1f2]1565{
1566  int k,j;
1567  poly m;
1568  int c=size(i);
[18dd47]1569
[d6db1f2]1570  if(size(#)==0)
1571  {
1572    for(j=1;j<c;j++)
1573    {
1574      if(deg(i[j])==0)
1575      {
1576        i=ideal(1);
1577        return(i);
[18dd47]1578      }
[d6db1f2]1579      if(deg(i[j])>0)
1580      {
1581        m=lead(i[j]);
1582        for(k=j+1;k<=c;k++)
1583        {
1584           if(size(lead(i[k])/m)>0)
1585           {
1586             i[k]=0;
1587           }
1588        }
1589      }
1590    }
1591  }
1592  else
1593  {
1594    j=0;
1595    while(j<c-1)
1596    {
1597      j++;
1598      if(deg(i[j])==0)
1599      {
1600        i=ideal(1);
1601        return(i);
[18dd47]1602      }
[d6db1f2]1603      if(deg(i[j])>0)
1604      {
1605        m=lead(i[j]);
1606        for(k=j+1;k<=c;k++)
1607        {
1608           if(size(lead(i[k])/m)>0)
1609           {
1610             if((leadexp(m)!=leadexp(i[k]))||(#[j]<=#[k]))
1611             {
1612                i[k]=0;
1613             }
1614             else
1615             {
1616                i[j]=0;
[18dd47]1617                break;
[d6db1f2]1618             }
1619           }
1620        }
1621      }
1622    }
1623  }
1624  return(simplify(i,2));
1625}
1626example
1627{ "EXAMPLE:"; echo = 2;
1628   ring  r = (0,a,b),(x,y,z),dp;
1629   ideal i=ax2+y,a2x+y,bx;
1630   list l=1,2,1;
1631   ideal j=clearSB(i,l);
1632   j;
1633}
1634
[f54c83]1635///////////////////////////////////////////////////////////////////////////////
1636static proc clearSBNeu (ideal i,list #)
1637"USAGE:   clearSB(i); i ideal which is SB ordered by monomial ordering
1638RETURN:  ideal = minimal SB
1639NOTE:
1640EXAMPLE: example clearSB; shows an example
1641"
1642{
1643 int k,j;
1644 intvec m,n,v,w;
1645 int c=size(i);
1646 w=leadexp(0);
1647 v[size(i)]=0;
1648 
1649 j=0;
1650 while(j<c-1)
1651 {
1652   j++;
1653   if(deg(i[j])==0)
1654   {
1655     i=ideal(1);
1656     return(i);
1657   }
1658   if(deg(i[j])>0)
1659   {
1660      m=leadexp(i[j]);
1661      for(k=j+1;k<=c;k++)
1662      {
1663        n=leadexp(i[k]);
1664        if(n!=w)
1665        {
1666           if(((m==n)&&(#[j]>#[k]))||((teilt(n,m))&&(n!=m)))
1667           {
1668             i[j]=0;
1669             v[j]=1;
1670             break;
1671           }
1672           if(((m==n)&&(#[j]<=#[k]))||((teilt(m,n))&&(n!=m)))
1673           {
1674             i[k]=0;
1675             v[k]=1;
1676           }
1677        }
1678      }
1679    }
1680  }
1681  return(v);
1682}
1683
1684static proc teilt(intvec a, intvec b)
1685{
1686   int i;
1687   for(i=1;i<=size(a);i++)
1688   {
1689      if(a[i]>b[i]){return(0);}
1690   }
1691   return(1);
1692}
[d6db1f2]1693///////////////////////////////////////////////////////////////////////////////
1694
[07c623]1695static proc independSet (ideal j)
[d2b2a7]1696"USAGE:   independentSet(i); i ideal
[d6db1f2]1697RETURN:  list = new varstring with the independent set at the end,
1698                ordstring with the corresponding block ordering,
1699                the integer where the independent set starts in the varstring
[18dd47]1700NOTE:
[d6db1f2]1701EXAMPLE: example independentSet; shows an example
[d2b2a7]1702"
[d6db1f2]1703{
1704   int n,k,di;
1705   list resu,hilf;
1706   string var1,var2;
[aa3811c]1707   list v=indepSet(j,1);
[18dd47]1708
[d6db1f2]1709   for(n=1;n<=size(v);n++)
1710   {
1711      di=0;
1712      var1="";
1713      var2="";
1714      for(k=1;k<=size(v[n]);k++)
1715      {
[18dd47]1716         if(v[n][k]!=0)
[d6db1f2]1717         {
1718            di++;
1719            var2=var2+"var("+string(k)+"),";
1720         }
1721         else
1722         {
1723            var1=var1+"var("+string(k)+"),";
1724         }
1725      }
1726      if(di>0)
1727      {
1728         var1=var1+var2;
1729         var1=var1[1..size(var1)-1];
1730         hilf[1]=var1;
1731         hilf[2]="lp";
1732         //"lp("+string(nvars(basering)-di)+"),dp("+string(di)+")";
1733         hilf[3]=di;
1734         resu[n]=hilf;
1735      }
1736      else
1737      {
1738         resu[n]=varstr(basering),ordstr(basering),0;
1739      }
1740   }
1741   return(resu);
1742}
1743example
1744{ "EXAMPLE:"; echo = 2;
1745   ring s1=(0,x,y),(a,b,c,d,e,f,g),lp;
1746   ideal i=ea-fbg,fa+be,ec-fdg,fc+de;
1747   i=std(i);
1748   list  l=independSet(i);
1749   l;
1750   i=i,g;
1751   l=independSet(i);
1752   l;
1753
1754   ring s=0,(x,y,z),lp;
1755   ideal i=z,yx;
1756   list l=independSet(i);
1757   l;
1758
1759
1760}
1761///////////////////////////////////////////////////////////////////////////////
1762
[07c623]1763static proc maxIndependSet (ideal j)
[d2b2a7]1764"USAGE:   maxIndependentSet(i); i ideal
[d6db1f2]1765RETURN:  list = new varstring with the maximal independent set at the end,
1766                ordstring with the corresponding block ordering,
1767                the integer where the independent set starts in the varstring
[18dd47]1768NOTE:
[d6db1f2]1769EXAMPLE: example maxIndependentSet; shows an example
[d2b2a7]1770"
[d6db1f2]1771{
1772   int n,k,di;
1773   list resu,hilf;
1774   string var1,var2;
[aa3811c]1775   list v=indepSet(j,0);
[18dd47]1776
[d6db1f2]1777   for(n=1;n<=size(v);n++)
1778   {
1779      di=0;
1780      var1="";
1781      var2="";
1782      for(k=1;k<=size(v[n]);k++)
1783      {
[18dd47]1784         if(v[n][k]!=0)
[d6db1f2]1785         {
1786            di++;
1787            var2=var2+"var("+string(k)+"),";
1788         }
1789         else
1790         {
1791            var1=var1+"var("+string(k)+"),";
1792         }
1793      }
1794      if(di>0)
1795      {
1796         var1=var1+var2;
1797         var1=var1[1..size(var1)-1];
1798         hilf[1]=var1;
1799         hilf[2]="lp";
1800         hilf[3]=di;
1801         resu[n]=hilf;
1802      }
1803      else
1804      {
1805         resu[n]=varstr(basering),ordstr(basering),0;
1806      }
1807   }
1808   return(resu);
1809}
1810example
1811{ "EXAMPLE:"; echo = 2;
1812   ring s1=(0,x,y),(a,b,c,d,e,f,g),lp;
1813   ideal i=ea-fbg,fa+be,ec-fdg,fc+de;
1814   i=std(i);
1815   list  l=maxIndependSet(i);
1816   l;
1817   i=i,g;
1818   l=maxIndependSet(i);
1819   l;
1820
1821   ring s=0,(x,y,z),lp;
1822   ideal i=z,yx;
1823   list l=maxIndependSet(i);
1824   l;
1825
1826
1827}
1828
1829///////////////////////////////////////////////////////////////////////////////
1830
[07c623]1831static proc prepareQuotientring (int nnp)
[d2b2a7]1832"USAGE:   prepareQuotientring(nnp); nnp int
[d6db1f2]1833RETURN:  string = to define Kvar(nnp+1),...,var(nvars)[..rest ]
[18dd47]1834NOTE:
[d6db1f2]1835EXAMPLE: example independentSet; shows an example
[d2b2a7]1836"
[18dd47]1837{
[d6db1f2]1838  ideal @ih,@jh;
1839  int npar=npars(basering);
1840  int @n;
[18dd47]1841
[d6db1f2]1842  string quotring= "ring quring = ("+charstr(basering);
1843  for(@n=nnp+1;@n<=nvars(basering);@n++)
1844  {
1845     quotring=quotring+",var("+string(@n)+")";
1846     @ih=@ih+var(@n);
1847  }
[18dd47]1848
[d6db1f2]1849  quotring=quotring+"),(var(1)";
1850  @jh=@jh+var(1);
1851  for(@n=2;@n<=nnp;@n++)
1852  {
1853    quotring=quotring+",var("+string(@n)+")";
1854    @jh=@jh+var(@n);
1855  }
[e801fe]1856  quotring=quotring+"),(C,lp);";
[18dd47]1857
[d6db1f2]1858  return(quotring);
1859
1860}
1861example
1862{ "EXAMPLE:"; echo = 2;
1863   ring s1=(0,x),(a,b,c,d,e,f,g),lp;
1864   def @Q=basering;
1865   list l= prepareQuotientring(3);
1866   l;
[2d2cad9]1867   execute(l[1]);
1868   execute(l[2]);
[d6db1f2]1869   basering;
1870   phi;
1871   setring @Q;
[18dd47]1872
[d6db1f2]1873}
1874
[091424]1875///////////////////////////////////////////////////////////////////////////////
[07c623]1876static proc cleanPrimary(list l)
[d6db1f2]1877{
1878   int i,j;
1879   list lh;
[67bd4c]1880   for(i=1;i<=size(l)/2;i++)
[d6db1f2]1881   {
1882      if(deg(l[2*i-1][1])>0)
1883      {
1884         j++;
1885         lh[j]=l[2*i-1];
1886         j++;
1887         lh[j]=l[2*i];
1888      }
1889   }
1890   return(lh);
1891}
1892///////////////////////////////////////////////////////////////////////////////
1893
[840745]1894
1895proc minAssPrimesold(ideal i, list #)
[d2b2a7]1896"USAGE:   minAssPrimes(i); i ideal
[d6db1f2]1897         minAssPrimes(i,1); i ideal  (to use also the factorizing Groebner)
1898RETURN:  list = the minimal associated prime ideals of i
1899EXAMPLE: example minAssPrimes; shows an example
[d2b2a7]1900"
[d6db1f2]1901{
1902   def @P=basering;
[fc5095]1903   if(size(i)==0){return(list(ideal(0)));}
[e801fe]1904   list qr=simplifyIdeal(i);
1905   map phi=@P,qr[2];
1906   i=qr[1];
[3939bc]1907
[b1d1e8c]1908   execute ("ring gnir = ("+charstr(basering)+"),("+varstr(basering)+"),("
[2d2cad9]1909             +ordstr(basering)+");");
[67bd4c]1910
1911
[d6db1f2]1912   ideal i=fetch(@P,i);
1913   if(size(#)==0)
1914   {
1915      int @wr;
1916      list tluser,@res;
1917      list primary=decomp(i,2);
1918
1919      @res[1]=primary;
1920
1921      tluser=union(@res);
1922      setring @P;
1923      list @res=imap(gnir,tluser);
[e801fe]1924      return(phi(@res));
[d6db1f2]1925   }
1926   list @res,empty;
[67bd4c]1927   ideal ser;
[d6db1f2]1928   option(redSB);
1929   list @pr=facstd(i);
[17407e]1930   //if(size(@pr)==1)
1931//   {
1932//      attrib(@pr[1],"isSB",1);
1933//      if((dim(@pr[1])==0)&&(homog(@pr[1])==1))
1934//      {
1935//         setring @P;
1936//         list @res=maxideal(1);
1937//         return(phi(@res));
1938//      }
1939//      if(dim(@pr[1])>1)
1940//      {
1941//         setring @P;
1942//        // kill gnir;
1943//         execute ("ring gnir1 = ("+charstr(basering)+"),
1944//                              ("+varstr(basering)+"),(C,lp);");
1945//         ideal i=fetch(@P,i);
1946//         list @pr=facstd(i);
1947//        // ideal ser;
1948//         setring gnir;
1949//         @pr=fetch(gnir1,@pr);
1950//         kill gnir1;
1951//      }
1952//   }
[840745]1953    option(noredSB);
[18dd47]1954   int j,k,odim,ndim,count;
[d6db1f2]1955   attrib(@pr[1],"isSB",1);
[80b3cd]1956   if(#[1]==77)
1957   {
1958     odim=dim(@pr[1]);
1959     count=1;
1960     intvec pos;
1961     pos[size(@pr)]=0;
1962     for(j=2;j<=size(@pr);j++)
1963     {
1964        attrib(@pr[j],"isSB",1);
1965        ndim=dim(@pr[j]);
1966        if(ndim>odim)
1967        {
1968           for(k=count;k<=j-1;k++)
1969           {
1970              pos[k]=1;
1971           }
1972           count=j;
1973           odim=ndim;
1974        }
1975        if(ndim<odim)
1976        {
1977           pos[j]=1;
1978        }
1979     }
1980     for(j=1;j<=size(@pr);j++)
1981     {
1982        if(pos[j]!=1)
1983        {
1984            @res[j]=decomp(@pr[j],2);
1985        }
1986        else
1987        {
1988           @res[j]=empty;
1989        }
1990     }
1991   }
1992   else
1993   {
[67bd4c]1994     ser=ideal(1);
[d6db1f2]1995     for(j=1;j<=size(@pr);j++)
1996     {
[e801fe]1997//@pr[j];
[917fb5]1998//pause();
[e801fe]1999        @res[j]=decomp(@pr[j],2);
2000//       @res[j]=decomp(@pr[j],2,@pr[j],ser);
2001//       for(k=1;k<=size(@res[j]);k++)
2002//       {
[d950c5]2003//          ser=intersect(ser,@res[j][k]);
[e801fe]2004//       }
[18dd47]2005     }
[80b3cd]2006   }
[d6db1f2]2007
2008   @res=union(@res);
2009   setring @P;
2010   list @res=imap(gnir,@res);
[e801fe]2011   return(phi(@res));
[d6db1f2]2012}
2013example
2014{ "EXAMPLE:"; echo = 2;
2015   ring  r = 32003,(x,y,z),lp;
2016   poly  p = z2+1;
2017   poly  q = z4+2;
2018   ideal i = p^2*q^3,(y-z3)^3,(x-yz+z4)^4;
[091424]2019   list pr= minAssPrimes(i);  pr;
2020
[9050ca]2021   minAssPrimes(i,1);
[d6db1f2]2022}
2023
[24f458]2024static proc primT(ideal i)
2025{
2026   //assumes that all generators of i are irreducible
2027   //i is standard basis
[840745]2028
[24f458]2029   attrib(i,"isSB",1);
2030   int j=size(i);
2031   int k;
2032   while(j>0)
2033   {
2034     if(deg(i[j])>1){break;}
2035     j--;
2036   }
2037   if(j==0){return(1);}
2038   if(deg(i[j])==vdim(i)){return(1);}
2039   return(0);
2040}
[840745]2041
2042
2043static proc minAssPrimes(ideal i, list #)
2044"USAGE:   minAssPrimes(i); i ideal
2045         minAssPrimes(i,1); i ideal  (to use also the factorizing Groebner)
2046RETURN:  list = the minimal associated prime ideals of i
2047EXAMPLE: example minAssPrimes; shows an example
2048"
2049{
2050   def P=basering;
[fc5095]2051   if(size(i)==0){return(list(ideal(0)));}
[840745]2052   list q=simplifyIdeal(i);
2053   list re=maxideal(1);
[24f458]2054   int j,a,k;
[840745]2055   intvec op=option(get);
2056   map phi=P,q[2];
2057
[24f458]2058   if(npars(P)==0){option(redSB);}
2059
[f54c83]2060   if(attrib(i,"isSB")!=1)
2061   {
2062      i=groebner(q[1]);
2063   }
2064   else
2065   {
2066      for(j=1;j<=nvars(basering);j++)
2067      {
2068         if(q[2][j]!=var(j)){k=1;break;}
2069      }
2070      if(k)
2071      {
2072         i=groebner(q[1]);
2073      }
2074   }
2075   if(dim(i)==-1){return(ideal(1));}
[24f458]2076   if((dim(i)==0)&&(npars(P)==0))
2077   {
2078      int di=vdim(i);
2079      execute ("ring gnir=("+charstr(P)+"),("+varstr(P)+"),lp;");
2080      ideal J=interred(imap(P,i));
2081      attrib(J,"isSB",1);
2082      if(vdim(J)!=di)
2083      {
2084         J=fglm(P,i);
2085      }
2086      list pr=triangMH(J,2);
2087      list qr,re;
2088
2089      for(k=1;k<=size(pr);k++)
2090      {
2091         if(primT(pr[k]))
2092         {
2093            re[size(re)+1]=pr[k];
2094         }
2095         else
2096         {
2097            attrib(pr[k],"isSB",1);
2098            qr=decomp(pr[k],2);
2099            for(j=1;j<=size(qr)/2;j++)
2100            {
2101               re[size(re)+1]=qr[2*j];
2102            }
2103         }
2104      }
2105      setring P;
2106      re=imap(gnir,re);
2107      option(set,op);
2108      return(phi(re));
2109   }
2110
[b9b906]2111   if((size(#)==0)||(dim(i)==0))
[840745]2112   {
2113      re[1]=decomp(i,2);
2114      re=union(re);
[24f458]2115      option(set,op);
[840745]2116      return(phi(re));
2117   }
[b9b906]2118
[840745]2119   q=facstd(i);
2120
[f54c83]2121/*
[840745]2122   if((size(q)==1)&&(dim(i)>1))
2123   {
2124      execute ("ring gnir=("+charstr(P)+"),("+varstr(P)+"),lp;");
[367e88]2125
[840745]2126      list p=facstd(fetch(P,i));
2127      if(size(p)>1)
2128      {
2129         a=1;
2130         setring P;
2131         q=fetch(gnir,p);
2132      }
2133      else
2134      {
2135         setring P;
2136      }
2137      kill gnir;
2138   }
[f54c83]2139*/
[840745]2140
2141   option(set,op);
2142   for(j=1;j<=size(q);j++)
2143   {
2144      if(a==0){attrib(q[j],"isSB",1);}
2145      re[j]=decomp(q[j],2);
2146   }
2147   re=union(re);
2148   return(phi(re));
2149}
2150example
2151{ "EXAMPLE:"; echo = 2;
2152   ring  r = 32003,(x,y,z),lp;
2153   poly  p = z2+1;
2154   poly  q = z4+2;
2155   ideal i = p^2*q^3,(y-z3)^3,(x-yz+z4)^4;
2156   list pr= minAssPrimes(i);  pr;
2157
2158   minAssPrimes(i,1);
2159}
2160
[07c623]2161static proc union(list li)
[d6db1f2]2162{
2163  int i,j,k;
[67bd4c]2164
2165  def P=basering;
2166
[2d2cad9]2167  execute("ring ir = ("+charstr(basering)+"),("+varstr(basering)+"),(C,lp);");
[67bd4c]2168  list l=fetch(P,li);
[d6db1f2]2169  list @erg;
2170
2171  for(k=1;k<=size(l);k++)
2172  {
[67bd4c]2173     for(j=1;j<=size(l[k])/2;j++)
[d6db1f2]2174     {
2175        if(deg(l[k][2*j][1])!=0)
2176        {
2177           i++;
2178           @erg[i]=l[k][2*j];
2179        }
2180     }
2181  }
2182
2183  list @wos;
2184  i=0;
2185  ideal i1,i2;
2186  while(i<size(@erg)-1)
2187  {
2188     i++;
2189     k=i+1;
2190     i1=lead(@erg[i]);
2191      attrib(i1,"isSB",1);
2192      attrib(@erg[i],"isSB",1);
2193
2194     while(k<=size(@erg))
2195     {
2196        if(deg(@erg[i][1])==0)
2197        {
2198           break;
2199        }
2200        i2=lead(@erg[k]);
2201        attrib(@erg[k],"isSB",1);
2202        attrib(i2,"isSB",1);
2203
2204        if(size(reduce(i1,i2,1))==0)
2205        {
[e801fe]2206           if(size(reduce(@erg[i],@erg[k],1))==0)
[d6db1f2]2207           {
2208              @erg[k]=ideal(1);
[18dd47]2209              i2=ideal(1);
2210           }
[d6db1f2]2211        }
2212        if(size(reduce(i2,i1,1))==0)
2213        {
[e801fe]2214           if(size(reduce(@erg[k],@erg[i],1))==0)
[d6db1f2]2215           {
2216              break;
[18dd47]2217           }
[d6db1f2]2218        }
2219        k++;
2220        if(k>size(@erg))
2221        {
2222           @wos[size(@wos)+1]=@erg[i];
2223        }
2224     }
2225  }
2226  if(deg(@erg[size(@erg)][1])!=0)
2227  {
2228     @wos[size(@wos)+1]=@erg[size(@erg)];
2229  }
[67bd4c]2230  setring P;
2231  list @ser=fetch(ir,@wos);
2232  return(@ser);
[d6db1f2]2233}
2234///////////////////////////////////////////////////////////////////////////////
[d8d3af]2235proc equidim(ideal i,list #)
[b9b906]2236"USAGE:  equidim(i) or equidim(i,1) ; i ideal
[7b3971]2237RETURN: list of equidimensional ideals a[1],...,a[s] with:
[25c431]2238        - a[s] the equidimensional locus of i, i.e. the intersection
2239          of the primary ideals of dimension of i
[367e88]2240        - a[1],...,a[s-1] the lower dimensional equidimensional loci.
2241NOTE:    An embedded component q (primary ideal) of i can be replaced in the
[7b3971]2242         decomposition by a primary ideal q1 with the same radical as q. @*
2243         @code{equidim(i,1)} uses the algorithm of Eisenbud/Huneke/Vasconcelos.
2244
[07c623]2245EXAMPLE:example equidim; shows an example
[ba94539]2246"
2247{
[07c623]2248  if(ord_test(basering)!=1)
2249  {
2250      ERROR(
2251      "// Not implemented for this ordering, please change to global ordering."
2252      );
2253  }
[b9b906]2254  intvec op ;
[ba94539]2255  def  P = basering;
2256  list eq;
2257  intvec w;
[4d68980]2258  int n,m;
[6d6ed5b]2259  int g=size(i);
[ba94539]2260  int a=attrib(i,"isSB");
2261  int homo=homog(i);
[d8d3af]2262  if(size(#)!=0)
2263  {
[4d68980]2264     m=1;
2265  }
2266
[ba94539]2267  if(((homo==1)||(a==1))&&(find(ordstr(basering),"l")==0)
2268                                &&(find(ordstr(basering),"s")==0))
2269  {
[2d2cad9]2270     execute("ring gnir = ("+charstr(basering)+"),("+varstr(basering)+"),("
2271                              +ordstr(basering)+");");
[ba94539]2272     ideal i=imap(P,i);
2273     ideal j=i;
2274     if(a==1)
2275     {
[b9b906]2276       attrib(j,"isSB",1);
[ba94539]2277     }
2278     else
2279     {
2280       j=groebner(i);
2281     }
2282  }
2283  else
2284  {
[2d2cad9]2285     execute("ring gnir = ("+charstr(basering)+"),("+varstr(basering)+"),dp;");
[ba94539]2286     ideal i=imap(P,i);
2287     ideal j=groebner(i);
[b9b906]2288  }
[ba94539]2289  if(homo==1)
2290  {
2291     for(n=1;n<=nvars(basering);n++)
2292     {
2293        w[n]=ord(var(n));
2294     }
2295     intvec hil=hilb(j,1,w);
2296  }
[4d68980]2297
[6d6ed5b]2298  if ((dim(j)==-1)||(size(j)==0)||(nvars(basering)==1)
2299                  ||(dim(j)==0)||(dim(j)+g==nvars(basering)))
[ba94539]2300  {
2301    setring P;
[6d6ed5b]2302    eq[1]=i;
[ba94539]2303    return(eq);
2304  }
2305
[4d68980]2306  if(m==0)
[ba94539]2307  {
[b9b906]2308     ideal k=equidimMax(j);
[ba94539]2309  }
2310  else
2311  {
[b9b906]2312     ideal k=equidimMaxEHV(j);
[ba94539]2313  }
[6d6ed5b]2314  if(size(reduce(k,j,1))==0)
2315  {
2316    setring P;
2317    eq[1]=i;
2318    kill gnir;
2319    return(eq);
2320  }
[466f80]2321  op=option(get);
[b9b906]2322  option(returnSB);
[651953]2323  j=quotient(j,k);
[02335e]2324  option(set,op);
[d8d3af]2325
[b9b906]2326  list equi=equidim(j);
[4d68980]2327  if(deg(equi[size(equi)][1])<=0)
[a9cf54]2328  {
[4d68980]2329      equi[size(equi)]=k;
[a9cf54]2330  }
2331  else
2332  {
[4d68980]2333    equi[size(equi)+1]=k;
[a9cf54]2334  }
[ba94539]2335  setring P;
[4d68980]2336  eq=imap(gnir,equi);
[ba94539]2337  kill gnir;
2338  return(eq);
2339}
2340example
2341{ "EXAMPLE:"; echo = 2;
2342   ring  r = 32003,(x,y,z),dp;
[7b3971]2343   ideal i = intersect(ideal(z),ideal(x,y),ideal(x2,z2),ideal(x5,y5,z5));
[ba94539]2344   equidim(i);
2345}
[6d6ed5b]2346
[03f29c]2347///////////////////////////////////////////////////////////////////////////////
2348proc equidimMax(ideal i)
[b9b906]2349"USAGE:  equidimMax(i); i ideal
[07c623]2350RETURN:  ideal of equidimensional locus (of maximal dimension) of i.
2351EXAMPLE: example equidimMax; shows an example
[03f29c]2352"
2353{
[07c623]2354  if(ord_test(basering)!=1)
2355  {
2356      ERROR(
2357      "// Not implemented for this ordering, please change to global ordering."
2358      );
2359  }
[03f29c]2360  def  P = basering;
2361  ideal eq;
2362  intvec w;
2363  int n;
[6d6ed5b]2364  int g=size(i);
[03f29c]2365  int a=attrib(i,"isSB");
2366  int homo=homog(i);
[b9b906]2367
[03f29c]2368  if(((homo==1)||(a==1))&&(find(ordstr(basering),"l")==0)
2369                                &&(find(ordstr(basering),"s")==0))
2370  {
[2d2cad9]2371     execute("ring gnir = ("+charstr(basering)+"),("+varstr(basering)+"),("
2372                              +ordstr(basering)+");");
[03f29c]2373     ideal i=imap(P,i);
2374     ideal j=i;
2375     if(a==1)
2376     {
[b9b906]2377       attrib(j,"isSB",1);
[03f29c]2378     }
2379     else
2380     {
2381       j=groebner(i);
2382     }
2383  }
2384  else
2385  {
[2d2cad9]2386     execute("ring gnir = ("+charstr(basering)+"),("+varstr(basering)+"),dp;");
[03f29c]2387     ideal i=imap(P,i);
2388     ideal j=groebner(i);
2389  }
2390  list indep;
2391  ideal equ,equi;
2392  if(homo==1)
2393  {
2394     for(n=1;n<=nvars(basering);n++)
2395     {
2396        w[n]=ord(var(n));
2397     }
2398     intvec hil=hilb(j,1,w);
2399  }
[6d6ed5b]2400  if ((dim(j)==-1)||(size(j)==0)||(nvars(basering)==1)
2401                  ||(dim(j)==0)||(dim(j)+g==nvars(basering)))
[03f29c]2402  {
2403    setring P;
[a9cf54]2404    return(i);
[03f29c]2405  }
2406
2407  indep=maxIndependSet(j);
[a9cf54]2408
[2d2cad9]2409  execute("ring gnir1 = ("+charstr(basering)+"),("+indep[1][1]+"),("
2410                              +indep[1][2]+");");
[03f29c]2411  if(homo==1)
2412  {
[b1d1e8c]2413     ideal j=std(imap(gnir,j),hil,w);
[03f29c]2414  }
2415  else
2416  {
[b1d1e8c]2417     ideal j=groebner(imap(gnir,j));
[03f29c]2418  }
2419  string quotring=prepareQuotientring(nvars(basering)-indep[1][3]);
[2d2cad9]2420  execute(quotring);
[03f29c]2421  ideal j=imap(gnir1,j);
2422  kill gnir1;
2423  j=clearSB(j);
2424  ideal h;
2425  for(n=1;n<=size(j);n++)
2426  {
2427     h[n]=leadcoef(j[n]);
2428  }
2429  setring gnir;
2430  ideal h=imap(quring,h);
2431  kill quring;
[6d6ed5b]2432
[03f29c]2433  list l=minSat(j,h);
[b9b906]2434
[b1d1e8c]2435  if(deg(l[2])>0)
2436  {
2437    equ=l[1];
2438    attrib(equ,"isSB",1);
2439    j=std(j,l[2]);
[6d6ed5b]2440
[b1d1e8c]2441    if(dim(equ)==dim(j))
2442    {
2443      equi=equidimMax(j);
2444      equ=interred(intersect(equ,equi));
2445    }
2446  }
2447  else
[03f29c]2448  {
[b1d1e8c]2449    equ=i;
[03f29c]2450  }
[b1d1e8c]2451
[03f29c]2452  setring P;
2453  eq=imap(gnir,equ);
2454  kill gnir;
2455  return(eq);
2456}
2457example
2458{ "EXAMPLE:"; echo = 2;
2459   ring  r = 32003,(x,y,z),dp;
[7b3971]2460   ideal i = intersect(ideal(z),ideal(x,y),ideal(x2,z2),ideal(x5,y5,z5));
[03f29c]2461   equidimMax(i);
2462}
[24f458]2463///////////////////////////////////////////////////////////////////////////////
2464static proc islp()
2465{
2466   string s=ordstr(basering);
2467   int n=find(s,"lp");
2468   if(!n){return(0);}
2469   int k=find(s,",");
2470   string t=s[k+1..size(s)];
2471   int l=find(t,",");
2472   t=s[1..k-1];
2473   int m=find(t,",");
2474   if(l+m){return(0);}
2475   return(1);
2476}
2477///////////////////////////////////////////////////////////////////////////////
2478
2479proc algeDeco(ideal i, int w)
2480{
2481//reduces primery decomposition over algebraic extensions to
2482//the other cases
2483   def R=basering;
2484   int n=nvars(R);
[fc5095]2485
2486//---Anfang Provisorium
[17407e]2487   if((size(i)==2) && (w==2))
[fc5095]2488   {
2489      option(redSB);
2490      ideal J=std(i);
2491      option(noredSB);
2492      if((size(J)==2)&&(deg(J[1])==1))
2493      {
2494         ideal keep;
2495         poly f;
2496         int j;
2497         for(j=1;j<=nvars(basering);j++)
2498         {
2499           f=J[2];
2500           while((f/var(j))*var(j)-f==0)
2501           {
2502             f=f/var(j);
2503             keep=keep,var(j);
2504           }
2505           J[2]=f;
2506         }
2507         ideal K=factorize(J[2],1);
2508         if(deg(K[1])==0){K=0;}
2509         K=K+std(keep);
2510         ideal L;
2511         list resu;
2512         for(j=1;j<=size(K);j++)
2513         {
2514            L=J[1],K[j];
2515            resu[j]=L;
2516         }
2517         return(resu);
2518      }
2519   }
2520//---Ende Provisorium
[24f458]2521   string mp="poly p="+string(minpoly)+";";
2522   string gnir="ring RH="+string(char(R))+",("+varstr(R)+","+string(par(1))
2523                +"),dp;";
2524   execute(gnir);
2525   execute(mp);
2526   ideal i=imap(R,i);
[fc5095]2527   ideal I=subst(i,var(nvars(basering)),0);
[24f458]2528   int j;
[fc5095]2529   for(j=1;j<=ncols(i);j++)
2530   {
2531     if(i[j]!=I[j]){break;}
2532   }
[3c4dcc]2533   if((j>ncols(i))&&(deg(p)==1))
[fc5095]2534   {
2535     setring R;
2536     kill RH;
2537     kill gnir;
2538     string gnir="ring RH="+string(char(R))+",("+varstr(R)+"),dp;";
2539     execute(gnir);
2540     ideal i=imap(R,i);
2541     ideal J;
2542   }
2543   else
2544   {
2545      i=i,p;
2546   }
2547   list pr;
[24f458]2548
2549   if(w==0)
2550   {
2551      pr=decomp(i);
2552   }
2553   if(w==1)
2554   {
2555      pr=prim_dec(i,1);
2556      pr=reconvList(pr);
2557   }
2558   if(w==2)
2559   {
2560      pr=minAssPrimes(i);
[3c4dcc]2561   }
2562   if(n<nvars(basering))
2563   {
[fc5095]2564      gnir="ring RS="+string(char(R))+",("+varstr(RH)
[24f458]2565                +"),(dp("+string(n)+"),lp);";
[fc5095]2566      execute(gnir);
2567      list pr=imap(RH,pr);
2568      ideal K;
2569      for(j=1;j<=size(pr);j++)
2570      {
2571         K=groebner(pr[j]);
2572         K=K[2..size(K)];
2573         pr[j]=K;
2574      }
2575      setring R;
2576      list pr=imap(RS,pr);
2577   }
2578   else
[24f458]2579   {
[fc5095]2580      setring R;
2581      list pr=imap(RH,pr);
[24f458]2582   }
[fc5095]2583   list re;
[24f458]2584   if(w==2)
2585   {
2586      re=pr;
2587   }
2588   else
2589   {
2590      re=convList(pr);
2591   }
2592   return(re);
2593}
[e801fe]2594
[67bd4c]2595///////////////////////////////////////////////////////////////////////////////
[07c623]2596static proc decomp(ideal i,list #)
[7a7df90]2597"USAGE:  decomp(i); i ideal  (for primary decomposition)   (resp.
2598         decomp(i,1);        (for the associated primes of dimension of i) )
2599         decomp(i,2);        (for the minimal associated primes) )
[6fa3af]2600         decomp(i,3);        (for the absolute primary decomposition) )
[d6db1f2]2601RETURN:  list = list of primary ideals and their associated primes
2602         (at even positions in the list)
2603         (resp. a list of the minimal associated primes)
[7b3971]2604NOTE:    Algorithm of Gianni/Trager/Zacharias
[d6db1f2]2605EXAMPLE: example decomp; shows an example
[d2b2a7]2606"
[d6db1f2]2607{
[466f80]2608  intvec op;
[d6db1f2]2609  def  @P = basering;
[67bd4c]2610  list primary,indep,ltras;
[d36f7f]2611  intvec @vh,isat,@w;
[6fa3af]2612  int @wr,@k,@n,@m,@n1,@n2,@n3,homo,seri,keepdi,abspri,ab,nn;
[d6db1f2]2613  ideal peek=i;
2614  ideal ser,tras;
[24f458]2615  int isS=(attrib(i,"isSB")==1);
[18dd47]2616
[6fa3af]2617
[d6db1f2]2618  if(size(#)>0)
2619  {
[6fa3af]2620     if((#[1]==1)||(#[1]==2)||(#[1]==3))
[d6db1f2]2621     {
2622        @wr=#[1];
[6fa3af]2623        if(@wr==3){abspri=1;@wr=0;}
[d6db1f2]2624        if(size(#)>1)
2625        {
[e801fe]2626          seri=1;
[d6db1f2]2627          peek=#[2];
2628          ser=#[3];
2629        }
2630      }
2631      else
2632      {
[e801fe]2633        seri=1;
2634        peek=#[1];
2635        ser=#[2];
[d6db1f2]2636      }
2637  }
[6fa3af]2638  if(abspri)
2639  {
2640     list absprimary,abskeep,absprimarytmp,abskeeptmp;
2641  }
[e801fe]2642  homo=homog(i);
[d6db1f2]2643  if(homo==1)
2644  {
[e801fe]2645    if(attrib(i,"isSB")!=1)
2646    {
[17407e]2647      //ltras=mstd(i);
2648      tras=groebner(i);
2649      ltras=tras,tras;
[e801fe]2650      attrib(ltras[1],"isSB",1);
2651    }
2652    else
2653    {
2654      ltras=i,i;
[24f458]2655      attrib(ltras[1],"isSB",1);
[e801fe]2656    }
2657    tras=ltras[1];
[24f458]2658    attrib(tras,"isSB",1);
[e801fe]2659    if(dim(tras)==0)
2660    {
[67bd4c]2661        primary[1]=ltras[2];
[d6db1f2]2662        primary[2]=maxideal(1);
2663        if(@wr>0)
2664        {
2665           list l;
2666           l[1]=maxideal(1);
2667           l[2]=maxideal(1);
2668           return(l);
2669        }
2670        return(primary);
2671     }
[d36f7f]2672     for(@n=1;@n<=nvars(basering);@n++)
[2d2c8be]2673     {
[d36f7f]2674        @w[@n]=ord(var(@n));
[2d2c8be]2675     }
2676     intvec @hilb=hilb(tras,1,@w);
[e801fe]2677     intvec keephilb=@hilb;
[d6db1f2]2678  }
[18dd47]2679
[d6db1f2]2680  //----------------------------------------------------------------
2681  //i is the zero-ideal
2682  //----------------------------------------------------------------
[18dd47]2683
[d6db1f2]2684  if(size(i)==0)
2685  {
2686     primary=i,i;
2687     return(primary);
2688  }
[18dd47]2689
[d6db1f2]2690  //----------------------------------------------------------------
2691  //pass to the lexicographical ordering and compute a standardbasis
2692  //----------------------------------------------------------------
2693
[24f458]2694  int lp=islp();
2695
[2d2cad9]2696  execute("ring gnir = ("+charstr(basering)+"),("+varstr(basering)+"),(C,lp);");
[466f80]2697  op=option(get);
[d6db1f2]2698  option(redSB);
[e801fe]2699
[3939bc]2700  ideal ser=fetch(@P,ser);
[18dd47]2701
[d6db1f2]2702  if(homo==1)
2703  {
[24f458]2704     if(!lp)
[d6db1f2]2705     {
[2d2c8be]2706       ideal @j=std(fetch(@P,i),@hilb,@w);
[d6db1f2]2707     }
2708     else
2709     {
2710        ideal @j=fetch(@P,tras);
2711        attrib(@j,"isSB",1);
2712     }
2713  }
2714  else
2715  {
[24f458]2716      if(lp&&isS)
2717      {
2718        ideal @j=fetch(@P,i);
2719        attrib(@j,"isSB",1);
2720      }
2721      else
2722      {
2723        ideal @j=groebner(fetch(@P,i));
2724      }
[d6db1f2]2725  }
[02335e]2726  option(set,op);
[e801fe]2727  if(seri==1)
2728  {
2729    ideal peek=fetch(@P,peek);
2730    attrib(peek,"isSB",1);
2731  }
2732  else
2733  {
2734    ideal peek=@j;
2735  }
[6fa3af]2736  if((size(ser)==0)&&(!abspri))
[e801fe]2737  {
2738    ideal fried;
2739    @n=size(@j);
2740    for(@k=1;@k<=@n;@k++)
2741    {
2742      if(deg(lead(@j[@k]))==1)
2743      {
2744        fried[size(fried)+1]=@j[@k];
2745        @j[@k]=0;
2746      }
2747    }
[5674d5]2748    if(size(fried)==nvars(basering))
2749    {
2750       setring @P;
2751       primary[1]=i;
2752       primary[2]=i;
2753       return(primary);
2754    }
[e801fe]2755    if(size(fried)>0)
2756    {
[948bcd]2757       string newva;
[b9b906]2758       string newma;
[948bcd]2759       for(@k=1;@k<=nvars(basering);@k++)
2760       {
2761          @n1=0;
2762          for(@n=1;@n<=size(fried);@n++)
2763          {
[0bcebab]2764             if(leadmonom(fried[@n])==var(@k))
[948bcd]2765             {
2766                @n1=1;
2767                break;
2768             }
[b9b906]2769          }
[948bcd]2770          if(@n1==0)
2771          {
2772            newva=newva+string(var(@k))+",";
2773            newma=newma+string(var(@k))+",";
2774          }
2775          else
2776          {
[b9b906]2777            newma=newma+string(0)+",";
2778          }
[948bcd]2779       }
2780       newva[size(newva)]=")";
2781       newma[size(newma)]=";";
2782       execute("ring @deirf=("+charstr(gnir)+"),("+newva+",lp;");
2783       execute("map @kappa=gnir,"+newma);
2784       ideal @j= @kappa(@j);
[e801fe]2785       @j=simplify(@j,2);
2786       attrib(@j,"isSB",1);
2787       list pr=decomp(@j);
[948bcd]2788       setring gnir;
[1e014d]2789       list pr=imap(@deirf,pr);
[e801fe]2790       for(@k=1;@k<=size(pr);@k++)
2791       {
2792         @j=pr[@k]+fried;
2793         pr[@k]=@j;
2794       }
2795       setring @P;
[1e014d]2796       return(imap(gnir,pr));
[e801fe]2797    }
2798  }
[d6db1f2]2799  //----------------------------------------------------------------
2800  //j is the ring
2801  //----------------------------------------------------------------
2802
2803  if (dim(@j)==-1)
2804  {
[e801fe]2805    setring @P;
[651953]2806    primary=ideal(1),ideal(1);
2807    return(primary);
[d6db1f2]2808  }
[18dd47]2809
[d6db1f2]2810  //----------------------------------------------------------------
2811  //  the case of one variable
2812  //----------------------------------------------------------------
2813
2814  if(nvars(basering)==1)
2815  {
[67bd4c]2816
[d6db1f2]2817     list fac=factor(@j[1]);
2818     list gprimary;
2819     for(@k=1;@k<=size(fac[1]);@k++)
2820     {
2821        if(@wr==0)
2822        {
2823           gprimary[2*@k-1]=ideal(fac[1][@k]^fac[2][@k]);
2824           gprimary[2*@k]=ideal(fac[1][@k]);
2825        }
2826        else
2827        {
2828           gprimary[2*@k-1]=ideal(fac[1][@k]);
2829           gprimary[2*@k]=ideal(fac[1][@k]);
2830        }
2831     }
2832     setring @P;
2833     primary=fetch(gnir,gprimary);
2834
[6fa3af]2835//HIER
2836    if(abspri)
2837    {
2838       list resu,tempo;
2839       string absotto;
2840       for(ab=1;ab<=size(primary)/2;ab++)
2841       {
2842          absotto= absFactorize(primary[2*ab][1],77);
2843          tempo=primary[2*ab-1],primary[2*ab],absotto,string(var(nvars(basering)));
2844          resu[ab]=tempo;
2845       }
2846       primary=resu;
2847     }
[d6db1f2]2848     return(primary);
2849  }
[3939bc]2850
[d6db1f2]2851 //------------------------------------------------------------------
2852 //the zero-dimensional case
2853 //------------------------------------------------------------------
2854  if (dim(@j)==0)
2855  {
[466f80]2856    op=option(get);
[e801fe]2857    option(redSB);
2858    list gprimary= zero_decomp(@j,ser,@wr);
[6fa3af]2859
[e801fe]2860    setring @P;
2861    primary=fetch(gnir,gprimary);
[6fa3af]2862
[e801fe]2863    if(size(ser)>0)
2864    {
2865      primary=cleanPrimary(primary);
2866    }
[6fa3af]2867//HIER
2868    if(abspri)
2869    {
2870       list resu,tempo;
2871       string absotto;
2872       for(ab=1;ab<=size(primary)/2;ab++)
2873       {
2874          absotto= absFactorize(primary[2*ab][1],77);
2875          tempo=primary[2*ab-1],primary[2*ab],absotto,string(var(nvars(basering)));
2876          resu[ab]=tempo;
2877       }
2878       primary=resu;
2879    }
[e801fe]2880    return(primary);
2881  }
[d6db1f2]2882
2883  poly @gs,@gh,@p;
2884  string @va,quotring;
2885  list quprimary,htprimary,collectprimary,lsau,lnew,allindep,restindep;
2886  ideal @h;
2887  int jdim=dim(@j);
2888  list fett;
[e801fe]2889  int lauf,di,newtest;
[67bd4c]2890  //------------------------------------------------------------------
2891  //search for a maximal independent set indep,i.e.
2892  //look for subring such that the intersection with the ideal is zero
2893  //j intersected with K[var(indep[3]+1),...,var(nvar] is zero,
[9050ca]2894  //indep[1] is the new varstring and indep[2] the string for block-ordering
[67bd4c]2895  //------------------------------------------------------------------
[d6db1f2]2896  if(@wr!=1)
2897  {
2898     allindep=independSet(@j);
2899     for(@m=1;@m<=size(allindep);@m++)
2900     {
2901        if(allindep[@m][3]==jdim)
2902        {
2903           di++;
2904           indep[di]=allindep[@m];
2905        }
2906        else
2907        {
2908           lauf++;
2909           restindep[lauf]=allindep[@m];
2910        }
2911     }
2912   }
2913   else
2914   {
2915      indep=maxIndependSet(@j);
2916   }
[3939bc]2917
[d6db1f2]2918  ideal jkeep=@j;
2919  if(ordstr(@P)[1]=="w")
2920  {
[2d2cad9]2921     execute("ring @Phelp=("+charstr(gnir)+"),("+varstr(gnir)+"),("+ordstr(@P)+");");
[d6db1f2]2922  }
2923  else
2924  {
[b1d1e8c]2925     execute( "ring @Phelp=("+charstr(gnir)+"),("+varstr(gnir)+"),(C,dp);");
[e801fe]2926  }
2927
2928  if(homo==1)
2929  {
2930    if((ordstr(@P)[3]=="d")||(ordstr(@P)[1]=="d")||(ordstr(@P)[1]=="w")
2931       ||(ordstr(@P)[3]=="w"))
2932    {
2933      ideal jwork=imap(@P,tras);
2934      attrib(jwork,"isSB",1);
2935    }
2936    else
2937    {
[2d2c8be]2938      ideal jwork=std(imap(gnir,@j),@hilb,@w);
[e801fe]2939    }
[3939bc]2940
[e801fe]2941  }
2942  else
2943  {
[9a384e]2944    ideal jwork=groebner(imap(gnir,@j));
[d6db1f2]2945  }
[e801fe]2946  list hquprimary;
[d6db1f2]2947  poly @p,@q;
[e801fe]2948  ideal @h,fac,ser;
[d6db1f2]2949  di=dim(jwork);
[e801fe]2950  keepdi=di;
[3939bc]2951
[d6db1f2]2952  setring gnir;
2953  for(@m=1;@m<=size(indep);@m++)
2954  {
2955     isat=0;
2956     @n2=0;
2957     if((indep[@m][1]==varstr(basering))&&(@m==1))
2958     //this is the good case, nothing to do, just to have the same notations
2959     //change the ring
2960     {
[2d2cad9]2961        execute("ring gnir1 = ("+charstr(basering)+"),("+varstr(basering)+"),("
2962                              +ordstr(basering)+");");
[d6db1f2]2963        ideal @j=fetch(gnir,@j);
2964        attrib(@j,"isSB",1);
[e801fe]2965        ideal ser=fetch(gnir,ser);
[3939bc]2966
[d6db1f2]2967     }
2968     else
2969     {
2970        @va=string(maxideal(1));
[2d2cad9]2971        execute("ring gnir1 = ("+charstr(basering)+"),("+indep[@m][1]+"),("
2972                              +indep[@m][2]+");");
2973        execute("map phi=gnir,"+@va+";");
[466f80]2974        op=option(get);
2975        option(redSB);
[d6db1f2]2976        if(homo==1)
2977        {
[2d2c8be]2978           ideal @j=std(phi(@j),@hilb,@w);
[d6db1f2]2979        }
2980        else
2981        {
[9a384e]2982          ideal @j=groebner(phi(@j));
[d6db1f2]2983        }
[e801fe]2984        ideal ser=phi(ser);
[3939bc]2985
[466f80]2986        option(set,op);
[e801fe]2987     }
[d6db1f2]2988     if((deg(@j[1])==0)||(dim(@j)<jdim))
2989     {
2990       setring gnir;
2991       break;
2992     }
2993     for (lauf=1;lauf<=size(@j);lauf++)
2994     {
2995         fett[lauf]=size(@j[lauf]);
2996     }
[091424]2997     //------------------------------------------------------------------------
[d6db1f2]2998     //we have now the following situation:
2999     //j intersected with K[var(nnp+1),..,var(nva)] is zero so we may pass
3000     //to this quotientring, j is their still a standardbasis, the
3001     //leading coefficients of the polynomials  there (polynomials in
3002     //K[var(nnp+1),..,var(nva)]) are collected in the list h,
[9050ca]3003     //we need their ggt, gh, because of the following: let
3004     //(j:gh^n)=(j:gh^infinity) then j*K(var(nnp+1),..,var(nva))[..the rest..]
[d6db1f2]3005     //intersected with K[var(1),...,var(nva)] is (j:gh^n)
3006     //on the other hand j=(j,gh^n) intersected with (j:gh^n)
[18dd47]3007
[091424]3008     //------------------------------------------------------------------------
[d6db1f2]3009
[9050ca]3010     //arrangement for quotientring K(var(nnp+1),..,var(nva))[..the rest..] and
[091424]3011     //map phi:K[var(1),...,var(nva)] --->K(var(nnpr+1),..,var(nva))[..rest..]
3012     //------------------------------------------------------------------------
[d6db1f2]3013
[18dd47]3014     quotring=prepareQuotientring(nvars(basering)-indep[@m][3]);
[d6db1f2]3015
3016     //---------------------------------------------------------------------
3017     //we pass to the quotientring   K(var(nnp+1),..,var(nva))[..the rest..]
3018     //---------------------------------------------------------------------
3019
[f54c83]3020     ideal @jj=lead(@j);               //!! vorn vereinbaren
[2d2cad9]3021     execute(quotring);
[f54c83]3022   
3023     ideal @jj=imap(gnir1,@jj);
3024     intvec @vv=clearSBNeu(@jj,fett);  //!! vorn vereinbaren
3025     setring gnir1;
3026     @k=size(@j);
3027     for (lauf=1;lauf<=@k;lauf++)
3028     {
3029         if(@vv[lauf]==1)
3030         {
3031            @j[lauf]=0;
3032         }
3033     }
3034     @j=simplify(@j,2);
3035     setring quring;
3036      // @j considered in the quotientring
[d6db1f2]3037     ideal @j=imap(gnir1,@j);
[f54c83]3038
[e801fe]3039     ideal ser=imap(gnir1,ser);
[d6db1f2]3040
3041     kill gnir1;
[18dd47]3042
[d6db1f2]3043     //j is a standardbasis in the quotientring but usually not minimal
3044     //here it becomes minimal
3045
3046     attrib(@j,"isSB",1);
3047
3048     //we need later ggt(h[1],...)=gh for saturation
3049     ideal @h;
3050     if(deg(@j[1])>0)
3051     {
3052        for(@n=1;@n<=size(@j);@n++)
3053        {
3054           @h[@n]=leadcoef(@j[@n]);
3055        }
3056        //the primary decomposition of j*K(var(nnp+1),..,var(nva))[..the rest..]
[466f80]3057        op=option(get);
[3939bc]3058        option(redSB);
[7a7df90]3059
[d6db1f2]3060        list uprimary= zero_decomp(@j,ser,@wr);
[6fa3af]3061//HIER
3062        if(abspri)
3063        {
3064           ideal II;
3065           ideal jmap;
3066           map sigma;
3067           nn=nvars(basering);
3068           map invsigma=basering,maxideal(1);
3069           for(ab=1;ab<=size(uprimary)/2;ab++)
3070           {
3071              II=uprimary[2*ab];
3072              attrib(II,"isSB",1);
3073              if(deg(II[1])!=vdim(II))
3074              {
3075                 jmap=randomLast(50);
3076                 sigma=basering,jmap;
3077                 jmap[nn]=2*var(nn)-jmap[nn];
3078                 invsigma=basering,jmap;
3079                 II=groebner(sigma(II));
3080               }
3081               absprimarytmp[ab]= absFactorize(II[1],77);
3082               II=var(nn);
3083               abskeeptmp[ab]=string(invsigma(II));
3084               invsigma=basering,maxideal(1);
3085           }
3086        }
[02335e]3087        option(set,op);
[d6db1f2]3088     }
3089     else
3090     {
3091       list uprimary;
[c2b529]3092       uprimary[1]=ideal(1);
[e801fe]3093       uprimary[2]=ideal(1);
[d6db1f2]3094     }
3095     //we need the intersection of the ideals in the list quprimary with the
3096     //polynomialring, i.e. let q=(f1,...,fr) in the quotientring such an ideal
3097     //but fi polynomials, then the intersection of q with the polynomialring
3098     //is the saturation of the ideal generated by f1,...,fr with respect to
[091424]3099     //h which is the lcm of the leading coefficients of the fi considered in
[9050ca]3100     //in the quotientring: this is coded in saturn
[d6db1f2]3101
3102     list saturn;
3103     ideal hpl;
[18dd47]3104
[d6db1f2]3105     for(@n=1;@n<=size(uprimary);@n++)
3106     {
[971ba6f]3107        uprimary[@n]=interred(uprimary[@n]); // temporary fix
[d6db1f2]3108        hpl=0;
3109        for(@n1=1;@n1<=size(uprimary[@n]);@n1++)
[18dd47]3110        {
[d6db1f2]3111           hpl=hpl,leadcoef(uprimary[@n][@n1]);
3112        }
3113        saturn[@n]=hpl;
3114     }
[971ba6f]3115
[d6db1f2]3116     //--------------------------------------------------------------------
3117     //we leave  the quotientring   K(var(nnp+1),..,var(nva))[..the rest..]
3118     //back to the polynomialring
3119     //---------------------------------------------------------------------
3120     setring gnir;
[18dd47]3121
[d6db1f2]3122     collectprimary=imap(quring,uprimary);
3123     lsau=imap(quring,saturn);
[18dd47]3124     @h=imap(quring,@h);
[d6db1f2]3125
3126     kill quring;
3127
3128     @n2=size(quprimary);
3129     @n3=@n2;
[18dd47]3130
[67bd4c]3131     for(@n1=1;@n1<=size(collectprimary)/2;@n1++)
[d6db1f2]3132     {
3133        if(deg(collectprimary[2*@n1][1])>0)
3134        {
3135           @n2++;
3136           quprimary[@n2]=collectprimary[2*@n1-1];
3137           lnew[@n2]=lsau[2*@n1-1];
3138           @n2++;
3139           lnew[@n2]=lsau[2*@n1];
3140           quprimary[@n2]=collectprimary[2*@n1];
[6fa3af]3141           if(abspri)
3142           {
3143              absprimary[@n2/2]=absprimarytmp[@n1];
3144              abskeep[@n2/2]=abskeeptmp[@n1];
3145           }
[d6db1f2]3146        }
[18dd47]3147     }
3148     //here the intersection with the polynomialring
[d6db1f2]3149     //mentioned above is really computed
[e801fe]3150     for(@n=@n3/2+1;@n<=@n2/2;@n++)
[3939bc]3151     {
[d6db1f2]3152        if(specialIdealsEqual(quprimary[2*@n-1],quprimary[2*@n]))
3153        {
3154           quprimary[2*@n-1]=sat2(quprimary[2*@n-1],lnew[2*@n-1])[1];
3155           quprimary[2*@n]=quprimary[2*@n-1];
3156        }
3157        else
3158        {
3159           if(@wr==0)
3160           {
3161              quprimary[2*@n-1]=sat2(quprimary[2*@n-1],lnew[2*@n-1])[1];
3162           }
3163           quprimary[2*@n]=sat2(quprimary[2*@n],lnew[2*@n])[1];
3164        }
3165     }
[3939bc]3166
[d6db1f2]3167     if(size(@h)>0)
3168     {
3169           //---------------------------------------------------------------
3170           //we change to @Phelp to have the ordering dp for saturation
3171           //---------------------------------------------------------------
3172        setring @Phelp;
3173        @h=imap(gnir,@h);
3174        if(@wr!=1)
3175        {
[3939bc]3176          @q=minSat(jwork,@h)[2];
[d6db1f2]3177        }
3178        else
3179        {
3180            fac=ideal(0);
3181            for(lauf=1;lauf<=ncols(@h);lauf++)
3182           {
3183              if(deg(@h[lauf])>0)
3184              {
[18dd47]3185                 fac=fac+factorize(@h[lauf],1);
[d6db1f2]3186              }
3187           }
3188           fac=simplify(fac,4);
3189           @q=1;
3190           for(lauf=1;lauf<=size(fac);lauf++)
3191           {
3192             @q=@q*fac[lauf];
3193           }
3194        }
[1c48057]3195        jwork=std(jwork,@q);
[3939bc]3196        keepdi=dim(jwork);
[e801fe]3197        if(keepdi<di)
[d6db1f2]3198        {
3199           setring gnir;
3200           @j=imap(@Phelp,jwork);
3201           break;
3202        }
3203        if(homo==1)
3204        {
[2d2c8be]3205              @hilb=hilb(jwork,1,@w);
[d6db1f2]3206        }
[18dd47]3207
[d6db1f2]3208        setring gnir;
3209        @j=imap(@Phelp,jwork);
[18dd47]3210     }
[d6db1f2]3211  }
[7a7df90]3212
3213  if((size(quprimary)==0)&&(@wr==1))
[d6db1f2]3214  {
3215     @j=ideal(1);
[c2b529]3216     quprimary[1]=ideal(1);
[e801fe]3217     quprimary[2]=ideal(1);
[d6db1f2]3218  }
[e801fe]3219  if((size(quprimary)==0))
3220  {
3221    keepdi=di-1;
[17407e]3222    quprimary[1]=ideal(1);
3223    quprimary[2]=ideal(1);
[3939bc]3224  }
[d6db1f2]3225  //---------------------------------------------------------------
3226  //notice that j=sat(j,gh) intersected with (j,gh^n)
3227  //we finished with sat(j,gh) and have to start with (j,gh^n)
3228  //---------------------------------------------------------------
3229  if((deg(@j[1])!=0)&&(@wr!=1))
3230  {
[e801fe]3231     if(size(quprimary)>0)
[d6db1f2]3232     {
[e801fe]3233        setring @Phelp;
3234        ser=imap(gnir,ser);
3235        hquprimary=imap(gnir,quprimary);
[d6db1f2]3236        if(@wr==0)
3237        {
[e801fe]3238           ideal htest=hquprimary[1];
3239           for (@n1=2;@n1<=size(hquprimary)/2;@n1++)
[d6db1f2]3240           {
[d950c5]3241              htest=intersect(htest,hquprimary[2*@n1-1]);
[d6db1f2]3242           }
3243        }
3244        else
3245        {
[e801fe]3246           ideal htest=hquprimary[2];
[d6db1f2]3247
[e801fe]3248           for (@n1=2;@n1<=size(hquprimary)/2;@n1++)
[d6db1f2]3249           {
[d950c5]3250              htest=intersect(htest,hquprimary[2*@n1]);
[d6db1f2]3251           }
3252        }
[e801fe]3253
[d6db1f2]3254        if(size(ser)>0)
[3939bc]3255        {
[d950c5]3256           ser=intersect(htest,ser);
[d6db1f2]3257        }
[e801fe]3258        else
3259        {
3260          ser=htest;
[3939bc]3261        }
[e801fe]3262        setring gnir;
3263        ser=imap(@Phelp,ser);
[d6db1f2]3264     }
[e801fe]3265     if(size(reduce(ser,peek,1))!=0)
[3939bc]3266     {
[d6db1f2]3267        for(@m=1;@m<=size(restindep);@m++)
3268        {
[e801fe]3269         // if(restindep[@m][3]>=keepdi)
[3939bc]3270         // {
[d6db1f2]3271           isat=0;
3272           @n2=0;
[3939bc]3273
[d6db1f2]3274           if(restindep[@m][1]==varstr(basering))
[091424]3275           //the good case, nothing to do, just to have the same notations
[d6db1f2]3276           //change the ring
3277           {
[2d2cad9]3278              execute("ring gnir1 = ("+charstr(basering)+"),("+
3279                varstr(basering)+"),("+ordstr(basering)+");");
[d6db1f2]3280              ideal @j=fetch(gnir,jkeep);
3281              attrib(@j,"isSB",1);
3282           }
3283           else
3284           {
3285              @va=string(maxideal(1));
[2d2cad9]3286              execute("ring gnir1 = ("+charstr(basering)+"),("+
3287                      restindep[@m][1]+"),(" +restindep[@m][2]+");");
3288              execute("map phi=gnir,"+@va+";");
[466f80]3289              op=option(get);
3290              option(redSB);
[d6db1f2]3291              if(homo==1)
3292              {
[2d2c8be]3293                 ideal @j=std(phi(jkeep),keephilb,@w);
[d6db1f2]3294              }
3295              else
3296              {
[9a384e]3297                ideal @j=groebner(phi(jkeep));
[d6db1f2]3298              }
[e801fe]3299              ideal ser=phi(ser);
[466f80]3300              option(set,op);
[d6db1f2]3301           }
[3939bc]3302
[d6db1f2]3303           for (lauf=1;lauf<=size(@j);lauf++)
3304           {
3305              fett[lauf]=size(@j[lauf]);
3306           }
[091424]3307           //------------------------------------------------------------------
[d6db1f2]3308           //we have now the following situation:
[091424]3309           //j intersected with K[var(nnp+1),..,var(nva)] is zero so we may
3310           //pass to this quotientring, j is their still a standardbasis, the
[d6db1f2]3311           //leading coefficients of the polynomials  there (polynomials in
3312           //K[var(nnp+1),..,var(nva)]) are collected in the list h,
3313           //we need their ggt, gh, because of the following:
[b9b906]3314           //let (j:gh^n)=(j:gh^infinity) then
[091424]3315           //j*K(var(nnp+1),..,var(nva))[..the rest..]
[d6db1f2]3316           //intersected with K[var(1),...,var(nva)] is (j:gh^n)
3317           //on the other hand j=(j,gh^n) intersected with (j:gh^n)
[18dd47]3318
[091424]3319           //------------------------------------------------------------------
[d6db1f2]3320
[091424]3321           //the arrangement for the quotientring
3322           // K(var(nnp+1),..,var(nva))[..the rest..]
3323           //and the map phi:K[var(1),...,var(nva)] ---->
3324           //--->K(var(nnpr+1),..,var(nva))[..the rest..]
3325           //------------------------------------------------------------------
[d6db1f2]3326
[18dd47]3327           quotring=prepareQuotientring(nvars(basering)-restindep[@m][3]);
[d6db1f2]3328
[091424]3329           //------------------------------------------------------------------
3330           //we pass to the quotientring  K(var(nnp+1),..,var(nva))[..rest..]
3331           //------------------------------------------------------------------
[18dd47]3332
[2d2cad9]3333           execute(quotring);
[d6db1f2]3334
3335           // @j considered in the quotientring
3336           ideal @j=imap(gnir1,@j);
[e801fe]3337           ideal ser=imap(gnir1,ser);
[d6db1f2]3338
3339           kill gnir1;
[18dd47]3340
[d6db1f2]3341           //j is a standardbasis in the quotientring but usually not minimal
3342           //here it becomes minimal
3343           @j=clearSB(@j,fett);
3344           attrib(@j,"isSB",1);
3345
3346           //we need later ggt(h[1],...)=gh for saturation
3347           ideal @h;
3348
3349           for(@n=1;@n<=size(@j);@n++)
3350           {
3351              @h[@n]=leadcoef(@j[@n]);
3352           }
[091424]3353           //the primary decomposition of j*K(var(nnp+1),..,var(nva))[..rest..]
[0c33fb]3354
3355           op=option(get);
[e801fe]3356           option(redSB);
3357           list uprimary= zero_decomp(@j,ser,@wr);
[6fa3af]3358//HIER
3359           if(abspri)
3360           {
3361              ideal II;
3362              ideal jmap;
3363              map sigma;
3364              nn=nvars(basering);
3365              map invsigma=basering,maxideal(1);
3366              for(ab=1;ab<=size(uprimary)/2;ab++)
3367              {
3368                 II=uprimary[2*ab];
3369                 attrib(II,"isSB",1);
3370                 if(deg(II[1])!=vdim(II))
3371                 {
3372                    jmap=randomLast(50);
3373                    sigma=basering,jmap;
3374                    jmap[nn]=2*var(nn)-jmap[nn];
3375                    invsigma=basering,jmap;
3376                    II=groebner(sigma(II));
3377                  }
3378                  absprimarytmp[ab]= absFactorize(II[1],77);
3379                  II=var(nn);
3380                  abskeeptmp[ab]=string(invsigma(II));
3381                  invsigma=basering,maxideal(1);
3382              }
3383           }
[02335e]3384           option(set,op);
[3939bc]3385
[b9b906]3386           //we need the intersection of the ideals in the list quprimary with
[091424]3387           //the polynomialring, i.e. let q=(f1,...,fr) in the quotientring
3388           //such an ideal but fi polynomials, then the intersection of q with
[b9b906]3389           //the polynomialring is the saturation of the ideal generated by
[091424]3390           //f1,...,fr with respect toh which is the lcm of the leading
3391           //coefficients of the fi considered in the quotientring:
3392           //this is coded in saturn
[d6db1f2]3393
3394           list saturn;
3395           ideal hpl;
[18dd47]3396
[d6db1f2]3397           for(@n=1;@n<=size(uprimary);@n++)
3398           {
3399              hpl=0;
3400              for(@n1=1;@n1<=size(uprimary[@n]);@n1++)
[18dd47]3401              {
[d6db1f2]3402                 hpl=hpl,leadcoef(uprimary[@n][@n1]);
3403              }
3404               saturn[@n]=hpl;
3405           }
[091424]3406           //------------------------------------------------------------------
3407           //we leave  the quotientring   K(var(nnp+1),..,var(nva))[..rest..]
[d6db1f2]3408           //back to the polynomialring
[091424]3409           //------------------------------------------------------------------
[d6db1f2]3410           setring gnir;
3411           collectprimary=imap(quring,uprimary);
3412           lsau=imap(quring,saturn);
[18dd47]3413           @h=imap(quring,@h);
[d6db1f2]3414
3415           kill quring;
3416
3417
3418           @n2=size(quprimary);
3419           @n3=@n2;
[3939bc]3420
[67bd4c]3421           for(@n1=1;@n1<=size(collectprimary)/2;@n1++)
[d6db1f2]3422           {
3423              if(deg(collectprimary[2*@n1][1])>0)
3424              {
3425                 @n2++;
3426                 quprimary[@n2]=collectprimary[2*@n1-1];
3427                 lnew[@n2]=lsau[2*@n1-1];
3428                 @n2++;
3429                 lnew[@n2]=lsau[2*@n1];
3430                 quprimary[@n2]=collectprimary[2*@n1];
[6fa3af]3431                 if(abspri)
3432                 {
3433                   absprimary[@n2/2]=absprimarytmp[@n1];
3434                   abskeep[@n2/2]=abskeeptmp[@n1];
3435                 }
[d6db1f2]3436              }
[18dd47]3437           }
[3939bc]3438
3439
[18dd47]3440           //here the intersection with the polynomialring
[d6db1f2]3441           //mentioned above is really computed
3442
[67bd4c]3443           for(@n=@n3/2+1;@n<=@n2/2;@n++)
[d6db1f2]3444           {
3445              if(specialIdealsEqual(quprimary[2*@n-1],quprimary[2*@n]))
3446              {
3447                 quprimary[2*@n-1]=sat2(quprimary[2*@n-1],lnew[2*@n-1])[1];
3448                 quprimary[2*@n]=quprimary[2*@n-1];
3449              }
3450              else
3451              {
3452                 if(@wr==0)
3453                 {
3454                    quprimary[2*@n-1]=sat2(quprimary[2*@n-1],lnew[2*@n-1])[1];
3455                 }
3456                 quprimary[2*@n]=sat2(quprimary[2*@n],lnew[2*@n])[1];
[e801fe]3457              }
[d6db1f2]3458           }
[e801fe]3459           if(@n2>=@n3+2)
3460           {
3461              setring @Phelp;
3462              ser=imap(gnir,ser);
3463              hquprimary=imap(gnir,quprimary);
3464              for(@n=@n3/2+1;@n<=@n2/2;@n++)
3465              {
3466                if(@wr==0)
3467                {
[d950c5]3468                   ser=intersect(ser,hquprimary[2*@n-1]);
[e801fe]3469                }
3470                else
3471                {
[d950c5]3472                   ser=intersect(ser,hquprimary[2*@n]);
[e801fe]3473                }
3474              }
3475              setring gnir;
3476              ser=imap(@Phelp,ser);
3477           }
[3939bc]3478
[e801fe]3479         // }
[3939bc]3480        }
[6fa3af]3481//HIER
3482        if(abspri)
3483        {
3484          list resu,tempo;
3485          for(ab=1;ab<=size(quprimary)/2;ab++)
3486          {
[fae51c]3487             if (deg(quprimary[2*ab][1])!=0)
3488             {
3489               tempo=quprimary[2*ab-1],quprimary[2*ab],
3490                         absprimary[ab],abskeep[ab];
3491               resu[ab]=tempo;
3492             }
[6fa3af]3493          }
3494          quprimary=resu;
3495          @wr=3;
3496        }
[e801fe]3497        if(size(reduce(ser,peek,1))!=0)
[d6db1f2]3498        {
3499           if(@wr>0)
3500           {
3501              htprimary=decomp(@j,@wr,peek,ser);
3502           }
3503           else
3504           {
3505              htprimary=decomp(@j,peek,ser);
[18dd47]3506           }
[d6db1f2]3507           // here we collect now both results primary(sat(j,gh))
3508           // and primary(j,gh^n)
3509           @n=size(quprimary);
3510           for (@k=1;@k<=size(htprimary);@k++)
3511           {
3512              quprimary[@n+@k]=htprimary[@k];
3513           }
3514        }
3515     }
[3939bc]3516
[d6db1f2]3517   }
[6fa3af]3518   else
3519   {
3520      if(abspri)
3521      {
3522        list resu,tempo;
3523        for(ab=1;ab<=size(quprimary)/2;ab++)
3524        {
3525           tempo=quprimary[2*ab-1],quprimary[2*ab],
3526                   absprimary[ab],abskeep[ab];
3527           resu[ab]=tempo;
3528        }
3529        quprimary=resu;
3530      }
3531   }
[091424]3532  //---------------------------------------------------------------------------
[d6db1f2]3533  //back to the ring we started with
3534  //the final result: primary
[091424]3535  //---------------------------------------------------------------------------
[3939bc]3536
[d6db1f2]3537  setring @P;
3538  primary=imap(gnir,quprimary);
3539  return(primary);
3540}
3541
3542
3543example
3544{ "EXAMPLE:"; echo = 2;
3545   ring  r = 32003,(x,y,z),lp;
3546   poly  p = z2+1;
3547   poly  q = z4+2;
3548   ideal i = p^2*q^3,(y-z3)^3,(x-yz+z4)^4;
3549   list pr= decomp(i);
3550   pr;
[18dd47]3551   testPrimary( pr, i);
[d6db1f2]3552}
[67bd4c]3553
3554///////////////////////////////////////////////////////////////////////////////
[07c623]3555static proc powerCoeffs(poly f,int e)
[80654d]3556//computes a polynomial with the same monomials as f but coefficients
3557//the p^e th power of the coefficients of f
[67bd4c]3558{
[80654d]3559   int i;
3560   poly g;
3561   int ex=char(basering)^e;
3562   for(i=1;i<=size(f);i++)
3563   {
3564      g=g+leadcoef(f[i])^ex*leadmonom(f[i]);
3565   }
3566   return(g);
3567}
3568///////////////////////////////////////////////////////////////////////////////
3569
[fc5095]3570proc sep(poly f,int i, list #)
[80654d]3571"USAGE:  input: a polynomial f depending on the i-th variable and optional
3572         an integer k considering the polynomial f defined over Fp(t1,...,tm)
3573         as polynomial over Fp(t(1)^(p^-k),...,t(m)^(p^-k))
3574 RETURN: the separabel part of f as polynomial in Fp(t1,...,tm)
[b9b906]3575        and an integer k to indicate that f should be considerd
[80654d]3576        as polynomial over Fp(t(1)^(p^-k),...,t(m)^(p^-k))
3577 EXAMPLE: example sep; shows an example
3578{
3579   def R=basering;
3580   int k;
3581   if(size(#)>0){k=#[1];}
3582
[fc5095]3583
[80654d]3584   poly h=gcd(f,diff(f,var(i)));
[fc5095]3585   if((reduce(f,std(h))!=0)||(reduce(diff(f,var(i)),std(h))!=0))
3586   {
3587      ERROR("FEHLER IN GCD");
3588   }
[80654d]3589   poly g1=lift(h,f)[1][1];    //  f/h
3590   poly h1;
3591
3592   while(h!=h1)
3593   {
3594      h1=h;
3595      h=gcd(h,diff(h,var(i)));
3596   }
3597
3598   if(deg(h1)==0){return(list(g1,k));} //in characteristic 0 we return here
3599
3600   k++;
3601
3602   ideal ma=maxideal(1);
3603   ma[i]=var(i)^char(R);
3604   map phi=R,ma;
3605   ideal hh=h;    //this is technical because preimage works only for ideals
3606
3607   poly u=preimage(R,phi,hh)[1]; //h=u(x(i)^p)
3608
3609   list g2=sep(u,i,k);           //we consider u(t(1)^(p^-1),...,t(m)^(p^-1))
3610   g1=powerCoeffs(g1,g2[2]-k+1); //to have g1 over the same field as g2[1]
3611
3612   list g3=sep(g1*g2[1],i,g2[2]);
3613   return(g3);
3614}
3615example
3616{ "EXAMPLE:"; echo = 2;
3617   ring R=(5,t,s),(x,y,z),dp;
3618   poly f=(x^25-t*x^5+t)*(x^3+s);
3619   sep(f,1);
3620}
3621
3622///////////////////////////////////////////////////////////////////////////////
[24f458]3623 proc zeroRad(ideal I,list #)
[80654d]3624"USAGE:  zeroRad(I) , I a zero-dimensional ideal
3625 RETURN: the radical of I
3626 NOTE:  Algorithm of Kemper
3627 EXAMPLE: example zeroRad; shows an example
3628{
[07c623]3629   if(homog(I)==1){return(maxideal(1));}
[80654d]3630   //I needs to be a reduced standard basis
[b9b906]3631   def R=basering;
[80654d]3632   int m=npars(R);
3633   int n=nvars(R);
[b9b906]3634   int p=char(R);
[fc5095]3635   int d=vdim(I);
[80654d]3636   int i,k;
3637   list l;
[fc5095]3638   if(((p==0)||(p>d))&&(d==deg(I[1])))
3639   {
3640     intvec e=leadexp(I[1]);
3641     for(i=1;i<=nvars(basering);i++)
3642     {
3643       if(e[i]!=0) break;
3644     }
3645     I[1]=sep(I[1],i)[1];
3646     return(interred(I));
3647   }
[02335e]3648   intvec op=option(get);
[80654d]3649
[b9b906]3650   option(redSB);
[80654d]3651   ideal F=finduni(I);//F[i] generates I intersected with K[var(i)]
[25c431]3652
[02335e]3653   option(set,op);
[07c623]3654   if(size(#)>0){I=#[1];}
[80654d]3655
3656   for(i=1;i<=n;i++)
3657   {
3658      l[i]=sep(F[i],i);
3659      F[i]=l[i][1];
3660      if(l[i][2]>k){k=l[i][2];}  //computation of the maximal k
3661   }
3662
[684cb0]3663   if((k==0)||(m==0)){return(interred(I+F));}        //the separable case
[80654d]3664
[b9b906]3665   for(i=1;i<=n;i++)             //consider all polynomials over
[80654d]3666   {                             //Fp(t(1)^(p^-k),...,t(m)^(p^-k))
3667      F[i]=powerCoeffs(F[i],k-l[i][2]);
3668   }
[24f458]3669
[80654d]3670   string cR="ring @R="+string(p)+",("+parstr(R)+","+varstr(R)+"),dp;";
3671   execute(cR);
3672   ideal F=imap(R,F);
[24f458]3673
[80654d]3674   string nR="ring @S="+string(p)+",(y(1..m),"+varstr(R)+","+parstr(R)+"),dp;";
3675   execute(nR);
3676
3677   ideal G=fetch(@R,F);    //G[i](t(1)^(p^-k),...,t(m)^(p^-k),x(i))=sep(F[i])
[24f458]3678
[80654d]3679   ideal I=imap(R,I);
3680   ideal J=I+G;
[24f458]3681   poly el=1;
[80654d]3682   k=p^k;
3683   for(i=1;i<=m;i++)
3684   {
3685      J=J,var(i)^k-var(m+n+i);
[24f458]3686      el=el*y(i);
[80654d]3687   }
3688
[24f458]3689   J=eliminate(J,el);
[80654d]3690   setring R;
3691   ideal J=imap(@S,J);
3692   return(J);
3693}
3694example
3695{ "EXAMPLE:"; echo = 2;
3696   ring R=(5,t),(x,y),dp;
3697   ideal I=x^5-t,y^5-t;
[24f458]3698   zeroRad(I);
[80654d]3699}
3700
3701///////////////////////////////////////////////////////////////////////////////
[07c623]3702static proc radicalKL (ideal i,ideal ser,list #)
[80654d]3703{
[0c33fb]3704   attrib(i,"isSB",1);   // i needs to be a reduced standard basis
[07c623]3705   list indep,fett;
[868c617]3706   intvec @w,@hilb,op;
[07c623]3707   int @wr,@n,@m,lauf,di;
3708   ideal fac,@h,collectrad,lsau;
3709   poly @q;
3710   string @va,quotring;
3711
[67bd4c]3712   def  @P = basering;
[07c623]3713   int jdim=dim(i);
3714   int  homo=homog(i);
[67bd4c]3715   ideal rad=ideal(1);
3716   ideal te=ser;
3717   if(size(#)>0)
3718   {
3719      @wr=#[1];
3720   }
3721   if(homo==1)
3722   {
[80654d]3723      for(@n=1;@n<=nvars(basering);@n++)
3724      {
3725         @w[@n]=ord(var(@n));
3726      }
[b9b906]3727      @hilb=hilb(i,1,@w);
[67bd4c]3728   }
[07c623]3729
3730
[091424]3731  //---------------------------------------------------------------------------
[67bd4c]3732  //j is the ring
[091424]3733  //---------------------------------------------------------------------------
[67bd4c]3734
3735   if (jdim==-1)
3736   {
3737
[80654d]3738      return(ideal(1));
[3939bc]3739   }
[67bd4c]3740
[091424]3741  //---------------------------------------------------------------------------
3742  //the zero-dimensional case
3743  //---------------------------------------------------------------------------
[67bd4c]3744
3745   if (jdim==0)
3746   {
[80654d]3747      return(zeroRad(i));
[67bd4c]3748   }
[091424]3749   //-------------------------------------------------------------------------
[67bd4c]3750   //search for a maximal independent set indep,i.e.
3751   //look for subring such that the intersection with the ideal is zero
3752   //j intersected with K[var(indep[3]+1),...,var(nvar] is zero,
[091424]3753   //indep[1] is the new varstring, indep[2] the string for the block-ordering
3754   //-------------------------------------------------------------------------
[67bd4c]3755
[80654d]3756   indep=maxIndependSet(i);
[67bd4c]3757
3758   for(@m=1;@m<=size(indep);@m++)
3759   {
3760      if((indep[@m][1]==varstr(basering))&&(@m==1))
3761      //this is the good case, nothing to do, just to have the same notations
3762      //change the ring
3763      {
[2d2cad9]3764        execute("ring gnir1 = ("+charstr(basering)+"),("+varstr(basering)+"),("
3765                              +ordstr(basering)+");");
[80654d]3766         ideal @j=fetch(@P,i);
[67bd4c]3767         attrib(@j,"isSB",1);
3768      }
3769      else
3770      {
3771         @va=string(maxideal(1));
[2d2cad9]3772         execute("ring gnir1 = ("+charstr(basering)+"),("+indep[@m][1]+"),("
3773                              +indep[@m][2]+");");
3774         execute("map phi=@P,"+@va+";");
[67bd4c]3775         if(homo==1)
3776         {
[80654d]3777            ideal @j=std(phi(i),@hilb,@w);
[67bd4c]3778         }
3779         else
3780         {
[80654d]3781           ideal @j=groebner(phi(i));
[67bd4c]3782         }
3783      }
3784      if((deg(@j[1])==0)||(dim(@j)<jdim))
3785      {
3786         setring @P;
3787         break;
3788      }
3789      for (lauf=1;lauf<=size(@j);lauf++)
3790      {
3791         fett[lauf]=size(@j[lauf]);
3792      }
[091424]3793     //------------------------------------------------------------------------
[67bd4c]3794     //we have now the following situation:
3795     //j intersected with K[var(nnp+1),..,var(nva)] is zero so we may pass
3796     //to this quotientring, j is their still a standardbasis, the
3797     //leading coefficients of the polynomials  there (polynomials in
3798     //K[var(nnp+1),..,var(nva)]) are collected in the list h,
3799     //we need their ggt, gh, because of the following:
[091424]3800     //let (j:gh^n)=(j:gh^infinity) then j*K(var(nnp+1),..,var(nva))[..rest..]
[67bd4c]3801     //intersected with K[var(1),...,var(nva)] is (j:gh^n)
3802     //on the other hand j=(j,gh^n) intersected with (j:gh^n)
3803
[091424]3804     //------------------------------------------------------------------------
[67bd4c]3805
[091424]3806     //the arrangement for the quotientring K(var(nnp+1),..,var(nva))[..rest..]
3807     //and the map phi:K[var(1),...,var(nva)] ----->
3808     //K(var(nnpr+1),..,var(nva))[..the rest..]
3809     //------------------------------------------------------------------------
[67bd4c]3810      quotring=prepareQuotientring(nvars(basering)-indep[@m][3]);
3811
[091424]3812     //------------------------------------------------------------------------
[67bd4c]3813     //we pass to the quotientring   K(var(nnp+1),..,var(nva))[..the rest..]
[091424]3814     //------------------------------------------------------------------------
[67bd4c]3815
[2d2cad9]3816      execute(quotring);
[67bd4c]3817
3818    // @j considered in the quotientring
3819      ideal @j=imap(gnir1,@j);
3820
3821      kill gnir1;
3822
3823     //j is a standardbasis in the quotientring but usually not minimal
3824     //here it becomes minimal
3825
3826      @j=clearSB(@j,fett);
3827
3828     //we need later ggt(h[1],...)=gh for saturation
3829      ideal @h;
3830      if(deg(@j[1])>0)
3831      {
3832         for(@n=1;@n<=size(@j);@n++)
3833         {
3834            @h[@n]=leadcoef(@j[@n]);
3835         }
[b9b906]3836         op=option(get);
[67bd4c]3837         option(redSB);
[80654d]3838         @j=interred(@j);  //to obtain a reduced standardbasis
[67bd4c]3839         attrib(@j,"isSB",1);
[02335e]3840         option(set,op);
[868c617]3841
[80654d]3842         ideal zero_rad= zeroRad(@j);
[67bd4c]3843      }
3844      else
3845      {
3846         ideal zero_rad=ideal(1);
3847      }
3848
3849     //we need the intersection of the ideals in the list quprimary with the
3850     //polynomialring, i.e. let q=(f1,...,fr) in the quotientring such an ideal
3851     //but fi polynomials, then the intersection of q with the polynomialring
3852     //is the saturation of the ideal generated by f1,...,fr with respect to
[091424]3853     //h which is the lcm of the leading coefficients of the fi considered in
3854     //the quotientring: this is coded in saturn
[b9b906]3855
[03f11f]3856      zero_rad=std(zero_rad);
[b9b906]3857
[67bd4c]3858      ideal hpl;
3859
3860      for(@n=1;@n<=size(zero_rad);@n++)
3861      {
3862         hpl=hpl,leadcoef(zero_rad[@n]);
3863      }
3864
[091424]3865     //------------------------------------------------------------------------
[67bd4c]3866     //we leave  the quotientring   K(var(nnp+1),..,var(nva))[..the rest..]
3867     //back to the polynomialring
[091424]3868     //------------------------------------------------------------------------
[67bd4c]3869      setring @P;
3870
3871      collectrad=imap(quring,zero_rad);
3872      lsau=simplify(imap(quring,hpl),2);
3873      @h=imap(quring,@h);
3874
3875      kill quring;
3876
3877
3878     //here the intersection with the polynomialring
3879     //mentioned above is really computed
3880
3881      collectrad=sat2(collectrad,lsau)[1];
3882      if(deg(@h[1])>=0)
3883      {
3884         fac=ideal(0);
[3939bc]3885         for(lauf=1;lauf<=ncols(@h);lauf++)
[67bd4c]3886         {
3887            if(deg(@h[lauf])>0)
3888            {
3889                fac=fac+factorize(@h[lauf],1);
3890            }
3891         }
3892         fac=simplify(fac,4);
3893         @q=1;
3894         for(lauf=1;lauf<=size(fac);lauf++)
3895         {
3896            @q=@q*fac[lauf];
3897         }
[868c617]3898         op=option(get);
[80654d]3899         option(returnSB);
3900         option(redSB);
3901         i=quotient(i+ideal(@q),rad);
3902         attrib(i,"isSB",1);
[02335e]3903         option(set,op);
[868c617]3904
[67bd4c]3905      }
3906      if((deg(rad[1])>0)&&(deg(collectrad[1])>0))
3907      {
[d950c5]3908         rad=intersect(rad,collectrad);
[03f11f]3909         te=intersect(te,collectrad);
3910         te=simplify(reduce(te,i,1),2);
[67bd4c]3911      }
3912      else
3913      {
3914         if(deg(collectrad[1])>0)
3915         {
3916            rad=collectrad;
[03f11f]3917            te=intersect(te,collectrad);
3918            te=simplify(reduce(te,i,1),2);
[67bd4c]3919         }
3920      }
[03f11f]3921
[80654d]3922      if((dim(i)<jdim)||(size(te)==0))
[67bd4c]3923      {
3924         break;
3925      }
3926      if(homo==1)
3927      {
[80654d]3928         @hilb=hilb(i,1,@w);
[67bd4c]3929      }
3930   }
[80654d]3931   if(((@wr==1)&&(dim(i)<jdim))||(deg(i[1])==0)||(size(te)==0))
[67bd4c]3932   {
3933      return(rad);
[3939bc]3934   }
[80654d]3935   rad=intersect(rad,radicalKL(i,ideal(1),@wr));
[67bd4c]3936   return(rad);
3937}
3938
[ebecf83]3939///////////////////////////////////////////////////////////////////////////////
[67bd4c]3940
[07c623]3941proc radicalEHV(ideal i)
3942"USAGE:   radicalEHV(i); i ideal.
3943RETURN:  ideal, the radical of i.
[7a7df90]3944NOTE:    Uses the algorithm of Eisenbud/Huneke/Vasconcelos, which
[50cbdc]3945         reduces the computation to the complete intersection case,
[7a7df90]3946         by taking, in the general case, a generic linear combination
3947         of the input.
[07c623]3948         Works only in characteristic 0 or p large.
3949EXAMPLE: example radicalEHV; shows an example
3950"
[67bd4c]3951{
[07c623]3952   if(ord_test(basering)!=1)
[67bd4c]3953   {
[07c623]3954      ERROR(
3955      "// Not implemented for this ordering, please change to global ordering."
3956      );
3957   }
3958   if((char(basering)<100)&&(char(basering)!=0))
[b9b906]3959   {
[07c623]3960      "WARNING: The characteristic is too small, the result may be wrong";
[67bd4c]3961   }
[07c623]3962   ideal J,I,I0,radI0,L,radI1,I2,radI2;
[7a7df90]3963   int l,n;
[02335e]3964   intvec op=option(get);
[7a7df90]3965   matrix M;
[50cbdc]3966
[67bd4c]3967   option(redSB);
[d950c5]3968   list m=mstd(i);
[67bd4c]3969        I=m[2];
[02335e]3970   option(set,op);
[07c623]3971
3972   int cod=nvars(basering)-dim(m[1]);
[7a7df90]3973   //-------------------complete intersection case:----------------------
[07c623]3974   if(cod==size(m[2]))
[67bd4c]3975   {
[07c623]3976     J=minor(jacob(I),cod);
3977     return(quotient(I,J));
[67bd4c]3978   }
[7a7df90]3979   //-----first codim elements of I are a complete intersection:---------
[07c623]3980   for(l=1;l<=cod;l++)
[67bd4c]3981   {
[07c623]3982      I0[l]=I[l];
3983   }
[7a7df90]3984   n=dim(std(I0))+cod-nvars(basering);
3985   //-----last codim elements of I are a complete intersection:----------
3986   if(n!=0)
3987   {
3988      for(l=1;l<=cod;l++)
3989      {
3990         I0[l]=I[size(I)-l+1];
3991      }
3992      n=dim(std(I0))+cod-nvars(basering);
3993   }
3994   //-----taking a generic linear combination of the input:--------------
3995   if(n!=0)
3996   {
3997      M=transpose(sparsetriag(size(m[2]),cod,95,1));
3998      I0=ideal(M*transpose(I));
3999      n=dim(std(I0))+cod-nvars(basering);
4000   }
4001   //-----taking a more generic linear combination of the input:---------
4002   if(n!=0)
4003   {
4004      M=transpose(sparsetriag(size(m[2]),cod,0,100));
4005      I0=ideal(M*transpose(I));
4006      n=dim(std(I0))+cod-nvars(basering);
4007   }
4008   if(n==0)
[07c623]4009   {
4010      J=minor(jacob(I0),cod);
4011      radI0=quotient(I0,J);
4012      L=quotient(radI0,I);
4013      radI1=quotient(radI0,L);
[3939bc]4014
[07c623]4015      if(size(reduce(radI1,m[1],1))==0)
[67bd4c]4016      {
[07c623]4017         return(I);
[67bd4c]4018      }
[091424]4019
[07c623]4020      I2=sat(I,radI1)[1];
[67bd4c]4021
[07c623]4022      if(deg(I2[1])<=0)
4023      {
4024         return(radI1);
[67bd4c]4025      }
[07c623]4026      return(intersect(radI1,radicalEHV(I2)));
[67bd4c]4027   }
[7a7df90]4028   //---------------------general case-------------------------------------
4029   return(radical(I));
[67bd4c]4030}
[07c623]4031example
4032{ "EXAMPLE:";  echo = 2;
4033   ring  r = 0,(x,y,z),dp;
4034   poly  p = z2+1;
4035   poly  q = z3+2;
4036   ideal i = p*q^2,y-z2;
4037   ideal pr= radicalEHV(i);
4038   pr;
4039}
4040
[ebecf83]4041///////////////////////////////////////////////////////////////////////////////
[67bd4c]4042
[24f458]4043proc Ann(module M)
[76aca2]4044"USAGE:   Ann(M);  M module
4045RETURN:  ideal, the annihilator of coker(M)
4046NOTE:    The output is the ideal of all elements a of the basering R such that
4047         a * R^m is contained in M  (m=number of rows of M).
4048EXAMPLE: example Ann; shows an example
4049"
[67bd4c]4050{
4051  M=prune(M);  //to obtain a small embedding
[d950c5]4052  ideal ann=quotient1(M,freemodule(nrows(M)));
[e801fe]4053  return(ann);
[67bd4c]4054}
[76aca2]4055example
4056{ "EXAMPLE:"; echo = 2;
4057   ring  r = 0,(x,y,z),lp;
4058   module M = x2-y2,z3;
4059   Ann(M);
4060   M = [1,x2],[y,x];
4061   Ann(M);
4062   qring Q=std(xy-1);
4063   module M=imap(r,M);
4064   Ann(M);
4065}
4066
[ebecf83]4067///////////////////////////////////////////////////////////////////////////////
[67bd4c]4068
4069//computes the equidimensional part of the ideal i of codimension e
[07c623]4070static proc int_ass_primary_e(ideal i, int e)
[67bd4c]4071{
4072  if(homog(i)!=1)
4073  {
4074     i=std(i);
4075  }
4076  list re=sres(i,0);                   //the resolution
4077  re=minres(re);                       //minimized resolution
4078  ideal ann=AnnExt_R(e,re);
4079  if(nvars(basering)-dim(std(ann))!=e)
4080  {
4081    return(ideal(1));
4082  }
4083  return(ann);
[3939bc]4084}
4085
[ebecf83]4086///////////////////////////////////////////////////////////////////////////////
[67bd4c]4087
4088//computes the annihilator of Ext^n(R/i,R) with given resolution re
4089//n is not necessarily the number of variables
[07c623]4090static proc AnnExt_R(int n,list re)
[67bd4c]4091{
4092  if(n<nvars(basering))
4093  {
[d950c5]4094     matrix f=transpose(re[n+1]);      //Hom(_,R)
4095     module k=nres(f,2)[2];            //the kernel
4096     matrix g=transpose(re[n]);        //the image of Hom(_,R)
4097
4098     ideal ann=quotient1(g,k);           //the anihilator
[67bd4c]4099  }
4100  else
4101  {
4102     ideal ann=Ann(transpose(re[n]));
4103  }
[3939bc]4104  return(ann);
[e801fe]4105}
[ebecf83]4106///////////////////////////////////////////////////////////////////////////////
[e801fe]4107
[07c623]4108static proc analyze(list pr)
[3939bc]4109{
[e801fe]4110   int ii,jj;
4111   for(ii=1;ii<=size(pr)/2;ii++)
4112   {
4113      dim(std(pr[2*ii]));
4114      idealsEqual(pr[2*ii-1],pr[2*ii]);
4115      "===========================";
4116   }
4117
4118   for(ii=size(pr)/2;ii>1;ii--)
4119   {
4120      for(jj=1;jj<ii;jj++)
4121      {
4122         if(size(reduce(pr[2*jj],std(pr[2*ii],1)))==0)
4123         {
4124            "eingebette Komponente";
4125            jj;
4126            ii;
4127         }
4128      }
[3939bc]4129   }
[e801fe]4130}
4131
[ebecf83]4132///////////////////////////////////////////////////////////////////////////////
4133//
4134//                  Shimoyama-Yokoyama
4135//
4136///////////////////////////////////////////////////////////////////////////////
[e801fe]4137
[07c623]4138static proc simplifyIdeal(ideal i)
[e801fe]4139{
4140  def r=basering;
[3939bc]4141
[e801fe]4142  int j,k;
4143  map phi;
4144  poly p;
[3939bc]4145
[e801fe]4146  ideal iwork=i;
4147  ideal imap1=maxideal(1);
4148  ideal imap2=maxideal(1);
[3939bc]4149
[e801fe]4150
4151  for(j=1;j<=nvars(basering);j++)
4152  {
4153    for(k=1;k<=size(i);k++)
4154    {
4155      if(deg(iwork[k]/var(j))==0)
4156      {
4157        p=-1/leadcoef(iwork[k]/var(j))*iwork[k];
4158        imap1[j]=p+2*var(j);
4159        phi=r,imap1;
4160        iwork=phi(iwork);
4161        iwork=subst(iwork,var(j),0);
4162        iwork[k]=var(j);
4163        imap1=maxideal(1);
[3939bc]4164        imap2[j]=-p;
[e801fe]4165        break;
4166      }
4167    }
4168  }
4169  return(iwork,imap2);
4170}
4171
[3939bc]4172
[e801fe]4173///////////////////////////////////////////////////////
4174// ini_mod
4175// input: a polynomial p
4176// output: the initial term of p as needed
4177// in the context of characteristic sets
4178//////////////////////////////////////////////////////
4179
[07c623]4180static proc ini_mod(poly p)
[e801fe]4181{
4182  if (p==0)
4183  {
4184    return(0);
4185  }
4186  int n; matrix m;
4187  for( n=nvars(basering); n>0; n=n-1)
4188  {
4189    m=coef(p,var(n));
4190    if(m[1,1]!=1)
4191    {
4192      p=m[2,1];
4193      break;
4194    }
4195  }
4196  if(deg(p)==0)
4197  {
4198    p=0;
4199  }
4200  return(p);
4201}
4202///////////////////////////////////////////////////////
4203// min_ass_prim_charsets
4204// input: generators of an ideal PS and an integer cho
4205// If cho=0, the given ordering of the variables is used.
4206// Otherwise, the system tries to find an "optimal ordering",
4207// which in some cases may considerably speed up the algorithm
4208// output: the minimal associated primes of PS
4209// algorithm: via characteriostic sets
4210//////////////////////////////////////////////////////
4211
4212
[07c623]4213static proc min_ass_prim_charsets (ideal PS, int cho)
[e801fe]4214{
4215  if((cho<0) and (cho>1))
4216    {
4217      "ERROR: <int> must be 0 or 1"
4218      return();
4219    }
4220  if(system("version")>933)
4221  {
4222    option(notWarnSB);
4223  }
4224  if(cho==0)
4225  {
4226    return(min_ass_prim_charsets0(PS));
4227  }
4228  else
4229  {
4230     return(min_ass_prim_charsets1(PS));
4231  }
[67bd4c]4232}
[e801fe]4233///////////////////////////////////////////////////////
4234// min_ass_prim_charsets0
4235// input: generators of an ideal PS
4236// output: the minimal associated primes of PS
4237// algorithm: via characteristic sets
4238// the given ordering of the variables is used
4239//////////////////////////////////////////////////////
[67bd4c]4240
[e801fe]4241
[07c623]4242static proc min_ass_prim_charsets0 (ideal PS)
[e801fe]4243{
[466f80]4244  intvec op;
[e801fe]4245  matrix m=char_series(PS);  // We compute an irreducible
4246                             // characteristic series
4247  int i,j,k;
4248  list PSI;
4249  list PHI;  // the ideals given by the characteristic series
4250  for(i=nrows(m);i>=1; i--)
4251  {
4252     PHI[i]=ideal(m[i,1..ncols(m)]);
4253  }
4254  // We compute the radical of each ideal in PHI
4255  ideal I,JS,II;
4256  int sizeJS, sizeII;
4257  for(i=size(PHI);i>=1; i--)
4258  {
4259     I=0;
4260     for(j=size(PHI[i]);j>0;j=j-1)
4261     {
4262       I=I+ini_mod(PHI[i][j]);
4263     }
4264     JS=std(PHI[i]);
4265     sizeJS=size(JS);
4266     for(j=size(I);j>0;j=j-1)
4267     {
4268       II=0;
4269       sizeII=0;
4270       k=0;
4271       while(k<=sizeII)                  // successive saturation
4272       {
[466f80]4273         op=option(get);
[e801fe]4274         option(returnSB);
4275         II=quotient(JS,I[j]);
[02335e]4276         option(set,op);
[e801fe]4277         sizeII=size(II);
4278         if(sizeII==sizeJS)
4279         {
4280            for(k=1;k<=sizeII;k++)
4281            {
4282              if(leadexp(II[k])!=leadexp(JS[k])) break;
4283            }
4284         }
4285         JS=II;
4286         sizeJS=sizeII;
4287       }
4288    }
4289    PSI=insert(PSI,JS);
4290  }
4291  int sizePSI=size(PSI);
4292  // We eliminate redundant ideals
4293  for(i=1;i<sizePSI;i++)
4294  {
4295    for(j=i+1;j<=sizePSI;j++)
4296    {
4297      if(size(PSI[i])!=0)
4298      {
4299        if(size(PSI[j])!=0)
4300        {
4301          if(size(NF(PSI[i],PSI[j],1))==0)
4302          {
4303            PSI[j]=ideal(0);
4304          }
4305          else
4306          {
4307            if(size(NF(PSI[j],PSI[i],1))==0)
4308            {
4309              PSI[i]=ideal(0);
4310            }
4311          }
4312        }
4313      }
4314    }
4315  }
4316  for(i=sizePSI;i>=1;i--)
4317  {
4318    if(size(PSI[i])==0)
4319    {
4320      PSI=delete(PSI,i);
4321    }
4322  }
4323  return (PSI);
4324}
4325
4326///////////////////////////////////////////////////////
4327// min_ass_prim_charsets1
4328// input: generators of an ideal PS
4329// output: the minimal associated primes of PS
4330// algorithm: via characteristic sets
4331// input: generators of an ideal PS and an integer i
4332// The system tries to find an "optimal ordering" of
4333// the variables
4334//////////////////////////////////////////////////////
4335
4336
[07c623]4337static proc min_ass_prim_charsets1 (ideal PS)
[e801fe]4338{
[466f80]4339  intvec op;
[e801fe]4340  def oldring=basering;
4341  string n=system("neworder",PS);
[2d2cad9]4342  execute("ring r=("+charstr(oldring)+"),("+n+"),dp;");
[e801fe]4343  ideal PS=imap(oldring,PS);
4344  matrix m=char_series(PS);  // We compute an irreducible
4345                             // characteristic series
4346  int i,j,k;
4347  ideal I;
4348  list PSI;
4349  list PHI;    // the ideals given by the characteristic series
4350  list ITPHI;  // their initial terms
4351  for(i=nrows(m);i>=1; i--)
4352  {
4353     PHI[i]=ideal(m[i,1..ncols(m)]);
4354     I=0;
4355     for(j=size(PHI[i]);j>0;j=j-1)
4356     {
4357       I=I,ini_mod(PHI[i][j]);
4358     }
4359      I=I[2..ncols(I)];
4360      ITPHI[i]=I;
4361  }
4362  setring oldring;
4363  matrix m=imap(r,m);
4364  list PHI=imap(r,PHI);
4365  list ITPHI=imap(r,ITPHI);
4366  // We compute the radical of each ideal in PHI
4367  ideal I,JS,II;
4368  int sizeJS, sizeII;
4369  for(i=size(PHI);i>=1; i--)
4370  {
4371     I=0;
4372     for(j=size(PHI[i]);j>0;j=j-1)
4373     {
4374       I=I+ITPHI[i][j];
4375     }
4376     JS=std(PHI[i]);
4377     sizeJS=size(JS);
4378     for(j=size(I);j>0;j=j-1)
4379     {
4380       II=0;
4381       sizeII=0;
4382       k=0;
4383       while(k<=sizeII)                  // successive iteration
4384       {
[466f80]4385         op=option(get);
[e801fe]4386         option(returnSB);
4387         II=quotient(JS,I[j]);
[02335e]4388         option(set,op);
[e801fe]4389//std
4390//         II=std(II);
4391         sizeII=size(II);
4392         if(sizeII==sizeJS)
4393         {
4394            for(k=1;k<=sizeII;k++)
4395            {
4396              if(leadexp(II[k])!=leadexp(JS[k])) break;
4397            }
4398         }
4399         JS=II;
4400         sizeJS=sizeII;
4401       }
4402    }
4403    PSI=insert(PSI,JS);
4404  }
4405  int sizePSI=size(PSI);
4406  // We eliminate redundant ideals
4407  for(i=1;i<sizePSI;i++)
4408  {
4409    for(j=i+1;j<=sizePSI;j++)
4410    {
4411      if(size(PSI[i])!=0)
4412      {
4413        if(size(PSI[j])!=0)
4414        {
4415          if(size(NF(PSI[i],PSI[j],1))==0)
4416          {
4417            PSI[j]=ideal(0);
4418          }
4419          else
4420          {
4421            if(size(NF(PSI[j],PSI[i],1))==0)
4422            {
4423              PSI[i]=ideal(0);
4424            }
4425          }
4426        }
4427      }
4428    }
4429  }
4430  for(i=sizePSI;i>=1;i--)
4431  {
4432    if(size(PSI[i])==0)
4433    {
4434      PSI=delete(PSI,i);
4435    }
4436  }
4437  return (PSI);
4438}
4439
4440
4441/////////////////////////////////////////////////////
4442// proc prim_dec
4443// input:  generators of an ideal I and an integer choose
4444// If choose=0, min_ass_prim_charsets with the given
4445// ordering of the variables is used.
4446// If choose=1, min_ass_prim_charsets with the "optimized"
4447// ordering of the variables is used.
4448// If choose=2, minAssPrimes from primdec.lib is used
4449// If choose=3, minAssPrimes+factorizing Buchberger from primdec.lib is used
4450// output: a primary decomposition of I, i.e., a list
4451// of pairs consisting of a standard basis of a primary component
4452// of I and a standard basis of the corresponding associated prime.
4453// To compute the minimal associated primes of a given ideal
4454// min_ass_prim_l is called, i.e., the minimal associated primes
4455// are computed via characteristic sets.
4456// In the homogeneous case, the performance of the procedure
4457// will be improved if I is already given by a minimal set of
4458// generators. Apply minbase if necessary.
4459//////////////////////////////////////////////////////////
4460
4461
[07c623]4462static proc prim_dec(ideal I, int choose)
[e801fe]4463{
4464   if((choose<0) or (choose>3))
4465   {
4466     "ERROR: <int> must be 0 or 1 or 2 or 3";
4467      return();
4468   }
4469   if(system("version")>933)
4470   {
4471      option(notWarnSB);
[333b889]4472   }
[e801fe]4473  ideal H=1; // The intersection of the primary components
4474  list U;    // the leaves of the decomposition tree, i.e.,
4475             // pairs consisting of a primary component of I
4476             // and the corresponding associated prime
4477  list W;    // the non-leaf vertices in the decomposition tree.
4478             // every entry has 6 components:
4479                // 1- the vertex itself , i.e., a standard bais of the
4480                //    given ideal I (type 1), or a standard basis of a
4481                //    pseudo-primary component arising from
4482                //    pseudo-primary decomposition (type 2), or a
4483                //    standard basis of a remaining component arising from
4484                //    pseudo-primary decomposition or extraction (type 3)
4485                // 2- the type of the vertex as indicated above
4486                // 3- the weighted_tree_depth of the vertex
4487                // 4- the tester of the vertex
4488                // 5- a standard basis of the associated prime
4489                //    of a vertex of type 2, or 0 otherwise
4490                // 6- a list of pairs consisting of a standard
4491                //    basis of a minimal associated prime ideal
4492                //    of the father of the vertex and the
4493                //    irreducible factors of the "minimal
4494                //    divisor" of the seperator or extractor
4495                //    corresponding to the prime ideal
4496                //    as computed by the procedure minsat,
4497                //    if the vertex is of type 3, or
4498                //    the empty list otherwise
4499  ideal SI=std(I);
[333b889]4500  if(SI[1]==1)  // primdecSY(ideal(1))
4501  {
4502    return(list());
4503  }
[e801fe]4504  int ncolsSI=ncols(SI);
4505  int ncolsH=1;
4506  W[1]=list(I,1,0,poly(1),ideal(0),list()); // The root of the tree
4507  int weighted_tree_depth;
4508  int i,j;
4509  int check;
4510  list V;  // current vertex
4511  list VV; // new vertex
4512  list QQ;
4513  list WI;
4514  ideal Qi,SQ,SRest,fac;
4515  poly tester;
4516
4517  while(1)
4518  {
4519    i=1;
4520    while(1)
4521    {
4522      while(i<=size(W)) // find vertex V of smallest weighted tree-depth
4523      {
4524        if (W[i][3]<=weighted_tree_depth) break;
4525        i++;
4526      }
4527      if (i<=size(W)) break;
4528      i=1;
4529      weighted_tree_depth++;
4530    }
4531    V=W[i];
4532    W=delete(W,i); // delete V from W
4533
4534    // now proceed by type of vertex V
4535
4536    if (V[2]==2)  // extraction needed
4537    {
4538      SQ,SRest,fac=extraction(V[1],V[5]);
4539                        // standard basis of primary component,
4540                        // standard basis of remaining component,
4541                        // irreducible factors of
4542                        // the "minimal divisor" of the extractor
4543                        // as computed by the procedure minsat,
4544      check=0;
4545      for(j=1;j<=ncolsH;j++)
4546      {
4547        if (NF(H[j],SQ,1)!=0) // Q is not redundant
4548        {
4549          check=1;
4550          break;
4551        }
4552      }
4553      if(check==1)             // Q is not redundant
4554      {
4555        QQ=list();
4556        QQ[1]=list(SQ,V[5]);  // primary component, associated prime,
4557                              // i.e., standard bases thereof
4558        U=U+QQ;
[d950c5]4559        H=intersect(H,SQ);
[e801fe]4560        H=std(H);
4561        ncolsH=ncols(H);
4562        check=0;
4563        if(ncolsH==ncolsSI)
4564        {
4565          for(j=1;j<=ncolsSI;j++)
4566          {
4567            if(leadexp(H[j])!=leadexp(SI[j]))
4568            {
4569              check=1;
4570              break;
4571            }
4572          }
4573        }
4574        else
4575        {
4576          check=1;
4577        }
4578        if(check==0) // H==I => U is a primary decomposition
4579        {
4580          return(U);
4581        }
4582      }
4583      if (SRest[1]!=1)        // the remaining component is not
4584                              // the whole ring
4585      {
4586        if (rad_con(V[4],SRest)==0) // the new vertex is not the
4587                                    // root of a redundant subtree
4588        {
4589          VV[1]=SRest;     // remaining component
4590          VV[2]=3;         // pseudoprimdec_special
4591          VV[3]=V[3]+1;    // weighted depth
4592          VV[4]=V[4];      // the tester did not change
4593          VV[5]=ideal(0);
4594          VV[6]=list(list(V[5],fac));
4595          W=insert(W,VV,size(W));
4596        }
4597      }
4598    }
4599    else
4600    {
4601      if (V[2]==3) // pseudo_prim_dec_special is needed
4602      {
4603        QQ,SRest=pseudo_prim_dec_special_charsets(V[1],V[6],choose);
4604                         // QQ = quadruples:
4605                         // standard basis of pseudo-primary component,
4606                         // standard basis of corresponding prime,
4607                         // seperator, irreducible factors of
4608                         // the "minimal divisor" of the seperator
4609                         // as computed by the procedure minsat,
4610                         // SRest=standard basis of remaining component
4611      }
4612      else     // V is the root, pseudo_prim_dec is needed
4613      {
4614        QQ,SRest=pseudo_prim_dec_charsets(I,SI,choose);
4615                         // QQ = quadruples:
4616                         // standard basis of pseudo-primary component,
4617                         // standard basis of corresponding prime,
4618                         // seperator, irreducible factors of
4619                         // the "minimal divisor" of the seperator
4620                         // as computed by the procedure minsat,
4621                         // SRest=standard basis of remaining component
4622
4623      }
[091424]4624      //check
[e801fe]4625      for(i=size(QQ);i>=1;i--)
4626      //for(i=1;i<=size(QQ);i++)
4627      {
4628        tester=QQ[i][3]*V[4];
4629        Qi=QQ[i][2];
4630        if(NF(tester,Qi,1)!=0)  // the new vertex is not the
4631                                // root of a redundant subtree
4632        {
4633          VV[1]=QQ[i][1];
4634          VV[2]=2;
4635          VV[3]=V[3]+1;
4636          VV[4]=tester;      // the new tester as computed above
4637          VV[5]=Qi;          // QQ[i][2];
4638          VV[6]=list();
4639          W=insert(W,VV,size(W));
4640        }
4641      }
4642      if (SRest[1]!=1)        // the remaining component is not
4643                              // the whole ring
4644      {
4645        if (rad_con(V[4],SRest)==0) // the vertex is not the root
4646                                    // of a redundant subtree
4647        {
4648          VV[1]=SRest;
4649          VV[2]=3;
4650          VV[3]=V[3]+2;
4651          VV[4]=V[4];      // the tester did not change
4652          VV[5]=ideal(0);
4653          WI=list();
4654          for(i=1;i<=size(QQ);i++)
4655          {
4656            WI=insert(WI,list(QQ[i][2],QQ[i][4]));
4657          }
4658          VV[6]=WI;
4659          W=insert(W,VV,size(W));
4660        }
4661      }
4662    }
4663  }
4664}
4665
4666//////////////////////////////////////////////////////////////////////////
4667// proc pseudo_prim_dec_charsets
4668// input: Generators of an arbitrary ideal I, a standard basis SI of I,
4669// and an integer choo
4670// If choo=0, min_ass_prim_charsets with the given
4671// ordering of the variables is used.
4672// If choo=1, min_ass_prim_charsets with the "optimized"
4673// ordering of the variables is used.
4674// If choo=2, minAssPrimes from primdec.lib is used
4675// If choo=3, minAssPrimes+factorizing Buchberger from primdec.lib is used
4676// output: a pseudo primary decomposition of I, i.e., a list
4677// of pseudo primary components together with a standard basis of the
4678// remaining component. Each pseudo primary component is
4679// represented by a quadrupel: A standard basis of the component,
4680// a standard basis of the corresponding associated prime, the
4681// seperator of the component, and the irreducible factors of the
4682// "minimal divisor" of the seperator as computed by the procedure minsat,
4683// calls  proc pseudo_prim_dec_i
4684//////////////////////////////////////////////////////////////////////////
4685
4686
[07c623]4687static proc pseudo_prim_dec_charsets (ideal I, ideal SI, int choo)
[e801fe]4688{
4689  list L;          // The list of minimal associated primes,
4690                   // each one given by a standard basis
4691  if((choo==0) or (choo==1))
4692    {
4693       L=min_ass_prim_charsets(I,choo);
4694    }
4695  else
4696    {
4697      if(choo==2)
4698      {
4699        L=minAssPrimes(I);
4700      }
4701      else
4702      {
4703        L=minAssPrimes(I,1);
4704      }
4705      for(int i=size(L);i>=1;i=i-1)
4706        {
4707          L[i]=std(L[i]);
4708        }
4709    }
4710  return (pseudo_prim_dec_i(SI,L));
4711}
4712
4713////////////////////////////////////////////////////////////////
4714// proc pseudo_prim_dec_special_charsets
4715// input: a standard basis of an ideal I whose radical is the
4716// intersection of the radicals of ideals generated by one prime ideal
4717// P_i together with one polynomial f_i, the list V6 must be the list of
4718// pairs (standard basis of P_i, irreducible factors of f_i),
4719// and an integer choo
4720// If choo=0, min_ass_prim_charsets with the given
4721// ordering of the variables is used.
4722// If choo=1, min_ass_prim_charsets with the "optimized"
4723// ordering of the variables is used.
4724// If choo=2, minAssPrimes from primdec.lib is used
4725// If choo=3, minAssPrimes+factorizing Buchberger from primdec.lib is used
4726// output: a pseudo primary decomposition of I, i.e., a list
4727// of pseudo primary components together with a standard basis of the
4728// remaining component. Each pseudo primary component is
4729// represented by a quadrupel: A standard basis of the component,
4730// a standard basis of the corresponding associated prime, the
4731// seperator of the component, and the irreducible factors of the
4732// "minimal divisor" of the seperator as computed by the procedure minsat,
4733// calls  proc pseudo_prim_dec_i
4734////////////////////////////////////////////////////////////////
4735
4736
[07c623]4737static proc pseudo_prim_dec_special_charsets (ideal SI,list V6, int choo)
[e801fe]4738{
4739  int i,j,l;
4740  list m;
4741  list L;
4742  int sizeL;
4743  ideal P,SP; ideal fac;
4744  int dimSP;
4745  for(l=size(V6);l>=1;l--)   // creates a list of associated primes
4746                             // of I, possibly redundant
4747  {
4748    P=V6[l][1];
4749    fac=V6[l][2];
4750    for(i=ncols(fac);i>=1;i--)
4751    {
4752      SP=P+fac[i];
4753      SP=std(SP);
4754      if(SP[1]!=1)
4755      {
4756        if((choo==0) or (choo==1))
4757        {
4758          m=min_ass_prim_charsets(SP,choo);  // a list of SB
4759        }
4760        else
4761        {
4762          if(choo==2)
4763          {
4764            m=minAssPrimes(SP);
4765          }
4766          else
4767          {
4768            m=minAssPrimes(SP,1);
4769          }
4770          for(j=size(m);j>=1;j=j-1)
4771            {
4772              m[j]=std(m[j]);
4773            }
4774        }
[3939bc]4775        dimSP=dim(SP);
[e801fe]4776        for(j=size(m);j>=1; j--)
4777        {
4778          if(dim(m[j])==dimSP)
4779          {
4780            L=insert(L,m[j],size(L));
4781          }
4782        }
4783      }
4784    }
4785  }
4786  sizeL=size(L);
4787  for(i=1;i<sizeL;i++)     // get rid of redundant primes
4788  {
4789    for(j=i+1;j<=sizeL;j++)
4790    {
4791      if(size(L[i])!=0)
4792      {
4793        if(size(L[j])!=0)
4794        {
4795          if(size(NF(L[i],L[j],1))==0)
4796          {
4797            L[j]=ideal(0);
4798          }
4799          else
4800          {
4801            if(size(NF(L[j],L[i],1))==0)
4802            {
4803              L[i]=ideal(0);
4804            }
4805          }
4806        }
4807      }
4808    }
4809  }
4810  for(i=sizeL;i>=1;i--)
4811  {
4812    if(size(L[i])==0)
4813    {
4814      L=delete(L,i);
4815    }
4816  }
4817  return (pseudo_prim_dec_i(SI,L));
4818}
4819
4820
4821////////////////////////////////////////////////////////////////
4822// proc pseudo_prim_dec_i
4823// input: A standard basis of an arbitrary ideal I, and standard bases
4824// of the minimal associated primes of I
4825// output: a pseudo primary decomposition of I, i.e., a list
4826// of pseudo primary components together with a standard basis of the
4827// remaining component. Each pseudo primary component is
4828// represented by a quadrupel: A standard basis of the component Q_i,
4829// a standard basis of the corresponding associated prime P_i, the
4830// seperator of the component, and the irreducible factors of the
4831// "minimal divisor" of the seperator as computed by the procedure minsat,
4832////////////////////////////////////////////////////////////////
4833
4834
[07c623]4835static proc pseudo_prim_dec_i (ideal SI, list L)
[e801fe]4836{
4837  list Q;
4838  if (size(L)==1)               // one minimal associated prime only
4839                                // the ideal is already pseudo primary
4840  {
4841    Q=SI,L[1],1;
4842    list QQ;
4843    QQ[1]=Q;
4844    return (QQ,ideal(1));
4845  }
4846
4847  poly f0,f,g;
4848  ideal fac;
4849  int i,j,k,l;
4850  ideal SQi;
4851  ideal I'=SI;
4852  list QP;
4853  int sizeL=size(L);
4854  for(i=1;i<=sizeL;i++)
4855  {
4856    fac=0;
4857    for(j=1;j<=sizeL;j++)           // compute the seperator sep_i
4858                                    // of the i-th component
4859    {
4860      if (i!=j)                       // search g not in L[i], but L[j]
4861      {
4862        for(k=1;k<=ncols(L[j]);k++)
4863        {
4864          if(NF(L[j][k],L[i],1)!=0)
4865          {
4866            break;
4867          }
4868        }
4869        fac=fac+L[j][k];
4870      }
4871    }
4872    // delete superfluous polynomials
4873    fac=simplify(fac,8);
4874    // saturation
4875    SQi,f0,f,fac=minsat_ppd(SI,fac);
4876    I'=I',f;
4877    QP=SQi,L[i],f0,fac;
4878             // the quadrupel:
4879             // a standard basis of Q_i,
4880             // a standard basis of P_i,
4881             // sep_i,
4882             // irreducible factors of
4883             // the "minimal divisor" of the seperator
4884             //  as computed by the procedure minsat,
4885    Q[i]=QP;
4886  }
4887  I'=std(I');
4888  return (Q, I');
4889                   // I' = remaining component
4890}
4891
4892
4893////////////////////////////////////////////////////////////////
4894// proc extraction
4895// input: A standard basis of a pseudo primary ideal I, and a standard
4896// basis of the unique minimal associated prime P of I
4897// output: an extraction of I, i.e., a standard basis of the primary
4898// component Q of I with associated prime P, a standard basis of the
4899// remaining component, and the irreducible factors of the
4900// "minimal divisor" of the extractor as computed by the procedure minsat
4901////////////////////////////////////////////////////////////////
4902
4903
[07c623]4904static proc extraction (ideal SI, ideal SP)
[e801fe]4905{
[aa3811c]4906  list indsets=indepSet(SP,0);
[e801fe]4907  poly f;
4908  if(size(indsets)!=0)      //check, whether dim P != 0
4909  {
4910    intvec v;               // a maximal independent set of variables
4911                            // modulo P
4912    string U;               // the independent variables
4913    string A;               // the dependent variables
4914    int j,k;
4915    int a;                  //  the size of A
4916    int degf;
4917    ideal g;
4918    list polys;
4919    int sizepolys;
4920    list newpoly;
4921    def R=basering;
4922    //intvec hv=hilb(SI,1);
4923    for (k=1;k<=size(indsets);k++)
4924    {
4925      v=indsets[k];
4926      for (j=1;j<=nvars(R);j++)
4927      {
4928        if (v[j]==1)
4929        {
4930          U=U+varstr(j)+",";
4931        }
4932        else
4933        {
4934          A=A+varstr(j)+",";
4935          a++;
4936        }
4937      }
4938
4939      U[size(U)]=")";           // we compute the extractor of I (w.r.t. U)
[24f458]4940      execute("ring RAU=("+charstr(basering)+"),("+A+U+",(dp("+string(a)+"),dp);");
[e801fe]4941      ideal I=imap(R,SI);
4942      //I=std(I,hv);            // the standard basis in (R[U])[A]
4943      I=std(I);            // the standard basis in (R[U])[A]
4944      A[size(A)]=")";
[2d2cad9]4945      execute("ring Rloc=("+charstr(basering)+","+U+",("+A+",dp;");
[e801fe]4946      ideal I=imap(RAU,I);
4947      //"std in lokalisierung:"+newline,I;
4948      ideal h;
4949      for(j=ncols(I);j>=1;j--)
4950      {
4951        h[j]=leadcoef(I[j]);  // consider I in (R(U))[A]
4952      }
4953      setring R;
4954      g=imap(Rloc,h);
4955      kill RAU,Rloc;
4956      U="";
4957      A="";
4958      a=0;
4959      f=lcm(g);
4960      newpoly[1]=f;
4961      polys=polys+newpoly;
4962      newpoly=list();
4963    }
4964    f=polys[1];
4965    degf=deg(f);
4966    sizepolys=size(polys);
4967    for (k=2;k<=sizepolys;k++)
4968    {
4969      if (deg(polys[k])<degf)
4970      {
4971        f=polys[k];
[3939bc]4972        degf=deg(f);
[e801fe]4973      }
4974    }
4975  }
4976  else
4977  {
4978    f=1;
4979  }
4980  poly f0,h0; ideal SQ; ideal fac;
4981  if(f!=1)
4982  {
4983    SQ,f0,h0,fac=minsat(SI,f);
4984    return(SQ,std(SI+h0),fac);
4985             // the tripel
4986             // a standard basis of Q,
4987             // a standard basis of remaining component,
4988             // irreducible factors of
4989             // the "minimal divisor" of the extractor
4990             // as computed by the procedure minsat
4991  }
4992  else
4993  {
4994    return(SI,ideal(1),ideal(1));
4995  }
4996}
4997
4998/////////////////////////////////////////////////////
4999// proc minsat
5000// input:  a standard basis of an ideal I and a polynomial p
5001// output: a standard basis IS of the saturation of I w.r. to p,
5002// the maximal squarefree factor f0 of p,
5003// the "minimal divisor" f of f0 such that the saturation of
5004// I w.r. to f equals the saturation of I w.r. to f0 (which is IS),
5005// the irreducible factors of f
5006//////////////////////////////////////////////////////////
5007
5008
[07c623]5009static proc minsat(ideal SI, poly p)
[e801fe]5010{
5011  ideal fac=factorize(p,1);       //the irreducible factors of p
5012  fac=sort(fac)[1];
5013  int i,k;
5014  poly f0=1;
5015  for(i=ncols(fac);i>=1;i--)
5016  {
5017    f0=f0*fac[i];
5018  }
5019  poly f=1;
5020  ideal iold;
5021  list quotM;
5022  quotM[1]=SI;
5023  quotM[2]=fac;
5024  quotM[3]=f0;
5025  // we deal seperately with the first quotient;
5026  // factors, which do not contribute to this one,
5027  // are omitted
5028  iold=quotM[1];
5029  quotM=minquot(quotM);
5030  fac=quotM[2];
5031  if(quotM[3]==1)
5032    {
5033      return(quotM[1],f0,f,fac);
5034    }
5035  while(special_ideals_equal(iold,quotM[1])==0)
5036    {
5037      f=f*quotM[3];
5038      iold=quotM[1];
5039      quotM=minquot(quotM);
5040    }
5041  return(quotM[1],f0,f,fac);           // the quadrupel ((I:p),f0,f, irr. factors of f)
5042}
5043
5044/////////////////////////////////////////////////////
5045// proc minsat_ppd
5046// input:  a standard basis of an ideal I and a polynomial p
5047// output: a standard basis IS of the saturation of I w.r. to p,
5048// the maximal squarefree factor f0 of p,
5049// the "minimal divisor" f of f0 such that the saturation of
5050// I w.r. to f equals the saturation of I w.r. to f0 (which is IS),
5051// the irreducible factors of f
5052//////////////////////////////////////////////////////////
5053
5054
[07c623]5055static proc minsat_ppd(ideal SI, ideal fac)
[e801fe]5056{
5057  fac=sort(fac)[1];
5058  int i,k;
5059  poly f0=1;
5060  for(i=ncols(fac);i>=1;i--)
5061  {
5062    f0=f0*fac[i];
5063  }
5064  poly f=1;
5065  ideal iold;
5066  list quotM;
5067  quotM[1]=SI;
5068  quotM[2]=fac;
5069  quotM[3]=f0;
5070  // we deal seperately with the first quotient;
5071  // factors, which do not contribute to this one,
5072  // are omitted
5073  iold=quotM[1];
5074  quotM=minquot(quotM);
5075  fac=quotM[2];
5076  if(quotM[3]==1)
5077    {
5078      return(quotM[1],f0,f,fac);
5079    }
5080  while(special_ideals_equal(iold,quotM[1])==0)
5081  {
5082    f=f*quotM[3];
5083    iold=quotM[1];
5084    quotM=minquot(quotM);
5085    k++;
5086  }
5087  return(quotM[1],f0,f,fac);           // the quadrupel ((I:p),f0,f, irr. factors of f)
5088}
5089/////////////////////////////////////////////////////////////////
5090// proc minquot
5091// input: a list with 3 components: a standard basis
5092// of an ideal I, a set of irreducible polynomials, and
5093// there product f0
5094// output: a standard basis of the ideal (I:f0), the irreducible
5095// factors of the "minimal divisor" f of f0 with (I:f0) = (I:f),
5096// the "minimal divisor" f
5097/////////////////////////////////////////////////////////////////
5098
[07c623]5099static proc minquot(list tsil)
[e801fe]5100{
[466f80]5101   intvec op;
[e801fe]5102   int i,j,k,action;
5103   ideal verg;
5104   list l;
5105   poly g;
5106   ideal laedi=tsil[1];
5107   ideal fac=tsil[2];
5108   poly f=tsil[3];
5109
5110//std
5111//   ideal star=quotient(laedi,f);
5112//   star=std(star);
[466f80]5113   op=option(get);
[e801fe]5114   option(returnSB);
5115   ideal star=quotient(laedi,f);
[02335e]5116   option(set,op);
[e801fe]5117   if(special_ideals_equal(laedi,star)==1)
5118     {
5119       return(laedi,ideal(1),1);
5120     }
5121   action=1;
5122   while(action==1)
5123   {
5124      if(size(fac)==1)
5125      {
5126         action=0;
5127         break;
5128      }
5129      for(i=1;i<=size(fac);i++)
5130      {
5131        g=1;
5132         for(j=1;j<=size(fac);j++)
5133         {
5134            if(i!=j)
5135            {
5136               g=g*fac[j];
5137            }
5138         }
5139//std
5140//         verg=quotient(laedi,g);
5141//         verg=std(verg);
[466f80]5142         op=option(get);
[e801fe]5143         option(returnSB);
5144         verg=quotient(laedi,g);
[02335e]5145         option(set,op);
[e801fe]5146         if(special_ideals_equal(verg,star)==1)
5147         {
5148            f=g;
5149            fac[i]=0;
5150            fac=simplify(fac,2);
5151            break;
5152         }
5153         if(i==size(fac))
5154         {
5155            action=0;
5156         }
5157      }
5158   }
5159   l=star,fac,f;
5160   return(l);
5161}
5162/////////////////////////////////////////////////
5163// proc special_ideals_equal
5164// input: standard bases of ideal k1 and k2 such that
5165// k1 is contained in k2, or k2 is contained ink1
5166// output: 1, if k1 equals k2, 0 otherwise
5167//////////////////////////////////////////////////
5168
[07c623]5169static proc special_ideals_equal( ideal k1, ideal k2)
[e801fe]5170{
5171   int j;
5172   if(size(k1)==size(k2))
5173   {
5174      for(j=1;j<=size(k1);j++)
5175      {
5176         if(leadexp(k1[j])!=leadexp(k2[j]))
5177         {
5178            return(0);
5179         }
5180      }
5181      return(1);
5182   }
5183   return(0);
5184}
[3939bc]5185
5186
[ebecf83]5187///////////////////////////////////////////////////////////////////////////////
5188
[07c623]5189static proc convList(list l)
[ebecf83]5190{
5191   int i;
5192   list re,he;
5193   for(i=1;i<=size(l)/2;i++)
5194   {
5195      he=l[2*i-1],l[2*i];
5196      re[i]=he;
5197   }
[3939bc]5198   return(re);
[ebecf83]5199}
5200///////////////////////////////////////////////////////////////////////////////
5201
[07c623]5202static proc reconvList(list l)
[ebecf83]5203{
5204   int i;
5205   list re;
5206   for(i=1;i<=size(l);i++)
5207   {
5208      re[2*i-1]=l[i][1];
5209      re[2*i]=l[i][2];
5210   }
[3939bc]5211   return(re);
[ebecf83]5212}
5213
5214///////////////////////////////////////////////////////////////////////////////
5215//
5216//     The main procedures
5217//
5218///////////////////////////////////////////////////////////////////////////////
5219
5220proc primdecGTZ(ideal i)
[091424]5221"USAGE:   primdecGTZ(i); i ideal
[07c623]5222RETURN:  a list pr of primary ideals and their associated primes:
[367e88]5223@format
[7b3971]5224   pr[i][1]   the i-th primary component,
5225   pr[i][2]   the i-th prime component.
5226@end format
5227NOTE:    Algorithm of Gianni/Trager/Zacharias.
[b9b906]5228         Designed for characteristic 0, works also in char k > 0, if it
[091424]5229         terminates (may result in an infinite loop in small characteristic!)
[ebecf83]5230EXAMPLE: example primdecGTZ; shows an example
5231"
5232{
[07c623]5233   if(ord_test(basering)!=1)
5234   {
5235      ERROR(
5236      "// Not implemented for this ordering, please change to global ordering."
5237      );
5238   }
[24f458]5239   if(minpoly!=0)
5240   {
5241      return(algeDeco(i,0));
5242      ERROR(
5243      "// Not implemented yet for algebraic extensions.Simulate the ring extension by adding the minpoly to the ideal"
5244      );
5245   }
5246  return(convList(decomp(i)));
[ebecf83]5247}
5248example
5249{ "EXAMPLE:";  echo = 2;
[07c623]5250   ring  r = 0,(x,y,z),lp;
[ebecf83]5251   poly  p = z2+1;
[07c623]5252   poly  q = z3+2;
5253   ideal i = p*q^2,y-z2;
[091424]5254   list pr = primdecGTZ(i);
[ebecf83]5255   pr;
5256}
5257///////////////////////////////////////////////////////////////////////////////
5258
[6fa3af]5259proc absPrimdecGTZ(ideal I)
5260"USAGE:   absPrimdecGTZ(I); I ideal
5261ASSUME:  Ground field has characteristic 0.
5262RETURN:  a ring containing two lists: @code{absolute_primes} (the absolute
5263         prime components of I) and @code{primary_decomp} (the output of
5264         @code{primdecGTZ(I)}).
5265         The list absolute_primes has to be interpreted as follows:
5266         each entry describes a class of conjugated absolute primes,
5267@format
[326dba]5268   absolute_primes[i][1]   the absolute prime component,
[6fa3af]5269   absolute_primes[i][2]   the number of conjugates.
5270@end format
5271         The first entry of @code{absolute_primes[i][1]} is the minimal
5272         polynomial of a minimal finite field extension over which the
5273         absolute prime component is defined.
5274NOTE:    Algorithm of Gianni/Trager/Zacharias combined with the
5275         @code{absFactorize} command.
5276SEE ALSO: primdecGTZ; absFactorize
5277EXAMPLE: example absPrimdecGTZ; shows an example
5278"
5279{
5280    if (char(basering) != 0) {
5281    ERROR("primdec.lib::absPrimdecGTZ is only implemented for "+
5282           +"characteristic 0");
5283  }
5284
5285   if(ord_test(basering)!=1)
5286   {
5287      ERROR(
5288      "// Not implemented for this ordering, please change to global ordering."
5289      );
5290   }
5291   if(minpoly!=0)
5292   {
5293      //return(algeDeco(i,0));
5294      ERROR(
5295      "// Not implemented yet for algebraic extensions.Simulate the ring extension by adding the minpoly to the ideal"
5296      );
5297   }
5298  def R=basering;
5299  int n=nvars(R);
5300  list L=decomp(I,3);
5301  string newvar=L[1][3];
5302  int k=find(newvar,",",find(newvar,",")+1);
5303  newvar=newvar[k+1..size(newvar)];
5304  list lR=ringlist(R);
5305  int i,d;
5306  intvec vv;
5307  for(i=1;i<=n;i++){vv[i]=1;}
5308
5309  list orst;
5310  orst[1]=list("dp",vv);
5311  orst[2]=list("dp",intvec(1));
5312  orst[3]=list("C",0);
5313  lR[3]=orst;
5314  lR[2][n+1] = newvar;
5315  def Rz = ring(lR);
5316  setring Rz;
5317  list L=imap(R,L);
5318  list absolute_primes,primary_decomp;
5319  ideal I,M,N,K;
5320  M=maxideal(1);
5321  N=maxideal(1);
5322  poly p,q,f,g;
5323  map phi,psi;
5324  for(i=1;i<=size(L);i++)
5325  {
5326    I=L[i][2];
5327    execute("K="+L[i][3]+";");
5328    p=K[1];
5329    q=K[2];
5330    execute("f="+L[i][4]+";");
5331    g=2*var(n)-f;
5332    M[n]=f;
5333    N[n]=g;
5334    d=deg(p);
5335    phi=Rz,M;
5336    psi=Rz,N;
5337    I=phi(I),p,q;
5338    I=std(I);
5339    absolute_primes[i]=list(psi(I),d);
5340    primary_decomp[i]=list(L[i][1],L[i][2]);
5341  }
5342  export(primary_decomp);
5343  export(absolute_primes);
5344  setring R;
5345  dbprint( printlevel-voice+3,"
5346// 'absPrimdecGTZ' created a ring, in which two lists absolute_primes (the
5347// absolute prime components) and primary_decomp (the primary and prime
5348// components over the current basering) are stored.
5349// To access the list of absolute prime components, type (if the name S was
5350// assigned to the return value):
5351        setring S; absolute_primes; ");
5352
5353  return(Rz);
5354}
5355example
5356{ "EXAMPLE:";  echo = 2;
5357   ring  r = 0,(x,y,z),lp;
5358   poly  p = z2+1;
5359   poly  q = z3+2;
5360   ideal i = p*q^2,y-z2;
5361   def S = absPrimdecGTZ(i);
5362   setring S;
5363   absolute_primes;
5364}
5365///////////////////////////////////////////////////////////////////////////////
5366
[7b3971]5367proc primdecSY(ideal i, list #)
[091424]5368"USAGE:   primdecSY(i); i ideal, c int
[07c623]5369RETURN:  a list pr of primary ideals and their associated primes:
[367e88]5370@format
[7b3971]5371   pr[i][1]   the i-th primary component,
5372   pr[i][2]   the i-th prime component.
5373@end format
5374NOTE:    Algorithm of Shimoyama/Yokoyama.
5375@format
5376   if c=0,  the given ordering of the variables is used,
5377   if c=1,  minAssChar tries to use an optimal ordering,
5378   if c=2,  minAssGTZ is used,
5379   if c=3,  minAssGTZ and facstd are used.
5380@end format
[ebecf83]5381EXAMPLE: example primdecSY; shows an example
5382"
5383{
[07c623]5384   if(ord_test(basering)!=1)
5385   {
5386      ERROR(
5387      "// Not implemented for this ordering, please change to global ordering."
5388      );
5389   }
[bf241b]5390   i=simplify(i,2);
[24f458]5391   if ((i[1]==0)||(i[1]==1))
[bf241b]5392   {
[24f458]5393     list L=list(ideal(i[1]),ideal(i[1]));
[bf241b]5394     return(list(L));
[24f458]5395   }
5396   if(minpoly!=0)
5397   {
5398      return(algeDeco(i,1));
5399   }
[2d3c9b]5400   if (size(#)==1)
5401   { return(prim_dec(i,#[1])); }
[e44953]5402   else
5403   { return(prim_dec(i,1)); }
[ebecf83]5404}
5405example
5406{ "EXAMPLE:";  echo = 2;
[07c623]5407   ring  r = 0,(x,y,z),lp;
[ebecf83]5408   poly  p = z2+1;
[07c623]5409   poly  q = z3+2;
5410   ideal i = p*q^2,y-z2;
[091424]5411   list pr = primdecSY(i);
[ebecf83]5412   pr;
5413}
5414///////////////////////////////////////////////////////////////////////////////
[25c431]5415proc minAssGTZ(ideal i,list #)
[091424]5416"USAGE:   minAssGTZ(i); i ideal
[25c431]5417          minAssGTZ(i,1); i ideal  does not use the factorizing Groebner
[07c623]5418RETURN:  a list, the minimal associated prime ideals of i.
[24f458]5419NOTE:    Designed for characteristic 0, works also in char k > 0 based
5420         on an algorithm of Yokoyama
[ebecf83]5421EXAMPLE: example minAssGTZ; shows an example
5422"
5423{
[07c623]5424   if(ord_test(basering)!=1)
5425   {
5426      ERROR(
5427      "// Not implemented for this ordering, please change to global ordering."
5428      );
5429   }
[24f458]5430   if(minpoly!=0)
5431   {
5432      return(algeDeco(i,2));
5433   }
[7b15eb7]5434   if(size(#)==0)
[25c431]5435   {
5436      return(minAssPrimes(i,1));
5437   }
[367e88]5438   return(minAssPrimes(i));
[ebecf83]5439}
5440example
5441{ "EXAMPLE:";  echo = 2;
[07c623]5442   ring  r = 0,(x,y,z),dp;
[ebecf83]5443   poly  p = z2+1;
[07c623]5444   poly  q = z3+2;
5445   ideal i = p*q^2,y-z2;
5446   list pr = minAssGTZ(i);
[ebecf83]5447   pr;
5448}
5449
5450///////////////////////////////////////////////////////////////////////////////
[2d3c9b]5451proc minAssChar(ideal i, list #)
[7b3971]5452"USAGE:   minAssChar(i[,c]); i ideal, c int.
5453RETURN:  list, the minimal associated prime ideals of i.
5454NOTE:    If c=0, the given ordering of the variables is used. @*
[2d3c9b]5455         Otherwise, the system tries to find an optimal ordering,
[7b3971]5456         which in some cases may considerably speed up the algorithm. @*
5457         Due to a bug in the factorization, the result may be not completely
[07c623]5458         decomposed in small characteristic.
[9050ca]5459EXAMPLE: example minAssChar; shows an example
[22c0fc9]5460"
5461{
[07c623]5462   if(ord_test(basering)!=1)
5463   {
5464      ERROR(
5465      "// Not implemented for this ordering, please change to global ordering."
5466      );
5467   }
5468   if (size(#)==1)
5469   { return(min_ass_prim_charsets(i,#[1])); }
5470   else
5471   { return(min_ass_prim_charsets(i,1)); }
[22c0fc9]5472}
5473example
5474{ "EXAMPLE:";  echo = 2;
[07c623]5475   ring  r = 0,(x,y,z),dp;
[22c0fc9]5476   poly  p = z2+1;
[07c623]5477   poly  q = z3+2;
5478   ideal i = p*q^2,y-z2;
5479   list pr = minAssChar(i);
[22c0fc9]5480   pr;
5481}
[ebecf83]5482///////////////////////////////////////////////////////////////////////////////
5483proc equiRadical(ideal i)
[091424]5484"USAGE:   equiRadical(i); i ideal
[07c623]5485RETURN:  ideal, intersection of associated primes of i of maximal dimension.
5486NOTE:    A combination of the algorithms of Krick/Logar and Kemper is used.
5487         Works also in positive characteristic (Kempers algorithm).
[ebecf83]5488EXAMPLE: example equiRadical; shows an example
5489"
5490{
[07c623]5491   if(ord_test(basering)!=1)
5492   {
5493      ERROR(
5494      "// Not implemented for this ordering, please change to global ordering."
5495      );
5496   }
[ebecf83]5497   return(radical(i,1));
5498}
5499example
5500{ "EXAMPLE:";  echo = 2;
[07c623]5501   ring  r = 0,(x,y,z),dp;
[ebecf83]5502   poly  p = z2+1;
[07c623]5503   poly  q = z3+2;
5504   ideal i = p*q^2,y-z2;
[ebecf83]5505   ideal pr= equiRadical(i);
5506   pr;
5507}
[fc5095]5508
[ebecf83]5509///////////////////////////////////////////////////////////////////////////////
5510proc radical(ideal i,list #)
[07c623]5511"USAGE:   radical(i); i ideal.
5512RETURN:  ideal, the radical of i.
5513NOTE:    A combination of the algorithms of Krick/Logar and Kemper is used.
5514         Works also in positive characteristic (Kempers algorithm).
[ebecf83]5515EXAMPLE: example radical; shows an example
5516"
5517{
[07c623]5518   if(ord_test(basering)!=1)
5519   {
5520      ERROR(
5521      "// Not implemented for this ordering, please change to global ordering."
5522      );
5523   }
[d950c5]5524   def @P=basering;
[ebecf83]5525   int j,il;
[0c33fb]5526   if(size(#)>0){il=#[1];}
5527   if(size(i)==0){return(ideal(0));}
[d950c5]5528   ideal re=1;
[02335e]5529   intvec op = option(get);
[ebecf83]5530   list qr=simplifyIdeal(i);
[fc5095]5531   ideal isave=i;
[ebecf83]5532   map phi=@P,qr[2];
[0c33fb]5533
[07c623]5534   option(redSB);
[0c33fb]5535   i=groebner(qr[1]);
[02335e]5536   option(set,op);
[0c33fb]5537   int di=dim(i);
5538
[80654d]5539   if(di==0)
[ebecf83]5540   {
[0c33fb]5541     i=zeroRad(i,qr[1]);
[09f420]5542     return(interred(phi(i)));
[ebecf83]5543   }
[0c33fb]5544
[07c623]5545   option(redSB);
[24f458]5546   list pr=i;
5547   if (!homog(i))
5548   {
5549     pr=facstd(i);
5550   }
[02335e]5551   option(set,op);
[ebecf83]5552   int s=size(pr);
[0c33fb]5553
[ebecf83]5554   for(j=1;j<=s;j++)
5555   {
[80654d]5556      attrib(pr[s+1-j],"isSB",1);
5557      if((size(reduce(re,pr[s+1-j],1))!=0)&&((dim(pr[s+1-j])==di)||!il))
[ebecf83]5558      {
[80654d]5559         re=intersect(re,radicalKL(pr[s+1-j],re,il));
[ebecf83]5560      }
5561   }
[868c617]5562   return(interred(phi(re)));
[1918008]5563}
[ebecf83]5564example
5565{ "EXAMPLE:";  echo = 2;
[07c623]5566   ring  r = 0,(x,y,z),dp;
[ebecf83]5567   poly  p = z2+1;
[07c623]5568   poly  q = z3+2;
5569   ideal i = p*q^2,y-z2;
[ebecf83]5570   ideal pr= radical(i);
5571   pr;
5572}
5573///////////////////////////////////////////////////////////////////////////////
5574proc prepareAss(ideal i)
[091424]5575"USAGE:   prepareAss(i); i ideal
[7b3971]5576RETURN:  list, the radicals of the maximal dimensional components of i.
5577NOTE:    Uses algorithm of Eisenbud/Huneke/Vasconcelos.
[ebecf83]5578EXAMPLE: example prepareAss; shows an example
5579"
5580{
[07c623]5581  if(ord_test(basering)!=1)
5582  {
5583      ERROR(
5584      "// Not implemented for this ordering, please change to global ordering."
5585      );
5586  }
[ebecf83]5587  ideal j=std(i);
[d950c5]5588  int cod=nvars(basering)-dim(j);
[ebecf83]5589  int e;
5590  list er;
5591  ideal ann;
5592  if(homog(i)==1)
5593  {
[0ad359]5594     list re=sres(j,0);                   //the resolution
[ebecf83]5595     re=minres(re);                       //minimized resolution
5596  }
5597  else
5598  {
[3939bc]5599    list re=mres(i,0);
5600  }
[ebecf83]5601  for(e=cod;e<=nvars(basering);e++)
5602  {
5603     ann=AnnExt_R(e,re);
[d950c5]5604
[ebecf83]5605     if(nvars(basering)-dim(std(ann))==e)
5606     {
5607        er[size(er)+1]=equiRadical(ann);
5608     }
5609  }
5610  return(er);
[3939bc]5611}
[ebecf83]5612example
5613{ "EXAMPLE:";  echo = 2;
[07c623]5614   ring  r = 0,(x,y,z),dp;
[ebecf83]5615   poly  p = z2+1;
[07c623]5616   poly  q = z3+2;
5617   ideal i = p*q^2,y-z2;
5618   list pr = prepareAss(i);
[ebecf83]5619   pr;
5620}
[03f29c]5621///////////////////////////////////////////////////////////////////////////////
5622proc equidimMaxEHV(ideal i)
5623"USAGE:  equidimMaxEHV(i); i ideal
[07c623]5624RETURN:  ideal, the equidimensional component (of maximal dimension) of i.
5625NOTE:    Uses algorithm of Eisenbud, Huneke and Vasconcelos.
[03f29c]5626EXAMPLE: example equidimMaxEHV; shows an example
5627"
5628{
[07c623]5629  if(ord_test(basering)!=1)
5630  {
5631      ERROR(
5632      "// Not implemented for this ordering, please change to global ordering."
5633      );
5634  }
[0ad359]5635  ideal j=groebner(i);
[03f29c]5636  int cod=nvars(basering)-dim(j);
5637  int e;
5638  ideal ann;
5639  if(homog(i)==1)
5640  {
[0ad359]5641     list re=sres(j,0);                   //the resolution
[03f29c]5642     re=minres(re);                       //minimized resolution
5643  }
5644  else
5645  {
5646    list re=mres(i,0);
5647  }
5648  ann=AnnExt_R(cod,re);
5649  return(ann);
5650}
5651example
5652{ "EXAMPLE:";  echo = 2;
[07c623]5653   ring  r = 0,(x,y,z),dp;
[03f29c]5654   ideal i=intersect(ideal(z),ideal(x,y),ideal(x2,z2),ideal(x5,y5,z5));
5655   equidimMaxEHV(i);
5656}
[ebecf83]5657
[838d37]5658proc testPrimary(list pr, ideal k)
[7b3971]5659"USAGE:   testPrimary(pr,k); pr a list, k an ideal.
5660ASSUME:  pr is the result of primdecGTZ(k) or primdecSY(k).
5661RETURN:  int, 1 if the intersection of the ideals in pr is k, 0 if not
[091424]5662EXAMPLE: example testPrimary; shows an example
[ebecf83]5663"
5664{
5665   int i;
5666   pr=reconvList(pr);
5667   ideal j=pr[1];
5668   for (i=2;i<=size(pr)/2;i++)
5669   {
[d950c5]5670       j=intersect(j,pr[2*i-1]);
[ebecf83]5671   }
5672   return(idealsEqual(j,k));
5673}
5674example
5675{ "EXAMPLE:";  echo = 2;
5676   ring  r = 32003,(x,y,z),dp;
5677   poly  p = z2+1;
5678   poly  q = z4+2;
5679   ideal i = p^2*q^3,(y-z3)^3,(x-yz+z4)^4;
[091424]5680   list pr = primdecGTZ(i);
[ebecf83]5681   testPrimary(pr,i);
5682}
5683
[55fcff]5684///////////////////////////////////////////////////////////////////////////////
[7f24dd7]5685proc zerodec(ideal I)
5686"USAGE:   zerodec(I); I ideal
[7b3971]5687ASSUME:  I is zero-dimensional, the characteristic of the ground field is 0
5688RETURN:  list of primary ideals, the zero-dimensional decomposition of I
5689NOTE:    The algorithm (of Monico), works well only for a small total number
[367e88]5690         of solutions (@code{vdim(std(I))} should be < 100) and without
5691         parameters. In practice, it works also in large characteristic p>0
[7b3971]5692         but may fail for small p.
5693@*       If printlevel > 0 (default = 0) additional information is displayed.
[55fcff]5694EXAMPLE: example zerodec; shows an example
[7f24dd7]5695"
5696{
[07c623]5697   if(ord_test(basering)!=1)
5698   {
5699      ERROR(
5700      "// Not implemented for this ordering, please change to global ordering."
5701      );
5702   }
[7f24dd7]5703   def R=basering;
5704   poly q;
[55fcff]5705   int j,time;
[cdd778]5706   matrix m;
5707   list re;
5708   poly va=var(1);
[7f24dd7]5709   ideal J=groebner(I);
5710   ideal ba=kbase(J);
[cdd778]5711   int d=vdim(J);
[55fcff]5712   dbprint(printlevel-voice+2,"// multiplicity of ideal : "+ string(d));
5713//------ compute matrix of multiplication on R/I with generic element p -----
[cdd778]5714   int e=nvars(basering);
[55fcff]5715   poly p=randomLast(100)[e]+random(-50,50);     //the generic element
[7f24dd7]5716   matrix n[d][d];
[55fcff]5717   time = timer;
[cdd778]5718   for(j=2;j<=e;j++)
[7f24dd7]5719   {
5720      va=va*var(j);
5721   }
5722   for(j=1;j<=d;j++)
5723   {
5724      q=reduce(p*ba[j],J);
5725      m=coeffs(q,ba,va);
5726      n[j,1..d]=m[1..d,1];
5727   }
[55fcff]5728   dbprint(printlevel-voice+2,
[b9b906]5729      "// time for computing multiplication matrix (with generic element) : "+
[55fcff]5730      string(timer-time));
5731//---------------- compute characteristic polynomial of matrix --------------
5732   execute("ring P1=("+charstr(R)+"),T,dp;");
5733   matrix n=imap(R,n);
5734   time = timer;
5735   poly charpol=det(n-T*freemodule(d));
[b9b906]5736   dbprint(printlevel-voice+2,"// time for computing char poly: "+
[55fcff]5737           string(timer-time));
5738//------------------- factorize characteristic polynomial -------------------
[b9b906]5739//check first if constant term of charpoly is != 0 (which is true for
[55fcff]5740//sufficiently generic element)
[7f24dd7]5741   if(charpol[size(charpol)]!=0)
5742   {
[55fcff]5743     time = timer;
[74e966]5744     list fac=factor(charpol);
5745     testFactor(fac,charpol);
[b9b906]5746     dbprint(printlevel-voice+2,"// time for factorizing char poly: "+
[55fcff]5747             string(timer-time));
[754cf99]5748     int f=size(fac[1]);
[55fcff]5749//--------------------------- the irreducible case --------------------------
[9ec5e7b]5750     if(f==1)
[754cf99]5751     {
[55fcff]5752       setring R;
[754cf99]5753       re=I;
5754       return(re);
5755     }
[55fcff]5756//---------------------------- the reducible case ---------------------------
[b9b906]5757//if f_i are the irreducible factors of charpoly, mult=ri, then <I,g_i^ri>
5758//are the primary components where g_i = f_i(p). However, substituting p in
5759//f_i may result in a huge object although the final result may be small.
5760//Hence it is better to simultaneously reduce with I. For this we need a new
[55fcff]5761//ring.
5762     execute("ring P=("+charstr(R)+"),(T,"+varstr(R)+"),(dp(1),dp);");
5763     list rfac=imap(P1,fac);
5764     intvec ov=option(get);;
[7f24dd7]5765     option(redSB);
[55fcff]5766     list re1;
5767     ideal new = T-imap(R,p),imap(R,J);
5768     attrib(new, "isSB",1);    //we know that new is a standard basis
[74e966]5769     for(j=1;j<=f;j++)
[7f24dd7]5770     {
[b9b906]5771        re1[j]=reduce(rfac[1][j]^rfac[2][j],new);
[7f24dd7]5772     }
[55fcff]5773     setring R;
5774     re = imap(P,re1);
5775     for(j=1;j<=f;j++)
5776     {
5777        J=I,re[j];
[b9b906]5778        re[j]=interred(J);
[55fcff]5779     }
5780     option(set,ov);
[7f24dd7]5781     return(re);
5782  }
5783  else
[55fcff]5784//------------------- choice of generic element failed -------------------
[7f24dd7]5785  {
[55fcff]5786     dbprint(printlevel-voice+2,"// try new generic element!");
5787     setring R;
5788     return(zerodec(I));
[7f24dd7]5789  }
5790}
5791example
5792{ "EXAMPLE:";  echo = 2;
[07c623]5793   ring r  = 0,(x,y),dp;
5794   ideal i = x2-2,y2-2;
5795   list pr = zerodec(i);
[7f24dd7]5796   pr;
5797}
[55fcff]5798////////////////////////////////////////////////////////////////////////////
5799/*
5800//Beispiele Wenk-Dipl (in ~/Texfiles/Diplom/Wenk/Examples/)
5801//Zeiten: Singular/Singular/Singular -r123456789 -v :wilde13 (PentiumPro200)
5802//Singular for HPUX-9 version 1-3-8  (2000060214)  Jun  2 2000 15:31:26
5803//(wilde13)
5804
5805//1. vdim=20, 3  Komponenten
5806//zerodec-time:2(1)  (matrix:1 charpoly:0 factor:1)
5807//primdecGTZ-time: 1(0)
5808ring rs= 0,(a,b,c),dp;
5809poly f1= a^2*b*c + a*b^2*c + a*b*c^2 + a*b*c + a*b + a*c + b*c;
5810poly f2= a^2*b^2*c + a*b^2*c^2 + a^2*b*c + a*b*c + b*c + a + c;
5811poly f3= a^2*b^2*c^2 + a^2*b^2*c + a*b^2*c + a*b*c + a*c + c + 1;
5812ideal gls=f1,f2,f3;
5813int time=timer;
5814printlevel =1;
5815time=timer; list pr1=zerodec(gls); timer-time;size(pr1);
5816time=timer; list pr =primdecGTZ(gls); timer-time;size(pr);
[07c623]5817time=timer; ideal ra =radical(gls); timer-time;size(pr);
[55fcff]5818
5819//2.cyclic5  vdim=70, 20 Komponenten
5820//zerodec-time:36(28)  (matrix:1(0) charpoly:18(19) factor:17(9)
5821//primdecGTZ-time: 28(5)
[b9b906]5822//radical : 0
[55fcff]5823ring rs= 0,(a,b,c,d,e),dp;
5824poly f0= a + b + c + d + e + 1;
5825poly f1= a + b + c + d + e;
5826poly f2= a*b + b*c + c*d + a*e + d*e;
5827poly f3= a*b*c + b*c*d + a*b*e + a*d*e + c*d*e;
5828poly f4= a*b*c*d + a*b*c*e + a*b*d*e + a*c*d*e + b*c*d*e;
5829poly f5= a*b*c*d*e - 1;
5830ideal gls= f1,f2,f3,f4,f5;
5831
5832//3. random vdim=40, 1 Komponente
5833//zerodec-time:126(304)  (matrix:1 charpoly:115(298) factor:10(5))
[b9b906]5834//primdecGTZ-time:17 (11)
[55fcff]5835ring rs=0,(x,y,z),dp;
5836poly f1=2*x^2 + 4*x + 3*y^2 + 7*x*z + 9*y*z + 5*z^2;
5837poly f2=7*x^3 + 8*x*y + 12*y^2 + 18*x*z + 3*y^4*z + 10*z^3 + 12;
5838poly f3=3*x^4 + 1*x*y*z + 6*y^3 + 3*x*z^2 + 2*y*z^2 + 4*z^2 + 5;
5839ideal gls=f1,f2,f3;
5840
5841//4. introduction into resultants, sturmfels, vdim=28, 1 Komponente
5842//zerodec-time:4  (matrix:0 charpoly:0 factor:4)
[b9b906]5843//primdecGTZ-time:1
[55fcff]5844ring rs=0,(x,y),dp;
5845poly f1= x4+y4-1;
5846poly f2= x5y2-4x3y3+x2y5-1;
5847ideal gls=f1,f2;
5848
5849//5. 3 quadratic equations with random coeffs, vdim=8, 1 Komponente
5850//zerodec-time:0(0)  (matrix:0 charpoly:0 factor:0)
[b9b906]5851//primdecGTZ-time:1(0)
[55fcff]5852ring rs=0,(x,y,z),dp;
5853poly f1=2*x^2 + 4*x*y + 3*y^2 + 7*x*z + 9*y*z + 5*z^2 + 2;
5854poly f2=7*x^2 + 8*x*y + 12*y^2 + 18*x*z + 3*y*z + 10*z^2 + 12;
5855poly f3=3*x^2 + 1*x*y + 6*y^2 + 3*x*z + 2*y*z + 4*z^2 + 5;
5856ideal gls=f1,f2,f3;
5857
5858//6. 3 polys    vdim=24, 1 Komponente
5859// run("ex14",2);
5860//zerodec-time:5(4)  (matrix:0 charpoly:3(3) factor:2(1))
5861//primdecGTZ-time:4 (2)
5862ring rs=0,(x1,x2,x3,x4),dp;
5863poly f1=16*x1^2 + 3*x2^2 + 5*x3^4 - 1 - 4*x4 + x4^3;
5864poly f2=5*x1^3 + 3*x2^2 + 4*x3^2*x4 + 2*x1*x4 - 1 + x4 + 4*x1 + x2 + x3 + x4;
5865poly f3=-4*x1^2 + x2^2 + x3^2 - 3 + x4^2 + 4*x1 + x2 + x3 + x4;
5866poly f4=-4*x1 + x2 + x3 + x4;
5867ideal gls=f1,f2,f3,f4;
5868
5869//7. ex43, PoSSo, caprasse   vdim=56, 16 Komponenten
[b9b906]5870//zerodec-time:23(15)  (matrix:0 charpoly:16(13) factor:3(2))
[55fcff]5871//primdecGTZ-time:3 (2)
5872ring rs= 0,(y,z,x,t),dp;
5873ideal gls=y^2*z+2*y*x*t-z-2*x,
58744*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,
58752*y*z*t+x*t^2-2*z-x,
5876-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;
5877
5878//8. Arnborg-System, n=6 (II),    vdim=156, 90 Komponenten
5879//zerodec-time (char32003):127(45)(matrix:2(0) charpoly:106(37) factor:16(7))
5880//primdecGTZ-time(char32003) :81 (18)
5881//ring rs= 0,(a,b,c,d,x,f),dp;
5882ring rs= 32003,(a,b,c,d,x,f),dp;
[b9b906]5883ideal gls=a+b+c+d+x+f, ab+bc+cd+dx+xf+af, abc+bcd+cdx+d*xf+axf+abf,
5884abcd+bcdx+cd*xf+ad*xf+abxf+abcf, abcdx+bcd*xf+acd*xf+abd*xf+abcxf+abcdf,
[55fcff]5885abcd*xf-1;
5886
5887//9. ex42, PoSSo, Methan6_1, vdim=27, 2 Komponenten
5888//zerodec-time:610  (matrix:10 charpoly:557 factor:26)
5889//primdecGTZ-time: 118
5890//zerodec-time(char32003):2
5891//primdecGTZ-time(char32003):4
5892//ring rs= 0,(x1,x2,x3,x4,x5,x6,x7,x8,x9,x10),dp;
5893ring rs= 32003,(x1,x2,x3,x4,x5,x6,x7,x8,x9,x10),dp;
5894ideal gls=64*x2*x7-10*x1*x8+10*x7*x9+11*x7*x10-320000*x1,
5895-32*x2*x7-5*x2*x8-5*x2*x10+160000*x1-5000*x2,
5896-x3*x8+x6*x8+x9*x10+210*x6+1300000,
5897-x4*x8+700000,
5898x10^2-2*x5,
5899-x6*x8+x7*x9-210*x6,
5900-64*x2*x7-10*x7*x9-11*x7*x10+320000*x1-16*x7+7000000,
5901-10*x1*x8-10*x2*x8-10*x3*x8-10*x4*x8-10*x6*x8+10*x2*x10+11*x7*x10
5902    +20000*x2+14*x5,
5903x4*x8-x7*x9-x9*x10-410*x9,
590410*x2*x8+10*x3*x8+10*x6*x8+10*x7*x9-10*x2*x10-11*x7*x10-10*x9*x10
5905    -10*x10^2+1400*x6-4200*x10;
5906
5907//10. ex33, walk-s7, Diplomarbeit von Tim, vdim=114
5908//zerfaellt in unterschiedlich viele Komponenten in versch. Charkteristiken:
5909//char32003:30, char0:3(2xdeg1,1xdeg112!), char181:4(2xdeg1,1xdeg28,1xdeg84)
5910//char 0: zerodec-time:10075 (ca 3h) (matrix:3 charpoly:9367, factor:680
5911//        + 24 sec fuer Normalform (anstatt einsetzen), total [29623k])
5912//        primdecGTZ-time: 214
5913//char 32003:zerodec-time:197(68) (matrix:2(1) charpoly:173(60) factor:15(6))
5914//        primdecGTZ-time:14 (5)
5915//char 181:zerodec-time:(87) (matrix:(1) charpoly:(58) factor:(25))
5916//        primdecGTZ-time:(2)
5917//in char181 stimmen Ergebnisse von zerodec und primdecGTZ ueberein (gecheckt)
5918
5919//ring rs= 0,(a,b,c,d,e,f,g),dp;
5920ring rs= 32003,(a,b,c,d,e,f,g),dp;
5921poly f1= 2gb + 2fc + 2ed + a2 + a;
5922poly f2= 2gc + 2fd + e2 + 2ba + b;
5923poly f3= 2gd + 2fe + 2ca + c + b2;
5924poly f4= 2ge + f2 + 2da + d + 2cb;
5925poly f5= 2fg + 2ea + e + 2db + c2;
5926poly f6= g2 + 2fa + f + 2eb + 2dc;
5927poly f7= 2ga + g + 2fb + 2ec + d2;
5928ideal gls= f1,f2,f3,f4,f5,f6,f7;
5929
5930~/Singular/Singular/Singular -r123456789 -v
5931LIB"./primdec.lib";
5932timer=1;
5933int time=timer;
5934printlevel =1;
5935option(prot,mem);
5936time=timer; list pr1=zerodec(gls); timer-time;
5937
5938time=timer; list pr =primdecGTZ(gls); timer-time;
5939time=timer; list pr =primdecSY(gls); timer-time;
[07c623]5940time=timer; ideal ra =radical(gls); timer-time;size(pr);
[24f458]5941LIB"all.lib";
5942
5943ring R=0,(a,b,c,d,e,f),dp;
5944ideal I=cyclic(6);
5945minAssGTZ(I);
5946
5947
5948ring S=(2,a,b),(x,y),lp;
5949ideal I=x8-b,y4+a;
5950minAssGTZ(I);
5951
5952ring S1=2,(x,y,a,b),lp;
5953ideal I=x8-b,y4+a;
5954minAssGTZ(I);
5955
5956
5957ring S2=(2,z),(x,y),dp;
5958minpoly=z2+z+1;
5959ideal I=y3+y+1,x4+x+1;
5960primdecGTZ(I);
5961minAssGTZ(I);
5962
5963ring S3=2,(x,y,z),dp;
5964ideal I=y3+y+1,x4+x+1,z2+z+1;
5965primdecGTZ(I);
5966minAssGTZ(I);
5967
5968
5969ring R1=2,(x,y,z),lp;
5970ideal I=y6+y5+y3+y2+1,x4+x+1,z2+z+1;
5971primdecGTZ(I);
5972minAssGTZ(I);
5973
5974
5975ring R2=(2,z),(x,y),lp;
5976minpoly=z3+z+1;
5977ideal I=y2+y+(z2+z+1),x4+x+1;
5978primdecGTZ(I);
5979minAssGTZ(I);
5980
[55fcff]5981*/
Note: See TracBrowser for help on using the repository browser.