source: git/Singular/LIB/dmodapp.lib @ 6a07eb

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