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

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