source: git/Singular/LIB/bfun.lib

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