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

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