source: git/Singular/LIB/normal.lib @ 49b2c8

spielwiese
Last change on this file since 49b2c8 was 49b2c8, checked in by Hans Schönemann <hannes@…>, 20 years ago
*pfister: again fixes git-svn-id: file:///usr/local/Singular/svn/trunk@7138 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 68.0 KB
Line 
1///////////////////////////////////////////////////////////////////////////////
2version="$Id: normal.lib,v 1.40 2004-04-20 14:27:46 Singular Exp $";
3category="Commutative Algebra";
4info="
5LIBRARY:  normal.lib     Normalization of Affine Rings
6AUTHORS:  G.-M. Greuel,  greuel@mathematik.uni-kl.de,
7@*        G. Pfister,    pfister@mathematik.uni-kl.de
8
9MAIN PROCEDURES:
10 normal(I[,wd]);     computes the normalization of basering/I,
11                     resp. computes the normalization of basering/I and
12                     the delta invariant
13 HomJJ(L);           presentation of End_R(J) as affine ring, L a list
14 genus(I);           computes genus of the projective curve defined by I
15
16AUXILIARY PROCEDURE:
17 deltaLoc(f,S);      (sum of) delta invariant(s) at conjugated singular points
18";
19
20LIB "general.lib";
21LIB "poly.lib";
22LIB "sing.lib";
23LIB "primdec.lib";
24LIB "elim.lib";
25LIB "presolve.lib";
26LIB "inout.lib";
27LIB "ring.lib";
28LIB "hnoether.lib";
29///////////////////////////////////////////////////////////////////////////////
30
31proc HomJJ (list Li)
32"USAGE:   HomJJ (Li);  Li = list: ideal SBid, ideal id, ideal J, poly p
33ASSUME:  R    = P/id,  P = basering, a polynomial ring, id an ideal of P,
34@*       SBid = standard basis of id,
35@*       J    = ideal of P containing the polynomial p,
36@*       p    = nonzero divisor of R
37COMPUTE: Endomorphism ring End_R(J)=Hom_R(J,J) with its ring structure as
38         affine ring, together with the canonical map R --> Hom_R(J,J),
39         where R is the quotient ring of P modulo the standard basis SBid.
40RETURN:  a list l of two objects
41@format
42         l[1] : a polynomial ring, containing two ideals, 'endid' and 'endphi'
43               such that l[1]/endid = Hom_R(J,J) and
44               endphi describes the canonical map R -> Hom_R(J,J)
45         l[2] : an integer which is 1 if phi is an isomorphism, 0 if not
46         l[3] : an integer, the contribution to delta
47@end format
48NOTE:    printlevel >=1: display comments (default: printlevel=0)
49EXAMPLE: example HomJJ;  shows an example
50"
51{
52//---------- initialisation ---------------------------------------------------
53   int isIso,isPr,isCo,isRe,isEq,oSAZ,ii,jj,q,y;
54   intvec rw,rw1;
55   list L;
56   y = printlevel-voice+2;  // y=printlevel (default: y=0)
57   def P = basering;
58   ideal SBid, id, J = Li[1], Li[2], Li[3];
59   poly p = Li[4];
60   attrib(SBid,"isSB",1);
61   int homo = homog(Li[2]);               //is 1 if id is homogeneous, 0 if not
62
63//---- set attributes for special cases where algorithm can be simplified -----
64   if( homo==1 )
65   {
66      rw = ringweights(P);
67   }
68   if( typeof(attrib(id,"isPrim"))=="int" )
69   {
70      if(attrib(id,"isPrim")==1)  { isPr=1; }
71   }
72   if( typeof(attrib(id,"onlySingularAtZero"))=="int" )
73   {
74      if(attrib(id,"onlySingularAtZero")==1){oSAZ=1; }
75   }
76   if( typeof(attrib(id,"isIsolatedSingularity"))=="int" )
77   {
78      if(attrib(id,"isIsolatedSingularity")==1) { isIso=1; }
79   }
80   if( typeof(attrib(id,"isCohenMacaulay"))=="int" )
81   {
82      if(attrib(id,"isCohenMacaulay")==1) { isCo=1; }
83   }
84   if( typeof(attrib(id,"isRegInCodim2"))=="int" )
85   {
86      if(attrib(id,"isRegInCodim2")==1) { isRe=1; }
87   }
88   if( typeof(attrib(id,"isEquidimensional"))=="int" )
89   {
90      if(attrib(id,"isEquidimensional")==1) { isEq=1; }
91   }
92//-------------------------- go to quotient ring ------------------------------
93   qring R  = SBid;
94   ideal id = fetch(P,id);
95   ideal J  = fetch(P,J);
96   poly p   = fetch(P,p);
97   ideal f,rf,f2;
98   module syzf;
99//---------- computation of p*Hom(J,J) as R-ideal -----------------------------
100   if ( y>=1 )
101   {
102     "// compute p*Hom(J,J) = p*J:J, p a non-zerodivisor";
103     "//   p is equal to:"; "";
104     p;
105     "";
106   }
107   f  = quotient(p*J,J);
108
109   if ( y>=1 )
110   { "// the module p*Hom(J,J) = p*J:J, p a non-zerodivisor";
111      "// p"; p;
112      "// f=p*J:J";f;
113   }
114   f2 = std(p);
115 
116//---------- Test: Hom(J,J) == R ?, if yes, go home ---------------------------
117
118   rf = interred(reduce(f,f2));       // represents p*Hom(J,J)/p*R = Hom(J,J)/R
119   if ( size(rf) == 0 )
120   {
121      if ( homog(f) && find(ordstr(basering),"s")==0 )
122      {
123         ring newR1 = char(P),(X(1..nvars(P))),(a(rw),dp);
124      }
125      else
126      {
127         ring newR1 = char(P),(X(1..nvars(P))),dp;
128      }
129      ideal endphi = maxideal(1);
130      ideal endid = fetch(P,id);
131      L=substpart(endid,endphi,homo,rw);
132      def lastRing=L[1];
133      setring lastRing;
134
135      attrib(endid,"onlySingularAtZero",oSAZ);
136      attrib(endid,"isCohenMacaulay",isCo);
137      attrib(endid,"isPrim",isPr);
138      attrib(endid,"isIsolatedSingularity",isIso);
139      attrib(endid,"isRegInCodim2",isRe);
140      attrib(endid,"isEqudimensional",isEq);
141      attrib(endid,"isCompleteIntersection",0);
142      attrib(endid,"isRad",0);
143      L=lastRing;
144      L = insert(L,1,1);
145      dbprint(y,"// case R = Hom(J,J)");
146      if(y>=1)
147      {
148         "//   R=Hom(J,J)";
149         "   ";
150         lastRing;
151         "   ";
152         "//   the new ideal";
153         endid;
154         "   ";
155         "//   the old ring";
156         "   ";
157         P;
158         "   ";
159         "//   the old ideal";
160         "   ";
161         setring P;
162         id;
163         "   ";
164         setring lastRing;
165         "//   the map";
166         "   ";
167         endphi;
168         "   ";
169         pause();
170         newline;
171      }
172      setring P;
173      L[3]=0;
174      return(L);
175   }
176   if(y>=1)
177   {
178      "// R is not equal to Hom(J,J), we have to try again";
179      pause();
180      newline;
181   }
182//---------- Hom(J,J) != R: create new ring and map from old ring -------------
183// the ring newR1/SBid+syzf will be isomorphic to Hom(J,J) as R-module
184
185   f=mstd(f)[2];
186   ideal ann=quotient(f2,f);
187   int delt;
188   if(isIso&&isEq){delt=vdim(std(modulo(f,ideal(p))));}
189
190   f = p,rf;          // generates pJ:J mod(p), i.e. p*Hom(J,J)/p*R as R-module
191   q = size(f);
192
193   syzf = syz(f);
194
195   if ( homo==1 )
196   {
197      rw1 = rw,0;
198      for ( ii=2; ii<=q; ii++ )
199      {
200         rw  = rw, deg(f[ii])-deg(f[1]);
201         rw1 = rw1, deg(f[ii])-deg(f[1]);
202      }
203      ring newR1 = char(R),(X(1..nvars(R)),T(1..q)),(a(rw1),dp);
204   }
205   else
206   {
207      ring newR1 = char(R),(X(1..nvars(R)),T(1..q)),dp;
208   }
209
210   map psi1 = P,maxideal(1);
211   ideal SBid = psi1(SBid);
212   attrib(SBid,"isSB",1);
213
214   qring newR = std(SBid);
215
216   map psi = R,ideal(X(1..nvars(R)));
217   ideal id = psi(id);
218   ideal f = psi(f);
219   module syzf = psi(syzf);
220   ideal pf,Lin,Quad,Q;
221   matrix T,A;
222   list L1;
223
224//---------- computation of Hom(J,J) as affine ring ---------------------------
225// determine kernel of: R[T1,...,Tq] -> J:J >-> R[1/p]=R[t]/(t*p-1),
226// Ti -> fi/p -> t*fi (p=f1=f[1]), to get ring structure. This is of course
227// the same as the kernel of R[T1,...,Tq] -> pJ:J >-> R, Ti -> fi.
228// It is a fact, that the kernel is generated by the linear and the quadratic
229// relations
230
231   pf = f[1]*f;
232   T = matrix(ideal(T(1..q)),1,q);
233   Lin = ideal(T*syzf);
234   if(y>=1)
235   {
236      "// the ring structure of Hom(J,J) as R-algebra";
237      " ";
238      "//   the linear relations";
239      " ";
240      Lin;
241      "   ";
242   }
243
244   for (ii=2; ii<=q; ii++ )
245   {
246      for ( jj=2; jj<=ii; jj++ )
247      {
248         A = lift(pf,f[ii]*f[jj]);
249         Quad = Quad, ideal(T(jj)*T(ii) - T*A);          // quadratic relations
250      }
251   }
252
253   if(y>=1)
254   {
255      "//   the quadratic relations";
256      "   ";
257      interred(Quad);
258      pause();
259      newline;
260   }
261   Q = Lin,Quad;
262   Q = subst(Q,T(1),1);
263   Q=mstd(Q)[2];
264//---------- reduce number of variables by substitution, if possible ----------
265   if (homo==1)
266   {
267      ring newRing = char(R),(X(1..nvars(R)),T(2..q)),(a(rw),dp);
268   }
269   else
270   {
271      ring newRing = char(R),(X(1..nvars(R)),T(2..q)),dp;
272   }
273
274   ideal endid  = imap(newR,id),imap(newR,Q);
275   ideal endphi = ideal(X(1..nvars(R)));
276
277   L=substpart(endid,endphi,homo,rw);
278
279   def lastRing=L[1];
280   setring lastRing;
281
282   attrib(endid,"onlySingularAtZero",0);
283   map sigma=R,endphi;
284   ideal an=sigma(ann);
285   export(an);  //noetig?
286   ideal te=an,endid;
287   if(isIso&&(size(reduce(te,std(maxideal(1))))==0))
288   {
289      attrib(endid,"onlySingularAtZero",oSAZ);
290   }
291   kill te;
292   attrib(endid,"isCohenMacaulay",isCo);
293   attrib(endid,"isPrim",isPr);
294   attrib(endid,"isIsolatedSingularity",isIso);
295   attrib(endid,"isRegInCodim2",isRe);
296   attrib(endid,"isEquidimensional",isEq);
297   attrib(endid,"isCompleteIntersection",0);
298   attrib(endid,"isRad",0);
299   if(y>=1)
300   {
301      "//   the new ring after reduction of the number of variables";
302      "   ";
303      lastRing;
304      "   ";
305      "//   the new ideal";
306      "   ";
307      endid;
308      "   ";
309      "//   the old ring";
310      "   ";
311      P;
312      "   ";
313      "//   the old ideal";
314      "   ";
315      setring P;
316      id;
317      "   ";
318      setring lastRing;
319      "//   the map";
320      "   ";
321      endphi;
322      "   ";
323      pause();
324      newline;
325   }
326   L = lastRing;
327   L = insert(L,0,1);
328   L[3]=delt;
329   return(L);
330}
331example
332{"EXAMPLE:";  echo = 2;
333  ring r   = 0,(x,y),wp(2,3);
334  ideal id = y^2-x^3;
335  ideal J  = x,y;
336  poly p   = x;
337  list Li = std(id),id,J,p;
338  list L   = HomJJ(Li);
339  def end = L[1];    // defines ring L[1], containing ideals endid, endphi
340  setring end;       // makes end the basering
341  end;
342  endid;             // end/endid is isomorphic to End(r/id) as ring
343  map psi = r,endphi;// defines the canonical map r/id -> End(r/id)
344  psi;
345}
346
347///////////////////////////////////////////////////////////////////////////////
348
349proc normal(ideal id, list #)
350"USAGE:   normal(i [,choose]);  i a radical ideal, choose empty, 1 ,\"g\" \"wd\"
351         if choose=1 the normalization of the associated primes is computed
352         (which is sometimes more efficient);
353         if @code{choose=\"wd\"} the delta invariant is computed
354         simultaneously; this may take much more time in the reducible case,
355         since the factorizing standard basis algorithm cannot be used.
356         if @code{choose=\"g\"} the generators of the integral closure
357         are computed.
358ASSUME:  The ideal must be radical, for non-radical ideals the output may
359         be wrong (i=radical(i); makes i radical)
360RETURN:  a list of rings, say nor and in case of @code{choose=\"wd\"} an
361         integer at the end of the list.
362         In case of @code{choose=\"g\"} it returns a list of polynomials
363         g_1,...,g_k+1 at the end of the list such that g_1/g_k+1,...
364         g_k/g_k+1 generate the integral closure.
365         Each ring @code{nor[i]} contains two ideals with given names
366         @code{norid} and @code{normap} such that@*
367         - the direct sum of the rings @code{nor[i]/norid} is the
368         normalization of basering/id;@*
369         - @code{normap} gives the normalization map from basering/id to
370         @code{nor[i]/norid} (for each i).
371NOTE:    to use the i-th ring type: @code{def R=nor[i]; setring R;}.
372@*       Increasing printlevel displays more comments (default: printlevel=0).
373@*       Not implemented for local or mixed orderings.
374@*       If the input ideal i is weighted homogeneous a weighted ordering may
375         be used (qhweight(i); computes weights).
376KEYWORDS: normalization; delta invariant.
377EXAMPLE: example normal; shows an example
378"
379{
380   int i,j,y,withdelta,withgens;
381   string sr;
382   list result,prim,keepresult;
383   y = printlevel-voice+2;
384   if(size(#)>0)
385   {
386     if(typeof(#[1])=="string")
387     {
388       if(#[1]=="g")
389       {
390          withgens=1;
391       }
392       else
393       {
394          withdelta=1;
395       }
396       kill #;
397       list #;
398     }
399   }
400   attrib(id,"isRadical",1);
401   if ( ord_test(basering) != 1)
402   {
403     "";
404     "// Not implemented for this ordering,";
405     "// please change to global ordering!";
406     return(result);
407   }
408   if(withgens)
409   {
410      list pr=minAssGTZ(id);
411      if(size(pr)>1){ERROR("ideal is not prime");}
412      def R=basering;
413      if(defined(ker)){kill ker;}
414      ideal ker=id;
415      export(ker);
416      list l=R;
417      l=primeClosure(l);
418      list gens=closureGenerators(l);
419      list resu=l[size(l)],gens;
420      dbprint(y+1,"
421// 'normal' created a list of one ring.
422// nor[2] is a list of elements of the basering such that
423// nor[2][i]/nor[2][size(nor[2])] generate the integral closure.
424// To see the rings, type (if the name of your list is nor):
425     show( nor);
426// To access the 1-st ring and map (similar for the others), type:
427     def R = nor[1]; setring R;  norid; normap;
428// R/norid is the 1-st ring of the normalization and
429// normap the map from the original basering to R/norid");
430
431      return(resu);
432   }
433   if( typeof(attrib(id,"isCompleteIntersection"))=="int" )
434   {
435      if(attrib(id,"isCompleteIntersection")==1)
436      {
437         attrib(id,"isCohenMacaulay",1);
438         attrib(id,"isEquidimensional",1);
439      }
440   }
441   if( typeof(attrib(id,"isCohenMacaulay"))=="int" )
442   {
443      if(attrib(id,"isCohenMacaulay")==1)
444      {
445         attrib(id,"isEquidimensional",1);
446      }
447   }
448   if( typeof(attrib(id,"isPrim"))=="int" )
449   {
450      if(attrib(id,"isPrim")==1)
451      {
452         attrib(id,"isEquidimensional",1);
453      }
454   }
455   if(size(#)==0)
456   {
457      if( typeof(attrib(id,"isEquidimensional"))=="int" )
458      {
459         if(attrib(id,"isEquidimensional")==1)
460         {
461            prim[1]=id;
462         }
463         else
464         {
465            prim=equidim(id);
466         }
467      }
468      else
469      {
470         prim=equidim(id);
471      }
472      if(y>=1)
473      {
474         "// we have ",size(prim),"equidimensional components";
475      }
476      if(withdelta &&(size(prim)>1))
477      {
478         withdelta=0;
479         "WARNING!  cannot compute delta,";
480         "the ideal is not equidimensional";
481      }
482      if(!withdelta)
483      {
484         option(redSB);
485         for(j=1;j<=size(prim);j++)
486         {
487            keepresult=keepresult+facstd(prim[j]);
488         }
489         prim=keepresult;
490         option(noredSB);
491      }
492   }
493   else
494   {
495      if( typeof(attrib(id,"isPrim"))=="int" )
496      {
497         if(attrib(id,"isPrim")==1)
498         {
499            prim[1]=id;
500         }
501         else
502         {
503            prim=minAssPrimes(id);
504         }
505      }
506      else
507      {
508         prim=minAssPrimes(id);
509      }
510      if(y>=1)
511      {
512         "// we have ",size(prim),"irreducible components";
513      }
514   }
515   for(i=1; i<=size(prim); i++)
516   {
517      if(y>=1)
518      {
519         "// we are in loop ",i;
520      }
521      attrib(prim[i],"isCohenMacaulay",0);
522      if(size(#)!=0)
523      {
524         attrib(prim[i],"isPrim",1);
525      }
526      else
527      {
528         attrib(prim[i],"isPrim",0);
529      }
530      attrib(prim[i],"isRegInCodim2",0);
531      attrib(prim[i],"isIsolatedSingularity",0);
532      attrib(prim[i],"isEquidimensional",1);
533      attrib(prim[i],"isCompleteIntersection",0);
534      attrib(prim[i],"onlySingularAtZero",0);
535      if( typeof(attrib(id,"onlySingularAtZero"))=="int" )
536      {
537            if(attrib(id,"onlySingularAtZero")==1)
538             {attrib(prim[i],"onlySingularAtZero",1); }
539      }
540
541      if( typeof(attrib(id,"isIsolatedSingularity"))=="int" )
542      {
543            if(attrib(id,"isIsolatedSingularity")==1)
544             {attrib(prim[i],"isIsolatedSingularity",1); }
545      }
546
547      if( typeof(attrib(id,"isCompleteIntersection"))=="int" )
548      {
549            if((attrib(id,"isIsolatedSingularity")==1)&&(size(#)==0))
550             {attrib(prim[i],"isIsolatedSingularity",1); }
551      }
552      keepresult=normalizationPrimes(prim[i],maxideal(1),0);
553
554      for(j=1;j<=size(keepresult)-1;j++)
555      {
556         result=insert(result,keepresult[j]);
557      }
558      sr = string(size(result));     
559   }
560   if(withdelta)
561   {
562      sr = string(size(keepresult)-1);
563      result=keepresult;
564   }
565      dbprint(y+1,"
566// 'normal' created a list of "+sr+" ring(s).");
567      if(withdelta)
568      {
569        dbprint(y+1,"// nor["+sr+"+1] is the delta-invariant.");
570      }
571      dbprint(y+1,"// To see the rings, type (if the name of your list is nor):
572     show( nor);
573// To access the 1-st ring and map (similar for the others), type:
574     def R = nor[1]; setring R;  norid; normap;
575// R/norid is the 1-st ring of the normalization and
576// normap the map from the original basering to R/norid");
577
578      //kill endphi,endid;
579      return(result);
580}
581example
582{ "EXAMPLE:"; echo = 2;
583   ring r=32003,(x,y,z),wp(2,1,2);
584   ideal i=z3-xy4;
585   list nor=normal(i);
586   show(nor);
587   def r1=nor[1];
588   setring r1;
589   norid;
590   normap;
591
592   ring s=0,(x,y),dp;
593   ideal i=(x-y^2)^2 - y*x^3;
594   nor=normal(i,"wd");
595   //the delta-invariant
596   nor[size(nor)];
597   nor=normal(i,"g");
598   nor[size(nor)];
599}
600
601///////////////////////////////////////////////////////////////////////////////
602static proc normalizationPrimes(ideal i,ideal ihp,int delt, list #)
603"USAGE:   normalizationPrimes(i,ihp[,si]);  i equidimensional ideal, ihp map
604         (partial normalization),delta partial delta-invariant,
605          # ideal of singular locus
606RETURN:   a list of rings, say nor, and an integer, the delta-invariant
607          at the end of the list.
608          each ring nor[i] contains two ideals
609          with given names norid and normap such that
610           - the direct sum of the rings nor[i]/norid is
611             the normalization of basering/id;
612           - normap gives the normalization map from basering/id
613             to nor[i]/norid (for each i)
614EXAMPLE: example normalizationPrimes; shows an example
615"
616{
617
618   int y = printlevel-voice+2;  // y=printlevel (default: y=0)
619
620   if(y>=1)
621   {
622     "";
623     "// START a normalization loop with the ideal";  "";
624     i;  "";
625     basering;  "";
626     pause();
627     newline;
628   }
629
630   def BAS=basering;
631   list result,keepresult1,keepresult2;
632   ideal J,SB,MB;
633   int depth,lauf,prdim;
634   int ti=timer;
635
636   if(size(i)==0)
637   {
638      if(y>=1)
639      {
640          "// the ideal was the zero-ideal";
641      }
642         execute("ring newR7="+charstr(basering)+",("+varstr(basering)+"),("
643                      +ordstr(basering)+");");
644         ideal norid=ideal(0);
645         ideal normap=fetch(BAS,ihp);
646         export norid;
647         export normap;
648         result=newR7;
649         result[size(result)+1]=delt;
650         setring BAS;
651         return(result);
652   }
653
654   if(y>=1)
655   {
656     "// SB-computation of the input ideal";
657   }
658   list SM=mstd(i);                //here the work starts
659   int dimSM =  dim(SM[1]);        //dimension of variety to normalize
660  // Case: Get an ideal containing a unit
661   if( dimSM == -1)
662   {  "";
663      "      // A unit ideal was found.";
664      "      // Stop with partial result computed so far";"";
665
666         MB=SM[2];
667         intvec rw;
668         list LL=substpart(MB,ihp,0,rw);
669         def newR6=LL[1];
670         setring newR6;
671         ideal norid=endid;
672         ideal normap=endphi;
673         kill endid,endphi;
674         export norid;
675         export normap;
676         result=newR6;
677         result[size(result)+1]=delt;
678         setring BAS;
679         return(result);
680   }
681
682   if(y>=1)
683   {
684      "//   the dimension is:"; "";
685      dimSM;"";
686   }
687   if(size(#)>0)
688   {
689      if(attrib(i,"onlySingularAtZero"))
690      {
691         list JM=maxideal(1),maxideal(1);
692         attrib(JM[1],"isSB",1);
693         attrib(JM[2],"isRad",1);
694      }
695      else
696      {
697         ideal te=#[1],SM[2];
698         list JM=mstd(te);
699         kill te;
700         if( typeof(attrib(#[1],"isRad"))!="int" )
701         {
702            attrib(JM[2],"isRad",0);
703         }
704      }
705   }
706
707   if(attrib(i,"isPrim")==1)
708   {
709      attrib(SM[2],"isPrim",1);
710   }
711   else
712   {
713      attrib(SM[2],"isPrim",0);
714   }
715   if(attrib(i,"isIsolatedSingularity")==1)
716   {
717      attrib(SM[2],"isIsolatedSingularity",1);
718   }
719   else
720   {
721      attrib(SM[2],"isIsolatedSingularity",0);
722   }
723   if(attrib(i,"isCohenMacaulay")==1)
724   {
725      attrib(SM[2],"isCohenMacaulay",1);
726   }
727   else
728   {
729      attrib(SM[2],"isCohenMacaulay",0);
730   }
731   if(attrib(i,"isRegInCodim2")==1)
732   {
733      attrib(SM[2],"isRegInCodim2",1);
734   }
735   else
736   {
737      attrib(SM[2],"isRegInCodim2",0);
738   }
739   if(attrib(i,"isEquidimensional")==1)
740   {
741      attrib(SM[2],"isEquidimensional",1);
742   }
743   else
744   {
745      attrib(SM[2],"isEquidimensional",0);
746   }
747   if(attrib(i,"isCompleteIntersection")==1)
748   {
749      attrib(SM[2],"isCompleteIntersection",1);
750   }
751   else
752   {
753      attrib(SM[2],"isCompleteIntersection",0);
754   }
755   if(attrib(i,"onlySingularAtZero")==1)
756   {
757      attrib(SM[2],"onlySingularAtZero",1);
758   }
759   else
760   {
761      attrib(SM[2],"onlySingularAtZero",0);
762   }
763   if((attrib(SM[2],"isIsolatedSingularity")==1)&&(homog(SM[2])==1))
764   {
765      attrib(SM[2],"onlySingularAtZero",1);
766   }
767
768   //the smooth case
769   if(size(#)>0)
770   {
771      if(dim(JM[1])==-1)
772      {
773         if(y>=1)
774         {
775            "// the ideal was smooth";
776         }
777         MB=SM[2];
778         intvec rw;;
779         list LL=substpart(MB,ihp,0,rw);
780         def newR6=LL[1];
781         setring newR6;
782         ideal norid=endid;
783         ideal normap=endphi;
784         kill endid,endphi;
785         export norid;
786         export normap;
787         result=newR6;
788         result[size(result)+1]=delt;
789         setring BAS;
790         return(result);
791     }
792   }
793
794   //the zero-dimensional case
795   if((dim(SM[1])==0)&&(homog(SM[2])==1))
796   {
797      if(y>=1)
798      {
799         "// the ideal was zero-dimensional and homogeneous";
800      }
801      MB=maxideal(1);
802      intvec rw;
803      list LL=substpart(MB,ihp,0,rw);
804      def newR5=LL[1];
805      setring newR5;
806      ideal norid=endid;
807      ideal normap=endphi;
808      kill endid,endphi;
809      export norid;
810      export normap;
811      result=newR5;
812      result[size(result)+1]=delt;
813      setring BAS;
814      return(result);
815   }
816
817   //the one-dimensional case
818   //in this case it is a line because
819   //it is irreducible and homogeneous
820   if((dim(SM[1])==1)&&(attrib(SM[2],"isPrim")==1)
821        &&(homog(SM[2])==1))
822   {
823      if(y>=1)
824      {
825         "// the ideal defines a line";
826      }
827      MB=SM[2];
828      intvec rw;
829      list LL=substpart(MB,ihp,0,rw);
830      def newR4=LL[1];
831      setring newR4;
832      ideal norid=endid;
833      ideal normap=endphi;
834      kill endid,endphi;
835      export norid;
836      export normap;
837      result=newR4;
838      result[size(result)+1]=delt;
839      setring BAS;
840      return(result);
841   }
842
843   //the higher dimensional case
844   //we test first of all CohenMacaulay and
845   //complete intersection
846   if(((size(SM[2])+dim(SM[1]))==nvars(basering))&&(homog(SM[2])==1))
847   {
848      //test for complete intersection
849      attrib(SM[2],"isCohenMacaulay",1);
850      attrib(SM[2],"isCompleteIntersection",1);
851      attrib(SM[2],"isEquidimensional",1);
852      if(y>=1)
853      {
854         "// the ideal is a complete intersection";
855      }
856   }
857   if((attrib(SM[2],"onlySingularAtZero")==0)&&(size(i)==1))
858   {
859      int tau=vdim(std(i+jacob(i)));
860      if(tau>=0)
861      {
862        execute("ring BASL="+charstr(BAS)+",("+varstr(BAS)+"),ds;");
863        ideal i=imap(BAS,i);
864        int tauloc=vdim(std(i+jacob(i)));
865        setring BAS;
866        attrib(SM[2],"onlySingularAtZero",(tau==tauloc));
867        kill BASL;
868      }
869   }
870   //compute the singular locus
871   if((attrib(SM[2],"onlySingularAtZero")==0)&&(size(#)==0))
872   {
873      J=minor(jacob(SM[2]),nvars(basering)-dim(SM[1]));
874      if(y >=1 )
875      {
876         "// SB of singular locus will be computed";
877      }
878      ideal sin=J,SM[1];
879      list JM=mstd(sin);
880      attrib(JM[1],"isSB",1);
881
882      //JM[1] SB of singular locus, JM[2]=minbasis of singular locus
883      //SM[1] SB of the input ideal, SM[2] minbasis
884      if(y>=1)
885      {
886         "//   the dimension of the singular locus is:";"";
887         dim(JM[1]); "";
888      }
889
890      if(dim(JM[1])==-1)
891      {
892         if(y>=1)
893         {
894            "// the ideal is smooth";
895         }
896         MB=SM[2];
897         intvec rw;
898         list LL=substpart(MB,ihp,0,rw);
899         def newR3=LL[1];
900         setring newR3;
901         ideal norid=endid;
902         ideal normap=endphi;
903         kill endid,endphi;
904         export norid;
905         export normap;
906         result=newR3;
907         result[size(result)+1]=delt;
908         setring BAS;
909         return(result);
910      }
911      if(dim(JM[1])==0)
912      {
913         attrib(SM[2],"isIsolatedSingularity",1);
914         if(homog(SM[2])){attrib(SM[2],"onlySingularAtZero",1);}
915      }
916      if(dim(JM[1])<=dim(SM[1])-2)
917      {
918         attrib(SM[2],"isRegInCodim2",1);
919      }
920   }
921   else
922   {
923     if(size(#)==0)
924     {
925        list JM=maxideal(1),maxideal(1);
926
927        attrib(JM[1],"isSB",1);
928        if(dim(SM[1])>=2){attrib(SM[2],"isRegInCodim2",1);}
929     }
930   }
931   if((attrib(SM[2],"isRegInCodim2")==1)&&(attrib(SM[2],"isCohenMacaulay")==1))
932   {
933      if(y>=1)
934      {
935            "// the ideal was CohenMacaulay and regular in codimension 2";
936      }
937      MB=SM[2];
938      intvec rw;
939      list LL=substpart(MB,ihp,0,rw);
940      def newR6=LL[1];
941      setring newR6;
942      ideal norid=endid;
943      ideal normap=endphi;
944      kill endid,endphi;
945      export norid;
946      export normap;
947      result=newR6;
948      result[size(result)+1]=delt;
949      setring BAS;
950      return(result);
951   }
952
953   //if it is an isolated singularity only at 0 things are easier
954   //JM ideal of singular locus, SM ideal of variety
955   if(attrib(SM[2],"onlySingularAtZero"))         
956   {
957      attrib(SM[2],"isIsolatedSingularity",1);
958      ideal SL=simplify(reduce(maxideal(1),SM[1]),2);
959      //vars not contained in ideal
960      ideal Ann=quotient(SM[2],SL[1]);
961      ideal qAnn=simplify(reduce(Ann,SM[1]),2);
962      //qAnn=0 ==> the first var(=SL[1]) not contained in SM is a nzd of R/SM
963      if(size(qAnn)==0)
964      {
965         if(y>=1)
966         {
967            "";
968            "//   the ideal rad(J):";
969            "";
970            maxideal(1);
971            newline;
972         }
973         //again test for normality
974         //Hom(I,R)=R
975         list RR;
976         RR=SM[1],SM[2],maxideal(1),SL[1];
977
978         RR=HomJJ(RR,y);
979         if(RR[2]==0)
980         {
981            def newR=RR[1];
982            setring newR;
983            map psi=BAS,endphi;
984            list tluser=normalizationPrimes(endid,psi(ihp),delt+RR[3],an);
985            setring BAS;
986            return(tluser);
987         }
988         MB=SM[2];
989         execute("ring newR7="+charstr(basering)+",("+varstr(basering)+"),("
990                      +ordstr(basering)+");");
991         ideal norid=fetch(BAS,MB);
992         ideal normap=fetch(BAS,ihp);
993         delt=delt+RR[3];
994         export norid;
995         export normap;
996         result=newR7;
997         result[size(result)+1]=delt;
998         setring BAS;
999         return(result);
1000
1001       }
1002      //Now the case where qAnn!=0, i.e.SL[1] is a zero divisor of R/SM
1003      //and we have found a splitting: id and id1
1004      //id=Ann defines components of R/SM in the complement of V(SL[1])
1005      //id1 defines components of R/SM in the complement of V(id)
1006       else
1007       {
1008          ideal id=Ann;
1009          attrib(id,"isCohenMacaulay",0);
1010          attrib(id,"isPrim",0);
1011          attrib(id,"isIsolatedSingularity",1);
1012          attrib(id,"isRegInCodim2",0);
1013          attrib(id,"isCompleteIntersection",0);
1014          attrib(id,"isEquidimensional",0);
1015          attrib(id,"onlySingularAtZero",1);
1016
1017          ideal id1=quotient(SM[2],Ann);
1018          //ideal id=SL[1],SM[2];
1019          attrib(id1,"isCohenMacaulay",0);
1020          attrib(id1,"isPrim",0);
1021          attrib(id1,"isIsolatedSingularity",1);
1022          attrib(id1,"isRegInCodim2",0);
1023          attrib(id1,"isCompleteIntersection",0);
1024          attrib(id1,"isEquidimensional",0);
1025          attrib(id1,"onlySingularAtZero",1);
1026         
1027          ideal t1=id,id1;
1028          int mul=vdim(std(t1));
1029          kill t1;
1030
1031          keepresult1=normalizationPrimes(id,ihp,0);
1032
1033          keepresult2=normalizationPrimes(id1,ihp,0);
1034           
1035          delt=delt+mul+keepresult1[size(keepresult1)]
1036                         +keepresult1[size(keepresult1)];
1037
1038          for(lauf=1;lauf<=size(keepresult2)-1;lauf++)
1039          {
1040             keepresult1=insert(keepresult1,keepresult2[lauf]);
1041          }
1042          keepresult1[size(keepresult1)]=delt;
1043          return(keepresult1);
1044       }
1045   }
1046
1047   //test for non-normality
1048   //Hom(I,I)<>R
1049   //we can use Hom(I,I) to continue
1050   ideal SL=simplify(reduce(JM[2],SM[1]),2);
1051   ideal Ann=quotient(SM[2],SL[1]);
1052   ideal qAnn=simplify(reduce(Ann,SM[1]),2);
1053
1054   if(size(qAnn)==0)
1055   {
1056      list RR;
1057      list RS;
1058      //now we have to compute the radical
1059      if(y>=1)
1060      {
1061         "// radical computation of singular locus";
1062      }
1063      J=radical(JM[2]);   //the singular locus
1064      JM=mstd(J);
1065     
1066      if((vdim(JM[1])==1)&&(size(reduce(J,std(maxideal(1))))==0))
1067      {
1068         attrib(SM[2],"onlySingularAtZero",1);
1069      }
1070      if(y>=1)
1071      {
1072        "//   radical is equal to:";"";
1073        J;
1074        "";
1075      }
1076      if(deg(SL[1])>deg(J[1]))
1077      {
1078         Ann=quotient(SM[2],J[1]);
1079         qAnn=simplify(reduce(Ann,SM[1]),2);
1080         if(size(qAnn)==0){SL[1]=J[1];}
1081      }
1082
1083      //evtl. fuer SL[1] anderen Nichtnullteiler aus J waehlen
1084      RR=SM[1],SM[2],JM[2],SL[1];
1085
1086      //   evtl eine geeignete Potenz von JM?
1087     if(y>=1)
1088     {
1089        "// compute Hom(rad(J),rad(J))";
1090     }
1091
1092     RS=HomJJ(RR,y);
1093
1094      if(RS[2]==1)
1095      {
1096         def lastR=RS[1];
1097         setring lastR;
1098         map psi1=BAS,endphi;
1099         ideal norid=endid;
1100         ideal normap=psi1(ihp);
1101         kill endid,endphi;
1102         export norid;
1103         export normap;
1104         result=lastR;
1105         result[size(result)+1]=delt+RS[3];
1106         setring BAS;
1107         return(result);
1108      }
1109      int n=nvars(basering);
1110      ideal MJ=JM[2];
1111
1112      def newR=RS[1];
1113      setring newR;
1114
1115      map psi=BAS,endphi;
1116      list tluser=
1117             normalizationPrimes(endid,psi(ihp),delt+RS[3],psi(MJ));
1118      setring BAS;
1119      return(tluser);
1120   }
1121    // A component with singular locus the whole component found
1122   if( Ann == 1)
1123   {
1124      "// Input appeared not to be a radical ideal!";
1125      "// A (everywhere singular) component with ideal";
1126      "// equal to its Jacobian ideal was found";
1127      "// Procedure will stop with partial result computed so far";"";
1128
1129         MB=SM[2];
1130         intvec rw;
1131         list LL=substpart(MB,ihp,0,rw);
1132         def newR6=LL[1];
1133         setring newR6;
1134         ideal norid=endid;
1135         ideal normap=endphi;
1136         kill endid,endphi;
1137         export norid;
1138         export normap;
1139         result=newR6;
1140         result[size(result)+1]=delt;
1141         setring BAS;
1142         return(result);
1143   }
1144   else
1145   {
1146      int equi=attrib(SM[2],"isEquidimensional");
1147      int oSAZ=attrib(SM[2],"onlySingularAtZero");
1148      int isIs=attrib(SM[2],"isIsolatedSingularity");
1149
1150      ideal new1=Ann;
1151      ideal new2=quotient(SM[2],Ann);
1152      //ideal new2=SL[1],SM[2];
1153
1154      int mul;
1155      if(equi&&isIs)
1156      {
1157          ideal t2=new1,new2;
1158          mul=vdim(std(t2));
1159      }
1160      execute("ring newR1="+charstr(basering)+",("+varstr(basering)+"),("
1161                      +ordstr(basering)+");");
1162      if(y>=1)
1163      {
1164         "// zero-divisor found";
1165      }
1166      ideal vid=fetch(BAS,new1);
1167      ideal ihp=fetch(BAS,ihp);
1168      attrib(vid,"isCohenMacaulay",0);
1169      attrib(vid,"isPrim",0);
1170      attrib(vid,"isIsolatedSingularity",isIs);
1171      attrib(vid,"isRegInCodim2",0);
1172      attrib(vid,"onlySingularAtZero",oSAZ);
1173      attrib(vid,"isEquidimensional",equi);     
1174      attrib(vid,"isCompleteIntersection",0);
1175
1176      keepresult1=normalizationPrimes(vid,ihp,0);
1177      int delta1=keepresult1[size(keepresult1)];
1178      setring BAS;
1179
1180      execute("ring newR2="+charstr(basering)+",("+varstr(basering)+"),("
1181                      +ordstr(basering)+");");
1182
1183      ideal vid=fetch(BAS,new2);
1184      ideal ihp=fetch(BAS,ihp);
1185      attrib(vid,"isCohenMacaulay",0);
1186      attrib(vid,"isPrim",0);
1187      attrib(vid,"isIsolatedSingularity",isIs);
1188      attrib(vid,"isRegInCodim2",0);
1189      attrib(vid,"isEquidimensional",equi);     
1190      attrib(vid,"isCompleteIntersection",0);
1191      attrib(vid,"onlySingularAtZero",oSAZ);
1192
1193      keepresult2=normalizationPrimes(vid,ihp,0);
1194      int delta2=keepresult2[size(keepresult2)];
1195
1196      setring BAS;
1197     
1198      for(lauf=1;lauf<=size(keepresult2)-1;lauf++)
1199      {
1200         keepresult1=insert(keepresult1,keepresult2[lauf]);
1201      }
1202      keepresult1[size(keepresult1)]=delt+mul+delta1+delta2;
1203      return(keepresult1);
1204   }
1205}
1206example
1207{ "EXAMPLE:";echo = 2;
1208   // Huneke
1209   ring qr=31991,(a,b,c,d,e),dp;
1210   ideal i=
1211   5abcde-a5-b5-c5-d5-e5,
1212   ab3c+bc3d+a3be+cd3e+ade3,
1213   a2bc2+b2cd2+a2d2e+ab2e2+c2de2,
1214   abc5-b4c2d-2a2b2cde+ac3d2e-a4de2+bcd2e3+abe5,
1215   ab2c4-b5cd-a2b3de+2abc2d2e+ad4e2-a2bce3-cde5,
1216   a3b2cd-bc2d4+ab2c3e-b5de-d6e+3abcd2e2-a2be4-de6,
1217   a4b2c-abc2d3-ab5e-b3c2de-ad5e+2a2bcde2+cd2e4,
1218   b6c+bc6+a2b4e-3ab2c2de+c4d2e-a3cde2-abd3e2+bce5;
1219
1220   list pr=normalizationPrimes(i);
1221   def r1=pr[1];
1222   setring r1;
1223   norid;
1224   normap;
1225}
1226///////////////////////////////////////////////////////////////////////////////
1227proc substpart(ideal endid, ideal endphi, int homo, intvec rw)
1228
1229"//Repeated application of elimpart to endid, until no variables can be
1230//directy substituded. homo=1 if input is homogeneous, rw contains
1231//original weights, endphi (partial) normalization map";
1232
1233{
1234   def newRing=basering;
1235   int ii,jj;
1236   map phi = basering,maxideal(1);
1237
1238   list Le = elimpart(endid);
1239                                     //this proc and the next loop try to
1240   int q = size(Le[2]);              //substitute as many variables as possible
1241   intvec rw1 = 0;                   //indices of substituted variables
1242   rw1[nvars(basering)] = 0;
1243   rw1 = rw1+1;
1244
1245   while( size(Le[2]) != 0 )
1246   {
1247      endid = Le[1];
1248      map ps = newRing,Le[5];
1249
1250      phi = ps(phi);
1251      for(ii=1;ii<=size(Le[2])-1;ii++)
1252      {
1253         phi=phi(phi);
1254      }
1255      //eingefuegt wegen x2-y2z2+z3
1256      kill ps;
1257
1258      for( ii=1; ii<=size(rw1); ii++ )
1259      {
1260         if( Le[4][ii]==0 )
1261         {
1262            rw1[ii]=0;                             //look for substituted vars
1263         }
1264      }
1265      Le=elimpart(endid);
1266      q = q + size(Le[2]);
1267   }
1268   endphi = phi(endphi);
1269
1270//---------- return -----------------------------------------------------------
1271// in the homogeneous case put weights for the remaining vars correctly, i.e.
1272// delete from rw those weights for which the corresponding entry of rw1 is 0
1273
1274   if (homo==1 && nvars(newRing)-q >1 && size(endid) >0 )
1275   {
1276      jj=1;
1277      for( ii=2; ii<size(rw1); ii++)
1278      {
1279         jj++;
1280         if( rw1[ii]==0 )
1281         {
1282            rw=rw[1..jj-1],rw[jj+1..size(rw)];
1283            jj=jj-1;
1284         }
1285      }
1286      if( rw1[1]==0 ) { rw=rw[2..size(rw)]; }
1287      if( rw1[size(rw1)]==0 ){ rw=rw[1..size(rw)-1]; }
1288
1289      ring lastRing = char(basering),(T(1..nvars(newRing)-q)),(a(rw),dp);
1290   }
1291   else
1292   {
1293      ring lastRing = char(basering),(T(1..nvars(newRing)-q)),dp;
1294   }
1295
1296   ideal lastmap;
1297   q = 1;
1298   for(ii=1; ii<=size(rw1); ii++ )
1299   {
1300      if ( rw1[ii]==1 ) { lastmap[ii] = T(q); q=q+1; }
1301      if ( rw1[ii]==0 ) { lastmap[ii] = 0; }
1302   }
1303   map phi1 = newRing,lastmap;
1304   ideal endid  = phi1(endid);
1305   ideal endphi = phi1(endphi);
1306   export(endid);
1307   export(endphi);
1308   list L = lastRing;
1309   setring newRing;
1310   return(L);
1311}
1312/////////////////////////////////////////////////////////////////////////////
1313
1314proc genus(ideal I,list #)
1315"USAGE:   genus(I) or genus(i,1); I a 1-dimensional ideal
1316RETURN:  an integer, the geometric genus p_g = p_a - delta of the projective
1317         curve defined by I, where p_a is the arithmetic genus.
1318NOTE:    delta is the sum of all local delta-invariants of the singularities,
1319         i.e. dim(R'/R), R' the normalization of the local ring R of the
1320         singularity.
1321         genus(i,1) uses the normalization to compute delta. Usually this
1322         is slow but sometimes not.
1323EXAMPLE: example genus; shows an example
1324"
1325{
1326   int w = printlevel-voice+2;  // w=printlevel (default: w=0)
1327
1328   def R=basering;
1329
1330   if(homog(I))
1331   {
1332      execute("ring newR=("+charstr(R)+"),("+varstr(R)+"),dp;");
1333      ideal I=imap(R,I); 
1334   }
1335   else
1336   {
1337      execute("ring newR=("+charstr(R)+"),("+varstr(R)+",@t),dp;");
1338      ideal I=imap(R,I); 
1339      I=homog(std(I),@t);
1340   }
1341   ideal J=std(I);
1342   if((dim(J)!=2)||((nvars(basering)==2)&&(dim(J)<1)))
1343   {
1344      ERROR("This is not a curve");
1345   }
1346   if((nvars(basering)<=3)&&(size(J)>1))
1347   {
1348       ERROR("This is not equidimensional");
1349   }
1350   
1351   intvec hp=hilbPoly(J);
1352   int p_a=1-hp[1];
1353   int d=hp[2];
1354
1355   if(w>=1)
1356   {
1357      "";"The ideal of the projective curve:";"";J;"";
1358      "The coefficients of the Hilbert polynomial";hp;
1359      "arithmetic genus:";p_a;
1360      "degree:";d;"";
1361   }
1362   
1363   intvec v = hilb(J,1);
1364   int o,i;
1365   
1366   if(nvars(basering)>3)
1367   {
1368      map phi=newR,maxideal(1);
1369      int de;
1370      ideal K,L;
1371      poly m=var(4);
1372      for(i=5;i<=nvars(basering);i++){m=m*var(i);}
1373      K=eliminate(J,m,v);
1374      if(size(K)==1){de=deg(K[1]);}
1375      m=var(1);
1376      for(i=2;i<=nvars(basering)-3;i++){m=m*var(i);}
1377      i=0;
1378      while(d!=de)
1379      {
1380         o=1;
1381         i++;
1382         K=phi(J);
1383         K=eliminate(K,m,v);
1384         if(size(K)==1){de=deg(K[1]);}
1385         if((i==5)&&(d!=de))   
1386         {
1387            K=reduce(equidimMax(J),J);
1388            if(size(K)!=0){ERROR("This is not equidimensional");}
1389          }
1390          if(i==10){ERROR("did not find a good projection");}
1391          L=sparsetriag(nvars(newR),nvars(newR),80-5*i,i)*transpose(maxideal(1));
1392          phi=newR,L;
1393      }
1394      J=K;
1395   }
1396   poly p=J[1];
1397   
1398   if(nvars(basering)==2)
1399   {
1400      if(p==0) { return(0); }
1401      if(deg(squarefree(p))<deg(p)){ERROR("Curve is not reduced");}
1402      return(-deg(p)+1);
1403   }
1404   
1405   execute("ring S=("+charstr(R)+"),(x,y,t),dp;");
1406   ideal L=maxideal(1);
1407   execute("ring C=("+charstr(R)+"),(x,y),ds;");
1408   ideal I;
1409   execute("ring A=("+charstr(R)+"),(x,t),dp;");
1410   map phi=S,1,x,t;
1411   map psi=S,x,1,t;
1412   poly g,h;
1413   ideal I,I1;
1414   execute("ring B=("+charstr(R)+"),(x,t),ds;");
1415   
1416   setring S;
1417   if(o)
1418   {
1419     for(i=1;i<=nvars(newR)-3;i++){L[i]=0;}
1420     L=L,maxideal(1);
1421   }   
1422   map sigma=newR,L;
1423   poly F=sigma(p);
1424   if(w>=1){"the projected curve:";"";F;"";}
1425   
1426   kill newR;
1427   
1428   int genus=(d-1)*(d-2)/2;
1429   if(w>=1){"the arithmetic genus of the plane curve:";genus;pause();}
1430 
1431   int delt,deltaloc,deltainf,tau,tauinf,cusps,iloc,iglob,l,nsing,
1432       tauloc,tausing,k,rat,nbranchinf,nbranch,nodes,cuspsinf,nodesinf;
1433   list inv;
1434
1435   if(w>=1)
1436     {"";"analyse the singularities at oo";"";"singular locus at (1,x,0):";"";}
1437   setring A;       
1438   g=phi(F);
1439   h=psi(F);
1440   I=g,jacob(g),var(2);
1441   I=std(I);
1442   if(deg(I[1])>0)
1443   {
1444      list qr=minAssGTZ(I);
1445      if(w>=1){qr;"";}
1446     
1447      for(k=1;k<=size(qr);k++)
1448      {
1449         if(w>=1){ nsing=nsing+vdim(std(qr[k]));}
1450         inv=deltaLoc(g,qr[k]);
1451         deltainf=deltainf+inv[1];
1452         tauinf=tauinf+inv[2];
1453         l=vdim(std(qr[k]));
1454         if(inv[2]==l){nodesinf=nodesinf+l;}
1455         if(inv[2]==2*l){cuspsinf=cuspsinf+l;}         
1456         nbranchinf=nbranchinf+inv[3];
1457      }
1458   }
1459   else
1460   {
1461     if(w>=1){"            the curve is smooth at (1,x,0)";"";}
1462   }
1463   if(w>=1){"singular locus at (0,1,0):";"";}
1464   inv=deltaLoc(h,maxideal(1));
1465   if((w>=1)&&(inv[2]!=0)){ nsing++;}
1466   deltainf=deltainf+inv[1];
1467   tauinf=tauinf+inv[2];
1468   if(inv[2]==1){nodesinf++;}
1469   if(inv[2]==2){cuspsinf++;}         
1470   
1471   if((w>=1)&&(inv[2]==0)){"            the curve is smooth at (0,1,0)";"";}
1472   if(inv[2]>0){nbranchinf=nbranchinf+inv[3];}
1473 
1474   if(w>=1)
1475   {
1476      if(tauinf==0)
1477      {
1478        "            the curve is smooth at oo";"";
1479      }
1480      else
1481      {
1482         "number of singularities at oo:";nsing;
1483         "nodes at oo:";nodesinf;
1484         "cusps at oo:";cuspsinf;
1485         "branches at oo:";nbranchinf;
1486         "Tjurina number at oo:";tauinf;
1487         "delta at oo:";deltainf;
1488         "Milnor number at oo:";2*deltainf-nbranchinf+nsing;
1489         pause();
1490      }
1491      "singularities at (x,y,1):";"";
1492   }
1493   execute("ring newR=("+charstr(R)+"),(x,y),dp;");
1494   //the singularities at the affine part
1495   map sigma=S,var(1),var(2),1;
1496   ideal I=sigma(F);
1497
1498   if(size(#)!=0)     
1499   {                              //uses the normalization to compute delta
1500      list nor=normal(I,"wd");
1501      delt=nor[size(nor)];
1502      genus=genus-delt-deltainf;
1503      setring R;
1504      return(genus);
1505   }
1506
1507   ideal I1=jacob(I);
1508   matrix Hess[2][2]=jacob(I1);
1509   ideal ID=I+I1+ideal(det(Hess));//singular locus of I+I1
1510   
1511   ideal radID=std(radical(ID));//the non-nodal locus
1512   if(w>=1){"the non-nodal locus:";"";radID;pause();"";}
1513   if(deg(radID[1])==0)
1514   {
1515     ideal IDsing=1;
1516   }
1517   else
1518   {
1519     ideal IDsing=minor(jacob(ID),2)+radID;//singular locus of ID
1520   }
1521   
1522   iglob=vdim(std(IDsing));
1523
1524   if(iglob!=0)//computation of the radical of IDsing
1525   {
1526      ideal radIDsing=reduce(IDsing,radID);
1527      if(size(radIDsing)==0)
1528      {
1529         radIDsing=radID;
1530         attrib(radIDsing,"isSB",1);
1531      }
1532      else
1533      {
1534         radIDsing=std(radical(IDsing));
1535      }
1536      iglob=vdim(radIDsing);
1537      if((w>=1)&&(iglob))
1538          {"the non-nodal-cuspidal locus:";radIDsing;pause();"";}
1539   }
1540   cusps=vdim(radID)-iglob;
1541   nsing=nsing+cusps;
1542   
1543   if(iglob==0)
1544   {
1545      if(w>=1){"             there are only cusps and nodes";"";}
1546      tau=vdim(std(I+jacob(I)));
1547      tauinf=tauinf+tau;
1548      nodes=tau-2*cusps;
1549      delt=nodes+cusps;
1550      nbranch=2*tau-3*cusps;
1551      nsing=nsing+nodes;
1552   }
1553   else
1554   {
1555       if(w>=1){"the non-nodal-cuspidal singularities";"";}
1556       setring C;                     
1557       ideal I1=imap(newR,IDsing);
1558       iloc=vdim(std(I1));
1559       if(iglob==iloc)
1560       {
1561          if(w>=1){"only cusps and nodes outside (0,0,1)";}
1562          setring newR;
1563          tau=vdim(std(I+jacob(I)));
1564          tauinf=tauinf+tau;
1565          inv=deltaLoc(I[1],maxideal(1));
1566          delt=inv[1];
1567          tauloc=inv[2];
1568          nodes=tau-tauloc-2*cusps;
1569          nsing=nsing+nodes;
1570          nbranch=inv[3]+ 2*nodes+cusps;         
1571          delt=delt+nodes+cusps;
1572          if((w>=1)&&(inv[2]==0)){"smooth at (0,0,1)";}
1573        }
1574        else
1575        {
1576           setring newR;
1577           list pr=minAssGTZ(IDsing);
1578           if(w>=1){pr;}
1579           
1580           for(k=1;k<=size(pr);k++)
1581           {
1582              if(w>=1){nsing=nsing+vdim(std(pr[k]));}
1583              inv=deltaLoc(I[1],pr[k]);
1584              delt=delt+inv[1];
1585              tausing=tausing+inv[2];
1586              nbranch=nbranch+inv[3];
1587           }
1588           tau=vdim(std(I+jacob(I)));
1589           tauinf=tauinf+tau;
1590           nodes=tau-tausing-2*cusps;
1591           nsing=nsing+nodes;
1592           delt=delt+nodes+cusps; 
1593           nbranch=nbranch+2*nodes+cusps;           
1594        }
1595   }
1596   genus=genus-delt-deltainf;
1597   if(w>=1)
1598   {
1599      "The projected plane curve has locally:";"";
1600      "singularities:";nsing;
1601      "branches:";nbranch+nbranchinf;
1602      "nodes:"; nodes+nodesinf;
1603      "cusps:";cusps+cuspsinf;
1604      "Tjurina number:";tauinf;
1605      "Milnor number:";2*(delt+deltainf)-nbranch-nbranchinf+nsing;
1606      "delta of the projected curve:";delt+deltainf;
1607      "delta of the curve:";p_a-genus;
1608      "genus:";genus;
1609      "====================================================";
1610      "";
1611   }
1612   setring R;
1613   return(genus);
1614}
1615example
1616{ "EXAMPLE:"; echo = 2;
1617   ring r=0,(x,y),dp;
1618   ideal i=y^9 - x^2*(x - 1)^9;
1619   genus(i);
1620}
1621
1622///////////////////////////////////////////////////////////////////////////////
1623proc deltaLoc(poly f,ideal singL)
1624"USAGE:  deltaLoc(f,J);  f poly, J ideal
1625ASSUME: f is reduced bivariate polynomial; basering has exactly two variables;
1626        J is irreducible prime component of the singular locus of f (e.g., one
1627        entry of the output of @code{minAssGTZ(I);}, I = <f,jacob(f)>).
1628RETURN:  list L:
1629@texinfo
1630@table @asis
1631@item @code{L[1]}; int:
1632         the sum of (local) delta invariants of f at the (conjugated) singular
1633         points given by J.
1634@item @code{L[2]}; int:
1635         the sum of (local) Tjurina numbers of f at the (conjugated) singular
1636         points given by J.
1637@item @code{L[3]}; int:
1638         the sum of (local) number of branches of f at the (conjugated)
1639         singular points given by J.
1640@end table
1641@end texinfo
1642NOTE:    procedure makes use of @code{execute}; increasing printlevel displays
1643         more comments (default: printlevel=0).
1644SEE ALSO: delta, tjurina
1645KEYWORDS: delta invariant; Tjurina number
1646EXAMPLE: example deltaLoc;  shows an example
1647"
1648{
1649   option(redSB);
1650   def R=basering;
1651   execute("ring S=("+charstr(R)+"),(x,y),lp;");
1652   map phi=R,x,y;
1653   ideal singL=phi(singL);
1654   singL=simplify(std(singL),1);
1655   attrib(singL,"isSB",1);
1656   int d=vdim(singL);
1657   poly f=phi(f);
1658   int i;
1659   int w = printlevel-voice+2;  // w=printlevel (default: w=0)
1660   if(d==1)
1661   {
1662      map alpha=S,var(1)-singL[2][2],var(2)-singL[1][2];
1663      f=alpha(f);
1664      execute("ring C=("+charstr(S)+"),("+varstr(S)+"),ds;");
1665      poly f=imap(S,f);
1666      ideal singL=imap(S,singL);
1667      if((w>=1)&&(ord(f)>=2))
1668      {
1669        "local analysis of the singularities";"";
1670        basering;
1671        singL;
1672        f;
1673        pause();
1674      }
1675   }
1676   else
1677   {
1678      poly p;
1679      poly c;
1680      map psi;
1681      number co;
1682     
1683      while((deg(lead(singL[1]))>1)&&(deg(lead(singL[2]))>1))
1684      {
1685         psi=S,x,y+random(-100,100)*x;
1686         singL=psi(singL);
1687         singL=std(singL);
1688          f=psi(f);
1689      }
1690     
1691      if(deg(lead(singL[2]))==1)
1692      {
1693         p=singL[1];
1694         c=singL[2]-lead(singL[2]);
1695         co=leadcoef(singL[2]);
1696      }
1697      if(deg(lead(singL[1]))==1)
1698      {
1699         psi=S,y,x;
1700         f=psi(f);
1701         singL=psi(singL);
1702         p=singL[2];
1703         c=singL[1]-lead(singL[1]);
1704         co=leadcoef(singL[1]);
1705      }
1706     
1707      execute("ring B=("+charstr(S)+"),a,dp;");
1708      map beta=S,a,a;
1709      poly p=beta(p);
1710     
1711      execute("ring C=("+charstr(S)+",a),("+varstr(S)+"),ds;");
1712      number p=number(imap(B,p));
1713     
1714      minpoly=p;
1715      map iota=S,a,a;
1716      number c=number(iota(c));
1717      number co=iota(co);
1718     
1719      map alpha=S,x-c/co,y+a;
1720      poly f=alpha(f);
1721      f=cleardenom(f);
1722      if((w>=1)&&(ord(f)>=2))
1723      {
1724        "local analysis of the singularities";"";
1725        basering;
1726        alpha;
1727        f;
1728        pause();
1729        "";
1730      }
1731   }
1732   option(noredSB);
1733   ideal fstd=std(ideal(f)+jacob(f));
1734   poly hc=highcorner(fstd);
1735   int tau=vdim(fstd);     
1736   int o=ord(f);
1737   int delt,nb;
1738   
1739   if(tau==0)                 //smooth case
1740   {
1741      setring R;
1742      return(list(0,0,1));
1743   }
1744   if((char(basering)>=181)||(char(basering)==0))
1745   {
1746      if(o==2)                //A_k-singularity
1747      {
1748        if(w>=1){"A_k-singularity";"";}       
1749         setring R;
1750         delt=(tau+1)/2;
1751         return(list(d*delt,d*tau,d*(2*delt-tau+1)));   
1752      }
1753      if((lead(f)==var(1)*var(2)^2)||(lead(f)==var(1)^2*var(2)))
1754      {
1755        if(w>=1){"D_k- singularity";"";}
1756       
1757         setring R;
1758         delt=(tau+2)/2;
1759         return(list(d*delt,d*tau,d*(2*delt-tau+1)));
1760      }
1761
1762      int mu=vdim(std(jacob(f)));
1763      poly g=f+var(1)^mu+var(2)^mu;  //to obtain a convenient Newton-polygon
1764 
1765      list NP=newtonpoly(g);
1766      if(w>=1){"Newton-Polygon:";NP;"";}
1767      int s=size(NP);
1768       
1769      if(is_NND(f,mu,NP))     
1770      { // the Newton-polygon is non-degenerate                           
1771        // compute nb, the number of branches
1772        for(i=1;i<=s-1;i++)
1773        {
1774          nb=nb+gcd(NP[i][2]-NP[i+1][2],NP[i][1]-NP[i+1][1]);
1775        }
1776        if(w>=1){"Newton-Polygon is non-degenerated";"";}
1777        return(list(d*(mu+nb-1)/2,d*tau,d*nb));
1778      }
1779
1780      if(w>=1){"Newton-Polygon is degenerated";"";}
1781
1782      // the following can certainly be made more efficient when replacing
1783      // 'reddevelop' (used only for computing number of branches) by
1784      // successive blowing-up + test if Newton polygon degenerate:
1785      if(s>2)    //  splitting of f
1786      {
1787         if(w>=1){"Newton polygon can be used for splitting";"";}
1788         intvec v=NP[1][2]-NP[2][2],NP[2][1];
1789         int de=w_deg(g,v);
1790         int st=w_deg(hc,v)+v[1]+v[2];
1791         poly f1=var(2)^NP[2][2];
1792         poly f2=jet(g,de,v)/var(2)^NP[2][2];
1793         poly h=g-f1*f2;
1794         de=w_deg(h,v);
1795         poly k;
1796         ideal wi=var(2)^NP[2][2],f2;
1797         matrix li;
1798         while(de<st)
1799         {
1800           k=jet(h,de,v);
1801           li=lift(wi,k);
1802           f1=f1+li[2,1];
1803           f2=f2+li[1,1];
1804           h=g-f1*f2;
1805           de=w_deg(h,v);
1806         }
1807         nb=deltaLoc(f1,maxideal(1))[3]+deltaLoc(f2,maxideal(1))[3];
1808         return(list(d*(mu+nb-1)/2,d*tau,d*nb));
1809      }
1810
1811      f=jet(f,deg(hc)+2);
1812      if(w>=1){"now we have to use Hamburger-Noether (Puiseux) expansion";}
1813      list hne=reddevelop(f);
1814      nb=size(hne);
1815      setring R;
1816      kill HNEring;       
1817      return(list(d*(mu+nb-1)/2,d*tau,d*nb));
1818   }
1819   else             //the case of small characteristic
1820   {
1821      f=jet(f,deg(hc)+2);
1822      if(w>=1){"now we have to use Hamburger-Noether (Puiseux) expansion";}
1823      delt=delta(f);
1824      return(list(d*delt,d*tau,d));
1825   }
1826}
1827example
1828{ "EXAMPLE:"; echo = 2;
1829  ring r=0,(x,y),dp;
1830  poly f=(x2+y^2-1)^3 +27x2y2;
1831  ideal I=f,jacob(f);
1832  I=std(I);
1833  list qr=minAssGTZ(I);
1834  size(qr);
1835  // each component of the singular locus either describes a cusp or a pair
1836  // of conjugated nodes:
1837  deltaLoc(f,qr[1]);
1838  deltaLoc(f,qr[2]);
1839  deltaLoc(f,qr[3]);
1840  deltaLoc(f,qr[4]);
1841  deltaLoc(f,qr[5]);
1842  deltaLoc(f,qr[6]);
1843}
1844///////////////////////////////////////////////////////////////////////////////
1845// compute the weighted degree of p
1846static proc w_deg(poly p, intvec v)
1847{
1848   if(p==0){return(-1);}
1849   int d=0;
1850   while(jet(p,d,v)==0){d++;}
1851   d=(transpose(leadexp(jet(p,d,v)))*v)[1];
1852   return(d); 
1853}
1854
1855//proc hilbPoly(ideal J)
1856//{ 
1857//   poly hp;
1858//   int i;
1859//   if(!attrib(J,"isSB")){J=std(J);}
1860//   intvec v = hilb(J,2);
1861//   for(i=1; i<=size(v); i++){ hp=hp+v[i]*(var(1)-i+2);}
1862//   return(hp);
1863//}
1864
1865
1866//////////////////////////////////////////////////////////////////////////////
1867
1868proc primeClosure (list L, list #)
1869"USAGE:    primeClosure(L [,c]); L a list of a ring containing a prime ideal
1870                                 ker, c an optional integer
1871RETURN:   a list L consisting of rings L[1],...,L[n] such that
1872          - L[1] is a copy of (not a reference to!) the input ring L[1]
1873          - all rings L[i] contain ideals ker, L[2],...,L[n] contain ideals phi
1874            such that
1875                    L[1]/ker --> ... --> L[n]/ker
1876            are injections given by the corresponding ideals phi, and L[n]/ker
1877            is the integral closure of L[1]/ker in its quotient field.
1878          - all rings L[i] contain a polynomial nzd such that elements of
1879            L[i]/ker are quotients of elements of L[i-1]/ker with denominator
1880            nzd via the injection phi.
1881NOTE:     - L is constructed by recursive calls of primeClosure itself.
1882          - c determines the choice of nzd:
1883               - c not given or equal to 0: first generator of the ideal SL,
1884                 the singular locus of Spec(L[i]/ker)
1885               - c<>0: the generator of SL with least number of monomials.
1886EXAMPLE:  example primeClosure; shows an example
1887"
1888{
1889// Start with a consistency check:
1890
1891  if (!(typeof(L[1])=="ring"))
1892    {
1893      "// Parameter must be a ring or a list containing a ring!";
1894      return(-1);
1895    }
1896
1897  int dblvl=printlevel-voice+2;
1898
1899
1900// Some auxiliary variables:
1901
1902  int n=size(L);
1903
1904// How to choose the non-zerodivisor later on?
1905
1906  int nzdoption=0;
1907  if (size(#)>0)
1908    {
1909      nzdoption=#[1];
1910    }
1911
1912// R0 is the ring to work with, if we are in step one, make a copy of the
1913// input ring, so that all objects are created in the copy, not in the original
1914// ring (therefore a copy, not a reference is defined).
1915
1916  if (n==1)
1917    {
1918      def R=L[1];
1919      def BAS=basering;
1920      setring R;
1921      if (!(typeof(ker)=="ideal"))
1922        {
1923          "// No ideal ker in the input ring!";
1924          return (-1);
1925        }
1926      ker=simplify(interred(ker),15);
1927      execute ("ring R0="+charstr(R)+",("+varstr(R)+"),("+ordstr(R)+");");
1928      ideal ker=fetch(R,ker);
1929       
1930      // check whether we compute the normalization of the blow up of
1931      // an isolated singularity at the origin (checked in normalI)
1932
1933      if (typeof(attrib(L[1],"iso_sing_Rees"))=="int")
1934      {
1935        attrib(R0,"iso_sing_Rees",attrib(L[1],"iso_sing_Rees"));
1936      }
1937      L=R0;
1938    }
1939  else
1940    {
1941      def R0=L[n];
1942      setring R0;
1943    }
1944
1945
1946// In order to apply HomJJ from normal.lib, we need the radical of the singular
1947// locus of ker, J:=rad(ker):
1948
1949//  if (homog(ker)==1)
1950//    {
1951      list SM=mstd(ker);
1952//    }
1953/*  else
1954    {
1955      list SM=groebner(ker),ker;
1956    }*/
1957
1958// In the first iteration, we have to compute the singular locus "from
1959// scratch". In further iterations, we can fetch it from the previous one but
1960// have to compute its radical.
1961
1962  if (n==1)
1963    {
1964      if (typeof(attrib(R0,"iso_sing_Rees"))=="int")
1965      {
1966        ideal J;
1967        for (int s=1;s<=attrib(R0,"iso_sing_Rees");s++)
1968        {
1969          J=J,var(s);
1970        }
1971      }
1972      else
1973      {
1974        ideal J=minor(jacob(SM[2]),nvars(basering)-dim(SM[1]));
1975      }
1976      J=J+SM[2];
1977      if (homog(J)==1)
1978        {
1979          J=mstd(J)[2];                 
1980        }
1981      J=radical(interred(J));                   
1982    }
1983  else
1984    {
1985      J=radical(interred(J));   
1986    }
1987
1988  // having computed the radical J of the ideal of the singular locus,
1989  // we now need to pick an element nzd of J
1990
1991  poly nzd=J[1];
1992  if (nzdoption)
1993  {
1994    for (int ii=2;ii<=ncols(J);ii++)
1995    {
1996      if ( (deg(nzd)>=deg(J[ii])) && (size(nzd)>size(J[ii])) )
1997      {
1998        nzd=J[ii];
1999      }
2000    }
2001  }
2002
2003  export nzd;
2004  list RR=SM[1],SM[2],J,nzd;
2005  list RS=HomJJ(RR); 
2006
2007
2008//////////////////////////////////////////////////////////////////////////////
2009
2010
2011// If we've reached the integral closure (as determined by the result of
2012// HomJJ), then we are done, otherwise we have to prepare the next iteration.
2013
2014  if (RS[2]==1)               // we've reached the integral closure
2015    {
2016      kill(J);
2017      return(L);
2018    }
2019  else                        // prepare the next iteration
2020    {
2021      if (n==1)               // In the first iteration: keep only the data
2022        {                     // needed later on.
2023          kill (RR,SM);
2024
2025          export(ker);
2026        }
2027
2028      def R1=RS[1];           // The data of the next ring R1:
2029      setring R1;             // keep only what is necessary and kill
2030      ideal ker=endid;        // everything else.
2031      export(ker);
2032      ideal norid=endid;
2033      export(norid);
2034      kill(endid);
2035
2036      map phi=R0,endphi;      // fetch the singular locus
2037      ideal J=mstd(simplify(phi(J)+ker,4))[2]; 
2038      export(J);
2039      if(n>1)
2040      {
2041         ideal normap=phi(normap);
2042      }
2043      else
2044      {
2045         ideal normap=endphi;
2046      }
2047      export(normap);
2048      kill(phi);              // we save phi as ideal, not as map, so that
2049      ideal phi=endphi;       // we have more flexibility in the ring names
2050      kill(endphi);           // later on.
2051      export(phi);
2052      L=insert(L,R1,n);       // Add the new ring R1 and go on with the
2053      if (size(#)>0)
2054        {
2055          return (primeClosure(L,#));
2056        }
2057      else
2058        {
2059          return(primeClosure(L));         // next iteration.
2060        }
2061    }
2062}
2063example
2064{
2065  "EXAMPLE:"; echo=2;
2066  ring R=0,(x,y),dp;
2067  ideal I=x4,y4;
2068  def K=ReesAlgebra(I)[1];        // K contains ker such that K/ker=R[It]
2069  list L=primeClosure(K);
2070  def R(1)=L[1];                  // L[4] contains ker, L[4]/ker is the
2071  def R(4)=L[4];                  // integral closure of L[1]/ker
2072  setring R(1);
2073  R(1);
2074  ker;
2075  setring R(4);
2076  R(4);
2077  ker;
2078}
2079
2080
2081//////////////////////////////////////////////////////////////////////////////
2082//////////////////////////////////////////////////////////////////////////////
2083
2084proc closureRingtower(list L)
2085"USAGE:    closureRingtower(list L); L a list of rings
2086CREATE:   rings R(1),...,R(n) such that R(i)=L[i] for all i
2087EXAMPLE:  example closureRingtower; shows an example
2088"
2089{
2090  int n=size(L);
2091
2092  for (int i=1;i<=n;i++)
2093    {
2094      def R(i)=L[i];
2095      keepring (R(i));
2096    }
2097
2098  return();
2099}
2100example
2101{
2102  "EXAMPLE:"; echo=2;
2103  ring R=0,(x,y),dp;
2104  ideal I=x4,y4;
2105  list L=primeClosure(ReesAlgebra(I)[1]);
2106  closureRingtower(L);
2107  R(1);
2108  R(4);
2109}
2110
2111//////////////////////////////////////////////////////////////////////////////
2112//////////////////////////////////////////////////////////////////////////////
2113
2114proc closureFrac(list L);
2115"USAGE:    closureFrac (L); L a list as in the result of primeClosure, L[n]
2116                           containing an additional poly f
2117CREATE:   a list fraction of two elements of L[1], such that
2118          f=fraction[1]/fraction[2] via the injections phi L[i]-->L[i+1].
2119EXAMPLE:  example closureFrac; shows an example
2120"
2121{
2122// Define some auxiliary variables:
2123
2124  int n=size(L);
2125  int j,k,l;
2126  string mapstr;
2127
2128  closureRingtower(L);         // The rings of L get names R[1],...,R[n]
2129
2130// The quotient representing f is computed as in 'closureGenerators' with
2131// the differences that
2132//   - the loop is done twice: for the numerator and for the denominator;
2133//   - the result is stored in the list fraction and
2134//   - we have to make sure that no more objects of the rings R(i) survive.
2135
2136  for (j=1;j<=2;j++)
2137    {
2138      setring R(n);
2139      if (j==1)
2140        {
2141          poly p=f;
2142        }
2143      else
2144        {
2145          p=1;
2146        }
2147
2148      for (k=n;k>1;k--)
2149        {
2150
2151          if (j==1)
2152            {
2153              map phimap=R(k-1),phi;
2154            }
2155
2156          p=p*phimap(nzd);
2157
2158          if (j==2)
2159            {
2160              kill(phimap);
2161            }
2162
2163          if (j==1)
2164            {
2165              execute ("ring S(k) = "+charstr(R(k))+",("+varstr(R(k))+",
2166                       Z(1.."+string(ncols(phi))+")),(dp("+string(nvars(R(k)))
2167                       +"),dp("+string(ncols(phi))+"));");
2168              ideal phi = imap(R(k),phi);
2169              ideal J= imap (R(k),ker);
2170              for (l=1;l<=ncols(phi);l++)
2171                {
2172                  J=J+(Z(l)-phi[l]);
2173                }
2174              J=groebner(J);
2175              poly h=NF(imap(R(k),p),J);
2176            }
2177          else
2178            {
2179              setring S(k);
2180              h=NF(imap(R(k),p),J);
2181              setring R(k);
2182              kill(p);
2183            }
2184
2185          setring R(k-1);
2186
2187          if (j==1)
2188            {
2189              mapstr=" map backmap = S(k),";
2190              for (l=1;l<=nvars(R(k));l++)
2191                {
2192                  mapstr=mapstr+"0,";
2193                }
2194              execute (mapstr+"maxideal(1);");
2195
2196              poly p;
2197            }
2198          p=NF(backmap(h),std(ker));
2199          if (j==2)
2200            {
2201              kill(backmap);
2202            }
2203        }
2204
2205      if (j==1)
2206        {
2207          if (defined(fraction))
2208            {
2209              kill(fraction);
2210              list fraction=p;
2211            }
2212          else
2213            {
2214              list fraction=p;
2215            }
2216        }
2217      else
2218        {
2219          fraction=insert(fraction,p,1);
2220        }
2221    }
2222  export(fraction);
2223  return ();
2224}
2225example
2226{
2227  "EXAMPLE:"; echo=2;
2228  ring R=0,(x,y),dp;
2229  ideal ker=x2+y2;
2230  export R;
2231  list L=primeClosure(R);          // We normalize R/ker
2232  closureRingtower(L);             // Now R/ker=R(1) with normalization R(2)
2233  setring R(2);
2234  kill(R);
2235  phi;                             // The map R(1)-->R(2)
2236  poly f=T(1)*T(2);                // We will get a representation of f
2237  export R(2);
2238  closureFrac(L);
2239  setring R(1);
2240  kill (R(2));
2241  fraction;                        // f=fraction[1]/fraction[2] via phi
2242}
2243
2244//////////////////////////////////////////////////////////////////////////////
2245//////////////////////////////////////////////////////////////////////////////
2246
2247static
2248proc closureGenerators(list L);    // called inside normalI
2249{
2250  // In the list L of rings R(1),...,R(n), compute representations of the ring
2251  // ring variables of the last ring R(n) as fractions of elements of R(1).
2252
2253  def Rees=basering;              // when called inside normalI, the Rees
2254                                  // Algebra is the current basering.
2255
2256  // First of all we need some variable declarations...
2257
2258  list preimages;
2259  int n=size(L);                  // the number of rings R(1)-->...-->R(n)
2260  int j,k,l;
2261  int length=nvars(L[n]);         // the number of variables of the last ring
2262  string mapstr;
2263
2264  closureRingtower(L);            // ...and the rings R(1),...,R(n) out of L.
2265
2266  // For each variable (counter j) and for each intermediate ring (counter k):
2267  // Find a preimage of var_j*phi(nzd(k-1)) in R(k-1).
2268  // Finally, do the same for nzd.
2269
2270  for (j=1;j<=length+1;j++)
2271    {
2272      setring R(n);
2273
2274      if (j==1)
2275        {
2276          poly p;
2277        }
2278
2279      if (j<=nvars(R(n)))
2280        {
2281          p=var(j);
2282        }
2283      else
2284        {
2285          p=1;
2286        }
2287
2288      for (k=n;k>1;k--)
2289        {
2290
2291          if (j==1)
2292            {
2293              map phimap=R(k-1),phi;      // phimap is the map corresponding
2294            }                             // to phi
2295
2296          p=p*phimap(nzd);
2297
2298          // Compute the preimage of [p mod ker(k)] under phi in R(k-1):
2299          // As p is an element of Image(phi), there is a polynomial h such
2300          // that h is mapped to [p mod ker(k)], and h can be computed as the
2301          // normal form of p w.r.t. a Gröbner basis of
2302          // J(k):=<ker(k),Z(l)-phi(k)(l)> in R(k)[Z]=:S(k)
2303
2304          if (j==1)   // In the first iteration: Create S(k), fetch phi and
2305                      // ker(k) and construct the ideal J(k).
2306            {
2307              execute ("ring S(k) = "+charstr(R(k))+",("+varstr(R(k))+",
2308                       Z(1.."+string(ncols(phi))+")),(dp("+string(nvars(R(k)))
2309                       +"),dp("+string(ncols(phi))+"));");
2310              ideal phi=imap(R(k),phi);
2311              ideal J=imap (R(k),ker);
2312              for (l=1;l<=ncols(phi);l++)
2313                {
2314                  J=J+(Z(l)-phi[l]);
2315                }
2316              J=groebner(J);
2317              poly h=NF(imap(R(k),p),J);
2318            }
2319          else
2320            {
2321              setring S(k);
2322              h=NF(imap(R(k),p),J);
2323            }
2324
2325          setring R(k-1);
2326
2327          if (j==1)  // In the first iteration: Compute backmap:S(k)-->R(k-1)
2328            {
2329              mapstr=" map backmap = S(k),";
2330              for (l=1;l<=nvars(R(k));l++)
2331                {
2332                  mapstr=mapstr+"0,";
2333                }
2334              execute (mapstr+"maxideal(1);");
2335
2336              poly p;
2337            }
2338          p=NF(backmap(h),std(ker));
2339        }
2340
2341      // When down to R(1), store the result in the list preimages
2342
2343      preimages = insert(preimages,p,j-1);
2344    }
2345
2346  // R(1) was a copy of Rees, so we have to get back to the basering Rees from
2347  // the beginning and fetch the result (the list preimages) to this ring.
2348
2349  setring Rees;
2350  return (fetch(R(1),preimages));
2351}
2352///////////////////////////////////////////////////////////////////////////
2353
2354/*
2355                           Examples:
2356LIB"normal.lib";
2357//Huneke
2358ring qr=31991,(a,b,c,d,e),dp;
2359ideal i=
23605abcde-a5-b5-c5-d5-e5,
2361ab3c+bc3d+a3be+cd3e+ade3,
2362a2bc2+b2cd2+a2d2e+ab2e2+c2de2,
2363abc5-b4c2d-2a2b2cde+ac3d2e-a4de2+bcd2e3+abe5,
2364ab2c4-b5cd-a2b3de+2abc2d2e+ad4e2-a2bce3-cde5,
2365a3b2cd-bc2d4+ab2c3e-b5de-d6e+3abcd2e2-a2be4-de6,
2366a4b2c-abc2d3-ab5e-b3c2de-ad5e+2a2bcde2+cd2e4,
2367b6c+bc6+a2b4e-3ab2c2de+c4d2e-a3cde2-abd3e2+bce5;
2368
2369
2370//Vasconcelos (dauert laenger: 70 sec)
2371ring r=32003,(x,y,z,w,t),dp;
2372ideal i=
2373x2+zw,
2374y3+xwt,
2375xw3+z3t+ywt2,
2376y2w4-xy2z2t-w3t3;
2377
2378//Theo1
2379ring r=32003,(x,y,z),wp(2,3,6);
2380ideal i=zy2-zx3-x6;
2381
2382//Theo1a (CohenMacaulay and regular in codimension 2)
2383ring r=32003,(x,y,z,u),wp(2,3,6,6);
2384ideal i=zy2-zx3-x6+u2;
2385
2386
2387//Theo2
2388ring r=32003,(x,y,z),wp(3,4,12);
2389ideal i=z*(y3-x4)+x8;
2390
2391//Theo2a
2392ring r=32003,(T(1..4)),wp(3,4,12,17);
2393ideal i=
2394T(1)^8-T(1)^4*T(3)+T(2)^3*T(3),
2395T(1)^4*T(2)^2-T(2)^2*T(3)+T(1)*T(4),
2396T(1)^7+T(1)^3*T(2)^3-T(1)^3*T(3)+T(2)*T(4),
2397T(1)^6*T(2)*T(3)+T(1)^2*T(2)^4*T(3)+T(1)^3*T(2)^2*T(4)-T(1)^2*T(2)*T(3)^2+T(4)^2;
2398
2399//Theo3
2400ring r=32003,(x,y,z),wp(3,5,15);
2401ideal i=z*(y3-x5)+x10;
2402
2403
2404//Theo4
2405ring r=32003,(x,y,z),dp;
2406ideal i=(x-y)*(x-z)*(y-z);
2407
2408//Theo5
2409ring r=32003,(x,y,z),wp(2,1,2);
2410ideal i=z3-xy4;
2411
2412//Theo6
2413ring r=32003,(x,y,z),dp;
2414ideal i=x2y2+x2z2+y2z2;
2415
2416ring r=32003,(a,b,c,d,e,f),dp;
2417ideal i=
2418bf,
2419af,
2420bd,
2421ad;
2422
2423//ist CM
2424//Sturmfels
2425ring r=32003,(b,s,t,u,v,w,x,y,z),dp;
2426ideal i=
2427bv+su,
2428bw+tu,
2429sw+tv,
2430by+sx,
2431bz+tx,
2432sz+ty,
2433uy+vx,
2434uz+wx,
2435vz+wy,
2436bvz;
2437
2438//J S/Y
2439ring r=32003,(x,y,z,t),dp;
2440ideal i=
2441x2z+xzt,
2442xyz,
2443xy2-xyt,
2444x2y+xyt;
2445
2446//St_S/Y
2447ring r=32003,(b,s,t,u,v,w,x,y,z),dp;
2448ideal i=
2449wy-vz,
2450vx-uy,
2451tv-sw,
2452su-bv,
2453tuy-bvz;
2454
2455//Horrocks:
2456ring r=32003,(a,b,c,d,e,f),dp;
2457ideal i=
2458adef-16000be2f+16001cef2,
2459ad2f+8002bdef+8001cdf2,
2460abdf-16000b2ef+16001bcf2,
2461a2df+8002abef+8001acf2,
2462ad2e-8000bde2-7999cdef,
2463acde-16000bce2+16001c2ef,
2464a2de-8000abe2-7999acef,
2465acd2+8002bcde+8001c2df,
2466abd2-8000b2de-7999bcdf,
2467a2d2+9603abde-10800b2e2-9601acdf+800bcef+11601c2f2,
2468abde-8000b2e2-acdf-16001bcef-8001c2f2,
2469abcd-16000b2ce+16001bc2f,
2470a2cd+8002abce+8001ac2f,
2471a2bd-8000ab2e-7999abcf,
2472ab3f-3bdf3,
2473a2b2f-2adf3-16000bef3+16001cf4,
2474a3bf+4aef3,
2475ac3e-10668cde3,
2476a2c2e+10667ade3+16001be4+5334ce3f,
2477a3ce+10669ae3f,
2478bc3d+8001cd3e,
2479ac3d+8000bc3e+16001cd2e2+8001c4f,
2480b2c2d+16001ad4+4000bd3e+12001cd3f,
2481b2c2e-10668bc3f-10667cd2ef,
2482abc2e-cde2f,
2483b3cd-8000bd3f,
2484b3ce-10668b2c2f-10667bd2ef,
2485abc2f-cdef2,
2486a2bce-16000be3f+16001ce2f2,
2487ab3d-8000b4e-8001b3cf+16000bd2f2,
2488ab2cf-bdef2,
2489a2bcf-16000be2f2+16001cef3,
2490a4d-8000a3be+8001a3cf-2ae2f2;
2491
2492
2493ring r=32003,(b,s,t,u,v,w,x,y,z),dp;
2494ideal k=
2495wy-vz,
2496vx-uy,
2497tv-sw,
2498su-bv,
2499tuy-bvz;
2500ideal j=x2y2+x2z2+y2z2;
2501ideal i=mstd(intersect(j,k))[2];
2502
2503
2504ring r=32003,(b,s,t,u,v,w,x,y,z),dp;
2505ideal i=
2506wx2y3-vx2y2z+wx2yz2+wy3z2-vx2z3-vy2z3,
2507vx3y2-ux2y3+vx3z2-ux2yz2+vxy2z2-uy3z2,
2508tvx2y2-swx2y2+tvx2z2-swx2z2+tvy2z2-swy2z2,
2509sux2y2-bvx2y2+sux2z2-bvx2z2+suy2z2-bvy2z2,
2510tux2y3-bvx2y2z+tux2yz2+tuy3z2-bvx2z3-bvy2z3;
2511
2512
2513//riemenschneider 
2514ring r=32000,(p,q,s,t,u,v,w,x,y,z),wp(1,1,1,1,1,1,2,1,1,1);
2515ideal i=
2516xz,
2517vx,
2518ux,
2519su,
2520qu,
2521txy,
2522stx,
2523qtx,
2524uv2z-uwz,
2525uv3-uvw,
2526puv2-puw;
2527
2528ring r=0,(u,v,w,x,y,z),wp(1,1,1,3,2,1);
2529ideal i=wx,wy,wz,vx,vy,vz,ux,uy,uz,y3-x2;
2530
2531//Yoshihiko Sakai
2532ring r=0,(x,y),dp;   //genus 0 4 nodes and 6 cusps   
2533ideal i=(x2+y^2-1)^3 +27x2y2;
2534
2535ring r=0,(x,y),dp;   //genus 0
2536ideal i=(x-y^2)^2 - y*x^3;
2537
2538ring r=0,(x,y),dp;  //genus 4
2539ideal i=y3-x6+1;
2540
2541int m=9;           // q=9: genus 0
2542int p=2;
2543int q=9;//2,...,9
2544ring r=0,(x,y),dp; 
2545ideal i=y^m - x^p*(x - 1)^q;
2546
2547ring r=0,(x,y),dp;  //genus 19
2548ideal i=55*x^8+66*y^2*x^9+837*x^2*y^6-75*y^4*x^2-70*y^6-97*y^7*x^2;
2549
2550
2551ring r=0,(x,y),dp;  //genus 34
2552ideal i=y10+(-2494x2+474)*y8+(84366+2042158x4-660492)*y6
2553        +(128361096x4-47970216x2+6697080-761328152x6)*y4
2554        +(-12024807786x4-506101284x2+15052058268x6+202172841-3212x8)*y2
2555        +34263110700x4-228715574724x6+5431439286x2+201803238
2556        -9127158539954x10-3212722859346x8;
2557
2558//Rob Koelman
2559ring r=0,(x,y,z),dp;//genus 10  with 26 cusps
2560ideal i=
2561761328152*x^6*z^4-5431439286*x^2*y^8+2494*x^2*z^8+228715574724*x^6*y^4+
2562 9127158539954*x^10-15052058268*x^6*y^2*z^2+3212722859346*x^8*y^2-
2563 134266087241*x^8*z^2-202172841*y^8*z^2-34263110700*x^4*y^6-6697080*y^6*z^4-
2564 2042158*x^4*z^6-201803238*y^10+12024807786*x^4*y^4*z^2-128361096*x^4*y^2*z^4+
2565 506101284*x^2*z^2*y^6+47970216*x^2*z^4*y^4+660492*x^2*z^6*y^2-
2566 z^10-474*z^8*y^2-84366*z^6*y^4;
2567
2568ring r=0,(x,y),dp;//genus 10  with 26 cusps
2569ideal i=9127158539954x10+3212722859346x8y2+228715574724x6y4-34263110700x4y6
2570-5431439286x2y8-201803238y10-134266087241x8-15052058268x6y2+12024807786x4y4
2571+506101284x2y6-202172841y8+761328152x6-128361096x4y2+47970216x2y4-6697080y6
2572-2042158x4+660492x2y2-84366y4+2494x2-474y2-1;
2573
2574
2575ring r=0,(x,y),dp;   // genus 1  with 5 cusps
2576ideal i=57y5+516x4y-320x4+66y4-340x2y3+73y3+128x2-84x2y2-96x2y;
2577
2578//Mark van Hoeij
2579ring r=0,(x,y),dp;  //genus 19
2580ideal i=y20+y13x+x4y5+x3*(x+1)^2;
2581
2582ring r=0,(x,y),dp;  //genus 35
2583ideal i=y30+y13x+x4y5+x3*(x+1)^2;
2584
2585ring r=0,(x,y),dp;   //genus 55
2586ideal i=y40+y13x+x4y5+x3*(x+1)^2;
2587
2588ring r=0,(x,y),dp;  //genus 4
2589ideal i=((x2+y3)^2+xy6)*((x3+y2)^2+x10y);
2590
2591ring r=0,(y,z,w,u),dp; //genus -5
2592ideal i=y2+z2+w2+u2,w4-u4;
2593
2594ring r=0,(x,y,t),dp; //genus -5
2595ideal i=x8+8x7y+32x6y2+80x5y3+136x4y4+160x3y5+128x2y6+64xy7+16y8+4x6t2+24x5yt2+72x4y2t2+128x3y3t2+144x2y4t2+96xy5t2+32y6t2+14x4t4+56x3yt4+112x2y2t4+112xy3t4+40y4t4+20x2t6+40xyt6+8y2t6+9t8;
2596
2597ring r=0,(y,z,w,u),dp; //genus 9
2598ideal i=y2+z2+w2+u2,z4+w4+u4;
2599
2600ring r=0,(x,y,t),dp;
2601ideal i=
260225x8+200x7y+720x6y2+1520x5y3+2064x4y4+1856x3y5+1088x2y6+384xy7+64y8-12x6t2-72x5yt2-184x4y2t2-256x3y3t2-192x2y4t2-64xy5t2-2x4t4-8x3yt4+16xy3t4+16y4t4+4x2t6+8xyt6+8y2t6+t8;
2603
2604ring r=0,(x,y,t),dp;
2605ideal i=
260632761x8+786264x7y+8314416x6y2+50590224x5y3+193727376x4y4+478146240x3y5+742996800x2y6+664848000xy7+262440000y8+524176x7t+11007696x6yt+99772992x5y2t+505902240x4y3t+1549819008x3y4t+2868877440x2y5t+2971987200xy6t+1329696000y7t+3674308x6t2+66137544x5yt2+499561128x4y2t2+2026480896x3y3t2+4656222144x2y4t2+5746386240xy5t2+2976652800y6t2+14737840x5t3+221067600x4yt3+1335875904x3y2t3+4064449536x2y3t3+6226336512xy4t3+3842432640y5t3+36997422x4t4+443969064x3yt4+2012198112x2y2t4+4081745520xy3t4+3126751632y4t4+59524208x3t5+535717872x2yt5+1618766208xy2t5+1641991392y3t5+59938996x2t6+359633976xyt6+543382632y2t6+34539344xt7+103618032yt7+8720497t8;
2607
2608ring r=32003,(x,y,z,w,u),dp;
2609ideal i=x2+y2+z2+w2+u2,x3+y3+z3,z4+w4+u4;
2610
2611*/
2612
Note: See TracBrowser for help on using the repository browser.