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

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