source: git/Singular/LIB/bfun.lib @ 237b3e4

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