source: git/Singular/LIB/dmodapp.lib @ dfb2c6

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