source: git/Singular/LIB/standard.lib @ 80cf34

spielwiese
Last change on this file since 80cf34 was 80cf34, checked in by Hans Schönemann <hannes@…>, 17 years ago
*gmg: new standard.lib git-svn-id: file:///usr/local/Singular/svn/trunk@9809 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 64.8 KB
Line 
1//////////////////////////////////////////////////////////////////////////////
2//major revision Jan/Feb. 2007, GMG
3//////////////////////////////////////////////////////////////////////////////
4version="$Id: standard.lib,v 1.85 2007-02-02 18:51:33 Singular Exp $";
5category="Miscellaneous";
6info="
7LIBRARY: standard.lib   Procedures which are always loaded at Start-up
8
9PROCEDURES:
10 stdfglm(ideal[,ord])   standard basis of ideal via fglm [and ordering ord]
11 stdhilb(ideal[,h])     Hilbert driven Groebner basis of ideal
12 quotientList(L,...)    a list, say L, s.t. ring(L) creates a correct qring
13 par2varRing([i])       create a ring with pars to vars together with i
14 hilbRing([i])          create a ring containing the homogenized i
15 qslimgb(i)             computes a standard basis with slimgb in a qring
16 groebner(ideal,...)    standard basis using a heuristically chosen method
17 res(ideal/module,[i])  free resolution of ideal or module
18 sprintf(fmt,...)       returns fomatted string
19 fprintf(link,fmt,..)   writes formatted string to link
20 printf(fmt,...)        displays formatted string
21 weightKB(stc,dd,vl)    degree dd part of a kbase wrt. some weigths
22";
23
24//////////////////////////////////////////////////////////////////////////////
25
26proc stdfglm (ideal i, list #)
27"SYNTAX: @code{stdfglm (} ideal_expression @code{)} @*
28         @code{stdfglm (} ideal_expression@code{,} string_expression @code{)}
29TYPE:    ideal
30PURPOSE: computes the standard basis of the ideal in the basering
31         via @code{fglm} (from the ordering given as the second argument
32         to the ordering of the basering).@*
33         If no second argument is given, \"dp\" is used.
34SEE ALSO: fglm, groebner, std, stdhilb
35KEYWORDS: fglm
36EXAMPLE: example stdfglm; shows an example"
37{
38    //### ev. erweitern: Gewichte von aussen setzen
39    string os;
40    int s = size(#);
41    def P= basering;
42    if( s==0 or (typeof(#[1]) != "string") )
43    {
44       os = "dp(" + string( nvars(P) ) + ")";
45       if ( (find( ordstr(P), os ) != 0) and (find( ordstr(P), "a") == 0) )
46       {
47          os= "Dp";
48       }
49       else
50       {
51          os= "dp";
52       }
53    }
54    else { os = #[1]; }
55
56    list BRlist = ringlist(P);
57    int nvarP = nvars(P);
58    intvec w;                       //for ringweights of basering P
59    int k;
60    for(k=1;  k<=nvarP; k++)
61    {
62       w[k]=deg(var(k));
63    }
64
65    BRlist[3] = list();
66    if( s==0 )
67    {
68      if( w==1 )
69      {
70         BRlist[3][1]=list("dp",w);
71      }
72      else
73      {
74         BRlist[3][1]=list("wp",w);
75      }
76      BRlist[3][2]=list("C",intvec(0));
77      def Pfglm = ring(quotientList(BRlist));
78      setring Pfglm;
79    }
80    else
81    {
82       ideal Qideal = ideal(P);
83       int sQ = size(Qideal);
84       int sM = size(minpoly);
85       if ( sM!=0 )
86       {
87          string mpoly = string(minpoly);
88       }
89       if (sQ!=0 )
90       {
91         execute("ring Rfglm=("+charstr(P)+"),("+varstr(P)+"),"+os+";");
92         ideal Qideal = fetch(P,Qideal);
93         qring Pfglm = groebner(Qideal,"std","slimgb");
94       }
95       else
96       {
97          execute("ring Pfglm=("+charstr(P)+"),("+varstr(P)+"),"+os+";");
98       }
99       if ( sM!=0 )
100       {
101          execute("minpoly="+mpoly+";");
102       }
103    }
104    ideal i= fetch(P,i);
105
106    //save options:
107    int p_opt;
108    string s_opt = option();
109    if (find(s_opt, "prot"))  { p_opt = 1; }
110    intvec opt= option(get);
111
112    option(redSB);
113    //if(p_opt){"groebner in "+string(Pfglm);}
114    i = groebner(i,"std","slimgb");
115    option(set,opt);
116    setring P;
117    return (fglm(Pfglm,i));
118}
119example
120{ "EXAMPLE:"; echo = 2;
121   ring r=0,(x,y,z),lp;
122   ideal i=y3+x2,x2y+x2,x3-x2,z4-x2-y;
123   stdfglm(i);         //uses fglm from "dp" to "lp"
124
125   ring s = (0,x),(y,z,u,v),lp;
126// qring qs = std(y2-z3);        ### Bug in fglm mit qring
127   minpoly = x2+1;
128   ideal i = y3+x2,u2y+u2,u3-u2,z4-u2-y,v;
129   stdfglm(i,"Dp");     //uses fglm from "Dp" to "lp"
130}
131
132/////////////////////////////////////////////////////////////////////////////
133
134proc stdhilb(ideal i,list #)
135"SYNTAX: @code{stdhilb (} ideal_expression @code{)} @*
136         @code{stdhilb (} ideal_expression@code{,} intvec_expression @code{)}
137         @code{stdhilb (} ideal_expression@code{,} list of string_expressions
138               and intvec_expressin @code{)} @*
139TYPE:    ideal
140PURPOSE: Compute a Groebner basis of the ideal in the basering by using the
141         Hilbert driven Groebner basis algorithm.
142         If an argument of type string @code{\"std\"} resp. @code{\"slimgb\"}
143         is given, the standard basis computation uses @code{std} or
144         @code{slimgb}, otherwise a heuristically chosen method (default)
145THEORY:  If the ideal is not homogeneous compute first a Groebner basis
146         of the homogenization of the ideal, then the Hilbert function and,
147         finally, a Groebner basis in the original ring by using the
148         computed Hilbert function.@*
149         If the ideal is homogeneous and a second argument of type intvec
150         is given it will be used as 1st Hilbert function in the Hilbert
151         driven algorithm.
152NOTE:    'homogeneous' means weighted homogeneous with respect to the weights
153         w[i] of the variables var(i) of the basering.
154ASSUME:  The argument of type intvec is the 1st Hilbert series as computed
155         by @code{hilb} using an intvector w with w[i]=deg(var(i)).
156SEE ALSO: stdfglm, std, slimgb, groebner
157KEYWORDS: Hilbert function
158EXAMPLE: example stdhilb;  shows an example"
159{
160
161//--------------------- save data from basering --------------------------
162  def P=basering;
163  ideal Qideal = ideal(P);      //defining the quotient ideal if P is a qring
164  int was_qring;                //remembers if basering was a qring
165  int is_homog = homog(Qideal); //remembers if Qideal was homog (homog(0)=1)
166  is_homog = is_homog*homog(i); //check for homogeneity of i and Qideal
167  if (size(Qideal) > 0)
168  {
169     was_qring = 1;
170  }
171
172  // save ordering of basering P for later use
173  list ord_P = ringlist(P)[3];     //ordering of basering in ringlist
174  string ordstr_P = ordstr(P);     //ordering of basering as string
175  int nvarP = nvars(P);
176  intvec w;                        //for ringweights of basering P
177  int k,neg;
178  for(k=1;  k<=nvarP; k++)
179  {
180     w[k]=deg(var(k));
181     if(w[k] <= 0)
182     {
183       neg=1;
184     }
185  }
186
187  //save options:
188  int p_opt;
189  string s_opt = option();
190  if (find(s_opt, "prot"))  { p_opt = 1; }
191
192//--------------------- check the given method ---------------------------
193  string method;
194  list Method;
195  for (k=1; k<=size(#); k++)
196  {
197     if (typeof(#[k]) == "intvec")
198     {
199        intvec hi = #[k];
200     }
201     if (typeof(#[k]) == "string")
202     {
203       method = method + "," + #[k];
204       Method = Method + list(#[k]);
205     }
206  }
207
208  if (npars(P) > 0)             //clear denominators of parameters
209  {
210    for( k=ncols(i); k>0; k-- )
211    {
212       i[k]=cleardenom(i[k]);
213    }
214  }
215
216//---------- exclude cases to which stdhilb should no be applied  ----------
217//Note that quotient ideal of qring must be homogeneous too
218
219   if( find(ordstr_P,"s") || find(ordstr_P,"M")
220       || find(ordstr_P,"a") || (neg > 0) )
221   {
222      if( defined(hi) && is_homog )
223      {
224         if (p_opt){"std with given Hilbert function in basering";}
225         return( std(i,hi,w) );
226      }
227      if (p_opt){"stdhilb not implemented, use std in basering";}
228      //if ( neg ) // std can handle local and mixed orderings
229      //{
230      //  "//*** WARNING: non-positive ring weights, computation may not finish";
231      //}
232      return( std(i) );
233   }
234
235//------------------------ change to hilbRing ----------------------------
236
237     list hiRi = hilbRing(i);
238     intvec W = hiRi[2];
239     def Philb = hiRi[1];      //note: Philb is no qring and the predefined
240     setring Philb;            //ideal Id(1) in Philb is homogeneous
241
242//-------- compute Hilbert function of homogenized ideal in Philb ---------
243//Philb has only 1 block. There are three cases
244
245     string algorithm;       //possibilities: std, slimgb, stdorslimgb
246     //define algorithm:
247     if( find(method,"std") && !find(method,"slimgb") )
248     {
249        algorithm = "std";
250     }
251     if( find(method,"slimgb") && !find(method,"std") )
252     {
253         algorithm = "slimgb";
254     }
255     if( find(method,"std") && find(method,"slimgb") ||
256         (!find(method,"std") && !find(method,"slimgb")) )
257     {
258        algorithm = "stdorslimgb";
259     }
260
261     if ( algorithm=="std" || ( algorithm=="stdorslimgb" && char(P)>0 ) )
262     {
263        if (p_opt) {"std in ring " + string(Philb);}
264        intvec hi = hilb( std(Id(1)),1,W );
265     }
266     if ( algorithm=="slimgb" || ( algorithm=="stdorslimgb" && char(P)==0 ) )
267     {
268       intvec hi = hilb(qslimgb(Id(1)),1,W);
269     }
270
271   //------------- case where we need another intermediate ring -------------
272   //we add extra blocks for homogenizing variable @hilbRing@
273   //and for converted parameters
274
275      list BRlist = ringlist(Philb);
276      BRlist[3] = list();
277      int so = size(ord_P);
278      if( ord_P[so][1] =="c" || ord_P[so][1] =="C" )
279      {
280         list moduleord = ord_P[so];
281         so = so-1;
282      }
283      for (k=1; k<=so; k++)
284      {
285         BRlist[3][k] = ord_P[k];
286      }
287
288      BRlist[3][so+1] = list("dp",1);
289      w = w,1;
290
291      if( defined(moduleord) )
292      {
293        BRlist[3][so+2] = moduleord;
294      }
295
296//------ change to extended ring and compute std with hilbert series ------
297      def Phelp = ring(quotientList(BRlist));
298      setring Phelp;
299      ideal i = imap(Philb, Id(1));
300      kill Philb;
301
302      // compute std with Hilbert series
303      if (w ==1 )
304      {
305         if (p_opt){ "std with hilb in " + string(Phelp);}
306         i = std(i, hi);
307      }
308      else
309      {
310         if(p_opt){"std with weighted hilb in "+string(Phelp);}
311         i = std(i, hi, w);
312      }
313
314//-------------------- go back to original ring ---------------------------
315 //The main computation is done. Do not forget to simplfy before maping.
316
317      // subst 1 for homogenizing var
318      if ( p_opt )
319      {
320          "dehomogenization";
321      }
322      i = subst(i, @hilbRing@, 1);
323
324       if (p_opt)
325       {
326         "simplification";
327       }
328       i= simplify(i,34);
329
330       setring P;
331       if (p_opt)
332       {
333         "imap to ring "+string(P);
334       }
335       i = imap(Phelp,i);
336       kill Phelp;
337       i = simplify(i,34);
338
339       // compute reduces SB
340       if (find(s_opt, "redSB") > 0)
341       {
342         if (p_opt)
343         {
344           "interreduction";
345         }
346         i=interred(i);
347       }
348       attrib(i, "isSB", 1);
349       return (i);
350}
351example
352{ "EXAMPLE:"; echo = 2;
353   ring  r = 0,(x,y,z),lp;
354   ideal i = y3+x2,x2y+x2z2,x3-z9,z4-y2-xz;
355   ideal j = stdhilb(i); j;
356
357   ring  r1 = 0,(x,y,z),wp(3,2,1);
358   ideal  i = y3+x2,x2y+x2z2,x3-z9,z4-y2-xz;  //ideal is homogeneous
359   ideal j = stdhilb(i,"std"); j;
360   //this is equivalent to:
361   intvec v = hilb(std(i),1);
362   ideal j1 = std(i,v,intvec(3,2,1)); j1;
363   size(NF(j,j1))+size(NF(j1,j));            //j and j1 define the same ideal
364}
365
366///////////////////////////////////////////////////////////////////////////////
367proc quotientList (list RL, list #)
368"SYNTAX: @code{quotientList (} list_expression @code{)} @*
369         @code{quotientList (} list_expression @code{,} string_expression@code{)}
370TYPE:    list
371PURPOSE: define a ringlist, say QL, of the first argument, say RL, which is
372         assumed to be the ringlist of a qring, but where the quotient ideal
373         RL[4] is not a standard basis with respect to the given monomial
374         order in RL[3]. Then QL will be obtained from RL just by replacing
375         RL[4] by a standard of it with respect to this order. RL itself
376         will be returnd if size(RL[4]) <= 1 (in which case it is known to be
377         a standard basis w.r.t. any ordering) or if a second argument
378         \"isSB\" of type string is given.
379NOTE:    the command ring(quotientList(RL)) defines a quotient ring correctly
380         and should be used instead of ring(RL) if the quotient ideal RL[4]
381         is not (or not known to be) a standard basis with respect to the
382         monomial ordering specified in RL[3].
383SEE ALSO: ringlist, ring
384EXAMPLE: example quotientList; shows an example"
385{
386   def P = basering;
387   if( size(#) > 0 )
388   {
389      if ( #[1] == "isSB")
390      {
391         return (RL);
392      }
393   }
394   ideal Qideal  = RL[4];  //##Achtung, nichtkommuatativem Fall behandeln
395   if( size(Qideal) <= 1)
396   {
397      return (RL);
398   }
399
400   RL[4] = ideal(0);
401   def Phelp = ring(RL);
402   setring Phelp;
403   ideal Qideal = groebner(fetch(P,Qideal));
404   setring P;
405   RL[4]=fetch(Phelp,Qideal);
406   return (RL);
407}
408example
409{ "EXAMPLE:"; echo = 2;
410   ring P = 0,(y,z,u,v),lp;
411   ideal i = y+u2+uv3, z+uv3;            //i is an lp-SB but not a dp_SB
412   qring Q = std(i);
413   list LQ = ringlist(Q);
414   LQ[3][1][1]="dp";
415   def Q1 = ring(quotientList(LQ));
416   setring Q1;
417   Q1;
418
419   setring Q;
420   ideal q1 = uv3+z, u2+y-z, yv3-zv3-zu; //q1 is a dp-standard basis
421   LQ[4] = q1;
422   def Q2 = ring(quotientList(LQ,"isSB"));
423   setring Q2;
424   Q2;
425}
426
427///////////////////////////////////////////////////////////////////////////////
428proc par2varRing (list #)
429"USAGE:   par2varRing([l]); l list of ideals [default:l=empty list]
430RETURN:  list, say L, with L[1] a ring where the parameters of the
431         basering have been converted to an additional last block of
432         variables all of weight 1 and ordering dp.
433         If a list l with l[i] an ideal is given, then l[i]+minpoly is
434         mapped to an ideal in L[1] with name Id(i)
435         If the basering has no parameters then L[1] is the basering.
436EXAMPLE: example par2varRing; shows an example"
437{
438   def P = basering;
439   int npar = npars(P);  //number of parameters
440   int s = size(#);
441   int ii;
442   if ( npar == 0)
443   {
444     dbprint(printlevel-voice+3,"// ** no parameters, ring was not changed");
445     for( ii = 1; ii <= s; ii++)
446     {
447        ideal Id(ii) = #[ii];
448        export (Id(ii));
449     }
450     return(list(P));
451   }
452
453   list rlist = ringlist(P);
454   list parlist = rlist[1];
455   rlist[1] = parlist[1];
456   poly Minpoly = minpoly;     //check for minpoly:
457
458   //now create new ring
459   if ( size(Minpoly) == 0 )
460   {
461      for( ii = 1; ii <= s; ii++)
462      {
463        ideal Id(ii) = #[ii];
464      }
465   }
466   else
467   {
468      if( find(option(),"prot") ){"add minpoly to input";}
469      for( ii = 1; ii <= s; ii++)
470      {
471        ideal Id(ii) = #[ii];
472        Id(ii)[ncols(Id(ii))+1]=Minpoly;
473      }
474   }
475   int nvar = size(rlist[2]);
476   int nblock = size(rlist[3]);
477   int k;
478   for (k=1; k<=npar; k++)
479   {
480      rlist[2][nvar+k] = parlist[2][k];   //change variable list
481   }
482
483   //converted parameters get one block dp. If module ordering was in front
484   //it stays in front, otherwise it will be moved to the end
485   intvec OW = 1;
486   for (k = 2; k <= npar; k++)
487   {
488      OW = OW,1;
489   }
490   if( rlist[3][nblock][1] =="c" || rlist[3][nblock][1] =="C" )
491   {
492      rlist[3][nblock+1] = rlist[3][nblock];
493      rlist[3][nblock] = list("dp",OW);
494   }
495   else
496   {
497      rlist[3][nblock+1] = list("dp",OW);
498   }
499
500   def Ppar2var = ring(quotientList(rlist));
501   setring Ppar2var;
502   for( ii = 1; ii <= s; ii++)
503   {
504      def Id(ii) = imap(P,Id(ii));
505      export (Id(ii));
506   }
507   list Lpar2var = Ppar2var;
508   return(Lpar2var);
509}
510example
511{ "EXAMPLE:"; echo = 2;
512   ring R = (0,x),(y,z,u,v),lp;
513   minpoly = x2+1;
514   ideal i = x3,x2+y+z+u+v,xyzuv-1; i;
515   def P = par2varRing(i)[1]; P;
516   setring(P);
517   Id(1);
518}
519
520//////////////////////////////////////////////////////////////////////////////
521proc hilbRing ( list # )
522"USAGE:   hilbRing([l]); l list of ideals [default:l=empty list]
523RETURN:  list, say L: L[1] is a ring and L[2] an intvec
524         L[1] is a ring whith an extra homogenizing variable
525         @hilbRing@. The monomial ordering of L[1] is 1 block dp if the
526         weights of the variables of the basering, say R, are all 1, resp.
527         wp(w,1) wehre w is the intvec of weights of the variables of R.
528         If the basering is a quotient ring P/Q, then L[1] is not a quotient
529         ring but contains the ideal @Qidealhilb@, the homogenized ideal
530         Q of P.
531         If a list l is given with l[i] an ideal, then l[i] is
532         mapped to the homogenized ideal Id(i) in L[1].
533         L[2] is the intvec (w,1)
534PURPOSE: Prepare a ring for computing the (weighted) hilbert series of
535         an ideal with an easy monomial ordering.
536EXAMPLE: example hilbRing; shows an example
537"
538{
539   def P = basering;
540   number Minpoly = minpoly;
541  //##kann entfallen, wenn minpoly richtig gemapt wird
542
543   if( size(Minpoly) > 0 )     //remember minpoly //##
544   {
545     int is_minpoly =1;
546   }
547
548   ideal Qideal = ideal(P);    //defining the quotient ideal if P is a qring
549   if( size(Qideal) != 0 )
550   {
551     int is_qring =1;
552   }
553   list BRlist = ringlist(P);
554   BRlist[4] = ideal(0);
555
556   int nvarP = nvars(P);
557   int s = size(#);
558   intvec w;                   //for ringweights of basering P
559   int k;
560   for(k=1;  k<=nvarP; k++)
561   {
562       w[k]=deg(var(k));
563   }
564
565   for(k = 1; k <= s; k++)
566   {
567      ideal Id(k) = #[k];
568   }
569
570    // a homogenizing variable is added
571    BRlist[2][nvarP+1] = "@hilbRing@";
572    w[nvarP +1]=1;
573
574    //ordering is set to (dp,C) if weights of all variables are 1
575    //resp. to (wp(w,1),C) where w are the ringweights of basering P
576    //homogenizing var gets weight 1:
577
578    BRlist[3] = list();
579    if(w==1)
580    {
581      BRlist[3][1]=list("dp",w);
582    }
583    else
584    {
585      BRlist[3][1]=list("wp",w);
586    }
587    BRlist[3][2]=list("C",intvec(0));
588
589    //change ring and get ideal from previous ring
590    //(imap converts parameters of P automatically to variables in Phelp)
591    if( defined(is_minpoly) ) //##
592    {
593       BRlist[1][4] = ideal(0);
594    }
595
596    def Philb = ring(quotientList(BRlist));
597    kill BRlist;
598    setring Philb;
599    if( defined(is_minpoly) ) //##
600    {
601       minpoly = imap(P,Minpoly);
602    }
603    if( defined(is_qring) )
604    {
605       ideal @Qidealhilb@ =  homog( imap(P,Qideal), @hilbRing@ );
606       export(@Qidealhilb@);
607
608       if( find(option(),"prot") ){"add quotient ideal to input";}
609       for(k = 1; k <= s; k++)
610       {  //homogenize
611          ideal Id(k) =  homog( imap(P,Id(k)), @hilbRing@ ), @Qidealhilb@ ;
612          export(Id(k));
613       }
614    }
615    else
616    {
617        for(k = 1; k <= s; k++)
618        { //homogenize
619            ideal Id(k) =  homog( imap(P,Id(k)), @hilbRing@ );
620            export(Id(k));
621        }
622    }
623
624    list Lhilb = Philb,w;
625    return(Lhilb);
626}
627example
628{ "EXAMPLE:"; echo = 2;
629   ring R = 0,(x,y,z,u,v),lp;
630   ideal i = x+y2+z3,xy+xv+yz+zu+uv,xyzuv-1;
631   def P = hilbRing(i)[1];  P;
632   setring P;
633   Id(1);
634   hilb(std(Id(1)),1);
635
636   ring S =  0,(x,y,z,u,v),lp;
637   qring T = std(x+y2+z3);
638   ideal i = xy+xv+yz+zu+uv,xyzuv-v5;
639   def Q = hilbRing(i)[1];  Q;
640   setring Q;
641   Id(1);
642}
643
644//////////////////////////////////////////////////////////////////////////////
645proc qslimgb (i)
646"USAGE:   qslimgb(i); i ideal
647RETURN:  ideal, a standard basis of i computed with slimgb
648NOTE:    As long as slimgb does not know qrings qslimgb should be used in case
649         the basering is (possibly) a quotient ring. The quotient ideal is
650         added to the input and slimgb is applied.
651         ** not yet implemented for modules
652EXAMPLE: example qslimgb; shows an example"
653{
654    def P = basering;
655    ideal Qideal = ideal(P);      //defining the quotient ideal if P is a qring
656    int p_opt;
657    if( find(option(),"prot") )
658    {
659      p_opt=1;
660    }
661    if (size(Qideal) == 0)
662    {
663      if (p_opt)
664      {
665         "slimgb in ring " + string(P);
666      }
667      return(slimgb(i));
668    }
669
670    //case of a qring; since slimgb does not know qrings we
671    //delete the quotient ideal and add it to i
672
673    list BRlist = ringlist(P);
674    BRlist[4] = ideal(0);
675    def Phelp = ring(BRlist);
676    kill BRlist;
677    setring Phelp;
678    ideal iq = imap(P,i), imap(P,Qideal);
679    if (p_opt)
680    {
681       "slimgb in ring " + string(Phelp);
682       "(with quotient ideal added to input)";
683    }
684    iq = slimgb(iq);
685
686    setring P;
687    if (p_opt)
688    {
689       "imap to original ring";
690    }
691    i = imap(Phelp,iq);
692    kill Phelp;
693
694    if (find(option(),"redSB") > 0)
695    {
696       if (p_opt)
697       {
698         "interreduction";
699       }
700       i=interred(i);
701    }
702    attrib(i, "isSB", 1);
703    return (i);
704}
705example
706{ "EXAMPLE:"; echo = 2;
707   ring R  = (0,v),(x,y,z,u),dp;
708   qring Q = std(x2-y3);
709   ideal i = x+y2,xy+yz+zu+u*v,xyzu*v-1;
710   ideal j = qslimgb(i);
711}
712
713//////////////////////////////////////////////////////////////////////////////
714proc groebner(def i, list #)
715"SYNTAX: @code{groebner (} ideal_expression @code{)} @*
716         @code{groebner (} module_expression @code{)} @*
717         @code{groebner (} ideal_expression@code{,} int_expression @code{)} @*
718         @code{groebner (} module_expression@code{,} int_expression @code{)}
719         @code{groebner (} ideal_expression@code{,} list of string_expressions
720               @code{)} @*
721         @code{groebner (} ideal_expression@code{,} list of string_expressions
722               and int_expression @code{)} @*
723         @code{groebner (} ideal_expression@code{,} int_expression @code{)} @*
724TYPE:    type of the first argument
725PURPOSE: computes a standard basis of the first argument @code{I}
726         (ideal or module), by a heuristically chosen method (default)
727         or by a method specified by further arguments of type string.
728         Possible methods are:  @*
729         - the direct methods @code{\"std\"} or @code{\"slimgb\"} without
730           conversion @*
731         - conversion methods @code{\"hilb\"} or @code{\"fglm\"} where
732           a Groebner basis is first computed with an \"easy\" ordering
733           and then converted to the ordering of the basering by the
734           Hilbert driven Groebner basis computation.
735           The actual computation of the Groebner basis can be
736           specified by @code{\"std\"} or by @code{\"slimgb\"}
737           (not implemented for all orderings) @*
738         A further string @code{\"par2var\"} converts parameters to an extra
739         block of variables before a Groebner basis computation (and
740         afterwards back).
741         @code{option(prot)} tells about the chosen method.
742NOTE:    If a further argument, say @code{wait}, of type int is given,
743         then the computation proceeds at most @code{wait} seconds.
744         That is, if no result could be computed in @code{wait} seconds,
745         then the computation is interrupted, 0 is returned, a warning
746         message is displayed, and the global variable
747         @code{Standard::groebner_error} is defined.
748         This feature uses MP and is hence only available on UNIX platforms.
749HINT:    Since there exists no uniform best method for computing standard
750         bases, and since the difference in performance of a method on
751         different examples can be huge, it is recommended to test, for hard
752         examples, first various methods on a simplified example (e.g. use
753         characteristic 32003 instead of 0 or substitute a subset of
754         parameters/variables by integers, etc.). @*
755SEE ALSO: stdhilb, stdfglm, std, slimgb
756KEYWORDS: time limit on computations; MP, groebner basis computations
757EXAMPLE: example groebner;  shows an example"
758{
759
760//Vorgabe einer Teilmenge aus {hilb,fglm,par2var,std,slimgb}
761//Aktuelle Einstellungen (Jan 2007):
762//---------------------------------
763//0. Immer Aufruf von std unabhaengig von der Vorgabe:
764//   gemischte Ordnungen, extra Gewichtsvektor, Matrix Ordnungen, Moduln
765
766//1. Keine Vorgabe: es wirkt die aktuelle Heuristk:
767//   - Char p: std
768//   - Char = 0: slimgb (im qring wird Quotientenideal zum Input addiert)
769//   - 1-Block-Ordnungen: direkt Aufruf von std oder slimgb
770//   - Komplizierte Ordnungen (lp oder > 1 Block): hilb
771//   - Parameter werden grundsaetzlich nicht in Variable umgewandelt
772//   ? alternativ: more than 1 parameter will be converted to ring variable ?
773//   - fglm is keine Heruristik, da sonst vorher dim==0 peprueft werden muss
774
775//2. Vorgabe aus {std,slimgb}: es wird wo immer moeglich das angegebene
776//   gewaehlt (da slimgb keine Hilbertfunktion kennt, wird std verwendet).
777//   Bei slimgb im qring, wird das Quotientenideal zum Ideal addiert.
778//   Bei Angabe von std zusammen mit slimgb (aeuquivalent zur Angabe von
779//   keinem von beidem) wirkt obige Heuristik.
780
781//3. Nichtleere Vorgabe aus {hilb,fglm,std,slimgb}:
782//   es wird nur das angegebene und moegliche sowie das notwendige verwendet
783//   und bei Wahlmoeglickeit je nach Heuristik.
784//   Z.B. Vorgabe von {hilb} ist aequivalent zu {hilb,std,slimgb} und es wird
785//   hilb und nach Heuristik std oder slimgb verwendet, aber nicht par2var;
786//   bei Vorgabe von {hilb,slimgb} wird hilb und wo moeglich slimgb verwendet.
787
788//4. Bei Vorgabe von {par2var} wird par2var immer mit hilb und nach Heuristik
789//   std oder slimgb verwendet. Zu Variablen konvertierte Parameter haben
790//   extra letzten Block und Gewichte 1.
791
792
793  def P=basering;
794//----------------------- save the given method ---------------------------
795  string method;
796  list Method;
797  int k;
798  for (k=1; k<=size(#); k++)
799  {
800     if (typeof(#[k]) == "int")
801     {
802       if (defined(wait) != voice)
803       {
804         int wait = #[k];
805       }
806     }
807     if (typeof(#[k]) == "string")
808     {
809       method = method + "," + #[k];
810       Method = Method + list(#[k]);
811     }
812  }
813
814 //======= we have an argument of type int -- try to use MPfork links =======
815  if ( defined(wait) == voice )
816  {
817    if ( system("with", "MP") )
818    {
819        int j = 10;
820
821        string bs = nameof(basering);
822        link l_fork = "MPtcp:fork";
823        open(l_fork);
824        write(l_fork, quote(system("pid")));
825        int pid = read(l_fork);
826        write(l_fork, quote(groebner(eval(i))));
827//###        write(l_fork, quote(groebner(eval(i),Method)));
828//Fehlermeldung:
829// ***dError: undef. ringorder used
830// occured at:
831
832        // sleep in small intervalls for appr. one second
833        if (wait > 0)
834        {
835          while(j < 1000000)
836          {
837            if (status(l_fork, "read", "ready", j)) {break;}
838            j = j + j;
839          }
840        }
841
842        // sleep in intervalls of one second from now on
843        j = 1;
844        while (j < wait)
845        {
846          if (status(l_fork, "read", "ready", 1000000)) {break;}
847          j = j + 1;
848        }
849
850        if (status(l_fork, "read", "ready"))
851        {
852          def result = read(l_fork);
853          if (bs != nameof(basering))
854          {
855            def PP = basering;
856            setring P;
857            def result = imap(PP, result);
858            kill PP;
859          }
860          if (defined(groebner_error))
861          {
862            kill groebner_error;
863          }
864          kill l_fork;
865        }
866        else
867        {
868          ideal result;
869          if (! defined(groebner_error))
870          {
871            int groebner_error = 1;
872            export groebner_error;
873          }
874          "** groebner did not finish";
875          j = system("sh", "kill " + string(pid));
876        }
877        return (result);
878    }
879    else
880    {
881      "** groebner with a time limit on computation is not supported
882          in this configuration";
883    }
884  }
885
886 //=========== we are still here -- do the actual computation =============
887
888//--------------------- save data from basering ---------------------------
889  poly Minpoly = minpoly;      //minimal polynomial
890  int was_minpoly;             //remembers if there was a minpoly in P
891  if (size(Minpoly) > 0)
892  {
893     was_minpoly = 1;
894  }
895
896  ideal Qideal = ideal(P);      //defining the quotient ideal if P is a qring
897  int was_qring;                //remembers if basering was a qring
898  int is_homog = homog(Qideal); //remembers if Qideal was homog (homog(0)=1)
899  if (size(Qideal) > 0)
900  {
901     was_qring = 1;
902  }
903  list BRlist = ringlist(P);
904
905  // save ordering of basering P for later use
906  list ord_P = BRlist[3];       //should be available in all rings
907  string ordstr_P = ordstr(P);
908  int nvars_P = nvars(P);
909  int npars_P = npars(P);
910  intvec w;                     //for ringweights of basering P
911  int neg;
912  for(k=1;  k<=nvars_P; k++)
913  {
914     w[k]=deg(var(k));
915     if(w[k] <= 0)
916     {
917       neg=1;
918     }
919  }
920
921  //save options:
922  intvec opt=option(get);
923  string s_opt = option();
924  int p_opt;
925  if (find(s_opt, "prot"))  { p_opt = 1; }
926
927//------------------ cases where std is always used ------------------------
928//If other methods are not implemented or do not make sense, i.e. for
929//local or mixed orderings, matrix orderings, extra weight vector and modules
930
931  if(  ( find(ordstr_P,"s") > 0 )
932    || ( find(ordstr_P,"M") > 0 )
933    || ( find(ordstr_P,"a") > 0 )
934    || ( nrows(i)>1 )    //module case, not yet handled by slimgb
935    || ( neg>0 ) )       //***fuer Moduln slimgb zulassen, wenn implementiert
936  {
937    if (p_opt) { "std in basering"; }
938    //if ( neg > 0 ) // std can handle local and mixed orderings
939    //{
940    //  "*** WARNING: some weights are negative, computation may not finish";
941    //}
942    i = std(i);
943    return(i);
944  }
945
946//now we have:
947//ideal, global ordering, no matrix ordering, no extra weight vector
948//The interesting cases start now.
949
950 //------------------ classify the possible settings ---------------------
951 string algorithm;       //possibilities: std, slimgb, stdorslimgb
952 string conversion;      //possibilities: hilb, fglm, hilborfglm, no
953 string partovar;        //possibilities: yes, no
954 string order;           //possibilities: simple, !simple
955 string direct;          //possibilities: yes, no
956
957  //define algorithm:
958  if( find(method,"std") && !find(method,"slimgb") )
959  {
960     algorithm = "std";
961  }
962  if( find(method,"slimgb") && !find(method,"std") )
963  {
964     algorithm = "slimgb";
965  }
966  if( find(method,"std") && find(method,"slimgb") ||
967      (!find(method,"std") && !find(method,"slimgb")) )
968  {
969     algorithm = "stdorslimgb";
970  }
971
972  //define conversion:
973  if( find(method,"hilb") && !find(method,"fglm") )
974  {
975     conversion = "hilb";
976  }
977  if( find(method,"fglm") && !find(method,"hilb") )
978  {
979     conversion = "fglm";
980  }
981  if( find(method,"fglm") && find(method,"hilb") )
982  {
983     conversion = "hilborfglm";
984  }
985  if( !find(method,"fglm") && !find(method,"hilb") )
986  {
987     conversion = "no";
988  }
989
990  //define partovar:
991  if( find(method,"par2var") && npars_P > 0 )
992  {
993     partovar = "yes";
994  }
995  else
996  {
997     partovar = "no";
998  }
999
1000  //define order:
1001  if (system("nblocks") <= 2)
1002  {
1003    if ( find(ordstr_P,"M")+find(ordstr_P,"lp")+find(ordstr_P,"rp") <= 0 )
1004    {
1005      order = "simple";
1006    }
1007  }
1008
1009  //define direct:
1010  if ( (order=="simple" && (size(method)==0 )) ||
1011       (order=="simple" && (method==",par2var" && npars_P==0 )) ||
1012         (conversion=="no" && partovar=="no" &&
1013           (algorithm=="std" || algorithm=="slimgb" ||
1014            (find(method,"std") && find(method,"slimgb")) ) ) )
1015  {
1016     direct = "yes";
1017  }
1018  else
1019  {
1020     direct = "no";
1021  }
1022
1023  //order=="simple" means that the ordering of the variables consists of one
1024  //block which is not a matrix ordering and not a lexicographical ordering.
1025  //(Note:Singular counts always least 2 blocks, one is for module component):
1026  //Call a method "direct" if conversion=="no" && partovar="no" which means
1027  //that we apply std or slimgb dircet in the basering (exception
1028  //as long as slimgb does not know qrings: in a qring of a ring P
1029  //the ideal Qideal is added to the ideal and slimgb is applied in P).
1030  //We apply a direct method if we have a simple monomial ordering, if no
1031  //conversion (fglm or hilb) is specified and if the parameters shall
1032  //not be made to variables
1033
1034//---------------------------- direct methods -----------------------------
1035  if ( direct == "yes" )
1036  {
1037     if ( algorithm=="std" || (algorithm=="stdorslimgb" && char(P)>0) )
1038     {
1039           if (p_opt) { "std in " + string(P); }
1040           i = std(i);
1041           return(i);
1042     }
1043     if ( algorithm=="slimgb" || (algorithm=="stdorslimgb" && char(P)==0) )
1044     {
1045           i = qslimgb(i);
1046           return(i);
1047     }
1048  }
1049
1050//--------------------------- indirect methods -----------------------------
1051//indirect methods are methods where a conversion is used with a ring change
1052//We are in the following situation:
1053//direct=="no" (i.e. "hilb" or "fglm" or "par2var" is given)
1054//or no method is given and we have a complicated monomial ordering
1055//Note thar "par2var" is not a default strategy, it must be explicitely
1056//given in order to be performed.
1057//## TODO: fglm has still to be implemented
1058
1059//------------ case where no parameters are made to variables  -------------
1060   if (  partovar == "no" && conversion == "hilb"
1061     || (partovar == "no" && conversion == "fglm" )
1062     || (partovar == "no" && conversion == "hilborfglm" )
1063     || (partovar == "no" && conversion == "no" && direct == "no") )
1064        //last case: heuristic
1065   {
1066     if ( conversion=="fglm" )
1067     {
1068       return (stdfglm(i));
1069     }
1070     if ( algorithm=="std" || (algorithm=="stdorslimgb" && char(P)>0) )
1071     {
1072       return (stdhilb(i,"std"));
1073     }
1074     if ( algorithm=="slimgb" || (algorithm=="stdorslimgb" && char(P)==0) )
1075     {
1076       return (stdhilb(i,"slimgb"));
1077     }
1078   }
1079
1080//------------ case where parameters are made to variables  ----------------
1081//define a ring Phelp via par2varRing in which the parameters are variables
1082
1083   else
1084   {
1085      // reset options
1086      option(none);
1087      // turn on options prot, mem, intStrategy if previously set
1088      if ( find(s_opt, "prot") )
1089      { option(prot); }
1090      if ( find(s_opt, "mem") )
1091      { option(mem); }
1092      if ( find(s_opt, "intStrategy") )
1093      { option(intStrategy); }
1094
1095      is_homog = is_homog*homog(i); //check for homogeneity of i and Qideal
1096
1097     //first clear denominators of parameters
1098      if (npars_P > 0)
1099      {
1100         for( k=ncols(i); k>0; k-- )
1101         { i[k]=cleardenom(i[k]); }
1102      }
1103
1104      def Phelp = par2varRing(i)[1];   //minpoly is mapped with i
1105      setring Phelp;
1106      ideal i = Id(1);
1107      is_homog = homog(i);
1108
1109      //If parameters are converted to ring variables, they appear in an extra
1110      //block. Therefore we use always hilb for this block ordering:
1111      if ( conversion=="fglm" )
1112      {
1113         i = (stdfglm(i));       //only uesful for 1 parameter with minpoly
1114      }
1115      else
1116      {
1117        if ( algorithm=="std" || (algorithm=="stdorslimgb" && char(P)>0) )
1118        {
1119           i = stdhilb(i,"std");
1120        }
1121        if ( algorithm=="slimgb" || (algorithm=="stdorslimgb" && char(P)==0) )
1122        {
1123           i = stdhilb(i,"slimgb");
1124        }
1125      }
1126   }
1127
1128//-------------------- go back to original ring ---------------------------
1129//The main computation is done. However, the SB coming from a ring with
1130//extra variables is in general too big. We simplify it befor mapping it
1131//to the basering.
1132
1133       if (p_opt)
1134       {
1135         "simplification";
1136       }
1137
1138       if (was_minpoly)
1139       {
1140          ideal Minpoly = imap(P,Minpoly);
1141          attrib(Minpoly,"isSB",1);
1142          i = simplify(NF(i,Minpoly),2);
1143       }
1144
1145       ideal Li = lead(i);
1146       setring P;
1147       ideal Li = imap(Phelp,Li);
1148       Li = simplify(Li,32);
1149       intvec vi;
1150       for (k=1; k<=ncols(Li); k++)
1151       {
1152         vi[k] = Li[k]==0;
1153       }
1154
1155       setring Phelp;
1156       for (k=1;  k<=size(i) ;k++)
1157       {
1158           if(vi[k]==1)
1159           {
1160              i[k]=0;
1161           }
1162       }
1163       i = simplify(i,2);
1164
1165       setring P;
1166       if (p_opt)
1167       {
1168         "imap to original ring";
1169       }
1170       i = imap(Phelp,i);
1171       kill Phelp;
1172       i = simplify(i,34);
1173
1174       // clean-up time
1175       option(set, opt);
1176       if (find(s_opt, "redSB") > 0)
1177       {
1178         if (p_opt)
1179         {
1180           "interreduction";
1181         }
1182         i=interred(i);
1183       }
1184       attrib(i, "isSB", 1);
1185       return (i);
1186}
1187example
1188{ "EXAMPLE: "; echo=2;
1189  intvec opt = option(get);
1190  option(prot);
1191  ring r  = 0,(a,b,c,d),dp;
1192  ideal i = a+b+c+d,ab+ad+bc+cd,abc+abd+acd+bcd,abcd-1;
1193  groebner(i);
1194
1195  ring s  = 0,(a,b,c,d),lp;
1196  ideal i = imap(r,i);
1197  groebner(i,"hilb");
1198
1199  ring R  = (0,a),(b,c,d),lp;
1200  minpoly = a2+1;
1201  ideal i = a+b+c+d,ab+ad+bc+cd,abc+abd+acd+bcd,d2-c2b2;
1202  groebner(i,"par2var","slimgb");
1203
1204  groebner(i,"fglm");          //computes a reduced standard basis
1205
1206  if (system("with","MP")) {groebner(i,0);}
1207  defined(Standard::groebner_error);
1208  option(set,opt);
1209}
1210
1211//////////////////////////////////////////////////////////////////////////
1212
1213proc res(list #)
1214"@c we do texinfo here:
1215@cindex resolution, computation of
1216@table @code
1217@item @strong{Syntax:}
1218@code{res (} ideal_expression@code{,} int_expression @code{[,} any_expression @code{])}
1219@*@code{res (} module_expression@code{,} int_expression @code{[,} any_expression @code{])}
1220@item @strong{Type:}
1221resolution
1222@item @strong{Purpose:}
1223computes a (possibly minimal) free resolution of an ideal or module using
1224a heuristically chosen method.
1225@* The second (int) argument (say, @code{k}) specifies the length of
1226the resolution. If it is not positive then @code{k} is assumed to be the
1227number of variables of the basering.
1228@* If a third argument is given, the returned resolution is minimized.
1229
1230Depending on the input, the returned resolution is computed using the
1231following methods:
1232@table @asis
1233@item @strong{quotient rings:}
1234@code{nres} (classical method using syzygies) , see @ref{nres}.
1235
1236@item @strong{homogeneous ideals and k=0:}
1237@code{lres} (La'Scala's method), see @ref{lres}.
1238
1239@item @strong{not minimized resolution and (homogeneous input with k not 0, or local rings):}
1240@code{sres} (Schreyer's method), see @ref{sres}.
1241
1242@item @strong{all other inputs:}
1243@code{mres} (classical method), see @ref{mres}.
1244@end table
1245@item @strong{Note:}
1246Accessing single elements of a resolution may require that some partial
1247computations have to be finished and may therefore take some time.
1248@end table
1249@c ref
1250See also
1251@ref{betti};
1252@ref{ideal};
1253@ref{minres};
1254@ref{module};
1255@ref{mres};
1256@ref{nres};
1257@ref{lres};
1258@ref{hres};
1259@ref{sres}.
1260@ref{resolution}
1261@c ref
1262"
1263{
1264   def P=basering;
1265   if (size(#) < 2)
1266   {
1267     ERROR("res: need at least two arguments: ideal/module, int");
1268   }
1269
1270   def m=#[1]; //the ideal or module
1271   int i=#[2]; //the length of the resolution
1272   if (i< 0) { i=0;}
1273
1274   string varstr_P = varstr(P);
1275
1276   int p_opt;
1277   string s_opt = option();
1278   // set p_opt, if option(prot) is set
1279   if (find(s_opt, "prot"))
1280   {
1281     p_opt = 1;
1282   }
1283
1284   if(size(ideal(basering)) > 0)
1285   {
1286     // the quick hack for qrings - seems to fit most needs
1287     // (lres is not implemented for qrings, sres is not so efficient)
1288     if (p_opt) { "using nres";}
1289     return(nres(m,i));
1290   }
1291
1292   if(homog(m)==1)
1293   {
1294      resolution re;
1295      if (((i==0) or (i>=nvars(basering))) && typeof(m) != "module")
1296      {
1297        //LaScala for the homogeneous case and i == 0
1298        if (p_opt) { "using lres";}
1299        re=lres(m,i);
1300        if(size(#)>2)
1301        {
1302           re=minres(re);
1303        }
1304      }
1305      else
1306      {
1307        if(size(#)>2)
1308        {
1309          if (p_opt) { "using mres";}
1310          re=mres(m,i);
1311        }
1312        else
1313        {
1314          if (p_opt) { "using sres";}
1315          re=sres(std(m),i);
1316        }
1317      }
1318      return(re);
1319   }
1320
1321   //mres for the global non homogeneous case
1322   if(find(ordstr(P),"s")==0)
1323   {
1324      string ri= "ring Phelp ="
1325                  +string(char(P))+",("+varstr_P+"),(dp,C);";
1326      execute(ri);
1327      def m=imap(P,m);
1328      if (p_opt) { "using mres in another ring";}
1329      list re=mres(m,i);
1330      setring P;
1331      resolution result=imap(Phelp,re);
1332      if (size(#) > 2) {result = minres(result);}
1333      return(result);
1334   }
1335
1336   //sres for the local case and not minimal resolution
1337   if(size(#)<=2)
1338   {
1339      string ri= "ring Phelp ="
1340                  +string(char(P))+",("+varstr_P+"),(ls,c);";
1341      execute(ri);
1342      def m=imap(P,m);
1343      m=std(m);
1344      if (p_opt) { "using sres in another ring";}
1345      list re=sres(m,i);
1346      setring P;
1347      resolution result=imap(Phelp,re);
1348      return(result);
1349   }
1350
1351   //mres for the local case and minimal resolution
1352   string ri= "ring Phelp ="
1353                  +string(char(P))+",("+varstr_P+"),(ls,C);";
1354   execute(ri);
1355   def m=imap(P,m);
1356    if (p_opt) { "using mres in another ring";}
1357   list re=mres(m,i);
1358   setring P;
1359   resolution result=imap(Phelp,re);
1360   result = minres(result);
1361   return(result);
1362}
1363example
1364{"EXAMPLE:"; echo = 2;
1365  ring r=0,(x,y,z),dp;
1366  ideal i=xz,yz,x3-y3;
1367  def l=res(i,0); // homogeneous ideal: uses lres
1368  l;
1369  print(betti(l), "betti"); // input to betti may be of type resolution
1370  l[2];         // element access may take some time
1371  i=i,x+1;
1372  l=res(i,0);   // inhomogeneous ideal: uses mres
1373  l;
1374  ring rs=0,(x,y,z),ds;
1375  ideal i=imap(r,i);
1376  def l=res(i,0); // local ring not minimized: uses sres
1377  l;
1378  res(i,0,0);     // local ring and minimized: uses mres
1379}
1380/////////////////////////////////////////////////////////////////////////
1381
1382proc quot (m1,m2,list #)
1383"SYNTAX: @code{quot (} module_expression@code{,} module_expression @code{)}
1384         @*@code{quot (} module_expression@code{,} module_expression@code{,}
1385            int_expression @code{)}
1386         @*@code{quot (} ideal_expression@code{,} ideal_expression @code{)}
1387         @*@code{quot (} ideal_expression@code{,} ideal_expression@code{,}
1388            int_expression @code{)}
1389TYPE:    ideal
1390SYNTAX:  @code{quot (} module_expression@code{,} ideal_expression @code{)}
1391TYPE:    module
1392PURPOSE: computes the quotient of the 1st and the 2nd argument.
1393         If a 3rd argument @code{n} is given the @code{n}-th method is used
1394         (@code{n}=1...5).
1395SEE ALSO: quotient
1396EXAMPLE: example quot; shows an example"
1397{
1398  if (((typeof(m1)!="ideal") and (typeof(m1)!="module"))
1399     or ((typeof(m2)!="ideal") and (typeof(m2)!="module")))
1400  {
1401    "USAGE:   quot(m1, m2[, n]); m1, m2 two submodules of k^s,";
1402    "         n (optional) integer (1<= n <=5)";
1403    "RETURN:  the quotient of m1 and m2";
1404    "EXAMPLE: example quot; shows an example";
1405    return();
1406  }
1407  if (typeof(m1)!=typeof(m2))
1408  {
1409    return(quotient(m1,m2));
1410  }
1411  if (size(#)>0)
1412  {
1413    if (typeof(#[1])=="int" )
1414    {
1415      return(quot1(m1,m2,#[1]));
1416    }
1417  }
1418  else
1419  {
1420    return(quot1(m1,m2,2));
1421  }
1422}
1423example
1424{ "EXAMPLE:"; echo = 2;
1425  ring r=181,(x,y,z),(c,ls);
1426  ideal id1=maxideal(4);
1427  ideal id2=x2+xyz,y2-z3y,z3+y5xz;
1428  option(prot);
1429  ideal id3=quotient(id1,id2);
1430  id3;
1431  ideal id4=quot(id1,id2,1);
1432  id4;
1433  ideal id5=quot(id1,id2,2);
1434  id5;
1435}
1436
1437static proc quot1 (module m1, module m2,int n)
1438"USAGE:   quot1(m1, m2, n); m1, m2 two submodules of k^s,
1439         n integer (1<= n <=5)
1440RETURN:  the quotient of m1 and m2
1441EXAMPLE: example quot1; shows an example"
1442{
1443  if (n==1)
1444  {
1445    return(quotient1(m1,m2));
1446  }
1447  else
1448  {
1449    if (n==2)
1450    {
1451      return(quotient2(m1,m2));
1452    }
1453    else
1454    {
1455      if (n==3)
1456      {
1457        return(quotient3(m1,m2));
1458      }
1459      else
1460      {
1461        if (n==4)
1462        {
1463          return(quotient4(m1,m2));
1464        }
1465        else
1466        {
1467          if (n==5)
1468          {
1469            return(quotient5(m1,m2));
1470          }
1471          else
1472          {
1473            return(quotient(m1,m2));
1474          }
1475        }
1476      }
1477    }
1478  }
1479}
1480example
1481{ "EXAMPLE:"; echo = 2;
1482  ring r=181,(x,y,z),(c,ls);
1483  ideal id1=maxideal(4);
1484  ideal id2=x2+xyz,y2-z3y,z3+y5xz;
1485  option(prot);
1486  ideal id6=quotient(id1,id2);
1487  id6;
1488  ideal id7=quot1(id1,id2,1);
1489  id7;
1490  ideal id8=quot1(id1,id2,2);
1491  id8;
1492}
1493
1494static proc quotient0(module a,module b)
1495{
1496  module mm=b+a;
1497  resolution rs=lres(mm,0);
1498  list I=list(rs);
1499  matrix M=I[2];
1500  matrix A[1][nrows(M)]=M[1..nrows(M),1];
1501  ideal i=A;
1502  return (i);
1503}
1504proc quotient1(module a,module b)  //17sec
1505"USAGE:   quotient1(m1, m2); m1, m2 two submodules of k^s,
1506RETURN:  the quotient of m1 and m2"
1507{
1508  int i;
1509  a=std(a);
1510  module dummy;
1511  module B=NF(b,a)+dummy;
1512  ideal re=quotient(a,module(B[1]));
1513  for(i=2;i<=ncols(B);i++)
1514  {
1515     re=intersect1(re,quotient(a,module(B[i])));
1516  }
1517  return(re);
1518}
1519proc quotient2(module a,module b)    //13sec
1520"USAGE:   quotient2(m1, m2); m1, m2 two submodules of k^s,
1521RETURN:  the quotient of m1 and m2"
1522{
1523  a=std(a);
1524  module dummy;
1525  module bb=NF(b,a)+dummy;
1526  int i=ncols(bb);
1527  ideal re=quotient(a,module(bb[i]));
1528  bb[i]=0;
1529  module temp;
1530  module temp1;
1531  module bbb;
1532  int mx;
1533  i=i-1;
1534  while (1)
1535  {
1536    if (i==0) break;
1537    temp = a+bb*re;
1538    temp1 = lead(interred(temp));
1539    mx=ncols(a);
1540    if (ncols(temp1)>ncols(a))
1541    {
1542      mx=ncols(temp1);
1543    }
1544    temp1 = matrix(temp1,1,mx)-matrix(lead(a),1,mx);
1545    temp1 = dummy+temp1;
1546    if (deg(temp1[1])<0) break;
1547    re=intersect1(re,quotient(a,module(bb[i])));
1548    bb[i]=0;
1549    i = i-1;
1550  }
1551  return(re);
1552}
1553proc quotient3(module a,module b)   //89sec
1554"USAGE:   quotient3(m1, m2); m1, m2 two submodules of k^s,
1555         only for global rings
1556RETURN:  the quotient of m1 and m2"
1557{
1558  string s="ring @newr=("+charstr(basering)+
1559           "),("+varstr(basering)+",@t,@w),dp;";
1560  def @newP=basering;
1561  execute(s);
1562  module b=imap(@newP,b);
1563  module a=imap(@newP,a);
1564  int i;
1565  int j=ncols(b);
1566  vector @b;
1567  for(i=1;i<=j;i++)
1568  {
1569     @b=@b+@t^(i-1)*@w^(j-i+1)*b[i];
1570  }
1571  ideal re=quotient(a,module(@b));
1572  setring @newP;
1573  ideal re=imap(@newr,re);
1574  return(re);
1575}
1576proc quotient5(module a,module b)   //89sec
1577"USAGE:   quotient5(m1, m2); m1, m2 two submodules of k^s,
1578         only for global rings
1579RETURN:  the quotient of m1 and m2"
1580{
1581  string s="ring @newr=("+charstr(basering)+
1582           "),("+varstr(basering)+",@t),dp;";
1583  def @newP=basering;
1584  execute(s);
1585  module b=imap(@newP,b);
1586  module a=imap(@newP,a);
1587  int i;
1588  int j=ncols(b);
1589  vector @b;
1590  for(i=1;i<=j;i++)
1591  {
1592     @b=@b+@t^(i-1)*b[i];
1593  }
1594  @b=homog(@b,@w);
1595  ideal re=quotient(a,module(@b));
1596  setring @newP;
1597  ideal re=imap(@newr,re);
1598  return(re);
1599}
1600proc quotient4(module a,module b)   //95sec
1601"USAGE:   quotient4(m1, m2); m1, m2 two submodules of k^s,
1602         only for global rings
1603RETURN:  the quotient of m1 and m2"
1604{
1605  string s="ring @newr=("+charstr(basering)+
1606           "),("+varstr(basering)+",@t),dp;";
1607  def @newP=basering;
1608  execute(s);
1609  module b=imap(@newP,b);
1610  module a=imap(@newP,a);
1611  int i;
1612  vector @b=b[1];
1613  for(i=2;i<=ncols(b);i++)
1614  {
1615     @b=@b+@t^(i-1)*b[i];
1616  }
1617  matrix sy=modulo(@b,a);
1618  ideal re=sy;
1619  setring @newP;
1620  ideal re=imap(@newr,re);
1621  return(re);
1622}
1623static proc intersect1(ideal i,ideal j)
1624{
1625  def R=basering;
1626  execute("ring gnir = ("+charstr(basering)+"),
1627                       ("+varstr(basering)+",@t),(C,dp);");
1628  ideal i=var(nvars(basering))*imap(R,i)+(var(nvars(basering))-1)*imap(R,j);
1629  ideal j=eliminate(i,var(nvars(basering)));
1630  setring R;
1631  map phi=gnir,maxideal(1);
1632  return(phi(j));
1633}
1634
1635//////////////////////////////////////////////////////////////////
1636///
1637/// sprintf, fprintf printf
1638///
1639proc sprintf(string fmt, list #)
1640"SYNTAX:  @code{sprintf (} string_expression @code{[,} any_expressions
1641               @code{] )}
1642RETURN:   string
1643PURPOSE:  @code{sprintf(fmt,...);} performs output formatting. The first
1644          argument is a format control string. Additional arguments may be
1645          required, depending on the content of the control string. A series
1646          of output characters is generated as directed by the control string;
1647          these characters are returned as a string. @*
1648          The control string @code{fmt} is simply text to be copied,
1649          except that the string may contain conversion specifications.@*
1650          Do @code{help print;} for a listing of valid conversion
1651          specifications. As an addition to the conversions of @code{print},
1652          the @code{%n} and @code{%2} conversion specification does not
1653          consume an additional argument, but simply generates a newline
1654          character.
1655NOTE:     If one of the additional arguments is a list, then it should be
1656          enclosed once more into a @code{list()} command, since passing a list
1657          as an argument flattens the list by one level.
1658SEE ALSO: fprintf, printf, print, string
1659EXAMPLE : example sprintf; shows an example
1660"
1661{
1662  int sfmt = size(fmt);
1663  if (sfmt  <= 1)
1664  {
1665    return (fmt);
1666  }
1667  int next, l, nnext;
1668  string ret;
1669  list formats = "%l", "%s", "%2l", "%2s", "%t", "%;", "%p", "%b", "%n", "%2";
1670  while (1)
1671  {
1672    if (size(#) <= 0)
1673    {
1674      return (ret + fmt);
1675    }
1676    nnext = 0;
1677    while (nnext < sfmt)
1678    {
1679      nnext = find(fmt, "%", nnext + 1);
1680      if (nnext == 0)
1681      {
1682        next = 0;
1683        break;
1684      }
1685      l = 1;
1686      while (l <= size(formats))
1687      {
1688        next = find(fmt, formats[l], nnext);
1689        if (next == nnext) break;
1690        l++;
1691      }
1692      if (next == nnext) break;
1693    }
1694    if (next == 0)
1695    {
1696      return (ret + fmt);
1697    }
1698    if (formats[l] != "%2" && formats[l] != "%n")
1699    {
1700      ret = ret + fmt[1, next - 1] + print(#[1], formats[l]);
1701      # = delete(#, 1);
1702    }
1703    else
1704    {
1705      ret = ret + fmt[1, next - 1] + print("", "%2s");
1706    }
1707    if (size(fmt) <= (next + size(formats[l]) - 1))
1708    {
1709      return (ret);
1710    }
1711    fmt = fmt[next + size(formats[l]), size(fmt)-next-size(formats[l]) + 1];
1712  }
1713}
1714example
1715{ "EXAMPLE:"; echo=2;
1716  ring r=0,(x,y,z),dp;
1717  module m=[1,y],[0,x+z];
1718  intmat M=betti(mres(m,0));
1719  list l = r, m, M;
1720  string s = sprintf("s:%s,%n l:%l", 1, 2); s;
1721  s = sprintf("s:%n%s", l); s;
1722  s = sprintf("s:%2%s", list(l)); s;
1723  s = sprintf("2l:%n%2l", list(l)); s;
1724  s = sprintf("%p", list(l)); s;
1725  s = sprintf("%;", list(l)); s;
1726  s = sprintf("%b", M); s;
1727}
1728
1729proc printf(string fmt, list #)
1730"SYNTAX:  @code{printf (} string_expression @code{[,} any_expressions@code{] )}
1731RETURN:   none
1732PURPOSE:  @code{printf(fmt,...);} performs output formatting. The first
1733          argument is a format control string. Additional arguments may be
1734          required, depending on the content of the control string. A series
1735          of output characters is generated as directed by the control string;
1736          these characters are displayed (i.e., printed to standard out). @*
1737          The control string @code{fmt} is simply text to be copied, except
1738          that the string may contain conversion specifications. @*
1739          Do @code{help print;} for a listing of valid conversion
1740          specifications. As an addition to the conversions of @code{print},
1741          the @code{%n} and @code{%2} conversion specification does not
1742          consume an additional argument, but simply generates a newline
1743          character.
1744NOTE:     If one of the additional arguments is a list, then it should be
1745          enclosed once more into a @code{list()} command, since passing a
1746          list as an argument flattens the list by one level.
1747SEE ALSO: sprintf, fprintf, print, string
1748EXAMPLE : example printf; shows an example
1749"
1750{
1751  write("", sprintf(fmt, #));
1752}
1753example
1754{ "EXAMPLE:"; echo=2;
1755  ring r=0,(x,y,z),dp;
1756  module m=[1,y],[0,x+z];
1757  intmat M=betti(mres(m,0));
1758  list l=r,m,matrix(M);
1759  printf("s:%s,l:%l",1,2);
1760  printf("s:%s",l);
1761  printf("s:%s",list(l));
1762  printf("2l:%2l",list(l));
1763  printf("%p",matrix(M));
1764  printf("%;",matrix(M));
1765  printf("%b",M);
1766}
1767
1768
1769proc fprintf(link l, string fmt, list #)
1770"SYNTAX:  @code{fprintf (} link_expression@code{,} string_expression @code{[,}
1771                any_expressions@code{] )}
1772RETURN:   none
1773PURPOSE:  @code{fprintf(l,fmt,...);} performs output formatting.
1774          The second argument is a format control string. Additional
1775          arguments may be required, depending on the content of the
1776          control string. A series of output characters is generated as
1777          directed by the control string; these characters are
1778          written to the link l.
1779          The control string @code{fmt} is simply text to be copied, except
1780          that the string may contain conversion specifications.@*
1781          Do @code{help print;} for a listing of valid conversion
1782          specifications. As an addition to the conversions of @code{print},
1783          the @code{%n} and @code{%2} conversion specification does not
1784          consume an additional argument, but simply generates a newline
1785          character.
1786NOTE:     If one of the additional arguments is a list, then it should be
1787          enclosed once more into a @code{list()} command, since passing
1788          a list as an argument flattens the list by one level.
1789SEE ALSO: sprintf, printf, print, string
1790EXAMPLE : example fprintf; shows an example
1791"
1792{
1793  write(l, sprintf(fmt, #));
1794}
1795example
1796{ "EXAMPLE:"; echo=2;
1797  ring r=0,(x,y,z),dp;
1798  module m=[1,y],[0,x+z];
1799  intmat M=betti(mres(m,0));
1800  list l=r,m,M;
1801  link li="";   // link to stdout
1802  fprintf(li,"s:%s,l:%l",1,2);
1803  fprintf(li,"s:%s",l);
1804  fprintf(li,"s:%s",list(l));
1805  fprintf(li,"2l:%2l",list(l));
1806  fprintf(li,"%p",list(l));
1807  fprintf(li,"%;",list(l));
1808  fprintf(li,"%b",M);
1809}
1810
1811//////////////////////////////////////////////////////////////////////////
1812
1813/*
1814proc minres(list #)
1815{
1816  if (size(#) == 2)
1817  {
1818    if (typeof(#[1]) == "ideal" || typeof(#[1]) == "module")
1819    {
1820      if (typeof(#[2] == "int"))
1821      {
1822        return (res(#[1],#[2],1));
1823      }
1824    }
1825  }
1826
1827  if (typeof(#[1]) == "resolution")
1828  {
1829    return minimizeres(#[1]);
1830  }
1831  else
1832  {
1833    return minimizeres(#);
1834  }
1835
1836}
1837*/
1838///////////////////////////////////////////////////////////////////////////////
1839
1840proc weightKB(def stc, int dd, list wim)
1841"SYNTAX: @code{weightKB (} module_expression@code{,} int_expression @code{,}
1842            list_expression @code{)}@*
1843         @code{weightKB (} ideal_expression@code{,} int_expression@code{,}
1844            list_expression @code{)}
1845RETURN:  the same as the input type of the first argument
1846PURPOSE: If @code{I,d,wim} denotes the three arguments then weightKB
1847         computes the weighted degree- @code{d} part of a vector space basis
1848         (consisting of monomials) of the quotient ring, resp. of the
1849         quotient module, modulo @code{I} w.r.t. weights given by @code{wim}
1850         The information about the weights is given as a list of two intvec:
1851            @code{wim[1]} weights for all variables (positive),
1852            @code{wim[2]} weights for the module generators.
1853NOTE:    This is a generalisation for the command @code{kbase} with the same
1854         first two arguments.
1855SEE ALSO: kbase
1856EXAMPLE: example weightKB; shows an example
1857"
1858{
1859  if(checkww(wim)){ERROR("wrong weights";);}
1860  kbclass();
1861  wwtop=wim[1];
1862  stc=interred(lead(stc));
1863  if(typeof(stc)=="ideal")
1864  {
1865    stdtop=stc;
1866    ideal out=widkbase(dd);
1867    delkbclass();
1868    return(out);
1869  }
1870  list mbase=kbprepare(stc);
1871  module mout;
1872  int im,ii;
1873  if(size(wim)>1){mmtop=wim[2];}
1874  else{mmtop=0;}
1875  for(im=size(mbase);im>0;im--)
1876  {
1877    stdtop=mbase[im];
1878    if(im>size(mmtop)){ii=dd;}
1879    else{ii=dd-mmtop[im];}
1880    mout=mout+widkbase(ii)*gen(im);
1881  }
1882  delkbclass();
1883  return(mout);
1884}
1885///////////////////////////////////////////////////////////////////////////////
1886// construct global values
1887static proc kbclass()
1888{
1889  intvec wwtop,mmtop;
1890  export (wwtop,mmtop);
1891  ideal stdtop,kbtop;
1892  export (stdtop,kbtop);
1893  return();
1894}
1895// delete global values
1896static proc delkbclass()
1897{
1898  kill wwtop,mmtop;
1899  kill stdtop,kbtop;
1900  return();
1901}
1902//  select parts of the modul
1903static proc kbprepare(module mstc)
1904{
1905  list rr;
1906  ideal kk;
1907  int i1,i2;
1908  mstc=transpose(mstc);
1909  for(i1=ncols(mstc);i1>0;i1--)
1910  {
1911    kk=0;
1912    for(i2=nrows(mstc[i1]);i2>0;i2--)
1913    {
1914      kk=kk+mstc[i1][i2];
1915    }
1916    rr[i1]=kk;
1917  }
1918  return(rr);
1919}
1920//  check for weights
1921static proc checkww(list vv)
1922{
1923  if(typeof(vv[1])!="intvec"){return(1);}
1924  intvec ww=vv[1];
1925  int mv=nvars(basering);
1926  if(size(ww)<mv){return(1);}
1927  while(mv>0)
1928  {
1929    if(ww[mv]<=0){return(1);}
1930    mv--;
1931  }
1932  if(size(vv)>1)
1933  {
1934    if(typeof(vv[2])!="intvec"){return(1);}
1935  }
1936  return(0);
1937}
1938// The "Caller" for ideals
1939//    dd   - the degree of the result
1940static proc widkbase(int dd)
1941{
1942  if((size(stdtop)==1)&&(deg(stdtop[1])==0)){return(0);}
1943  if(dd<=0)
1944  {
1945    if(dd<0){return(0);}
1946    else{return(1);}
1947  }
1948  int m1,m2;
1949  m1=nvars(basering);
1950  while(wwtop[m1]>dd)
1951  {
1952    m1--;
1953    if(m1==0){return(0);}
1954  }
1955  attrib(stdtop,"isSB",1);
1956  poly mo=1;
1957  if(m1==1)
1958  {
1959    m2=dd/wwtop[1];
1960    if((m2*wwtop[1])==dd)
1961    {
1962      mo=var(1)^m2;
1963      if(reduce(mo,stdtop)==mo){return(mo);}
1964      else{return(0);}
1965    }
1966  }
1967  kbtop=0;
1968  m2=dd;
1969  weightmon(m1-1,m2,mo);
1970  while(m2>=wwtop[m1])
1971  {
1972    m2=m2-wwtop[m1];
1973    mo=mo*var(m1);
1974    if(m2==0)
1975    {
1976      if(reduce(mo,stdtop)==mo)
1977      {
1978        kbtop=kbtop+mo;
1979        return(kbtop);
1980      }
1981    }
1982    weightmon(m1-1,m2,mo);
1983  }
1984  return(kbtop);
1985}
1986// the recursive prozedur
1987//    va     - number of the variable
1988//    drest  - rest of the degree
1989//    mm     - the candidate
1990static proc weightmon(int va, int drest, poly mm)
1991{
1992  while(wwtop[va]>drest)
1993  {
1994    va--;
1995    if(va==0){return();}
1996  }
1997  int m2;
1998  if(va==1)
1999  {
2000    m2=drest/wwtop[1];
2001    if((m2*wwtop[1])==drest)
2002    {
2003      mm=mm*var(1)^m2;
2004      if(reduce(mm,stdtop)==mm){kbtop=kbtop+mm;}
2005    }
2006    return();
2007  }
2008  m2=drest;
2009  weightmon(va-1,m2,mm);
2010  while(m2>=wwtop[va])
2011  {
2012    m2=m2-wwtop[va];
2013    mm=mm*var(va);
2014    if(m2==0)
2015    {
2016      if(reduce(mm,stdtop)==mm)
2017      {
2018        kbtop=kbtop+mm;
2019        return();
2020      }
2021    }
2022    weightmon(va-1,m2,mm);
2023  }
2024  return();
2025}
2026example
2027{ "EXAMPLE:"; echo=2;
2028  ring r=0,(x,y,z),dp;
2029  ideal i = x6,y4,xyz;
2030  intvec w = 2,3,6;
2031  weightKB(i, 12, list(w));
2032}
2033//////////////////////////////////////////////////////////////////////////////
2034
2035/*
2036///////////////////////////////////////////////////////////////////////////////
2037proc downsizeSB (I, list #)
2038"USAGE:   downsizeSB(I [,l]); I ideal, l list of integers [default: l=0]
2039RETURN:  intvec, say v, with v[j] either 1 or 0. We have v[j]=1 if
2040         leadmonom(I[j]) is divisible by some leadmonom(I[k]) or if
2041         leadmonom(i[j]) == leadmonom(i[k]) and l[j] >= l[k], with k!=j.
2042PURPOSE: The procedure is applied in a situation where the standard basis
2043         computation in the basering R is done via a conversion through an
2044         overring Phelp with additional variables and where a direct
2045         imap from Phelp to R is too expensive.
2046         Assume Phelp is created by the procedure @code{par2varRing} or
2047         @code{hilbRing} and IPhelp is a SB in Phelp [ with l[j]=
2048         length(IPhelp(j)) or any other integer reflecting the complexity
2049         of a IPhelp[j] ]. Let I = lead(IPhelp) mapped to R and compute
2050         v = downsizeSB(imap(Phelp,I),l) in R. Then, if Ihelp[j] is deleted
2051         for all j with v[j]=1, we can apply imap to the remaining generators
2052         of Ihelp and still get SB in R  (in general not minimal).
2053EXAMPLE: example downsizeSB; shows an example"
2054{
2055   int k,j;
2056   intvec v,l;
2057   poly M,N,W;
2058   int c=size(I);
2059   if( size(#) != 0 )
2060   {
2061     if ( typeof(#[1]) == "intvec" )
2062     {
2063       l = #[1];
2064     }
2065     else
2066     {
2067        ERROR("2nd argument must be an intvec");
2068     }
2069   }
2070
2071   l[c+1]=0;
2072   v[c]=0;
2073
2074   j=0;
2075   while(j<c-1)
2076   {
2077     j++;
2078     M = leadmonom(I[j]);
2079     if( M != 0 )
2080     {
2081        for( k=j+1; k<=c; k++ )
2082        {
2083          N = leadmonom(I[k]);
2084          if( N != 0 )
2085          {
2086             if( (M==N) && (l[j]>l[k]) )
2087             {
2088               I[j]=0;
2089               v[j]=1;
2090               break;
2091             }
2092             if( (M==N) && (l[j]<=l[k]) || N/M != 0 )
2093             {
2094               I[k]=0;
2095               v[k]=1;
2096             }
2097          }
2098        }
2099      }
2100   }
2101   return(v);
2102}
2103example
2104{ "EXAMPLE:"; echo = 2;
2105   ring  r = 0,(x,y,z,t),(dp(3),dp);
2106   ideal i = x+y+z+t,xy+yz+xt+zt,xyz+xyt+xzt+yzt,xyzt-t4;
2107   ideal Id = std(i);
2108   ideal I = lead(Id);  I;
2109   ring S = (0,t),(x,y,z),dp;
2110   downsizeSB(imap(r,I));
2111   //Id[5] can be deleted, we still have a SB of i in the ring S
2112
2113   ring R = (0,x),(y,z,u),lp;
2114   ideal i = x+y+z+u,xy+xu+yz+zu,xyz+xyu+xzu+yzu,xyzu-1;
2115   def Phelp = par2varRing()[1];
2116   setring Phelp;
2117   ideal IPhelp = std(imap(R,i));
2118   ideal I = lead(IPhelp);
2119   setring R;
2120   ideal I = imap(Phelp,I); I;
2121   intvec v = downsizeSB(I); v;
2122}
2123///////////////////////////////////////////////////////////////////////////
2124// PROBLEM: Die Prozedur funktioniert nur fuer Ringe die global bekannt
2125//          sind, also interaktiv, aber nicht aus einer Prozedur.
2126//          Z.B. funktioniert example imapDownsize; nicht
2127
2128proc imapDownsize (string R, string I)
2129"SYNTAX: @code{imapDownsize (} string @code{,} string @code{)} *@
2130         First string must be the string of the name of a ring, second
2131         string must be the string of the name of an object in the ring.
2132TYPE:    same type as the object with name the second string
2133PURPOSE: maps the object given by the second string to the basering.
2134         If R resp. I are the first resp. second string, then
2135         imapDownsize(R,I) is equivalent to simplify(imap(`R`,`I`),34).
2136NOTE:    imapDownsize is usually faster than imap if `I` is large and if
2137         simplify has a great effect, since the procedure maps only those
2138         generators from `I` which are not killed by simplify( - ,34).
2139         This is useful if `I` is a standard bases for a block ordering of
2140         `R` and if some variables from the last block in `R` are mapped
2141         to parameters. Then the returned result is a standard basis in
2142         the basering.
2143SEE ALSO: imap, fetch, map
2144EXAMPLE: example imapDownsize; shows an example"
2145{
2146       def BR = basering;
2147       int k;
2148
2149       setring `R`;
2150       def @leadI@ = lead(`I`);
2151       int s = ncols(@leadI@);
2152       setring BR;
2153       ideal @leadI@ = simplify(imap(`R`,@leadI@),32);
2154       intvec vi;
2155       for (k=1; k<=s; k++)
2156       {
2157         vi[k] = @leadI@[k]==0;
2158       }
2159       kill @leadI@;
2160
2161       setring `R`;
2162       kill @leadI@;
2163       for (k=1;  k<=s; k++)
2164       {
2165           if( vi[k]==1 )
2166           {
2167              `I`[k]=0;
2168           }
2169       }
2170       `I` = simplify(`I`,2);
2171
2172       setring BR;
2173       return(imap(`R`,`I`));
2174}
2175example
2176{ "EXAMPLE:"; echo = 2;
2177   ring  r = 0,(x,y,z,t),(dp(3),dp);
2178   ideal i = x+y+z+t,xy+yz+xt+zt,xyz+xyt+xzt+yzt,xyzt-1;
2179   i = std(i); i;
2180
2181   ring s = (0,t),(x,y,z),dp;
2182   imapDownsize("r","i");     //i[5] is omitted since lead(i[2]) | lead(i[5])
2183}
2184///////////////////////////////////////////////////////////////////////////////
2185//die folgende proc war fuer groebner mit fglm vorgesehen
2186//um die projektive Dimension korrekt zu berechnen, muss man aber
2187//voerher ein SB bzgl. einer Gradordnung berechnen und dann homogenisieren.
2188//Sonst koennen hoeherdimensionale Komponenten in Unendlich entstehen
2189
2190proc projInvariants(ideal i,list #)
2191"SYNTAX: @code{projInvariants (} ideal_expression @code{)} @*
2192         @code{projInvariants (} ideal_expression@code{,} list of string_expres          sions@code{)}
2193TYPE:    list, say L, with L[1] and L[2] of type int and L[3] of type intvec
2194PURPOSE: Computes the (projective) dimension (L[1]), degree (L[2]) and the
2195         first Hilbert series (L[3], as intvec) of the homogenized ideal
2196         in the ring given by the procedure @code{hilbRing} with global
2197         ordering dp (resp. wp if the variables have weights >1)
2198         If an argument of type string @code{\"std\"} resp. @code{\"slimgb\"}
2199         is given, the standard basis computatuion uses @code{std} or
2200         @code{slimgb}, otherwise a heuristically chosen method (default)
2201NOTE:    Homogenized means weighted homogenized with respect to the weights
2202         w[i] of the variables var(i) of the basering. The returned dimension,
2203         degree and Hilbertseries are the respective invariants of the
2204         projective variety defined by the homogenized ideal. The dimension
2205         is equal to the (affine) dimension of the ideal in the basering
2206         (degree and Hilbert series make only sense for homogeneous ideals).
2207SEE ALSO: dim, dmult, hilb
2208KEYWORDS: dimension, degree, Hilbert function
2209EXAMPLE: example projInvariants;  shows an example"
2210{
2211  def P = basering;
2212  int p_opt;
2213  string s_opt = option();
2214  if (find(option(), "prot"))  { p_opt = 1; }
2215
2216//---------------- check method and clear denomintors --------------------
2217  int k;
2218  string method;
2219  for (k=1; k<=size(#); k++)
2220  {
2221     if (typeof(#[k]) == "string")
2222     {
2223       method = method + "," + #[k];
2224     }
2225  }
2226
2227  if (npars(P) > 0)             //clear denominators of parameters
2228  {
2229    for( k=ncols(i); k>0; k-- )
2230    {
2231       i[k]=cleardenom(i[k]);
2232    }
2233  }
2234
2235//------------------------ change to hilbRing ----------------------------
2236     list hiRi = hilbRing(i);
2237     intvec W = hiRi[2];
2238     def Philb = hiRi[1];      //note: Philb is no qring and the predefined
2239     setring Philb;            //ideal Id(1) in Philb is homogeneous
2240     int di, de;               //for dimension, degree
2241     intvec hi;                //for hilbert series
2242
2243//-------- compute Hilbert function of homogenized ideal in Philb ---------
2244//Philb has only 1 block. There are three cases
2245
2246     string algorithm;       //possibilities: std, slimgb, stdorslimgb
2247     //define algorithm:
2248     if( find(method,"std") && !find(method,"slimgb") )
2249     {
2250        algorithm = "std";
2251     }
2252     if( find(method,"slimgb") && !find(method,"std") )
2253     {
2254         algorithm = "slimgb";
2255     }
2256     if( find(method,"std") && find(method,"slimgb") ||
2257         (!find(method,"std") && !find(method,"slimgb")) )
2258     {
2259         algorithm = "stdorslimgb";
2260     }
2261
2262     if ( algorithm=="std" || ( algorithm=="stdorslimgb" && char(P)>0 ) )
2263     {
2264        if (p_opt) {"std in ring " + string(Philb);}
2265        Id(1) = std(Id(1));
2266        di = dim(Id(1))-1;
2267        de = mult(Id(1));
2268        hi = hilb( Id(1),1,W );
2269     }
2270     if ( algorithm=="slimgb" || ( algorithm=="stdorslimgb" && char(P)==0 ) )
2271     {
2272        if (p_opt) {"slimgb in ring " + string(Philb);}
2273        Id(1) = slimgb(Id(1));
2274        di = dim( Id(1) );
2275        if (di > -1)
2276        {
2277           di = di-1;
2278        }
2279        de = mult( Id(1) );
2280        hi = hilb( Id(1),1,W );
2281     }
2282     kill Philb;
2283     list L = di,de,hi;
2284     return(L);
2285}
2286example
2287{ "EXAMPLE:"; echo = 2;
2288   ring r = 32003,(x,y,z),lp;
2289   ideal i = y2-xz,x2-z;
2290   projInvariants(i);
2291
2292   ring R = (0),(x,y,z,u,v),lp;
2293   //minpoly = x2+1;
2294   ideal i = x2+1,x2+y+z+u+v,xyzuv-1;
2295   projInvariants(i);
2296   qring S =std(x2+1);
2297   ideal i = imap(R,i);
2298   projInvariants(i);
2299}
2300
2301*/
Note: See TracBrowser for help on using the repository browser.