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

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