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

spielwiese
Last change on this file since e5af4b5 was e5af4b5, checked in by Viktor Levandovskyy <levandov@…>, 13 years ago
*levandov: annfsBMI changed, now being able to compute B sigma ideal git-svn-id: file:///usr/local/Singular/svn/trunk@14331 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100755
File size: 164.5 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). Otherwise, and by
2454@*       default, the ideal B (cf. the paper) is computed.
2455@*       If the output ideal happens to be principal, the list of factors
2456@*       with their multiplicities is returned instead of the ideal.
2457@*       If printlevel=1, progress debug messages will be printed,
2458@*       if printlevel>=2, all the debug messages will be printed.
2459EXAMPLE: example annfsBMI; shows examples
2460"
2461{
2462  int eng = 0;
2463  int met = 0;
2464  if ( size(#)>0 )
2465  {
2466    if ( typeof(#[1]) == "int" )
2467    {
2468      eng = int(#[1]);
2469    }
2470    if ( size(#)>1 )
2471    {
2472      if ( typeof(#[2]) == "int" )
2473      {
2474        met = int(#[2]);
2475      }
2476    }
2477  }
2478  // returns a list with a ring and an ideal LD in it
2479  int ppl = printlevel-voice+2;
2480  //  printf("plevel :%s, voice: %s",printlevel,voice);
2481  def save = basering;
2482  int N = nvars(basering);
2483  int P = size(F);  //if F has some generators which are zero, int P = ncols(I);
2484  int Nnew = 2*N+2*P;
2485  int i,j;
2486  string s;
2487  list RL = ringlist(basering);
2488  list L, Lord;
2489  list tmp;
2490  intvec iv;
2491  L[1] = RL[1];  //char
2492  L[4] = RL[4];  //char, minpoly
2493  // check whether vars have admissible names
2494  list Name  = RL[2];
2495  list RName;
2496  for (j=1; j<=P; j++)
2497  {
2498    RName[j] = "t("+string(j)+")";
2499    RName[j+P] = "s("+string(j)+")";
2500  }
2501  for(i=1; i<=N; i++)
2502  {
2503    for(j=1; j<=size(RName); j++)
2504    {
2505      if (Name[i] == RName[j])
2506      { ERROR("Variable names should not include t(i),s(i)"); }
2507    }
2508  }
2509  // now, create the names for new vars
2510  list DName;
2511  for(i=1; i<=N; i++)
2512  {
2513    DName[i] = "D"+Name[i];  //concat
2514  }
2515  list NName = RName + Name + DName;
2516  L[2]   = NName;
2517  // Name, Dname will be used further
2518  kill NName;
2519  // block ord (lp(P),dp);
2520  tmp[1] = "lp";  //string
2521  s      = "iv=";
2522  for (i=1; i<=2*P; i++)
2523  {
2524    s = s+"1,";
2525  }
2526  s[size(s)]= ";";
2527  execute(s);
2528  tmp[2] = iv;  //intvec
2529  Lord[1] = tmp;
2530  // continue with dp 1,1,1,1...
2531  tmp[1] = "dp";  //string
2532  s      = "iv=";
2533  for (i=1; i<=Nnew; i++)  //actually i<=2*N
2534  {
2535    s = s+"1,";
2536  }
2537  s[size(s)]= ";";
2538  execute(s);
2539  kill s;
2540  tmp[2]  = iv;
2541  Lord[2] = tmp;
2542  tmp[1]  = "C";
2543  iv      = 0;
2544  tmp[2]  = iv;
2545  Lord[3] = tmp;
2546  tmp     = 0;
2547  L[3]    = Lord;
2548  // we are done with the list
2549  def @R@ = ring(L);
2550  setring @R@;
2551  matrix @D[Nnew][Nnew];
2552  for (i=1; i<=P; i++)
2553  {
2554    @D[i,i+P] = t(i);
2555  }
2556  for(i=1; i<=N; i++)
2557  {
2558    @D[2*P+i,2*P+N+i] = 1;
2559  }
2560  // L[5] = matrix(UpOneMatrix(Nnew));
2561  // L[6] = @D;
2562  def @R = nc_algebra(1,@D);
2563  setring @R;
2564  kill @R@;
2565  dbprint(ppl,"// -1-1- the ring @R(_t,_s,_x,_Dx) is ready");
2566  dbprint(ppl-1, @R);
2567  // create the ideal I
2568  ideal  F = imap(save,F);
2569  ideal I = t(1)*F[1]+s(1);
2570  for (j=2; j<=P; j++)
2571  {
2572    I = I, t(j)*F[j]+s(j);
2573  }
2574  poly p,q;
2575  for (i=1; i<=N; i++)
2576  {
2577    p=0;
2578    for (j=1; j<=P; j++)
2579    {
2580      q = t(j);
2581      q = diff(F[j],var(2*P+i))*q;
2582      p = p + q;
2583    }
2584    I = I, var(2*P+N+i) + p;
2585  }
2586  // -------- the ideal I is ready ----------
2587  dbprint(ppl,"// -1-2- starting the elimination of "+string(t(1..P))+" in @R");
2588  dbprint(ppl-1, I);
2589  ideal J = engine(I,eng);
2590  ideal K = nselect(J,1..P);
2591  kill I,J;
2592  dbprint(ppl,"// -1-3- all t(i) are eliminated");
2593  dbprint(ppl-1, K);  //K is without t(i)
2594  // ----------- the ring @R2 ------------
2595  // _x, _Dx,s;  elim.ord for _x,_Dx.
2596  // keep: N, i,j,s, tmp, RL
2597  setring save;
2598  Nnew = 2*N+P;
2599  kill Lord, tmp, iv, RName;
2600  list Lord, tmp;
2601  intvec iv;
2602  L[1] = RL[1];  //char
2603  L[4] = RL[4];  //char, minpoly
2604  // check whether vars hava admissible names -> done earlier
2605  // now, create the names for new var
2606  for (j=1; j<=P; j++)
2607  {
2608    tmp[j] = "s("+string(j)+")";
2609  }
2610  // DName is defined earlier
2611  list NName = Name + DName + tmp;
2612  L[2] = NName;
2613  tmp = 0;
2614  // block ord (dp(N),dp);
2615  string s = "iv=";
2616  for (i=1; i<=Nnew-P; i++)
2617  {
2618    s = s+"1,";
2619  }
2620  s[size(s)]=";";
2621  execute(s);
2622  tmp[1] = "dp";  //string
2623  tmp[2] = iv;    //intvec
2624  Lord[1] = tmp;
2625  // continue with dp 1,1,1,1...
2626  tmp[1] = "dp";  //string
2627  s[size(s)] = ",";
2628  for (j=1; j<=P; j++)
2629  {
2630    s = s+"1,";
2631  }
2632  s[size(s)]=";";
2633  execute(s);
2634  kill s;
2635  kill NName;
2636  tmp[2]  = iv;
2637  Lord[2] = tmp;
2638  tmp[1]  = "C";
2639  iv      = 0;
2640  tmp[2]  = iv;
2641  Lord[3] = tmp;
2642  tmp     = 0;
2643  L[3]    = Lord;
2644  // we are done with the list. Now add a Plural part
2645  def @R2@ = ring(L);
2646  setring @R2@;
2647  matrix @D[Nnew][Nnew];
2648  for (i=1; i<=N; i++)
2649  {
2650    @D[i,N+i]=1;
2651  }
2652  def @R2 = nc_algebra(1,@D);
2653  setring @R2;
2654  kill @R2@;
2655  dbprint(ppl,"// -2-1- the ring @R2(_x,_Dx,_s) is ready");
2656  dbprint(ppl-1, @R2);
2657//  ideal MM = maxideal(1);
2658//  MM = 0,s,MM;
2659//  map R01 = @R, MM;
2660//  ideal K = R01(K);
2661  ideal F = imap(save,F);  // maybe ideal F = R01(I); ?
2662  ideal K = imap(@R,K);    // maybe ideal K = R01(I); ?
2663  if (met)
2664  {
2665    poly f=1;
2666    for (j=1; j<=P; j++)
2667    {
2668      f = f*F[j];
2669    }
2670    K = K,f;       // to compute B (Bernstein-Sato ideal)
2671    dbprint(ppl,"// -2-1-1 computing the ideal B from Castro-Ucha");
2672  }
2673  else
2674  {
2675  //K = K,F;     // to compute Bsigma (see "On the computation of Bernstein-Sato ideals"; Castro, Ucha)
2676    K = K,F;
2677    dbprint(ppl,"// -2-1-1 computing the ideal B-Sigma from Castro-Ucha");
2678  }
2679  //j=2;         // for example
2680  //K = K,F[j];  // to compute Bj (see "On the computation of Bernstein-Sato ideals"; Castro, Ucha)
2681  dbprint(ppl,"// -2-2- starting the elimination of _x,_Dx in @R2");
2682  dbprint(ppl-1, K);
2683  ideal M = engine(K,eng);
2684  ideal K2 = nselect(M,1..Nnew-P);
2685  kill K,M;
2686  dbprint(ppl,"// -2-3- _x,_Dx are eliminated in @R2");
2687  dbprint(ppl-1, K2);
2688  // the ring @R3 and factorize
2689  ring @R3 = 0,s(1..P),dp;
2690  dbprint(ppl,"// -3-1- the ring @R3(_s) is ready");
2691  ideal K3 = imap(@R2,K2);
2692  if (ncols(K3)==1)
2693  {
2694    poly p = K3[1];
2695    dbprint(ppl,"// -3-2- the Bernstein ideal is principal");
2696    dbprint(ppl,"// -3-2-1- factorization");
2697    // Warning: now P is an integer
2698    list Q = factorize(p);         //with constants and multiplicities
2699    ideal bs; intvec m;
2700    for (i=2; i<=size(Q[1]); i++)  //we delete Q[1][1] and Q[2][1]
2701    {
2702      bs[i-1] = Q[1][i];
2703      m[i-1]  = Q[2][i];
2704    }
2705    //  "--------- Q-ideal factorizes into ---------";  list(bs,m);
2706    list BS = bs,m;
2707  }
2708  else
2709  {
2710    // conjecture for some ideals: the Bernstein ideal is principal
2711    dbprint(ppl,"// -3-2- the Bernstein ideal is not principal");
2712    ideal BS = K3;
2713  }
2714  // create the ring @R4(_x,_Dx,_s) and put the result into it,
2715  // _x, _Dx,s;  ord "dp".
2716  // keep: N, i,j,s, tmp, RL
2717  setring save;
2718  Nnew = 2*N+P;
2719  // list RL = ringlist(save);  //is defined earlier
2720  kill Lord, tmp, iv;
2721  L = 0;
2722  list Lord, tmp;
2723  intvec iv;
2724  L[1] = RL[1];  //char
2725  L[4] = RL[4];  //char, minpoly
2726  // check whether vars hava admissible names -> done earlier
2727  // now, create the names for new var
2728  for (j=1; j<=P; j++)
2729  {
2730    tmp[j] = "s("+string(j)+")";
2731  }
2732  // DName is defined earlier
2733  list NName = Name + DName + tmp;
2734  L[2] = NName;
2735  tmp = 0;
2736  // dp ordering;
2737  string s = "iv=";
2738  for (i=1; i<=Nnew; i++)
2739  {
2740    s = s+"1,";
2741  }
2742  s[size(s)]=";";
2743  execute(s);
2744  kill s;
2745  kill NName;
2746  tmp[1] = "dp";  //string
2747  tmp[2] = iv;    //intvec
2748  Lord[1] = tmp;
2749  tmp[1]  = "C";
2750  iv      = 0;
2751  tmp[2]  = iv;
2752  Lord[2] = tmp;
2753  tmp     = 0;
2754  L[3]    = Lord;
2755  // we are done with the list. Now add a Plural part
2756  def @R4@ = ring(L);
2757  setring @R4@;
2758  matrix @D[Nnew][Nnew];
2759  for (i=1; i<=N; i++)
2760  {
2761    @D[i,N+i]=1;
2762  }
2763  def @R4 = nc_algebra(1,@D);
2764  setring @R4;
2765  kill @R4@;
2766  dbprint(ppl,"// -4-1- the ring @R4i(_x,_Dx,_s) is ready");
2767  dbprint(ppl-1, @R4);
2768  ideal K4 = imap(@R,K);
2769  option(redSB);
2770  dbprint(ppl,"// -4-2- the final cosmetic std");
2771  K4 = engine(K4,eng);  //std does the job too
2772  // total cleanup
2773  kill @R;
2774  kill @R2;
2775  def BS = imap(@R3,BS);
2776  export BS;
2777  kill @R3;
2778  ideal LD = K4;
2779  export LD;
2780  return(@R4);
2781}
2782example
2783{
2784  "EXAMPLE:"; echo = 2;
2785  ring r = 0,(x,y),Dp;
2786  ideal F = x,y,x+y;
2787  printlevel = 0;
2788  def A = annfsBMI(F);    setring A;
2789  LD; // annihilator
2790  BS; // Bernstein-Sato ideal
2791  // now, let us compute B-Sigma ideal
2792  setring r;
2793  def Sigma = annfsBMI(F,0,1); setring Sigma;
2794  LD; // annihilator
2795  BS; // Bernstein-Sato B-Sigma ideal
2796}
2797
2798proc annfsOT(poly F, list #)
2799"USAGE:  annfsOT(f [,eng]);  f a poly, eng an optional int
2800RETURN:  ring
2801PURPOSE: compute the D-module structure of basering[1/f]*f^s,
2802@* according to the algorithm by Oaku and Takayama
2803NOTE:    activate the output ring with the @code{setring} command. In this ring,
2804@*       - the ideal LD (which is a Groebner basis) is the needed D-module structure,
2805@*         which is obtained by substituting the minimal integer root of a Bernstein
2806@*         polynomial into the s-parametric ideal;
2807@*       - the list BS contains roots with multiplicities of a Bernstein polynomial of f.
2808@*       If eng <>0, @code{std} is used for Groebner basis computations,
2809@*       otherwise, and by default @code{slimgb} is used.
2810@*       If printlevel=1, progress debug messages will be printed,
2811@*       if printlevel>=2, all the debug messages will be printed.
2812EXAMPLE: example annfsOT; shows examples
2813"
2814{
2815  int eng = 0;
2816  if ( size(#)>0 )
2817  {
2818    if ( typeof(#[1]) == "int" )
2819    {
2820      eng = int(#[1]);
2821    }
2822  }
2823  // returns a list with a ring and an ideal LD in it
2824  int ppl = printlevel-voice+2;
2825  //  printf("plevel :%s, voice: %s",printlevel,voice);
2826  def save = basering;
2827  int N = nvars(basering);
2828  int Nnew = 2*(N+2);
2829  int i,j;
2830  string s;
2831  list RL = ringlist(basering);
2832  list L, Lord;
2833  list tmp;
2834  intvec iv;
2835  L[1] = RL[1]; // char
2836  L[4] = RL[4]; // char, minpoly
2837  // check whether vars have admissible names
2838  list Name  = RL[2];
2839  list RName;
2840  RName[1] = "u";
2841  RName[2] = "v";
2842  RName[3] = "t";
2843  RName[4] = "Dt";
2844  for(i=1;i<=N;i++)
2845  {
2846    for(j=1; j<=size(RName);j++)
2847    {
2848      if (Name[i] == RName[j])
2849      {
2850        ERROR("Variable names should not include u,v,t,Dt");
2851      }
2852    }
2853  }
2854  // now, create the names for new vars
2855  tmp[1]     = "u";
2856  tmp[2]     = "v";
2857  list UName = tmp;
2858  list DName;
2859  for(i=1;i<=N;i++)
2860  {
2861    DName[i] = "D"+Name[i]; // concat
2862  }
2863  tmp    =  0;
2864  tmp[1] = "t";
2865  tmp[2] = "Dt";
2866  list NName = UName +  tmp + Name + DName;
2867  L[2]   = NName;
2868  tmp    = 0;
2869  // Name, Dname will be used further
2870  kill UName;
2871  kill NName;
2872  // block ord (a(1,1),dp);
2873  tmp[1]  = "a"; // string
2874  iv      = 1,1;
2875  tmp[2]  = iv; //intvec
2876  Lord[1] = tmp;
2877  // continue with dp 1,1,1,1...
2878  tmp[1]  = "dp"; // string
2879  s       = "iv=";
2880  for(i=1;i<=Nnew;i++)
2881  {
2882    s = s+"1,";
2883  }
2884  s[size(s)]= ";";
2885  execute(s);
2886  tmp[2]    = iv;
2887  Lord[2]   = tmp;
2888  tmp[1]    = "C";
2889  iv        = 0;
2890  tmp[2]    = iv;
2891  Lord[3]   = tmp;
2892  tmp       = 0;
2893  L[3]      = Lord;
2894  // we are done with the list
2895  def @R@ = ring(L);
2896  setring @R@;
2897  matrix @D[Nnew][Nnew];
2898  @D[3,4]=1;
2899  for(i=1; i<=N; i++)
2900  {
2901    @D[4+i,N+4+i]=1;
2902  }
2903  //  @D[N+3,2*(N+2)]=1; old t,Dt stuff
2904  //  L[5] = matrix(UpOneMatrix(Nnew));
2905  //  L[6] = @D;
2906  def @R = nc_algebra(1,@D);
2907  setring @R;
2908  kill @R@;
2909  dbprint(ppl,"// -1-1- the ring @R(u,v,t,Dt,_x,_Dx) is ready");
2910  dbprint(ppl-1, @R);
2911  // create the ideal I
2912  poly  F = imap(save,F);
2913  ideal I = u*F-t,u*v-1;
2914  poly p;
2915  for(i=1; i<=N; i++)
2916  {
2917    p = u*Dt; // u*Dt
2918    p = diff(F,var(4+i))*p;
2919    I = I, var(N+4+i) + p;
2920  }
2921  // -------- the ideal I is ready ----------
2922  dbprint(ppl,"// -1-2- starting the elimination of u,v in @R");
2923  dbprint(ppl-1, I);
2924  ideal J = engine(I,eng);
2925  ideal K = nselect(J,1..2);
2926  dbprint(ppl,"// -1-3- u,v are eliminated");
2927  dbprint(ppl-1, K);  // K is without u,v
2928  setring save;
2929  // ------------ new ring @R2 ------------------
2930  // without u,v and with the elim.ord for t,Dt
2931  // tensored with the K[s]
2932  // keep: N, i,j,s, tmp, RL
2933  Nnew = 2*N+2+1;
2934  //  list RL = ringlist(save); // is defined earlier
2935  L = 0;  //  kill L;
2936  kill Lord, tmp, iv, RName;
2937  list Lord, tmp;
2938  intvec iv;
2939  L[1] = RL[1]; L[4] = RL[4]; // char, minpoly
2940  // check whether vars have admissible names -> done earlier
2941  //  list Name  = RL[2];
2942  list RName;
2943  RName[1] = "t";
2944  RName[2] = "Dt";
2945  // now, create the names for new var (here, s only)
2946  tmp[1]     = "s";
2947  // DName is defined earlier
2948  list NName = RName + Name + DName + tmp;
2949  L[2]   = NName;
2950  tmp    = 0;
2951  // block ord (a(1,1),dp);
2952  tmp[1]  = "a";  iv = 1,1; tmp[2]  = iv; //intvec
2953  Lord[1] = tmp;
2954  // continue with a(1,1,1,1)...
2955  tmp[1]  = "dp"; s  = "iv=";
2956  for(i=1; i<= Nnew; i++)
2957  {
2958    s = s+"1,";
2959  }
2960  s[size(s)]= ";";  execute(s);
2961  kill NName;
2962  tmp[2]    = iv;
2963  Lord[2]   = tmp;
2964  // extra block for s
2965  // tmp[1] = "dp"; iv = 1;
2966  //  s[size(s)]= ",";  s = s + "1,1,1;";  execute(s);  tmp[2]    = iv;
2967  //  Lord[3]   = tmp;
2968  kill s;
2969  tmp[1]    = "C";   iv  = 0; tmp[2] = iv;
2970  Lord[3]   = tmp;   tmp = 0;
2971  L[3]      = Lord;
2972  // we are done with the list. Now, add a Plural part
2973  def @R2@ = ring(L);
2974  setring @R2@;
2975  matrix @D[Nnew][Nnew];
2976  @D[1,2] = 1;
2977  for(i=1; i<=N; i++)
2978  {
2979    @D[2+i,2+N+i] = 1;
2980  }
2981  def @R2 = nc_algebra(1,@D);
2982  setring @R2;
2983  kill @R2@;
2984  dbprint(ppl,"// -2-1- the ring @R2(t,Dt,_x,_Dx,s) is ready");
2985  dbprint(ppl-1, @R2);
2986  ideal MM = maxideal(1);
2987  MM = 0,0,MM;
2988  map R01 = @R, MM;
2989  ideal K = R01(K);
2990  //  ideal K = imap(@R,K); // names of vars are important!
2991  poly G = t*Dt+s+1; // s is a variable here
2992  K = NF(K,std(G)),G;
2993  // -------- the ideal K_(@R2) is ready ----------
2994  dbprint(ppl,"// -2-2- starting the elimination of t,Dt in @R2");
2995  dbprint(ppl-1, K);
2996  ideal M  = engine(K,eng);
2997  ideal K2 = nselect(M,1..2);
2998  dbprint(ppl,"// -2-3- t,Dt are eliminated");
2999  dbprint(ppl-1, K2);
3000  //  dbprint(ppl-1+1," -2-4- std of K2");
3001  //  option(redSB);  option(redTail);  K2 = std(K2);
3002  //  K2; // without t,Dt, and with s
3003  // -------- the ring @R3 ----------
3004  // _x, _Dx, s; elim.ord for _x,_Dx.
3005  // keep: N, i,j,s, tmp, RL
3006  setring save;
3007  Nnew = 2*N+1;
3008  //  list RL = ringlist(save); // is defined earlier
3009  //  kill L;
3010  kill Lord, tmp, iv, RName;
3011  list Lord, tmp;
3012  intvec iv;
3013  L[1] = RL[1]; L[4] = RL[4]; // char, minpoly
3014  // check whether vars have admissible names -> done earlier
3015  //  list Name  = RL[2];
3016  // now, create the names for new var (here, s only)
3017  tmp[1]     = "s";
3018  // DName is defined earlier
3019  list NName = Name + DName + tmp;
3020  L[2]   = NName;
3021  tmp    = 0;
3022  // block ord (a(1,1...),dp);
3023  string  s = "iv=";
3024  for(i=1; i<=Nnew-1; i++)
3025  {
3026    s = s+"1,";
3027  }
3028  s[size(s)]= ";";
3029  execute(s);
3030  tmp[1]  = "a"; // string
3031  tmp[2]  = iv; //intvec
3032  Lord[1] = tmp;
3033  // continue with dp 1,1,1,1...
3034  tmp[1]  = "dp"; // string
3035  s[size(s)]=","; s= s+"1;";
3036  execute(s);
3037  kill s;
3038  kill NName;
3039  tmp[2]    = iv;
3040  Lord[2]   = tmp;
3041  tmp[1]    = "C";  iv  = 0;  tmp[2] = iv;
3042  Lord[3]   = tmp;  tmp = 0;
3043  L[3]      = Lord;
3044  // we are done with the list. Now add a Plural part
3045  def @R3@ = ring(L);
3046  setring @R3@;
3047  matrix @D[Nnew][Nnew];
3048  for(i=1; i<=N; i++)
3049  {
3050    @D[i,N+i]=1;
3051  }
3052  def @R3 = nc_algebra(1,@D);
3053  setring @R3;
3054  kill @R3@;
3055  dbprint(ppl,"// -3-1- the ring @R3(_x,_Dx,s) is ready");
3056  dbprint(ppl-1, @R3);
3057  ideal MM = maxideal(1);
3058  MM = 0,0,MM;
3059  map R12 = @R2, MM;
3060  ideal K = R12(K2);
3061  poly  F = imap(save,F);
3062  K = K,F;
3063  dbprint(ppl,"// -3-2- starting the elimination of _x,_Dx in @R3");
3064  dbprint(ppl-1, K);
3065  ideal M = engine(K,eng);
3066  ideal K3 = nselect(M,1..Nnew-1);
3067  dbprint(ppl,"// -3-3-  _x,_Dx are eliminated in @R3");
3068  dbprint(ppl-1, K3);
3069  // the ring @R4  and the search for minimal negative int s
3070  ring @R4 = 0,(s),dp;
3071  dbprint(ppl,"// -4-1- the ring @R4 is ready");
3072  ideal K4 = imap(@R3,K3);
3073  poly p = K4[1];
3074  dbprint(ppl,"// -4-2- factorization");
3075////  ideal P = factorize(p,1);  // without constants and multiplicities
3076  list P = factorize(p);         // with constants and multiplicities
3077  ideal bs; intvec m;            // the Bernstein polynomial is monic, so we are not interested in constants
3078  for (i=2; i<=size(P[1]); i++)  // we delete P[1][1] and P[2][1]
3079  {
3080    bs[i-1] = P[1][i];
3081    m[i-1]  = P[2][i];
3082  }
3083  //  "------ b-function factorizes into ----------";  P;
3084////  int sP  = minIntRoot(P, 1);
3085  int sP = minIntRoot(bs,1);
3086  dbprint(ppl,"// -4-3- minimal integer root found");
3087  dbprint(ppl-1, sP);
3088  // convert factors to a list of their roots
3089  // assume all factors are linear
3090////  ideal BS = normalize(P);
3091////  BS = subst(BS,s,0);
3092////  BS = -BS;
3093  bs = normalize(bs);
3094  bs = subst(bs,s,0);
3095  bs = -bs;
3096  list BS = bs,m;
3097  // TODO: sort BS!
3098  // ------ substitute s found in the ideal ------
3099  // ------- going back to @R2 and substitute --------
3100  setring @R2;
3101  ideal K3 = subst(K2,s,sP);
3102  // create the ordinary Weyl algebra and put the result into it,
3103  // thus creating the ring @R5
3104  // keep: N, i,j,s, tmp, RL
3105  setring save;
3106  Nnew = 2*N;
3107  //  list RL = ringlist(save); // is defined earlier
3108  kill Lord, tmp, iv;
3109  L = 0;
3110  list Lord, tmp;
3111  intvec iv;
3112  L[1] = RL[1];   L[4] = RL[4]; // char, minpoly
3113  // check whether vars have admissible names -> done earlier
3114  //  list Name  = RL[2];
3115  // DName is defined earlier
3116  list NName = Name + DName;
3117  L[2]   = NName;
3118  // dp ordering;
3119  string   s       = "iv=";
3120  for(i=1;i<=Nnew;i++)
3121  {
3122    s = s+"1,";
3123  }
3124  s[size(s)]= ";";
3125  execute(s);
3126  tmp     = 0;
3127  tmp[1]  = "dp"; // string
3128  tmp[2]  = iv; //intvec
3129  Lord[1] = tmp;
3130  kill s;
3131  tmp[1]    = "C";
3132  iv        = 0;
3133  tmp[2]    = iv;
3134  Lord[2]   = tmp;
3135  tmp       = 0;
3136  L[3]      = Lord;
3137  // we are done with the list
3138  // Add: Plural part
3139  def @R5@ = ring(L);
3140  setring @R5@;
3141  matrix @D[Nnew][Nnew];
3142  for(i=1; i<=N; i++)
3143  {
3144    @D[i,N+i]=1;
3145  }
3146  def @R5 = nc_algebra(1,@D);
3147  setring @R5;
3148  kill @R5@;
3149  dbprint(ppl,"// -5-1- the ring @R5 is ready");
3150  dbprint(ppl-1, @R5);
3151  ideal K5 = imap(@R2,K3);
3152  option(redSB);
3153  dbprint(ppl,"// -5-2- the final cosmetic std");
3154  K5 = engine(K5,eng); // std does the job too
3155  // total cleanup
3156  kill @R;
3157  kill @R2;
3158  kill @R3;
3159////  ideal BS = imap(@R4,BS);
3160  list BS = imap(@R4,BS);
3161  export BS;
3162  ideal LD = K5;
3163  kill @R4;
3164  export LD;
3165  return(@R5);
3166}
3167example
3168{
3169  "EXAMPLE:"; echo = 2;
3170  ring r = 0,(x,y,z),Dp;
3171  poly F = x^2+y^3+z^5;
3172  printlevel = 0;
3173  def A  = annfsOT(F);
3174  setring A;
3175  LD;
3176  BS;
3177}
3178
3179
3180proc SannfsOT(poly F, list #)
3181"USAGE:  SannfsOT(f [,eng]);  f a poly, eng an optional int
3182RETURN:  ring
3183PURPOSE: compute the D-module structure of basering[1/f]*f^s, according to the
3184@* 1st step of the algorithm by Oaku and Takayama in the ring D[s]
3185NOTE:    activate the output ring with the @code{setring} command.
3186@*  In the output ring D[s], the ideal LD (which is NOT a Groebner basis)
3187@*  is the needed D-module structure.
3188@*  If eng <>0, @code{std} is used for Groebner basis computations,
3189@*  otherwise, and by default @code{slimgb} is used.
3190@*  If printlevel=1, progress debug messages will be printed,
3191@*  if printlevel>=2, all the debug messages will be printed.
3192EXAMPLE: example SannfsOT; shows examples
3193"
3194{
3195  int eng = 0;
3196  if ( size(#)>0 )
3197  {
3198    if ( typeof(#[1]) == "int" )
3199    {
3200      eng = int(#[1]);
3201    }
3202  }
3203  // returns a list with a ring and an ideal LD in it
3204  int ppl = printlevel-voice+2;
3205  //  printf("plevel :%s, voice: %s",printlevel,voice);
3206  def save = basering;
3207  int N = nvars(basering);
3208  int Nnew = 2*(N+2);
3209  int i,j;
3210  string s;
3211  list RL = ringlist(basering);
3212  list L, Lord;
3213  list tmp;
3214  intvec iv;
3215  L[1] = RL[1]; // char
3216  L[4] = RL[4]; // char, minpoly
3217  // check whether vars have admissible names
3218  list Name  = RL[2];
3219  list RName;
3220  RName[1] = "u";
3221  RName[2] = "v";
3222  RName[3] = "t";
3223  RName[4] = "Dt";
3224  for(i=1;i<=N;i++)
3225  {
3226    for(j=1; j<=size(RName);j++)
3227    {
3228      if (Name[i] == RName[j])
3229      {
3230        ERROR("Variable names should not include u,v,t,Dt");
3231      }
3232    }
3233  }
3234  // now, create the names for new vars
3235  tmp[1]     = "u";
3236  tmp[2]     = "v";
3237  list UName = tmp;
3238  list DName;
3239  for(i=1;i<=N;i++)
3240  {
3241    DName[i] = "D"+Name[i]; // concat
3242  }
3243  tmp    =  0;
3244  tmp[1] = "t";
3245  tmp[2] = "Dt";
3246  list NName = UName +  tmp + Name + DName;
3247  L[2]   = NName;
3248  tmp    = 0;
3249  // Name, Dname will be used further
3250  kill UName;
3251  kill NName;
3252  // block ord (a(1,1),dp);
3253  tmp[1]  = "a"; // string
3254  iv      = 1,1;
3255  tmp[2]  = iv; //intvec
3256  Lord[1] = tmp;
3257  // continue with dp 1,1,1,1...
3258  tmp[1]  = "dp"; // string
3259  s       = "iv=";
3260  for(i=1;i<=Nnew;i++)
3261  {
3262    s = s+"1,";
3263  }
3264  s[size(s)]= ";";
3265  execute(s);
3266  tmp[2]    = iv;
3267  Lord[2]   = tmp;
3268  tmp[1]    = "C";
3269  iv        = 0;
3270  tmp[2]    = iv;
3271  Lord[3]   = tmp;
3272  tmp       = 0;
3273  L[3]      = Lord;
3274  // we are done with the list
3275  def @R@ = ring(L);
3276  setring @R@;
3277  matrix @D[Nnew][Nnew];
3278  @D[3,4]=1;
3279  for(i=1; i<=N; i++)
3280  {
3281    @D[4+i,N+4+i]=1;
3282  }
3283  //  @D[N+3,2*(N+2)]=1; old t,Dt stuff
3284  //  L[5] = matrix(UpOneMatrix(Nnew));
3285  //  L[6] = @D;
3286  def @R =  nc_algebra(1,@D);
3287  setring @R;
3288  kill @R@;
3289  dbprint(ppl,"// -1-1- the ring @R(u,v,t,Dt,_x,_Dx) is ready");
3290  dbprint(ppl-1, @R);
3291  // create the ideal I
3292  poly  F = imap(save,F);
3293  ideal I = u*F-t,u*v-1;
3294  poly p;
3295  for(i=1; i<=N; i++)
3296  {
3297    p = u*Dt; // u*Dt
3298    p = diff(F,var(4+i))*p;
3299    I = I, var(N+4+i) + p;
3300  }
3301  // -------- the ideal I is ready ----------
3302  dbprint(ppl,"// -1-2- starting the elimination of u,v in @R");
3303  dbprint(ppl-1, I);
3304  ideal J = engine(I,eng);
3305  ideal K = nselect(J,1..2);
3306  dbprint(ppl,"// -1-3- u,v are eliminated");
3307  dbprint(ppl-1, K);  // K is without u,v
3308  setring save;
3309  // ------------ new ring @R2 ------------------
3310  // without u,v and with the elim.ord for t,Dt
3311  // tensored with the K[s]
3312  // keep: N, i,j,s, tmp, RL
3313  Nnew = 2*N+2+1;
3314  //  list RL = ringlist(save); // is defined earlier
3315  L = 0;  //  kill L;
3316  kill Lord, tmp, iv, RName;
3317  list Lord, tmp;
3318  intvec iv;
3319  L[1] = RL[1]; L[4] = RL[4]; // char, minpoly
3320  // check whether vars have admissible names -> done earlier
3321  //  list Name  = RL[2];
3322  list RName;
3323  RName[1] = "t";
3324  RName[2] = "Dt";
3325  // now, create the names for new var (here, s only)
3326  tmp[1]     = "s";
3327  // DName is defined earlier
3328  list NName = RName + Name + DName + tmp;
3329  L[2]   = NName;
3330  tmp    = 0;
3331  // block ord (a(1,1),dp);
3332  tmp[1]  = "a";  iv = 1,1; tmp[2]  = iv; //intvec
3333  Lord[1] = tmp;
3334  // continue with a(1,1,1,1)...
3335  tmp[1]  = "dp"; s  = "iv=";
3336  for(i=1; i<= Nnew; i++)
3337  {
3338    s = s+"1,";
3339  }
3340  s[size(s)]= ";";  execute(s);
3341  kill NName;
3342  tmp[2]    = iv;
3343  Lord[2]   = tmp;
3344  // extra block for s
3345  // tmp[1] = "dp"; iv = 1;
3346  //  s[size(s)]= ",";  s = s + "1,1,1;";  execute(s);  tmp[2]    = iv;
3347  //  Lord[3]   = tmp;
3348  kill s;
3349  tmp[1]    = "C";   iv  = 0; tmp[2] = iv;
3350  Lord[3]   = tmp;   tmp = 0;
3351  L[3]      = Lord;
3352  // we are done with the list. Now, add a Plural part
3353  def @R2@ = ring(L);
3354  setring @R2@;
3355  matrix @D[Nnew][Nnew];
3356  @D[1,2] = 1;
3357  for(i=1; i<=N; i++)
3358  {
3359    @D[2+i,2+N+i] = 1;
3360  }
3361  def @R2 = nc_algebra(1,@D);
3362  setring @R2;
3363  kill @R2@;
3364  dbprint(ppl,"// -2-1- the ring @R2(t,Dt,_x,_Dx,s) is ready");
3365  dbprint(ppl-1, @R2);
3366  ideal MM = maxideal(1);
3367  MM = 0,0,MM;
3368  map R01 = @R, MM;
3369  ideal K = R01(K);
3370  //  ideal K = imap(@R,K); // names of vars are important!
3371  poly G = t*Dt+s+1; // s is a variable here
3372  K = NF(K,std(G)),G;
3373  // -------- the ideal K_(@R2) is ready ----------
3374  dbprint(ppl,"// -2-2- starting the elimination of t,Dt in @R2");
3375  dbprint(ppl-1, K);
3376  ideal M  = engine(K,eng);
3377  ideal K2 = nselect(M,1..2);
3378  dbprint(ppl,"// -2-3- t,Dt are eliminated");
3379  dbprint(ppl-1, K2);
3380  K2 = engine(K2,eng);
3381  setring save;
3382  // ----------- the ring @R3 ------------
3383  // _x, _Dx,s;  elim.ord for _x,_Dx.
3384  // keep: N, i,j,s, tmp, RL
3385  Nnew = 2*N+1;
3386  kill Lord, tmp, iv, RName;
3387  list Lord, tmp;
3388  intvec iv;
3389  L[1] = RL[1];
3390  L[4] = RL[4];  // char, minpoly
3391  // check whether vars hava admissible names -> done earlier
3392  // now, create the names for new var
3393  tmp[1] = "s";
3394  // DName is defined earlier
3395  list NName = Name + DName + tmp;
3396  L[2] = NName;
3397  tmp = 0;
3398  // block ord (dp(N),dp);
3399  string s = "iv=";
3400  for (i=1; i<=Nnew-1; i++)
3401  {
3402    s = s+"1,";
3403  }
3404  s[size(s)]=";";
3405  execute(s);
3406  tmp[1] = "dp";  // string
3407  tmp[2] = iv;   // intvec
3408  Lord[1] = tmp;
3409  // continue with dp 1,1,1,1...
3410  tmp[1] = "dp";  // string
3411  s[size(s)] = ",";
3412  s = s+"1;";
3413  execute(s);
3414  kill s;
3415  kill NName;
3416  tmp[2]      = iv;
3417  Lord[2]     = tmp;
3418  tmp[1]      = "C";  iv  = 0;  tmp[2]=iv;
3419  Lord[3]     = tmp;  tmp = 0;
3420  L[3]        = Lord;
3421  // we are done with the list. Now add a Plural part
3422  def @R3@ = ring(L);
3423  setring @R3@;
3424  matrix @D[Nnew][Nnew];
3425  for (i=1; i<=N; i++)
3426  {
3427    @D[i,N+i]=1;
3428  }
3429  def @R3 = nc_algebra(1,@D);
3430  setring @R3;
3431  kill @R3@;
3432  dbprint(ppl,"// -3-1- the ring @R3(_x,_Dx,s) is ready");
3433  dbprint(ppl-1, @R3);
3434  ideal MM = maxideal(1);
3435  MM = 0,s,MM;
3436  map R01 = @R2, MM;
3437  ideal K2 = R01(K2);
3438  // total cleanup
3439  ideal LD = K2;
3440  // make leadcoeffs positive
3441  for (i=1; i<= ncols(LD); i++)
3442  {
3443    if (leadcoef(LD[i]) <0 )
3444    {
3445      LD[i] = -LD[i];
3446    }
3447  }
3448  export LD;
3449  kill @R;
3450  kill @R2;
3451  return(@R3);
3452}
3453example
3454{
3455  "EXAMPLE:"; echo = 2;
3456  ring r = 0,(x,y,z),Dp;
3457  poly F = x^3+y^3+z^3;
3458  printlevel = 0;
3459  def A  = SannfsOT(F);
3460  setring A;
3461  LD;
3462}
3463
3464proc SannfsBM(poly F, list #)
3465"USAGE:  SannfsBM(f [,eng]);  f a poly, eng an optional int
3466RETURN:  ring
3467PURPOSE: compute the D-module structure of basering[1/f]*f^s, according to the
3468@* 1st step of the algorithm by Briancon and Maisonobe in the ring D[s].
3469NOTE:  activate the output ring with the @code{setring} command.
3470@*   In the output ring D[s], the ideal LD (which is NOT a Groebner basis) is
3471@*   the needed D-module structure.
3472@*   If eng <>0, @code{std} is used for Groebner basis computations,
3473@*   otherwise, and by default @code{slimgb} is used.
3474@*   If printlevel=1, progress debug messages will be printed,
3475@*   if printlevel>=2, all the debug messages will be printed.
3476EXAMPLE: example SannfsBM; shows examples
3477"
3478{
3479  int eng = 0;
3480  if ( size(#)>0 )
3481  {
3482    if ( typeof(#[1]) == "int" )
3483    {
3484      eng = int(#[1]);
3485    }
3486  }
3487  // returns a list with a ring and an ideal LD in it
3488  int ppl = printlevel-voice+2;
3489  //  printf("plevel :%s, voice: %s",printlevel,voice);
3490  def save = basering;
3491  int N = nvars(basering);
3492  int Nnew = 2*N+2;
3493  int i,j;
3494  string s;
3495  list RL = ringlist(basering);
3496  list L, Lord;
3497  list tmp;
3498  intvec iv;
3499  L[1] = RL[1]; // char
3500  L[4] = RL[4]; // char, minpoly
3501  // check whether vars have admissible names
3502  list Name  = RL[2];
3503  list RName;
3504  RName[1] = "t";
3505  RName[2] = "s";
3506  for(i=1;i<=N;i++)
3507  {
3508    for(j=1; j<=size(RName);j++)
3509    {
3510      if (Name[i] == RName[j])
3511      {
3512        ERROR("Variable names should not include t,s");
3513      }
3514    }
3515  }
3516  // now, create the names for new vars
3517  list DName;
3518  for(i=1;i<=N;i++)
3519  {
3520    DName[i] = "D"+Name[i]; // concat
3521  }
3522  tmp[1] = "t";
3523  tmp[2] = "s";
3524  list NName = tmp + Name + DName;
3525  L[2]   = NName;
3526  // Name, Dname will be used further
3527  kill NName;
3528  // block ord (lp(2),dp);
3529  tmp[1]  = "lp"; // string
3530  iv      = 1,1;
3531  tmp[2]  = iv; //intvec
3532  Lord[1] = tmp;
3533  // continue with dp 1,1,1,1...
3534  tmp[1]  = "dp"; // string
3535  s       = "iv=";
3536  for(i=1;i<=Nnew;i++)
3537  {
3538    s = s+"1,";
3539  }
3540  s[size(s)]= ";";
3541  execute(s);
3542  kill s;
3543  tmp[2]    = iv;
3544  Lord[2]   = tmp;
3545  tmp[1]    = "C";
3546  iv        = 0;
3547  tmp[2]    = iv;
3548  Lord[3]   = tmp;
3549  tmp       = 0;
3550  L[3]      = Lord;
3551  // we are done with the list
3552  def @R@ = ring(L);
3553  setring @R@;
3554  matrix @D[Nnew][Nnew];
3555  @D[1,2]=t;
3556  for(i=1; i<=N; i++)
3557  {
3558    @D[2+i,N+2+i]=1;
3559  }
3560  //  L[5] = matrix(UpOneMatrix(Nnew));
3561  //  L[6] = @D;
3562  def @R = nc_algebra(1,@D);
3563  setring @R;
3564  kill @R@;
3565  dbprint(ppl,"// -1-1- the ring @R(t,s,_x,_Dx) is ready");
3566  dbprint(ppl-1, @R);
3567  // create the ideal I
3568  poly  F = imap(save,F);
3569  ideal I = t*F+s;
3570  poly p;
3571  for(i=1; i<=N; i++)
3572  {
3573    p = t; // t
3574    p = diff(F,var(2+i))*p;
3575    I = I, var(N+2+i) + p;
3576  }
3577  // -------- the ideal I is ready ----------
3578  dbprint(ppl,"// -1-2- starting the elimination of t in @R");
3579  dbprint(ppl-1, I);
3580  ideal J = engine(I,eng);
3581  ideal K = nselect(J,1);
3582  dbprint(ppl,"// -1-3- t is eliminated");
3583  dbprint(ppl-1, K);  // K is without t
3584  K = engine(K,eng);  // std does the job too
3585  // now, we must change the ordering
3586  // and create a ring without t, Dt
3587  //  setring S;
3588  // ----------- the ring @R3 ------------
3589  // _x, _Dx,s;  elim.ord for _x,_Dx.
3590  // keep: N, i,j,s, tmp, RL
3591  Nnew = 2*N+1;
3592  kill Lord, tmp, iv, RName;
3593  list Lord, tmp;
3594  intvec iv;
3595  list L=imap(save,L);
3596  list RL=imap(save,RL);
3597  L[1] = RL[1];
3598  L[4] = RL[4];  // char, minpoly
3599  // check whether vars hava admissible names -> done earlier
3600  // now, create the names for new var
3601  tmp[1] = "s";
3602  // DName is defined earlier
3603  list NName = Name + DName + tmp;
3604  L[2] = NName;
3605  tmp = 0;
3606  // block ord (dp(N),dp);
3607  string s = "iv=";
3608  for (i=1; i<=Nnew-1; i++)
3609  {
3610    s = s+"1,";
3611  }
3612  s[size(s)]=";";
3613  execute(s);
3614  tmp[1] = "dp";  // string
3615  tmp[2] = iv;   // intvec
3616  Lord[1] = tmp;
3617  // continue with dp 1,1,1,1...
3618  tmp[1] = "dp";  // string
3619  s[size(s)] = ",";
3620  s = s+"1;";
3621  execute(s);
3622  kill s;
3623  kill NName;
3624  tmp[2]      = iv;
3625  Lord[2]     = tmp;
3626  tmp[1]      = "C";  iv  = 0;  tmp[2]=iv;
3627  Lord[3]     = tmp;  tmp = 0;
3628  L[3]        = Lord;
3629  // we are done with the list. Now add a Plural part
3630  def @R2@ = ring(L);
3631  setring @R2@;
3632  matrix @D[Nnew][Nnew];
3633  for (i=1; i<=N; i++)
3634  {
3635    @D[i,N+i]=1;
3636  }
3637  def @R2 = nc_algebra(1,@D);
3638  setring @R2;
3639  kill @R2@;
3640  dbprint(ppl,"//  -2-1- the ring @R2(_x,_Dx,s) is ready");
3641  dbprint(ppl-1, @R2);
3642  ideal MM = maxideal(1);
3643  MM = 0,s,MM;
3644  map R01 = @R, MM;
3645  ideal K = R01(K);
3646  // total cleanup
3647  ideal LD = K;
3648  // make leadcoeffs positive
3649  for (i=1; i<= ncols(LD); i++)
3650  {
3651    if (leadcoef(LD[i]) <0 )
3652    {
3653      LD[i] = -LD[i];
3654    }
3655  }
3656  export LD;
3657  kill @R;
3658  return(@R2);
3659}
3660example
3661{
3662  "EXAMPLE:"; echo = 2;
3663  ring r = 0,(x,y,z),Dp;
3664  poly F = x^3+y^3+z^3;
3665  printlevel = 0;
3666  def A = SannfsBM(F);
3667  setring A;
3668  LD;
3669}
3670
3671static proc safeVarName (string s, list #)
3672{
3673  string S;
3674  int cv = 1;
3675  if (size(#)>1)
3676  {
3677    if (#[1]=="v") { cv = 0; S = varstr(basering); }
3678    if (#[1]=="c") { cv = 0; S = charstr(basering); }
3679  }
3680  if (cv) { S = charstr(basering) + "," + varstr(basering); }
3681  S = "," + S + ",";
3682  s = "," + s + ",";
3683  while (find(S,s) <> 0)
3684  {
3685    s[1] = "@";
3686    s = "," + s;
3687  }
3688  s = s[2..size(s)-1];
3689  return(s)
3690}
3691
3692proc SannfsBFCT(poly F, list #)
3693"USAGE:  SannfsBFCT(f [,a,b,c]);  f a poly, a,b,c optional ints
3694RETURN:  ring
3695PURPOSE: compute a Groebner basis either of Ann(f^s)+<f> or of
3696@*       Ann(f^s)+<f,f_1,...,f_n> in D[s]
3697NOTE:    Activate the output ring with the @code{setring} command.
3698@*  This procedure, unlike SannfsBM, returns the ring D[s] with an anti-
3699@*  elimination ordering for s.
3700@*  The output ring contains an ideal @code{LD}, being a Groebner basis
3701@*  either of  Ann(f^s)+<f>, if a=0 (and by default), or of
3702@*  Ann(f^s)+<f,f_1,...,f_n>, otherwise.
3703@*  Here, f_i stands for the i-th  partial derivative of f.
3704@*  If b<>0, @code{std} is used for Groebner basis computations,
3705@*  otherwise, and by default @code{slimgb} is used.
3706@*  If c<>0, @code{std} is used for Groebner basis computations of
3707@*  ideals <I+J> when I is already a Groebner basis of <I>.
3708@*  Otherwise, and by default the engine determined by the switch b is
3709@*  used. Note that in the case c<>0, the choice for b will be
3710@*  overwritten only for the types of ideals mentioned above.
3711@*  This means that if b<>0, specifying c has no effect.
3712DISPLAY: If printlevel=1, progress debug messages will be printed,
3713@*       if printlevel>=2, all the debug messages will be printed.
3714EXAMPLE: example SannfsBFCT; shows examples
3715"
3716{
3717  int addPD,eng,stdsum;
3718  if (size(#)>0)
3719  {
3720    if (typeof(#[1])=="int" || typeof(#[1])=="number")
3721    {
3722      addPD = int(#[1]);
3723    }
3724    if (size(#)>1)
3725    {
3726      if (typeof(#[2])=="int" || typeof(#[2])=="number")
3727      {
3728        eng = int(#[2]);
3729      }
3730      if (size(#)>2)
3731      {
3732        if (typeof(#[3])=="int" || typeof(#[3])=="number")
3733        {
3734          stdsum = int(#[3]);
3735        }
3736      }
3737    }
3738  }
3739  int ppl = printlevel-voice+2;
3740  def save = basering;
3741  int N = nvars(save);
3742  intvec optSave = option(get);
3743  int i,j;
3744  list RL = ringlist(save);
3745  // ----- step 1: compute syzigies
3746  intvec iv;
3747  list L,Lord;
3748  iv = 1:N; Lord[1] = list("dp",iv);
3749  iv = 0;   Lord[2] = list("C",iv);
3750  L = RL;
3751  L[3] = Lord;
3752  def @RM = ring(L);
3753  kill L,Lord;
3754  setring @RM;
3755  option(redSB);
3756  option(redTail);
3757  def RM = makeModElimRing(@RM);
3758  setring RM;
3759  poly F = imap(save,F);
3760  ideal J = jacob(F);
3761  J = F,J;
3762  dbprint(ppl,"// -1-1- Starting the computation of syz(F,_Dx(F))");
3763  dbprint(ppl-1, J);
3764  module M = syz(J);
3765  dbprint(ppl,"// -1-2- The module syz(F,_Dx(F)) has been computed");
3766  dbprint(ppl-1, M);
3767  dbprint(ppl,"// -1-3- Starting GB computation of syz(F,_Dx(F))");
3768  M = engine(M,eng);
3769  dbprint(ppl,"// -1-4- GB computation finished");
3770  dbprint(ppl-1, M);
3771  // ----- step 2: compute part of Ann(F^s)
3772  setring save;
3773  option(set,optSave);
3774  module M = imap(RM,M);
3775  kill optSave,RM;
3776  // ----- create D[s]
3777  int Nnew = 2*N+1;
3778  list L, Lord;
3779  // ----- keep char, minpoly
3780  L[1] = RL[1];
3781  L[4] = RL[4];
3782  // ----- create names for new vars
3783  list Name  = RL[2];
3784  string newVar@s = safeVarName("s");
3785  if (newVar@s[1] == "@")
3786  {
3787    print("Name s already assigned to parameter/ringvar.");
3788    print("Using " + newVar@s + " instead.")
3789  }
3790  list DName;
3791  for (i=1; i<=N; i++)
3792  {
3793    DName[i] = safeVarName("D" + Name[i]);
3794  }
3795  L[2] = list(newVar@s) + Name + DName;
3796  // ----- create ordering
3797  // --- anti-elimination ordering for s
3798  iv = 1;       Lord[1] = list("dp",iv);
3799  iv = 1:(2*N); Lord[2] = list("dp",iv);
3800  iv = 0;       Lord[3] = list("C",iv);
3801  L[3] = Lord;
3802  // ----- create commutative ring
3803  def @Ds = ring(L);
3804  kill L,Lord;
3805  setring @Ds;
3806  // ----- create nc relations
3807   matrix Drel[Nnew][Nnew];
3808  for (i=1; i<=N; i++)
3809  {
3810    Drel[i+1,N+1+i] = 1;
3811  }
3812  def Ds = nc_algebra(1,Drel);
3813  setring Ds;
3814  kill @Ds;
3815  dbprint(ppl,"// -2-1- The ring D[s] is ready");
3816  dbprint(ppl-1, Ds);
3817  matrix M = imap(save,M);
3818  vector v = var(1)*gen(1);
3819  for (i=1; i<=N; i++)
3820  {
3821    v = v + var(i+1+N)*gen(i+1); //[s,_Dx]
3822  }
3823  ideal J = transpose(M)*v;
3824  kill M,v;
3825  dbprint(ppl,"// -2-2- Compute part of Ann(F^s)");
3826  dbprint(ppl-1, J);
3827  J = engine(J,eng);
3828  dbprint(ppl,"// -2-3- GB computation finished");
3829  dbprint(ppl-1, J);
3830  // ----- step 3: the full annihilator
3831  // ----- create D<t,s>
3832  setring save;
3833  Nnew = 2*N+2;
3834  list L, Lord;
3835  // ----- keep char, minpoly
3836  L[1] = RL[1];
3837  L[4] = RL[4];
3838  // ----- create vars
3839  string newVar@t = safeVarName("t");
3840  L[2] = list(newVar@t,newVar@s) + DName + Name;
3841  // ----- create ordering for elimination of t
3842  // block ord (lp(2),dp);
3843  iv = 1,1;    Lord[1] = list("lp",iv);
3844  iv = 1:Nnew; Lord[2] = list("dp",iv);
3845  iv = 0;      Lord[3] = list("C",iv);
3846  L[3] = Lord;
3847  def @Dts = ring(L);
3848  kill RL,L,Lord,Name,DName,newVar@s,newVar@t;
3849  setring @Dts;
3850  // ----- create nc relations
3851  matrix Drel[Nnew][Nnew];
3852  Drel[1,2] = var(1);
3853  for(i=1; i<=N; i++)
3854  {
3855    Drel[2+i,N+2+i]=-1;
3856  }
3857  def Dts = nc_algebra(1,Drel);
3858  setring Dts;
3859  kill @Dts;
3860  dbprint(ppl,"// -3-1- The ring D<t,s> is ready");
3861  dbprint(ppl-1, Dts);
3862  // ----- create the ideal I following BM
3863  poly  F = imap(save,F);
3864  ideal I = var(1)*F + var(2); // = t*F + s
3865  poly p;
3866  for(i=1; i<=N; i++)
3867  {
3868    p = var(1)*diff(F,var(N+2+i)) + var(2+i); // = t*F_i + D_i
3869    I[i+1] = p;
3870  }
3871  // ----- add already computed part to it
3872  ideal MM = var(2);      // s
3873  for (i=1; i<=N; i++)
3874  {
3875    MM[1+i] = var(2+N+i); // _x
3876    MM[1+N+i] = var(2+i); // _Dx
3877  }
3878  map Ds2Dts = Ds,MM;
3879  ideal J = Ds2Dts(J);
3880  attrib(J,"isSB",1);
3881  kill MM,Ds2Dts;
3882  // ----- start the elimination
3883  dbprint(ppl,"// -3-2- Starting the elimination of t in D<t,s>");
3884  dbprint(ppl-1, I);
3885  if (stdsum || eng <> 0)
3886  {
3887    I = std(J,I);
3888  }
3889  else
3890  {
3891    I = J,I;
3892    I = engine(I,eng);
3893  }
3894  kill J;
3895  I = nselect(I,1);
3896  dbprint(ppl,"// -3-3- t is eliminated");
3897  dbprint(ppl-1, I);  // I is without t
3898  // ----- step 4: add F
3899  // ----- back to D[s]
3900  setring Ds;
3901  ideal MM = 0,var(1);      // 0,s
3902  for (i=1; i<=N; i++)
3903  {
3904    MM[2+i]   = var(1+N+i); // _Dx
3905    MM[2+N+i] = var(1+i);   // _x
3906  }
3907  map Dts2Ds = Dts, MM;
3908  ideal LD = Dts2Ds(I);
3909  kill J,Dts,Dts2Ds,MM;
3910  dbprint(ppl,"// -4-1- Starting cosmetic Groebner computation");
3911  LD = engine(LD,eng);
3912  dbprint(ppl,"// -4-2- Finished cosmetic Groebner computation");
3913  dbprint(ppl-1, LD);
3914  // ----- use reduction trick as Macaulay2 does: compute b(s)/(s+1) by adding all partial derivations also
3915  ideal J;
3916  if (addPD)
3917  {
3918    setring @RM;
3919    poly F = imap(save,F);
3920    ideal J = jacob(F);
3921    J = F,J;
3922    dbprint(ppl,"// -4-2-1- Start GB computation <f, f_i>");
3923    J = engine(J,eng);
3924    dbprint(ppl,"// -4-2-2- Finished GB computation <f, f_i>");
3925    dbprint(ppl-1, J);
3926    setring Ds;
3927    J = imap(@RM,J);
3928    attrib(J,"isSB",1);
3929    dbprint(ppl,"// -4-3- Start GB computations for Ann f^s + <f, f_i>");
3930  }
3931  else
3932  {
3933    J = imap(save,F);
3934    dbprint(ppl,"// -4-3- Start GB computations for Ann f^s + <f>");
3935  }
3936  kill @RM;
3937  // ----- the really hard part
3938  if (stdsum || eng <> 0)
3939  {
3940    LD = std(LD,J);
3941  }
3942  else
3943  {
3944    LD = LD,J;
3945    LD = engine(LD,eng);
3946  }
3947  if (addPD) { dbprint(ppl,"// -4-4- Finished GB computations for Ann f^s + <f, f_i>"); }
3948  else       { dbprint(ppl,"// -4-4- Finished GB computations for Ann f^s + <f>"); }
3949  dbprint(ppl-1, LD);
3950  export LD;
3951  return(Ds);
3952}
3953example
3954{
3955  "EXAMPLE:"; echo = 2;
3956  ring r = 0,(x,y,z,w),Dp;
3957  poly F = x^3+y^3+z^3*w;
3958  // compute Ann(F^s)+<F> using slimgb only
3959  def A = SannfsBFCT(F);
3960  setring A; A;
3961  LD;
3962  // the Bernstein-Sato poly of F:
3963  vec2poly(pIntersect(s,LD));
3964  // a fancier example:
3965  def R = reiffen(4,5); setring R;
3966  RC; // the Reiffen curve in 4,5
3967  // compute Ann(RC^s)+<RC,diff(RC,x),diff(RC,y)>
3968  // using std for GB computations of ideals <I+J>
3969  // where I is already a GB of <I>
3970  // and slimgb for other ideals
3971  def B = SannfsBFCT(RC,1,0,1);
3972  setring B;
3973  // the Bernstein-Sato poly of RC:
3974  (s-1)*vec2poly(pIntersect(s,LD));
3975}
3976
3977
3978proc SannfsBFCTstd(poly F, list #)
3979"USAGE:  SannfsBFCTstd(f [,eng]);  f a poly, eng an optional int
3980RETURN:  ring
3981PURPOSE: compute Ann f^s and Groebner basis of Ann f^s+f in D[s]
3982NOTE:    activate the output ring with the @code{setring} command.
3983@*    This procedure, unlike SannfsBM, returns a ring with the degrevlex
3984@*    ordering in all variables.
3985@*    In the ring D[s], the ideal LD (which IS a Groebner basis) is the needed ideal.
3986@*    In this procedure @code{std} is used for Groebner basis computations.
3987DISPLAY: If printlevel=1, progress debug messages will be printed,
3988@*       if printlevel>=2, all the debug messages will be printed.
3989EXAMPLE: example SannfsBFCTstd; shows examples
3990"
3991{
3992  // DEBUG INFO: ordering on the output ring = dp,
3993  // use std(K,F); for reusing the std property of K
3994
3995  int eng = 0;
3996  if ( size(#)>0 )
3997  {
3998    if ( typeof(#[1]) == "int" )
3999    {
4000      eng = int(#[1]);
4001    }
4002  }
4003  // returns a list with a ring and an ideal LD in it
4004  int ppl = printlevel-voice+2;
4005  //  printf("plevel :%s, voice: %s",printlevel,voice);
4006  def save = basering;
4007  int N = nvars(basering);
4008  int Nnew = 2*N+2;
4009  int i,j;
4010  string s;
4011  list RL = ringlist(basering);
4012  list L, Lord;
4013  list tmp;
4014  intvec iv;
4015  L[1] = RL[1]; // char
4016  L[4] = RL[4]; // char, minpoly
4017  // check whether vars have admissible names
4018  list Name  = RL[2];
4019  list RName;
4020  RName[1] = "@t";
4021  RName[2] = "@s";
4022  for(i=1;i<=N;i++)
4023  {
4024    for(j=1; j<=size(RName);j++)
4025    {
4026      if (Name[i] == RName[j])
4027      {
4028        ERROR("Variable names should not include @t,@s");
4029      }
4030    }
4031  }
4032  // now, create the names for new vars
4033  list DName;
4034  for(i=1;i<=N;i++)
4035  {
4036    DName[i] = "D"+Name[i]; // concat
4037  }
4038  tmp[1] = "t";
4039  tmp[2] = "s";
4040  list NName = tmp + DName + Name ;
4041  L[2]   = NName;
4042  // Name, Dname will be used further
4043  kill NName;
4044  // block ord (lp(2),dp);
4045  tmp[1]  = "lp"; // string
4046  iv      = 1,1;
4047  tmp[2]  = iv; //intvec
4048  Lord[1] = tmp;
4049  // continue with dp 1,1,1,1...
4050  tmp[1]  = "dp"; // string
4051  s       = "iv=";
4052  for(i=1;i<=Nnew;i++)
4053  {
4054    s = s+"1,";
4055  }
4056  s[size(s)]= ";";
4057  execute(s);
4058  kill s;
4059  tmp[2]    = iv;
4060  Lord[2]   = tmp;
4061  tmp[1]    = "C";
4062  iv        = 0;
4063  tmp[2]    = iv;
4064  Lord[3]   = tmp;
4065  tmp       = 0;
4066  L[3]      = Lord;
4067  // we are done with the list
4068  def @R@ = ring(L);
4069  setring @R@;
4070  matrix @D[Nnew][Nnew];
4071  @D[1,2]=t;
4072  for(i=1; i<=N; i++)
4073  {
4074    @D[2+i,N+2+i]=-1;
4075  }
4076  //  L[5] = matrix(UpOneMatrix(Nnew));
4077  //  L[6] = @D;
4078  def @R = nc_algebra(1,@D);
4079  setring @R;
4080  kill @R@;
4081  dbprint(ppl,"// -1-1- the ring @R(t,s,_Dx,_x) is ready");
4082  dbprint(ppl-1, @R);
4083  // create the ideal I
4084  poly  F = imap(save,F);
4085  ideal I = t*F+s;
4086  poly p;
4087  for(i=1; i<=N; i++)
4088  {
4089    p = t; // t
4090    p = diff(F,var(N+2+i))*p;
4091    I = I, var(2+i) + p;
4092  }
4093  // -------- the ideal I is ready ----------
4094  dbprint(ppl,"// -1-2- starting the elimination of t in @R");
4095  dbprint(ppl-1, I);
4096  ideal J = engine(I,eng);
4097  ideal K = nselect(J,1);
4098  dbprint(ppl,"// -1-3- t is eliminated");
4099  dbprint(ppl-1, K);  // K is without t
4100  K = engine(K,eng);  // std does the job too
4101  // now, we must change the ordering
4102  // and create a ring without t
4103  //  setring S;
4104  // ----------- the ring @R3 ------------
4105  // _Dx,_x,s;  +fast ord !
4106  // keep: N, i,j,s, tmp, RL
4107  Nnew = 2*N+1;
4108  kill Lord, tmp, iv, RName;
4109  list Lord, tmp;
4110  intvec iv;
4111  list L=imap(save,L);
4112  list RL=imap(save,RL);
4113  L[1] = RL[1];
4114  L[4] = RL[4];  // char, minpoly
4115  // check whether vars hava admissible names -> done earlier
4116  // now, create the names for new var
4117  tmp[1] = "s";
4118  // DName is defined earlier
4119  list NName = DName + Name + tmp;
4120  L[2] = NName;
4121  tmp = 0;
4122  // just dp
4123  // block ord (dp(N),dp);
4124  string s = "iv=";
4125  for (i=1; i<=Nnew; i++)
4126  {
4127    s = s+"1,";
4128  }
4129  s[size(s)]=";";
4130  execute(s);
4131  tmp[1] = "dp";  // string
4132  tmp[2] = iv;   // intvec
4133  Lord[1] = tmp;
4134  kill s;
4135  kill NName;
4136  tmp[1]      = "C";
4137  Lord[2]     = tmp;  tmp = 0;
4138  L[3]        = Lord;
4139  // we are done with the list. Now add a Plural part
4140  def @R2@ = ring(L);
4141  setring @R2@;
4142  matrix @D[Nnew][Nnew];
4143  for (i=1; i<=N; i++)
4144  {
4145    @D[i,N+i]=-1;
4146  }
4147  def @R2 = nc_algebra(1,@D);
4148  setring @R2;
4149  kill @R2@;
4150  dbprint(ppl,"//  -2-1- the ring @R2(_Dx,_x,s) is ready");
4151  dbprint(ppl-1, @R2);
4152  ideal MM = maxideal(1);
4153  MM = 0,s,MM;
4154  map R01 = @R, MM;
4155  ideal K = R01(K);
4156  // total cleanup
4157  poly F = imap(save, F);
4158  //  ideal LD = K,F;
4159  dbprint(ppl,"//  -2-2- start GB computations for Ann f^s + f");
4160  //  dbprint(ppl-1, LD);
4161  ideal LD = std(K,F);
4162  //  LD = engine(LD,eng);
4163  dbprint(ppl,"//  -2-3- finished GB computations for Ann f^s + f");
4164  dbprint(ppl-1, LD);
4165  // make leadcoeffs positive
4166  for (i=1; i<= ncols(LD); i++)
4167  {
4168    if (leadcoef(LD[i]) <0 )
4169    {
4170      LD[i] = -LD[i];
4171    }
4172  }
4173  export LD;
4174  kill @R;
4175  return(@R2);
4176}
4177example
4178{
4179  "EXAMPLE:"; echo = 2;
4180  ring r = 0,(x,y,z,w),Dp;
4181  poly F = x^3+y^3+z^3*w;
4182  printlevel = 0;
4183  def A = SannfsBFCT(F); setring A;
4184  intvec v = 1,2,3,4,5,6,7,8;
4185  // are there polynomials, depending on s only?
4186  nselect(LD,v);
4187  // a fancier example:
4188  def R = reiffen(4,5); setring R;
4189  v = 1,2,3,4;
4190  RC; // the Reiffen curve in 4,5
4191  def B = SannfsBFCT(RC);
4192  setring B;
4193  // Are there polynomials, depending on s only?
4194  nselect(LD,v);
4195  // It is not the case. Are there leading monomials in s only?
4196  nselect(lead(LD),v);
4197}
4198
4199// use a finer ordering
4200
4201proc SannfsLOT(poly F, list #)
4202"USAGE:  SannfsLOT(f [,eng]);  f a poly, eng an optional int
4203RETURN:  ring
4204PURPOSE: compute the D-module structure of basering[1/f]*f^s, according to the
4205@* Levandovskyy's modification of the algorithm by Oaku and Takayama in D[s]
4206NOTE:    activate the output ring with the @code{setring} command.
4207@*    In the ring D[s], the ideal LD (which is NOT a Groebner basis) is
4208@*    the needed D-module structure.
4209@*    If eng <>0, @code{std} is used for Groebner basis computations,
4210@*    otherwise, and by default @code{slimgb} is used.
4211@*    If printlevel=1, progress debug messages will be printed,
4212@*    if printlevel>=2, all the debug messages will be printed.
4213EXAMPLE: example SannfsLOT; shows examples
4214"
4215{
4216  int eng = 0;
4217  if ( size(#)>0 )
4218  {
4219    if ( typeof(#[1]) == "int" )
4220    {
4221      eng = int(#[1]);
4222    }
4223  }
4224  // returns a list with a ring and an ideal LD in it
4225  int ppl = printlevel-voice+2;
4226  //  printf("plevel :%s, voice: %s",printlevel,voice);
4227  def save = basering;
4228  int N = nvars(basering);
4229  //  int Nnew = 2*(N+2);
4230  int Nnew = 2*(N+1)+1; //removed u,v; added s
4231  int i,j;
4232  string s;
4233  list RL = ringlist(basering);
4234  list L, Lord;
4235  list tmp;
4236  intvec iv;
4237  L[1] = RL[1]; // char
4238  L[4] = RL[4]; // char, minpoly
4239  // check whether vars have admissible names
4240  list Name  = RL[2];
4241  list RName;
4242//   RName[1] = "u";
4243//   RName[2] = "v";
4244  RName[1] = "t";
4245  RName[2] = "Dt";
4246  for(i=1;i<=N;i++)
4247  {
4248    for(j=1; j<=size(RName);j++)
4249    {
4250      if (Name[i] == RName[j])
4251      {
4252        ERROR("Variable names should not include t,Dt");
4253      }
4254    }
4255  }
4256  // now, create the names for new vars
4257//   tmp[1]     = "u";
4258//   tmp[2]     = "v";
4259//   list UName = tmp;
4260  list DName;
4261  for(i=1;i<=N;i++)
4262  {
4263    DName[i] = "D"+Name[i]; // concat
4264  }
4265  tmp    =  0;
4266  tmp[1] = "t";
4267  tmp[2] = "Dt";
4268  list SName ; SName[1] = "s";
4269  //  list NName = tmp + Name + DName + SName;
4270  list NName = tmp + SName + Name + DName;
4271  L[2]   = NName;
4272  tmp    = 0;
4273  // Name, Dname will be used further
4274  //  kill UName;
4275  kill NName;
4276  // block ord (a(1,1),dp);
4277  tmp[1]  = "a"; // string
4278  iv      = 1,1;
4279  tmp[2]  = iv; //intvec
4280  Lord[1] = tmp;
4281  // continue with a(0,0,1)
4282  tmp[1]  = "a"; // string
4283  iv      = 0,0,1;
4284  tmp[2]  = iv; //intvec
4285  Lord[2] = tmp;
4286  // continue with dp 1,1,1,1...
4287  tmp[1]  = "dp"; // string
4288  s       = "iv=";
4289  for(i=1;i<=Nnew;i++)
4290  {
4291    s = s+"1,";
4292  }
4293  s[size(s)]= ";";
4294  execute(s);
4295  tmp[2]    = iv;
4296  Lord[3]   = tmp;
4297  tmp[1]    = "C";
4298  iv        = 0;
4299  tmp[2]    = iv;
4300  Lord[4]   = tmp;
4301  tmp       = 0;
4302  L[3]      = Lord;
4303  // we are done with the list
4304  def @R@ = ring(L);
4305  setring @R@;
4306  matrix @D[Nnew][Nnew];
4307  @D[1,2]=1;
4308  for(i=1; i<=N; i++)
4309  {
4310    @D[3+i,N+3+i]=1;
4311  }
4312  // ADD [s,t]=-t, [s,Dt]=Dt
4313  @D[1,3] = -var(1);
4314  @D[2,3] = var(2);
4315  //  @D[N+3,2*(N+2)]=1; old t,Dt stuff
4316  //  L[5] = matrix(UpOneMatrix(Nnew));
4317  //  L[6] = @D;
4318  def @R = nc_algebra(1,@D);
4319  setring @R;
4320  kill @R@;
4321  dbprint(ppl,"// -1-1- the ring @R(t,Dt,s,_x,_Dx) is ready");
4322  dbprint(ppl-1, @R);
4323  // create the ideal I
4324  poly  F = imap(save,F);
4325  //  ideal I = u*F-t,u*v-1;
4326  ideal I = F-t;
4327  poly p;
4328  for(i=1; i<=N; i++)
4329  {
4330    //    p = u*Dt; // u*Dt
4331    p = Dt;
4332    p = diff(F,var(3+i))*p;
4333    I = I, var(N+3+i) + p;
4334  }
4335  //  I = I, var(1)*var(2) + var(Nnew) +1; // reduce it with t-f!!!
4336  // t*Dt + s +1 reduced with t-f gives f*Dt + s
4337  I = I, F*var(2) + var(3);
4338  // -------- the ideal I is ready ----------
4339  dbprint(ppl,"// -1-2- starting the elimination of t,Dt in @R");
4340  dbprint(ppl-1, I);
4341  ideal J = engine(I,eng);
4342  ideal K = nselect(J,1..2);
4343  dbprint(ppl,"// -1-3- t,Dt are eliminated");
4344  dbprint(ppl-1, K);  // K is without t, Dt
4345  K = engine(K,eng);  // std does the job too
4346  // now, we must change the ordering
4347  // and create a ring without t, Dt
4348  setring save;
4349  // ----------- the ring @R3 ------------
4350  // _x, _Dx,s;  elim.ord for _x,_Dx.
4351  // keep: N, i,j,s, tmp, RL
4352  Nnew = 2*N+1;
4353  kill Lord, tmp, iv, RName;
4354  list Lord, tmp;
4355  intvec iv;
4356  L[1] = RL[1];
4357  L[4] = RL[4];  // char, minpoly
4358  // check whether vars hava admissible names -> done earlier
4359  // now, create the names for new var
4360  tmp[1] = "s";
4361  // DName is defined earlier
4362  list NName = Name + DName + tmp;
4363  L[2] = NName;
4364  tmp = 0;
4365  // block ord (dp(N),dp);
4366  // string s is already defined
4367  s = "iv=";
4368  for (i=1; i<=Nnew-1; i++)
4369  {
4370    s = s+"1,";
4371  }
4372  s[size(s)]=";";
4373  execute(s);
4374  tmp[1] = "dp";  // string
4375  tmp[2] = iv;   // intvec
4376  Lord[1] = tmp;
4377  // continue with dp 1,1,1,1...
4378  tmp[1] = "dp";  // string
4379  s[size(s)] = ",";
4380  s = s+"1;";
4381  execute(s);
4382  kill s;
4383  kill NName;
4384  tmp[2]      = iv;
4385  Lord[2]     = tmp;
4386  tmp[1]      = "C";  iv  = 0;  tmp[2]=iv;
4387  Lord[3]     = tmp;  tmp = 0;
4388  L[3]        = Lord;
4389  // we are done with the list. Now add a Plural part
4390  def @R2@ = ring(L);
4391  setring @R2@;
4392  matrix @D[Nnew][Nnew];
4393  for (i=1; i<=N; i++)
4394  {
4395    @D[i,N+i]=1;
4396  }
4397  def @R2 = nc_algebra(1,@D);
4398  setring @R2;
4399  kill @R2@;
4400  dbprint(ppl,"//  -2-1- the ring @R2(_x,_Dx,s) is ready");
4401  dbprint(ppl-1, @R2);
4402  ideal MM = maxideal(1);
4403  //  MM = 0,s,MM;
4404  MM = 0,0,s,MM[1..size(MM)-1];
4405  map R01 = @R, MM;
4406  ideal K = R01(K);
4407  // total cleanup
4408  ideal LD = K;
4409  // make leadcoeffs positive
4410  for (i=1; i<= ncols(LD); i++)
4411  {
4412    if (leadcoef(LD[i]) <0 )
4413    {
4414      LD[i] = -LD[i];
4415    }
4416  }
4417  export LD;
4418  kill @R;
4419  return(@R2);
4420}
4421example
4422{
4423  "EXAMPLE:"; echo = 2;
4424  ring r = 0,(x,y,z),Dp;
4425  poly F = x^3+y^3+z^3;
4426  printlevel = 0;
4427  def A  = SannfsLOT(F);
4428  setring A;
4429  LD;
4430}
4431
4432/*
4433proc SannfsLOTold(poly F, list #)
4434"USAGE:  SannfsLOT(f [,eng]);  f a poly, eng an optional int
4435RETURN:  ring
4436PURPOSE: 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
4437NOTE:    activate the output ring with the @code{setring} command.
4438@*       In the ring D[s], the ideal LD (which is NOT a Groebner basis) is the needed D-module structure.
4439@*       If eng <>0, @code{std} is used for Groebner basis computations,
4440@*       otherwise, and by default @code{slimgb} is used.
4441@*       If printlevel=1, progress debug messages will be printed,
4442@*       if printlevel>=2, all the debug messages will be printed.
4443EXAMPLE: example SannfsLOT; shows examples
4444"
4445{
4446  int eng = 0;
4447  if ( size(#)>0 )
4448  {
4449    if ( typeof(#[1]) == "int" )
4450    {
4451      eng = int(#[1]);
4452    }
4453  }
4454  // returns a list with a ring and an ideal LD in it
4455  int ppl = printlevel-voice+2;
4456  //  printf("plevel :%s, voice: %s",printlevel,voice);
4457  def save = basering;
4458  int N = nvars(basering);
4459  //  int Nnew = 2*(N+2);
4460  int Nnew = 2*(N+1)+1; //removed u,v; added s
4461  int i,j;
4462  string s;
4463  list RL = ringlist(basering);
4464  list L, Lord;
4465  list tmp;
4466  intvec iv;
4467  L[1] = RL[1]; // char
4468  L[4] = RL[4]; // char, minpoly
4469  // check whether vars have admissible names
4470  list Name  = RL[2];
4471  list RName;
4472//   RName[1] = "u";
4473//   RName[2] = "v";
4474  RName[1] = "t";
4475  RName[2] = "Dt";
4476  for(i=1;i<=N;i++)
4477  {
4478    for(j=1; j<=size(RName);j++)
4479    {
4480      if (Name[i] == RName[j])
4481      {
4482        ERROR("Variable names should not include t,Dt");
4483      }
4484    }
4485  }
4486  // now, create the names for new vars
4487//   tmp[1]     = "u";
4488//   tmp[2]     = "v";
4489//   list UName = tmp;
4490  list DName;
4491  for(i=1;i<=N;i++)
4492  {
4493    DName[i] = "D"+Name[i]; // concat
4494  }
4495  tmp    =  0;
4496  tmp[1] = "t";
4497  tmp[2] = "Dt";
4498  list SName ; SName[1] = "s";
4499  //  list NName = UName +  tmp + Name + DName;
4500  list NName = tmp + Name + DName + SName;
4501  L[2]   = NName;
4502  tmp    = 0;
4503  // Name, Dname will be used further
4504  //  kill UName;
4505  kill NName;
4506  // block ord (a(1,1),dp);
4507  tmp[1]  = "a"; // string
4508  iv      = 1,1;
4509  tmp[2]  = iv; //intvec
4510  Lord[1] = tmp;
4511  // continue with dp 1,1,1,1...
4512  tmp[1]  = "dp"; // string
4513  s       = "iv=";
4514  for(i=1;i<=Nnew;i++)
4515  {
4516    s = s+"1,";
4517  }
4518  s[size(s)]= ";";
4519  execute(s);
4520  tmp[2]    = iv;
4521  Lord[2]   = tmp;
4522  tmp[1]    = "C";
4523  iv        = 0;
4524  tmp[2]    = iv;
4525  Lord[3]   = tmp;
4526  tmp       = 0;
4527  L[3]      = Lord;
4528  // we are done with the list
4529  def @R@ = ring(L);
4530  setring @R@;
4531  matrix @D[Nnew][Nnew];
4532  @D[1,2]=1;
4533  for(i=1; i<=N; i++)
4534  {
4535    @D[2+i,N+2+i]=1;
4536  }
4537  // ADD [s,t]=-t, [s,Dt]=Dt
4538  @D[1,Nnew] = -var(1);
4539  @D[2,Nnew] = var(2);
4540  //  @D[N+3,2*(N+2)]=1; old t,Dt stuff
4541  //  L[5] = matrix(UpOneMatrix(Nnew));
4542  //  L[6] = @D;
4543  def @R = nc_algebra(1,@D);
4544  setring @R;
4545  kill @R@;
4546  dbprint(ppl,"// -1-1- the ring @R(t,Dt,_x,_Dx,s) is ready");
4547  dbprint(ppl-1, @R);
4548  // create the ideal I
4549  poly  F = imap(save,F);
4550  //  ideal I = u*F-t,u*v-1;
4551  ideal I = F-t;
4552  poly p;
4553  for(i=1; i<=N; i++)
4554  {
4555    //    p = u*Dt; // u*Dt
4556    p = Dt;
4557    p = diff(F,var(2+i))*p;
4558    I = I, var(N+2+i) + p;
4559  }
4560  //  I = I, var(1)*var(2) + var(Nnew) +1; // reduce it with t-f!!!
4561  // t*Dt + s +1 reduced with t-f gives f*Dt + s
4562  I = I, F*var(2) + var(Nnew);
4563  // -------- the ideal I is ready ----------
4564  dbprint(ppl,"// -1-2- starting the elimination of t,Dt in @R");
4565  dbprint(ppl-1, I);
4566  ideal J = engine(I,eng);
4567  ideal K = nselect(J,1..2);
4568  dbprint(ppl,"// -1-3- t,Dt are eliminated");
4569  dbprint(ppl-1, K);  // K is without t, Dt
4570  K = engine(K,eng);  // std does the job too
4571  // now, we must change the ordering
4572  // and create a ring without t, Dt
4573  setring save;
4574  // ----------- the ring @R3 ------------
4575  // _x, _Dx,s;  elim.ord for _x,_Dx.
4576  // keep: N, i,j,s, tmp, RL
4577  Nnew = 2*N+1;
4578  kill Lord, tmp, iv, RName;
4579  list Lord, tmp;
4580  intvec iv;
4581  L[1] = RL[1];
4582  L[4] = RL[4];  // char, minpoly
4583  // check whether vars hava admissible names -> done earlier
4584  // now, create the names for new var
4585  tmp[1] = "s";
4586  // DName is defined earlier
4587  list NName = Name + DName + tmp;
4588  L[2] = NName;
4589  tmp = 0;
4590  // block ord (dp(N),dp);
4591  // string s is already defined
4592  s = "iv=";
4593  for (i=1; i<=Nnew-1; i++)
4594  {
4595    s = s+"1,";
4596  }
4597  s[size(s)]=";";
4598  execute(s);
4599  tmp[1] = "dp";  // string
4600  tmp[2] = iv;   // intvec
4601  Lord[1] = tmp;
4602  // continue with dp 1,1,1,1...
4603  tmp[1] = "dp";  // string
4604  s[size(s)] = ",";
4605  s = s+"1;";
4606  execute(s);
4607  kill s;
4608  kill NName;
4609  tmp[2]      = iv;
4610  Lord[2]     = tmp;
4611  tmp[1]      = "C";  iv  = 0;  tmp[2]=iv;
4612  Lord[3]     = tmp;  tmp = 0;
4613  L[3]        = Lord;
4614  // we are done with the list. Now add a Plural part
4615  def @R2@ = ring(L);
4616  setring @R2@;
4617  matrix @D[Nnew][Nnew];
4618  for (i=1; i<=N; i++)
4619  {
4620    @D[i,N+i]=1;
4621  }
4622  def @R2 = nc_algebra(1,@D);
4623  setring @R2;
4624  kill @R2@;
4625  dbprint(ppl,"//  -2-1- the ring @R2(_x,_Dx,s) is ready");
4626  dbprint(ppl-1, @R2);
4627  ideal MM = maxideal(1);
4628  MM = 0,s,MM;
4629  map R01 = @R, MM;
4630  ideal K = R01(K);
4631  // total cleanup
4632  ideal LD = K;
4633  // make leadcoeffs positive
4634  for (i=1; i<= ncols(LD); i++)
4635  {
4636    if (leadcoef(LD[i]) <0 )
4637    {
4638      LD[i] = -LD[i];
4639    }
4640  }
4641  export LD;
4642  kill @R;
4643  return(@R2);
4644}
4645example
4646{
4647  "EXAMPLE:"; echo = 2;
4648  ring r = 0,(x,y,z),Dp;
4649  poly F = x^3+y^3+z^3;
4650  printlevel = 0;
4651  def A  = SannfsLOTold(F);
4652  setring A;
4653  LD;
4654}
4655
4656*/
4657
4658proc annfsLOT(poly F, list #)
4659"USAGE:  annfsLOT(F [,eng]);  F a poly, eng an optional int
4660RETURN:  ring
4661PURPOSE: compute the D-module structure of basering[1/f]*f^s, according to
4662@* the Levandovskyy's modification of the algorithm by Oaku and Takayama
4663NOTE:    activate the output ring with the @code{setring} command. In this ring,
4664@*  - the ideal LD (which is a Groebner basis) is the needed D-module structure,
4665@*    which is obtained by substituting the minimal integer root of a Bernstein
4666@*    polynomial into the s-parametric ideal;
4667@*  - the list BS contains the roots with multiplicities of BS polynomial of f.
4668@*    If eng <>0, @code{std} is used for Groebner basis computations,
4669@*    otherwise and by default @code{slimgb} is used.
4670@*    If printlevel=1, progress debug messages will be printed,
4671@*    if printlevel>=2, all the debug messages will be printed.
4672EXAMPLE: example annfsLOT; shows examples
4673"
4674{
4675  int eng = 0;
4676  if ( size(#)>0 )
4677  {
4678    if ( typeof(#[1]) == "int" )
4679    {
4680      eng = int(#[1]);
4681    }
4682  }
4683  printlevel=printlevel+1;
4684  def save = basering;
4685  def @A = SannfsLOT(F,eng);
4686  setring @A;
4687  poly F = imap(save,F);
4688  def B  = annfs0(LD,F,eng);
4689  return(B);
4690}
4691example
4692{
4693  "EXAMPLE:"; echo = 2;
4694  ring r = 0,(x,y,z),Dp;
4695  poly F = z*x^2+y^3;
4696  printlevel = 0;
4697  def A  = annfsLOT(F);
4698  setring A;
4699  LD;
4700  BS;
4701}
4702
4703proc annfs0(ideal I, poly F, list #)
4704"USAGE:  annfs0(I, F [,eng]);  I an ideal, F a poly, eng an optional int
4705RETURN:  ring
4706PURPOSE: compute the annihilator ideal of f^s in the Weyl Algebra, based
4707@* on the output of Sannfs-like procedure
4708NOTE:    activate the output ring with the @code{setring} command. In this ring,
4709@* - the ideal LD (which is a Groebner basis) is the annihilator of f^s,
4710@* - the list BS contains the roots with multiplicities of BS polynomial of f.
4711@*  If eng <>0, @code{std} is used for Groebner basis computations,
4712@*  otherwise and by default @code{slimgb} is used.
4713@*  If printlevel=1, progress debug messages will be printed,
4714@*  if printlevel>=2, all the debug messages will be printed.
4715EXAMPLE: example annfs0; shows examples
4716"
4717{
4718  int eng = 0;
4719  if ( size(#)>0 )
4720  {
4721    if ( typeof(#[1]) == "int" )
4722    {
4723      eng = int(#[1]);
4724    }
4725  }
4726  def @R2 = basering;
4727  // we're in D_n[s], where the elim ord for s is set
4728  ideal J = NF(I,std(F));
4729  // make leadcoeffs positive
4730  int i;
4731  for (i=1; i<= ncols(J); i++)
4732  {
4733    if (leadcoef(J[i]) <0 )
4734    {
4735      J[i] = -J[i];
4736    }
4737  }
4738  J = J,F;
4739  ideal M = engine(J,eng);
4740  int Nnew = nvars(@R2);
4741  ideal K2 = nselect(M,1..Nnew-1);
4742  int ppl = printlevel-voice+2;
4743  dbprint(ppl,"// -1-1- _x,_Dx are eliminated in basering");
4744  dbprint(ppl-1, K2);
4745  // the ring @R3 and the search for minimal negative int s
4746  ring @R3 = 0,s,dp;
4747  dbprint(ppl,"// -2-1- the ring @R3 i.e. K[s] is ready");
4748  ideal K3 = imap(@R2,K2);
4749  poly p = K3[1];
4750  dbprint(ppl,"// -2-2- factorization");
4751  //  ideal P = factorize(p,1);  //without constants and multiplicities
4752  //  "--------- b-function factorizes into ---------";   P;
4753  // convert factors to the list of their roots with mults
4754  // assume all factors are linear
4755  //  ideal BS = normalize(P);
4756  //  BS = subst(BS,s,0);
4757  //  BS = -BS;
4758  list P = factorize(p);          //with constants and multiplicities
4759  ideal bs; intvec m;             //the Bernstein polynomial is monic, so we are not interested in constants
4760  for (i=2; i<= size(P[1]); i++)  //we delete P[1][1] and P[2][1]
4761  {
4762    bs[i-1] = P[1][i];
4763    m[i-1]  = P[2][i];
4764  }
4765  int sP = minIntRoot(bs,1);
4766  bs =  normalize(bs);
4767  bs = -subst(bs,s,0);
4768  dbprint(ppl,"// -2-3- minimal integer root found");
4769  dbprint(ppl-1, sP);
4770 //TODO: sort BS!
4771  // --------- substitute s found in the ideal ---------
4772  // --------- going back to @R and substitute ---------
4773  setring @R2;
4774  K2 = subst(I,s,sP);
4775  // create the ordinary Weyl algebra and put the result into it,
4776  // thus creating the ring @R5
4777  // keep: N, i,j,s, tmp, RL
4778  Nnew = Nnew - 1; // former 2*N;
4779  // list RL = ringlist(save);  // is defined earlier
4780  //  kill Lord, tmp, iv;
4781  list L = 0;
4782  list Lord, tmp;
4783  intvec iv;
4784  list RL = ringlist(basering);
4785  L[1] = RL[1];
4786  L[4] = RL[4];  //char, minpoly
4787  // check whether vars have admissible names -> done earlier
4788  // list Name = RL[2]M
4789  // DName is defined earlier
4790  list NName; // = RL[2]; // skip the last var 's'
4791  for (i=1; i<=Nnew; i++)
4792  {
4793    NName[i] =  RL[2][i];
4794  }
4795  L[2] = NName;
4796  // dp ordering;
4797  string s = "iv=";
4798  for (i=1; i<=Nnew; i++)
4799  {
4800    s = s+"1,";
4801  }
4802  s[size(s)] = ";";
4803  execute(s);
4804  tmp     = 0;
4805  tmp[1]  = "dp";  // string
4806  tmp[2]  = iv;  // intvec
4807  Lord[1] = tmp;
4808  kill s;
4809  tmp[1]  = "C";
4810  iv = 0;
4811  tmp[2]  = iv;
4812  Lord[2] = tmp;
4813  tmp     = 0;
4814  L[3]    = Lord;
4815  // we are done with the list
4816  // Add: Plural part
4817  def @R4@ = ring(L);
4818  setring @R4@;
4819  int N = Nnew div 2;
4820  matrix @D[Nnew][Nnew];
4821  for (i=1; i<=N; i++)
4822  {
4823    @D[i,N+i]=1;
4824  }
4825  def @R4 = nc_algebra(1,@D);
4826  setring @R4;
4827  kill @R4@;
4828  dbprint(ppl,"// -3-1- the ring @R4 is ready");
4829  dbprint(ppl-1, @R4);
4830  ideal K4 = imap(@R2,K2);
4831  option(redSB);
4832  dbprint(ppl,"// -3-2- the final cosmetic std");
4833  K4 = engine(K4,eng);  // std does the job too
4834  // total cleanup
4835  ideal bs = imap(@R3,bs);
4836  kill @R3;
4837  list BS = bs,m;
4838  export BS;
4839  ideal LD = K4;
4840  export LD;
4841  return(@R4);
4842}
4843example
4844{ "EXAMPLE:"; echo = 2;
4845  ring r = 0,(x,y,z),Dp;
4846  poly F = x^3+y^3+z^3;
4847  printlevel = 0;
4848  def A = SannfsBM(F);   setring A;
4849  // alternatively, one can use SannfsOT or SannfsLOT
4850  LD;
4851  poly F = imap(r,F);
4852  def B  = annfs0(LD,F);  setring B;
4853  LD;
4854  BS;
4855}
4856
4857// proc annfsgms(poly F, list #)
4858// "USAGE:  annfsgms(f [,eng]);  f a poly, eng an optional int
4859// ASSUME:  f has an isolated critical point at 0
4860// RETURN:  ring
4861// PURPOSE: compute the D-module structure of basering[1/f]*f^s
4862// NOTE:    activate the output ring with the @code{setring} command. In this ring,
4863// @*       - the ideal LD is the needed D-mod structure,
4864// @*       - the ideal BS is the list of roots of a Bernstein polynomial of f.
4865// @*       If eng <>0, @code{std} is used for Groebner basis computations,
4866// @*       otherwise (and by default) @code{slimgb} is used.
4867// @*       If printlevel=1, progress debug messages will be printed,
4868// @*       if printlevel>=2, all the debug messages will be printed.
4869// EXAMPLE: example annfsgms; shows examples
4870// "
4871// {
4872//   LIB "gmssing.lib";
4873//   int eng = 0;
4874//   if ( size(#)>0 )
4875//   {
4876//     if ( typeof(#[1]) == "int" )
4877//     {
4878//       eng = int(#[1]);
4879//     }
4880//   }
4881//   int ppl = printlevel-voice+2;
4882//   // returns a ring with the ideal LD in it
4883//   def save = basering;
4884//   // compute the Bernstein polynomial from gmssing.lib
4885//   list RL = ringlist(basering);
4886//   // in the descr. of the ordering, replace "p" by "s"
4887//   list NL = convloc(RL);
4888//   // create a ring with the ordering, converted to local
4889//   def @LR = ring(NL);
4890//   setring @LR;
4891//   poly F  = imap(save, F);
4892//   ideal B = bernstein(F)[1];
4893//   // since B may not contain (s+1) [following gmssing.lib]
4894//   // add it!
4895//   B = B,-1;
4896//   B = simplify(B,2+4); // erase zero and repeated entries
4897//   // find the minimal integer value
4898//   int   S = minIntRoot(B,0);
4899//   dbprint(ppl,"// -0- minimal integer root found");
4900//   dbprint(ppl-1,S);
4901//   setring save;
4902//   int N = nvars(basering);
4903//   int Nnew = 2*(N+2);
4904//   int i,j;
4905//   string s;
4906//   //  list RL = ringlist(basering);
4907//   list L, Lord;
4908//   list tmp;
4909//   intvec iv;
4910//   L[1] = RL[1]; // char
4911//   L[4] = RL[4]; // char, minpoly
4912//   // check whether vars have admissible names
4913//   list Name  = RL[2];
4914//   list RName;
4915//   RName[1] = "u";
4916//   RName[2] = "v";
4917//   RName[3] = "t";
4918//   RName[4] = "Dt";
4919//   for(i=1;i<=N;i++)
4920//   {
4921//     for(j=1; j<=size(RName);j++)
4922//     {
4923//       if (Name[i] == RName[j])
4924//       {
4925//         ERROR("Variable names should not include u,v,t,Dt");
4926//       }
4927//     }
4928//   }
4929//   // now, create the names for new vars
4930//   //  tmp[1]     = "u";  tmp[2]     = "v";  tmp[3]     = "t";  tmp[4]     = "Dt";
4931//   list UName = RName;
4932//   list DName;
4933//   for(i=1;i<=N;i++)
4934//   {
4935//     DName[i] = "D"+Name[i]; // concat
4936//   }
4937//   list NName = UName + Name + DName;
4938//   L[2]       = NName;
4939//   tmp        = 0;
4940//   // Name, Dname will be used further
4941//   kill UName;
4942//   kill NName;
4943//   // block ord (a(1,1),dp);
4944//   tmp[1]  = "a"; // string
4945//   iv      = 1,1;
4946//   tmp[2]  = iv; //intvec
4947//   Lord[1] = tmp;
4948//   // continue with dp 1,1,1,1...
4949//   tmp[1]  = "dp"; // string
4950//   s       = "iv=";
4951//   for(i=1; i<=Nnew; i++) // need really all vars!
4952//   {
4953//     s = s+"1,";
4954//   }
4955//   s[size(s)]= ";";
4956//   execute(s);
4957//   tmp[2]    = iv;
4958//   Lord[2]   = tmp;
4959//   tmp[1]    = "C";
4960//   iv        = 0;
4961//   tmp[2]    = iv;
4962//   Lord[3]   = tmp;
4963//   tmp       = 0;
4964//   L[3]      = Lord;
4965//   // we are done with the list
4966//   def @R = ring(L);
4967//   setring @R;
4968//   matrix @D[Nnew][Nnew];
4969//   @D[3,4] = 1; // t,Dt
4970//   for(i=1; i<=N; i++)
4971//   {
4972//     @D[4+i,4+N+i]=1;
4973//   }
4974//   //  L[5] = matrix(UpOneMatrix(Nnew));
4975//   //  L[6] = @D;
4976//   nc_algebra(1,@D);
4977//   dbprint(ppl,"// -1-1- the ring @R is ready");
4978//   dbprint(ppl-1,@R);
4979//   // create the ideal
4980//   poly F  = imap(save,F);
4981//   ideal I = u*F-t,u*v-1;
4982//   poly p;
4983//   for(i=1; i<=N; i++)
4984//   {
4985//     p = u*Dt; // u*Dt
4986//     p = diff(F,var(4+i))*p;
4987//     I = I, var(N+4+i) + p; // Dx, Dy
4988//   }
4989//   // add the relations between t,Dt and s
4990//   //  I = I, t*Dt+1+S;
4991//   // -------- the ideal I is ready ----------
4992//   dbprint(ppl,"// -1-2- starting the elimination of u,v in @R");
4993//   ideal J = engine(I,eng);
4994//   ideal K = nselect(J,1..2);
4995//   dbprint(ppl,"// -1-3- u,v are eliminated in @R");
4996//   dbprint(ppl-1,K); // without u,v: not yet our answer
4997//   //----- create a ring with elim.ord for t,Dt -------
4998//   setring save;
4999//   // ------------ new ring @R2 ------------------
5000//   // without u,v and with the elim.ord for t,Dt
5001//   // keep: N, i,j,s, tmp, RL
5002//   Nnew = 2*N+2;
5003//   //  list RL = ringlist(save); // is defined earlier
5004//   kill Lord,tmp,iv, RName;
5005//   L = 0;
5006//   list Lord, tmp;
5007//   intvec iv;
5008//   L[1] = RL[1]; // char
5009//   L[4] = RL[4]; // char, minpoly
5010//   // check whether vars have admissible names -> done earlier
5011//   //  list Name  = RL[2];
5012//   list RName;
5013//   RName[1] = "t";
5014//   RName[2] = "Dt";
5015//   // DName is defined earlier
5016//   list NName = RName + Name + DName;
5017//   L[2]   = NName;
5018//   tmp    = 0;
5019//   // block ord (a(1,1),dp);
5020//   tmp[1]  = "a"; // string
5021//   iv      = 1,1;
5022//   tmp[2]  = iv; //intvec
5023//   Lord[1] = tmp;
5024//   // continue with dp 1,1,1,1...
5025//   tmp[1]  = "dp"; // string
5026//   s       = "iv=";
5027//   for(i=1;i<=Nnew;i++)
5028//   {
5029//     s = s+"1,";
5030//   }
5031//   s[size(s)]= ";";
5032//   execute(s);
5033//   kill s;
5034//   kill NName;
5035//   tmp[2]    = iv;
5036//   Lord[2]   = tmp;
5037//   tmp[1]    = "C";
5038//   iv        = 0;
5039//   tmp[2]    = iv;
5040//   Lord[3]   = tmp;
5041//   tmp       = 0;
5042//   L[3]      = Lord;
5043//   // we are done with the list
5044//   // Add: Plural part
5045//   def @R2 = ring(L);
5046//   setring @R2;
5047//   matrix @D[Nnew][Nnew];
5048//   @D[1,2]=1;
5049//   for(i=1; i<=N; i++)
5050//   {
5051//     @D[2+i,2+N+i]=1;
5052//   }
5053//   nc_algebra(1,@D);
5054//   dbprint(ppl,"// -2-1- the ring @R2 is ready");
5055//   dbprint(ppl-1,@R2);
5056//   ideal MM = maxideal(1);
5057//   MM = 0,0,MM;
5058//   map R01 = @R, MM;
5059//   ideal K2 = R01(K);
5060//   // add the relations between t,Dt and s
5061//   //  K2       = K2, t*Dt+1+S;
5062//   poly G = t*Dt+S+1;
5063//   K2 = NF(K2,std(G)),G;
5064//   dbprint(ppl,"// -2-2- starting elimination for t,Dt in @R2");
5065//   ideal J  = engine(K2,eng);
5066//   ideal K  = nselect(J,1..2);
5067//   dbprint(ppl,"// -2-3- t,Dt are eliminated");
5068//   dbprint(ppl-1,K);
5069//   //  "------- produce a final result --------";
5070//   // ----- create the ordinary Weyl algebra and put
5071//   // ----- the result into it
5072//   // ------ create the ring @R5
5073//   // keep: N, i,j,s, tmp, RL
5074//   setring save;
5075//   Nnew = 2*N;
5076//   //  list RL = ringlist(save); // is defined earlier
5077//   kill Lord, tmp, iv;
5078//   //  kill L;
5079//   L = 0;
5080//   list Lord, tmp;
5081//   intvec iv;
5082//   L[1] = RL[1]; // char
5083//   L[4] = RL[4]; // char, minpoly
5084//   // check whether vars have admissible names -> done earlier
5085//   //  list Name  = RL[2];
5086//   // DName is defined earlier
5087//   list NName = Name + DName;
5088//   L[2]   = NName;
5089//   // dp ordering;
5090//   string   s       = "iv=";
5091//   for(i=1;i<=2*N;i++)
5092//   {
5093//     s = s+"1,";
5094//   }
5095//   s[size(s)]= ";";
5096//   execute(s);
5097//   tmp     = 0;
5098//   tmp[1]  = "dp"; // string
5099//   tmp[2]  = iv; //intvec
5100//   Lord[1] = tmp;
5101//   kill s;
5102//   tmp[1]    = "C";
5103//   iv        = 0;
5104//   tmp[2]    = iv;
5105//   Lord[2]   = tmp;
5106//   tmp       = 0;
5107//   L[3]      = Lord;
5108//   // we are done with the list
5109//   // Add: Plural part
5110//   def @R5 = ring(L);
5111//   setring @R5;
5112//   matrix @D[Nnew][Nnew];
5113//   for(i=1; i<=N; i++)
5114//   {
5115//     @D[i,N+i]=1;
5116//   }
5117//   nc_algebra(1,@D);
5118//   dbprint(ppl,"// -3-1- the ring @R5 is ready");
5119//   dbprint(ppl-1,@R5);
5120//   ideal K5 = imap(@R2,K);
5121//   option(redSB);
5122//   dbprint(ppl,"// -3-2- the final cosmetic std");
5123//   K5 = engine(K5,eng); // std does the job too
5124//   // total cleanup
5125//   kill @R;
5126//   kill @R2;
5127//   ideal LD = K5;
5128//   ideal BS = imap(@LR,B);
5129//   kill @LR;
5130//   export BS;
5131//   export LD;
5132//   return(@R5);
5133// }
5134// example
5135// {
5136//   "EXAMPLE:"; echo = 2;
5137//   ring r = 0,(x,y,z),Dp;
5138//   poly F = x^2+y^3+z^5;
5139//   def A = annfsgms(F);
5140//   setring A;
5141//   LD;
5142//   print(matrix(BS));
5143// }
5144
5145
5146proc convloc(list @NL)
5147"USAGE:  convloc(L); L a list
5148RETURN:  list
5149PURPOSE: convert a ringlist L into another ringlist,
5150@* where all the 'p' orderings are replaced with the 's' orderings, e.g. @code{dp} by @code{ds}.
5151ASSUME: L is a result of a ringlist command
5152EXAMPLE: example convloc; shows examples
5153"
5154{
5155  list NL = @NL;
5156  // given a ringlist, returns a new ringlist,
5157  // where all the p-orderings are replaced with s-ord's
5158  int i,j,k,found;
5159  int nblocks = size(NL[3]);
5160  for(i=1; i<=nblocks; i++)
5161  {
5162    for(j=1; j<=size(NL[3][i]); j++)
5163    {
5164      if (typeof(NL[3][i][j]) == "string" )
5165      {
5166        found = 0;
5167        for (k=1; k<=size(NL[3][i][j]); k++)
5168        {
5169          if (NL[3][i][j][k]=="p")
5170          {
5171            NL[3][i][j][k]="s";
5172            found = 1;
5173            //    printf("replaced at %s,%s,%s",i,j,k);
5174          }
5175        }
5176      }
5177    }
5178  }
5179  return(NL);
5180}
5181example
5182{
5183  "EXAMPLE:"; echo = 2;
5184  ring r = 0,(x,y,z),(Dp(2),dp(1));
5185  list L = ringlist(r);
5186  list N = convloc(L);
5187  def rs = ring(N);
5188  setring rs;
5189  rs;
5190}
5191
5192proc annfspecial(ideal I, poly F, int mir, number n)
5193"USAGE:  annfspecial(I,F,mir,n);  I an ideal, F a poly, int mir, number n
5194RETURN:  ideal
5195PURPOSE: compute the annihilator ideal of F^n in the Weyl Algebra
5196@*           for the given rational number n
5197ASSUME:  The basering is D[s] and contains 's' explicitly as a variable,
5198@*   the ideal I is the Ann F^s in D[s] (obtained with e.g. SannfsBM),
5199@*   the integer 'mir' is the minimal integer root of the BS polynomial of F,
5200@*   and the number n is rational.
5201NOTE: We compute the real annihilator for any rational value of n (both
5202@*       generic and exceptional). The implementation goes along the lines of
5203@*       the Algorithm 5.3.15 from Saito-Sturmfels-Takayama.
5204DISPLAY: If printlevel=1, progress debug messages will be printed,
5205@*       if printlevel>=2, all the debug messages will be printed.
5206EXAMPLE: example annfspecial; shows examples
5207"
5208{
5209
5210  if (!isRational(n))
5211  {
5212    "ERROR: n must be a rational number!";
5213  }
5214  int ppl = printlevel-voice+2;
5215  //  int mir =  minIntRoot(L[1],0);
5216  int ns   = varNum("s");
5217  if (!ns)
5218  {
5219    ERROR("Variable s expected in the ideal AnnFs");
5220  }
5221  int d;
5222  ideal P = subst(I,var(ns),n);
5223  if (denominator(n) == 1)
5224  {
5225    // n is fraction-free
5226    d = int(numerator(n));
5227    if ( (!d) && (n!=0))
5228    {
5229      ERROR("no parametric special values are allowed");
5230    }
5231    d = d - mir;
5232    if (d>0)
5233    {
5234      dbprint(ppl,"// -1-1- starting syzygy computations");
5235      matrix J[1][1] = F^d;
5236      dbprint(ppl-1,"// -1-1-1- of the polynomial ideal");
5237      dbprint(ppl-1,J);
5238      matrix K[1][size(I)] = subst(I,var(ns),mir);
5239      dbprint(ppl-1,"// -1-1-2- modulo ideal:");
5240      dbprint(ppl-1, K);
5241      module M = modulo(J,K);
5242      dbprint(ppl-1,"// -1-1-3- getting the result:");
5243      dbprint(ppl-1, M);
5244      P  = P, ideal(M);
5245      dbprint(ppl,"// -1-2- finished syzygy computations");
5246    }
5247    else
5248    {
5249      dbprint(ppl,"// -1-1- d<=0, no syzygy computations needed");
5250      dbprint(ppl-1,"// -1-2- for d =");
5251      dbprint(ppl-1, d);
5252    }
5253  }
5254  // also the else case: d<=0 or n is not an integer
5255  dbprint(ppl,"// -2-1- starting final Groebner basis");
5256  P = groebner(P);
5257  dbprint(ppl,"// -2-2- finished final Groebner basis");
5258  return(P);
5259}
5260example
5261{
5262  "EXAMPLE:"; echo = 2;
5263  ring r = 0,(x,y),dp;
5264  poly F = x3-y2;
5265  def  B = annfs(F);  setring B;
5266  minIntRoot(BS[1],0);
5267  // So, the minimal integer root is -1
5268  setring r;
5269  def  A = SannfsBM(F);
5270  setring A;
5271  poly F = x3-y2;
5272  annfspecial(LD,F,-1,3/4); // generic root
5273  annfspecial(LD,F,-1,-2);  // integer but still generic root
5274  annfspecial(LD,F,-1,1);   // exceptional root
5275}
5276
5277/*
5278//static proc new_ex_annfspecial()
5279{
5280  //another example for annfspecial: x3+y3+z3
5281  ring r = 0,(x,y,z),dp;
5282  poly F =  x3+y3+z3;
5283  def  B = annfs(F);  setring B;
5284  minIntRoot(BS[1],0);
5285  // So, the minimal integer root is -1
5286  setring r;
5287  def  A = SannfsBM(F);
5288  setring A;
5289  poly F =  x3+y3+z3;
5290  annfspecial(LD,F,-1,3/4); // generic root
5291  annfspecial(LD,F,-1,-2);  // integer but still generic root
5292  annfspecial(LD,F,-1,1);   // exceptional root
5293}
5294*/
5295
5296proc minIntRoot(ideal P, int fact)
5297"USAGE:  minIntRoot(P, fact); P an ideal, fact an int
5298RETURN:  int
5299PURPOSE: minimal integer root of a maximal ideal P
5300NOTE:    if fact==1, P is the result of some 'factorize' call,
5301@*       else P is treated as the result of bernstein::gmssing.lib
5302@*       in both cases without constants and multiplicities
5303EXAMPLE: example minIntRoot; shows examples
5304"
5305{
5306  //    ideal P = factorize(p,1);
5307  // or ideal P = bernstein(F)[1];
5308  intvec vP;
5309  number nP;
5310  int i;
5311  if ( fact )
5312  {
5313    // the result comes from "factorize"
5314    P = normalize(P); // now leadcoef = 1
5315    // TODO: hunt for units and kill then !!!
5316    P = matrix(lead(P))-P;
5317    // nP = leadcoef(P[i]-lead(P[i])); // for 1 var only, extract the coeff
5318  }
5319  else
5320  {
5321    // bernstein deletes -1 usually
5322    P = P, -1;
5323  }
5324  // for both situations:
5325  // now we have an ideal of fractions of type "number"
5326  int sP = size(P);
5327  for(i=1; i<=sP; i++)
5328  {
5329    nP = leadcoef(P[i]);
5330    if ( (nP - int(nP)) == 0 )
5331    {
5332      vP = vP,int(nP);
5333    }
5334  }
5335  if ( size(vP)>=2 )
5336  {
5337    vP = vP[2..size(vP)];
5338  }
5339  sP = -Max(-vP);
5340  if (sP == 0)
5341  {
5342    "Warning: zero root present!";
5343  }
5344  return(sP);
5345}
5346example
5347{
5348  "EXAMPLE:"; echo = 2;
5349  ring r   = 0,(x,y),ds;
5350  poly f1  = x*y*(x+y);
5351  ideal I1 = bernstein(f1)[1]; // a local Bernstein poly
5352  I1;
5353  minIntRoot(I1,0);
5354  poly  f2  = x2-y3;
5355  ideal I2  = bernstein(f2)[1];
5356  I2;
5357  minIntRoot(I2,0);
5358  // now we illustrate the behaviour of factorize
5359  // together with a global ordering
5360  ring r2  = 0,x,dp;
5361  poly f3   = 9*(x+2/3)*(x+1)*(x+4/3); //global b-polynomial of f1=x*y*(x+y)
5362  ideal I3 = factorize(f3,1);
5363  I3;
5364  minIntRoot(I3,1);
5365  // and a more interesting situation
5366  ring  s  = 0,(x,y,z),ds;
5367  poly  f  = x3 + y3 + z3;
5368  ideal I  = bernstein(f)[1];
5369  I;
5370  minIntRoot(I,0);
5371}
5372
5373proc isHolonomic(def M)
5374"USAGE:  isHolonomic(M); M an ideal/module/matrix
5375RETURN:  int, 1 if M is holonomic over the base ring, and 0 otherwise
5376ASSUME: basering is a Weyl algebra in characteristic 0
5377PURPOSE: check whether M is holonomic over the base ring
5378NOTE:    M is holonomic if 2*dim(M) = dim(R), where R is the
5379base ring; dim stands for Gelfand-Kirillov dimension
5380EXAMPLE: example isHolonomic; shows examples
5381"
5382{
5383  // char>0 or qring
5384  if (  (size(ideal(basering)) >0) || (char(basering) >0) )
5385  {
5386    ERROR("Basering is inappropriate: characteristic>0 or qring present");
5387  }
5388  if (!isWeyl(basering))
5389  {
5390    ERROR("Basering is not a Weyl algebra");
5391  }
5392
5393  if ( (typeof(M) != "ideal") && (typeof(M) != "module") && (typeof(M) != "matrix") )
5394  {
5395  //  print(typeof(M));
5396    ERROR("an argument of type ideal/module/matrix expected");
5397  }
5398  if (attrib(M,"isSB")!=1)
5399  {
5400    M = engine(M,0);
5401  }
5402  int dimR = gkdim(std(0));
5403  int dimM = gkdim(M);
5404  return( (dimR==2*dimM) );
5405}
5406example
5407{
5408  "EXAMPLE:"; echo = 2;
5409  ring R = 0,(x,y),dp;
5410  poly F = x*y*(x+y);
5411  def A = annfsBM(F,0);
5412  setring A;
5413  LD;
5414  isHolonomic(LD);
5415  ideal I = std(LD[1]);
5416  I;
5417  isHolonomic(I);
5418}
5419
5420proc reiffen(int p, int q)
5421"USAGE:  reiffen(p, q);  int p, int q
5422RETURN:  ring
5423PURPOSE: set up the polynomial, describing a Reiffen curve
5424NOTE:  activate the output ring with the @code{setring} command and
5425@*       find the curve as a polynomial RC.
5426@*  A Reiffen curve is defined as RC = x^p + y^q + xy^{q-1}, q >= p+1 >= 5
5427
5428EXAMPLE: example reiffen; shows examples
5429"
5430{
5431  // we allow also other numbers, p \geq 1, q\geq 1
5432// a Reiffen curve is defined as
5433// F = x^p + y^q +x*y^{q-1}, q \geq p+1 \geq 5
5434
5435// ASSUME: q >= p+1 >= 5. Otherwise an error message is returned
5436
5437//   if ( (p<4) || (q<5) || (q-p<1) )
5438//   {
5439//     ERROR("Some of conditions p>=4, q>=5 or q>=p+1 is not satisfied!");
5440//   }
5441  if ( (p<1) || (q<1) )
5442  {
5443    ERROR("Some of conditions p>=1, q>=1 is not satisfied!");
5444  }
5445  ring @r = 0,(x,y),dp;
5446  poly RC = y^q +x^p + x*y^(q-1);
5447  export RC;
5448  return(@r);
5449}
5450example
5451{
5452  "EXAMPLE:"; echo = 2;
5453  def r = reiffen(4,5);
5454  setring r;
5455  RC;
5456}
5457
5458proc arrange(int p)
5459"USAGE:  arrange(p);  int p
5460RETURN:  ring
5461PURPOSE: set up the polynomial, describing a hyperplane arrangement
5462NOTE:  must be executed in a commutative ring
5463ASSUME: basering is present and it is commutative
5464EXAMPLE: example arrange; shows examples
5465"
5466{
5467  int UseBasering = 0 ;
5468  if (p<2)
5469  {
5470    ERROR("p>=2 is required!");
5471  }
5472  if ( nameof(basering)!="basering" )
5473  {
5474    if (p > nvars(basering))
5475    {
5476      ERROR("too big p");
5477    }
5478    else
5479    {
5480      def @r = basering;
5481      UseBasering = 1;
5482    }
5483  }
5484  else
5485  {
5486    // no basering found
5487    ERROR("no basering found!");
5488    //    ring @r = 0,(x(1..p)),dp;
5489  }
5490  int i,j,sI;
5491  poly  q = 1;
5492  list ar;
5493  ideal tmp;
5494  tmp = ideal(var(1));
5495  ar[1] = tmp;
5496  for (i = 2; i<=p; i++)
5497  {
5498    // add i-nary sums to the product
5499    ar = indAR(ar,i);
5500  }
5501  for (i = 1; i<=p; i++)
5502  {
5503    tmp = ar[i]; sI = size(tmp);
5504    for (j = 1; j<=sI; j++)
5505    {
5506      q = q*tmp[j];
5507    }
5508  }
5509  if (UseBasering)
5510  {
5511    return(q);
5512  }
5513  //  poly AR = q; export AR;
5514  //  return(@r);
5515}
5516example
5517{
5518  "EXAMPLE:"; echo = 2;
5519  ring X = 0,(x,y,z,t),dp;
5520  poly q = arrange(3);
5521  factorize(q,1);
5522}
5523
5524proc checkRoot(poly F, number a, list #)
5525"USAGE:  checkRoot(f,alpha [,S,eng]);  poly f, number alpha, string S, int eng
5526RETURN:  int
5527ASSUME: Basering is a commutative ring, alpha is a positive rational number.
5528PURPOSE: check whether a negative rational number -alpha is a root of the global
5529@* Bernstein-Sato polynomial of f and compute its multiplicity,
5530@* with the algorithm given by S and with the Groebner basis engine given by eng.
5531NOTE:  The annihilator of f^s in D[s] is needed and hence it is computed with the
5532@*       algorithm by Briancon and Maisonobe. The value of a string S can be
5533@*       'alg1' (default) - for the algorithm 1 of [LM08]
5534@*       'alg2' - for the algorithm 2 of [LM08]
5535@*       Depending on the value of S, the output of type int is:
5536@*       'alg1': 1 only if -alpha is a root of the global Bernstein-Sato polynomial
5537@*       'alg2':  the multiplicity of -alpha as a root of the global Bernstein-Sato
5538@*                  polynomial of f. If -alpha is not a root, the output is 0.
5539@*       If eng <>0, @code{std} is used for Groebner basis computations,
5540@*       otherwise (and by default) @code{slimgb} is used.
5541DISPLAY: If printlevel=1, progress debug messages will be printed,
5542@*          if printlevel>=2, all the debug messages will be printed.
5543EXAMPLE: example checkRoot; shows examples
5544"
5545{
5546  int eng = 0;
5547  int chs = 0; // choice
5548  string algo = "alg1";
5549  string st;
5550  if ( size(#)>0 )
5551  {
5552   if ( typeof(#[1]) == "string" )
5553   {
5554     st = string(#[1]);
5555     if ( (st == "alg1") || (st == "ALG1") || (st == "Alg1") ||(st == "aLG1"))
5556     {
5557       algo = "alg1";
5558       chs  = 1;
5559     }
5560     if ( (st == "alg2") || (st == "ALG2") || (st == "Alg2") || (st == "aLG2"))
5561     {
5562       algo = "alg2";
5563       chs  = 1;
5564     }
5565     if (chs != 1)
5566     {
5567       // incorrect value of S
5568       print("Incorrect algorithm given, proceed with the default alg1");
5569       algo = "alg1";
5570     }
5571     // second arg
5572     if (size(#)>1)
5573     {
5574       // exists 2nd arg
5575       if ( typeof(#[2]) == "int" )
5576       {
5577         // the case: given alg, given engine
5578         eng = int(#[2]);
5579       }
5580       else
5581       {
5582         eng = 0;
5583       }
5584     }
5585     else
5586     {
5587       // no second arg
5588       eng = 0;
5589     }
5590   }
5591   else
5592   {
5593     if ( typeof(#[1]) == "int" )
5594     {
5595       // the case: default alg, engine
5596       eng = int(#[1]);
5597       // algo = "alg1";  //is already set
5598     }
5599     else
5600     {
5601       // incorr. 1st arg
5602       algo = "alg1";
5603     }
5604   }
5605  }
5606  // size(#)=0, i.e. there is no algorithm and no engine given
5607  //  eng = 0; algo = "alg1";  //are already set
5608  // int ppl = printlevel-voice+2;
5609// check assume: a is positive rational number
5610  if (!isRational(a))
5611  {
5612    ERROR("rational root expected for checking");
5613  }
5614  if (numerator(a) < 0 )
5615  {
5616    ERROR("expected positive -alpha");
5617    // the following is more user-friendly but less correct
5618    //    print("proceeding with the negated root");
5619    //    a = -a;
5620  }
5621  printlevel=printlevel+1;
5622  def save = basering;
5623  def @A = SannfsBM(F);
5624  setring @A;
5625  poly F = imap(save,F);
5626  number a = imap(save,a);
5627  if ( algo=="alg1")
5628  {
5629    int output = checkRoot1(LD,F,a,eng);
5630  }
5631  else
5632  {
5633    if ( algo=="alg2")
5634    {
5635      int output = checkRoot2(LD,F,a,eng);
5636    }
5637  }
5638  printlevel=printlevel-1;
5639  return(output);
5640}
5641example
5642{
5643  "EXAMPLE:"; echo = 2;
5644  printlevel=0;
5645  ring r = 0,(x,y),Dp;
5646  poly F = x^4+y^5+x*y^4;
5647  checkRoot(F,11/20);    // -11/20 is a root of bf
5648  poly G = x*y;
5649  checkRoot(G,1,"alg2"); // -1 is a root of bg with multiplicity 2
5650}
5651
5652proc checkRoot1(ideal I, poly F, number a, list #)
5653"USAGE:  checkRoot1(I,f,alpha [,eng]);  ideal I, poly f, number alpha, int eng
5654ASSUME:  Basering is D[s], I is the annihilator of f^s in D[s],
5655@* that is basering and I are the output of Sannfs-like procedure,
5656@* f is a polynomial in K[x] and alpha is a rational number.
5657RETURN:  int, 1 if -alpha is a root of the Bernstein-Sato polynomial of f
5658PURPOSE: check, whether alpha is a root of the global Bernstein-Sato polynomial of f
5659NOTE:  If eng <>0, @code{std} is used for Groebner basis computations,
5660@*       otherwise (and by default) @code{slimgb} is used.
5661DISPLAY: If printlevel=1, progress debug messages will be printed,
5662@*          if printlevel>=2, all the debug messages will be printed.
5663EXAMPLE: example checkRoot1; shows examples
5664"
5665{
5666  // to check: alpha is rational (has char 0 check inside)
5667  if (!isRational(a))
5668  {
5669    "ERROR: alpha must be a rational number!";
5670  }
5671  //  no qring
5672  if ( size(ideal(basering)) >0 )
5673  {
5674    "ERROR: no qring is allowed";
5675  }
5676  int eng = 0;
5677  if ( size(#)>0 )
5678  {
5679    if ( typeof(#[1]) == "int" )
5680    {
5681      eng = int(#[1]);
5682    }
5683  }
5684  int ppl = printlevel-voice+2;
5685  dbprint(ppl,"// -0-1- starting the procedure checkRoot1");
5686  def save = basering;
5687  int N = nvars(basering);
5688  int Nnew = N-1;
5689  int n = Nnew div 2;
5690  int i;
5691  string s;
5692  list RL = ringlist(basering);
5693  list L, Lord;
5694  list tmp;
5695  intvec iv;
5696  L[1] = RL[1];  // char
5697  L[4] = RL[4];  // char, minpoly
5698  // check whether basering is D[s]=K(_x,_Dx,s)
5699  list Name = RL[2];
5700//   for (i=1; i<=n; i++)
5701//   {
5702//     if ( bracket(var(i+n),var(i))!=1 )
5703//     {
5704//       ERROR("basering should be D[s]=K(_x,_Dx,s)");
5705//     }
5706//   }
5707  if ( Name[N]!="s" )
5708  {
5709    ERROR("the last variable of basering should be s");
5710  }
5711  // now, create the new vars
5712  list NName;
5713  for (i=1; i<=Nnew; i++)
5714  {
5715    NName[i] = Name[i];
5716  }
5717  L[2] = NName;
5718  kill Name,NName;
5719  // block ord (dp);
5720  tmp[1] = "dp"; // string
5721  s = "iv=";
5722  for (i=1; i<=Nnew; i++)
5723  {
5724    s = s+"1,";
5725  }
5726  s[size(s)]=";";
5727  execute(s);
5728  kill s;
5729  tmp[2]  = iv;
5730  Lord[1] = tmp;
5731  tmp[1]  = "C";
5732  iv      = 0;
5733  tmp[2]  = iv;
5734  Lord[2] = tmp;
5735  tmp     = 0;
5736  L[3]    = Lord;
5737  // we are done with the list
5738  def @R@ = ring(L);
5739  setring @R@;
5740  matrix @D[Nnew][Nnew];
5741  for (i=1; i<=n; i++)
5742  {
5743    @D[i,i+n]=1;
5744  }
5745  def @R = nc_algebra(1,@D);
5746  setring @R;
5747  kill @R@;
5748  dbprint(ppl,"// -1-1- the ring @R(_x,_Dx) is ready");
5749  dbprint(ppl-1, S);
5750  // create the ideal K = ann_D[s](f^s)_{s=-alpha} + < f >
5751  setring save;
5752  ideal K = subst(I,s,-a);
5753  dbprint(ppl,"// -1-2- the variable s has been substituted by "+string(-a));
5754  dbprint(ppl-1, K);
5755  K = NF(K,std(F));
5756  // make leadcoeffs positive
5757  for (i=1; i<=ncols(K); i++)
5758  {
5759    if ( leadcoef(K[i])<0 )
5760    {
5761      K[i] = -K[i];
5762    }
5763  }
5764  K = K,F;
5765  // ------------ the ideal K is ready ------------
5766  setring @R;
5767  ideal K = imap(save,K);
5768  dbprint(ppl,"// -1-3- starting the computation of a Groebner basis of K in @R");
5769  dbprint(ppl-1, K);
5770  ideal G = engine(K,eng);
5771  dbprint(ppl,"// -1-4- the Groebner basis has been computed");
5772  dbprint(ppl-1, G);
5773  return(G[1]!=1);
5774}
5775example
5776{
5777  "EXAMPLE:"; echo = 2;
5778  ring r = 0,(x,y),Dp;
5779  poly F = x^4+y^5+x*y^4;
5780  printlevel = 0;
5781  def A = Sannfs(F);
5782  setring A;
5783  poly F = imap(r,F);
5784  checkRoot1(LD,F,31/20);   // -31/20 is not a root of bs
5785  checkRoot1(LD,F,11/20);   // -11/20 is a root of bs
5786}
5787
5788proc checkRoot2 (ideal I, poly F, number a, list #)
5789"USAGE:  checkRoot2(I,f,a [,eng]);  I an ideal, f a poly, alpha a number, eng an optional int
5790ASSUME:  I is the annihilator of f^s in D[s], basering is D[s],
5791@* that is basering and I are the output os Sannfs-like procedure,
5792@* f is a polynomial in K[_x] and alpha is a rational number.
5793RETURN:  int, the multiplicity of -alpha as a root of the BS polynomial of f.
5794PURPOSE: check whether a rational number alpha is a root of the global Bernstein-
5795@* Sato polynomial of f and compute its multiplicity from the known Ann F^s in D[s]
5796NOTE:   If -alpha is not a root, the output is 0.
5797@*       If eng <>0, @code{std} is used for Groebner basis computations,
5798@*       otherwise (and by default) @code{slimgb} is used.
5799DISPLAY: If printlevel=1, progress debug messages will be printed,
5800@*          if printlevel>=2, all the debug messages will be printed.
5801EXAMPLE: example checkRoot2; shows examples
5802"
5803{
5804
5805
5806  // to check: alpha is rational (has char 0 check inside)
5807  if (!isRational(a))
5808  {
5809    "ERROR: alpha must be a rational number!";
5810  }
5811  //  no qring
5812  if ( size(ideal(basering)) >0 )
5813  {
5814    "ERROR: no qring is allowed";
5815  }
5816
5817  int eng = 0;
5818  if ( size(#)>0 )
5819  {
5820    if ( typeof(#[1]) == "int" )
5821    {
5822      eng = int(#[1]);
5823    }
5824  }
5825  int ppl = printlevel-voice+2;
5826  dbprint(ppl,"// -0-1- starting the procedure checkRoot2");
5827  def save = basering;
5828  int N = nvars(basering);
5829  int n = (N-1) div 2;
5830  int i;
5831  string s;
5832  list RL = ringlist(basering);
5833  list L, Lord;
5834  list tmp;
5835  intvec iv;
5836  L[1] = RL[1];  // char
5837  L[4] = RL[4];  // char, minpoly
5838  // check whether basering is D[s]=K(_x,_Dx,s)
5839  list Name = RL[2];
5840  for (i=1; i<=n; i++)
5841  {
5842    if ( bracket(var(i+n),var(i))!=1 )
5843    {
5844      ERROR("basering should be D[s]=K(_x,_Dx,s)");
5845    }
5846  }
5847  if ( Name[N]!="s" )
5848  {
5849    ERROR("the last variable of basering should be s");
5850  }
5851  // now, create the new vars
5852  L[2] = Name;
5853  kill Name;
5854  // block ord (dp);
5855  tmp[1] = "dp"; // string
5856  s = "iv=";
5857  for (i=1; i<=N; i++)
5858  {
5859    s = s+"1,";
5860  }
5861  s[size(s)]=";";
5862  execute(s);
5863  kill s;
5864  tmp[2]  = iv;
5865  Lord[1] = tmp;
5866  tmp[1]  = "C";
5867  iv      = 0;
5868  tmp[2]  = iv;
5869  Lord[2] = tmp;
5870  tmp     = 0;
5871  L[3]    = Lord;
5872  // we are done with the list
5873  def @R@ = ring(L);
5874  setring @R@;
5875  matrix @D[N][N];
5876  for (i=1; i<=n; i++)
5877  {
5878    @D[i,i+n]=1;
5879  }
5880  def @R = nc_algebra(1,@D);
5881  setring @R;
5882  kill @R@;
5883  dbprint(ppl,"// -1-1- the ring @R(_x,_Dx,s) is ready");
5884  dbprint(ppl-1, @R);
5885  // now, continue with the algorithm
5886  ideal I = imap(save,I);
5887  poly F = imap(save,F);
5888  number a = imap(save,a);
5889  ideal II = NF(I,std(F));
5890  // make leadcoeffs positive
5891  for (i=1; i<=ncols(II); i++)
5892  {
5893    if ( leadcoef(II[i])<0 )
5894    {
5895      II[i] = -II[i];
5896    }
5897  }
5898  ideal J,G;
5899  int m;  // the output (multiplicity)
5900  dbprint(ppl,"// -2- starting the bucle");
5901  for (i=0; i<=n; i++)  // the multiplicity has to be <= n
5902  {
5903    // create the ideal Ji = ann_D[s](f^s) + < f, (s+alpha)^{i+1} >
5904    // (s+alpha)^i in Ji <==> -alpha is a root with multiplicity >= i
5905    J = II,F,(s+a)^(i+1);
5906    // ------------ the ideal Ji is ready -----------
5907    dbprint(ppl,"// -2-"+string(i+1)+"-1- starting the computation of a Groebner basis of J"+string(i)+" in @R");
5908    dbprint(ppl-1, J);
5909    G = engine(J,eng);
5910    dbprint(ppl,"// -2-"+string(i+1)+"-2- the Groebner basis has been computed");
5911    dbprint(ppl-1, G);
5912    if ( NF((s+a)^i,G)==0 )
5913    {
5914      dbprint(ppl,"// -2-"+string(i+1)+"-3- the number "+string(-a)+" has not multiplicity "+string(i+1));
5915      m = i;
5916      break;
5917    }
5918    dbprint(ppl,"// -2-"+string(i+1)+"-3- the number "+string(-a)+" has multiplicity at least "+string(i+1));
5919  }
5920  dbprint(ppl,"// -3- the bucle has finished");
5921  return(m);
5922}
5923example
5924{
5925  "EXAMPLE:"; echo = 2;
5926  ring r = 0,(x,y,z),Dp;
5927  poly F = x*y*z;
5928  printlevel = 0;
5929  def A = Sannfs(F);
5930  setring A;
5931  poly F = imap(r,F);
5932  checkRoot2(LD,F,1);    // -1 is a root of bs with multiplicity 3
5933  checkRoot2(LD,F,1/3);  // -1/3 is not a root
5934}
5935
5936proc checkFactor(ideal I, poly F, poly q, list #)
5937"USAGE:  checkFactor(I,f,qs [,eng]);  I an ideal, f a poly, qs a poly, eng an optional int
5938ASSUME:  checkFactor is called from the basering, created by Sannfs-like proc,
5939@* that is, from the Weyl algebra in x1,..,xN,d1,..,dN tensored with K[s].
5940@* The ideal I is the annihilator of f^s in D[s], that is the ideal, computed
5941@* by Sannfs-like procedure (usually called LD there).
5942@* Moreover, f is a polynomial in K[x1,..,xN] and qs is a polynomial in K[s].
5943RETURN:  int, 1 if qs is a factor of the global Bernstein polynomial of f and 0 otherwise
5944PURPOSE: check whether a univariate polynomial qs is a factor of the
5945@*  Bernstein-Sato polynomial of f without explicit knowledge of the latter.
5946NOTE:    If eng <>0, @code{std} is used for Groebner basis computations,
5947@*       otherwise (and by default) @code{slimgb} is used.
5948DISPLAY: If printlevel=1, progress debug messages will be printed,
5949@*          if printlevel>=2, all the debug messages will be printed.
5950EXAMPLE: example checkFactor; shows examples
5951"
5952{
5953
5954  // ASSUME too complicated, cannot check it.
5955
5956  int eng = 0;
5957  if ( size(#)>0 )
5958  {
5959    if ( typeof(#[1]) == "int" )
5960    {
5961      eng = int(#[1]);
5962    }
5963  }
5964  int ppl = printlevel-voice+2;
5965  def @R2 = basering;
5966  int N = nvars(@R2);
5967  int i;
5968  // we're in D_n[s], where the elim ord for s is set
5969  dbprint(ppl,"// -0-1- starting the procedure checkFactor");
5970  dbprint(ppl,"// -1-1- the ring @R2(_x,_Dx,s) is ready");
5971  dbprint(ppl-1, @R2);
5972  // create the ideal J = ann_D[s](f^s) + < f,q >
5973  ideal J = NF(I,std(F));
5974  // make leadcoeffs positive
5975  for (i=1; i<=ncols(J); i++)
5976  {
5977    if ( leadcoef(J[i])<0 )
5978    {
5979      J[i] = -J[i];
5980    }
5981  }
5982  J = J,F,q;
5983  // ------------ the ideal J is ready -----------
5984  dbprint(ppl,"// -1-2- starting the elimination of _x,_Dx in @R2");
5985  dbprint(ppl-1, J);
5986  ideal G = engine(J,eng);
5987  ideal K = nselect(G,1..N-1);
5988  kill J,G;
5989  dbprint(ppl,"// -1-3- _x,_Dx are eliminated");
5990  dbprint(ppl-1, K);
5991  //q is a factor of bs if and only if K = < q >
5992  //K = normalize(K);
5993  //q = normalize(q);
5994  //return( (K[1]==q) );
5995  return( NF(K[1],std(q))==0 );
5996}
5997example
5998{
5999  "EXAMPLE:"; echo = 2;
6000  ring r = 0,(x,y),Dp;
6001  poly F = x^4+y^5+x*y^4;
6002  printlevel = 0;
6003  def A = Sannfs(F);
6004  setring A;
6005  poly F = imap(r,F);
6006  checkFactor(LD,F,20*s+31);     // -31/20 is not a root of bs
6007  checkFactor(LD,F,20*s+11);     // -11/20 is a root of bs
6008  checkFactor(LD,F,(20*s+11)^2); // the multiplicity of -11/20 is 1
6009}
6010
6011proc varNum(string s)
6012"USAGE:  varNum(s);  string s
6013RETURN:  int
6014PURPOSE: returns the number of the variable with the name s
6015@*  among the variables of basering or 0 if there is no such variable
6016EXAMPLE: example varNum; shows examples
6017"
6018{
6019  int i;
6020  for (i=1; i<= nvars(basering); i++)
6021  {
6022    if ( string(var(i)) == s )
6023    {
6024      return(i);
6025    }
6026  }
6027  return(0);
6028}
6029example
6030{
6031  "EXAMPLE:"; echo = 2;
6032  ring X = 0,(x,y1,t,z(0),z,tTa),dp;
6033  varNum("z");
6034  varNum("t");
6035  varNum("xyz");
6036}
6037
6038static proc indAR(list L, int n)
6039"USAGE:  indAR(L,n);  list L, int n
6040RETURN:  list
6041PURPOSE: computes arrangement inductively, using L and
6042@* var(n) as the next variable
6043ASSUME: L has a structure of an arrangement
6044EXAMPLE: example indAR; shows examples
6045"
6046{
6047  if ( (n<2) || (n>nvars(basering)) )
6048  {
6049    ERROR("incorrect n");
6050  }
6051  int sl = size(L);
6052  list K;
6053  ideal tmp;
6054  poly @t = L[sl][1] + var(n); //1 elt
6055  K[sl+1] = ideal(@t);
6056  tmp = L[1]+var(n);
6057  K[1] = tmp; tmp = 0;
6058  int i,j,sI;
6059  ideal I;
6060  for(i=sl; i>=2; i--)
6061  {
6062    I = L[i-1]; sI = size(I);
6063    for(j=1; j<=sI; j++)
6064    {
6065      I[j] = I[j] + var(n);
6066    }
6067    tmp  = L[i],I;
6068    K[i] = tmp;
6069    I = 0; tmp = 0;
6070  }
6071  kill I; kill tmp;
6072  return(K);
6073}
6074example
6075{
6076  "EXAMPLE:"; echo = 2;
6077  ring r = 0,(x,y,z,t,v),dp;
6078  list L;
6079  L[1] = ideal(x);
6080  list K = indAR(L,2);
6081  K;
6082  list M = indAR(K,3);
6083  M;
6084  M = indAR(M,4);
6085  M;
6086}
6087
6088proc isRational(number n)
6089"USAGE:  isRational(n); n number
6090RETURN:  int
6091PURPOSE: determine whether n is a rational number,
6092@* that is it does not contain parameters.
6093ASSUME: ground field is of characteristic 0
6094EXAMPLE: example indAR; shows examples
6095"
6096{
6097  if (char(basering) != 0)
6098  {
6099    ERROR("The ground field must be of characteristic 0!");
6100  }
6101  number dn = denominator(n);
6102  number nn = numerator(n);
6103  return( ((int(dn)==dn) && (int(nn)==nn)) );
6104}
6105example
6106{
6107  "EXAMPLE:"; echo = 2;
6108  ring r = (0,a),(x,y),dp;
6109  number n1 = 11/73;
6110  isRational(n1);
6111  number n2 = (11*a+3)/72;
6112  isRational(n2);
6113}
6114
6115proc bernsteinLift(ideal I, poly F, list #)
6116"USAGE:  bernsteinLift(I, F [,eng]);  I an ideal, F a poly, eng an optional int
6117RETURN:  list
6118PURPOSE: compute the (multiple of) Bernstein-Sato polynomial with lift-like method,
6119@* based on the output of Sannfs-like procedure
6120NOTE:  the output list contains the roots with multiplicities of the candidate
6121@* for being Bernstein-Sato polynomial of f.
6122@*  If eng <>0, @code{std} is used for Groebner basis computations,
6123@*  otherwise and by default @code{slimgb} is used.
6124@*  If printlevel=1, progress debug messages will be printed,
6125@*  if printlevel>=2, all the debug messages will be printed.
6126EXAMPLE: example bernsteinLift; shows examples
6127"
6128{
6129  // assume: s is the last variable! check in the code
6130  int eng = 0;
6131  if ( size(#)>0 )
6132  {
6133    if ( typeof(#[1]) == "int" )
6134    {
6135      eng = int(#[1]);
6136    }
6137  }
6138  def @R2 = basering;
6139  int Nnew = nvars(@R2);
6140  int N = Nnew div 2;
6141  int ppl = printlevel-voice+2;
6142  // we're in D_n[s], where the elim ord for s is set
6143  // create D_n(s)
6144  // create the ordinary Weyl algebra and put the result into it,
6145  // keep: N, i,j,s, tmp, RL
6146  Nnew = Nnew - 1; // former 2*N;
6147  list L = 0;
6148  list Lord, tmp;
6149  intvec iv; int i;
6150  list RL = ringlist(basering);
6151  // if we work over alg. extension => problem!
6152  if (size(RL[1]) > 1)
6153  {
6154    ERROR("cannot work over algebraic field extension");
6155  }
6156  tmp[1] = RL[1]; // char
6157  tmp[2] = list("s");
6158  tmp[3] = list(list("lp",int(1)));
6159  tmp[4] = ideal(0);
6160  L[1] = tmp; // field
6161  tmp = 0;
6162  L[4] = RL[4];  // factor ideal
6163
6164  // check whether vars have admissible names -> done earlier
6165  // list Name = RL[2]M
6166  // DName is defined earlier
6167  list NName; // = RL[2]; // skip the last var 's'
6168  for (i=1; i<=Nnew; i++)
6169  {
6170    NName[i] =  RL[2][i];
6171  }
6172  L[2] = NName;
6173  // (c, ) ordering:
6174  tmp[1]  = "c";
6175  iv = 0;
6176  tmp[2]  = iv;
6177  Lord[1] = tmp;
6178  tmp=0;
6179  // dp ordering;
6180  string s = "iv=";
6181  for (i=1; i<=Nnew; i++)
6182  {
6183    s = s+"1,";
6184  }
6185  s[size(s)] = ";";
6186  execute(s);
6187  tmp     = 0;
6188  tmp[1]  = "dp";  // string
6189  tmp[2]  = iv;  // intvec
6190  Lord[2] = tmp;
6191  kill s;
6192  tmp     = 0;
6193  L[3]    = Lord;
6194  // we are done with the list
6195  // Add: Plural part
6196  def @R4@ = ring(L);
6197  setring @R4@;
6198  matrix @D[Nnew][Nnew];
6199  for (i=1; i<=N; i++)
6200  {
6201    @D[i,N+i]=1;
6202  }
6203  def @R4 = nc_algebra(1,@D);
6204  setring @R4;
6205  kill @R4@;
6206  dbprint(ppl,"// -3-1- the ring K(s)<x,dx> is ready");
6207  dbprint(ppl-1, @R4);
6208  // map things correctly, using names
6209  ideal J = imap(@R2, I), imap(@R2,F);
6210  module M;
6211  // make leadcoeffs positive
6212  for (i=1; i<= ncols(J); i++)
6213  {
6214    if (J[i]!=0)
6215    {
6216      M[i] = J[i]*gen(1) + gen(1+i);
6217    }
6218  }
6219  dbprint(ppl,"// -3-2- starting GB of the assoc. module M");
6220  M = engine(M,eng);
6221  dbprint(ppl,"// -3-3- finished GB of the assoc. module M");
6222  dbprint(ppl-1, M);
6223  // now look for (1) entry with 1st comp nonzero
6224  // determine whether there are several 1st comps nonzero
6225  module M2;
6226  for (i=1; i<= ncols(M); i++)
6227  {
6228    if (M[1,i]!=0)
6229    {
6230      M2 = M2, M[i];
6231    }
6232  }
6233  M2 = simplify(M2,2); // skip 0s
6234  if (ncols(M2) > 1)
6235  {
6236    dbprint(ppl,"// -*- more than 1 element with nonzero leading component");
6237    option(redSB);    option(redTail); // set them back?
6238    M2 = interred(M2);
6239    if (ncols(M2) > 1)
6240    {
6241      ERROR("more than one leading component after interred: assume violation!");
6242    }
6243    if (leadexp(M2[1]) != 0)
6244    {
6245      ERROR("nonconstant entry after interred: assume violation!");
6246    }
6247  }
6248  // now there's only one el-t with leadcomp<>0
6249  vector V = M2[1];
6250  number bcand = leadcoef(V[1]); // 1st component
6251  V[1]=0;
6252  number ct = content(V); // content of the cofactors
6253  poly CF = ct*V[ncols(J)]; // polynomial in K[s]<x,dx>, cofactor to F
6254  dbprint(ppl,"// -3-4- the cofactor candidate found");
6255  dbprint(ppl-1,CF);
6256  dbprint(ppl,"// -3-5- the entry as it is");
6257  dbprint(ppl-1,bcand);
6258  bcand = bcand*ct; // a product of both
6259  dbprint(ppl,"// -3-6- the content of the rest vector");
6260  dbprint(ppl-1,ct);
6261  ring @R3 = 0,s,dp;
6262  dbprint(ppl,"// -4-1- the ring @R3 i.e. K[s] is ready");
6263  poly bcand = imap(@R4,bcand);
6264  dbprint(ppl,"// -4-2- factorization");
6265  list P = factorize(bcand);          //with constants and multiplicities
6266  ideal bs; intvec m;             //the Bernstein polynomial is monic, so we are not interested in constants
6267  for (i=2; i<= size(P[1]); i++)  //we delete P[1][1] and P[2][1]
6268  {
6269    bs[i-1] = P[1][i];
6270    m[i-1]  = P[2][i];
6271  }
6272  bs = normalize(bs); bs = -subst(bs,s,0); // to get roots only
6273  setring @R2; // the ring the story started with
6274  ideal bs = imap(@R3,bs); // intvec m is global
6275  intvec mm = m; m = 0;
6276  kill @R3; // kills m as well....
6277  list @L = list(bs, mm);
6278  // look for (2) return the GB of syzygies?
6279  return(@L);
6280}
6281example
6282{ "EXAMPLE:"; echo = 2;
6283  ring r = 0,(x,y,z),Dp;
6284  poly F = x^3+y^3+z^3;
6285  printlevel = 0;
6286  def A = Sannfs(F);   setring A;
6287  LD;
6288  poly F = imap(r,F);
6289  list L  = bernsteinLift(LD,F); L;
6290  poly bs = fl2poly(L,"s"); bs; // the candidate for Bernstein-Sato polynomial
6291}
6292
6293/// ****** EXAMPLES ************
6294
6295/*
6296
6297//static proc exCheckGenericity()
6298{
6299  LIB "control.lib";
6300  ring r = (0,a,b,c),x,dp;
6301  poly p = (x-a)*(x-b)*(x-c);
6302  def A = annfsBM(p);
6303  setring A;
6304  ideal J = slimgb(LD);
6305  matrix T = lift(LD,J);
6306  T = normalize(T);
6307  genericity(T);
6308  // 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)
6309  // genericity: g = a2-ab-ac+b2-bc+c2 =0
6310  // g = (a -(b+c)/2)^2 + (3/4)*(b-c)^2;
6311  // g ==0 <=> a=b=c
6312  // indeed, Ann = (x-a)^2*(x*Dx+3*t*Dt+(-a)*Dx+3)
6313  // --------------------------------------------
6314  // BUT a direct computation shows
6315  // when a=b=c,
6316  // Ann = x*Dx+3*t*Dt+(-a)*Dx+3
6317}
6318
6319//static proc exOT_17()
6320{
6321  // Oaku-Takayama, p.208
6322  ring R = 0,(x,y),dp;
6323  poly F = x^3-y^2; // x^2+x*y+y^2;
6324  option(prot);
6325  option(mem);
6326  //  option(redSB);
6327  def A = annfsOT(F,0);
6328  setring A;
6329  LD;
6330  gkdim(LD); // a holonomic check
6331  //  poly F = x^3-y^2; // = x^7 - y^5; // x^3-y^4; // x^5 - y^4;
6332}
6333
6334//static proc exOT_16()
6335{
6336  // Oaku-Takayama, p.208
6337  ring R = 0,(x),dp;
6338  poly F = x*(1-x);
6339  option(prot);
6340  option(mem);
6341  //  option(redSB);
6342  def A = annfsOT(F,0);
6343  setring A;
6344  LD;
6345  gkdim(LD); // a holonomic check
6346}
6347
6348//static proc ex_bcheck()
6349{
6350  ring R = 0,(x,y),dp;
6351  poly F = x*y*(x+y);
6352  option(prot);
6353  option(mem);
6354  int eng = 0;
6355  //  option(redSB);
6356  def A = annfsOT(F,eng);
6357  setring A;
6358  LD;
6359}
6360
6361//static proc ex_bcheck2()
6362{
6363  ring R = 0,(x,y),dp;
6364  poly F = x*y*(x+y);
6365  int eng = 0;
6366  def A = annfsBM(F,eng);
6367  setring A;
6368  LD;
6369}
6370
6371//static proc ex_BMI()
6372{
6373  // a hard example
6374  ring r = 0,(x,y),Dp;
6375  poly F1 = (x2-y3)*(x3-y2);
6376  poly F2 = (x2-y3)*(xy4+y5+x4);
6377  ideal F = F1,F2;
6378  def A = annfsBMI(F);
6379  setring A;
6380  LD;
6381  BS;
6382}
6383
6384//static proc ex2_BMI()
6385{
6386  // this example was believed to be intractable in 2005 by Gago-Vargas, Castro and Ucha
6387  ring r = 0,(x,y),Dp;
6388  option(prot);
6389  option(mem);
6390  ideal F = x2+y3,x3+y2;
6391  printlevel = 2;
6392  def A = annfsBMI(F);
6393  setring A;
6394  LD;
6395  BS;
6396}
6397
6398//static proc ex_operatorBM()
6399{
6400  ring r = 0,(x,y,z,w),Dp;
6401  poly F = x^3+y^3+z^2*w;
6402  printlevel = 0;
6403  def A = operatorBM(F);
6404  setring A;
6405  F; // the original polynomial itself
6406  LD; // generic annihilator
6407  LD0; // annihilator
6408  bs; // normalized Bernstein poly
6409  BS; // root and multiplicities of the Bernstein poly
6410  PS; // the operator, s.t. PS*F^{s+1} = bs*F^s mod LD
6411  reduce(PS*F-bs,LD); // check the property of PS
6412}
6413
6414*/
Note: See TracBrowser for help on using the repository browser.