source: git/Singular/LIB/standard.lib @ 2302217

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