source: git/Singular/LIB/standard.lib

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