source: git/Singular/LIB/dmod.lib @ 0ab7da

spielwiese
Last change on this file since 0ab7da was 0ab7da, checked in by Viktor Levandovskyy <levandov@…>, 16 years ago
*levandov: annfs2 added, minor fixes git-svn-id: file:///usr/local/Singular/svn/trunk@10510 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100755
File size: 122.5 KB
Line 
1//////////////////////////////////////////////////////////////////////////////
2version="$Id: dmod.lib,v 1.24 2008-01-17 21:05: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 "nctools.lib";
78LIB "elim.lib";
79LIB "qhmoduli.lib"; // for Max
80LIB "gkdim.lib";
81LIB "gmssing.lib";
82LIB "control.lib";  // for genericity
83
84proc tstdmodlib()
85{
86  /* tests all procs for consistency */
87  /* adding the new proc, add it here */
88
89  "MAIN PROCEDURES:";
90  example annfs;
91  example annfs0;
92  example Sannfs;
93  example Sannfslog;
94  example bernsteinBM;
95  example operatorBM;
96  example annfspecial;
97  example annfsParamBM;
98  example annfsBMI;
99  example checkRoot;
100  "SECONDARY D-MOD PROCEDURES:";
101  example annfsBM;
102  example annfsLOT;
103  example annfsOT;
104  example SannfsBM;
105  example SannfsLOT;
106  example SannfsOT;
107  example annfs0;
108  example checkRoot1;
109  example checkRoot2;
110  example checkFactor;
111}
112
113static proc engine(ideal I, int i)
114{
115  /* std - slimgb mix */
116  ideal J;
117  if (i==0)
118  {
119    J = slimgb(I);
120  }
121  else
122  {
123    // without options -> strange! (ringlist?)
124    option(redSB);
125    option(redTail);
126    J = std(I);
127  }
128  return(J);
129}
130
131
132// new top-level procedures
133proc annfs(poly F, list #)
134"USAGE:  annfs(f [,S,eng]);  f a poly, S a string, eng an optional int
135RETURN:  ring
136PURPOSE: 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'
137NOTE:    activate the output ring with the @code{setring} command.
138@*       The value of a string S can be
139@*       'bm' (default) - for the algorithm of Briancon and Maisonobe,
140@*       'ot'  - for the algorithm of Oaku and Takayama,
141@*       'lot' - for the Levandovskyy's modification of the algorithm of Oaku and Takayama.
142@*       If eng <>0, @code{std} is used for Groebner basis computations,
143@*       otherwise and by default @code{slimgb} is used.
144@*       In the output ring:
145@*       - the ideal LD (which is a Groebner basis) is the needed D-module structure,
146@*       - the list  BS is the list of roots and multiplicities of a Bernstein polynomial of f.
147@*       If @code{printlevel}=1, progress debug messages will be printed,
148@*       if @code{printlevel}>=2, all the debug messages will be printed.
149EXAMPLE: example annfs; shows examples
150"
151{
152  int eng = 0;
153  int chs = 0; // choice
154  string algo = "bm";
155  string st;
156  if ( size(#)>0 )
157  {
158   if ( typeof(#[1]) == "string" )
159   {
160     st = string(#[1]);
161     if ( (st == "BM") || (st == "Bm") || (st == "bM") ||(st == "bm"))
162     {
163       algo = "bm";
164       chs  = 1;
165     }
166     if ( (st == "OT") || (st == "Ot") || (st == "oT") || (st == "ot"))
167     {
168       algo = "ot";
169       chs  = 1;
170     }
171     if ( (st == "LOT") || (st == "lOT") || (st == "Lot") || (st == "lot"))
172     {
173       algo = "lot";
174       chs  = 1;
175     }
176     if (chs != 1)
177     {
178       // incorrect value of S
179       print("Incorrect algorithm given, proceed with the default BM");
180       algo = "bm";
181     }
182     // second arg
183     if (size(#)>1)
184     {
185       // exists 2nd arg
186       if ( typeof(#[2]) == "int" )
187       {
188         // the case: given alg, given engine
189         eng = int(#[2]);
190       }
191       else
192       {
193         eng = 0;
194       }
195     }
196     else
197     {
198       // no second arg
199       eng = 0;
200     }
201   }
202   else
203   {
204     if ( typeof(#[1]) == "int" )
205     {
206     // the case: default alg, engine
207     eng = int(#[1]);
208     //      algo = "bm";  //is already set
209     }
210     else
211     {
212       // incorr. 1st arg
213       algo = "bm";
214     }
215   }
216  }
217
218   // size(#)=0, i.e. there is no algorithm and no engine given
219   //  eng = 0; algo = "bm";  //are already set
220   // int ppl = printlevel-voice+2;
221
222  int old_printlevel = printlevel;
223  printlevel=printlevel+1;
224  def save = basering;
225  if ( algo=="ot")
226  {
227    def @A = annfsOT(F,eng);
228  }
229  else
230  {
231    if ( algo=="lot")
232    {
233      def @A = annfsLOT(F,eng);
234    }
235    else
236    {
237      // bm = default
238      def @A = annfsBM(F,eng);
239    }
240  }
241  printlevel = old_printlevel;
242  return(@A);
243}
244example
245{
246  "EXAMPLE:"; echo = 2;
247  ring r = 0,(x,y,z),Dp;
248  poly F = z*x^2+y^3;
249  printlevel = 0;
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
1394proc operatorBM(poly F, list #)
1395"USAGE:  operatorBM(f [,eng]);  f a poly, eng an optional int
1396RETURN:  ring
1397PURPOSE: compute the B-operator and other relevant data for Ann F^s, according to the algorithm by Briancon and Maisonobe
1398NOTE:    activate this ring with the @code{setring} command. In this ring D[s]
1399@*       - the polynomial F is the same as the input,
1400@*       - the ideal LD is the annihilator of f^s in Dn[s],
1401@*       - the ideal LD0 is the needed D-mod structure, where LD0 = LD|s=s0,
1402@*       - the polynomial bs is the global Bernstein polynomial of f in the variable s,
1403@*       - the list BS contains all the roots with multiplicities of the global Bernstein polynomial of f,
1404@*       - the polynomial PS is an operator in Dn[s] such that PS*f^(s+1) = bs*f^s.
1405@*       If eng <>0, @code{std} is used for Groebner basis computations,
1406@*       otherwise and by default @code{slimgb} is used.
1407@*       If printlevel=1, progress debug messages will be printed,
1408@*       if printlevel>=2, all the debug messages will be printed.
1409EXAMPLE: example operatorBM; shows examples
1410"
1411{
1412  int eng = 0;
1413  if ( size(#)>0 )
1414  {
1415    if ( typeof(#[1]) == "int" )
1416    {
1417      eng = int(#[1]);
1418    }
1419  }
1420  // returns a list with a ring and an ideal LD in it
1421  int ppl = printlevel-voice+2;
1422  //  printf("plevel :%s, voice: %s",printlevel,voice);
1423  def save = basering;
1424  int N = nvars(basering);
1425  int Nnew = 2*N+2;
1426  int i,j;
1427  string s;
1428  list RL = ringlist(basering);
1429  list L, Lord;
1430  list tmp;
1431  intvec iv;
1432  L[1] = RL[1];  //char
1433  L[4] = RL[4];  //char, minpoly
1434  // check whether vars have admissible names
1435  list Name  = RL[2];
1436  list RName;
1437  RName[1] = "t";
1438  RName[2] = "s";
1439  for (i=1; i<=N; i++)
1440  {
1441    for(j=1; j<=size(RName); j++)
1442    {
1443      if (Name[i] == RName[j])
1444      {
1445        ERROR("Variable names should not include t,s");
1446      }
1447    }
1448  }
1449  // now, create the names for new vars
1450  list DName;
1451  for (i=1; i<=N; i++)
1452  {
1453    DName[i] = "D"+Name[i];  //concat
1454  }
1455  tmp[1] = "t";
1456  tmp[2] = "s";
1457  list NName = tmp + Name + DName;
1458  L[2]   = NName;
1459  // Name, Dname will be used further
1460  kill NName;
1461  // block ord (lp(2),dp);
1462  tmp[1]  = "lp"; // string
1463  iv      = 1,1;
1464  tmp[2]  = iv; //intvec
1465  Lord[1] = tmp;
1466  // continue with dp 1,1,1,1...
1467  tmp[1]  = "dp"; // string
1468  s       = "iv=";
1469  for (i=1; i<=Nnew; i++)
1470  {
1471    s = s+"1,";
1472  }
1473  s[size(s)]= ";";
1474  execute(s);
1475  kill s;
1476  tmp[2]    = iv;
1477  Lord[2]   = tmp;
1478  tmp[1]    = "C";
1479  iv        = 0;
1480  tmp[2]    = iv;
1481  Lord[3]   = tmp;
1482  tmp       = 0;
1483  L[3]      = Lord;
1484  // we are done with the list
1485  def @R@ = ring(L);
1486  setring @R@;
1487  matrix @D[Nnew][Nnew];
1488  @D[1,2]=t;
1489  for(i=1; i<=N; i++)
1490  {
1491    @D[2+i,N+2+i]=1;
1492  }
1493  // L[5] = matrix(UpOneMatrix(Nnew));
1494  // L[6] = @D;
1495  def @R = nc_algebra(1,@D);
1496  setring @R;
1497  kill @R@;
1498  dbprint(ppl,"// -1-1- the ring @R(t,s,_x,_Dx) is ready");
1499  dbprint(ppl-1, @R);
1500  // create the ideal I
1501  poly  F = imap(save,F);
1502  ideal I = t*F+s;
1503  poly p;
1504  for(i=1; i<=N; i++)
1505  {
1506    p = t;  //t
1507    p = diff(F,var(2+i))*p;
1508    I = I, var(N+2+i) + p;
1509  }
1510  // -------- the ideal I is ready ----------
1511  dbprint(ppl,"// -1-2- starting the elimination of t in @R");
1512  dbprint(ppl-1, I);
1513  ideal J = engine(I,eng);
1514  ideal K = nselect(J,1);
1515  kill I,J;
1516  dbprint(ppl,"// -1-3- t is eliminated");
1517  dbprint(ppl-1, K);  //K is without t
1518  setring save;
1519  // ----------- the ring @R2 ------------
1520  // _x, _Dx,s;  elim.ord for _x,_Dx.
1521  // keep: N, i,j,s, tmp, RL
1522  Nnew = 2*N+1;
1523  kill Lord, tmp, iv, RName;
1524  list Lord, tmp;
1525  intvec iv;
1526  L[1] = RL[1];
1527  L[4] = RL[4];  //char, minpoly
1528  // check whether vars hava admissible names -> done earlier
1529  // now, create the names for new var
1530  tmp[1] = "s";
1531  // DName is defined earlier
1532  list NName = Name + DName + tmp;
1533  L[2] = NName;
1534  tmp = 0;
1535  // block ord (dp(N),dp);
1536  string s = "iv=";
1537  for (i=1; i<=Nnew-1; i++)
1538  {
1539    s = s+"1,";
1540  }
1541  s[size(s)]=";";
1542  execute(s);
1543  tmp[1] = "dp";  //string
1544  tmp[2] = iv;    //intvec
1545  Lord[1] = tmp;
1546  // continue with dp 1,1,1,1...
1547  tmp[1] = "dp";  //string
1548  s[size(s)] = ",";
1549  s = s+"1;";
1550  execute(s);
1551  kill s;
1552  kill NName;
1553  tmp[2]  = iv;
1554  Lord[2] = tmp;
1555  tmp[1]  = "C";
1556  iv      = 0;
1557  tmp[2]  = iv;
1558  Lord[3] = tmp;
1559  tmp     = 0;
1560  L[3]    = Lord;
1561  // we are done with the list. Now add a Plural part
1562  def @R2@ = ring(L);
1563  setring @R2@;
1564  matrix @D[Nnew][Nnew];
1565  for (i=1; i<=N; i++)
1566  {
1567    @D[i,N+i]=1;
1568  }
1569  def @R2 = nc_algebra(1,@D);
1570  setring @R2;
1571  kill @R2@;
1572  dbprint(ppl,"// -2-1- the ring @R2(_x,_Dx,s) is ready");
1573  dbprint(ppl-1, @R2);
1574  ideal MM = maxideal(1);
1575  MM = 0,s,MM;
1576  map R01 = @R, MM;
1577  ideal K = R01(K);
1578  poly F = imap(save,F);
1579  K = K,F;
1580  dbprint(ppl,"// -2-2- starting the elimination of _x,_Dx in @R2");
1581  dbprint(ppl-1, K);
1582  ideal M = engine(K,eng);
1583  ideal K2 = nselect(M,1,Nnew-1);
1584  kill K,M;
1585  dbprint(ppl,"// -2-3- _x,_Dx are eliminated in @R2");
1586  dbprint(ppl-1, K2);
1587  // the ring @R3 and the search for minimal negative int s
1588  ring @R3 = 0,s,dp;
1589  dbprint(ppl,"// -3-1- the ring @R3(s) is ready");
1590  ideal K3 = imap(@R2,K2);
1591  kill @R2;
1592  poly p = K3[1];
1593  dbprint(ppl,"// -3-2- factorization");
1594  list P = factorize(p);          //with constants and multiplicities
1595  ideal bs; intvec m;             //the Bernstein polynomial is monic, so we are not interested in constants
1596  for (i=2; i<= size(P[1]); i++)  //we delete P[1][1] and P[2][1]
1597  {
1598    bs[i-1] = P[1][i];
1599    m[i-1]  = P[2][i];
1600  }
1601  // "--------- b-function factorizes into ---------";  P;
1602  int sP = minIntRoot(bs,1);
1603  dbprint(ppl,"// -3-3- minimal integer root found");
1604  dbprint(ppl-1, sP);
1605  // convert factors to a list of their roots with multiplicities
1606  bs = normalize(bs);
1607  bs = -subst(bs,s,0);
1608  list BS = bs,m;
1609  //TODO: sort BS!
1610  // --------- substitute s found in the ideal ---------
1611  // --------- going back to @R and substitute ---------
1612  setring @R;
1613  ideal K2 = subst(K,s,sP);
1614  // create Dn[s], where Dn is the ordinary Weyl algebra, and put the result into it,
1615  // thus creating the ring @R4
1616  // keep: N, i,j,s, tmp, RL
1617  setring save;
1618  Nnew = 2*N+1;
1619  // list RL = ringlist(save);  //is defined earlier
1620  kill Lord, tmp, iv;
1621  L = 0;
1622  list Lord, tmp;
1623  intvec iv;
1624  L[1] = RL[1];
1625  L[4] = RL[4];  //char, minpoly
1626  // check whether vars have admissible names -> done earlier
1627  // list Name = RL[2]
1628  // DName is defined earlier
1629  tmp[1] = "s";
1630  list NName = Name + DName + tmp;
1631  L[2] = NName;
1632  // dp ordering;
1633  string s = "iv=";
1634  for (i=1; i<=Nnew; i++)
1635  {
1636    s = s+"1,";
1637  }
1638  s[size(s)] = ";";
1639  execute(s);
1640  kill s;
1641  tmp     = 0;
1642  tmp[1]  = "dp";  //string
1643  tmp[2]  = iv;    //intvec
1644  Lord[1] = tmp;
1645  tmp[1]  = "C";
1646  iv      = 0;
1647  tmp[2]  = iv;
1648  Lord[2] = tmp;
1649  tmp     = 0;
1650  L[3]    = Lord;
1651  // we are done with the list
1652  // Add: Plural part
1653  def @R4@ = ring(L);
1654  setring @R4@;
1655  matrix @D[Nnew][Nnew];
1656  for (i=1; i<=N; i++)
1657  {
1658    @D[i,N+i]=1;
1659  }
1660  def @R4 = nc_algebra(1,@D);
1661  setring @R4;
1662  kill @R4@;
1663  dbprint(ppl,"// -4-1- the ring @R4(_x,_Dx,s) is ready");
1664  dbprint(ppl-1, @R4);
1665  ideal LD0 = imap(@R,K2);
1666  ideal LD  = imap(@R,K);
1667  kill @R;
1668  poly bs = imap(@R3,p);
1669  list BS = imap(@R3,BS);
1670  kill @R3;
1671  bs = normalize(bs);
1672  poly F = imap(save,F);
1673  dbprint(ppl,"// -4-2- starting the computation of PS via lift");
1674//better liftstd, I didn't knot it works also for Plural, liftslimgb?
1675// liftstd may give extra coeffs in the resulting ideal
1676  matrix T = lift(F+LD,bs);
1677  poly PS = T[1,1];
1678  dbprint(ppl,"// -4-3- an operator PS found, PS*f^(s+1) = b(s)*f^s");
1679  dbprint(ppl-1,PS);
1680  option(redSB);
1681  dbprint(ppl,"// -4-4- the final cosmetic std");
1682  LD0 = engine(LD0,eng);  //std does the job too
1683  LD  = engine(LD,eng);
1684  export F,LD,LD0,bs,BS,PS;
1685  return(@R4);
1686}
1687example
1688{
1689  "EXAMPLE:"; echo = 2;
1690  //  ring r = 0,(x,y,z,w),Dp;
1691  //  poly F = x^3+y^3+z^2*w;
1692  ring r = 0,(x,y,z),Dp;
1693  poly F = x^3+y^3+z^3;
1694  printlevel = 0;
1695  def A = operatorBM(F);
1696  setring A;
1697  F; // the original polynomial itself
1698  LD; // generic annihilator
1699  LD0; // annihilator
1700  bs; // normalized Bernstein poly
1701  BS; // root and multiplicities of the Bernstein poly
1702  PS; // the operator, s.t. PS*F^{s+1} = bs*F^s mod LD
1703  reduce(PS*F-bs,LD); // check the property of PS
1704}
1705
1706proc annfsParamBM (poly F, list #)
1707"USAGE:  annfsParamBM(f [,eng]);  f a poly, eng an optional int
1708RETURN:  ring
1709PURPOSE: compute the generic Ann F^s and exceptional parametric constellations of a polynomial with parametric coefficients, according to the algorithm by Briancon and Maisonobe
1710NOTE:    activate this ring with the @code{setring} command. In this ring,
1711@*       - the ideal LD is the D-module structure oa Ann F^s
1712@*       - the ideal Param contains the list of the special parameters.
1713@*       If eng <>0, @code{std} is used for Groebner basis computations,
1714@*       otherwise, and by default @code{slimgb} is used.
1715@*       If printlevel=1, progress debug messages will be printed,
1716@*       if printlevel>=2, all the debug messages will be printed.
1717EXAMPLE: example annfsParamBM; shows examples
1718"
1719{
1720  //PURPOSE: compute the list of all possible Bernstein-Sato polynomials for a polynomial with parametric coefficients, according to the algorithm by Briancon and Maisonobe
1721  // @*       - the list BS is the list of roots and multiplicities of a Bernstein polynomial of f.
1722  // ***** not implented yet ****
1723  int eng = 0;
1724  if ( size(#)>0 )
1725  {
1726    if ( typeof(#[1]) == "int" )
1727    {
1728      eng = int(#[1]);
1729    }
1730  }
1731  // returns a list with a ring and an ideal LD in it
1732  int ppl = printlevel-voice+2;
1733  //  printf("plevel :%s, voice: %s",printlevel,voice);
1734  def save = basering;
1735  int N = nvars(basering);
1736  int Nnew = 2*N+2;
1737  int i,j;
1738  string s;
1739  list RL = ringlist(basering);
1740  list L, Lord;
1741  list tmp;
1742  intvec iv;
1743  L[1] = RL[1];  //char
1744  L[4] = RL[4];  //char, minpoly
1745  // check whether vars have admissible names
1746  list Name  = RL[2];
1747  list RName;
1748  RName[1] = "t";
1749  RName[2] = "s";
1750  for (i=1; i<=N; i++)
1751  {
1752    for(j=1; j<=size(RName); j++)
1753    {
1754      if (Name[i] == RName[j])
1755      {
1756        ERROR("Variable names should not include t,s");
1757      }
1758    }
1759  }
1760  // now, create the names for new vars
1761  list DName;
1762  for (i=1; i<=N; i++)
1763  {
1764    DName[i] = "D"+Name[i];  //concat
1765  }
1766  tmp[1] = "t";
1767  tmp[2] = "s";
1768  list NName = tmp + Name + DName;
1769  L[2]   = NName;
1770  // Name, Dname will be used further
1771  kill NName;
1772  // block ord (lp(2),dp);
1773  tmp[1]  = "lp"; // string
1774  iv      = 1,1;
1775  tmp[2]  = iv; //intvec
1776  Lord[1] = tmp;
1777  // continue with dp 1,1,1,1...
1778  tmp[1]  = "dp"; // string
1779  s       = "iv=";
1780  for (i=1; i<=Nnew; i++)
1781  {
1782    s = s+"1,";
1783  }
1784  s[size(s)]= ";";
1785  execute(s);
1786  kill s;
1787  tmp[2]    = iv;
1788  Lord[2]   = tmp;
1789  tmp[1]    = "C";
1790  iv        = 0;
1791  tmp[2]    = iv;
1792  Lord[3]   = tmp;
1793  tmp       = 0;
1794  L[3]      = Lord;
1795  // we are done with the list
1796  def @R@ = ring(L);
1797  setring @R@;
1798  matrix @D[Nnew][Nnew];
1799  @D[1,2]=t;
1800  for(i=1; i<=N; i++)
1801  {
1802    @D[2+i,N+2+i]=1;
1803  }
1804  // L[5] = matrix(UpOneMatrix(Nnew));
1805  // L[6] = @D;
1806  def @R = nc_algebra(1,@D);
1807  setring @R;
1808  kill @R@;
1809  dbprint(ppl,"// -1-1- the ring @R(t,s,_x,_Dx) is ready");
1810  dbprint(ppl-1, @R);
1811  // create the ideal I
1812  poly  F = imap(save,F);
1813  ideal I = t*F+s;
1814  poly p;
1815  for(i=1; i<=N; i++)
1816  {
1817    p = t;  //t
1818    p = diff(F,var(2+i))*p;
1819    I = I, var(N+2+i) + p;
1820  }
1821  // -------- the ideal I is ready ----------
1822  dbprint(ppl,"// -1-2- starting the elimination of t in @R");
1823  dbprint(ppl-1, I);
1824  ideal J = engine(I,eng);
1825  ideal K = nselect(J,1);
1826  dbprint(ppl,"// -1-3- t is eliminated");
1827  dbprint(ppl-1, K);  //K is without t
1828  // ----- looking for special parameters -----
1829  dbprint(ppl,"// -2-1- starting the computation of the transformation matrix (via lift)");
1830  J = normalize(J);
1831  matrix T = lift(I,J);  //try also with liftstd
1832  kill I,J;
1833  dbprint(ppl,"// -2-2- the transformation matrix has been computed");
1834  dbprint(ppl-1, T);  //T is the transformation matrix
1835  dbprint(ppl,"// -2-3- genericity does the job");
1836  list lParam = genericity(T);
1837  int ip = size(lParam);
1838  int cip;
1839  string sParam;
1840  if (sParam[1]=="-") { sParam=""; } //genericity returns "-"
1841  // if no parameters exist in a basering
1842  for (cip=1; cip <= ip; cip++)
1843  {
1844    sParam = sParam + "," +lParam[cip];
1845  }
1846  if (size(sParam) >=2)
1847  {
1848    sParam = sParam[2..size(sParam)]; // removes the 1st colon
1849  }
1850  export sParam;
1851  kill T;
1852  dbprint(ppl,"// -2-4- the special parameters has been computed");
1853  dbprint(ppl, sParam);
1854  // create Dn[s], where Dn is the ordinary Weyl Algebra, and put the result into it,
1855  // thus creating the ring @R2
1856  // keep: N, i,j,s, tmp, RL
1857  setring save;
1858  Nnew = 2*N+1;
1859  // list RL = ringlist(save);  //is defined earlier
1860  kill Lord, tmp, iv;
1861  L = 0;
1862  list Lord, tmp;
1863  intvec iv;
1864  L[1] = RL[1];
1865  L[4] = RL[4];  //char, minpoly
1866  // check whether vars have admissible names -> done earlier
1867  // list Name = RL[2]M
1868  // DName is defined earlier
1869  tmp[1] = "s";
1870  list NName = Name + DName + tmp;
1871  L[2] = NName;
1872  // dp ordering;
1873  string s = "iv=";
1874  for (i=1; i<=Nnew; i++)
1875  {
1876    s = s+"1,";
1877  }
1878  s[size(s)] = ";";
1879  execute(s);
1880  kill s;
1881  tmp     = 0;
1882  tmp[1]  = "dp";  //string
1883  tmp[2]  = iv;    //intvec
1884  Lord[1] = tmp;
1885  tmp[1]  = "C";
1886  iv      = 0;
1887  tmp[2]  = iv;
1888  Lord[2] = tmp;
1889  tmp     = 0;
1890  L[3]    = Lord;
1891  // we are done with the list
1892  // Add: Plural part
1893  def @R2@ = ring(L);
1894  setring @R2@;
1895  matrix @D[Nnew][Nnew];
1896  for (i=1; i<=N; i++)
1897  {
1898    @D[i,N+i]=1;
1899  }
1900  def @R2 = nc_algebra(1,@D);
1901  setring @R2;
1902  kill @R2@;
1903  dbprint(ppl,"// -3-1- the ring @R2(_x,_Dx,s) is ready");
1904  dbprint(ppl-1, @R2);
1905  ideal K = imap(@R,K);
1906  kill @R;
1907  option(redSB);
1908  dbprint(ppl,"// -3-2- the final cosmetic std");
1909  K = engine(K,eng);  //std does the job too
1910  ideal LD = K;
1911  export LD;
1912  if (sParam[1] == ",")
1913  {
1914    sParam = sParam[2..size(sParam)];
1915  }
1916  //  || ((sParam[1] == " ") && (sParam[2] == ",")))
1917  execute("ideal Param ="+sParam+";");
1918  export Param;
1919  kill sParam;
1920  return(@R2);
1921}
1922example
1923{
1924  "EXAMPLE:"; echo = 2;
1925  ring r = (0,a,b),(x,y),Dp;
1926  poly F = x^2 - (y-a)*(y-b);
1927  printlevel = 0;
1928  def A = annfsParamBM(F);  setring A;
1929  LD;
1930  Param;
1931  setring r;
1932  poly G = x2-(y-a)^2; // try the exceptional value b=a of parameters
1933  def B = annfsParamBM(G); setring B;
1934  LD;
1935  Param;
1936}
1937
1938// *** the following example is nice, but too complicated for the documentation ***
1939//   ring r = (0,a),(x,y,z),Dp;
1940//   poly F = x^4+y^4+z^2+a*x*y*z;
1941//   printlevel = 2; //0
1942//   def A = annfsParamBM(F);
1943//   setring A;
1944//   LD;
1945//   Param;
1946
1947
1948proc annfsBMI(ideal F, list #)
1949"USAGE:  annfsBMI(F [,eng]);  F an ideal, eng an optional int
1950RETURN:  ring
1951PURPOSE: compute the D-module structure of basering[1/f]*f^s where f = F[1]*..*F[P],
1952according to the algorithm by Briancon and Maisonobe.
1953NOTE:    activate this ring with the @code{setring} command. In this ring,
1954@*       - the ideal LD is the needed D-mod structure,
1955@*       - the list BS is the Bernstein ideal of a polynomial f = F[1]*..*F[P].
1956@*       If eng <>0, @code{std} is used for Groebner basis computations,
1957@*       otherwise, and by default @code{slimgb} is used.
1958@*       If printlevel=1, progress debug messages will be printed,
1959@*       if printlevel>=2, all the debug messages will be printed.
1960EXAMPLE: example annfsBMI; shows examples
1961"
1962{
1963  int eng = 0;
1964  if ( size(#)>0 )
1965  {
1966    if ( typeof(#[1]) == "int" )
1967    {
1968      eng = int(#[1]);
1969    }
1970  }
1971  // returns a list with a ring and an ideal LD in it
1972  int ppl = printlevel-voice+2;
1973  //  printf("plevel :%s, voice: %s",printlevel,voice);
1974  def save = basering;
1975  int N = nvars(basering);
1976  int P = size(F);  //if F has some generators which are zero, int P = ncols(I);
1977  int Nnew = 2*N+2*P;
1978  int i,j;
1979  string s;
1980  list RL = ringlist(basering);
1981  list L, Lord;
1982  list tmp;
1983  intvec iv;
1984  L[1] = RL[1];  //char
1985  L[4] = RL[4];  //char, minpoly
1986  // check whether vars have admissible names
1987  list Name  = RL[2];
1988  list RName;
1989  for (j=1; j<=P; j++)
1990  {
1991    RName[j] = "t("+string(j)+")";
1992    RName[j+P] = "s("+string(j)+")";
1993  }
1994  for(i=1; i<=N; i++)
1995  {
1996    for(j=1; j<=size(RName); j++)
1997    {
1998      if (Name[i] == RName[j])
1999      { ERROR("Variable names should not include t(i),s(i)"); }
2000    }
2001  }
2002  // now, create the names for new vars
2003  list DName;
2004  for(i=1; i<=N; i++)
2005  {
2006    DName[i] = "D"+Name[i];  //concat
2007  }
2008  list NName = RName + Name + DName;
2009  L[2]   = NName;
2010  // Name, Dname will be used further
2011  kill NName;
2012  // block ord (lp(P),dp);
2013  tmp[1] = "lp";  //string
2014  s      = "iv=";
2015  for (i=1; i<=2*P; i++)
2016  {
2017    s = s+"1,";
2018  }
2019  s[size(s)]= ";";
2020  execute(s);
2021  tmp[2] = iv;  //intvec
2022  Lord[1] = tmp;
2023  // continue with dp 1,1,1,1...
2024  tmp[1] = "dp";  //string
2025  s      = "iv=";
2026  for (i=1; i<=Nnew; i++)  //actually i<=2*N
2027  {
2028    s = s+"1,";
2029  }
2030  s[size(s)]= ";";
2031  execute(s);
2032  kill s;
2033  tmp[2]  = iv;
2034  Lord[2] = tmp;
2035  tmp[1]  = "C";
2036  iv      = 0;
2037  tmp[2]  = iv;
2038  Lord[3] = tmp;
2039  tmp     = 0;
2040  L[3]    = Lord;
2041  // we are done with the list
2042  def @R@ = ring(L);
2043  setring @R@;
2044  matrix @D[Nnew][Nnew];
2045  for (i=1; i<=P; i++)
2046  {
2047    @D[i,i+P] = t(i);
2048  }
2049  for(i=1; i<=N; i++)
2050  {
2051    @D[2*P+i,2*P+N+i] = 1;
2052  }
2053  // L[5] = matrix(UpOneMatrix(Nnew));
2054  // L[6] = @D;
2055  def @R = nc_algebra(1,@D);
2056  setring @R;
2057  kill @R@;
2058  dbprint(ppl,"// -1-1- the ring @R(_t,_s,_x,_Dx) is ready");
2059  dbprint(ppl-1, @R);
2060  // create the ideal I
2061  ideal  F = imap(save,F);
2062  ideal I = t(1)*F[1]+s(1);
2063  for (j=2; j<=P; j++)
2064  {
2065    I = I, t(j)*F[j]+s(j);
2066  }
2067  poly p,q;
2068  for (i=1; i<=N; i++)
2069  {
2070    p=0;
2071    for (j=1; j<=P; j++)
2072    {
2073      q = t(j);
2074      q = diff(F[j],var(2*P+i))*q;
2075      p = p + q;
2076    }
2077    I = I, var(2*P+N+i) + p;
2078  }
2079  // -------- the ideal I is ready ----------
2080  dbprint(ppl,"// -1-2- starting the elimination of "+string(t(1..P))+" in @R");
2081  dbprint(ppl-1, I);
2082  ideal J = engine(I,eng);
2083  ideal K = nselect(J,1,P);
2084  kill I,J;
2085  dbprint(ppl,"// -1-3- all t(i) are eliminated");
2086  dbprint(ppl-1, K);  //K is without t(i)
2087  // ----------- the ring @R2 ------------
2088  // _x, _Dx,s;  elim.ord for _x,_Dx.
2089  // keep: N, i,j,s, tmp, RL
2090  setring save;
2091  Nnew = 2*N+P;
2092  kill Lord, tmp, iv, RName;
2093  list Lord, tmp;
2094  intvec iv;
2095  L[1] = RL[1];  //char
2096  L[4] = RL[4];  //char, minpoly
2097  // check whether vars hava admissible names -> done earlier
2098  // now, create the names for new var
2099  for (j=1; j<=P; j++)
2100  {
2101    tmp[j] = "s("+string(j)+")";
2102  }
2103  // DName is defined earlier
2104  list NName = Name + DName + tmp;
2105  L[2] = NName;
2106  tmp = 0;
2107  // block ord (dp(N),dp);
2108  string s = "iv=";
2109  for (i=1; i<=Nnew-P; i++)
2110  {
2111    s = s+"1,";
2112  }
2113  s[size(s)]=";";
2114  execute(s);
2115  tmp[1] = "dp";  //string
2116  tmp[2] = iv;    //intvec
2117  Lord[1] = tmp;
2118  // continue with dp 1,1,1,1...
2119  tmp[1] = "dp";  //string
2120  s[size(s)] = ",";
2121  for (j=1; j<=P; j++)
2122  {
2123    s = s+"1,";
2124  }
2125  s[size(s)]=";";
2126  execute(s);
2127  kill s;
2128  kill NName;
2129  tmp[2]  = iv;
2130  Lord[2] = tmp;
2131  tmp[1]  = "C";
2132  iv      = 0;
2133  tmp[2]  = iv;
2134  Lord[3] = tmp;
2135  tmp     = 0;
2136  L[3]    = Lord;
2137  // we are done with the list. Now add a Plural part
2138  def @R2@ = ring(L);
2139  setring @R2@;
2140  matrix @D[Nnew][Nnew];
2141  for (i=1; i<=N; i++)
2142  {
2143    @D[i,N+i]=1;
2144  }
2145  def @R2 = nc_algebra(1,@D);
2146  setring @R2;
2147  kill @R2@;
2148  dbprint(ppl,"// -2-1- the ring @R2(_x,_Dx,_s) is ready");
2149  dbprint(ppl-1, @R2);
2150//  ideal MM = maxideal(1);
2151//  MM = 0,s,MM;
2152//  map R01 = @R, MM;
2153//  ideal K = R01(K);
2154  ideal F = imap(save,F);  // maybe ideal F = R01(I); ?
2155  ideal K = imap(@R,K);    // maybe ideal K = R01(I); ?
2156  poly f=1;
2157  for (j=1; j<=P; j++)
2158  {
2159    f = f*F[j];
2160  }
2161  K = K,f;       // to compute B (Bernstein-Sato ideal)
2162  //j=2;         // for example
2163  //K = K,F[j];  // to compute Bj (see "On the computation of Bernstein-Sato ideals"; Castro, Ucha)
2164  //K = K,F;     // to compute Bsigma (see "On the computation of Bernstein-Sato ideals"; Castro, Ucha)
2165  dbprint(ppl,"// -2-2- starting the elimination of _x,_Dx in @R2");
2166  dbprint(ppl-1, K);
2167  ideal M = engine(K,eng);
2168  ideal K2 = nselect(M,1,Nnew-P);
2169  kill K,M;
2170  dbprint(ppl,"// -2-3- _x,_Dx are eliminated in @R2");
2171  dbprint(ppl-1, K2);
2172  // the ring @R3 and factorize
2173  ring @R3 = 0,s(1..P),dp;
2174  dbprint(ppl,"// -3-1- the ring @R3(_s) is ready");
2175  ideal K3 = imap(@R2,K2);
2176  if (size(K3)==1)
2177  {
2178    poly p = K3[1];
2179    dbprint(ppl,"// -3-2- factorization");
2180    // Warning: now P is an integer
2181    list Q = factorize(p);         //with constants and multiplicities
2182    ideal bs; intvec m;
2183    for (i=2; i<=size(Q[1]); i++)  //we delete Q[1][1] and Q[2][1]
2184    {
2185      bs[i-1] = Q[1][i];
2186      m[i-1]  = Q[2][i];
2187    }
2188    //  "--------- Q-ideal factorizes into ---------";  list(bs,m);
2189    list BS = bs,m;
2190  }
2191  else
2192  {
2193    // conjecture: the Bernstein ideal is principal
2194    dbprint(ppl,"// -3-2- the Bernstein ideal is not principal");
2195    ideal BS = K3;
2196  }
2197  // create the ring @R4(_x,_Dx,_s) and put the result into it,
2198  // _x, _Dx,s;  ord "dp".
2199  // keep: N, i,j,s, tmp, RL
2200  setring save;
2201  Nnew = 2*N+P;
2202  // list RL = ringlist(save);  //is defined earlier
2203  kill Lord, tmp, iv;
2204  L = 0;
2205  list Lord, tmp;
2206  intvec iv;
2207  L[1] = RL[1];  //char
2208  L[4] = RL[4];  //char, minpoly
2209  // check whether vars hava admissible names -> done earlier
2210  // now, create the names for new var
2211  for (j=1; j<=P; j++)
2212  {
2213    tmp[j] = "s("+string(j)+")";
2214  }
2215  // DName is defined earlier
2216  list NName = Name + DName + tmp;
2217  L[2] = NName;
2218  tmp = 0;
2219  // dp ordering;
2220  string s = "iv=";
2221  for (i=1; i<=Nnew; i++)
2222  {
2223    s = s+"1,";
2224  }
2225  s[size(s)]=";";
2226  execute(s);
2227  kill s;
2228  kill NName;
2229  tmp[1] = "dp";  //string
2230  tmp[2] = iv;    //intvec
2231  Lord[1] = tmp;
2232  tmp[1]  = "C";
2233  iv      = 0;
2234  tmp[2]  = iv;
2235  Lord[2] = tmp;
2236  tmp     = 0;
2237  L[3]    = Lord;
2238  // we are done with the list. Now add a Plural part
2239  def @R4@ = ring(L);
2240  setring @R4@;
2241  matrix @D[Nnew][Nnew];
2242  for (i=1; i<=N; i++)
2243  {
2244    @D[i,N+i]=1;
2245  }
2246  def @R4 = nc_algebra(1,@D);
2247  setring @R4;
2248  kill @R4@;
2249  dbprint(ppl,"// -4-1- the ring @R4i(_x,_Dx,_s) is ready");
2250  dbprint(ppl-1, @R4);
2251  ideal K4 = imap(@R,K);
2252  option(redSB);
2253  dbprint(ppl,"// -4-2- the final cosmetic std");
2254  K4 = engine(K4,eng);  //std does the job too
2255  // total cleanup
2256  kill @R;
2257  kill @R2;
2258  def BS = imap(@R3,BS);
2259  export BS;
2260  kill @R3;
2261  ideal LD = K4;
2262  export LD;
2263  return(@R4);
2264}
2265example
2266{
2267  "EXAMPLE:"; echo = 2;
2268  ring r = 0,(x,y),Dp;
2269  ideal F = x,y,x+y;
2270  printlevel = 0;
2271  def A = annfsBMI(F);
2272  setring A;
2273  LD;
2274  BS;
2275}
2276
2277proc annfsOT(poly F, list #)
2278"USAGE:  annfsOT(f [,eng]);  f a poly, eng an optional int
2279RETURN:  ring
2280PURPOSE: compute the D-module structure of basering[1/f]*f^s, according
2281to the algorithm by Oaku and Takayama
2282NOTE:    activate this ring with the @code{setring} command. In this ring,
2283@*       - the ideal LD (which is a Groebner basis) is the needed D-module structure,
2284@*         which is obtained by substituting the minimal integer root of a Bernstein
2285@*         polynomial into the s-parametric ideal;
2286@*       - the list BS contains roots with multiplicities of a Bernstein polynomial of f.
2287@*       If eng <>0, @code{std} is used for Groebner basis computations,
2288@*       otherwise, and by default @code{slimgb} is used.
2289@*       If printlevel=1, progress debug messages will be printed,
2290@*       if printlevel>=2, all the debug messages will be printed.
2291EXAMPLE: example annfsOT; shows examples
2292"
2293{
2294  int eng = 0;
2295  if ( size(#)>0 )
2296  {
2297    if ( typeof(#[1]) == "int" )
2298    {
2299      eng = int(#[1]);
2300    }
2301  }
2302  // returns a list with a ring and an ideal LD in it
2303  int ppl = printlevel-voice+2;
2304  //  printf("plevel :%s, voice: %s",printlevel,voice);
2305  def save = basering;
2306  int N = nvars(basering);
2307  int Nnew = 2*(N+2);
2308  int i,j;
2309  string s;
2310  list RL = ringlist(basering);
2311  list L, Lord;
2312  list tmp;
2313  intvec iv;
2314  L[1] = RL[1]; // char
2315  L[4] = RL[4]; // char, minpoly
2316  // check whether vars have admissible names
2317  list Name  = RL[2];
2318  list RName;
2319  RName[1] = "u";
2320  RName[2] = "v";
2321  RName[3] = "t";
2322  RName[4] = "Dt";
2323  for(i=1;i<=N;i++)
2324  {
2325    for(j=1; j<=size(RName);j++)
2326    {
2327      if (Name[i] == RName[j])
2328      {
2329        ERROR("Variable names should not include u,v,t,Dt");
2330      }
2331    }
2332  }
2333  // now, create the names for new vars
2334  tmp[1]     = "u";
2335  tmp[2]     = "v";
2336  list UName = tmp;
2337  list DName;
2338  for(i=1;i<=N;i++)
2339  {
2340    DName[i] = "D"+Name[i]; // concat
2341  }
2342  tmp    =  0;
2343  tmp[1] = "t";
2344  tmp[2] = "Dt";
2345  list NName = UName +  tmp + Name + DName;
2346  L[2]   = NName;
2347  tmp    = 0;
2348  // Name, Dname will be used further
2349  kill UName;
2350  kill NName;
2351  // block ord (a(1,1),dp);
2352  tmp[1]  = "a"; // string
2353  iv      = 1,1;
2354  tmp[2]  = iv; //intvec
2355  Lord[1] = tmp;
2356  // continue with dp 1,1,1,1...
2357  tmp[1]  = "dp"; // string
2358  s       = "iv=";
2359  for(i=1;i<=Nnew;i++)
2360  {
2361    s = s+"1,";
2362  }
2363  s[size(s)]= ";";
2364  execute(s);
2365  tmp[2]    = iv;
2366  Lord[2]   = tmp;
2367  tmp[1]    = "C";
2368  iv        = 0;
2369  tmp[2]    = iv;
2370  Lord[3]   = tmp;
2371  tmp       = 0;
2372  L[3]      = Lord;
2373  // we are done with the list
2374  def @R@ = ring(L);
2375  setring @R@;
2376  matrix @D[Nnew][Nnew];
2377  @D[3,4]=1;
2378  for(i=1; i<=N; i++)
2379  {
2380    @D[4+i,N+4+i]=1;
2381  }
2382  //  @D[N+3,2*(N+2)]=1; old t,Dt stuff
2383  //  L[5] = matrix(UpOneMatrix(Nnew));
2384  //  L[6] = @D;
2385  def @R = nc_algebra(1,@D);
2386  setring @R;
2387  kill @R@;
2388  dbprint(ppl,"// -1-1- the ring @R(u,v,t,Dt,_x,_Dx) is ready");
2389  dbprint(ppl-1, @R);
2390  // create the ideal I
2391  poly  F = imap(save,F);
2392  ideal I = u*F-t,u*v-1;
2393  poly p;
2394  for(i=1; i<=N; i++)
2395  {
2396    p = u*Dt; // u*Dt
2397    p = diff(F,var(4+i))*p;
2398    I = I, var(N+4+i) + p;
2399  }
2400  // -------- the ideal I is ready ----------
2401  dbprint(ppl,"// -1-2- starting the elimination of u,v in @R");
2402  dbprint(ppl-1, I);
2403  ideal J = engine(I,eng);
2404  ideal K = nselect(J,1,2);
2405  dbprint(ppl,"// -1-3- u,v are eliminated");
2406  dbprint(ppl-1, K);  // K is without u,v
2407  setring save;
2408  // ------------ new ring @R2 ------------------
2409  // without u,v and with the elim.ord for t,Dt
2410  // tensored with the K[s]
2411  // keep: N, i,j,s, tmp, RL
2412  Nnew = 2*N+2+1;
2413  //  list RL = ringlist(save); // is defined earlier
2414  L = 0;  //  kill L;
2415  kill Lord, tmp, iv, RName;
2416  list Lord, tmp;
2417  intvec iv;
2418  L[1] = RL[1]; L[4] = RL[4]; // char, minpoly
2419  // check whether vars have admissible names -> done earlier
2420  //  list Name  = RL[2];
2421  list RName;
2422  RName[1] = "t";
2423  RName[2] = "Dt";
2424  // now, create the names for new var (here, s only)
2425  tmp[1]     = "s";
2426  // DName is defined earlier
2427  list NName = RName + Name + DName + tmp;
2428  L[2]   = NName;
2429  tmp    = 0;
2430  // block ord (a(1,1),dp);
2431  tmp[1]  = "a";  iv = 1,1; tmp[2]  = iv; //intvec
2432  Lord[1] = tmp;
2433  // continue with a(1,1,1,1)...
2434  tmp[1]  = "dp"; s  = "iv=";
2435  for(i=1; i<= Nnew; i++)
2436  {
2437    s = s+"1,";
2438  }
2439  s[size(s)]= ";";  execute(s);
2440  kill NName;
2441  tmp[2]    = iv;
2442  Lord[2]   = tmp;
2443  // extra block for s
2444  // tmp[1] = "dp"; iv = 1;
2445  //  s[size(s)]= ",";  s = s + "1,1,1;";  execute(s);  tmp[2]    = iv;
2446  //  Lord[3]   = tmp;
2447  kill s;
2448  tmp[1]    = "C";   iv  = 0; tmp[2] = iv;
2449  Lord[3]   = tmp;   tmp = 0;
2450  L[3]      = Lord;
2451  // we are done with the list. Now, add a Plural part
2452  def @R2@ = ring(L);
2453  setring @R2@;
2454  matrix @D[Nnew][Nnew];
2455  @D[1,2] = 1;
2456  for(i=1; i<=N; i++)
2457  {
2458    @D[2+i,2+N+i] = 1;
2459  }
2460  def @R2 = nc_algebra(1,@D);
2461  setring @R2;
2462  kill @R2@;
2463  dbprint(ppl,"// -2-1- the ring @R2(t,Dt,_x,_Dx,s) is ready");
2464  dbprint(ppl-1, @R2);
2465  ideal MM = maxideal(1);
2466  MM = 0,0,MM;
2467  map R01 = @R, MM;
2468  ideal K = R01(K);
2469  //  ideal K = imap(@R,K); // names of vars are important!
2470  poly G = t*Dt+s+1; // s is a variable here
2471  K = NF(K,std(G)),G;
2472  // -------- the ideal K_(@R2) is ready ----------
2473  dbprint(ppl,"// -2-2- starting the elimination of t,Dt in @R2");
2474  dbprint(ppl-1, K);
2475  ideal M  = engine(K,eng);
2476  ideal K2 = nselect(M,1,2);
2477  dbprint(ppl,"// -2-3- t,Dt are eliminated");
2478  dbprint(ppl-1, K2);
2479  //  dbprint(ppl-1+1," -2-4- std of K2");
2480  //  option(redSB);  option(redTail);  K2 = std(K2);
2481  //  K2; // without t,Dt, and with s
2482  // -------- the ring @R3 ----------
2483  // _x, _Dx, s; elim.ord for _x,_Dx.
2484  // keep: N, i,j,s, tmp, RL
2485  setring save;
2486  Nnew = 2*N+1;
2487  //  list RL = ringlist(save); // is defined earlier
2488  //  kill L;
2489  kill Lord, tmp, iv, RName;
2490  list Lord, tmp;
2491  intvec iv;
2492  L[1] = RL[1]; L[4] = RL[4]; // char, minpoly
2493  // check whether vars have admissible names -> done earlier
2494  //  list Name  = RL[2];
2495  // now, create the names for new var (here, s only)
2496  tmp[1]     = "s";
2497  // DName is defined earlier
2498  list NName = Name + DName + tmp;
2499  L[2]   = NName;
2500  tmp    = 0;
2501  // block ord (a(1,1...),dp);
2502  string  s = "iv=";
2503  for(i=1; i<=Nnew-1; i++)
2504  {
2505    s = s+"1,";
2506  }
2507  s[size(s)]= ";";
2508  execute(s);
2509  tmp[1]  = "a"; // string
2510  tmp[2]  = iv; //intvec
2511  Lord[1] = tmp;
2512  // continue with dp 1,1,1,1...
2513  tmp[1]  = "dp"; // string
2514  s[size(s)]=","; s= s+"1;";
2515  execute(s);
2516  kill s;
2517  kill NName;
2518  tmp[2]    = iv;
2519  Lord[2]   = tmp;
2520  tmp[1]    = "C";  iv  = 0;  tmp[2] = iv;
2521  Lord[3]   = tmp;  tmp = 0;
2522  L[3]      = Lord;
2523  // we are done with the list. Now add a Plural part
2524  def @R3@ = ring(L);
2525  setring @R3@;
2526  matrix @D[Nnew][Nnew];
2527  for(i=1; i<=N; i++)
2528  {
2529    @D[i,N+i]=1;
2530  }
2531  def @R3 = nc_algebra(1,@D);
2532  setring @R3;
2533  kill @R3@;
2534  dbprint(ppl,"// -3-1- the ring @R3(_x,_Dx,s) is ready");
2535  dbprint(ppl-1, @R3);
2536  ideal MM = maxideal(1);
2537  MM = 0,0,MM;
2538  map R12 = @R2, MM;
2539  ideal K = R12(K2);
2540  poly  F = imap(save,F);
2541  K = K,F;
2542  dbprint(ppl,"// -3-2- starting the elimination of _x,_Dx in @R3");
2543  dbprint(ppl-1, K);
2544  ideal M = engine(K,eng);
2545  ideal K3 = nselect(M,1,Nnew-1);
2546  dbprint(ppl,"// -3-3-  _x,_Dx are eliminated in @R3");
2547  dbprint(ppl-1, K3);
2548  // the ring @R4  and the search for minimal negative int s
2549  ring @R4 = 0,(s),dp;
2550  dbprint(ppl,"// -4-1- the ring @R4 is ready");
2551  ideal K4 = imap(@R3,K3);
2552  poly p = K4[1];
2553  dbprint(ppl,"// -4-2- factorization");
2554////  ideal P = factorize(p,1);  // without constants and multiplicities
2555  list P = factorize(p);         // with constants and multiplicities
2556  ideal bs; intvec m;            // the Bernstein polynomial is monic, so we are not interested in constants
2557  for (i=2; i<=size(P[1]); i++)  // we delete P[1][1] and P[2][1]
2558  {
2559    bs[i-1] = P[1][i];
2560    m[i-1]  = P[2][i];
2561  }
2562  //  "------ b-function factorizes into ----------";  P;
2563////  int sP  = minIntRoot(P, 1);
2564  int sP = minIntRoot(bs,1);
2565  dbprint(ppl,"// -4-3- minimal integer root found");
2566  dbprint(ppl-1, sP);
2567  // convert factors to a list of their roots
2568  // assume all factors are linear
2569////  ideal BS = normalize(P);
2570////  BS = subst(BS,s,0);
2571////  BS = -BS;
2572  bs = normalize(bs);
2573  bs = subst(bs,s,0);
2574  bs = -bs;
2575  list BS = bs,m;
2576  // TODO: sort BS!
2577  // ------ substitute s found in the ideal ------
2578  // ------- going back to @R2 and substitute --------
2579  setring @R2;
2580  ideal K3 = subst(K2,s,sP);
2581  // create the ordinary Weyl algebra and put the result into it,
2582  // thus creating the ring @R5
2583  // keep: N, i,j,s, tmp, RL
2584  setring save;
2585  Nnew = 2*N;
2586  //  list RL = ringlist(save); // is defined earlier
2587  kill Lord, tmp, iv;
2588  L = 0;
2589  list Lord, tmp;
2590  intvec iv;
2591  L[1] = RL[1];   L[4] = RL[4]; // char, minpoly
2592  // check whether vars have admissible names -> done earlier
2593  //  list Name  = RL[2];
2594  // DName is defined earlier
2595  list NName = Name + DName;
2596  L[2]   = NName;
2597  // dp ordering;
2598  string   s       = "iv=";
2599  for(i=1;i<=Nnew;i++)
2600  {
2601    s = s+"1,";
2602  }
2603  s[size(s)]= ";";
2604  execute(s);
2605  tmp     = 0;
2606  tmp[1]  = "dp"; // string
2607  tmp[2]  = iv; //intvec
2608  Lord[1] = tmp;
2609  kill s;
2610  tmp[1]    = "C";
2611  iv        = 0;
2612  tmp[2]    = iv;
2613  Lord[2]   = tmp;
2614  tmp       = 0;
2615  L[3]      = Lord;
2616  // we are done with the list
2617  // Add: Plural part
2618  def @R5@ = ring(L);
2619  setring @R5@;
2620  matrix @D[Nnew][Nnew];
2621  for(i=1; i<=N; i++)
2622  {
2623    @D[i,N+i]=1;
2624  }
2625  def @R5 = nc_algebra(1,@D);
2626  setring @R5;
2627  kill @R5@;
2628  dbprint(ppl,"// -5-1- the ring @R5 is ready");
2629  dbprint(ppl-1, @R5);
2630  ideal K5 = imap(@R2,K3);
2631  option(redSB);
2632  dbprint(ppl,"// -5-2- the final cosmetic std");
2633  K5 = engine(K5,eng); // std does the job too
2634  // total cleanup
2635  kill @R;
2636  kill @R2;
2637  kill @R3;
2638////  ideal BS = imap(@R4,BS);
2639  list BS = imap(@R4,BS);
2640  export BS;
2641  ideal LD = K5;
2642  kill @R4;
2643  export LD;
2644  return(@R5);
2645}
2646example
2647{
2648  "EXAMPLE:"; echo = 2;
2649  ring r = 0,(x,y,z),Dp;
2650  poly F = x^2+y^3+z^5;
2651  printlevel = 0;
2652  def A  = annfsOT(F);
2653  setring A;
2654  LD;
2655  BS;
2656}
2657
2658
2659proc SannfsOT(poly F, list #)
2660"USAGE:  SannfsOT(f [,eng]);  f a poly, eng an optional int
2661RETURN:  ring
2662PURPOSE: 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
2663NOTE:    activate this ring with the @code{setring} command.
2664@*       In the ring D[s], the ideal LD (which is NOT a Groebner basis) is the needed D-module structure.
2665@*       If eng <>0, @code{std} is used for Groebner basis computations,
2666@*       otherwise, and by default @code{slimgb} is used.
2667@*       If printlevel=1, progress debug messages will be printed,
2668@*       if printlevel>=2, all the debug messages will be printed.
2669EXAMPLE: example SannfsOT; shows examples
2670"
2671{
2672  int eng = 0;
2673  if ( size(#)>0 )
2674  {
2675    if ( typeof(#[1]) == "int" )
2676    {
2677      eng = int(#[1]);
2678    }
2679  }
2680  // returns a list with a ring and an ideal LD in it
2681  int ppl = printlevel-voice+2;
2682  //  printf("plevel :%s, voice: %s",printlevel,voice);
2683  def save = basering;
2684  int N = nvars(basering);
2685  int Nnew = 2*(N+2);
2686  int i,j;
2687  string s;
2688  list RL = ringlist(basering);
2689  list L, Lord;
2690  list tmp;
2691  intvec iv;
2692  L[1] = RL[1]; // char
2693  L[4] = RL[4]; // char, minpoly
2694  // check whether vars have admissible names
2695  list Name  = RL[2];
2696  list RName;
2697  RName[1] = "u";
2698  RName[2] = "v";
2699  RName[3] = "t";
2700  RName[4] = "Dt";
2701  for(i=1;i<=N;i++)
2702  {
2703    for(j=1; j<=size(RName);j++)
2704    {
2705      if (Name[i] == RName[j])
2706      {
2707        ERROR("Variable names should not include u,v,t,Dt");
2708      }
2709    }
2710  }
2711  // now, create the names for new vars
2712  tmp[1]     = "u";
2713  tmp[2]     = "v";
2714  list UName = tmp;
2715  list DName;
2716  for(i=1;i<=N;i++)
2717  {
2718    DName[i] = "D"+Name[i]; // concat
2719  }
2720  tmp    =  0;
2721  tmp[1] = "t";
2722  tmp[2] = "Dt";
2723  list NName = UName +  tmp + Name + DName;
2724  L[2]   = NName;
2725  tmp    = 0;
2726  // Name, Dname will be used further
2727  kill UName;
2728  kill NName;
2729  // block ord (a(1,1),dp);
2730  tmp[1]  = "a"; // string
2731  iv      = 1,1;
2732  tmp[2]  = iv; //intvec
2733  Lord[1] = tmp;
2734  // continue with dp 1,1,1,1...
2735  tmp[1]  = "dp"; // string
2736  s       = "iv=";
2737  for(i=1;i<=Nnew;i++)
2738  {
2739    s = s+"1,";
2740  }
2741  s[size(s)]= ";";
2742  execute(s);
2743  tmp[2]    = iv;
2744  Lord[2]   = tmp;
2745  tmp[1]    = "C";
2746  iv        = 0;
2747  tmp[2]    = iv;
2748  Lord[3]   = tmp;
2749  tmp       = 0;
2750  L[3]      = Lord;
2751  // we are done with the list
2752  def @R@ = ring(L);
2753  setring @R@;
2754  matrix @D[Nnew][Nnew];
2755  @D[3,4]=1;
2756  for(i=1; i<=N; i++)
2757  {
2758    @D[4+i,N+4+i]=1;
2759  }
2760  //  @D[N+3,2*(N+2)]=1; old t,Dt stuff
2761  //  L[5] = matrix(UpOneMatrix(Nnew));
2762  //  L[6] = @D;
2763  def @R =  nc_algebra(1,@D);
2764  setring @R;
2765  kill @R@;
2766  dbprint(ppl,"// -1-1- the ring @R(u,v,t,Dt,_x,_Dx) is ready");
2767  dbprint(ppl-1, @R);
2768  // create the ideal I
2769  poly  F = imap(save,F);
2770  ideal I = u*F-t,u*v-1;
2771  poly p;
2772  for(i=1; i<=N; i++)
2773  {
2774    p = u*Dt; // u*Dt
2775    p = diff(F,var(4+i))*p;
2776    I = I, var(N+4+i) + p;
2777  }
2778  // -------- the ideal I is ready ----------
2779  dbprint(ppl,"// -1-2- starting the elimination of u,v in @R");
2780  dbprint(ppl-1, I);
2781  ideal J = engine(I,eng);
2782  ideal K = nselect(J,1,2);
2783  dbprint(ppl,"// -1-3- u,v are eliminated");
2784  dbprint(ppl-1, K);  // K is without u,v
2785
2786
2787  setring save;
2788  // ------------ new ring @R2 ------------------
2789  // without u,v and with the elim.ord for t,Dt
2790  // tensored with the K[s]
2791  // keep: N, i,j,s, tmp, RL
2792  Nnew = 2*N+2+1;
2793  //  list RL = ringlist(save); // is defined earlier
2794  L = 0;  //  kill L;
2795  kill Lord, tmp, iv, RName;
2796  list Lord, tmp;
2797  intvec iv;
2798  L[1] = RL[1]; L[4] = RL[4]; // char, minpoly
2799  // check whether vars have admissible names -> done earlier
2800  //  list Name  = RL[2];
2801  list RName;
2802  RName[1] = "t";
2803  RName[2] = "Dt";
2804  // now, create the names for new var (here, s only)
2805  tmp[1]     = "s";
2806  // DName is defined earlier
2807  list NName = RName + Name + DName + tmp;
2808  L[2]   = NName;
2809  tmp    = 0;
2810  // block ord (a(1,1),dp);
2811  tmp[1]  = "a";  iv = 1,1; tmp[2]  = iv; //intvec
2812  Lord[1] = tmp;
2813  // continue with a(1,1,1,1)...
2814  tmp[1]  = "dp"; s  = "iv=";
2815  for(i=1; i<= Nnew; i++)
2816  {
2817    s = s+"1,";
2818  }
2819  s[size(s)]= ";";  execute(s);
2820  kill NName;
2821  tmp[2]    = iv;
2822  Lord[2]   = tmp;
2823  // extra block for s
2824  // tmp[1] = "dp"; iv = 1;
2825  //  s[size(s)]= ",";  s = s + "1,1,1;";  execute(s);  tmp[2]    = iv;
2826  //  Lord[3]   = tmp;
2827  kill s;
2828  tmp[1]    = "C";   iv  = 0; tmp[2] = iv;
2829  Lord[3]   = tmp;   tmp = 0;
2830  L[3]      = Lord;
2831  // we are done with the list. Now, add a Plural part
2832  def @R2@ = ring(L);
2833  setring @R2@;
2834  matrix @D[Nnew][Nnew];
2835  @D[1,2] = 1;
2836  for(i=1; i<=N; i++)
2837  {
2838    @D[2+i,2+N+i] = 1;
2839  }
2840  def @R2 = nc_algebra(1,@D);
2841  setring @R2;
2842  kill @R2@;
2843  dbprint(ppl,"// -2-1- the ring @R2(t,Dt,_x,_Dx,s) is ready");
2844  dbprint(ppl-1, @R2);
2845  ideal MM = maxideal(1);
2846  MM = 0,0,MM;
2847  map R01 = @R, MM;
2848  ideal K = R01(K);
2849  //  ideal K = imap(@R,K); // names of vars are important!
2850  poly G = t*Dt+s+1; // s is a variable here
2851  K = NF(K,std(G)),G;
2852  // -------- the ideal K_(@R2) is ready ----------
2853  dbprint(ppl,"// -2-2- starting the elimination of t,Dt in @R2");
2854  dbprint(ppl-1, K);
2855  ideal M  = engine(K,eng);
2856  ideal K2 = nselect(M,1,2);
2857  dbprint(ppl,"// -2-3- t,Dt are eliminated");
2858  dbprint(ppl-1, K2);
2859  K2 = engine(K2,eng);
2860  setring save;
2861  // ----------- the ring @R3 ------------
2862  // _x, _Dx,s;  elim.ord for _x,_Dx.
2863  // keep: N, i,j,s, tmp, RL
2864  Nnew = 2*N+1;
2865  kill Lord, tmp, iv, RName;
2866  list Lord, tmp;
2867  intvec iv;
2868  L[1] = RL[1];
2869  L[4] = RL[4];  // char, minpoly
2870  // check whether vars hava admissible names -> done earlier
2871  // now, create the names for new var
2872  tmp[1] = "s";
2873  // DName is defined earlier
2874  list NName = Name + DName + tmp;
2875  L[2] = NName;
2876  tmp = 0;
2877  // block ord (dp(N),dp);
2878  string s = "iv=";
2879  for (i=1; i<=Nnew-1; i++)
2880  {
2881    s = s+"1,";
2882  }
2883  s[size(s)]=";";
2884  execute(s);
2885  tmp[1] = "dp";  // string
2886  tmp[2] = iv;   // intvec
2887  Lord[1] = tmp;
2888  // continue with dp 1,1,1,1...
2889  tmp[1] = "dp";  // string
2890  s[size(s)] = ",";
2891  s = s+"1;";
2892  execute(s);
2893  kill s;
2894  kill NName;
2895  tmp[2]      = iv;
2896  Lord[2]     = tmp;
2897  tmp[1]      = "C";  iv  = 0;  tmp[2]=iv;
2898  Lord[3]     = tmp;  tmp = 0;
2899  L[3]        = Lord;
2900  // we are done with the list. Now add a Plural part
2901  def @R3@ = ring(L);
2902  setring @R3@;
2903  matrix @D[Nnew][Nnew];
2904  for (i=1; i<=N; i++)
2905  {
2906    @D[i,N+i]=1;
2907  }
2908  def @R3 = nc_algebra(1,@D);
2909  setring @R3;
2910  kill @R3@;
2911  dbprint(ppl,"// -3-1- the ring @R3(_x,_Dx,s) is ready");
2912  dbprint(ppl-1, @R3);
2913  ideal MM = maxideal(1);
2914  MM = 0,s,MM;
2915  map R01 = @R2, MM;
2916  ideal K2 = R01(K2);
2917  // total cleanup
2918  ideal LD = K2;
2919  // make leadcoeffs positive
2920  for (i=1; i<= ncols(LD); i++)
2921  {
2922    if (leadcoef(LD[i]) <0 )
2923    {
2924      LD[i] = -LD[i];
2925    }
2926  }
2927  export LD;
2928  kill @R;
2929  kill @R2;
2930  return(@R3);
2931}
2932example
2933{
2934  "EXAMPLE:"; echo = 2;
2935  ring r = 0,(x,y,z),Dp;
2936  poly F = x^3+y^3+z^3;
2937  printlevel = 0;
2938  def A  = SannfsOT(F);
2939  setring A;
2940  LD;
2941}
2942
2943proc SannfsBM(poly F, list #)
2944"USAGE:  SannfsBM(f [,eng]);  f a poly, eng an optional int
2945RETURN:  ring
2946PURPOSE: 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
2947NOTE:    activate this ring with the @code{setring} command.
2948@*       In the ring D[s], the ideal LD (which is NOT a Groebner basis) is the needed D-module structure,
2949@*       If eng <>0, @code{std} is used for Groebner basis computations,
2950@*       otherwise, and by default @code{slimgb} is used.
2951@*       If printlevel=1, progress debug messages will be printed,
2952@*       if printlevel>=2, all the debug messages will be printed.
2953EXAMPLE: example SannfsBM; shows examples
2954"
2955{
2956  int eng = 0;
2957  if ( size(#)>0 )
2958  {
2959    if ( typeof(#[1]) == "int" )
2960    {
2961      eng = int(#[1]);
2962    }
2963  }
2964  // returns a list with a ring and an ideal LD in it
2965  int ppl = printlevel-voice+2;
2966  //  printf("plevel :%s, voice: %s",printlevel,voice);
2967  def save = basering;
2968  int N = nvars(basering);
2969  int Nnew = 2*N+2;
2970  int i,j;
2971  string s;
2972  list RL = ringlist(basering);
2973  list L, Lord;
2974  list tmp;
2975  intvec iv;
2976  L[1] = RL[1]; // char
2977  L[4] = RL[4]; // char, minpoly
2978  // check whether vars have admissible names
2979  list Name  = RL[2];
2980  list RName;
2981  RName[1] = "t";
2982  RName[2] = "s";
2983  for(i=1;i<=N;i++)
2984  {
2985    for(j=1; j<=size(RName);j++)
2986    {
2987      if (Name[i] == RName[j])
2988      {
2989        ERROR("Variable names should not include t,s");
2990      }
2991    }
2992  }
2993  // now, create the names for new vars
2994  list DName;
2995  for(i=1;i<=N;i++)
2996  {
2997    DName[i] = "D"+Name[i]; // concat
2998  }
2999  tmp[1] = "t";
3000  tmp[2] = "s";
3001  list NName = tmp + Name + DName;
3002  L[2]   = NName;
3003  // Name, Dname will be used further
3004  kill NName;
3005  // block ord (lp(2),dp);
3006  tmp[1]  = "lp"; // string
3007  iv      = 1,1;
3008  tmp[2]  = iv; //intvec
3009  Lord[1] = tmp;
3010  // continue with dp 1,1,1,1...
3011  tmp[1]  = "dp"; // string
3012  s       = "iv=";
3013  for(i=1;i<=Nnew;i++)
3014  {
3015    s = s+"1,";
3016  }
3017  s[size(s)]= ";";
3018  execute(s);
3019  kill s;
3020  tmp[2]    = iv;
3021  Lord[2]   = tmp;
3022  tmp[1]    = "C";
3023  iv        = 0;
3024  tmp[2]    = iv;
3025  Lord[3]   = tmp;
3026  tmp       = 0;
3027  L[3]      = Lord;
3028  // we are done with the list
3029  def @R@ = ring(L);
3030  setring @R@;
3031  matrix @D[Nnew][Nnew];
3032  @D[1,2]=t;
3033  for(i=1; i<=N; i++)
3034  {
3035    @D[2+i,N+2+i]=1;
3036  }
3037  //  L[5] = matrix(UpOneMatrix(Nnew));
3038  //  L[6] = @D;
3039  def @R = nc_algebra(1,@D);
3040  setring @R;
3041  kill @R@;
3042  dbprint(ppl,"// -1-1- the ring @R(t,s,_x,_Dx) is ready");
3043  dbprint(ppl-1, @R);
3044  // create the ideal I
3045  poly  F = imap(save,F);
3046  ideal I = t*F+s;
3047  poly p;
3048  for(i=1; i<=N; i++)
3049  {
3050    p = t; // t
3051    p = diff(F,var(2+i))*p;
3052    I = I, var(N+2+i) + p;
3053  }
3054  // -------- the ideal I is ready ----------
3055  dbprint(ppl,"// -1-2- starting the elimination of t in @R");
3056  dbprint(ppl-1, I);
3057  ideal J = engine(I,eng);
3058  ideal K = nselect(J,1);
3059  dbprint(ppl,"// -1-3- t is eliminated");
3060  dbprint(ppl-1, K);  // K is without t
3061  K = engine(K,eng);  // std does the job too
3062  // now, we must change the ordering
3063  // and create a ring without t, Dt
3064  //  setring S;
3065  // ----------- the ring @R3 ------------
3066  // _x, _Dx,s;  elim.ord for _x,_Dx.
3067  // keep: N, i,j,s, tmp, RL
3068  Nnew = 2*N+1;
3069  kill Lord, tmp, iv, RName;
3070  list Lord, tmp;
3071  intvec iv;
3072  list L=imap(save,L);
3073  list RL=imap(save,RL);
3074  L[1] = RL[1];
3075  L[4] = RL[4];  // char, minpoly
3076  // check whether vars hava admissible names -> done earlier
3077  // now, create the names for new var
3078  tmp[1] = "s";
3079  // DName is defined earlier
3080  list NName = Name + DName + tmp;
3081  L[2] = NName;
3082  tmp = 0;
3083  // block ord (dp(N),dp);
3084  string s = "iv=";
3085  for (i=1; i<=Nnew-1; i++)
3086  {
3087    s = s+"1,";
3088  }
3089  s[size(s)]=";";
3090  execute(s);
3091  tmp[1] = "dp";  // string
3092  tmp[2] = iv;   // intvec
3093  Lord[1] = tmp;
3094  // continue with dp 1,1,1,1...
3095  tmp[1] = "dp";  // string
3096  s[size(s)] = ",";
3097  s = s+"1;";
3098  execute(s);
3099  kill s;
3100  kill NName;
3101  tmp[2]      = iv;
3102  Lord[2]     = tmp;
3103  tmp[1]      = "C";  iv  = 0;  tmp[2]=iv;
3104  Lord[3]     = tmp;  tmp = 0;
3105  L[3]        = Lord;
3106  // we are done with the list. Now add a Plural part
3107  def @R2@ = ring(L);
3108  setring @R2@;
3109  matrix @D[Nnew][Nnew];
3110  for (i=1; i<=N; i++)
3111  {
3112    @D[i,N+i]=1;
3113  }
3114  def @R2 = nc_algebra(1,@D);
3115  setring @R2;
3116  kill @R2@;
3117  dbprint(ppl,"//  -2-1- the ring @R2(_x,_Dx,s) is ready");
3118  dbprint(ppl-1, @R2);
3119  ideal MM = maxideal(1);
3120  MM = 0,s,MM;
3121  map R01 = @R, MM;
3122  ideal K = R01(K);
3123  // total cleanup
3124  ideal LD = K;
3125  // make leadcoeffs positive
3126  for (i=1; i<= ncols(LD); i++)
3127  {
3128    if (leadcoef(LD[i]) <0 )
3129    {
3130      LD[i] = -LD[i];
3131    }
3132  }
3133  export LD;
3134  kill @R;
3135  return(@R2);
3136}
3137example
3138{
3139  "EXAMPLE:"; echo = 2;
3140  ring r = 0,(x,y,z),Dp;
3141  poly F = x^3+y^3+z^3;
3142  printlevel = 0;
3143  def A = SannfsBM(F);
3144  setring A;
3145  LD;
3146}
3147
3148proc SannfsLOT(poly F, list #)
3149"USAGE:  SannfsLOT(f [,eng]);  f a poly, eng an optional int
3150RETURN:  ring
3151PURPOSE: 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
3152NOTE:    activate this ring with the @code{setring} command.
3153@*       In the ring D[s], the ideal LD (which is NOT a Groebner basis) is the needed D-module structure.
3154@*       If eng <>0, @code{std} is used for Groebner basis computations,
3155@*       otherwise, and by default @code{slimgb} is used.
3156@*       If printlevel=1, progress debug messages will be printed,
3157@*       if printlevel>=2, all the debug messages will be printed.
3158EXAMPLE: example SannfsLOT; shows examples
3159"
3160{
3161  int eng = 0;
3162  if ( size(#)>0 )
3163  {
3164    if ( typeof(#[1]) == "int" )
3165    {
3166      eng = int(#[1]);
3167    }
3168  }
3169  // returns a list with a ring and an ideal LD in it
3170  int ppl = printlevel-voice+2;
3171  //  printf("plevel :%s, voice: %s",printlevel,voice);
3172  def save = basering;
3173  int N = nvars(basering);
3174  //  int Nnew = 2*(N+2);
3175  int Nnew = 2*(N+1)+1; //removed u,v; added s
3176  int i,j;
3177  string s;
3178  list RL = ringlist(basering);
3179  list L, Lord;
3180  list tmp;
3181  intvec iv;
3182  L[1] = RL[1]; // char
3183  L[4] = RL[4]; // char, minpoly
3184  // check whether vars have admissible names
3185  list Name  = RL[2];
3186  list RName;
3187//   RName[1] = "u";
3188//   RName[2] = "v";
3189  RName[1] = "t";
3190  RName[2] = "Dt";
3191  for(i=1;i<=N;i++)
3192  {
3193    for(j=1; j<=size(RName);j++)
3194    {
3195      if (Name[i] == RName[j])
3196      {
3197        ERROR("Variable names should not include t,Dt");
3198      }
3199    }
3200  }
3201  // now, create the names for new vars
3202//   tmp[1]     = "u";
3203//   tmp[2]     = "v";
3204//   list UName = tmp;
3205  list DName;
3206  for(i=1;i<=N;i++)
3207  {
3208    DName[i] = "D"+Name[i]; // concat
3209  }
3210  tmp    =  0;
3211  tmp[1] = "t";
3212  tmp[2] = "Dt";
3213  list SName ; SName[1] = "s";
3214  //  list NName = UName +  tmp + Name + DName;
3215  list NName = tmp + Name + DName + SName;
3216  L[2]   = NName;
3217  tmp    = 0;
3218  // Name, Dname will be used further
3219  //  kill UName;
3220  kill NName;
3221  // block ord (a(1,1),dp);
3222  tmp[1]  = "a"; // string
3223  iv      = 1,1;
3224  tmp[2]  = iv; //intvec
3225  Lord[1] = tmp;
3226  // continue with dp 1,1,1,1...
3227  tmp[1]  = "dp"; // string
3228  s       = "iv=";
3229  for(i=1;i<=Nnew;i++)
3230  {
3231    s = s+"1,";
3232  }
3233  s[size(s)]= ";";
3234  execute(s);
3235  tmp[2]    = iv;
3236  Lord[2]   = tmp;
3237  tmp[1]    = "C";
3238  iv        = 0;
3239  tmp[2]    = iv;
3240  Lord[3]   = tmp;
3241  tmp       = 0;
3242  L[3]      = Lord;
3243  // we are done with the list
3244  def @R@ = ring(L);
3245  setring @R@;
3246  matrix @D[Nnew][Nnew];
3247  @D[1,2]=1;
3248  for(i=1; i<=N; i++)
3249  {
3250    @D[2+i,N+2+i]=1;
3251  }
3252  // ADD [s,t]=-t, [s,Dt]=Dt
3253  @D[1,Nnew] = -var(1);
3254  @D[2,Nnew] = var(2);
3255  //  @D[N+3,2*(N+2)]=1; old t,Dt stuff
3256  //  L[5] = matrix(UpOneMatrix(Nnew));
3257  //  L[6] = @D;
3258  def @R = nc_algebra(1,@D);
3259  setring @R;
3260  kill @R@;
3261  dbprint(ppl,"// -1-1- the ring @R(t,Dt,_x,_Dx,s) is ready");
3262  dbprint(ppl-1, @R);
3263  // create the ideal I
3264  poly  F = imap(save,F);
3265  //  ideal I = u*F-t,u*v-1;
3266  ideal I = F-t;
3267  poly p;
3268  for(i=1; i<=N; i++)
3269  {
3270    //    p = u*Dt; // u*Dt
3271    p = Dt;
3272    p = diff(F,var(2+i))*p;
3273    I = I, var(N+2+i) + p;
3274  }
3275  //  I = I, var(1)*var(2) + var(Nnew) +1; // reduce it with t-f!!!
3276  // t*Dt + s +1 reduced with t-f gives f*Dt + s
3277  I = I, F*var(2) + var(Nnew);
3278  // -------- the ideal I is ready ----------
3279  dbprint(ppl,"// -1-2- starting the elimination of t,Dt in @R");
3280  dbprint(ppl-1, I);
3281  ideal J = engine(I,eng);
3282  ideal K = nselect(J,1,2);
3283  dbprint(ppl,"// -1-3- t,Dt are eliminated");
3284  dbprint(ppl-1, K);  // K is without t, Dt
3285  K = engine(K,eng);  // std does the job too
3286  // now, we must change the ordering
3287  // and create a ring without t, Dt
3288  setring save;
3289  // ----------- the ring @R3 ------------
3290  // _x, _Dx,s;  elim.ord for _x,_Dx.
3291  // keep: N, i,j,s, tmp, RL
3292  Nnew = 2*N+1;
3293  kill Lord, tmp, iv, RName;
3294  list Lord, tmp;
3295  intvec iv;
3296  L[1] = RL[1];
3297  L[4] = RL[4];  // char, minpoly
3298  // check whether vars hava admissible names -> done earlier
3299  // now, create the names for new var
3300  tmp[1] = "s";
3301  // DName is defined earlier
3302  list NName = Name + DName + tmp;
3303  L[2] = NName;
3304  tmp = 0;
3305  // block ord (dp(N),dp);
3306  // string s is already defined
3307  s = "iv=";
3308  for (i=1; i<=Nnew-1; i++)
3309  {
3310    s = s+"1,";
3311  }
3312  s[size(s)]=";";
3313  execute(s);
3314  tmp[1] = "dp";  // string
3315  tmp[2] = iv;   // intvec
3316  Lord[1] = tmp;
3317  // continue with dp 1,1,1,1...
3318  tmp[1] = "dp";  // string
3319  s[size(s)] = ",";
3320  s = s+"1;";
3321  execute(s);
3322  kill s;
3323  kill NName;
3324  tmp[2]      = iv;
3325  Lord[2]     = tmp;
3326  tmp[1]      = "C";  iv  = 0;  tmp[2]=iv;
3327  Lord[3]     = tmp;  tmp = 0;
3328  L[3]        = Lord;
3329  // we are done with the list. Now add a Plural part
3330  def @R2@ = ring(L);
3331  setring @R2@;
3332  matrix @D[Nnew][Nnew];
3333  for (i=1; i<=N; i++)
3334  {
3335    @D[i,N+i]=1;
3336  }
3337  def @R2 = nc_algebra(1,@D);
3338  setring @R2;
3339  kill @R2@;
3340  dbprint(ppl,"//  -2-1- the ring @R2(_x,_Dx,s) is ready");
3341  dbprint(ppl-1, @R2);
3342  ideal MM = maxideal(1);
3343  MM = 0,s,MM;
3344  map R01 = @R, MM;
3345  ideal K = R01(K);
3346  // total cleanup
3347  ideal LD = K;
3348  // make leadcoeffs positive
3349  for (i=1; i<= ncols(LD); i++)
3350  {
3351    if (leadcoef(LD[i]) <0 )
3352    {
3353      LD[i] = -LD[i];
3354    }
3355  }
3356  export LD;
3357  kill @R;
3358  return(@R2);
3359}
3360example
3361{
3362  "EXAMPLE:"; echo = 2;
3363  ring r = 0,(x,y,z),Dp;
3364  poly F = x^3+y^3+z^3;
3365  printlevel = 0;
3366  def A  = SannfsLOT(F);
3367  setring A;
3368  LD;
3369}
3370
3371
3372proc annfsLOT(poly F, list #)
3373"USAGE:  annfsLOT(F [,eng]);  F a poly, eng an optional int
3374RETURN:  ring
3375PURPOSE: compute the D-module structure of basering[1/f]*f^s, according to the Levandovskyy's modification of the algorithm by Oaku and Takayama
3376NOTE:    activate this ring with the @code{setring} command. In this ring,
3377@*       - the ideal LD (which is a Groebner basis) is the needed D-module structure,
3378@*         which is obtained by substituting the minimal integer root of a Bernstein
3379@*         polynomial into the s-parametric ideal;
3380@*       - the list BS contains the roots with multiplicities of a Bernstein polynomial of f.
3381@*       If eng <>0, @code{std} is used for Groebner basis computations,
3382@*       otherwise and by default @code{slimgb} is used.
3383@*       If printlevel=1, progress debug messages will be printed,
3384@*       if printlevel>=2, all the debug messages will be printed.
3385EXAMPLE: example annfsLOT; shows examples
3386"
3387{
3388  int eng = 0;
3389  if ( size(#)>0 )
3390  {
3391    if ( typeof(#[1]) == "int" )
3392    {
3393      eng = int(#[1]);
3394    }
3395  }
3396  printlevel=printlevel+1;
3397  def save = basering;
3398  def @A = SannfsLOT(F,eng);
3399  setring @A;
3400  poly F = imap(save,F);
3401  def B  = annfs0(LD,F,eng);
3402  return(B);
3403}
3404example
3405{
3406  "EXAMPLE:"; echo = 2;
3407  ring r = 0,(x,y,z),Dp;
3408  poly F = z*x^2+y^3;
3409  printlevel = 0;
3410  def A  = annfsLOT(F);
3411  setring A;
3412  LD;
3413  BS;
3414}
3415
3416proc annfs0(ideal I, poly F, list #)
3417"USAGE:  annfs0(I, F [,eng]);  I an ideal, F a poly, eng an optional int
3418RETURN:  ring
3419PURPOSE: compute the annihilator ideal of f^s in the Weyl Algebra, based on the
3420output of procedures SannfsBM, SannfsOT or SannfsLOT
3421NOTE:    activate this ring with the @code{setring} command. In this ring,
3422@*       - the ideal LD (which is a Groebner basis) is the annihilator of f^s,
3423@*       - the list BS contains the roots with multiplicities of a Bernstein polynomial of f.
3424@*       If eng <>0, @code{std} is used for Groebner basis computations,
3425@*       otherwise and by default @code{slimgb} is used.
3426@*       If printlevel=1, progress debug messages will be printed,
3427@*       if printlevel>=2, all the debug messages will be printed.
3428EXAMPLE: example annfs0; shows examples
3429"
3430{
3431  int eng = 0;
3432  if ( size(#)>0 )
3433  {
3434    if ( typeof(#[1]) == "int" )
3435    {
3436      eng = int(#[1]);
3437    }
3438  }
3439  def @R2 = basering;
3440  // we're in D_n[s], where the elim ord for s is set
3441  ideal J = NF(I,std(F));
3442  // make leadcoeffs positive
3443  int i;
3444  for (i=1; i<= ncols(J); i++)
3445  {
3446    if (leadcoef(J[i]) <0 )
3447    {
3448      J[i] = -J[i];
3449    }
3450  }
3451  J = J,F;
3452  ideal M = engine(J,eng);
3453  int Nnew = nvars(@R2);
3454  ideal K2 = nselect(M,1,Nnew-1);
3455  int ppl = printlevel-voice+2;
3456  dbprint(ppl,"// -1-1- _x,_Dx are eliminated in basering");
3457  dbprint(ppl-1, K2);
3458  // the ring @R3 and the search for minimal negative int s
3459  ring @R3 = 0,s,dp;
3460  dbprint(ppl,"// -2-1- the ring @R3 i.e. K[s] is ready");
3461  ideal K3 = imap(@R2,K2);
3462  poly p = K3[1];
3463  dbprint(ppl,"// -2-2- factorization");
3464  //  ideal P = factorize(p,1);  //without constants and multiplicities
3465  //  "--------- b-function factorizes into ---------";   P;
3466  // convert factors to the list of their roots with mults
3467  // assume all factors are linear
3468  //  ideal BS = normalize(P);
3469  //  BS = subst(BS,s,0);
3470  //  BS = -BS;
3471  list P = factorize(p);          //with constants and multiplicities
3472  ideal bs; intvec m;             //the Bernstein polynomial is monic, so we are not interested in constants
3473  for (i=2; i<= size(P[1]); i++)  //we delete P[1][1] and P[2][1]
3474  {
3475    bs[i-1] = P[1][i];
3476    m[i-1]  = P[2][i];
3477  }
3478  int sP = minIntRoot(bs,1);
3479  bs =  normalize(bs);
3480  bs = -subst(bs,s,0);
3481  dbprint(ppl,"// -2-3- minimal integer root found");
3482  dbprint(ppl-1, sP);
3483 //TODO: sort BS!
3484  // --------- substitute s found in the ideal ---------
3485  // --------- going back to @R and substitute ---------
3486  setring @R2;
3487  K2 = subst(I,s,sP);
3488  // create the ordinary Weyl algebra and put the result into it,
3489  // thus creating the ring @R5
3490  // keep: N, i,j,s, tmp, RL
3491  Nnew = Nnew - 1; // former 2*N;
3492  // list RL = ringlist(save);  // is defined earlier
3493  //  kill Lord, tmp, iv;
3494  list L = 0;
3495  list Lord, tmp;
3496  intvec iv;
3497  list RL = ringlist(basering);
3498  L[1] = RL[1];
3499  L[4] = RL[4];  //char, minpoly
3500  // check whether vars have admissible names -> done earlier
3501  // list Name = RL[2]M
3502  // DName is defined earlier
3503  list NName; // = RL[2]; // skip the last var 's'
3504  for (i=1; i<=Nnew; i++)
3505  {
3506    NName[i] =  RL[2][i];
3507  }
3508  L[2] = NName;
3509  // dp ordering;
3510  string s = "iv=";
3511  for (i=1; i<=Nnew; i++)
3512  {
3513    s = s+"1,";
3514  }
3515  s[size(s)] = ";";
3516  execute(s);
3517  tmp     = 0;
3518  tmp[1]  = "dp";  // string
3519  tmp[2]  = iv;  // intvec
3520  Lord[1] = tmp;
3521  kill s;
3522  tmp[1]  = "C";
3523  iv = 0;
3524  tmp[2]  = iv;
3525  Lord[2] = tmp;
3526  tmp     = 0;
3527  L[3]    = Lord;
3528  // we are done with the list
3529  // Add: Plural part
3530  def @R4@ = ring(L);
3531  setring @R4@;
3532  int N = Nnew/2;
3533  matrix @D[Nnew][Nnew];
3534  for (i=1; i<=N; i++)
3535  {
3536    @D[i,N+i]=1;
3537  }
3538  def @R4 = nc_algebra(1,@D);
3539  setring @R4;
3540  kill @R4@;
3541  dbprint(ppl,"// -3-1- the ring @R4 is ready");
3542  dbprint(ppl-1, @R4);
3543  ideal K4 = imap(@R2,K2);
3544  option(redSB);
3545  dbprint(ppl,"// -3-2- the final cosmetic std");
3546  K4 = engine(K4,eng);  // std does the job too
3547  // total cleanup
3548  ideal bs = imap(@R3,bs);
3549  kill @R3;
3550  list BS = bs,m;
3551  export BS;
3552  ideal LD = K4;
3553  export LD;
3554  return(@R4);
3555}
3556example
3557{ "EXAMPLE:"; echo = 2;
3558  ring r = 0,(x,y,z),Dp;
3559  poly F = x^3+y^3+z^3;
3560  printlevel = 0;
3561  def A = SannfsBM(F);
3562  // alternatively, one can use SannfsOT or SannfsLOT
3563  setring A;
3564  LD;
3565  poly F = imap(r,F);
3566  def B  = annfs0(LD,F);
3567  setring B;
3568  LD;
3569  BS;
3570}
3571
3572// proc annfsgms(poly F, list #)
3573// "USAGE:  annfsgms(f [,eng]);  f a poly, eng an optional int
3574// ASSUME:  f has an isolated critical point at 0
3575// RETURN:  ring
3576// PURPOSE: compute the D-module structure of basering[1/f]*f^s
3577// NOTE:    activate this ring with the @code{setring} command. In this ring,
3578// @*       - the ideal LD is the needed D-mod structure,
3579// @*       - the ideal BS is the list of roots of a Bernstein polynomial of f.
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.
3584// EXAMPLE: example annfsgms; shows examples
3585// "
3586// {
3587//   LIB "gmssing.lib";
3588//   int eng = 0;
3589//   if ( size(#)>0 )
3590//   {
3591//     if ( typeof(#[1]) == "int" )
3592//     {
3593//       eng = int(#[1]);
3594//     }
3595//   }
3596//   int ppl = printlevel-voice+2;
3597//   // returns a ring with the ideal LD in it
3598//   def save = basering;
3599//   // compute the Bernstein poly from gmssing.lib
3600//   list RL = ringlist(basering);
3601//   // in the descr. of the ordering, replace "p" by "s"
3602//   list NL = convloc(RL);
3603//   // create a ring with the ordering, converted to local
3604//   def @LR = ring(NL);
3605//   setring @LR;
3606//   poly F  = imap(save, F);
3607//   ideal B = bernstein(F)[1];
3608//   // since B may not contain (s+1) [following gmssing.lib]
3609//   // add it!
3610//   B = B,-1;
3611//   B = simplify(B,2+4); // erase zero and repeated entries
3612//   // find the minimal integer value
3613//   int   S = minIntRoot(B,0);
3614//   dbprint(ppl,"// -0- minimal integer root found");
3615//   dbprint(ppl-1,S);
3616//   setring save;
3617//   int N = nvars(basering);
3618//   int Nnew = 2*(N+2);
3619//   int i,j;
3620//   string s;
3621//   //  list RL = ringlist(basering);
3622//   list L, Lord;
3623//   list tmp;
3624//   intvec iv;
3625//   L[1] = RL[1]; // char
3626//   L[4] = RL[4]; // char, minpoly
3627//   // check whether vars have admissible names
3628//   list Name  = RL[2];
3629//   list RName;
3630//   RName[1] = "u";
3631//   RName[2] = "v";
3632//   RName[3] = "t";
3633//   RName[4] = "Dt";
3634//   for(i=1;i<=N;i++)
3635//   {
3636//     for(j=1; j<=size(RName);j++)
3637//     {
3638//       if (Name[i] == RName[j])
3639//       {
3640//         ERROR("Variable names should not include u,v,t,Dt");
3641//       }
3642//     }
3643//   }
3644//   // now, create the names for new vars
3645//   //  tmp[1]     = "u";  tmp[2]     = "v";  tmp[3]     = "t";  tmp[4]     = "Dt";
3646//   list UName = RName;
3647//   list DName;
3648//   for(i=1;i<=N;i++)
3649//   {
3650//     DName[i] = "D"+Name[i]; // concat
3651//   }
3652//   list NName = UName + Name + DName;
3653//   L[2]       = NName;
3654//   tmp        = 0;
3655//   // Name, Dname will be used further
3656//   kill UName;
3657//   kill NName;
3658//   // block ord (a(1,1),dp);
3659//   tmp[1]  = "a"; // string
3660//   iv      = 1,1;
3661//   tmp[2]  = iv; //intvec
3662//   Lord[1] = tmp;
3663//   // continue with dp 1,1,1,1...
3664//   tmp[1]  = "dp"; // string
3665//   s       = "iv=";
3666//   for(i=1; i<=Nnew; i++) // need really all vars!
3667//   {
3668//     s = s+"1,";
3669//   }
3670//   s[size(s)]= ";";
3671//   execute(s);
3672//   tmp[2]    = iv;
3673//   Lord[2]   = tmp;
3674//   tmp[1]    = "C";
3675//   iv        = 0;
3676//   tmp[2]    = iv;
3677//   Lord[3]   = tmp;
3678//   tmp       = 0;
3679//   L[3]      = Lord;
3680//   // we are done with the list
3681//   def @R = ring(L);
3682//   setring @R;
3683//   matrix @D[Nnew][Nnew];
3684//   @D[3,4] = 1; // t,Dt
3685//   for(i=1; i<=N; i++)
3686//   {
3687//     @D[4+i,4+N+i]=1;
3688//   }
3689//   //  L[5] = matrix(UpOneMatrix(Nnew));
3690//   //  L[6] = @D;
3691//   nc_algebra(1,@D);
3692//   dbprint(ppl,"// -1-1- the ring @R is ready");
3693//   dbprint(ppl-1,@R);
3694//   // create the ideal
3695//   poly F  = imap(save,F);
3696//   ideal I = u*F-t,u*v-1;
3697//   poly p;
3698//   for(i=1; i<=N; i++)
3699//   {
3700//     p = u*Dt; // u*Dt
3701//     p = diff(F,var(4+i))*p;
3702//     I = I, var(N+4+i) + p; // Dx, Dy
3703//   }
3704//   // add the relations between t,Dt and s
3705//   //  I = I, t*Dt+1+S;
3706//   // -------- the ideal I is ready ----------
3707//   dbprint(ppl,"// -1-2- starting the elimination of u,v in @R");
3708//   ideal J = engine(I,eng);
3709//   ideal K = nselect(J,1,2);
3710//   dbprint(ppl,"// -1-3- u,v are eliminated in @R");
3711//   dbprint(ppl-1,K); // without u,v: not yet our answer
3712//   //----- create a ring with elim.ord for t,Dt -------
3713//   setring save;
3714//   // ------------ new ring @R2 ------------------
3715//   // without u,v and with the elim.ord for t,Dt
3716//   // keep: N, i,j,s, tmp, RL
3717//   Nnew = 2*N+2;
3718//   //  list RL = ringlist(save); // is defined earlier
3719//   kill Lord,tmp,iv, RName;
3720//   L = 0;
3721//   list Lord, tmp;
3722//   intvec iv;
3723//   L[1] = RL[1]; // char
3724//   L[4] = RL[4]; // char, minpoly
3725//   // check whether vars have admissible names -> done earlier
3726//   //  list Name  = RL[2];
3727//   list RName;
3728//   RName[1] = "t";
3729//   RName[2] = "Dt";
3730//   // DName is defined earlier
3731//   list NName = RName + Name + DName;
3732//   L[2]   = NName;
3733//   tmp    = 0;
3734//   // block ord (a(1,1),dp);
3735//   tmp[1]  = "a"; // string
3736//   iv      = 1,1;
3737//   tmp[2]  = iv; //intvec
3738//   Lord[1] = tmp;
3739//   // continue with dp 1,1,1,1...
3740//   tmp[1]  = "dp"; // string
3741//   s       = "iv=";
3742//   for(i=1;i<=Nnew;i++)
3743//   {
3744//     s = s+"1,";
3745//   }
3746//   s[size(s)]= ";";
3747//   execute(s);
3748//   kill s;
3749//   kill NName;
3750//   tmp[2]    = iv;
3751//   Lord[2]   = tmp;
3752//   tmp[1]    = "C";
3753//   iv        = 0;
3754//   tmp[2]    = iv;
3755//   Lord[3]   = tmp;
3756//   tmp       = 0;
3757//   L[3]      = Lord;
3758//   // we are done with the list
3759//   // Add: Plural part
3760//   def @R2 = ring(L);
3761//   setring @R2;
3762//   matrix @D[Nnew][Nnew];
3763//   @D[1,2]=1;
3764//   for(i=1; i<=N; i++)
3765//   {
3766//     @D[2+i,2+N+i]=1;
3767//   }
3768//   nc_algebra(1,@D);
3769//   dbprint(ppl,"// -2-1- the ring @R2 is ready");
3770//   dbprint(ppl-1,@R2);
3771//   ideal MM = maxideal(1);
3772//   MM = 0,0,MM;
3773//   map R01 = @R, MM;
3774//   ideal K2 = R01(K);
3775//   // add the relations between t,Dt and s
3776//   //  K2       = K2, t*Dt+1+S;
3777//   poly G = t*Dt+S+1;
3778//   K2 = NF(K2,std(G)),G;
3779//   dbprint(ppl,"// -2-2- starting elimination for t,Dt in @R2");
3780//   ideal J  = engine(K2,eng);
3781//   ideal K  = nselect(J,1,2);
3782//   dbprint(ppl,"// -2-3- t,Dt are eliminated");
3783//   dbprint(ppl-1,K);
3784//   //  "------- produce a final result --------";
3785//   // ----- create the ordinary Weyl algebra and put
3786//   // ----- the result into it
3787//   // ------ create the ring @R5
3788//   // keep: N, i,j,s, tmp, RL
3789//   setring save;
3790//   Nnew = 2*N;
3791//   //  list RL = ringlist(save); // is defined earlier
3792//   kill Lord, tmp, iv;
3793//   //  kill L;
3794//   L = 0;
3795//   list Lord, tmp;
3796//   intvec iv;
3797//   L[1] = RL[1]; // char
3798//   L[4] = RL[4]; // char, minpoly
3799//   // check whether vars have admissible names -> done earlier
3800//   //  list Name  = RL[2];
3801//   // DName is defined earlier
3802//   list NName = Name + DName;
3803//   L[2]   = NName;
3804//   // dp ordering;
3805//   string   s       = "iv=";
3806//   for(i=1;i<=2*N;i++)
3807//   {
3808//     s = s+"1,";
3809//   }
3810//   s[size(s)]= ";";
3811//   execute(s);
3812//   tmp     = 0;
3813//   tmp[1]  = "dp"; // string
3814//   tmp[2]  = iv; //intvec
3815//   Lord[1] = tmp;
3816//   kill s;
3817//   tmp[1]    = "C";
3818//   iv        = 0;
3819//   tmp[2]    = iv;
3820//   Lord[2]   = tmp;
3821//   tmp       = 0;
3822//   L[3]      = Lord;
3823//   // we are done with the list
3824//   // Add: Plural part
3825//   def @R5 = ring(L);
3826//   setring @R5;
3827//   matrix @D[Nnew][Nnew];
3828//   for(i=1; i<=N; i++)
3829//   {
3830//     @D[i,N+i]=1;
3831//   }
3832//   nc_algebra(1,@D);
3833//   dbprint(ppl,"// -3-1- the ring @R5 is ready");
3834//   dbprint(ppl-1,@R5);
3835//   ideal K5 = imap(@R2,K);
3836//   option(redSB);
3837//   dbprint(ppl,"// -3-2- the final cosmetic std");
3838//   K5 = engine(K5,eng); // std does the job too
3839//   // total cleanup
3840//   kill @R;
3841//   kill @R2;
3842//   ideal LD = K5;
3843//   ideal BS = imap(@LR,B);
3844//   kill @LR;
3845//   export BS;
3846//   export LD;
3847//   return(@R5);
3848// }
3849// example
3850// {
3851//   "EXAMPLE:"; echo = 2;
3852//   ring r = 0,(x,y,z),Dp;
3853//   poly F = x^2+y^3+z^5;
3854//   def A = annfsgms(F);
3855//   setring A;
3856//   LD;
3857//   print(matrix(BS));
3858// }
3859
3860
3861proc convloc(list @NL)
3862"USAGE:  convloc(L); L a list
3863RETURN:  list
3864PURPOSE: convert a ringlist L into another ringlist,
3865where all the 'p' orderings are replaced with the 's' orderings.
3866ASSUME: L is a result of a ringlist command
3867EXAMPLE: example convloc; shows examples
3868"
3869{
3870  list NL = @NL;
3871  // given a ringlist, returns a new ringlist,
3872  // where all the p-orderings are replaced with s-ord's
3873  int i,j,k,found;
3874  int nblocks = size(NL[3]);
3875  for(i=1; i<=nblocks; i++)
3876  {
3877    for(j=1; j<=size(NL[3][i]); j++)
3878    {
3879      if (typeof(NL[3][i][j]) == "string" )
3880      {
3881        found = 0;
3882        for (k=1; k<=size(NL[3][i][j]); k++)
3883        {
3884          if (NL[3][i][j][k]=="p")
3885          {
3886            NL[3][i][j][k]="s";
3887            found = 1;
3888            //    printf("replaced at %s,%s,%s",i,j,k);
3889          }
3890        }
3891      }
3892    }
3893  }
3894  return(NL);
3895}
3896example
3897{
3898  "EXAMPLE:"; echo = 2;
3899  ring r = 0,(x,y,z),(Dp(2),dp(1));
3900  list L = ringlist(r);
3901  list N = convloc(L);
3902  def rs = ring(N);
3903  setring rs;
3904  rs;
3905}
3906
3907proc annfspecial(ideal I, poly F, int mir, number n)
3908"USAGE:  annfspecial(I,F,mir,n);  I an ideal, F a poly, int mir, number n
3909RETURN:  ideal
3910PURPOSE: compute the annihilator ideal of F^n in the Weyl Algebra for a rational number n
3911ASSUME:  the basering contains 's' as a variable
3912NOTE:    We assume that the basering is D[s],
3913@*          ideal I is the Ann F^s in D[s] (obtained with e.g. SannfsBM, SannfsLOT, SannfsOT)
3914@*          integer 'mir' is the minimal integer root of the Bernstein polynomial of F
3915@*          and the number n is rational.
3916@*       We compute the real annihilator for any rational value of n (both generic and exceptional).
3917@*       The implementation goes along the lines of Saito-Sturmfels-Takayama, Alg. 5.3.15
3918@*       If printlevel=1, progress debug messages will be printed,
3919@*       if printlevel>=2, all the debug messages will be printed.
3920EXAMPLE: example annfspecial; shows examples
3921"
3922{
3923  int ppl = printlevel-voice+2;
3924  //  int mir =  minIntRoot(L[1],0);
3925  int ns   = varnum("s");
3926  if (!ns)
3927  {
3928    ERROR("Variable s expected in the ideal AnnFs");
3929  }
3930  int d;
3931  ideal P = subst(I,var(ns),n);
3932  if (denominator(n) == 1)
3933  {
3934    // n is fraction-free
3935    d = int(numerator(n));
3936    if ( (!d) && (n!=0))
3937    {
3938      ERROR("no parametric special values are allowed");
3939    }
3940    d = d - mir;
3941    if (d>0)
3942    {
3943      dbprint(ppl,"// -1-1- starting syzygy computations");
3944      matrix J[1][1] = F^d;
3945      dbprint(ppl-1,"// -1-1-1- of the polynomial ideal");
3946      dbprint(ppl-1,J);
3947      matrix K[1][size(I)] = subst(I,var(ns),mir);
3948      dbprint(ppl-1,"// -1-1-2- modulo ideal:");
3949      dbprint(ppl-1, K);
3950      module M = modulo(J,K);
3951      dbprint(ppl-1,"// -1-1-3- getting the result:");
3952      dbprint(ppl-1, M);
3953      P  = P, ideal(M);
3954      dbprint(ppl,"// -1-2- finished syzygy computations");
3955    }
3956    else
3957    {
3958      dbprint(ppl,"// -1-1- d<=0, no syzygy computations needed");
3959      dbprint(ppl-1,"// -1-2- for d =");
3960      dbprint(ppl-1, d);
3961    }
3962  }
3963  // also the else case: d<=0 or n is not an integer
3964  dbprint(ppl,"// -2-1- starting final Groebner basis");
3965  P = groebner(P);
3966  dbprint(ppl,"// -2-2- finished final Groebner basis");
3967  return(P);
3968}
3969example
3970{
3971  "EXAMPLE:"; echo = 2;
3972  ring r = 0,(x,y),dp;
3973  poly F = x3-y2;
3974  def  B = annfs(F);  setring B;
3975  minIntRoot(BS[1],0);
3976  // So, the minimal integer root is -1
3977  setring r;
3978  def  A = SannfsBM(F);
3979  setring A;
3980  poly F = x3-y2;
3981  annfspecial(LD,F,-1,3/4); // generic root
3982  annfspecial(LD,F,-1,-2);  // integer but still generic root
3983  annfspecial(LD,F,-1,1);   // exceptional root
3984}
3985
3986static proc new_ex_annfspecial()
3987{
3988  //another example for annfspecial: x3+y3+z3
3989  ring r = 0,(x,y,z),dp;
3990  poly F =  x3+y3+z3;
3991  def  B = annfs(F);  setring B;
3992  minIntRoot(BS[1],0);
3993  // So, the minimal integer root is -1
3994  setring r;
3995  def  A = SannfsBM(F);
3996  setring A;
3997  poly F =  x3+y3+z3;
3998  annfspecial(LD,F,-1,3/4); // generic root
3999  annfspecial(LD,F,-1,-2);  // integer but still generic root
4000  annfspecial(LD,F,-1,1);   // exceptional root
4001}
4002
4003proc minIntRoot(ideal P, int fact)
4004"USAGE:  minIntRoot(P, fact); P an ideal, fact an int
4005RETURN:  int
4006PURPOSE: minimal integer root of a maximal ideal P
4007NOTE:    if fact==1, P is the result of some 'factorize' call,
4008@*       else P is treated as the result of bernstein::gmssing.lib
4009@*       in both cases without constants and multiplicities
4010EXAMPLE: example minIntRoot; shows examples
4011"
4012{
4013  //    ideal P = factorize(p,1);
4014  // or ideal P = bernstein(F)[1];
4015  intvec vP;
4016  number nP;
4017  int i;
4018  if ( fact )
4019  {
4020    // the result comes from "factorize"
4021    P = normalize(P); // now leadcoef = 1
4022    // TODO: hunt for units and kill then !!!
4023    P = lead(P)-P;
4024    // nP = leadcoef(P[i]-lead(P[i])); // for 1 var only, extract the coeff
4025  }
4026  else
4027  {
4028    // bernstein deletes -1 usually
4029    P = P, -1;
4030  }
4031  // for both situations:
4032  // now we have an ideal of fractions of type "number"
4033  int sP = size(P);
4034  for(i=1; i<=sP; i++)
4035  {
4036    nP = leadcoef(P[i]);
4037    if ( (nP - int(nP)) == 0 )
4038    {
4039      vP = vP,int(nP);
4040    }
4041  }
4042  if ( size(vP)>=2 )
4043  {
4044    vP = vP[2..size(vP)];
4045  }
4046  sP = -Max(-vP);
4047  if (sP == 0)
4048  {
4049    "Warning: zero root!";
4050  }
4051  return(sP);
4052}
4053example
4054{
4055  "EXAMPLE:"; echo = 2;
4056  ring r   = 0,(x,y),ds;
4057  poly f1  = x*y*(x+y);
4058  ideal I1 = bernstein(f1)[1]; // a local Bernstein poly
4059  minIntRoot(I1,0);
4060  poly  f2  = x2-y3;
4061  ideal I2  = bernstein(f2)[1];
4062  minIntRoot(I2,0);
4063  // now we illustrate the behaviour of factorize
4064  // together with a global ordering
4065  ring r2  = 0,x,dp;
4066  poly f3   = 9*(x+2/3)*(x+1)*(x+4/3); //global b-poly of f1=x*y*(x+y)
4067  ideal I3 = factorize(f3,1);
4068  minIntRoot(I3,1);
4069  // and a more interesting situation
4070  ring  s  = 0,(x,y,z),ds;
4071  poly  f  = x3 + y3 + z3;
4072  ideal I  = bernstein(f)[1];
4073  minIntRoot(I,0);
4074}
4075
4076proc isHolonomic(def M)
4077"USAGE:  isHolonomic(M); M an ideal/module/matrix
4078RETURN:  int, 1 if M is holonomic and 0 otherwise
4079PURPOSE: check the modules for the property of holonomy
4080NOTE:    M is holonomic, if 2*dim(M) = dim(R), where R is a
4081ground ring; dim stays for Gelfand-Kirillov dimension
4082EXAMPLE: example isHolonomic; shows examples
4083"
4084{
4085  if ( (typeof(M) != "ideal") && (typeof(M) != "module") && (typeof(M) != "matrix") )
4086  {
4087  //  print(typeof(M));
4088    ERROR("an argument of type ideal/module/matrix expected");
4089  }
4090  if (attrib(M,"isSB")!=1)
4091  {
4092    M = std(M);
4093  }
4094  int dimR = gkdim(std(0));
4095  int dimM = gkdim(M);
4096  return( (dimR==2*dimM) );
4097}
4098example
4099{
4100  "EXAMPLE:"; echo = 2;
4101  ring R = 0,(x,y),dp;
4102  poly F = x*y*(x+y);
4103  def A = annfsBM(F,0);
4104  setring A;
4105  LD;
4106  isHolonomic(LD);
4107  ideal I = std(LD[1]);
4108  I;
4109  isHolonomic(I);
4110}
4111
4112proc reiffen(int p, int q)
4113"USAGE:  reiffen(p, q);  int p, int q
4114RETURN:  ring
4115PURPOSE: set up the polynomial, describing a Reiffen curve
4116NOTE:    activate this ring with the @code{setring} command and find the
4117         curve as a polynomial RC
4118@*   a Reiffen curve is defined as F = x^p + y^q + xy^{q-1}, q >= p+1 >= 5
4119ASSUME: q >= p+1 >= 5. Otherwise an error message is returned
4120EXAMPLE: example reiffen; shows examples
4121"
4122{
4123// a Reiffen curve is defined as
4124// F = x^p + y^q +x*y^{q-1}, q \geq p+1 \geq 5
4125
4126  if ( (p<4) || (q<5) || (q-p<1) )
4127  {
4128    ERROR("Some of conditions p>=4, q>=5 or q>=p+1 is not satisfied!");
4129  }
4130  ring @r = 0,(x,y),dp;
4131  poly RC = y^q +x^p + x*y^(q-1);
4132  export RC;
4133  return(@r);
4134}
4135example
4136{
4137  "EXAMPLE:"; echo = 2;
4138  def r = reiffen(4,5);
4139  setring r;
4140  RC;
4141}
4142
4143proc arrange(int p)
4144"USAGE:  arrange(p);  int p
4145RETURN:  ring
4146PURPOSE: set up the polynomial, describing a hyperplane arrangement
4147NOTE:   must be executed in a ring
4148ASSUME: basering is present
4149EXAMPLE: example arrange; shows examples
4150"
4151{
4152  int UseBasering = 0 ;
4153  if (p<2)
4154  {
4155    ERROR("p>=2 is required!");
4156  }
4157  if ( nameof(basering)!="basering" )
4158  {
4159    if (p > nvars(basering))
4160    {
4161      ERROR("too big p");
4162    }
4163    else
4164    {
4165      def @r = basering;
4166      UseBasering = 1;
4167    }
4168  }
4169  else
4170  {
4171    // no basering found
4172    ERROR("no basering found!");
4173    //    ring @r = 0,(x(1..p)),dp;
4174  }
4175  int i,j,sI;
4176  poly  q = 1;
4177  list ar;
4178  ideal tmp;
4179  tmp = ideal(var(1));
4180  ar[1] = tmp;
4181  for (i = 2; i<=p; i++)
4182  {
4183    // add i-nary sums to the product
4184    ar = indAR(ar,i);
4185  }
4186  for (i = 1; i<=p; i++)
4187  {
4188    tmp = ar[i]; sI = size(tmp);
4189    for (j = 1; j<=sI; j++)
4190    {
4191      q = q*tmp[j];
4192    }
4193  }
4194  if (UseBasering)
4195  {
4196    return(q);
4197  }
4198  //  poly AR = q; export AR;
4199  //  return(@r);
4200}
4201example
4202{
4203  "EXAMPLE:"; echo = 2;
4204  ring X = 0,(x,y,z,t),dp;
4205  poly q = arrange(3);
4206  factorize(q,1);
4207}
4208
4209proc checkRoot(poly F, number a, list #)
4210"USAGE:  checkRoot(f,alpha [,S,eng]);  f a poly, alpha a number, S a string , eng an optional int
4211RETURN:  int
4212PURPOSE: check whether a rational is a root of the global Bernstein polynomial of f (and compute its multiplicity)
4213with the algorithm given in S and with the Groebner basis engine given in eng
4214NOTE:    The annihilator of f^s in D[s] is needed and it is computed according to the algorithm by Briancon and Maisonobe
4215@*       The value of a string S can be
4216@*       'alg1' (default) - for the algorithm 1 of J. Martin-Morales (unpublished)
4217@*       'alg2' - for the algorithm 2 of J. Martin-Morales (unpublished)
4218@*       The output int is:
4219@*       - if the algorithm 1 is chosen: 1 if -alpha is a root of the global Bernstein polynomial and 0 otherwise
4220@*       - if the algorithm 2 is chosen: the multiplicity of -alpha as a root of the global Bernstein polynomial of f.
4221@*                                       (If -alpha is not a root, the output is 0)
4222@*       If eng <>0, @code{std} is used for Groebner basis computations,
4223@*       otherwise (and by default) @code{slimgb} is used.
4224@*       If printlevel=1, progress debug messages will be printed,
4225@*       if printlevel>=2, all the debug messages will be printed.
4226EXAMPLE: example checkRoot; shows examples
4227"
4228{
4229  int eng = 0;
4230  int chs = 0; // choice
4231  string algo = "alg1";
4232  string st;
4233  if ( size(#)>0 )
4234  {
4235   if ( typeof(#[1]) == "string" )
4236   {
4237     st = string(#[1]);
4238     if ( (st == "alg1") || (st == "ALG1") || (st == "Alg1") ||(st == "aLG1"))
4239     {
4240       algo = "alg1";
4241       chs  = 1;
4242     }
4243     if ( (st == "alg2") || (st == "ALG2") || (st == "Alg2") || (st == "aLG2"))
4244     {
4245       algo = "alg2";
4246       chs  = 1;
4247     }
4248     if (chs != 1)
4249     {
4250       // incorrect value of S
4251       print("Incorrect algorithm given, proceed with the default alg1 of J. Martín-Morales");
4252       algo = "alg1";
4253     }
4254     // second arg
4255     if (size(#)>1)
4256     {
4257       // exists 2nd arg
4258       if ( typeof(#[2]) == "int" )
4259       {
4260         // the case: given alg, given engine
4261         eng = int(#[2]);
4262       }
4263       else
4264       {
4265         eng = 0;
4266       }
4267     }
4268     else
4269     {
4270       // no second arg
4271       eng = 0;
4272     }
4273   }
4274   else
4275   {
4276     if ( typeof(#[1]) == "int" )
4277     {
4278       // the case: default alg, engine
4279       eng = int(#[1]);
4280       // algo = "alg1";  //is already set
4281     }
4282     else
4283     {
4284       // incorr. 1st arg
4285       algo = "alg1";
4286     }
4287   }
4288  }
4289  // size(#)=0, i.e. there is no algorithm and no engine given
4290  //  eng = 0; algo = "alg1";  //are already set
4291  // int ppl = printlevel-voice+2;
4292  printlevel=printlevel+1;
4293  def save = basering;
4294  def @A = SannfsBM(F);
4295  setring @A;
4296  poly F = imap(save,F);
4297  number a = imap(save,a);
4298  if ( algo=="alg1")
4299  {
4300    int output = checkRoot1(LD,F,a,eng);
4301  }
4302  else
4303  {
4304    if ( algo=="alg2")
4305    {
4306      int output = checkRoot2(LD,F,a,eng);
4307    }
4308  }
4309  printlevel=printlevel-1;
4310  return(output);
4311}
4312example
4313{
4314  "EXAMPLE:"; echo = 2;
4315  printlevel=0;
4316  ring r = 0,(x,y),Dp;
4317  poly F = x^4+y^5+x*y^4;
4318  checkRoot(F,11/20);    // -11/20 is a root of bf
4319  poly G = x*y;
4320  checkRoot(G,1,"alg2"); // -1 is a root of bg with multiplicity 2
4321}
4322
4323proc checkRoot1(ideal I, poly F, number a, list #)
4324"USAGE:  checkRoot1(I,f,alpha [,eng]);  I an ideal, f a poly, alpha a number, eng an optional int
4325ASSUME:  I is the annihilator of f^s in D[s], f is a polynomial in K[_x]
4326RETURN:  int, 1 if -alpha is a root of the global Bernstein polynomial of f and 0 otherwise
4327PURPOSE: check whether a rational is a root of the global Bernstein polynomial of f
4328NOTE:    If eng <>0, @code{std} is used for Groebner basis computations,
4329@*       otherwise (and by default) @code{slimgb} is used.
4330@*       If printlevel=1, progress debug messages will be printed,
4331@*       if printlevel>=2, all the debug messages will be printed.
4332EXAMPLE: example checkRoot1; shows examples
4333"
4334{
4335  int eng = 0;
4336  if ( size(#)>0 )
4337  {
4338    if ( typeof(#[1]) == "int" )
4339    {
4340      eng = int(#[1]);
4341    }
4342  }
4343  int ppl = printlevel-voice+2;
4344  dbprint(ppl,"// -0-1- starting the procedure checkRoot1");
4345  def save = basering;
4346  int N = nvars(basering);
4347  int Nnew = N-1;
4348  int n = Nnew / 2;
4349  int i;
4350  string s;
4351  list RL = ringlist(basering);
4352  list L, Lord;
4353  list tmp;
4354  intvec iv;
4355  L[1] = RL[1];  // char
4356  L[4] = RL[4];  // char, minpoly
4357  // check whether basering is D[s]=K(_x,_Dx,s)
4358  list Name = RL[2];
4359  for (i=1; i<=n; i++)
4360  {
4361    if ( bracket(var(i+n),var(i))!=1 )
4362    {
4363      ERROR("basering should be D[s]=K(_x,_Dx,s)");
4364    }
4365  }
4366  if ( Name[N]!="s" )
4367  {
4368    ERROR("the last variable of basering should be s");
4369  }
4370  // now, create the new vars
4371  list NName;
4372  for (i=1; i<=Nnew; i++)
4373  {
4374    NName[i] = Name[i];
4375  }
4376  L[2] = NName;
4377  kill Name,NName;
4378  // block ord (dp);
4379  tmp[1] = "dp"; // string
4380  s = "iv=";
4381  for (i=1; i<=Nnew; i++)
4382  {
4383    s = s+"1,";
4384  }
4385  s[size(s)]=";";
4386  execute(s);
4387  kill s;
4388  tmp[2]  = iv;
4389  Lord[1] = tmp;
4390  tmp[1]  = "C";
4391  iv      = 0;
4392  tmp[2]  = iv;
4393  Lord[2] = tmp;
4394  tmp     = 0;
4395  L[3]    = Lord;
4396  // we are done with the list
4397  def @R@ = ring(L);
4398  setring @R@;
4399  matrix @D[Nnew][Nnew];
4400  for (i=1; i<=n; i++)
4401  {
4402    @D[i,i+n]=1;
4403  }
4404  def @R = nc_algebra(1,@D);
4405  setring @R;
4406  kill @R@;
4407  dbprint(ppl,"// -1-1- the ring @R(_x,_Dx) is ready");
4408  dbprint(ppl-1, S);
4409  // create the ideal K = ann_D[s](f^s)_{s=-alpha} + < f >
4410  setring save;
4411  ideal K = subst(I,s,-a);
4412  dbprint(ppl,"// -1-2- the variable s has been substituted by "+string(-a));
4413  dbprint(ppl-1, K);
4414  K = NF(K,std(F));
4415  // make leadcoeffs positive
4416  for (i=1; i<=ncols(K); i++)
4417  {
4418    if ( leadcoef(K[i])<0 )
4419    {
4420      K[i] = -K[i];
4421    }
4422  }
4423  K = K,F;
4424  // ------------ the ideal K is ready ------------
4425  setring @R;
4426  ideal K = imap(save,K);
4427  dbprint(ppl,"// -1-3- starting the computation of a Groebner basis of K in @R");
4428  dbprint(ppl-1, K);
4429  ideal G = engine(K,eng);
4430  dbprint(ppl,"// -1-4- the Groebner basis has been computed");
4431  dbprint(ppl-1, G);
4432  return(G[1]!=1);
4433}
4434example
4435{
4436  "EXAMPLE:"; echo = 2;
4437  ring r = 0,(x,y),Dp;
4438  poly F = x^4+y^5+x*y^4;
4439  printlevel = 0;
4440  def A = Sannfs(F);
4441  setring A;
4442  poly F = imap(r,F);
4443  checkRoot1(LD,F,31/20);   // -31/20 is not a root of bs
4444  checkRoot1(LD,F,11/20);   // -11/20 is a root of bs
4445}
4446
4447proc checkRoot2 (ideal I, poly F, number a, list #)
4448"USAGE:  checkRoot2(I,f,alpha [,eng]);  I an ideal, f a poly, alpha a number, eng an optional int
4449ASSUME:  I is the annihilator of f^s in D[s], f is a polynomial in K[_x]
4450RETURN:  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
4451PURPOSE: 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]
4452NOTE:    If eng <>0, @code{std} is used for Groebner basis computations,
4453@*       otherwise (and by default) @code{slimgb} is used.
4454@*       If printlevel=1, progress debug messages will be printed,
4455@*       if printlevel>=2, all the debug messages will be printed.
4456EXAMPLE: example checkRoot2; shows examples
4457"
4458{
4459  int eng = 0;
4460  if ( size(#)>0 )
4461  {
4462    if ( typeof(#[1]) == "int" )
4463    {
4464      eng = int(#[1]);
4465    }
4466  }
4467  int ppl = printlevel-voice+2;
4468  dbprint(ppl,"// -0-1- starting the procedure checkRoot2");
4469  def save = basering;
4470  int N = nvars(basering);
4471  int n = (N-1) / 2;
4472  int i;
4473  string s;
4474  list RL = ringlist(basering);
4475  list L, Lord;
4476  list tmp;
4477  intvec iv;
4478  L[1] = RL[1];  // char
4479  L[4] = RL[4];  // char, minpoly
4480  // check whether basering is D[s]=K(_x,_Dx,s)
4481  list Name = RL[2];
4482  for (i=1; i<=n; i++)
4483  {
4484    if ( bracket(var(i+n),var(i))!=1 )
4485    {
4486      ERROR("basering should be D[s]=K(_x,_Dx,s)");
4487    }
4488  }
4489  if ( Name[N]!="s" )
4490  {
4491    ERROR("the last variable of basering should be s");
4492  }
4493  // now, create the new vars
4494  L[2] = Name;
4495  kill Name;
4496  // block ord (dp);
4497  tmp[1] = "dp"; // string
4498  s = "iv=";
4499  for (i=1; i<=N; i++)
4500  {
4501    s = s+"1,";
4502  }
4503  s[size(s)]=";";
4504  execute(s);
4505  kill s;
4506  tmp[2]  = iv;
4507  Lord[1] = tmp;
4508  tmp[1]  = "C";
4509  iv      = 0;
4510  tmp[2]  = iv;
4511  Lord[2] = tmp;
4512  tmp     = 0;
4513  L[3]    = Lord;
4514  // we are done with the list
4515  def @R@ = ring(L);
4516  setring @R@;
4517  matrix @D[N][N];
4518  for (i=1; i<=n; i++)
4519  {
4520    @D[i,i+n]=1;
4521  }
4522  def @R = nc_algebra(1,@D);
4523  setring @R;
4524  kill @R@;
4525  dbprint(ppl,"// -1-1- the ring @R(_x,_Dx,s) is ready");
4526  dbprint(ppl-1, @R);
4527  // now, continue with the algorithm
4528  ideal I = imap(save,I);
4529  poly F = imap(save,F);
4530  number a = imap(save,a);
4531  ideal II = NF(I,std(F));
4532  // make leadcoeffs positive
4533  for (i=1; i<=ncols(II); i++)
4534  {
4535    if ( leadcoef(II[i])<0 )
4536    {
4537      II[i] = -II[i];
4538    }
4539  }
4540  ideal J,G;
4541  int m;  // the output (multiplicity)
4542  dbprint(ppl,"// -2- starting the bucle");
4543  for (i=0; i<=n; i++)  // the multiplicity has to be <= n
4544  {
4545    // create the ideal Ji = ann_D[s](f^s) + < f, (s+alpha)^{i+1} >
4546    // (s+alpha)^i in Ji <==> -alpha is a root with multiplicity >= i
4547    J = II,F,(s+a)^(i+1);
4548    // ------------ the ideal Ji is ready -----------
4549    dbprint(ppl,"// -2-"+string(i+1)+"-1- starting the computation of a Groebner basis of J"+string(i)+" in @R");
4550    dbprint(ppl-1, J);
4551    G = engine(J,eng);
4552    dbprint(ppl,"// -2-"+string(i+1)+"-2- the Groebner basis has been computed");
4553    dbprint(ppl-1, G);
4554    if ( NF((s+a)^i,G)==0 )
4555    {
4556      dbprint(ppl,"// -2-"+string(i+1)+"-3- the number "+string(-a)+" has not multiplicity "+string(i+1));
4557      m = i;
4558      break;
4559    }
4560    dbprint(ppl,"// -2-"+string(i+1)+"-3- the number "+string(-a)+" has multiplicity at least "+string(i+1));
4561  }
4562  dbprint(ppl,"// -3- the bucle has finished");
4563  return(m);
4564}
4565example
4566{
4567  "EXAMPLE:"; echo = 2;
4568  ring r = 0,(x,y,z),Dp;
4569  poly F = x*y*z;
4570  printlevel = 0;
4571  def A = Sannfs(F);
4572  setring A;
4573  poly F = imap(r,F);
4574  checkRoot2(LD,F,1);    // -1 is a root of bs with multiplicity 3
4575  checkRoot2(LD,F,1/3);  // -1/3 is not a root
4576}
4577
4578proc checkFactor(ideal I, poly F, poly q, list #)
4579"USAGE:  checkFactor(I,f,qs [,eng]);  I an ideal, f a poly, qs a poly, eng an optional int
4580ASSUME:  I is the output of Sannfs, SannfsBM, SannfsLOT or SannfsOT,
4581         f is a polynomial in K[_x], qs is a polynomial in K[s]
4582RETURN:  int, 1 if qs is a factor of the global Bernstein polynomial of f and 0 otherwise
4583PURPOSE: 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]
4584NOTE:    If eng <>0, @code{std} is used for Groebner basis computations,
4585@*       otherwise (and by default) @code{slimgb} is used.
4586@*       If printlevel=1, progress debug messages will be printed,
4587@*       if printlevel>=2, all the debug messages will be printed.
4588EXAMPLE: example checkFactor; shows examples
4589"
4590{
4591  int eng = 0;
4592  if ( size(#)>0 )
4593  {
4594    if ( typeof(#[1]) == "int" )
4595    {
4596      eng = int(#[1]);
4597    }
4598  }
4599  int ppl = printlevel-voice+2;
4600  def @R2 = basering;
4601  int N = nvars(@R2);
4602  int i;
4603  // we're in D_n[s], where the elim ord for s is set
4604  dbprint(ppl,"// -0-1- starting the procedure checkFactor");
4605  dbprint(ppl,"// -1-1- the ring @R2(_x,_Dx,s) is ready");
4606  dbprint(ppl-1, @R2);
4607  // create the ideal J = ann_D[s](f^s) + < f,q >
4608  ideal J = NF(I,std(F));
4609  // make leadcoeffs positive
4610  for (i=1; i<=ncols(J); i++)
4611  {
4612    if ( leadcoef(J[i])<0 )
4613    {
4614      J[i] = -J[i];
4615    }
4616  }
4617  J = J,F,q;
4618  // ------------ the ideal J is ready -----------
4619  dbprint(ppl,"// -1-2- starting the elimination of _x,_Dx in @R2");
4620  dbprint(ppl-1, J);
4621  ideal G = engine(J,eng);
4622  ideal K = nselect(G,1,N-1);
4623  kill J,G;
4624  dbprint(ppl,"// -1-3- _x,_Dx are eliminated");
4625  dbprint(ppl-1, K);
4626  //q is a factor of bs iff K = < q >
4627  //K = normalize(K);
4628  //q = normalize(q);
4629  //return( (K[1]==q) );
4630  return( NF(K[1],std(q))==0 );
4631}
4632example
4633{
4634  "EXAMPLE:"; echo = 2;
4635  ring r = 0,(x,y),Dp;
4636  poly F = x^4+y^5+x*y^4;
4637  printlevel = 0;
4638  def A = Sannfs(F);
4639  setring A;
4640  poly F = imap(r,F);
4641  checkFactor(LD,F,20*s+31);     // -31/20 is not a root of bs
4642  checkFactor(LD,F,20*s+11);     // -11/20 is a root of bs
4643  checkFactor(LD,F,(20*s+11)^2); // the multiplicity of -11/20 is 1
4644}
4645
4646proc varnum(string s)
4647"USAGE:  varnum(s);  string s
4648RETURN:  int
4649PURPOSE: returns the number of the variable with the name s
4650among the variables of basering or 0 if there is no such variable
4651EXAMPLE: example varnum; shows examples
4652"
4653{
4654  int i;
4655  for (i=1; i<= nvars(basering); i++)
4656  {
4657    if ( string(var(i)) == s )
4658    {
4659      return(i);
4660    }
4661  }
4662  return(0);
4663}
4664example
4665{
4666  "EXAMPLE:"; echo = 2;
4667  ring X = 0,(x,y1,z(0),tTa),dp;
4668  varnum("z(0)");
4669  varnum("tTa");
4670  varnum("xyz");
4671}
4672
4673static proc indAR(list L, int n)
4674"USAGE:  indAR(L,n);  list L, int n
4675RETURN:  list
4676PURPOSE: computes arrangement inductively, using L and var(n) as the
4677next variable
4678ASSUME: L has a structure of an arrangement
4679EXAMPLE: example indAR; shows examples
4680"
4681{
4682  if ( (n<2) || (n>nvars(basering)) )
4683  {
4684    ERROR("incorrect n");
4685  }
4686  int sl = size(L);
4687  list K;
4688  ideal tmp;
4689  poly @t = L[sl][1] + var(n); //1 elt
4690  K[sl+1] = ideal(@t);
4691  tmp = L[1]+var(n);
4692  K[1] = tmp; tmp = 0;
4693  int i,j,sI;
4694  ideal I;
4695  for(i=sl; i>=2; i--)
4696  {
4697    I = L[i-1]; sI = size(I);
4698    for(j=1; j<=sI; j++)
4699    {
4700      I[j] = I[j] + var(n);
4701    }
4702    tmp  = L[i],I;
4703    K[i] = tmp;
4704    I = 0; tmp = 0;
4705  }
4706  kill I; kill tmp;
4707  return(K);
4708}
4709example
4710{
4711  "EXAMPLE:"; echo = 2;
4712  ring r = 0,(x,y,z,t,v),dp;
4713  list L;
4714  L[1] = ideal(x);
4715  list K = indAR(L,2);
4716  K;
4717  list M = indAR(K,3);
4718  M;
4719  M = indAR(M,4);
4720  M;
4721}
4722
4723static proc exCheckGenericity()
4724{
4725  LIB "control.lib";
4726  ring r = (0,a,b,c),x,dp;
4727  poly p = (x-a)*(x-b)*(x-c);
4728  def A = annfsBM(p);
4729  setring A;
4730  ideal J = slimgb(LD);
4731  matrix T = lift(LD,J);
4732  T = normalize(T);
4733  genericity(T);
4734  // 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)
4735  // genericity: g = a2-ab-ac+b2-bc+c2 =0
4736  // g = (a -(b+c)/2)^2 + (3/4)*(b-c)^2;
4737  // g ==0 <=> a=b=c
4738  // indeed, Ann = (x-a)^2*(x*Dx+3*t*Dt+(-a)*Dx+3)
4739  // --------------------------------------------
4740  // BUT a direct computation shows
4741  // when a=b=c,
4742  // Ann = x*Dx+3*t*Dt+(-a)*Dx+3
4743}
4744
4745static proc exOT_17()
4746{
4747  // Oaku-Takayama, p.208
4748  ring R = 0,(x,y),dp;
4749  poly F = x^3-y^2; // x^2+x*y+y^2;
4750  option(prot);
4751  option(mem);
4752  //  option(redSB);
4753  def A = annfsOT(F,0);
4754  setring A;
4755  LD;
4756  gkdim(LD); // a holonomic check
4757  //  poly F = x^3-y^2; // = x^7 - y^5; // x^3-y^4; // x^5 - y^4;
4758}
4759
4760static proc exOT_16()
4761{
4762  // Oaku-Takayama, p.208
4763  ring R = 0,(x),dp;
4764  poly F = x*(1-x);
4765  option(prot);
4766  option(mem);
4767  //  option(redSB);
4768  def A = annfsOT(F,0);
4769  setring A;
4770  LD;
4771  gkdim(LD); // a holonomic check
4772}
4773
4774static proc ex_bcheck()
4775{
4776  ring R = 0,(x,y),dp;
4777  poly F = x*y*(x+y);
4778  option(prot);
4779  option(mem);
4780  int eng = 0;
4781  //  option(redSB);
4782  def A = annfsOT(F,eng);
4783  setring A;
4784  LD;
4785}
4786
4787static proc ex_bcheck2()
4788{
4789  ring R = 0,(x,y),dp;
4790  poly F = x*y*(x+y);
4791  int eng = 0;
4792  def A = annfsBM(F,eng);
4793  setring A;
4794  LD;
4795}
4796
4797static proc ex_BMI()
4798{
4799  // a hard example
4800  ring r = 0,(x,y),Dp;
4801  poly F1 = (x2-y3)*(x3-y2);
4802  poly F2 = (x2-y3)*(xy4+y5+x4);
4803  ideal F = F1,F2;
4804  def A = annfsBMI(F);
4805  setring A;
4806  LD;
4807  BS;
4808}
4809
4810static proc ex2_BMI()
4811{
4812  // this example was believed to be intractable in 2005 by Gago-Vargas, Castro and Ucha
4813  ring r = 0,(x,y),Dp;
4814  option(prot);
4815  option(mem);
4816  ideal F = x2+y3,x3+y2;
4817  printlevel = 2;
4818  def A = annfsBMI(F);
4819  setring A;
4820  LD;
4821  BS;
4822}
4823
4824static proc ex_operatorBM()
4825{
4826  ring r = 0,(x,y,z,w),Dp;
4827  poly F = x^3+y^3+z^2*w;
4828  printlevel = 0;
4829  def A = operatorBM(F);
4830  setring A;
4831  F; // the original polynomial itself
4832  LD; // generic annihilator
4833  LD0; // annihilator
4834  bs; // normalized Bernstein poly
4835  BS; // root and multiplicities of the Bernstein poly
4836  PS; // the operator, s.t. PS*F^{s+1} = bs*F^s mod LD
4837  reduce(PS*F-bs,LD); // check the property of PS
4838}
Note: See TracBrowser for help on using the repository browser.