source: git/Singular/LIB/dmod.lib @ ea87a9

spielwiese
Last change on this file since ea87a9 was ea87a9, checked in by Hans Schoenemann <hannes@…>, 14 years ago
tabs and spaces git-svn-id: file:///usr/local/Singular/svn/trunk@13403 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100755
File size: 163.4 KB
Line 
1//////////////////////////////////////////////////////////////////////////////
2version="$Id$";
3category="Noncommutative";
4info="
5LIBRARY: dmod.lib     Algorithms for algebraic D-modules
6AUTHORS: Viktor Levandovskyy,     levandov@math.rwth-aachen.de
7         Jorge Martin Morales,    jorge@unizar.es
8
9OVERVIEW:
10Theory: Let K be a field of characteristic 0. Given a polynomial ring
11      R = K[x_1,...,x_n] and a polynomial F in R,
12      one is interested in the R[1/F]-module of rank one, generated by
13      the symbol F^s for a symbolic discrete variable s.
14In fact, the module R[1/F]*F^s has a structure of a D(R)[s]-module, where D(R)
15is an n-th Weyl algebra K<x_1,...,x_n,d_1,...,d_n | d_j x_j = x_j d_j +1> and
16D(R)[s] = D(R) tensored with K[s] over K.
17Constructively, one needs to find a left ideal I = I(F^s) in D(R), such
18that K[x_1,...,x_n,1/F]*F^s is isomorphic to D(R)/I as a D(R)-module.
19We often write just D for D(R) and D[s] for D(R)[s].
20One is interested in the following data:
21- Ann F^s = I = I(F^s) in D(R)[s], denoted by LD in the output
22- global Bernstein polynomial in K[s], denoted by bs,
23- its minimal integer root s0, the list of all roots of bs, which are known
24   to be rational, with their multiplicities, which is denoted by BS
25- Ann F^s0 = I(F^s0) in D(R), denoted by LD0 in the output
26   (LD0 is a holonomic ideal in D(R))
27- Ann^(1) F^s in D(R)[s], denoted by LD1 (logarithmic derivations)
28- an operator in D(R)[s], denoted by PS, such that the functional equality
29     PS*F^(s+1) = bs*F^s holds in K[x_1,...,x_n,1/F]*F^s.
30
31References:
32We provide the following implementations of algorithms:
33@*(OT) the classical Ann F^s algorithm from Oaku and Takayama (Journal of
34Pure and Applied Math., 1999),
35@*(LOT) Levandovskyy's modification of the Oaku-Takayama algorithm (ISSAC 2007)
36@*(BM) the Ann F^s algorithm by Briancon and Maisonobe (Remarques sur
37l'ideal de Bernstein associe a des polynomes, preprint, 2002)
38@*(LM08) V. Levandovskyy and J. Martin-Morales, ISSAC 2008
39@*(C) Countinho, A Primer of Algebraic D-Modules,
40@*(SST) Saito, Sturmfels, Takayama 'Groebner Deformations of Hypergeometric
41Differential Equations', Springer, 2000
42
43
44Guide:
45@*- Ann F^s = I(F^s) = LD in D(R)[s] can be computed by Sannfs [BM, OT, LOT]
46@*- Ann^(1) F^s in D(R)[s] can be computed by Sannfslog
47@*- global Bernstein polynomial bs in K[s] can be computed by bernsteinBM
48@*- Ann F^s0 = I(F^s0) = LD0 in D(R) can be computed by annfs0, annfs, annfsBM,
49    annfsOT, annfsLOT, annfs2, annfsRB etc.
50@*- all the relevant data to F^s (LD, LD0, bs, PS) are computed by operatorBM
51@*- operator PS can be computed via operatorModulo or operatorBM
52
53@*- annihilator of F^{s1} for a number s1 is computed with annfspecial
54@*- annihilator of F_1^s_1 * ... * F_p^s_p is computed with annfsBMI
55@*- computing the multiplicity of a rational number r in the Bernstein poly
56   of a given ideal goes with checkRoot
57@*- check, whether a given univariate polynomial divides the Bernstein poly
58   goes with checkFactor
59
60PROCEDURES:
61annfs(F[,S,eng]);       compute Ann F^s0 in D and Bernstein polynomial for a poly F
62annfspecial(I, F, m, n);  compute Ann F^n from Ann F^s for a polynomial F and a number n
63Sannfs(F[,S,eng]);      compute Ann F^s in D[s] for a polynomial F
64Sannfslog(F[,eng]);     compute Ann^(1) F^s in D[s] for a polynomial F
65bernsteinBM(F[,eng]);   compute global Bernstein-Sato polynomial of a poly F (alg of Briancon-Maisonobe)
66bernsteinLift(I,F [,eng]);  compute a multiple of Bernstein-Sato polynomial via lift-like procedure
67operatorBM(F[,eng]);    compute Ann F^s, Ann F^s0, BS and PS for a poly F (algorithm of Briancon-Maisonobe)
68operatorModulo(F, I, b); compute PS via the modulo approach
69annfsParamBM(F[,eng]);  compute the generic Ann F^s (algorithm by Briancon and Maisonobe) and exceptional parametric constellations for a polynomial F with parametric coefficients
70annfsBMI(F[,eng]);      compute Ann F^s and Bernstein ideal for a polynomial F=f1*..*fP (multivariate algorithm of Briancon-Maisonobe)
71checkRoot(F,a[,S,eng]); check if a given rational is a root of the global Bernstein polynomial of F and compute its multiplicity
72SannfsBFCT(F[,eng]);      compute Ann F^s in D[s] for a polynomial F (algorithm of Briancon-Maisonobe, other output ordering)
73annfs0(I,F [,eng]);          compute Ann F^s0 in D and Bernstein polynomial from the known Ann F^s in D[s]
74annfs2(I,F [,eng]);           compute Ann F^s0 in D and Bernstein polynomial from the known Ann F^s in D[s] by using a trick of Noro
75annfsRB(I,F [,eng]);          compute Ann F^s0 in D and Bernstein polynomial from the known Ann F^s in D[s] by using Jacobian ideal
76checkFactor(I,F,q[,eng]); check whether a polynomial q in K[s] is a factor of the global Bernstein polynomial of F from the known Ann F^s in D[s]
77
78
79arrange(p);           create a poly, describing a full hyperplane arrangement
80reiffen(p,q);         create a poly, describing a Reiffen curve
81isHolonomic(M);   check whether a module is holonomic
82convloc(L);         replace global orderings with local in the ringlist L
83minIntRoot(P,fact); minimal integer root among the roots of a maximal ideal P
84varNum(s);          the number of the variable with the name s
85isRational(n);  check whether n is a rational number
86
87SEE ALSO: bfun_lib, dmodapp_lib, dmodvar_lib, gmssing_lib
88
89KEYWORDS: D-module; D-module structure; left annihilator ideal; Bernstein-Sato polynomial; global Bernstein-Sato polynomial;
90Weyl algebra; Bernstein operator; logarithmic annihilator ideal; parametric annihilator; root of Bernstein-Sato polynomial;
91hyperplane arrangement; Oaku-Takayama algorithm; Briancon-Maisonobe algorithm; LOT algorithm
92";
93
94// reworked by JM+VL on 9.3.2010: Sannfslog
95// added by VL on 2.3.2010: bernsteinLift
96// ****** commented out for better readability by VL on 2.3.2010
97// annfsBM(F[,eng]);          compute Ann F^s0 in D and Bernstein polynomial for a polynomial F (algorithm of Briancon-Maisonobe)
98// annfsLOT(F[,eng]);         compute Ann F^s0 in D and Bernstein polynomial for a polynomial F (Levandovskyy modification of the Oaku-Takayama algorithm)
99// annfsOT(F[,eng]);          compute Ann F^s0 in D and Bernstein polynomial for a polynomial F (algorithm of Oaku-Takayama)
100// SannfsBM(F[,eng]);         compute Ann F^s in D[s] for a polynomial F (algorithm of Briancon-Maisonobe)
101// SannfsLOT(F[,eng]);        compute Ann F^s in D[s] for a polynomial F (Levandovskyy modification of the Oaku-Takayama algorithm)
102// SannfsOT(F[,eng]);         compute Ann F^s in D[s] for a polynomial F (algorithm of Oaku-Takayama)
103// checkRoot1(I,F,a[,eng]);   check whether a rational is a root of the global Bernstein polynomial of F from the known Ann F^s in D[s]
104// checkRoot2(I,F,a[,eng]);   check whether a rational is a root of the global Bernstein polynomial of F and compute its multiplicity from the known Ann F^s in D[s]
105
106LIB "matrix.lib"; // for submat
107LIB "nctools.lib"; // makeModElimRing etc.
108LIB "elim.lib"; // for nselect
109LIB "qhmoduli.lib"; // for Max
110LIB "gkdim.lib";
111LIB "gmssing.lib";
112LIB "control.lib";  // for genericity
113LIB "dmodapp.lib"; // for e.g. engine
114LIB "poly.lib";
115
116proc testdmodlib()
117{
118  /* tests all procs for consistency */
119  /* adding the new proc, add it here */
120
121  "MAIN PROCEDURES:";
122  example annfs;
123  example Sannfs;
124  example Sannfslog;
125  example bernsteinBM;
126  example operatorBM;
127  example annfspecial;
128  example annfsParamBM;
129  example annfsBMI;
130  example checkRoot;
131  example annfs0;
132  example annfs2;
133  example annfsRB;
134  example annfs2;
135  example operatorModulo;
136  "SECONDARY D-MOD PROCEDURES:";
137  example annfsBM;
138  example annfsLOT;
139  example annfsOT;
140  example SannfsBM;
141  example SannfsLOT;
142  example SannfsOT;
143  example SannfsBFCT;
144  example checkRoot1;
145  example checkRoot2;
146  example checkFactor;
147}
148
149
150
151// new top-level procedures
152proc annfs(poly F, list #)
153"USAGE:  annfs(f [,S,eng]);  f a poly, S a string, eng an optional int
154RETURN:  ring
155PURPOSE: compute the D-module structure of basering[1/f]*f^s with the algorithm
156@*  given in S and with the Groebner basis engine given in ''eng''
157NOTE:  activate the output ring with the @code{setring} command.
158@*    String S; S can be one of the following:
159@*    'bm' (default) - for the algorithm of Briancon and Maisonobe,
160@*    'ot'  - for the algorithm of Oaku and Takayama,
161@*    'lot' - for the Levandovskyy's modification of the algorithm of OT.
162@*  If eng <>0, @code{std} is used for Groebner basis computations,
163@*  otherwise and by default @code{slimgb} is used.
164@*  In the output ring:
165@*  - the ideal LD (which is a Groebner basis) is the needed D-module structure,
166@*  - the list  BS contains roots and multiplicities of a BS-polynomial of f.
167DISPLAY: If @code{printlevel}=1, progress debug messages will be printed,
168@*          if @code{printlevel}>=2, all the debug messages will be printed.
169EXAMPLE: example annfs; shows examples
170"
171{
172  int eng = 0;
173  int chs = 0; // choice
174  string algo = "bm";
175  string st;
176  if ( size(#)>0 )
177  {
178   if ( typeof(#[1]) == "string" )
179   {
180     st = string(#[1]);
181     if ( (st == "BM") || (st == "Bm") || (st == "bM") ||(st == "bm"))
182     {
183       algo = "bm";
184       chs  = 1;
185     }
186     if ( (st == "OT") || (st == "Ot") || (st == "oT") || (st == "ot"))
187     {
188       algo = "ot";
189       chs  = 1;
190     }
191     if ( (st == "LOT") || (st == "lOT") || (st == "Lot") || (st == "lot"))
192     {
193       algo = "lot";
194       chs  = 1;
195     }
196     if (chs != 1)
197     {
198       // incorrect value of S
199       print("Incorrect algorithm given, proceed with the default BM");
200       algo = "bm";
201     }
202     // second arg
203     if (size(#)>1)
204     {
205       // exists 2nd arg
206       if ( typeof(#[2]) == "int" )
207       {
208         // the case: given alg, given engine
209         eng = int(#[2]);
210       }
211       else
212       {
213         eng = 0;
214       }
215     }
216     else
217     {
218       // no second arg
219       eng = 0;
220     }
221   }
222   else
223   {
224     if ( typeof(#[1]) == "int" )
225     {
226     // the case: default alg, engine
227     eng = int(#[1]);
228     //      algo = "bm";  //is already set
229     }
230     else
231     {
232       // incorr. 1st arg
233       algo = "bm";
234     }
235   }
236  }
237
238   // size(#)=0, i.e. there is no algorithm and no engine given
239   //  eng = 0; algo = "bm";  //are already set
240   // int ppl = printlevel-voice+2;
241
242  int old_printlevel = printlevel;
243  printlevel=printlevel+1;
244  def save = basering;
245  if ( algo=="ot")
246  {
247    def @A = annfsOT(F,eng);
248  }
249  else
250  {
251    if ( algo=="lot")
252    {
253      def @A = annfsLOT(F,eng);
254    }
255    else
256    {
257      // bm = default
258      def @A = annfsBM(F,eng);
259    }
260  }
261  printlevel = old_printlevel;
262  return(@A);
263}
264example
265{
266  "EXAMPLE:"; echo = 2;
267  ring r = 0,(x,y,z),Dp;
268  poly F = z*x^2+y^3;
269  def A  = annfs(F); // here, the default BM algorithm will be used
270  setring A; // the Weyl algebra in (x,y,z,Dx,Dy,Dz)
271  LD; //the annihilator of F^{-1} over A
272  BS; // roots with multiplicities of BS polynomial
273}
274
275
276proc Sannfs(poly F, list #)
277"USAGE:  Sannfs(f [,S,eng]);  f a poly, S a string, eng an optional int
278RETURN:  ring
279PURPOSE: compute the D-module structure of basering[f^s] with the algorithm
280@*  given in S and with the Groebner basis engine given in eng
281NOTE:    activate the output ring with the @code{setring} command.
282@*       The value of a string S can be
283@*       'bm' (default) - for the algorithm of  Briancon and Maisonobe,
284@*       'lot' - for the Levandovskyy's modification of the algorithm of OT,
285@*       'ot'  - for the algorithm of Oaku and Takayama.
286@*       If eng <>0, @code{std} is used for Groebner basis computations,
287@*       otherwise, and by default @code{slimgb} is used.
288@*       In the output ring:
289@*       - the ideal LD is the needed D-module structure.
290DISPLAY: If @code{printlevel}=1, progress debug messages will be printed,
291@*          if @code{printlevel}>=2, all the debug messages will be printed.
292EXAMPLE: example Sannfs; shows examples
293"
294{
295  int eng = 0;
296  int chs = 0; // choice
297  string algo = "bm";
298  string st;
299  if ( size(#)>0 )
300  {
301   if ( typeof(#[1]) == "string" )
302   {
303     st = string(#[1]);
304     if ( (st == "BM") || (st == "Bm") || (st == "bM") ||(st == "bm"))
305     {
306       algo = "bm";
307       chs  = 1;
308     }
309     if ( (st == "OT") || (st == "Ot") || (st == "oT") || (st == "ot"))
310     {
311       algo = "ot";
312       chs  = 1;
313     }
314     if ( (st == "LOT") || (st == "lOT") || (st == "Lot") || (st == "lot"))
315     {
316       algo = "lot";
317       chs  = 1;
318     }
319     if (chs != 1)
320     {
321       // incorrect value of S
322       print("Incorrect algorithm given, proceed with the default BM");
323       algo = "bm";
324     }
325     // second arg
326     if (size(#)>1)
327     {
328       // exists 2nd arg
329       if ( typeof(#[2]) == "int" )
330       {
331         // the case: given alg, given engine
332         eng = int(#[2]);
333       }
334       else
335       {
336         eng = 0;
337       }
338     }
339     else
340     {
341       // no second arg
342       eng = 0;
343     }
344   }
345   else
346   {
347     if ( typeof(#[1]) == "int" )
348     {
349     // the case: default alg, engine
350     eng = int(#[1]);
351     //      algo = "bm";  //is already set
352     }
353     else
354     {
355       // incorr. 1st arg
356       algo = "bm";
357     }
358   }
359  }
360  // size(#)=0, i.e. there is no algorithm and no engine given
361  //  eng = 0; algo = "bm";  //are already set
362  // int ppl = printlevel-voice+2;
363  printlevel=printlevel+1;
364  def save = basering;
365  if ( algo=="ot")
366  {
367    def @A = SannfsOT(F,eng);
368  }
369  else
370  {
371    if ( algo=="lot")
372    {
373      def @A = SannfsLOT(F,eng);
374    }
375    else
376    {
377      // bm = default
378      def @A = SannfsBM(F,eng);
379    }
380  }
381  printlevel=printlevel-1;
382  return(@A);
383}
384example
385{
386  "EXAMPLE:"; echo = 2;
387  ring r = 0,(x,y,z),Dp;
388  poly F = x^3+y^3+z^3;
389  printlevel = 0;
390  def A  = Sannfs(F); // here, the default BM algorithm will be used
391  setring A;
392  LD;
393}
394
395proc Sannfslog (poly F, list #)
396"USAGE:  Sannfslog(f [,eng]);  f a poly, eng an optional int
397RETURN:  ring
398PURPOSE: compute the D-module structure of basering[1/f]*f^s
399NOTE:    activate the output ring with the @code{setring} command.
400@*   In the output ring D[s], the ideal LD1 is generated by the elements
401@*   in Ann F^s in D[s], coming from logarithmic derivations.
402@*       If eng <>0, @code{std} is used for Groebner basis computations,
403@*       otherwise, and by default @code{slimgb} is used.
404DISPLAY: If @code{printlevel}=1, progress debug messages will be printed,
405@*          if @code{printlevel}>=2, all the debug messages will be printed.
406EXAMPLE: example Sannfslog; shows examples
407"
408{
409  int eng = 0;
410  if ( size(#)>0 )
411  {
412    if ( typeof(#[1]) == "int" )
413    {
414      eng = int(#[1]);
415    }
416  }
417  int ppl = printlevel-voice+2;
418  def save = basering;
419  int N = nvars(basering);
420  int Nnew = 2*N+1;
421  int i;
422  string s;
423  list RL = ringlist(basering);
424  list L, Lord;
425  list tmp;
426  intvec iv;
427  L[1] = RL[1]; // char
428  L[4] = RL[4]; // char, minpoly
429  // check whether vars have admissible names
430  list Name = RL[2];
431  for (i=1; i<=N; i++)
432  {
433    if (Name[i] == "s")
434    {
435      ERROR("Variable names should not include s");
436    }
437  }
438  // the ideal I
439  ideal I = -F, jacob(F);
440  dbprint(ppl,"// -1-1- starting the computation of syz(-F,_Dx(F))");
441  dbprint(ppl-1, I);
442  matrix M = syz(I);
443  M = transpose(M);  // it is more usefull working with columns
444  dbprint(ppl,"// -1-2- the module syz(-F,_Dx(F)) has been computed");
445  dbprint(ppl-1, M);
446  // ------------ the ring @R ------------
447  // _x, _Dx, s;  elim.ord for _x,_Dx.
448  // now, create the names for new vars
449  list DName;
450  for (i=1; i<=N; i++)
451  {
452    DName[i] = "D"+Name[i]; // concat
453  }
454  tmp[1] = "s";
455  list NName;
456  NName = Name + DName + tmp;
457  L[2] = NName;
458  tmp = 0;
459  // block ord (dp(N),dp);
460  s = "iv=";
461  for (i=1; i<=Nnew-1; i++)
462  {
463    s = s+"1,";
464  }
465  s[size(s)]=";";
466  execute(s);
467  tmp[1] = "dp";  // string
468  tmp[2] = iv;   // intvec
469  Lord[1] = tmp;
470  // continue with dp 1,1,1,1...
471  tmp[1] = "dp";  // string
472  s[size(s)] = ",";
473  s = s+"1;";
474  execute(s);
475  kill s;
476  kill NName;
477  tmp[2]      = iv;
478  Lord[2]     = tmp;
479  tmp[1]      = "C";  iv  = 0;  tmp[2]=iv;
480  Lord[3]     = tmp;  tmp = 0;
481  L[3]        = Lord;
482  // we are done with the list. Now add a Plural part
483  def @R@ = ring(L);
484  setring @R@;
485  matrix @D[Nnew][Nnew];
486  for (i=1; i<=N; i++)
487  {
488    @D[i,N+i]=1;
489  }
490  def @R = nc_algebra(1,@D);
491  setring @R;
492  kill @R@;
493  dbprint(ppl,"// -2-1- the ring @R(_x,_Dx,s) is ready");
494  dbprint(ppl-1, @R);
495  matrix M = imap(save,M);
496  // now, create the vector [-s,_Dx]
497  vector v = [-s];  // now s is a variable
498  for (i=1; i<=N; i++)
499  {
500    v = v + var(i+N)*gen(i+1);
501  }
502  ideal J = ideal(M*v);
503  // make leadcoeffs positive
504  for (i=1; i<= ncols(J); i++)
505  {
506    if ( leadcoef(J[i])<0 )
507    {
508      J[i] = -J[i];
509    }
510  }
511  ideal LD1 = J;
512  kill J;
513  export LD1;
514  return(@R);
515}
516example
517{
518  "EXAMPLE:"; echo = 2;
519  ring r = 0,(x,y),Dp;
520  poly F = x4+y5+x*y4;
521  printlevel = 0;
522  def A  = Sannfslog(F);
523  setring A;
524  LD1;
525}
526
527// JM+VL: output ring restructured into "normal"
528
529// proc Sannfslog (poly F, list #)
530// "USAGE:  Sannfslog(f [,eng]);  f a poly, eng an optional int
531// RETURN:  ring
532// PURPOSE: compute the D-module structure of basering[1/f]*f^s
533// NOTE:    activate the output ring with the @code{setring} command.
534// @*   In the output ring D[s], the ideal LD1 is generated by the elements
535// @*   in Ann F^s in D[s], coming from logarithmic derivations.
536// @*       If eng <>0, @code{std} is used for Groebner basis computations,
537// @*       otherwise, and by default @code{slimgb} is used.
538// DISPLAY: If @code{printlevel}=1, progress debug messages will be printed,
539// @*          if @code{printlevel}>=2, all the debug messages will be printed.
540// EXAMPLE: example Sannfslog; shows examples
541// "
542// {
543//   int eng = 0;
544//   if ( size(#)>0 )
545//   {
546//     if ( typeof(#[1]) == "int" )
547//     {
548//       eng = int(#[1]);
549//     }
550//   }
551//   int ppl = printlevel-voice+2;
552//   def save = basering;
553//   int N = nvars(basering);
554//   int Nnew = 2*N+1;
555//   int i;
556//   string s;
557//   list RL = ringlist(basering);
558//   list L, Lord;
559//   list tmp;
560//   intvec iv;
561//   L[1] = RL[1]; // char
562//   L[4] = RL[4]; // char, minpoly
563//   // check whether vars have admissible names
564//   list Name = RL[2];
565//   for (i=1; i<=N; i++)
566//   {
567//     if (Name[i] == "s")
568//     {
569//       ERROR("Variable names should not include s");
570//     }
571//   }
572//   // the ideal I
573//   ideal I = -F, jacob(F);
574//   dbprint(ppl,"// -1-1- starting the computation of syz(-F,_Dx(F))");
575//   dbprint(ppl-1, I);
576//   matrix M = syz(I);
577//   M = transpose(M);  // it is more usefull working with columns
578//   dbprint(ppl,"// -1-2- the module syz(-F,_Dx(F)) has been computed");
579//   dbprint(ppl-1, M);
580//   // ------------ the ring @R ------------
581//   // _x, _Dx, s;  elim.ord for _x,_Dx.
582//   // now, create the names for new vars
583//   list DName;
584//   for (i=1; i<=N; i++)
585//   {
586//     DName[i] = "D"+Name[i]; // concat
587//   }
588//   tmp[1] = "s";
589//   list NName;
590//   for (i=1; i<=N; i++)
591//   {
592//     NName[2*i-1] = Name[i];
593//     NName[2*i] = DName[i];
594//     //NName[2*i-1] = DName[i];
595//     //NName[2*i] = Name[i];
596//   }
597//   NName[Nnew] = tmp[1];
598//   L[2] = NName;
599//   tmp = 0;
600//   // block ord (a(1,1),a(0,0,1,1),...,dp);
601//   //list("a",intvec(1,1)), list("a",intvec(0,0,1,1)), ...
602//   tmp[1] = "a";  // string
603//   for (i=1; i<=N; i++)
604//   {
605//     iv[2*i-1] = 1;
606//     iv[2*i]   = 1;
607//     tmp[2]    = iv;  iv = 0;  // intvec
608//     Lord[i]   = tmp;
609//   }
610//   //list("dp",intvec(1,1,1,1,1,...))
611//   s = "iv=";
612//   for (i=1; i<=Nnew; i++)
613//   {
614//     s = s+"1,";
615//   }
616//   s[size(s)]=";";
617//   execute(s);
618//   kill s;
619//   tmp[1] = "dp";  // string
620//   tmp[2] = iv;    // intvec
621//   Lord[N+1] = tmp;
622//   //list("C",intvec(0))
623//   tmp[1] = "C";  // string
624//   iv = 0;
625//   tmp[2] = iv;   // intvec
626//   Lord[N+2] = tmp;
627//   tmp = 0;
628//   L[3]    = Lord;
629//   // we are done with the list. Now add a Plural part
630//   def @R@ = ring(L);
631//   setring @R@;
632//   matrix @D[Nnew][Nnew];
633//   for (i=1; i<=N; i++)
634//   {
635//     @D[2*i-1,2*i]=1;
636//     //@D[2*i-1,2*i]=-1;
637//   }
638//   def @R = nc_algebra(1,@D);
639//   setring @R;
640//   kill @R@;
641//   dbprint(ppl,"// -2-1- the ring @R(_x,_Dx,s) is ready");
642//   dbprint(ppl-1, @R);
643//   matrix M = imap(save,M);
644//   // now, create the vector [-s,_Dx]
645//   vector v = [-s];  // now s is a variable
646//   for (i=1; i<=N; i++)
647//   {
648//     v = v + var(2*i)*gen(i+1);
649//     //v = v + var(2*i-1)*gen(i+1);
650//   }
651//   ideal J = ideal(M*v);
652//   // make leadcoeffs positive
653//   for (i=1; i<= ncols(J); i++)
654//   {
655//     if ( leadcoef(J[i])<0 )
656//     {
657//       J[i] = -J[i];
658//     }
659//   }
660//   ideal LD1 = J;
661//   kill J;
662//   export LD1;
663//   return(@R);
664// }
665// example
666// {
667//   "EXAMPLE:"; echo = 2;
668//   ring r = 0,(x,y),Dp;
669//   poly F = x^4+y^5+x*y^4;
670//   printlevel = 0;
671//   def A  = Sannfslog(F);
672//   setring A;
673//   LD1;
674// }
675
676
677// alternative code for SannfsBM, renamed from annfsBM to ALTannfsBM
678// is superfluos - will not be included in the official documentation
679static proc ALTannfsBM (poly F, list #)
680"USAGE:  ALTannfsBM(f [,eng]);  f a poly, eng an optional int
681RETURN:  ring
682PURPOSE: compute the annihilator ideal of f^s in D[s], where D is the Weyl
683@*   algebra, according to the algorithm by Briancon and Maisonobe
684NOTE:  activate the output ring with the @code{setring} command. In this ring,
685@*       - the ideal LD is the annihilator of f^s.
686@*       If eng <>0, @code{std} is used for Groebner basis computations,
687@*       otherwise, and by default @code{slimgb} is used.
688DISPLAY: If @code{printlevel}=1, progress debug messages will be printed,
689@*          if @code{printlevel}>=2, all the debug messages will be printed.
690EXAMPLE: example ALTannfsBM; shows examples
691"
692{
693  int eng = 0;
694  if ( size(#)>0 )
695  {
696    if ( typeof(#[1]) == "int" )
697    {
698      eng = int(#[1]);
699    }
700  }
701  // returns a list with a ring and an ideal LD in it
702  int ppl = printlevel-voice+2;
703  //  printf("plevel :%s, voice: %s",printlevel,voice);
704  def save = basering;
705  int N = nvars(basering);
706  int Nnew = 2*N+2;
707  int i,j;
708  string s;
709  list RL = ringlist(basering);
710  list L, Lord;
711  list tmp;
712  intvec iv;
713  L[1] = RL[1];  //char
714  L[4] = RL[4];  //char, minpoly
715  // check whether vars have admissible names
716  list Name  = RL[2];
717  list RName;
718  RName[1] = "t";
719  RName[2] = "s";
720  for (i=1; i<=N; i++)
721  {
722    for(j=1; j<=size(RName); j++)
723    {
724      if (Name[i] == RName[j])
725      {
726        ERROR("Variable names should not include t,s");
727      }
728    }
729  }
730  // now, create the names for new vars
731  list DName;
732  for (i=1; i<=N; i++)
733  {
734    DName[i] = "D"+Name[i];  //concat
735  }
736  tmp[1] = "t";
737  tmp[2] = "s";
738  list NName = tmp + Name + DName;
739  L[2]   = NName;
740  // Name, Dname will be used further
741  kill NName;
742  // block ord (lp(2),dp);
743  tmp[1]  = "lp"; // string
744  iv      = 1,1;
745  tmp[2]  = iv; //intvec
746  Lord[1] = tmp;
747  // continue with dp 1,1,1,1...
748  tmp[1]  = "dp"; // string
749  s       = "iv=";
750  for (i=1; i<=Nnew; i++)
751  {
752    s = s+"1,";
753  }
754  s[size(s)]= ";";
755  execute(s);
756  kill s;
757  tmp[2]    = iv;
758  Lord[2]   = tmp;
759  tmp[1]    = "C";
760  iv        = 0;
761  tmp[2]    = iv;
762  Lord[3]   = tmp;
763  tmp       = 0;
764  L[3]      = Lord;
765  // we are done with the list
766  def @R@ = ring(L);
767  setring @R@;
768  matrix @D[Nnew][Nnew];
769  @D[1,2]=t;
770  for(i=1; i<=N; i++)
771  {
772    @D[2+i,N+2+i]=1;
773  }
774  // L[5] = matrix(UpOneMatrix(Nnew));
775  // L[6] = @D;
776  def @R = nc_algebra(1,@D);
777  setring @R;
778  kill @R@;
779  dbprint(ppl,"// -1-1- the ring @R(t,s,_x,_Dx) is ready");
780  dbprint(ppl-1, @R);
781  // create the ideal I
782  poly  F = imap(save,F);
783  ideal I = t*F+s;
784  poly p;
785  for(i=1; i<=N; i++)
786  {
787    p = t;  //t
788    p = diff(F,var(2+i))*p;
789    I = I, var(N+2+i) + p;
790  }
791  // -------- the ideal I is ready ----------
792  dbprint(ppl,"// -1-2- starting the elimination of t in @R");
793  dbprint(ppl-1, I);
794  ideal J = engine(I,eng);
795  ideal K = nselect(J,1);
796  kill I,J;
797  dbprint(ppl,"// -1-3- t is eliminated");
798  dbprint(ppl-1, K);  //K is without t
799  // create Dn[s], where Dn is the ordinary Weyl Algebra, and put the result into it,
800  // thus creating the ring @R2
801  // keep: N, i,j,s, tmp, RL
802  setring save;
803  Nnew = 2*N+1;
804  // list RL = ringlist(save);  //is defined earlier
805  kill Lord, tmp, iv;
806  L = 0;
807  list Lord, tmp;
808  intvec iv;
809  L[1] = RL[1];
810  L[4] = RL[4];  //char, minpoly
811  // check whether vars have admissible names -> done earlier
812  // list Name = RL[2]
813  // DName is defined earlier
814  tmp[1] = "s";
815  list NName = Name + DName + tmp;
816  L[2] = NName;
817  // dp ordering;
818  string s = "iv=";
819  for (i=1; i<=Nnew; i++)
820  {
821    s = s+"1,";
822  }
823  s[size(s)] = ";";
824  execute(s);
825  kill s;
826  tmp     = 0;
827  tmp[1]  = "dp";  //string
828  tmp[2]  = iv;    //intvec
829  Lord[1] = tmp;
830  tmp[1]  = "C";
831  iv      = 0;
832  tmp[2]  = iv;
833  Lord[2] = tmp;
834  tmp     = 0;
835  L[3]    = Lord;
836  // we are done with the list
837  // Add: Plural part
838  def @R2@ = ring(L);
839  setring @R2@;
840  matrix @D[Nnew][Nnew];
841  for (i=1; i<=N; i++)
842  {
843    @D[i,N+i]=1;
844  }
845  def @R2 = nc_algebra(1,@D);
846  setring @R2;
847  kill @R2@;
848  dbprint(ppl,"// -2-1- the ring @R2(_x,_Dx,s) is ready");
849  dbprint(ppl-1, @R2);
850  ideal K = imap(@R,K);
851  option(redSB);
852  //dbprint(ppl,"// -2-2- the final cosmetic std");
853  //K = engine(K,eng);  //std does the job too
854  // total cleanup
855  kill @R;
856  ideal LD = K;
857  export LD;
858  return(@R2);
859}
860example
861{
862  "EXAMPLE:"; echo = 2;
863  ring r = 0,(x,y,z,w),Dp;
864  poly F = x^3+y^3+z^2*w;
865  printlevel = 0;
866  def A = ALTannfsBM(F);
867  setring A;
868  LD;
869}
870
871proc bernsteinBM(poly F, list #)
872"USAGE:  bernsteinBM(f [,eng]);  f a poly, eng an optional int
873RETURN:  list (of roots of the Bernstein polynomial b and their multiplicies)
874PURPOSE: compute the global Bernstein-Sato polynomial for a hypersurface,
875@* defined by f, according to the algorithm by Briancon and Maisonobe
876NOTE:    If eng <>0, @code{std} is used for Groebner basis computations,
877@*       otherwise, and by default @code{slimgb} is used.
878DISPLAY: If @code{printlevel}=1, progress debug messages will be printed,
879@*          if @code{printlevel}>=2, all the debug messages will be printed.
880EXAMPLE: example bernsteinBM; shows examples
881"
882{
883  int eng = 0;
884  if ( size(#)>0 )
885  {
886    if ( typeof(#[1]) == "int" )
887    {
888      eng = int(#[1]);
889    }
890  }
891  // returns a list with a ring and an ideal LD in it
892  int ppl = printlevel-voice+2;
893  //  printf("plevel :%s, voice: %s",printlevel,voice);
894  def save = basering;
895  int N = nvars(basering);
896  int Nnew = 2*N+2;
897  int i,j;
898  string s;
899  list RL = ringlist(basering);
900  list L, Lord;
901  list tmp;
902  intvec iv;
903  L[1] = RL[1];  //char
904  L[4] = RL[4];  //char, minpoly
905  // check whether vars have admissible names
906  list Name  = RL[2];
907  list RName;
908  RName[1] = "t";
909  RName[2] = "s";
910  for (i=1; i<=N; i++)
911  {
912    for(j=1; j<=size(RName); j++)
913    {
914      if (Name[i] == RName[j])
915      {
916        ERROR("Variable names should not include t,s");
917      }
918    }
919  }
920  // now, create the names for new vars
921  list DName;
922  for (i=1; i<=N; i++)
923  {
924    DName[i] = "D"+Name[i];  //concat
925  }
926  tmp[1] = "t";
927  tmp[2] = "s";
928  list NName = tmp + Name + DName;
929  L[2]   = NName;
930  // Name, Dname will be used further
931  kill NName;
932  // block ord (lp(2),dp);
933  tmp[1]  = "lp"; // string
934  iv      = 1,1;
935  tmp[2]  = iv; //intvec
936  Lord[1] = tmp;
937  // continue with dp 1,1,1,1...
938  tmp[1]  = "dp"; // string
939  s       = "iv=";
940  for (i=1; i<=Nnew; i++)
941  {
942    s = s+"1,";
943  }
944  s[size(s)]= ";";
945  execute(s);
946  kill s;
947  tmp[2]    = iv;
948  Lord[2]   = tmp;
949  tmp[1]    = "C";
950  iv        = 0;
951  tmp[2]    = iv;
952  Lord[3]   = tmp;
953  tmp       = 0;
954  L[3]      = Lord;
955  // we are done with the list
956  def @R@ = ring(L);
957  setring @R@;
958  matrix @D[Nnew][Nnew];
959  @D[1,2]=t;
960  for(i=1; i<=N; i++)
961  {
962    @D[2+i,N+2+i]=1;
963  }
964  // L[5] = matrix(UpOneMatrix(Nnew));
965  // L[6] = @D;
966  def @R = nc_algebra(1,@D);
967  setring @R;
968  kill @R@;
969  dbprint(ppl,"// -1-1- the ring @R(t,s,_x,_Dx) is ready");
970  dbprint(ppl-1, @R);
971  // create the ideal I
972  poly  F = imap(save,F);
973  ideal I = t*F+s;
974  poly p;
975  for(i=1; i<=N; i++)
976  {
977    p = t;  //t
978    p = diff(F,var(2+i))*p;
979    I = I, var(N+2+i) + p;
980  }
981  // -------- the ideal I is ready ----------
982  dbprint(ppl,"// -1-2- starting the elimination of t in @R");
983  dbprint(ppl-1, I);
984  ideal J = engine(I,eng);
985  ideal K = nselect(J,1);
986  kill I,J;
987  dbprint(ppl,"// -1-3- t is eliminated");
988  dbprint(ppl-1, K);  //K is without t
989  // ----------- the ring @R2 ------------
990  // _x, _Dx,s;  elim.ord for _x,_Dx.
991  // keep: N, i,j,s, tmp, RL
992  setring save;
993  Nnew = 2*N+1;
994  kill Lord, tmp, iv, RName;
995  list Lord, tmp;
996  intvec iv;
997  L[1] = RL[1];
998  L[4] = RL[4];  //char, minpoly
999  // check whether vars hava admissible names -> done earlier
1000  // now, create the names for new var
1001  tmp[1] = "s";
1002  // DName is defined earlier
1003  list NName = Name + DName + tmp;
1004  L[2] = NName;
1005  tmp = 0;
1006  // block ord (dp(N),dp);
1007  string s = "iv=";
1008  for (i=1; i<=Nnew-1; i++)
1009  {
1010    s = s+"1,";
1011  }
1012  s[size(s)]=";";
1013  execute(s);
1014  tmp[1] = "dp";  //string
1015  tmp[2] = iv;    //intvec
1016  Lord[1] = tmp;
1017  // continue with dp 1,1,1,1...
1018  tmp[1] = "dp";  //string
1019  s[size(s)] = ",";
1020  s = s+"1;";
1021  execute(s);
1022  kill s;
1023  kill NName;
1024  tmp[2]  = iv;
1025  Lord[2] = tmp;
1026  tmp[1]  = "C";
1027  iv      = 0;
1028  tmp[2]  = iv;
1029  Lord[3] = tmp;
1030  tmp     = 0;
1031  L[3]    = Lord;
1032  // we are done with the list. Now add a Plural part
1033  def @R2@ = ring(L);
1034  setring @R2@;
1035  matrix @D[Nnew][Nnew];
1036  for (i=1; i<=N; i++)
1037  {
1038    @D[i,N+i]=1;
1039  }
1040  def @R2 = nc_algebra(1,@D);
1041  setring @R2;
1042  kill @R2@;
1043  dbprint(ppl,"// -2-1- the ring @R2(_x,_Dx,s) is ready");
1044  dbprint(ppl-1, @R2);
1045  ideal MM = maxideal(1);
1046  MM = 0,s,MM;
1047  map R01 = @R, MM;
1048  ideal K = R01(K);
1049  kill @R, R01;
1050  poly F = imap(save,F);
1051  K = K,F;
1052  dbprint(ppl,"// -2-2- starting the elimination of _x,_Dx in @R2");
1053  dbprint(ppl-1, K);
1054  ideal M = engine(K,eng);
1055  ideal K2 = nselect(M,1..Nnew-1);
1056  kill K,M;
1057  dbprint(ppl,"// -2-3- _x,_Dx are eliminated in @R2");
1058  dbprint(ppl-1, K2);
1059  // the ring @R3 and the search for minimal negative int s
1060  ring @R3 = 0,s,dp;
1061  dbprint(ppl,"// -3-1- the ring @R3(s) is ready");
1062  ideal K3 = imap(@R2,K2);
1063  kill @R2;
1064  poly p = K3[1];
1065  dbprint(ppl,"// -3-2- factorization");
1066  list P = factorize(p);          //with constants and multiplicities
1067  ideal bs; intvec m;             //the Bernstein polynomial is monic, so we are not interested in constants
1068  for (i=2; i<= size(P[1]); i++)  //we delete P[1][1] and P[2][1]
1069  {
1070    bs[i-1] = P[1][i];
1071    m[i-1]  = P[2][i];
1072  }
1073  // "--------- b-function factorizes into ---------";  P;
1074  //int sP = minIntRoot(bs,1);
1075  //dbprint(ppl,"// -3-3- minimal integer root found");
1076  //dbprint(ppl-1, sP);
1077  // convert factors to a list of their roots and multiplicities
1078  bs =  normalize(bs);
1079  bs = -subst(bs,s,0);
1080  setring save;
1081  ideal bs = imap(@R3,bs);
1082  kill @R3;
1083  list BS = bs,m;
1084  return(BS);
1085}
1086example
1087{
1088  "EXAMPLE:"; echo = 2;
1089  ring r = 0,(x,y,z,w),Dp;
1090  poly F = x^3+y^3+z^2*w;
1091  printlevel = 0;
1092  bernsteinBM(F);
1093}
1094
1095// some changes
1096proc annfsBM (poly F, list #)
1097"USAGE:  annfsBM(f [,eng]);  f a poly, eng an optional int
1098RETURN:  ring
1099PURPOSE: compute the D-module structure of basering[1/f]*f^s, according
1100@* to the algorithm by Briancon and Maisonobe
1101NOTE:    activate the output ring with the @code{setring} command. In this ring,
1102@*       - the ideal LD (which is a Groebner basis) is the needed D-module structure,
1103@*         which is obtained by substituting the minimal integer root of a Bernstein
1104@*         polynomial into the s-parametric ideal;
1105@*       - the list BS is the list of roots and multiplicities of a Bernstein polynomial of f.
1106@*       If eng <>0, @code{std} is used for Groebner basis computations,
1107@*       otherwise, and by default @code{slimgb} is used.
1108DISPLAY: If @code{printlevel}=1, progress debug messages will be printed,
1109@*          if @code{printlevel}>=2, all the debug messages will be printed.
1110EXAMPLE: example annfsBM; shows examples
1111"
1112{
1113  int eng = 0;
1114  if ( size(#)>0 )
1115  {
1116    if ( typeof(#[1]) == "int" )
1117    {
1118      eng = int(#[1]);
1119    }
1120  }
1121  // returns a list with a ring and an ideal LD in it
1122  int ppl = printlevel-voice+2;
1123  //  printf("plevel :%s, voice: %s",printlevel,voice);
1124  def save = basering;
1125  int N = nvars(basering);
1126  int Nnew = 2*N+2;
1127  int i,j;
1128  string s;
1129  list RL = ringlist(basering);
1130  list L, Lord;
1131  list tmp;
1132  intvec iv;
1133  L[1] = RL[1];  //char
1134  L[4] = RL[4];  //char, minpoly
1135  // check whether vars have admissible names
1136  list Name  = RL[2];
1137  list RName;
1138  RName[1] = "t";
1139  RName[2] = "s";
1140  for (i=1; i<=N; i++)
1141  {
1142    for(j=1; j<=size(RName); j++)
1143    {
1144      if (Name[i] == RName[j])
1145      {
1146        ERROR("Variable names should not include t,s");
1147      }
1148    }
1149  }
1150  // now, create the names for new vars
1151  list DName;
1152  for (i=1; i<=N; i++)
1153  {
1154    DName[i] = "D"+Name[i];  //concat
1155  }
1156  tmp[1] = "t";
1157  tmp[2] = "s";
1158  list NName = tmp + Name + DName;
1159  L[2]   = NName;
1160  // Name, Dname will be used further
1161  kill NName;
1162  // block ord (lp(2),dp);
1163  tmp[1]  = "lp"; // string
1164  iv      = 1,1;
1165  tmp[2]  = iv; //intvec
1166  Lord[1] = tmp;
1167  // continue with dp 1,1,1,1...
1168  tmp[1]  = "dp"; // string
1169  s       = "iv=";
1170  for (i=1; i<=Nnew; i++)
1171  {
1172    s = s+"1,";
1173  }
1174  s[size(s)]= ";";
1175  execute(s);
1176  kill s;
1177  tmp[2]    = iv;
1178  Lord[2]   = tmp;
1179  tmp[1]    = "C";
1180  iv        = 0;
1181  tmp[2]    = iv;
1182  Lord[3]   = tmp;
1183  tmp       = 0;
1184  L[3]      = Lord;
1185  // we are done with the list
1186  def @R@ = ring(L);
1187  setring @R@;
1188  matrix @D[Nnew][Nnew];
1189  @D[1,2]=t;
1190  for(i=1; i<=N; i++)
1191  {
1192    @D[2+i,N+2+i]=1;
1193  }
1194  // L[5] = matrix(UpOneMatrix(Nnew));
1195  // L[6] = @D;
1196  def @R = nc_algebra(1,@D);
1197  setring @R;
1198  kill @R@;
1199  dbprint(ppl,"// -1-1- the ring @R(t,s,_x,_Dx) is ready");
1200  dbprint(ppl-1, @R);
1201  // create the ideal I
1202  poly  F = imap(save,F);
1203  ideal I = t*F+s;
1204  poly p;
1205  for(i=1; i<=N; i++)
1206  {
1207    p = t;  //t
1208    p = diff(F,var(2+i))*p;
1209    I = I, var(N+2+i) + p;
1210  }
1211  // -------- the ideal I is ready ----------
1212  dbprint(ppl,"// -1-2- starting the elimination of t in @R");
1213  dbprint(ppl-1, I);
1214  ideal J = engine(I,eng);
1215  ideal K = nselect(J,1);
1216  kill I,J;
1217  dbprint(ppl,"// -1-3- t is eliminated");
1218  dbprint(ppl-1, K);  //K is without t
1219  setring save;
1220  // ----------- the ring @R2 ------------
1221  // _x, _Dx,s;  elim.ord for _x,_Dx.
1222  // keep: N, i,j,s, tmp, RL
1223  Nnew = 2*N+1;
1224  kill Lord, tmp, iv, RName;
1225  list Lord, tmp;
1226  intvec iv;
1227  L[1] = RL[1];
1228  L[4] = RL[4];  //char, minpoly
1229  // check whether vars hava admissible names -> done earlier
1230  // now, create the names for new var
1231  tmp[1] = "s";
1232  // DName is defined earlier
1233  list NName = Name + DName + tmp;
1234  L[2] = NName;
1235  tmp = 0;
1236  // block ord (dp(N),dp);
1237  string s = "iv=";
1238  for (i=1; i<=Nnew-1; i++)
1239  {
1240    s = s+"1,";
1241  }
1242  s[size(s)]=";";
1243  execute(s);
1244  tmp[1] = "dp";  //string
1245  tmp[2] = iv;    //intvec
1246  Lord[1] = tmp;
1247  // continue with dp 1,1,1,1...
1248  tmp[1] = "dp";  //string
1249  s[size(s)] = ",";
1250  s = s+"1;";
1251  execute(s);
1252  kill s;
1253  kill NName;
1254  tmp[2]  = iv;
1255  Lord[2] = tmp;
1256  tmp[1]  = "C";
1257  iv      = 0;
1258  tmp[2]  = iv;
1259  Lord[3] = tmp;
1260  tmp     = 0;
1261  L[3]    = Lord;
1262  // we are done with the list. Now add a Plural part
1263  def @R2@ = ring(L);
1264  setring @R2@;
1265  matrix @D[Nnew][Nnew];
1266  for (i=1; i<=N; i++)
1267  {
1268    @D[i,N+i]=1;
1269  }
1270  def @R2 = nc_algebra(1,@D);
1271  setring @R2;
1272  kill @R2@;
1273  dbprint(ppl,"// -2-1- the ring @R2(_x,_Dx,s) is ready");
1274  dbprint(ppl-1, @R2);
1275  ideal MM = maxideal(1);
1276  MM = 0,s,MM;
1277  map R01 = @R, MM;
1278  ideal K = R01(K);
1279  poly F = imap(save,F);
1280  K = K,F;
1281  dbprint(ppl,"// -2-2- starting the elimination of _x,_Dx in @R2");
1282  dbprint(ppl-1, K);
1283  ideal M = engine(K,eng);
1284  ideal K2 = nselect(M,1..Nnew-1);
1285  kill K,M;
1286  dbprint(ppl,"// -2-3- _x,_Dx are eliminated in @R2");
1287  dbprint(ppl-1, K2);
1288  // the ring @R3 and the search for minimal negative int s
1289  ring @R3 = 0,s,dp;
1290  dbprint(ppl,"// -3-1- the ring @R3(s) is ready");
1291  ideal K3 = imap(@R2,K2);
1292  poly p = K3[1];
1293  dbprint(ppl,"// -3-2- factorization");
1294  list P = factorize(p);          //with constants and multiplicities
1295  ideal bs; intvec m;             //the Bernstein polynomial is monic, so we are not interested in constants
1296  for (i=2; i<= size(P[1]); i++)  //we ignore P[1][1] (constant) and P[2][1] (its mult.)
1297  {
1298    bs[i-1] = P[1][i];
1299    m[i-1]  = P[2][i];
1300  }
1301  // "--------- b-function factorizes into ---------";  P;
1302  int sP = minIntRoot(bs,1);
1303  dbprint(ppl,"// -3-3- minimal integer root found");
1304  dbprint(ppl-1, sP);
1305  // convert factors to a list of their roots
1306  bs = normalize(bs);
1307  bs = -subst(bs,s,0);
1308  list BS = bs,m;
1309  //TODO: sort BS!
1310  // --------- substitute s found in the ideal ---------
1311  // --------- going back to @R and substitute ---------
1312  setring @R;
1313  ideal K2 = subst(K,s,sP);
1314  kill K;
1315  // create the ordinary Weyl algebra and put the result into it,
1316  // thus creating the ring @R4
1317  // keep: N, i,j,s, tmp, RL
1318  setring save;
1319  Nnew = 2*N;
1320  // list RL = ringlist(save);  //is defined earlier
1321  kill Lord, tmp, iv;
1322  L = 0;
1323  list Lord, tmp;
1324  intvec iv;
1325  L[1] = RL[1];
1326  L[4] = RL[4];  //char, minpoly
1327  // check whether vars have admissible names -> done earlier
1328  // list Name = RL[2]M
1329  // DName is defined earlier
1330  list NName = Name + DName;
1331  L[2] = NName;
1332  // dp ordering;
1333  string s = "iv=";
1334  for (i=1; i<=Nnew; i++)
1335  {
1336    s = s+"1,";
1337  }
1338  s[size(s)] = ";";
1339  execute(s);
1340  kill s;
1341  tmp     = 0;
1342  tmp[1]  = "dp";  //string
1343  tmp[2]  = iv;    //intvec
1344  Lord[1] = tmp;
1345  tmp[1]  = "C";
1346  iv      = 0;
1347  tmp[2]  = iv;
1348  Lord[2] = tmp;
1349  tmp     = 0;
1350  L[3]    = Lord;
1351  // we are done with the list
1352  // Add: Plural part
1353  def @R4@ = ring(L);
1354  setring @R4@;
1355  matrix @D[Nnew][Nnew];
1356  for (i=1; i<=N; i++)
1357  {
1358    @D[i,N+i]=1;
1359  }
1360  def @R4 = nc_algebra(1,@D);
1361  setring @R4;
1362  kill @R4@;
1363  dbprint(ppl,"// -4-1- the ring @R4(_x,_Dx) is ready");
1364  dbprint(ppl-1, @R4);
1365  ideal K4 = imap(@R,K2);
1366  option(redSB);
1367  dbprint(ppl,"// -4-2- the final cosmetic std");
1368  K4 = engine(K4,eng);  //std does the job too
1369  // total cleanup
1370  kill @R;
1371  kill @R2;
1372  list BS = imap(@R3,BS);
1373  export BS;
1374  kill @R3;
1375  ideal LD = K4;
1376  export LD;
1377  return(@R4);
1378}
1379example
1380{
1381  "EXAMPLE:"; echo = 2;
1382  ring r = 0,(x,y,z),Dp;
1383  poly F = z*x^2+y^3;
1384  printlevel = 0;
1385  def A = annfsBM(F);
1386  setring A;
1387  LD;
1388  BS;
1389}
1390
1391
1392// replacing s with -s-1 => data is shorter
1393// analogue of annfs0
1394proc annfs2(ideal I, poly F, list #)
1395"USAGE:  annfs2(I, F [,eng]);  I an ideal, F a poly, eng an optional int
1396RETURN:  ring
1397PURPOSE: compute the annihilator ideal of f^s in the Weyl Algebra,
1398@*       based on the output of Sannfs-like procedure
1399@*       annfs2 uses shorter expressions in the variable s (the idea of Noro).
1400NOTE: activate the output ring with the @code{setring} command. In this ring,
1401@*      - the ideal LD (which is a Groebner basis) is the annihilator of f^s,
1402@*      - the list BS contains the roots with multiplicities of the BS polynomial.
1403@*    If eng <>0, @code{std} is used for Groebner basis computations,
1404@*    otherwise and by default @code{slimgb} is used.
1405DISPLAY: If @code{printlevel}=1, progress debug messages will be printed,
1406@*       if @code{printlevel}>=2, all the debug messages will be printed.
1407EXAMPLE: example annfs2; shows examples
1408"
1409{
1410  int eng = 0;
1411  if ( size(#)>0 )
1412  {
1413    if ( typeof(#[1]) == "int" )
1414    {
1415      eng = int(#[1]);
1416    }
1417  }
1418  def @R2 = basering;
1419  // we're in D_n[s], where the elim ord for s is set
1420  ideal J = NF(I,std(F));
1421  // make leadcoeffs positive
1422  int i;
1423  J = subst(J,s,-s-1);
1424  for (i=1; i<= ncols(J); i++)
1425  {
1426    if (leadcoef(J[i]) <0 )
1427    {
1428      J[i] = -J[i];
1429    }
1430  }
1431  J = J,F;
1432  ideal M = engine(J,eng);
1433  int Nnew = nvars(@R2);
1434  ideal K2 = nselect(M,1..Nnew-1);
1435  int ppl = printlevel-voice+2;
1436  dbprint(ppl,"// -1-1- _x,_Dx are eliminated in basering");
1437  dbprint(ppl-1, K2);
1438  // the ring @R3 and the search for minimal negative int s
1439  ring @R3 = 0,s,dp;
1440  dbprint(ppl,"// -2-1- the ring @R3 i.e. K[s] is ready");
1441  ideal K3 = imap(@R2,K2);
1442  poly p = K3[1];
1443  dbprint(ppl,"// -2-2- factorization");
1444  //  ideal P = factorize(p,1);  //without constants and multiplicities
1445  //  "--------- b-function factorizes into ---------";   P;
1446  // convert factors to the list of their roots with mults
1447  // assume all factors are linear
1448  //  ideal BS = normalize(P);
1449  //  BS = subst(BS,s,0);
1450  //  BS = -BS;
1451  list P = factorize(p);          //with constants and multiplicities
1452  ideal bs; intvec m;             //the Bernstein polynomial is monic, so we are not interested in constants
1453  for (i=2; i<= size(P[1]); i++)  //we delete P[1][1] and P[2][1]
1454  {
1455    bs[i-1] = P[1][i]; bs[i-1] = subst(bs[i-1],s,-s-1);
1456    m[i-1]  = P[2][i];
1457  }
1458  int sP = minIntRoot(bs,1);
1459  bs =  normalize(bs);
1460  bs = -subst(bs,s,0);
1461  dbprint(ppl,"// -2-3- minimal integer root found");
1462  dbprint(ppl-1, sP);
1463 //TODO: sort BS!
1464  // --------- substitute s found in the ideal ---------
1465  // --------- going back to @R and substitute ---------
1466  setring @R2;
1467  K2 = subst(I,s,sP);
1468  // create the ordinary Weyl algebra and put the result into it,
1469  // thus creating the ring @R5
1470  // keep: N, i,j,s, tmp, RL
1471  Nnew = Nnew - 1; // former 2*N;
1472  // list RL = ringlist(save);  // is defined earlier
1473  //  kill Lord, tmp, iv;
1474  list L = 0;
1475  list Lord, tmp;
1476  intvec iv;
1477  list RL = ringlist(basering);
1478  L[1] = RL[1];
1479  L[4] = RL[4];  //char, minpoly
1480  // check whether vars have admissible names -> done earlier
1481  // list Name = RL[2]M
1482  // DName is defined earlier
1483  list NName; // = RL[2]; // skip the last var 's'
1484  for (i=1; i<=Nnew; i++)
1485  {
1486    NName[i] =  RL[2][i];
1487  }
1488  L[2] = NName;
1489  // dp ordering;
1490  string s = "iv=";
1491  for (i=1; i<=Nnew; i++)
1492  {
1493    s = s+"1,";
1494  }
1495  s[size(s)] = ";";
1496  execute(s);
1497  tmp     = 0;
1498  tmp[1]  = "dp";  // string
1499  tmp[2]  = iv;  // intvec
1500  Lord[1] = tmp;
1501  kill s;
1502  tmp[1]  = "C";
1503  iv = 0;
1504  tmp[2]  = iv;
1505  Lord[2] = tmp;
1506  tmp     = 0;
1507  L[3]    = Lord;
1508  // we are done with the list
1509  // Add: Plural part
1510  def @R4@ = ring(L);
1511  setring @R4@;
1512  int N = Nnew/2;
1513  matrix @D[Nnew][Nnew];
1514  for (i=1; i<=N; i++)
1515  {
1516    @D[i,N+i]=1;
1517  }
1518  def @R4 = nc_algebra(1,@D);
1519  setring @R4;
1520  kill @R4@;
1521  dbprint(ppl,"// -3-1- the ring @R4 is ready");
1522  dbprint(ppl-1, @R4);
1523  ideal K4 = imap(@R2,K2);
1524  option(redSB);
1525  dbprint(ppl,"// -3-2- the final cosmetic std");
1526  K4 = engine(K4,eng);  // std does the job too
1527  // total cleanup
1528  ideal bs = imap(@R3,bs);
1529  kill @R3;
1530  list BS = bs,m;
1531  export BS;
1532  ideal LD = K4;
1533  export LD;
1534  return(@R4);
1535}
1536example
1537{ "EXAMPLE:"; echo = 2;
1538  ring r = 0,(x,y,z),Dp;
1539  poly F = x^3+y^3+z^3;
1540  printlevel = 0;
1541  def A = SannfsBM(F);
1542  setring A;
1543  LD;
1544  poly F = imap(r,F);
1545  def B  = annfs2(LD,F);
1546  setring B;
1547  LD;
1548  BS;
1549}
1550
1551// try to replace s with -s-1 => data is shorter as in annfs2
1552// and use what Macaulay2 people call reduceB strategy, that is add
1553// not F but Tjurina ideal <F,dF/dx1,...,dF/dxN>; the resulting B-function
1554// has to be multiplied with (s+1) at the very end
1555proc annfsRB(ideal I, poly F, list #)
1556"USAGE:  annfsRB(I, F [,eng]);  I an ideal, F a poly, eng an optional int
1557RETURN:  ring
1558PURPOSE: compute the annihilator ideal of f^s in the Weyl Algebra,
1559@* based on the output of Sannfs like procedure
1560NOTE:    activate the output ring with the @code{setring} command. In this ring,
1561@*       - the ideal LD (which is a Groebner basis) is the annihilator of f^s,
1562@*       - the list BS contains the roots with multiplicities of a Bernstein polynomial of f.
1563@*       If eng <>0, @code{std} is used for Groebner basis computations,
1564@*       otherwise and by default @code{slimgb} is used.
1565@*       This procedure uses in addition to F its Jacobian ideal.
1566DISPLAY: If @code{printlevel}=1, progress debug messages will be printed,
1567@*       if @code{printlevel}>=2, all the debug messages will be printed.
1568EXAMPLE: example annfsRB; shows examples
1569"
1570{
1571  int eng = 0;
1572  if ( size(#)>0 )
1573  {
1574    if ( typeof(#[1]) == "int" )
1575    {
1576      eng = int(#[1]);
1577    }
1578  }
1579  def @R2 = basering;
1580  int ppl = printlevel-voice+2;
1581  // we're in D_n[s], where the elim ord for s is set
1582  // switch to comm. ring in X's and compute the GB of Tjurina ideal
1583  dbprint(ppl,"// -1-0- creating K[x] and Tjurina ideal");
1584  list nL = ringlist(@R2);
1585  list temp,t2;
1586  temp[1] = nL[1];
1587  temp[4] = nL[4];
1588  int @n = int((nvars(@R2)-1)/2); // # of x's
1589  int i;
1590  for (i=1; i<=@n; i++)
1591  {
1592    t2[i] = nL[2][i];
1593  }
1594  temp[2] = t2;
1595  t2 = 0;
1596  t2[1] = nL[3][1]; // more weights than vars?
1597  t2[2] = nL[3][3];
1598  temp[3] = t2;
1599  def @R22 = ring(temp);
1600  setring @R22;
1601  poly F = imap(@R2,F);
1602  ideal J = F;
1603  for (i=1; i<=@n; i++)
1604  {
1605    J = J, diff(F,var(i));
1606  }
1607  J = engine(J,eng);
1608  dbprint(ppl,"// -1-1- finished computing the GB of Tjurina ideal");
1609  dbprint(ppl-1, J);
1610  setring @R2;
1611  ideal JF = imap(@R22,J);
1612  kill @R22;
1613  attrib(JF,"isSB",1); // embedded comm ring is used
1614  ideal J = NF(I,JF);
1615  dbprint(ppl,"// -1-2- finished computing the NF of I w.r.t. Tjurina ideal");
1616  dbprint(ppl-1, J2);
1617  // make leadcoeffs positive
1618  J = subst(J,s,-s-1);
1619  for (i=1; i<= ncols(J); i++)
1620  {
1621    if (leadcoef(J[i]) <0 )
1622    {
1623      J[i] = -J[i];
1624    }
1625  }
1626  J = J,JF;
1627  ideal M = engine(J,eng);
1628  int Nnew = nvars(@R2);
1629  ideal K2 = nselect(M,1..Nnew-1);
1630  dbprint(ppl,"// -2-0- _x,_Dx are eliminated in basering");
1631  dbprint(ppl-1, K2);
1632  // the ring @R3 and the search for minimal negative int s
1633  ring @R3 = 0,s,dp;
1634  dbprint(ppl,"// -2-1- the ring @R3 i.e. K[s] is ready");
1635  ideal K3 = imap(@R2,K2);
1636  poly p = K3[1];
1637  p = s*p; // mult with the lost (s+1) factor
1638  dbprint(ppl,"// -2-2- factorization");
1639  //  ideal P = factorize(p,1);  //without constants and multiplicities
1640  //  "--------- b-function factorizes into ---------";   P;
1641  // convert factors to the list of their roots with mults
1642  // assume all factors are linear
1643  //  ideal BS = normalize(P);
1644  //  BS = subst(BS,s,0);
1645  //  BS = -BS;
1646  list P = factorize(p);          //with constants and multiplicities
1647  ideal bs; intvec m;             //the Bernstein polynomial is monic, so we are not interested in constants
1648  for (i=2; i<= size(P[1]); i++)  //we delete P[1][1] and P[2][1]
1649  {
1650    bs[i-1] = P[1][i]; bs[i-1] = subst(bs[i-1],s,-s-1);
1651    m[i-1]  = P[2][i];
1652  }
1653  int sP = minIntRoot(bs,1);
1654  bs =  normalize(bs);
1655  bs = -subst(bs,s,0);
1656  dbprint(ppl,"// -2-3- minimal integer root found");
1657  dbprint(ppl-1, sP);
1658 //TODO: sort BS!
1659  // --------- substitute s found in the ideal ---------
1660  // --------- going back to @R and substitute ---------
1661  setring @R2;
1662  K2 = subst(I,s,sP);
1663  // create the ordinary Weyl algebra and put the result into it,
1664  // thus creating the ring @R5
1665  // keep: N, i,j,s, tmp, RL
1666  Nnew = Nnew - 1; // former 2*N;
1667  // list RL = ringlist(save);  // is defined earlier
1668  //  kill Lord, tmp, iv;
1669  list L = 0;
1670  list Lord, tmp;
1671  intvec iv;
1672  list RL = ringlist(basering);
1673  L[1] = RL[1];
1674  L[4] = RL[4];  //char, minpoly
1675  // check whether vars have admissible names -> done earlier
1676  // list Name = RL[2]M
1677  // DName is defined earlier
1678  list NName; // = RL[2]; // skip the last var 's'
1679  for (i=1; i<=Nnew; i++)
1680  {
1681    NName[i] =  RL[2][i];
1682  }
1683  L[2] = NName;
1684  // dp ordering;
1685  string s = "iv=";
1686  for (i=1; i<=Nnew; i++)
1687  {
1688    s = s+"1,";
1689  }
1690  s[size(s)] = ";";
1691  execute(s);
1692  tmp     = 0;
1693  tmp[1]  = "dp";  // string
1694  tmp[2]  = iv;  // intvec
1695  Lord[1] = tmp;
1696  kill s;
1697  tmp[1]  = "C";
1698  iv = 0;
1699  tmp[2]  = iv;
1700  Lord[2] = tmp;
1701  tmp     = 0;
1702  L[3]    = Lord;
1703  // we are done with the list
1704  // Add: Plural part
1705  def @R4@ = ring(L);
1706  setring @R4@;
1707  int N = Nnew/2;
1708  matrix @D[Nnew][Nnew];
1709  for (i=1; i<=N; i++)
1710  {
1711    @D[i,N+i]=1;
1712  }
1713  def @R4 = nc_algebra(1,@D);
1714  setring @R4;
1715  kill @R4@;
1716  dbprint(ppl,"// -3-1- the ring @R4 is ready");
1717  dbprint(ppl-1, @R4);
1718  ideal K4 = imap(@R2,K2);
1719  option(redSB);
1720  dbprint(ppl,"// -3-2- the final cosmetic std");
1721  K4 = engine(K4,eng);  // std does the job too
1722  // total cleanup
1723  ideal bs = imap(@R3,bs);
1724  kill @R3;
1725  list BS = bs,m;
1726  export BS;
1727  ideal LD = K4;
1728  export LD;
1729  return(@R4);
1730}
1731example
1732{ "EXAMPLE:"; echo = 2;
1733  ring r = 0,(x,y,z),Dp;
1734  poly F = x^3+y^3+z^3;
1735  printlevel = 0;
1736  def A = SannfsBM(F); setring A;
1737  LD; // s-parametric ahhinilator
1738  poly F = imap(r,F);
1739  def B  = annfsRB(LD,F); setring B;
1740  LD;
1741  BS;
1742}
1743
1744proc operatorBM(poly F, list #)
1745"USAGE:  operatorBM(f [,eng]);  f a poly, eng an optional int
1746RETURN:  ring
1747PURPOSE: compute the B-operator and other relevant data for Ann F^s,
1748@*  using e.g. algorithm by Briancon and Maisonobe for Ann F^s and BS.
1749NOTE:    activate the output ring with the @code{setring} command. In the output ring D[s]
1750@*       - the polynomial F is the same as the input,
1751@*       - the ideal LD is the annihilator of f^s in Dn[s],
1752@*       - the ideal LD0 is the needed D-mod structure, where LD0 = LD|s=s0,
1753@*       - the polynomial bs is the global Bernstein polynomial of f in the variable s,
1754@*       - the list BS contains all the roots with multiplicities of the global Bernstein polynomial of f,
1755@*       - the polynomial PS is an operator in Dn[s] such that PS*f^(s+1) = bs*f^s.
1756@*       If eng <>0, @code{std} is used for Groebner basis computations,
1757@*       otherwise and by default @code{slimgb} is used.
1758DISPLAY: If @code{printlevel}=1, progress debug messages will be printed,
1759@*       if @code{printlevel}>=2, all the debug messages will be printed.
1760EXAMPLE: example operatorBM; shows examples
1761"
1762{
1763  int eng = 0;
1764  if ( size(#)>0 )
1765  {
1766    if ( typeof(#[1]) == "int" )
1767    {
1768      eng = int(#[1]);
1769    }
1770  }
1771  // returns a list with a ring and an ideal LD in it
1772  int ppl = printlevel-voice+2;
1773  //  printf("plevel :%s, voice: %s",printlevel,voice);
1774  def save = basering;
1775  int N = nvars(basering);
1776  int Nnew = 2*N+2;
1777  int i,j;
1778  string s;
1779  list RL = ringlist(basering);
1780  list L, Lord;
1781  list tmp;
1782  intvec iv;
1783  L[1] = RL[1];  //char
1784  L[4] = RL[4];  //char, minpoly
1785  // check whether vars have admissible names
1786  list Name  = RL[2];
1787  list RName;
1788  RName[1] = "t";
1789  RName[2] = "s";
1790  for (i=1; i<=N; i++)
1791  {
1792    for(j=1; j<=size(RName); j++)
1793    {
1794      if (Name[i] == RName[j])
1795      {
1796        ERROR("Variable names should not include t,s");
1797      }
1798    }
1799  }
1800  // now, create the names for new vars
1801  list DName;
1802  for (i=1; i<=N; i++)
1803  {
1804    DName[i] = "D"+Name[i];  //concat
1805  }
1806  tmp[1] = "t";
1807  tmp[2] = "s";
1808  list NName = tmp + Name + DName;
1809  L[2]   = NName;
1810  // Name, Dname will be used further
1811  kill NName;
1812  // block ord (lp(2),dp);
1813  tmp[1]  = "lp"; // string
1814  iv      = 1,1;
1815  tmp[2]  = iv; //intvec
1816  Lord[1] = tmp;
1817  // continue with dp 1,1,1,1...
1818  tmp[1]  = "dp"; // string
1819  s       = "iv=";
1820  for (i=1; i<=Nnew; i++)
1821  {
1822    s = s+"1,";
1823  }
1824  s[size(s)]= ";";
1825  execute(s);
1826  kill s;
1827  tmp[2]    = iv;
1828  Lord[2]   = tmp;
1829  tmp[1]    = "C";
1830  iv        = 0;
1831  tmp[2]    = iv;
1832  Lord[3]   = tmp;
1833  tmp       = 0;
1834  L[3]      = Lord;
1835  // we are done with the list
1836  def @R@ = ring(L);
1837  setring @R@;
1838  matrix @D[Nnew][Nnew];
1839  @D[1,2]=t;
1840  for(i=1; i<=N; i++)
1841  {
1842    @D[2+i,N+2+i]=1;
1843  }
1844  // L[5] = matrix(UpOneMatrix(Nnew));
1845  // L[6] = @D;
1846  def @R = nc_algebra(1,@D);
1847  setring @R;
1848  kill @R@;
1849  dbprint(ppl,"// -1-1- the ring @R(t,s,_x,_Dx) is ready");
1850  dbprint(ppl-1, @R);
1851  // create the ideal I
1852  poly  F = imap(save,F);
1853  ideal I = t*F+s;
1854  poly p;
1855  for(i=1; i<=N; i++)
1856  {
1857    p = t;  //t
1858    p = diff(F,var(2+i))*p;
1859    I = I, var(N+2+i) + p;
1860  }
1861  // -------- the ideal I is ready ----------
1862  dbprint(ppl,"// -1-2- starting the elimination of t in @R");
1863  dbprint(ppl-1, I);
1864  ideal J = engine(I,eng);
1865  ideal K = nselect(J,1);
1866  kill I,J;
1867  dbprint(ppl,"// -1-3- t is eliminated");
1868  dbprint(ppl-1, K);  //K is without t
1869  setring save;
1870  // ----------- the ring @R2 ------------
1871  // _x, _Dx,s;  elim.ord for _x,_Dx.
1872  // keep: N, i,j,s, tmp, RL
1873  Nnew = 2*N+1;
1874  kill Lord, tmp, iv, RName;
1875  list Lord, tmp;
1876  intvec iv;
1877  L[1] = RL[1];
1878  L[4] = RL[4];  //char, minpoly
1879  // check whether vars hava admissible names -> done earlier
1880  // now, create the names for new var
1881  tmp[1] = "s";
1882  // DName is defined earlier
1883  list NName = Name + DName + tmp;
1884  L[2] = NName;
1885  tmp = 0;
1886  // block ord (dp(N),dp);
1887  string s = "iv=";
1888  for (i=1; i<=Nnew-1; i++)
1889  {
1890    s = s+"1,";
1891  }
1892  s[size(s)]=";";
1893  execute(s);
1894  tmp[1] = "dp";  //string
1895  tmp[2] = iv;    //intvec
1896  Lord[1] = tmp;
1897  // continue with dp 1,1,1,1...
1898  tmp[1] = "dp";  //string
1899  s[size(s)] = ",";
1900  s = s+"1;";
1901  execute(s);
1902  kill s;
1903  kill NName;
1904  tmp[2]  = iv;
1905  Lord[2] = tmp;
1906  tmp[1]  = "C";
1907  iv      = 0;
1908  tmp[2]  = iv;
1909  Lord[3] = tmp;
1910  tmp     = 0;
1911  L[3]    = Lord;
1912  // we are done with the list. Now add a Plural part
1913  def @R2@ = ring(L);
1914  setring @R2@;
1915  matrix @D[Nnew][Nnew];
1916  for (i=1; i<=N; i++)
1917  {
1918    @D[i,N+i]=1;
1919  }
1920  def @R2 = nc_algebra(1,@D);
1921  setring @R2;
1922  kill @R2@;
1923  dbprint(ppl,"// -2-1- the ring @R2(_x,_Dx,s) is ready");
1924  dbprint(ppl-1, @R2);
1925  ideal MM = maxideal(1);
1926  MM = 0,s,MM;
1927  map R01 = @R, MM;
1928  ideal K = R01(K);
1929  poly F = imap(save,F);
1930  K = K,F;
1931  dbprint(ppl,"// -2-2- starting the elimination of _x,_Dx in @R2");
1932  dbprint(ppl-1, K);
1933  ideal M = engine(K,eng);
1934  ideal K2 = nselect(M,1..Nnew-1);
1935  kill K,M;
1936  dbprint(ppl,"// -2-3- _x,_Dx are eliminated in @R2");
1937  dbprint(ppl-1, K2);
1938  // the ring @R3 and the search for minimal negative int s
1939  ring @R3 = 0,s,dp;
1940  dbprint(ppl,"// -3-1- the ring @R3(s) is ready");
1941  ideal K3 = imap(@R2,K2);
1942  kill @R2;
1943  poly p = K3[1];
1944  dbprint(ppl,"// -3-2- factorization");
1945  list P = factorize(p);          //with constants and multiplicities
1946  ideal bs; intvec m;             //the Bernstein polynomial is monic, so we are not interested in constants
1947  for (i=2; i<= size(P[1]); i++)  //we delete P[1][1] and P[2][1]
1948  {
1949    bs[i-1] = P[1][i];
1950    m[i-1]  = P[2][i];
1951  }
1952  // "--------- b-function factorizes into ---------";  P;
1953  int sP = minIntRoot(bs,1);
1954  dbprint(ppl,"// -3-3- minimal integer root found");
1955  dbprint(ppl-1, sP);
1956  // convert factors to a list of their roots with multiplicities
1957  bs = normalize(bs);
1958  bs = -subst(bs,s,0);
1959  list BS = bs,m;
1960  //TODO: sort BS!
1961  // --------- substitute s found in the ideal ---------
1962  // --------- going back to @R and substitute ---------
1963  setring @R;
1964  ideal K2 = subst(K,s,sP);
1965  // create Dn[s], where Dn is the ordinary Weyl algebra, and put the result into it,
1966  // thus creating the ring @R4
1967  // keep: N, i,j,s, tmp, RL
1968  setring save;
1969  Nnew = 2*N+1;
1970  // list RL = ringlist(save);  //is defined earlier
1971  kill Lord, tmp, iv;
1972  L = 0;
1973  list Lord, tmp;
1974  intvec iv;
1975  L[1] = RL[1];
1976  L[4] = RL[4];  //char, minpoly
1977  // check whether vars have admissible names -> done earlier
1978  // list Name = RL[2]
1979  // DName is defined earlier
1980  tmp[1] = "s";
1981  list NName = Name + DName + tmp;
1982  L[2] = NName;
1983  // dp ordering;
1984  string s = "iv=";
1985  for (i=1; i<=Nnew; i++)
1986  {
1987    s = s+"1,";
1988  }
1989  s[size(s)] = ";";
1990  execute(s);
1991  kill s;
1992  tmp     = 0;
1993  tmp[1]  = "dp";  //string
1994  tmp[2]  = iv;    //intvec
1995  Lord[1] = tmp;
1996  tmp[1]  = "C";
1997  iv      = 0;
1998  tmp[2]  = iv;
1999  Lord[2] = tmp;
2000  tmp     = 0;
2001  L[3]    = Lord;
2002  // we are done with the list
2003  // Add: Plural part
2004  def @R4@ = ring(L);
2005  setring @R4@;
2006  matrix @D[Nnew][Nnew];
2007  for (i=1; i<=N; i++)
2008  {
2009    @D[i,N+i]=1;
2010  }
2011  def @R4 = nc_algebra(1,@D);
2012  setring @R4;
2013  kill @R4@;
2014  dbprint(ppl,"// -4-1- the ring @R4(_x,_Dx,s) is ready");
2015  dbprint(ppl-1, @R4);
2016  ideal LD0 = imap(@R,K2);
2017  ideal LD  = imap(@R,K);
2018  kill @R;
2019  poly bs = imap(@R3,p);
2020  list BS = imap(@R3,BS);
2021  kill @R3;
2022  bs = normalize(bs);
2023  poly F = imap(save,F);
2024  dbprint(ppl,"// -4-2- starting the computation of PS via lift");
2025//better liftstd, I didn't knot it works also for Plural, liftslimgb?
2026// liftstd may give extra coeffs in the resulting ideal
2027  matrix T = lift(F+LD,bs);
2028  poly PS = T[1,1];
2029  dbprint(ppl,"// -4-3- an operator PS found, PS*f^(s+1) = b(s)*f^s");
2030  dbprint(ppl-1,PS);
2031  option(redSB);
2032  dbprint(ppl,"// -4-4- the final cosmetic std");
2033  LD0 = engine(LD0,eng);  //std does the job too
2034  LD  = engine(LD,eng);
2035  export F,LD,LD0,bs,BS,PS;
2036  return(@R4);
2037}
2038example
2039{
2040  "EXAMPLE:"; echo = 2;
2041  ring r = 0,(x,y,z),Dp;
2042  poly F = x^3+y^3+z^3;
2043  printlevel = 0;
2044  def A = operatorBM(F);
2045  setring A;
2046  F; // the original polynomial itself
2047  LD; // generic annihilator
2048  LD0; // annihilator
2049  bs; // normalized Bernstein poly
2050  BS; // roots and multiplicities of the Bernstein poly
2051  PS; // the operator, s.t. PS*F^{s+1} = bs*F^s mod LD
2052  reduce(PS*F-bs,LD); // check the property of PS
2053}
2054
2055// more interesting:
2056//  ring r = 0,(x,y,z,w),Dp;
2057//  poly F = x^3+y^3+z^2*w;
2058
2059// need: (c,<) ordering for such comp's
2060
2061proc operatorModulo(poly F, ideal I, poly b)
2062"USAGE:  operatorModulo(f,I,b);  f a poly, I an ideal, b a poly
2063RETURN:  poly
2064PURPOSE: compute the B-operator from the polynomial f,
2065@*           ideal I = Ann f^s and Bernstein-Sato polynomial b
2066@*           using modulo i.e. kernel of module homomorphism
2067NOTE:  The computations take place in the ring, similar to the one
2068@*       returned by Sannfs procedure.
2069@*     Note, that operator is not completely reduced wrt Ann f^{s+1}.
2070@*     If printlevel=1, progress debug messages will be printed,
2071@*     if printlevel>=2, all the debug messages will be printed.
2072EXAMPLE: example operatorModulo; shows examples
2073"
2074{
2075  int ppl = printlevel-voice+2;
2076  def save = basering;
2077  // change the ordering on the currRing
2078  def mering = makeModElimRing(save);
2079  setring mering;
2080  poly b = imap(save, b);
2081  poly F = imap(save, F);
2082  ideal I = imap(save, I);
2083  matrix N = matrix(I); // ann f^s
2084  //  matrix K = hom_kernel(AA,M,N);
2085  // option(noreturnSB)?
2086  /// matrix K = modulo(AA,N); // too slow: do it with slim!
2087    module M = b,-F;
2088    dbprint(ppl,"starting modulo computation");
2089    module K = moduloSlim(M,N);
2090    dbprint(ppl,"finished modulo computation");
2091    //    K = transpose(K);
2092//     matrix M[3][s+2] = F,-b,I[1..s], 1,0:(s+1),0,1,0:(s);
2093//     module GM = slimgb(M);
2094//     module GMT = transpose(G);
2095//     GMT = GMT[2],GMT[3]; // modulo matrix
2096//     module K = GMT[2];
2097//     GMT = transpose(GMT);
2098//     K = transpose(K);
2099//     matrix K = GMT;
2100//////////////////////////////////////////////////
2101//  now select those elts whose 0's entry is nonzero
2102// if there is constant => done
2103// if not => compute GB and get it
2104    module L;
2105    ideal J;
2106    int i;
2107    poly t; number n;
2108    for(i=1; i<=ncols(K); i++)
2109    {
2110      if (K[1,i]!=0)
2111      {
2112        L = L,K[i];
2113        if ( leadmonom(K[1,i]) == 1)
2114        {
2115          t = K[2,i];
2116          n = leadcoef(K[1,i]);
2117          t = t/n;
2118          break;
2119          //          return(t);
2120        }
2121      }
2122    }
2123    if (n!=0)
2124    {
2125      // constant found
2126      setring save; poly t = imap(mering,t); kill mering;
2127      return(t);
2128    }
2129    dbprint(ppl,"no explicit constant. Start one more GB computation");
2130    // else: compute GB and do the same
2131    L = L[2..ncols(L)];
2132    K  = slimgb(L);
2133    dbprint(ppl,"finished GB computation");
2134    for(i=1; i<=ncols(K); i++)
2135    {
2136      if (K[1,i]!=0)
2137      {
2138        if ( leadmonom(K[1,i]) == 1)
2139        {
2140          t = K[2,i];
2141          n = leadcoef(K[1,i]);
2142          t = t/n;
2143//          break;
2144          setring save; poly t = imap(mering,t); kill mering;
2145          return(t);
2146        }
2147      }
2148    }
2149
2150    // we are here if no constant found
2151    "ERROR: must never get here!";
2152    return(0);
2153//     for(i=1; i<=nrows(K); i++)
2154//     {
2155//       if (K[i,2]!=0)
2156//       {
2157//         if ( leadmonom(K[i,2]) == 1)
2158//         {
2159//           t = K[i,1];
2160//           n = leadcoef(K[i,2]);
2161//           t = t/n;
2162// //        J = J, K[i][2];
2163//           break;
2164//         }
2165//      }
2166//   }
2167//   ideal J = groebner(subst(I,s,s+1)); // for NF
2168//   t = NF(t,J);
2169//   "candidate:"; t;
2170//   J = subst(J,s,s-1);
2171//   // test:
2172//   if ( NF(t*F-b,J) !=0)
2173//   {
2174//     "Problem: PS does not work on F";
2175//   }
2176//   return(t);
2177}
2178example
2179{
2180  "EXAMPLE:"; echo = 2;
2181  //  LIB "dmod.lib"; option(prot); option(mem);
2182  ring r = 0,(x,y),Dp;
2183  poly F = x^3+y^3+x*y^3;
2184  def A = Sannfs(F); // here we get LD = ann f^s
2185  setring A;
2186  poly F = imap(r,F);
2187  def B = annfs0(LD,F); // to obtain BS polynomial
2188  list BS = imap(B,BS);   poly bs = fl2poly(BS,"s");
2189  poly PS = operatorModulo(F,LD,bs);
2190  LD = groebner(LD);
2191  PS = NF(PS,subst(LD,s,s+1));; // reduction modulo Ann s^{s+1}
2192  size(PS);
2193  lead(PS);
2194  reduce(PS*F-bs,LD); // check the defining property of PS
2195}
2196
2197proc annfsParamBM (poly F, list #)
2198"USAGE:  annfsParamBM(f [,eng]);  f a poly, eng an optional int
2199RETURN:  ring
2200PURPOSE: compute the generic Ann F^s and exceptional parametric constellations
2201@* of a polynomial with parametric coefficients with the BM algorithm
2202NOTE:    activate the output ring with the @code{setring} command. In this ring,
2203@*       - the ideal LD is the D-module structure oa Ann F^s
2204@*       - the ideal Param contains special parameters as entries
2205@*       If eng <>0, @code{std} is used for Groebner basis computations,
2206@*       otherwise, and by default @code{slimgb} is used.
2207DISPLAY: If @code{printlevel}=1, progress debug messages will be printed,
2208@*          if @code{printlevel}>=2, all the debug messages will be printed.
2209EXAMPLE: example annfsParamBM; shows examples
2210"
2211{
2212  //PURPOSE: compute the list of all possible Bernstein-Sato polynomials for a polynomial with parametric coefficients, according to the algorithm by Briancon and Maisonobe
2213  // @*       - the list BS is the list of roots and multiplicities of a Bernstein polynomial of f.
2214  // ***** not implented yet ****
2215  int eng = 0;
2216  if ( size(#)>0 )
2217  {
2218    if ( typeof(#[1]) == "int" )
2219    {
2220      eng = int(#[1]);
2221    }
2222  }
2223  // returns a list with a ring and an ideal LD in it
2224  int ppl = printlevel-voice+2;
2225  //  printf("plevel :%s, voice: %s",printlevel,voice);
2226  def save = basering;
2227  int N = nvars(basering);
2228  int Nnew = 2*N+2;
2229  int i,j;
2230  string s;
2231  list RL = ringlist(basering);
2232  list L, Lord;
2233  list tmp;
2234  intvec iv;
2235  L[1] = RL[1];  //char
2236  L[4] = RL[4];  //char, minpoly
2237  // check whether vars have admissible names
2238  list Name  = RL[2];
2239  list RName;
2240  RName[1] = "t";
2241  RName[2] = "s";
2242  for (i=1; i<=N; i++)
2243  {
2244    for(j=1; j<=size(RName); j++)
2245    {
2246      if (Name[i] == RName[j])
2247      {
2248        ERROR("Variable names should not include t,s");
2249      }
2250    }
2251  }
2252  // now, create the names for new vars
2253  list DName;
2254  for (i=1; i<=N; i++)
2255  {
2256    DName[i] = "D"+Name[i];  //concat
2257  }
2258  tmp[1] = "t";
2259  tmp[2] = "s";
2260  list NName = tmp + Name + DName;
2261  L[2]   = NName;
2262  // Name, Dname will be used further
2263  kill NName;
2264  // block ord (lp(2),dp);
2265  tmp[1]  = "lp"; // string
2266  iv      = 1,1;
2267  tmp[2]  = iv; //intvec
2268  Lord[1] = tmp;
2269  // continue with dp 1,1,1,1...
2270  tmp[1]  = "dp"; // string
2271  s       = "iv=";
2272  for (i=1; i<=Nnew; i++)
2273  {
2274    s = s+"1,";
2275  }
2276  s[size(s)]= ";";
2277  execute(s);
2278  kill s;
2279  tmp[2]    = iv;
2280  Lord[2]   = tmp;
2281  tmp[1]    = "C";
2282  iv        = 0;
2283  tmp[2]    = iv;
2284  Lord[3]   = tmp;
2285  tmp       = 0;
2286  L[3]      = Lord;
2287  // we are done with the list
2288  def @R@ = ring(L);
2289  setring @R@;
2290  matrix @D[Nnew][Nnew];
2291  @D[1,2]=t;
2292  for(i=1; i<=N; i++)
2293  {
2294    @D[2+i,N+2+i]=1;
2295  }
2296  // L[5] = matrix(UpOneMatrix(Nnew));
2297  // L[6] = @D;
2298  def @R = nc_algebra(1,@D);
2299  setring @R;
2300  kill @R@;
2301  dbprint(ppl,"// -1-1- the ring @R(t,s,_x,_Dx) is ready");
2302  dbprint(ppl-1, @R);
2303  // create the ideal I
2304  poly  F = imap(save,F);
2305  ideal I = t*F+s;
2306  poly p;
2307  for(i=1; i<=N; i++)
2308  {
2309    p = t;  //t
2310    p = diff(F,var(2+i))*p;
2311    I = I, var(N+2+i) + p;
2312  }
2313  // -------- the ideal I is ready ----------
2314  dbprint(ppl,"// -1-2- starting the elimination of t in @R");
2315  dbprint(ppl-1, I);
2316  ideal J = engine(I,eng);
2317  ideal K = nselect(J,1);
2318  dbprint(ppl,"// -1-3- t is eliminated");
2319  dbprint(ppl-1, K);  //K is without t
2320  // ----- looking for special parameters -----
2321  dbprint(ppl,"// -2-1- starting the computation of the transformation matrix (via lift)");
2322  J = normalize(J);
2323  matrix T = lift(I,J);  //try also with liftstd
2324  kill I,J;
2325  dbprint(ppl,"// -2-2- the transformation matrix has been computed");
2326  dbprint(ppl-1, T);  //T is the transformation matrix
2327  dbprint(ppl,"// -2-3- genericity does the job");
2328  list lParam = genericity(T);
2329  int ip = size(lParam);
2330  int cip;
2331  string sParam;
2332  if (sParam[1]=="-") { sParam=""; } //genericity returns "-"
2333  // if no parameters exist in a basering
2334  for (cip=1; cip <= ip; cip++)
2335  {
2336    sParam = sParam + "," +lParam[cip];
2337  }
2338  if (size(sParam) >=2)
2339  {
2340    sParam = sParam[2..size(sParam)]; // removes the 1st colon
2341  }
2342  export sParam;
2343  kill T;
2344  dbprint(ppl,"// -2-4- the special parameters has been computed");
2345  dbprint(ppl, sParam);
2346  // create Dn[s], where Dn is the ordinary Weyl Algebra, and put the result into it,
2347  // thus creating the ring @R2
2348  // keep: N, i,j,s, tmp, RL
2349  setring save;
2350  Nnew = 2*N+1;
2351  // list RL = ringlist(save);  //is defined earlier
2352  kill Lord, tmp, iv;
2353  L = 0;
2354  list Lord, tmp;
2355  intvec iv;
2356  L[1] = RL[1];
2357  L[4] = RL[4];  //char, minpoly
2358  // check whether vars have admissible names -> done earlier
2359  // list Name = RL[2]M
2360  // DName is defined earlier
2361  tmp[1] = "s";
2362  list NName = Name + DName + tmp;
2363  L[2] = NName;
2364  // dp ordering;
2365  string s = "iv=";
2366  for (i=1; i<=Nnew; i++)
2367  {
2368    s = s+"1,";
2369  }
2370  s[size(s)] = ";";
2371  execute(s);
2372  kill s;
2373  tmp     = 0;
2374  tmp[1]  = "dp";  //string
2375  tmp[2]  = iv;    //intvec
2376  Lord[1] = tmp;
2377  tmp[1]  = "C";
2378  iv      = 0;
2379  tmp[2]  = iv;
2380  Lord[2] = tmp;
2381  tmp     = 0;
2382  L[3]    = Lord;
2383  // we are done with the list
2384  // Add: Plural part
2385  def @R2@ = ring(L);
2386  setring @R2@;
2387  matrix @D[Nnew][Nnew];
2388  for (i=1; i<=N; i++)
2389  {
2390    @D[i,N+i]=1;
2391  }
2392  def @R2 = nc_algebra(1,@D);
2393  setring @R2;
2394  kill @R2@;
2395  dbprint(ppl,"// -3-1- the ring @R2(_x,_Dx,s) is ready");
2396  dbprint(ppl-1, @R2);
2397  ideal K = imap(@R,K);
2398  kill @R;
2399  option(redSB);
2400  dbprint(ppl,"// -3-2- the final cosmetic std");
2401  K = engine(K,eng);  //std does the job too
2402  ideal LD = K;
2403  export LD;
2404  if (sParam[1] == ",")
2405  {
2406    sParam = sParam[2..size(sParam)];
2407  }
2408  //  || ((sParam[1] == " ") && (sParam[2] == ",")))
2409  execute("ideal Param ="+sParam+";");
2410  export Param;
2411  kill sParam;
2412  return(@R2);
2413}
2414example
2415{
2416  "EXAMPLE:"; echo = 2;
2417  ring r = (0,a,b),(x,y),Dp;
2418  poly F = x^2 - (y-a)*(y-b);
2419  printlevel = 0;
2420  def A = annfsParamBM(F);  setring A;
2421  LD;
2422  Param;
2423  setring r;
2424  poly G = x2-(y-a)^2; // try the exceptional value b=a of parameters
2425  def B = annfsParamBM(G); setring B;
2426  LD;
2427  Param;
2428}
2429
2430// *** the following example is nice, but too complicated for the documentation ***
2431//   ring r = (0,a),(x,y,z),Dp;
2432//   poly F = x^4+y^4+z^2+a*x*y*z;
2433//   printlevel = 2; //0
2434//   def A = annfsParamBM(F);
2435//   setring A;
2436//   LD;
2437//   Param;
2438
2439
2440proc annfsBMI(ideal F, list #)
2441"USAGE:  annfsBMI(F [,eng]);  F an ideal, eng an optional int
2442RETURN:  ring
2443PURPOSE: compute the D-module structure of basering[1/f]*f^s where
2444@* f = F[1]*..*F[P], according to the algorithm by Briancon and Maisonobe.
2445NOTE:    activate the output ring with the @code{setring} command. In this ring,
2446@*       - the ideal LD is the needed D-mod structure,
2447@*       - the list BS is the Bernstein ideal of a polynomial f = F[1]*..*F[P].
2448@*       If eng <>0, @code{std} is used for Groebner basis computations,
2449@*       otherwise, and by default @code{slimgb} is used.
2450@*       If printlevel=1, progress debug messages will be printed,
2451@*       if printlevel>=2, all the debug messages will be printed.
2452EXAMPLE: example annfsBMI; shows examples
2453"
2454{
2455  int eng = 0;
2456  if ( size(#)>0 )
2457  {
2458    if ( typeof(#[1]) == "int" )
2459    {
2460      eng = int(#[1]);
2461    }
2462  }
2463  // returns a list with a ring and an ideal LD in it
2464  int ppl = printlevel-voice+2;
2465  //  printf("plevel :%s, voice: %s",printlevel,voice);
2466  def save = basering;
2467  int N = nvars(basering);
2468  int P = size(F);  //if F has some generators which are zero, int P = ncols(I);
2469  int Nnew = 2*N+2*P;
2470  int i,j;
2471  string s;
2472  list RL = ringlist(basering);
2473  list L, Lord;
2474  list tmp;
2475  intvec iv;
2476  L[1] = RL[1];  //char
2477  L[4] = RL[4];  //char, minpoly
2478  // check whether vars have admissible names
2479  list Name  = RL[2];
2480  list RName;
2481  for (j=1; j<=P; j++)
2482  {
2483    RName[j] = "t("+string(j)+")";
2484    RName[j+P] = "s("+string(j)+")";
2485  }
2486  for(i=1; i<=N; i++)
2487  {
2488    for(j=1; j<=size(RName); j++)
2489    {
2490      if (Name[i] == RName[j])
2491      { ERROR("Variable names should not include t(i),s(i)"); }
2492    }
2493  }
2494  // now, create the names for new vars
2495  list DName;
2496  for(i=1; i<=N; i++)
2497  {
2498    DName[i] = "D"+Name[i];  //concat
2499  }
2500  list NName = RName + Name + DName;
2501  L[2]   = NName;
2502  // Name, Dname will be used further
2503  kill NName;
2504  // block ord (lp(P),dp);
2505  tmp[1] = "lp";  //string
2506  s      = "iv=";
2507  for (i=1; i<=2*P; i++)
2508  {
2509    s = s+"1,";
2510  }
2511  s[size(s)]= ";";
2512  execute(s);
2513  tmp[2] = iv;  //intvec
2514  Lord[1] = tmp;
2515  // continue with dp 1,1,1,1...
2516  tmp[1] = "dp";  //string
2517  s      = "iv=";
2518  for (i=1; i<=Nnew; i++)  //actually i<=2*N
2519  {
2520    s = s+"1,";
2521  }
2522  s[size(s)]= ";";
2523  execute(s);
2524  kill s;
2525  tmp[2]  = iv;
2526  Lord[2] = tmp;
2527  tmp[1]  = "C";
2528  iv      = 0;
2529  tmp[2]  = iv;
2530  Lord[3] = tmp;
2531  tmp     = 0;
2532  L[3]    = Lord;
2533  // we are done with the list
2534  def @R@ = ring(L);
2535  setring @R@;
2536  matrix @D[Nnew][Nnew];
2537  for (i=1; i<=P; i++)
2538  {
2539    @D[i,i+P] = t(i);
2540  }
2541  for(i=1; i<=N; i++)
2542  {
2543    @D[2*P+i,2*P+N+i] = 1;
2544  }
2545  // L[5] = matrix(UpOneMatrix(Nnew));
2546  // L[6] = @D;
2547  def @R = nc_algebra(1,@D);
2548  setring @R;
2549  kill @R@;
2550  dbprint(ppl,"// -1-1- the ring @R(_t,_s,_x,_Dx) is ready");
2551  dbprint(ppl-1, @R);
2552  // create the ideal I
2553  ideal  F = imap(save,F);
2554  ideal I = t(1)*F[1]+s(1);
2555  for (j=2; j<=P; j++)
2556  {
2557    I = I, t(j)*F[j]+s(j);
2558  }
2559  poly p,q;
2560  for (i=1; i<=N; i++)
2561  {
2562    p=0;
2563    for (j=1; j<=P; j++)
2564    {
2565      q = t(j);
2566      q = diff(F[j],var(2*P+i))*q;
2567      p = p + q;
2568    }
2569    I = I, var(2*P+N+i) + p;
2570  }
2571  // -------- the ideal I is ready ----------
2572  dbprint(ppl,"// -1-2- starting the elimination of "+string(t(1..P))+" in @R");
2573  dbprint(ppl-1, I);
2574  ideal J = engine(I,eng);
2575  ideal K = nselect(J,1..P);
2576  kill I,J;
2577  dbprint(ppl,"// -1-3- all t(i) are eliminated");
2578  dbprint(ppl-1, K);  //K is without t(i)
2579  // ----------- the ring @R2 ------------
2580  // _x, _Dx,s;  elim.ord for _x,_Dx.
2581  // keep: N, i,j,s, tmp, RL
2582  setring save;
2583  Nnew = 2*N+P;
2584  kill Lord, tmp, iv, RName;
2585  list Lord, tmp;
2586  intvec iv;
2587  L[1] = RL[1];  //char
2588  L[4] = RL[4];  //char, minpoly
2589  // check whether vars hava admissible names -> done earlier
2590  // now, create the names for new var
2591  for (j=1; j<=P; j++)
2592  {
2593    tmp[j] = "s("+string(j)+")";
2594  }
2595  // DName is defined earlier
2596  list NName = Name + DName + tmp;
2597  L[2] = NName;
2598  tmp = 0;
2599  // block ord (dp(N),dp);
2600  string s = "iv=";
2601  for (i=1; i<=Nnew-P; i++)
2602  {
2603    s = s+"1,";
2604  }
2605  s[size(s)]=";";
2606  execute(s);
2607  tmp[1] = "dp";  //string
2608  tmp[2] = iv;    //intvec
2609  Lord[1] = tmp;
2610  // continue with dp 1,1,1,1...
2611  tmp[1] = "dp";  //string
2612  s[size(s)] = ",";
2613  for (j=1; j<=P; j++)
2614  {
2615    s = s+"1,";
2616  }
2617  s[size(s)]=";";
2618  execute(s);
2619  kill s;
2620  kill NName;
2621  tmp[2]  = iv;
2622  Lord[2] = tmp;
2623  tmp[1]  = "C";
2624  iv      = 0;
2625  tmp[2]  = iv;
2626  Lord[3] = tmp;
2627  tmp     = 0;
2628  L[3]    = Lord;
2629  // we are done with the list. Now add a Plural part
2630  def @R2@ = ring(L);
2631  setring @R2@;
2632  matrix @D[Nnew][Nnew];
2633  for (i=1; i<=N; i++)
2634  {
2635    @D[i,N+i]=1;
2636  }
2637  def @R2 = nc_algebra(1,@D);
2638  setring @R2;
2639  kill @R2@;
2640  dbprint(ppl,"// -2-1- the ring @R2(_x,_Dx,_s) is ready");
2641  dbprint(ppl-1, @R2);
2642//  ideal MM = maxideal(1);
2643//  MM = 0,s,MM;
2644//  map R01 = @R, MM;
2645//  ideal K = R01(K);
2646  ideal F = imap(save,F);  // maybe ideal F = R01(I); ?
2647  ideal K = imap(@R,K);    // maybe ideal K = R01(I); ?
2648  poly f=1;
2649  for (j=1; j<=P; j++)
2650  {
2651    f = f*F[j];
2652  }
2653  K = K,f;       // to compute B (Bernstein-Sato ideal)
2654  //j=2;         // for example
2655  //K = K,F[j];  // to compute Bj (see "On the computation of Bernstein-Sato ideals"; Castro, Ucha)
2656  //K = K,F;     // to compute Bsigma (see "On the computation of Bernstein-Sato ideals"; Castro, Ucha)
2657  dbprint(ppl,"// -2-2- starting the elimination of _x,_Dx in @R2");
2658  dbprint(ppl-1, K);
2659  ideal M = engine(K,eng);
2660  ideal K2 = nselect(M,1..Nnew-P);
2661  kill K,M;
2662  dbprint(ppl,"// -2-3- _x,_Dx are eliminated in @R2");
2663  dbprint(ppl-1, K2);
2664  // the ring @R3 and factorize
2665  ring @R3 = 0,s(1..P),dp;
2666  dbprint(ppl,"// -3-1- the ring @R3(_s) is ready");
2667  ideal K3 = imap(@R2,K2);
2668  if (size(K3)==1)
2669  {
2670    poly p = K3[1];
2671    dbprint(ppl,"// -3-2- factorization");
2672    // Warning: now P is an integer
2673    list Q = factorize(p);         //with constants and multiplicities
2674    ideal bs; intvec m;
2675    for (i=2; i<=size(Q[1]); i++)  //we delete Q[1][1] and Q[2][1]
2676    {
2677      bs[i-1] = Q[1][i];
2678      m[i-1]  = Q[2][i];
2679    }
2680    //  "--------- Q-ideal factorizes into ---------";  list(bs,m);
2681    list BS = bs,m;
2682  }
2683  else
2684  {
2685    // conjecture: the Bernstein ideal is principal
2686    dbprint(ppl,"// -3-2- the Bernstein ideal is not principal");
2687    ideal BS = K3;
2688  }
2689  // create the ring @R4(_x,_Dx,_s) and put the result into it,
2690  // _x, _Dx,s;  ord "dp".
2691  // keep: N, i,j,s, tmp, RL
2692  setring save;
2693  Nnew = 2*N+P;
2694  // list RL = ringlist(save);  //is defined earlier
2695  kill Lord, tmp, iv;
2696  L = 0;
2697  list Lord, tmp;
2698  intvec iv;
2699  L[1] = RL[1];  //char
2700  L[4] = RL[4];  //char, minpoly
2701  // check whether vars hava admissible names -> done earlier
2702  // now, create the names for new var
2703  for (j=1; j<=P; j++)
2704  {
2705    tmp[j] = "s("+string(j)+")";
2706  }
2707  // DName is defined earlier
2708  list NName = Name + DName + tmp;
2709  L[2] = NName;
2710  tmp = 0;
2711  // dp ordering;
2712  string s = "iv=";
2713  for (i=1; i<=Nnew; i++)
2714  {
2715    s = s+"1,";
2716  }
2717  s[size(s)]=";";
2718  execute(s);
2719  kill s;
2720  kill NName;
2721  tmp[1] = "dp";  //string
2722  tmp[2] = iv;    //intvec
2723  Lord[1] = tmp;
2724  tmp[1]  = "C";
2725  iv      = 0;
2726  tmp[2]  = iv;
2727  Lord[2] = tmp;
2728  tmp     = 0;
2729  L[3]    = Lord;
2730  // we are done with the list. Now add a Plural part
2731  def @R4@ = ring(L);
2732  setring @R4@;
2733  matrix @D[Nnew][Nnew];
2734  for (i=1; i<=N; i++)
2735  {
2736    @D[i,N+i]=1;
2737  }
2738  def @R4 = nc_algebra(1,@D);
2739  setring @R4;
2740  kill @R4@;
2741  dbprint(ppl,"// -4-1- the ring @R4i(_x,_Dx,_s) is ready");
2742  dbprint(ppl-1, @R4);
2743  ideal K4 = imap(@R,K);
2744  option(redSB);
2745  dbprint(ppl,"// -4-2- the final cosmetic std");
2746  K4 = engine(K4,eng);  //std does the job too
2747  // total cleanup
2748  kill @R;
2749  kill @R2;
2750  def BS = imap(@R3,BS);
2751  export BS;
2752  kill @R3;
2753  ideal LD = K4;
2754  export LD;
2755  return(@R4);
2756}
2757example
2758{
2759  "EXAMPLE:"; echo = 2;
2760  ring r = 0,(x,y),Dp;
2761  ideal F = x,y,x+y;
2762  printlevel = 0;
2763  def A = annfsBMI(F);
2764  setring A;
2765  LD;
2766  BS;
2767}
2768
2769proc annfsOT(poly F, list #)
2770"USAGE:  annfsOT(f [,eng]);  f a poly, eng an optional int
2771RETURN:  ring
2772PURPOSE: compute the D-module structure of basering[1/f]*f^s,
2773@* according to the algorithm by Oaku and Takayama
2774NOTE:    activate the output ring with the @code{setring} command. In this ring,
2775@*       - the ideal LD (which is a Groebner basis) is the needed D-module structure,
2776@*         which is obtained by substituting the minimal integer root of a Bernstein
2777@*         polynomial into the s-parametric ideal;
2778@*       - the list BS contains roots with multiplicities of a Bernstein polynomial of f.
2779@*       If eng <>0, @code{std} is used for Groebner basis computations,
2780@*       otherwise, and by default @code{slimgb} is used.
2781@*       If printlevel=1, progress debug messages will be printed,
2782@*       if printlevel>=2, all the debug messages will be printed.
2783EXAMPLE: example annfsOT; shows examples
2784"
2785{
2786  int eng = 0;
2787  if ( size(#)>0 )
2788  {
2789    if ( typeof(#[1]) == "int" )
2790    {
2791      eng = int(#[1]);
2792    }
2793  }
2794  // returns a list with a ring and an ideal LD in it
2795  int ppl = printlevel-voice+2;
2796  //  printf("plevel :%s, voice: %s",printlevel,voice);
2797  def save = basering;
2798  int N = nvars(basering);
2799  int Nnew = 2*(N+2);
2800  int i,j;
2801  string s;
2802  list RL = ringlist(basering);
2803  list L, Lord;
2804  list tmp;
2805  intvec iv;
2806  L[1] = RL[1]; // char
2807  L[4] = RL[4]; // char, minpoly
2808  // check whether vars have admissible names
2809  list Name  = RL[2];
2810  list RName;
2811  RName[1] = "u";
2812  RName[2] = "v";
2813  RName[3] = "t";
2814  RName[4] = "Dt";
2815  for(i=1;i<=N;i++)
2816  {
2817    for(j=1; j<=size(RName);j++)
2818    {
2819      if (Name[i] == RName[j])
2820      {
2821        ERROR("Variable names should not include u,v,t,Dt");
2822      }
2823    }
2824  }
2825  // now, create the names for new vars
2826  tmp[1]     = "u";
2827  tmp[2]     = "v";
2828  list UName = tmp;
2829  list DName;
2830  for(i=1;i<=N;i++)
2831  {
2832    DName[i] = "D"+Name[i]; // concat
2833  }
2834  tmp    =  0;
2835  tmp[1] = "t";
2836  tmp[2] = "Dt";
2837  list NName = UName +  tmp + Name + DName;
2838  L[2]   = NName;
2839  tmp    = 0;
2840  // Name, Dname will be used further
2841  kill UName;
2842  kill NName;
2843  // block ord (a(1,1),dp);
2844  tmp[1]  = "a"; // string
2845  iv      = 1,1;
2846  tmp[2]  = iv; //intvec
2847  Lord[1] = tmp;
2848  // continue with dp 1,1,1,1...
2849  tmp[1]  = "dp"; // string
2850  s       = "iv=";
2851  for(i=1;i<=Nnew;i++)
2852  {
2853    s = s+"1,";
2854  }
2855  s[size(s)]= ";";
2856  execute(s);
2857  tmp[2]    = iv;
2858  Lord[2]   = tmp;
2859  tmp[1]    = "C";
2860  iv        = 0;
2861  tmp[2]    = iv;
2862  Lord[3]   = tmp;
2863  tmp       = 0;
2864  L[3]      = Lord;
2865  // we are done with the list
2866  def @R@ = ring(L);
2867  setring @R@;
2868  matrix @D[Nnew][Nnew];
2869  @D[3,4]=1;
2870  for(i=1; i<=N; i++)
2871  {
2872    @D[4+i,N+4+i]=1;
2873  }
2874  //  @D[N+3,2*(N+2)]=1; old t,Dt stuff
2875  //  L[5] = matrix(UpOneMatrix(Nnew));
2876  //  L[6] = @D;
2877  def @R = nc_algebra(1,@D);
2878  setring @R;
2879  kill @R@;
2880  dbprint(ppl,"// -1-1- the ring @R(u,v,t,Dt,_x,_Dx) is ready");
2881  dbprint(ppl-1, @R);
2882  // create the ideal I
2883  poly  F = imap(save,F);
2884  ideal I = u*F-t,u*v-1;
2885  poly p;
2886  for(i=1; i<=N; i++)
2887  {
2888    p = u*Dt; // u*Dt
2889    p = diff(F,var(4+i))*p;
2890    I = I, var(N+4+i) + p;
2891  }
2892  // -------- the ideal I is ready ----------
2893  dbprint(ppl,"// -1-2- starting the elimination of u,v in @R");
2894  dbprint(ppl-1, I);
2895  ideal J = engine(I,eng);
2896  ideal K = nselect(J,1..2);
2897  dbprint(ppl,"// -1-3- u,v are eliminated");
2898  dbprint(ppl-1, K);  // K is without u,v
2899  setring save;
2900  // ------------ new ring @R2 ------------------
2901  // without u,v and with the elim.ord for t,Dt
2902  // tensored with the K[s]
2903  // keep: N, i,j,s, tmp, RL
2904  Nnew = 2*N+2+1;
2905  //  list RL = ringlist(save); // is defined earlier
2906  L = 0;  //  kill L;
2907  kill Lord, tmp, iv, RName;
2908  list Lord, tmp;
2909  intvec iv;
2910  L[1] = RL[1]; L[4] = RL[4]; // char, minpoly
2911  // check whether vars have admissible names -> done earlier
2912  //  list Name  = RL[2];
2913  list RName;
2914  RName[1] = "t";
2915  RName[2] = "Dt";
2916  // now, create the names for new var (here, s only)
2917  tmp[1]     = "s";
2918  // DName is defined earlier
2919  list NName = RName + Name + DName + tmp;
2920  L[2]   = NName;
2921  tmp    = 0;
2922  // block ord (a(1,1),dp);
2923  tmp[1]  = "a";  iv = 1,1; tmp[2]  = iv; //intvec
2924  Lord[1] = tmp;
2925  // continue with a(1,1,1,1)...
2926  tmp[1]  = "dp"; s  = "iv=";
2927  for(i=1; i<= Nnew; i++)
2928  {
2929    s = s+"1,";
2930  }
2931  s[size(s)]= ";";  execute(s);
2932  kill NName;
2933  tmp[2]    = iv;
2934  Lord[2]   = tmp;
2935  // extra block for s
2936  // tmp[1] = "dp"; iv = 1;
2937  //  s[size(s)]= ",";  s = s + "1,1,1;";  execute(s);  tmp[2]    = iv;
2938  //  Lord[3]   = tmp;
2939  kill s;
2940  tmp[1]    = "C";   iv  = 0; tmp[2] = iv;
2941  Lord[3]   = tmp;   tmp = 0;
2942  L[3]      = Lord;
2943  // we are done with the list. Now, add a Plural part
2944  def @R2@ = ring(L);
2945  setring @R2@;
2946  matrix @D[Nnew][Nnew];
2947  @D[1,2] = 1;
2948  for(i=1; i<=N; i++)
2949  {
2950    @D[2+i,2+N+i] = 1;
2951  }
2952  def @R2 = nc_algebra(1,@D);
2953  setring @R2;
2954  kill @R2@;
2955  dbprint(ppl,"// -2-1- the ring @R2(t,Dt,_x,_Dx,s) is ready");
2956  dbprint(ppl-1, @R2);
2957  ideal MM = maxideal(1);
2958  MM = 0,0,MM;
2959  map R01 = @R, MM;
2960  ideal K = R01(K);
2961  //  ideal K = imap(@R,K); // names of vars are important!
2962  poly G = t*Dt+s+1; // s is a variable here
2963  K = NF(K,std(G)),G;
2964  // -------- the ideal K_(@R2) is ready ----------
2965  dbprint(ppl,"// -2-2- starting the elimination of t,Dt in @R2");
2966  dbprint(ppl-1, K);
2967  ideal M  = engine(K,eng);
2968  ideal K2 = nselect(M,1..2);
2969  dbprint(ppl,"// -2-3- t,Dt are eliminated");
2970  dbprint(ppl-1, K2);
2971  //  dbprint(ppl-1+1," -2-4- std of K2");
2972  //  option(redSB);  option(redTail);  K2 = std(K2);
2973  //  K2; // without t,Dt, and with s
2974  // -------- the ring @R3 ----------
2975  // _x, _Dx, s; elim.ord for _x,_Dx.
2976  // keep: N, i,j,s, tmp, RL
2977  setring save;
2978  Nnew = 2*N+1;
2979  //  list RL = ringlist(save); // is defined earlier
2980  //  kill L;
2981  kill Lord, tmp, iv, RName;
2982  list Lord, tmp;
2983  intvec iv;
2984  L[1] = RL[1]; L[4] = RL[4]; // char, minpoly
2985  // check whether vars have admissible names -> done earlier
2986  //  list Name  = RL[2];
2987  // now, create the names for new var (here, s only)
2988  tmp[1]     = "s";
2989  // DName is defined earlier
2990  list NName = Name + DName + tmp;
2991  L[2]   = NName;
2992  tmp    = 0;
2993  // block ord (a(1,1...),dp);
2994  string  s = "iv=";
2995  for(i=1; i<=Nnew-1; i++)
2996  {
2997    s = s+"1,";
2998  }
2999  s[size(s)]= ";";
3000  execute(s);
3001  tmp[1]  = "a"; // string
3002  tmp[2]  = iv; //intvec
3003  Lord[1] = tmp;
3004  // continue with dp 1,1,1,1...
3005  tmp[1]  = "dp"; // string
3006  s[size(s)]=","; s= s+"1;";
3007  execute(s);
3008  kill s;
3009  kill NName;
3010  tmp[2]    = iv;
3011  Lord[2]   = tmp;
3012  tmp[1]    = "C";  iv  = 0;  tmp[2] = iv;
3013  Lord[3]   = tmp;  tmp = 0;
3014  L[3]      = Lord;
3015  // we are done with the list. Now add a Plural part
3016  def @R3@ = ring(L);
3017  setring @R3@;
3018  matrix @D[Nnew][Nnew];
3019  for(i=1; i<=N; i++)
3020  {
3021    @D[i,N+i]=1;
3022  }
3023  def @R3 = nc_algebra(1,@D);
3024  setring @R3;
3025  kill @R3@;
3026  dbprint(ppl,"// -3-1- the ring @R3(_x,_Dx,s) is ready");
3027  dbprint(ppl-1, @R3);
3028  ideal MM = maxideal(1);
3029  MM = 0,0,MM;
3030  map R12 = @R2, MM;
3031  ideal K = R12(K2);
3032  poly  F = imap(save,F);
3033  K = K,F;
3034  dbprint(ppl,"// -3-2- starting the elimination of _x,_Dx in @R3");
3035  dbprint(ppl-1, K);
3036  ideal M = engine(K,eng);
3037  ideal K3 = nselect(M,1..Nnew-1);
3038  dbprint(ppl,"// -3-3-  _x,_Dx are eliminated in @R3");
3039  dbprint(ppl-1, K3);
3040  // the ring @R4  and the search for minimal negative int s
3041  ring @R4 = 0,(s),dp;
3042  dbprint(ppl,"// -4-1- the ring @R4 is ready");
3043  ideal K4 = imap(@R3,K3);
3044  poly p = K4[1];
3045  dbprint(ppl,"// -4-2- factorization");
3046////  ideal P = factorize(p,1);  // without constants and multiplicities
3047  list P = factorize(p);         // with constants and multiplicities
3048  ideal bs; intvec m;            // the Bernstein polynomial is monic, so we are not interested in constants
3049  for (i=2; i<=size(P[1]); i++)  // we delete P[1][1] and P[2][1]
3050  {
3051    bs[i-1] = P[1][i];
3052    m[i-1]  = P[2][i];
3053  }
3054  //  "------ b-function factorizes into ----------";  P;
3055////  int sP  = minIntRoot(P, 1);
3056  int sP = minIntRoot(bs,1);
3057  dbprint(ppl,"// -4-3- minimal integer root found");
3058  dbprint(ppl-1, sP);
3059  // convert factors to a list of their roots
3060  // assume all factors are linear
3061////  ideal BS = normalize(P);
3062////  BS = subst(BS,s,0);
3063////  BS = -BS;
3064  bs = normalize(bs);
3065  bs = subst(bs,s,0);
3066  bs = -bs;
3067  list BS = bs,m;
3068  // TODO: sort BS!
3069  // ------ substitute s found in the ideal ------
3070  // ------- going back to @R2 and substitute --------
3071  setring @R2;
3072  ideal K3 = subst(K2,s,sP);
3073  // create the ordinary Weyl algebra and put the result into it,
3074  // thus creating the ring @R5
3075  // keep: N, i,j,s, tmp, RL
3076  setring save;
3077  Nnew = 2*N;
3078  //  list RL = ringlist(save); // is defined earlier
3079  kill Lord, tmp, iv;
3080  L = 0;
3081  list Lord, tmp;
3082  intvec iv;
3083  L[1] = RL[1];   L[4] = RL[4]; // char, minpoly
3084  // check whether vars have admissible names -> done earlier
3085  //  list Name  = RL[2];
3086  // DName is defined earlier
3087  list NName = Name + DName;
3088  L[2]   = NName;
3089  // dp ordering;
3090  string   s       = "iv=";
3091  for(i=1;i<=Nnew;i++)
3092  {
3093    s = s+"1,";
3094  }
3095  s[size(s)]= ";";
3096  execute(s);
3097  tmp     = 0;
3098  tmp[1]  = "dp"; // string
3099  tmp[2]  = iv; //intvec
3100  Lord[1] = tmp;
3101  kill s;
3102  tmp[1]    = "C";
3103  iv        = 0;
3104  tmp[2]    = iv;
3105  Lord[2]   = tmp;
3106  tmp       = 0;
3107  L[3]      = Lord;
3108  // we are done with the list
3109  // Add: Plural part
3110  def @R5@ = ring(L);
3111  setring @R5@;
3112  matrix @D[Nnew][Nnew];
3113  for(i=1; i<=N; i++)
3114  {
3115    @D[i,N+i]=1;
3116  }
3117  def @R5 = nc_algebra(1,@D);
3118  setring @R5;
3119  kill @R5@;
3120  dbprint(ppl,"// -5-1- the ring @R5 is ready");
3121  dbprint(ppl-1, @R5);
3122  ideal K5 = imap(@R2,K3);
3123  option(redSB);
3124  dbprint(ppl,"// -5-2- the final cosmetic std");
3125  K5 = engine(K5,eng); // std does the job too
3126  // total cleanup
3127  kill @R;
3128  kill @R2;
3129  kill @R3;
3130////  ideal BS = imap(@R4,BS);
3131  list BS = imap(@R4,BS);
3132  export BS;
3133  ideal LD = K5;
3134  kill @R4;
3135  export LD;
3136  return(@R5);
3137}
3138example
3139{
3140  "EXAMPLE:"; echo = 2;
3141  ring r = 0,(x,y,z),Dp;
3142  poly F = x^2+y^3+z^5;
3143  printlevel = 0;
3144  def A  = annfsOT(F);
3145  setring A;
3146  LD;
3147  BS;
3148}
3149
3150
3151proc SannfsOT(poly F, list #)
3152"USAGE:  SannfsOT(f [,eng]);  f a poly, eng an optional int
3153RETURN:  ring
3154PURPOSE: compute the D-module structure of basering[1/f]*f^s, according to the
3155@* 1st step of the algorithm by Oaku and Takayama in the ring D[s]
3156NOTE:    activate the output ring with the @code{setring} command.
3157@*  In the output ring D[s], the ideal LD (which is NOT a Groebner basis)
3158@*  is the needed D-module structure.
3159@*  If eng <>0, @code{std} is used for Groebner basis computations,
3160@*  otherwise, and by default @code{slimgb} is used.
3161@*  If printlevel=1, progress debug messages will be printed,
3162@*  if printlevel>=2, all the debug messages will be printed.
3163EXAMPLE: example SannfsOT; shows examples
3164"
3165{
3166  int eng = 0;
3167  if ( size(#)>0 )
3168  {
3169    if ( typeof(#[1]) == "int" )
3170    {
3171      eng = int(#[1]);
3172    }
3173  }
3174  // returns a list with a ring and an ideal LD in it
3175  int ppl = printlevel-voice+2;
3176  //  printf("plevel :%s, voice: %s",printlevel,voice);
3177  def save = basering;
3178  int N = nvars(basering);
3179  int Nnew = 2*(N+2);
3180  int i,j;
3181  string s;
3182  list RL = ringlist(basering);
3183  list L, Lord;
3184  list tmp;
3185  intvec iv;
3186  L[1] = RL[1]; // char
3187  L[4] = RL[4]; // char, minpoly
3188  // check whether vars have admissible names
3189  list Name  = RL[2];
3190  list RName;
3191  RName[1] = "u";
3192  RName[2] = "v";
3193  RName[3] = "t";
3194  RName[4] = "Dt";
3195  for(i=1;i<=N;i++)
3196  {
3197    for(j=1; j<=size(RName);j++)
3198    {
3199      if (Name[i] == RName[j])
3200      {
3201        ERROR("Variable names should not include u,v,t,Dt");
3202      }
3203    }
3204  }
3205  // now, create the names for new vars
3206  tmp[1]     = "u";
3207  tmp[2]     = "v";
3208  list UName = tmp;
3209  list DName;
3210  for(i=1;i<=N;i++)
3211  {
3212    DName[i] = "D"+Name[i]; // concat
3213  }
3214  tmp    =  0;
3215  tmp[1] = "t";
3216  tmp[2] = "Dt";
3217  list NName = UName +  tmp + Name + DName;
3218  L[2]   = NName;
3219  tmp    = 0;
3220  // Name, Dname will be used further
3221  kill UName;
3222  kill NName;
3223  // block ord (a(1,1),dp);
3224  tmp[1]  = "a"; // string
3225  iv      = 1,1;
3226  tmp[2]  = iv; //intvec
3227  Lord[1] = tmp;
3228  // continue with dp 1,1,1,1...
3229  tmp[1]  = "dp"; // string
3230  s       = "iv=";
3231  for(i=1;i<=Nnew;i++)
3232  {
3233    s = s+"1,";
3234  }
3235  s[size(s)]= ";";
3236  execute(s);
3237  tmp[2]    = iv;
3238  Lord[2]   = tmp;
3239  tmp[1]    = "C";
3240  iv        = 0;
3241  tmp[2]    = iv;
3242  Lord[3]   = tmp;
3243  tmp       = 0;
3244  L[3]      = Lord;
3245  // we are done with the list
3246  def @R@ = ring(L);
3247  setring @R@;
3248  matrix @D[Nnew][Nnew];
3249  @D[3,4]=1;
3250  for(i=1; i<=N; i++)
3251  {
3252    @D[4+i,N+4+i]=1;
3253  }
3254  //  @D[N+3,2*(N+2)]=1; old t,Dt stuff
3255  //  L[5] = matrix(UpOneMatrix(Nnew));
3256  //  L[6] = @D;
3257  def @R =  nc_algebra(1,@D);
3258  setring @R;
3259  kill @R@;
3260  dbprint(ppl,"// -1-1- the ring @R(u,v,t,Dt,_x,_Dx) is ready");
3261  dbprint(ppl-1, @R);
3262  // create the ideal I
3263  poly  F = imap(save,F);
3264  ideal I = u*F-t,u*v-1;
3265  poly p;
3266  for(i=1; i<=N; i++)
3267  {
3268    p = u*Dt; // u*Dt
3269    p = diff(F,var(4+i))*p;
3270    I = I, var(N+4+i) + p;
3271  }
3272  // -------- the ideal I is ready ----------
3273  dbprint(ppl,"// -1-2- starting the elimination of u,v in @R");
3274  dbprint(ppl-1, I);
3275  ideal J = engine(I,eng);
3276  ideal K = nselect(J,1..2);
3277  dbprint(ppl,"// -1-3- u,v are eliminated");
3278  dbprint(ppl-1, K);  // K is without u,v
3279  setring save;
3280  // ------------ new ring @R2 ------------------
3281  // without u,v and with the elim.ord for t,Dt
3282  // tensored with the K[s]
3283  // keep: N, i,j,s, tmp, RL
3284  Nnew = 2*N+2+1;
3285  //  list RL = ringlist(save); // is defined earlier
3286  L = 0;  //  kill L;
3287  kill Lord, tmp, iv, RName;
3288  list Lord, tmp;
3289  intvec iv;
3290  L[1] = RL[1]; L[4] = RL[4]; // char, minpoly
3291  // check whether vars have admissible names -> done earlier
3292  //  list Name  = RL[2];
3293  list RName;
3294  RName[1] = "t";
3295  RName[2] = "Dt";
3296  // now, create the names for new var (here, s only)
3297  tmp[1]     = "s";
3298  // DName is defined earlier
3299  list NName = RName + Name + DName + tmp;
3300  L[2]   = NName;
3301  tmp    = 0;
3302  // block ord (a(1,1),dp);
3303  tmp[1]  = "a";  iv = 1,1; tmp[2]  = iv; //intvec
3304  Lord[1] = tmp;
3305  // continue with a(1,1,1,1)...
3306  tmp[1]  = "dp"; s  = "iv=";
3307  for(i=1; i<= Nnew; i++)
3308  {
3309    s = s+"1,";
3310  }
3311  s[size(s)]= ";";  execute(s);
3312  kill NName;
3313  tmp[2]    = iv;
3314  Lord[2]   = tmp;
3315  // extra block for s
3316  // tmp[1] = "dp"; iv = 1;
3317  //  s[size(s)]= ",";  s = s + "1,1,1;";  execute(s);  tmp[2]    = iv;
3318  //  Lord[3]   = tmp;
3319  kill s;
3320  tmp[1]    = "C";   iv  = 0; tmp[2] = iv;
3321  Lord[3]   = tmp;   tmp = 0;
3322  L[3]      = Lord;
3323  // we are done with the list. Now, add a Plural part
3324  def @R2@ = ring(L);
3325  setring @R2@;
3326  matrix @D[Nnew][Nnew];
3327  @D[1,2] = 1;
3328  for(i=1; i<=N; i++)
3329  {
3330    @D[2+i,2+N+i] = 1;
3331  }
3332  def @R2 = nc_algebra(1,@D);
3333  setring @R2;
3334  kill @R2@;
3335  dbprint(ppl,"// -2-1- the ring @R2(t,Dt,_x,_Dx,s) is ready");
3336  dbprint(ppl-1, @R2);
3337  ideal MM = maxideal(1);
3338  MM = 0,0,MM;
3339  map R01 = @R, MM;
3340  ideal K = R01(K);
3341  //  ideal K = imap(@R,K); // names of vars are important!
3342  poly G = t*Dt+s+1; // s is a variable here
3343  K = NF(K,std(G)),G;
3344  // -------- the ideal K_(@R2) is ready ----------
3345  dbprint(ppl,"// -2-2- starting the elimination of t,Dt in @R2");
3346  dbprint(ppl-1, K);
3347  ideal M  = engine(K,eng);
3348  ideal K2 = nselect(M,1..2);
3349  dbprint(ppl,"// -2-3- t,Dt are eliminated");
3350  dbprint(ppl-1, K2);
3351  K2 = engine(K2,eng);
3352  setring save;
3353  // ----------- the ring @R3 ------------
3354  // _x, _Dx,s;  elim.ord for _x,_Dx.
3355  // keep: N, i,j,s, tmp, RL
3356  Nnew = 2*N+1;
3357  kill Lord, tmp, iv, RName;
3358  list Lord, tmp;
3359  intvec iv;
3360  L[1] = RL[1];
3361  L[4] = RL[4];  // char, minpoly
3362  // check whether vars hava admissible names -> done earlier
3363  // now, create the names for new var
3364  tmp[1] = "s";
3365  // DName is defined earlier
3366  list NName = Name + DName + tmp;
3367  L[2] = NName;
3368  tmp = 0;
3369  // block ord (dp(N),dp);
3370  string s = "iv=";
3371  for (i=1; i<=Nnew-1; i++)
3372  {
3373    s = s+"1,";
3374  }
3375  s[size(s)]=";";
3376  execute(s);
3377  tmp[1] = "dp";  // string
3378  tmp[2] = iv;   // intvec
3379  Lord[1] = tmp;
3380  // continue with dp 1,1,1,1...
3381  tmp[1] = "dp";  // string
3382  s[size(s)] = ",";
3383  s = s+"1;";
3384  execute(s);
3385  kill s;
3386  kill NName;
3387  tmp[2]      = iv;
3388  Lord[2]     = tmp;
3389  tmp[1]      = "C";  iv  = 0;  tmp[2]=iv;
3390  Lord[3]     = tmp;  tmp = 0;
3391  L[3]        = Lord;
3392  // we are done with the list. Now add a Plural part
3393  def @R3@ = ring(L);
3394  setring @R3@;
3395  matrix @D[Nnew][Nnew];
3396  for (i=1; i<=N; i++)
3397  {
3398    @D[i,N+i]=1;
3399  }
3400  def @R3 = nc_algebra(1,@D);
3401  setring @R3;
3402  kill @R3@;
3403  dbprint(ppl,"// -3-1- the ring @R3(_x,_Dx,s) is ready");
3404  dbprint(ppl-1, @R3);
3405  ideal MM = maxideal(1);
3406  MM = 0,s,MM;
3407  map R01 = @R2, MM;
3408  ideal K2 = R01(K2);
3409  // total cleanup
3410  ideal LD = K2;
3411  // make leadcoeffs positive
3412  for (i=1; i<= ncols(LD); i++)
3413  {
3414    if (leadcoef(LD[i]) <0 )
3415    {
3416      LD[i] = -LD[i];
3417    }
3418  }
3419  export LD;
3420  kill @R;
3421  kill @R2;
3422  return(@R3);
3423}
3424example
3425{
3426  "EXAMPLE:"; echo = 2;
3427  ring r = 0,(x,y,z),Dp;
3428  poly F = x^3+y^3+z^3;
3429  printlevel = 0;
3430  def A  = SannfsOT(F);
3431  setring A;
3432  LD;
3433}
3434
3435proc SannfsBM(poly F, list #)
3436"USAGE:  SannfsBM(f [,eng]);  f a poly, eng an optional int
3437RETURN:  ring
3438PURPOSE: compute the D-module structure of basering[1/f]*f^s, according to the
3439@* 1st step of the algorithm by Briancon and Maisonobe in the ring D[s].
3440NOTE:  activate the output ring with the @code{setring} command.
3441@*   In the output ring D[s], the ideal LD (which is NOT a Groebner basis) is
3442@*   the needed D-module structure.
3443@*   If eng <>0, @code{std} is used for Groebner basis computations,
3444@*   otherwise, and by default @code{slimgb} is used.
3445@*   If printlevel=1, progress debug messages will be printed,
3446@*   if printlevel>=2, all the debug messages will be printed.
3447EXAMPLE: example SannfsBM; shows examples
3448"
3449{
3450  int eng = 0;
3451  if ( size(#)>0 )
3452  {
3453    if ( typeof(#[1]) == "int" )
3454    {
3455      eng = int(#[1]);
3456    }
3457  }
3458  // returns a list with a ring and an ideal LD in it
3459  int ppl = printlevel-voice+2;
3460  //  printf("plevel :%s, voice: %s",printlevel,voice);
3461  def save = basering;
3462  int N = nvars(basering);
3463  int Nnew = 2*N+2;
3464  int i,j;
3465  string s;
3466  list RL = ringlist(basering);
3467  list L, Lord;
3468  list tmp;
3469  intvec iv;
3470  L[1] = RL[1]; // char
3471  L[4] = RL[4]; // char, minpoly
3472  // check whether vars have admissible names
3473  list Name  = RL[2];
3474  list RName;
3475  RName[1] = "t";
3476  RName[2] = "s";
3477  for(i=1;i<=N;i++)
3478  {
3479    for(j=1; j<=size(RName);j++)
3480    {
3481      if (Name[i] == RName[j])
3482      {
3483        ERROR("Variable names should not include t,s");
3484      }
3485    }
3486  }
3487  // now, create the names for new vars
3488  list DName;
3489  for(i=1;i<=N;i++)
3490  {
3491    DName[i] = "D"+Name[i]; // concat
3492  }
3493  tmp[1] = "t";
3494  tmp[2] = "s";
3495  list NName = tmp + Name + DName;
3496  L[2]   = NName;
3497  // Name, Dname will be used further
3498  kill NName;
3499  // block ord (lp(2),dp);
3500  tmp[1]  = "lp"; // string
3501  iv      = 1,1;
3502  tmp[2]  = iv; //intvec
3503  Lord[1] = tmp;
3504  // continue with dp 1,1,1,1...
3505  tmp[1]  = "dp"; // string
3506  s       = "iv=";
3507  for(i=1;i<=Nnew;i++)
3508  {
3509    s = s+"1,";
3510  }
3511  s[size(s)]= ";";
3512  execute(s);
3513  kill s;
3514  tmp[2]    = iv;
3515  Lord[2]   = tmp;
3516  tmp[1]    = "C";
3517  iv        = 0;
3518  tmp[2]    = iv;
3519  Lord[3]   = tmp;
3520  tmp       = 0;
3521  L[3]      = Lord;
3522  // we are done with the list
3523  def @R@ = ring(L);
3524  setring @R@;
3525  matrix @D[Nnew][Nnew];
3526  @D[1,2]=t;
3527  for(i=1; i<=N; i++)
3528  {
3529    @D[2+i,N+2+i]=1;
3530  }
3531  //  L[5] = matrix(UpOneMatrix(Nnew));
3532  //  L[6] = @D;
3533  def @R = nc_algebra(1,@D);
3534  setring @R;
3535  kill @R@;
3536  dbprint(ppl,"// -1-1- the ring @R(t,s,_x,_Dx) is ready");
3537  dbprint(ppl-1, @R);
3538  // create the ideal I
3539  poly  F = imap(save,F);
3540  ideal I = t*F+s;
3541  poly p;
3542  for(i=1; i<=N; i++)
3543  {
3544    p = t; // t
3545    p = diff(F,var(2+i))*p;
3546    I = I, var(N+2+i) + p;
3547  }
3548  // -------- the ideal I is ready ----------
3549  dbprint(ppl,"// -1-2- starting the elimination of t in @R");
3550  dbprint(ppl-1, I);
3551  ideal J = engine(I,eng);
3552  ideal K = nselect(J,1);
3553  dbprint(ppl,"// -1-3- t is eliminated");
3554  dbprint(ppl-1, K);  // K is without t
3555  K = engine(K,eng);  // std does the job too
3556  // now, we must change the ordering
3557  // and create a ring without t, Dt
3558  //  setring S;
3559  // ----------- the ring @R3 ------------
3560  // _x, _Dx,s;  elim.ord for _x,_Dx.
3561  // keep: N, i,j,s, tmp, RL
3562  Nnew = 2*N+1;
3563  kill Lord, tmp, iv, RName;
3564  list Lord, tmp;
3565  intvec iv;
3566  list L=imap(save,L);
3567  list RL=imap(save,RL);
3568  L[1] = RL[1];
3569  L[4] = RL[4];  // char, minpoly
3570  // check whether vars hava admissible names -> done earlier
3571  // now, create the names for new var
3572  tmp[1] = "s";
3573  // DName is defined earlier
3574  list NName = Name + DName + tmp;
3575  L[2] = NName;
3576  tmp = 0;
3577  // block ord (dp(N),dp);
3578  string s = "iv=";
3579  for (i=1; i<=Nnew-1; i++)
3580  {
3581    s = s+"1,";
3582  }
3583  s[size(s)]=";";
3584  execute(s);
3585  tmp[1] = "dp";  // string
3586  tmp[2] = iv;   // intvec
3587  Lord[1] = tmp;
3588  // continue with dp 1,1,1,1...
3589  tmp[1] = "dp";  // string
3590  s[size(s)] = ",";
3591  s = s+"1;";
3592  execute(s);
3593  kill s;
3594  kill NName;
3595  tmp[2]      = iv;
3596  Lord[2]     = tmp;
3597  tmp[1]      = "C";  iv  = 0;  tmp[2]=iv;
3598  Lord[3]     = tmp;  tmp = 0;
3599  L[3]        = Lord;
3600  // we are done with the list. Now add a Plural part
3601  def @R2@ = ring(L);
3602  setring @R2@;
3603  matrix @D[Nnew][Nnew];
3604  for (i=1; i<=N; i++)
3605  {
3606    @D[i,N+i]=1;
3607  }
3608  def @R2 = nc_algebra(1,@D);
3609  setring @R2;
3610  kill @R2@;
3611  dbprint(ppl,"//  -2-1- the ring @R2(_x,_Dx,s) is ready");
3612  dbprint(ppl-1, @R2);
3613  ideal MM = maxideal(1);
3614  MM = 0,s,MM;
3615  map R01 = @R, MM;
3616  ideal K = R01(K);
3617  // total cleanup
3618  ideal LD = K;
3619  // make leadcoeffs positive
3620  for (i=1; i<= ncols(LD); i++)
3621  {
3622    if (leadcoef(LD[i]) <0 )
3623    {
3624      LD[i] = -LD[i];
3625    }
3626  }
3627  export LD;
3628  kill @R;
3629  return(@R2);
3630}
3631example
3632{
3633  "EXAMPLE:"; echo = 2;
3634  ring r = 0,(x,y,z),Dp;
3635  poly F = x^3+y^3+z^3;
3636  printlevel = 0;
3637  def A = SannfsBM(F);
3638  setring A;
3639  LD;
3640}
3641
3642static proc safeVarName (string s, list #)
3643{
3644  string S;
3645  int cv = 1;
3646  if (size(#)>1)
3647  {
3648    if (#[1]=="v") { cv = 0; S = varstr(basering); }
3649    if (#[1]=="c") { cv = 0; S = charstr(basering); }
3650  }
3651  if (cv) { S = charstr(basering) + "," + varstr(basering); }
3652  S = "," + S + ",";
3653  s = "," + s + ",";
3654  while (find(S,s) <> 0)
3655  {
3656    s[1] = "@";
3657    s = "," + s;
3658  }
3659  s = s[2..size(s)-1];
3660  return(s)
3661}
3662
3663proc SannfsBFCT(poly F, list #)
3664"USAGE:  SannfsBFCT(f [,a,b,c]);  f a poly, a,b,c optional ints
3665RETURN:  ring
3666PURPOSE: compute a Groebner basis either of Ann(f^s)+<f> or of
3667@*       Ann(f^s)+<f,f_1,...,f_n> in D[s]
3668NOTE:    Activate the output ring with the @code{setring} command.
3669@*  This procedure, unlike SannfsBM, returns the ring D[s] with an anti-
3670@*  elimination ordering for s.
3671@*  The output ring contains an ideal @code{LD}, being a Groebner basis
3672@*  either of  Ann(f^s)+<f>, if a=0 (and by default), or of
3673@*  Ann(f^s)+<f,f_1,...,f_n>, otherwise.
3674@*  Here, f_i stands for the i-th  partial derivative of f.
3675@*  If b<>0, @code{std} is used for Groebner basis computations,
3676@*  otherwise, and by default @code{slimgb} is used.
3677@*  If c<>0, @code{std} is used for Groebner basis computations of
3678@*  ideals <I+J> when I is already a Groebner basis of <I>.
3679@*  Otherwise, and by default the engine determined by the switch b is
3680@*  used. Note that in the case c<>0, the choice for b will be
3681@*  overwritten only for the types of ideals mentioned above.
3682@*  This means that if b<>0, specifying c has no effect.
3683DISPLAY: If printlevel=1, progress debug messages will be printed,
3684@*       if printlevel>=2, all the debug messages will be printed.
3685EXAMPLE: example SannfsBFCT; shows examples
3686"
3687{
3688  int addPD,eng,stdsum;
3689  if (size(#)>0)
3690  {
3691    if (typeof(#[1])=="int" || typeof(#[1])=="number")
3692    {
3693      addPD = int(#[1]);
3694    }
3695    if (size(#)>1)
3696    {
3697      if (typeof(#[2])=="int" || typeof(#[2])=="number")
3698      {
3699        eng = int(#[2]);
3700      }
3701      if (size(#)>2)
3702      {
3703        if (typeof(#[3])=="int" || typeof(#[3])=="number")
3704        {
3705          stdsum = int(#[3]);
3706        }
3707      }
3708    }
3709  }
3710  int ppl = printlevel-voice+2;
3711  def save = basering;
3712  int N = nvars(save);
3713  intvec optSave = option(get);
3714  int i,j;
3715  list RL = ringlist(save);
3716  // ----- step 1: compute syzigies
3717  intvec iv;
3718  list L,Lord;
3719  iv = 1:N; Lord[1] = list("dp",iv);
3720  iv = 0;   Lord[2] = list("C",iv);
3721  L = RL;
3722  L[3] = Lord;
3723  def @RM = ring(L);
3724  kill L,Lord;
3725  setring @RM;
3726  option(redSB);
3727  option(redTail);
3728  def RM = makeModElimRing(@RM);
3729  setring RM;
3730  poly F = imap(save,F);
3731  ideal J = jacob(F);
3732  J = F,J;
3733  dbprint(ppl,"// -1-1- Starting the computation of syz(F,_Dx(F))");
3734  dbprint(ppl-1, J);
3735  module M = syz(J);
3736  dbprint(ppl,"// -1-2- The module syz(F,_Dx(F)) has been computed");
3737  dbprint(ppl-1, M);
3738  dbprint(ppl,"// -1-3- Starting GB computation of syz(F,_Dx(F))");
3739  M = engine(M,eng);
3740  dbprint(ppl,"// -1-4- GB computation finished");
3741  dbprint(ppl-1, M);
3742  // ----- step 2: compute part of Ann(F^s)
3743  setring save;
3744  option(set,optSave);
3745  module M = imap(RM,M);
3746  kill optSave,RM;
3747  // ----- create D[s]
3748  int Nnew = 2*N+1;
3749  list L, Lord;
3750  // ----- keep char, minpoly
3751  L[1] = RL[1];
3752  L[4] = RL[4];
3753  // ----- create names for new vars
3754  list Name  = RL[2];
3755  string newVar@s = safeVarName("s");
3756  if (newVar@s[1] == "@")
3757  {
3758    print("Name s already assigned to parameter/ringvar.");
3759    print("Using " + newVar@s + " instead.")
3760  }
3761  list DName;
3762  for (i=1; i<=N; i++)
3763  {
3764    DName[i] = safeVarName("D" + Name[i]);
3765  }
3766  L[2] = list(newVar@s) + Name + DName;
3767  // ----- create ordering
3768  // --- anti-elimination ordering for s
3769  iv = 1;       Lord[1] = list("dp",iv);
3770  iv = 1:(2*N); Lord[2] = list("dp",iv);
3771  iv = 0;       Lord[3] = list("C",iv);
3772  L[3] = Lord;
3773  // ----- create commutative ring
3774  def @Ds = ring(L);
3775  kill L,Lord;
3776  setring @Ds;
3777  // ----- create nc relations
3778   matrix Drel[Nnew][Nnew];
3779  for (i=1; i<=N; i++)
3780  {
3781    Drel[i+1,N+1+i] = 1;
3782  }
3783  def Ds = nc_algebra(1,Drel);
3784  setring Ds;
3785  kill @Ds;
3786  dbprint(ppl,"// -2-1- The ring D[s] is ready");
3787  dbprint(ppl-1, Ds);
3788  matrix M = imap(save,M);
3789  vector v = var(1)*gen(1);
3790  for (i=1; i<=N; i++)
3791  {
3792    v = v + var(i+1+N)*gen(i+1); //[s,_Dx]
3793  }
3794  ideal J = transpose(M)*v;
3795  kill M,v;
3796  dbprint(ppl,"// -2-2- Compute part of Ann(F^s)");
3797  dbprint(ppl-1, J);
3798  J = engine(J,eng);
3799  dbprint(ppl,"// -2-3- GB computation finished");
3800  dbprint(ppl-1, J);
3801  // ----- step 3: the full annihilator
3802  // ----- create D<t,s>
3803  setring save;
3804  Nnew = 2*N+2;
3805  list L, Lord;
3806  // ----- keep char, minpoly
3807  L[1] = RL[1];
3808  L[4] = RL[4];
3809  // ----- create vars
3810  string newVar@t = safeVarName("t");
3811  L[2] = list(newVar@t,newVar@s) + DName + Name;
3812  // ----- create ordering for elimination of t
3813  // block ord (lp(2),dp);
3814  iv = 1,1;    Lord[1] = list("lp",iv);
3815  iv = 1:Nnew; Lord[2] = list("dp",iv);
3816  iv = 0;      Lord[3] = list("C",iv);
3817  L[3] = Lord;
3818  def @Dts = ring(L);
3819  kill RL,L,Lord,Name,DName,newVar@s,newVar@t;
3820  setring @Dts;
3821  // ----- create nc relations
3822  matrix Drel[Nnew][Nnew];
3823  Drel[1,2] = var(1);
3824  for(i=1; i<=N; i++)
3825  {
3826    Drel[2+i,N+2+i]=-1;
3827  }
3828  def Dts = nc_algebra(1,Drel);
3829  setring Dts;
3830  kill @Dts;
3831  dbprint(ppl,"// -3-1- The ring D<t,s> is ready");
3832  dbprint(ppl-1, Dts);
3833  // ----- create the ideal I following BM
3834  poly  F = imap(save,F);
3835  ideal I = var(1)*F + var(2); // = t*F + s
3836  poly p;
3837  for(i=1; i<=N; i++)
3838  {
3839    p = var(1)*diff(F,var(N+2+i)) + var(2+i); // = t*F_i + D_i
3840    I[i+1] = p;
3841  }
3842  // ----- add already computed part to it
3843  ideal MM = var(2);      // s
3844  for (i=1; i<=N; i++)
3845  {
3846    MM[1+i] = var(2+N+i); // _x
3847    MM[1+N+i] = var(2+i); // _Dx
3848  }
3849  map Ds2Dts = Ds,MM;
3850  ideal J = Ds2Dts(J);
3851  attrib(J,"isSB",1);
3852  kill MM,Ds2Dts;
3853  // ----- start the elimination
3854  dbprint(ppl,"// -3-2- Starting the elimination of t in D<t,s>");
3855  dbprint(ppl-1, I);
3856  if (stdsum || eng <> 0)
3857  {
3858    I = std(J,I);
3859  }
3860  else
3861  {
3862    I = J,I;
3863    I = engine(I,eng);
3864  }
3865  kill J;
3866  I = nselect(I,1);
3867  dbprint(ppl,"// -3-3- t is eliminated");
3868  dbprint(ppl-1, I);  // I is without t
3869  // ----- step 4: add F
3870  // ----- back to D[s]
3871  setring Ds;
3872  ideal MM = 0,var(1);      // 0,s
3873  for (i=1; i<=N; i++)
3874  {
3875    MM[2+i]   = var(1+N+i); // _Dx
3876    MM[2+N+i] = var(1+i);   // _x
3877  }
3878  map Dts2Ds = Dts, MM;
3879  ideal LD = Dts2Ds(I);
3880  kill J,Dts,Dts2Ds,MM;
3881  dbprint(ppl,"// -4-1- Starting cosmetic Groebner computation");
3882  LD = engine(LD,eng);
3883  dbprint(ppl,"// -4-2- Finished cosmetic Groebner computation");
3884  dbprint(ppl-1, LD);
3885  // ----- use reduction trick as Macaulay2 does: compute b(s)/(s+1) by adding all partial derivations also
3886  ideal J;
3887  if (addPD)
3888  {
3889    setring @RM;
3890    poly F = imap(save,F);
3891    ideal J = jacob(F);
3892    J = F,J;
3893    dbprint(ppl,"// -4-2-1- Start GB computation <f, f_i>");
3894    J = engine(J,eng);
3895    dbprint(ppl,"// -4-2-2- Finished GB computation <f, f_i>");
3896    dbprint(ppl-1, J);
3897    setring Ds;
3898    J = imap(@RM,J);
3899    attrib(J,"isSB",1);
3900    dbprint(ppl,"// -4-3- Start GB computations for Ann f^s + <f, f_i>");
3901  }
3902  else
3903  {
3904    J = imap(save,F);
3905    dbprint(ppl,"// -4-3- Start GB computations for Ann f^s + <f>");
3906  }
3907  kill @RM;
3908  // ----- the really hard part
3909  if (stdsum || eng <> 0)
3910  {
3911    LD = std(LD,J);
3912  }
3913  else
3914  {
3915    LD = LD,J;
3916    LD = engine(LD,eng);
3917  }
3918  if (addPD) { dbprint(ppl,"// -4-4- Finished GB computations for Ann f^s + <f, f_i>"); }
3919  else       { dbprint(ppl,"// -4-4- Finished GB computations for Ann f^s + <f>"); }
3920  dbprint(ppl-1, LD);
3921  export LD;
3922  return(Ds);
3923}
3924example
3925{
3926  "EXAMPLE:"; echo = 2;
3927  ring r = 0,(x,y,z,w),Dp;
3928  poly F = x^3+y^3+z^3*w;
3929  // compute Ann(F^s)+<F> using slimgb only
3930  def A = SannfsBFCT(F);
3931  setring A; A;
3932  LD;
3933  // the Bernstein-Sato poly of F:
3934  vec2poly(pIntersect(s,LD));
3935  // a fancier example:
3936  def R = reiffen(4,5); setring R;
3937  RC; // the Reiffen curve in 4,5
3938  // compute Ann(RC^s)+<RC,diff(RC,x),diff(RC,y)>
3939  // using std for GB computations of ideals <I+J>
3940  // where I is already a GB of <I>
3941  // and slimgb for other ideals
3942  def B = SannfsBFCT(RC,1,0,1);
3943  setring B;
3944  // the Bernstein-Sato poly of RC:
3945  (s-1)*vec2poly(pIntersect(s,LD));
3946}
3947
3948
3949proc SannfsBFCTstd(poly F, list #)
3950"USAGE:  SannfsBFCTstd(f [,eng]);  f a poly, eng an optional int
3951RETURN:  ring
3952PURPOSE: compute Ann f^s and Groebner basis of Ann f^s+f in D[s]
3953NOTE:    activate the output ring with the @code{setring} command.
3954@*    This procedure, unlike SannfsBM, returns a ring with the degrevlex
3955@*    ordering in all variables.
3956@*    In the ring D[s], the ideal LD (which IS a Groebner basis) is the needed ideal.
3957@*    In this procedure @code{std} is used for Groebner basis computations.
3958DISPLAY: If printlevel=1, progress debug messages will be printed,
3959@*       if printlevel>=2, all the debug messages will be printed.
3960EXAMPLE: example SannfsBFCTstd; shows examples
3961"
3962{
3963  // DEBUG INFO: ordering on the output ring = dp,
3964  // use std(K,F); for reusing the std property of K
3965
3966  int eng = 0;
3967  if ( size(#)>0 )
3968  {
3969    if ( typeof(#[1]) == "int" )
3970    {
3971      eng = int(#[1]);
3972    }
3973  }
3974  // returns a list with a ring and an ideal LD in it
3975  int ppl = printlevel-voice+2;
3976  //  printf("plevel :%s, voice: %s",printlevel,voice);
3977  def save = basering;
3978  int N = nvars(basering);
3979  int Nnew = 2*N+2;
3980  int i,j;
3981  string s;
3982  list RL = ringlist(basering);
3983  list L, Lord;
3984  list tmp;
3985  intvec iv;
3986  L[1] = RL[1]; // char
3987  L[4] = RL[4]; // char, minpoly
3988  // check whether vars have admissible names
3989  list Name  = RL[2];
3990  list RName;
3991  RName[1] = "@t";
3992  RName[2] = "@s";
3993  for(i=1;i<=N;i++)
3994  {
3995    for(j=1; j<=size(RName);j++)
3996    {
3997      if (Name[i] == RName[j])
3998      {
3999        ERROR("Variable names should not include @t,@s");
4000      }
4001    }
4002  }
4003  // now, create the names for new vars
4004  list DName;
4005  for(i=1;i<=N;i++)
4006  {
4007    DName[i] = "D"+Name[i]; // concat
4008  }
4009  tmp[1] = "t";
4010  tmp[2] = "s";
4011  list NName = tmp + DName + Name ;
4012  L[2]   = NName;
4013  // Name, Dname will be used further
4014  kill NName;
4015  // block ord (lp(2),dp);
4016  tmp[1]  = "lp"; // string
4017  iv      = 1,1;
4018  tmp[2]  = iv; //intvec
4019  Lord[1] = tmp;
4020  // continue with dp 1,1,1,1...
4021  tmp[1]  = "dp"; // string
4022  s       = "iv=";
4023  for(i=1;i<=Nnew;i++)
4024  {
4025    s = s+"1,";
4026  }
4027  s[size(s)]= ";";
4028  execute(s);
4029  kill s;
4030  tmp[2]    = iv;
4031  Lord[2]   = tmp;
4032  tmp[1]    = "C";
4033  iv        = 0;
4034  tmp[2]    = iv;
4035  Lord[3]   = tmp;
4036  tmp       = 0;
4037  L[3]      = Lord;
4038  // we are done with the list
4039  def @R@ = ring(L);
4040  setring @R@;
4041  matrix @D[Nnew][Nnew];
4042  @D[1,2]=t;
4043  for(i=1; i<=N; i++)
4044  {
4045    @D[2+i,N+2+i]=-1;
4046  }
4047  //  L[5] = matrix(UpOneMatrix(Nnew));
4048  //  L[6] = @D;
4049  def @R = nc_algebra(1,@D);
4050  setring @R;
4051  kill @R@;
4052  dbprint(ppl,"// -1-1- the ring @R(t,s,_Dx,_x) is ready");
4053  dbprint(ppl-1, @R);
4054  // create the ideal I
4055  poly  F = imap(save,F);
4056  ideal I = t*F+s;
4057  poly p;
4058  for(i=1; i<=N; i++)
4059  {
4060    p = t; // t
4061    p = diff(F,var(N+2+i))*p;
4062    I = I, var(2+i) + p;
4063  }
4064  // -------- the ideal I is ready ----------
4065  dbprint(ppl,"// -1-2- starting the elimination of t in @R");
4066  dbprint(ppl-1, I);
4067  ideal J = engine(I,eng);
4068  ideal K = nselect(J,1);
4069  dbprint(ppl,"// -1-3- t is eliminated");
4070  dbprint(ppl-1, K);  // K is without t
4071  K = engine(K,eng);  // std does the job too
4072  // now, we must change the ordering
4073  // and create a ring without t
4074  //  setring S;
4075  // ----------- the ring @R3 ------------
4076  // _Dx,_x,s;  +fast ord !
4077  // keep: N, i,j,s, tmp, RL
4078  Nnew = 2*N+1;
4079  kill Lord, tmp, iv, RName;
4080  list Lord, tmp;
4081  intvec iv;
4082  list L=imap(save,L);
4083  list RL=imap(save,RL);
4084  L[1] = RL[1];
4085  L[4] = RL[4];  // char, minpoly
4086  // check whether vars hava admissible names -> done earlier
4087  // now, create the names for new var
4088  tmp[1] = "s";
4089  // DName is defined earlier
4090  list NName = DName + Name + tmp;
4091  L[2] = NName;
4092  tmp = 0;
4093  // just dp
4094  // block ord (dp(N),dp);
4095  string s = "iv=";
4096  for (i=1; i<=Nnew; i++)
4097  {
4098    s = s+"1,";
4099  }
4100  s[size(s)]=";";
4101  execute(s);
4102  tmp[1] = "dp";  // string
4103  tmp[2] = iv;   // intvec
4104  Lord[1] = tmp;
4105  kill s;
4106  kill NName;
4107  tmp[1]      = "C";
4108  Lord[2]     = tmp;  tmp = 0;
4109  L[3]        = Lord;
4110  // we are done with the list. Now add a Plural part
4111  def @R2@ = ring(L);
4112  setring @R2@;
4113  matrix @D[Nnew][Nnew];
4114  for (i=1; i<=N; i++)
4115  {
4116    @D[i,N+i]=-1;
4117  }
4118  def @R2 = nc_algebra(1,@D);
4119  setring @R2;
4120  kill @R2@;
4121  dbprint(ppl,"//  -2-1- the ring @R2(_Dx,_x,s) is ready");
4122  dbprint(ppl-1, @R2);
4123  ideal MM = maxideal(1);
4124  MM = 0,s,MM;
4125  map R01 = @R, MM;
4126  ideal K = R01(K);
4127  // total cleanup
4128  poly F = imap(save, F);
4129  //  ideal LD = K,F;
4130  dbprint(ppl,"//  -2-2- start GB computations for Ann f^s + f");
4131  //  dbprint(ppl-1, LD);
4132  ideal LD = std(K,F);
4133  //  LD = engine(LD,eng);
4134  dbprint(ppl,"//  -2-3- finished GB computations for Ann f^s + f");
4135  dbprint(ppl-1, LD);
4136  // make leadcoeffs positive
4137  for (i=1; i<= ncols(LD); i++)
4138  {
4139    if (leadcoef(LD[i]) <0 )
4140    {
4141      LD[i] = -LD[i];
4142    }
4143  }
4144  export LD;
4145  kill @R;
4146  return(@R2);
4147}
4148example
4149{
4150  "EXAMPLE:"; echo = 2;
4151  ring r = 0,(x,y,z,w),Dp;
4152  poly F = x^3+y^3+z^3*w;
4153  printlevel = 0;
4154  def A = SannfsBFCT(F); setring A;
4155  intvec v = 1,2,3,4,5,6,7,8;
4156  // are there polynomials, depending on s only?
4157  nselect(LD,v);
4158  // a fancier example:
4159  def R = reiffen(4,5); setring R;
4160  v = 1,2,3,4;
4161  RC; // the Reiffen curve in 4,5
4162  def B = SannfsBFCT(RC);
4163  setring B;
4164  // Are there polynomials, depending on s only?
4165  nselect(LD,v);
4166  // It is not the case. Are there leading monomials in s only?
4167  nselect(lead(LD),v);
4168}
4169
4170// use a finer ordering
4171
4172proc SannfsLOT(poly F, list #)
4173"USAGE:  SannfsLOT(f [,eng]);  f a poly, eng an optional int
4174RETURN:  ring
4175PURPOSE: compute the D-module structure of basering[1/f]*f^s, according to the
4176@* Levandovskyy's modification of the algorithm by Oaku and Takayama in D[s]
4177NOTE:    activate the output ring with the @code{setring} command.
4178@*    In the ring D[s], the ideal LD (which is NOT a Groebner basis) is
4179@*    the needed D-module structure.
4180@*    If eng <>0, @code{std} is used for Groebner basis computations,
4181@*    otherwise, and by default @code{slimgb} is used.
4182@*    If printlevel=1, progress debug messages will be printed,
4183@*    if printlevel>=2, all the debug messages will be printed.
4184EXAMPLE: example SannfsLOT; shows examples
4185"
4186{
4187  int eng = 0;
4188  if ( size(#)>0 )
4189  {
4190    if ( typeof(#[1]) == "int" )
4191    {
4192      eng = int(#[1]);
4193    }
4194  }
4195  // returns a list with a ring and an ideal LD in it
4196  int ppl = printlevel-voice+2;
4197  //  printf("plevel :%s, voice: %s",printlevel,voice);
4198  def save = basering;
4199  int N = nvars(basering);
4200  //  int Nnew = 2*(N+2);
4201  int Nnew = 2*(N+1)+1; //removed u,v; added s
4202  int i,j;
4203  string s;
4204  list RL = ringlist(basering);
4205  list L, Lord;
4206  list tmp;
4207  intvec iv;
4208  L[1] = RL[1]; // char
4209  L[4] = RL[4]; // char, minpoly
4210  // check whether vars have admissible names
4211  list Name  = RL[2];
4212  list RName;
4213//   RName[1] = "u";
4214//   RName[2] = "v";
4215  RName[1] = "t";
4216  RName[2] = "Dt";
4217  for(i=1;i<=N;i++)
4218  {
4219    for(j=1; j<=size(RName);j++)
4220    {
4221      if (Name[i] == RName[j])
4222      {
4223        ERROR("Variable names should not include t,Dt");
4224      }
4225    }
4226  }
4227  // now, create the names for new vars
4228//   tmp[1]     = "u";
4229//   tmp[2]     = "v";
4230//   list UName = tmp;
4231  list DName;
4232  for(i=1;i<=N;i++)
4233  {
4234    DName[i] = "D"+Name[i]; // concat
4235  }
4236  tmp    =  0;
4237  tmp[1] = "t";
4238  tmp[2] = "Dt";
4239  list SName ; SName[1] = "s";
4240  //  list NName = tmp + Name + DName + SName;
4241  list NName = tmp + SName + Name + DName;
4242  L[2]   = NName;
4243  tmp    = 0;
4244  // Name, Dname will be used further
4245  //  kill UName;
4246  kill NName;
4247  // block ord (a(1,1),dp);
4248  tmp[1]  = "a"; // string
4249  iv      = 1,1;
4250  tmp[2]  = iv; //intvec
4251  Lord[1] = tmp;
4252  // continue with a(0,0,1)
4253  tmp[1]  = "a"; // string
4254  iv      = 0,0,1;
4255  tmp[2]  = iv; //intvec
4256  Lord[2] = tmp;
4257  // continue with dp 1,1,1,1...
4258  tmp[1]  = "dp"; // string
4259  s       = "iv=";
4260  for(i=1;i<=Nnew;i++)
4261  {
4262    s = s+"1,";
4263  }
4264  s[size(s)]= ";";
4265  execute(s);
4266  tmp[2]    = iv;
4267  Lord[3]   = tmp;
4268  tmp[1]    = "C";
4269  iv        = 0;
4270  tmp[2]    = iv;
4271  Lord[4]   = tmp;
4272  tmp       = 0;
4273  L[3]      = Lord;
4274  // we are done with the list
4275  def @R@ = ring(L);
4276  setring @R@;
4277  matrix @D[Nnew][Nnew];
4278  @D[1,2]=1;
4279  for(i=1; i<=N; i++)
4280  {
4281    @D[3+i,N+3+i]=1;
4282  }
4283  // ADD [s,t]=-t, [s,Dt]=Dt
4284  @D[1,3] = -var(1);
4285  @D[2,3] = var(2);
4286  //  @D[N+3,2*(N+2)]=1; old t,Dt stuff
4287  //  L[5] = matrix(UpOneMatrix(Nnew));
4288  //  L[6] = @D;
4289  def @R = nc_algebra(1,@D);
4290  setring @R;
4291  kill @R@;
4292  dbprint(ppl,"// -1-1- the ring @R(t,Dt,s,_x,_Dx) is ready");
4293  dbprint(ppl-1, @R);
4294  // create the ideal I
4295  poly  F = imap(save,F);
4296  //  ideal I = u*F-t,u*v-1;
4297  ideal I = F-t;
4298  poly p;
4299  for(i=1; i<=N; i++)
4300  {
4301    //    p = u*Dt; // u*Dt
4302    p = Dt;
4303    p = diff(F,var(3+i))*p;
4304    I = I, var(N+3+i) + p;
4305  }
4306  //  I = I, var(1)*var(2) + var(Nnew) +1; // reduce it with t-f!!!
4307  // t*Dt + s +1 reduced with t-f gives f*Dt + s
4308  I = I, F*var(2) + var(3);
4309  // -------- the ideal I is ready ----------
4310  dbprint(ppl,"// -1-2- starting the elimination of t,Dt in @R");
4311  dbprint(ppl-1, I);
4312  ideal J = engine(I,eng);
4313  ideal K = nselect(J,1..2);
4314  dbprint(ppl,"// -1-3- t,Dt are eliminated");
4315  dbprint(ppl-1, K);  // K is without t, Dt
4316  K = engine(K,eng);  // std does the job too
4317  // now, we must change the ordering
4318  // and create a ring without t, Dt
4319  setring save;
4320  // ----------- the ring @R3 ------------
4321  // _x, _Dx,s;  elim.ord for _x,_Dx.
4322  // keep: N, i,j,s, tmp, RL
4323  Nnew = 2*N+1;
4324  kill Lord, tmp, iv, RName;
4325  list Lord, tmp;
4326  intvec iv;
4327  L[1] = RL[1];
4328  L[4] = RL[4];  // char, minpoly
4329  // check whether vars hava admissible names -> done earlier
4330  // now, create the names for new var
4331  tmp[1] = "s";
4332  // DName is defined earlier
4333  list NName = Name + DName + tmp;
4334  L[2] = NName;
4335  tmp = 0;
4336  // block ord (dp(N),dp);
4337  // string s is already defined
4338  s = "iv=";
4339  for (i=1; i<=Nnew-1; i++)
4340  {
4341    s = s+"1,";
4342  }
4343  s[size(s)]=";";
4344  execute(s);
4345  tmp[1] = "dp";  // string
4346  tmp[2] = iv;   // intvec
4347  Lord[1] = tmp;
4348  // continue with dp 1,1,1,1...
4349  tmp[1] = "dp";  // string
4350  s[size(s)] = ",";
4351  s = s+"1;";
4352  execute(s);
4353  kill s;
4354  kill NName;
4355  tmp[2]      = iv;
4356  Lord[2]     = tmp;
4357  tmp[1]      = "C";  iv  = 0;  tmp[2]=iv;
4358  Lord[3]     = tmp;  tmp = 0;
4359  L[3]        = Lord;
4360  // we are done with the list. Now add a Plural part
4361  def @R2@ = ring(L);
4362  setring @R2@;
4363  matrix @D[Nnew][Nnew];
4364  for (i=1; i<=N; i++)
4365  {
4366    @D[i,N+i]=1;
4367  }
4368  def @R2 = nc_algebra(1,@D);
4369  setring @R2;
4370  kill @R2@;
4371  dbprint(ppl,"//  -2-1- the ring @R2(_x,_Dx,s) is ready");
4372  dbprint(ppl-1, @R2);
4373  ideal MM = maxideal(1);
4374  //  MM = 0,s,MM;
4375  MM = 0,0,s,MM[1..size(MM)-1];
4376  map R01 = @R, MM;
4377  ideal K = R01(K);
4378  // total cleanup
4379  ideal LD = K;
4380  // make leadcoeffs positive
4381  for (i=1; i<= ncols(LD); i++)
4382  {
4383    if (leadcoef(LD[i]) <0 )
4384    {
4385      LD[i] = -LD[i];
4386    }
4387  }
4388  export LD;
4389  kill @R;
4390  return(@R2);
4391}
4392example
4393{
4394  "EXAMPLE:"; echo = 2;
4395  ring r = 0,(x,y,z),Dp;
4396  poly F = x^3+y^3+z^3;
4397  printlevel = 0;
4398  def A  = SannfsLOT(F);
4399  setring A;
4400  LD;
4401}
4402
4403/*
4404proc SannfsLOTold(poly F, list #)
4405"USAGE:  SannfsLOT(f [,eng]);  f a poly, eng an optional int
4406RETURN:  ring
4407PURPOSE: compute the D-module structure of basering[1/f]*f^s, according to the Levandovskyy's modification of the algorithm by Oaku and Takayama in the ring D[s], where D is the Weyl algebra
4408NOTE:    activate the output ring with the @code{setring} command.
4409@*       In the ring D[s], the ideal LD (which is NOT a Groebner basis) is the needed D-module structure.
4410@*       If eng <>0, @code{std} is used for Groebner basis computations,
4411@*       otherwise, and by default @code{slimgb} is used.
4412@*       If printlevel=1, progress debug messages will be printed,
4413@*       if printlevel>=2, all the debug messages will be printed.
4414EXAMPLE: example SannfsLOT; shows examples
4415"
4416{
4417  int eng = 0;
4418  if ( size(#)>0 )
4419  {
4420    if ( typeof(#[1]) == "int" )
4421    {
4422      eng = int(#[1]);
4423    }
4424  }
4425  // returns a list with a ring and an ideal LD in it
4426  int ppl = printlevel-voice+2;
4427  //  printf("plevel :%s, voice: %s",printlevel,voice);
4428  def save = basering;
4429  int N = nvars(basering);
4430  //  int Nnew = 2*(N+2);
4431  int Nnew = 2*(N+1)+1; //removed u,v; added s
4432  int i,j;
4433  string s;
4434  list RL = ringlist(basering);
4435  list L, Lord;
4436  list tmp;
4437  intvec iv;
4438  L[1] = RL[1]; // char
4439  L[4] = RL[4]; // char, minpoly
4440  // check whether vars have admissible names
4441  list Name  = RL[2];
4442  list RName;
4443//   RName[1] = "u";
4444//   RName[2] = "v";
4445  RName[1] = "t";
4446  RName[2] = "Dt";
4447  for(i=1;i<=N;i++)
4448  {
4449    for(j=1; j<=size(RName);j++)
4450    {
4451      if (Name[i] == RName[j])
4452      {
4453        ERROR("Variable names should not include t,Dt");
4454      }
4455    }
4456  }
4457  // now, create the names for new vars
4458//   tmp[1]     = "u";
4459//   tmp[2]     = "v";
4460//   list UName = tmp;
4461  list DName;
4462  for(i=1;i<=N;i++)
4463  {
4464    DName[i] = "D"+Name[i]; // concat
4465  }
4466  tmp    =  0;
4467  tmp[1] = "t";
4468  tmp[2] = "Dt";
4469  list SName ; SName[1] = "s";
4470  //  list NName = UName +  tmp + Name + DName;
4471  list NName = tmp + Name + DName + SName;
4472  L[2]   = NName;
4473  tmp    = 0;
4474  // Name, Dname will be used further
4475  //  kill UName;
4476  kill NName;
4477  // block ord (a(1,1),dp);
4478  tmp[1]  = "a"; // string
4479  iv      = 1,1;
4480  tmp[2]  = iv; //intvec
4481  Lord[1] = tmp;
4482  // continue with dp 1,1,1,1...
4483  tmp[1]  = "dp"; // string
4484  s       = "iv=";
4485  for(i=1;i<=Nnew;i++)
4486  {
4487    s = s+"1,";
4488  }
4489  s[size(s)]= ";";
4490  execute(s);
4491  tmp[2]    = iv;
4492  Lord[2]   = tmp;
4493  tmp[1]    = "C";
4494  iv        = 0;
4495  tmp[2]    = iv;
4496  Lord[3]   = tmp;
4497  tmp       = 0;
4498  L[3]      = Lord;
4499  // we are done with the list
4500  def @R@ = ring(L);
4501  setring @R@;
4502  matrix @D[Nnew][Nnew];
4503  @D[1,2]=1;
4504  for(i=1; i<=N; i++)
4505  {
4506    @D[2+i,N+2+i]=1;
4507  }
4508  // ADD [s,t]=-t, [s,Dt]=Dt
4509  @D[1,Nnew] = -var(1);
4510  @D[2,Nnew] = var(2);
4511  //  @D[N+3,2*(N+2)]=1; old t,Dt stuff
4512  //  L[5] = matrix(UpOneMatrix(Nnew));
4513  //  L[6] = @D;
4514  def @R = nc_algebra(1,@D);
4515  setring @R;
4516  kill @R@;
4517  dbprint(ppl,"// -1-1- the ring @R(t,Dt,_x,_Dx,s) is ready");
4518  dbprint(ppl-1, @R);
4519  // create the ideal I
4520  poly  F = imap(save,F);
4521  //  ideal I = u*F-t,u*v-1;
4522  ideal I = F-t;
4523  poly p;
4524  for(i=1; i<=N; i++)
4525  {
4526    //    p = u*Dt; // u*Dt
4527    p = Dt;
4528    p = diff(F,var(2+i))*p;
4529    I = I, var(N+2+i) + p;
4530  }
4531  //  I = I, var(1)*var(2) + var(Nnew) +1; // reduce it with t-f!!!
4532  // t*Dt + s +1 reduced with t-f gives f*Dt + s
4533  I = I, F*var(2) + var(Nnew);
4534  // -------- the ideal I is ready ----------
4535  dbprint(ppl,"// -1-2- starting the elimination of t,Dt in @R");
4536  dbprint(ppl-1, I);
4537  ideal J = engine(I,eng);
4538  ideal K = nselect(J,1..2);
4539  dbprint(ppl,"// -1-3- t,Dt are eliminated");
4540  dbprint(ppl-1, K);  // K is without t, Dt
4541  K = engine(K,eng);  // std does the job too
4542  // now, we must change the ordering
4543  // and create a ring without t, Dt
4544  setring save;
4545  // ----------- the ring @R3 ------------
4546  // _x, _Dx,s;  elim.ord for _x,_Dx.
4547  // keep: N, i,j,s, tmp, RL
4548  Nnew = 2*N+1;
4549  kill Lord, tmp, iv, RName;
4550  list Lord, tmp;
4551  intvec iv;
4552  L[1] = RL[1];
4553  L[4] = RL[4];  // char, minpoly
4554  // check whether vars hava admissible names -> done earlier
4555  // now, create the names for new var
4556  tmp[1] = "s";
4557  // DName is defined earlier
4558  list NName = Name + DName + tmp;
4559  L[2] = NName;
4560  tmp = 0;
4561  // block ord (dp(N),dp);
4562  // string s is already defined
4563  s = "iv=";
4564  for (i=1; i<=Nnew-1; i++)
4565  {
4566    s = s+"1,";
4567  }
4568  s[size(s)]=";";
4569  execute(s);
4570  tmp[1] = "dp";  // string
4571  tmp[2] = iv;   // intvec
4572  Lord[1] = tmp;
4573  // continue with dp 1,1,1,1...
4574  tmp[1] = "dp";  // string
4575  s[size(s)] = ",";
4576  s = s+"1;";
4577  execute(s);
4578  kill s;
4579  kill NName;
4580  tmp[2]      = iv;
4581  Lord[2]     = tmp;
4582  tmp[1]      = "C";  iv  = 0;  tmp[2]=iv;
4583  Lord[3]     = tmp;  tmp = 0;
4584  L[3]        = Lord;
4585  // we are done with the list. Now add a Plural part
4586  def @R2@ = ring(L);
4587  setring @R2@;
4588  matrix @D[Nnew][Nnew];
4589  for (i=1; i<=N; i++)
4590  {
4591    @D[i,N+i]=1;
4592  }
4593  def @R2 = nc_algebra(1,@D);
4594  setring @R2;
4595  kill @R2@;
4596  dbprint(ppl,"//  -2-1- the ring @R2(_x,_Dx,s) is ready");
4597  dbprint(ppl-1, @R2);
4598  ideal MM = maxideal(1);
4599  MM = 0,s,MM;
4600  map R01 = @R, MM;
4601  ideal K = R01(K);
4602  // total cleanup
4603  ideal LD = K;
4604  // make leadcoeffs positive
4605  for (i=1; i<= ncols(LD); i++)
4606  {
4607    if (leadcoef(LD[i]) <0 )
4608    {
4609      LD[i] = -LD[i];
4610    }
4611  }
4612  export LD;
4613  kill @R;
4614  return(@R2);
4615}
4616example
4617{
4618  "EXAMPLE:"; echo = 2;
4619  ring r = 0,(x,y,z),Dp;
4620  poly F = x^3+y^3+z^3;
4621  printlevel = 0;
4622  def A  = SannfsLOTold(F);
4623  setring A;
4624  LD;
4625}
4626
4627*/
4628
4629proc annfsLOT(poly F, list #)
4630"USAGE:  annfsLOT(F [,eng]);  F a poly, eng an optional int
4631RETURN:  ring
4632PURPOSE: compute the D-module structure of basering[1/f]*f^s, according to
4633@* the Levandovskyy's modification of the algorithm by Oaku and Takayama
4634NOTE:    activate the output ring with the @code{setring} command. In this ring,
4635@*  - the ideal LD (which is a Groebner basis) is the needed D-module structure,
4636@*    which is obtained by substituting the minimal integer root of a Bernstein
4637@*    polynomial into the s-parametric ideal;
4638@*  - the list BS contains the roots with multiplicities of BS polynomial of f.
4639@*    If eng <>0, @code{std} is used for Groebner basis computations,
4640@*    otherwise and by default @code{slimgb} is used.
4641@*    If printlevel=1, progress debug messages will be printed,
4642@*    if printlevel>=2, all the debug messages will be printed.
4643EXAMPLE: example annfsLOT; shows examples
4644"
4645{
4646  int eng = 0;
4647  if ( size(#)>0 )
4648  {
4649    if ( typeof(#[1]) == "int" )
4650    {
4651      eng = int(#[1]);
4652    }
4653  }
4654  printlevel=printlevel+1;
4655  def save = basering;
4656  def @A = SannfsLOT(F,eng);
4657  setring @A;
4658  poly F = imap(save,F);
4659  def B  = annfs0(LD,F,eng);
4660  return(B);
4661}
4662example
4663{
4664  "EXAMPLE:"; echo = 2;
4665  ring r = 0,(x,y,z),Dp;
4666  poly F = z*x^2+y^3;
4667  printlevel = 0;
4668  def A  = annfsLOT(F);
4669  setring A;
4670  LD;
4671  BS;
4672}
4673
4674proc annfs0(ideal I, poly F, list #)
4675"USAGE:  annfs0(I, F [,eng]);  I an ideal, F a poly, eng an optional int
4676RETURN:  ring
4677PURPOSE: compute the annihilator ideal of f^s in the Weyl Algebra, based
4678@* on the output of Sannfs-like procedure
4679NOTE:    activate the output ring with the @code{setring} command. In this ring,
4680@* - the ideal LD (which is a Groebner basis) is the annihilator of f^s,
4681@* - the list BS contains the roots with multiplicities of BS polynomial of f.
4682@*  If eng <>0, @code{std} is used for Groebner basis computations,
4683@*  otherwise and by default @code{slimgb} is used.
4684@*  If printlevel=1, progress debug messages will be printed,
4685@*  if printlevel>=2, all the debug messages will be printed.
4686EXAMPLE: example annfs0; shows examples
4687"
4688{
4689  int eng = 0;
4690  if ( size(#)>0 )
4691  {
4692    if ( typeof(#[1]) == "int" )
4693    {
4694      eng = int(#[1]);
4695    }
4696  }
4697  def @R2 = basering;
4698  // we're in D_n[s], where the elim ord for s is set
4699  ideal J = NF(I,std(F));
4700  // make leadcoeffs positive
4701  int i;
4702  for (i=1; i<= ncols(J); i++)
4703  {
4704    if (leadcoef(J[i]) <0 )
4705    {
4706      J[i] = -J[i];
4707    }
4708  }
4709  J = J,F;
4710  ideal M = engine(J,eng);
4711  int Nnew = nvars(@R2);
4712  ideal K2 = nselect(M,1..Nnew-1);
4713  int ppl = printlevel-voice+2;
4714  dbprint(ppl,"// -1-1- _x,_Dx are eliminated in basering");
4715  dbprint(ppl-1, K2);
4716  // the ring @R3 and the search for minimal negative int s
4717  ring @R3 = 0,s,dp;
4718  dbprint(ppl,"// -2-1- the ring @R3 i.e. K[s] is ready");
4719  ideal K3 = imap(@R2,K2);
4720  poly p = K3[1];
4721  dbprint(ppl,"// -2-2- factorization");
4722  //  ideal P = factorize(p,1);  //without constants and multiplicities
4723  //  "--------- b-function factorizes into ---------";   P;
4724  // convert factors to the list of their roots with mults
4725  // assume all factors are linear
4726  //  ideal BS = normalize(P);
4727  //  BS = subst(BS,s,0);
4728  //  BS = -BS;
4729  list P = factorize(p);          //with constants and multiplicities
4730  ideal bs; intvec m;             //the Bernstein polynomial is monic, so we are not interested in constants
4731  for (i=2; i<= size(P[1]); i++)  //we delete P[1][1] and P[2][1]
4732  {
4733    bs[i-1] = P[1][i];
4734    m[i-1]  = P[2][i];
4735  }
4736  int sP = minIntRoot(bs,1);
4737  bs =  normalize(bs);
4738  bs = -subst(bs,s,0);
4739  dbprint(ppl,"// -2-3- minimal integer root found");
4740  dbprint(ppl-1, sP);
4741 //TODO: sort BS!
4742  // --------- substitute s found in the ideal ---------
4743  // --------- going back to @R and substitute ---------
4744  setring @R2;
4745  K2 = subst(I,s,sP);
4746  // create the ordinary Weyl algebra and put the result into it,
4747  // thus creating the ring @R5
4748  // keep: N, i,j,s, tmp, RL
4749  Nnew = Nnew - 1; // former 2*N;
4750  // list RL = ringlist(save);  // is defined earlier
4751  //  kill Lord, tmp, iv;
4752  list L = 0;
4753  list Lord, tmp;
4754  intvec iv;
4755  list RL = ringlist(basering);
4756  L[1] = RL[1];
4757  L[4] = RL[4];  //char, minpoly
4758  // check whether vars have admissible names -> done earlier
4759  // list Name = RL[2]M
4760  // DName is defined earlier
4761  list NName; // = RL[2]; // skip the last var 's'
4762  for (i=1; i<=Nnew; i++)
4763  {
4764    NName[i] =  RL[2][i];
4765  }
4766  L[2] = NName;
4767  // dp ordering;
4768  string s = "iv=";
4769  for (i=1; i<=Nnew; i++)
4770  {
4771    s = s+"1,";
4772  }
4773  s[size(s)] = ";";
4774  execute(s);
4775  tmp     = 0;
4776  tmp[1]  = "dp";  // string
4777  tmp[2]  = iv;  // intvec
4778  Lord[1] = tmp;
4779  kill s;
4780  tmp[1]  = "C";
4781  iv = 0;
4782  tmp[2]  = iv;
4783  Lord[2] = tmp;
4784  tmp     = 0;
4785  L[3]    = Lord;
4786  // we are done with the list
4787  // Add: Plural part
4788  def @R4@ = ring(L);
4789  setring @R4@;
4790  int N = Nnew/2;
4791  matrix @D[Nnew][Nnew];
4792  for (i=1; i<=N; i++)
4793  {
4794    @D[i,N+i]=1;
4795  }
4796  def @R4 = nc_algebra(1,@D);
4797  setring @R4;
4798  kill @R4@;
4799  dbprint(ppl,"// -3-1- the ring @R4 is ready");
4800  dbprint(ppl-1, @R4);
4801  ideal K4 = imap(@R2,K2);
4802  option(redSB);
4803  dbprint(ppl,"// -3-2- the final cosmetic std");
4804  K4 = engine(K4,eng);  // std does the job too
4805  // total cleanup
4806  ideal bs = imap(@R3,bs);
4807  kill @R3;
4808  list BS = bs,m;
4809  export BS;
4810  ideal LD = K4;
4811  export LD;
4812  return(@R4);
4813}
4814example
4815{ "EXAMPLE:"; echo = 2;
4816  ring r = 0,(x,y,z),Dp;
4817  poly F = x^3+y^3+z^3;
4818  printlevel = 0;
4819  def A = SannfsBM(F);   setring A;
4820  // alternatively, one can use SannfsOT or SannfsLOT
4821  LD;
4822  poly F = imap(r,F);
4823  def B  = annfs0(LD,F);  setring B;
4824  LD;
4825  BS;
4826}
4827
4828// proc annfsgms(poly F, list #)
4829// "USAGE:  annfsgms(f [,eng]);  f a poly, eng an optional int
4830// ASSUME:  f has an isolated critical point at 0
4831// RETURN:  ring
4832// PURPOSE: compute the D-module structure of basering[1/f]*f^s
4833// NOTE:    activate the output ring with the @code{setring} command. In this ring,
4834// @*       - the ideal LD is the needed D-mod structure,
4835// @*       - the ideal BS is the list of roots of a Bernstein polynomial of f.
4836// @*       If eng <>0, @code{std} is used for Groebner basis computations,
4837// @*       otherwise (and by default) @code{slimgb} is used.
4838// @*       If printlevel=1, progress debug messages will be printed,
4839// @*       if printlevel>=2, all the debug messages will be printed.
4840// EXAMPLE: example annfsgms; shows examples
4841// "
4842// {
4843//   LIB "gmssing.lib";
4844//   int eng = 0;
4845//   if ( size(#)>0 )
4846//   {
4847//     if ( typeof(#[1]) == "int" )
4848//     {
4849//       eng = int(#[1]);
4850//     }
4851//   }
4852//   int ppl = printlevel-voice+2;
4853//   // returns a ring with the ideal LD in it
4854//   def save = basering;
4855//   // compute the Bernstein polynomial from gmssing.lib
4856//   list RL = ringlist(basering);
4857//   // in the descr. of the ordering, replace "p" by "s"
4858//   list NL = convloc(RL);
4859//   // create a ring with the ordering, converted to local
4860//   def @LR = ring(NL);
4861//   setring @LR;
4862//   poly F  = imap(save, F);
4863//   ideal B = bernstein(F)[1];
4864//   // since B may not contain (s+1) [following gmssing.lib]
4865//   // add it!
4866//   B = B,-1;
4867//   B = simplify(B,2+4); // erase zero and repeated entries
4868//   // find the minimal integer value
4869//   int   S = minIntRoot(B,0);
4870//   dbprint(ppl,"// -0- minimal integer root found");
4871//   dbprint(ppl-1,S);
4872//   setring save;
4873//   int N = nvars(basering);
4874//   int Nnew = 2*(N+2);
4875//   int i,j;
4876//   string s;
4877//   //  list RL = ringlist(basering);
4878//   list L, Lord;
4879//   list tmp;
4880//   intvec iv;
4881//   L[1] = RL[1]; // char
4882//   L[4] = RL[4]; // char, minpoly
4883//   // check whether vars have admissible names
4884//   list Name  = RL[2];
4885//   list RName;
4886//   RName[1] = "u";
4887//   RName[2] = "v";
4888//   RName[3] = "t";
4889//   RName[4] = "Dt";
4890//   for(i=1;i<=N;i++)
4891//   {
4892//     for(j=1; j<=size(RName);j++)
4893//     {
4894//       if (Name[i] == RName[j])
4895//       {
4896//         ERROR("Variable names should not include u,v,t,Dt");
4897//       }
4898//     }
4899//   }
4900//   // now, create the names for new vars
4901//   //  tmp[1]     = "u";  tmp[2]     = "v";  tmp[3]     = "t";  tmp[4]     = "Dt";
4902//   list UName = RName;
4903//   list DName;
4904//   for(i=1;i<=N;i++)
4905//   {
4906//     DName[i] = "D"+Name[i]; // concat
4907//   }
4908//   list NName = UName + Name + DName;
4909//   L[2]       = NName;
4910//   tmp        = 0;
4911//   // Name, Dname will be used further
4912//   kill UName;
4913//   kill NName;
4914//   // block ord (a(1,1),dp);
4915//   tmp[1]  = "a"; // string
4916//   iv      = 1,1;
4917//   tmp[2]  = iv; //intvec
4918//   Lord[1] = tmp;
4919//   // continue with dp 1,1,1,1...
4920//   tmp[1]  = "dp"; // string
4921//   s       = "iv=";
4922//   for(i=1; i<=Nnew; i++) // need really all vars!
4923//   {
4924//     s = s+"1,";
4925//   }
4926//   s[size(s)]= ";";
4927//   execute(s);
4928//   tmp[2]    = iv;
4929//   Lord[2]   = tmp;
4930//   tmp[1]    = "C";
4931//   iv        = 0;
4932//   tmp[2]    = iv;
4933//   Lord[3]   = tmp;
4934//   tmp       = 0;
4935//   L[3]      = Lord;
4936//   // we are done with the list
4937//   def @R = ring(L);
4938//   setring @R;
4939//   matrix @D[Nnew][Nnew];
4940//   @D[3,4] = 1; // t,Dt
4941//   for(i=1; i<=N; i++)
4942//   {
4943//     @D[4+i,4+N+i]=1;
4944//   }
4945//   //  L[5] = matrix(UpOneMatrix(Nnew));
4946//   //  L[6] = @D;
4947//   nc_algebra(1,@D);
4948//   dbprint(ppl,"// -1-1- the ring @R is ready");
4949//   dbprint(ppl-1,@R);
4950//   // create the ideal
4951//   poly F  = imap(save,F);
4952//   ideal I = u*F-t,u*v-1;
4953//   poly p;
4954//   for(i=1; i<=N; i++)
4955//   {
4956//     p = u*Dt; // u*Dt
4957//     p = diff(F,var(4+i))*p;
4958//     I = I, var(N+4+i) + p; // Dx, Dy
4959//   }
4960//   // add the relations between t,Dt and s
4961//   //  I = I, t*Dt+1+S;
4962//   // -------- the ideal I is ready ----------
4963//   dbprint(ppl,"// -1-2- starting the elimination of u,v in @R");
4964//   ideal J = engine(I,eng);
4965//   ideal K = nselect(J,1..2);
4966//   dbprint(ppl,"// -1-3- u,v are eliminated in @R");
4967//   dbprint(ppl-1,K); // without u,v: not yet our answer
4968//   //----- create a ring with elim.ord for t,Dt -------
4969//   setring save;
4970//   // ------------ new ring @R2 ------------------
4971//   // without u,v and with the elim.ord for t,Dt
4972//   // keep: N, i,j,s, tmp, RL
4973//   Nnew = 2*N+2;
4974//   //  list RL = ringlist(save); // is defined earlier
4975//   kill Lord,tmp,iv, RName;
4976//   L = 0;
4977//   list Lord, tmp;
4978//   intvec iv;
4979//   L[1] = RL[1]; // char
4980//   L[4] = RL[4]; // char, minpoly
4981//   // check whether vars have admissible names -> done earlier
4982//   //  list Name  = RL[2];
4983//   list RName;
4984//   RName[1] = "t";
4985//   RName[2] = "Dt";
4986//   // DName is defined earlier
4987//   list NName = RName + Name + DName;
4988//   L[2]   = NName;
4989//   tmp    = 0;
4990//   // block ord (a(1,1),dp);
4991//   tmp[1]  = "a"; // string
4992//   iv      = 1,1;
4993//   tmp[2]  = iv; //intvec
4994//   Lord[1] = tmp;
4995//   // continue with dp 1,1,1,1...
4996//   tmp[1]  = "dp"; // string
4997//   s       = "iv=";
4998//   for(i=1;i<=Nnew;i++)
4999//   {
5000//     s = s+"1,";
5001//   }
5002//   s[size(s)]= ";";
5003//   execute(s);
5004//   kill s;
5005//   kill NName;
5006//   tmp[2]    = iv;
5007//   Lord[2]   = tmp;
5008//   tmp[1]    = "C";
5009//   iv        = 0;
5010//   tmp[2]    = iv;
5011//   Lord[3]   = tmp;
5012//   tmp       = 0;
5013//   L[3]      = Lord;
5014//   // we are done with the list
5015//   // Add: Plural part
5016//   def @R2 = ring(L);
5017//   setring @R2;
5018//   matrix @D[Nnew][Nnew];
5019//   @D[1,2]=1;
5020//   for(i=1; i<=N; i++)
5021//   {
5022//     @D[2+i,2+N+i]=1;
5023//   }
5024//   nc_algebra(1,@D);
5025//   dbprint(ppl,"// -2-1- the ring @R2 is ready");
5026//   dbprint(ppl-1,@R2);
5027//   ideal MM = maxideal(1);
5028//   MM = 0,0,MM;
5029//   map R01 = @R, MM;
5030//   ideal K2 = R01(K);
5031//   // add the relations between t,Dt and s
5032//   //  K2       = K2, t*Dt+1+S;
5033//   poly G = t*Dt+S+1;
5034//   K2 = NF(K2,std(G)),G;
5035//   dbprint(ppl,"// -2-2- starting elimination for t,Dt in @R2");
5036//   ideal J  = engine(K2,eng);
5037//   ideal K  = nselect(J,1..2);
5038//   dbprint(ppl,"// -2-3- t,Dt are eliminated");
5039//   dbprint(ppl-1,K);
5040//   //  "------- produce a final result --------";
5041//   // ----- create the ordinary Weyl algebra and put
5042//   // ----- the result into it
5043//   // ------ create the ring @R5
5044//   // keep: N, i,j,s, tmp, RL
5045//   setring save;
5046//   Nnew = 2*N;
5047//   //  list RL = ringlist(save); // is defined earlier
5048//   kill Lord, tmp, iv;
5049//   //  kill L;
5050//   L = 0;
5051//   list Lord, tmp;
5052//   intvec iv;
5053//   L[1] = RL[1]; // char
5054//   L[4] = RL[4]; // char, minpoly
5055//   // check whether vars have admissible names -> done earlier
5056//   //  list Name  = RL[2];
5057//   // DName is defined earlier
5058//   list NName = Name + DName;
5059//   L[2]   = NName;
5060//   // dp ordering;
5061//   string   s       = "iv=";
5062//   for(i=1;i<=2*N;i++)
5063//   {
5064//     s = s+"1,";
5065//   }
5066//   s[size(s)]= ";";
5067//   execute(s);
5068//   tmp     = 0;
5069//   tmp[1]  = "dp"; // string
5070//   tmp[2]  = iv; //intvec
5071//   Lord[1] = tmp;
5072//   kill s;
5073//   tmp[1]    = "C";
5074//   iv        = 0;
5075//   tmp[2]    = iv;
5076//   Lord[2]   = tmp;
5077//   tmp       = 0;
5078//   L[3]      = Lord;
5079//   // we are done with the list
5080//   // Add: Plural part
5081//   def @R5 = ring(L);
5082//   setring @R5;
5083//   matrix @D[Nnew][Nnew];
5084//   for(i=1; i<=N; i++)
5085//   {
5086//     @D[i,N+i]=1;
5087//   }
5088//   nc_algebra(1,@D);
5089//   dbprint(ppl,"// -3-1- the ring @R5 is ready");
5090//   dbprint(ppl-1,@R5);
5091//   ideal K5 = imap(@R2,K);
5092//   option(redSB);
5093//   dbprint(ppl,"// -3-2- the final cosmetic std");
5094//   K5 = engine(K5,eng); // std does the job too
5095//   // total cleanup
5096//   kill @R;
5097//   kill @R2;
5098//   ideal LD = K5;
5099//   ideal BS = imap(@LR,B);
5100//   kill @LR;
5101//   export BS;
5102//   export LD;
5103//   return(@R5);
5104// }
5105// example
5106// {
5107//   "EXAMPLE:"; echo = 2;
5108//   ring r = 0,(x,y,z),Dp;
5109//   poly F = x^2+y^3+z^5;
5110//   def A = annfsgms(F);
5111//   setring A;
5112//   LD;
5113//   print(matrix(BS));
5114// }
5115
5116
5117proc convloc(list @NL)
5118"USAGE:  convloc(L); L a list
5119RETURN:  list
5120PURPOSE: convert a ringlist L into another ringlist,
5121@* where all the 'p' orderings are replaced with the 's' orderings, e.g. @code{dp} by @code{ds}.
5122ASSUME: L is a result of a ringlist command
5123EXAMPLE: example convloc; shows examples
5124"
5125{
5126  list NL = @NL;
5127  // given a ringlist, returns a new ringlist,
5128  // where all the p-orderings are replaced with s-ord's
5129  int i,j,k,found;
5130  int nblocks = size(NL[3]);
5131  for(i=1; i<=nblocks; i++)
5132  {
5133    for(j=1; j<=size(NL[3][i]); j++)
5134    {
5135      if (typeof(NL[3][i][j]) == "string" )
5136      {
5137        found = 0;
5138        for (k=1; k<=size(NL[3][i][j]); k++)
5139        {
5140          if (NL[3][i][j][k]=="p")
5141          {
5142            NL[3][i][j][k]="s";
5143            found = 1;
5144            //    printf("replaced at %s,%s,%s",i,j,k);
5145          }
5146        }
5147      }
5148    }
5149  }
5150  return(NL);
5151}
5152example
5153{
5154  "EXAMPLE:"; echo = 2;
5155  ring r = 0,(x,y,z),(Dp(2),dp(1));
5156  list L = ringlist(r);
5157  list N = convloc(L);
5158  def rs = ring(N);
5159  setring rs;
5160  rs;
5161}
5162
5163proc annfspecial(ideal I, poly F, int mir, number n)
5164"USAGE:  annfspecial(I,F,mir,n);  I an ideal, F a poly, int mir, number n
5165RETURN:  ideal
5166PURPOSE: compute the annihilator ideal of F^n in the Weyl Algebra
5167@*           for the given rational number n
5168ASSUME:  The basering is D[s] and contains 's' explicitly as a variable,
5169@*   the ideal I is the Ann F^s in D[s] (obtained with e.g. SannfsBM),
5170@*   the integer 'mir' is the minimal integer root of the BS polynomial of F,
5171@*   and the number n is rational.
5172NOTE: We compute the real annihilator for any rational value of n (both
5173@*       generic and exceptional). The implementation goes along the lines of
5174@*       the Algorithm 5.3.15 from Saito-Sturmfels-Takayama.
5175DISPLAY: If printlevel=1, progress debug messages will be printed,
5176@*       if printlevel>=2, all the debug messages will be printed.
5177EXAMPLE: example annfspecial; shows examples
5178"
5179{
5180
5181  if (!isRational(n))
5182  {
5183    "ERROR: n must be a rational number!";
5184  }
5185  int ppl = printlevel-voice+2;
5186  //  int mir =  minIntRoot(L[1],0);
5187  int ns   = varNum("s");
5188  if (!ns)
5189  {
5190    ERROR("Variable s expected in the ideal AnnFs");
5191  }
5192  int d;
5193  ideal P = subst(I,var(ns),n);
5194  if (denominator(n) == 1)
5195  {
5196    // n is fraction-free
5197    d = int(numerator(n));
5198    if ( (!d) && (n!=0))
5199    {
5200      ERROR("no parametric special values are allowed");
5201    }
5202    d = d - mir;
5203    if (d>0)
5204    {
5205      dbprint(ppl,"// -1-1- starting syzygy computations");
5206      matrix J[1][1] = F^d;
5207      dbprint(ppl-1,"// -1-1-1- of the polynomial ideal");
5208      dbprint(ppl-1,J);
5209      matrix K[1][size(I)] = subst(I,var(ns),mir);
5210      dbprint(ppl-1,"// -1-1-2- modulo ideal:");
5211      dbprint(ppl-1, K);
5212      module M = modulo(J,K);
5213      dbprint(ppl-1,"// -1-1-3- getting the result:");
5214      dbprint(ppl-1, M);
5215      P  = P, ideal(M);
5216      dbprint(ppl,"// -1-2- finished syzygy computations");
5217    }
5218    else
5219    {
5220      dbprint(ppl,"// -1-1- d<=0, no syzygy computations needed");
5221      dbprint(ppl-1,"// -1-2- for d =");
5222      dbprint(ppl-1, d);
5223    }
5224  }
5225  // also the else case: d<=0 or n is not an integer
5226  dbprint(ppl,"// -2-1- starting final Groebner basis");
5227  P = groebner(P);
5228  dbprint(ppl,"// -2-2- finished final Groebner basis");
5229  return(P);
5230}
5231example
5232{
5233  "EXAMPLE:"; echo = 2;
5234  ring r = 0,(x,y),dp;
5235  poly F = x3-y2;
5236  def  B = annfs(F);  setring B;
5237  minIntRoot(BS[1],0);
5238  // So, the minimal integer root is -1
5239  setring r;
5240  def  A = SannfsBM(F);
5241  setring A;
5242  poly F = x3-y2;
5243  annfspecial(LD,F,-1,3/4); // generic root
5244  annfspecial(LD,F,-1,-2);  // integer but still generic root
5245  annfspecial(LD,F,-1,1);   // exceptional root
5246}
5247
5248/*
5249//static proc new_ex_annfspecial()
5250{
5251  //another example for annfspecial: x3+y3+z3
5252  ring r = 0,(x,y,z),dp;
5253  poly F =  x3+y3+z3;
5254  def  B = annfs(F);  setring B;
5255  minIntRoot(BS[1],0);
5256  // So, the minimal integer root is -1
5257  setring r;
5258  def  A = SannfsBM(F);
5259  setring A;
5260  poly F =  x3+y3+z3;
5261  annfspecial(LD,F,-1,3/4); // generic root
5262  annfspecial(LD,F,-1,-2);  // integer but still generic root
5263  annfspecial(LD,F,-1,1);   // exceptional root
5264}
5265*/
5266
5267proc minIntRoot(ideal P, int fact)
5268"USAGE:  minIntRoot(P, fact); P an ideal, fact an int
5269RETURN:  int
5270PURPOSE: minimal integer root of a maximal ideal P
5271NOTE:    if fact==1, P is the result of some 'factorize' call,
5272@*       else P is treated as the result of bernstein::gmssing.lib
5273@*       in both cases without constants and multiplicities
5274EXAMPLE: example minIntRoot; shows examples
5275"
5276{
5277  //    ideal P = factorize(p,1);
5278  // or ideal P = bernstein(F)[1];
5279  intvec vP;
5280  number nP;
5281  int i;
5282  if ( fact )
5283  {
5284    // the result comes from "factorize"
5285    P = normalize(P); // now leadcoef = 1
5286    // TODO: hunt for units and kill then !!!
5287    P = matrix(lead(P))-P;
5288    // nP = leadcoef(P[i]-lead(P[i])); // for 1 var only, extract the coeff
5289  }
5290  else
5291  {
5292    // bernstein deletes -1 usually
5293    P = P, -1;
5294  }
5295  // for both situations:
5296  // now we have an ideal of fractions of type "number"
5297  int sP = size(P);
5298  for(i=1; i<=sP; i++)
5299  {
5300    nP = leadcoef(P[i]);
5301    if ( (nP - int(nP)) == 0 )
5302    {
5303      vP = vP,int(nP);
5304    }
5305  }
5306  if ( size(vP)>=2 )
5307  {
5308    vP = vP[2..size(vP)];
5309  }
5310  sP = -Max(-vP);
5311  if (sP == 0)
5312  {
5313    "Warning: zero root present!";
5314  }
5315  return(sP);
5316}
5317example
5318{
5319  "EXAMPLE:"; echo = 2;
5320  ring r   = 0,(x,y),ds;
5321  poly f1  = x*y*(x+y);
5322  ideal I1 = bernstein(f1)[1]; // a local Bernstein poly
5323  I1;
5324  minIntRoot(I1,0);
5325  poly  f2  = x2-y3;
5326  ideal I2  = bernstein(f2)[1];
5327  I2;
5328  minIntRoot(I2,0);
5329  // now we illustrate the behaviour of factorize
5330  // together with a global ordering
5331  ring r2  = 0,x,dp;
5332  poly f3   = 9*(x+2/3)*(x+1)*(x+4/3); //global b-polynomial of f1=x*y*(x+y)
5333  ideal I3 = factorize(f3,1);
5334  I3;
5335  minIntRoot(I3,1);
5336  // and a more interesting situation
5337  ring  s  = 0,(x,y,z),ds;
5338  poly  f  = x3 + y3 + z3;
5339  ideal I  = bernstein(f)[1];
5340  I;
5341  minIntRoot(I,0);
5342}
5343
5344proc isHolonomic(def M)
5345"USAGE:  isHolonomic(M); M an ideal/module/matrix
5346RETURN:  int, 1 if M is holonomic over the base ring, and 0 otherwise
5347ASSUME: basering is a Weyl algebra in characteristic 0
5348PURPOSE: check whether M is holonomic over the base ring
5349NOTE:    M is holonomic if 2*dim(M) = dim(R), where R is the
5350base ring; dim stays for Gelfand-Kirillov dimension
5351EXAMPLE: example isHolonomic; shows examples
5352"
5353{
5354  if (dmodappassumeViolation())
5355  {
5356    ERROR("Basering is inappropriate: characteristic>0 or qring present");
5357  }
5358  if (!isWeyl(basering))
5359  {
5360    ERROR("Basering is not a Weyl algebra");
5361  }
5362
5363  if ( (typeof(M) != "ideal") && (typeof(M) != "module") && (typeof(M) != "matrix") )
5364  {
5365  //  print(typeof(M));
5366    ERROR("an argument of type ideal/module/matrix expected");
5367  }
5368  if (attrib(M,"isSB")!=1)
5369  {
5370    M = std(M);
5371  }
5372  int dimR = gkdim(std(0));
5373  int dimM = gkdim(M);
5374  return( (dimR==2*dimM) );
5375}
5376example
5377{
5378  "EXAMPLE:"; echo = 2;
5379  ring R = 0,(x,y),dp;
5380  poly F = x*y*(x+y);
5381  def A = annfsBM(F,0);
5382  setring A;
5383  LD;
5384  isHolonomic(LD);
5385  ideal I = std(LD[1]);
5386  I;
5387  isHolonomic(I);
5388}
5389
5390proc reiffen(int p, int q)
5391"USAGE:  reiffen(p, q);  int p, int q
5392RETURN:  ring
5393PURPOSE: set up the polynomial, describing a Reiffen curve
5394NOTE:  activate the output ring with the @code{setring} command and
5395@*       find the curve as a polynomial RC.
5396@*  A Reiffen curve is defined as RC = x^p + y^q + xy^{q-1}, q >= p+1 >= 5
5397
5398EXAMPLE: example reiffen; shows examples
5399"
5400{
5401  // we allow also other numbers, p \geq 1, q\geq 1
5402// a Reiffen curve is defined as
5403// F = x^p + y^q +x*y^{q-1}, q \geq p+1 \geq 5
5404
5405// ASSUME: q >= p+1 >= 5. Otherwise an error message is returned
5406
5407//   if ( (p<4) || (q<5) || (q-p<1) )
5408//   {
5409//     ERROR("Some of conditions p>=4, q>=5 or q>=p+1 is not satisfied!");
5410//   }
5411  if ( (p<1) || (q<1) )
5412  {
5413    ERROR("Some of conditions p>=1, q>=1 is not satisfied!");
5414  }
5415  ring @r = 0,(x,y),dp;
5416  poly RC = y^q +x^p + x*y^(q-1);
5417  export RC;
5418  return(@r);
5419}
5420example
5421{
5422  "EXAMPLE:"; echo = 2;
5423  def r = reiffen(4,5);
5424  setring r;
5425  RC;
5426}
5427
5428proc arrange(int p)
5429"USAGE:  arrange(p);  int p
5430RETURN:  ring
5431PURPOSE: set up the polynomial, describing a hyperplane arrangement
5432NOTE:  must be executed in a commutative ring
5433ASSUME: basering is present and it is commutative
5434EXAMPLE: example arrange; shows examples
5435"
5436{
5437  int UseBasering = 0 ;
5438  if (p<2)
5439  {
5440    ERROR("p>=2 is required!");
5441  }
5442  if ( nameof(basering)!="basering" )
5443  {
5444    if (p > nvars(basering))
5445    {
5446      ERROR("too big p");
5447    }
5448    else
5449    {
5450      def @r = basering;
5451      UseBasering = 1;
5452    }
5453  }
5454  else
5455  {
5456    // no basering found
5457    ERROR("no basering found!");
5458    //    ring @r = 0,(x(1..p)),dp;
5459  }
5460  int i,j,sI;
5461  poly  q = 1;
5462  list ar;
5463  ideal tmp;
5464  tmp = ideal(var(1));
5465  ar[1] = tmp;
5466  for (i = 2; i<=p; i++)
5467  {
5468    // add i-nary sums to the product
5469    ar = indAR(ar,i);
5470  }
5471  for (i = 1; i<=p; i++)
5472  {
5473    tmp = ar[i]; sI = size(tmp);
5474    for (j = 1; j<=sI; j++)
5475    {
5476      q = q*tmp[j];
5477    }
5478  }
5479  if (UseBasering)
5480  {
5481    return(q);
5482  }
5483  //  poly AR = q; export AR;
5484  //  return(@r);
5485}
5486example
5487{
5488  "EXAMPLE:"; echo = 2;
5489  ring X = 0,(x,y,z,t),dp;
5490  poly q = arrange(3);
5491  factorize(q,1);
5492}
5493
5494proc checkRoot(poly F, number a, list #)
5495"USAGE:  checkRoot(f,alpha [,S,eng]);  poly f, number alpha, string S, int eng
5496RETURN:  int
5497ASSUME: Basering is a commutative ring, alpha is a positive rational number.
5498PURPOSE: check whether a negative rational number -alpha is a root of the global
5499@* Bernstein-Sato polynomial of f and compute its multiplicity,
5500@* with the algorithm given by S and with the Groebner basis engine given by eng.
5501NOTE:  The annihilator of f^s in D[s] is needed and hence it is computed with the
5502@*       algorithm by Briancon and Maisonobe. The value of a string S can be
5503@*       'alg1' (default) - for the algorithm 1 of [LM08]
5504@*       'alg2' - for the algorithm 2 of [LM08]
5505@*       Depending on the value of S, the output of type int is:
5506@*       'alg1': 1 only if -alpha is a root of the global Bernstein-Sato polynomial
5507@*       'alg2':  the multiplicity of -alpha as a root of the global Bernstein-Sato
5508@*                  polynomial of f. If -alpha is not a root, the output is 0.
5509@*       If eng <>0, @code{std} is used for Groebner basis computations,
5510@*       otherwise (and by default) @code{slimgb} is used.
5511DISPLAY: If printlevel=1, progress debug messages will be printed,
5512@*          if printlevel>=2, all the debug messages will be printed.
5513EXAMPLE: example checkRoot; shows examples
5514"
5515{
5516  int eng = 0;
5517  int chs = 0; // choice
5518  string algo = "alg1";
5519  string st;
5520  if ( size(#)>0 )
5521  {
5522   if ( typeof(#[1]) == "string" )
5523   {
5524     st = string(#[1]);
5525     if ( (st == "alg1") || (st == "ALG1") || (st == "Alg1") ||(st == "aLG1"))
5526     {
5527       algo = "alg1";
5528       chs  = 1;
5529     }
5530     if ( (st == "alg2") || (st == "ALG2") || (st == "Alg2") || (st == "aLG2"))
5531     {
5532       algo = "alg2";
5533       chs  = 1;
5534     }
5535     if (chs != 1)
5536     {
5537       // incorrect value of S
5538       print("Incorrect algorithm given, proceed with the default alg1");
5539       algo = "alg1";
5540     }
5541     // second arg
5542     if (size(#)>1)
5543     {
5544       // exists 2nd arg
5545       if ( typeof(#[2]) == "int" )
5546       {
5547         // the case: given alg, given engine
5548         eng = int(#[2]);
5549       }
5550       else
5551       {
5552         eng = 0;
5553       }
5554     }
5555     else
5556     {
5557       // no second arg
5558       eng = 0;
5559     }
5560   }
5561   else
5562   {
5563     if ( typeof(#[1]) == "int" )
5564     {
5565       // the case: default alg, engine
5566       eng = int(#[1]);
5567       // algo = "alg1";  //is already set
5568     }
5569     else
5570     {
5571       // incorr. 1st arg
5572       algo = "alg1";
5573     }
5574   }
5575  }
5576  // size(#)=0, i.e. there is no algorithm and no engine given
5577  //  eng = 0; algo = "alg1";  //are already set
5578  // int ppl = printlevel-voice+2;
5579// check assume: a is positive rational number
5580  if (!isRational(a))
5581  {
5582    ERROR("rational root expected for checking");
5583  }
5584  if (numerator(a) < 0 )
5585  {
5586    ERROR("expected positive -alpha");
5587    // the following is more user-friendly but less correct
5588    //    print("proceeding with the negated root");
5589    //    a = -a;
5590  }
5591  printlevel=printlevel+1;
5592  def save = basering;
5593  def @A = SannfsBM(F);
5594  setring @A;
5595  poly F = imap(save,F);
5596  number a = imap(save,a);
5597  if ( algo=="alg1")
5598  {
5599    int output = checkRoot1(LD,F,a,eng);
5600  }
5601  else
5602  {
5603    if ( algo=="alg2")
5604    {
5605      int output = checkRoot2(LD,F,a,eng);
5606    }
5607  }
5608  printlevel=printlevel-1;
5609  return(output);
5610}
5611example
5612{
5613  "EXAMPLE:"; echo = 2;
5614  printlevel=0;
5615  ring r = 0,(x,y),Dp;
5616  poly F = x^4+y^5+x*y^4;
5617  checkRoot(F,11/20);    // -11/20 is a root of bf
5618  poly G = x*y;
5619  checkRoot(G,1,"alg2"); // -1 is a root of bg with multiplicity 2
5620}
5621
5622proc checkRoot1(ideal I, poly F, number a, list #)
5623"USAGE:  checkRoot1(I,f,alpha [,eng]);  ideal I, poly f, number alpha, int eng
5624ASSUME:  Basering is D[s], I is the annihilator of f^s in D[s],
5625@* that is basering and I are the output of Sannfs-like procedure,
5626@* f is a polynomial in K[x] and alpha is a rational number.
5627RETURN:  int, 1 if -alpha is a root of the Bernstein-Sato polynomial of f
5628PURPOSE: check, whether alpha is a root of the global Bernstein-Sato polynomial of f
5629NOTE:  If eng <>0, @code{std} is used for Groebner basis computations,
5630@*       otherwise (and by default) @code{slimgb} is used.
5631DISPLAY: If printlevel=1, progress debug messages will be printed,
5632@*          if printlevel>=2, all the debug messages will be printed.
5633EXAMPLE: example checkRoot1; shows examples
5634"
5635{
5636  // to check: alpha is rational (has char 0 check inside)
5637  if (!isRational(a))
5638  {
5639    "ERROR: alpha must be a rational number!";
5640  }
5641  //  no qring
5642  if ( size(ideal(basering)) >0 )
5643  {
5644    "ERROR: no qring is allowed";
5645  }
5646  int eng = 0;
5647  if ( size(#)>0 )
5648  {
5649    if ( typeof(#[1]) == "int" )
5650    {
5651      eng = int(#[1]);
5652    }
5653  }
5654  int ppl = printlevel-voice+2;
5655  dbprint(ppl,"// -0-1- starting the procedure checkRoot1");
5656  def save = basering;
5657  int N = nvars(basering);
5658  int Nnew = N-1;
5659  int n = Nnew / 2;
5660  int i;
5661  string s;
5662  list RL = ringlist(basering);
5663  list L, Lord;
5664  list tmp;
5665  intvec iv;
5666  L[1] = RL[1];  // char
5667  L[4] = RL[4];  // char, minpoly
5668  // check whether basering is D[s]=K(_x,_Dx,s)
5669  list Name = RL[2];
5670//   for (i=1; i<=n; i++)
5671//   {
5672//     if ( bracket(var(i+n),var(i))!=1 )
5673//     {
5674//       ERROR("basering should be D[s]=K(_x,_Dx,s)");
5675//     }
5676//   }
5677  if ( Name[N]!="s" )
5678  {
5679    ERROR("the last variable of basering should be s");
5680  }
5681  // now, create the new vars
5682  list NName;
5683  for (i=1; i<=Nnew; i++)
5684  {
5685    NName[i] = Name[i];
5686  }
5687  L[2] = NName;
5688  kill Name,NName;
5689  // block ord (dp);
5690  tmp[1] = "dp"; // string
5691  s = "iv=";
5692  for (i=1; i<=Nnew; i++)
5693  {
5694    s = s+"1,";
5695  }
5696  s[size(s)]=";";
5697  execute(s);
5698  kill s;
5699  tmp[2]  = iv;
5700  Lord[1] = tmp;
5701  tmp[1]  = "C";
5702  iv      = 0;
5703  tmp[2]  = iv;
5704  Lord[2] = tmp;
5705  tmp     = 0;
5706  L[3]    = Lord;
5707  // we are done with the list
5708  def @R@ = ring(L);
5709  setring @R@;
5710  matrix @D[Nnew][Nnew];
5711  for (i=1; i<=n; i++)
5712  {
5713    @D[i,i+n]=1;
5714  }
5715  def @R = nc_algebra(1,@D);
5716  setring @R;
5717  kill @R@;
5718  dbprint(ppl,"// -1-1- the ring @R(_x,_Dx) is ready");
5719  dbprint(ppl-1, S);
5720  // create the ideal K = ann_D[s](f^s)_{s=-alpha} + < f >
5721  setring save;
5722  ideal K = subst(I,s,-a);
5723  dbprint(ppl,"// -1-2- the variable s has been substituted by "+string(-a));
5724  dbprint(ppl-1, K);
5725  K = NF(K,std(F));
5726  // make leadcoeffs positive
5727  for (i=1; i<=ncols(K); i++)
5728  {
5729    if ( leadcoef(K[i])<0 )
5730    {
5731      K[i] = -K[i];
5732    }
5733  }
5734  K = K,F;
5735  // ------------ the ideal K is ready ------------
5736  setring @R;
5737  ideal K = imap(save,K);
5738  dbprint(ppl,"// -1-3- starting the computation of a Groebner basis of K in @R");
5739  dbprint(ppl-1, K);
5740  ideal G = engine(K,eng);
5741  dbprint(ppl,"// -1-4- the Groebner basis has been computed");
5742  dbprint(ppl-1, G);
5743  return(G[1]!=1);
5744}
5745example
5746{
5747  "EXAMPLE:"; echo = 2;
5748  ring r = 0,(x,y),Dp;
5749  poly F = x^4+y^5+x*y^4;
5750  printlevel = 0;
5751  def A = Sannfs(F);
5752  setring A;
5753  poly F = imap(r,F);
5754  checkRoot1(LD,F,31/20);   // -31/20 is not a root of bs
5755  checkRoot1(LD,F,11/20);   // -11/20 is a root of bs
5756}
5757
5758proc checkRoot2 (ideal I, poly F, number a, list #)
5759"USAGE:  checkRoot2(I,f,a [,eng]);  I an ideal, f a poly, alpha a number, eng an optional int
5760ASSUME:  I is the annihilator of f^s in D[s], basering is D[s],
5761@* that is basering and I are the output os Sannfs-like procedure,
5762@* f is a polynomial in K[_x] and alpha is a rational number.
5763RETURN:  int, the multiplicity of -alpha as a root of the BS polynomial of f.
5764PURPOSE: check whether a rational number alpha is a root of the global Bernstein-
5765@* Sato polynomial of f and compute its multiplicity from the known Ann F^s in D[s]
5766NOTE:   If -alpha is not a root, the output is 0.
5767@*       If eng <>0, @code{std} is used for Groebner basis computations,
5768@*       otherwise (and by default) @code{slimgb} is used.
5769DISPLAY: If printlevel=1, progress debug messages will be printed,
5770@*          if printlevel>=2, all the debug messages will be printed.
5771EXAMPLE: example checkRoot2; shows examples
5772"
5773{
5774
5775
5776  // to check: alpha is rational (has char 0 check inside)
5777  if (!isRational(a))
5778  {
5779    "ERROR: alpha must be a rational number!";
5780  }
5781  //  no qring
5782  if ( size(ideal(basering)) >0 )
5783  {
5784    "ERROR: no qring is allowed";
5785  }
5786
5787  int eng = 0;
5788  if ( size(#)>0 )
5789  {
5790    if ( typeof(#[1]) == "int" )
5791    {
5792      eng = int(#[1]);
5793    }
5794  }
5795  int ppl = printlevel-voice+2;
5796  dbprint(ppl,"// -0-1- starting the procedure checkRoot2");
5797  def save = basering;
5798  int N = nvars(basering);
5799  int n = (N-1) / 2;
5800  int i;
5801  string s;
5802  list RL = ringlist(basering);
5803  list L, Lord;
5804  list tmp;
5805  intvec iv;
5806  L[1] = RL[1];  // char
5807  L[4] = RL[4];  // char, minpoly
5808  // check whether basering is D[s]=K(_x,_Dx,s)
5809  list Name = RL[2];
5810  for (i=1; i<=n; i++)
5811  {
5812    if ( bracket(var(i+n),var(i))!=1 )
5813    {
5814      ERROR("basering should be D[s]=K(_x,_Dx,s)");
5815    }
5816  }
5817  if ( Name[N]!="s" )
5818  {
5819    ERROR("the last variable of basering should be s");
5820  }
5821  // now, create the new vars
5822  L[2] = Name;
5823  kill Name;
5824  // block ord (dp);
5825  tmp[1] = "dp"; // string
5826  s = "iv=";
5827  for (i=1; i<=N; i++)
5828  {
5829    s = s+"1,";
5830  }
5831  s[size(s)]=";";
5832  execute(s);
5833  kill s;
5834  tmp[2]  = iv;
5835  Lord[1] = tmp;
5836  tmp[1]  = "C";
5837  iv      = 0;
5838  tmp[2]  = iv;
5839  Lord[2] = tmp;
5840  tmp     = 0;
5841  L[3]    = Lord;
5842  // we are done with the list
5843  def @R@ = ring(L);
5844  setring @R@;
5845  matrix @D[N][N];
5846  for (i=1; i<=n; i++)
5847  {
5848    @D[i,i+n]=1;
5849  }
5850  def @R = nc_algebra(1,@D);
5851  setring @R;
5852  kill @R@;
5853  dbprint(ppl,"// -1-1- the ring @R(_x,_Dx,s) is ready");
5854  dbprint(ppl-1, @R);
5855  // now, continue with the algorithm
5856  ideal I = imap(save,I);
5857  poly F = imap(save,F);
5858  number a = imap(save,a);
5859  ideal II = NF(I,std(F));
5860  // make leadcoeffs positive
5861  for (i=1; i<=ncols(II); i++)
5862  {
5863    if ( leadcoef(II[i])<0 )
5864    {
5865      II[i] = -II[i];
5866    }
5867  }
5868  ideal J,G;
5869  int m;  // the output (multiplicity)
5870  dbprint(ppl,"// -2- starting the bucle");
5871  for (i=0; i<=n; i++)  // the multiplicity has to be <= n
5872  {
5873    // create the ideal Ji = ann_D[s](f^s) + < f, (s+alpha)^{i+1} >
5874    // (s+alpha)^i in Ji <==> -alpha is a root with multiplicity >= i
5875    J = II,F,(s+a)^(i+1);
5876    // ------------ the ideal Ji is ready -----------
5877    dbprint(ppl,"// -2-"+string(i+1)+"-1- starting the computation of a Groebner basis of J"+string(i)+" in @R");
5878    dbprint(ppl-1, J);
5879    G = engine(J,eng);
5880    dbprint(ppl,"// -2-"+string(i+1)+"-2- the Groebner basis has been computed");
5881    dbprint(ppl-1, G);
5882    if ( NF((s+a)^i,G)==0 )
5883    {
5884      dbprint(ppl,"// -2-"+string(i+1)+"-3- the number "+string(-a)+" has not multiplicity "+string(i+1));
5885      m = i;
5886      break;
5887    }
5888    dbprint(ppl,"// -2-"+string(i+1)+"-3- the number "+string(-a)+" has multiplicity at least "+string(i+1));
5889  }
5890  dbprint(ppl,"// -3- the bucle has finished");
5891  return(m);
5892}
5893example
5894{
5895  "EXAMPLE:"; echo = 2;
5896  ring r = 0,(x,y,z),Dp;
5897  poly F = x*y*z;
5898  printlevel = 0;
5899  def A = Sannfs(F);
5900  setring A;
5901  poly F = imap(r,F);
5902  checkRoot2(LD,F,1);    // -1 is a root of bs with multiplicity 3
5903  checkRoot2(LD,F,1/3);  // -1/3 is not a root
5904}
5905
5906proc checkFactor(ideal I, poly F, poly q, list #)
5907"USAGE:  checkFactor(I,f,qs [,eng]);  I an ideal, f a poly, qs a poly, eng an optional int
5908ASSUME:  checkFactor is called from the basering, created by Sannfs-like proc,
5909@* that is, from the Weyl algebra in x1,..,xN,d1,..,dN tensored with K[s].
5910@* The ideal I is the annihilator of f^s in D[s], that is the ideal, computed
5911@* by Sannfs-like procedure (usually called LD there).
5912@* Moreover, f is a polynomial in K[x1,..,xN] and qs is a polynomial in K[s].
5913RETURN:  int, 1 if qs is a factor of the global Bernstein polynomial of f and 0 otherwise
5914PURPOSE: check whether a univariate polynomial qs is a factor of the
5915@*  Bernstein-Sato polynomial of f without explicit knowledge of the latter.
5916NOTE:    If eng <>0, @code{std} is used for Groebner basis computations,
5917@*       otherwise (and by default) @code{slimgb} is used.
5918DISPLAY: If printlevel=1, progress debug messages will be printed,
5919@*          if printlevel>=2, all the debug messages will be printed.
5920EXAMPLE: example checkFactor; shows examples
5921"
5922{
5923
5924  // ASSUME too complicated, cannot check it.
5925
5926  int eng = 0;
5927  if ( size(#)>0 )
5928  {
5929    if ( typeof(#[1]) == "int" )
5930    {
5931      eng = int(#[1]);
5932    }
5933  }
5934  int ppl = printlevel-voice+2;
5935  def @R2 = basering;
5936  int N = nvars(@R2);
5937  int i;
5938  // we're in D_n[s], where the elim ord for s is set
5939  dbprint(ppl,"// -0-1- starting the procedure checkFactor");
5940  dbprint(ppl,"// -1-1- the ring @R2(_x,_Dx,s) is ready");
5941  dbprint(ppl-1, @R2);
5942  // create the ideal J = ann_D[s](f^s) + < f,q >
5943  ideal J = NF(I,std(F));
5944  // make leadcoeffs positive
5945  for (i=1; i<=ncols(J); i++)
5946  {
5947    if ( leadcoef(J[i])<0 )
5948    {
5949      J[i] = -J[i];
5950    }
5951  }
5952  J = J,F,q;
5953  // ------------ the ideal J is ready -----------
5954  dbprint(ppl,"// -1-2- starting the elimination of _x,_Dx in @R2");
5955  dbprint(ppl-1, J);
5956  ideal G = engine(J,eng);
5957  ideal K = nselect(G,1..N-1);
5958  kill J,G;
5959  dbprint(ppl,"// -1-3- _x,_Dx are eliminated");
5960  dbprint(ppl-1, K);
5961  //q is a factor of bs if and only if K = < q >
5962  //K = normalize(K);
5963  //q = normalize(q);
5964  //return( (K[1]==q) );
5965  return( NF(K[1],std(q))==0 );
5966}
5967example
5968{
5969  "EXAMPLE:"; echo = 2;
5970  ring r = 0,(x,y),Dp;
5971  poly F = x^4+y^5+x*y^4;
5972  printlevel = 0;
5973  def A = Sannfs(F);
5974  setring A;
5975  poly F = imap(r,F);
5976  checkFactor(LD,F,20*s+31);     // -31/20 is not a root of bs
5977  checkFactor(LD,F,20*s+11);     // -11/20 is a root of bs
5978  checkFactor(LD,F,(20*s+11)^2); // the multiplicity of -11/20 is 1
5979}
5980
5981proc varNum(string s)
5982"USAGE:  varNum(s);  string s
5983RETURN:  int
5984PURPOSE: returns the number of the variable with the name s
5985@*  among the variables of basering or 0 if there is no such variable
5986EXAMPLE: example varNum; shows examples
5987"
5988{
5989  int i;
5990  for (i=1; i<= nvars(basering); i++)
5991  {
5992    if ( string(var(i)) == s )
5993    {
5994      return(i);
5995    }
5996  }
5997  return(0);
5998}
5999example
6000{
6001  "EXAMPLE:"; echo = 2;
6002  ring X = 0,(x,y1,t,z(0),z,tTa),dp;
6003  varNum("z");
6004  varNum("t");
6005  varNum("xyz");
6006}
6007
6008static proc indAR(list L, int n)
6009"USAGE:  indAR(L,n);  list L, int n
6010RETURN:  list
6011PURPOSE: computes arrangement inductively, using L and
6012@* var(n) as the next variable
6013ASSUME: L has a structure of an arrangement
6014EXAMPLE: example indAR; shows examples
6015"
6016{
6017  if ( (n<2) || (n>nvars(basering)) )
6018  {
6019    ERROR("incorrect n");
6020  }
6021  int sl = size(L);
6022  list K;
6023  ideal tmp;
6024  poly @t = L[sl][1] + var(n); //1 elt
6025  K[sl+1] = ideal(@t);
6026  tmp = L[1]+var(n);
6027  K[1] = tmp; tmp = 0;
6028  int i,j,sI;
6029  ideal I;
6030  for(i=sl; i>=2; i--)
6031  {
6032    I = L[i-1]; sI = size(I);
6033    for(j=1; j<=sI; j++)
6034    {
6035      I[j] = I[j] + var(n);
6036    }
6037    tmp  = L[i],I;
6038    K[i] = tmp;
6039    I = 0; tmp = 0;
6040  }
6041  kill I; kill tmp;
6042  return(K);
6043}
6044example
6045{
6046  "EXAMPLE:"; echo = 2;
6047  ring r = 0,(x,y,z,t,v),dp;
6048  list L;
6049  L[1] = ideal(x);
6050  list K = indAR(L,2);
6051  K;
6052  list M = indAR(K,3);
6053  M;
6054  M = indAR(M,4);
6055  M;
6056}
6057
6058proc isRational(number n)
6059"USAGE:  isRational(n); n number
6060RETURN:  int
6061PURPOSE: determine whether n is a rational number,
6062@* that is it does not contain parameters.
6063ASSUME: ground field is of characteristic 0
6064EXAMPLE: example indAR; shows examples
6065"
6066{
6067  if (char(basering) != 0)
6068  {
6069    ERROR("The ground field must be of characteristic 0!");
6070  }
6071  number dn = denominator(n);
6072  number nn = numerator(n);
6073  return( ((int(dn)==dn) && (int(nn)==nn)) );
6074}
6075example
6076{
6077  "EXAMPLE:"; echo = 2;
6078  ring r = (0,a),(x,y),dp;
6079  number n1 = 11/73;
6080  isRational(n1);
6081  number n2 = (11*a+3)/72;
6082  isRational(n2);
6083}
6084
6085proc bernsteinLift(ideal I, poly F, list #)
6086"USAGE:  bernsteinLift(I, F [,eng]);  I an ideal, F a poly, eng an optional int
6087RETURN:  list
6088PURPOSE: compute the (multiple of) Bernstein-Sato polynomial with lift-like method,
6089@* based on the output of Sannfs-like procedure
6090NOTE:  the output list contains the roots with multiplicities of the candidate
6091@* for being Bernstein-Sato polynomial of f.
6092@*  If eng <>0, @code{std} is used for Groebner basis computations,
6093@*  otherwise and by default @code{slimgb} is used.
6094@*  If printlevel=1, progress debug messages will be printed,
6095@*  if printlevel>=2, all the debug messages will be printed.
6096EXAMPLE: example bernsteinLift; shows examples
6097"
6098{
6099  // assume: s is the last variable! check in the code
6100  int eng = 0;
6101  if ( size(#)>0 )
6102  {
6103    if ( typeof(#[1]) == "int" )
6104    {
6105      eng = int(#[1]);
6106    }
6107  }
6108  def @R2 = basering;
6109  int Nnew = nvars(@R2);
6110  int N = Nnew/2;
6111  int ppl = printlevel-voice+2;
6112  // we're in D_n[s], where the elim ord for s is set
6113  // create D_n(s)
6114  // create the ordinary Weyl algebra and put the result into it,
6115  // keep: N, i,j,s, tmp, RL
6116  Nnew = Nnew - 1; // former 2*N;
6117  list L = 0;
6118  list Lord, tmp;
6119  intvec iv; int i;
6120  list RL = ringlist(basering);
6121  // if we work over alg. extension => problem!
6122  if (size(RL[1]) > 1)
6123  {
6124    ERROR("cannot work over algebraic field extension");
6125  }
6126  tmp[1] = RL[1]; // char
6127  tmp[2] = list("s");
6128  tmp[3] = list(list("lp",int(1)));
6129  tmp[4] = ideal(0);
6130  L[1] = tmp; // field
6131  tmp = 0;
6132  L[4] = RL[4];  // factor ideal
6133
6134  // check whether vars have admissible names -> done earlier
6135  // list Name = RL[2]M
6136  // DName is defined earlier
6137  list NName; // = RL[2]; // skip the last var 's'
6138  for (i=1; i<=Nnew; i++)
6139  {
6140    NName[i] =  RL[2][i];
6141  }
6142  L[2] = NName;
6143  // (c, ) ordering:
6144  tmp[1]  = "c";
6145  iv = 0;
6146  tmp[2]  = iv;
6147  Lord[1] = tmp;
6148  tmp=0;
6149  // dp ordering;
6150  string s = "iv=";
6151  for (i=1; i<=Nnew; i++)
6152  {
6153    s = s+"1,";
6154  }
6155  s[size(s)] = ";";
6156  execute(s);
6157  tmp     = 0;
6158  tmp[1]  = "dp";  // string
6159  tmp[2]  = iv;  // intvec
6160  Lord[2] = tmp;
6161  kill s;
6162  tmp     = 0;
6163  L[3]    = Lord;
6164  // we are done with the list
6165  // Add: Plural part
6166  def @R4@ = ring(L);
6167  setring @R4@;
6168  matrix @D[Nnew][Nnew];
6169  for (i=1; i<=N; i++)
6170  {
6171    @D[i,N+i]=1;
6172  }
6173  def @R4 = nc_algebra(1,@D);
6174  setring @R4;
6175  kill @R4@;
6176  dbprint(ppl,"// -3-1- the ring K(s)<x,dx> is ready");
6177  dbprint(ppl-1, @R4);
6178  // map things correctly, using names
6179  ideal J = imap(@R2, I), imap(@R2,F);
6180  module M;
6181  // make leadcoeffs positive
6182  for (i=1; i<= ncols(J); i++)
6183  {
6184    if (J[i]!=0)
6185    {
6186      M[i] = J[i]*gen(1) + gen(1+i);
6187    }
6188  }
6189  dbprint(ppl,"// -3-2- starting GB of the assoc. module M");
6190  M = engine(M,eng);
6191  dbprint(ppl,"// -3-3- finished GB of the assoc. module M");
6192  dbprint(ppl-1, M);
6193  // now look for (1) entry with 1st comp nonzero
6194  // determine whether there are several 1st comps nonzero
6195  module M2;
6196  for (i=1; i<= ncols(M); i++)
6197  {
6198    if (M[1,i]!=0)
6199    {
6200      M2 = M2, M[i];
6201    }
6202  }
6203  M2 = simplify(M2,2); // skip 0s
6204  if (ncols(M2) > 1)
6205  {
6206    dbprint(ppl,"// -*- more than 1 element with nonzero leading component");
6207    option(redSB);    option(redTail); // set them back?
6208    M2 = interred(M2);
6209    if (ncols(M2) > 1)
6210    {
6211      ERROR("more than one leading component after interred: assume violation!");
6212    }
6213    if (leadexp(M2[1]) != 0)
6214    {
6215      ERROR("nonconstant entry after interred: assume violation!");
6216    }
6217  }
6218  // now there's only one el-t with leadcomp<>0
6219  vector V = M2[1];
6220  number bcand = leadcoef(V[1]); // 1st component
6221  V[1]=0;
6222  number ct = content(V); // content of the cofactors
6223  // addition by VL: indeed just gcd of denominators is needed!!!
6224  // hence TODO
6225  poly CF = ct*V[ncols(J)]; // polynomial in K[s]<x,dx>, cofactor to F
6226  dbprint(ppl,"// -3-4- the cofactor candidate found");
6227  dbprint(ppl-1,CF);
6228  dbprint(ppl,"// -3-5- the entry as it is");
6229  dbprint(ppl-1,bcand);
6230  bcand = bcand*ct; // a product of both
6231  dbprint(ppl,"// -3-6- the content of the rest vector");
6232  dbprint(ppl-1,ct);
6233  ring @R3 = 0,s,dp;
6234  dbprint(ppl,"// -4-1- the ring @R3 i.e. K[s] is ready");
6235  poly bcand = imap(@R4,bcand);
6236  dbprint(ppl,"// -4-2- factorization");
6237  list P = factorize(bcand);          //with constants and multiplicities
6238  ideal bs; intvec m;             //the Bernstein polynomial is monic, so we are not interested in constants
6239  for (i=2; i<= size(P[1]); i++)  //we delete P[1][1] and P[2][1]
6240  {
6241    bs[i-1] = P[1][i];
6242    m[i-1]  = P[2][i];
6243  }
6244  bs = normalize(bs); bs = -subst(bs,s,0); // to get roots only
6245  setring @R2; // the ring the story started with
6246  ideal bs = imap(@R3,bs); // intvec m is global
6247  intvec mm = m; m = 0;
6248  kill @R3; // kills m as well....
6249  list @L = list(bs, mm);
6250  // look for (2) return the GB of syzygies?
6251  return(@L);
6252}
6253example
6254{ "EXAMPLE:"; echo = 2;
6255  ring r = 0,(x,y,z),Dp;
6256  poly F = x^3+y^3+z^3;
6257  printlevel = 0;
6258  def A = Sannfs(F);   setring A;
6259  LD;
6260  poly F = imap(r,F);
6261  list L  = bernsteinLift(LD,F); L;
6262  poly bs = fl2poly(L,"s"); bs; // the candidate for Bernstein-Sato polynomial
6263}
6264
6265/// ****** EXAMPLES ************
6266
6267/*
6268
6269//static proc exCheckGenericity()
6270{
6271  LIB "control.lib";
6272  ring r = (0,a,b,c),x,dp;
6273  poly p = (x-a)*(x-b)*(x-c);
6274  def A = annfsBM(p);
6275  setring A;
6276  ideal J = slimgb(LD);
6277  matrix T = lift(LD,J);
6278  T = normalize(T);
6279  genericity(T);
6280  // Ann =x^3*Dx+3*x^2*t*Dt+(-a-b-c)*x^2*Dx+(-2*a-2*b-2*c)*x*t*Dt+3*x^2+(a*b+a*c+b*c)*x*Dx+(a*b+a*c+b*c)*t*Dt+(-2*a-2*b-2*c)*x+(-a*b*c)*Dx+(a*b+a*c+b*c)
6281  // genericity: g = a2-ab-ac+b2-bc+c2 =0
6282  // g = (a -(b+c)/2)^2 + (3/4)*(b-c)^2;
6283  // g ==0 <=> a=b=c
6284  // indeed, Ann = (x-a)^2*(x*Dx+3*t*Dt+(-a)*Dx+3)
6285  // --------------------------------------------
6286  // BUT a direct computation shows
6287  // when a=b=c,
6288  // Ann = x*Dx+3*t*Dt+(-a)*Dx+3
6289}
6290
6291//static proc exOT_17()
6292{
6293  // Oaku-Takayama, p.208
6294  ring R = 0,(x,y),dp;
6295  poly F = x^3-y^2; // x^2+x*y+y^2;
6296  option(prot);
6297  option(mem);
6298  //  option(redSB);
6299  def A = annfsOT(F,0);
6300  setring A;
6301  LD;
6302  gkdim(LD); // a holonomic check
6303  //  poly F = x^3-y^2; // = x^7 - y^5; // x^3-y^4; // x^5 - y^4;
6304}
6305
6306//static proc exOT_16()
6307{
6308  // Oaku-Takayama, p.208
6309  ring R = 0,(x),dp;
6310  poly F = x*(1-x);
6311  option(prot);
6312  option(mem);
6313  //  option(redSB);
6314  def A = annfsOT(F,0);
6315  setring A;
6316  LD;
6317  gkdim(LD); // a holonomic check
6318}
6319
6320//static proc ex_bcheck()
6321{
6322  ring R = 0,(x,y),dp;
6323  poly F = x*y*(x+y);
6324  option(prot);
6325  option(mem);
6326  int eng = 0;
6327  //  option(redSB);
6328  def A = annfsOT(F,eng);
6329  setring A;
6330  LD;
6331}
6332
6333//static proc ex_bcheck2()
6334{
6335  ring R = 0,(x,y),dp;
6336  poly F = x*y*(x+y);
6337  int eng = 0;
6338  def A = annfsBM(F,eng);
6339  setring A;
6340  LD;
6341}
6342
6343//static proc ex_BMI()
6344{
6345  // a hard example
6346  ring r = 0,(x,y),Dp;
6347  poly F1 = (x2-y3)*(x3-y2);
6348  poly F2 = (x2-y3)*(xy4+y5+x4);
6349  ideal F = F1,F2;
6350  def A = annfsBMI(F);
6351  setring A;
6352  LD;
6353  BS;
6354}
6355
6356//static proc ex2_BMI()
6357{
6358  // this example was believed to be intractable in 2005 by Gago-Vargas, Castro and Ucha
6359  ring r = 0,(x,y),Dp;
6360  option(prot);
6361  option(mem);
6362  ideal F = x2+y3,x3+y2;
6363  printlevel = 2;
6364  def A = annfsBMI(F);
6365  setring A;
6366  LD;
6367  BS;
6368}
6369
6370//static proc ex_operatorBM()
6371{
6372  ring r = 0,(x,y,z,w),Dp;
6373  poly F = x^3+y^3+z^2*w;
6374  printlevel = 0;
6375  def A = operatorBM(F);
6376  setring A;
6377  F; // the original polynomial itself
6378  LD; // generic annihilator
6379  LD0; // annihilator
6380  bs; // normalized Bernstein poly
6381  BS; // root and multiplicities of the Bernstein poly
6382  PS; // the operator, s.t. PS*F^{s+1} = bs*F^s mod LD
6383  reduce(PS*F-bs,LD); // check the property of PS
6384}
6385
6386*/
Note: See TracBrowser for help on using the repository browser.