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

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