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

spielwiese
Last change on this file since d033934 was d033934, checked in by Viktor Levandovskyy <levandov@…>, 14 years ago
*levandov: doc changes and minor fixes git-svn-id: file:///usr/local/Singular/svn/trunk@13434 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 85.8 KB
Line 
1//////////////////////////////////////////////////////////////////////////////
2version="$Id$";
3category="Noncommutative";
4info="
5LIBRARY: dmodapp.lib     Applications of algebraic D-modules
6AUTHORS: Viktor Levandovskyy,  levandov@math.rwth-aachen.de
7@*       Daniel Andres,   daniel.andres@math.rwth-aachen.de
8
9Support: DFG Graduiertenkolleg 1632 'Experimentelle und konstruktive Algebra'
10
11OVERVIEW: Let K be a field of characteristic 0, R = K[x1,...,xN] and
12@* D be the Weyl algebra in variables x1,...,xN,d1,...,dN.
13@* In this library there are the following procedures for algebraic D-modules:
14@*
15@* - given a cyclic representation D/I of a holonomic module and a polynomial
16@* F in R, it is proved that the localization of D/I with respect to the mult.
17@* closed set of all powers of F is a holonomic D-module. Thus we aim to compute
18@* its cyclic representaion D/L for an ideal L in D. The procedures for the
19@* localization are DLoc, SDLoc and DLoc0.
20@*
21@* - annihilator in D of a given polynomial F from R as well as
22@* of a given rational function G/F from Quot(R). These can be computed via
23@* procedures annPoly resp. annRat.
24@*
25@* - Groebner bases with respect to weights (according to (SST), given an
26@* arbitrary integer vector containing weights for variables, one computes the
27@* homogenization of a given ideal relative to this vector, then one computes a
28@* Groebner basis and returns the dehomogenization of the result), initial
29@* forms and initial ideals in Weyl algebras with respect to a given weight
30@* vector can be computed with GBWeight, inForm, initialMalgrange and
31@* initialIdealW.
32@*
33@* - restriction and integration of a holonomic module D/I. Suppose I
34@* annihilates a function F(x1,...,xn). Our aim is to compute an ideal J
35@* directly from I, which annihilates
36@*   - F(0,...,0,xk,...,xn) in case of restriction or
37@*   - the integral of F with respect to x1,...,xm in case of integration.
38@* The corresponding procedures are restrictionModule, restrictionIdeal,
39@* integralModule and integralIdeal.
40@*
41@* - characteristic varieties defined by ideals in Weyl algebras can be computed
42@* with charVariety and charInfo.
43@*
44@* - appelF1, appelF2 and appelF4 return ideals in parametric Weyl algebras,
45@* which annihilate corresponding Appel hypergeometric functions.
46
47
48References:
49@* (SST) Saito, Sturmfels, Takayama 'Groebner Deformations of Hypergeometric
50@*         Differential Equations', Springer, 2000
51@* (OTW) Oaku, Takayama, Walther 'A Localization Algorithm for D-modules',
52@*         Journal of Symbolic Computation, 2000
53@* (OT)  Oaku, Takayama 'Algorithms for D-modules',
54@*         Journal of Pure and Applied Algebra, 1998
55
56
57PROCEDURES:
58
59annPoly(f);  computes annihilator of a polynomial f in the corr. Weyl algebra
60annRat(f,g); computes annihilator of rational function f/g in corr. Weyl algebra
61DLoc(I,f);   computes presentation of localization of D/I wrt symbolic power f^s
62SDLoc(I,f);  computes generic presentation of the localization of D/I wrt f^s
63DLoc0(I,f);  computes presentation of localization of D/I wrt f^s based on SDLoc
64
65GBWeight(I,u,v[,a,b]);       computes Groebner basis of I wrt a weight vector
66initialMalgrange(f[,s,t,v]); computes Groebner basis of initial Malgrange ideal
67initialIdealW(I,u,v[,s,t]);  computes initial ideal of  wrt a given weight
68inForm(f,w);                 computes initial form of poly/ideal wrt a weight
69
70restrictionIdeal(I,w[,eng,m,G]);  computes restriction ideal of I wrt w
71restrictionModule(I,w[,eng,m,G]); computes restriction module of I wrt w
72integralIdeal(I,w[,eng,m,G]);     computes integral ideal of I wrt w
73integralModule(I,w[,eng,m,G]);    computes integral module of I wrt w
74deRhamCohom(f[,eng,m]);           computes basis of n-th de Rham cohom. group
75deRhamCohomIdeal(I[,w,eng,m,G]);  computes basis of n-th de Rham cohom. group
76
77charVariety(I); computes characteristic variety of the ideal I
78charInfo(I);    computes char. variety, singular locus and primary decomp.
79isFsat(I,F);    checks whether the ideal I is F-saturated
80
81
82
83appelF1();     creates an ideal annihilating Appel F1 function
84appelF2();     creates an ideal annihilating Appel F2 function
85appelF4();     creates an ideal annihilating Appel F4 function
86
87fourier(I[,v]);        applies Fourier automorphism to ideal
88inverseFourier(I[,v]); applies inverse Fourier automorphism to ideal
89
90bFactor(F);    computes the roots of irreducible factors of an univariate poly
91intRoots(L);   dismisses non-integer roots from list in bFactor format
92poly2list(f);  decomposes the polynomial f into a list of terms and exponents
93fl2poly(L,s);  reconstructs a monic univariate polynomial from its factorization
94
95insertGenerator(id,p[,k]); inserts an element into an ideal/module
96deleteGenerator(id,k);     deletes the k-th element from an ideal/module
97
98engine(I,i);   computes a Groebner basis with the algorithm specified by i
99isInt(n);      checks whether number n is actually an int
100sortIntvec(v); sorts intvec
101
102
103SEE ALSO: bfun_lib, dmod_lib, dmodvar_lib, gmssing_lib
104
105
106KEYWORDS: D-module; annihilator of polynomial; annihilator of rational function;
107D-localization; localization of D-module; D-restriction; restriction of
108D-module; D-integration; integration of D-module; characteristic variety;
109Appel function; Appel hypergeometric function
110";
111
112
113/*
114CHANGELOG
11521.09.10 by DA:
116- restructured library for better readability
117- new / improved procs:
118  - toolbox: isInt, intRoots, sortIntvec
119  - GB wrt weights: GBWeight, initialIdealW rewritten using GBWeight
120  - restriction/integration: restrictionX, integralX where X in {Module, Ideal},
121    fourier, inverseFourier, deRhamCohom, deRhamCohomIdeal
122  - characteristic variety: charVariety, charInfo
123- added keywords for features
124- reformated help strings and examples in existing procs
125- added SUPPORT in header
126- added reference (OT)
127
12804.10.10 by DA:
129- incorporated suggestions by Oleksandr Motsak, among other:
130  - bugfixes for fl2poly, sortIntvec, annPoly, GBWeight
131  - enhanced functionality for deleteGenerator, inForm
132*/
133
134
135LIB "bfun.lib";     // for pIntersect etc
136LIB "dmod.lib";     // for SannfsBM etc
137LIB "general.lib";  // for sort
138LIB "gkdim.lib";
139LIB "nctools.lib";  // for isWeyl etc
140LIB "poly.lib";
141LIB "primdec.lib";  // for primdecGKZ
142LIB "qhmoduli.lib"; // for Max
143LIB "sing.lib";     // for slocus
144
145
146///////////////////////////////////////////////////////////////////////////////
147// testing for consistency of the library:
148proc testdmodapp()
149{
150  example annPoly;
151  example annRat;
152  example DLoc;
153  example SDLoc;
154  example DLoc0;
155  example GBWeight;
156  example initialMalgrange;
157  example initialIdealW;
158  example inForm;
159  example restrictionIdeal;
160  example restrictionModule;
161  example integralIdeal;
162  example integralModule;
163  example deRhamCohom;
164  example deRhamCohomIdeal;
165  example charVariety;
166  example charInfo;
167  example isFsat;
168  example appelF1;
169  example appelF2;
170  example appelF4;
171  example fourier;
172  example inverseFourier;
173  example bFactor;
174  example intRoots;
175  example poly2list;
176  example fl2poly;
177  example insertGenerator;
178  example deleteGenerator;
179  example engine;
180  example isInt;
181  example sortIntvec;
182}
183
184
185// general assumptions ////////////////////////////////////////////////////////
186
187static proc dmodappAssumeViolation()
188
189  // char K <> 0 or qring
190  if (  (size(ideal(basering)) >0) || (char(basering) >0) )
191  {
192    ERROR("Basering is inappropriate: characteristic>0 or qring present");
193  }
194  return();
195}
196
197static proc dmodappMoreAssumeViolation()
198{
199  // char K <> 0, qring
200  dmodappAssumeViolation();
201  // no Weyl algebra
202  if (isWeyl() == 0)
203  {
204    ERROR("Basering is not a Weyl algebra");
205  }
206  // wrong sequence of vars
207  int i,n;
208  n = nvars(basering)/2;
209  for (i=1; i<=n; i++)
210  {
211    if (bracket(var(i+n),var(i))<>1)
212    {
213      ERROR(string(var(i+n))+" is not a differential operator for " +string(var(i)));
214    }
215  }
216  return();
217}
218
219static proc safeVarName (string s, string cv)
220// assumes 's' to be a valid variable name
221// returns valid var name string @@..@s
222{
223  string S;
224  if (cv == "v")  { S = "," + "," + varstr(basering)  + ","; }
225  if (cv == "c")  { S = "," + "," + charstr(basering) + ","; }
226  if (cv == "cv") { S = "," + charstr(basering) + "," + varstr(basering) + ","; }
227  s = "," + s + ",";
228  while (find(S,s) <> 0)
229  {
230    s[1] = "@";
231    s = "," + s;
232  }
233  s = s[2..size(s)-1];
234  return(s)
235}
236
237static proc intLike (def i)
238{
239  string str = typeof(i);
240  if (str == "int" || str == "number" || str == "bigint")
241  {
242    return(1);
243  }
244  else
245  {
246    return(0);
247  }
248}
249
250
251// toolbox ////////////////////////////////////////////////////////////////////
252
253proc engine(def I, int i)
254"USAGE:  engine(I,i);  I  ideal/module/matrix, i an int
255RETURN:  the same type as I
256PURPOSE: compute the Groebner basis of I with the algorithm, chosen via i
257NOTE:    By default and if i=0, slimgb is used; otherwise std does the job.
258EXAMPLE: example engine; shows examples
259"
260{
261  /* std - slimgb mix */
262  def J;
263  //  ideal J;
264  if (i==0)
265  {
266    J = slimgb(I);
267  }
268  else
269  {
270    // without options -> strange! (ringlist?)
271    intvec v = option(get);
272    option(redSB);
273    option(redTail);
274    J = std(I);
275    option(set, v);
276  }
277  return(J);
278}
279example
280{
281  "EXAMPLE:"; echo = 2;
282  ring r = 0,(x,y),Dp;
283  ideal I  = y*(x3-y2),x*(x3-y2);
284  engine(I,0); // uses slimgb
285  engine(I,1); // uses std
286}
287
288proc poly2list (poly f)
289"USAGE:  poly2list(f); f a poly
290RETURN:  list of exponents and corresponding terms of f
291PURPOSE: converts a poly to a list of pairs consisting of intvecs (1st entry)
292@*       and polys (2nd entry), where the i-th pair contains the exponent of the
293@*       i-th term of f and the i-th term (with coefficient) itself.
294EXAMPLE: example poly2list; shows examples
295"
296{
297  list l;
298  int i = 1;
299  if (f == 0) // just for the zero polynomial
300  {
301    l[1] = list(leadexp(f), lead(f));
302  }
303  else
304  {
305    l[size(f)] = list(); // memory pre-allocation
306    while (f != 0)
307    {
308      l[i] = list(leadexp(f), lead(f));
309      f = f - lead(f);
310      i++;
311    }
312  }
313  return(l);
314}
315example
316{
317  "EXAMPLE:"; echo = 2;
318  ring r = 0,x,dp;
319  poly F = x;
320  poly2list(F);
321  ring r2 = 0,(x,y),dp;
322  poly F = x2y+5xy2;
323  poly2list(F);
324  poly2list(0);
325}
326
327proc fl2poly(list L, string s)
328"USAGE:  fl2poly(L,s); L a list, s a string
329RETURN:  poly
330PURPOSE: reconstruct a monic polynomial in one variable from its factorization
331ASSUME:  s is a string with the name of some variable and
332@*       L is supposed to consist of two entries:
333@*        - L[1] of the type ideal with the roots of a polynomial
334@*        - L[2] of the type intvec with the multiplicities of corr. roots
335EXAMPLE: example fl2poly; shows examples
336"
337{
338  if (varNum(s)==0)
339  {
340    ERROR(s+ " is no variable in the basering");
341  }
342  poly x = var(varNum(s));
343  poly P = 1;
344  ideal RR = L[1];
345  int sl = ncols(RR);
346  intvec IV = L[2];
347  if (sl <> nrows(IV))
348  {
349    ERROR("number of roots doesn't match number of multiplicites");
350  }
351  for(int i=1; i<=sl; i++)
352  {
353    if (IV[i] > 0)
354    {
355      P = P*((x-RR[i])^IV[i]);
356    }
357    else
358    {
359      printf("Ignored the root with incorrect multiplicity %s",string(IV[i]));
360    }
361  }
362  return(P);
363}
364example
365{
366  "EXAMPLE:"; echo = 2;
367  ring r = 0,(x,y,z,s),Dp;
368  ideal I = -1,-4/3,0,-5/3,-2;
369  intvec mI = 2,1,2,1,1;
370  list BS = I,mI;
371  poly p = fl2poly(BS,"s");
372  p;
373  factorize(p,2);
374}
375
376proc insertGenerator (list #)
377"USAGE:  insertGenerator(id,p[,k]);
378@*       id an ideal/module, p a poly/vector, k an optional int
379RETURN:  of the same type as id
380PURPOSE: inserts p into id at k-th position and returns the enlarged object
381NOTE:    If k is given, p is inserted at position k, otherwise (and by default),
382@*       p is inserted at the beginning (k=1).
383SEE ALSO: deleteGenerator
384EXAMPLE: example insertGenerator; shows examples
385"
386{
387  if (size(#) < 2)
388  {
389    ERROR("insertGenerator has to be called with at least 2 arguments (ideal/module,poly/vector)");
390  }
391  string inp1 = typeof(#[1]);
392  if (inp1 == "ideal" || inp1 == "module")
393  {
394    def id = #[1];
395  }
396  else { ERROR("first argument has to be of type ideal or module"); }
397  string inp2 = typeof(#[2]);
398  if (inp2 == "poly" || inp2 == "vector")
399  {
400    def f = #[2];
401  }
402  else { ERROR("second argument has to be of type poly/vector"); }
403  if (inp1 == "ideal" && inp2 == "vector")
404  {
405    ERROR("second argument has to be a polynomial if first argument is an ideal");
406  }
407  // don't check module/poly combination due to auto-conversion
408  //   if (inp1 == "module" && inp2 == "poly")
409  //   {
410  //     ERROR("second argument has to be a vector if first argument is a module");
411  //   }
412  int n = ncols(id);
413  int k = 1; // default
414  if (size(#)>=3)
415  {
416    if (intLike(#[3]))
417    {
418      k = int(#[3]);
419      if (k<=0)
420      {
421        ERROR("third argument has to be positive");
422      }
423    }
424    else { ERROR("third argument has to be of type int"); }
425  }
426  execute(inp1 +" J;");
427  if (k == 1) { J = f,id; }
428  else
429  {
430    if (k>n)
431    {
432      J = id;
433      J[k] = f;
434    }
435    else // 1<k<=n
436    {
437      J[n+1] = id[n]; // preinit
438      J[1..k-1] = id[1..k-1];
439      J[k] = f;
440      J[k+1..n+1] = id[k..n];
441    }
442  }
443  return(J);
444}
445example
446{
447  "EXAMPLE:"; echo = 2;
448  ring r = 0,(x,y,z),dp;
449  ideal I = x^2,z^4;
450  insertGenerator(I,y^3);
451  insertGenerator(I,y^3,2);
452  module M = I*gen(3);
453  insertGenerator(M,[x^3,y^2,z],2);
454  insertGenerator(M,x+y+z,4);
455}
456
457proc deleteGenerator (def id, int k)
458"USAGE:   deleteGenerator(id,k);  id an ideal/module, k an int
459RETURN:   of the same type as id
460PURPOSE:  deletes the k-th generator from the first argument and returns
461@*        the altered object
462SEE ALSO: insertGenerator
463EXAMPLE:  example deleteGenerator; shows examples
464"
465{
466  string inp1 = typeof(id);
467  if (inp1 <> "ideal" && inp1 <> "module")
468  {
469    ERROR("first argument has to be of type ideal or module");
470  }
471  execute(inp1 +" J;");
472  int n = ncols(id);
473  if (n == 1 && k == 1) { return(J); }
474  if (k<=0 || k>n)
475  {
476    ERROR("second argument has to be in the range 1,...,"+string(n));
477  }
478  J[n-1] = 0; // preinit
479  if (k == 1) { J = id[2..n]; }
480  else
481  {
482    if (k == n) { J = id[1..n-1]; }
483    else
484    {
485      J[1..k-1] = id[1..k-1];
486      J[k..n-1] = id[k+1..n];
487    }
488  }
489  return(J);
490}
491example
492{
493  "EXAMPLE:"; echo = 2;
494  ring r = 0,(x,y,z),dp;
495  ideal I = x^2,y^3,z^4;
496  deleteGenerator(I,2);
497  module M = [x,y,z],[x2,y2,z2],[x3,y3,z3];
498  print(deleteGenerator(M,2));
499  M = M[1];
500  deleteGenerator(M,1);
501}
502
503proc bFactor (poly F)
504"USAGE:  bFactor(f);  f poly
505RETURN:  list of ideal and intvec and possibly a string
506PURPOSE: tries to compute the roots of a univariate poly f
507NOTE:    The output list consists of two or three entries:
508@*       roots of f as an ideal, their multiplicities as intvec, and,
509@*       if present, a third one being the product of all irreducible factors
510@*       of degree greater than one, given as string.
511@*       If f is the zero polynomial or if f has no roots in the ground field,
512@*       this is encoded as root 0 with multiplicity 0.
513DISPLAY: If printlevel=1, progress debug messages will be printed,
514@*       if printlevel>=2, all the debug messages will be printed.
515EXAMPLE: example bFactor; shows examples
516"
517{
518  int ppl = printlevel - voice +2;
519  def save = basering;
520  ideal LI = variables(F);
521  list L;
522  int i = size(LI);
523  if (i>1) { ERROR("poly has to be univariate")}
524  if (i == 0)
525  {
526    dbprint(ppl,"// poly is constant");
527    L = list(ideal(0),intvec(0),string(F));
528    return(L);
529  }
530  poly v = LI[1];
531  L = ringlist(save); L = L[1..4];
532  L[2] = list(string(v));
533  L[3] = list(list("dp",intvec(1)),list("C",intvec(0)));
534  def @S = ring(L);
535  setring @S;
536  poly ir = 1; poly F = imap(save,F);
537  list L = factorize(F);
538  ideal I = L[1];
539  intvec m = L[2];
540  ideal II; intvec mm;
541  for (i=2; i<=ncols(I); i++)
542  {
543    if (deg(I[i]) > 1)
544    {
545      ir = ir * I[i]^m[i];
546    }
547    else
548    {
549      II[size(II)+1] = I[i];
550      mm[size(II)] = m[i];
551    }
552  }
553  II = normalize(II);
554  II = subst(II,var(1),0);
555  II = -II;
556  if (size(II)>0)
557  {
558    dbprint(ppl,"// found roots");
559    dbprint(ppl-1,string(II));
560  }
561  else
562  {
563    dbprint(ppl,"// found no roots");
564  }
565  L = list(II,mm);
566  if (ir <> 1)
567  {
568    dbprint(ppl,"// found irreducible factors");
569    ir = cleardenom(ir);
570    dbprint(ppl-1,string(ir));
571    L = L + list(string(ir));
572  }
573  else
574  {
575    dbprint(ppl,"// no irreducible factors found");
576  }
577  setring save;
578  L = imap(@S,L);
579  return(L);
580}
581example
582{
583  "EXAMPLE:"; echo = 2;
584  ring r = 0,(x,y),dp;
585  bFactor((x^2-1)^2);
586  bFactor((x^2+1)^2);
587  bFactor((y^2+1/2)*(y+9)*(y-7));
588  bFactor(1);
589  bFactor(0);
590}
591
592proc isInt (number n)
593"USAGE:  isInt(n); n a number
594RETURN:  int, 1 if n is an integer or 0 otherwise
595PURPOSE: check whether given object of type number is actually an int
596NOTE:    Parameters are treated as integers.
597EXAMPLE: example isInt; shows an example
598"
599{
600  number d = denominator(n);
601  if (d<>1)
602  {
603    return(0);
604  }
605  else
606  {
607    return(1);
608  }
609}
610example
611{
612  "EXAMPLE:"; echo = 2;
613  ring r = 0,x,dp;
614  number n = 4/3;
615  isInt(n);
616  n = 11;
617  isInt(n);
618}
619
620proc intRoots (list l)
621"USAGE:  isInt(L); L a list
622RETURN:  list
623PURPOSE: extracts integer roots from a list given in @code{bFactor} format
624ASSUME:  The input list must be given in the format of @code{bFactor}.
625NOTE:    Parameters are treated as integers.
626SEE ALSO: bFactor
627EXAMPLE: example intRoots; shows an example
628"
629{
630  int wronginput;
631  int sl = size(l);
632  if (sl>0)
633  {
634    if (typeof(l[1])<>"ideal"){wronginput = 1;}
635    if (sl>1)
636    {
637      if (typeof(l[2])<>"intvec"){wronginput = 1;}
638      if (sl>2)
639      {
640        if (typeof(l[3])<>"string"){wronginput = 1;}
641        if (sl>3){wronginput = 1;}
642      }
643    }
644  }
645  if (sl<2){wronginput = 1;}
646  if (wronginput)
647  {
648    ERROR("Given list has wrong format.");
649  }
650  int i,j;
651  ideal l1 = l[1];
652  int n = ncols(l1);
653  j = 1;
654  ideal I;
655  intvec v;
656  for (i=1; i<=n; i++)
657  {
658    if (size(l1[j])>1) // poly not number
659    {
660      ERROR("Ideal in list has wrong format.");
661    }
662    if (isInt(leadcoef(l1[i])))
663    {
664      I[j] = l1[i];
665      v[j] = l[2][i];
666      j++;
667    }
668  }
669  return(list(I,v));
670}
671example
672{
673  "EXAMPLE:"; echo = 2;
674  ring r = 0,x,dp;
675  list L = bFactor((x-4/3)*(x+3)^2*(x-5)^4); L;
676  intRoots(L);
677}
678
679proc sortIntvec (intvec v)
680"USAGE:  sortIntvec(v); v an intvec
681RETURN:  list of two intvecs
682PURPOSE: sorts an intvec
683NOTE:    In the output list L, the first entry consists of the entries of v
684@*       satisfying L[1][i] >= L[1][i+1]. The second entry is a permutation
685@*       such that v[L[2]] = L[1].
686@*       Unlike in the procedure @code{sort}, zeros are not dismissed.
687SEE ALSO: sort
688EXAMPLE: example sortIntvec; shows examples
689"
690{
691  int i;
692  intvec vpos,vzero,vneg,vv,sortv,permv;
693  list l;
694  for (i=1; i<=nrows(v); i++)
695  {
696    if (v[i]>0)
697    {
698      vpos = vpos,i;
699    }
700    else
701    {
702      if (v[i]==0)
703      {
704        vzero = vzero,i;
705      }
706      else // v[i]<0
707      {
708        vneg = vneg,i;
709      }
710    }
711  }
712  if (size(vpos)>1)
713  {
714    vpos = vpos[2..size(vpos)];
715    vv = v[vpos];
716    l = sort(vv);
717    vv = l[1];
718    vpos = vpos[l[2]];
719    sortv = vv[size(vv)..1];
720    permv = vpos[size(vv)..1];
721  }
722  if (size(vzero)>1)
723  {
724    vzero = vzero[2..size(vzero)];
725    permv = permv,vzero;
726    sortv = sortv,0:size(vzero);
727  }
728  if (size(vneg)>1)
729  {
730    vneg = vneg[2..size(vneg)];
731    vv = -v[vneg];
732    l = sort(vv);
733    vv = -l[1];
734    vneg = vneg[l[2]];
735    sortv = sortv,vv;
736    permv = permv,vneg;
737  }
738  if (permv[1]==0)
739  {
740    sortv = sortv[2..size(sortv)];
741    permv = permv[2..size(permv)];
742  }
743  return(list(sortv,permv));
744}
745example
746{
747  "EXAMPLE:"; echo = 2;
748  ring r = 0,x,dp;
749  intvec v = -1,0,1,-2,0,2;
750  list L = sortIntvec(v); L;
751  v[L[2]];
752  v = -3,0;
753  sortIntvec(v);
754  v = 0,-3;
755  sortIntvec(v);
756}
757
758
759// F-saturation ///////////////////////////////////////////////////////////////
760
761proc isFsat(ideal I, poly F)
762"USAGE:  isFsat(I, F);  I an ideal, F a poly
763RETURN:  int, 1  if I is F-saturated and 0 otherwise
764PURPOSE: checks whether the ideal I is F-saturated
765NOTE:    We check indeed that Ker(D--> F--> D/I) is 0, where D is the basering.
766EXAMPLE: example isFsat; shows examples
767"
768{
769  /* checks whether I is F-saturated, that is Ke  (D -F-> D/I) is 0 */
770  /* works in any algebra */
771  /*  for simplicity : later check attrib */
772  /* returns 1 if I is F-sat */
773  if (attrib(I,"isSB")!=1)
774  {
775    I = groebner(I);
776  }
777  matrix @M = matrix(I);
778  matrix @F[1][1] = F;
779  def S = modulo(module(@F),module(@M));
780  S = NF(S,I);
781  S = groebner(S);
782  return( (gkdim(S) == -1) );
783}
784example
785{
786  "EXAMPLE:"; echo = 2;
787  ring r = 0,(x,y),dp;
788  poly G = x*(x-y)*y;
789  def A = annfs(G);
790  setring A;
791  poly F = x3-y2;
792  isFsat(LD,F);
793  ideal J = LD*F;
794  isFsat(J,F);
795}
796
797
798// annihilators ///////////////////////////////////////////////////////////////
799
800proc annRat(poly g, poly f)
801"USAGE:   annRat(g,f);  f, g polynomials
802RETURN:   ring (a Weyl algebra) containing an ideal 'LD'
803PURPOSE:  compute the annihilator of the rational function g/f in the
804@*        corresponding Weyl algebra
805ASSUME:   basering is commutative and over a field of characteristic 0
806NOTE:     Activate the output ring with the @code{setring} command.
807@*        In the output ring, the ideal 'LD' (in Groebner basis) is the
808@*        annihilator of g/f.
809@*        The algorithm uses the computation of Ann(f^{-1}) via D-modules,
810@*        see (SST).
811DISPLAY:  If printlevel =1, progress debug messages will be printed,
812@*        if printlevel>=2, all the debug messages will be printed.
813SEE ALSO: annPoly
814EXAMPLE:  example annRat; shows examples
815"
816{
817  // assumption check
818  dmodappAssumeViolation();
819  if (!isCommutative())
820  {
821    ERROR("Basering must be commutative.");
822  }
823  // assumptions: f is not a constant
824  if (f==0) { ERROR("the denominator f cannot be zero"); }
825  if ((leadexp(f) == 0) && (size(f) < 2))
826  {
827    // f = const, so use annPoly
828    g = g/f;
829    def @R = annPoly(g);
830    return(@R);
831  }
832  // computes the annihilator of g/f
833  def save = basering;
834  int ppl = printlevel-voice+2;
835  dbprint(ppl,"// -1-[annRat] computing the ann f^s");
836  def  @R1 = SannfsBM(f);
837  setring @R1;
838  poly f = imap(save,f);
839  int i,mir;
840  int isr = 0; // checkRoot1(LD,f,1); // roots are negative, have to enter positive int
841  if (!isr)
842  {
843    // -1 is not the root
844    // find the m.i.r iteratively
845    mir = 0;
846    for(i=nvars(save)+1; i>=1; i--)
847    {
848      isr =  checkRoot1(LD,f,i);
849      if (isr) { mir =-i; break; }
850    }
851    if (mir ==0)
852    {
853      ERROR("No integer root found! Aborting computations, inform the authors!");
854    }
855    // now mir == i is m.i.r.
856  }
857  else
858  {
859    // -1 is the m.i.r
860    mir = -1;
861  }
862  dbprint(ppl,"// -2-[annRat] the minimal integer root is ");
863  dbprint(ppl-1, mir);
864  // use annfspecial
865  dbprint(ppl,"// -3-[annRat] running annfspecial ");
866  ideal AF = annfspecial(LD,f,mir,-1); // ann f^{-1}
867  //  LD = subst(LD,s,j);
868  //  LD = engine(LD,0);
869  // modify the ring: throw s away
870  // output ring comes from SannfsBM
871  list U = ringlist(@R1);
872  list tmp; // variables
873  for(i=1; i<=size(U[2])-1; i++)
874  {
875    tmp[i] = U[2][i];
876  }
877  U[2] = tmp;
878  tmp = 0;
879  tmp[1] = U[3][1]; // x,Dx block
880  tmp[2] = U[3][3]; // module block
881  U[3] = tmp;
882  tmp = 0;
883  tmp = U[1],U[2],U[3],U[4];
884  def @R2 = ring(tmp);
885  setring @R2;
886  // now supply with Weyl algebra relations
887  int N = nvars(@R2)/2;
888  matrix @D[2*N][2*N];
889  for(i=1; i<=N; i++)
890  {
891    @D[i,N+i]=1;
892  }
893  def @R3 = nc_algebra(1,@D);
894  setring @R3;
895  dbprint(ppl,"// - -[annRat] ring without s is ready:");
896  dbprint(ppl-1,@R3);
897  poly g = imap(save,g);
898  matrix G[1][1] = g;
899  matrix LL = matrix(imap(@R1,AF));
900  kill @R1;   kill @R2;
901  dbprint(ppl,"// -4-[annRat] running modulo");
902  ideal LD  = modulo(G,LL);
903  dbprint(ppl,"// -4-[annRat] running GB on the final result");
904  LD  = engine(LD,0);
905  export LD;
906  return(@R3);
907}
908example
909{
910  "EXAMPLE:"; echo = 2;
911  ring r = 0,(x,y),dp;
912  poly g = 2*x*y;  poly f = x^2 - y^3;
913  def B = annRat(g,f);
914  setring B;
915  LD;
916  // Now, compare with the output of Macaulay2:
917  ideal tst = 3*x*Dx + 2*y*Dy + 1, y^3*Dy^2 - x^2*Dy^2 + 6*y^2*Dy + 6*y,
9189*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;
919 option(redSB); option(redTail);
920 LD = groebner(LD);
921 tst = groebner(tst);
922 print(matrix(NF(LD,tst)));  print(matrix(NF(tst,LD)));
923 // So, these two answers are the same
924}
925
926proc annPoly(poly f)
927"USAGE:   annPoly(f);  f a poly
928RETURN:   ring (a Weyl algebra) containing an ideal 'LD'
929PURPOSE:  compute the complete annihilator ideal of f in the corresponding
930@*        Weyl algebra
931ASSUME:   basering is commutative and over a field of characteristic 0
932NOTE:     Activate the output ring with the @code{setring} command.
933@*        In the output ring, the ideal 'LD' (in Groebner basis) is the
934@*        annihilator.
935DISPLAY:  If printlevel =1, progress debug messages will be printed,
936@*        if printlevel>=2, all the debug messages will be printed.
937SEE ALSO: annRat
938EXAMPLE:  example annPoly; shows examples
939"
940{
941  // assumption check
942  dmodappAssumeViolation();
943  if (!isCommutative())
944  {
945    ERROR("Basering must be commutative.");
946  }
947  // computes a system of linear PDEs with polynomial coeffs for f
948  def save = basering;
949  list L = ringlist(save);
950  list Name = L[2];
951  int N = nvars(save);
952  int i;
953  for (i=1; i<=N; i++)
954  {
955    Name[N+i] = safeVarName("D"+Name[i],"cv"); // concat
956  }
957  L[2] = Name;
958  def @R = ring(L);
959  setring @R;
960  def @@R = Weyl();
961  setring @@R;
962  kill @R;
963  matrix M[1][N];
964  for (i=1; i<=N; i++)
965  {
966    M[1,i] = var(N+i);
967  }
968  matrix F[1][1] = imap(save,f);
969  def I = modulo(module(F),module(M));
970  ideal LD = I;
971  LD = groebner(LD);
972  export LD;
973  return(@@R);
974}
975example
976{
977  "EXAMPLE:"; echo = 2;
978  ring r = 0,(x,y,z),dp;
979  poly f = x^2*z - y^3;
980  def A = annPoly(f);
981  setring A;    // A is the 3rd Weyl algebra in 6 variables
982  LD;           // the Groebner basis of annihilator
983  gkdim(LD);    // must be 3 = 6/2, since A/LD is holonomic module
984  NF(Dy^4, LD); // must be 0 since Dy^4 clearly annihilates f
985  poly f = imap(r,f);
986  NF(LD*f,std(ideal(Dx,Dy,Dz))); // must be zero if LD indeed annihilates f
987}
988
989
990
991// localizations //////////////////////////////////////////////////////////////
992
993proc DLoc(ideal I, poly F)
994"USAGE:  DLoc(I, f);  I an ideal, f a poly
995RETURN:  list of ideal and list
996ASSUME:  the basering is a Weyl algebra
997PURPOSE: compute the presentation of the localization of D/I w.r.t. f^s
998NOTE:    In the output list L,
999@*       - L[1] is an ideal (given as Groebner basis), the presentation of the
1000@*       localization,
1001@*       - L[2] is a list containing roots with multiplicities of Bernstein
1002@*       polynomial of (D/I)_f.
1003DISPLAY: If printlevel =1, progress debug messages will be printed,
1004@*       if printlevel>=2, all the debug messages will be printed.
1005EXAMPLE: example DLoc; shows examples
1006"
1007{
1008  /* runs SDLoc and DLoc0 */
1009  /* assume: run from Weyl algebra */
1010  dmodappAssumeViolation();
1011  if (!isWeyl())
1012  {
1013    ERROR("Basering is not a Weyl algebra");
1014  }
1015  int old_printlevel = printlevel;
1016  printlevel=printlevel+1;
1017  def @R = basering;
1018  def @R2 = SDLoc(I,F);
1019  setring @R2;
1020  poly F = imap(@R,F);
1021  def @R3 = DLoc0(LD,F);
1022  setring @R3;
1023  ideal bs = BS[1];
1024  intvec m = BS[2];
1025  setring @R;
1026  ideal LD0 = imap(@R3,LD0);
1027  ideal bs = imap(@R3,bs);
1028  list BS; BS[1] = bs; BS[2] = m;
1029  kill @R3;
1030  printlevel = old_printlevel;
1031  return(list(LD0,BS));
1032}
1033example;
1034{
1035  "EXAMPLE:"; echo = 2;
1036  ring r = 0,(x,y,Dx,Dy),dp;
1037  def R = Weyl();    setring R; // Weyl algebra in variables x,y,Dx,Dy
1038  poly F = x2-y3;
1039  ideal I = (y^3 - x^2)*Dx - 2*x, (y^3 - x^2)*Dy + 3*y^2; // I = Dx*F, Dy*F;
1040  // I is not holonomic, since its dimension is not 4/2=2
1041  gkdim(I);
1042  list L = DLoc(I, x2-y3);
1043  L[1]; // localized module (R/I)_f is isomorphic to R/LD0
1044  L[2]; // description of b-function for localization
1045}
1046
1047proc DLoc0(ideal I, poly F)
1048"USAGE:  DLoc0(I, f);  I an ideal, f a poly
1049RETURN:  ring (a Weyl algebra) containing an ideal 'LD0' and a list 'BS'
1050PURPOSE: compute the presentation of the localization of D/I w.r.t. f^s,
1051@*       where D is a Weyl Algebra, based on the output of procedure SDLoc
1052ASSUME:  the basering is similar to the output ring of SDLoc procedure
1053NOTE:    activate the output ring with the @code{setring} command. In this ring,
1054@*       - the ideal LD0 (given as Groebner basis) is the presentation of the
1055@*       localization,
1056@*       - the list BS contains roots and multiplicities of Bernstein
1057@*       polynomial of (D/I)_f.
1058DISPLAY: If printlevel =1, progress debug messages will be printed,
1059@*       if printlevel>=2, all the debug messages will be printed.
1060EXAMPLE: example DLoc0; shows examples
1061"
1062{
1063  dmodappAssumeViolation();
1064  /* assume: to be run in the output ring of SDLoc */
1065  /* doing: add F, eliminate vars*Dvars, factorize BS */
1066  /* analogue to annfs0 */
1067  def @R2 = basering;
1068  // we're in D_n[s], where the elim ord for s is set
1069  ideal J = NF(I,std(F));
1070  // make leadcoeffs positive
1071  int i;
1072  for (i=1; i<= ncols(J); i++)
1073  {
1074    if (leadcoef(J[i]) <0 )
1075    {
1076      J[i] = -J[i];
1077    }
1078  }
1079  J = J,F;
1080  ideal M = groebner(J);
1081  int Nnew = nvars(@R2);
1082  ideal K2 = nselect(M,1..Nnew-1);
1083  int ppl = printlevel-voice+2;
1084  dbprint(ppl,"// -1-1- _x,_Dx are eliminated in basering");
1085  dbprint(ppl-1, K2);
1086  // the ring @R3 and the search for minimal negative int s
1087  ring @R3 = 0,s,dp;
1088  dbprint(ppl,"// -2-1- the ring @R3 = K[s] is ready");
1089  ideal K3 = imap(@R2,K2);
1090  poly p = K3[1];
1091  dbprint(ppl,"// -2-2- attempt the factorization");
1092  list PP = factorize(p);          //with constants and multiplicities
1093  ideal bs; intvec m;             //the Bernstein polynomial is monic, so we are not interested in constants
1094  for (i=2; i<= size(PP[1]); i++)  //we delete P[1][1] and P[2][1]
1095  {
1096    bs[i-1] = PP[1][i];
1097    m[i-1]  = PP[2][i];
1098  }
1099  ideal bbs; int srat=0; int HasRatRoots = 0;
1100  int sP;
1101  for (i=1; i<= size(bs); i++)
1102  {
1103    if (deg(bs[i]) == 1)
1104    {
1105      bbs = bbs,bs[i];
1106    }
1107  }
1108  if (size(bbs)==0)
1109  {
1110    dbprint(ppl-1,"// -2-3- factorization: no rational roots");
1111    //    HasRatRoots = 0;
1112    HasRatRoots = 1; // s0 = -1 then
1113    sP = -1;
1114    // todo: return ideal with no subst and a b-function unfactorized
1115  }
1116  else
1117  {
1118    // exist rational roots
1119    dbprint(ppl-1,"// -2-3- factorization: rational roots found");
1120    HasRatRoots = 1;
1121    //    dbprint(ppl-1,bbs);
1122    bbs = bbs[2..ncols(bbs)];
1123    ideal P = bbs;
1124    dbprint(ppl-1,P);
1125    srat = size(bs) - size(bbs);
1126    // define minIntRoot on linear factors or find out that it doesn't exist
1127    intvec vP;
1128    number nP;
1129    P = normalize(P); // now leadcoef = 1
1130    P = ideal(matrix(lead(P))-matrix(P));
1131    sP = size(P);
1132    int cnt = 0;
1133    for (i=1; i<=sP; i++)
1134    {
1135      nP = leadcoef(P[i]);
1136      if ( (nP - int(nP)) == 0 )
1137      {
1138        cnt++;
1139        vP[cnt] = int(nP);
1140      }
1141    }
1142//     if ( size(vP)>=2 )
1143//     {
1144//       vP = vP[2..size(vP)];
1145//     }
1146    if ( size(vP)==0 )
1147    {
1148      // no roots!
1149      dbprint(ppl,"// -2-4- no integer root, setting s0 = -1");
1150      sP = -1;
1151      //      HasRatRoots = 0; // older stuff, here we do substitution
1152      HasRatRoots = 1;
1153    }
1154    else
1155    {
1156      HasRatRoots = 1;
1157      sP = -Max(-vP);
1158      dbprint(ppl,"// -2-4- minimal integer root found");
1159      dbprint(ppl-1, sP);
1160      //    int sP = minIntRoot(bbs,1);
1161//       P =  normalize(P);
1162//       bs = -subst(bs,s,0);
1163      if (sP >=0)
1164      {
1165        dbprint(ppl,"// -2-5- nonnegative root, setting s0 = -1");
1166        sP = -1;
1167      }
1168      else
1169      {
1170        dbprint(ppl,"// -2-5- the root is negative");
1171      }
1172    }
1173  }
1174
1175  if (HasRatRoots)
1176  {
1177    setring @R2;
1178    K2 = subst(I,s,sP);
1179    // IF min int root exists ->
1180    // create the ordinary Weyl algebra and put the result into it,
1181    // thus creating the ring @R5
1182    // ELSE : return the same ring with new objects
1183    // keep: N, i,j,s, tmp, RL
1184    Nnew = Nnew - 1; // former 2*N;
1185    // list RL = ringlist(save);  // is defined earlier
1186    //  kill Lord, tmp, iv;
1187    list L = 0;
1188    list Lord, tmp;
1189    intvec iv;
1190    list RL = ringlist(basering);
1191    L[1] = RL[1];
1192    L[4] = RL[4];  //char, minpoly
1193    // check whether vars have admissible names -> done earlier
1194    // list Name = RL[2]M
1195    // DName is defined earlier
1196    list NName; // = RL[2]; // skip the last var 's'
1197    for (i=1; i<=Nnew; i++)
1198    {
1199      NName[i] =  RL[2][i];
1200    }
1201    L[2] = NName;
1202    // dp ordering;
1203    string s = "iv=";
1204    for (i=1; i<=Nnew; i++)
1205    {
1206      s = s+"1,";
1207    }
1208    s[size(s)] = ";";
1209    execute(s);
1210    tmp     = 0;
1211    tmp[1]  = "dp";  // string
1212    tmp[2]  = iv;  // intvec
1213    Lord[1] = tmp;
1214    kill s;
1215    tmp[1]  = "C";
1216    iv = 0;
1217    tmp[2]  = iv;
1218    Lord[2] = tmp;
1219    tmp     = 0;
1220    L[3]    = Lord;
1221    // we are done with the list
1222    // Add: Plural part
1223    def @R4@ = ring(L);
1224    setring @R4@;
1225    int N = Nnew/2;
1226    matrix @D[Nnew][Nnew];
1227    for (i=1; i<=N; i++)
1228    {
1229      @D[i,N+i]=1;
1230    }
1231    def @R4 = nc_algebra(1,@D);
1232    setring @R4;
1233    kill @R4@;
1234    dbprint(ppl,"// -3-1- the ring @R4 is ready");
1235    dbprint(ppl-1, @R4);
1236    ideal K4 = imap(@R2,K2);
1237    intvec vopt = option(get);
1238    option(redSB);
1239    dbprint(ppl,"// -3-2- the final cosmetic std");
1240    K4 = groebner(K4);  // std does the job too
1241    option(set,vopt);
1242    // total cleanup
1243    setring @R2;
1244    ideal bs = imap(@R3,bs);
1245    bs = -normalize(bs); // "-" for getting correct coeffs!
1246    bs = subst(bs,s,0);
1247    kill @R3;
1248    setring @R4;
1249    ideal bs = imap(@R2,bs); // only rationals are the entries
1250    list BS; BS[1] = bs; BS[2] = m;
1251    export BS;
1252    //    list LBS = imap(@R3,LBS);
1253    //    list BS; BS[1] = sbs; BS[2] = m;
1254    //    BS;
1255    //    export BS;
1256    ideal LD0 = K4;
1257    export LD0;
1258    return(@R4);
1259  }
1260  else
1261  {
1262    /* SHOULD NEVER GET THERE */
1263    /* no rational/integer roots */
1264    /* return objects in the copy of current ring */
1265    setring @R2;
1266    ideal LD0 = I;
1267    poly BS = normalize(K2[1]);
1268    export LD0;
1269    export BS;
1270    return(@R2);
1271  }
1272}
1273example;
1274{
1275  "EXAMPLE:"; echo = 2;
1276  ring r = 0,(x,y,Dx,Dy),dp;
1277  def R = Weyl();    setring R; // Weyl algebra in variables x,y,Dx,Dy
1278  poly F = x2-y3;
1279  ideal I = (y^3 - x^2)*Dx - 2*x, (y^3 - x^2)*Dy + 3*y^2; // I = Dx*F, Dy*F;
1280  // moreover I is not holonomic, since its dimension is not 2 = 4/2
1281  gkdim(I); // 3
1282  def W = SDLoc(I,F);  setring W; // creates ideal LD in W = R[s]
1283  def U = DLoc0(LD, x2-y3);  setring U; // compute in R
1284  LD0; // Groebner basis of the presentation of localization
1285  BS; // description of b-function for localization
1286}
1287
1288proc SDLoc(ideal I, poly F)
1289"USAGE:  SDLoc(I, f);  I an ideal, f a poly
1290RETURN:  ring (basering extended by a new variable) containing an ideal 'LD'
1291PURPOSE: compute a generic presentation of the localization of D/I w.r.t. f^s
1292ASSUME:  the basering D is a Weyl algebra over a field of characteristic 0
1293NOTE:    Activate this ring with the @code{setring} command. In this ring,
1294@*       the ideal LD (given as Groebner basis) is the presentation of the
1295@*       localization.
1296DISPLAY: If printlevel =1, progress debug messages will be printed,
1297@*       if printlevel>=2, all the debug messages will be printed.
1298EXAMPLE: example SDLoc; shows examples
1299"
1300{
1301  /* analogue to Sannfs */
1302  /* printlevel >=4 gives debug info */
1303  /* assume: we're in the Weyl algebra D  in x1,x2,...,d1,d2,... */
1304
1305  dmodappAssumeViolation();
1306  if (!isWeyl())
1307  {
1308    ERROR("Basering is not a Weyl algebra");
1309  }
1310  def save = basering;
1311  /* 1. create D <t, dt, s > as in LOT */
1312  /* ordering: eliminate t,dt */
1313  int ppl = printlevel-voice+2;
1314  int N = nvars(save); N = N div 2;
1315  int Nnew = 2*N + 3; // t,Dt,s
1316  int i,j;
1317  string s;
1318  list RL = ringlist(save);
1319  list L, Lord;
1320  list tmp;
1321  intvec iv;
1322  L[1] = RL[1]; // char
1323  L[4] = RL[4]; // char, minpoly
1324  // check whether vars have admissible names
1325  list Name  = RL[2];
1326  list RName;
1327  RName[1] = "@t";
1328  RName[2] = "@Dt";
1329  RName[3] = "@s";
1330  for(i=1;i<=N;i++)
1331  {
1332    for(j=1; j<=size(RName);j++)
1333    {
1334      if (Name[i] == RName[j])
1335      {
1336        ERROR("Variable names should not include @t,@Dt,@s");
1337      }
1338    }
1339  }
1340  // now, create the names for new vars
1341  tmp    =  0;
1342  tmp[1] = "@t";
1343  tmp[2] = "@Dt";
1344  list SName ; SName[1] = "@s";
1345  list NName = tmp + Name + SName;
1346  L[2]   = NName;
1347  tmp    = 0;
1348  kill NName;
1349  // block ord (a(1,1),dp);
1350  tmp[1]  = "a"; // string
1351  iv      = 1,1;
1352  tmp[2]  = iv; //intvec
1353  Lord[1] = tmp;
1354  // continue with dp 1,1,1,1...
1355  tmp[1]  = "dp"; // string
1356  s       = "iv=";
1357  for(i=1;i<=Nnew;i++)
1358  {
1359    s = s+"1,";
1360  }
1361  s[size(s)]= ";";
1362  execute(s);
1363  tmp[2]    = iv;
1364  Lord[2]   = tmp;
1365  tmp[1]    = "C";
1366  iv        = 0;
1367  tmp[2]    = iv;
1368  Lord[3]   = tmp;
1369  tmp       = 0;
1370  L[3]      = Lord;
1371  // we are done with the list
1372  def @R@ = ring(L);
1373  setring @R@;
1374  matrix @D[Nnew][Nnew];
1375  @D[1,2]=1;
1376  for(i=1; i<=N; i++)
1377  {
1378    @D[2+i,N+2+i]=1;
1379  }
1380  // ADD [s,t]=-t, [s,Dt]=Dt
1381  @D[1,Nnew] = -var(1);
1382  @D[2,Nnew] = var(2);
1383  def @R = nc_algebra(1,@D);
1384  setring @R;
1385  kill @R@;
1386  dbprint(ppl,"// -1-1- the ring @R(@t,@Dt,_x,_Dx,@s) is ready");
1387  dbprint(ppl-1, @R);
1388  poly  F = imap(save,F);
1389  ideal I = imap(save,I);
1390  dbprint(ppl-1, "the ideal after map:");
1391  dbprint(ppl-1, I);
1392  poly p = 0;
1393  for(i=1; i<=N; i++)
1394  {
1395    p = diff(F,var(2+i))*@Dt + var(2+N+i);
1396    dbprint(ppl-1, p);
1397    I = subst(I,var(2+N+i),p);
1398    dbprint(ppl-1, var(2+N+i));
1399    p = 0;
1400  }
1401  I = I, @t - F;
1402  // t*Dt + s +1 reduced with t-f gives f*Dt + s
1403  I = I, F*var(2) + var(Nnew); // @s
1404  // -------- the ideal I is ready ----------
1405  dbprint(ppl,"// -1-2- starting the elimination of @t,@Dt in @R");
1406  dbprint(ppl-1, I);
1407  //  ideal J = engine(I,eng);
1408  ideal J = groebner(I);
1409  dbprint(ppl-1,"// -1-2-1- result of the  elimination of @t,@Dt in @R");
1410  dbprint(ppl-1, J);;
1411  ideal K = nselect(J,1..2);
1412  dbprint(ppl,"// -1-3- @t,@Dt are eliminated");
1413  dbprint(ppl-1, K);  // K is without t, Dt
1414  K = groebner(K);  // std does the job too
1415  // now, we must change the ordering
1416  // and create a ring without t, Dt
1417  setring save;
1418  // ----------- the ring @R3 ------------
1419  // _x, _Dx,s;  elim.ord for _x,_Dx.
1420  // keep: N, i,j,s, tmp, RL
1421  Nnew = 2*N+1;
1422  kill Lord, tmp, iv, RName;
1423  list Lord, tmp;
1424  intvec iv;
1425  L[1] = RL[1];
1426  L[4] = RL[4];  // char, minpoly
1427  // check whether vars hava admissible names -> done earlier
1428  // now, create the names for new var
1429  tmp[1] = "s";
1430  list NName = Name + tmp;
1431  L[2] = NName;
1432  tmp = 0;
1433  // block ord (dp(N),dp);
1434  // string s is already defined
1435  s = "iv=";
1436  for (i=1; i<=Nnew-1; i++)
1437  {
1438    s = s+"1,";
1439  }
1440  s[size(s)]=";";
1441  execute(s);
1442  tmp[1] = "dp";  // string
1443  tmp[2] = iv;   // intvec
1444  Lord[1] = tmp;
1445  // continue with dp 1,1,1,1...
1446  tmp[1] = "dp";  // string
1447  s[size(s)] = ",";
1448  s = s+"1;";
1449  execute(s);
1450  kill s;
1451  kill NName;
1452  tmp[2]      = iv;
1453  Lord[2]     = tmp;
1454  tmp[1]      = "C";  iv  = 0;  tmp[2]=iv;
1455  Lord[3]     = tmp;  tmp = 0;
1456  L[3]        = Lord;
1457  // we are done with the list. Now add a Plural part
1458  def @R2@ = ring(L);
1459  setring @R2@;
1460  matrix @D[Nnew][Nnew];
1461  for (i=1; i<=N; i++)
1462  {
1463    @D[i,N+i]=1;
1464  }
1465  def @R2 = nc_algebra(1,@D);
1466  setring @R2;
1467  kill @R2@;
1468  dbprint(ppl,"//  -2-1- the ring @R2(_x,_Dx,s) is ready");
1469  dbprint(ppl-1, @R2);
1470  ideal MM = maxideal(1);
1471  MM = 0,s,MM;
1472  map R01 = @R, MM;
1473  ideal K = R01(K);
1474  // total cleanup
1475  ideal LD = K;
1476  // make leadcoeffs positive
1477  for (i=1; i<= ncols(LD); i++)
1478  {
1479    if (leadcoef(LD[i]) <0 )
1480    {
1481      LD[i] = -LD[i];
1482    }
1483  }
1484  export LD;
1485  kill @R;
1486  return(@R2);
1487}
1488example;
1489{
1490  "EXAMPLE:"; echo = 2;
1491  ring r = 0,(x,y,Dx,Dy),dp;
1492  def R = Weyl(); // Weyl algebra on the variables x,y,Dx,Dy
1493  setring R;
1494  poly F = x2-y3;
1495  ideal I = Dx*F, Dy*F;
1496  // note, that I is not holonomic, since it's dimension is not 2
1497  gkdim(I);  // 3, while dim R = 4
1498  def W = SDLoc(I,F);
1499  setring W; // = R[s], where s is a new variable
1500  LD;        // Groebner basis of s-parametric presentation
1501}
1502
1503
1504// Groebner basis wrt weights and initial ideal business //////////////////////
1505
1506proc GBWeight (ideal I, intvec u, intvec v, list #)
1507"USAGE:  GBWeight(I,u,v [,s,t,w]); 
1508@*       I ideal, u,v intvecs, s,t optional ints, w an optional intvec
1509RETURN:  ideal, Groebner basis of I w.r.t. the weights u and v
1510ASSUME:  The basering is the n-th Weyl algebra over a field of characteristic 0
1511@*       and for all 1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1
1512@*       holds, i.e. the sequence of variables is given by
1513@*       x(1),...,x(n),D(1),...,D(n), where D(i) is the differential operator
1514@*       belonging to x(i).
1515PURPOSE: computes a Groebner basis with respect to given weights
1516NOTE:    The weights u and v are understood as weight vectors for x(i) and D(i),
1517@*       respectively. According to (SST), one computes the homogenization of a
1518@*       given ideal relative to (u,v), then one computes a Groebner basis and
1519@*       returns the dehomogenization of the result.
1520@*       If s<>0, @code{std} is used for Groebner basis computations,
1521@*       otherwise, and by default, @code{slimgb} is used.
1522@*       If t<>0, a matrix ordering is used for Groebner basis computations,
1523@*       otherwise, and by default, a block ordering is used.
1524@*       If w is given and consists of exactly 2*n strictly positive entries,
1525@*       w is used for constructing the weighted homogenized Weyl algebra,
1526@*       see Noro (2002). Otherwise, and by default, the homogenization weight
1527@*       (1,...,1) is used.
1528DISPLAY: If printlevel=1, progress debug messages will be printed,
1529@*       if printlevel>=2, all the debug messages will be printed.
1530EXAMPLE: example GBWeight; shows examples
1531"
1532{
1533  dmodappMoreAssumeViolation();
1534  int ppl = printlevel - voice +2;
1535  def save = basering;
1536  int n = nvars(save)/2;
1537  int whichengine = 0;           // default
1538  int methodord   = 0;           // default
1539  intvec homogweights = 1:(2*n); // default
1540  if (size(#)>0)
1541  {
1542    if (intLike(#[1]))
1543    {
1544      whichengine = int(#[1]);
1545    }
1546    if (size(#)>1)
1547    {
1548      if (intLike(#[2]))
1549      {
1550        methodord = int(#[2]);
1551      }
1552      if (size(#)>2)
1553      {
1554        if (typeof(#[3])=="intvec")
1555        {
1556          if (size(#[3])==2*n && allPositive(#[3])==1)
1557          {
1558            homogweights = #[3];
1559          }
1560          else
1561          {
1562            print("// Homogenization weight vector must consist of positive entries and be");
1563            print("// of size " + string(n) + ". Using weight (1,...,1).");
1564          }
1565        }
1566      }
1567    }
1568  }
1569  // 1. create  homogenized Weyl algebra
1570  // 1.1 create ordering
1571  int i;
1572  list RL = ringlist(save);
1573  int N = 2*n+1;
1574  intvec uv = u,v,0;
1575  homogweights = homogweights,1;
1576  list Lord = list(list("a",homogweights));
1577  list C0 = list("C",intvec(0));
1578  if (methodord == 0) // default: blockordering
1579  {
1580    Lord[5] = C0;
1581    Lord[4] = list("lp",intvec(1));
1582    Lord[3] = list("dp",intvec(1:(N-1)));
1583    Lord[2] = list("a",uv);
1584  }
1585  else                // M() ordering
1586  {
1587    intmat @Ord[N][N];
1588    @Ord[1,1..N] = uv; @Ord[2,1..N] = 1:(N-1);
1589    for (i=1; i<=N-2; i++)
1590    {
1591      @Ord[2+i,N - i] = -1;
1592    }
1593    dbprint(ppl-1,"// the ordering matrix:",@Ord);
1594    Lord[2] = list("M",intvec(@Ord));
1595    Lord[3] = C0;
1596  }
1597  // 1.2 the homog var
1598  list Lvar = RL[2]; Lvar[N] = safeVarName("h","cv");
1599  // 1.3 create commutative ring
1600  list L@@Dh = RL; L@@Dh = L@@Dh[1..4];
1601  L@@Dh[2] = Lvar; L@@Dh[3] = Lord;
1602  def @Dh = ring(L@@Dh); kill L@@Dh;
1603  setring @Dh;
1604  // 1.4 create non-commutative relations
1605  matrix @relD[N][N];
1606  for (i=1; i<=n; i++)
1607  {
1608    @relD[i,n+i] = var(N)^(homogweights[i]+homogweights[n+i]);
1609  }
1610  def Dh = nc_algebra(1,@relD);
1611  setring Dh; kill @Dh;
1612  dbprint(ppl-1,"// computing in ring",Dh);
1613  // 2. Compute the initial ideal
1614  ideal I = imap(save,I);
1615  I = homog(I,var(N));
1616  // 2.1 the hard part: Groebner basis computation
1617  dbprint(ppl, "// starting Groebner basis computation with engine: "+string(whichengine));
1618  I = engine(I, whichengine);
1619  dbprint(ppl, "// finished Groebner basis computation");
1620  dbprint(ppl-1, "// ideal before dehomogenization is " +string(I));
1621  I = subst(I,var(N),1); // dehomogenization
1622  setring save;
1623  I = imap(Dh,I); kill Dh;
1624  return(I);
1625}
1626example
1627{
1628  "EXAMPLE:"; echo = 2;
1629  ring r = 0,(x,y,Dx,Dy),dp;
1630  def D2 = Weyl();
1631  setring D2;
1632  ideal I = 3*x^2*Dy+2*y*Dx,2*x*Dx+3*y*Dy+6;
1633  intvec u = -2,-3;
1634  intvec v = -u;
1635  GBWeight(I,u,v);
1636  ideal J = std(I);
1637  GBWeight(J,u,v); // same as above
1638  u = 0,1;
1639  GBWeight(I,u,v);
1640}
1641
1642proc inForm (def I, intvec w)
1643"USAGE:  inForm(I,w);  I ideal or poly, w intvec
1644RETURN:  ideal, generated by initial forms of generators of I w.r.t. w, or
1645@*       poly, initial form of input poly w.r.t. w
1646PURPOSE: computes the initial form of an ideal or a poly w.r.t. the weight w
1647NOTE:    The size of the weight vector must be equal to the number of variables
1648@*       of the basering.
1649EXAMPLE: example inForm; shows examples
1650"
1651{
1652  string inp1 = typeof(I);
1653  if ((inp1 <> "ideal") && (inp1 <> "poly"))
1654  {
1655    ERROR("first argument has to be an ideal or a poly");
1656  }
1657  if (size(w) != nvars(basering))
1658  {
1659    ERROR("weight vector has wrong dimension");
1660  }
1661  if (I == 0)
1662  {
1663    return(I);
1664  }
1665  int j,i;
1666  bigint s,m;
1667  list l;
1668  poly g;
1669  ideal J;
1670  for (j=1; j<=ncols(I); j++)
1671  {
1672    l = poly2list(I[j]);
1673    m = scalarProd(w,l[1][1]);
1674    g = l[1][2];
1675    for (i=2; i<=size(l); i++)
1676    {
1677      s = scalarProd(w,l[i][1]);
1678      if (s == m)
1679      {
1680        g = g + l[i][2];
1681      }
1682      else
1683      {
1684        if (s > m)
1685        {
1686          m = s;
1687          g = l[i][2];
1688        }
1689      }
1690    }
1691    J[j] = g;
1692  }
1693  if (inp1 == "ideal")
1694  {
1695    return(J);
1696  }
1697  else
1698  {
1699    return(J[1]);
1700  }
1701}
1702example
1703{
1704  "EXAMPLE:"; echo = 2;
1705  ring r = 0,(x,y,Dx,Dy),dp;
1706  def D = Weyl(); setring D;
1707  poly F = 3*x^2*Dy+2*y*Dx;
1708  poly G = 2*x*Dx+3*y*Dy+6;
1709  ideal I = F,G;
1710  intvec w1 = -1,-1,1,1;
1711  intvec w2 = -1,-2,1,2;
1712  intvec w3 = -2,-3,2,3;
1713  inForm(I,w1);
1714  inForm(I,w2);
1715  inForm(I,w3);
1716  inForm(F,w1);
1717}
1718
1719proc initialIdealW(ideal I, intvec u, intvec v, list #)
1720"USAGE:  initialIdealW(I,u,v [,s,t,w]);
1721@*       I ideal, u,v intvecs, s,t optional ints, w an optional intvec
1722RETURN:  ideal, GB of initial ideal of the input ideal wrt the weights u and v
1723ASSUME:  The basering is the n-th Weyl algebra in characteristic 0 and for all
1724@*       1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1 holds, i.e. the
1725@*       sequence of variables is given by x(1),...,x(n),D(1),...,D(n),
1726@*       where D(i) is the differential operator belonging to x(i).
1727PURPOSE: computes the initial ideal with respect to given weights.
1728NOTE:    u and v are understood as weight vectors for x(1..n) and D(1..n)
1729@*       respectively.
1730@*       If s<>0, @code{std} is used for Groebner basis computations,
1731@*       otherwise, and by default, @code{slimgb} is used.
1732@*       If t<>0, a matrix ordering is used for Groebner basis computations,
1733@*       otherwise, and by default, a block ordering is used.
1734@*       If w is given and consists of exactly 2*n strictly positive entries,
1735@*       w is used as homogenization weight.
1736@*       Otherwise, and by default, the homogenization weight (1,...,1) is used.
1737DISPLAY: If printlevel=1, progress debug messages will be printed,
1738@*       if printlevel>=2, all the debug messages will be printed.
1739EXAMPLE: example initialIdealW; shows examples
1740"
1741{
1742  // assumption check in GBWeight
1743  int ppl = printlevel - voice + 2;
1744  printlevel = printlevel + 1;
1745  I = GBWeight(I,u,v,#);
1746  printlevel = printlevel - 1;
1747  intvec uv = u,v;
1748  I = inForm(I,uv);
1749  int eng;
1750  if (size(#)>0)
1751  {
1752    if(typeof(#[1])=="int" || typeof(#[1])=="number")
1753    {
1754      eng = int(#[1]);
1755    }
1756  }
1757  dbprint(ppl,"// starting cosmetic Groebner basis computation");
1758  I = engine(I,eng);
1759  dbprint(ppl,"// finished cosmetic Groebner basis computation");
1760  return(I);
1761}
1762example
1763{
1764  "EXAMPLE:"; echo = 2;
1765  ring r = 0,(x,y,Dx,Dy),dp;
1766  def D2 = Weyl();
1767  setring D2;
1768  ideal I = 3*x^2*Dy+2*y*Dx,2*x*Dx+3*y*Dy+6;
1769  intvec u = -2,-3;
1770  intvec v = -u;
1771  initialIdealW(I,u,v);
1772  ideal J = std(I);
1773  initialIdealW(J,u,v); // same as above
1774  u = 0,1;
1775  initialIdealW(I,u,v);
1776}
1777
1778proc initialMalgrange (poly f,list #)
1779"USAGE:  initialMalgrange(f,[,a,b,v]); f poly, a,b optional ints, v opt. intvec
1780RETURN:  ring, Weyl algebra induced by basering, extended by two new vars t,Dt
1781PURPOSE: computes the initial Malgrange ideal of a given polynomial w.r.t. the
1782@*       weight vector (-1,0...,0,1,0,...,0) such that the weight of t is -1
1783@*       and the weight of Dt is 1.
1784ASSUME:  The basering is commutative and over a field of characteristic 0.
1785NOTE:    Activate the output ring with the @code{setring} command.
1786@*       The returned ring contains the ideal 'inF', being the initial ideal
1787@*       of the Malgrange ideal of f.
1788@*       Varnames of the basering should not include t and Dt.
1789@*       If a<>0, @code{std} is used for Groebner basis computations,
1790@*       otherwise, and by default, @code{slimgb} is used.
1791@*       If b<>0, a matrix ordering is used for Groebner basis computations,
1792@*       otherwise, and by default, a block ordering is used.
1793@*       If a positive weight vector v is given, the weight
1794@*       (d,v[1],...,v[n],1,d+1-v[1],...,d+1-v[n]) is used for homogenization
1795@*       computations, where d denotes the weighted degree of f.
1796@*       Otherwise and by default, v is set to (1,...,1). See Noro (2002).
1797DISPLAY: If printlevel=1, progress debug messages will be printed,
1798@*       if printlevel>=2, all the debug messages will be printed.
1799EXAMPLE: example initialMalgrange; shows examples
1800"
1801{
1802  dmodappAssumeViolation();
1803  if (!isCommutative())
1804  {
1805    ERROR("Basering must be commutative.");
1806  }
1807  int ppl = printlevel - voice + 2;
1808  def save = basering;
1809  int n = nvars(save);
1810  int i;
1811  int whichengine = 0; // default
1812  int methodord   = 0; // default
1813  intvec u0 = 1:n;     // default
1814  if (size(#)>0)
1815  {
1816    if (intLike(#[1]))
1817    {
1818      whichengine = int(#[1]);
1819    }
1820    if (size(#)>1)
1821    {
1822      if (intLike(#[2]))
1823      {
1824        methodord = int(#[2]);
1825      }
1826      if (size(#)>2)
1827      {
1828        if ((typeof(#[3])=="intvec") && (size(#[3])==n) && (allPositive(#[3])==1))
1829        {
1830          u0 = #[3];
1831        }
1832      }
1833    }
1834  }
1835  list RL = ringlist(save);
1836  RL = RL[1..4]; // if basering is commutative nc_algebra
1837  list C0 = list("C",intvec(0));
1838  // 1. create homogenization weights
1839  // 1.1. get the weighted degree of f
1840  list Lord = list(list("wp",u0),C0);
1841  list L@r = RL;
1842  L@r[3] = Lord;
1843  def r = ring(L@r); kill L@r,Lord;
1844  setring r;
1845  poly f = imap(save,f);
1846  int d = deg(f);
1847  setring save; kill r;
1848  // 1.2 the homogenization weights
1849  intvec homogweights = d;
1850  homogweights[n+2] = 1;
1851  for (i=1; i<=n; i++)
1852  {
1853    homogweights[i+1]   = u0[i];
1854    homogweights[n+2+i] = d+1-u0[i];
1855  }
1856  // 2. create extended Weyl algebra
1857  int N = 2*n+2;
1858  // 2.1 create names for vars
1859  string vart  = safeVarName("t","cv");
1860  string varDt = safeVarName("D"+vart,"cv");
1861  while (varDt <> "D"+vart)
1862  {
1863    vart  = safeVarName("@"+vart,"cv");
1864    varDt = safeVarName("D"+vart,"cv");
1865  }
1866  list Lvar;
1867  Lvar[1] = vart; Lvar[n+2] = varDt;
1868  for (i=1; i<=n; i++)
1869  {
1870    Lvar[i+1]   = string(var(i));
1871    Lvar[i+n+2] = safeVarName("D" + string(var(i)),"cv");
1872  }
1873  //  2.2 create ordering
1874  list Lord = list(list("dp",intvec(1:N)),C0);
1875  // 2.3 create the (n+1)-th Weyl algebra
1876  list L@D = RL; L@D[2] = Lvar; L@D[3] = Lord;
1877  def @D = ring(L@D); kill L@D;
1878  setring @D;
1879  def D = Weyl();
1880  setring D; kill @D;
1881  dbprint(ppl,"// the (n+1)-th Weyl algebra :" ,D);
1882  // 3. compute the initial ideal
1883  // 3.1 create the Malgrange ideal
1884  poly f = imap(save,f);
1885  ideal I = var(1)-f;
1886  for (i=1; i<=n; i++)
1887  {
1888    I = I, var(n+2+i)+diff(f,var(i+1))*var(n+2);
1889  }
1890  // I = engine(I,whichengine); // todo efficient to compute GB wrt dp first?
1891  // 3.2 computie the initial ideal
1892  intvec w = 1,0:n;
1893  printlevel = printlevel + 1;
1894  I = initialIdealW(I,-w,w,whichengine,methodord,homogweights);
1895  printlevel = printlevel - 1;
1896  ideal inF = I; attrib(inF,"isSB",1);
1897  export(inF);
1898  setring save;
1899  return(D);
1900}
1901example
1902{
1903  "EXAMPLE:"; echo = 2;
1904  ring r = 0,(x,y),dp;
1905  poly f = x^2+y^3+x*y^2;
1906  def D = initialMalgrange(f);
1907  setring D;
1908  inF;
1909  setring r;
1910  intvec v = 3,2;
1911  def D2 = initialMalgrange(f,1,1,v);
1912  setring D2;
1913  inF;
1914}
1915
1916
1917// restriction and integration ////////////////////////////////////////////////
1918
1919static proc restrictionModuleEngine (ideal I, intvec w, list #)
1920// returns list L with 2 entries of type ideal
1921// L[1]=basis of free module, L[2]=generating system of submodule
1922// #=eng,m,G; eng=engine; m=min int root of bfctIdeal(I,w); G=GB of I wrt (-w,w)
1923{
1924  dmodappMoreAssumeViolation();
1925  if (!isHolonomic(I))
1926  {
1927    ERROR("Given ideal is not holonomic");
1928  }
1929  int l0,l0set,Gset;
1930  ideal G;
1931  int whichengine = 0;         // default
1932  if (size(#)>0)
1933  {
1934    if (intLike(#[1]))
1935    {
1936      whichengine = int(#[1]);
1937    }
1938    if (size(#)>1)
1939    {
1940      if (intLike(#[2]))
1941      {
1942        l0 = int(#[2]);
1943        l0set = 1;
1944      }
1945      if (size(#)>2)
1946      {
1947        if (typeof(#[3])=="ideal")
1948        {
1949          G = #[3];
1950          Gset = 1;
1951        }
1952      }
1953    }
1954  }
1955  int ppl = printlevel;
1956  int i,j,k;
1957  int n = nvars(basering)/2;
1958  if (w == 0:size(w))
1959  {
1960    ERROR("weight vector must not be zero");
1961  }
1962  if (size(w)<>n)
1963  {
1964    ERROR("weight vector must have exactly " + string(n) + " entries");
1965  }
1966  for (i=1; i<=n; i++)
1967  {
1968    if (w[i]<0)
1969    {
1970      ERROR("weight vector must not have negative entries");
1971    }
1972  }
1973  intvec ww = -w,w;
1974  if (!Gset)
1975  {
1976    G = GBWeight(I,-w,w,whichengine);
1977    dbprint(ppl,"// found GB wrt weight " +string(w));
1978    dbprint(ppl-1,"// " + string(G));
1979  }
1980  if (!l0set)
1981  {
1982    ideal inG = inForm(G,ww);
1983    inG = engine(inG,whichengine);
1984    poly s = 0;
1985    for (i=1; i<=n; i++)
1986    {
1987      s = s + w[i]*var(i)*var(i+n);
1988    }
1989    vector v = pIntersect(s,inG);
1990    list L = bFactor(vec2poly(v));
1991    dbprint(ppl,"// found b-function of given ideal wrt given weight");
1992    dbprint(ppl-1,"// roots: "+string(L[1]));
1993    dbprint(ppl-1,"// multiplicities: "+string(L[2]));
1994    kill inG,v,s;
1995    L = intRoots(L);           // integral roots of b-function
1996    if (L[2]==0:size(L[2]))       // no integral roots
1997    {
1998      return(list(ideal(0),ideal(0)));
1999    }
2000    intvec v;
2001    for (i=1; i<=ncols(L[1]); i++)
2002    {
2003      v[i] = int(L[1][i]);
2004    }
2005    l0 = Max(v);
2006    dbprint(ppl,"// maximal integral root is " +string(l0));
2007    kill L,v;
2008  }
2009  if (l0 < 0)                  // maximal integral root is < 0
2010  {
2011    return(list(ideal(0),ideal(0)));
2012  }
2013  intvec m;
2014  for (i=ncols(G); i>0; i--)
2015  {
2016    m[i] = deg(G[i],ww);
2017  }
2018  dbprint(ppl,"// weighted degree of generators of GB is " +string(m));
2019  def save = basering;
2020  list RL = ringlist(save);
2021  RL = RL[1..4];
2022  list Lvar;
2023  j = 1;
2024  intvec neww;
2025  for (i=1; i<=n; i++)
2026  {
2027    if (w[i]>0)
2028    {
2029      Lvar[j] = string(var(i+n));
2030      neww[j] = w[i];
2031      j++;
2032    }
2033  }
2034  list Lord;
2035  Lord[1] = list("dp",intvec(1:n));
2036  Lord[2] = list("C", intvec(0));
2037  RL[2] = Lvar;
2038  RL[3] = Lord;
2039  def r = ring(RL);
2040  kill Lvar, Lord, RL;
2041  setring r;
2042  ideal B;
2043  list Blist;
2044  intvec mm = l0,-m+l0;
2045  for (i=0; i<=Max(mm); i++)
2046  {
2047    B = weightKB(std(0),i,neww);
2048    Blist[i+1] = B;
2049  }
2050  setring save;
2051  list Blist = imap(r,Blist);
2052  ideal ff = maxideal(1);
2053  for (i=1; i<=n; i++)
2054  {
2055    if (w[i]<>0)
2056    {
2057      ff[i] = 0;
2058    }
2059  }
2060  map f = save,ff;
2061  ideal B,M;
2062  poly p;
2063  for (i=1; i<=size(G); i++)
2064  {
2065    for (j=1; j<=l0-m[i]+1; j++)
2066    {
2067      B = Blist[j];
2068      for (k=1; k<=ncols(B); k++)
2069      {
2070        p = B[k]*G[i];
2071        p = f(p);
2072        M[size(M)+1] = p;
2073      }
2074    }
2075  }
2076  ideal Bl0 = Blist[1..(l0+1)];
2077  dbprint(ppl,"// found basis of free module");
2078  dbprint(ppl-1,"// " + string(Bl0));
2079  dbprint(ppl,"// found generators of submodule");
2080  dbprint(ppl-1,"// " + string(M));
2081  return(list(Bl0,M));
2082}
2083
2084static proc restrictionModuleOutput (ideal B, ideal N, intvec w, int eng, string str)
2085// returns ring, which contains module "str"
2086{
2087  int n = nvars(basering)/2;
2088  int i,j;
2089  def save = basering;
2090  // 1: create new ring
2091  list RL = ringlist(save);
2092  RL = RL[1..4];
2093  list V = RL[2];
2094  poly prodvar = 1;
2095  int zeropresent;
2096  j = 0;
2097  for (i=1; i<=n; i++)
2098  {
2099    if (w[i]<>0)
2100    {
2101      V = delete(V,i-j);
2102      V = delete(V,i-2*j-1+n);
2103      j = j+1;
2104      prodvar = prodvar*var(i)*var(i+n);
2105    }
2106    else
2107    {
2108      zeropresent = 1;
2109    }
2110  }
2111  if (!zeropresent) // restrict/integrate all vars, return input ring
2112  {
2113    def newR = save;
2114  }
2115  else
2116  {
2117    RL[2] = V;
2118    V = list();
2119    V[1] = list("C", intvec(0));
2120    V[2] = list("dp",intvec(1:(2*size(ideal(w)))));
2121    RL[3] = V;
2122    def @D = ring(RL);
2123    setring @D;
2124    def newR = Weyl();
2125    setring save;
2126    kill @D;
2127  }
2128  // 2. get coker representation of module
2129  module M = coeffs(N,B,prodvar);
2130  if (zeropresent)
2131  {
2132    setring newR;
2133    module M = imap(save,M);
2134  }
2135  M = engine(M,eng);
2136  M = prune(M);
2137  M = engine(M,eng);
2138  execute("module " + str + " = M;");
2139  execute("export(" + str + ");");
2140  setring save;
2141  return(newR);
2142}
2143
2144proc restrictionModule (ideal I, intvec w, list #)
2145"USAGE:  restrictionModule(I,w,[,eng,m,G]);
2146@*       I ideal, w intvec, eng and m optional ints, G optional ideal
2147RETURN:  ring (a Weyl algebra) containing a module 'resMod'
2148ASSUME:  The basering is the n-th Weyl algebra over a field of characteristic 0
2149@*       and for all 1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1
2150@*       holds, i.e. the sequence of variables is given by
2151@*       x(1),...,x(n),D(1),...,D(n), where D(i) is the differential operator
2152@*       belonging to x(i).
2153@*       Further, assume that I is holonomic and that w is n-dimensional with
2154@*       non-negative entries.
2155PURPOSE: computes the restriction module of a holonomic ideal to the subspace
2156@*       defined by the variables corresponding to the non-zero entries of the
2157@*       given intvec
2158NOTE:    The output ring is the Weyl algebra defined by the zero entries of w.
2159@*       It contains a module 'resMod' being the restriction module of I wrt w.
2160@*       If there are no zero entries, the input ring is returned.
2161@*       If eng<>0, @code{std} is used for Groebner basis computations,
2162@*       otherwise, and by default, @code{slimgb} is used.
2163@*       The minimal integer root of the b-function of I wrt the weight (-w,w)
2164@*       can be specified via the optional argument m.
2165@*       The optional argument G is used for specifying a Groebner Basis of I
2166@*       wrt the weight (-w,w), that is, the initial form of G generates the
2167@*       initial ideal of I wrt the weight (-w,w).
2168@*       Further note, that the assumptions on m and G (if given) are not
2169@*       checked.
2170DISPLAY: If printlevel=1, progress debug messages will be printed,
2171@*       if printlevel>=2, all the debug messages will be printed.
2172EXAMPLE: example restrictionModule; shows examples
2173"
2174{
2175  list L = restrictionModuleEngine(I,w,#);
2176  int eng;
2177  if (size(#)>0)
2178  {
2179    if (intLike(#[1]))
2180    {
2181      eng = int(#[1]);
2182    }
2183  }
2184  def newR = restrictionModuleOutput(L[1],L[2],w,eng,"resMod");
2185  return(newR);
2186}
2187example
2188{
2189  "EXAMPLE:"; echo = 2;
2190  ring r = 0,(a,x,b,Da,Dx,Db),dp;
2191  def D3 = Weyl();
2192  setring D3;
2193  ideal I = a*Db-Dx+2*Da, x*Db-Da, x*Da+a*Da+b*Db+1,
2194    x*Dx-2*x*Da-a*Da, b*Db^2+Dx*Da-Da^2+Db,
2195    a*Dx*Da+2*x*Da^2+a*Da^2+b*Dx*Db+Dx+2*Da;
2196  intvec w = 1,0,0;
2197  def rm = restrictionModule(I,w);
2198  setring rm; rm;
2199  print(resMod);
2200}
2201
2202static proc restrictionIdealEngine (ideal I, intvec w, string cf, list #)
2203{
2204  int eng;
2205  if (size(#)>0)
2206  {
2207    if(intLike(#[1]))
2208    {
2209      eng = int(#[1]);
2210    }
2211  }
2212  def save = basering;
2213  if (cf == "restriction")
2214  {
2215    def newR = restrictionModule(I,w,#);
2216    setring newR;
2217    matrix M = resMod;
2218    kill resMod;
2219  }
2220  if (cf == "integral")
2221  {
2222    def newR = integralModule(I,w,#);
2223    setring newR;
2224    matrix M = intMod;
2225    kill intMod;
2226  }
2227  int i,r,c;
2228  r = nrows(M);
2229  c = ncols(M);
2230  ideal J;
2231  if (r == 1) // nothing to do
2232  {
2233    J = M;
2234  }
2235  else
2236  {
2237    matrix zm[r-1][1]; // zero matrix
2238    matrix v[r-1][1];
2239    for (i=1; i<=c; i++)
2240    {
2241      if (M[1,i]<>0)
2242      {
2243        v = M[2..r,i];
2244        if (v == zm)
2245        {
2246          J[size(J+1)] = M[1,i];
2247        }
2248      }
2249    }
2250  }
2251  J = engine(J,eng);
2252  if (cf == "restriction")
2253  {
2254    ideal resIdeal = J;
2255    export(resIdeal);
2256  }
2257  if (cf == "integral")
2258  {
2259    ideal intIdeal = J;
2260    export(intIdeal);
2261  }
2262  setring save;
2263  return(newR);
2264}
2265
2266proc restrictionIdeal (ideal I, intvec w, list #)
2267"USAGE:  restrictionIdeal(I,w,[,eng,m,G]);
2268@*       I ideal, w intvec, eng and m optional ints, G optional ideal
2269RETURN:  ring (a Weyl algebra) containing an ideal 'resIdeal'
2270ASSUME:  The basering is the n-th Weyl algebra over a field of characteristic 0
2271@*       and for all 1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1
2272@*       holds, i.e. the sequence of variables is given by
2273@*       x(1),...,x(n),D(1),...,D(n), where D(i) is the differential operator
2274@*       belonging to x(i).
2275@*       Further, assume that I is holonomic and that w is n-dimensional with
2276@*       non-negative entries.
2277PURPOSE: computes the restriction ideal of a holonomic ideal to the subspace
2278@*       defined by the variables corresponding to the non-zero entries of the
2279@*       given intvec
2280NOTE:    The output ring is the Weyl algebra defined by the zero entries of w.
2281@*       It contains an ideal 'resIdeal' being the restriction ideal of I wrt w.
2282@*       If there are no zero entries, the input ring is returned.
2283@*       If eng<>0, @code{std} is used for Groebner basis computations,
2284@*       otherwise, and by default, @code{slimgb} is used.
2285@*       The minimal integer root of the b-function of I wrt the weight (-w,w)
2286@*       can be specified via the optional argument m.
2287@*       The optional argument G is used for specifying a Groebner basis of I
2288@*       wrt the weight (-w,w), that is, the initial form of G generates the
2289@*       initial ideal of I wrt the weight (-w,w).
2290@*       Further note, that the assumptions on m and G (if given) are not
2291@*       checked.
2292DISPLAY: If printlevel=1, progress debug messages will be printed,
2293@*       if printlevel>=2, all the debug messages will be printed.
2294EXAMPLE: example restrictionIdeal; shows examples
2295"
2296{
2297  def rm = restrictionIdealEngine(I,w,"restriction",#);
2298  return(rm);
2299}
2300example
2301{
2302  "EXAMPLE:"; echo = 2;
2303  ring r = 0,(a,x,b,Da,Dx,Db),dp;
2304  def D3 = Weyl();
2305  setring D3;
2306  ideal I = a*Db-Dx+2*Da,
2307    x*Db-Da,
2308    x*Da+a*Da+b*Db+1,
2309    x*Dx-2*x*Da-a*Da,
2310    b*Db^2+Dx*Da-Da^2+Db,
2311    a*Dx*Da+2*x*Da^2+a*Da^2+b*Dx*Db+Dx+2*Da;
2312  intvec w = 1,0,0;
2313  def D2 = restrictionIdeal(I,w);
2314  setring D2; D2;
2315  resIdeal;
2316}
2317
2318proc fourier (ideal I, list #)
2319"USAGE:  fourier(I[,v]); I an ideal, v an optional intvec
2320RETURN:  ideal
2321PURPOSE: computes the Fourier transform of an ideal in a Weyl algebra
2322ASSUME:  The basering is the n-th Weyl algebra over a field of characteristic 0
2323@*       and for all 1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1
2324@*       holds, i.e. the sequence of variables is given by
2325@*       x(1),...,x(n),D(1),...,D(n), where D(i) is the differential operator
2326@*       belonging to x(i).
2327NOTE:    The Fourier automorphism is defined by mapping x(i) to -D(i) and
2328@*       D(i) to x(i).
2329@*       If v is an intvec with entries ranging from 1 to n, the Fourier
2330@*       transform of I restricted to the variables given by v is computed.
2331SEE ALSO: inverseFourier
2332EXAMPLE: example fourier; shows examples
2333"
2334{
2335  dmodappMoreAssumeViolation();
2336  intvec v;
2337  if (size(#)>0)
2338  {
2339    if(typeof(#[1])=="intvec")
2340    {
2341      v = #[1];
2342    }
2343  }
2344  int n = nvars(basering)/2;
2345  int i;
2346  if(v <> 0:size(v))
2347  {
2348    v = sortIntvec(v)[1];
2349    for (i=1; i<size(v); i++)
2350    {
2351      if (v[i] == v[i+1])
2352      {
2353        ERROR("No double entries allowed in intvec");
2354      }
2355    }
2356  }
2357  else 
2358  {
2359    v = 1..n;
2360  }
2361  ideal m = maxideal(1);
2362  for (i=1; i<=size(v); i++)
2363  {
2364    if (v[i]<0 || v[i]>n)
2365    {
2366      ERROR("Entries of intvec must range from 1 to "+string(n));
2367    }
2368    m[v[i]] = -var(v[i]+n);
2369    m[v[i]+n] = var(v[i]);
2370  }
2371  map F = basering,m;
2372  ideal FI = F(I);
2373  return(FI);
2374}
2375example
2376{
2377  "EXAMPLE:"; echo = 2;
2378  ring r = 0,(x,y,Dx,Dy),dp;
2379  def D2 = Weyl();
2380  setring D2;
2381  ideal I = x*Dx+2*y*Dy+2, x^2*Dx+y*Dx+2*x;
2382  intvec v = 2;
2383  fourier(I,v);
2384  fourier(I);
2385}
2386
2387proc inverseFourier (ideal I, list #)
2388"USAGE:  inverseFourier(I[,v]); I an ideal, v an optional intvec
2389RETURN:  ideal
2390PURPOSE: computes the inverse Fourier transform of an ideal in a Weyl algebra
2391ASSUME:  The basering is the n-th Weyl algebra over a field of characteristic 0
2392@*       and for all 1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1
2393@*       holds, i.e. the sequence of variables is given by
2394@*       x(1),...,x(n),D(1),...,D(n), where D(i) is the differential operator
2395@*       belonging to x(i).
2396NOTE:    The Fourier automorphism is defined by mapping x(i) to -D(i) and
2397@*       D(i) to x(i).
2398@*       If v is an intvec with entries ranging from 1 to n, the inverse Fourier
2399@*       transform of I restricted to the variables given by v is computed.
2400SEE ALSO: fourier
2401EXAMPLE: example inverseFourier; shows examples
2402"
2403{
2404  dmodappMoreAssumeViolation();
2405  intvec v;
2406  if (size(#)>0)
2407  {
2408    if(typeof(#[1])=="intvec")
2409    {
2410      v = #[1];
2411    }
2412  }
2413  int n = nvars(basering)/2;
2414  int i;
2415  if(v <> 0:size(v))
2416  {
2417    v = sortIntvec(v)[1];
2418    for (i=1; i<size(v); i++)
2419    {
2420      if (v[i] == v[i+1])
2421      {
2422        ERROR("No double entries allowed in intvec");
2423      }
2424    }
2425  }
2426  else 
2427  {
2428    v = 1..n;
2429  }
2430  ideal m = maxideal(1);
2431  for (i=1; i<=size(v); i++)
2432  {
2433    if (v[i]<0 || v[i]>n)
2434    {
2435      ERROR("Entries of intvec must range between 1 and "+string(n));
2436    }
2437    m[v[i]] = var(v[i]+n);
2438    m[v[i]+n] = -var(v[i]);
2439  }
2440  map F = basering,m;
2441  ideal FI = F(I);
2442  return(FI);
2443}
2444example
2445{
2446  "EXAMPLE:"; echo = 2;
2447  ring r = 0,(x,y,Dx,Dy),dp;
2448  def D2 = Weyl();
2449  setring D2;
2450  ideal I = x*Dx+2*y*Dy+2, x^2*Dx+y*Dx+2*x;
2451  intvec v = 2;
2452  ideal FI = fourier(I);
2453  inverseFourier(FI);
2454}
2455
2456proc integralModule (ideal I, intvec w, list #)
2457"USAGE:  integralModule(I,w,[,eng,m,G]);
2458@*       I ideal, w intvec, eng and m optional ints, G optional ideal
2459RETURN:  ring (a Weyl algebra) containing a module 'intMod'
2460ASSUME:  The basering is the n-th Weyl algebra over a field of characteristic 0
2461@*       and for all 1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1
2462@*       holds, i.e. the sequence of variables is given by
2463@*       x(1),...,x(n),D(1),...,D(n), where D(i) is the differential operator
2464@*       belonging to x(i).
2465@*       Further, assume that I is holonomic and that w is n-dimensional with
2466@*       non-negative entries.
2467PURPOSE: computes the integral module of a holonomic ideal w.r.t. the subspace
2468@*       defined by the variables corresponding to the non-zero entries of the
2469@*       given intvec
2470NOTE:    The output ring is the Weyl algebra defined by the zero entries of w.
2471@*       It contains a module 'intMod' being the integral module of I wrt w.
2472@*       If there are no zero entries, the input ring is returned.
2473@*       If eng<>0, @code{std} is used for Groebner basis computations,
2474@*       otherwise, and by default, @code{slimgb} is used.
2475@*       Let F(I) denote the Fourier transform of I w.r.t. w.
2476@*       The minimal integer root of the b-function of F(I) w.r.t. the weight
2477@*       (-w,w) can be specified via the optional argument m.
2478@*       The optional argument G is used for specifying a Groebner Basis of F(I)
2479@*       wrt the weight (-w,w), that is, the initial form of G generates the
2480@*       initial ideal of F(I) w.r.t. the weight (-w,w).
2481@*       Further note, that the assumptions on m and G (if given) are not
2482@*       checked.
2483DISPLAY: If printlevel=1, progress debug messages will be printed,
2484@*       if printlevel>=2, all the debug messages will be printed.
2485EXAMPLE: example integralModule; shows examples
2486"
2487{
2488  int l0,l0set,Gset;
2489  ideal G;
2490  int whichengine = 0;         // default
2491  if (size(#)>0)
2492  {
2493    if (intLike(#[1]))
2494    {
2495      whichengine = int(#[1]);
2496    }
2497    if (size(#)>1)
2498    {
2499      if (intLike(#[2]))
2500      {
2501        l0 = int(#[2]);
2502        l0set = 1;
2503      }
2504      if (size(#)>2)
2505      {
2506        if (typeof(#[3])=="ideal")
2507        {
2508          G = #[3];
2509          Gset = 1;
2510        }
2511      }
2512    }
2513  }
2514  int ppl = printlevel;
2515  int i;
2516  int n = nvars(basering)/2;
2517  intvec v;
2518  for (i=1; i<=n; i++)
2519  {
2520    if (w[i]>0)
2521    {
2522      if (v == 0:size(v))
2523      {
2524        v[1] = i;
2525      }
2526      else
2527      {
2528        v[size(v)+1] = i;
2529      }
2530    }
2531  }
2532  ideal FI = fourier(I,v);
2533  dbprint(ppl,"// computed Fourier transform of given ideal");
2534  dbprint(ppl-1,"// " + string(FI));
2535  list L;
2536  if (l0set)
2537  {
2538    if (Gset) // l0 and G given
2539    {
2540      L = restrictionModuleEngine(FI,w,whichengine,l0,G);
2541    }
2542    else      // l0 given, G not
2543    {
2544      L = restrictionModuleEngine(FI,w,whichengine,l0);
2545    }
2546  }
2547  else        // nothing given
2548  {
2549    L = restrictionModuleEngine(FI,w,whichengine);
2550  }
2551  ideal B,N;
2552  B = inverseFourier(L[1],v);
2553  N = inverseFourier(L[2],v);
2554  def newR = restrictionModuleOutput(B,N,w,whichengine,"intMod");
2555  return(newR);
2556}
2557example
2558{
2559  "EXAMPLE:"; echo = 2;
2560  ring r = 0,(x,b,Dx,Db),dp;
2561  def D2 = Weyl();
2562  setring D2;
2563  ideal I = x*Dx+2*b*Db+2, x^2*Dx+b*Dx+2*x;
2564  intvec w = 1,0;
2565  def im = integralModule(I,w);
2566  setring im; im;
2567  print(intMod);
2568}
2569
2570proc integralIdeal (ideal I, intvec w, list #)
2571"USAGE:  integralIdeal(I,w,[,eng,m,G]);
2572@*       I ideal, w intvec, eng and m optional ints, G optional ideal
2573RETURN:  ring (a Weyl algebra) containing an ideal 'intIdeal'
2574ASSUME:  The basering is the n-th Weyl algebra over a field of characteristic 0
2575@*       and for all 1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1
2576@*       holds, i.e. the sequence of variables is given by
2577@*       x(1),...,x(n),D(1),...,D(n), where D(i) is the differential operator
2578@*       belonging to x(i).
2579@*       Further, assume that I is holonomic and that w is n-dimensional with
2580@*       non-negative entries.
2581PURPOSE: computes the integral ideal of a holonomic ideal w.r.t. the subspace
2582@*       defined by the variables corresponding to the non-zero entries of the
2583@*       given intvec.
2584NOTE:    The output ring is the Weyl algebra defined by the zero entries of w.
2585@*       It contains ideal 'intIdeal' being the integral ideal of I w.r.t. w.
2586@*       If there are no zero entries, the input ring is returned.
2587@*       If eng<>0, @code{std} is used for Groebner basis computations,
2588@*       otherwise, and by default, @code{slimgb} is used.
2589@*       The minimal integer root of the b-function of I wrt the weight (-w,w)
2590@*       can be specified via the optional argument m.
2591@*       The optional argument G is used for specifying a Groebner basis of I
2592@*       wrt the weight (-w,w), that is, the initial form of G generates the
2593@*       initial ideal of I wrt the weight (-w,w).
2594@*       Further note, that the assumptions on m and G (if given) are not
2595@*       checked.
2596DISPLAY: If printlevel=1, progress debug messages will be printed,
2597@*       if printlevel>=2, all the debug messages will be printed.
2598EXAMPLE: example integralIdeal; shows examples
2599"
2600{
2601  def im = restrictionIdealEngine(I,w,"integral",#);
2602  return(im);
2603}
2604example
2605{
2606  "EXAMPLE:"; echo = 2;
2607  ring r = 0,(x,b,Dx,Db),dp;
2608  def D2 = Weyl();
2609  setring D2;
2610  ideal I = x*Dx+2*b*Db+2, x^2*Dx+b*Dx+2*x;
2611  intvec w = 1,0;
2612  def D1 = integralIdeal(I,w);
2613  setring D1; D1;
2614  intIdeal;
2615}
2616
2617proc deRhamCohomIdeal (ideal I, list #)
2618"USAGE:  deRhamCohomIdeal (I[,w,eng,k,G]);
2619@*       I ideal, w optional intvec, eng and k optional ints, G optional ideal
2620RETURN:  ideal
2621ASSUME:  The basering is the n-th Weyl algebra D over a field of characteristic
2622@*       zero and for all 1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1
2623@*       holds, i.e. the sequence of variables is given by
2624@*       x(1),...,x(n),D(1),...,D(n), where D(i) is the differential operator
2625@*       belonging to x(i).
2626@*       Further, assume that I is of special kind, namely let f in K[x] and
2627@*       consider the module K[x,1/f]f^m, where m is smaller than or equal to
2628@*       the minimal integer root of the Bernstein-Sato polynomial of f.
2629@*       Since this module is known to be a holonomic D-module, it has a cyclic
2630@*       presentation D/I.
2631PURPOSE: computes a basis of the n-th de Rham cohomology group of the complement
2632@*       of the hypersurface defined by f
2633NOTE:    If I does not satisfy the assumptions described above, the result might
2634@*       have no meaning. Note that I can be computed with @code{annfs}.
2635@*       If w is an intvec with exactly n strictly positive entries, w is used
2636@*       in the computation. Otherwise, and by default, w is set to (1,...,1).
2637@*       If eng<>0, @code{std} is used for Groebner basis computations,
2638@*       otherwise, and by default, @code{slimgb} is used.
2639@*       Let F(I) denote the Fourier transform of I wrt w.
2640@*       An integer smaller than or equal to the minimal integer root of the
2641@*       b-function of F(I) wrt the weight (-w,w) can be specified via the
2642@*       optional argument k.
2643@*       The optional argument G is used for specifying a Groebner Basis of F(I)
2644@*       wrt the weight (-w,w), that is, the initial form of G generates the
2645@*       initial ideal of F(I) wrt the weight (-w,w).
2646@*       Further note, that the assumptions on I, k and G (if given) are not
2647@*       checked.
2648THEORY:  (SST) pp. 232-235
2649DISPLAY: If printlevel=1, progress debug messages will be printed,
2650@*       if printlevel>=2, all the debug messages will be printed.
2651SEE ALSO: deRhamCohom
2652EXAMPLE: example deRhamCohomIdeal; shows examples
2653"
2654{
2655  intvec w = 1:(nvars(basering)/2);
2656  int l0,l0set,Gset;
2657  ideal G;
2658  int whichengine = 0;         // default
2659  if (size(#)>0)
2660  {
2661    if (typeof(#[1])=="intvec")
2662    {
2663      if (allPositive(#[1])==1)
2664      {
2665        w = #[1];
2666      }
2667      else
2668      {
2669        print("// Entries of intvec must be strictly positive");
2670        print("// Using weight " + string(w));
2671      }
2672      if (size(#)>1)
2673      {
2674        if (intLike(#[2]))
2675        {
2676          whichengine = int(#[2]);
2677        }
2678        if (size(#)>2)
2679        {
2680          if (intLike(#[3]))
2681          {
2682            l0 = int(#[3]);
2683            l0set = 1;
2684          }
2685          if (size(#)>3)
2686          {
2687            if (typeof(#[4])=="ideal")
2688            {
2689              G = #[4];
2690              Gset = 1;
2691            }
2692          }
2693        }
2694      }
2695    }
2696  }
2697  int ppl = printlevel;
2698  int i,j;
2699  int n = nvars(basering)/2;
2700  intvec v;
2701  for (i=1; i<=n; i++)
2702  {
2703    if (w[i]>0)
2704    {
2705      if (v == 0:size(v))
2706      {
2707        v[1] = i;
2708      }
2709      else
2710      {
2711        v[size(v)+1] = i;
2712      }
2713    }
2714  }
2715  ideal FI = fourier(I,v);
2716  dbprint(ppl,"// computed Fourier transform of given ideal");
2717  dbprint(ppl-1,"// " + string(FI));
2718  list L;
2719  if (l0set)
2720  {
2721    if (Gset) // l0 and G given
2722    {
2723      L = restrictionModuleEngine(FI,w,whichengine,l0,G);
2724    }
2725    else      // l0 given, G not
2726    {
2727      L = restrictionModuleEngine(FI,w,whichengine,l0);
2728    }
2729  }
2730  else        // nothing given
2731  {
2732    L = restrictionModuleEngine(FI,w,whichengine);
2733  }
2734  ideal B,N;
2735  B = inverseFourier(L[1],v);
2736  N = inverseFourier(L[2],v);
2737  dbprint(ppl,"// computed integral module of given ideal");
2738  dbprint(ppl-1,"// " + string(B));
2739  dbprint(ppl-1,"// " + string(N));
2740  ideal DR;
2741  poly p;
2742  poly Dt = 1;
2743  for (i=1; i<=n; i++)
2744  {
2745    Dt = Dt*var(i+n);
2746  }
2747  N = simplify(N,2+8);
2748  printlevel = printlevel-1;
2749  N = linReduceIdeal(N); 
2750  N = simplify(N,2+8);
2751  for (i=1; i<=size(B); i++)
2752  {
2753    p = linReduce(B[i],N);
2754    if (p<>0)
2755    {
2756      DR[size(DR)+1] = B[i]*Dt;
2757      j=1;
2758      while (p<N[j])
2759      {
2760        j++;
2761      }
2762      N = insertGenerator(N,p,j+1);
2763    }
2764  }
2765  printlevel = printlevel + 1;
2766  return(DR);
2767}
2768example
2769{
2770  "EXAMPLE:"; echo = 2;
2771  ring r = 0,(x,y,z),dp;
2772  poly F = x^3+y^3+z^3;
2773  bfctAnn(F);            // Bernstein-Sato poly of F has minimal integer root -2
2774  def W = annRat(1,F^2); // so we compute the annihilator of 1/F^2
2775  setring W; W;          // Weyl algebra, contains LD = Ann(1/F^2)
2776  LD;                    // K[x,y,z,1/F]F^(-2) is isomorphic to W/LD as W-module
2777  deRhamCohomIdeal(LD);  // we see that the K-dim is 2
2778}
2779
2780proc deRhamCohom (poly f, list #)
2781"USAGE:  deRhamCohom(f[,eng,m]);  f poly, eng and m optional ints
2782RETURN:  ring (a Weyl Algebra) containing an ideal 'DR'
2783ASSUME:  Basering is a commutative and over a field of characteristic 0.
2784PURPOSE: computes a basis of the n-th de Rham cohomology group of the complement
2785@*       of the hypersurface defined by f, where n denotes the number of
2786@*       variables of the basering
2787NOTE:    The output ring is the n-th Weyl algebra. It contains an ideal 'DR'
2788@*       being a basis of the n-th de Rham cohomology group of the complement of
2789@*       the hypersurface defined by f.
2790@*       If eng<>0, @code{std} is used for Groebner basis computations,
2791@*       otherwise, and by default, @code{slimgb} is used.
2792@*       If m is given, it is assumed to be less than or equal to the minimal
2793@*       integer root of the Bernstein-Sato polynomial of f. This assumption is
2794@*       not checked. If not specified, m is set to the minimal integer root of
2795@*       the Bernstein-Sato polynomial of f.
2796THEORY:  (SST) pp. 232-235
2797DISPLAY: If printlevel=1, progress debug messages will be printed,
2798@*       if printlevel>=2, all the debug messages will be printed.
2799SEE ALSO: deRhamCohomIdeal
2800EXAMPLE: example deRhamCohom; shows example
2801"
2802{
2803  int ppl = printlevel - voice + 2;
2804  int eng,l0,l0given;
2805  if (size(#)>0)
2806  {
2807    if(intLike(#[1]))
2808    {
2809      eng = int(#[1]);
2810    }
2811    if (size(#)>1)
2812    {
2813      if(intLike(#[2]))
2814      {
2815        l0 = int(#[2]);
2816        l0given = 1;
2817      }
2818    }
2819  }
2820  if (!isCommutative())
2821  {
2822    ERROR("Basering must be commutative.");
2823  }
2824  int i;
2825  def save = basering;
2826  int n = nvars(save);
2827  dbprint(ppl,"// Computing s-parametric annihilator Ann(f^s)...");
2828  def A = Sannfs(f);
2829  setring A;
2830  dbprint(ppl,"// ...done");
2831  dbprint(ppl-1,"//    Got: " + string(LD));
2832  poly f = imap(save,f);
2833  if (!l0given)
2834  {
2835    dbprint(ppl,"// Computing b-function of given poly...");
2836    ideal LDf = LD,f;
2837    LDf = engine(LDf,eng);
2838    vector v = pIntersect(var(2*n+1),LDf);   // BS poly of f
2839    list BS = bFactor(vec2poly(v));
2840    dbprint(ppl,"// ...done");
2841    dbprint(ppl-1,"// roots: " + string(BS[1]));
2842    dbprint(ppl-1,"// multiplicities: " + string(BS[2]));
2843    BS = intRoots(BS);
2844    intvec iv;
2845    for (i=1; i<=ncols(BS[1]); i++)
2846    {
2847      iv[i] = int(BS[1][i]);
2848    }
2849    l0 = Min(iv);
2850    kill v,iv,BS,LDf;
2851  }
2852  dbprint(ppl,"// Computing Ann(f^" + string(l0) + ")...");
2853  LD = annfspecial(LD,f,l0,l0); // Ann(f^l0)
2854  // create new ring without s
2855  list RL = ringlist(A);
2856  RL = RL[1..4];
2857  list Lt = RL[2];
2858  Lt = delete(Lt,2*n+1);
2859  RL[2] = Lt;
2860  Lt = RL[3];
2861  Lt = delete(Lt,2);
2862  RL[3] = Lt;
2863  def @B = ring(RL);
2864  setring @B;
2865  def B = Weyl();
2866  setring B;
2867  kill @B;
2868  ideal LD = imap(A,LD);
2869  LD = engine(LD,eng);
2870  dbprint(ppl,"// ...done");
2871  dbprint(ppl-1,"//    Got: " + string(LD));
2872  kill A;
2873  intvec w = 1:n;
2874  ideal DR = deRhamCohomIdeal(LD,w,eng);
2875  export(DR);
2876  setring save;
2877  return(B);
2878}
2879example
2880{
2881  "EXAMPLE:"; echo = 2;
2882  ring r = 0,(x,y,z),dp;
2883  poly f = x^3+y^3+z^3;
2884  def A = deRhamCohom(f); // we see that the K-dim is 2
2885  setring A;
2886  DR;
2887}
2888
2889// Appel hypergeometric functions /////////////////////////////////////////////
2890
2891proc appelF1()
2892"USAGE:  appelF1();
2893RETURN:  ring (a parametric Weyl algebra) containing an ideal 'IAppel1'
2894PURPOSE: defines the ideal in a parametric Weyl algebra,
2895@*       which annihilates Appel F1 hypergeometric function
2896NOTE:    The output ring is a parametric Weyl algebra. It contains an ideal
2897@*       'IAappel1' annihilating Appel F1 hypergeometric function.
2898@*       See (SST) p. 48.
2899EXAMPLE: example appelF1; shows example
2900"
2901{
2902  // Appel F1, d = b', SST p.48
2903  ring @r = (0,a,b,c,d),(x,y,Dx,Dy),(a(0,0,1,1),a(0,0,1,0),dp);
2904  def @S = Weyl();
2905  setring @S;
2906  ideal IAppel1 =
2907    (x*Dx)*(x*Dx+y*Dy+c-1) - x*(x*Dx+y*Dy+a)*(x*Dx+b),
2908    (y*Dy)*(x*Dx+y*Dy+c-1) - y*(x*Dx+y*Dy+a)*(y*Dy+d),
2909    (x-y)*Dx*Dy - d*Dx + b*Dy;
2910  export IAppel1;
2911  kill @r;
2912  return(@S);
2913}
2914example
2915{
2916  "EXAMPLE:"; echo = 2;
2917  def A = appelF1();
2918  setring A;
2919  IAppel1;
2920}
2921
2922proc appelF2()
2923"USAGE:  appelF2();
2924RETURN:  ring (a parametric Weyl algebra) containing an ideal 'IAppel2'
2925PURPOSE: defines the ideal in a parametric Weyl algebra,
2926@*       which annihilates Appel F2 hypergeometric function
2927NOTE:    The output ring is a parametric Weyl algebra. It contains an ideal
2928@*       'IAappel2' annihilating Appel F2 hypergeometric function.
2929@*       See (SST) p. 85.
2930EXAMPLE: example appelF2; shows example
2931"
2932{
2933  // Appel F2, c = b', SST p.85
2934  ring @r = (0,a,b,c),(x,y,Dx,Dy),(a(0,0,1,1),a(0,0,1,0),dp);
2935  def @S = Weyl();
2936  setring @S;
2937  ideal IAppel2 =
2938    (x*Dx)^2 - x*(x*Dx+y*Dy+a)*(x*Dx+b),
2939    (y*Dy)^2 - y*(x*Dx+y*Dy+a)*(y*Dy+c);
2940  export IAppel2;
2941  kill @r;
2942  return(@S);
2943}
2944example
2945{
2946  "EXAMPLE:"; echo = 2;
2947  def A = appelF2();
2948  setring A;
2949  IAppel2;
2950}
2951
2952proc appelF4()
2953"USAGE:  appelF4();
2954RETURN:  ring (a parametric Weyl algebra) containing an ideal 'IAppel4'
2955PURPOSE: defines the ideal in a parametric Weyl algebra,
2956@*       which annihilates Appel F4 hypergeometric function
2957NOTE:    The output ring is a parametric Weyl algebra. It contains an ideal
2958@*       'IAappel4' annihilating Appel F4 hypergeometric function.
2959@*       See (SST) p. 39.
2960EXAMPLE: example appelF4; shows example
2961"
2962{
2963  // Appel F4, d = c', SST, p. 39
2964  ring @r = (0,a,b,c,d),(x,y,Dx,Dy),(a(0,0,1,1),a(0,0,1,0),dp);
2965  def @S = Weyl();
2966  setring @S;
2967  ideal IAppel4 =
2968    Dx*(x*Dx+c-1) - (x*Dx+y*Dy+a)*(x*Dx+y*Dy+b),
2969    Dy*(y*Dy+d-1) - (x*Dx+y*Dy+a)*(x*Dx+y*Dy+b);
2970  export IAppel4;
2971  kill @r;
2972  return(@S);
2973}
2974example
2975{
2976  "EXAMPLE:"; echo = 2;
2977  def A = appelF4();
2978  setring A;
2979  IAppel4;
2980}
2981
2982
2983// characteric variety ////////////////////////////////////////////////////////
2984
2985proc charVariety(ideal I, list #)
2986"USAGE:  charVariety(I [,eng]); I an ideal, eng an optional int
2987RETURN:  ring (commutative) containing an ideal 'charVar'
2988PURPOSE: computes an ideal whose zero set is the characteristic variety of I in
2989@*       the sense of D-module theory
2990ASSUME:  The basering is the n-th Weyl algebra over a field of characteristic 0
2991@*       and for all 1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1
2992@*       holds, i.e. the sequence of variables is given by
2993@*       x(1),...,x(n),D(1),...,D(n), where D(i) is the differential operator
2994@*       belonging to x(i).
2995NOTE:    The output ring is commutative. It contains an ideal 'charVar'.
2996@*       If eng<>0, @code{std} is used for Groebner basis computations,
2997@*       otherwise, and by default, @code{slimgb} is used.
2998DISPLAY: If @code{printlevel}=1, progress debug messages will be printed,
2999@*       if @code{printlevel}>=2, all the debug messages will be printed.
3000SEE ALSO: charInfo
3001EXAMPLE: example charVariety; shows examples
3002"
3003{
3004  // assumption check is done in GBWeight
3005  int eng;
3006  if (size(#)>0)
3007  {
3008    if (intLike(#[1]))
3009    {
3010      eng = int(#[1]);
3011    }
3012  }
3013  int ppl = printlevel - voice + 2;
3014  def save = basering;
3015  int n = nvars(save)/2;
3016  intvec u = 0:n;
3017  intvec v = 1:n;
3018  dbprint(ppl,"// Computing Groebner basis wrt weights...");
3019  I = GBWeight(I,u,v,eng);
3020  dbprint(ppl,"// ...finished");
3021  dbprint(ppl-1,"//    Got: " + string(I));
3022  list RL = ringlist(save);
3023  RL = RL[1..4];
3024  def newR = ring(RL);
3025  setring newR;
3026  ideal charVar = imap(save,I);
3027  intvec uv = u,v;
3028  charVar = inForm(charVar,uv);
3029  charVar = groebner(charVar);
3030  export(charVar);
3031  setring save;
3032  return(newR);
3033}
3034example
3035{
3036  "EXAMPLE:"; echo = 2;
3037  ring r = 0,(x,y),Dp;
3038  poly F = x3-y2;
3039  printlevel = 0;
3040  def A  = annfs(F);
3041  setring A;      // Weyl algebra
3042  LD;             // the annihilator of F
3043  def CA = charVariety(LD);
3044  setring CA; CA; // commutative ring
3045  charVar;
3046  dim(charVar);   // hence I is holonomic
3047}
3048
3049proc charInfo(ideal I)
3050"USAGE:  charInfo(I);  I an ideal
3051RETURN:  ring (commut.) containing ideals 'charVar','singLoc' and list 'primDec'
3052PURPOSE: computes characteristic variety of I (in the sense of D-module theory),
3053@*       its singular locus and primary decomposition
3054ASSUME:  The basering is the n-th Weyl algebra over a field of characteristic 0
3055@*       and for all 1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1
3056@*       holds, i.e. the sequence of variables is given by
3057@*       x(1),...,x(n),D(1),...,D(n), where D(i) is the differential operator
3058@*       belonging to x(i).
3059NOTE:    In the output ring, which is commutative:
3060@*       - the ideal 'charVar' is the characteristic variety char(I),
3061@*       - the ideal 'SingLoc' is the singular locus of char(I),
3062@*       - the list 'primDec' is the primary decomposition of char(I).
3063DISPLAY: If @code{printlevel}=1, progress debug messages will be printed,
3064@*       if @code{printlevel}>=2, all the debug messages will be printed.
3065EXAMPLE: example charInfo; shows examples
3066"
3067{
3068  int ppl = printlevel - voice + 2;
3069  def save = basering;
3070  dbprint(ppl,"// computing characteristic variety...");
3071  def A = charVariety(I);
3072  setring A;
3073  dbprint(ppl,"// ...done");
3074  dbprint(ppl-1,"//    Got: " + string(charVar));
3075  dbprint(ppl,"// computing singular locus...");
3076  ideal singLoc = slocus(charVar);
3077  singLoc = groebner(singLoc);
3078  dbprint(ppl,"// ...done");
3079  dbprint(ppl-1,"//    Got: " + string(singLoc));
3080  dbprint(ppl,"// computing primary decomposition...");
3081  list primDec = primdecGTZ(charVar);
3082  dbprint(ppl,"// ...done");
3083  //export(charVar,singLoc,primDec);
3084  export(singLoc,primDec);
3085  setring save;
3086  return(A);
3087}
3088example
3089{
3090  "EXAMPLE:"; echo = 2;
3091  ring r = 0,(x,y),Dp;
3092  poly F = x3-y2;
3093  printlevel = 0;
3094  def A  = annfs(F);
3095  setring A;      // Weyl algebra
3096  LD;             // the annihilator of F
3097  def CA = charInfo(LD);
3098  setring CA; CA; // commutative ring
3099  charVar;        // characteristic variety
3100  singLoc;        // singular locus
3101  primDec;        // primary decomposition
3102}
3103
3104
3105// examples ///////////////////////////////////////////////////////////////////
3106
3107/*
3108static proc exCusp()
3109{
3110  "EXAMPLE:"; echo = 2;
3111  ring r = 0,(x,y,Dx,Dy),dp;
3112  def R = Weyl();   setring R;
3113  poly F = x2-y3;
3114  ideal I = (y^3 - x^2)*Dx - 2*x, (y^3 - x^2)*Dy + 3*y^2; // I = Dx*F, Dy*F;
3115  def W = SDLoc(I,F);
3116  setring W;
3117  LD;
3118  def U = DLoc0(LD,x2-y3);
3119  setring U;
3120  LD0;
3121  BS;
3122  // the same with DLoc:
3123  setring R;
3124  DLoc(I,F);
3125}
3126
3127static proc exWalther1()
3128{
3129  // p.18 Rem 3.10
3130  ring r = 0,(x,Dx),dp;
3131  def R = nc_algebra(1,1);
3132  setring R;
3133  poly F = x;
3134  ideal I = x*Dx+1;
3135  def W = SDLoc(I,F);
3136  setring W;
3137  LD;
3138  ideal J = LD, x;
3139  eliminate(J,x*Dx); // must be [1]=s // agree!
3140  // the same result with Dloc0:
3141  def U = DLoc0(LD,x);
3142  setring U;
3143  LD0;
3144  BS;
3145}
3146
3147static proc exWalther2()
3148{
3149  // p.19 Rem 3.10 cont'd
3150  ring r = 0,(x,Dx),dp;
3151  def R = nc_algebra(1,1);
3152  setring R;
3153  poly F = x;
3154  ideal I = (x*Dx)^2+1;
3155  def W = SDLoc(I,F);
3156  setring W;
3157  LD;
3158  ideal J = LD, x;
3159  eliminate(J,x*Dx); // must be [1]=s^2+2*s+2 // agree!
3160  // the same result with Dloc0:
3161  def U = DLoc0(LD,x);
3162  setring U;
3163  LD0;
3164  BS;
3165  // almost the same with DLoc
3166  setring R;
3167  DLoc(I,F);
3168}
3169
3170static proc exWalther3()
3171{
3172  // can check with annFs too :-)
3173  // p.21 Ex 3.15
3174  LIB "nctools.lib";
3175  ring r = 0,(x,y,z,w,Dx,Dy,Dz,Dw),dp;
3176  def R = Weyl();
3177  setring R;
3178  poly F = x2+y2+z2+w2;
3179  ideal I = Dx,Dy,Dz,Dw;
3180  def W = SDLoc(I,F);
3181  setring W;
3182  LD;
3183  ideal J = LD, x2+y2+z2+w2;
3184  eliminate(J,x*y*z*w*Dx*Dy*Dz*Dw); // must be [1]=s^2+3*s+2 // agree
3185  ring r2 =  0,(x,y,z,w),dp;
3186  poly F = x2+y2+z2+w2;
3187  def Z = annfs(F);
3188  setring Z;
3189  LD;
3190  BS;
3191  // the same result with Dloc0:
3192  setring W;
3193  def U = DLoc0(LD,x2+y2+z2+w2);
3194  setring U;
3195  LD0;  BS;
3196  // the same result with DLoc:
3197  setring R;
3198  DLoc(I,F);
3199}
3200
3201static proc ex_annRat()
3202{
3203  // more complicated example for annRat
3204  ring r = 0,(x,y,z),dp;
3205  poly f = x3+y3+z3; // mir = -2
3206  poly g = x*y*z;
3207  def A = annRat(g,f);
3208  setring A;
3209}
3210*/
Note: See TracBrowser for help on using the repository browser.