source: git/Singular/LIB/mprimdec.lib @ 1e1990

spielwiese
Last change on this file since 1e1990 was 1e1990, checked in by Frédéric Chapoton <chapoton@…>, 17 months ago
fixing various typos (found using egrep)
  • Property mode set to 100644
File size: 61.8 KB
Line 
1//////////////////////////////////////////////////////////////////////////////
2version="version mprimdec.lib 4.1.2.0 Feb_2019 "; // $Id$
3category="Commutative Algebra";
4
5info="
6LIBRARY: mprimdec.lib   PROCEDURES FOR PRIMARY DECOMPOSITION OF MODULES
7AUTHORS:  Alexander Dreyer, dreyer@mathematik.uni-kl.de; adreyer@web.de
8
9OVERVIEW:
10 Algorithms for primary decomposition for modules based on
11 the algorithms of Gianni, Trager and Zacharias and
12 Shimoyama and Yokoyama (generalization of the latter
13 suggested by Hans-Gert Graebe, Leipzig  )
14 using elements of primdec.lib
15
16REMARK:
17These procedures are implemented to be used in characteristic 0.
18@*They also work in positive characteristic >> 0.
19@*In small characteristic and for algebraic extensions, the
20procedures via Gianni, Trager, Zacharias may not terminate.
21
22PROCEDURES:
23  separator(l);                computes a list of separators of prime ideals
24  PrimdecA(N[,i]);             (not necessarily minimal) primary decomposition
25                               via Shimoyama/Yokoyama (suggested by Graebe)
26  PrimdecB(N,p);               (not necessarily minimal) primary decomposition
27                               for pseudo-primary ideals
28  modDec(N[,i]);               minimal primary decomposition
29                               via Shimoyama/Yokoyama (suggested by Graebe)
30  zeroMod(N[,check]);          minimal zero-dimensional primary decomposition
31                               via Gianni, Trager and Zacharias
32  GTZmod(N[,check]);           minimal primary decomposition
33                               via Gianni, Trager and Zacharias
34  dec1var(N[,check[,ann]]);    primary decomposition for one variable
35  annil(N);                    the annihilator of M/N in the basering
36  splitting(N[,check[,ann]]);  splitting to simpler modules
37  primTest(i[,p]);             tests whether i is prime or homogeneous
38  preComp(N,check[,ann]);      enhanced Version of splitting
39  indSet(i);                   lists with varstrings of(in)dependent variables
40  GTZopt(N[,check[,ann]]);     a faster version of GTZmod
41  zeroOpt(N[,check[,ann]]);    a faster version of zeroMod
42
43KEYWORDS: primary decomposition of modules;decomposition of modules
44";
45
46LIB "primdec.lib";
47LIB "ring.lib";
48
49
50/////////////////////////////////////////////////////////////////////////////
51// separator(l)
52// computes a list of separators for a list of prime ideals
53// it in a generalization of parts of pseudo_prim_dec_i from primdec.lib
54/////////////////////////////////////////////////////////////////////////////
55
56proc separator (list @L)
57"USAGE:   separator(l); list l of prime ideals
58RETURN:  list sepList;
59         a list of separators of the prime ideals in l,
60         i.e. polynomials p_ij, s.th. p_ij is in l[j],
61         for all l[j] not contained in l[i]
62         but p_ij is not in l[i]
63EXAMPLE: example separator; shows an example
64"
65
66{
67  ideal p_ij;                        // generating p_ij in @L[@j], not in @L[@i]
68  list f_i;                        // generating f_i NOT in @L[@i], but in all @L[@j]
69  int @i,@j,@k;
70  int sizeL=size(@L);
71  poly @tmp;
72
73  for(@i=1;@i<=sizeL;@i++)
74  {
75    p_ij=0;
76
77    @L[@i]=std(@L[@i]);
78    for(@j=1;@j<=sizeL;@j++)            // compute the separator sep_i
79                                        // of the i-th component
80                                        // f_i separates {Pj not incl in Pi} from Pi
81    {
82      if (@i!=@j)                       // searching for g: not in @L[@i], but @L[@j]
83      {
84        for(@k=1;@k<=ncols(@L[@j]);@k++)
85        {
86          if(NF(@L[@j][@k],@L[@i],1)!=0)
87          {
88            p_ij=p_ij+@L[@j][@k];
89            break;
90          }
91        }
92      }
93    }
94  @tmp=lcm(p_ij);
95  if(@tmp==0)
96  {
97    @tmp=1;
98  }
99  f_i=f_i+list(@tmp);
100  }
101  return(f_i);
102}
103example
104{ "EXAMPLE:"; echo = 2;
105  ring r=0,(x,y,z),dp;
106  ideal i=(x2y,xz2,y2z,z3);
107  list l=minAssGTZ(i);
108  list sepL=separator(l);
109  sepL;
110}
111
112/////////////////////////////////////////////////////////////////////////////
113// PrimdecA(N[,i])
114// computes a primary decomposition, not necessarily minimal,
115// using a generalization of the algorithm of Shimoyama/Yokoyama,
116// suggested by Hans-Gerd Graebe, Leipzig
117// [Hans-Gert Graebe, Minimal Primary Decomposition
118//  and Factorized Groebner Bases, AAECC 8, 265-278 (1997)]
119/////////////////////////////////////////////////////////////////////////////
120
121
122proc PrimdecA(module @N, list #)
123"USAGE:   PrimdecA (N[, i]); module N, int i
124RETURN:  list l
125         a (not necessarily minimal) primary decomposition of N
126         computed by a generalized version of the algorithm of Shimoyama/Yokoyama,
127         @*if i!=0 is given, the factorizing Groebner is used to compute the
128         isolated primes
129EXAMPLE: example PrimdecA; shows an example
130"
131
132{
133  module @M=freemodule(nrows(@N));        // @M=basering^k
134  ideal ann=annil(@N);                    // the annihilator of @N
135  ////////////////////////////////////////////////////////////////
136  // in the trivial case we avoid to compute anything
137  ////////////////////////////////////////////////////////////////
138  if (ann[1]==1)
139  {
140    return(list());
141  }
142  ////////////////////////////////////////////////////////////////
143  // Computation of the Associated Primes
144  ////////////////////////////////////////////////////////////////
145  if (ann[1]==0)
146  {
147    list pr=list(ideal(0));
148  }
149  else
150  {
151    if( (size(#)>0) ){
152      list pr = minAssChar(ann);   // causes message  "/ ** redefining @res **"
153    }
154    else{
155      list pr = minAssGTZ(ann);
156    }
157  }
158
159  list sp, pprimary;     // the separators and the pseudo-primary modules
160  int @i;
161  ideal rest;            // for the computation of the remaining components
162  sp=separator(pr);
163  int sizeSp=size(sp);   // the number of separators
164
165  ////////////////////////////////////////////////////////////////
166  // Computation of the pseudo-primary modules
167  // and an ideal rest s.th. @N is the intersection of the
168  // pseudo-primary modules and @N+rest*@M
169  ////////////////////////////////////////////////////////////////
170  for(@i=1;@i<=sizeSp;@i++)
171  {
172    pprimary=pprimary+list(sat(@N,sp[@i]));
173    rest=rest+sp[@i]^pprimary[@i][2];
174  }
175  list result;           // a primary decomposition of @N
176
177  ////////////////////////////////////////////////////////////////
178  // Extraction of the pseudo-primary modules
179  ////////////////////////////////////////////////////////////////
180  for (@i=1;@i<=size(pprimary);@i++)
181  {
182   result=result+PrimdecB(pprimary[@i][1],pr[@i]);
183  }
184
185  ////////////////////////////////////////////////////////////////
186  // Computation of remaining components
187  ////////////////////////////////////////////////////////////////
188  result=result+PrimdecA(@N+rest*@M);
189
190  return(result);
191}
192example
193{ "EXAMPLE:"; echo = 2;
194  ring r=0,(x,y,z),dp;
195  module N=x*gen(1)+ y*gen(2),
196           x*gen(1)-x2*gen(2);
197  list l=PrimdecA(N);
198  l;
199}
200
201
202/////////////////////////////////////////////////////////////////////////////
203// PrimdecB(N, p)
204// computes a primary decomposition, not necessarily minimal,
205// of a pseudo-primary module N with isolated prime p
206// it is based on extraction in primdec.lib
207/////////////////////////////////////////////////////////////////////////////
208
209proc PrimdecB(module @N, ideal isoPrim)
210"USAGE:   PrimdecB (N, p); pseudo-primary module N, isolated prime ideal p
211RETURN:  list l
212         a (not necessarily minimal) primary decomposition of N
213EXAMPLE: example PrimdecB; shows an example
214"
215
216{
217  module @M=freemodule(nrows(@N));        // @M=basering^k
218  ideal ann=annil(@N);                    // the annihilator of @N
219
220  ////////////////////////////////////////////////////////////////
221  // the not-that-trivial case of ann==0
222  ////////////////////////////////////////////////////////////////
223  if(size(ann)==0)
224  {
225    def BAS=basering;
226    ring Rloc = create_ring("("+charstr(basering)+","+varstr(basering)+")", "dummy", "(C,dp)");
227    module @N=imap(BAS, @N);
228    poly @q=prepareSat(@N);
229
230    setring BAS;
231    poly @q=imap(Rloc, @q);
232    list satu=sat(@N,@q);
233    if(satu[2]==0)
234    {
235      return(list(list(@N,ideal(0))));
236    }
237    else
238    {
239      return(list(list(satu[1],ideal(0)))+ PrimdecA(@N+(@q^satu[2])*@M));
240    }
241  }
242
243  ////////////////////////////////////////////////////////////////
244  // Extraction of the isolated component @N' and
245  // searching for a polynomial @f of minimal degree
246  // s.th. @N=intersect(@N', @N+@f*@M)
247  ////////////////////////////////////////////////////////////////
248  list indSets=indepSet(ann,0);
249  poly @f;
250  if(size(indSets)!=0)           //check, whether dim isoPrim !=0
251  {
252    intvec indVec;               // a maximal independent set of variables
253                                 // modulo isoPrim
254    string @U;                   // the independent variables
255    string @A;                   // the dependent variables
256    int @j,@k;
257    int szA;                     //  the size of @A
258    int degf;
259    ideal @g;
260    list polys;
261    int sizePolys;
262    list newPoly;
263
264    ////////////////////////////////////////////////////////////////
265    // the preparation of the quotient ring
266    ////////////////////////////////////////////////////////////////
267    def BAS=basering;
268    for (@k=1;@k<=size(indSets);@k++)
269    {
270      indVec=indSets[@k];
271      for (@j=1;@j<=nvars(BAS);@j++)
272      {
273        if (indVec[@j]==1)
274        {
275          @U=@U+varstr(@j)+",";
276        }
277        else
278        {
279          @A=@A+varstr(@j)+",";
280          szA++;
281        }
282      }
283
284      @U[size(@U)]=")";           // we compute the extractor (w.r.t. @U)
285      ring RAU = create_ring(ring_list(basering)[1],"("+@A+@U,"(C,dp("+string(szA)+"),dp)","no_minpoly");
286      module @N=std(imap(BAS,@N));
287                                  // this is also a standard basis in (R[U])[A]
288      @A[size(@A)]=")";
289      ring Rloc = create_ring("("+charstr(basering)+","+@U, "("+@A, "(C,dp)");
290      module @N=imap(RAU,@N);
291      ideal @h;
292      for(@j=ncols(@N);@j>=1;@j--)
293      {
294        @h[@j]=leadcoef(@N[@j]);  // consider I in (R(U))[A]
295      }
296      setring BAS;
297      @g=imap(Rloc,@h);
298      kill RAU,Rloc;
299      @U="";
300      @A="";
301      szA=0;
302      @f=lcm(@g);
303      newPoly[1]=@f;
304      polys=polys+newPoly;
305      newPoly=list();
306    }
307    @f=polys[1];
308    degf=deg(@f);
309    sizePolys=size(polys);
310    for (@k=2;@k<=sizePolys;@k++)
311    {
312      if (deg(polys[@k])<degf)
313      {
314        //Waehlt das poly mit dem geringsten Grad.
315        @f=polys[@k];
316        degf=deg(@f);
317      }
318    }
319  }
320  else
321  {
322    @f=1;
323  }
324  if(@f!=1)
325  {
326    list satu = minSatMod(@N,@f);
327    return(list(list(satu[1],isoPrim))+ PrimdecA(@N+satu[2]*@M));
328    //    list satu = sat(@N,@f);
329    //return(list(list(satu[1],isoPrim))+ PrimdecA(@N+@f^satu[2]*@M));
330  }
331  else
332  {
333    return(list(list(@N,isoPrim)));
334  }
335}
336example
337{ "EXAMPLE:"; echo = 2;
338  ring r=0,(x,y,z),dp;
339  module N=y*gen(1),y2*gen(2),yz*gen(2),yx*gen(2);
340  ideal p=y;
341  list l=PrimdecB(N,p);
342  l;
343}
344
345/////////////////////////////////////////////////////////////////////////////
346// modDec(N[,i])
347// extracts a minimal primary decomposition from the
348// primary decomposition computed by PrimdecA(N[, i])
349// using a Minimality Test suggested by Hans-Gerd Graebe, Leipzig
350/////////////////////////////////////////////////////////////////////////////
351
352proc modDec(module @N, list #)
353"USAGE:   modDec (N[, i]); module N, int i
354RETURN:  list l
355         a minimal primary decomposition of N
356         computed by an generalized version of the algorithm of Shimoyama/Yokoyama,
357         @*if i=1 is given, the factorizing Groebner basis algorithm is used internally.
358EXAMPLE: example modDec; shows an example
359"
360{
361  list prim = PrimdecA(@N, #);
362  int @i,@j,@k,@l;
363  int sizePrim=size(prim);
364
365  ////////////////////////////////////////////////////////////////
366  // the trivial case
367  ////////////////////////////////////////////////////////////////
368  if (sizePrim==0)
369  {
370    return(list(list(@N, ideal(1))));
371  }
372
373  ////////////////////////////////////////////////////////////////
374  // collect primary components with the same associated prime
375  // and substitute them by their intersection
376  ////////////////////////////////////////////////////////////////
377  for(@i=1;@i<=sizePrim;@i++)
378  {
379    for(@j=@i+1;@j<=sizePrim;@j++)
380    {
381      if (@j!=@i)
382      {
383        if (modulesEqual(prim[@i][2],prim[@j-@l][2])==1)
384        {
385          prim[@i][1]=intersect(prim[@i][1],prim[@j-@l][1]);
386          prim=delete(prim,@j-@l);
387          @l++;
388          sizePrim--;
389        }
390      }
391    }
392  }
393
394  ////////////////////////////////////////////////////////////////
395  // minimality test suggested by Graebe:
396  // if f separates the prime p from the primes not contained in p,
397  // then p is not in Ass(M/N) <=> sat(N,f)=sat(sat(N,f),p)
398  ////////////////////////////////////////////////////////////////
399  list tempList;
400  for(@i=1;@i<=sizePrim;@i++)
401  {
402    tempList=tempList+list(prim[@i][2]);
403  }
404  list sepPrimes=separator(tempList);   // the separators of the primes
405  tempList=list();
406  for(@i=1;@i<=sizePrim;@i++)     // compute sat(N,f), for all separators f
407  {
408    tempList=tempList+list(sat(@N,sepPrimes[@i])[1]);
409  }
410  module testMod;
411  @k=0;
412  for(@i=1;@i<=sizePrim;@i++)
413  {
414    testMod=sat(tempList[@i],prim[@i-@k][2])[1];  // computes sat(sat(N,f),p)
415    if (size(NF(testMod,std(tempList[@i]),1))==0) // tests if equal to sat(N,f)
416    {
417      prim=delete(prim,@i-@k);                    // if yes: the component
418      @k++;                                       // is superfluous
419    }
420  }
421
422  return(prim);
423}
424example
425{ "EXAMPLE:"; echo = 2;
426  ring r=0,(x,y,z),dp;
427  module N=x*gen(1)+ y*gen(2),
428           x*gen(1)-x2*gen(2);
429  list l=modDec(N);
430  l;
431}
432
433/////////////////////////////////////////////////////////////////////////////
434// zeroMod (N[, check])
435// computes a minimal primary decomposition of a zero-dimensional Module
436// using a generalized version of the algorithm of
437// Gianni, Trager and Zacharias, suggested by Alexander Dreyer
438// [Diploma Thesis, University of Kaiserslautern, 2001]
439/////////////////////////////////////////////////////////////////////////////
440
441proc zeroMod (module @N, list #)
442"USAGE:   zeroMod (N[, check]); zero-dimensional module N[, module check]
443RETURN:  list l
444         the minimal primary decomposition of a zero-dimensional module N,
445         computed by a generalized version of the algorithm of Gianni, Trager and Zacharias
446NOTE:    if the parameter check is given, only components not containing check are computed
447EXAMPLE: example zeroMod; shows an example
448"
449{
450  ////////////////////////////////////////////////////////////////
451  // the module check is needed to compute a minimal decomposition
452  // components containing check are ignored
453  ////////////////////////////////////////////////////////////////
454  if (size(#)>0)
455  {
456    module check=#[1];
457    if (size(NF(check,std(@N),1))==0)
458    {
459      return(list());
460    }
461  }
462  else
463  {
464    module check=freemodule(nrows(@N));
465  }
466
467  ////////////////////////////////////////////////////////////////
468  // the ordering is changed to lex
469  ////////////////////////////////////////////////////////////////
470  def BAS = basering;
471  def @R=changeord(list(list("lp",1:nvars(basering))));
472  setring @R;
473  module @N=fetch(BAS,@N);
474  int nVar=nvars(@R);
475  module @M=freemodule(nrows(@N));     // @M=basering^k
476  ideal ann=std(quotient(@N,@M));      // the annihilator of @M/@N
477  int @k;
478  list result, rest;
479  ideal primary, prim;
480  module primMod;
481
482  ////////////////////////////////////////////////////////////////
483  // the random coordnate change and its inverse
484  ////////////////////////////////////////////////////////////////
485  option(redSB);
486  ideal prepMap=maxideal(1);
487  prepMap[nVar]=0;
488  prepMap[nVar]=(random(100,1,nVar)*transpose(prepMap))[1,1]+var(nVar);
489  map phi=@R,prepMap;
490  prepMap[nVar]=2*var(nVar)-prepMap[nVar];
491  map invphi=@R,prepMap;
492
493  ideal @j=std(phi(ann));
494
495  list fac=factorize(@j[1],2);   // factorization of the 1st elt. in Ann(@N)
496
497  ////////////////////////////////////////////////////////////////
498  // Case: 1st element irreducible
499  ////////////////////////////////////////////////////////////////
500  if(size(fac[2])==1)
501  {
502    prim=primaryTest(@j,fac[1][1]);
503    prim=invphi(prim);
504    setring BAS;
505    @N=std(@N);
506    ideal prim=std(imap(@R,prim));
507    kill @R;
508    if(prim!=0)
509    {
510      return(list(list(@N,prim)));
511    }
512    else
513    {
514      return(zeroMod(@N,check));
515    }
516   }
5172;
518  ////////////////////////////////////////////////////////////////
519  // Computation of the - hopefully primary - modules
520  // their annihilators and associated primes
521  ////////////////////////////////////////////////////////////////
522  poly @p, @h;
523  module check;
524  for (@k=1;@k<=size(fac[1]);@k++)
525  {
526    @p=fac[1][@k]^fac[2][@k];
527    @h=@j[1]/@p;
528    primMod=std(quotient(phi(@N),@h));
529    check=imap(BAS,check);
530    check=phi(check);
531    if (size(NF(check,primMod,1))>0)
532    {
533      primary=std(@j+@p);
534      // test if the modules were primary and in general position
535      prim=primaryTest(primary,fac[1][@k]);
536      if (prim==0)
537      {
538            rest[size(rest)+1]=invphi(primMod);
539      }
540      else
541      {
542            result[size(result)+1]=list(std(invphi(primMod)),std(invphi(prim)));
543      }
544
545    }
546  }
547
548  ////////////////////////////////////////////////////////////////
549  // the bad cases
550  ////////////////////////////////////////////////////////////////
551
552  for (@k=1; @k<=size(rest);@k++)
553  {
554    result = result+zeroMod(rest[@k],invphi(check));
555  }
556
557  option(noredSB);
558  setring BAS;
559  list result=imap(@R, result);
560  kill @R;
561  return(result);
562}
563example
564{ "EXAMPLE:"; echo = 2;
565  ring r=0,z,dp;
566  module N=z*gen(1),(z-1)*gen(2),(z+1)*gen(3);
567  list l=zeroMod(N);
568  l;
569}
570
571
572/////////////////////////////////////////////////////////////////////////////
573// GTZmod (N[, check])
574// computes a minimal primary decomposition of N
575// using a generalized version of the algorithm of
576// Gianni, Trager and Zacharias, suggested by Alexander Dreyer
577// [Diploma Thesis, University of Kaiserslautern, Germany, 2001]
578/////////////////////////////////////////////////////////////////////////////
579
580proc GTZmod (module @N, list #)
581"USAGE:   GTZmod (N[, check]); module N[, module check]
582RETURN:  list l
583         the minimal primary decomposition of the module N,
584         computed by a generalized version of the algorithm of Gianni, Trager and Zacharias
585NOTE:    if the parameter check is given, only components not containing check are computed
586EXAMPLE: example GTZmod; shows an example
587"
588{
589  if (size(@N)==0)
590  {
591    return(list(@N,ideal(0)));
592  }
593
594  ////////////////////////////////////////////////////////////////
595  // the module check is needed to compute a minimal decomposition
596  // components containing check are ignored
597  ////////////////////////////////////////////////////////////////
598  if (size(#)>0)
599  {
600    module check=#[1];
601    if (size(NF(check,std(@N),1))==0)
602    {
603      return(list());
604    }
605  }
606  else
607  {
608    module check= freemodule(nrows(@N));
609  }
610
611  module @M=freemodule(nrows(@N));
612  def BAS = basering;
613  int @j;
614  int nVar=nvars(BAS);
615  int @k;
616  string @U;                       // the independent variables
617  string @A;                       // the dependent variables
618  @N=std(@N);
619  ideal ann=std(quotient(@N,@M));  // the annihilator of @M/@N
620
621
622  ////////////////////////////////////////////////////////////////
623  // the trivial and the zero-dimensional case
624  ////////////////////////////////////////////////////////////////
625  int Ndim=dim(@N);
626  if ((Ndim==0)||(Ndim==-1))
627  {
628    return(zeroMod(@N, check));
629  }
630
631  ////////////////////////////////////////////////////////////////
632  // the not-that-trivial case of ann==0
633  ////////////////////////////////////////////////////////////////
634  if(size(ann)==0)
635  {
636    ring Rloc = create_ring("("+charstr(basering)+","+varstr(basering)+")", "dummy", "(C,dp)");
637    module @N=imap(BAS, @N);
638    poly @q=prepareSat(@N);
639
640    setring BAS;
641    poly @q=imap(Rloc, @q);
642    list satu=sat(@N,@q);
643    if(satu[2]==0)
644    {
645      return(list(list(@N,ideal(0))));
646    }
647    else
648    {
649      check=intersect(check,satu[1]);
650      return(list(list(satu[1],ideal(0)))+GTZmod(@N+(@q^satu[2])*@M,check));
651    }
652  }
653
654  ////////////////////////////////////////////////////////////////
655  // the preparation of the quotient ring
656  ////////////////////////////////////////////////////////////////
657  intvec indVec=indepSet(ann);
658  int szA;
659  for (@k=1;@k<=size(indVec);@k++)
660  {
661    if (indVec[@k]==1)
662    {
663      @U=@U+varstr(@k)+",";
664    }
665    else
666    {
667      @A=@A+varstr(@k)+",";
668      szA++;
669    }
670  }
671  @U[size(@U)]=")";             // we compute the extractor (w.r.t. @U)
672  ring RAU = create_ring(ring_list(basering)[1],"("+@A+@U,"(C,dp("+string(szA)+"),dp)","no_minpoly");
673  module @N=std(imap(BAS,@N));  // this is also a standard basis in (R[U])[A]
674  @A[size(@A)]=")";
675  ring Rloc = create_ring("("+charstr(basering)+","+@U, "("+@A, "(C,dp)");
676  module @N=imap(RAU,@N);
677  kill RAU;
678
679  ////////////////////////////////////////////////////////////////
680  // the zero-dimensional decomposition
681  ////////////////////////////////////////////////////////////////
682  list qprim=zeroMod(@N,imap(BAS,check));
683
684  ////////////////////////////////////////////////////////////////
685  //  preparation for saturation
686  ////////////////////////////////////////////////////////////////
687  poly @q=prepareSat(@N);
688  if (size(qprim)==0)
689  {
690    setring BAS;
691    poly @q=imap(Rloc,@q);
692    kill Rloc;
693    @q=@q^sat(@N,@q)[2];
694    if (deg(@q)>0)
695    {
696      return(GTZmod(@N+@q*@M,check));
697    }
698    else
699    {
700      return(list());
701    }
702  }
703
704  list @p;
705  for (@k=1;@k<=size(qprim);@k++)
706  {
707    @p[@k]=list(prepareSat(qprim[@k][1]),prepareSat(qprim[@k][2]));
708  }
709
710  ////////////////////////////////////////////////////////////////
711  // compute the recontractions
712  // back in the original ring
713  ////////////////////////////////////////////////////////////////
714  setring BAS;
715  list @p=imap(Rloc,@p);
716  list qprim=imap(Rloc,qprim);
717  poly @q=imap(Rloc,@q);
718  kill Rloc;
719  for(@k=1;@k<=size(qprim);@k++)
720  {
721    qprim[@k]=list(sat(qprim[@k][1],@p[@k][1])[1],
722                   sat(qprim[@k][2],@p[@k][2])[1]);
723    check=intersect(check,qprim[@k][1]);
724  }
725  @q=@q^sat(@N,@q)[2];
726  if (deg(@q)>0)
727  {
728    qprim=qprim+GTZmod(@N+@q*@M,check);
729  }
730
731  return(qprim);
732}
733example
734{ "EXAMPLE:"; echo = 2;
735  ring r=0,(x,y,z),dp;
736  module N=x*gen(1)+ y*gen(2),
737           x*gen(1)-x2*gen(2);
738  list l=GTZmod(N);
739  l;
740}
741
742
743proc prepareSat(module @N, list #)
744
745{
746  int @k;
747  poly @p=leadcoef(@N[1]);
748  for (@k=2;@k<=size(@N);@k++)
749  {
750    @p=lcm_chr(@p,leadcoef(@N[@k]));
751    //    @p=@p*leadcoef(@N[@k]);
752  }
753  return(@p);
754}
755
756proc lcm_chr(poly @i, poly @j)
757
758{
759  def LBAS = basering;
760  if (npars(basering)==0)
761  {
762    string strg="";
763  }
764  else
765  {
766     if (nvars(basering)==0)
767     {
768       string strg=parstr(basering);
769     }
770     else
771     {
772       string strg=parstr(basering)+",";
773     }
774  }
775  ring PRing = create_ring(char(basering), "("+strg+varstr(basering)+")", "dp");
776  ideal @a=ideal(imap(LBAS,@i),imap(LBAS,@j));
777  poly @p=lcm(@a);
778  setring LBAS;
779  poly @p=imap(PRing,@p);
780  kill PRing;
781  return(@p);
782}
783
784///////////////////////////////////////////////////////////////////////
785// The optimized procedures and procedures needed for this optimization
786///////////////////////////////////////////////////////////////////////
787
788/////////////////////////////////////////////////////////////////////////////
789// testit (N, l)
790// a small procedure, which checks whether
791// N=intersect(l[1][1],...,l[size(l)][1])
792// and whether annil(l[i][1]) is primary
793// Just for testing the procedures.
794/////////////////////////////////////////////////////////////////////////////
795
796proc testit (module N, list #)
797"USAGE:   testit (N, l); module N, list l
798EXAMPLE: example testit; shows an example
799"
800{
801  if (size(#)==0)
802  {
803    return()
804  }
805  int i;
806  list l=#;
807  module nn=freemodule(nrows(N));
808  module M=freemodule(nrows(N));
809
810  for(i=1;i<=size(l);i++)
811  {
812    nn=intersect(nn,l[i][1]);
813    if ((size(decomp(quotient(l[i][1],M)))>2)&&(size(l[i][2])>0))
814    {
815     "nicht primary obwohl erkannt!";
816     l[i];std(quotient(l[i][1],M));std(radical(quotient(l[i][1],M)));
817      pause();
818     }
819  }
820  int j,k;
821  j=size(NF(nn,std(N),1));
822  k=size(NF(N,std(nn),1));
823  if ((j!=0)||(k!=0))
824  {
825    "testit fehler!!!";
826    pause();
827  }
828}
829example
830{ "EXAMPLE:"; echo = 2;
831  ring r=0,(x,y,z),dp;
832  module N=x*gen(1)+ y*gen(2),
833           x*gen(1)-x2*gen(2);
834  list l=GTZmod(N);
835  testit(N,l);
836}
837
838/////////////////////////////////////////////////////////////////////////////
839// annil (N)
840// computes the annihilator of M/N in the basering
841/////////////////////////////////////////////////////////////////////////////
842
843proc annil (module N)
844"USAGE:   annil(N);  modul N
845RETURN:  ideal ann=std(quotient(N,freemodule(nrows(N))));
846         the annihilator of M/N in the basering
847NOTE:    ann is a std basis in the basering
848EXAMPLE: example annil; shows an example
849"
850{
851 intvec optionsVec=option(get);
852 option (returnSB);
853 ideal ann=quotient(N,freemodule(nrows(N)));
854 attrib (ann, "isSB",1);
855 option (set,optionsVec);
856 return(ann);
857}
858example
859{ "EXAMPLE:"; echo = 2;
860  ring r=0,(x,y,z),dp;
861  module N=x*gen(1), y*gen(2);
862  ideal ann=annil(N);
863  ann;
864}
865
866/////////////////////////////////////////////////////////////////////////////
867//  splitting(N[,check[, ann]])
868//  INPUT:  a zero-dimensional module N, module check, ideal ann=annil(N)
869//          splitting computes an list of modules
870//          using the factorization of the elements of annil(N)
871//          s.th. N is equal to the intersections of these modules
872//          A prim test is used to check if the modules are primary
873//  OUTPUT: (l, check)
874/////////////////////////////////////////////////////////////////////////////
875
876proc splitting (module @N, list #)
877"USAGE:   splitting(N[,check[, ann]]);  modul N, module check, ideal ann
878RETURN:  (l, check) list l, module check
879         the elements of l consists of quadruples, where
880         [1] is of type module, [2], [3] and [4] are of type ideal,
881         s.th. the intersection of the modules is equal to the
882         zero-dimensional module N, furthermore l[j][3]=annil(l[j][1])
883         and l[j][4] contains internal ideal data;
884         if l[j][2]!=0 then the module l[j][1] is primary
885            with associated prime l[j][2], and check=intersect(check, l[j][1]) is computed
886NOTE:    if the parameter check is given, only components not containing
887         check are computed; if ann is given, ann is used instead of annil(N)
888EXAMPLE: example splitting; shows an example
889"
890{
891  ideal ann; module check, @M; int checked;
892  (ann, check, @M,checked)=getData(@N,#);
893  if(checked)
894  {
895    return(list());
896  }
897  if(size(#)>=3)
898  {
899    ideal splitPrime=#[3];
900  }
901  else
902  {
903    ideal splitPrime=ann;
904  }
905
906  list fact, result, splitTemp;
907  int @i,@k,@j,szFact;
908  for (@i=1;@i<=size(ann);@i++)
909  {
910    fact=factorize(ann[@i],2);
911    szFact=size(fact[2]);
912    // if the element is the power of an irreducible element
913    if(szFact==1)
914    {
915      if(vdim(ann)==deg(ann[@i]))
916      {
917        splitPrime=interred(splitPrime+ideal(fact[1][1]));
918        result=result+list(list(@N,splitPrime,ann,splitPrime));
919      }
920      else
921      {
922        splitPrime=interred(splitPrime+ideal(fact[1][1]));
923        if (homog(splitPrime))
924        {
925           result=result+list(list(@N,maxideal(1),ann,splitPrime));
926        }
927      }
928    }
929    else
930    {
931      if(gcdTest(fact[1]))       // Case: (f1,...,fk)=(1)
932      {
933        (splitTemp, check)=sp1(@N,fact,check,ann,splitPrime);
934        result=result+splitTemp;
935      }
936      else
937      {
938                                // if the element is not irreducible
939        (splitTemp, check)=sp2(@N,fact[1][1],check,ann,splitPrime);
940        result=result+splitTemp;
941      }
942    }
943  }
944  @i=1;@k=size(result);
945
946  ////////////////////////////////////////////////////////////////
947  // delete multiple Modules
948  ////////////////////////////////////////////////////////////////
949  while (@i<=@k)
950  {
951    @j=1;
952    while(@j<=@i-1)
953    {
954      if (stdModulesEqual(result[@j][1],result[@k][1]))
955      {
956        result=delete(result,@i);
957        @k--;@i--;break;
958      }
959      @j++;
960    }
961    @i++;
962  }
963  list rest;
964  @i=1;@k=size(result);
965
966  ////////////////////////////////////////////////////////////////
967  // if not primary then split the obtained modules once again
968  ////////////////////////////////////////////////////////////////
969  while (@i<=@k)
970  {
971    if (size(result[@i][2])==0)
972    {
973      rest=rest+list(list(result[@i][1],result[@i][3],result[@i][4]));
974      result=delete(result,@i);
975      @k--;@i--;
976    }
977    else
978    {
979      check=intersect(check,result[@i][1]);
980    }
981    @i++;
982  }
983  for(@i=1;@i<=size(rest);@i++)
984  {
985    (splitTemp,check)=splitting(rest[@i][1],check,rest[@i][2],rest[@i][3]);
986    result=result+splitTemp;
987  }
988
989  if (size(result)==0)
990  {
991    result=list(list(@N,ideal(0),ann,ann));
992  }
993  return(result, check);
994}
995example
996{ "EXAMPLE:"; echo = 2;
997  ring r=0,z,lp;
998  module N=z*gen(1), (z+1)*gen(2);
999  N=std(N);
1000  list l; module check;
1001  (l, check)=splitting(N);
1002  l;
1003  check;
1004}
1005
1006  ////////////////////////////////////////////////////////////////
1007  // sp1: splits a module as follows
1008  // (N+f*g*M)=intersect((N+f*M),(N+g*M)) if (f,g)=(1)
1009  ////////////////////////////////////////////////////////////////
1010
1011static proc sp1(module @N,list fact,list #)
1012{
1013  ideal ann; module check, @M; int @i;
1014  (ann, check, @M, @i)=getData(@N, #);
1015  if(size(#)>=3)
1016  {
1017    ideal splitPrime=#[3];
1018  }
1019  else
1020  {
1021    ideal splitPrime=ann;
1022  }
1023  list pr;
1024  module splitMod;
1025  ideal splitAnn, prim, tempPrime;
1026  for(@i=1;@i<=size(fact[2]);@i++)
1027  {
1028    splitMod=std(@N+(fact[1][@i]^fact[2][@i])*@M);
1029    if(size(NF(check,splitMod,1))>0)
1030    {
1031      splitAnn=std(ann,(fact[1][@i]^fact[2][@i]));
1032      tempPrime=interred(splitPrime+ideal(fact[1][@i]));
1033      prim=primTest(splitAnn,fact[1][@i],tempPrime);
1034      pr=pr+list(list(splitMod,prim,splitAnn,tempPrime));
1035      if (size(prim)>0)
1036      {
1037        check=intersect(check,splitMod);
1038      }
1039    }
1040  }
1041  return (pr, check);
1042}
1043
1044  ////////////////////////////////////////////////////////////////
1045  // sp2: splits a module as follows
1046  // N=intersect((N:f),(N+f*M))
1047  ////////////////////////////////////////////////////////////////
1048
1049static proc sp2(module @N,  poly p, list #)
1050{
1051  ideal ann; module check, @M; int @i;
1052  (ann, check, @M, @i)=getData(@N, #);
1053  if(size(#)>=3)
1054  {
1055    ideal splitPrime=#[3];
1056  }
1057  else
1058  {
1059    ideal splitPrime=ann;
1060  }
1061  list fact=sat(@N, p);
1062  list splitList;
1063  ideal splitAnn, prim, tempPrime;
1064  if (fact[2]>0)
1065  {
1066   module n1=std(@N+(p^fact[2]*@M));
1067   module n2=fact[1];
1068   if (size(NF(check,n1,1))>0)
1069   {
1070    splitAnn=std(ann+ideal(p^fact[2]));
1071    tempPrime=interred(splitPrime+ideal(p));
1072    prim=primTest(tempPrime);
1073    splitList=list(list(n1, prim, splitAnn,tempPrime));
1074    if(size(prim)>0)
1075    {
1076      check=intersect(check, n1);
1077    }
1078   }
1079   if(size(NF(check,n2,1))>0)
1080   {
1081    splitAnn=annil(n2);
1082    prim=primTest(splitAnn);
1083    splitList=splitList+list(list(n2,prim,splitAnn,splitAnn));
1084    if(size(prim)>0)
1085    {
1086    check=intersect(check, n2);
1087    }
1088   }
1089   return(splitList, check);
1090  }
1091  else
1092  {
1093   return (list(list(@N,ideal(0),ideal(0))), check);
1094  }
1095}
1096
1097/////////////////////////////////////////////////////////////////////////////
1098//  primeTest(i[, p])
1099//  tests whether i is prime or homogeneous
1100//  is both cases radical(i) is returned
1101/////////////////////////////////////////////////////////////////////////////
1102
1103proc primTest(ideal id, list #)
1104"USAGE:   primTest(i[, p]); a zero-dimensional ideal i, irreducible poly p in i
1105RETURN:  if i is neither prime nor homogeneous then ideal(0) is returned,
1106         otherwise radical(i)
1107EXAMPLE: example primTest; shows an example
1108"
1109{
1110  ideal tempPrime;
1111  int testTempPrime;
1112  if (size(#)>0)
1113  {
1114    poly @p=#[1];
1115    if(size(#)>1)
1116    {
1117      tempPrime=#[2];
1118      testTempPrime=1;
1119    }
1120  }
1121  else
1122  {
1123    poly @p=0;
1124
1125  }
1126  ideal prim=ideal(0);
1127  if((size(#)>0)&&(vdim(id)==deg(@p)))
1128  {
1129    prim=id;
1130  }
1131  else
1132  {
1133    if ((homog(id))||((testTempPrime)&&(homog(tempPrime))))
1134    {
1135      prim=maxideal(1);
1136    }
1137  }
1138  return (prim);
1139}
1140example
1141{ "EXAMPLE:"; echo=2;
1142  ring r=0,(x,y,z),lp;
1143  ideal i=x+1,y-1,z;
1144  i=std(i);
1145  ideal primId=primTest(i,z);
1146  primId;
1147
1148  i=x,z2,yz,y2;
1149  i=std(i);
1150  primId=primTest(i);
1151  primId;
1152}
1153
1154/////////////////////////////////////////////////////////////////////////////
1155// preComp(N, check[, ann])
1156// preComp is an enhanced version of splitting,
1157// but before computing splitting the first element of std(annil(N))
1158// is factorized and the obtained modules are tested for primarity
1159/////////////////////////////////////////////////////////////////////////////
1160
1161proc preComp (module @N, list #)
1162"USAGE:   preComp(N,check[, ann]);  modul N, module check, ideal ann
1163RETURN:  (l, check) list l, module check
1164         the elements of l consists of a triple with
1165         [1] of type module [2] and [3] of type ideal
1166         s.th. the intersection of the modules is equal to the
1167         zero-dimensional module N, furthermore l[j][3]=annil(l[j][1])
1168         if l[j][2]!=0 then the module l[j][1] is primary
1169            with associated prime l[j][2],
1170            and check=intersect(check, l[j][1]) is computed
1171NOTE:    only components not containing check are computed;
1172         if ann is given, ann is used instead of annil(N)
1173EXAMPLE: example preComp; shows an example
1174"
1175{
1176  def BAS=basering;
1177  def @R=changeord(list(list("C",0:1),list("lp",1:nvars(basering))));
1178  setring @R;
1179  module @N=std(imap(BAS,@N));
1180  ideal ann; module check, @M; int @k;
1181  (ann, check, @M, @k)=getData(@N,imap(BAS,#),1);
1182  list act,primary;
1183  ideal primid,helpid;
1184  module primmod;
1185
1186  ////////////////////////////////////////////////////////////////
1187  // the first element of the standardbase is factorized
1188  ////////////////////////////////////////////////////////////////
1189  if(deg(ann[1])>0)
1190  {
1191    act=factorize(ann[1],2);
1192  }
1193  else
1194  {
1195    setring BAS;
1196    module check=imap(@R,check);
1197    kill @R;
1198    return(list(), check);
1199  }
1200
1201  ////////////////////////////////////////////////////////////////
1202  // with the factors new modules are created
1203  // (hopefully the primary decomposition)
1204  ////////////////////////////////////////////////////////////////
1205  if(size(act[1])>1)               // Case: act[1] not irreducible
1206  {
1207     for(@k=1;@k<=size(act[1]);@k++)
1208     {
1209       primmod=std(@N+(act[1][@k]^act[2][@k])*@M);
1210       if (size(NF(check,primmod,1))>0)
1211       {
1212         primid=std(ann,act[1][@k]^act[2][@k]);
1213         if((act[2][@k]==1)&&(vdim(primid)==deg(act[1][@k])))
1214         {
1215           primary = primary+list(list(primmod,primid,primid));
1216         }
1217         else
1218         {
1219           helpid=primid;
1220           primid=primaryTest(primid,act[1][@k]);
1221           primary = primary+list(list(primmod,primid,helpid));
1222         }
1223       }
1224       if (size(primid)>0)
1225       {
1226         check=intersect(check, primmod);
1227       }
1228     }
1229   }
1230   else                            // Case: act[1]  irreducible
1231   {
1232     primid=ann;
1233     primmod=@N;
1234
1235     if (size(NF(check,primmod,1))>0)
1236     {
1237       if((act[2][1]==1)&&(vdim(primid)==deg(act[1][1])))
1238       {
1239         primary = primary+list(list(primmod,primid,primid));
1240       }
1241       else
1242       {
1243         primid = primaryTest(primid,act[1][1]);
1244         primary = primary+list(list(primmod,primid,ann));
1245       }
1246       if (size(primid)>0)
1247       {
1248         check=intersect(check,primmod);
1249       }
1250     }
1251  }
1252
1253  if (size(primary)==0)
1254  {
1255    setring BAS;
1256    module check=imap(@R,check);
1257    kill @R;
1258    return(list(), check);
1259  }
1260
1261  ////////////////////////////////////////////////////////////////
1262  // the modules which are not primary are split
1263  ////////////////////////////////////////////////////////////////
1264  list splitTemp;
1265  int sz=size(primary);
1266  @k=1;
1267  while (@k<=sz)
1268  {
1269    if (size(primary[@k][2])==0)
1270    {
1271      (splitTemp, check)=splitting(primary[@k][1],check,primary[@k][3]);
1272      primary = delete(primary, @k)+splitTemp;
1273      @k--;sz--;
1274    }
1275    @k++;
1276  }
1277
1278  setring BAS;
1279  list primary=imap(@R,primary);
1280  module check=imap(@R,check);
1281  kill @R;
1282  return(primary,check);
1283}
1284example
1285{ "EXAMPLE:"; echo = 2;
1286  ring r=0,z,lp;
1287  module N=z*gen(1), (z+1)*gen(2);
1288  N=std(N);
1289  list l; module check;
1290  (l, check)=preComp(N,freemodule(2));
1291  l;
1292  check;
1293}
1294
1295/////////////////////////////////////////////////////////////////////////////
1296// indSet(i)
1297// based on independendSet from primdec.lib
1298/////////////////////////////////////////////////////////////////////////////
1299
1300proc indSet (ideal @j)
1301"USAGE:   indSet(i); i ideal
1302RETURN:  list with two entries
1303         both are lists of new varstrings with the dependent variables,
1304         the independent set, the ordstring with the corresp. block ordering,
1305         and the integer where the independent set starts in the varstring
1306NOTE:    the first entry gives the strings for all maximal independent sets
1307         the second gives the strings for the independent sets,
1308         which cannot be enhanced
1309EXAMPLE: example indSet; shows an example
1310"
1311{
1312   int n,k,di;
1313   int jdim=dim(@j);
1314   list maxind, rest,hilf;
1315   string var1,var2;
1316   list v=indepSet(@j,1);
1317
1318   for(n=1;n<=size(v);n++)
1319   {
1320      di=0;
1321      var1="";
1322      var2="";
1323      for(k=1;k<=size(v[n]);k++)
1324      {
1325         if(v[n][k]!=0)
1326         {
1327            di++;
1328            var2=var2+string(var(k))+",";
1329         }
1330         else
1331         {
1332            var1=var1+string(var(k))+",";
1333         }
1334      }
1335      if(di>0)
1336      {
1337         var1=var1[1..size(var1)-1];
1338         var2=var2[1..size(var2)-1];
1339         hilf[1]=var1;
1340         hilf[2]=var2;
1341         hilf[3]="(C,dp("+string(nvars(basering)-di)+"),dp)";
1342         //"lp("+string(nvars(basering)-di)+"),dp("+string(di)+")";
1343         hilf[4]=di;
1344         if(di==jdim)
1345         {
1346          maxind=maxind+list(hilf);
1347         }
1348         else
1349         {
1350          rest=rest+list(hilf);
1351         }
1352     }
1353      else
1354      {
1355
1356        if(jdim==0)
1357         {
1358          maxind=maxind+list(varstr(basering),"dummy",ordstr(basering),0);
1359         }
1360         else
1361         {
1362          rest=rest+list(varstr(basering),"dummy",ordstr(basering),0);
1363         }
1364         resu[n]=varstr(basering),ordstr(basering),0;
1365      }
1366   }
1367   return(list(maxind,rest));
1368}
1369example
1370{ "EXAMPLE:"; echo = 2;
1371   ring s1=(0,x,y),(a,b,c,d,e,f,g),lp;
1372   ideal i=ea-fbg,fa+be,ec-fdg,fc+de;
1373   i=std(i);
1374   list  l=indSet(i);
1375   l;
1376}
1377
1378/////////////////////////////////////////////////////////////////////////////
1379// GTZopt(N[,check[, ann]])
1380// a faster version of GTZMod
1381/////////////////////////////////////////////////////////////////////////////
1382
1383proc GTZopt (module @N, list #)
1384"USAGE:   GTZopt (N[, check]); module N[, module check]
1385RETURN:  list l
1386         the minimal primary decomposition of the module N,
1387         computed by a generalized and optimized version of
1388         the algorithm of Gianni, Trager and Zacharias
1389NOTE:    if the parameter check is given, only components
1390         not containing check are computed
1391EXAMPLE: example GTZmod; shows an example
1392"
1393{
1394  @N=std(@N);
1395  if (size(@N)==0)
1396  {
1397    return(list(@N,ideal(0)));
1398  }
1399
1400  ////////////////////////////////////////////////////////////////
1401  // the module check is needed to compute a minimal decomposition
1402  // components containing check are ignored
1403  ////////////////////////////////////////////////////////////////
1404  ideal ann; module check, @M; int checked;
1405  (ann, check, @M, checked)=getData(@N, #);
1406  if (checked)
1407  {
1408    return(list());
1409  }
1410
1411  ////////////////////////////////////////////////////////////////
1412  // if ann is zero-dimensional and homogeneous
1413  // then it is primary with associated prime maxideal(1)
1414  ////////////////////////////////////////////////////////////////
1415  if((homog(ann)==1)&&(dim(ann)==0))
1416  {
1417    return(list(list(@N,maxideal(1))));
1418  }
1419
1420  ////////////////////////////////////////////////////////////////
1421  // the not-that-trivial case of ann==0
1422  ////////////////////////////////////////////////////////////////
1423  def BAS = basering;
1424  if(size(ann)==0)      //check, whether ann=0
1425  {
1426   ring Rloc = create_ring("("+charstr(basering)+","+varstr(basering)+")", "dummy", "(C,dp)");
1427   module @N=clrSBmod(imap(BAS, @N));
1428   module @M=freemodule(nrows(@N));
1429   poly @q=prepareSat(@N);
1430
1431   setring BAS;
1432   poly @q=imap(Rloc, @q);
1433   list satu=sat(@N,@q);
1434
1435   if(satu[2]==0)
1436   {
1437     return(list(list(@N,ideal(0))));
1438   }
1439   else
1440   {
1441    check=intersect(check,satu[1]);
1442    return(list(list(satu[1],ideal(0)))+GTZopt(@N+(@q^satu[2])*@M,check));
1443   }
1444  }
1445
1446  int @k1, @k2, @k3, @k4;   // the indices for nested for/while loops
1447  int nVar=nvars(BAS);
1448  int Ndim=dim(@N);
1449
1450  ////////////////////////////////////////////////////////////////
1451  // Simplification of the modules using
1452  // N=N/(a*x_i+b)*M+(a*x_i+b)*M, for (a*x_i+b) in ann
1453  ////////////////////////////////////////////////////////////////
1454  if (size(#)==0)
1455  {
1456    ideal fried;
1457    @k2=size(ann);
1458    for(@k1=1;@k1<=@k2;@k1++)
1459    {
1460      if(deg(lead(ann[@k1]))==1)
1461      {
1462        fried[size(fried)+1]=ann[@k1];
1463      }
1464    }
1465    if(size(fried)==nVar)
1466    {
1467       return(list(list(@N, ann)));
1468    }
1469    if(size(fried)>0)
1470    {
1471       string newva;
1472       string newma;
1473       for(@k1=1;@k1<=nVar;@k1++)
1474       {
1475          checked=0;
1476          for(@k2=1;@k2<=size(fried);@k2++)
1477          {
1478             if(leadmonom(fried[@k2])==var(@k1))
1479             {
1480                checked=1;
1481                break;
1482             }
1483          }
1484          if(checked==0)
1485          {
1486            newva=newva+string(var(@k1))+",";
1487            newma=newma+string(var(@k1))+",";
1488          }
1489          else
1490          {
1491            newma=newma+string(var(@k1)-((1/leadcoef(fried[@k2]))*fried[@k2]))+",";
1492          }
1493       }
1494       newva[size(newva)]=")";
1495       newma[size(newma)]=";";
1496       ring @deirf = create_ring(ring_list(BAS)[1],"("+newva,"(C,lp)","no_minpoly");
1497       execute("map @kappa=BAS,"+newma);
1498       ideal @j = @kappa(ann);
1499       module @N = @kappa(@N);
1500       @N=simplify(@N,2);
1501       @j=simplify(@j,2);
1502       list pr=GTZopt(@N,freemodule(nrows(@N)),@j);
1503       setring BAS;
1504       list pr=imap(@deirf,pr);
1505
1506       for(@k1=1;@k1<=size(pr);@k1++)
1507       {
1508         pr[@k1][1]=std(pr[@k1][1]+fried*@M);
1509         pr[@k1][2]=std(pr[@k1][2]+fried);
1510       }
1511       return(pr);
1512    }
1513  }
1514
1515  ////////////////////////////////////////////////////////////////
1516  // the trivial case
1517  ////////////////////////////////////////////////////////////////
1518  if(Ndim==-1)
1519  {
1520    return(list(list(@N,ideal(1))));
1521  }
1522
1523  ////////////////////////////////////////////////////////////////
1524  // the case of one variable
1525  ////////////////////////////////////////////////////////////////
1526  if(nVar==1)
1527  {
1528    return(dec1var(@N));
1529  }
1530
1531  ////////////////////////////////////////////////////////////////
1532  // the zerodimensional case
1533  ////////////////////////////////////////////////////////////////
1534  if (Ndim==0)
1535  {
1536    return(zeroOpt(@N, check, ann));
1537  }
1538
1539  ////////////////////////////////////////////////////////////////
1540  // the preparation of the quotient ring
1541  ////////////////////////////////////////////////////////////////
1542  list result;
1543  list indep =indSet(ann);
1544  poly @q;
1545  list @p,primary;
1546  ideal @h;
1547  int szIndep;
1548  for (@k1=1;@k1<=2;@k1++)
1549  {
1550    szIndep=size(indep[@k1]);
1551    for (@k2=1;@k2<=szIndep;@k2++)
1552    {
1553      ring RAU = create_ring(ring_list(basering)[1], "("+indep[@k1][@k2][1]+","+indep[@k1][@k2][2]+")", indep[@k1][@k2][3], "no_minpoly");
1554      module @N=std(imap(BAS,@N)); // the standard basis in (R[U])[A]
1555      ring Rloc = create_ring("("+charstr(basering)+","+indep[@k1][@k2][2]+")", "("+indep[@k1][@k2][1]+")", "(C,dp)");
1556      module @N=imap(RAU,@N); //std in lokalisierung
1557      @N=clrSBmod(@N);
1558      kill RAU;
1559
1560      ////////////////////////////////////////////////////////////////
1561      // the zero-dimensional decomposition
1562      ////////////////////////////////////////////////////////////////
1563      list qprim, preList;
1564      module check=imap(BAS, check);
1565      (preList,check)=preComp(@N,check);
1566      for (@k3=1; @k3<=size(preList); @k3++)
1567      {
1568        if(size(preList[@k3][2])>0)
1569        {
1570          qprim=qprim+list(list(preList[@k3][1],preList[@k3][2]));
1571        }
1572        else
1573        {
1574          checked=size(qprim);
1575          qprim=qprim+zeroOpt(preList[@k3][1], check, preList[@k3][3]);
1576          for(@k4=checked+1;@k4<=size(qprim);@k4++)
1577          {
1578            check=intersect(check, qprim[@k4][1]);
1579          }
1580        }
1581      }  // end of for(@k3...)
1582      kill preList;
1583
1584      ////////////////////////////////////////////////////////////////
1585      // Preparation of the saturation of @N
1586      ////////////////////////////////////////////////////////////////
1587      //poly pp=prepareSat(@N);
1588      ideal @h2;
1589      for (@k3=1;@k3<=size(@N);@k3++)
1590      {
1591        @h2[@k3]=leadcoef(@N[@k3]);
1592      }
1593
1594      if (size(qprim)==0)     // there aren't any new components
1595      {
1596        setring BAS;
1597        check=imap(Rloc,check);
1598        @h=imap(Rloc,@h2);
1599        @q=minSatMod(imap(BAS,@N),@h)[2];
1600        // @q=imap(Rloc,pp)^sat(imap(BAS,@N),imap(Rloc,pp))[2];
1601        kill Rloc;
1602        if (deg(@q)>0)
1603        {
1604          @N=std(@N+@q*@M);
1605          ann=std(ideal(ann+@q));
1606          kill qprim;
1607        }
1608      }
1609      else                    // there are new components
1610      {
1611        ////////////////////////////////////////////////////////////////
1612        // Preparation of the saturation of qprim
1613        ////////////////////////////////////////////////////////////////
1614        list @p2;
1615        for (@k3=1;@k3<=size(qprim);@k3++)
1616        {
1617          @p2[@k3]=list(prepareSat(qprim[@k3][1]),prepareSat(qprim[@k3][2]));
1618        }
1619
1620
1621        ////////////////////////////////////////////////////////////////
1622        // compute the recontractions
1623        // back in the original ring
1624        ////////////////////////////////////////////////////////////////
1625        setring BAS;
1626        @p=imap(Rloc,@p2);
1627        primary=imap(Rloc,qprim);
1628        @h=imap(Rloc,@h2);
1629        kill Rloc;
1630        for(@k3=1;@k3<=size(primary);@k3++)
1631        {
1632          primary[@k3]=list(sat(primary[@k3][1],@p[@k3][1])[1],
1633                            sat(primary[@k3][2],@p[@k3][2])[1]);
1634          check=intersect(check,primary[@k3][1]);
1635        }
1636        @q=minSatMod(imap(BAS,@N),@h)[2];
1637        result=result+primary;
1638        if (deg(@q)>0)
1639        {
1640          @N=std(@N+@q*@M);
1641          ann=std(ideal(ann+@q));
1642        }
1643      }                       // end of else
1644      if ((@k1==1)&&(@k2<szIndep)&&(Ndim>dim(ann)))
1645      {
1646        break;
1647      }
1648    }
1649  }
1650  return(result+GTZopt(@N,check,ann));
1651}
1652example
1653{ "EXAMPLE:"; echo = 2;
1654  ring r=0,(x,y,z),dp;
1655  module N=x*gen(1)+ y*gen(2),
1656           x*gen(1)-x2*gen(2);
1657  list l=GTZopt(N);
1658  l;
1659}
1660
1661
1662/////////////////////////////////////////////////////////////////////////////
1663// dec1var(N[,check[, ann]])
1664// primary decomposition for a ring with one variable
1665/////////////////////////////////////////////////////////////////////////////
1666
1667proc dec1var (module @N, list #)
1668"USAGE:   dec1var (N); zero-dimensional module N[, module check]
1669RETURN:  list l
1670         the minimal primary decomposition of a submodule N of R^s
1671         if nvars(R)=1
1672NOTE:    if the parameter check is given, only components not containing check are computed
1673EXAMPLE: example zeroMod; shows an example
1674"
1675{
1676  ideal ann; module @M, check; int checked;
1677  (ann, check, @M, checked)=getData(@N, #);
1678
1679  list fac = factorize(ann[1],2);
1680  if(size(fac[2])==1)
1681  {
1682   return(list(list(@N,ann)));
1683  }
1684  // comp of the primary modules, the primary ideals and the primes
1685  poly @h;
1686  module primod;
1687  list result;
1688  int @k;
1689  for (@k=1;@k<=size(fac[1]);@k++)
1690  {
1691    @h=ann[1]/(fac[1][@k]^fac[2][@k]);
1692    result =result+list(list(std(quotient(@N,@h)), std(ann,fac[1][@k])));
1693  }
1694    return(result);
1695}
1696example
1697{ "EXAMPLE:"; echo = 2;
1698  ring r=0,z,dp;
1699  module N=z*gen(1),(z-1)*gen(2),(z+1)*gen(3);
1700  list l=dec1var(N);
1701  l;
1702}
1703
1704/////////////////////////////////////////////////////////////////////////////
1705// zeroOpt(N[,check[, ann]])
1706// a faster version of zeroMod
1707/////////////////////////////////////////////////////////////////////////////
1708
1709proc zeroOpt (module @N, list #)
1710"USAGE:   zeroOpt (N[, check]); zero-dimensional module N[, module check]
1711RETURN:  list l
1712         the minimal primary decomposition of a zero-dimensional module N,
1713         computed by a generalized and optimized version of the algorithm
1714         of Gianni, Trager and Zacharias
1715NOTE:    if the parameter check is given, only components
1716         not containing check are computed
1717EXAMPLE: example zeroMod; shows an example
1718"
1719{
1720  @N=interred(@N);
1721  attrib(@N,"isSB",1);
1722
1723  ////////////////////////////////////////////////////////////////
1724  // the module check is needed to compute a minimal decomposition
1725  // components containing check are ignored
1726  ////////////////////////////////////////////////////////////////
1727  ideal ann; module @M, check; int checked;
1728  (ann, check, @M, checked)=getData(@N, #);
1729
1730  if (checked)
1731  {
1732    return(list());
1733  }
1734  ////////////////////////////////////////////////////////////////
1735  // the ordering is changed to lex
1736  ////////////////////////////////////////////////////////////////
1737  def BAS = basering;
1738  def @R=changeord(list(list("C",0:1),list("lp",1:nvars(basering))));
1739  setring @R;
1740  module @N=std(imap(BAS,@N));
1741  module @M=imap(BAS,@M);
1742  ideal ann=std(imap(BAS,ann));
1743  module check=imap(BAS,check);
1744
1745  ////////////////////////////////////////////////////////////////
1746  if(vdim(ann)==deg(ann[1]))           // if ann ist prime
1747  {
1748    list fact=factorize(ann[1],2);
1749    int k;ideal id;list result;
1750    module hilf;
1751    for(k=1;k<=size(fact[1]);k++)
1752    {
1753      id=ann;
1754      hilf=std(@N+(fact[1][k]^fact[2][k])*@M);
1755      id[1]=fact[1][k];
1756      if(size(NF(check,hilf,1))>0)
1757      {
1758        result=result+list(list(hilf,interred(id)));
1759      }
1760    }
1761    setring BAS;
1762    list result=imap(@R, result);
1763    kill @R;
1764    return(result);
1765
1766  }
1767
1768
1769  if (homog(ann))                      // if ann is homogeneous
1770  {                                    // then radical(ann)=maxideal(1)
1771    if(size(NF(check,@N,1))>0)
1772    {
1773      setring BAS;
1774      kill @R;
1775      return (list(list(@N,maxideal(1))));
1776    }
1777    else
1778    {
1779      setring BAS;
1780      kill @R;
1781      return(list());
1782    }
1783  }
1784
1785  ////////////////////////////////////////////////////////////////
1786  // the random coordnate change and its inverse
1787  // furthermore the module is simplified using
1788  // N=N/(a*x_i+b)+(a*x_i+b)*M, for a*x_i+b in ann
1789  ////////////////////////////////////////////////////////////////
1790  int nVar=nvars(@R);
1791  int @k, @k1;
1792  list result, rest;
1793  ideal primary, prim;
1794  module primmod;
1795  ideal fried;
1796  intvec optionsVec=option(get);
1797  option(redSB);
1798  ideal prepMap = randomLast(100);
1799  ideal prepInv=maxideal(1);
1800  for(@k=1;@k<=size(ann);@k++)
1801  {
1802    if(deg(lead(ann[@k]))==1)
1803    {
1804      fried[size(fried)+1]=ann[@k];
1805    }
1806  }
1807  if(size(fried)==nVar)
1808  {
1809    return(list(list(@N, ann)));
1810  }
1811  if(size(fried)>0)
1812  {
1813    for(@k=1;@k<@k1;@k1++)
1814    {
1815      for(@k1=1;@k1<=size(fried);@k1++)
1816      {
1817        if(leadmonom(fried[@k1])==var(@k))
1818        {
1819          prepMap[@k]=var(@k)+((1/leadcoef(fried[@k1]))*(var(@k)-fried[@k1]));
1820          prepMap[nVar]=subst(prepMap[nVar],var(@k),0);
1821          prepInv[@k]=fried[@k1];
1822        }
1823      }
1824    }
1825  }
1826  map phi=@R,prepMap;
1827  prepInv[nVar]=2*var(nVar)-prepMap[nVar];
1828  map invphi=@R,prepInv;
1829  ideal @j=std(phi(ann));         // factorization of the 1st elt. in Ann(@N)
1830  list fac = factorize(@j[1],2);
1831
1832  ////////////////////////////////////////////////////////////////
1833  // Case: 1st element irreducible
1834  ////////////////////////////////////////////////////////////////
1835  if(size(fac[2])==1)
1836  {
1837    prim=primaryTest(@j,fac[1][1]);
1838    prim=invphi(prim);
1839    setring BAS;
1840    @N=std(@N);
1841    ideal prim =imap(@R,prim);
1842    kill @R;
1843    if(prim!=0)
1844    {
1845      return(list(list(@N,prim)));
1846    }
1847    else
1848    {
1849      return(zeroOpt(@N,check));
1850    }
1851  }
1852
1853  ////////////////////////////////////////////////////////////////
1854  // Computation of the - hopefully primary - modules
1855  // their annihilators and associated primes
1856  ////////////////////////////////////////////////////////////////
1857  poly @p, @h;
1858  for (@k=1;@k<=size(fac[1]);@k++)
1859  {
1860    @p=fac[1][@k]^fac[2][@k];
1861    @h=@j[1]/@p;
1862    primmod=std(quotient(phi(@N),@h));
1863    check=phi(check);
1864    if (size(NF(check,primmod,1))>0)
1865    {
1866      primary=std(@j+@p);
1867      // test if the modules were primary and in general position
1868      prim=primTest(primary,fac[1][@k]);
1869      if(size(prim)==0)
1870      {
1871        prim=primaryTest(primary,fac[1][@k]);
1872      }
1873      if (prim==0)
1874      {
1875        rest[size(rest)+1]=invphi(primmod);
1876      }
1877      else
1878      {
1879        result[size(result)+1]=list(std(invphi(primmod)),std(invphi(prim)));
1880      }
1881    }
1882  }
1883
1884  ////////////////////////////////////////////////////////////////
1885  // the bad cases
1886  ////////////////////////////////////////////////////////////////
1887  for (@k=1; @k<=size(rest);@k++)
1888  {
1889    result = result+zeroOpt(rest[@k],check);
1890  }
1891  option (set,optionsVec);
1892  if(size(result)==0)
1893  {
1894    setring BAS;
1895    kill @R;
1896    return(list());
1897  }
1898  setring BAS;
1899  list result=imap(@R, result);
1900  kill @R;
1901
1902  return(result);
1903}
1904example
1905{ "EXAMPLE:"; echo = 2;
1906  ring r=0,z,dp;
1907  module N=z*gen(1),(z-1)*gen(2),(z+1)*gen(3);
1908  list l=zeroOpt(N);
1909  l;
1910}
1911
1912/////////////////////////////////////////////////////////////////////////////
1913// clrSBmod(N)
1914// Generalization of clearSB from primdec.lib
1915/////////////////////////////////////////////////////////////////////////////
1916
1917static proc clrSBmod (module @N)
1918"USAGE:   clrSBmod(N); N module which is SB ordered by monomial ordering
1919RETURN:  module = minimal SB
1920EXAMPLE: example clrSBmod; shows an example
1921"
1922{
1923  int @k,@j;
1924  list Nsizes;
1925  for (@k=1;@k<=size(@N);@k++)
1926  {
1927    Nsizes[@k]=size(@N[@k]);
1928  }
1929  module leadVec;
1930  int szN=size(@N);
1931  @j=0;
1932  while(@j<szN-1)
1933  {
1934    @j++;
1935    if(deg(@N[@j])>0)
1936    {
1937      leadVec=lead(@N[@j]);
1938      attrib(leadVec,"isSB",1);
1939      for(@k=@j+1;@k<=szN;@k++)
1940      {
1941        if(size(NF(lead(@N[@k]),leadVec,1))==0)
1942        {
1943          if((leadexp(leadVec[1])!=leadexp(@N[@k]))||(Nsizes[@j]<=Nsizes[@k]))
1944          {
1945            @N[@k]=0;
1946          }
1947          else
1948          {
1949            @N[@j]=0;
1950             break;
1951          }
1952        }
1953      }
1954    }
1955  }
1956  return(simplify(@N,2));
1957}
1958example
1959{ "EXAMPLE:"; echo = 2;
1960   ring  r = (0,a,b),(x,y,z),dp;
1961   module N1=ax2+y,a2x+y,bx;
1962   module N2=clrSBmod(N1);
1963   N2;
1964}
1965
1966
1967/////////////////////////////////////////////////////////////////////////////
1968// minSatMod(N, id)
1969// Generalization of minsat from primdec.lib
1970/////////////////////////////////////////////////////////////////////////////
1971
1972static proc minSatMod(module Nnew, ideal @h)
1973"USAGE:   minSatMod(N, I); module N, ideal I
1974RETURN:  list with 2 elements:
1975         [1]=sat(N,product(I))[1],
1976         [2]=p, the polynomial of minimal degree s.th. [1]=quotient(N,p)
1977EXAMPLE: example minSatMod; shows an example
1978"
1979{
1980   int @i,@k;
1981   poly @f=1;
1982   module Nold;
1983   ideal fac;
1984   list quotM,@l;
1985
1986   for(@i=1;@i<=ncols(@h);@i++)
1987   {
1988      if(deg(@h[@i])>0)
1989      {
1990         fac=fac+factorize(@h[@i],1);
1991      }
1992   }
1993   fac=simplify(fac,4);
1994   if(size(fac)==0)
1995   {
1996      @l=Nnew,1;
1997      return(@l);
1998   }
1999   fac=sort(fac)[1];
2000   for(@i=1;@i<=size(fac);@i++)
2001   {
2002      @f=@f*fac[@i];
2003   }
2004   quotM[1]=Nnew;
2005   quotM[2]=fac;
2006   quotM[3]=@f;
2007   @f=1;
2008   while(specialModulesEqual(Nold,quotM[1])==0)
2009   {
2010      if(@k>0)
2011      {
2012         @f=@f*quotM[3];
2013      }
2014      Nold=quotM[1];
2015      quotM=quotMinMod(quotM);
2016      @k++;
2017   }
2018   @l=quotM[1],@f;
2019   return(@l);
2020}
2021example
2022{ "EXAMPLE:"; echo = 2;
2023   ring  r = 0,(x,y,z),dp;
2024   module N=xy*gen(1);
2025   ideal h=yz,z2;
2026   list l=minSatMod(N,h);
2027   l;
2028}
2029
2030/////////////////////////////////////////////////////////////////////////////
2031// quotMinMod(N, fac, f)
2032// Generalization of quotMin from primdec.lib
2033/////////////////////////////////////////////////////////////////////////////
2034
2035proc quotMinMod(list tsil)
2036{
2037   int @i,@j,action;
2038   module verg;
2039   list @l;
2040   poly @g;
2041   intvec optionsVec;
2042
2043   module laedi=tsil[1];
2044   ideal fac=tsil[2];
2045   poly @f=tsil[3];
2046   optionsVec=option(get);
2047   option(returnSB);
2048   module star=quotient(laedi,@f);
2049   option(set,optionsVec);
2050   if(specialModulesEqual(star,laedi))
2051   {
2052      @l=star,fac,@f;
2053      return(@l);
2054   }
2055
2056   action=1;
2057   while(action==1)
2058   {
2059      if(size(fac)==1)
2060      {
2061         action=0;
2062         break;
2063      }
2064      for(@i=1;@i<=size(fac);@i++)
2065      {
2066        @g=1;
2067        verg=laedi;
2068
2069         for(@j=1;@j<=size(fac);@j++)
2070         {
2071            if(@i!=@j)
2072            {
2073               @g=@g*fac[@j];
2074            }
2075         }
2076         optionsVec=option(get);
2077         option(returnSB);
2078         verg=quotient(laedi,@g);
2079         option(set,optionsVec);
2080         if(specialModulesEqual(verg,star)==1)
2081         {
2082            @f=@g;
2083            fac[@i]=0;
2084            fac=simplify(fac,2);
2085            break;
2086         }
2087
2088         if(@i==size(fac))
2089         {
2090            action=0;
2091         }
2092      }
2093   }
2094   @l=star,fac,@f;
2095   return(@l);
2096}
2097
2098/////////////////////////////////////////////////////////////////////////////
2099// specialModulesEqual(N1,N2)
2100// Generalization of specialIdealsEqual from primdec.lib
2101/////////////////////////////////////////////////////////////////////////////
2102
2103static proc specialModulesEqual( module k1, module k2)
2104"USAGE:   specialModulesEqual(N1, N2) N1, N2 standard bases of modules,
2105         s.th. N1 is contained in N2 or vice versa
2106RETURN:  int i
2107         if (N1==N2) then i=1
2108         else i=0
2109EXAMPLE: example specialModulesEqual; shows an example
2110"
2111{
2112   int @j;
2113
2114   if(size(k1)==size(k2))
2115   {
2116      for(@j=1;@j<=size(k1);@j++)
2117      {
2118         if(leadexp(k1[@j])!=leadexp(k2[@j]))
2119         {
2120            return(0);
2121         }
2122      }
2123      return(1);
2124   }
2125   return(0);
2126}
2127example
2128{ "EXAMPLE:"; echo = 2;
2129   ring  r = 0,(x,y,z),dp;
2130   module N1=x*freemodule(2);
2131   module N2=xy*freemodule(2);
2132   int i=specialModulesEqual(N1,N2);
2133   i;
2134
2135   N2=N1;
2136   i=specialModulesEqual(N1,N2);
2137   i;
2138}
2139
2140/////////////////////////////////////////////////////////////////////////////
2141// sat2mod(N,i)
2142// Generalization of sat2 from primdec.lib
2143/////////////////////////////////////////////////////////////////////////////
2144
2145proc sat2mod (module id, ideal h1)
2146"USAGE:   sat2mod(id,j);  id ideal, j polynomial
2147RETURN:  saturation of id with respect to j (= union_(k=1...) of id:j^k)
2148NOTE:    result is a std basis in the basering
2149"
2150{
2151   int @k,@i;
2152   def @P= basering;
2153   if(ordstr(basering)[1,2]!="dp")
2154   {
2155      ring @Phelp = create_ring(ring_list(@P)[1],"("+varstr(@P)+")","(C,dp)","no_minpoly");
2156      module inew=std(imap(@P,id));
2157      ideal  @h=imap(@P,h1);
2158   }
2159   else
2160   {
2161      ideal @h=h1;
2162      module inew=std(id);
2163   }
2164   ideal fac;
2165
2166   for(@i=1;@i<=ncols(@h);@i++)
2167   {
2168     if(deg(@h[@i])>0)
2169     {
2170        fac=fac+factorize(@h[@i],1);
2171     }
2172   }
2173   fac=simplify(fac,4);
2174   poly @f=1;
2175   if(deg(fac[1])>0)
2176   {
2177      module iold;
2178
2179      for(@i=1;@i<=size(fac);@i++)
2180      {
2181        @f=@f*fac[@i];
2182      }
2183      intvec optionsVec=option(get)
2184      option(returnSB);
2185      while(specialModulesEqual(iold,inew)==0 )
2186      {
2187         iold=inew;
2188         if(deg(iold[size(iold)])!=1)
2189         {
2190            inew=quotient(iold,@f);
2191         }
2192         else
2193         {
2194            inew=iold;
2195         }
2196         @k++;
2197      }
2198      option(set,optionsVec);
2199      @k--;
2200   }
2201
2202   if(ordstr(@P)[1,2]!="dp")
2203   {
2204      setring @P;
2205      module inew=std(imap(@Phelp,inew));
2206      poly @f=imap(@Phelp,@f);
2207   }
2208   list L =inew,@f^@k;
2209   return (L);
2210}
2211
2212/////////////////////////////////////////////////////////////////////////////
2213// stdModulesEqual(N1,N2)
2214// Generalization of stdIdealsEqual from primdec.lib
2215/////////////////////////////////////////////////////////////////////////////
2216
2217static proc stdModulesEqual(module k1, module k2)
2218"USAGE:   stdModulesEqual(N1, N2) N1, N2 standard bases of modules,
2219RETURN:  int i
2220         if (N1==N2) then i=1
2221         else i=0
2222EXAMPLE: example stdModulesEqual; shows an example
2223"
2224{
2225   int @j;
2226
2227   if(size(k1)==size(k2))
2228   {
2229      for(@j=1;@j<=size(k1);@j++)
2230      {
2231         if(leadexp(k1[@j])!=leadexp(k2[@j]))
2232         {
2233            return(0);
2234         }
2235      }
2236      attrib(k2,"isSB",1);
2237      if(size(reduce(k1,k2,5))==0)
2238      {
2239         return(1);
2240      }
2241   }
2242   return(0);
2243}
2244example
2245{ "EXAMPLE:"; echo = 2;
2246   ring  r = 0,(x,y,z),dp;
2247   module N1=x*freemodule(2);
2248   module N2=xy*freemodule(2);
2249   int i=stdModulesEqual(N1,N2);
2250   i;
2251
2252   N2=N1;
2253   i=stdModulesEqual(N1,N2);
2254   i;
2255}
2256
2257/////////////////////////////////////////////////////////////////////////////
2258// ModulesEqual(N1,N2)
2259// Generalization of IdealsEqual from primdec.lib
2260/////////////////////////////////////////////////////////////////////////////
2261
2262static proc modulesEqual( module @k, module @j)
2263"USAGE:   modulesEqual(N1, N2) N1, N2 modules,
2264RETURN:  int i
2265         if (N1==N2) then i=1
2266         else i=0
2267EXAMPLE: example modulesEqual; shows an example
2268"
2269{
2270   return(stdModulesEqual(std(@k),std(@j)));
2271}
2272example
2273{ "EXAMPLE:"; echo = 2;
2274   ring  r = 0,(x,y,z),dp;
2275   module N1=x*freemodule(2);
2276   module N2=xy*freemodule(2);
2277   int i=stdModulesEqual(N1,N2);
2278   i;
2279
2280   N2=N1;
2281   i=modulesEqual(N1,N2);
2282   i;
2283}
2284example
2285{ "EXAMPLE:"; echo = 2;
2286   ring  r = 0,(x,y,z),dp;
2287   module N1=x*freemodule(2);
2288   module N2=xy*freemodule(2);
2289   int i=modulesEqual(N1,N2);
2290   i;
2291
2292   N2=N1;
2293   i=modulesEqual(N1,N2);
2294   i;
2295}
2296
2297static proc getData (module @N, list oldData, list #)
2298"USAGE:   getData(N, l[, noCheck]);  module N, list l[, int noCheck]
2299RETURN:  (ann, check, M, checked)
2300         ideal ann, module check, M, int checked
2301
2302         if l[1] is contained in N [and noCheck is not given]
2303            then checked=1, ann=ideal(0), check=0, M=0;
2304         else checked=0, M=freemodule(nrows(N)); check=l[1]
2305            (resp. check=M if l is an empty list) and
2306            if size(l)>1 then  ann=l[2] else ann is the annihilator of M/N.
2307
2308NOTE:    ann is a std basis in the basering
2309EXAMPLE: example getData; shows an example
2310"
2311{
2312  if (size(oldData)>0)
2313  {
2314    if ((size(#)==0)&&(size(NF(oldData[1],@N,1))==0))
2315    {
2316      return(ideal(0), 0 ,  0, 1);
2317    }
2318    module @M=freemodule(nrows(@N));
2319    if (size(oldData)>1)
2320    {
2321      ideal ann=oldData[2];
2322      attrib(ann,"isSB",1);
2323    }
2324    else
2325    {
2326      ideal ann=annil(@N);
2327    }
2328  }
2329  else
2330  {
2331   module @M=freemodule(nrows(@N));
2332   oldData[1]=@M;
2333   ideal ann=annil(@N);
2334  }
2335 return(ann, oldData[1], @M, 0);
2336}
2337example
2338{ "EXAMPLE:"; echo = 2;
2339   ring  r = 0,(x,y,z),lp;
2340   module N=x*gen(1),y*gen(2);
2341   N=std(N);
2342   ideal ann; module check, M; int checked; list l;
2343   (ann, check, M, checked)=getData(N,l);
2344   ann; check; M; checked;
2345
2346   l=list(check,ann);
2347   (ann, check, M, checked)=getData(N,l);
2348   ann; check; M; checked;
2349
2350   l=list(N);
2351   (ann, check, M, checked)=getData(N,l);
2352   ann; check; M; checked;
2353}
Note: See TracBrowser for help on using the repository browser.