source: git/Singular/LIB/reesclos.lib @ 0ae4ce

spielwiese
Last change on this file since 0ae4ce was 0ae4ce, checked in by Anne Frühbis-Krüger <anne@…>, 23 years ago
*anne: added category to libraries for "Commutative Algebra" git-svn-id: file:///usr/local/Singular/svn/trunk@4941 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 17.6 KB
Line 
1///////////////////////////////////////////////////////////////////////////////
2// reesclos.lib
3///////////////////////////////////////////////////////////////////////////////
4
5version="$id reesclos.lib,v 1.30 2000/12/5 hirsch Exp $";
6category="Commutative Algebra";
7info="
8LIBRARY:     reesclos.lib
9AUTHOR:      Tobias Hirsch, email: hirsch@math.tu-cottbus.de
10
11OVERVIEW:
12 A library to compute the integral closure of an ideal I in a polynomial ring
13 R=k[x(1),...,x(n)] using the Rees Algebra R[It] of I. It computes the integral
14 closure of R[It] (in the same manner as done in the library 'normal.lib');
15 which is a graded subalgebra of R[t]. The degree-k-component is the integral
16 closure of the k-th power of I.
17
18PROCEDURES: 
19 ReesAlgebra(I);        computes the Rees Algebra of an ideal I
20 NormalI(I[,p[,r]]);    computes the integral closure of an ideal I using R[It]
21";
22
23LIB "normal.lib";       // for HomJJ
24LIB "standard.lib";     // for groebner
25
26///////////////////////////////////////////////////////////////////////////////
27
28proc ReesAlgebra (ideal I)
29"USAGE:    ReesAlgebra (I); I = ideal
30COMPUTE:  The Rees algebra R[I*t] as an affine ring, where I is an ideal in R
31RETURN:   a list containing two rings:
32          [1]: a ring, say RR; in the ring an ideal ker such that R[I*t]=RR/ker
33          [2]: a ring, say Kxt; the basering with additional variable t con-
34               taining an ideal mapI defining the map RR-->Kxt
35EXAMPLE:  example ReesAlgebra; shows an example
36"
37{
38  // remember the data of the basering
39
40  def oldring = basering;
41  string oldchar = charstr(basering);
42  string oldvar  = varstr(basering);
43  string oldord  = ordstr(basering);
44  int n = ncols(I);
45  ideal m = maxideal(1);
46
47 
48  // Create a new ring with variables for each generator of I
49
50  execute ("ring Rees = "+oldchar+",("+oldvar+",U(1.."+string(n)+")),dp");
51
52 
53  // Kxt is the old ring with additional variable t
54  // Here I -> t*I, so the generators of I generate the subalgebra R[It] in Kxt
55
56  execute ("ring Kxt = "+oldchar+",("+oldvar+",t),dp");
57  ideal I = fetch(oldring,I);
58  ideal m = fetch(oldring,m);
59  int k;
60  for (k=1;k<=n;k++)
61  {
62    I[k]=t*I[k];
63  }
64 
65
66  // Now we map from Rees to Kxt, identity on the original variables, and
67  // U(k) -> I[k]
68
69  ideal mapI = m,I;
70  map phi = Rees,mapI;
71  ideal zero = 0;
72  export (mapI);
73
74  // Now the Rees-Algebra is Rees/ker(phi)
75
76  setring Rees;
77  ideal ker = preimage(Kxt,phi,zero);
78  export (ker);
79 
80  list result = Rees,Kxt;
81 
82  return(result);
83 
84}
85example
86{
87  "EXAMPLE:"; echo=2;
88  ring R = 0,(x,y),dp;
89  ideal I = x2,xy4,y5;
90  list L = ReesAlgebra(I);
91  def Rees = L[1];       // defines the ring Rees, containing the ideal ker
92  setring Rees;          // passes to the ring Rees
93  Rees;
94  ker;                   // R[I*t] is isomorphic to Rees/ker
95}
96 
97
98////////////////////////////////////////////////////////////////////////////
99
100static
101proc ClosureRees (list L)
102"USAGE:    ClosureRees (L); L a list containing
103          - a ring L[1], inside L[1] an ideal ker such that L[1]/ker is
104            isomorphic to the Rees Algebra R[It] of an ideal I in k[x]
105          - a ring L[2]=k[x,t], inside L[1] an ideal mapI defining the
106            map L[1] --> L[2] with image R[It]
107COMPUTE:  quotients of elements of k[x,t] representing generators of the
108          integral closure of R[It]
109RETURN:   a list images, the first size(images)-1 entries are the nu-
110          merators of the generators, the last one is the universal deno-
111          minator
112"
113{
114  int dblvl=printlevel-voice+2;   // toggles how much data is printed
115                                  // during the procedure
116
117  def Kxt = basering;
118  def R(1) = L[1];
119  setring R(1);                   // declaration of variables used later
120  ideal ker(1)=ker;               // in STEP 2
121  poly p;
122
123  // some auxiliary variables
124
125  int i=1;         // counts the number of steps to reach the closure of R(1)
126  int check=0;     // a 'boolean' variable for several checks
127  int isIsoSing=0; // '1' in case of an isolated singularity
128
129  /////// STEP 1: ///////////////////////////////////////////////////////////
130  // construct R(i) step by step as done in normal.lib; 2 differences:     //
131  //  - since the input is a prime ideal, no splitting will occur          //
132  //  - the intermediate rings and nonzerodivisors for J are remembered    //
133  ///////////////////////////////////////////////////////////////////////////
134
135  if (dblvl>0)
136  {
137    "// STEP 1: Compute the integral closure of R[It]";
138  }
139
140  list RS;
141
142  while (check==0)  // repeat until the closure is reached
143  {
144    // construction of HomJJ, J an ideal containing the non-normal locus
145    // of R(i)/ker(i), as done in normalizationPrimes in normal.lib for
146    // the special case that we are working with a prime ideal
147
148    if (dblvl>0)
149    {
150      "";
151      "// We are in step",i;
152      pause();
153    }
154
155    if (homog(ker(i))==1)
156    {
157      list SM=mstd(ker(i));
158    }
159    else
160    {
161      list SM=groebner(ker(i)),ker(i);
162    }
163
164    if (dblvl>0)
165    {
166      "// Standard basis of the current ideal:";
167      SM[1];
168    }
169
170    // In the first iteration, we have to compute the singular locus and
171    // to check whether it is an isolated singularity (this makes things
172    // much easier: for further iterations, we just take the max. ideal).
173    // If not, we still fetch the singular locus but have to compute
174    // its radical.
175
176    if (i==1)
177    {
178      ideal J=minor(jacob(SM[2]),nvars(basering)-dim(SM[1]));
179      ideal sin=J+SM[2];
180      if (homog(SM[2])==1)
181      {
182        list JM=mstd(sin);
183      }
184      else
185      {
186        list JM=groebner(sin),sin;
187      }
188 
189      if (dim(JM[1])==0 && homog(SM[2])==1)
190      {
191        isIsoSing=1;
192      }
193      J=equiRadical(JM[2]);
194    }
195    else
196    {
197      if (isIsoSing==0)
198      {
199        ideal J=equiRadical(JM[2]);
200      }
201      else
202      {
203        ideal J=maxideal(1);
204      }
205    }
206   
207    if (dblvl>0)
208    {
209      "// Radical of the singular locus:";
210      J;
211    }
212
213    ideal SL=simplify(reduce(JM[2],SM[1]),2);
214    JM =J,J;
215    poly nzd=SL[1];           // universal denominator for HomJJ
216   
217    if (dblvl>0)
218    {
219      "// The non-zerodivisor";
220      nzd;
221      pause();
222    }
223
224    list RR=SM[1],SM[2],JM[2],SL[1];
225    RS=HomJJ(RR);
226
227    if (RS[2]==1)             // we've reached the integral closure
228    {
229      if (dblvl>0)
230      {
231        "";
232        "// We've reached the integral closure after",i,"iterations";
233        pause();
234      }
235      check=1;
236    }
237    else                      // prepare the next iteration with new
238    {                         // ring R(i+1)
239      ideal MJ=JM[2];
240 
241      def R(i+1)=RS[1];       // the data of and some variable decla-
242      setring R(i+1);         // rations in R(i+1) needed in STEP 2
243      ideal ker(i+1)=endid;
244      map phi=R(i),endphi;
245      poly p;
246
247      if (isIsoSing==0)       // fetch the singular locus if it is not
248      {                       // an isolated singularity
249        list JM=mstd(simplify(phi(MJ)+ker(i+1),4));
250      }
251      i++;
252    }
253  }
254
255  if (i==1)                     // R[It] (and thus I) was integrally
256  {                             // closed ==> we're already done
257        list result="closed";
258        return(result);
259  }
260
261
262  /////// STEP 2: ////////////////////////////////////////////////////////
263  // compute representations of the ring variables of R(i) as fractions //
264  // of elements of R(1);                                               //
265  ////////////////////////////////////////////////////////////////////////
266
267  int length=nvars(R(i));  // the number of variables of the last ring
268  int j,k,n;               // some counters
269  string mapstr;           // will be used while constructing preimages
270
271  list preimages;          // here the fractions are stored in the
272                           // form var(j)=preimages[j]/preimages[length+1]
273                           // ('=' means identification via the inclusion)
274                           // the last entry corresponds to nzd in R(i)
275
276  // For each variable (counter j) and for each intermediate ring (k):
277  // find preimages of var(j)*endphi(nzd_k-1) in R(k-1).
278  // Finally, do the same for nzd.
279
280  if (dblvl>0)
281  {
282    "// STEP 2: Compute fractions representing the ring variables of";
283    "           the last ring";
284  }
285
286  for (j=1;j<=length+1;j++)
287  {
288    setring R(i);
289
290    if (j<=length)          // do it with for ring variables...
291    {
292      p=var(j);
293    }
294    else                   // ...and finally for nzd in R(i)
295    {
296      p=1;
297    }
298
299    // get back from R(i) to R(1) step by step
300
301    for (k=i;k>1;k--)
302    {
303      // clear the fraction in the representation in R(i)   
304
305      p=p*phi(nzd);     
306
307      // compute the preimage of [p mod ker(k)] under phi in R(k-1):
308      // as p is an element of im(phi), there is a poly h such that
309      // h(vars(R(k-1)) is mapped to [p mod ker (k)], and h can be com-
310      // puted as the normal form of a w.r.t <ker(k),Z(n)-phi(k)(n)> in R(k)[Z]
311
312         // compute this normal form h...
313
314      if (j==1)    // in the first iteration: construct S(k)=R(k)[Z], fetch
315                   // endphi (the ideal defining phi) and ker(k) and construct
316                   // the ideal from above
317      {
318        execute ("ring S(k) = "+charstr(R(k))+",("+varstr(R(k))+",Z(1.."+string(ncols(endphi))+")),(dp("+string(nvars(R(k)))+"),dp("+string(ncols(endphi))+"));");
319        ideal endphi = imap(R(k),endphi);
320        ideal J = imap(R(k),ker(k));
321        for (n=1;n<=ncols(endphi);n++)
322        {
323          J=J+(Z(n)-endphi[n]);
324        }
325        J=groebner(J);
326        poly h=NF(imap(R(k),p),J);
327      }
328      else
329      {
330        setring S(k);
331        h=NF(imap(R(k),p),J);
332      }
333
334         // and compute h(vars(R(k-1)))
335
336      setring R(k-1);
337      if (j==1)  // in the first iteration: compute backmap:S(k)-->R(k-1)
338      {
339        mapstr="map backmap = S(k),";
340        for (n=1;n<=nvars(R(k));n++)
341        {
342          mapstr=mapstr+"0,";
343        }
344        execute (mapstr+"maxideal(1);");
345      }
346
347      p=NF(backmap(h),std(ker(k-1)));
348    }
349
350    // when down to R(1), store the result in the list preimages
351
352    preimages=insert(preimages,p,j-1);
353    if (dblvl>0)
354    {
355      if (j<=length)
356      {
357        "numerator of variable ",j,":",p;
358      }
359      else
360      {
361        "";
362        "and finally the 'universal' denominator:",p;
363      }
364    }
365  }
366
367  // at the end: go back to the original basering and construct gene-
368  // rators of the closure of I
369
370  setring Kxt;
371  map psi=R(1),mapI;              // from ReesAlgebra: the map Rees->Kxt
372
373  list images=psi(preimages);   
374 
375  if (dblvl>-1)
376  {
377    pause();
378    "";
379    "// Get back to the original basering and construct the";
380    "// generators of the closure of I";
381    "";
382    "// Back in k[x,t], the fractions, stored in the list images:";
383    for (int j=1;j<=size(images);j++)
384    {
385      if (j<size(images))
386      {
387        "numerator",j,":",images[j];
388      }
389      else
390      {
391        "";
392        "denominator:  ",images[j];
393      }
394    }
395    pause();
396  }
397  return (images);
398}
399
400
401////////////////////////////////////////////////////////////////////////////
402
403static
404proc ClosurePower(list images, list #)
405"USAGE:    ClosurePower (L [,#]);
406          - L a list containing generators of the closure of R[It] in k[x,t]
407            (the first size(L)-1 elements are the numerators, the last one
408            is the denominator)
409          - if # is given: #[1] is an integer, compute generators for the
410                           closure of I, I^2, ..., I^#[1]
411COMPUTE:  the integral closure of I, ... I^#[1]. If # is not given, compute
412          the closure of all powers up to the maximum degree in t occurring
413          in the closure of R[It] (so this is the last one that is not just
414          the sum/product of the above ones).
415RETURN:   a list containing generators of the closure of the desired powers
416          of I as elements of k[x,t].
417"
418{
419  int dblvl=printlevel-voice+2;   // toggles how much data is printed
420                                  // during the procedure 
421
422  int j,k,d,computepow;                    // some counters
423  int pow=0;
424  int length = size(images)-1;             // the number of generators
425  poly image;
426  poly denominator = images[length+1];     // the universal denominator
427
428  if (size(#)>0)
429  {
430    pow=#[1];
431  }
432  computepow=pow;
433
434  if (dblvl>0)
435  {
436    "";
437    "// The generators of the closure of R[It]:";
438  }
439
440  intmat m[nvars(basering)-1][1];  // an intvec used for jet and maxdeg1
441  intvec tw=m,1;                   // such that t has weight 1 and all
442                                   // other variables have weight 0
443
444  // Construct the generators of the closure of R[It] as elements of k[x,t]
445  // If # is not given, determine the highest degree pow in t that occurs.
446
447  for (j=1;j<=length;j++)
448  {
449    images[j] = (images[j]/denominator); // construct the fraction
450    image = images[j];
451    if (dblvl>0)
452    {
453      "generator",j,":",image;
454    }
455
456    if (computepow==0)              // #[1] not given or ==0 => compute pow
457    {
458      if (maxdeg1(image,tw)>pow)    // from poly.lib
459      {
460        pow=maxdeg1(image,tw);
461      }
462    }
463  } 
464
465  if (dblvl>0)
466  {
467    "";
468    if (computepow==0)
469    {
470      "// Compute the closure up to the given powers of I";
471    }
472    else
473    {
474     "// Compute the closure up to the maximal power of t that occured:",pow;
475    }
476  }
477
478  // Construct a list consisting of #[1] resp. pow times the zero ideal
479
480  ideal CurrentPower=0;
481  list result;
482  for (k=1;k<=pow;k++)
483  {
484    result=insert(result,CurrentPower);
485  }
486
487  // For each generator and each k, add its degree-k-coefficient to the #
488  // closure of I^k
489
490  for (j=1;j<=length;j++)
491  {
492    for (k=1;k<=pow;k++)
493    {
494      image=images[j]-jet(images[j],k-1,tw);
495      if (image<>0)                 
496      {                                       
497        image=subst(image/t^k,t,0);
498        if (image<>0)
499        {
500          result[k]=result[k]+image;
501        }
502      }
503    }
504  }
505
506  if (dblvl>0)
507  {
508    "";
509    "// The 'pure' parts of degrees 1..pow:";
510    result;
511    "";
512  }
513
514  // finally, add the suitable products of generators in lower degrees
515
516  for (k=2;k<=pow;k++)
517  {
518    for (j=1;j<=(k div 2);j++)
519    {
520      result[k]=result[k]+result[j]*result[k-j];
521    }
522  }
523 
524  return(result);
525}
526
527////////////////////////////////////////////////////////////////////////////
528
529proc normalI(ideal I, list #)
530"USAGE:    normalI (I [,p[,r]]); I an ideal, p and r optional integers
531COMPUTE:  the integral closure of I, ..., I^p. If p is not given, or p==0,
532          compute the closure of all powers up to the maximum degree in t
533          occurring in the closure of R[It] (so this is the last one that
534          is not just the sum/product of the above ones).
535          If r is given and <>1, the check whether the input ideal is
536          already a radical ideal is omitted.
537RETURN:   a list containing the closure of the desired powers of I as ideals
538          of the basering.
539DISPLAY:  The procedure displays more comments for higher printlevel
540EXAMPLE:  example normalI; shows an example
541"
542{
543  int dblvl=printlevel-voice+2;   // toggles how much data is printed
544                                  // during the procedure
545
546  def BAS=basering;               // remember the basering
547
548  // two simple cases: principal ideals and radical ideals are always
549  // integrally closed
550
551  if (size(I)<=1)        // includes the case I=(0)
552  {
553    if (dblvl>0)
554    {
555      "// Trivial case: I is a principal ideal";
556    }
557    list result=I;
558    if (size(#)>0)
559    {
560      for (int k=1;k<=#[1]-1;k++)
561      {
562        result=insert(result,I*result[k],k);
563      }
564    }
565    return(result);
566  }
567
568  int testrad=1;      // do the radical check?
569  if (size(#)>1)
570  {
571    if (#[2]<>1)
572    {
573      testrad=0;
574    }
575  }
576  if (testrad==1)
577  {
578    if (dblvl>0)
579    {
580      "//Check whether I is radical";
581    }
582
583    if (size(reduce(radical(I),std(I)))==0)
584    {
585      if (dblvl>0)
586      {
587        "//Trivial case: I is a radical ideal";
588      }
589      list result=I;
590      if (size(#)>0)
591      {
592        for (int k=1;k<=#[1]-1;k++)
593        {
594          result=insert(result,I*result[k],k);
595        }
596      }
597      return(result);
598    }
599  }
600
601  // start with the computation of the Rees Algebra R[It] of I
602
603  if (dblvl>0)
604  {
605    "// We start with the Rees Algebra of I:";
606  }
607 
608  list Rees = ReesAlgebra(I);
609  def R(1)=Rees[1];
610  def Kxt=Rees[2];
611  setring R(1);
612 
613  if (dblvl>0)
614  {
615    R(1);
616    ker;
617    "";
618    "// Now ClosureRees computes generators for the integral closure";
619    "// of R[It] step by step";
620  }
621
622  // ClosureRees computes fractions in R[x,t] representing the generators
623  // of the closure of R[It] in k[x,t], which is the same as the closure
624  // in Q(R[It]).
625  // the first size(images)-1 entries are the numerators of the gene-
626  // rators, the last entry is the 'universal' denominator
627
628  setring Kxt;
629  list images = ClosureRees(Rees);
630
631  // ClosureRees was done after the first HomJJ-call
632  // ==> I is integrally closed, and images consists of the only entry "closed"
633
634  if ((size(images)==1) && (typeof(images[1])=="string"))
635  {
636    if (dblvl>0)
637    {
638      "//I is integrally closed!";
639    }
640   
641    setring BAS;
642    list result=I;
643    if (size(#)>0)
644    {
645      for (int k=1;k<=#[1]-1;k++)
646      {
647        result=insert(result,I*result[k],k);
648      }
649    }
650    return(result);
651  }
652   
653  // construct the fractions corresponding to the generators of the
654  // closure of I and its powers, depending on # (in fact, they will
655  // not be real fractions, of course). This is done in ClosurePower.
656
657  list result = ClosurePower(images,#);
658
659  // finally fetch the result to the old basering
660
661  setring BAS;
662  list result=fetch(Kxt,result);
663  return(result); 
664}
665example
666{
667  "EXAMPLE:"; echo=2;
668  ring R=0,(x,y),dp;
669  ideal I = x2,xy4,y5;
670  list J = normalI(I);
671  I;
672  J;                             // J is the integral closure of I
673}
Note: See TracBrowser for help on using the repository browser.