source: git/Singular/LIB/bfun.lib @ 40e810d

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