source: git/Singular/LIB/dmod.lib @ 9e7006

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