source: git/Singular/LIB/sagbi.lib @ a57b65

spielwiese
Last change on this file since a57b65 was 3686937, checked in by Oleksandr Motsak <motsak@…>, 11 years ago
Added '$Id$' as a comment to all libs (LIB/*.lib)
  • Property mode set to 100644
File size: 39.7 KB
Line 
1///////////////////////////////////////////////////////////////////////////
2version="version sagbi.lib 4.0.0.0 Jun_2013 "; // $Id$
3category="Commutative Algebra";
4info="
5LIBRARY: sagbi.lib  Compute SAGBI basis (subalgebra bases analogous to Groebner bases for ideals) of a subalgebra
6AUTHORS: Jan Hackfeld,     Jan.Hackfeld@rwth-aachen.de
7         Gerhard Pfister,  pfister@mathematik.uni-kl.de
8         Viktor Levandovskyy,     levandov@math.rwth-aachen.de
9
10OVERVIEW:
11SAGBI stands for 'subalgebra bases analogous to Groebner bases for ideals'.
12SAGBI bases provide important tools for working with finitely presented
13subalgebras of a polynomial ring. Note, that in contrast to Groebner
14bases, SAGBI bases may be infinite.
15
16REFERENCES:
17Ana Bravo: Some Facts About Canonical Subalgebra Bases,
18MSRI Publications  51, p. 247-254
19
20PROCEDURES:
21 sagbiSPoly(A [,r,m]); computes SAGBI S-polynomials of A
22 sagbiReduce(I,A [,t,mt]);  performs subalgebra reduction of I by A
23 sagbi(A [,m,t]);      computes SAGBI basis for A
24 sagbiPart(A,k[,m]);   computes partial SAGBI basis for A
25 algebraicDependence(I,it); performs iterations of SAGBI for algebraic dependencies of I
26
27SEE ALSO: algebra_lib
28";
29
30LIB "elim.lib";
31LIB "toric.lib";
32LIB "algebra.lib";
33//////////////////////////////////////////////////////////////////////////////
34
35static proc assumeQring()
36{
37  if (ideal(basering) != 0)
38  {
39    ERROR("This function has not yet been implemented over qrings.");
40  }
41}
42
43
44static proc uniqueVariableName (string variableName)
45{
46  //Adds character "@" at the beginning of variableName until this name ist unique
47  //(not contained in the names of the ring variables or description of the coefficient field)
48  string ringVars = charstr(basering) + "," + varstr(basering);
49  while (find(ringVars,variableName) <> 0)
50  {
51    variableName="@"+variableName;
52  }
53  return(variableName);
54}
55
56static proc extendRing(r, ideal leadTermsAlgebra, int method) {
57  /* Extends ring r with additional variables. If k=ncols(leadTermsAlgebra) and
58   * r contains already m additional variables @y, the procedure adds k-m variables
59   * @y(m+1)...@y(k) to the ring.
60   * The monomial ordering of the extended ring depends on method.
61   * Important: When calling this function, the basering (where algebra is defined) has to be active
62   */
63  def br=basering;
64  int i;
65  ideal varsBasering=maxideal(1);
66  int numTotalAdditionalVars=ncols(leadTermsAlgebra);
67  string variableName=uniqueVariableName("@y");
68  //get a variable name different from existing variables
69
70  //-------- extend current baserring r with new variables @y,
71  // one for each new element in ideal algebra  -------------
72  setring r;
73  list l = ringlist(r);
74  for (i=nvars(r)-nvars(br)+1; i<=numTotalAdditionalVars;i++)
75  {
76    l[2][i+nvars(br)]=string(variableName,"(",i,")");
77  }
78  if (method>=0 && method<=1)
79  {
80    if (nvars(r)==nvars(br))
81    {        //first run of spolynomialGB in sagbi construction algorithms
82      l[3][size(l[3])+1]=l[3][size(l[3])]; //save module ordering
83      l[3][size(l[3])-1]=list("dp",intvec(1:numTotalAdditionalVars));
84    }
85    else
86    {        //overwrite existing order for @y(i) to only get one block for the @y
87      l[3][size(l[3])-1]=list("dp",intvec(1:numTotalAdditionalVars));
88    }
89  }
90  // VL : todo noncomm case: correctly use l[5] and l[6]
91  // that is update matrices
92  // at the moment this is troublesome, so use nc_algebra call
93  // see how it done in algebraicDependence proc // VL
94  def rNew=ring(l);
95  setring br;
96  return(rNew);
97}
98
99
100static proc stdKernPhi(ideal kernNew, ideal kernOld, ideal leadTermsAlgebra,int method)
101{
102  /* Computes Groebner basis of kernNew+kernOld, where kernOld already is a GB
103   * and kernNew contains elements of the form @y(i)-leadTermsAlgebra[i] added to it.
104   * The techniques chosen is specified by the integer method
105   */
106  ideal kern;
107  attrib(kernOld,"isSB",1);
108  if (method==0)
109  {
110    kernNew=reduce(kernNew,kernOld);
111    kern=kernOld+kernNew;
112    kern=std(kern);
113    //kern=std(kernOld,kernNew); //Found bug using this method.
114    // TODO Change if bug is removed
115    //this call of std return Groebner Basis of ideal kernNew+kernOld
116    // given that kernOld is a Groebner basis
117  }
118  if (method==1)
119  {
120    kernNew=reduce(kernNew,kernOld);
121    kern=slimgb(kernNew+kernOld);
122  }
123  return(kern);
124}
125
126
127static proc spolynomialsGB(ideal algebra,r,int method)
128{
129  /* This procedure does the actual S-polynomial calculation using Groebner basis methods and is
130   * called by the procedures sagbiSPoly,sagbi and sagbiPart. As this procedure is called
131   * at each step of the SAGBI construction algorithm, we can reuse the information already calculated
132   * which is contained in the ring r. This is done in the following order
133   * 1. If r already contain m additional variables and m'=number of elements in algebra, extend r with variables @y(m+1),...,@y(m')
134   * 2. Transfer all objects to this ring, kernOld=kern is the Groebnerbasis already computed
135   * 3. Define ideal kernNew containing elements of the form leadTermsAlgebra(m+1)-@y(m+1),...,leadTermsAlgebra(m')-@y(m')
136   * 4. Compute Groebnerbasis of kernOld+kernNew
137   * 5. Compute the new algebraic relations
138   */
139  int ppl = printlevel-voice+3; //variable for additional printlevel-dependend information
140  dbprint(ppl,"//Spoly-1- initialisation and precomputation");
141  def br=basering;
142  ideal varsBasering=maxideal(1);
143  ideal leadTermsAlgebra=lead(algebra);
144  //save leading terms as ordering in ring extension
145  //may not be compatible with ordering in basering
146  int numGenerators=ncols(algebra);
147
148  def rNew=extendRing(r,leadTermsAlgebra,method);
149  // important: br has to be active here
150  setring r;
151  if (!defined(kern))
152  //only true for first run of spolynomialGB in sagbi construction algorithms
153  {
154    ideal kern=0;
155    ideal algebraicRelations=0;
156  }
157  setring rNew;
158  //-------------------------- transfer object to new ring rNew ----------------------
159  ideal varsBasering=fetch(br,varsBasering);
160  ideal kernOld,algebraicRelationsOld;
161  kernOld=fetch(r,kern); //kern is Groebner basis of the kernel of the map Phi:r->K[x_1,...,x_n], x(i)->x(i), @y(i)->leadTermsAlgebra(i)
162  algebraicRelationsOld=fetch(r,algebraicRelations);
163  ideal leadTermsAlgebra=fetch(br,leadTermsAlgebra);
164  ideal listOfVariables=maxideal(1);
165  //---------define kernNew containing elements to be added to the ideal kern --------
166  ideal kernNew;
167  for (int i=nvars(r)-nvars(br)+1; i<=numGenerators; i++)
168  {
169    kernNew[i-nvars(r)+nvars(br)]=leadTermsAlgebra[i]-listOfVariables[i+nvars(br)];
170  }
171  //--------------- calculate kernel of Phi depending on method chosen ---------------
172  dbprint(ppl,"//Spoly-2- Groebner basis computation");
173  attrib(kernOld,"isSB",1);
174  ideal kern=stdKernPhi(kernNew,kernOld,leadTermsAlgebra,method);
175  dbprint(ppl-2,"//Spoly-2-1- ideal kern",kern);
176  //-------------------------- calulate algebraic relations -----------------------
177  dbprint(ppl,"//Spoly-3- computing new algebraic relations");
178  ideal algebraicRelations=nselect(kern,1..nvars(br));
179  attrib(algebraicRelationsOld,"isSB",1);
180  ideal algebraicRelationsNew=reduce(algebraicRelations,algebraicRelationsOld);
181  /* canonicalizing: */
182  algebraicRelationsNew=canonicalform(algebraicRelationsNew);
183  dbprint(ppl-2,"//Spoly-3-1- ideal of new algebraic relations",algebraicRelationsNew);
184  /*        algebraicRelationsOld is a groebner basis by construction (as variable
185   *        ordering is
186   *        block ordering we have an elemination ordering for the varsBasering)
187   *        Therefore, to only get the new algebraic relations, calculate
188   *        <algebraicRelations>\<algebraicRelationsOld> using groebner reduction
189   */
190  kill kernOld,kernNew,algebraicRelationsOld,listOfVariables;
191  export algebraicRelationsNew,algebraicRelations,kern;
192  setring br;
193  return(rNew);
194}
195
196static proc spolynomialsToric(ideal algebra) {
197  /* This procedure does the actual S-polynomial calculation using toric.lib for
198   * computation of a Groebner basis for the toric ideal kern(phi), where
199   * phi:K[y_1,...,y_m]->K[x_1,...,x_n], y_i->leadmonom(algebra[i])
200   * By suitable substitutions we obtain the kernel of the map
201   * K[y_1,...,y_m]->K[x_1,...,x_n], x(i)->x(i), @y(i)->leadterm(algebra[i])
202   */
203  int ppl = printlevel-voice+3; //variable for additional printlevel-dependend information
204  dbprint(ppl,"//Spoly-1- initialisation and precomputation");
205  def br=basering;
206  int m=ncols(algebra);
207  int n=nvars(basering);
208  intvec tempVec;
209  int i,j;
210  ideal leadCoefficients;
211  for (i=1;i<=m; i++)
212  {
213    leadCoefficients[i]=leadcoef(algebra[i]);
214  }
215  dbprint(ppl-2,"//Spoly-1-1- Vector of leading coefficients",leadCoefficients);
216  int k=1;
217  for (i=1;i<=n;i++)
218  {
219    for (j=1; j<=m; j++)
220    {
221      tempVec[k]=leadexp(algebra[j])[i];
222      k++;
223    }
224  }
225  //The columns of the matrix A are now the exponent vectors
226  //of the leadings monomials in algebra.
227  intmat A[n][m]=intmat(tempVec,n,m);
228  dbprint(ppl-2,"//Spoly-1-2- Matrix A",A);
229  //Create the preimage ring K[@y(1),...,@y(m)], where m=ncols(algebra).
230  string variableName=uniqueVariableName("@y");
231  list l = ringlist(basering);
232  for (i=1; i<=m;i++)
233  {
234    l[2][i]=string(variableName,"(",i,")");
235  }
236  l[3][2]=l[3][size(l[3])];
237  l[3][1]=list("dp",intvec(1:m));
238  def rNew=ring(l);
239  setring rNew;
240  //Use toric_ideal to compute the kernel
241   dbprint(ppl,"//Spoly-2- call of toric_ideal");
242  ideal algebraicRelations=toric_ideal(A,"ect");
243  //Suitable substitution
244        dbprint(ppl,"//Spoly-3- substitutions");
245  ideal leadCoefficients=fetch(br,leadCoefficients);
246  for (i=1; i<=m; i++)
247  {
248    if (leadCoefficients[i]!=0)
249    {
250      algebraicRelations=subst(algebraicRelations,var(i),1/leadCoefficients[i]*var(i));
251    }
252  }
253        dbprint(ppl-2,"//Spoly-3-1- algebraic relations",algebraicRelations);
254  export algebraicRelations;
255  return(rNew);
256}
257
258
259static proc reductionGB(ideal F, ideal algebra,r, int tailreduction,int method,int parRed)
260{
261  /* This procedure does the actual SAGBI/subalgebra reduction using GB methods and is
262   * called by the procedures sagbiReduce,sagbi and sagbiPart
263   * If r already is an extension of the basering
264   * and contains the ideal kern needed for the subalgebra reduction,
265   * the reduction can be started directly, at each reduction step using the fact that
266   * p=reduce(leadF,kern) in K[@y(1),...,@y(m)] <=> leadF in K[lead(algebra)]
267   * Otherwise some precomputation has to be done, outlined below.
268   * When using sagbiReduce,sagbi and sagbiPart the integer parRed will always be zero. Only the procedure
269   * algebraicDependence causes this procedure to be called with parRed<>0. The only difference when parRed<>0
270   * is that the reduction algorithms returns the non-zero constants it attains (instead of just returning zero as the
271         * correct remainder), as they will be expressions in parameters for an algebraic dependence.
272   */
273  int ppl = printlevel-voice+3; //variable for additional printlevel-dependend information
274  dbprint(ppl,"//Red-1- initialisation and precomputation");
275  def br=basering;
276  int numVarsBasering=nvars(br);
277  ideal varsBasering=maxideal(1);
278  int i;
279
280  if (numVarsBasering==nvars(r))
281  {
282                dbprint(ppl-1,"//Red-1-1- Groebner basis computation");
283    /* Case that ring r is the same ring as the basering. Using proc extendRing,
284     * stdKernPhi
285     * one construct the extension of the current baserring with new variables @y, one for each element
286     * in ideal algebra and calculates the kernel of Phi, where
287     * Phi: r---->br, x_i-->x_i, y_i-->f_i,
288     * algebra={f_1,...f_m}, br=K[x1,...,x_n] und r=K[x1,...x_n,@y1,...@y_m]
289     * This is similarly dones
290     * (however step by step for each run of the SAGBI construction algorithm)
291     * in the procedure spolynomialsGB
292     */
293    ideal leadTermsAlgebra=lead(algebra);
294    kill r;
295    def r=extendRing(br,leadTermsAlgebra,method);
296    setring r;
297    ideal listOfVariables=maxideal(1);
298    ideal leadTermsAlgebra=fetch(br,leadTermsAlgebra);
299    ideal kern;
300    for (i=1; i<=ncols(leadTermsAlgebra); i++)
301    {
302      kern[i]=leadTermsAlgebra[i]-listOfVariables[numVarsBasering+i];
303    }
304    kern=stdKernPhi(kern,0,leadTermsAlgebra,method);
305    dbprint(ppl-2,"//Red-1-1-1- Ideal kern",kern);
306  }
307  setring r;
308  poly p,leadF;
309  ideal varsBasering=fetch(br,varsBasering);
310  setring br;
311  map phi=r,varsBasering,algebra;
312  poly p,normalform,leadF;
313  intvec tempExp;
314  //-------------algebraic reduction for each polynomial F[i] ------------------------
315  dbprint(ppl,"//Red-2- reduction, polynomial by polynomial");
316  for (i=1; i<=ncols(F);i++)
317  {
318                dbprint(ppl-1,"//Red-2-"+string(i)+"- starting with new polynomial");
319                dbprint(ppl-2,"//Red-2-"+string(i)+"-1- Polynomial before reduction",F[i]);
320    normalform=0;
321    while (F[i]!=0)
322    {
323      leadF=lead(F[i]);
324      if(leadmonom(leadF)==1)
325      {
326      //K is always contained in the subalgebra,
327      //thus the remainder is zero in this case
328        if (parRed)
329        {
330                                //If parRed<>0 save non-zero constants the reduction algorithms attains.
331                                        break;
332                                }
333        else
334        {
335                                        F[i]=0;
336                                        break;
337                                }
338      }
339      //note: as the ordering in br and r might not be compatible
340      //it can be that lead(F[i]) in r is
341      //different from lead(F[i]) in br.
342      //To take the "correct" leading term therefore take lead(F[i])
343      //in br and transfer it to the extension r
344      setring r;
345      leadF=fetch(br,leadF);
346      p=reduce(leadF,kern);
347      if (leadmonom(p)<varsBasering[numVarsBasering])
348      {
349        //as chosen ordering is a block ordering,
350        //lm(p) in K[y_1...y_m] is equivalent to lm(p)<x_n
351        //Needs to be changed, if no block ordering is used!
352        setring br;
353        F[i]=F[i]-phi(p);
354      }
355      else
356      {
357        if (tailreduction)
358        {
359          setring br;
360          normalform=normalform+lead(F[i]);
361          F[i]=F[i]-lead(F[i]);
362        }
363        else
364        {
365          setring br;
366          break;
367        }
368      }
369    }
370    if (tailreduction)
371    {
372      F[i] = normalform;
373    }
374    dbprint(ppl-2,"//Red-2-"+string(i)+"-2- Polynomial after reduction",F[i]);
375  }
376  return(F);
377}
378
379static proc reduceByMonomials(ideal algebra)
380/*This procedures uses the sagbiReduce procedure to reduce all polynomials in algebra,
381 * which are not monomials, by the subset of all monomials.
382 */
383{
384  ideal monomials;
385  int i;
386  for (i=1; i<=ncols(algebra);i++)
387  {
388    if(size(algebra[i])==1)
389    {
390      monomials[i]=algebra[i];
391      algebra[i]=0;
392    }
393    else
394    {
395      monomials[i]=0;
396    }
397  }
398  //Monomials now contains the subset of all monomials in algebra,
399  //algebra contains the non-monomials.
400  if(size(monomials)>0)
401  {
402    algebra=sagbiReduce(algebra,monomials,1);
403    for (i=1; i<=ncols(algebra);i++)
404    {
405      if(size(monomials[i])==1)
406      {
407        //Put back monomials into algebra.
408        algebra[i]=monomials[i];
409      }
410    }
411  }
412  return(algebra);
413}
414
415
416static proc sagbiConstruction(ideal algebra, int iterations, int tailreduction, int method,int parRed)
417/* This procedure is the SAGBI construction algorithm and does the actual computation
418 * both for the procedure sagbi and sagbiPart.
419 * - If the sagbi procedure calls this procedure, iterations==-1
420 *   and this procedure only stops
421 *   if all S-Polynomials reduce to zero
422 *   (criterion for termination of SAGBI construction algorithm).
423 * - If the sagbiPart procedure calls this procedure, iterations>=0
424 *   and iterations specifies the
425 *   number of iterations. A degree boundary is not used here.
426 * When this method is called via the procedures sagbi and sagbiPart the integer parRed
427 * will always be zero. Only the procedure algebraicDependence calls this procedure with
428 * parRed<>0. The only difference when parRed<>0 is that the reduction algorithms returns
429 * the non-zero constants it attains (instead of just returning zero as the correct
430 * remainder), as they will be expressions in parameters for an algebraic dependence.
431 * These constants are saved in the ideal reducedParameters.
432 */
433{
434  int ppl = printlevel-voice+3; //variable for additional printlevel-dependend information
435  dbprint(ppl,"// -0- initialisation and precomputation");
436  def br=basering;
437  int i=1;
438
439  ideal reducedParameters;
440  int numReducedParameters=1; //number of elements plus one in reducedParameters
441  int j;
442  if (parRed==0) //if parRed<>0 the algebra does not contain monomials and normalisation should be avoided
443  {
444    algebra=reduceByMonomials(algebra);
445    algebra=simplify(simplify(algebra,3),4);
446  }
447  // canonicalizing the gen's:
448  algebra = canonicalform(algebra);
449  ideal P=1;
450  //note: P is initialized this way, so that the while loop is entered.
451  //P gets overriden there, anyhow.
452  ideal varsBasering=maxideal(1);
453  map phi;
454  ideal spolynomialsNew;
455  def r=br;
456  while (size(P)>0)
457  {
458    dbprint(ppl,"// -"+string(i)+"- interation of SAGBI construction algorithm");
459    dbprint(ppl-1,"// -"+string(i)+"-1- Computing algebraic relations");
460    def rNew=spolynomialsGB(algebra,r,method); /* canonicalizing inside! */
461    kill r;
462    def r=rNew;
463    kill rNew;
464    phi=r,varsBasering,algebra;
465    dbprint(ppl-1,"// -"+string(i)+"-2- Substituting into algebraic relations");
466    spolynomialsNew=simplify(phi(algebraicRelationsNew),6);
467    //By construction spolynomialsNew only contains the spolynomials,
468    //that have not already
469    //been calculated in the steps before.
470    dbprint(ppl-1,"// -"+string(i)+"-3- SAGBI reduction");
471    dbprint(ppl-2,"// -"+string(i)+"-3-1- new S-polynomials before reduction",spolynomialsNew);
472    P=reductionGB(spolynomialsNew,algebra,r,tailreduction,method,parRed);
473    if (parRed)
474    {
475      for(j=1; j<=ncols(P); j++)
476      {
477        if (leadmonom(P[j])==1)
478        {
479          reducedParameters[numReducedParameters]=P[j];
480          P[j]=0;
481          numReducedParameters++;
482        }
483      }
484    }
485    if (parRed==0)
486    {
487      P=reduceByMonomials(P);
488      //Reducing with monomials is cheap and can only result in less terms
489      P=simplify(simplify(P,3),4);
490      //Avoid that zeros are added to the bases or one element in P more than once
491    }
492    else
493    {
494      P=simplify(P,6);
495    }
496    /* canonicalize ! */
497    P = canonicalform(P);
498    dbprint(ppl-2,"// -"+string(i)+"-3-1- new S-polynomials after reduction",P);
499    algebra=algebra,P;
500    //Note that elements and order of elements must in algebra must not be changed,
501    //otherwise the already calculated
502    //ideal in r will give wrong results. Thus it is important to use a komma here.
503    i=i+1;
504    if (iterations!=-1 && i>iterations) //When iterations==-1 the number of iterations is unlimited
505    {
506      break;
507    }
508  }
509  if (iterations!=-1)
510  { //case that sagbiPart called this procedure
511    if (size(P)==0)
512    {
513      dbprint(4-voice,
514              "//SAGBI construction algorithm terminated after "+string(i-1)
515              +" iterations, as all SAGBI S-polynomials reduced to 0.
516//Returned generators therefore are a SAGBI basis.");
517    }
518    else
519    {
520      dbprint(4-voice,
521              "//SAGBI construction algorithm stopped as it reached the limit of "
522              +string(iterations)+" iterations.
523//In general the returned generators are no SAGBI basis for the given algebra.");
524    }
525  }
526  kill r;
527  if (parRed)
528  {
529    algebra=algebra,reducedParameters;
530  }
531  algebra = simplify(algebra,6);
532  algebra = canonicalform(algebra);
533  return(algebra);
534}
535
536
537proc sagbiSPoly(ideal algebra,list #)
538"USAGE:   sagbiSPoly(A[, returnRing, meth]);  A is an ideal, returnRing and meth are integers.
539RETURN:   ideal or ring
540ASSUME: basering is not a qring
541PURPOSE: Returns SAGBI S-polynomials of the leading terms of a given ideal A if returnRing=0.
542@*       Otherwise returns a new ring containing the ideals algebraicRelations
543@*       and spolynomials, where these objects are explained by their name.
544@*       See the example on how to access these objects.
545@format     The other optional argument meth determines which method is
546            used for computing the algebraic relations.
547            - If meth=0 (default), the procedure std is used.
548            - If meth=1, the procedure slimgb is used.
549            - If meth=2, the prodecure uses toric_ideal.
550@end format
551EXAMPLE:  example sagbiSPoly; shows an example"
552{
553  assumeQring();
554  int returnRing;
555  int method=0;
556  def br=basering;
557  ideal spolynomials;
558  if (size(#)>=1)
559  {
560    if (typeof(#[1])=="int")
561    {
562      returnRing=#[1];
563    }
564    else
565    {
566      ERROR("Type of first optional argument needs to be int.");
567    }
568  }
569  if (size(#)==2)
570  {
571    if (typeof(#[2])=="int")
572    {
573      if (#[2]<0 || #[2]>2)
574      {
575        ERROR("Type of second optional argument needs to be 0,1 or 2.");
576      }
577      else
578      {
579        method=#[2];
580      }
581    }
582    else
583    {
584      ERROR("Type of second optional argument needs to be int.");
585    }
586  }
587  if (method>=0 and method<=1)
588  {
589    ideal varsBasering=maxideal(1);
590    def rNew=spolynomialsGB(algebra,br,method);
591    map phi=rNew,varsBasering,algebra;
592    spolynomials=simplify(phi(algebraicRelationsNew),7);
593  }
594  if(method==2)
595  {
596    def r2=spolynomialsToric(algebra);
597    map phi=r2,algebra;
598    spolynomials=simplify(phi(algebraicRelations),7);
599    def rNew=extendRing(br,lead(algebra),0);
600    setring rNew;
601    ideal algebraicRelations=imap(r2,algebraicRelations);
602    export algebraicRelations;
603    setring br;
604  }
605
606  if (returnRing==0)
607  {
608    return(spolynomials);
609  }
610  else
611  {
612    setring rNew;
613    ideal spolynomials=fetch(br,spolynomials);
614    export spolynomials;
615    setring br;
616    return(rNew);
617  }
618}
619example
620{ "EXAMPLE:"; echo = 2;
621  ring r= 0,(x,y),dp;
622  ideal A=x*y+x,x*y^2,y^2+y,x^2+x;
623  //------------------ Compute the SAGBI S-polynomials only
624  sagbiSPoly(A);
625  //------------------ Extended ring is to be returned, which contains
626  // the ideal of algebraic relations and the ideal of the S-polynomials
627  def rNew=sagbiSPoly(A,1);  setring rNew;
628  spolynomials;
629  algebraicRelations;
630  //----------------- Now we verify that the substitution of A[i] into @y(i)
631  // results in the spolynomials listed above
632  ideal A=fetch(r,A);
633  map phi=rNew,x,y,A;
634  ideal spolynomials2=simplify(phi(algebraicRelations),1);
635  spolynomials2;
636}
637
638
639proc sagbiReduce(idealORpoly, ideal algebra, list #)
640"USAGE: sagbiReduce(I, A[, tr, mt]); I, A ideals, tr, mt optional integers
641RETURN: ideal of remainders of I after SAGBI reduction by A
642ASSUME: basering is not a qring
643PURPOSE:
644@format
645    The optional argument tr=tailred determines whether tail reduction will be performed.
646     - If (tailred=0), no tail reduction is done.
647     - If (tailred<>0), tail reduction is done.
648     The other optional argument meth determines which method is
649         used for Groebner basis computations.
650         - If mt=0 (default), the procedure std is used.
651         - If mt=1, the procedure slimgb is used.
652@end format
653EXAMPLE:  example sagbiReduce; shows an example"
654{
655  assumeQring();
656  int tailreduction=0; //Default
657  int method=0; //Default
658  ideal I;
659  if(typeof(idealORpoly)=="ideal")
660  {
661    I=idealORpoly;
662  }
663  else
664  {
665    if(typeof(idealORpoly)=="poly")
666    {
667      I[1]=idealORpoly;
668    }
669    else
670    {
671      ERROR("Type of first argument needs to be an ideal or polynomial.");
672    }
673  }
674  if (size(#)>=1)
675  {
676    if (typeof(#[1])=="int")
677    {
678      tailreduction=#[1];
679    }
680    else
681    {
682      ERROR("Type of optional argument needs to be int.");
683    }
684  }
685  if (size(#)>=2 )
686  {
687    if (typeof(#[2])=="int")
688    {
689      if (#[2]<0 || #[2]>1)
690      {
691        ERROR("Type of second optional argument needs to be 0 or 1.");
692      }
693      else
694      {
695        method=#[2];
696      }
697    }
698    else
699    {
700      ERROR("Type of optional arguments needs to be int.");
701    }
702  }
703
704  def r=basering;
705  I=simplify(reductionGB(I,algebra,r,tailreduction,method,0),1);
706
707  if(typeof(idealORpoly)=="ideal")
708  {
709    return(I);
710  }
711  else
712  {
713    if(typeof(idealORpoly)=="poly")
714    {
715      return(I[1]);
716    }
717  }
718}
719example
720{ "EXAMPLE:"; echo = 2;
721  ring r=0,(x,y,z),dp;
722  ideal A=x2,2*x2y+y,x3y2;
723  poly p1=x^5+x2y+y;
724  poly p2=x^16+x^12*y^5+6*x^8*y^4+x^6+y^4+3;
725  ideal P=p1,p2;
726  //---------------------------------------------
727  //SAGBI reduction of polynomial p1 by algebra A.
728  //Default call, that is, no tail-reduction is done.
729  sagbiReduce(p1,A);
730  //---------------------------------------------
731  //SAGBI reduction of set of polynomials P by algebra A,
732  //now tail-reduction is done.
733  sagbiReduce(P,A,1);
734}
735
736proc sagbi(ideal algebra, list #)
737"USAGE:   sagbi(A[, tr, mt]); A ideal, tr, mt optional integers
738RETURN: ideal, a SAGBI basis for A
739ASSUME: basering is not a qring
740PURPOSE: Computes a SAGBI basis for the subalgebra given by the generators in A.
741@format
742    The optional argument tr=tailred determines whether tail reduction will be performed.
743     - If (tailred=0), no tail reduction is performed,
744     - If (tailred<>0), tail reduction is performed.
745     The other optional argument meth determines which method is
746         used for Groebner basis computations.
747         - If mt=0 (default), the procedure std is used.
748         - If mt=1, the procedure slimgb is used.
749@end format
750EXAMPLE:  example sagbi; shows an example"
751{
752  assumeQring();
753  int tailreduction=0; //default value
754  int method=0; //default value
755  if (size(#)>=1)
756  {
757    if (typeof(#[1])=="int")
758    {
759      tailreduction=#[1];
760    }
761    else
762    {
763      ERROR("Type of optional argument needs to be int.");
764    }
765  }
766  if (size(#)>=2 )
767  {
768    if (typeof(#[2])=="int")
769    {
770      if (#[2]<0 || #[2]>1)
771      {
772        ERROR("Type of second optional argument needs to be 0 or 1.");
773      }
774      else
775      {
776        method=#[2];
777      }
778    }
779    else
780    {
781      ERROR("Type of optional arguments needs to be int.");
782    }
783  }
784  ideal a;
785  a=sagbiConstruction(algebra,-1,tailreduction,method,0);
786  a=simplify(a,7);
787  //  a=interreduced(a);
788  return(a);
789}
790example
791{ "EXAMPLE:"; echo = 2;
792  ring r= 0,(x,y,z),dp;
793  ideal A=x2,y2,xy+y;
794  //Default call, no tail-reduction is done.
795  sagbi(A);
796  //---------------------------------------------
797  //Call with tail-reduction and method specified.
798  sagbi(A,1,0);
799}
800
801proc sagbiPart(ideal algebra, int iterations, list #)
802"USAGE: sagbiPart(A, k,[tr, mt]); A is an ideal, k, tr and mt are integers
803RETURN: ideal
804ASSUME: basering is not a qring
805PURPOSE: Performs k iterations of the SAGBI construction algorithm for the subalgebra given by the generators given by A.
806@format
807     The optional argument tr=tailred determines if tail reduction will be performed.
808     - If (tailred=0), no tail reduction is performed,
809     - If (tailred<>0), tail reduction is performed.
810     The other optional argument meth determines which method is
811         used for Groebner basis computations.
812         - If mt=0 (default), the procedure std is used.
813         - If mt=1, the procedure slimgb is used.
814@end format
815EXAMPLE:  example sagbiPart; shows an example"
816{
817  assumeQring();
818  int tailreduction=0; //default value
819  int method=0; //default value
820  if (size(#)>=1)
821  {
822    if (typeof(#[1])=="int")
823    {
824      tailreduction=#[1];
825    }
826    else
827    {
828      ERROR("Type of optional argument needs to be int.");
829    }
830  }
831  if (size(#)>=2 )
832  {
833    if (typeof(#[2])=="int")
834    {
835      if (#[2]<0 || #[2]>3)
836      {
837        ERROR("Type of second optional argument needs to be 0 or 1.");
838      }
839      else
840      {
841        method=#[2];
842      }
843    }
844    else
845    {
846      ERROR("Type of optional arguments needs to be int.");
847    }
848  }
849  if (iterations<0)
850  {
851    ERROR("Number of iterations needs to be non-negative.");
852  }
853  ideal a;
854  a=sagbiConstruction(algebra,iterations,tailreduction,method,0);
855  a=simplify(a,6);
856  //  a=interreduced(a);
857  return(a);
858}
859example
860{ "EXAMPLE:"; echo = 2;
861  ring r= 0,(x,y,z),dp;
862  //The following algebra does not have a finite SAGBI basis.
863  ideal A=x,xy-y2,xy2;
864  //---------------------------------------------------
865  //Call with two iterations, no tail-reduction is done.
866  sagbiPart(A,2);
867  //---------------------------------------------------
868  //Call with three iterations, tail-reduction and method 0.
869  sagbiPart(A,3,1,0);
870}
871
872
873proc algebraicDependence(ideal I,int iterations)
874"USAGE: algebraicDependence(I,it); I an an ideal, it is an integer
875RETURN: ring
876ASSUME: basering is not a qring
877PURPOSE: Returns a ring containing the ideal @code{algDep}, which contains possibly
878@*                 some algebraic dependencies of the elements of I obtained through @code{it}
879@*                 iterations of the SAGBI construction algorithms. See the example on how
880@*                 to access these objects.
881EXAMPLE: example algebraicDependence; shows an example"
882{
883        assumeQring();
884        int ppl = printlevel-voice+3; //variable for additional printlevel-dependend information
885  dbprint(ppl,"//AlgDep-1- initialisation and precomputation");
886  def br=basering;
887  int i;
888  I=simplify(I,2); //avoid that I contains zeros
889
890        //Create two polynomial rings, which both are extensions of the current basering.
891  //The first ring will contain the additional paramteres @c(1),...,@c(m), the second one
892  //will contain the additional variables @c(1),...,@c(m), where m=ncols(I).
893  string parameterName=uniqueVariableName("@c");
894  list l = ringlist(basering);
895  list parList;
896  for (i=1; i<=ncols(I);i++)
897  {
898    parList[i]=string(parameterName,"(",i,")");
899  }
900  l[1]=list(l[1],parList,list(list("dp",1:ncols(I)))); //add @c(i) to the ring as paramteres
901  ideal temp=0;
902  l[1][4]=temp;
903  // addition VL: noncomm case
904  int isNCcase = 0; // default for comm
905  //         if (size(l)>4)
906  //         {
907  //           // that is we're in the noncomm algebra
908  //           isNCcase = 1; // noncomm
909  //           matrix @C@ = l[5];
910  //           matrix @D@ = l[6];
911  //           l = l[1],l[2],l[3],l[4];
912  //         }
913  def parameterRing=ring(l);
914
915  string extendVarName=uniqueVariableName("@c");
916  list l2 = ringlist(basering);
917  for (i=1; i<=ncols(I);i++)
918  {
919    l2[2][i+nvars(br)]=string(extendVarName,"(",i,")"); //add @c(i) to the rings as variables
920  }
921  l2[3][size(l2[3])+1]=l2[3][size(l2[3])];
922  l2[3][size(l2[3])-1]=list("dp",intvec(1:ncols(I)));
923  //         if (isNCcase)
924  //         {
925  //           // that is we're in the noncomm algebra
926  //           matrix @C@2 = l2[5];
927  //           matrix @D@2 = l2[6];
928  //           l2 = l2[1],l2[2],l2[3],l2[4];
929  //         }
930
931  def extendVarRing=ring(l2);
932  setring extendVarRing;
933  // VL : this requires extended matrices
934  // let's forget it for the moment
935  // since this holds only for showing the answer
936  //         if (isNCcase)
937  //         {
938  //           matrix C2=imap(br,@C@2);
939  //           matrix D2=imap(br,@D@2);
940  //           def er2 = nc_algebra(C2,D2);
941  //           setring er2;
942  //           def extendVarRing=er2;
943  //         }
944
945  setring parameterRing;
946
947  //         if (isNCcase)
948  //         {
949  //           matrix C=imap(br,@C@);
950  //           matrix D=imap(br,@D@);
951  //           def pr = nc_algebra(C,D);
952  //           setring pr;
953  //           def parameterRing=pr;
954  //         }
955
956        //Compute a partial SAGBI basis of the algebra generated by I[1]-@c(1),...,I[m]-@c(m),
957  //where the @c(n) are parameters
958  ideal I=fetch(br,I);
959  ideal algebra;
960  for (i=1; i<=ncols(I);i++)
961  {
962    algebra[i]=I[i]-par(i);
963  }
964  dbprint(ppl,"//AlgDep-2- call of SAGBI construction algorithm");
965  algebra=sagbiConstruction(algebra, iterations,0,0,1);
966  dbprint(ppl,"//AlgDep-3- postprocessing of results");
967  int j=1;
968  //If K[x_1,...,x_n] was the basering, then algebra is in K(@c(1),...,@c(m))[x_1,...x_n]. We intersect
969  //elements in algebra with K(@c(1),..,@c(n)) to get algDep. Note that @c(i) can only appear in the numerator,
970  //as the SAGBI construction algorithms just multiplies and substracts polynomials. So actually we have
971  //algDep=algebra intersect K[@c(1),...,@c(m)]
972  ideal algDep;
973  for (i=1; i<= ncols(algebra); i++)
974  {
975    if (leadmonom(algebra[i])==1) //leadmonom(algebra[i])==1 iff algebra[i] in K[@c(1),...,@c(m)]
976    {
977      algDep[j]=algebra[i];
978      j++;
979    }
980  }
981  //Transfer algebraic dependencies to ring where @c(i) are not parameters, but now variables.
982  setring extendVarRing;
983  ideal algDep=imap(parameterRing,algDep);
984  ideal algebra=imap(parameterRing,algebra);
985  //Now get rid of constants in K that may have been added to algDep.
986  for (i=1; i<=ncols(algDep); i++)
987  {
988                if(leadmonom(algDep[i])==1)
989                {
990                                algDep[i]=0;
991                }
992        }
993        algDep=simplify(algDep,2);
994  export algDep,algebra;
995  setring br;
996  return(extendVarRing);
997}
998example
999{ "EXAMPLE:"; echo = 2;
1000  ring r= 0,(x,y),dp;
1001  //The following algebra does not have a finite SAGBI basis.
1002  ideal I=x^2, xy-y2, xy2;
1003  //---------------------------------------------------
1004  //Call with two iterations
1005  def DI = algebraicDependence(I,2);
1006  setring DI; algDep;
1007  // we see that no dependency has been seen so far
1008  //---------------------------------------------------
1009  //Call with two iterations
1010  setring r; kill DI;
1011  def DI = algebraicDependence(I,3);
1012  setring DI; algDep;
1013  map F = DI,x,y,x^2, xy-y2, xy2;
1014  F(algDep); // we see that it is a dependence indeed
1015}
1016
1017static proc interreduced(ideal I)
1018{
1019  /* performs subalgebra interreduction of a set of subalgebra generators */
1020  int ppl = printlevel-voice+3; //variable for additional printlevel-dependend information
1021  dbprint(ppl,"//Interred-1- starting interreduction");
1022  ideal J,B;
1023  int i,j,k;
1024  poly f;
1025  for(k=1;k<=ncols(I);k++)
1026  {
1027    dbprint(ppl-1,"//Interred-1-"+string(k)+"- reducing next poly");
1028    f=I[k];
1029    I[k]=0;
1030    f=sagbiReduce(f,I,1);
1031    I[k]=f;
1032  }
1033  I=simplify(I,2);
1034  dbprint(ppl,"//Interred-2- interreduction completed");
1035  return(I);
1036}
1037///////////////////////////////////////////////////////////////////////////////
1038
1039proc sagbiReduction(poly p,ideal dom,list #)
1040"USAGE: sagbiReduction(p,dom[,n]); p poly , dom  ideal
1041RETURN: polynomial, after one step of subalgebra reduction
1042PURPOSE:
1043@format
1044    Three algorithm variants are used to perform subalgebra reduction.
1045    The positive interger n determines which variant should be used.
1046    n may take the values 0 (default), 1 or 2.
1047@end format
1048NOTE: works over both polynomial rings and their quotients
1049EXAMPLE: example sagbiReduction; shows an example"
1050{
1051  def bsr=basering;
1052  ideal B=ideal(bsr);//When the basering is quotient ring  this type casting
1053                     // gives the quotient ideal.
1054  int b=size(B);
1055  int n=nvars(bsr);
1056
1057  //In quotient rings, SINGULAR, usually does not reduce polynomials w.r.t the
1058  //quotient ideal,therefore we should first  reduce,
1059  //when it is necessary for computations,
1060  // to have a uniquely determined representant for each equivalent
1061  //class,which is the case of this algorithm.
1062
1063  if(b !=0) //means that the basering is a quotient ring
1064  {
1065    p=reduce(p,std(0));
1066    dom=reduce(dom,std(0));
1067  }
1068
1069  int i,choose;
1070  int z=ncols(dom);
1071
1072  if((size(#)>0) && (typeof(#[1])=="int"))
1073  {
1074    choose = #[1];
1075  }
1076  if (size(#)>1)
1077  {
1078    choose =#[2];
1079  }
1080
1081  //=======================first algorithm(default)=========================
1082  if ( choose == 0 )
1083  {
1084    list L = algebra_containment(lead(p),lead(dom),1);
1085    if( L[1]==1 )
1086    {
1087      // the ring L[2] = char(bsr),(x(1..nvars(bsr)),y(1..z)),(dp(n),dp(m)),
1088      // contains poly check s.t. LT(p) is of the form check(LT(f1),...,LT(fr))
1089      def s1 = L[2];
1090      map psi = s1,maxideal(1),dom;
1091      poly re = p - psi(check);
1092      // divide by the maximal power of #[1]
1093      if ( (size(#)>0) && (typeof(#[1])=="poly") )
1094      {
1095        while ((re!=0) && (re!=#[1]) &&(subst(re,#[1],0)==0))
1096        {
1097          re=re/#[1];
1098        }
1099      }
1100      return(re);
1101    }
1102    return(p);
1103  }
1104  //======================2end variant of algorithm=========================
1105  //It uses two different commands for elimaination.
1106  //if(choose==1):"elimainate"command.
1107  //if (choose==2):"nselect" command.
1108  else
1109  {
1110    poly v=product(maxideal(1));
1111
1112    //------------- change the basering bsr to bsr[@(0),...,@(z)] ----------
1113    execute("ring s=("+charstr(basering)+"),("+varstr(basering)+",@(0..z)),dp;");
1114    // Ev hier die Reihenfolge der Vars aendern. Dazu muss unten aber entsprechend
1115    // geaendert werden:
1116    //  execute("ring s="+charstr(basering)+",(@(0..z),"+varstr(basering)+"),dp;");
1117
1118    //constructs the leading ideal of dom=(p-@(0),dom[1]-@(1),...,dom[z]-@(z))
1119    ideal dom=imap(bsr,dom);
1120    for (i=1;i<=z;i++)
1121    {
1122      dom[i]=lead(dom[i])-var(nvars(bsr)+i+1);
1123    }
1124    dom=lead(imap(bsr,p))-@(0),dom;
1125
1126    //---------- eliminate the variables of the basering bsr --------------
1127    //i.e. computes dom intersected with K[@(0),...,@(z)].
1128
1129    if(choose==1)
1130    {
1131      ideal kern=eliminate(dom,imap(bsr,v));//eliminate does not need a
1132                                            //standard basis as input.
1133    }
1134    if(choose==2)
1135    {
1136      ideal kern= nselect(groebner(dom),1..n);//"nselect" is combinatorial command
1137                                         //which uses the internal command
1138                                         // "simplify"
1139    }
1140
1141    //---------  test wether @(0)-h(@(1),...,@(z)) is in ker ---------------
1142    // for some poly h and divide by maximal power of q=#[1]
1143    poly h;
1144    z=size(kern);
1145    for (i=1;i<=z;i++)
1146    {
1147      h=kern[i]/@(0);
1148      if (deg(h)==0)
1149      {
1150        h=(1/h)*kern[i];
1151        // define the map psi : s ---> bsr defined by @(i) ---> p,dom[i]
1152        setring bsr;
1153        map psi=s,maxideal(1),p,dom;
1154        poly re=psi(h);
1155        // divide by the maximal power of #[1]
1156        if ((size(#)>0) && (typeof(#[1])== "poly") )
1157        {
1158          while ((re!=0) && (re!=#[1]) &&(subst(re,#[1],0)==0))
1159          {
1160            re=re/#[1];
1161          }
1162        }
1163        return(re);
1164      }
1165    }
1166    setring bsr;
1167    return(p);
1168  }
1169}
1170example
1171{"EXAMPLE:"; echo = 2;
1172  ring r= 0,(x,y),dp;
1173  ideal dom =x2,y2,xy-y;
1174  poly p=x4+x3y+xy2-y2;
1175  sagbiReduction(p,dom);
1176  sagbiReduction(p,dom,2);
1177  // now let us see the action over quotient ring
1178  ideal I = xy;
1179  qring Q = std(I);
1180  ideal dom = imap(r,dom); poly p = imap(r,p);
1181  sagbiReduction(p,dom,1);
1182}
1183
1184proc sagbiNF(id,ideal dom,int k,list#)
1185"USAGE: sagbiNF(id,dom,k[,n]); id either poly or ideal,dom ideal, k and n positive intergers.
1186RETURN: same as type of id; ideal or polynomial.
1187PURPOSE:
1188@format
1189    The integer k determines what kind of s-reduction is performed:
1190    - if (k=0) no tail s-reduction is performed.
1191    - if (k=1) tail s-reduction is performed.
1192    Three Algorithm variants are used to perform subalgebra reduction.
1193    The positive integer n determines which variant should be used.
1194    n may take the values (0 or default),1 or 2.
1195@end format
1196NOTE: sagbiNF works over both rings and quotient rings
1197EXAMPLE: example sagbiNF; show example "
1198{
1199  ideal rs;
1200  if (ideal(basering) == 0)
1201  {
1202    rs = sagbiReduce(id,dom,k) ;
1203  }
1204  else
1205  {
1206    rs = sagbiReduction(id,dom,k) ;
1207  }
1208  return(rs);
1209}
1210example
1211{"EXAMPLE:"; echo = 2;
1212 ring r=0,(x,y),dp;
1213 poly p=x4+x2y+y;
1214 ideal dom =x2,x2y+y,x3y2;
1215 sagbiNF(p,dom,1);
1216 ideal I= x2-xy;
1217 qring Q=std(I); // we go to the quotient ring
1218 poly p=imap(r,p);
1219 NF(p,std(0)); // the representative of p has changed
1220 ideal dom = imap(r,dom);
1221 print(matrix(NF(dom,std(0)))); // dom has changed as well
1222 sagbiNF(p,dom,0); // no tail reduction
1223 sagbiNF(p,dom,1);// tail subalgebra reduction is performed
1224}
1225
1226static proc canonicalform(ideal I)
1227{
1228  /* placeholder for the canonical form of a set of gen's */
1229  /* for the time being we agree on content(p)=1; that is coeffs with no fractions */
1230  int i; ideal J=I;
1231  for(i=ncols(I); i>=1; i--)
1232  {
1233    J[i] = canonicalform_poly(I[i]);
1234  }
1235  return(J);
1236}
1237
1238static proc canonicalform_poly(poly p)
1239{
1240  /* placeholder for the canonical form of a poly */
1241  /* for the time being we agree on content(p)=1; that is coeffs with no fractions */
1242  number n = content(p);
1243  return( p/content(p) );
1244}
1245
1246/*
1247  ring r= 0,(x,y),dp;
1248  //The following algebra does not have a finite SAGBI basis.
1249  ideal J=x^2, xy-y2, xy2, x^2*(x*y-y^2)^2 - (x*y^2)^2*x^4 + 11;
1250  //---------------------------------------------------
1251  //Call with two iterations
1252  def DI = algebraicDependence(J,2);
1253  setring DI; algDep;
1254*/
Note: See TracBrowser for help on using the repository browser.