source: git/Singular/LIB/dmod.lib @ 73c3c95

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