source: git/Singular/LIB/bfun.lib @ dfb2c6

spielwiese
Last change on this file since dfb2c6 was dfb2c6, checked in by Viktor Levandovskyy <levandov@…>, 15 years ago
*levandov: bfun and dmodapp seriously reworked git-svn-id: file:///usr/local/Singular/svn/trunk@11521 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100755
File size: 47.3 KB
Line 
1//////////////////////////////////////////////////////////////////////////////
2version="$Id: bfun.lib,v 1.3 2009-03-06 20:32:28 levandov Exp $";
3category="Noncommutative";
4info="
5LIBRARY: bfun.lib     Algorithms for b-functions and Bernstein-Sato polynomial
6AUTHORS: Daniel Andres, daniel.andres@math.rwth-aachen.de
7@* Viktor Levandovskyy,      levandov@math.rwth-aachen.de
8
9THEORY: Given a polynomial ring R = K[x_1,...,x_n] and a polynomial F in R,
10@*      one is interested in the global b-Function (also known as Bernstein-Sato
11@*      polynomial) b(s) in K[s], defined to be the monic polynomial, satisfying
12@*      a functional identity    L * F^{s+1} = b(s) F^s,   
13@*      for some operator L in D[s]. Here, D stands for an n-th Weyl algebra
14@*      K<x_1,...,x_n,d_1,...,d_n | d_j x_j = x_j d_j +1>.
15@*      One is interested in the following data:
16@*      - Bernstein-Sato polynomial b(s) in K[s],
17@*      - the list of its roots, which are known to be rational
18@*      - the multiplicities of the roots.
19@*
20@*    There is a general definition of a b-function of a holonomic ideal [SST]
21@*    (that is, an ideal I in a Weyl algebra D, such that D/I is holonomic module)
22@*    with respect to the given weight vector. B-function b_w(s) is in K[s].
23@*    Unlike Bernstein-Sato polynomial, general B-function with respect to
24@*    arbitrary weights need not have rational roots at all.
25@*
26@*      References: [SST] Saito, Sturmfels, Takayama: Groebner Deformations of
27@*      Hypergeometric Differential Equations (2000),
28@*      Noro: An Efficient Modular Algorithm for Computing the Global b-function,
29@*      (2002).
30
31
32MAIN PROCEDURES:
33
34bfct(f[,s,t,v]);            computes the Bernstein-Sato polynomial of poly f
35bfctSyz(f[,r,s,t,u,v]);     computes the Bernstein-Sato polynomial of poly f
36bfctAnn(f[,s]);             computes the Bernstein-Sato polynomial of poly f
37bfctOneGB(f[,s,t]);         computes the Bernstein-Sato polynomial of poly f
38bfctIdeal(I,w[,s,t]);       computes the global b-function of ideal wrt weight
39pIntersect(f,I[,s]);        intersection of ideal with subalgebra K[f] for poly f
40pIntersectSyz(f,I[,p,s,t]); intersection of ideal with subalgebra K[f] for poly f
41linReduce(f,I[,s]);         reduces a poly by linear reductions only
42linReduceIdeal(I,[s,t]);    reduces generators of ideal by linear reductions only
43linSyzSolve(I[,s]);         computes a linear dependency of elements of ideal I
44
45AUXILIARY PROCEDURES:
46
47allPositive(v);  checks whether all entries of an intvec are positive
48scalarProd(v,w); computes the standard scalar product of two intvecs
49vec2poly(v[,i]); constructs an univariate poly with given coefficients
50
51SEE ALSO: dmod_lib, dmodapp_lib, gmssing_lib
52";
53
54
55LIB "qhmoduli.lib"; // for Max
56LIB "dmod.lib";     // for SannfsBFCT etc
57LIB "dmodapp.lib";  // for initialIdealW etc
58LIB "nctools.lib"; // for isWeyl etc
59
60///////////////////////////////////////////////////////////////////////////////
61// testing for consistency of the library:
62proc testbfunlib ()
63{
64  // tests all procs for consistency
65  "AUXILIARY PROCEDURES:";
66  example allPositive;
67  example scalarProd;
68  example vec2poly;
69  "MAIN PROCEDURES:";
70  example bfct;
71  example bfctSyz;
72  example bfctAnn;
73  example bfctOneGB;
74  example bfctIdeal;
75  example pIntersect;
76  example pIntersectSyz;
77  example linReduce;
78  example linReduceIdeal;
79  example linSyzSolve;
80}
81
82//--------------- auxiliary procedures ----------------------------------------
83
84static proc gradedWeyl (intvec u,intvec v)
85"USAGE:  gradedWeyl(u,v); u,v intvecs
86RETURN:  a ring, the associated graded ring of the basering w.r.t. u and v
87PURPOSE: compute the associated graded ring of the basering w.r.t. u and v
88ASSUME: basering is a Weyl algebra
89EXAMPLE: example gradedWeyl; shows examples
90NOTE:    u[i] is the weight of x(i), v[i] the weight of D(i).
91@*       u+v has to be a non-negative intvec.
92"
93{
94  // todo check assumption
95  int i;
96  def save = basering;
97  int n = nvars(save)/2;
98  if (nrows(u)<>n || nrows(v)<>n)
99  {
100    ERROR("weight vectors have wrong dimension");
101  }
102  intvec uv,gr;
103  uv = u+v;
104  for (i=1; i<=n; i++)
105  {
106    if (uv[i]>=0)
107    {
108      if (uv[i]==0)
109      {
110        gr[i] = 0;
111      }
112      else
113      {
114        gr[i] = 1;
115      }
116    }
117    else
118    {
119      ERROR("the sum of the weight vectors has to be a non-negative intvec");
120    }
121  }
122  list l = ringlist(save);
123  list l2 = l[2];
124  matrix l6 = l[6];
125  for (i=1; i<=n; i++)
126  {
127    if (gr[i] == 1) 
128    {
129       l2[n+i] = "xi("+string(i)+")";
130       l6[i,n+i] = 0;
131    }
132  }
133  l[2] = l2;
134  l[6] = l6;
135  def G = ring(l);
136  return(G);
137}
138example
139{
140  "EXAMPLE:"; echo = 2;
141  ring @D = 0,(x,y,z,Dx,Dy,Dz),dp;
142  def D = Weyl();
143  setring D;
144  intvec u = -1,-1,1; intvec v = 2,1,1;
145  def G = gradedWeyl(u,v);
146  setring G; G;
147}
148
149static proc safeVarName (string s)
150{
151  string cv = "," + charstr(basering) + "," + varstr(basering) + ",";
152  s = "," + s + ",";
153  while (find(cv,s) <> 0)
154  {
155    s[1] = "@";
156    s = "," + s;
157  }
158  s = s[2..size(s)-1];
159  return(s)
160}
161
162proc allPositive (intvec v)
163"USAGE:  allPositive(v);  v an intvec
164RETURN:  int, 1 if all components of v are positive, or 0 otherwise
165PURPOSE: check whether all components of an intvec are positive
166EXAMPLE: example allPositive; shows an example
167"
168{
169  int i;
170  for (i=1; i<=size(v); i++)
171  {
172    if (v[i]<=0)
173    {
174      return(0);
175      break;
176    }
177  }
178  return(1);
179}
180example
181{
182  "EXAMPLE:"; echo = 2;
183  intvec v = 1,2,3;
184  allPositive(v);
185  intvec w = 1,-2,3;
186  allPositive(w);
187}
188
189static proc findFirst (list l, i)
190"USAGE:  findFirst(l,i);  l a list, i an argument of any type
191RETURN:  int, the position of the first appearance of i in l,
192@*       or 0 if i is not a member of l
193PURPOSE: check whether the second argument is a member of a list
194EXAMPLE: example findFirst; shows an example
195"
196{
197  int j;
198  for (j=1; j<=size(l); j++)
199  {
200    if (l[j]==i)
201    {
202      return(j);
203      break;
204    }
205  }
206  return(0);
207}
208//   findFirst(list(1, 2, list(1)),2);       // seems to be a bit buggy,
209//   findFirst(list(1, 2, list(1)),3);       // but works for the purposes
210//   findFirst(list(1, 2, list(1)),list(1)); // of this library
211//   findFirst(l,list(2));
212example
213{
214  "EXAMPLE:"; echo = 2;
215  ring r = 0,x,dp;
216  list l = 1,2,3;
217  findFirst(l,4);
218  findFirst(l,2);
219}
220
221proc scalarProd (intvec v, intvec w)
222"USAGE:  scalarProd(v,w);  v,w intvecs
223RETURN:  int, the standard scalar product of v and w
224PURPOSE: computes the scalar product of two intvecs
225ASSUME:  the arguments are of the same size
226EXAMPLE: example scalarProd; shows examples
227"
228{
229  int i; int sp;
230  if (size(v)!=size(w))
231  {
232    ERROR("non-matching dimensions");
233  }
234  else
235  {
236    for (i=1; i<=size(v);i++)
237    {
238      sp = sp + v[i]*w[i];
239    }
240  }
241  return(sp);
242}
243example
244{
245  "EXAMPLE:"; echo = 2;
246  intvec v = 1,2,3;
247  intvec w = 4,5,6;
248  scalarProd(v,w);
249}
250
251//-------------- main procedures -------------------------------------------------------
252proc linReduceIdeal(ideal I, list #)
253"USAGE:  linReduceIdeal(I [,s,t,u]); I an ideal, s,t,u optional ints
254RETURN:  ideal or list, linear reductum (over field) of I by its elements
255PURPOSE: reduces a list of polys only by linear reductions (no monomial
256@*        multiplications)
257NOTE:    If s<>0, a list consisting of the reduced ideal and the coefficient
258@*       vectors of the used reductions given as module is returned.
259@*       Otherwise (and by default), only the reduced ideal is returned.
260@*       If t<>0 (and by default) all monomials are reduced (if possible),
261@*       otherwise, only leading monomials are reduced.
262@*       If u<>0 (and by default), the ideal is first sorted in increasing order.
263@*       If u is set to 0 and the given ideal is not sorted in the way described,
264@*       the result might not be as expected.
265DISPLAY: If @code{printlevel}=1, progress debug messages will be printed,
266@*       if printlevel>=2, all the debug messages will be printed.
267EXAMPLE: example linReduceIdeal; shows examples
268"
269{
270  // #[1] = remembercoeffs
271  // #[2] = redtail
272  // #[3] = sortideal
273  int ppl = printlevel - voice + 2;
274  int remembercoeffs = 0; // default
275  int redtail        = 1; // default
276  int sortideal      = 1; // default
277  if (size(#)>0)
278  {
279    if (typeof(#[1])=="int" || typeof(#[1])=="number")
280    {
281      remembercoeffs = #[1];
282    }
283    if (size(#)>1)
284    {
285      if (typeof(#[2])=="int" || typeof(#[2])=="number")
286      {
287        redtail = #[2];
288      }
289      if (size(#)>2)
290      {
291        if (typeof(#[3])=="int" || typeof(#[3])=="number")
292        {
293          sortideal = #[3];
294        }
295      }
296    }
297  }
298  int sI = ncols(I);
299  int sZeros = sI - size(I);
300  int i,j;
301  ideal J,lmJ,ordJ;
302  list lJ = sort(I);
303  module M; // for the coefficients
304  // step 1: prepare, e.g. sort I
305  if (sortideal <> 0)
306  {
307    if (sZeros > 0) // I contains zeros
308    {
309      if (remembercoeffs <> 0)
310      {
311        j = 0;
312        for (i=1; i<=sI; i++)
313        {
314          if (I[i] == 0)
315          {
316            j++;
317            J[j] = 0;
318            ordJ[j] = -1;
319            M[j] = gen(i);
320          }
321          else
322          {
323            M[i+sZeros-j] = gen(lJ[2][i-j]+j);
324          }
325        }
326      }
327      else
328      {
329        for (i=1; i<=sZeros; i++)
330        {
331          J[i] = 0;
332          ordJ[i] = -1;
333        }
334      }
335      I = J,lJ[1];
336    }
337    else // I contains no zeros
338    {
339      I = lJ[1];
340      if (remembercoeffs <> 0)
341      {
342        for (i=1; i<=size(lJ[1]); i++) { M[i+sZeros] = gen(lJ[2][i]); }
343      }
344    }
345  }
346  else // assume I is already sorted
347  {
348    if (remembercoeffs <> 0)
349    {
350      for (i=1; i<=ncols(I); i++) { M[i] = gen(i);  }
351    }
352  } 
353  dbprint(ppl-1,"// initially sorted ideal:", I);
354  if (remembercoeffs <> 0) { dbprint(ppl-1,"// used permutations:", M); }
355  // step 2: reduce leading monomials by linear reductions
356  poly lm,c,redpoly,maxlmJ;
357  J[sZeros+1] = I[sZeros+1];
358  lm = I[sZeros+1];
359  maxlmJ = leadmonom(lm);
360  lmJ[sZeros+1] = maxlmJ;
361  int ordlm,reduction;
362  ordJ[sZeros+1] = ord(lm);
363  vector v;
364  int noRedPast;
365  for (i=sZeros+2; i<=sI; i++)
366  {
367    redpoly = I[i];
368    lm = leadmonom(redpoly);
369    ordlm = ord(lm);
370    if (remembercoeffs <> 0) { v = M[i]; }
371    reduction = 1;
372    while (reduction == 1) // while there was a reduction
373    {
374      noRedPast = i;
375      reduction = 0;
376      for (j=sZeros+1; j<noRedPast; j++)
377      {
378        if (lm == 0) { break; } // nothing more to reduce
379        if (lm > maxlmJ) { break; } //lm is bigger than maximal monomial to reduce with
380        if (ordlm == ordJ[j])
381        {
382          if (lm == lmJ[j])
383          {
384            dbprint(ppl-1,"// reducing " + string(redpoly));
385            dbprint(ppl-1,"//  with " + string(J[j]));
386            c = leadcoef(redpoly)/leadcoef(J[j]);
387            redpoly = redpoly - c*J[j];
388            dbprint(ppl-1,"//  to " + string(redpoly));
389            lm = leadmonom(redpoly);
390            ordlm = ord(lm);
391            if (remembercoeffs <> 0) { M[i] = M[i] - c * M[j]; }
392            noRedPast = j;
393            reduction = 1;
394          }
395        }
396      }
397    }
398    for (j=sZeros+1; j<i; j++)
399    {
400      if (redpoly < J[j]) { break; }
401    }
402    J = insertGenerator(J,redpoly,j);
403    lmJ = insertGenerator(lmJ,lm,j);
404    ordJ = insertGenerator(ordJ,poly(ordlm),j);
405    if (remembercoeffs <> 0)
406    {
407      v = M[i];
408      M = deleteGenerator(M,i);
409      M = insertGenerator(M,v,j);
410    }
411    maxlmJ = lmJ[i];
412  }
413  // step 3: reduce tails by linear reductions as well
414  if (redtail <> 0)
415  {
416    dbprint(ppl,"// finished reducing leading monomials");
417    dbprint(ppl-1,string(J));
418    if (remembercoeffs <> 0) { dbprint(ppl-1,"// used reductions:" + string(M)); }
419    int k;
420    for (i=sZeros+1; i<=sI; i++)
421    {
422      lm = lmJ[i];
423      for (j=i+1; j<=sI; j++)
424      {
425        for (k=2; k<=size(J[j]); k++) // run over all terms in J[j]
426        {
427          if (ordJ[i] == ord(J[j][k]))
428          {   
429            if (lm == normalize(J[j][k]))
430            {
431              c = leadcoef(J[j][k])/leadcoef(J[i]);
432              dbprint(ppl-1,"// reducing " + string(J[j]));
433              dbprint(ppl-1,"//  with " + string(J[i]));
434              J[j] = J[j] - c*J[i];
435              dbprint(ppl-1,"//  to " + string(J[j]));
436              if (remembercoeffs <> 0) { M[j] = M[j] - c * M[i]; }
437            }
438          }
439        }
440      }
441    }
442  }
443  if (remembercoeffs <> 0) { return(list(J,M)); }
444  else { return(J); }
445}
446example
447{
448  "EXAMPLE:"; echo = 2;
449  ring r = 0,(x,y),dp;
450  ideal I = 3,x+9,y4+5x,2y4+7x+2;
451  linReduceIdeal(I);     // reduces tails
452  linReduceIdeal(I,0,0); // no reductions of tails
453  list l = linReduceIdeal(I,1); // reduces tails and shows reductions used
454  l;
455  module M = I;
456  l[1] - ideal(M*l[2]);
457}
458
459proc linReduce(poly f, ideal I, list #)
460"USAGE:  linReduce(f, I [,s,t,u]); f a poly, I an ideal, s,t,u optional ints
461RETURN:  poly or list, linear reductum (over field) of f by elements from I
462PURPOSE: reduce a poly only by linear reductions (no monomial multiplications)
463NOTE:    If s<>0, a list consisting of the reduced poly and the coefficient
464@*       vector of the used reductions is returned, otherwise (and by default)
465@*       only reduced poly is returned.
466@*       If t<>0 (and by default) all monomials are reduced (if possible),
467@*       otherwise, only leading monomials are reduced.
468@*       If u<>0 (and by default), the ideal is linearly pre-reduced, i.e.
469@*       instead of the given ideal, the output of @code{linReduceIdeal} is used.
470@*       If u is set to 0 and the given ideal does not equal the output of
471@*       @code{linReduceIdeal}, the result might not be as expected.
472DISPLAY: If @code{printlevel}=1, progress debug messages will be printed,
473@*       if printlevel>=2, all the debug messages will be printed.
474EXAMPLE: example linReduce; shows examples
475"
476{
477  int ppl = printlevel - voice + 2;
478  int remembercoeffs = 0; // default
479  int redtail        = 1; // default
480  int prepareideal   = 1; // default
481  if (size(#)>0)
482  {
483    if (typeof(#[1])=="int" || typeof(#[1])=="number")
484    {
485      remembercoeffs = #[1];
486    }
487    if (size(#)>1)
488    {
489      if (typeof(#[2])=="int" || typeof(#[2])=="number")
490      {
491        redtail = #[2];
492      }
493      if (size(#)>2)
494      {
495        if (typeof(#[3])=="int" || typeof(#[3])=="number")
496        {
497          prepareideal = #[3];
498        }
499      }
500    }
501  }
502  int i,j,k;
503  int sI = ncols(I);
504  // pre-reduce I:
505  module M;
506  if (prepareideal <> 0)
507  {
508    if (remembercoeffs <> 0)
509    {
510      list sortedI = linReduceIdeal(I,1,redtail);
511      I = sortedI[1];
512      M = sortedI[2];
513      dbprint(ppl-1,"// prepared ideal:" +string(I));
514      dbprint(ppl-1,"//  with operations:" +string(M));
515    }
516    else { I = linReduceIdeal(I,0,redtail); }
517  }
518  else
519  {
520    if (remembercoeffs <> 0)
521    {
522      for (i=1; i<=sI; i++) { M[i] = gen(i); }
523    }
524  }
525  ideal lmI,lcI,ordI;
526  for (i=1; i<=sI; i++)
527  {
528    lmI[i] = leadmonom(I[i]);
529    lcI[i] = leadcoef(I[i]);
530    ordI[i] = ord(lmI[i]);
531  }
532  vector v;
533  poly c;
534  // === reduce leading monomials ===
535  poly lm = leadmonom(f);
536  int ordf = ord(lm);
537  for (i=sI; i>=1; i--)  // I is sorted: smallest lm's on top
538  {
539    if (lm == 0) { break; }
540    else
541    {
542      if (ordf == ordI[i])
543      {
544        if (lm == lmI[i])
545        {
546          c = leadcoef(f)/lcI[i];
547          f = f - c*I[i];
548          lm = leadmonom(f);
549          ordf = ord(lm);
550          if (remembercoeffs <> 0) { v = v - c * M[i]; }
551        }
552      }
553    }
554  }
555  // === reduce tails as well ===
556  if (redtail <> 0)
557  {
558    dbprint(ppl,"// finished reducing leading monomials");
559    dbprint(ppl-1,string(f));
560    if (remembercoeffs <> 0) { dbprint(ppl-1,"// used reductions:" + string(v)); }
561    for (i=1; i<=sI; i++)
562    {
563      dbprint(ppl,"// testing ideal entry "+string(i));
564      for (j=1; j<=size(f); j++)
565      {
566        if (ord(f[j]) == ordI[i])
567        {
568          if (normalize(f[j]) == lmI[i])
569          {
570            c = leadcoef(f[j])/lcI[i];
571            f = f - c*I[i];
572            dbprint(ppl-1,"// reducing with " + string(I[i]));
573            dbprint(ppl-1,"//  to " + string(f));
574            if (remembercoeffs <> 0) { v = v - c * M[i]; }
575          }
576        }
577      }
578    }
579  }
580  if (remembercoeffs <> 0)
581  {
582    list l = f,v;
583    return(l);
584  }
585  else { return(f); }
586}
587example
588{
589  "EXAMPLE:"; echo = 2;
590  ring r = 0,(x,y),dp;
591  ideal I = 1,y,xy;
592  poly f = 5xy+7y+3;
593  poly g = 7x+5y+3;
594  linReduce(g,I);     // reduces tails
595  linReduce(g,I,0,0); // no reductions of tails
596  linReduce(f,I,1);   // reduces tails and shows reductions used
597  f = x3+y2+x2+y+x;
598  I = x3-y3, y3-x2,x3-y2,x2-y,y2-x;
599  list l = linReduce(f,I,1);
600  l;
601  module M = I;
602  f - (l[1]-(M*l[2])[1,1]);
603}
604
605proc linSyzSolve (ideal I, list #)
606"USAGE:  linSyzSolve(I[,s]);  I an ideal, s an optional int
607RETURN:  vector, coefficient vector of linear combination of 0 in elements of I
608PURPOSE: compute a linear dependency between the elements of an ideal
609@*       if such one exists
610NOTE:    If s<>0, @code{std} is used for Groebner basis computations,
611@*       otherwise, @code{slimgb} is used.
612@*       By default, @code{slimgb} is used in char 0 and @code{std} in char >0.
613DISPLAY: If printlevel=1, progress debug messages will be printed,
614@*       if printlevel>=2, all the debug messages will be printed.
615EXAMPLE: example linSyzSolve; shows examples
616"
617{
618  int whichengine     = 0; // default
619  int enginespecified = 0; // default
620  if (size(#)>0)
621  {
622    if (typeof(#[1])=="int" || typeof(#[1])=="number")
623    {
624      whichengine = int( #[1]);
625      enginespecified = 1;
626    }
627  }
628  int ppl = printlevel - voice +2;
629  int sI = ncols(I);
630  // check if we are done
631  if (I[sI]==0)
632  {
633    vector v = gen(sI);
634  }
635  else
636  {
637    // ------- 1. introduce undefined coeffs ------------------
638    def save = basering;
639    list RL = ringlist(save);
640    int nv = nvars(save);
641    int np = npars(save);
642    int p = char(save);
643    string cs = "(" + charstr(save) + ")";
644    if (enginespecified == 0)
645    {
646      if (p <> 0)
647      {
648        whichengine = 1;
649      }
650    }
651    int i;
652    list Lvar;
653    for (i=1; i<=sI; i++)
654    {
655      Lvar[i] = safeVarName("@a(" + string(i) + ")");
656    }
657    list L@A = RL[1..4];
658    L@A[2] = Lvar;
659    L@A[3] = list(list("lp",intvec(1:sI)),list("C",intvec(0)));
660    def @A = ring(L@A);
661    L@A[2] = list(safeVarName("@z"));
662    L@A[3][1] = list("dp",intvec(1));
663    if (size(L@A[1])>1)
664    {
665      L@A[1][2] = L@A[1][2] + Lvar;
666      L@A[1][3][size(L@A[1][3])+1] = list("lp",intvec(1:sI));
667    }
668    else
669    {
670      L@A[1] = list(p,Lvar,list(list("lp",intvec(1:sI))),ideal(0));
671    }
672    def @aA = ring(L@A);
673    def @B = save + @aA;
674    setring @B;
675    ideal I = imap(save,I);
676    // ------- 2. form the linear system for the undef coeffs ---
677     poly W;  ideal QQ;
678    for (i=1; i<=sI; i++)
679    {
680      W = W + par(np+i)*I[i];
681    }
682    while (W!=0)
683    {
684      QQ = QQ,leadcoef(W);
685      W = W - lead(W);
686    }
687    // QQ consists of polynomial expressions in @a(i) of type number
688    setring @A;
689    ideal QQ = imap(@B,QQ);
690    // ------- 3. this QQ is a polynomial ideal, so "solve" the system -----
691    dbprint(ppl, "// linSyzSolve: starting Groebner basis computation with engine:", whichengine);
692    QQ = engine(QQ,whichengine);
693    dbprint(ppl, "// QQ after engine:", QQ);
694    if (dim(QQ) == -1)
695    {
696      dbprint(ppl+1, "// no solutions by linSyzSolve");
697      // output zeroes
698      setring save;
699      kill @A,@aA,@B;
700      return(v);
701    }
702    // ------- 4. in order to get the numeric values -------
703    matrix AA = matrix(maxideal(1));
704    module MQQ = std(module(QQ));
705    AA = NF(AA,MQQ); // todo: we still receive NF warnings
706    dbprint(ppl, "// AA after NF:",AA);
707    //    "AA after NF:"; print(AA);
708    for(i=1; i<=sI; i++)
709    {
710      AA = subst(AA,var(i),1);
711    }
712    dbprint(ppl, "// AA after subst:",AA);
713    //    "AA after subst: "; print(AA);
714    vector v = (module(transpose(AA)))[1];
715    setring save;
716    vector v = imap(@A,v);
717    kill @A,@aA,@B;
718  }
719  return(v);
720}
721example
722{
723  "EXAMPLE:"; echo = 2;
724  ring r = 0,x,dp;
725  ideal I = x,2x;
726  linSyzSolve(I);
727  ideal J = x,x2;
728  linSyzSolve(J);
729}
730
731proc pIntersect (poly s, ideal I, list #)
732"USAGE:  pIntersect(f, I [,s]);  f a poly, I an ideal, s an optional int
733RETURN:  vector, coefficient vector of the monic polynomial
734PURPOSE: compute the intersection of ideal I with the subalgebra K[f]
735ASSUME:  I is given as Groebner basis, basering is not a qring.
736NOTE:    If the intersection is zero, this proc might not terminate.
737@*       If s>0 is given, it is searched for the generator of the intersection
738@*       only up to degree s. Otherwise (and by default), no bound is assumed.
739DISPLAY: If printlevel=1, progress debug messages will be printed,
740@*       if printlevel>=2, all the debug messages will be printed.
741EXAMPLE: example pIntersect; shows examples
742"
743{
744  def save = basering;
745  int n = nvars(save);
746  list RL = ringlist(save);
747  int i,j,k;
748  if (RL[4]<>0)
749  {
750    ERROR ("basering must not be a qring");
751  }
752  // assume I is given in Groebner basis
753  if (attrib(I,"isSB") <> 1)
754  {
755    print("// WARNING: The input has no SB attribute!");
756    print("// Treating it as if it were a Groebner basis and proceeding...");
757    attrib(I,"isSB",1); // set attribute for suppressing NF messages
758  }
759  int bound = 0; // default
760  if (size(#)>0)
761  {
762    if (typeof(#[1])=="int" || typeof(#[1])=="number")
763    {
764      bound = #[1];
765    }
766  }
767  int ppl = printlevel-voice+2;
768  // ---case 1: I = basering---
769  if (size(I) == 1)
770  {
771    if (simplify(I,2)[1] == 1)
772    {
773      return(gen(1)); // = 1
774    }
775  }
776  // ---case 2: intersection is zero---
777  intvec degs = leadexp(s);
778  intvec possdegbounds;
779  list degI;
780  i = 1;
781  while (i <= ncols(I))
782  {
783    if (i == ncols(I)+1) { break; }
784    degI[i] = leadexp(I[i]);
785    for (j=1; j<=n; j++)
786    {
787      if (degs[j] == 0)
788      {
789        if (degI[i][j] <> 0) { break; }
790      }
791      if (j == n)
792      {
793        k++;
794        possdegbounds[k] = Max(degI[i]);
795      }
796    }
797    i++;
798  }
799  int degbound = Min(possdegbounds);
800  if (bound>0 && bound<degbound) // given bound is too small
801  {
802    print("// Try a bound of at least " + string(degbound));
803    return(vector(0));
804  } 
805  dbprint(ppl,"// lower bound for the degree of the insection is " +string(degbound));
806  if (degbound == 0) // lm(s) does not appear in lm(I)
807  {
808    print("// Intersection is zero");
809    return(vector(0));
810  }
811  // ---case 3: intersection is non-trivial---
812  ideal redNI = 1;
813  vector v;
814  list l,ll;
815  l[1] = vector(0);
816  poly toNF,tobracket,newNF,rednewNF,oldNF,secNF;
817  i = 1;
818  while (1)
819  {
820    if (bound>0 && i>bound) { return(vector(0)); }
821    dbprint(ppl,"// Testing degree "+string(i));
822    if (i>1)
823    {
824      oldNF = newNF;
825      tobracket = s^(i-1) - oldNF;
826      if (tobracket==0) // todo bug in bracket?
827      {
828        toNF = 0;
829      }
830      else
831      {
832        toNF = bracket(tobracket,secNF);
833      }
834      newNF = NF(toNF+oldNF*secNF,I);  // = NF(s^i,I)
835    }
836    else
837    {
838      newNF = NF(s,I);
839      secNF = newNF;
840    }
841    ll = linReduce(newNF,redNI,1);
842    rednewNF = ll[1];
843    l[i+1] = ll[2];
844    dbprint(ppl-1,"// newNF is: "+string(newNF));
845    dbprint(ppl-1,"// rednewNF is: "+string(rednewNF));
846    if (rednewNF != 0) // no linear dependency
847    {
848      redNI[i+1] = rednewNF;
849      i++;
850    }
851    else // there is a linear dependency, hence we are done
852    {
853      dbprint(ppl,"// degree of the generator of the intersection is: "+string(i));
854      break;
855    }
856  }
857  dbprint(ppl-1,"// used linear reductions:", l);
858  // we obtain the coefficients of the generator by the used reductions:
859  list Lvar;
860  for (j=1; j<=i+1; j++)
861  {
862    Lvar[j] = safeVarName("a("+string(j)+")");
863  }
864  list Lord = list("dp",intvec(1:(i+1))),list("C",intvec(0));
865  list L@R = RL[1..4];
866  L@R[2] = Lvar; L@R[3] = Lord;
867  def @R = ring(L@R); setring @R;
868  list l = imap(save,l);
869  ideal C;
870  for (j=1;j<=i+1;j++)
871  {
872    C[j] = 0;
873    for (k=1;k<=j;k++)
874    {
875      C[j] = C[j]+l[j][k]*var(k);
876    }
877  }
878  for (j=i;j>=1;j--)
879  {
880    C[i+1]= subst(C[i+1],var(j),var(j)+C[j]);
881  }
882  matrix m = coeffs(C[i+1],maxideal(1));
883  vector v = gen(i+1);
884  for (j=1;j<=i+1;j++)
885  {
886    v = v + m[j,1]*gen(j);
887  }
888  setring save;
889  v = imap(@R,v);
890  kill @R;
891  return(v);
892}
893example
894{
895  "EXAMPLE:"; echo = 2;
896  ring r = 0,(x,y),dp;
897  poly f = x^2+y^3+x*y^2;
898  def D = initialMalgrange(f);
899  setring D;
900  inF;
901  pIntersect(t*Dt,inF);
902  pIntersect(t*Dt,inF,1);
903}
904
905proc pIntersectSyz (poly s, ideal II, list #)
906"USAGE:  pIntersectSyz(f, I [,p,s,t]);  f poly, I ideal, p,t optial ints, p prime
907RETURN:  vector, coefficient vector of the monic polynomial
908PURPOSE: compute the intersection of an ideal I with the subalgebra K[f]
909ASSUME:  I is given as Groebner basis, basering is free of parameters.
910NOTE:    If the intersection is zero, this procedure might not terminate.
911@*       If p>0 is given, this proc computes the generator of the intersection in
912@*       char p first and then only searches for a generator of the obtained
913@*       degree in the basering. Otherwise, it searched for all degrees by
914@*       computing syzygies.
915@*       If s<>0, @code{std} is used for Groebner basis computations in char 0,
916@*       otherwise, and by default, @code{slimgb} is used.
917@*       If t<>0 and by default, @code{std} is used for Groebner basis
918@*       computations in char >0, otherwise, @code{slimgb} is used.
919DISPLAY: If printlevel=1, progress debug messages will be printed,
920@*       if printlevel>=2, all the debug messages will be printed.
921EXAMPLE: example pIntersectSyz; shows examples
922"
923{
924  // assume I is given in Groebner basis
925  ideal I = II;
926  if (attrib(I,"isSB") <> 1)
927  {
928    print("// WARNING: The input has no SB attribute!");
929    print("//  Treating it as if it were a Groebner basis and proceeding...");
930    attrib(I,"isSB",1); // set attribute for suppressing NF messages
931  }
932  int ppl = printlevel-voice+2;
933  int whichengine  = 0; // default
934  int modengine    = 1; // default
935  int solveincharp = 0; // default
936  def save = basering;
937  if (size(#)>0)
938  {
939    if (typeof(#[1])=="int" || typeof(#[1])=="number")
940    {
941      solveincharp = int(#[1]);
942    }
943    if (size(#)>1)
944    {
945      if (typeof(#[2])=="int" || typeof(#[2])=="number")
946      {
947        whichengine = int(#[2]);
948      }
949      if (size(#)>2)
950      {
951        if (typeof(#[3])=="int" || typeof(#[3])=="number")
952        {
953          modengine = int(#[3]);
954        }
955      }
956    }
957  }
958  int i,j;
959  vector v;
960  poly tobracket,toNF,newNF,p;
961  ideal NI = 1;
962  newNF = NF(s,I);
963  NI[2] = newNF;
964  if (solveincharp<>0)
965  {
966    list l = ringlist(save);
967    l[1] = solveincharp;
968    matrix l5 = l[5];
969    matrix l6 = l[6];
970    def @Rp = ring(l);
971    setring @Rp;
972    list l = ringlist(@Rp);
973    l[5] = fetch(save,l5);
974    l[6] = fetch(save,l6);
975    def Rp = ring(l);
976    setring Rp;
977    kill @Rp;
978    dbprint(ppl+1,"// solving in ring ", Rp);
979    vector v;
980    map phi = save,maxideal(1);
981    poly s = phi(s);
982    ideal NI = 1;
983    setring save;
984  }
985  i = 1;
986  dbprint(ppl+1,"// pIntersectSyz starts...");
987  dbprint(ppl+1,"// with ideal I=", I);
988  while (1)
989  {
990    dbprint(ppl,"// i:"+string(i));
991    if (i>1)
992    {
993      tobracket = s^(i-1)-NI[i];
994      if (tobracket!=0)
995      {
996        toNF = bracket(tobracket,NI[2]) + NI[i]*NI[2];
997      }
998      else
999      {
1000        toNF = NI[i]*NI[2];
1001      }
1002      newNF =  NF(toNF,I);
1003      NI[i+1] = newNF;
1004    }
1005    // look for a solution
1006    dbprint(ppl,"// linSyzSolve starts with: "+string(matrix(NI)));
1007    if (solveincharp<>0) // modular method
1008    {
1009      setring Rp;
1010      NI[i+1] = phi(newNF);
1011      v = linSyzSolve(NI,modengine);
1012      if (v!=0) // there is a modular solution
1013      {
1014        dbprint(ppl,"// got solution in char "+string(solveincharp)+" of degree "+string(i));
1015        setring save;
1016        v = linSyzSolve(NI,whichengine);
1017        if (v==0)
1018        {
1019          break;
1020        }
1021      }
1022      else // no modular solution
1023      {
1024        setring save;
1025        v = 0;
1026      }
1027    }
1028    else // non-modular method
1029    {
1030      v = linSyzSolve(NI,whichengine);
1031    }
1032    matrix MM[1][nrows(v)] = matrix(v);
1033    dbprint(ppl,"// linSyzSolve ready  with: "+string(MM));
1034    kill MM;
1035    //  "linSyzSolve ready with"; print(v);
1036    if (v!=0)
1037    {
1038      // a solution:
1039      //check for the reality of the solution
1040      p = 0;
1041      for (j=1; j<=i+1; j++)
1042      {
1043        p = p + v[j]*NI[j];
1044      }
1045      if (p!=0)
1046      {
1047        dbprint(ppl,"// linSyzSolve: bad solution!");
1048      }
1049      else
1050      {
1051        dbprint(ppl,"// linSyzSolve: got solution!");
1052        // "got solution!";
1053        break;
1054      }
1055    }
1056    // no solution:
1057    i++;
1058  }
1059  dbprint(ppl+1,"// pIntersectSyz finished");
1060  return(v);
1061}
1062example
1063{
1064  "EXAMPLE:"; echo = 2;
1065  ring r = 0,(x,y),dp;
1066  poly f = x^2+y^3+x*y^2;
1067  def D = initialMalgrange(f);
1068  setring D;
1069  inF;
1070  poly s = t*Dt;
1071  pIntersectSyz(s,inF);
1072  int p = prime(20000);
1073  pIntersectSyz(s,inF,p,0,0);
1074}
1075
1076proc vec2poly (list #)
1077"USAGE:  vec2poly(v [,i]);  v a vector or an intvec, i an optional int
1078RETURN:  poly, an univariate poly in i-th variable with coefficients given by v
1079PURPOSE: constructs an univariate poly in K[var(i)] with given coefficients,
1080@*       such that the coefficient at var(i)^{j-1} is v[j].
1081NOTE:    The optional argument i must be positive, by default i is 1.
1082EXAMPLE: example vec2poly; shows examples
1083"
1084{
1085  def save = basering;
1086  int i,ringvar;
1087  ringvar = 1; // default
1088  if (size(#) > 0)
1089  {
1090    if (typeof(#[1])=="vector" || typeof(#[1])=="intvec")
1091    {
1092      def v = #[1];
1093    }
1094    else
1095    {
1096      ERROR("wrong input: expected vector/intvec expression");
1097    }
1098    if (size(#) > 1)
1099    {
1100      if (typeof(#[2])=="int" || typeof(#[2])=="number")
1101      {
1102        ringvar = int(#[2]);
1103      }
1104    }
1105  }
1106  if (ringvar > nvars(save))
1107  {
1108    ERROR("var out of range");
1109  }
1110  poly p;
1111  for (i=1; i<=nrows(v); i++)
1112  {
1113    p = p + v[i]*(var(ringvar))^(i-1);
1114  }
1115  return(p);
1116}
1117example
1118{
1119  "EXAMPLE:"; echo = 2;
1120  ring r = 0,(x,y),dp;
1121  vector v = gen(1) + 3*gen(3) + 22/9*gen(4);
1122  intvec iv = 3,2,1;
1123  vec2poly(v,2);
1124  vec2poly(iv);
1125}
1126
1127static proc listofroots (list #)
1128{
1129  def save = basering;
1130  int n = nvars(save);
1131  int i;
1132  poly p;
1133  if (typeof(#[1])=="vector")
1134  {
1135    vector b = #[1];
1136    for (i=1; i<=nrows(b); i++)
1137    {
1138      p = p + b[i]*(var(1))^(i-1);
1139    }
1140  }
1141  else
1142  {
1143    p = #[1];
1144  }
1145  int substitution = int(#[2]);
1146  string s = safeVarName("s");
1147  list RL = ringlist(save); RL = RL[1..4];
1148  RL[2] = list(s); RL[3] = list(list("dp",intvec(1)),list("C",0));
1149  def S = ring(RL); setring S;
1150  ideal J;
1151  for (i=1; i<=n; i++)
1152  {
1153    J[i] = var(1);
1154  }
1155  map @m = save,J;
1156  poly p = @m(p);
1157  if (substitution == 1)
1158  {
1159    p = subst(p,var(1),-var(1)-1);
1160  }
1161  // the rest of this proc is nicked from bernsteinBM from dmod.lib
1162  list P = factorize(p);//with constants and multiplicities
1163  ideal bs; intvec m;   //the BS poly is monic, so we are not interested in constants
1164  for (i=2; i<= size(P[1]); i++)  //we delete P[1][1] and P[2][1]
1165  {
1166    bs[i-1] = P[1][i];
1167    m[i-1]  = P[2][i];
1168  }
1169  bs =  normalize(bs);
1170  bs = -subst(bs,var(1),0);
1171  setring save;
1172  ideal bs = imap(S,bs);
1173  kill S;
1174  list BS = bs,m;
1175  return(BS);
1176}
1177
1178static proc bfctengine (poly f, int inorann, int whichengine, int methodord, int methodpIntersect, int pIntersectchar, int modengine, intvec u0)
1179{
1180  int ppl = printlevel - voice +2;
1181  int i;
1182  def save = basering;
1183  int n = nvars(save);
1184  if (isCommutative() == 0) { ERROR("basering must be commutative"); }
1185  if (char(save) <> 0) { ERROR("characteristic of basering has to be 0"); }
1186  list L = ringlist(save);
1187  int qr;
1188  if (L[4] <> 0) // qring
1189  {
1190    print("// basering is qring:");
1191    print("// discarding the quotient and proceeding...");
1192    L[4] = 0;
1193    qr = 1;
1194    def save2 = ring(L);
1195    setring save2;
1196    poly f = imap(save,f);
1197  }
1198  if (size(variables(f)) == 0) // f is constant
1199  {
1200    return(list(ideal(0),intvec(0)));
1201  } 
1202  if (inorann == 0) // bfct using initial ideal
1203  {
1204    def D = initialMalgrange(f,whichengine,methodord,u0);
1205    setring D;
1206    ideal J = inF;
1207    kill inF;
1208    poly s = t*Dt;
1209  }
1210  else // bfct using Ann(f^s)
1211  {
1212    def D = SannfsBFCT(f,whichengine);
1213    setring D;
1214    ideal J = LD;
1215    kill LD;
1216  }
1217  vector b;
1218  // try it modular
1219  if (methodpIntersect <> 0) // pIntersectSyz
1220  {
1221    if (pIntersectchar == 0) // pIntersectSyz::modular
1222    {
1223      int lb = 30000;
1224      int ub = 536870909;
1225      i = 1;
1226      list usedprimes;
1227      while (b == 0)
1228      {
1229        dbprint(ppl,"// number of run in the loop: "+string(i));
1230        int q = prime(random(lb,ub));
1231        if (findFirst(usedprimes,q)==0) // if q was not already used
1232        {
1233          usedprimes = usedprimes,q;
1234          dbprint(ppl,"// used prime is: "+string(q));
1235          b = pIntersectSyz(s,J,q,whichengine,modengine);
1236        }
1237        i++;
1238      }
1239    }
1240    else // pIntersectSyz::non-modular
1241    {
1242      b = pIntersectSyz(s,J,0,whichengine);
1243    }
1244  }
1245  else // pIntersect: linReduce
1246  {
1247    b = pIntersect(s,J);
1248  }
1249  if (qr == 1) { setring save2; }
1250  else { setring save; }
1251  vector b = imap(D,b);
1252  if (inorann == 0) { list l = listofroots(b,1); }
1253  else              { list l = listofroots(b,0); }
1254  if (qr == 1)
1255  {
1256    setring save;
1257    list l = imap(save2,l);
1258  }
1259  return(l);
1260}
1261
1262proc bfct (poly f, list #)
1263"USAGE:  bfct(f [,s,t,v]);  f a poly, s,t optional ints, v an optional intvec
1264RETURN:  list of ideal and intvec
1265PURPOSE: computes the roots of the Bernstein-Sato polynomial b(s)
1266@*       for the hypersurface defined by f.
1267ASSUME:  The basering is commutative and of characteristic 0.
1268BACKGROUND: In this proc, the initial Malgrange ideal is computed according to
1269@*       the algorithm by Masayuki Noro and then a system of linear equations is
1270@*       solved by linear reductions.
1271NOTE:    In the output list, the ideal contains all the roots
1272@*       and the intvec their multiplicities.
1273@*       If s<>0, @code{std} is used for GB computations,
1274@*       otherwise, and by default, @code{slimgb} is used.
1275@*       If t<>0, a matrix ordering is used for Groebner basis computations,
1276@*       otherwise, and by default, a block ordering is used.
1277@*       If v is a positive weight vector, v is used for homogenization
1278@*       computations, otherwise and by default, no weights are used.
1279DISPLAY: If printlevel=1, progress debug messages will be printed,
1280@*       if printlevel>=2, all the debug messages will be printed.
1281EXAMPLE: example bfct; shows examples
1282"
1283{
1284  int ppl = printlevel - voice +2;
1285  int i;
1286  int n = nvars(basering);
1287  // in # we have two switches:
1288  // one for the engine used for Groebner basis computations,
1289  // one for  M() ordering or its realization
1290  // in # can also be the optional weight vector
1291  int whichengine  = 0; // default
1292  int methodord    = 0; // default
1293  intvec u0        = 0; // default
1294  if (size(#)>0)
1295  {
1296    if (typeof(#[1])=="int" || typeof(#[1])=="number")
1297    {
1298      whichengine = int(#[1]);
1299    }
1300    if (size(#)>1)
1301    {
1302      if (typeof(#[2])=="int" || typeof(#[2])=="number")
1303      {
1304        methodord = int(#[2]);
1305      }
1306      if (size(#)>2)
1307      {
1308        if (typeof(#[3])=="intvec" && size(#[3])==n && allPositive(#[3])==1)
1309        {
1310          u0 = #[3];
1311        }
1312      }
1313    }
1314  }
1315  list b = bfctengine(f,0,whichengine,methodord,0,0,0,u0);
1316  return(b);
1317}
1318example
1319{
1320  "EXAMPLE:"; echo = 2;
1321  ring r = 0,(x,y),dp;
1322  poly f = x^2+y^3+x*y^2;
1323  bfct(f);
1324  intvec v = 3,2;
1325  bfct(f,1,0,v);
1326}
1327
1328proc bfctSyz (poly f, list #)
1329"USAGE:  bfctSyz(f [,r,s,t,u,v]);  f poly, r,s,t,u optional ints, v opt. intvec
1330RETURN:  list of ideal and intvec
1331PURPOSE: computes the roots of the Bernstein-Sato polynomial b(s)
1332@*       for the hypersurface defined by f
1333ASSUME:  The basering is commutative and of characteristic 0.
1334BACKGROUND: In this proc, the initial Malgrange ideal is computed according to
1335@*       the algorithm by Masayuki Noro and then a system of linear equations is
1336@*       solved by computing syzygies.
1337NOTE:    In the output list, the ideal contains all the roots and the intvec
1338@*       their multiplicities.
1339@*       If r<>0, @code{std} is used for GB computations in characteristic 0,
1340@*       otherwise, and by default, @code{slimgb} is used.
1341@*       If s<>0, a matrix ordering is used for GB computations, otherwise,
1342@*       and by default, a block ordering is used.
1343@*       If t<>0, the computation of the intersection is solely performed over
1344@*       charasteristic 0, otherwise and by default, a modular method is used.
1345@*       If u<>0 and by default, @code{std} is used for GB computations in
1346@*       characteristic >0, otherwise, @code{slimgb} is used.
1347@*       If v is a positive weight vector, v is used for homogenization
1348@*       computations, otherwise and by default, no weights are used.
1349DISPLAY: If printlevel=1, progress debug messages will be printed,
1350@*       if printlevel>=2, all the debug messages will be printed.
1351EXAMPLE: example bfctSyz; shows examples
1352"
1353{
1354  int ppl = printlevel - voice +2;
1355  int i;
1356  // in # we have four switches:
1357  // one for the engine used for Groebner basis computations in char 0,
1358  // one for  M() ordering or its realization
1359  // one for a modular method when computing the intersection
1360  // and one for the engine used for Groebner basis computations in char >0
1361  // in # can also be the optional weight vector
1362  int n = nvars(basering);
1363  int whichengine = 0; // default
1364  int methodord   = 0; // default
1365  int pIntersectchar  = 0; // default
1366  int modengine   = 1; // default
1367  intvec u0       = 0; // default
1368  if (size(#)>0)
1369  {
1370    if (typeof(#[1])=="int" || typeof(#[1])=="number")
1371    {
1372      whichengine = int(#[1]);
1373    }
1374    if (size(#)>1)
1375    {
1376      if (typeof(#[2])=="int" || typeof(#[2])=="number")
1377      {
1378        methodord = int(#[2]);
1379      }
1380      if (size(#)>2)
1381      {
1382        if (typeof(#[3])=="int" || typeof(#[3])=="number")
1383        {
1384          pIntersectchar = int(#[3]);
1385        }
1386        if (size(#)>3)
1387        {
1388          if (typeof(#[4])=="int" || typeof(#[4])=="number")
1389          {
1390            modengine = int(#[4]);
1391          }
1392          if (size(#)>4)
1393          {
1394            if (typeof(#[5])=="intvec" && size(#[5])==n && allPositive(#[5])==1)
1395            {
1396              u0 = #[5];
1397            }
1398          }
1399        }
1400      }
1401    }
1402  }
1403  list b = bfctengine(f,0,whichengine,methodord,1,pIntersectchar,modengine,u0);
1404  return(b);
1405}
1406example
1407{
1408  "EXAMPLE:"; echo = 2;
1409  ring r = 0,(x,y),dp;
1410  poly f = x^2+y^3+x*y^2;
1411  bfctSyz(f);
1412  intvec v = 3,2;
1413  bfctSyz(f,0,1,1,0,v);
1414}
1415
1416proc bfctIdeal (ideal I, intvec w, list #)
1417"USAGE:  bfctIdeal(I,w[,s,t]);  I an ideal, w an intvec, s,t optional ints
1418RETURN:  list of ideal and intvec
1419PURPOSE: computes the roots of the global b-function of I wrt the weight (-w,w).
1420ASSUME:  The basering is the n-th Weyl algebra in characteristic 0 and  for all
1421@*       1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1 holds, i.e. the
1422@*       sequence of variables is given by x(1),...,x(n),D(1),...,D(n),
1423@*       where D(i) is the differential operator belonging to x(i).
1424@*       Further assume that I is holonomic.
1425BACKGROUND:  In this proc, the initial ideal of I is computed according to the
1426@*       algorithm by Masayuki Noro and then a system of linear equations is
1427@*       solved by linear reductions.
1428NOTE:    In the output list, the ideal contains all the roots and the intvec
1429@*       their multiplicities.
1430@*       If s<>0, @code{std} is used for GB computations in characteristic 0,
1431@*       otherwise, and by default, @code{slimgb} is used.
1432@*       If t<>0, a matrix ordering is used for GB computations, otherwise,
1433@*       and by default, a block ordering is used.
1434DISPLAY: If printlevel=1, progress debug messages will be printed,
1435@*       if printlevel>=2, all the debug messages will be printed.
1436EXAMPLE: example bfctIdeal; shows examples
1437"
1438{
1439  int ppl = printlevel - voice +2;
1440  int i;
1441  def save = basering;
1442  int n = nvars(save)/2;
1443  int whichengine = 0; // default
1444  int methodord   = 0; // default
1445  if (size(#)>0)
1446  {
1447    if (typeof(#[1])=="int" || typeof(#[1])=="number")
1448    {
1449      whichengine = int(#[1]);
1450    }
1451    if (size(#)>1)
1452    {
1453      if (typeof(#[2])=="int" || typeof(#[2])=="number")
1454      {
1455        methodord = int(#[2]);
1456      }
1457    }
1458  }
1459  if (isWeyl()==0) { ERROR("basering is not a Weyl algebra"); }
1460  for (i=1; i<=n; i++)
1461  {
1462    if (bracket(var(i+n),var(i))<>1)
1463    {
1464      ERROR(string(var(i+n))+" is not a differential operator for " +string(var(i)));
1465    }
1466  }
1467  int isH = isHolonomic(I);
1468  if (isH<>1)
1469  {
1470    print("// given ideal is not holonomic");
1471    print("// setting bound for degree of b-fubction to 10 and proceeding");
1472    isH = 10;
1473  }
1474  else { isH = 0; } // no degree bound for pIntersect
1475  ideal J = initialIdealW(I,-w,w,whichengine,methodord);
1476  poly s;
1477  for (i=1; i<=n; i++)
1478  {
1479    s = s + w[i]*var(i)*var(n+i);
1480  }
1481  vector b = pIntersect(s,J,isH);
1482  list RL = ringlist(save); RL = RL[1..4];
1483  RL[2] = list(safeVarName("s"));
1484  RL[3] = list(list("dp",intvec(1)),list("C",intvec(0)));
1485  def @S = ring(RL); setring @S;
1486  vector b = imap(save,b);
1487  poly bs = vec2poly(b);
1488  list l = bFactor(bs);
1489  setring save;
1490  list l = imap(@S,l);
1491  return(l);
1492}
1493example
1494{
1495  "EXAMPLE:"; echo = 2;
1496  ring @D = 0,(x,y,Dx,Dy),dp;
1497  def D = Weyl();
1498  setring D;
1499  ideal I = 3*x^2*Dy+2*y*Dx,2*x*Dx+3*y*Dy+6; I = std(I);
1500  intvec w1 = 1,1;
1501  intvec w2 = 1,2;
1502  intvec w3 = 2,3;
1503  bfctIdeal(I,w1);
1504  bfctIdeal(I,w2,1);
1505  bfctIdeal(I,w3,0,1);
1506}
1507
1508proc bfctOneGB (poly f,list #)
1509"USAGE:  bfctOneGB(f [,s,t]);  f a poly, s,t optional ints
1510RETURN:  list of ideal and intvec
1511PURPOSE: computes the roots of the Bernstein-Sato polynomial b(s) for the
1512@*       hypersurface defined by f, using only one GB computation
1513ASSUME:  The basering is commutative and of characteristic 0.
1514BACKGROUND: In this proc, the initial Malgrange ideal is computed based on the
1515@*       algorithm by Masayuki Noro and combined with an elimination ordering.
1516NOTE:    In the output list, the ideal contains all the roots and the intvec
1517@*       their multiplicities.
1518@*       If s<>0, @code{std} is used for the GB computation, otherwise,
1519@*       and by default, @code{slimgb} is used.
1520@*       If t<>0, a matrix ordering is used for GB computations,
1521@*       otherwise, and by default, a block ordering is used.
1522DISPLAY: If printlevel=1, progress debug messages will be printed,
1523@*       if printlevel>=2, all the debug messages will be printed.
1524EXAMPLE: example bfctOneGB; shows examples
1525"
1526{
1527  int ppl = printlevel - voice +2;
1528  if (isCommutative() == 0) { ERROR("basering must be commutative"); }
1529  def save = basering;
1530  int n = nvars(save);
1531  if (char(save) <> 0)
1532  {
1533    ERROR("characteristic of basering has to be 0");
1534  }
1535  list L = ringlist(save);
1536  int qr;
1537  if (L[4] <> 0) // qring?
1538  {
1539    print("// basering is qring:");
1540    print("// discarding the quotient and proceeding...");
1541    L[4] = 0;
1542    qr = 1;
1543    def save2 = ring(L);
1544    setring save2;
1545    poly f = imap(save,f);
1546  }
1547  int noofvars = 2*n+4;
1548  int i;
1549  int whichengine = 0; // default
1550  int methodord   = 0; // default
1551  if (size(#)>0)
1552  {
1553    if (typeof(#[1])=="int" || typeof(#[1])=="number")
1554    {
1555      whichengine = int(#[1]);
1556    }
1557    if (size(#)>1)
1558    {
1559      if (typeof(#[2])=="int" || typeof(#[2])=="number")
1560      {
1561        methodord = int(#[2]);
1562      }
1563    }
1564  }
1565  intvec uv;
1566  uv[n+3] = 1;
1567  ring r = 0,(x(1..n)),dp;
1568  poly f = fetch(save,f);
1569  uv[1] = -1; uv[noofvars] = 0;
1570  //  for the ordering
1571  intvec @a; @a = 1:noofvars; @a[2] = 2;
1572  intvec @a2 = @a; @a2[2] = 0; @a2[2*n+4] = 0;
1573  if (methodord == 0) // default: block ordering
1574  {
1575    ring @Dh = 0,(t,s,x(n..1),Dt,D(n..1),h),(a(@a),a(@a2),a(uv),dp(noofvars-1),lp(1));
1576  }
1577  else // M() ordering
1578  {
1579    intmat @Ord[noofvars][noofvars];
1580    @Ord[1,1..noofvars] = uv;
1581    @Ord[2,1..noofvars] = 1:(noofvars-1);
1582    for (i=1; i<=noofvars-2; i++)
1583    {
1584      @Ord[2+i,noofvars - i] = -1;
1585    }
1586    dbprint(ppl,"// weights for ordering: "+string(transpose(@a)));
1587    dbprint(ppl,"// the ordering matrix:",@Ord);
1588    ring @Dh = 0,(t,s,x(n..1),Dt,D(n..1),h),(a(@a),a(@a2),M(@Ord));
1589  }
1590  dbprint(ppl,"// the ring Dh:",Dh);
1591  // non-commutative relations
1592  matrix @relD[noofvars][noofvars];
1593  @relD[1,2] = t*h^2;// s*t = t*s+t*h^2
1594  @relD[2,n+3] = Dt*h^2;// Dt*s = s*Dt+h^2
1595  @relD[1,n+3] = h^2;
1596  for (i=1; i<=n; i++)
1597  {
1598    @relD[i+2,n+3+i] = h^2;
1599  }
1600  dbprint(ppl,"// nc relations:",@relD);
1601  def Dh = nc_algebra(1,@relD);
1602  setring Dh;
1603  dbprint(ppl,"// computing in ring",DDh);
1604  ideal I;
1605  poly f = imap(r,f);
1606  kill r;
1607  f = homog(f,h);
1608  I = t - f, t*Dt - s;  // defining the Malgrange ideal
1609  for (i=1; i<=n; i++)
1610  {
1611    I = I, D(i)+diff(f,x(i))*Dt;
1612  }
1613  dbprint(ppl, "// starting Groebner basis computation with engine: "+string(whichengine));
1614  I = engine(I, whichengine);
1615  dbprint(ppl, "// finished Groebner basis computation");
1616  dbprint(ppl, "// I before dehomogenization: "+string(I));
1617  I = subst(I,h,1); // dehomogenization
1618  dbprint(ppl, "// I after dehomogenization: " +string(I));
1619  I = inForm(I,uv); // we are only interested in the initial form w.r.t. uv
1620  dbprint(ppl, "// the initial ideal:", string(matrix(I)));
1621  intvec tonselect = 1;
1622  for (i=3; i<=2*n+4; i++) { tonselect = tonselect,i; }
1623  I = nselect(I,tonselect);
1624  dbprint(ppl, "// generators containing only s:", string(matrix(I)));
1625  I = engine(I, whichengine); // is now a principal ideal;
1626  if (qr == 1) { setring save2; }
1627  else { setring save; }
1628  ideal J; J[2] = var(1);
1629  map @m = Dh,J;
1630  ideal I = @m(I);
1631  poly p = I[1];
1632  list l = listofroots(p,1);
1633  if (qr == 1)
1634  {
1635    setring save;
1636    list l = imap(save2,l);
1637  }
1638  return(l);
1639}
1640example
1641{
1642  "EXAMPLE:"; echo = 2;
1643  ring r = 0,(x,y),dp;
1644  poly f = x^2+y^3+x*y^2;
1645  bfctOneGB(f);
1646  bfctOneGB(f,1,1);
1647}
1648
1649proc bfctAnn (poly f, list #)
1650"USAGE:  bfctAnn(f [,r]);  f a poly, r an optional int
1651RETURN:  list of ideal and intvec
1652PURPOSE: computes the roots of the Bernstein-Sato polynomial b(s) for the
1653@*       hypersurface defined by f.
1654ASSUME:  The basering is commutative and of characteristic 0.
1655BACKGROUND: In this proc, ann(f^s) is computed and then a system of linear
1656@*       equations is solved by linear reductions.
1657NOTE:    In the output list, the ideal contains all the roots and the intvec
1658@*       their multiplicities.
1659@*       If r<>0, @code{std} is used for GB computations,
1660@*       otherwise, and by default, @code{slimgb} is used.
1661DISPLAY: If printlevel=1, progress debug messages will be printed,
1662@*       if printlevel>=2, all the debug messages will be printed.
1663EXAMPLE: example bfctAnn; shows examples
1664"
1665{
1666  def save = basering;
1667  int ppl = printlevel - voice + 2;
1668  int whichengine = 0; // default
1669  if (size(#)>0)
1670  {
1671    if (typeof(#[1])=="int" || typeof(#[1])=="number")
1672    {
1673      whichengine = int(#[1]);
1674    }
1675  }
1676  list b = bfctengine(f,1,whichengine,0,0,0,0,0);
1677  return(b);
1678}
1679example
1680{
1681  "EXAMPLE:"; echo = 2;
1682  ring r = 0,(x,y),dp;
1683  poly f = x^2+y^3+x*y^2;
1684  bfctAnn(f);
1685}
1686
1687/*
1688//static proc hardexamples ()
1689{
1690  //  some hard examples
1691  ring r1 = 0,(x,y,z,w),dp;
1692  // ab34
1693  poly ab34 = (z3+w4)*(3z2x+4w3y);
1694  bfct(ab34);
1695  // ha3
1696  poly ha3 = xyzw*(x+y)*(x+z)*(x+w)*(y+z+w);
1697  bfct(ha3);
1698  // ha4
1699  poly ha4 = xyzw*(x+y)*(x+z)*(x+w)*(y+z)*(y+w);
1700  bfct(ha4);
1701  // chal4: reiffen(4,5)*reiffen(5,4)
1702  ring r2 = 0,(x,y),dp;
1703  poly chal4 = (x4+xy4+y5)*(x5+x4y+y4);
1704  bfct(chal4);
1705  // (xy+z)*reiffen(4,5)
1706  ring r3 = 0,(x,y,z),dp;
1707  poly xyzreiffen45 = (xy+z)*(y4+yz4+z5);
1708  bfct(xyzreiffen45);
1709}
1710*/
Note: See TracBrowser for help on using the repository browser.