source: git/Singular/LIB/dmodapp.lib @ 2c3a5d

spielwiese
Last change on this file since 2c3a5d was 2c3a5d, checked in by Hans Schönemann <hannes@…>, 15 years ago
*hannes: code cleanup git-svn-id: file:///usr/local/Singular/svn/trunk@11694 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 47.9 KB
Line 
1//////////////////////////////////////////////////////////////////////////////
2version="$Id: dmodapp.lib,v 1.28 2009-04-14 11:52:54 Singular Exp $";
3category="Noncommutative";
4info="
5LIBRARY: dmodapp.lib     Applications of algebraic D-modules
6AUTHORS: Viktor Levandovskyy,      levandov@math.rwth-aachen.de
7@*             Daniel Andres, daniel.andres@math.rwth-aachen.de
8
9GUIDE: Let K be a field of characteristic 0, R = K[x1,..xN] and
10@* D be the Weyl algebra in variables x1,..xN,d1,..dN.
11@* In this library there are the following procedures for algebraic D-modules:
12@* - localization of a holonomic module D/I with respect to a mult. closed set
13@* of all powers of a given polynomial F from R. Our aim is to compute an
14@* ideal L in D, such that D/L is a presentation of a localized module. Such L
15@* always exists, since such localizations are known to be holonomic and thus
16@* cyclic modules. The procedures for the localization are DLoc,SDLoc and DLoc0.
17@*
18@* - annihilator in D of a given polynomial F from R as well as
19@* of a given rational function G/F from Quot(R). These can be computed via
20@* procedures annPoly resp. annRat.
21@*
22@* - initial form and initial ideals in Weyl algebras with respect to a given
23@* weight vector can be computed with  inForm, initialMalgrange, initialIdealW.
24@*
25@* - appelF1, appelF2 and appelF4 return ideals in parametric Weyl algebras,
26@* which annihilate corresponding Appel hypergeometric functions.
27
28REFERENCES:
29@* (SST) Saito, Sturmfels, Takayama 'Groebner Deformations of Hypergeometric
30@*         Differential Equations', Springer, 2000
31@* (ONW) Oaku, Takayama, Walther 'A Localization Algorithm for D-modules', 2000
32
33MAIN PROCEDURES:
34
35annPoly(f);   annihilator of a polynomial f in the corr. Weyl algebra
36annRat(f,g);  annihilator of a rational function f/g in the corr. Weyl algebra
37DLoc(I,F);     presentation of the localization of D/I w.r.t. f^s
38SDLoc(I, F);  a generic presentation of the localization of D/I w.r.t. f^s
39DLoc0(I, F);  presentation of the localization of D/I w.r.t. f^s, based on SDLoc
40
41initialMalgrange(f[,s,t,v]); Groebner basis of the initial Malgrange ideal for f
42initialIdealW(I,u,v[,s,t]); initial ideal of a given ideal w.r.t. given weights
43inForm(f,w);     initial form of a poly/ideal w.r.t. a given weight
44isFsat(I, F);       check whether the ideal I is F-saturated
45
46AUXILIARY PROCEDURES:
47
48bFactor(F);  computes the roots of irreducible factors of an univariate poly
49appelF1();      create an ideal annihilating Appel F1 function
50appelF2();      create an ideal annihilating Appel F2 function
51appelF4();      create an ideal annihilating Appel F4 function
52engine(I,i);     computes a Groebner basis with the algorithm given by i
53poly2list(f);   decompose a poly to a list of terms and exponents
54fl2poly(L,s);  reconstruct a monic univariate polynomial from its factorization
55insertGenerator(id,p[,k]); insert an element into an ideal/module
56deleteGenerator(id,k); delete the k-th element from an ideal/module
57
58
59SEE ALSO: dmod_lib, gmssing_lib, bfun_lib
60";
61
62LIB "poly.lib";
63LIB "sing.lib";
64LIB "primdec.lib";
65LIB "dmod.lib"; // loads e.g. nctools.lib
66LIB "bfun.lib"; //formerly LIB "bfct.lib";
67LIB "nctools.lib"; // for isWeyl etc
68LIB "gkdim.lib";
69
70proc inForm (ideal I, intvec w)
71"USAGE:  inForm(I,w);  I ideal, w intvec
72RETURN:  the initial form of I wrt the weight vector w
73PURPOSE: computes the initial form of an ideal wrt a given weight vector
74NOTE:  the size of the weight vector must be equal to the number of variables
75@*     of the basering.
76EXAMPLE: example inForm; shows examples
77"
78{
79  if (size(w) != nvars(basering))
80  {
81    ERROR("weight vector has wrong dimension");
82  }
83  if (I == 0)
84  {
85    return(I);
86  }
87  int j,i,s,m;
88  list l;
89  poly g;
90  ideal J;
91  for (j=1; j<=ncols(I); j++)
92  {
93    l = poly2list(I[j]);
94    m = scalarProd(w,l[1][1]);
95    g = l[1][2];
96    for (i=2; i<=size(l); i++)
97    {
98      s = scalarProd(w,l[i][1]);
99      if (s == m)
100      {
101        g = g + l[i][2];
102      }
103      else
104      {
105        if (s > m)
106        {
107          m = s;
108          g = l[i][2];
109        }
110      }
111    }
112    J[j] = g;
113  }
114  return(J);
115}
116example
117{
118  "EXAMPLE:"; echo = 2;
119  ring @D = 0,(x,y,Dx,Dy),dp;
120  def D = Weyl();
121  setring D;
122  poly F = 3*x^2*Dy+2*y*Dx;
123  poly G = 2*x*Dx+3*y*Dy+6;
124  ideal I = F,G;
125  intvec w1 = -1,-1,1,1;
126  intvec w2 = -1,-2,1,2;
127  intvec w3 = -2,-3,2,3;
128  inForm(I,w1);
129  inForm(I,w2);
130  inForm(I,w3);
131}
132
133/*
134
135proc charVariety(ideal I)
136"USAGE:  charVariety(I);  I an ideal
137RETURN:  ring
138PURPOSE: compute the characteristic variety of a D-module D/I
139STATUS: experimental, todo
140ASSUME: the ground ring is the Weyl algebra with x's before d's
141NOTE:    activate the output ring with the @code{setring} command.
142@*       In the output (in a commutative ring):
143@*       - the ideal CV is the characteristic variety char(I)
144@*       If @code{printlevel}=1, progress debug messages will be printed,
145@*       if @code{printlevel}>=2, all the debug messages will be printed.
146EXAMPLE: example charVariety; shows examples
147"
148{
149  // 1. introduce the weights 0, 1
150  def save = basering;
151  list LL = ringlist(save);
152  list L;
153  int i;
154  for(i=1;i<=4;i++)
155  {
156    L[i] = LL[i];
157  }
158  list OLD = L[3];
159  list NEW; list tmp;
160  tmp[1] = "a";  // string
161  intvec iv;
162  int N = nvars(basering); N = N div 2;
163  for(i=N+1; i<=2*N; i++)
164  {
165    iv[i] = 1;
166  }
167  tmp[2] = iv;
168  NEW[1] = tmp;
169  for (i=2; i<=size(OLD);i++)
170  {
171    NEW[i] = OLD[i-1];
172  }
173  L[3] = NEW;
174  list ncr =ncRelations(save);
175  matrix @C = ncr[1];
176  matrix @D = ncr[2];
177  def @U = ring(L);
178  // 2. create the commutative ring
179  setring save;
180  list CL;
181  for(i=1;i<=4;i++)
182  {
183    CL[i] = L[i];
184  }
185  CL[3] = OLD;
186  def @CU = ring(CL);
187  // comm ring is ready
188  setring @U;
189  // make @U noncommutative
190  matrix @C = imap(save,@C);
191  matrix @D = imap(save,@D);
192  def @@U = nc_algebra(@C,@D);
193  setring @@U; kill @U;
194  // 2. compute Groebner basis
195  ideal I = imap(save,I);
196  //  I = groebner(I);
197  I = slimgb(I); // a bug?
198  setring @CU;
199  ideal CV = imap(@@U,I);
200  //  CV = groebner(CV); // cosmetics
201  CV = slimgb(CV);
202  export CV;
203  return(@CU);
204}
205example
206{
207  "EXAMPLE:"; echo = 2;
208  ring r = 0,(x,y),Dp;
209  poly F = x3-y2;
210  printlevel = 0;
211  def A  = annfs(F);
212  setring A; // Weyl algebra
213  LD; // the ideal
214  def CA = charVariety(LD);
215  setring CA;
216  CV;
217  dim(CV);
218}
219
220/*
221
222// TODO
223
224/*
225proc charInfo(ideal I)
226"USAGE:  charInfo(I);  I an ideal
227RETURN:  ring
228STATUS: experimental, todo
229PURPOSE: compute the characteristic information for I
230ASSUME: the ground ring is the Weyl algebra with x's before d's
231NOTE:    activate the output ring with the @code{setring} command.
232@*       In the output (in a commutative ring):
233@*       - the ideal CV is the characteristic variety char(I)
234@*       - the ideal SL is the singular locus of char(I)
235@*       - the list PD is the primary decomposition of char(I)
236@*       If @code{printlevel}=1, progress debug messages will be printed,
237@*       if @code{printlevel}>=2, all the debug messages will be printed.
238EXAMPLE: example annfs; shows examples
239"
240{
241  def save = basering;
242  def @A = charVariety(I);
243  setring @A;
244  // run slocus
245  // run primdec
246}
247*/
248
249
250proc appelF1()
251"USAGE:  appelF1();
252RETURN:  ring  (and exports an ideal into it)
253PURPOSE: define the ideal in a parametric Weyl algebra,
254@* which annihilates Appel F1 hypergeometric function
255NOTE: the ideal called  IAppel1 is exported to the output ring
256EXAMPLE: example appelF1; shows examples
257"
258{
259  // Appel F1, d = b', SST p.48
260  ring @r = (0,a,b,c,d),(x,y,Dx,Dy),(a(0,0,1,1),a(0,0,1,0),dp);
261  matrix @D[4][4];
262  @D[1,3]=1; @D[2,4]=1;
263  def @S = nc_algebra(1,@D);
264  setring @S;
265  ideal IAppel1 =
266    (x*Dx)*(x*Dx+y*Dy+c-1) - x*(x*Dx+y*Dy+a)*(x*Dx+b),
267    (y*Dy)*(x*Dx+y*Dy+c-1) - y*(x*Dx+y*Dy+a)*(y*Dy+d),
268    (x-y)*Dx*Dy - d*Dx + b*Dy;
269  export IAppel1;
270  kill @r;
271  return(@S);
272}
273example
274{
275  "EXAMPLE:"; echo = 2;
276  def A = appelF1();
277  setring A;
278  IAppel1;
279}
280
281proc appelF2() //(number a,b,c)
282"USAGE:  appelF2();
283RETURN:  ring (and exports an ideal into it)
284PURPOSE: define the ideal in a parametric Weyl algebra,
285@* which annihilates Appel F2 hypergeometric function
286NOTE: the ideal called  IAppel2 is exported to the output ring
287EXAMPLE: example appelF2; shows examples
288"
289{
290  // Appel F2, c = b', SST p.85
291  ring @r = (0,a,b,c),(x,y,Dx,Dy),(a(0,0,1,1),a(0,0,1,0),dp);
292  matrix @D[4][4];
293  @D[1,3]=1; @D[2,4]=1;
294  def @S = nc_algebra(1,@D);
295  setring @S;
296  ideal IAppel2 =
297    (x*Dx)^2 - x*(x*Dx+y*Dy+a)*(x*Dx+b),
298    (y*Dy)^2 - y*(x*Dx+y*Dy+a)*(y*Dy+c);
299  export IAppel2;
300  kill @r;
301  return(@S);
302}
303example
304{
305  "EXAMPLE:"; echo = 2;
306  def A = appelF2();
307  setring A;
308  IAppel2;
309}
310
311proc appelF4()
312"USAGE:  appelF4();
313RETURN:  ring  (and exports an ideal into it)
314PURPOSE: define the ideal in a parametric Weyl algebra,
315@* which annihilates Appel F4 hypergeometric function
316NOTE: the ideal called  IAppel4 is exported to the output ring
317EXAMPLE: example appelF4; shows examples
318"
319{
320  // Appel F4, d = c', SST, p. 39
321  ring @r = (0,a,b,c,d),(x,y,Dx,Dy),(a(0,0,1,1),a(0,0,1,0),dp);
322  matrix @D[4][4];
323  @D[1,3]=1; @D[2,4]=1;
324  def @S = nc_algebra(1,@D);
325  setring @S;
326  ideal IAppel4 =
327    Dx*(x*Dx+c-1) - (x*Dx+y*Dy+a)*(x*Dx+y*Dy+b),
328    Dy*(y*Dy+d-1) - (x*Dx+y*Dy+a)*(x*Dx+y*Dy+b);
329  export IAppel4;
330  kill @r;
331  return(@S);
332}
333example
334{
335  "EXAMPLE:"; echo = 2;
336  def A = appelF4();
337  setring A;
338  IAppel4;
339}
340
341proc poly2list (poly f)
342"USAGE:  poly2list(f); f a poly
343RETURN:  list of exponents and corresponding terms of f
344PURPOSE: convert a polynomial to a list of exponents and corresponding terms
345EXAMPLE: example poly2list; shows examples
346"
347{
348  list l;
349  int i = 1;
350  if (f == 0) // just for the zero polynomial
351  {
352    l[1] = list(leadexp(f), lead(f));
353  }
354  else { l[size(f)] = list(); } // memory pre-allocation
355  while (f != 0)
356  {
357    l[i] = list(leadexp(f), lead(f));
358    f = f - lead(f);
359    i++;
360  }
361  return(l);
362}
363example
364{
365  "EXAMPLE:"; echo = 2;
366  ring r = 0,x,dp;
367  poly F = x;
368  poly2list(F);
369  ring r2 = 0,(x,y),dp;
370  poly F = x2y+x*y2;
371  poly2list(F);
372}
373
374proc isFsat(ideal I, poly F)
375"USAGE:  isFsat(I, F);  I an ideal, F a poly
376RETURN: int
377PURPOSE: check whether the ideal I is F-saturated
378NOTE:    1 is returned if I is F-saturated, otherwise 0 is returned.
379@*   we check indeed that Ker(D --F--> D/I) is (0)
380EXAMPLE: example isFsat; shows examples
381"
382{
383  /* checks whether I is F-saturated, that is Ke  (D -F-> D/I) is 0 */
384  /* works in any algebra */
385  /*  for simplicity : later check attrib */
386  /* returns -1 if true */
387  if (attrib(I,"isSB")!=1)
388  {
389    I = groebner(I);
390  }
391  matrix @M = matrix(I);
392  matrix @F[1][1] = F;
393  module S = modulo(@F,@M);
394  S = NF(S,I);
395  S = groebner(S);
396  return( (gkdim(S) == -1) );
397}
398example
399{
400  "EXAMPLE:"; echo = 2;
401  ring r = 0,(x,y),dp;
402  poly G = x*(x-y)*y;
403  def A = annfs(G);
404  setring A;
405  poly F = x3-y2;
406  isFsat(LD,F);
407  ideal J = LD*F;
408  isFsat(J,F);
409}
410
411proc DLoc(ideal I, poly F)
412"USAGE:  DLoc(I, F);  I an ideal, F a poly
413RETURN: nothing (exports objects instead)
414ASSUME: the basering is a Weyl algebra
415PURPOSE: compute the presentation of the localization of D/I w.r.t. f^s
416NOTE:    In the basering, the following objects are exported:
417@* the ideal LD0 (in Groebner basis) is the presentation of the localization
418@* the list BS contains roots with multiplicities of Bernstein poly of (D/I)_f.
419DISPLAY: If printlevel=1, progress debug messages will be printed,
420@*       if printlevel>=2, all the debug messages will be printed.
421EXAMPLE: example DLoc; shows examples
422"
423{
424  /* runs SDLoc and DLoc0 */
425  /* assume: run from Weyl algebra */
426  if (dmodappassumeViolation())
427  {
428    ERROR("Basering is inappropriate: characteristic>0 or qring present");
429  }
430  if (!isWeyl())
431  {
432    ERROR("Basering is not a Weyl algebra");
433  }
434  if (defined(LD0) || defined(BS))
435  {
436    ERROR("Reserved names LD0 and/or BS are used. Please rename the objects.");
437  }
438  int old_printlevel = printlevel;
439  printlevel=printlevel+1;
440  def @R = basering;
441  def @R2 = SDLoc(I,F);
442  setring @R2;
443  poly F = imap(@R,F);
444  def @R3 = DLoc0(LD,F);
445  setring @R3;
446  ideal bs = BS[1];
447  intvec m = BS[2];
448  setring @R;
449  ideal LD0 = imap(@R3,LD0);
450  export LD0;
451  ideal bs = imap(@R3,bs);
452  list BS; BS[1] = bs; BS[2] = m;
453  export BS;
454  kill @R3;
455  printlevel = old_printlevel;
456}
457example;
458{
459  "EXAMPLE:"; echo = 2;
460  ring r = 0,(x,y,Dx,Dy),dp;
461  def R = Weyl();    setring R; // Weyl algebra in variables x,y,Dx,Dy
462  poly F = x2-y3;
463  ideal I = (y^3 - x^2)*Dx - 2*x, (y^3 - x^2)*Dy + 3*y^2; // I = Dx*F, Dy*F;
464  // I is not holonomic, since its dimension is not 4/2=2
465  gkdim(I);
466  DLoc(I, x2-y3); // exports LD0 and BS
467  LD0; // localized module (R/I)_f is isomorphic to R/LD0
468  BS; // description of b-function for localization
469}
470
471proc DLoc0(ideal I, poly F)
472"USAGE:  DLoc0(I, F);  I an ideal, F a poly
473RETURN:  ring
474PURPOSE: compute the presentation of the localization of D/I w.r.t. f^s,
475@*           where D is a Weyl Algebra, based on the output of procedure SDLoc
476ASSUME: the basering is similar to the output ring of SDLoc procedure
477NOTE:    activate this ring with the @code{setring} command. In this ring,
478@* the ideal LD0 (in Groebner basis) is the presentation of the localization
479@* the list BS contains roots and multiplicities of Bernstein poly of (D/I)_f.
480DISPLAY: If printlevel=1, progress debug messages will be printed,
481@*       if printlevel>=2, all the debug messages will be printed.
482EXAMPLE: example DLoc0; shows examples
483"
484{
485  if (dmodappassumeViolation())
486  {
487    ERROR("Basering is inappropriate: characteristic>0 or qring present");
488  }
489  /* assume: to be run in the output ring of SDLoc */
490  /* doing: add F, eliminate vars*Dvars, factorize BS */
491  /* analogue to annfs0 */
492  def @R2 = basering;
493  // we're in D_n[s], where the elim ord for s is set
494  ideal J = NF(I,std(F));
495  // make leadcoeffs positive
496  int i;
497  for (i=1; i<= ncols(J); i++)
498  {
499    if (leadcoef(J[i]) <0 )
500    {
501      J[i] = -J[i];
502    }
503  }
504  J = J,F;
505  ideal M = groebner(J);
506  int Nnew = nvars(@R2);
507  ideal K2 = nselect(M,1..Nnew-1);
508  int ppl = printlevel-voice+2;
509  dbprint(ppl,"// -1-1- _x,_Dx are eliminated in basering");
510  dbprint(ppl-1, K2);
511  // the ring @R3 and the search for minimal negative int s
512  ring @R3 = 0,s,dp;
513  dbprint(ppl,"// -2-1- the ring @R3 = K[s] is ready");
514  ideal K3 = imap(@R2,K2);
515  poly p = K3[1];
516  dbprint(ppl,"// -2-2- attempt the factorization");
517  list PP = factorize(p);          //with constants and multiplicities
518  ideal bs; intvec m;             //the Bernstein polynomial is monic, so we are not interested in constants
519  for (i=2; i<= size(PP[1]); i++)  //we delete P[1][1] and P[2][1]
520  {
521    bs[i-1] = PP[1][i];
522    m[i-1]  = PP[2][i];
523  }
524  ideal bbs; int srat=0; int HasRatRoots = 0;
525  int sP;
526  for (i=1; i<= size(bs); i++)
527  {
528    if (deg(bs[i]) == 1)
529    {
530      bbs = bbs,bs[i];
531    }
532  }
533  if (size(bbs)==0)
534  {
535    dbprint(ppl-1,"// -2-3- factorization: no rational roots");
536    //    HasRatRoots = 0;
537    HasRatRoots = 1; // s0 = -1 then
538    sP = -1;
539    // todo: return ideal with no subst and a b-function unfactorized
540  }
541  else
542  {
543    // exist rational roots
544    dbprint(ppl-1,"// -2-3- factorization: rational roots found");
545    HasRatRoots = 1;
546    //    dbprint(ppl-1,bbs);
547    bbs = bbs[2..ncols(bbs)];
548    ideal P = bbs;
549    dbprint(ppl-1,P);
550    srat = size(bs) - size(bbs);
551    // define minIntRoot on linear factors or find out that it doesn't exist
552    intvec vP;
553    number nP;
554    P = normalize(P); // now leadcoef = 1
555    P = lead(P)-P;
556    sP = size(P);
557    int cnt = 0;
558    for (i=1; i<=sP; i++)
559    {
560      nP = leadcoef(P[i]);
561      if ( (nP - int(nP)) == 0 )
562      {
563        cnt++;
564        vP[cnt] = int(nP);
565      }
566    }
567//     if ( size(vP)>=2 )
568//     {
569//       vP = vP[2..size(vP)];
570//     }
571    if ( size(vP)==0 )
572    {
573      // no roots!
574      dbprint(ppl,"// -2-4- no integer root, setting s0 = -1");
575      sP = -1;
576      //      HasRatRoots = 0; // older stuff, here we do substitution
577      HasRatRoots = 1;
578    }
579    else
580    {
581      HasRatRoots = 1;
582      sP = -Max(-vP);
583      dbprint(ppl,"// -2-4- minimal integer root found");
584      dbprint(ppl-1, sP);
585      //    int sP = minIntRoot(bbs,1);
586//       P =  normalize(P);
587//       bs = -subst(bs,s,0);
588      if (sP >=0)
589      {
590        dbprint(ppl,"// -2-5- nonnegative root, setting s0 = -1");
591        sP = -1;
592      }
593      else
594      {
595        dbprint(ppl,"// -2-5- the root is negative");
596      }
597    }
598  }
599
600  if (HasRatRoots)
601  {
602    setring @R2;
603    K2 = subst(I,s,sP);
604    // IF min int root exists ->
605    // create the ordinary Weyl algebra and put the result into it,
606    // thus creating the ring @R5
607    // ELSE : return the same ring with new objects
608    // keep: N, i,j,s, tmp, RL
609    Nnew = Nnew - 1; // former 2*N;
610    // list RL = ringlist(save);  // is defined earlier
611    //  kill Lord, tmp, iv;
612    list L = 0;
613    list Lord, tmp;
614    intvec iv;
615    list RL = ringlist(basering);
616    L[1] = RL[1];
617    L[4] = RL[4];  //char, minpoly
618    // check whether vars have admissible names -> done earlier
619    // list Name = RL[2]M
620    // DName is defined earlier
621    list NName; // = RL[2]; // skip the last var 's'
622    for (i=1; i<=Nnew; i++)
623    {
624      NName[i] =  RL[2][i];
625    }
626    L[2] = NName;
627    // dp ordering;
628    string s = "iv=";
629    for (i=1; i<=Nnew; i++)
630    {
631      s = s+"1,";
632    }
633    s[size(s)] = ";";
634    execute(s);
635    tmp     = 0;
636    tmp[1]  = "dp";  // string
637    tmp[2]  = iv;  // intvec
638    Lord[1] = tmp;
639    kill s;
640    tmp[1]  = "C";
641    iv = 0;
642    tmp[2]  = iv;
643    Lord[2] = tmp;
644    tmp     = 0;
645    L[3]    = Lord;
646    // we are done with the list
647    // Add: Plural part
648    def @R4@ = ring(L);
649    setring @R4@;
650    int N = Nnew/2;
651    matrix @D[Nnew][Nnew];
652    for (i=1; i<=N; i++)
653    {
654      @D[i,N+i]=1;
655    }
656    def @R4 = nc_algebra(1,@D);
657    setring @R4;
658    kill @R4@;
659    dbprint(ppl,"// -3-1- the ring @R4 is ready");
660    dbprint(ppl-1, @R4);
661    ideal K4 = imap(@R2,K2);
662    intvec vopt = option(get);
663    option(redSB);
664    dbprint(ppl,"// -3-2- the final cosmetic std");
665    K4 = groebner(K4);  // std does the job too
666    option(set,vopt);
667    // total cleanup
668    setring @R2;
669    ideal bs = imap(@R3,bs);
670    bs = -normalize(bs); // "-" for getting correct coeffs!
671    bs = subst(bs,s,0);
672    kill @R3;
673    setring @R4;
674    ideal bs = imap(@R2,bs); // only rationals are the entries
675    list BS; BS[1] = bs; BS[2] = m;
676    export BS;
677    //    list LBS = imap(@R3,LBS);
678    //    list BS; BS[1] = sbs; BS[2] = m;
679    //    BS;
680    //    export BS;
681    ideal LD0 = K4;
682    export LD0;
683    return(@R4);
684  }
685  else
686  {
687    /* SHOULD NEVER GET THERE */
688    /* no rational/integer roots */
689    /* return objects in the copy of current ring */
690    setring @R2;
691    ideal LD0 = I;
692    poly BS = normalize(K2[1]);
693    export LD0;
694    export BS;
695    return(@R2);
696  }
697}
698example;
699{
700  "EXAMPLE:"; echo = 2;
701  ring r = 0,(x,y,Dx,Dy),dp;
702  def R = Weyl();    setring R; // Weyl algebra in variables x,y,Dx,Dy
703  poly F = x2-y3;
704  ideal I = (y^3 - x^2)*Dx - 2*x, (y^3 - x^2)*Dy + 3*y^2; // I = Dx*F, Dy*F;
705  // moreover I is not holonomic, since its dimension is not 2 = 4/2
706  gkdim(I); // 3
707  def W = SDLoc(I,F);  setring W; // creates ideal LD in W = R[s]
708  def U = DLoc0(LD, x2-y3);  setring U; // compute in R
709  LD0; // Groebner basis of the presentation of localization
710  BS; // description of b-function for localization
711}
712
713
714proc SDLoc(ideal I, poly F)
715"USAGE:  SDLoc(I, F);  I an ideal, F a poly
716RETURN:  ring
717PURPOSE: compute a generic presentation of the localization of D/I w.r.t. f^s
718ASSUME: the basering D is a Weyl algebra
719NOTE:    activate this ring with the @code{setring} command. In this ring,
720@*  the ideal LD (in Groebner basis) is the presentation of the localization
721DISPLAY: If printlevel=1, progress debug messages will be printed,
722@*       if printlevel>=2, all the debug messages will be printed.
723EXAMPLE: example SDLoc; shows examples
724"
725{
726  /* analogue to Sannfs */
727  /* printlevel >=4 gives debug info */
728  /* assume: we're in the Weyl algebra D  in x1,x2,...,d1,d2,... */
729
730  if (dmodappassumeViolation())
731  {
732    ERROR("Basering is inappropriate: characteristic>0 or qring present");
733  }
734  if (!isWeyl())
735  {
736    ERROR("Basering is not a Weyl algebra");
737  }
738  def save = basering;
739  /* 1. create D <t, dt, s > as in LOT */
740  /* ordering: eliminate t,dt */
741  int ppl = printlevel-voice+2;
742  int N = nvars(save); N = N div 2;
743  int Nnew = 2*N + 3; // t,Dt,s
744  int i,j;
745  string s;
746  list RL = ringlist(save);
747  list L, Lord;
748  list tmp;
749  intvec iv;
750  L[1] = RL[1]; // char
751  L[4] = RL[4]; // char, minpoly
752  // check whether vars have admissible names
753  list Name  = RL[2];
754  list RName;
755  RName[1] = "@t";
756  RName[2] = "@Dt";
757  RName[3] = "@s";
758  for(i=1;i<=N;i++)
759  {
760    for(j=1; j<=size(RName);j++)
761    {
762      if (Name[i] == RName[j])
763      {
764        ERROR("Variable names should not include @t,@Dt,@s");
765      }
766    }
767  }
768  // now, create the names for new vars
769  tmp    =  0;
770  tmp[1] = "@t";
771  tmp[2] = "@Dt";
772  list SName ; SName[1] = "@s";
773  list NName = tmp + Name + SName;
774  L[2]   = NName;
775  tmp    = 0;
776  kill NName;
777  // block ord (a(1,1),dp);
778  tmp[1]  = "a"; // string
779  iv      = 1,1;
780  tmp[2]  = iv; //intvec
781  Lord[1] = tmp;
782  // continue with dp 1,1,1,1...
783  tmp[1]  = "dp"; // string
784  s       = "iv=";
785  for(i=1;i<=Nnew;i++)
786  {
787    s = s+"1,";
788  }
789  s[size(s)]= ";";
790  execute(s);
791  tmp[2]    = iv;
792  Lord[2]   = tmp;
793  tmp[1]    = "C";
794  iv        = 0;
795  tmp[2]    = iv;
796  Lord[3]   = tmp;
797  tmp       = 0;
798  L[3]      = Lord;
799  // we are done with the list
800  def @R@ = ring(L);
801  setring @R@;
802  matrix @D[Nnew][Nnew];
803  @D[1,2]=1;
804  for(i=1; i<=N; i++)
805  {
806    @D[2+i,N+2+i]=1;
807  }
808  // ADD [s,t]=-t, [s,Dt]=Dt
809  @D[1,Nnew] = -var(1);
810  @D[2,Nnew] = var(2);
811  def @R = nc_algebra(1,@D);
812  setring @R;
813  kill @R@;
814  dbprint(ppl,"// -1-1- the ring @R(@t,@Dt,_x,_Dx,@s) is ready");
815  dbprint(ppl-1, @R);
816  poly  F = imap(save,F);
817  ideal I = imap(save,I);
818  dbprint(ppl-1, "the ideal after map:");
819  dbprint(ppl-1, I);
820  poly p = 0;
821  for(i=1; i<=N; i++)
822  {
823    p = diff(F,var(2+i))*@Dt + var(2+N+i);
824    dbprint(ppl-1, p);
825    I = subst(I,var(2+N+i),p);
826    dbprint(ppl-1, var(2+N+i));
827    p = 0;
828  }
829  I = I, @t - F;
830  // t*Dt + s +1 reduced with t-f gives f*Dt + s
831  I = I, F*var(2) + var(Nnew); // @s
832  // -------- the ideal I is ready ----------
833  dbprint(ppl,"// -1-2- starting the elimination of @t,@Dt in @R");
834  dbprint(ppl-1, I);
835  //  ideal J = engine(I,eng);
836  ideal J = groebner(I);
837  dbprint(ppl-1,"// -1-2-1- result of the  elimination of @t,@Dt in @R");
838  dbprint(ppl-1, J);;
839  ideal K = nselect(J,1..2);
840  dbprint(ppl,"// -1-3- @t,@Dt are eliminated");
841  dbprint(ppl-1, K);  // K is without t, Dt
842  K = groebner(K);  // std does the job too
843  // now, we must change the ordering
844  // and create a ring without t, Dt
845  setring save;
846  // ----------- the ring @R3 ------------
847  // _x, _Dx,s;  elim.ord for _x,_Dx.
848  // keep: N, i,j,s, tmp, RL
849  Nnew = 2*N+1;
850  kill Lord, tmp, iv, RName;
851  list Lord, tmp;
852  intvec iv;
853  L[1] = RL[1];
854  L[4] = RL[4];  // char, minpoly
855  // check whether vars hava admissible names -> done earlier
856  // now, create the names for new var
857  tmp[1] = "s";
858  list NName = Name + tmp;
859  L[2] = NName;
860  tmp = 0;
861  // block ord (dp(N),dp);
862  // string s is already defined
863  s = "iv=";
864  for (i=1; i<=Nnew-1; i++)
865  {
866    s = s+"1,";
867  }
868  s[size(s)]=";";
869  execute(s);
870  tmp[1] = "dp";  // string
871  tmp[2] = iv;   // intvec
872  Lord[1] = tmp;
873  // continue with dp 1,1,1,1...
874  tmp[1] = "dp";  // string
875  s[size(s)] = ",";
876  s = s+"1;";
877  execute(s);
878  kill s;
879  kill NName;
880  tmp[2]      = iv;
881  Lord[2]     = tmp;
882  tmp[1]      = "C";  iv  = 0;  tmp[2]=iv;
883  Lord[3]     = tmp;  tmp = 0;
884  L[3]        = Lord;
885  // we are done with the list. Now add a Plural part
886  def @R2@ = ring(L);
887  setring @R2@;
888  matrix @D[Nnew][Nnew];
889  for (i=1; i<=N; i++)
890  {
891    @D[i,N+i]=1;
892  }
893  def @R2 = nc_algebra(1,@D);
894  setring @R2;
895  kill @R2@;
896  dbprint(ppl,"//  -2-1- the ring @R2(_x,_Dx,s) is ready");
897  dbprint(ppl-1, @R2);
898  ideal MM = maxideal(1);
899  MM = 0,s,MM;
900  map R01 = @R, MM;
901  ideal K = R01(K);
902  // total cleanup
903  ideal LD = K;
904  // make leadcoeffs positive
905  for (i=1; i<= ncols(LD); i++)
906  {
907    if (leadcoef(LD[i]) <0 )
908    {
909      LD[i] = -LD[i];
910    }
911  }
912  export LD;
913  kill @R;
914  return(@R2);
915}
916example;
917{
918  "EXAMPLE:"; echo = 2;
919  ring r = 0,(x,y,Dx,Dy),dp;
920  def R = Weyl(); // Weyl algebra on the variables x,y,Dx,Dy
921  setring R;
922  poly F = x2-y3;
923  ideal I = Dx*F, Dy*F;
924  // note, that I is not holonomic, since it's dimension is not 2
925  gkdim(I); // 3, while dim R = 4
926  def W = SDLoc(I,F);
927  setring W; // = R[s], where s is a new variable
928  LD; // Groebner basis of s-parametric presentation
929}
930
931proc annRat(poly g, poly f)
932"USAGE:  annRat(g,f);  f, g polynomials
933RETURN:  ring
934PURPOSE: compute the annihilator of the rational function g/f in the Weyl algebra D
935NOTE: activate the output ring with the @code{setring} command.
936@*      In the output ring, the ideal LD (in Groebner basis) is the annihilator.
937@*      The algorithm uses the computation of ann f^{-1} via D-modules.
938DISPLAY: If printlevel=1, progress debug messages will be printed,
939@*       if printlevel>=2, all the debug messages will be printed.
940SEE ALSO: annPoly
941EXAMPLE: example annRat; shows examples
942"
943{
944
945  if (dmodappassumeViolation())
946  {
947    ERROR("Basering is inappropriate: characteristic>0 or qring present");
948  }
949
950  // assumptions: f is not a constant
951  if (f==0) { ERROR("Denominator cannot be zero"); }
952  if (leadexp(f) == 0)
953  {
954    // f = const, so use annPoly
955    g = g/f;
956    def @R = annPoly(g);
957    return(@R);
958  }
959    // computes the annihilator of g/f
960  def save = basering;
961  int ppl = printlevel-voice+2;
962  dbprint(ppl,"// -1-[annRat] computing the ann f^s");
963  def  @R1 = SannfsBM(f);
964  setring @R1;
965  poly f = imap(save,f);
966  int i,mir;
967  int isr = 0; // checkRoot1(LD,f,1); // roots are negative, have to enter positive int
968  if (!isr)
969  {
970    // -1 is not the root
971    // find the m.i.r iteratively
972    mir = 0;
973    for(i=nvars(save)+1; i>=1; i--)
974    {
975      isr =  checkRoot1(LD,f,i);
976      if (isr) { mir =-i; break; }
977    }
978    if (mir ==0)
979    {
980      "No integer root found! Aborting computations, inform the authors!";
981      return(0);
982    }
983    // now mir == i is m.i.r.
984  }
985  else
986  {
987    // -1 is the m.i.r
988    mir = -1;
989  }
990  dbprint(ppl,"// -2-[annRat] the minimal integer root is ");
991  dbprint(ppl-1, mir);
992  // use annfspecial
993  dbprint(ppl,"// -3-[annRat] running annfspecial ");
994  ideal AF = annfspecial(LD,f,mir,-1); // ann f^{-1}
995  //  LD = subst(LD,s,j);
996  //  LD = engine(LD,0);
997  // modify the ring: throw s away
998  // output ring comes from SannfsBM
999  list U = ringlist(@R1);
1000  list tmp; // variables
1001  for(i=1; i<=size(U[2])-1; i++)
1002  {
1003    tmp[i] = U[2][i];
1004  }
1005  U[2] = tmp;
1006  tmp = 0;
1007  tmp[1] = U[3][1]; // x,Dx block
1008  tmp[2] = U[3][3]; // module block
1009  U[3] = tmp;
1010  tmp = 0;
1011  tmp = U[1],U[2],U[3],U[4];
1012  def @R2 = ring(tmp);
1013  setring @R2;
1014  // now supply with Weyl algebra relations
1015  int N = nvars(@R2)/2;
1016  matrix @D[2*N][2*N];
1017  for(i=1; i<=N; i++)
1018  {
1019    @D[i,N+i]=1;
1020  }
1021  def @R3 = nc_algebra(1,@D);
1022  setring @R3;
1023  dbprint(ppl,"// - -[annRat] ring without s is ready:");
1024  dbprint(ppl-1,@R3);
1025  poly g = imap(save,g);
1026  matrix G[1][1] = g;
1027  matrix LL = matrix(imap(@R1,AF));
1028  kill @R1;   kill @R2;
1029  dbprint(ppl,"// -4-[annRat] running modulo");
1030  ideal LD  = modulo(G,LL);
1031  dbprint(ppl,"// -4-[annRat] running GB on the final result");
1032  LD  = engine(LD,0);
1033  export LD;
1034  return(@R3);
1035}
1036example
1037{
1038  "EXAMPLE:"; echo = 2;
1039  ring r = 0,(x,y),dp;
1040  poly g = 2*x*y;  poly f = x^2 - y^3;
1041  def B = annRat(g,f);
1042  setring B;
1043  LD;
1044  // Now, compare with the output of Macaulay2:
1045  ideal tst = 3*x*Dx + 2*y*Dy + 1, y^3*Dy^2 - x^2*Dy^2 + 6*y^2*Dy + 6*y,
10469*y^2*Dx^2*Dy-4*y*Dy^3+27*y*Dx^2+2*Dy^2, 9*y^3*Dx^2-4*y^2*Dy^2+10*y*Dy -10;
1047 option(redSB); option(redTail);
1048 LD = groebner(LD);
1049 tst = groebner(tst);
1050 print(matrix(NF(LD,tst)));  print(matrix(NF(tst,LD)));
1051 // So, these two answers are the same
1052}
1053
1054/*
1055//static proc ex_annRat()
1056{
1057  // more complicated example for annRat
1058  ring r = 0,(x,y,z),dp;
1059  poly f = x3+y3+z3; // mir = -2
1060  poly g = x*y*z;
1061  def A = annRat(g,f);
1062  setring A;
1063}
1064*/
1065
1066proc annPoly(poly f)
1067"USAGE:  annPoly(f);  f a poly
1068RETURN:  ring
1069PURPOSE: compute the complete annihilator ideal of f in the Weyl algebra D
1070NOTE:  activate the output ring with the @code{setring} command.
1071@*   In the output ring, the ideal LD (in Groebner basis) is the annihilator.
1072DISPLAY: If printlevel=1, progress debug messages will be printed,
1073@*       if printlevel>=2, all the debug messages will be printed.
1074SEE ALSO: annRat
1075EXAMPLE: example annPoly; shows examples
1076"
1077{
1078  // computes a system of linear PDEs with polynomial coeffs for f
1079  def save = basering;
1080  list L = ringlist(save);
1081  list Name = L[2];
1082  int N = nvars(save);
1083  int i;
1084  for (i=1; i<=N; i++)
1085  {
1086    Name[N+i] = "D"+Name[i]; // concat
1087  }
1088  L[2] = Name;
1089  def @R = ring(L);
1090  setring @R;
1091  def @@R = Weyl();
1092  setring @@R;
1093  kill @R;
1094  matrix M[1][N];
1095  for (i=1; i<=N; i++)
1096  {
1097    M[1,i] = var(N+i);
1098  }
1099  matrix F[1][1] = imap(save,f);
1100  ideal I = modulo(F,M);
1101  ideal LD = groebner(I);
1102  export LD;
1103  return(@@R);
1104}
1105example
1106{
1107  "EXAMPLE:"; echo = 2;
1108  ring r = 0,(x,y,z),dp;
1109  poly f = x^2*z - y^3;
1110  def A = annPoly(f);
1111  setring A; // A is the 3rd Weyl algebra in 6 variables
1112  LD; // the Groebner basis of annihilator
1113  gkdim(LD); // must be 3 = 6/2, since A/LD is holonomic module
1114  NF(Dy^4, LD); // must be 0 since Dy^4 clearly annihilates f
1115}
1116
1117/* DIFFERENT EXAMPLES
1118
1119//static proc exCusp()
1120{
1121  "EXAMPLE:"; echo = 2;
1122  ring r = 0,(x,y,Dx,Dy),dp;
1123  def R = Weyl();   setring R;
1124  poly F = x2-y3;
1125  ideal I = (y^3 - x^2)*Dx - 2*x, (y^3 - x^2)*Dy + 3*y^2; // I = Dx*F, Dy*F;
1126  def W = SDLoc(I,F);
1127  setring W;
1128  LD;
1129  def U = DLoc0(LD,x2-y3);
1130  setring U;
1131  LD0;
1132  BS;
1133  // the same with DLoc:
1134  setring R;
1135  DLoc(I,F);
1136}
1137
1138//static proc exWalther1()
1139{
1140  // p.18 Rem 3.10
1141  ring r = 0,(x,Dx),dp;
1142  def R = nc_algebra(1,1);
1143  setring R;
1144  poly F = x;
1145  ideal I = x*Dx+1;
1146  def W = SDLoc(I,F);
1147  setring W;
1148  LD;
1149  ideal J = LD, x;
1150  eliminate(J,x*Dx); // must be [1]=s // agree!
1151  // the same result with Dloc0:
1152  def U = DLoc0(LD,x);
1153  setring U;
1154  LD0;
1155  BS;
1156}
1157
1158//static proc exWalther2()
1159{
1160  // p.19 Rem 3.10 cont'd
1161  ring r = 0,(x,Dx),dp;
1162  def R = nc_algebra(1,1);
1163  setring R;
1164  poly F = x;
1165  ideal I = (x*Dx)^2+1;
1166  def W = SDLoc(I,F);
1167  setring W;
1168  LD;
1169  ideal J = LD, x;
1170  eliminate(J,x*Dx); // must be [1]=s^2+2*s+2 // agree!
1171  // the same result with Dloc0:
1172  def U = DLoc0(LD,x);
1173  setring U;
1174  LD0;
1175  BS;
1176  // almost the same with DLoc
1177  setring R;
1178  DLoc(I,F);
1179  LD0;  BS;
1180}
1181
1182//static proc exWalther3()
1183{
1184  // can check with annFs too :-)
1185  // p.21 Ex 3.15
1186  LIB "nctools.lib";
1187  ring r = 0,(x,y,z,w,Dx,Dy,Dz,Dw),dp;
1188  def R = Weyl();
1189  setring R;
1190  poly F = x2+y2+z2+w2;
1191  ideal I = Dx,Dy,Dz,Dw;
1192  def W = SDLoc(I,F);
1193  setring W;
1194  LD;
1195  ideal J = LD, x2+y2+z2+w2;
1196  eliminate(J,x*y*z*w*Dx*Dy*Dz*Dw); // must be [1]=s^2+3*s+2 // agree
1197  ring r2 =  0,(x,y,z,w),dp;
1198  poly F = x2+y2+z2+w2;
1199  def Z = annfs(F);
1200  setring Z;
1201  LD;
1202  BS;
1203  // the same result with Dloc0:
1204  setring W;
1205  def U = DLoc0(LD,x2+y2+z2+w2);
1206  setring U;
1207  LD0;  BS;
1208  // the same result with DLoc:
1209  setring R;
1210  DLoc(I,F);
1211  LD0;  BS;
1212}
1213
1214*/
1215
1216proc engine(def I, int i)
1217"USAGE:  engine(I,i);  I  ideal/module/matrix, i an int
1218RETURN:  the same type as I
1219PURPOSE: compute the Groebner basis of I with the algorithm, chosen via i
1220NOTE: By default and if i=0, slimgb is used; otherwise std does the job.
1221EXAMPLE: example engine; shows examples
1222"
1223{
1224  /* std - slimgb mix */
1225  def J;
1226  //  ideal J;
1227  if (i==0)
1228  {
1229    J = slimgb(I);
1230  }
1231  else
1232  {
1233    // without options -> strange! (ringlist?)
1234    intvec v = option(get);
1235    option(redSB);
1236    option(redTail);
1237    J = std(I);
1238    option(set, v);
1239  }
1240  return(J);
1241}
1242example
1243{
1244  "EXAMPLE:"; echo = 2;
1245  ring r = 0,(x,y),Dp;
1246  ideal I  = y*(x3-y2),x*(x3-y2);
1247  engine(I,0); // uses slimgb
1248  engine(I,1); // uses std
1249}
1250
1251proc insertGenerator (list #)
1252"USAGE:  insertGenerator(id,p[,k]);  id an ideal/module, p a poly/vector, k an optional int
1253RETURN:  same as id
1254PURPOSE: inserts p into the first argument at k-th index position and returns the enlarged object
1255NOTE:    If k is given, p is inserted at position k, otherwise (and by default),
1256@*       p is inserted at the beginning.
1257EXAMPLE: example insertGenerator; shows examples
1258"
1259{
1260  if (size(#) < 2)
1261  {
1262    ERROR("insertGenerator has to be called with at least 2 arguments (ideal/module,poly/vector)");
1263  }
1264  string inp1 = typeof(#[1]);
1265  if (inp1 == "ideal" || inp1 == "module")
1266  {
1267    if (inp1 == "ideal") { ideal id = #[1]; }
1268    else { module id = #[1]; }
1269  }
1270  else { ERROR("first argument has to be of type ideal or module"); }
1271  string inp2 = typeof(#[2]);
1272  if (inp2 == "poly" || inp2 == "vector")
1273  {
1274    if (inp2 =="poly") { poly f = #[2]; }
1275    else
1276    {
1277      if (inp1 == "ideal")
1278      {
1279        ERROR("second argument has to be a poly if first argument is an ideal");
1280      }
1281      else { vector f = #[2]; }
1282    }
1283  }
1284  else { ERROR("second argument has to be of type poly/vector"); }
1285  int n = ncols(id);
1286  int k = 1; // default
1287  if (size(#)>=3)
1288  {
1289    if (typeof(#[3]) == "int")
1290    {
1291      k = #[3];
1292      if (k<=0)
1293      {
1294        ERROR("third argument has to be positive");
1295      }
1296    }
1297    else { ERROR("third argument has to be of type int"); }
1298  }
1299  execute(inp1 +" J;");
1300  if (k == 1) { J = f,id; }
1301  else
1302  {
1303    if (k>n)
1304    {
1305      J = id;
1306      J[k] = f;
1307    }
1308    else // 1<k<=n
1309    {
1310      J[1..k-1] = id[1..k-1];
1311      J[k] = f;
1312      J[k+1..n+1] = id[k..n];
1313    }
1314  }
1315  return(J);
1316}
1317example
1318{
1319  "EXAMPLE:"; echo = 2;
1320  ring r = 0,(x,y,z),dp;
1321  ideal I = x^2,z^4;
1322  insertGenerator(I,y^3);
1323  insertGenerator(I,y^3,2);
1324  module M = I;
1325  insertGenerator(M,[x^3,y^2,z],2);
1326}
1327
1328proc deleteGenerator (list #)
1329"USAGE:  deleteGenerator(id,k);  id an ideal/module, k an int
1330RETURN:  same as id
1331PURPOSE: deletes the k-th generator from the first argument and returns the altered object
1332EXAMPLE: example insertGenerator; shows examples
1333"
1334{
1335  if (size(#) < 2)
1336  {
1337    ERROR("deleteGenerator has to be called with 2 arguments (ideal/module,int)");
1338  }
1339  string inp1 = typeof(#[1]);
1340  if (inp1 == "ideal" || inp1 == "module")
1341  {
1342    if (inp1 == "ideal") { ideal id = #[1]; }
1343    else { module id = #[1]; }
1344  }
1345  else { ERROR("first argument has to be of type ideal or module"); }
1346  string inp2 = typeof(#[2]);
1347  if (inp2 == "int" || inp2 == "number") { int k = int(#[2]); }
1348  else { ERROR("second argument has to be of type int"); }
1349  int n = ncols(id);
1350  if (n == 1) { ERROR(inp1+" must have more than one generator"); }
1351  if (k<=0 || k>n) { ERROR("second argument has to be in the range 1,...,"+string(n)); }
1352  execute(inp1 +" J;");
1353  if (k == 1) { J = id[2..n]; }
1354  else
1355  {
1356    if (k == n) { J = id[1..n-1]; }
1357    else
1358    {
1359      J[1..k-1] = id[1..k-1];
1360      J[k..n-1] = id[k+1..n];
1361    }
1362  }
1363  return(J);
1364}
1365example
1366{
1367  "EXAMPLE:"; echo = 2;
1368  ring r = 0,(x,y,z),dp;
1369  ideal I = x^2,y^3,z^4;
1370  deleteGenerator(I,2);
1371  module M = [x,y,z],[x2,y2,z2],[x3,y3,z3];;
1372  deleteGenerator(M,2);
1373}
1374
1375proc fl2poly(list L, string s)
1376"USAGE:  fl2poly(L,s); L a list, s a string
1377RETURN:  poly
1378PURPOSE: reconstruct a monic polynomial in one variable from its factorization
1379ASSUME:  s is a string with the name of some variable and
1380@*         L is supposed to consist of two entries:
1381@*         L[1] of the type ideal with the roots of a polynomial
1382@*         L[2] of the type intvec with the multiplicities of corr. roots
1383EXAMPLE: example fl2poly; shows examples
1384"
1385{
1386  if (varNum(s)==0)
1387  {
1388    ERROR("no such variable found in the basering"); return(0);
1389  }
1390  poly x = var(varNum(s));
1391  poly P = 1;
1392  int sl = size(L[1]);
1393  ideal RR = L[1];
1394  intvec IV = L[2];
1395  for(int i=1; i<= sl; i++)
1396  {
1397    if (IV[i] > 0)
1398    {
1399      P = P*((x-RR[i])^IV[i]);
1400    }
1401    else
1402    {
1403      printf("Ignored the root with incorrect multiplicity %s",string(IV[i]));
1404    }
1405  }
1406  return(P);
1407}
1408example
1409{
1410  "EXAMPLE:"; echo = 2;
1411  ring r = 0,(x,y,z,s),Dp;
1412  ideal I = -1,-4/3,-5/3,-2;
1413  intvec mI = 2,1,1,1;
1414  list BS = I,mI;
1415  poly p = fl2poly(BS,"s");
1416  p;
1417  factorize(p,2);
1418}
1419
1420static proc safeVarName (string s, string cv)
1421{
1422  string S;
1423  if (cv == "v")  { S = "," + "," + varstr(basering)  + ","; }
1424  if (cv == "c")  { S = "," + "," + charstr(basering) + ","; }
1425  if (cv == "cv") { S = "," + charstr(basering) + "," + varstr(basering) + ","; }
1426  s = "," + s + ",";
1427  while (find(S,s) <> 0)
1428  {
1429    s[1] = "@";
1430    s = "," + s;
1431  }
1432  s = s[2..size(s)-1];
1433  return(s)
1434}
1435
1436proc initialIdealW (ideal I, intvec u, intvec v, list #)
1437"USAGE:  initialIdealW(I,u,v [,s,t]);  I ideal, u,v intvecs, s,t optional ints
1438RETURN:  ideal, GB of initial ideal of the input ideal wrt the weights u and v
1439ASSUME:  The basering is the n-th Weyl algebra in characteristic 0 and  for all
1440@*       1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1 holds, i.e. the
1441@*       sequence of variables is given by x(1),...,x(n),D(1),...,D(n),
1442@*       where D(i) is the differential operator belonging to x(i).
1443PURPOSE: computes the initial ideal with respect to given weights.
1444NOTE:    u and v are understood as weight vectors for x(i) and D(i)
1445@*       respectively.
1446@*       If s<>0, @code{std} is used for Groebner basis computations,
1447@*       otherwise, and by default, @code{slimgb} is used.
1448@*       If t<>0, a matrix ordering is used for Groebner basis computations,
1449@*       otherwise, and by default, a block ordering is used.
1450DISPLAY: If printlevel=1, progress debug messages will be printed,
1451@*       if printlevel>=2, all the debug messages will be printed.
1452EXAMPLE: example initialIdealW; shows examples
1453"
1454{
1455
1456  if (dmodappassumeViolation())
1457  {
1458    ERROR("Basering is inappropriate: characteristic>0 or qring present");
1459  }
1460
1461  if (!isWeyl())
1462  {
1463    ERROR("Basering is not a Weyl algebra");
1464  }
1465
1466  int ppl = printlevel - voice +2;
1467  def save = basering;
1468  int n = nvars(save)/2;
1469  int N = 2*n+1;
1470  list RL = ringlist(save);
1471  int i;
1472  int whichengine = 0; // default
1473  int methodord   = 0; // default
1474  if (size(#)>0)
1475  {
1476    if (typeof(#[1])=="int" || typeof(#[1])=="number")
1477    {
1478      whichengine = int(#[1]);
1479    }
1480    if (size(#)>1)
1481    {
1482      if (typeof(#[2])=="int" || typeof(#[2])=="number")
1483      {
1484        methodord = int(#[2]);
1485      }
1486    }
1487  }
1488  if (char(save) <> 0) { ERROR("characteristic of basering has to be 0"); }
1489  if (isWeyl() == 0)   { ERROR("basering is not a Weyl algebra"); }
1490  for (i=1; i<=n; i++)
1491  {
1492    if (bracket(var(i+n),var(i))<>1)
1493    {
1494      ERROR(string(var(i+n))+" is not a differential operator for " +string(var(i)));
1495    }
1496  }
1497
1498  // 1. create  homogenized Weyl algebra
1499  // 1.1 create ordering
1500  intvec uv = u,v,0;
1501  list Lord = list(list("a",intvec(1:N)));
1502  list C0 = list("C",intvec(0));
1503  if (methodord == 0) // default: blockordering
1504  {
1505    Lord[2] = list("dp",intvec(1:(N-1)));
1506    Lord[3] = list("lp",intvec(1));
1507    Lord[4] = C0;
1508  }
1509  else // M() ordering
1510  {
1511    intmat @Ord[N][N];
1512    @Ord[1,1..N] = uv; @Ord[2,1..N] = 1:(N-1);
1513    for (i=1; i<=N-2; i++) { @Ord[2+i,N - i] = -1; }
1514    dbprint(ppl,"// the ordering matrix:",@Ord);
1515    Lord[2] = list("M",intvec(@Ord));
1516    Lord[3] = C0;
1517  }
1518  // 1.2 the new var
1519  list Lvar = RL[2]; Lvar[N] = safeVarName("h","cv");
1520  // 1.3 create commutative ring
1521  list L@@Dh = RL; L@@Dh = L@@Dh[1..4];
1522  L@@Dh[2] = Lvar; L@@Dh[3] = Lord;
1523  def @Dh = ring(L@@Dh); kill L@@Dh;
1524  setring @Dh;
1525  dbprint(ppl,"// the ring @Dh:",@Dh);
1526  // 1.4 create non-commutative relations
1527  matrix @relD[N][N];
1528  for (i=1; i<=n; i++) { @relD[i,n+i] = var(N)^2; }
1529  dbprint(ppl,"// nc relations:",@relD);
1530  def Dh = nc_algebra(1,@relD);
1531  setring Dh; kill @Dh;
1532  dbprint(ppl,"// computing in ring",Dh);
1533  // 2. Compute the initial ideal
1534  ideal I = imap(save,I);
1535  I = homog(I,h);
1536  // 2.1 the hard part: Groebner basis computation
1537  dbprint(ppl, "// starting Groebner basis computation with engine: "+string(whichengine));
1538  I = engine(I, whichengine);
1539  dbprint(ppl, "// finished Groebner basis computation");
1540  dbprint(ppl, "// I before dehomogenization is " +string(I));
1541  I = subst(I,var(N),1); // dehomogenization
1542  dbprint(ppl, "I after dehomogenization is " +string(I));
1543  // 2.2 the initial form
1544  I = inForm(I,uv);
1545  setring save;
1546  I = imap(Dh,I); kill Dh;
1547  // 2.3 the final GB
1548  dbprint(ppl, "// starting cosmetic Groebner basis computation with engine: "+string(whichengine));
1549  I = engine(I, whichengine);
1550  dbprint(ppl,"// finished cosmetic Groebner basis computation");
1551  return(I);
1552}
1553example
1554{
1555  "EXAMPLE:"; echo = 2;
1556  ring @D = 0,(x,Dx),dp;
1557  def D = Weyl();
1558  setring D;
1559  intvec u = -1; intvec v = 2;
1560  ideal I = x^2*Dx^2,x*Dx^4;
1561  ideal J = initialIdealW(I,u,v); J;
1562}
1563
1564proc initialMalgrange (poly f,list #)
1565"USAGE:  initialMalgrange(f,[,s,t,v]); f poly, s,t optional ints, v opt. intvec
1566RETURN:  ring, the Weyl algebra induced by basering, extended by two new vars
1567PURPOSE: computes the initial Malgrange ideal of a given poly wrt the weight
1568@*       vector (-1,0...,0,1,0,...,0) such that the weight of t is -1 and the
1569@*       weight of Dt is 1.
1570ASSUME:  The basering is commutative and of characteristic 0.
1571NOTE:    Activate the output ring with the @code{setring} command.
1572@*       The returned ring contains the ideal \"inF\", being the initial ideal
1573@*       of the Malgrange ideal of f.
1574@*       Varnames of the basering should not include t and Dt.
1575@*       If s<>0, @code{std} is used for Groebner basis computations,
1576@*       otherwise, and by default, @code{slimgb} is used.
1577@*       If t<>0, a matrix ordering is used for Groebner basis computations,
1578@*       otherwise, and by default, a block ordering is used.
1579@*       If v is a positive weight vector, v is used for homogenization
1580@*       computations, otherwise and by default, no weights are used.
1581DISPLAY: If printlevel=1, progress debug messages will be printed,
1582@*       if printlevel>=2, all the debug messages will be printed.
1583EXAMPLE: example initialMalgrange; shows examples
1584"
1585{
1586
1587  if (dmodappassumeViolation())
1588  {
1589    ERROR("Basering is inappropriate: characteristic>0 or qring present");
1590  }
1591
1592  if (!isCommutative())
1593  {
1594    ERROR("Basering must be commutative");
1595  }
1596
1597  int ppl = printlevel - voice +2;
1598  def save = basering;
1599  int n = nvars(save);
1600  int i;
1601  int whichengine = 0; // default
1602  int methodord   = 0; // default
1603  intvec u0 = 0;
1604  if (size(#)>0)
1605  {
1606    if (typeof(#[1])=="int" || typeof(#[1])=="number")
1607    {
1608      whichengine = int(#[1]);
1609    }
1610    if (size(#)>1)
1611    {
1612      if (typeof(#[2])=="int" || typeof(#[2])=="number")
1613      {
1614        methodord = int(#[2]);
1615      }
1616      if (size(#)>2)
1617      {
1618        if (typeof(#[3])=="intvec" && size(#[3])==n && allPositive(#[3])==1)
1619        {
1620          u0 = #[3];
1621        }
1622      }
1623    }
1624  }
1625  if (u0 == 0)
1626  {
1627    u0 = 1:n;
1628  }
1629  if (char(save) <> 0)      { ERROR("characteristic of basering has to be 0"); }
1630  // creating the homogenized extended Weyl algebra
1631  list RL = ringlist(save);
1632  RL = RL[1..4]; // if basering is commutative nc_algebra
1633  list C0 = list("C",intvec(0));
1634  // 1. get the weighted degree of f
1635  list Lord = list(list("wp",u0),C0);
1636  list L@r = RL;
1637  L@r[3] = Lord;
1638  def r = ring(L@r); kill L@r;
1639  setring r;
1640  poly f = imap(save,f);
1641  int d = deg(f);
1642  setring save; kill r;
1643  // 2. create homogenized extended Weyl algebra
1644  int N = 2*n+3;
1645  // 2.1 create names for vars
1646  string vart  = safeVarName("t","cv");
1647  string varDt = safeVarName("D"+vart,"cv");
1648  while (varDt <> "D"+vart)
1649  {
1650    vart  = safeVarName("@"+vart,"cv");
1651    varDt = safeVarName("D"+vart,"cv");
1652  }
1653  list Lvar,Lvarh;
1654  Lvar[1] = vart; Lvar[n+2] = varDt;
1655  for (i=1; i<=n; i++)
1656  {
1657    Lvar[i+1]   = string(var(i));
1658    Lvar[i+n+2] = safeVarName("D" + string(var(i)),"cv");
1659  }
1660  Lvarh = Lvar; Lvarh[N] = safeVarName("h","cv");
1661  //  2.2 create ordering
1662  intvec uv,@a,weighttx,weightD;
1663  uv[1] = -1; uv[n+2] = 1; uv[N] = 0;
1664  weighttx = d; weightD = 1;
1665  for (i=1; i<=n; i++)
1666  {
1667    weighttx[i+1] = u0[n-i+1];
1668    weightD[i+1]  = d+1-u0[n-i+1];
1669  }
1670  @a = weighttx,weightD,1;
1671  Lord[1] = list("a",@a);
1672  if (methodord == 0) // default: block ordering
1673  {
1674    Lord[2] = list("a",uv);
1675    Lord[3] = list("dp",intvec(1:(N-1)));
1676    Lord[4] = list("lp",intvec(1));
1677    Lord[5] = C0;
1678  }
1679  else // M() ordering
1680  {
1681    intmat @Ord[N][N];
1682    @Ord[1,1..N] = uv; @Ord[2,1..N] = 1:(N-1);
1683    for (i=1; i<=N-2; i++) { @Ord[2+i,N - i] = -1; }
1684    dbprint(ppl,"// weights for ordering: "+string(transpose(@a)));
1685    dbprint(ppl,"// the ordering matrix:",@Ord);
1686    Lord[2] = list("M",intvec(@Ord));
1687    Lord[3] = C0;
1688  }
1689  // 2.3 create commutative ring
1690  list L@@Dh = RL;
1691  L@@Dh[2] = Lvarh; L@@Dh[3] = Lord;
1692  def @Dh = ring(L@@Dh); kill L@@Dh;
1693  setring @Dh;
1694  dbprint(ppl,"// the ring @Dh:",@Dh);
1695  // var(1)=t, var(2..n+1) = x(1..n), var(n+2)=Dt, var(n+3..2*n+2)=D(1..n),var(2*n+3)=h
1696  // 2.4 create non-commutative relations
1697  matrix @relD[N][N];
1698  for (i=1; i<=n+1; i++) { @relD[i,n+1+i] = var(N)^(d+1); }
1699  dbprint(ppl,"// nc relations:",@relD);
1700  def Dh = nc_algebra(1,@relD);
1701  setring Dh; kill @Dh;
1702  dbprint(ppl,"// computing in ring",Dh);
1703  // 3. compute the initial ideal
1704  poly f = imap(save,f);
1705  f = homog(f,h);
1706  // 3.1 create the Malgrange ideal
1707  ideal I = var(1)-f;
1708  for (i=1; i<=n; i++)
1709  {
1710    I = I, var(n+2+i)+diff(f,var(i+1))*var(n+2);
1711  }
1712  // 3.2 the hard part: Groebner basis computation
1713  dbprint(ppl, "// starting Groebner basis computation with engine: "+string(whichengine));
1714  I = engine(I, whichengine);
1715  dbprint(ppl, "// finished Groebner basis computation");
1716  dbprint(ppl, "// I before dehomogenization is " +string(I));
1717  I = subst(I,var(N),1); // dehomogenization
1718  dbprint(ppl, "// I after dehomogenization is " +string(I));
1719  // 3.3 the initial form
1720  I = inForm(I,uv);
1721  // 3.4 create Weyl algebra
1722  setring save;
1723  Lord = list();
1724  Lord[1] = list("dp",intvec(1:(N-1)));
1725  Lord[2] = C0;
1726  list L@@D = RL;
1727  L@@D[2] = Lvar; L@@D[3] = Lord;
1728  def @D = ring(L@@D); kill L@@D;
1729  setring @D; def D = Weyl(); setring D;
1730  ideal I = imap(Dh,I);
1731  kill @D,Dh;
1732  // 3.5 the final GB
1733  dbprint(ppl, "// starting cosmetic Groebner basis computation with engine: "+string(whichengine));
1734  I = engine(I, whichengine);
1735  dbprint(ppl,"// finished cosmetic Groebner basis computation");
1736  ideal inF = I; attrib(inF,"isSB",1);
1737  export(inF);
1738  return(D);
1739}
1740example
1741{
1742  "EXAMPLE:"; echo = 2;
1743  ring r = 0,(x,y),dp;
1744  poly f = x^2+y^3+x*y^2;
1745  def D = initialMalgrange(f);
1746  setring D;
1747  inF;
1748  setring r;
1749  intvec v = 3,2;
1750  def D2 = initialMalgrange(f,1,0,1,v);
1751  setring D2;
1752  inF;
1753}
1754
1755proc dmodappassumeViolation()
1756{
1757  // returns Boolean : yes/no [for assume violation]
1758  // char K = 0
1759  // no qring
1760  if (  (size(ideal(basering)) >0) || (char(basering) >0) )
1761  {
1762    //    "ERROR: no qring is allowed";
1763    return(1);
1764  }
1765  return(0);
1766}
1767
1768proc bFactor (poly F)
1769"USAGE:  bFactor(f);  f poly
1770RETURN:  list
1771PURPOSE: tries to compute the roots of a univariate poly f
1772NOTE:    The output list consists of two or three entries:
1773@*       roots of f as an ideal, their multiplicities as intvec, and,
1774@*       if present, a third one being the product of all irreducible factors
1775@*       of degree greater than one, given as string.
1776DISPLAY: If printlevel=1, progress debug messages will be printed,
1777@*       if printlevel>=2, all the debug messages will be printed.
1778EXAMPLE: example bFactor; shows examples
1779"
1780{
1781  int ppl = printlevel - voice +2;
1782  def save = basering;
1783  ideal LI = variables(F);
1784  list L;
1785  int i = size(LI);
1786  if (i>1) { ERROR("poly has to be univariate")}
1787  if (i == 0)
1788  {
1789    dbprint(ppl,"// poly is constant");
1790    L = list(ideal(0),intvec(0),string(F));
1791    return(L);
1792  }
1793  poly v = LI[1];
1794  L = ringlist(save); L = L[1..4];
1795  L[2] = list(string(v));
1796  L[3] = list(list("dp",intvec(1)),list("C",intvec(0)));
1797  def @S = ring(L);
1798  setring @S;
1799  poly ir = 1; poly F = imap(save,F);
1800  list L = factorize(F);
1801  ideal I = L[1];
1802  intvec m = L[2];
1803  ideal II; intvec mm;
1804  for (i=2; i<=ncols(I); i++)
1805  {
1806    if (deg(I[i]) > 1)
1807    {
1808      ir = ir * I[i]^m[i];
1809    }
1810    else
1811    {
1812      II[size(II)+1] = I[i];
1813      mm[size(II)] = m[i];
1814    }
1815  }
1816  II = normalize(II);
1817  II = subst(II,var(1),0);
1818  II = -II;
1819  if (size(II)>0)
1820  {
1821    dbprint(ppl,"// found roots");
1822    dbprint(ppl-1,string(II));
1823  }
1824  else
1825  {
1826    dbprint(ppl,"// found no roots");
1827  }
1828  L = list(II,mm);
1829  if (ir <> 1)
1830  {
1831    dbprint(ppl,"// found irreducible factors");
1832    ir = cleardenom(ir);
1833    dbprint(ppl-1,string(ir));
1834    L = L + list(string(ir));
1835  }
1836  else
1837  {
1838    dbprint(ppl,"// no irreducible factors found");
1839  }
1840  setring save;
1841  L = imap(@S,L);
1842  return(L);
1843}
1844example
1845{
1846  "EXAMPLE:"; echo = 2;
1847  ring r = 0,(x,y),dp;
1848  bFactor((x^2-1)^2);
1849  bFactor((x^2+1)^2);
1850  bFactor((y^2+1/2)*(y+9)*(y-7));
1851}
Note: See TracBrowser for help on using the repository browser.