source: git/Singular/LIB/dmodapp.lib @ 5291ef

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