source: git/Singular/LIB/standard.lib @ 4bde6b

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