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

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