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

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