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

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