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

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