source: git/Singular/LIB/dmodapp.lib @ 0a2f7d

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