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

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