Changeset a9431c in git
- Timestamp:
- Mar 26, 2009, 5:37:19 PM (14 years ago)
- Branches:
- (u'jengelh-datetime', 'ceac47cbc86fe4a15902392bdbb9bd2ae0ea02c6')(u'spielwiese', 'a800fe4b3e9d37a38c5a10cc0ae9dfa0c15a4ee6')
- Children:
- 53e33d93f45a825808d84cade536120482dc46c3
- Parents:
- 54248e343a5d77bfd7f19c65855707d3950619e8
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
Singular/LIB/normal.lib
r54248e ra9431c 1 1 /////////////////////////////////////////////////////////////////////////////// 2 version="$Id: normal.lib,v 1. 49 2006-07-25 17:54:28Singular Exp $";2 version="$Id: normal.lib,v 1.50 2009-03-26 16:37:19 Singular Exp $"; 3 3 category="Commutative Algebra"; 4 4 info=" 5 5 LIBRARY: normal.lib Normalization of Affine Rings 6 6 AUTHORS: G.-M. Greuel, greuel@mathematik.uni-kl.de, 7 @* S. Laplagne, slaplagn@dm.uba.ar, 7 8 @* G. Pfister, pfister@mathematik.uni-kl.de 8 9 10 9 11 MAIN 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 primeClosure(L); integral closure of R/p (p prime), L a list 16 closureFrac(L) write poly in integral closure as element of Quot(R/p) 17 18 AUXILIARY PROCEDURE: 19 deltaLoc(f,S); (sum of) delta invariant(s) at conjugated singular points 12 normal(I[...]); normalization of an affine ring 13 normalP(I,[...]; normalization of an affine ring in positive characteristic 14 normalC(I,[...]; normalization of an affine ring through a chain of rings 15 HomJJ(L); presentation of the End_R(J) as affine ring, J an ideal 16 genus(I); computes the geometric genus of a projective curve 17 primeClosure(L); integral closure of R/p, p a prime ideal 18 closureFrac(L); write a poly in integral closure as element of Quot(R/p) 19 iMult(L); intersection multiplicity of the ideals of the list L 20 21 AUXILIARY PROCEDURES: 22 deltaLoc(f,S); sum of delta invariants at conjugated singular points 23 locAtZero(I); checks whether the zero set of I is located at 0 24 norTest(i,nor;) checks whether result of normal or mormal_p was correct 20 25 "; 21 26 … … 30 35 LIB "hnoether.lib"; 31 36 LIB "reesclos.lib"; 37 LIB "algebra.lib"; 38 39 40 /////////////////////////////////////////////////////////////////////////////// 41 42 proc normal(ideal id, list #) 43 "USAGE: normal(id [,choose]); id = radical ideal, choose = optional string. @* 44 Optional parameters in list choose (can be entered in any order):@* 45 Decomposition:@* 46 - \"prim\" -> computes first the minimal associated primes, and then 47 the normalization of each prime. (default)@* 48 - \"equidim\" -> computes first an equidimensional decomposition, 49 and then the normalization of each component. @* 50 - \"noDeco\" -> no preliminary decomposition is done. If the ideal is 51 not equidimensional radical, output might be wrong.@* 52 - \"isPrim\" -> assumes that the ideal is prime. If assumption does 53 not hold, output might be wrong.@* 54 - \"noFac\" -> factorization is avoided in the computation of the 55 minimal associated primes; 56 Other:@* 57 - \"useRing\" -> uses the original ring ordering.@* 58 If the ring ordering is not global, it will change to a global 59 ordering only for computing radicals and prime or equidimensional 60 decompositions.@* 61 If this option is not set, changes to dp ordering and perform all 62 computation with respect to this ordering.@* 63 - \"withDelta\" (or \"wd\") -> returns also the delta invariants. 64 If choose is not given or empty, the default options are used.@* 65 ASSUME: The ideal must be radical, for non-radical ideals the output may 66 be wrong (id=radical(id); makes id radical). However, when using 67 \"prim\" option the minimal associated primes of id are computed first 68 and hence normal computes the normalization of the radical of id. 69 \"isPrim\" should only be used if id is known to be prime. 70 RETURN: a list, say nor, of size 1 (resp. 2 with option \"withDelta\"). 71 @format 72 The first element nor[1] is a list of r elements, where r is the 73 number of associated primes P_i with option \"prim\" (resp. >= no 74 of equidimenensional components P_i with option \"equidim\").@* 75 Each element of nor[1] is a list with the information on the 76 normalization of the i-th component, i.e. the integral closure 77 in its field of fractions (as affine ring).@* 78 Each list nor[1][i] contains 3 elements (resp. 4 with option 79 \"withDelta\"). @* 80 The first two element of nor[1][i] give the normalization by 81 module generators. The normalization is of the form 82 1/c * U, with U = nor[1][i][1] an ideal of R / P_i and 83 c = nor[1][i][2] a polynomial in R / P_i.@* 84 The third element is a ring Ri=nor[1][i][3], i=1..r, 85 which contains two ideals with given 86 names @code{norid} and @code{normap} such that @* 87 - Ri/norid is the normalization of the i-th component. 88 - the direct sum of the rings Ri/norid is the normalization 89 of basering/id; @* 90 - @code{normap} gives the normalization map from basering/id to 91 Ri/norid for each j.@* 92 When option \"withDelta\" is set, the forth element nor[1][i][4] is 93 the delta invariant of the i-th component. (-1 means infinite, and 0 94 that basering/P_i is normal)@* 95 @* 96 Also, When option \"withDelta\" is set the second element of the list 97 nor, nor[2], is an integer, the total delta invariant of basering/id 98 (-1 means infinite, and 0 that basering/id is normal). 99 @end format 100 THEORY: We use a general algorithm described in [G.-M. Greuel, S. Laplagne, 101 F. Seelisch: Normalization of Rings (2009)]. 102 The delta invariant of a reduced ring K[x1,...,xn]/id is 103 dim_K(normalization(K[x1,...,xn]/id) / K[x1,...,xn]/id) 104 We call this number also the delta invariant of id. 105 NOTE: To use the i-th ring type: @code{def R=nor[1][i][3]; setring R;}. 106 @* Increasing/decreasing printlevel displays more/less comments 107 (default: printlevel=0). 108 @* Implementation works also for local rings. 109 @* Not implemented for quotient rings. 110 @* If the input ideal id is weighted homogeneous a weighted ordering may 111 be used (qhweight(id); computes weights). 112 KEYWORDS: normalization; integral closure; delta invariant. 113 EXAMPLE: example normal; shows an example 114 " 115 { 116 intvec opt = option(get); // Save current options 117 118 int i,j; 119 int decomp; // Preliminar decomposition: 120 // 0 -> no decomposition (id is assumed to be prime) 121 // 1 -> no decomposition 122 // (id is assumed to be equidimensional radical) 123 // 2 -> equidimensional decomposition 124 // 3 -> minimal associated primes 125 int noFac, useRing, withDelta; 126 int dbg = printlevel - voice + 2; 127 int nvar = nvars(basering); 128 int chara = char(basering); 129 list result; 130 list keepresult; 131 list ringStruc; 132 ideal U; 133 poly c; 134 135 // Default methods: 136 noFac = 0; // Use facSTD when computing minimal associated primes 137 decomp = 3; // Minimal associated primes 138 useRing = 0; // Change first to dp ordering, and perform all 139 // computations there. 140 withDelta = 0; // Do not compute the delta invariant. 141 142 143 //--------------------------- define the method --------------------------- 144 string method; //make all options one string in order to use 145 //all combinations of options simultaneously 146 for ( i=1; i <= size(#); i++ ) 147 { 148 if ( typeof(#[i]) == "string" ) 149 { 150 method = method + #[i]; 151 } 152 } 153 154 //--------------------------- choosen methods ----------------------- 155 if ( find(method,"isprim") or find(method,"isPrim") ) 156 {decomp = 0;} 157 158 if ( find(method,"nodeco") or find(method,"noDeco") ) 159 {decomp = 1;} 160 161 if ( find(method,"equidim") ) 162 {decomp = 2;} 163 164 if ( find(method,"prim") ) 165 {decomp = 3;} 166 167 if ( find(method,"nofac") or find(method,"noFac") ) 168 {noFac=1;} 169 170 if ( (find(method,"useRing") or find(method,"usering")) and (ordstr(basering) != "dp("+string(nvars(basering))+"),C")) 171 {useRing = 1;} 172 173 if ( find(method,"withDelta") or find(method,"wd") or find(method,"withdelta")) 174 { 175 if((decomp == 0) or (decomp == 3)){ 176 withDelta = 1; 177 } else { 178 "WARNING: the delta invariants cannot be computed with an equidimensional"; 179 " decomposition."; 180 " Use option \"prim\" to compute first the minimal associated primes."; 181 ""; 182 } 183 } 184 185 kill #; 186 list #; 187 188 //------------------------ change ring if required ------------------------ 189 // If the ordering is not global, we change to dp ordering for computing the 190 // min ass primes. 191 // If the ordering is global, but not dp, and useRing = 0, we also change to 192 // dp ordering. 193 194 int isGlobal = ord_test(basering); // Checks if the original ring has 195 // global ordering. 196 197 def origR = basering; // origR is the original ring 198 // R is the ring where computations will be done 199 200 if((useRing == 1) and (isGlobal == 1)){ 201 def globR = basering; 202 } else { 203 // We change to dp ordering. 204 list rl = ringlist(origR); 205 list origOrd = rl[3]; 206 list newOrd = list("dp", intvec(1:nvars(origR))), list("C", 0); 207 rl[3] = newOrd; 208 def globR = ring(rl); 209 setring globR; 210 ideal id = fetch(origR, id); 211 } 212 213 //------------------------ preliminary decomposition----------------------- 214 list prim; 215 if(decomp == 2){ 216 dbprint(dbg, "// Computing the equidimensional decomposition..."); 217 prim = equidim(id); 218 } 219 if((decomp == 0) or (decomp == 1)){ 220 prim = id; 221 } 222 if(decomp == 3){ 223 dbprint(dbg, "// Computing the minimal associated primes..."); 224 if( noFac ) 225 { prim = minAssGTZ(id,1); } 226 else 227 { prim = minAssGTZ(id); } 228 } 229 230 // if ring was not global and useRing is on, we go back to the original ring 231 if((useRing == 1) and (isGlobal != 1)){ 232 setring origR; 233 def R = basering; 234 list prim = fetch(globR, prim); 235 } else { 236 def R = basering; 237 if(useRing == 0){ 238 ideal U; 239 poly c; 240 } 241 } 242 243 if(dbg>=1) 244 { 245 prim; ""; 246 "// number of components is", size(prim); 247 ""; 248 } 249 250 // ---------------- normalization of the components------------------------- 251 // calls normalM to compute the normalization of each component. 252 253 list norComp; // The normalization of each component. 254 int delt; 255 int deltI = 0; 256 int totalComps = 0; 257 258 setring origR; 259 def newROrigOrd; 260 list newRListO; 261 setring R; 262 def newR; 263 list newRList; 264 265 for(i=1; i<=size(prim); i++) 266 { 267 if(dbg>=2){pause();} 268 if(dbg>=1){ 269 "// start computation of component",i; 270 " --------------------------------"; 271 } 272 if(groebner(prim[i])[1] != 1){ 273 if(dbg>=2){ 274 "We compute the normalization in the ring"; basering; 275 } 276 printlevel = printlevel + 1; 277 norComp = normalM(prim[i], decomp, withDelta); 278 printlevel = printlevel - 1; 279 for(j = 1; j <= size(norComp); j++){ 280 newR = norComp[j][3]; 281 newRList = ringlist(newR); 282 U = norComp[j][1]; 283 c = norComp[j][2]; 284 if(withDelta){ 285 delt = norComp[j][4]; 286 if((delt >= 0) and (deltI >= 0)){ 287 deltI = deltI + delt; 288 } else { 289 deltI = -1; 290 } 291 } 292 if(useRing == 0){ 293 // We go back to the original ring. 294 setring origR; 295 U = fetch(R, U); 296 c = fetch(R, c); 297 newRListO = imap(R, newRList); 298 // We change the ordering in the new ring. 299 if(nvars(newR) > nvars(origR)){ 300 newRListO[3]=insert(origOrd, newRListO[3][1]); 301 } else { 302 newRListO[3] = origOrd; 303 } 304 newROrigOrd = ring(newRListO); 305 setring newROrigOrd; 306 ideal norid = imap(newR, norid); 307 ideal normap = imap(newR, normap); 308 export norid; 309 export normap; 310 setring origR; 311 totalComps++; 312 result[totalComps] = list(U, c, newROrigOrd); 313 if(withDelta){ 314 result[totalComps] = insert(result[totalComps], delt, 3); 315 } 316 setring R; 317 } else { 318 setring R; 319 totalComps++; 320 result[totalComps] = norComp[j]; 321 } 322 } 323 } 324 } 325 326 // -------------------------- delta computation ---------------------------- 327 if(withDelta == 1){ 328 // Intersection multiplicities of list prim, sp=size(prim). 329 if ( dbg >= 1 ) 330 { 331 "// Sum of delta for all components: ", deltI; 332 } 333 if(size(prim) > 1){ 334 dbprint(dbg, "// Computing the sum of the intersection multiplicities of the components..."); 335 int mul = iMult(prim); 336 if ( mul < 0 ) 337 { 338 deltI = -1; 339 } else { 340 deltI = deltI + mul; 341 } 342 if ( dbg >= 1 ) 343 { 344 "// Intersection multiplicity is : ", mul; 345 } 346 } 347 } 348 349 // -------------------------- prepare output ------------------------------ 350 setring origR; 351 if(withDelta){ 352 result = result, deltI; 353 } else { 354 result = list(result); 355 } 356 357 option(set, opt); 358 return(result); 359 } 360 361 362 example 363 { "EXAMPLE:"; 364 printlevel = printlevel+1; 365 echo = 2; 366 ring s = 0,(x,y),dp; 367 ideal i = (x2-y3)*(x2+y2)*x; 368 list nor = normal(i, "withDelta"); 369 nor; 370 371 // 2 branches have delta = 1, and 1 branch has delta = 0 372 // the total delta invariant is 13 373 374 def R2 = nor[1][2][3]; setring R2; 375 norid; normap; 376 377 echo = 0; 378 printlevel = printlevel-1; 379 pause(" hit return to continue"); echo=2; 380 381 ring r = 2,(x,y,z),dp; 382 ideal i = z3-xy4; 383 list nor = normal(i, "withDelta"); nor; 384 // the delta invariant is infinite 385 // xy2z/z2 and xy3/z2 generate the integral closure of r/i as r/i-module 386 // in its quotient field Quot(r/i) 387 388 // the normalization as affine algebra over the ground field: 389 def R = nor[1][1][3]; setring R; 390 norid; normap; 391 } 392 32 393 /////////////////////////////////////////////////////////////////////////////// 33 394 … … 39 400 @* p = nonzero divisor of R 40 401 COMPUTE: Endomorphism ring End_R(J)=Hom_R(J,J) with its ring structure as 41 affine ring, together with the canonical map R --> Hom_R(J,J),402 affine ring, together with the map R --> Hom_R(J,J) of affine rings, 42 403 where R is the quotient ring of P modulo the standard basis SBid. 43 RETURN: a list l of t woobjects404 RETURN: a list l of three objects 44 405 @format 45 406 l[1] : a polynomial ring, containing two ideals, 'endid' and 'endphi' … … 47 408 endphi describes the canonical map R -> Hom_R(J,J) 48 409 l[2] : an integer which is 1 if phi is an isomorphism, 0 if not 49 l[3] : an integer, the contribution to delta 410 l[3] : an integer, = dim_K(Hom_R(J,J)/R) (the contribution to delta) 411 if the dimension is finite, -1 otherwise 50 412 @end format 51 413 NOTE: printlevel >=1: display comments (default: printlevel=0) … … 54 416 { 55 417 //---------- initialisation --------------------------------------------------- 56 int isIso,isPr,is Co,isRe,isEq,oSAZ,ii,jj,q,y;418 int isIso,isPr,isHy,isCo,isRe,isEq,oSAZ,ii,jj,q,y; 57 419 intvec rw,rw1; 58 420 list L; … … 103 465 if ( y>=1 ) 104 466 { 105 "// compute p*Hom(J,J) = p*J:J, p a non-zerodivisor"; 106 "// p is equal to:"; ""; 107 p; 108 ""; 467 "// compute p*Hom(J,J) = p*J:J"; 468 "// the ideal J:";J; 109 469 } 110 470 f = quotient(p*J,J); 111 471 472 //### (neu GMG 4.10.08) divide by the greatest common divisor: 473 poly gg = gcd( f[1],p ); 474 for(ii=2; ii <=ncols(f); ii++) 475 { 476 gg=gcd(gg,f[ii]); 477 } 478 for(ii=1; ii<=ncols(f); ii++) 479 { 480 f[ii]=f[ii]/gg; 481 } 482 p = p/gg; 483 112 484 if ( y>=1 ) 113 { "// the module p*Hom(J,J) = p*J:J, p a non-zerodivisor"; 114 "// p"; p; 115 "// f=p*J:J";f; 485 { 486 "// the non-zerodivisor p:"; p; 487 "// the module p*Hom(J,J) = p*J:J :"; f; 488 ""; 116 489 } 117 490 f2 = std(p); … … 119 492 //---------- Test: Hom(J,J) == R ?, if yes, go home --------------------------- 120 493 121 rf = interred(reduce(f,f2)); // represents p*Hom(J,J)/p*R = Hom(J,J)/R 494 //rf = interred(reduce(f,f2)); 495 //### interred hier weggelassen, unten zugefgt 496 rf = reduce(f,f2); //represents p*Hom(J,J)/p*R = Hom(J,J)/R 122 497 if ( size(rf) == 0 ) 123 498 { … … 132 507 ideal endphi = maxideal(1); 133 508 ideal endid = fetch(P,id); 134 L=substpart(endid,endphi,homo,rw); 135 def lastRing=L[1]; 509 endid = simplify(endid,2); 510 L = substpart(endid,endphi,homo,rw); //## hier substpart 511 def lastRing = L[1]; 136 512 setring lastRing; 137 513 … … 142 518 attrib(endid,"isRegInCodim2",isRe); 143 519 attrib(endid,"isEqudimensional",isEq); 520 attrib(endid,"isHypersurface",0); 144 521 attrib(endid,"isCompleteIntersection",0); 145 attrib(endid,"isRad ",0);522 attrib(endid,"isRadical",0); 146 523 L=lastRing; 147 524 L = insert(L,1,1); … … 150 527 { 151 528 "// R=Hom(J,J)"; 152 " ";153 529 lastRing; 154 " ";155 530 "// the new ideal"; 156 531 endid; 157 532 " "; 158 533 "// the old ring"; 159 " ";160 534 P; 161 " ";162 535 "// the old ideal"; 163 " ";164 536 setring P; 165 537 id; 166 538 " "; 167 539 setring lastRing; 168 "// the map"; 169 " "; 540 "// the map to the new ring"; 170 541 endphi; 171 542 " "; 172 543 pause(); 173 newline;544 ""; 174 545 } 175 546 setring P; … … 181 552 "// R is not equal to Hom(J,J), we have to try again"; 182 553 pause(); 183 newline;554 ""; 184 555 } 185 556 //---------- Hom(J,J) != R: create new ring and map from old ring ------------- 186 557 // the ring newR1/SBid+syzf will be isomorphic to Hom(J,J) as R-module 187 188 f=mstd(f)[2]; 189 ideal ann=quotient(f2,f); 190 int delt; 191 if(isIso&&isEq){delt=vdim(std(modulo(f,ideal(p))));} 558 // f2=p (i.e. ideal generated by p) 559 560 //f = mstd(f)[2]; //### gendert GMG 04.10.08 561 //ideal ann = quotient(f2,f); //### f durch rf ersetzt 562 rf = mstd(rf)[2]; //rf = NF(f,p), hence <p,rf> = <p,f> 563 ideal ann = quotient(f2,rf); //p:f = p:rf 564 565 //------------- compute the contribution to delta ---------- 566 //delt=dim_K(Hom(JJ)/R (or -1 if infinite) 567 568 int delt=vdim(std(modulo(f,ideal(p)))); 192 569 193 570 f = p,rf; // generates pJ:J mod(p), i.e. p*Hom(J,J)/p*R as R-module 194 571 q = size(f); 195 196 572 syzf = syz(f); 197 573 … … 211 587 } 212 588 213 map psi1 = P,maxideal(1); 214 ideal SBid = psi1(SBid); 589 //map psi1 = P,maxideal(1); //### psi1 durch fetch ersetzt 590 //ideal SBid = psi1(SBid); 591 ideal SBid = fetch(P,SBid); 215 592 attrib(SBid,"isSB",1); 216 593 217 594 qring newR = std(SBid); 218 595 219 map psi = R,ideal(X(1..nvars(R))); 220 ideal id = psi(id); 221 ideal f = psi(f); 222 module syzf = psi(syzf); 596 //map psi = R,ideal(X(1..nvars(R))); //### psi durch fetch ersetzt 597 //ideal id = psi(id); 598 //ideal f = psi(f); 599 //module syzf = psi(syzf); 600 ideal id = fetch(R,id); 601 ideal f = fetch(R,f); 602 module syzf = fetch(R,syzf); 223 603 ideal pf,Lin,Quad,Q; 224 604 matrix T,A; … … 231 611 // It is a fact, that the kernel is generated by the linear and the quadratic 232 612 // relations 613 // f=p,rf, rf=reduce(f,p), generates pJ:J mod(p), 614 // i.e. p*Hom(J,J)/p*R as R-module 233 615 234 616 pf = f[1]*f; … … 238 620 { 239 621 "// the ring structure of Hom(J,J) as R-algebra"; 240 " "; 241 "// the linear relations"; 242 " "; 622 "// the linear relations:"; 243 623 Lin; 244 " ";245 } 246 624 } 625 626 poly ff; 247 627 for (ii=2; ii<=q; ii++ ) 248 628 { 249 629 for ( jj=2; jj<=ii; jj++ ) 250 630 { 251 A = lift(pf,f[ii]*f[jj]); 252 Quad = Quad, ideal(T(jj)*T(ii) - T*A); // quadratic relations 631 ff = NF(f[ii]*f[jj],std(0)); //this makes lift much faster 632 A = lift(pf,ff); //ff lin. comb. of elts of pf mod I 633 Quad = Quad, ideal(T(jj)*T(ii) - T*A); //quadratic relations 253 634 } 254 635 } … … 257 638 { 258 639 "// the quadratic relations"; 259 " "; 260 interred(Quad); 640 Quad; 261 641 pause(); 262 642 newline; … … 264 644 Q = Lin,Quad; 265 645 Q = subst(Q,T(1),1); 266 Q=mstd(Q)[2]; 646 //Q = mstd(Q)[2]; //### sehr aufwendig, daher weggelassen (GMG) 647 //### ev das neue interred 648 //mstd dient nur zum verkleinern, die SB-Eigenschaft geht spaeter verloren 649 //da in neuen Ring abgebildet und mit id vereinigt 650 267 651 //---------- reduce number of variables by substitution, if possible ---------- 268 652 if (homo==1) … … 275 659 } 276 660 277 ideal endid = imap(newR,id),imap(newR,Q); 661 ideal endid = imap(newR,id),imap(newR,Q); 662 //hier wird Q weiterverwendet, die SB-Eigenschaft wird nicht verwendet. 663 endid = simplify(endid,2); 278 664 ideal endphi = ideal(X(1..nvars(R))); 279 665 280 L =substpart(endid,endphi,homo,rw);666 L = substpart(endid,endphi,homo,rw); 281 667 282 668 def lastRing=L[1]; … … 287 673 ideal an=sigma(ann); 288 674 export(an); //noetig? 289 ideal te=an,endid;290 if(isIso&&(size(reduce(te,std(maxideal(1))))==0))291 {292 attrib(endid,"onlySingularAtZero",oSAZ);293 }294 kill te;295 attrib(endid,"isCohenMacaulay",isCo); 675 //ideal te=an,endid; 676 //if(isIso && (size(reduce(te,std(maxideal(1))))==0)) //#### ok??? 677 // { 678 // attrib(endid,"onlySingularAtZero",oSAZ); 679 // } 680 //kill te; 681 attrib(endid,"isCohenMacaulay",isCo); //#### ok??? 296 682 attrib(endid,"isPrim",isPr); 297 683 attrib(endid,"isIsolatedSingularity",isIso); 298 684 attrib(endid,"isRegInCodim2",isRe); 299 685 attrib(endid,"isEquidimensional",isEq); 686 attrib(endid,"isHypersurface",0); 300 687 attrib(endid,"isCompleteIntersection",0); 301 attrib(endid,"isRad ",0);688 attrib(endid,"isRadical",0); 302 689 if(y>=1) 303 690 { 304 "// the new ring after reduction of the number of variables"; 305 " "; 691 "// the new ring after reduction of the number of variables"; 306 692 lastRing; 307 " ";308 693 "// the new ideal"; 309 " "; 310 endid; 311 " "; 312 "// the old ring"; 313 " "; 694 endid; ""; 695 "// the old ring"; 314 696 P; 315 " ";316 697 "// the old ideal"; 317 " ";318 698 setring P; 319 699 id; 320 700 " "; 321 701 setring lastRing; 322 "// the map"; 323 " "; 702 "// the map to the new ring"; 324 703 endphi; 325 704 " "; 326 705 pause(); 327 newline;706 ""; 328 707 } 329 708 L = lastRing; 330 709 L = insert(L,0,1); 331 L[3] =delt;710 L[3] = delt; 332 711 return(L); 333 712 } … … 338 717 ideal J = x,y; 339 718 poly p = x; 340 list Li = std(id),id,J,p;719 list Li = std(id),id,J,p; 341 720 list L = HomJJ(Li); 342 721 def end = L[1]; // defines ring L[1], containing ideals endid, endphi … … 346 725 map psi = r,endphi;// defines the canonical map r/id -> End(r/id) 347 726 psi; 727 L[3]; // contribution to delta 348 728 } 349 729 730 350 731 /////////////////////////////////////////////////////////////////////////////// 351 352 proc normal(ideal id, list #) 353 "USAGE: normal(i [,choose]); i a radical ideal, choose empty, 1 ,\"g\" \"wd\" 354 if choose=1 the normalization of the associated primes is computed 355 (which is sometimes more efficient); 356 if @code{choose=\"wd\"} the delta invariant is computed 357 simultaneously; this may take much more time in the reducible case, 358 since the factorizing standard basis algorithm cannot be used.@* 359 if @code{choose=\"g\"} the generators of the integral closure 360 are computed. 361 ASSUME: The ideal must be radical, for non-radical ideals the output may 362 be wrong (i=radical(i); makes i radical) 363 RETURN: a list of rings, say nor and in case of @code{choose=\"wd\"} an 364 integer at the end of the list. 365 In case of @code{choose=\"g\"} it returns a list of polynomials 366 g_1,...,g_k+1 at the end of the list such that g_1/g_k+1,... 367 g_k/g_k+1 generate the integral closure. 368 Each ring @code{nor[i]} contains two ideals with given names 369 @code{norid} and @code{normap} such that@* 370 - the direct sum of the rings @code{nor[i]/norid} is the 371 normalization of basering/id;@* 372 - @code{normap} gives the normalization map from basering/id to 373 @code{nor[i]/norid} (for each i). 374 NOTE: to use the i-th ring type: @code{def R=nor[i]; setring R;}. 375 @* Increasing printlevel displays more comments (default: printlevel=0). 376 @* Not implemented for local or mixed orderings. 377 @* If the input ideal i is weighted homogeneous a weighted ordering may 378 be used (qhweight(i); computes weights). 379 KEYWORDS: normalization; delta invariant. 380 EXAMPLE: example normal; shows an example 732 //compute intersection multiplicities as needed for delta(I) in 733 //normalizationPrimes and normalP: 734 735 proc iMult (list prim) 736 "USAGE: iMult(L); L a list of ideals 737 RETURN: int, the intersection multiplicity of the ideals of L; 738 if iMult(L) is infinite, -1 is returned. 739 THEORY: If r=size(L)=2 then iMult(L) = vdim(std(L[1]+L[2])) and in general 740 iMult(L) = sum{ iMult(L[j],Lj) | j=1..r-1 } with Lj the intersection 741 of L[j+1],...,L[r]. If I is the intersection of all ideals in L then 742 we have delta(I) = delta(L[1])+...+delta(L[r]) + iMult(L) where 743 delta(I) = vdim (normalisation(R/I)/(R/I)), R the basering. 744 EXAMPLE: example iMult; shows an example 381 745 " 382 { 383 int i,j,y,withdelta,withgens; 384 string sr; 385 list result,prim,keepresult; 386 y = printlevel-voice+2; 387 if(size(#)>0) 388 { 389 if(typeof(#[1])=="string") 746 { int i,mul,mu; 747 int sp = size(prim); 748 int y = printlevel-voice+2; 749 if ( sp > 1 ) 390 750 { 391 if(#[1]=="g") 392 { 393 withgens=1; 394 } 395 else 396 { 397 withdelta=1; 398 } 399 kill #; 400 list #; 751 ideal I(sp-1) = prim[sp]; 752 mu = vdim(std(I(sp-1)+prim[sp-1])); 753 mul = mu; 754 if ( y>=1 ) 755 { 756 "// intersection multiplicity of component",sp,"with",sp-1,":"; mu; 757 } 758 if ( mu >= 0 ) 759 { 760 for (i=sp-2; i>=1 ; i--) 761 { 762 ideal I(i) = intersect(I(i+1),prim[i+1]); 763 mu = vdim(std(I(i)+prim[i])); 764 if ( mu < 0 ) 765 { 766 break; 767 } 768 mul = mul + mu; 769 if ( y>=1 ) 770 { 771 "// intersection multiplicity of components",sp,"...",i+1,"with",i; mu; 772 } 773 } 774 } 401 775 } 402 } 403 attrib(id,"isRadical",1); 404 if ( ord_test(basering) != 1) 405 { 406 ""; 407 "// Not implemented for this ordering,"; 408 "// please change to global ordering!"; 409 return(result); 410 } 411 if(withgens) 412 { 413 list pr=minAssGTZ(id); 414 if(size(pr)>1){ERROR("ideal is not prime");} 415 def R=basering; 416 if(defined(ker)){kill ker;} 417 ideal ker=id; 418 export(ker); 419 list l=R; 420 l=primeClosure(l); 421 list gens=closureGenerators(l); 422 list resu=l[size(l)],gens; 423 dbprint(y+1," 424 // 'normal' created a list of one ring. 425 // nor[2] is a list of elements of the basering such that 426 // nor[2][i]/nor[2][size(nor[2])] generate the integral closure. 427 // To see the rings, type (if the name of your list is nor): 428 show( nor); 429 // To access the 1-st ring and map (similar for the others), type: 430 def R = nor[1]; setring R; norid; normap; 431 // R/norid is the 1-st ring of the normalization and 432 // normap the map from the original basering to R/norid"); 433 434 return(resu); 435 } 436 if( typeof(attrib(id,"isCompleteIntersection"))=="int" ) 437 { 438 if(attrib(id,"isCompleteIntersection")==1) 439 { 440 attrib(id,"isCohenMacaulay",1); 441 attrib(id,"isEquidimensional",1); 442 } 443 } 444 if( typeof(attrib(id,"isCohenMacaulay"))=="int" ) 445 { 446 if(attrib(id,"isCohenMacaulay")==1) 447 { 448 attrib(id,"isEquidimensional",1); 449 } 450 } 451 if( typeof(attrib(id,"isPrim"))=="int" ) 452 { 453 if(attrib(id,"isPrim")==1) 454 { 455 attrib(id,"isEquidimensional",1); 456 } 457 } 458 if(size(#)==0) 459 { 460 if( typeof(attrib(id,"isEquidimensional"))=="int" ) 461 { 462 if(attrib(id,"isEquidimensional")==1) 463 { 464 prim[1]=id; 465 } 466 else 467 { 468 prim=equidim(id); 469 } 470 } 471 else 472 { 473 prim=equidim(id); 474 } 475 if(y>=1) 476 { 477 "// we have ",size(prim),"equidimensional components"; 478 } 479 if(withdelta &&(size(prim)>1)) 480 { 481 withdelta=0; 482 "WARNING! cannot compute delta,"; 483 "the ideal is not equidimensional"; 484 } 485 if(!withdelta) 486 { 487 option(redSB); 488 for(j=1;j<=size(prim);j++) 489 { 490 keepresult=keepresult+facstd(prim[j]); 491 } 492 prim=keepresult; 493 option(noredSB); 494 } 495 } 496 else 497 { 498 if( typeof(attrib(id,"isPrim"))=="int" ) 499 { 500 if(attrib(id,"isPrim")==1) 501 { 502 prim[1]=id; 503 } 504 else 505 { 506 prim=minAssGTZ(id); 507 } 508 } 509 else 510 { 511 prim=minAssGTZ(id); 512 } 513 if(y>=1) 514 { 515 "// we have ",size(prim),"irreducible components"; 516 } 517 } 518 for(i=1; i<=size(prim); i++) 519 { 520 if(y>=1) 521 { 522 "// we are in loop ",i; 523 } 524 attrib(prim[i],"isCohenMacaulay",0); 525 if(size(#)!=0) 526 { 527 attrib(prim[i],"isPrim",1); 528 } 529 else 530 { 531 attrib(prim[i],"isPrim",0); 532 } 533 attrib(prim[i],"isRegInCodim2",0); 534 attrib(prim[i],"isIsolatedSingularity",0); 535 attrib(prim[i],"isEquidimensional",1); 536 attrib(prim[i],"isCompleteIntersection",0); 537 attrib(prim[i],"onlySingularAtZero",0); 538 if( typeof(attrib(id,"onlySingularAtZero"))=="int" ) 539 { 540 if(attrib(id,"onlySingularAtZero")==1) 541 {attrib(prim[i],"onlySingularAtZero",1); } 542 } 543 544 if( typeof(attrib(id,"isIsolatedSingularity"))=="int" ) 545 { 546 if(attrib(id,"isIsolatedSingularity")==1) 547 {attrib(prim[i],"isIsolatedSingularity",1); } 548 } 549 550 if( typeof(attrib(id,"isCompleteIntersection"))=="int" ) 551 { 552 if((attrib(id,"isIsolatedSingularity")==1)&&(size(#)==0)) 553 {attrib(prim[i],"isIsolatedSingularity",1); } 554 } 555 keepresult=normalizationPrimes(prim[i],maxideal(1),0); 556 557 for(j=1;j<=size(keepresult)-1;j++) 558 { 559 result=insert(result,keepresult[j]); 560 } 561 sr = string(size(result)); 562 } 563 if(withdelta) 564 { 565 sr = string(size(keepresult)-1); 566 result=keepresult; 567 } 568 dbprint(y+1," 569 // 'normal' created a list of "+sr+" ring(s)."); 570 if(withdelta) 571 { 572 dbprint(y+1,"// nor["+sr+"+1] is the delta-invariant."); 573 } 574 dbprint(y+1,"// To see the rings, type (if the name of your list is nor): 575 show( nor); 576 // To access the 1-st ring and map (similar for the others), type: 577 def R = nor[1]; setring R; norid; normap; 578 // R/norid is the 1-st ring of the normalization and 579 // normap the map from the original basering to R/norid"); 580 581 //kill endphi,endid; 582 return(result); 776 return(mul); 583 777 } 584 778 example 585 779 { "EXAMPLE:"; echo = 2; 586 ring r=32003,(x,y,z),wp(2,1,2); 587 ideal i=z3-xy4; 588 list nor=normal(i); 589 show(nor); 590 def r1=nor[1]; 591 setring r1; 592 norid; 593 normap; 594 595 ring s=0,(x,y),dp; 596 ideal i=(x-y^2)^2 - y*x^3; 597 nor=normal(i,"wd"); 598 //the delta-invariant 599 nor[size(nor)]; 600 nor=normal(i,"g"); 601 nor[size(nor)]; 780 ring s = 23,(x,y),dp; 781 list L = (x-y),(x3+y2); 782 iMult(L); 783 L = (x-y),(x3+y2),(x3-y4); 784 iMult(L); 785 } 786 /////////////////////////////////////////////////////////////////////////////// 787 //check if I has a singularity only at zero, as needed in normalizationPrimes 788 789 proc locAtZero (ideal I) 790 "USAGE: locAtZero(I); I = ideal 791 RETURN: int, 1 if I has only one point which is located at zero, 0 otherwise 792 ASSUME: I is given as a standard bases in the basering 793 NOTE: only useful in affine rings, in local rings vdim does the check 794 EXAMPLE: example locAtZero; shows an example 795 " 796 { 797 int ii,jj, caz; //caz: conzentrated at zero 798 int dbp = printlevel-voice+2; 799 int nva = nvars(basering); 800 int vdi = vdim(I); 801 if ( vdi < 0 ) 802 { 803 if (dbp >=1) 804 { "// non-isolated singularitiy";""; } 805 return(caz); 806 } 807 808 //Now the ideal is 0-dim 809 //First an easy test 810 //If I is homogenous and not constant it is concentrated at 0 811 if( homog(I)==1 && size(jet(I,0))==0) 812 { 813 caz=1; 814 if (dbp >=1) 815 { "// isolated singularity and homogeneous";""; } 816 return(caz); 817 } 818 819 //Now the general case with I 0-dim. Choose an appropriate power pot, 820 //and check each variable x whether x^pot is in I. 821 int mi1 = mindeg1(lead(I)); 822 int pot = vdi; 823 if ( (mi1+(mi1==1))^2 < vdi ) 824 { 825 pot = (mi1+(mi1==1))^2; //### alternativ: pot = vdi lassen 826 } 827 828 while ( 1 ) 829 { 830 caz = 1; 831 for ( ii=1; ii<= nva; ii++ ) 832 { 833 if ( NF(var(ii)^pot,I) != 0 ) 834 { 835 caz = 0; break; 836 } 837 } 838 if ( caz == 1 || pot >= vdi ) 839 { 840 if (dbp >=1) 841 { 842 "// mindeg, exponent, vdim used in 'locAtZero':", mi1,pot,vdi; ""; 843 } 844 return(caz); 845 } 846 else 847 { 848 if ( pot^2 < vdi ) 849 { pot = pot^2; } 850 else 851 { pot = vdi; } 852 } 853 } 602 854 } 855 example 856 { "EXAMPLE:"; echo = 2; 857 ring r = 0,(x,y,z),dp; 858 poly f = z5+y4+x3+xyz; 859 ideal i = jacob(f),f; 860 i=std(i); 861 locAtZero(i); 862 i= std(i*ideal(x-1,y,z)); 863 locAtZero(i); 864 } 603 865 604 866 /////////////////////////////////////////////////////////////////////////////// 605 static proc normalizationPrimes(ideal i,ideal ihp,int delt, list #) 606 "USAGE: normalizationPrimes(i,ihp[,si]); i equidimensional ideal, ihp map 607 (partial normalization),delta partial delta-invariant, 608 # ideal of singular locus 867 868 //The next procedure normalizationPrimes computes the normalization of an 869 //irreducible or an equidimensional ideal i. 870 //- If i is irreducuble, then the returned list, say nor, has size 2 871 //with nor[1] the normalization ring and nor[2] the delta invariant. 872 //- If i is equidimensional, than the "splitting tools" can create a 873 //decomposition of i and nor can have more than 1 ring. 874 875 static proc normalizationPrimes(ideal i,ideal ihp,int delt,intvec delti,list #) 876 "USAGE: normalizationPrimes(i,ihp,delt[,si]); i = equidimensional ideal, 877 ihp = map (partial normalization), delt = partial delta-invariant, 878 si = ideal s.t. V(si) contains singular locus (optional) 609 879 RETURN: a list of rings, say nor, and an integer, the delta-invariant 610 880 at the end of the list. 611 each ring nor[ i]contains two ideals881 each ring nor[j], j = 1..size(nor)-1, contains two ideals 612 882 with given names norid and normap such that 613 - the direct sum of the rings nor[ i]/norid is614 the normalization of basering/i d;883 - the direct sum of the rings nor[j]/norid is 884 the normalization of basering/i; 615 885 - normap gives the normalization map from basering/id 616 to nor[i]/norid (for each i) 886 to nor[j]/norid (for each j) 887 nor[size(nor)] = dim_K(normalisation(P/i) / (P/i)) is the 888 delta-invariant, where P is the basering. 617 889 EXAMPLE: example normalizationPrimes; shows an example 618 890 " 619 891 { 620 892 //Note: this procedure calls itself as long as the test for 893 //normality, i.e if R==Hom(J,J), is negative. 894 895 int printlev = printlevel; //store printlevel in order to reset it later 621 896 int y = printlevel-voice+2; // y=printlevel (default: y=0) 622 623 897 if(y>=1) 624 898 { 625 899 ""; 626 "// START a normalization loop with the ideal"; "";900 "// START a normalization loop with the ideal"; 627 901 i; ""; 902 "// in the ring:"; 628 903 basering; ""; 629 904 pause(); 630 newline;905 ""; 631 906 } 632 907 633 908 def BAS=basering; 634 list result,keepresult1,keepresult2 ;909 list result,keepresult1,keepresult2,JM,gnirlist; 635 910 ideal J,SB,MB; 636 int depth,lauf,prdim ;911 int depth,lauf,prdim,osaz; 637 912 int ti=timer; 638 913 914 gnirlist = ringlist(BAS); 915 916 //----------- the trivial case of a zero ideal as input, RETURN ------------ 639 917 if(size(i)==0) 640 918 { … … 643 921 "// the ideal was the zero-ideal"; 644 922 } 645 execute("ring newR7="+charstr(basering)+",("+varstr(basering)+"),(" 646 +ordstr(basering)+");"); 923 // execute("ring newR7="+charstr(basering)+",("+varstr(basering)+"),(" 924 // +ordstr(basering)+");"); 925 def newR7 = ring(gnirlist); 926 setring newR7; 647 927 ideal norid=ideal(0); 648 928 ideal normap=fetch(BAS,ihp); … … 650 930 export normap; 651 931 result=newR7; 652 result[size(result)+1]= delt;932 result[size(result)+1]=list(delt,delti); 653 933 setring BAS; 654 934 return(result); 655 935 } 656 936 937 //--------------- General NOTATION, compute SB of input ----------------- 938 // SM is a list, the result of mstd(i) 939 // SM[1] = SB of input ideal i, 940 // SM[2] = (minimal) generators for i. 941 // We work with SM and will copy the attributes from i to SM[2] 942 // JM will be a list, either JM[1]=maxideal(1),JM[2]=maxideal(1) 943 // in case i has onlySingularAtZero, or JM = mstd(si) where si = #[1], 944 // or JM = mstd(J) where J is the ideal of the singular locus 945 // JM[2] must be (made) radical 946 657 947 if(y>=1) 658 948 { 659 "// SB-computation of the input ideal"; 660 } 661 list SM=mstd(i); //here the work starts 949 "// SB-computation of the ideal"; 950 } 951 952 list SM = mstd(i); //Now the work starts 662 953 int dimSM = dim(SM[1]); //dimension of variety to normalize 663 // Case: Get an ideal containing a unit 954 if(y>=1) 955 { 956 "// the dimension is:"; dimSM; 957 } 958 //----------------- the general case, set attributes ---------------- 959 //Note: onlySingularAtZero is NOT preserved under the ring extension 960 //basering --> Hom(J,J) (in contrast to isIsolatedSingularity), 961 //therefore we reset it: 962 963 attrib(i,"onlySingularAtZero",0); 964 965 if(attrib(i,"isPrim")==1) 966 { 967 attrib(SM[2],"isPrim",1); 968 } 969 else 970 { 971 attrib(SM[2],"isPrim",0); 972 } 973 if(attrib(i,"isIsolatedSingularity")==1) 974 { 975 attrib(SM[2],"isIsolatedSingularity",1); 976 } 977 else 978 { 979 attrib(SM[2],"isIsolatedSingularity",0); 980 } 981 if(attrib(i,"isCohenMacaulay")==1) 982 { 983 attrib(SM[2],"isCohenMacaulay",1); 984 } 985 else 986 { 987 attrib(SM[2],"isCohenMacaulay",0); 988 } 989 if(attrib(i,"isRegInCodim2")==1) 990 { 991 attrib(SM[2],"isRegInCodim2",1); 992 } 993 else 994 { 995 attrib(SM[2],"isRegInCodim2",0); 996 } 997 if(attrib(i,"isEquidimensional")==1) 998 { 999 attrib(SM[2],"isEquidimensional",1); 1000 } 1001 else 1002 { 1003 attrib(SM[2],"isEquidimensional",0); 1004 } 1005 if(attrib(i,"isCompleteIntersection")==1) 1006 { 1007 attrib(SM[2],"isCompleteIntersection",1); 1008 } 1009 else 1010 { 1011 attrib(SM[2],"isCompleteIntersection",0); 1012 } 1013 if(attrib(i,"isHypersurface")==1) 1014 { 1015 attrib(SM[2],"isHypersurface",1); 1016 } 1017 else 1018 { 1019 attrib(SM[2],"isHypersurface",0); 1020 } 1021 1022 if(attrib(i,"onlySingularAtZero")==1) 1023 { 1024 attrib(SM[2],"onlySingularAtZero",1); 1025 } 1026 else 1027 { 1028 attrib(SM[2],"onlySingularAtZero",0); 1029 } 1030 1031 //------- an easy and cheap test for onlySingularAtZero --------- 1032 if( (attrib(SM[2],"isIsolatedSingularity")==1) && (homog(SM[2])==1) ) 1033 { 1034 attrib(SM[2],"onlySingularAtZero",1); 1035 } 1036 1037 //-------------------- Trivial cases, in each case RETURN ------------------ 1038 // input ideal is the ideal of a partial normalization 1039 1040 // ------------ Trivial case: input ideal contains a unit --------------- 664 1041 if( dimSM == -1) 665 1042 { ""; … … 678 1055 export normap; 679 1056 result=newR6; 680 result[size(result)+1]= delt;1057 result[size(result)+1]=list(delt,delti); 681 1058 setring BAS; 682 1059 return(result); 683 1060 } 684 685 if(y>=1) 686 { 687 "// the dimension is:"; ""; 688 dimSM;""; 689 } 690 if(size(#)>0) 691 { 692 if(attrib(i,"onlySingularAtZero")) 693 { 694 list JM=maxideal(1),maxideal(1); 695 attrib(JM[1],"isSB",1); 696 attrib(JM[2],"isRad",1); 697 } 698 else 699 { 700 ideal te=#[1],SM[2]; 701 list JM=mstd(te); 702 kill te; 703 if( typeof(attrib(#[1],"isRad"))!="int" ) 704 { 705 attrib(JM[2],"isRad",0); 706 } 707 } 708 } 709 710 if(attrib(i,"isPrim")==1) 711 { 712 attrib(SM[2],"isPrim",1); 713 } 714 else 715 { 716 attrib(SM[2],"isPrim",0); 717 } 718 if(attrib(i,"isIsolatedSingularity")==1) 719 { 720 attrib(SM[2],"isIsolatedSingularity",1); 721 } 722 else 723 { 724 attrib(SM[2],"isIsolatedSingularity",0); 725 } 726 if(attrib(i,"isCohenMacaulay")==1) 727 { 728 attrib(SM[2],"isCohenMacaulay",1); 729 } 730 else 731 { 732 attrib(SM[2],"isCohenMacaulay",0); 733 } 734 if(attrib(i,"isRegInCodim2")==1) 735 { 736 attrib(SM[2],"isRegInCodim2",1); 737 } 738 else 739 { 740 attrib(SM[2],"isRegInCodim2",0); 741 } 742 if(attrib(i,"isEquidimensional")==1) 743 { 744 attrib(SM[2],"isEquidimensional",1); 745 } 746 else 747 { 748 attrib(SM[2],"isEquidimensional",0); 749 } 750 if(attrib(i,"isCompleteIntersection")==1) 751 { 752 attrib(SM[2],"isCompleteIntersection",1); 753 } 754 else 755 { 756 attrib(SM[2],"isCompleteIntersection",0); 757 } 758 if(attrib(i,"onlySingularAtZero")==1) 759 { 760 attrib(SM[2],"onlySingularAtZero",1); 761 } 762 else 763 { 764 attrib(SM[2],"onlySingularAtZero",0); 765 } 766 if((attrib(SM[2],"isIsolatedSingularity")==1)&&(homog(SM[2])==1)) 767 { 768 attrib(SM[2],"onlySingularAtZero",1); 769 } 770 771 //the smooth case 772 if(size(#)>0) 773 { 774 if(dim(JM[1])==-1) 775 { 776 if(y>=1) 777 { 778 "// the ideal was smooth"; 779 } 780 MB=SM[2]; 781 intvec rw;; 782 list LL=substpart(MB,ihp,0,rw); 783 def newR6=LL[1]; 784 setring newR6; 785 ideal norid=endid; 786 ideal normap=endphi; 787 kill endid,endphi; 788 export norid; 789 export normap; 790 result=newR6; 791 result[size(result)+1]=delt; 792 setring BAS; 793 return(result); 794 } 795 } 796 797 //the zero-dimensional case 798 if((dim(SM[1])==0)&&(homog(SM[2])==1)) 1061 1062 // --- Trivial case: input ideal is zero-dimensional and homog --- 1063 if( (dim(SM[1])==0) && (homog(SM[2])==1) ) 799 1064 { 800 1065 if(y>=1) … … 803 1068 } 804 1069 MB=maxideal(1); 805 intvec rw; 806 list LL=substpart(MB,ihp,0,rw); 1070 intvec rw; 1071 list LL=substpart(MB,ihp,0,rw); 807 1072 def newR5=LL[1]; 808 1073 setring newR5; … … 813 1078 export normap; 814 1079 result=newR5; 815 result[size(result)+1]= delt;1080 result[size(result)+1]=list(delt,delti); 816 1081 setring BAS; 817 1082 return(result); 818 1083 } 819 1084 820 //the one-dimensional case 821 //in this case it is a line because 822 //it is irreducible and homogeneous 823 if((dim(SM[1])==1)&&(attrib(SM[2],"isPrim")==1) 824 &&(homog(SM[2])==1)) 1085 // --- Trivial case: input ideal defines a line --- 1086 //the one-dimensional, homogeneous case and degree 1 case 1087 if( (dim(SM[1])==1) && (maxdeg1(SM[2])==1) && (homog(SM[2])==1) ) 825 1088 { 826 1089 if(y>=1) … … 839 1102 export normap; 840 1103 result=newR4; 841 result[size(result)+1]= delt;1104 result[size(result)+1]=list(delt,delti); 842 1105 setring BAS; 843 1106 return(result); 844 1107 } 845 1108 1109 //---------------------- The non-trivial cases start ------------------- 846 1110 //the higher dimensional case 847 //we test first of all CohenMacaulay and848 //complete intersection 849 if( ((size(SM[2])+dim(SM[1]))==nvars(basering))&&(homog(SM[2])==1))850 { 851 //t est for complete intersection1111 //we test first hypersurface, CohenMacaulay and complete intersection 1112 1113 if( ((size(SM[2])+dim(SM[1])) == nvars(basering)) ) 1114 { 1115 //the test for complete intersection 852 1116 attrib(SM[2],"isCohenMacaulay",1); 853 1117 attrib(SM[2],"isCompleteIntersection",1); … … 858 1122 } 859 1123 } 860 if((attrib(SM[2],"onlySingularAtZero")==0)&&(size(i)==1)) 861 { 862 int tau=vdim(std(i+jacob(i))); 863 if(tau>=0) 864 { 865 execute("ring BASL="+charstr(BAS)+",("+varstr(BAS)+"),ds;"); 866 ideal i=imap(BAS,i); 867 int tauloc=vdim(std(i+jacob(i))); 868 setring BAS; 869 attrib(SM[2],"onlySingularAtZero",(tau==tauloc)); 870 kill BASL; 871 } 872 } 873 //compute the singular locus 874 if((attrib(SM[2],"onlySingularAtZero")==0)&&(size(#)==0)) 875 { 876 J=minor(jacob(SM[2]),nvars(basering)-dim(SM[1])); 877 if(y >=1 ) 878 { 879 "// SB of singular locus will be computed"; 880 } 881 ideal sin=J,SM[1]; 882 list JM=mstd(sin); 1124 if( size(SM[2]) == 1 ) 1125 { 1126 attrib(SM[2],"isHypersurface",1); 1127 if(y>=1) 1128 { 1129 "// the ideal is a hypersurface"; 1130 } 1131 } 1132 1133 //------------------- compute the singular locus ------------------- 1134 // Computation if singular locus is critical 1135 // Notation: J ideal of singular locus or (if given) containing it 1136 // JM = mstd(J) or maxideal(1),maxideal(1) 1137 // JM[1] SB of singular locus, JM[2] minbasis, dimJ = dim(JM[1]) 1138 // SM[1] SB of the input ideal i, SM[2] minbasis 1139 // Computation if singular locus is critical, because it determines the 1140 // size of the ring Hom_R(J,J). We only need a test ideal contained in J. 1141 1142 //----------------------- onlySingularAtZero ------------------------- 1143 if( attrib(SM[2],"onlySingularAtZero") ) 1144 { 1145 JM = maxideal(1),maxideal(1); 1146 attrib(JM[1],"isSB",1); 1147 attrib(JM[2],"isRadical",1); 1148 if( dim(SM[1]) >=2 ) 1149 { 1150 attrib(SM[2],"isRegInCodim2",1); 1151 } 1152 } 1153 1154 //-------------------- not onlySingularAtZero ------------------------- 1155 if( attrib(SM[2],"onlySingularAtZero") == 0 ) 1156 { 1157 //--- the case where an ideal #[1] is given: 1158 if( size(#)>0 ) 1159 { 1160 J = #[1],SM[2]; 1161 JM = mstd(J); 1162 if( typeof(attrib(#[1],"isRadical"))!="int" ) 1163 { 1164 attrib(JM[2],"isRadical",0); 1165 } 1166 } 1167 1168 //--- the case where an ideal #[1] is not given: 1169 if( (size(#)==0) ) 1170 { 1171 if(y >=1 ) 1172 { 1173 "// singular locus will be computed"; 1174 } 1175 1176 J = SM[1],minor(jacob(SM[2]),nvars(basering)-dim(SM[1]),SM[1]); 1177 if( y >=1 ) 1178 { 1179 "// SB of singular locus will be computed"; 1180 } 1181 JM = mstd(J); 1182 } 1183 1184 int dimJ = dim(JM[1]); 883 1185 attrib(JM[1],"isSB",1); 884 885 //JM[1] SB of singular locus, JM[2]=minbasis of singular locus 886 //SM[1] SB of the input ideal, SM[2] minbasis 887 if(y>=1) 888 { 889 "// the dimension of the singular locus is:";""; 890 dim(JM[1]); ""; 891 } 892 893 if(dim(JM[1])==-1) 1186 if( y>=1 ) 1187 { 1188 "// the dimension of the singular locus is"; dimJ ; ""; 1189 } 1190 1191 if(dim(JM[1]) <= dim(SM[1])-2) 1192 { 1193 attrib(SM[2],"isRegInCodim2",1); 1194 } 1195 1196 //------------------ the smooth case, RETURN ------------------- 1197 if( dimJ == -1 ) 894 1198 { 895 1199 if(y>=1) … … 908 1212 export normap; 909 1213 result=newR3; 910 result[size(result)+1]= delt;1214 result[size(result)+1]=list(delt,delti); 911 1215 setring BAS; 912 1216 return(result); 913 1217 } 914 if(dim(JM[1])==0) 915 { 916 attrib(SM[2],"isIsolatedSingularity",1); 917 if(homog(SM[2])){attrib(SM[2],"onlySingularAtZero",1);} 918 } 919 if(dim(JM[1])<=dim(SM[1])-2) 920 { 921 attrib(SM[2],"isRegInCodim2",1); 922 } 923 } 924 else 925 { 926 if(size(#)==0) 927 { 928 list JM=maxideal(1),maxideal(1); 929 930 attrib(JM[1],"isSB",1); 931 if(dim(SM[1])>=2){attrib(SM[2],"isRegInCodim2",1);} 932 } 933 } 934 if((attrib(SM[2],"isRegInCodim2")==1)&&(attrib(SM[2],"isCohenMacaulay")==1)) 1218 1219 //------- extra check for onlySingularAtZero, relatively cheap ---------- 1220 //it uses the procedure 'locAtZero' from for testing 1221 //if an ideal is concentrated at 0 1222 if(y>=1) 1223 { 1224 "// extra test for onlySingularAtZero:"; 1225 } 1226 if ( locAtZero(JM[1]) ) 1227 { 1228 attrib(SM[2],"onlySingularAtZero",1); 1229 JM = maxideal(1),maxideal(1); 1230 attrib(JM[1],"isSB",1); 1231 attrib(JM[2],"isRadical",1); 1232 } 1233 else 1234 { 1235 attrib(SM[2],"onlySingularAtZero",0); 1236 } 1237 } 1238 1239 //displaying the attributes: 1240 if(y>=2) 1241 { 1242 "// the attributes of the ideal are:"; 1243 "// isCohenMacaulay:", attrib(SM[2],"isCohenMacaulay"); 1244 "// isCompleteIntersection:", attrib(SM[2],"isCompleteIntersection"); 1245 "// isHypersurface:", attrib(SM[2],"isHypersurface"); 1246 "// isEquidimensional:", attrib(SM[2],"isEquidimensional"); 1247 "// isPrim:", attrib(SM[2],"isPrim"); 1248 "// isRegInCodim2:", attrib(SM[2],"isRegInCodim2"); 1249 "// isIsolatedSingularity:", attrib(SM[2],"isIsolatedSingularity"); 1250 "// onlySingularAtZero:", attrib(SM[2],"onlySingularAtZero"); 1251 "// isRad:", attrib(SM[2],"isRad");""; 1252 } 1253 1254 //------------- case: CohenMacaulay in codim 2, RETURN --------------- 1255 if( (attrib(SM[2],"isRegInCodim2")==1) && 1256 (attrib(SM[2],"isCohenMacaulay")==1) ) 935 1257 { 936 1258 if(y>=1) 937 1259 { 938 "// the ideal was CohenMacaulay and regular in codimension 2";1260 "// the ideal was CohenMacaulay and regular in codim 2, hence normal"; 939 1261 } 940 1262 MB=SM[2]; … … 949 1271 export normap; 950 1272 result=newR6; 951 result[size(result)+1]= delt;1273 result[size(result)+1]=list(delt,delti); 952 1274 setring BAS; 953 1275 return(result); 954 1276 } 955 1277 956 //if it is an isolated singularity only at 0 things are easier 957 //JM ideal of singular locus, SM ideal of variety 958 if(attrib(SM[2],"onlySingularAtZero")) 959 { 1278 //---------- case: isolated singularity only at 0, RETURN ------------ 1279 // In this case things are easier, we can use the maximal ideal as radical 1280 // of the singular locus; 1281 // JM mstd of ideal of singular locus, SM mstd of input ideal 1282 1283 if( attrib(SM[2],"onlySingularAtZero") ) 1284 { 1285 //------ check variables for being a non zero-divizor ------ 1286 // SL = ideal of vars not contained in ideal SM[1]: 1287 960 1288 attrib(SM[2],"isIsolatedSingularity",1); 961 ideal SL=simplify(reduce(maxideal(1),SM[1]),2); 962 //vars not contained in ideal 963 ideal Ann=quotient(SM[2],SL[1]); 964 ideal qAnn=simplify(reduce(Ann,SM[1]),2); 965 //qAnn=0 ==> the first var(=SL[1]) not contained in SM is a nzd of R/SM 966 if(size(qAnn)==0) 1289 ideal SL = simplify(reduce(maxideal(1),SM[1]),2); 1290 ideal Ann = quotient(SM[2],SL[1]); 1291 ideal qAnn = simplify(reduce(Ann,SM[1]),2); 1292 //NOTE: qAnn=0 iff first var (=SL[1]) not in SM is a nzd of R/SM 1293 1294 //------------- We found a non-zerodivisor of R/SM ----------------------- 1295 // here the enlarging of the ring via Hom_R(J,J) starts 1296 1297 if( size(qAnn)==0 ) 967 1298 { 968 1299 if(y>=1) 969 1300 { 970 1301 ""; 971 "// the ideal rad(J):";1302 "// the ideal rad(J):"; maxideal(1); 972 1303 ""; 973 maxideal(1);974 newline;975 1304 } 976 //again test for normality 977 //Hom(I,R)=R 1305 1306 // ------------- test for normality, compute Hom_R(J,J) ------------- 1307 // Note: 1308 // HomJJ (ideal SBid, ideal id, ideal J, poly p) with 1309 // SBid = SB of id, J = radical ideal of basering P with: 1310 // nonNormal(R) is in V(J), J contains the nonzero divisor p 1311 // of R = P/id (J = test ideal) 1312 // returns a list l of three objects 1313 // l[1] : a polynomial ring, containing two ideals, 'endid' and 'endphi' 1314 // s.t. l[1]/endid = Hom_R(J,J) and endphi= map R -> Hom_R(J,J) 1315 // l[2] : an integer which is 1 if phi is an isomorphism, 0 if not 1316 // l[3] : an integer, = dim_K(Hom_R(J,J)/R) if finite, -1 otherwise 1317 978 1318 list RR; 979 RR=SM[1],SM[2],maxideal(1),SL[1]; 980 981 RR=HomJJ(RR,y); 982 if(RR[2]==0) 1319 RR = SM[1],SM[2],maxideal(1),SL[1]; 1320 RR = HomJJ(RR,y); 1321 // --------------------- non-normal case ------------------ 1322 //RR[2]==0 means that the test for normality is negative 1323 if( RR[2]==0 ) 983 1324 { 984 1325 def newR=RR[1]; 985 1326 setring newR; 986 1327 map psi=BAS,endphi; 987 list tluser=normalizationPrimes(endid,psi(ihp),delt+RR[3],an); 988 setring BAS; 989 return(tluser); 1328 list JM = psi(JM); //### 1329 ideal J = JM[2]; 1330 if ( delt>=0 && RR[3]>=0 ) 1331 { 1332 delt = delt+RR[3]; 1333 } 1334 else 1335 { delt = -1; } 1336 delti[size(delti)]=delt; 1337 1338 // ---------- recursive call of normalizationPrimes ----------- 1339 //normalizationPrimes(ideal i,ideal ihp,int delt,intvec delti,list #) 1340 //ihp = (partial) normalisation map from basering 1341 //#[1] ideal s.t. V(#[1]) contains singular locus of i (test ideal) 1342 1343 if ( y>=1 ) 1344 { 1345 "// case: onlySingularAtZero, non-zerodivisor found"; 1346 "// contribution of delta in ringextension R -> Hom_R(J,J):"; delt; 1347 } 1348 1349 //intvec atr=getAttrib(endid); 1350 //"//### case: isolated singularity only at 0, recursive"; 1351 //"size endid:", size(endid), size(string(endid)); 1352 //"interred:"; 1353 //endid = interred(endid); 1354 //endid = setAttrib(endid,atr); 1355 //"size endid:", size(endid), size(string(endid)); 1356 1357 printlevel=printlevel+1; 1358 list tluser = 1359 normalizationPrimes(endid,psi(ihp),delt,delti); 1360 //list tluser = 1361 // normalizationPrimes(endid,psi(ihp),delt,delti,J); 1362 //#### ??? improvement: give also the old ideal of sing locus??? 1363 1364 printlevel = printlev; //reset printlevel 1365 setring BAS; 1366 return(tluser); 990 1367 } 1368 1369 // ------------------ the normal case, RETURN ----------------- 1370 // Now RR[2] must be 1, hence the test for normality was positive 991 1371 MB=SM[2]; 992 execute("ring newR7="+charstr(basering)+",("+varstr(basering)+"),(" 993 +ordstr(basering)+");"); 1372 //execute("ring newR7="+charstr(basering)+",("+varstr(basering)+"),(" 1373 // +ordstr(basering)+");"); 1374 def newR7 = ring(gnirlist); 1375 setring newR7; 994 1376 ideal norid=fetch(BAS,MB); 995 1377 ideal normap=fetch(BAS,ihp); 996 delt=delt+RR[3]; 1378 if ( delt>=0 && RR[3]>=0 ) 1379 { 1380 delt = delt+RR[3]; 1381 } 1382 else 1383 { delt = -1; } 1384 delti[size(delti)]=delt; 1385 1386 intvec atr = getAttrib(norid); 1387 1388 //"//### case: isolated singularity only at 0, final"; 1389 //"size norid:", size(norid), size(string(norid)); 1390 //"interred:"; 1391 //norid = interred(norid); 1392 //norid = setAttrib(norid,atr); 1393 //"size norid:", size(norid), size(string(norid)); 1394 997 1395 export norid; 998 1396 export normap; 999 1397 result=newR7; 1000 result[size(result)+1]= delt;1398 result[size(result)+1]=list(delt,delti); 1001 1399 setring BAS; 1002 1400 return(result); 1003 1004 } 1005 //Now the case where qAnn!=0, i.e.SL[1] is a zero divisor of R/SM 1006 //and we have found a splitting: id and id1 1007 //id=Ann defines components of R/SM in the complement of V(SL[1]) 1008 //id1 defines components of R/SM in the complement of V(id) 1009 else 1401 } 1402 1403 //------ zerodivisor of R/SM was found, gives a splitting ------------ 1404 //Now the case where qAnn!=0, i.e. SL[1] is a zero divisor of R/SM 1405 //and we have found a splitting: id and id1 1406 //id = Ann defines components of R/SM in the complement of V(SL[1]) 1407 //id1 defines components of R/SM in the complement of V(id) 1408 1409 else 1010 1410 { 1011 ideal id =Ann;1411 ideal id = Ann; 1012 1412 attrib(id,"isCohenMacaulay",0); 1013 1413 attrib(id,"isPrim",0); 1014 1414 attrib(id,"isIsolatedSingularity",1); 1015 1415 attrib(id,"isRegInCodim2",0); 1416 attrib(id,"isHypersurface",0); 1016 1417 attrib(id,"isCompleteIntersection",0); 1017 1418 attrib(id,"isEquidimensional",0); 1018 1419 attrib(id,"onlySingularAtZero",1); 1019 1420 1020 ideal id1=quotient(SM[2],Ann); 1021 //ideal id=SL[1],SM[2]; 1421 ideal id1 = quotient(SM[2],Ann); 1022 1422 attrib(id1,"isCohenMacaulay",0); 1023 1423 attrib(id1,"isPrim",0); 1024 1424 attrib(id1,"isIsolatedSingularity",1); 1025 1425 attrib(id1,"isRegInCodim2",0); 1426 attrib(id1,"isHypersurface",0); 1026 1427 attrib(id1,"isCompleteIntersection",0); 1027 1428 attrib(id1,"isEquidimensional",0); 1028 1429 attrib(id1,"onlySingularAtZero",1); 1029 1430 1030 ideal t1=id,id1; 1031 int mul=vdim(std(t1)); 1032 kill t1; 1033 1034 keepresult1=normalizationPrimes(id,ihp,0); 1035 1036 keepresult2=normalizationPrimes(id1,ihp,0); 1037 1038 delt=delt+mul+keepresult1[size(keepresult1)] 1039 +keepresult1[size(keepresult1)]; 1040 1431 // ---------- recursive call of normalizationPrimes ----------- 1432 if ( y>=1 ) 1433 { 1434 "// case: onlySingularAtZero, zerodivisor found, splitting:"; 1435 "// total delta before splitting:", delt; 1436 "// splitting in two components:"; 1437 } 1438 1439 printlevel = printlevel+1; //to see comments in normalizationPrimes 1440 keepresult1 = normalizationPrimes(id,ihp,0,0); //1st split factor 1441 keepresult2 = normalizationPrimes(id1,ihp,0,0); //2nd split factor 1442 printlevel = printlev; //reset printlevel 1443 1444 int delt1 = keepresult1[size(keepresult1)][1]; 1445 int delt2 = keepresult2[size(keepresult2)][1]; 1446 intvec delti1 = keepresult1[size(keepresult1)][2]; 1447 intvec delti2 = keepresult2[size(keepresult2)][2]; 1448 1449 if( delt>=0 && delt1>=0 && delt2>=0 ) 1450 { ideal idid1=id,id1; 1451 int mul = vdim(std(idid1)); 1452 if ( mul>=0 ) 1453 { 1454 delt = delt+mul+delt1+delt2; 1455 } 1456 else 1457 { 1458 delt = -1; 1459 } 1460 } 1461 if ( y>=1 ) 1462 { 1463 "// delta of first component:", delt1; 1464 "// delta of second componenet:", delt2; 1465 "// intersection multiplicity of both components:", mul; 1466 "// total delta after splitting:", delt; 1467 } 1468 1469 else 1470 { 1471 delt = -1; 1472 } 1041 1473 for(lauf=1;lauf<=size(keepresult2)-1;lauf++) 1042 1474 { 1043 1475 keepresult1=insert(keepresult1,keepresult2[lauf]); 1044 1476 } 1045 keepresult1[size(keepresult1)]=delt; 1477 keepresult1[size(keepresult1)]=list(delt,delti); 1478 1046 1479 return(keepresult1); 1047 1480 } 1048 1481 } 1049 1050 //test for non-normality 1051 //Hom(I,I)<>R 1482 // Case "onlySingularAtZero" has finished and returned result 1483 1484 //-------------- General case, not onlySingularAtZero, RETURN --------------- 1485 //test for non-normality, i.e. if Hom(I,I)<>R 1052 1486 //we can use Hom(I,I) to continue 1053 ideal SL=simplify(reduce(JM[2],SM[1]),2); 1054 ideal Ann=quotient(SM[2],SL[1]); 1055 ideal qAnn=simplify(reduce(Ann,SM[1]),2); 1056 1057 if(size(qAnn)==0) 1487 1488 //------ check variables for being a non zero-divizor ------ 1489 // SL = ideal of vars not contained in ideal SM[1]: 1490 1491 ideal SL = simplify(reduce(JM[2],SM[1]),2); 1492 ideal Ann = quotient(SM[2],SL[1]); 1493 ideal qAnn = simplify(reduce(Ann,SM[1]),2); 1494 //NOTE: qAnn=0 <==> first var (=SL[1]) not contained in SM is a nzd of R/SM 1495 1496 //------------- We found a non-zerodivisor of R/SM ----------------------- 1497 //SM = mstd of ideal of variety, JM = mstd of ideal of singular locus 1498 1499 if( size(qAnn)==0 ) 1058 1500 { 1059 1501 list RR; 1060 1502 list RS; 1061 // now we have to compute the radical1503 // ----------------- Computation of the radical ----------------- 1062 1504 if(y>=1) 1063 1505 { 1064 1506 "// radical computation of singular locus"; 1065 1507 } 1066 J=radical(JM[2]); //the singular locus 1067 JM=mstd(J); 1068 1069 if((vdim(JM[1])==1)&&(size(reduce(J,std(maxideal(1))))==0)) 1070 { 1071 attrib(SM[2],"onlySingularAtZero",1); 1072 } 1508 J = radical(JM[2]); //the radical of singular locus 1509 JM = mstd(J); 1510 1073 1511 if(y>=1) 1074 1512 { 1075 "// radical is equal to:";""; 1076 J; 1513 "// radical is equal to:";""; JM[2]; 1077 1514 ""; 1078 1515 } 1079 if(deg(SL[1])>deg(J[1])) 1516 // ------------ choose non-zerodivisor of smaller degree ---------- 1517 //### evtl. fuer SL[1] anderen Nichtnullteiler aus J waehlen ? 1518 if( deg(SL[1]) > deg(J[1]) ) 1080 1519 { 1081 1520 Ann=quotient(SM[2],J[1]); 1082 1521 qAnn=simplify(reduce(Ann,SM[1]),2); 1083 if(size(qAnn)==0){SL[1]=J[1];} 1084 } 1085 1086 //evtl. fuer SL[1] anderen Nichtnullteiler aus J waehlen 1522 if(size(qAnn)==0) 1523 { 1524 SL[1]=J[1]; 1525 } 1526 } 1527 1528 // --------------- computation of Hom(rad(J),rad(J)) -------------- 1087 1529 RR=SM[1],SM[2],JM[2],SL[1]; 1088 1530 1089 // evtl eine geeignete Potenz von JM?1090 1531 if(y>=1) 1091 1532 { … … 1093 1534 } 1094 1535 1095 RS=HomJJ(RR,y); 1096 1097 if(RS[2]==1) 1098 { 1536 RS=HomJJ(RR,y); //most important subprocedure 1537 1538 // ------------------ the normal case, RETURN ----------------- 1539 // RS[2]==1 means that the test for normality was positive 1540 if(RS[2]==1) 1541 { 1099 1542 def lastR=RS[1]; 1100 1543 setring lastR; … … 1103 1546 ideal normap=psi1(ihp); 1104 1547 kill endid,endphi; 1548 1549 intvec atr=getAttrib(norid); 1550 1551 //"//### general case: not isolated singularity only at 0, final"; 1552 //"size norid:", size(norid), size(string(norid)); 1553 //"interred:"; 1554 //norid = interred(norid); 1555 //norid = setAttrib(norid,atr); 1556 //"size norid:", size(norid), size(string(norid)); 1557 1105 1558 export norid; 1106 1559 export normap; 1107 1560 result=lastR; 1108 result[size(result)+1]=delt+RS[3]; 1561 if ( y>=1 ) 1562 { 1563 "// case: not onlySingularAtZero, last ring Hom_R(J,J) computed"; 1564 "// delta before last ring:", delt; 1565 } 1566 1567 if ( delt>=0 && RS[3]>=0 ) 1568 { 1569 delt = delt+RS[3]; 1570 } 1571 else 1572 { delt = -1; } 1573 1574 // delti = delti,delt; 1575 delti[size(delti)]=delt; 1576 1577 if ( y>=1 ) 1578 { 1579 "// delta of last ring:", delt; 1580 } 1581 1582 result[size(result)+1]=list(delt,delti); 1109 1583 setring BAS; 1110 1584 return(result); 1111 } 1112 int n=nvars(basering); 1113 ideal MJ=JM[2]; 1585 } 1586 1587 // ----- the non-normal case, recursive call of normalizationPrimes ------- 1588 // RS=HomJJ(RR,y) was computed above, RS[1] contains endid and endphi 1589 // RS[1] = new ring Hom_R(J,J), RS[2]= 0 or 1, RS[2]=contribution to delta 1590 // now RS[2]must be 0, i.e. the test for normality was negative 1591 1592 int n = nvars(basering); 1593 ideal MJ = JM[2]; 1114 1594 1115 1595 def newR=RS[1]; 1116 1596 setring newR; 1117 1118 1597 map psi=BAS,endphi; 1598 if ( y>=1 ) 1599 { 1600 "// case: not onlySingularAtZero, compute new ring = Hom_R(J,J)"; 1601 "// delta of old ring:", delt; 1602 } 1603 if ( delt>=0 && RS[3]>=0 ) 1604 { 1605 delt = delt+RS[3]; 1606 } 1607 else 1608 { delt = -1; } 1609 if ( y>=1 ) 1610 { 1611 "// delta of new ring:", delt; 1612 } 1613 1614 delti[size(delti)]=delt; 1615 intvec atr=getAttrib(endid); 1616 1617 //"//### general case: not isolated singularity only at 0, recursive"; 1618 //"size endid:", size(endid), size(string(endid)); 1619 //"interred:"; 1620 //endid = interred(endid); 1621 //endid = setAttrib(endid,atr); 1622 //"size endid:", size(endid), size(string(endid)); 1623 1624 printlevel = printlevel+1; 1119 1625 list tluser= 1120 normalizationPrimes(endid,psi(ihp),delt+RS[3],psi(MJ)); 1626 normalizationPrimes(endid,psi(ihp),delt,delti,psi(MJ)); 1627 printlevel = printlev; //reset printlevel 1121 1628 setring BAS; 1122 1629 return(tluser); 1123 1630 } 1124 // A component with singular locus the whole component found 1631 1632 //---- A whole singular component was found, RETURN ----- 1125 1633 if( Ann == 1) 1126 1634 { … … 1141 1649 export normap; 1142 1650 result=newR6; 1143 result[size(result)+1]= delt;1651 result[size(result)+1]=lst(delt,delti); 1144 1652 setring BAS; 1145 1653 return(result); 1146 1654 } 1655 1656 //------ zerodivisor of R/SM was found, gives a splitting ------------ 1657 //Now the case where qAnn!=0, i.e. SL[1] is a zero divisor of R/SM 1658 //and we have found a splitting: new1 and new2 1659 //id = Ann defines components of R/SM in the complement of V(SL[1]) 1660 //id1 defines components of R/SM in the complement of V(id) 1661 1147 1662 else 1148 1663 { 1149 int equi=attrib(SM[2],"isEquidimensional"); 1150 int oSAZ=attrib(SM[2],"onlySingularAtZero"); 1151 int isIs=attrib(SM[2],"isIsolatedSingularity"); 1152 1153 ideal new1=Ann; 1154 ideal new2=quotient(SM[2],Ann); 1664 if(y>=1) 1665 { 1666 "// zero-divisor found"; 1667 } 1668 int equi = attrib(SM[2],"isEquidimensional"); 1669 int oSAZ = attrib(SM[2],"onlySingularAtZero"); 1670 int isIs = attrib(SM[2],"isIsolatedSingularity"); 1671 1672 ideal new1 = Ann; 1673 ideal new2 = quotient(SM[2],Ann); 1155 1674 //ideal new2=SL[1],SM[2]; 1156 1675 1157 int mul; 1158 if(equi&&isIs) 1159 { 1160 ideal t2=new1,new2; 1161 mul=vdim(std(t2)); 1162 } 1163 execute("ring newR1="+charstr(basering)+",("+varstr(basering)+"),(" 1164 +ordstr(basering)+");"); 1165 if(y>=1) 1166 { 1167 "// zero-divisor found"; 1168 } 1169 ideal vid=fetch(BAS,new1); 1170 ideal ihp=fetch(BAS,ihp); 1676 //execute("ring newR1="+charstr(basering)+",("+varstr(basering)+"),(" 1677 // +ordstr(basering)+");"); 1678 def newR1 = ring(gnirlist); 1679 setring newR1; 1680 1681 ideal vid = fetch(BAS,new1); 1682 ideal ihp = fetch(BAS,ihp); 1171 1683 attrib(vid,"isCohenMacaulay",0); 1172 1684 attrib(vid,"isPrim",0); … … 1175 1687 attrib(vid,"onlySingularAtZero",oSAZ); 1176 1688 attrib(vid,"isEquidimensional",equi); 1689 attrib(vid,"isHypersurface",0); 1177 1690 attrib(vid,"isCompleteIntersection",0); 1178 1691 1179 keepresult1=normalizationPrimes(vid,ihp,0); 1180 int delta1=keepresult1[size(keepresult1)]; 1692 // ---------- recursive call of normalizationPrimes ----------- 1693 if ( y>=1 ) 1694 { 1695 "// total delta before splitting:", delt; 1696 "// splitting in two components:"; 1697 } 1698 printlevel = printlevel+1; 1699 keepresult1 = 1700 normalizationPrimes(vid,ihp,0,0); //1st split factor 1701 1702 list delta1 = keepresult1[size(keepresult1)]; 1703 1181 1704 setring BAS; 1182 1183 execute("ring newR2="+charstr(basering)+",("+varstr(basering)+"),(" 1184 +ordstr(basering)+");"); 1185 1186 ideal vid=fetch(BAS,new2); 1187 ideal ihp=fetch(BAS,ihp); 1705 //execute("ring newR2="+charstr(basering)+",("+varstr(basering)+"),(" 1706 // +ordstr(basering)+");"); 1707 def newR2 = ring(gnirlist); 1708 setring newR2; 1709 1710 ideal vid = fetch(BAS,new2); 1711 ideal ihp = fetch(BAS,ihp); 1188 1712 attrib(vid,"isCohenMacaulay",0); 1189 1713 attrib(vid,"isPrim",0); … … 1191 1715 attrib(vid,"isRegInCodim2",0); 1192 1716 attrib(vid,"isEquidimensional",equi); 1717 attrib(vid,"isHypersurface",0); 1193 1718 attrib(vid,"isCompleteIntersection",0); 1194 1719 attrib(vid,"onlySingularAtZero",oSAZ); 1195 1720 1196 keepresult2=normalizationPrimes(vid,ihp,0); 1197 int delta2=keepresult2[size(keepresult2)]; 1198 1721 keepresult2 = 1722 normalizationPrimes(vid,ihp,0,0); 1723 list delta2 = keepresult2[size(keepresult2)]; //2nd split factor 1724 printlevel = printlev; //reset printlevel 1725 1199 1726 setring BAS; 1200 1727 1728 //compute intersection multiplicity of both components: 1729 new1 = new1,new2; 1730 int mul=vdim(std(new1)); 1731 1732 // ----- normalizationPrimes finished, add up results, RETURN -------- 1201 1733 for(lauf=1;lauf<=size(keepresult2)-1;lauf++) 1202 1734 { 1203 keepresult1=insert(keepresult1,keepresult2[lauf]); 1204 } 1205 keepresult1[size(keepresult1)]=delt+mul+delta1+delta2; 1735 keepresult1 = insert(keepresult1,keepresult2[lauf]); 1736 } 1737 if ( delt >=0 && delta1[1] >=0 && delta2[1] >=0 && mul >=0 ) 1738 { 1739 delt = delt+mul+delta1[1]+delta2[1]; 1740 } 1741 else 1742 { delt = -1; } 1743 delti = -2; 1744 1745 if ( y>=1 ) 1746 { 1747 "// zero divisor produced a splitting into two components"; 1748 "// delta of first component:", delta1; 1749 "// delta of second componenet:", delta2; 1750 "// intersection multiplicity of both components:", mul; 1751 "// total delta after splitting:", delt; 1752 } 1753 keepresult1[size(keepresult1)] = list(delt,delti); 1206 1754 return(keepresult1); 1207 1755 } … … 1222 1770 1223 1771 list pr=normalizationPrimes(i); 1224 def r1 =pr[1];1772 def r1 = pr[1]; 1225 1773 setring r1; 1226 1774 norid; 1227 1775 normap; 1228 1776 } 1777 1229 1778 /////////////////////////////////////////////////////////////////////////////// 1230 proc substpart(ideal endid, ideal endphi, int homo, intvec rw)1779 static proc substpart(ideal endid, ideal endphi, int homo, intvec rw) 1231 1780 1232 1781 "//Repeated application of elimpart to endid, until no variables can be … … 1234 1783 //original weights, endphi (partial) normalization map"; 1235 1784 1785 //NOTE concerning iteration of maps: Let phi: x->f(y,z), y->g(x,z) then 1786 //phi: x+y+z->f(y,z)+g(x,z)+z, phi(phi):x+y+z->f(g(x,z),z)+g(f(y,z),z)+z 1787 //and so on: none of the x or y will be eliminated 1788 //Now subst: first x and then y: x+y+z->f(g(x,z),z)+g(x,z)+z eliminates y 1789 //further subst replaces x by y, makes no sense (objects more compicated). 1790 //Subst first y and then x eliminates x 1791 //In our situation we have triangular form: x->f(y,z), y->g(z). 1792 //phi: x+y+z->f(y,z)+g(z)+z, phi(phi):x+y+z->f(g(z),z)+g(z)+z eliminates x,y 1793 //subst x,y: x+y+z->f(g(z),z)+g(z)+z, eliminates x,y 1794 //subst y,x: x+y+z->f(y,z)+g(z)+z eliminates only x 1795 //HENCE: substitute vars depending on most other vars first 1796 //However, if the sytem xi-fi is reduced then xi does not appear in any of the 1797 //fj and hence the order does'nt matter when substitutinp xi by fi 1798 1236 1799 { 1237 def newRing =basering;1800 def newRing = basering; 1238 1801 int ii,jj; 1239 map phi = basering,maxideal(1); 1240 1802 map phi = newRing,maxideal(1); //identity map 1241 1803 list Le = elimpart(endid); 1242 //this proc and the next loop try to 1243 int q = size(Le[2]); //substitute as many variables as possible 1244 intvec rw1 = 0; //indices of substituted variables 1804 //this proc and the next loop try to substitute as many variables as 1805 //possible indices of substituted variables 1806 1807 int q = size(Le[2]); //q vars, stored in Le[2], have been substitutet 1808 intvec rw1 = 0; //will become indices of substituted variables 1245 1809 rw1[nvars(basering)] = 0; 1246 rw1 = rw1+1; 1810 rw1 = rw1+1; //rw1=1,..,1 (as many 1 as nvars(basering)) 1247 1811 1248 1812 while( size(Le[2]) != 0 ) 1249 1813 { 1250 1814 endid = Le[1]; 1815 if ( defined(ps) ) 1816 { kill ps; } 1251 1817 map ps = newRing,Le[5]; 1252 1253 1818 phi = ps(phi); 1254 for(ii=1;ii<=size(Le[2]) -1;ii++)1819 for(ii=1;ii<=size(Le[2]);ii++) 1255 1820 { 1256 1821 phi=phi(phi); 1257 1822 } 1258 1823 //eingefuegt wegen x2-y2z2+z3 1259 kill ps;1260 1824 1261 1825 for( ii=1; ii<=size(rw1); ii++ ) 1262 1826 { 1263 if( Le[4][ii]==0 ) 1827 if( Le[4][ii]==0 ) //ii = index of var which was substituted 1264 1828 { 1265 rw1[ii]=0; //look for substituted vars1829 rw1[ii]=0; //substituted vars have entry 0 in rw1 1266 1830 } 1267 1831 } 1268 Le=elimpart(endid); 1832 Le=elimpart(endid); //repeated application of elimpart 1269 1833 q = q + size(Le[2]); 1270 1834 } 1271 1835 endphi = phi(endphi); 1272 1273 1836 //---------- return ----------------------------------------------------------- 1837 // first the trivial case, where all variable have been eliminated 1838 if( nvars(newRing) == q ) 1839 { 1840 ring lastRing = char(basering),T(1),dp; 1841 ideal endid = T(1); 1842 ideal endphi = T(1); 1843 for(ii=2; ii<=q; ii++ ) 1844 { 1845 endphi[ii] = 0; 1846 } 1847 export(endid,endphi); 1848 list L = lastRing; 1849 setring newRing; 1850 return(L); 1851 } 1852 1274 1853 // in the homogeneous case put weights for the remaining vars correctly, i.e. 1275 1854 // delete from rw those weights for which the corresponding entry of rw1 is 0 … … 1296 1875 ring lastRing = char(basering),(T(1..nvars(newRing)-q)),dp; 1297 1876 } 1298 1299 1877 ideal lastmap; 1300 q = 1; 1878 jj = 1; 1879 1301 1880 for(ii=1; ii<=size(rw1); ii++ ) 1302 1881 { 1303 if ( rw1[ii]==1 ) { lastmap[ii] = T( q); q=q+1; }1882 if ( rw1[ii]==1 ) { lastmap[ii] = T(jj); jj=jj+1; } 1304 1883 if ( rw1[ii]==0 ) { lastmap[ii] = 0; } 1305 1884 } 1306 1885 map phi1 = newRing,lastmap; 1307 ideal endid = phi1(endid); 1886 ideal endid = phi1(endid); //### bottelneck 1308 1887 ideal endphi = phi1(endphi); 1888 1889 /* 1890 Versuch: subst statt phi 1891 for(ii=1; ii<=size(rw1); ii++ ) 1892 { 1893 if ( rw1[ii]==1 ) { endid = subst(endid,var(ii),T(jj)); } 1894 if ( rw1[ii]==0 ) { endid = subst(endid,var(ii),0); } 1895 } 1896 */ 1309 1897 export(endid); 1310 1898 export(endphi); … … 1313 1901 return(L); 1314 1902 } 1315 ///////////////////////////////////////////////////////////////////////////// 1903 /////////////////////////////////////////////////////////////////////////////// 1316 1904 1317 1905 proc genus(ideal I,list #) 1318 "USAGE: genus( I) or genus(i,1); I a 1-dimensional ideal1906 "USAGE: genus(i) or genus(i,1); I a 1-dimensional ideal 1319 1907 RETURN: an integer, the geometric genus p_g = p_a - delta of the projective 1320 curve defined by I, where p_a is the arithmetic genus.1908 curve defined by i, where p_a is the arithmetic genus. 1321 1909 NOTE: delta is the sum of all local delta-invariants of the singularities, 1322 1910 i.e. dim(R'/R), R' the normalization of the local ring R of the 1323 singularity. 1324 genus(i,1) uses the normalization to compute delta. Usually this1325 is slow but sometimes not.1911 singularity. @* 1912 genus(i,1) uses the normalization to compute delta. Usually genus(i,1) 1913 is slower than genus(i) but sometimes not. 1326 1914 EXAMPLE: example genus; shows an example 1327 1915 " … … 1336 1924 { 1337 1925 // ERROR("This is not a curve"); 1338 if(w==1){" WARNING:This is not a curve";}1926 if(w==1){"** WARNING: Input does not define a curve **"; "";} 1339 1927 } 1340 1928 } … … 1357 1945 return(-deg(p)+1); 1358 1946 } 1359 if(size(N[1]) <nvars(R0))1947 if(size(N[1]) < nvars(R0)) 1360 1948 { 1361 1949 string newvar=string(N[1]); … … 1562 2150 if(size(#)!=0) 1563 2151 { //uses the normalization to compute delta 1564 list nor=normal(I ,"wd");1565 delt=nor[size(nor)] ;2152 list nor=normal(I); 2153 delt=nor[size(nor)][2]; 1566 2154 genus=genus-delt-deltainf; 1567 2155 setring R0; … … 1953 2541 "USAGE: primeClosure(L [,c]); L a list of a ring containing a prime ideal 1954 2542 ker, c an optional integer 1955 RETURN: a list L consisting of rings L[1],...,L[n] such that2543 RETURN: a list L (of size n+1) consisting of rings L[1],...,L[n] such that 1956 2544 - L[1] is a copy of (not a reference to!) the input ring L[1] 1957 2545 - all rings L[i] contain ideals ker, L[2],...,L[n] contain ideals phi … … 1963 2551 L[i]/ker are quotients of elements of L[i-1]/ker with denominator 1964 2552 nzd via the injection phi. 2553 L[n+1] is the delta invariant 1965 2554 NOTE: - L is constructed by recursive calls of primeClosure itself. 1966 2555 - c determines the choice of nzd: … … 1971 2560 " 1972 2561 { 1973 //Start with a consistency check:2562 //---- Start with a consistency check: 1974 2563 1975 2564 if (!(typeof(L[1])=="ring")) 1976 2565 { 1977 2566 "// Parameter must be a ring or a list containing a ring!"; 1978 2567 return(-1); 1979 } 1980 1981 int dblvl=printlevel-voice+2; 1982 1983 1984 // Some auxiliary variables: 1985 1986 int n=size(L); 1987 1988 // How to choose the non-zerodivisor later on? 2568 } 2569 2570 int dblvl = printlevel-voice+2; 2571 list gnirlist = ringlist(basering); 2572 2573 //---- Some auxiliary variables: 2574 int delt; //finally the delta invariant 2575 if ( size(L) == 1 ) 2576 { 2577 L[2] = delt; //set delta to 0 2578 } 2579 int n = size(L)-1; //L without delta invariant 2580 2581 //---- How to choose the non-zerodivisor later on? 1989 2582 1990 2583 int nzdoption=0; 1991 2584 if (size(#)>0) 1992 2585 { 1993 2586 nzdoption=#[1]; 1994 2587 } 1995 2588 1996 2589 // R0 is the ring to work with, if we are in step one, make a copy of the … … 1999 2592 2000 2593 if (n==1) 2001 { 2002 def R=L[1]; 2003 def BAS=basering; 2594 { 2595 def R = L[1]; 2596 list Rlist = ringlist(R); 2597 def BAS = basering; 2004 2598 setring R; 2005 2599 if (!(typeof(ker)=="ideal")) 2006 2600 { 2007 2601 "// No ideal ker in the input ring!"; 2008 2602 return (-1); 2009 2603 } 2010 2604 ker=simplify(interred(ker),15); 2011 execute ("ring R0="+charstr(R)+",("+varstr(R)+"),("+ordstr(R)+");"); 2605 //execute ("ring R0="+charstr(R)+",("+varstr(R)+"),("+ordstr(R)+");"); 2606 def R0 = ring(Rlist); 2607 setring R0; 2012 2608 ideal ker=fetch(R,ker); 2013 2609 … … 2019 2615 attrib(R0,"iso_sing_Rees",attrib(L[1],"iso_sing_Rees")); 2020 2616 } 2021 L =R0;2022 2617 L[1]=R0; 2618 } 2023 2619 else 2024 2025 def R0 =L[n];2620 { 2621 def R0 = L[n]; 2026 2622 setring R0; 2027 2623 } 2028 2624 2029 2625 … … 2031 2627 // locus of ker, J:=rad(ker): 2032 2628 2033 // if (homog(ker)==1) 2034 // { 2035 list SM=mstd(ker); 2036 // } 2037 /* else 2038 { 2039 list SM=groebner(ker),ker; 2040 }*/ 2629 list SM=mstd(ker); 2041 2630 2042 2631 // In the first iteration, we have to compute the singular locus "from 2043 // scratch". In further iterations, we can fetch it from the previous one but 2044 // have to compute its radical. 2045 2046 if (n==1) 2047 { 2632 // scratch". 2633 // In further iterations, we can fetch it from the previous one but 2634 // have to compute its radical 2635 // the next rings R1 contain already the (fetched) ideal 2636 2637 if (n==1) //we are in R0=L[1] 2638 { 2048 2639 if (typeof(attrib(R0,"iso_sing_Rees"))=="int") 2049 2640 { … … 2053 2644 J=J,var(s); 2054 2645 } 2646 J = J,SM[2]; 2647 list JM = mstd(J); 2055 2648 } 2056 2649 else 2057 2650 { 2058 ideal J=minor(jacob(SM[2]),nvars(basering)-dim(SM[1])); 2059 } 2060 J=J+SM[2]; 2061 if (homog(J)==1) 2062 { 2063 J=mstd(J)[2]; 2064 } 2065 J=radical(interred(J)); 2066 } 2651 if ( dblvl >= 1 ) 2652 {""; 2653 "// compute the singular locus"; 2654 } 2655 //### Berechnung des singulren Orts gendert (ist so schneller) 2656 ideal J = minor(jacob(SM[2]),nvars(basering)-dim(SM[1]),SM[1]); 2657 J = J,SM[2]; 2658 list JM = mstd(J); 2659 } 2660 2661 if ( dblvl >= 1 ) 2662 {""; 2663 "// dimension of singular locus is", dim(JM[1]); 2664 if ( dblvl >= 2 ) 2665 {""; 2666 "// the singular locus is:"; JM[2]; 2667 } 2668 } 2669 2670 if ( dblvl >= 1 ) 2671 {""; 2672 "// compute radical of singular locus"; 2673 } 2674 2675 J = simplify(radical(JM[2]),2); 2676 if ( dblvl >= 1 ) 2677 {""; 2678 "// radical of singular locus is:"; J; 2679 pause(); 2680 } 2681 } 2067 2682 else 2068 { 2069 J=radical(interred(J)); 2070 } 2071 2072 // having computed the radical J of the ideal of the singular locus, 2073 // we now need to pick an element nzd of J 2074 2075 poly nzd=J[1]; 2076 if (nzdoption) 2683 { 2684 if ( dblvl >= 1 ) 2685 {""; 2686 "// compute radical of test ideal in ideal of singular locus"; 2687 } 2688 J = simplify(radical(J),2); 2689 if ( dblvl >= 1 ) 2690 {""; 2691 "// radical of test ideal is:"; J; 2692 pause(); 2693 } 2694 } 2695 2696 // having computed the radical J of/in the ideal of the singular locus, 2697 // we now need to pick an element nzd of J; 2698 // NOTE: nzd must be a non-zero divisor mod ker, i.e. not contained in ker 2699 2700 poly nzd = J[1]; 2701 poly nzd1 = NF(nzd,SM[1]); 2702 if (nzd1 != 0) 2703 { 2704 if ( deg(nzd)>=deg(nzd1) && size(nzd)>size(nzd1) ) 2705 { 2706 nzd = nzd1; 2707 } 2708 } 2709 2710 if (nzdoption || nzd1==0) 2077 2711 { 2078 2712 for (int ii=2;ii<=ncols(J);ii++) 2079 2713 { 2080 if ( (deg(nzd)>=deg(J[ii])) && (size(nzd)>size(J[ii])) ) 2081 { 2082 nzd=J[ii]; 2714 nzd1 = NF(J[ii],SM[1]); 2715 if ( nzd1 != 0 ) 2716 { 2717 if ( (deg(nzd)>=deg(J[ii])) && (size(nzd)>size(J[ii])) ) 2718 { 2719 nzd=J[ii]; 2720 } 2721 if ( deg(nzd)>=deg(nzd1) && size(nzd)>size(nzd1) ) 2722 { 2723 nzd = nzd1; 2724 } 2083 2725 } 2084 2726 } … … 2086 2728 2087 2729 export nzd; 2088 list RR=SM[1],SM[2],J,nzd; 2089 list RS=HomJJ(RR); 2090 2091 2092 ////////////////////////////////////////////////////////////////////////////// 2093 2094 2730 list RR = SM[1],SM[2],J,nzd; 2731 2732 if ( dblvl >= 1 ) 2733 {""; 2734 "// compute the first ring extension:"; 2735 } 2736 2737 list RS = HomJJ(RR); 2738 2739 //------------------------------------------------------------------------- 2095 2740 // If we've reached the integral closure (as determined by the result of 2096 2741 // HomJJ), then we are done, otherwise we have to prepare the next iteration. 2097 2742 2098 if (RS[2]==1) // we've reached the integral closure2743 if (RS[2]==1) // we've reached the integral closure, we are still in R0 2099 2744 { 2100 2745 kill J; 2746 if ( n== 1) 2747 { 2748 def R1 = RS[1]; 2749 setring R1; 2750 ideal norid, normap = endid, endphi; 2751 kill endid, endphi; 2752 2753 //"//### case: primeClosure, final"; 2754 //"size norid:", size(norid), size(string(norid)); 2755 //"interred:"; 2756 //norid = interred(norid); 2757 //"size norid:", size(norid), size(string(norid)); 2758 2759 export (norid, normap); 2760 L[1] = R1; 2761 } 2101 2762 return(L); 2102 2763 } … … 2104 2765 { 2105 2766 if (n==1) // In the first iteration: keep only the data 2106 { // needed later on. 2107 kill RR,SM; 2108 2109 export(ker); 2110 } 2111 2112 def R1=RS[1]; // The data of the next ring R1: 2767 { // needed later on. 2768 kill RR,SM; 2769 export(ker); 2770 } 2771 if ( dblvl >= 1 ) 2772 {""; 2773 "// computing the next ring extension, we are in loop"; n+1; 2774 } 2775 2776 def R1 = RS[1]; // The data of the next ring R1: 2777 delt = RS[3]; // the delta invariant of the ring extension 2113 2778 setring R1; // keep only what is necessary and kill 2114 2779 ideal ker=endid; // everything else. 2115 2780 export(ker); 2116 2781 ideal norid=endid; 2782 2783 //"//### case: primeClosure, loop", n+1; 2784 //"size norid:", size(norid), size(string(norid)); 2785 //"interred:"; 2786 //norid = interred(norid); //???? 2787 //"size norid:", size(norid), size(string(norid)); 2788 2117 2789 export(norid); 2118 2790 kill endid; 2119 2791 2120 map phi =R0,endphi;// fetch the singular locus2121 ideal J =mstd(simplify(phi(J)+ker,4))[2];2792 map phi = R0,endphi; // fetch the singular locus 2793 ideal J = mstd(simplify(phi(J)+ker,4))[2]; // ideal J in R1 2122 2794 export(J); 2123 2795 if(n>1) … … 2131 2803 export(normap); 2132 2804 kill phi; // we save phi as ideal, not as map, so that 2133 ideal phi=endphi; 2805 ideal phi=endphi; // we have more flexibility in the ring names 2134 2806 kill endphi; // later on. 2135 2807 export(phi); 2136 2808 L=insert(L,R1,n); // Add the new ring R1 and go on with the 2809 // next iteration 2810 if ( L[size(L)] >= 0 && delt >= 0 ) 2811 { 2812 delt = L[size(L)] + delt; 2813 } 2814 else 2815 { 2816 delt = -1; 2817 } 2818 L[size(L)] = delt; 2819 2137 2820 if (size(#)>0) 2138 2821 { 2139 2822 return (primeClosure(L,#)); 2140 2823 } 2141 2824 else 2142 2825 { 2143 2826 return(primeClosure(L)); // next iteration. 2144 2827 } 2145 2828 } 2146 2829 } … … 2162 2845 } 2163 2846 2164 2165 ////////////////////////////////////////////////////////////////////////////// 2166 ////////////////////////////////////////////////////////////////////////////// 2167 2168 proc closureRingtower(list L) 2169 "USAGE: closureRingtower(list L); L a list of rings 2170 CREATE: rings R(1),...,R(n) such that R(i)=L[i] for all i 2171 EXAMPLE: example closureRingtower; shows an example 2172 " 2173 { 2174 int n=size(L); 2175 2176 for (int i=1;i<=n;i++) 2177 { 2178 if (defined(R(i))) { 2179 string s="Fixed name R("+string(i)+") leads to conflict with existing " 2180 +"object having this name"; 2181 ERROR(s); 2182 } 2183 def R(i)=L[i]; 2184 export R(i); 2185 } 2186 2187 return(); 2188 } 2189 example 2190 { 2191 "EXAMPLE:"; echo=2; 2192 ring R=0,(x,y),dp; 2193 ideal I=x4,y4; 2194 list L=primeClosure(ReesAlgebra(I)[1]); 2195 closureRingtower(L); 2196 R(1); 2197 R(4); 2198 kill R(1),R(2),R(3),R(4); 2199 } 2200 2201 ////////////////////////////////////////////////////////////////////////////// 2202 ////////////////////////////////////////////////////////////////////////////// 2847 /////////////////////////////////////////////////////////////////////////////// 2203 2848 2204 2849 proc closureFrac(list L) 2205 "USAGE: closureFrac (L); L a list as in the result of primeClosure, L[n]2206 containingan additional poly f2850 "USAGE: closureFrac (L); L a list of size n+1 as in the result of 2851 primeClosure, L[n] contains an additional poly f 2207 2852 CREATE: a list fraction of two elements of L[1], such that 2208 2853 f=fraction[1]/fraction[2] via the injections phi L[i]-->L[i+1]. … … 2212 2857 // Define some auxiliary variables: 2213 2858 2214 int n=size(L) ;2215 int j,k,l;2859 int n=size(L)-1; 2860 int i,j,k,l; 2216 2861 string mapstr; 2217 2218 for (int i=1;i<=n;i++) { def R(i)=L[i]; } 2862 for (i=1; i<=n; i++) { def R(i) = L[i]; } 2219 2863 2220 2864 // The quotient representing f is computed as in 'closureGenerators' with … … 2224 2868 // - we have to make sure that no more objects of the rings R(i) survive. 2225 2869 2226 for (j=1; j<=2;j++)2870 for (j=1; j<=2; j++) 2227 2871 { 2228 2872 setring R(n); 2229 2873 if (j==1) 2230 2231 2232 2874 { 2875 poly p=f; 2876 } 2233 2877 else 2234 { 2235 p=1; 2236 } 2237 2238 for (k=n;k>1;k--) 2239 { 2240 2878 { 2879 p=1; 2880 } 2881 2882 for (k=n; k>1; k--) 2883 { 2241 2884 if (j==1) 2242 2243 2244 2885 { 2886 map phimap=R(k-1),phi; 2887 } 2245 2888 2246 2889 p=p*phimap(nzd); … … 2252 2895 2253 2896 if (j==1) 2254 { 2255 execute ("ring S(k) = "+charstr(R(k))+",("+varstr(R(k))+", 2256 Z(1.."+string(ncols(phi))+")),(dp("+string(nvars(R(k))) 2257 +"),dp("+string(ncols(phi))+"));"); 2897 { 2898 //### noch abfragen ob Z(i) definiert ist 2899 list gnirlist = ringlist(R(k)); 2900 int n2 = size(gnirlist[2]); 2901 int n3 = size(gnirlist[3]); 2902 for( i=1; i<=ncols(phi); i++) 2903 { 2904 gnirlist[2][n2+i] = "Z("+string(i)+")"; 2905 } 2906 intvec V; 2907 V[ncols(phi)]=0; V=V+1; 2908 gnirlist[3] = insert(gnirlist[3],list("dp",V),n3-1); 2909 def S(k) = ring(gnirlist); 2910 setring S(k); 2911 2912 //execute ("ring S(k) = "+charstr(R(k))+",("+varstr(R(k))+", 2913 // Z(1.."+string(ncols(phi))+")),(dp("+string(nvars(R(k))) 2914 // +"),dp("+string(ncols(phi))+"));"); 2915 2258 2916 ideal phi = imap(R(k),phi); 2259 ideal J = imap (R(k),ker);2917 ideal J = imap (R(k),ker); 2260 2918 for (l=1;l<=ncols(phi);l++) 2261 2919 { 2262 2920 J=J+(Z(l)-phi[l]); 2263 2921 } 2264 2922 J=groebner(J); 2265 2923 poly h=NF(imap(R(k),p),J); 2266 2924 } 2267 2925 else 2268 2926 { 2269 2927 setring S(k); 2270 2928 h=NF(imap(R(k),p),J); 2271 2929 setring R(k); 2272 2930 kill p; 2273 2931 } 2274 2932 2275 2933 setring R(k-1); 2276 2934 2277 2935 if (j==1) 2278 { 2279 mapstr=" map backmap = S(k),"; 2280 for (l=1;l<=nvars(R(k));l++) 2281 { 2282 mapstr=mapstr+"0,"; 2283 } 2284 execute (mapstr+"maxideal(1);"); 2285 2936 { 2937 ideal maxi; 2938 maxi[nvars(R(k))] = 0; 2939 maxi = maxi,maxideal(1); 2940 map backmap = S(k),maxi; 2941 2942 //mapstr=" map backmap = S(k),"; 2943 //for (l=1;l<=nvars(R(k));l++) 2944 //{ 2945 // mapstr=mapstr+"0,"; 2946 //} 2947 //execute (mapstr+"maxideal(1);"); 2286 2948 poly p; 2287 2949 } 2288 2950 p=NF(backmap(h),std(ker)); 2289 2951 if (j==2) … … 2334 2996 } 2335 2997 2336 ////////////////////////////////////////////////////////////////////////////// 2337 ////////////////////////////////////////////////////////////////////////////// 2338 2339 static 2340 proc closureGenerators(list L); // called inside normalI 2998 /////////////////////////////////////////////////////////////////////////////// 2999 // closureGenerators is called inside proc normal (option "withGens" ) 3000 // 3001 3002 // INPUT is the output of proc primeClosure (except for the last element, the 3003 // delta invariant) : hence input is a list L consisting of rings 3004 // L[1],...,L[n] (denoted R(1)...R(n) below) such that 3005 // - L[1] is a copy of (not a reference to!) the input ring L[1] 3006 // - all rings L[i] contain ideals ker, L[2],...,L[n] contain ideals phi 3007 // such that 3008 // L[1]/ker --> ... --> L[n]/ker 3009 // are injections given by the corresponding ideals phi, and L[n]/ker 3010 // is the integral closure of L[1]/ker in its quotient field. 3011 // - all rings L[i] contain a polynomial nzd such that elements of 3012 // L[i]/ker are quotients of elements of L[i-1]/ker with denominator 3013 // nzd via the injection phi. 3014 3015 // COMPUTE: In the list L of rings R(1),...,R(n), compute representations of 3016 // the ring variables of the last ring R(n) as fractions of elements of R(1): 3017 // The proc returns an ideal preim s.t. preim[i]/preim[size(preim)] expresses 3018 // the ith variable of R(n) as fraction of elements of the basering R(1) 3019 // preim[size(preim)] is a non-zero divisor of basering/i. 3020 3021 proc closureGenerators(list L); 2341 3022 { 2342 // In the list L of rings R(1),...,R(n), compute representations of the ring 2343 // ring variables of the last ring R(n) as fractions of elements of R(1). 2344 2345 def Rees=basering; // when called inside normalI, the Rees 2346 // Algebra is the current basering. 2347 2348 // First of all we need some variable declarations... 2349 2350 list preimages; 2351 int n=size(L); // the number of rings R(1)-->...-->R(n) 3023 def Rees=basering; // when called inside normalI (in reesclos.lib) 3024 // the Rees Algebra is the current basering 3025 3026 // ------- First of all we need some variable declarations ----------- 3027 int n = size(L); // the number of rings R(1)-->...-->R(n) 3028 int length = nvars(L[n]); // the number of variables of the last ring 2352 3029 int j,k,l; 2353 int length=nvars(L[n]); // the number of variables of the last ring 2354 string mapstr; 2355 2356 for (int i=1;i<=n;i++) { def R(i)=L[i]; } 3030 string mapstr; 3031 list preimages; 3032 //Note: the empty list belongs to no ring, hence preimages can be used 3033 //later in R(1) 3034 //this is not possible for ideals (belong always to some ring) 3035 3036 for (int i=1; i<=n; i++) 3037 { 3038 def R(i)=L[i]; //give the rings from L a name 3039 } 2357 3040 2358 3041 // For each variable (counter j) and for each intermediate ring (counter k): … … 2360 3043 // Finally, do the same for nzd. 2361 3044 2362 for (j=1; j<=length+1;j++)2363 3045 for (j=1; j <= length+1; j++ ) 3046 { 2364 3047 setring R(n); 2365 2366 3048 if (j==1) 3049 { 3050 poly p; 3051 } 3052 if (j <= length ) 3053 { 3054 p=var(j); 3055 } 3056 else 3057 { 3058 p=1; 3059 } 3060 //i.e. p=j-th var of R(n) for j<=length and p=1 for j=length+1 3061 3062 for (k=n; k>1; k--) 3063 { 3064 3065 if (j==1) 2367 3066 { 2368 poly p; 2369 } 2370 2371 if (j<=nvars(R(n))) 2372 { 2373 p=var(j); 2374 } 2375 else 2376 { 2377 p=1; 2378 } 2379 2380 for (k=n;k>1;k--) 2381 { 2382 2383 if (j==1) 2384 { 2385 map phimap=R(k-1),phi; // phimap is the map corresponding 2386 } // to phi 2387 2388 p=p*phimap(nzd); 3067 map phimap=R(k-1),phi; //phimap:R(k-1)-->R(n), k=2..n, is the map 3068 //belonging to phi in R(n) 3069 } 3070 3071 p = p*phimap(nzd); 2389 3072 2390 3073 // Compute the preimage of [p mod ker(k)] under phi in R(k-1): 2391 3074 // As p is an element of Image(phi), there is a polynomial h such 2392 3075 // that h is mapped to [p mod ker(k)], and h can be computed as the 2393 // normal form of p w.r.t. a Gröbner basis of 2394 // J(k):=<ker(k),Z(l)-phi(k)(l)> in R(k)[Z]=:S(k) 2395 2396 if (j==1) // In the first iteration: Create S(k), fetch phi and 2397 // ker(k) and construct the ideal J(k). 2398 { 2399 execute ("ring S(k) = "+charstr(R(k))+",("+varstr(R(k))+", 2400 Z(1.."+string(ncols(phi))+")),(dp("+string(nvars(R(k))) 2401 +"),dp("+string(ncols(phi))+"));"); 2402 ideal phi=imap(R(k),phi); 2403 ideal J=imap (R(k),ker); 2404 for (l=1;l<=ncols(phi);l++) 2405 { 2406 J=J+(Z(l)-phi[l]); 2407 } 2408 J=groebner(J); 2409 poly h=NF(imap(R(k),p),J); 2410 } 2411 else 2412 { 2413 setring S(k); 2414 h=NF(imap(R(k),p),J); 2415 } 2416 2417 setring R(k-1); 2418 2419 if (j==1) // In the first iteration: Compute backmap:S(k)-->R(k-1) 2420 { 2421 mapstr=" map backmap = S(k),"; 2422 for (l=1;l<=nvars(R(k));l++) 2423 { 2424 mapstr=mapstr+"0,"; 2425 } 2426 execute (mapstr+"maxideal(1);"); 2427 2428 poly p; 2429 } 2430 p=NF(backmap(h),std(ker)); 3076 // normal form of p w.r.t. a Groebner basis of 3077 // J(k) := <ker(k),Z(l)-phi(k)(l)> in R(k)[Z]=:S(k) 3078 3079 if (j==1) // In the first iteration: Create S(k), fetch phi and 3080 // ker(k) and construct the ideal J(k). 3081 { 3082 //### noch abfragen ob Z(i) definiert ist 3083 list gnirlist = ringlist(R(k)); 3084 int n2 = size(gnirlist[2]); 3085 int n3 = size(gnirlist[3]); 3086 for( i=1; i<=ncols(phi); i++) 3087 { 3088 gnirlist[2][n2+i] = "Z("+string(i)+")"; 3089 } 3090 intvec V; 3091 V[ncols(phi)]=0; 3092 V=V+1; 3093 gnirlist[3] = insert(gnirlist[3],list("dp",V),n3-1); 3094 def S(k) = ring(gnirlist); 3095 setring S(k); 3096 3097 // execute ("ring S(k) = "+charstr(R(k))+",("+varstr(R(k))+", 3098 // Z(1.."+string(ncols(phi))+")),(dp("+string(nvars(R(k))) 3099 // +"),dp("+string(ncols(phi))+"));"); 3100 3101 ideal phi = imap(R(k),phi); 3102 ideal J = imap (R(k),ker); 3103 for ( l=1; l<=ncols(phi); l++ ) 3104 { 3105 J=J+(Z(l)-phi[l]); 3106 } 3107 J = groebner(J); 3108 poly h = NF(imap(R(k),p),J); 2431 3109 } 2432 2433 // When down to R(1), store the result in the list preimages 2434 2435 preimages = insert(preimages,p,j-1); 3110 else 3111 { 3112 setring S(k); 3113 h = NF(imap(R(k),p),J); 3114 } 3115 3116 setring R(k-1); 3117 3118 if (j==1) // In the first iteration: Compute backmap:S(k)-->R(k-1) 3119 { 3120 ideal maxi; 3121 maxi[nvars(R(k))] = 0; 3122 maxi = maxi,maxideal(1); 3123 map backmap = S(k),maxi; 3124 3125 //mapstr=" map backmap = S(k),"; 3126 //for (l=1;l<=nvars(R(k));l++) 3127 //{ 3128 // mapstr=mapstr+"0,"; 3129 //} 3130 //execute (mapstr+"maxideal(1);"); 3131 3132 poly p; 3133 } 3134 p = NF(backmap(h),std(ker)); 3135 } 3136 // Whe are down to R(1), store here the result in the list preimages 3137 preimages = insert(preimages,p,j-1); 3138 } 3139 ideal preim; //make the list preimages to an ideal preim 3140 for ( i=1; i<=size(preimages); i++ ) 3141 { 3142 preim[i] = preimages[i]; 3143 } 3144 // R(1) was a copy of Rees, so we have to get back to the basering Rees from 3145 // the beginning and fetch the result (the ideal preim) to this ring. 3146 setring Rees; 3147 return (fetch(R(1),preim)); 3148 } 3149 3150 /////////////////////////////////////////////////////////////////////////////// 3151 // From here: procedures for char p with Frobenius 3152 /////////////////////////////////////////////////////////////////////////////// 3153 3154 proc normalP(ideal id,list #) 3155 "USAGE: normalP(id [,choose]); id a radical ideal, choose a comma separated 3156 list of optional strings: \"withRing\" or \"isPrim\" or \"noFac\".@* 3157 If choose = \"noFac\", factorization is avoided during the computation 3158 of the minimal associated primes; choose = \"isPrim\" disables the 3159 computation of the minimal associated primes (should only be used 3160 if the ideal is known to be prime).@* 3161 ASSUME: The characteristic of the ground field must be positive. The ideal 3162 id is assumed to be radical. However, if choose does not contain 3163 \"isPrim\" the minimal associated primes of id are computed first 3164 and hence normal computes the normalization of the radical of id. 3165 If choose = \"isPrim\" the ideal must be a prime ideal (this is not 3166 tested) otherwise the result may be wrong. 3167 RETURN: a list, say 'nor' of size 2 (default) or, if \"withRing\" is given, 3168 of size 3. @* 3169 nor[1] (resp. nor[2] if \"withRing\" is given) is a list of ideals 3170 Ii, i=1..r, in the basering where r is the number of associated prime 3171 ideals P_i (irreducible components) of id.@* 3172 - Ii is an ideal given by polynomials g_1,...,g_k,g_k+1 such that 3173 g_1/g_k+1,...,g_k/g_k+1 generate the integral closure of 3174 basering/P_i as module (over the basering) in its quotient field.@* 3175 3176 nor[2] (resp. nor[3] if choose=\"withRing\") is a list of an intvec 3177 of size r, the delta invariants of the r components, and an integer, 3178 the total delta invariant of basering/id (-1 means infinite, and 0 3179 that basering/P_i resp. basering/input is normal). @* 3180 3181 If the optional string \"withRing\" is given, the ring structure of 3182 the normalization is computed too and nor[1] is a list of r rings.@* 3183 Each ring Ri = nor[1][i], i=1..r, contains two ideals with given names 3184 @code{norid} and @code{normap} such that @* 3185 - Ri/norid is the normalization of the i-th rime component P_i, i.e. 3186 isomorphic to the integral closure of basering/P_i in its field 3187 of fractions; @* 3188 - the direct sum of the rings Ri/norid is the normalization 3189 of basering/id; @* 3190 - @code{normap} gives the normalization map from basering/P_i to 3191 Ri/norid (for each i).@* 3192 THEORY: The delta invariant of a reduced ring K[x1,...,xn]/id is 3193 dim_K(normalization(K[x1,...,xn]/id) / K[x1,...,xn]/id) 3194 We call this number also the delta invariant of id. normalP uses 3195 the qth-power algorithm suggested by Leonard-Pellikaan (using the 3196 Frobenius) in part similair to an implementation by Singh-Swanson. 3197 NOTE: To use the i-th ring type: @code{def R=nor[1][i]; setring R;}. 3198 @* Increasing/decreasing printlevel displays more/less comments 3199 (default: printlevel = 0). 3200 @* Not implemented for local or mixed orderings or quotient rings. 3201 @* If the input ideal id is weighted homogeneous a weighted ordering may 3202 be used (qhweight(id); computes weights). 3203 @* works only in characteristic p > 0. 3204 KEYWORDS: normalization; integral closure; delta invariant. 3205 SEE ALSO: normal 3206 EXAMPLE: example normalP; shows an example 3207 " 3208 { 3209 int i,j,y, wring, isPrim, noFac, sr, del, co;; 3210 intvec deli; 3211 list resu, Resu, prim, Gens, mstdid; 3212 ideal gens; 3213 y = printlevel-voice+2; 3214 3215 if ( ord_test(basering) != 1) 3216 { 3217 ""; 3218 "// Not implemented for this ordering,"; 3219 "// please change to global ordering!"; 3220 return(resu); 3221 } 3222 if ( char(basering) <= 0) 3223 { 3224 ""; 3225 "// Algorithm works only in positive characteristic,"; 3226 "// use procedure 'normal' if the characteristic is 0"; 3227 return(resu); 3228 } 3229 3230 //--------------------------- define the method --------------------------- 3231 string method; //make all options one string in order to use 3232 //all combinations of options simultaneously 3233 for ( i=1; i<= size(#); i++ ) 3234 { 3235 if ( typeof(#[i]) == "string" ) 3236 { 3237 method = method + #[i]; 3238 } 3239 } 3240 3241 if ( find(method,"withring") or find(method,"withRing") ) 3242 { 3243 wring=1; 3244 } 3245 if ( find(method,"isPrim") or find(method,"isprim") ) 3246 { 3247 isPrim=1; 3248 } 3249 if ( find(method,"noFac") ) 3250 { 3251 noFac=1; 3252 } 3253 3254 kill #; 3255 list #; 3256 //--------------------------- start computation --------------------------- 3257 ideal II,K1,K2; 3258 3259 //----------- check first (or ignore) if input id is prime ------------- 3260 3261 if ( isPrim ) 3262 { 3263 prim[1] = id; 3264 if( y >= 0 ) 3265 { ""; 3266 "// ** WARNING: result is correct if ideal is prime (not checked) **"; 3267 "// disable option \"isPrim\" to decompose ideal into prime components";""; 3268 } 3269 } 3270 else 3271 { 3272 if(y>=1) 3273 { "// compute minimal associated primes"; } 3274 3275 if( noFac ) 3276 { prim = minAssGTZ(id,1); } 3277 else 3278 { prim = minAssGTZ(id); } 3279 3280 if(y>=1) 3281 { 3282 prim;""; 3283 "// number of irreducible components is", size(prim); 3284 } 3285 } 3286 3287 //----------- compute integral closure for every component ------------- 3288 3289 for(i=1; i<=size(prim); i++) 3290 { 3291 if(y>=1) 3292 { 3293 ""; pause(); ""; 3294 "// start computation of component",i; 3295 " --------------------------------"; 3296 } 3297 if(y>=1) 3298 { "// compute SB of ideal"; 3299 } 3300 mstdid = mstd(prim[i]); 3301 if(y>=1) 3302 { "// dimension of component is", dim(mstdid[1]);"";} 3303 3304 //------- 1-st main subprocedure: compute module generators ---------- 3305 printlevel = printlevel+1; 3306 II = normalityTest(mstdid); 3307 3308 //------ compute also the ringstructure if "withRing" is given ------- 3309 if ( wring ) 3310 { 3311 //------ 2-nd main subprocedure: compute ring structure ----------- 3312 resu = list(computeRing(II,prim[i])) + resu; 3313 } 3314 printlevel = printlevel-1; 3315 3316 //----- rearrange module generators s.t. denominator comes last ------ 3317 gens=0; 3318 for( j=2; j<=size(II); j++ ) 3319 { 3320 gens[j-1]=II[j]; 3321 } 3322 gens[size(gens)+1]=II[1]; 3323 Gens = list(gens) + Gens; 3324 //------------------------------ compute delta ----------------------- 3325 K1 = mstdid[1]+II; 3326 K1 = std(K1); 3327 K2 = mstdid[1]+II[1]; 3328 K2 = std(K2); 3329 // K1 = std(mstdid[1],II); //### besser 3330 // K2 = std(mstdid[1],II[1]); //### besser: Hannes, fixen! 3331 co = codim(K1,K2); 3332 deli = co,deli; 3333 if ( co >= 0 && del >= 0 ) 3334 { 3335 del = del + co; 3336 } 3337 else 3338 { del = -1; } 3339 } 3340 3341 if ( del >= 0 ) 3342 { 3343 int mul = iMult(prim); 3344 del = del + mul; 3345 } 3346 else 3347 { del = -1; } 3348 3349 deli = deli[1..size(deli)-1]; 3350 if ( wring ) 3351 { Resu = resu,Gens,list(deli,del); } 3352 else 3353 { Resu = Gens,list(deli,del); } 3354 3355 sr = size(prim); 3356 3357 //-------------------- Finally print comments and return -------------------- 3358 if(y >= 0) 3359 {""; 3360 if ( wring ) 3361 { 3362 "// 'normalP' created a list, say nor, of three lists: 3363 // nor[1] resp. nor[2] are lists of",sr,"ring(s) resp. ideal(s) 3364 // and nor[3] is a list of an intvec and an integer. 3365 // To see the result, type 3366 nor; 3367 // To access the i-th ring nor[1][i] give it a name, say Ri, and type e.g. 3368 def R1 = nor[1][1]; setring R1; norid; normap; 3369 // for the other rings type first setring r; (if r is the name of your 3370 // original basering) and then continue as for the first ring; 3371 // Ri/norid is the affine algebra of the normalization of the i-th 3372 // component r/P_i (where P_i is an associated prime of the input ideal) 3373 // and normap the normalization map from r to Ri/norid; 3374 // nor[2] is a list of",sr,"ideal(s), each ideal nor[2][i] consists of 3375 // elements g1..gk of r such that the gj/gk generate the integral 3376 // closure of r/P_i as (r/P_i)-module in the quotient field of r/P_i. 3377 // nor[3] shows the delta-invariant of each component and of the input 3378 // ideal (-1 means infinite, and 0 that r/P_i is normal)."; 3379 } 3380 else 3381 { 3382 "// 'normalP' computed a list, say nor, of two lists: 3383 // nor[1] is a list of",sr,"ideal(s), where each ideal nor[1][i] consists 3384 // of elements g1..gk of the basering such that gj/gk generate the integral 3385 // closure of the i-th component as (basering/P_i)-module in the quotient 3386 // field of basering/P_i (P_i an associated prime of the input ideal); 3387 // nor[2] shows the delta-invariant of each component and of the input ideal 3388 // (-1 means infinite, and 0 that r/P_i is normal)."; 3389 } 3390 } 3391 3392 return(Resu); 3393 } 3394 example 3395 { "EXAMPLE:"; echo = 2; 3396 ring r = 11,(x,y,z),wp(2,1,2); 3397 ideal i = x*(z3 - xy4 + x2); 3398 list nor= normalP(i); nor; 3399 //the result says that both components of i are normal, but i itself 3400 //has infinite delta 3401 pause("hit return to continue"); 3402 3403 ring s = 2,(x,y),dp; 3404 ideal i = y*((x-y^2)^2 - x^3); 3405 list nor = normalP(i,"withRing"); nor; 3406 3407 def R2 = nor[1][2]; setring R2; 3408 norid; normap; 3409 } 3410 3411 /////////////////////////////////////////////////////////////////////////////// 3412 // Assume: mstdid is the result of mstd(prim[i]), prim[i] a prime component of 3413 // the input ideal id of normalP. 3414 // Output is an ideal U s.t. U[i]/U[1] are module generators. 3415 3416 static proc normalityTest(list mstdid) 3417 { 3418 int y = printlevel-voice+2; 3419 intvec op = option(get); 3420 option(redSB); 3421 def R = basering; 3422 int n, p = nvars(R), char(R); 3423 int ii; 3424 3425 ideal J = mstdid[1]; //J is the SB of I 3426 ideal I = mstdid[2]; 3427 int h = n-dim(J); //codimension of V(I), I is a prime ideal 3428 3429 //-------------------------- compute singular locus ---------------------- 3430 qring Q = J; //pass to quotient ring 3431 ideal I = imap(R,I); 3432 ideal J = imap(R,J); 3433 attrib(J,"isSB",1); 3434 if ( y >= 1) 3435 { "start normality test"; "compute singular locus";} 3436 3437 ideal M = minor(jacob(I),h,J); //use the command minor modulo J (hence J=0) 3438 M = std(M); //this makes M much smaller 3439 //keep only minors which are not 0 mod I (!) this is important since we 3440 //need a nzd mod I 3441 3442 //---------------- choose nzd from ideal of singular locus -------------- 3443 ideal D = M[1]; 3444 for( ii=2; ii<=size(M); ii++ ) //look for the shortest one 3445 { 3446 if( size(M[ii]) < size(D[1]) ) 3447 { 3448 D = M[ii]; 3449 } 3450 } 3451 3452 //--------------- start p-th power algorithm and return ---------------- 3453 ideal F = var(1)^p; 3454 for(ii=2; ii<=n; ii++) 3455 { 3456 F=F,var(ii)^p; 3457 } 3458 3459 ideal Dp=D^(p-1); 3460 ideal U=1; 3461 ideal K,L; 3462 map phi=Q,F; 3463 if ( y >= 1) 3464 { "compute module generators of integral closure"; 3465 "denominator D is:"; D; 3466 pause(); 3467 } 3468 3469 ii=0; 3470 list LK; 3471 while(1) 3472 { 3473 ii=ii+1; 3474 if ( y >= 1) 3475 { "iteration", ii; } 3476 L = U*Dp + I; 3477 //### L=interred(L) oder msdt(L)[2]? 3478 //Wird dadurch kleiner aber string(L) wird groesser 3479 K = preimage(Q,phi,L); //### Improvement by block ordering? 3480 option(returnSB); 3481 K = intersect(U,K); //K is the new U, it is a SB 3482 LK = mstd(K); 3483 K = LK[2]; 3484 3485 //---------------------------- simplify output -------------------------- 3486 if(size(reduce(U,LK[1]))==0) //previous U coincides with new U 3487 { //i.e. we reached the integral closure 3488 U=simplify(reduce(U,groebner(D)),2); 3489 U = D,U; 3490 poly gg = gcd(U[1],U[size(U)]); 3491 for(ii=2; ii<=size(U)-1 ;ii++) 3492 { 3493 gg = gcd(gg,U[ii]); 3494 } 3495 for(ii=1; ii<=size(U); ii++) 3496 { 3497 U[ii]=U[ii]/gg; 3498 } 3499 U = simplify(U,6); 3500 //if ( y >= 1) 3501 //{ "module generators are U[i]/U[1], with U:"; U; 3502 // ""; pause(); } 3503 option(set,op); 3504 setring R; 3505 ideal U = imap(Q,U); 3506 return(U); 3507 } 3508 U=K; 3509 } 3510 } 3511 3512 /////////////////////////////////////////////////////////////////////////////// 3513 3514 static proc substpartSpecial(ideal endid, ideal endphi) 3515 { 3516 //Note: newRing is of the form (R the original basering): 3517 //char(R),(T(1..N),X(1..nvars(R))),(dp(N),...); 3518 3519 int ii,jj,kk; 3520 def BAS = basering; 3521 int n = nvars(basering); 3522 3523 list Le = elimpart(endid); 3524 int q = size(Le[2]); //q variables have been substituted 3525 //Le;""; 3526 if ( q == 0 ) 3527 { 3528 ideal normap = endphi; 3529 ideal norid = endid; 3530 export(norid); 3531 export(normap); 3532 list L = BAS; 3533 return(L); 3534 } 3535 3536 list gnirlist = ringlist(basering); 3537 endid = Le[1]; 3538 //endphi;""; 3539 for( ii=1; ii<=n; ii++) 3540 { 3541 if( Le[4][ii] == 0 ) //ii=index of substituted var 3542 { 3543 endphi = subst(endphi,var(ii),Le[5][ii]); 3544 } 3545 } 3546 //endphi;""; 3547 list g2 = gnirlist[2]; //the varlist 3548 list g3 = gnirlist[3]; //contains blocks of orderings 3549 int n3 = size(g3); 3550 //----------------- first identify module ordering ------------------ 3551 if ( g3[n3][1]== "c" or g3[n3][1] == "C" ) 3552 { 3553 list gm = g3[n3]; //last blockis module ordering 3554 g3 = delete(g3,n3); 3555 int m = 0; 3556 } 3557 else 3558 { 3559 list gm = g3[1]; //first block is module ordering 3560 g3 = delete(g3,1); 3561 int m = 1; 3562 } 3563 //---- delete variables which were substituted and weights -------- 3564 //gnirlist;""; 3565 intvec V; 3566 int n(0); 3567 list newg2; 3568 list newg3; 3569 for ( ii=1; ii<=n3-1; ii++ ) 3570 { 3571 V = V,g3[ii][2]; //copy weights for ordering in each block 3572 if ( ii==1 ) //into one intvector 3573 { 3574 V = V[2..size(V)]; 3575 } 3576 // int n(ii) = size(g3[ii][2]); 3577 int n(ii) = size(V); 3578 intvec V(ii); 3579 3580 for ( jj = n(ii-1)+1; jj<=n(ii); jj++) 3581 { 3582 //"ii, jj", ii,jj; 3583 if( Le[4][jj] !=0 ) //jj=index of var which was not substituted 3584 { 3585 kk=kk+1; 3586 newg2[kk] = g2[jj]; //not substituted var from varlist 3587 V(ii)=V(ii),V[jj]; //weight of not substituted variable 3588 //"V(",ii,")", V(ii); 3589 } 3590 } 3591 if ( size(V(ii)) >= 2 ) 3592 { 3593 V(ii) = V(ii)[2..size(V(ii))]; 3594 list g3(ii)=g3[ii][1],V(ii); 3595 newg3 = insert(newg3,g3(ii),size(newg3)); 3596 //"newg3"; newg3; 3597 } 3598 } 3599 //"newg3"; newg3; 3600 //newg3 = delete(newg3,1); //delete empty list 3601 3602 /* 3603 //### neue Ordnung, 1 Block fuer alle vars, aber Gewichte erhalten; 3604 //vorerst nicht realisiert, da bei leonhard1 alte Version (neue Variable T(i) 3605 //ein neuer Block) ein kuerzeres Ergebnis liefert 3606 kill g3; 3607 list g3; 3608 V=0; 3609 for ( ii= 1; ii<=n3-1; ii++ ) 3610 { 3611 V=V,V(ii); 3612 } 3613 V = V[2..size(V)]; 3614 3615 if ( V==1 ) 3616 { 3617 g3[1] = list("dp",V); 3618 } 3619 else 3620 { 3621 g3[1] = lis("wp",V); 3622 } 3623 newg3 = g3; 3624 3625 //"newg3";newg3;""; 3626 //### Ende neue Ordnung 3627 */ 3628 3629 if ( m == 0 ) 3630 { 3631 newg3 = insert(newg3,gm,size(newg3)); 3632 } 3633 else 3634 { 3635 newg3 = insert(newg3,gm); 3636 } 3637 gnirlist[2] = newg2; 3638 gnirlist[3] = newg3; 3639 3640 //gnirlist; 3641 def newBAS = ring(gnirlist); //change of ring to less vars 3642 setring newBAS; 3643 ideal normap = imap(BAS,endphi); 3644 //normap = simplify(normap,2); 3645 ideal norid = imap(BAS,endid); 3646 export(norid); 3647 export(normap); 3648 list L = newBAS; 3649 return(L); 3650 3651 //Hier scheint interred gut zu sein, da es Ergebnis relativ schnell 3652 //verkleinert. Hier wird z.B. bei leonard1 size(norid) verkleinert aber 3653 //size(string(norid)) stark vergroessert, aber es hat keine Auswirkungen 3654 //da keine map mehr folgt. 3655 //### Bei Leonard2 haengt interred (BUG) 3656 //mstd[2] verkleinert norid nocheinmal um die Haelfte, dauert aber 3.71 sec 3657 //### Ev. Hinweis auf mstd in der Hilfe? 3658 3659 } 3660 3661 /////////////////////////////////////////////////////////////////////////////// 3662 // Computes the ring structure of a ring given by module generators. 3663 // Assume: J[i]/J[1] are the module generators in the quotient field 3664 // with J[1] as universal denominator. 3665 // If option "noRed" is not given, a reduction in the number of variables is 3666 // attempted. 3667 static proc computeRing(ideal J, ideal I, list #) 3668 { 3669 int i, ii,jj; 3670 intvec V; // to be used for variable weights 3671 int y = printlevel-voice+2; 3672 def R = basering; 3673 poly c = J[1]; // the denominator 3674 list gnirlist = ringlist(basering); 3675 string svars = varstr(basering); 3676 int nva = nvars(basering); 3677 string svar; 3678 ideal maxid = maxideal(1); 3679 3680 int noRed = 0; // By default, we try to reduce the number of generators. 3681 if(size(#) > 0){ 3682 if ( typeof(#[1]) == "string" ) 3683 { 3684 if (#[1] == "noRed"){noRed = 1;} 2436 3685 } 2437 2438 // R(1) was a copy of Rees, so we have to get back to the basering Rees from 2439 // the beginning and fetch the result (the list preimages) to this ring. 2440 2441 setring Rees; 2442 return (fetch(R(1),preimages)); 3686 } 3687 3688 if ( y >= 1){"// computing the ring structure...";} 3689 3690 if(c==1) 3691 { 3692 if( defined(norid) ) { kill norid; } 3693 if( defined(normap) ) { kill normap; } 3694 ideal norid = I; 3695 ideal normap = maxid; 3696 export norid; 3697 export normap; 3698 if(noRed == 1){ 3699 setring R; 3700 return(R); 3701 } else { 3702 list L = substpartSpecial(norid,normap); 3703 def lastRing = L[1]; 3704 setring R; 3705 return(lastRing); 3706 } 3707 } 3708 3709 3710 //-------------- Enlarge ring by creating new variables ------------------ 3711 //check first whether variables T(i) and then whether Z(i),...,A(i) exist 3712 //old variable names are not touched 3713 3714 if ( find(svars,"T(") == 0 ) 3715 { 3716 svar = "T"; 3717 } 3718 else 3719 { 3720 for (ii=90; ii>=65; ii--) 3721 { 3722 if ( find(svars,ASCII(ii)+"(") == 0 ) 3723 { 3724 svar = ASCII(ii); break; 3725 } 3726 } 3727 } 3728 3729 int q = size(J)-1; 3730 if ( size(svar) != 0 ) 3731 { 3732 for ( ii=q; ii>=1; ii-- ) 3733 { 3734 gnirlist[2] = insert(gnirlist[2],svar+"("+string(ii)+")"); 3735 } 3736 } 3737 else 3738 { 3739 for ( ii=q; ii>=1; ii-- ) 3740 { 3741 gnirlist[2] = insert(gnirlist[2],"T("+string(100*nva+ii)+")"); 3742 } 3743 } 3744 3745 V[q]=0; //create intvec of variable weights 3746 V=V+1; 3747 gnirlist[3] = insert(gnirlist[3],list("dp",V)); 3748 3749 //this is a block ordering with one dp-block (1st block) for new vars 3750 //the remaining weights and blocks for old vars are kept 3751 //### perhaps better to make only one block, keeping weights ? 3752 //this might effect syz below 3753 //alt: ring newR = char(R),(X(1..nvars(R)),T(1..q)),dp; 3754 //Reihenfolge gendert:neue Variablen kommen zuerst, Namen ev. nicht T(i) 3755 3756 def newR = ring(gnirlist); 3757 setring newR; //new extended ring 3758 ideal I = imap(R,I); 3759 3760 //------------- Compute linear and quadratic relations --------------- 3761 if(y>=1) 3762 { 3763 "// compute linear relations:"; 3764 } 3765 qring newQ = std(I); 3766 3767 ideal f = imap(R,J); 3768 module syzf = syz(f); 3769 ideal pf = f[1]*f; 3770 //f[1] is the denominator D from normalityTest, a non zero divisor of R/I 3771 3772 ideal newT = maxideal(1); 3773 newT = 1,newT[1..q]; 3774 //matrix T = matrix(ideal(1,T(1..q)),1,q+1); //alt 3775 matrix T = matrix(newT,1,q+1); 3776 ideal Lin = ideal(T*syzf); 3777 //Lin=interred(Lin); 3778 //### interred reduziert ev size aber size(string(LIN)) wird groesser 3779 3780 if(y>=1) 3781 { 3782 if(y>=3) 3783 { 3784 "// the linear relations:"; Lin; pause();""; 3785 } 3786 "// the ring structure of the normalization as affine algebra"; 3787 "// number of linear relations:", size(Lin); 3788 } 3789 3790 if(y>=1) 3791 { 3792 "// compute quadratic relations:"; 3793 } 3794 matrix A; 3795 ideal Quad; 3796 poly ff; 3797 newT = newT[2..size(newT)]; 3798 matrix u; // The units for non-global orderings. 3799 3800 // Quadratic relations 3801 for (ii=2; ii<=q+1; ii++ ) 3802 { 3803 for ( jj=2; jj<=ii; jj++ ) 3804 { 3805 ff = NF(f[ii]*f[jj],std(0)); // this makes lift much faster 3806 // For non-global orderings, we have to take care of the units. 3807 if(ord_test(basering) != 1){ 3808 A = lift(pf, ff, u); 3809 Quad = Quad,ideal(newT[jj-1]*newT[ii-1] * u[1, 1]- T*A); 3810 } else { 3811 A = lift(pf,ff); // ff lin. comb. of elts of pf mod I 3812 Quad = Quad,ideal(newT[jj-1]*newT[ii-1] - T*A); 3813 } 3814 //A = lift(pf, f[ii]*f[jj]); 3815 //Quad = Quad, ideal(T(jj-1)*T(ii-1) - T*A); 3816 } 3817 } 3818 Quad = Quad[2..ncols(Quad)]; 3819 3820 if(y>=1) 3821 { 3822 if(y>=3) 3823 { 3824 "// the quadratic relations"; Quad; pause();""; 3825 } 3826 "// number of quadratic relations:", size(Quad); 3827 } 3828 ideal Q1 = Lin,Quad; //elements of Q1 are in NF w.r.t. I 3829 3830 //Q1 = mstd(Q1)[2]; 3831 //### weglassen, ist sehr zeitaufwendig. 3832 //Ebenso interred, z.B. bei Leonard1 (1. Komponente von Leonard): 3833 //"size Q1:", size(Q1), size(string(Q1)); //75 60083 3834 //Q1 = interred(Q1); 3835 //"size Q1:", size(Q1), size(string(Q1)); //73 231956 (!) 3836 //### Speicherueberlauf bei substpartSpecial bei 'ideal norid = phi1(endid)' 3837 //Beispiel fuer Hans um map zu testen! 3838 3839 setring newR; 3840 ideal endid = imap(newQ,Q1),I; 3841 ideal endphi = imap(R,maxid); 3842 3843 if(noRed == 0){ 3844 list L=substpartSpecial(endid,endphi); 3845 def lastRing=L[1]; 3846 if(y>=1) 3847 { 3848 "// number of substituted variables:", nvars(newR)-nvars(lastRing); 3849 pause();""; 3850 } 3851 return(lastRing); 3852 } else { 3853 ideal norid = endid; 3854 ideal normap = endphi; 3855 export(norid); 3856 export(normap); 3857 setring R; 3858 return(newR); 3859 } 2443 3860 } 3861 3862 // Up to here: procedures for char p with Frobenius 3863 /////////////////////////////////////////////////////////////////////////////// 3864 3865 /////////////////////////////////////////////////////////////////////////////// 3866 // From here: subprocedures for normal 3867 3868 static proc normalM(ideal I, int decomp, int withDelta){ 3869 // Computes the normalization of a ring R / I using the module structure as far 3870 // as possible. 3871 // The ring R is the basering. 3872 // Input: ideal I 3873 // Output: a list of 3 elements (resp 4 if withDelta = 1), say nor. 3874 // - nor[1] = U, an ideal of R. 3875 // - nor[2] = c, an element of R. 3876 // U and c satisfy that 1/c * U is the normalization of R / I in the 3877 // quotient field Q(R/I). 3878 // - nor[3] = ring say T, containing two ideals norid and normap such that 3879 // normap gives the normalization map from R / I to T / norid. 3880 // - nor[4] = the delta invariant, if withDelta = 1. 3881 3882 // Details: 3883 // -------- 3884 // Computes the ideal of the minors in the first step and then reuses it in all 3885 // steps. 3886 // In step s, the denominator is D^s, where D is a nzd of the original quotient 3887 // ring, contained in the radical of the singular locus. 3888 // This denominator is used except when the degree of D^i is greater than the 3889 // degree of a conductor. 3890 // The nzd is taken as the smallest degree polynomial in the radical of the 3891 // singular locus. 3892 3893 // It assumes that the ideal I is equidimensional radical. This is not checked 3894 // in the procedure! 3895 // If decomp = 0 or decomp = 3 it assumes further that I is prime. Therefore 3896 // any non-zero element in the jacobian ideal is assumed to be a 3897 // non-zerodivisor. 3898 3899 // It works over the given basering. 3900 // If it has a non-global ordering, it changes it to dp global only for 3901 // computing radical. 3902 3903 // The delta invariant is only computed if withDelta = 1, and decomp = 0 or 3904 // decomp = 3 (meaning that the ideal is prime). 3905 3906 option("redSB"); 3907 option("returnSB"); 3908 int step = 0; // Number of steps. (for debugging) 3909 int dbg = printlevel - voice + 2; // dbg = printlevel (default: dbg = 0) 3910 int i; // counter 3911 int isGlobal = ord_test(basering); 3912 3913 poly c; // The common denominator. 3914 3915 def R = basering; 3916 3917 // ---------------- computation of the singular locus --------------------- 3918 // We compute the radical of the ideal of minors modulo the original ideal. 3919 // This is done only in the first step. 3920 3921 if(isGlobal == 1){ 3922 list IM = mstd(I); 3923 I = IM[1]; 3924 ideal IMin = IM[2]; // A minimal set of generators in the groebner basis. 3925 } else { 3926 // The minimal set of generators is not computed by mstd for 3927 // non-global orderings. 3928 I = groebner(I); 3929 ideal IMin = I; 3930 } 3931 int d = dim(I); 3932 3933 qring Q = I; // We work in the quotient by the groebner base of the ideal I 3934 option("redSB"); 3935 option("returnSB"); 3936 ideal I = fetch(R, I); 3937 attrib(I, "isSB", 1); 3938 ideal IMin = fetch(R, IMin); 3939 3940 dbprint(dbg, "Computing the jacobian ideal..."); 3941 ideal J = minor(jacob(IMin), nvars(basering) - d, I); 3942 J = groebner(J); 3943 3944 // -------------------- election of the conductor ------------------------- 3945 poly condu = getSmallest(J); // Choses the polynomial of smallest degree 3946 // of J as universal denominator. 3947 if(dbg >= 1){ 3948 ""; 3949 "The universal denominator is ", condu; 3950 } 3951 3952 // --------- splitting the ideal by the conductor (if possible) ----------- 3953 // If the ideal is equidimensional, but not necessarily prime, we check if 3954 // the conductor is a non-zerodivisor of R/I. 3955 // If not, we split I. 3956 if((decomp == 1) or (decomp == 2)){ 3957 ideal Id1 = quotient(0, condu); 3958 if(size(Id1) > 0){ 3959 // We have to split. 3960 if(dbg >= 1){ 3961 "A zerodivisor was found. We split the ideal. The zerodivisor is ", condu; 3962 } 3963 setring R; 3964 ideal Id1 = fetch(Q, Id1), I; 3965 Id1 = groebner(Id1); 3966 ideal Id2 = quotient(I, Id1); 3967 // I = I1 \cap I2 3968 printlevel = printlevel + 1; 3969 list nor1 = normalM(Id1, decomp, withDelta)[1]; 3970 list nor2 = normalM(Id2, decomp, withDelta)[1]; 3971 printlevel = printlevel - 1; 3972 return(list(nor1, nor2)); 3973 } 3974 } 3975 3976 // --------------- computation of the first test ideal --------------------- 3977 // To compute the radical we go back to the original ring. 3978 // If we are using a non-global ordering, we must change to the global 3979 // ordering. 3980 if(isGlobal == 1){ 3981 setring R; 3982 ideal J = fetch(Q, J); 3983 J = J, I; 3984 if(dbg >= 1){ 3985 "The original singular locus is"; 3986 groebner(J); 3987 if(dbg >= 2){pause();} 3988 ""; 3989 } 3990 J = radical(J); 3991 } else { 3992 // We change to global dp ordering. 3993 list rl = ringlist(R); 3994 list origOrd = rl[3]; 3995 list newOrd = list("dp", intvec(1:nvars(R))), list("C", 0); 3996 rl[3] = newOrd; 3997 def globR = ring(rl); 3998 setring globR; 3999 ideal J = fetch(Q, J); 4000 ideal I = fetch(R, I); 4001 J = J, I; 4002 if(dbg >= 1){ 4003 "The original singular locus is"; 4004 groebner(J); 4005 if(dbg>=2){pause();} 4006 ""; 4007 } 4008 J = radical(J); 4009 setring R; 4010 ideal J = fetch(globR, J); 4011 } 4012 4013 if(dbg >= 1){ 4014 "The radical of the original singular locus is"; 4015 J; 4016 if(dbg>=2){pause();} 4017 } 4018 4019 // ---------------- election of the non zero divisor --------------------- 4020 setring Q; 4021 J = fetch(R, J); 4022 J = interred(J); 4023 poly D = getSmallest(J); // Chooses the poly of smallest degree as 4024 // non-zerodivisor. 4025 if(dbg >= 1){ 4026 "The non zero divisor is ", D; 4027 ""; 4028 } 4029 4030 // ------- splitting the ideal by the non-zerodivisor (if possible) -------- 4031 // If the ideal is equidimensional, but not necessarily prime, we check if D 4032 // is actually a non-zerodivisor of R/I. 4033 // If not, we split I. 4034 if((decomp == 1) or (decomp == 2)){ 4035 // We check if D is actually a non-zerodivisor of R/I. 4036 // If not, we split I. 4037 Id1 = quotient(0, D); 4038 if(size(Id1) > 0){ 4039 // We have to split. 4040 if(dbg >= 1){ 4041 "A zerodivisor was found. We split the ideal. The zerodivisor is ", D; 4042 } 4043 setring R; 4044 ideal Id1 = fetch(Q, Id1), I; 4045 Id1 = groebner(Id1); 4046 ideal I2 = quotient(I, Id1); 4047 // I = Id1 \cap Id2 4048 printlevel = printlevel + 1; 4049 list nor1 = normalM(Id1, decomp, withDelta)[1]; 4050 list nor2 = normalM(Id2, decomp, withDelta)[1]; 4051 printlevel = printlevel - 1; 4052 return(list(nor1, nor2)); 4053 } 4054 } 4055 4056 // --------------------- normalization ------------------------------------ 4057 // We call normalMEqui to compute the normalization. 4058 setring R; 4059 poly D = fetch(Q, D); 4060 poly condu = fetch(Q, condu); 4061 J = fetch(Q, J); 4062 printlevel = printlevel + 1; 4063 list result = normalMEqui(I, J, condu, D, withDelta); 4064 printlevel = printlevel - 1; 4065 return(list(result)); 4066 } 4067 4068 /////////////////////////////////////////////////////////////////////////////// 4069 4070 static proc normalMEqui(ideal I, ideal origJ, poly condu, poly D, int withDelta) 4071 // Here is where the normalization is actually computed. 4072 4073 // Computes the normalization of R/I. (basering is R) 4074 // I is assumed to be radical and equidimensional. 4075 // origJ is the first test ideal. 4076 // D is a non-zerodivisor of R/I. 4077 // condu is a non-zerodivisor in the conductor. 4078 // If withDelta = 1, computes the delta invariant. 4079 { 4080 int step = 0; // Number of steps. (for debugging) 4081 int dbg = printlevel - voice + 2; // dbg = printlevel (default: dbg = 0) 4082 int i; // counter 4083 int isNormal = 0; // check for exiting the loop 4084 int isGlobal = ord_test(basering); 4085 int delt; 4086 4087 def R = basering; 4088 poly c = D; 4089 ideal U; 4090 ideal cJ; 4091 list testOut; // Output of proc testIdeal 4092 // (the test ideal and the ring structure) 4093 4094 qring Q = groebner(I); 4095 option("redSB"); 4096 option("returnSB"); 4097 ideal J = imap(R, origJ); 4098 poly c = imap(R, c); 4099 poly D = imap(R, D); 4100 poly condu = imap(R, condu); 4101 ideal cJ; 4102 ideal cJMod; 4103 4104 dbprint(dbg, "Preliminar step begins."); 4105 4106 // --------------------- computation of A1 ------------------------------- 4107 dbprint(dbg, "Computing the quotient (DJ : J)..."); 4108 ideal U = groebner(quotient(D*J, J)); 4109 ideal oldU = 1; 4110 4111 if(dbg >= 2){ 4112 "The quotient is"; U; 4113 } 4114 4115 // ----------------- Grauer-Remmert criterion check ----------------------- 4116 // We check if the equality in Grauert - Remmert criterion is satisfied. 4117 isNormal = checkInclusions(D*oldU, U); 4118 if(isNormal == 0){ 4119 if(dbg >= 1){ 4120 "In this step, we have the ring 1/c * U, with c =", c; 4121 "and U = "; U; 4122 } 4123 } else { 4124 // The original ring R/I was normal. Nothing to do. 4125 // We define anyway a new ring, equal to R, to be able to return it. 4126 setring R; 4127 list lR = ringlist(R); 4128 def ROut = ring(lR); 4129 setring ROut; 4130 ideal norid = 0; 4131 ideal normap = maxideal(1); 4132 export norid; 4133 export normap; 4134 setring R; 4135 if(withDelta){ 4136 list output = ideal(1), poly(1), ROut, 0; 4137 } else { 4138 list output = ideal(1), poly(1), ROut; 4139 } 4140 return(output); 4141 } 4142 4143 // ----- computation of the chain of ideals A1 c A2 c ... c An ------------ 4144 while(isNormal == 0){ 4145 step++; 4146 if(dbg >= 1){ 4147 ""; 4148 "Step ", step, " begins."; 4149 } 4150 dbprint(dbg, "Computing the test ideal..."); 4151 4152 // --------------- computation of the test ideal ------------------------ 4153 // Computes a test ideal for the new ring. 4154 // The test ideal will be the radical in the new ring of the original 4155 // test ideal. 4156 setring R; 4157 U = imap(Q, U); 4158 c = imap(Q, c); 4159 testOut = testIdeal(I, U, origJ, c, D); 4160 cJ = testOut[1]; 4161 4162 setring Q; 4163 cJ = imap(R, cJ); 4164 cJ = groebner(cJ); 4165 4166 // cJ / c is now the ideal mapped back. 4167 // We have the generators as an ideal in the new ring, 4168 // but we want the generators as an ideal in the original ring. 4169 cJMod = getGenerators(cJ, U, c); 4170 4171 if(dbg >= 2){ 4172 "The test ideal in this step is "; 4173 cJMod; 4174 } 4175 4176 cJ = cJMod; 4177 4178 // ------------- computation of the quotient (DJ : J)-------------------- 4179 oldU = U; 4180 dbprint(dbg, "Computing the quotient (c*D*cJ : cJ)..."); 4181 U = quotient(c*D*cJ, cJ); 4182 if(dbg >= 2){"The quotient is "; U;} 4183 4184 // ------------- Grauert - Remmert criterion check ---------------------- 4185 // We check if the equality in Grauert - Remmert criterion is satisfied. 4186 isNormal = checkInclusions(D*oldU, U); 4187 4188 if(isNormal == 1){ 4189 // We go one step back. In the last step we didnt get antyhing new, 4190 // we just verified that the ring was already normal. 4191 dbprint(dbg, "The ring in the previous step was already normal."); 4192 dbprint(dbg, ""); 4193 U = oldU; 4194 } else { 4195 // ------------- preparation for next iteration ---------------------- 4196 // We have to go on. 4197 // The new denominator is chosen. 4198 c = D * c; 4199 if(deg(c) > deg(condu)){ 4200 U = changeDenominatorQ(U, c, condu); 4201 c = condu; 4202 } 4203 if(dbg >= 1){ 4204 "In this step, we have the ring 1/c * U, with c =", c; 4205 "and U = "; 4206 U; 4207 if(dbg>=2){pause();} 4208 } 4209 } 4210 } 4211 4212 // ------------------------- delta computation ---------------------------- 4213 if(withDelta){ 4214 ideal UD = groebner(U); 4215 delt = vdim(std(modulo(UD, c))); 4216 } 4217 4218 // -------------------------- prepare output ----------------------------- 4219 setring R; 4220 U = fetch(Q, U); 4221 c = fetch(Q, c); 4222 4223 // Ring structure of the new ring 4224 def ere = testOut[2]; 4225 if(withDelta){ 4226 list output = U, c, ere, delt; 4227 } else { 4228 list output = U, c, ere; 4229 } 4230 return(output); 4231 4232 } 4233 4234 /////////////////////////////////////////////////////////////////////////////// 4235 4236 static proc lineUp(ideal U, poly c) 4237 // Sets c as the first generator of U. 4238 { 4239 int i; 4240 ideal newU = c; 4241 for (i = 1; i <= ncols(U); i++){ 4242 if(U[i] != c){ 4243 newU = newU, U[i]; 4244 } 4245 } 4246 return(newU); 4247 } 4248 4249 /////////////////////////////////////////////////////////////////////////////// 4250 4251 static proc getSmallest(ideal J){ 4252 // Computes the polynomial of smallest degree of J. 4253 // If there are more than one, it chooses the one with smallest number 4254 // of monomials. 4255 int i; 4256 poly p = J[1]; 4257 int d = deg(p); 4258 int di; 4259 for(i = 2; i <= ncols(J); i++){ 4260 if(J[i] != 0){ 4261 di = deg(J[i]); 4262 if(di < d){ 4263 p = J[i]; 4264 d = di; 4265 } else { 4266 if(di == d){ 4267 if(size(J[i]) < size(p)){ 4268 p = J[i]; 4269 } 4270 } 4271 } 4272 } 4273 } 4274 return(p); 4275 } 4276 4277 /////////////////////////////////////////////////////////////////////////////// 4278 4279 static proc getGenerators(ideal J, ideal U, poly c){ 4280 // Computes the generators of J as an ideal in the original ring, 4281 // where J is given by generators in the new ring. 4282 4283 // The new ring is given by 1/c * U in the total ring of fractions. 4284 4285 int i, j; // counters; 4286 int dbg = printlevel - voice + 2; // dbg = printlevel (default: dbg = 0) 4287 poly p; // The lifted polynomial 4288 ideal JGr = groebner(J); // Groebner base of J 4289 4290 if(dbg>1){"Checking for new generators...";} 4291 for(i = 1; i <= ncols(J); i++){ 4292 for(j = 1; j <= ncols(U); j++){ 4293 p = lift(c, J[i]*U[j])[1,1]; 4294 p = reduce(p, JGr); 4295 if(p != 0){ 4296 if(dbg>1){ 4297 "New polynoial added:", p; 4298 if(dbg>4){pause();} 4299 } 4300 JGr = JGr, p; 4301 JGr = groebner(JGr); 4302 J = J, p; 4303 } 4304 } 4305 } 4306 return(J); 4307 } 4308 4309 /////////////////////////////////////////////////////////////////////////////// 4310 4311 static proc testIdeal(ideal I, ideal U, ideal origJ, poly c, poly D){ 4312 // Internal procedure, used in normalM. 4313 // Computes the test ideal in the new ring. 4314 // It takes the original test ideal and computes the radical of it in the 4315 // new ring. 4316 4317 // The new ring is 1/c * U. 4318 // The original test ideal is origJ. 4319 // The original ring is R / I, where R is the basering. 4320 int i; // counter 4321 int dbg = printlevel - voice + 2; // dbg = printlevel (default: dbg = 0) 4322 def R = basering; // We dont work in the quo 4323 ideal J = origJ; 4324 4325 // ---------- computation of the ring structure of 1/c * U ---------------- 4326 U = lineUp(U, c); 4327 4328 if(dbg > 1){"Computing the new ring structure...";} 4329 list ele = computeRing(U, I, "noRed"); 4330 4331 def origEre = ele[1]; 4332 setring origEre; 4333 if(dbg > 1){"The relations are"; norid;} 4334 4335 // ---------------- setting the ring to work in -------------------------- 4336 int isGlobal = ord_test(origEre); // Checks if the original ring has 4337 // global ordering. 4338 if(isGlobal != 1){ 4339 list rl = ringlist(origEre); 4340 list origOrd = rl[3]; 4341 list newOrd = list("dp", intvec(1:nvars(origEre))), list("C", 0); 4342 rl[3] = newOrd; 4343 def ere = ring(rl); // globR is the original ring but 4344 // with a global ordering. 4345 setring ere; 4346 ideal norid = imap(origEre, norid); 4347 } else { 4348 def ere = origEre; 4349 } 4350 4351 ideal I = imap(R, I); 4352 ideal J = imap(R, J); 4353 J = J, norid, I; 4354 4355 4356 // ----- computation of the test ideal using the ring structure of Ai ----- 4357 option("redSB"); 4358 option("returnSB"); 4359 4360 if(dbg > 1){"Computing the radical of J...";} 4361 J = radical(J); 4362 if(dbg > 1){"Computing the interreduction of the radical...";} 4363 J = groebner(J); 4364 //J = interred(J); 4365 if(dbg > 1){ 4366 "The radical in the generated ring is"; 4367 J; 4368 if(dbg>4){pause();} 4369 } 4370 4371 setring ere; 4372 4373 // -------------- map from Ai to the total ring of fractions --------------- 4374 // Now we must map back this ideal J to U_i / c in the total ring of 4375 // fractions. 4376 // The map sends T_j -> u_j / c. 4377 // The map is built by the following steps: 4378 // 1) We compute the degree of the generators of J with respect to the 4379 // new variables T_j. 4380 // 2) For each generator, we multiply each term by a power of c, as if 4381 // taking c^n as a common denominator (considering the new variables as 4382 // a polynomial in the old variables divided by c). 4383 // 3) We replace the new variables T_j by the corresponding numerator u_j. 4384 // 4) We lift the resulting polynomial to change the denominator 4385 // from c^n to c. 4386 int nNewVars = nvars(ere) - nvars(R); // Number of new variables 4387 poly c = imap(R, c); 4388 intvec @v = 1..nNewVars; // Vector of the new variables. 4389 // They must be the first ones. 4390 if(dbg > 1){"The indices of the new variables are", @v;} 4391 4392 // ---------------------- step 1 of the mapping --------------------------- 4393 intvec degs; 4394 for(i = 1; i<=ncols(J); i++){ 4395 degs[i] = degSubring(J[i], @v); 4396 } 4397 if(dbg > 1){ 4398 "The degrees with respect to the new variables are"; 4399 degs; 4400 } 4401 4402 // ---------------------- step 2 of the mapping --------------------------- 4403 ideal mapJ = mapBackIdeal(J, c, @v); 4404 4405 setring R; 4406 4407 // ---------------------- step 3 of the mapping --------------------------- 4408 ideal z; // The variables of the original ring in order. 4409 for(i = 1; i<=nvars(R); i++){ 4410 z[i] = var(i); 4411 } 4412 4413 map f = ere, U[2..ncols(U)], z[1..ncols(z)]; // The map to the original ring. 4414 if(dbg > 1){ 4415 "The map is "; 4416 f; 4417 if(dbg>4){pause();} 4418 } 4419 4420 if(dbg > 1){ 4421 "Computing the map..."; 4422 } 4423 4424 J = f(mapJ); 4425 if(dbg > 1){ 4426 "The ideal J mapped back (before lifting) is"; 4427 J; 4428 if(dbg>4){pause();} 4429 } 4430 4431 // ---------------------- step 4 of the mapping --------------------------- 4432 qring Q = groebner(I); 4433 ideal J = imap(R, J); 4434 poly c = imap(R, c); 4435 for(i = 1; i<=ncols(J); i++){ 4436 if(degs[i]>1){ 4437 J[i] = lift(c^(degs[i]-1), J[i])[1,1]; 4438 } else { 4439 if(degs[i]==0){ 4440 J[i] = c*J[i]; 4441 } 4442 } 4443 } 4444 4445 if(dbg > 1){ 4446 "The ideal J lifted is"; 4447 J; 4448 if(dbg>4){pause();} 4449 } 4450 4451 // --------------------------- prepare output ---------------------------- 4452 J = groebner(J); 4453 4454 setring R; 4455 J = imap(Q, J); 4456 4457 return(list(J, ele[1])); 4458 } 4459 4460 /////////////////////////////////////////////////////////////////////////////// 4461 4462 static proc changeDenominator(ideal U1, poly c1, poly c2, ideal I){ 4463 // Given a ring in the form 1/c1 * U, it computes a new ideal U2 such that the 4464 // ring is 1/c2 * U2. 4465 // The base ring is R, but the computations are to be done in R / I. 4466 int a; // counter 4467 def R = basering; 4468 qring Q = I; 4469 ideal U1 = fetch(R, U1); 4470 poly c1 = fetch(R, c1); 4471 poly c2 = fetch(R, c2); 4472 ideal U2 = changeDenominatorQ(U1, c1, c2); 4473 setring R; 4474 ideal U2 = fetch(Q, U2); 4475 return(U2); 4476 } 4477 4478 /////////////////////////////////////////////////////////////////////////////// 4479 4480 static proc changeDenominatorQ(ideal U1, poly c1, poly c2){ 4481 // Given a ring in the form 1/c1 * U, it computes a new U2 st the ring 4482 // is 1/c2 * U2. 4483 // The base ring is already a quotient ring R / I. 4484 int a; // counter 4485 ideal U2; 4486 poly p; 4487 for(a = 1; a <= ncols(U1); a++){ 4488 p = lift(c1, c2*U1[a])[1,1]; 4489 U2[a] = p; 4490 } 4491 return(U2); 4492 } 4493 4494 /////////////////////////////////////////////////////////////////////////////// 4495 4496 static proc checkInclusions(ideal U1, ideal U2){ 4497 // Checks if the identity A = Hom(J, J) of Grauert-Remmert criterion is 4498 // satisfied. 4499 int dbg = printlevel - voice + 2; // dbg = printlevel (default: dbg = 0) 4500 list reduction1; 4501 list reduction2; 4502 4503 // ---------------------- inclusion Hom(J, J) c A ------------------------- 4504 if(dbg > 1){"Checking the inclusion Hom(J, J) c A:";} 4505 // This interred is used only because a bug in groebner! 4506 U1 = groebner(U1); 4507 reduction1 = reduce(U2, U1); 4508 if(dbg > 1){reduction1[1];} 4509 4510 // ---------------------- inclusion A c Hom(J, J) ------------------------- 4511 // The following check should always be satisfied. 4512 // This is only used for debugging. 4513 if(dbg > 1){ 4514 "and the inclusion A c Hom(J, J): (this should always be satisfied)"; 4515 // This interred is used only because a bug in groebner! 4516 U2 = groebner(U2); 4517 reduction2 = reduce(U1, groebner(U2)); 4518 reduction2[1]; 4519 if(size(reduction2[1]) > 0){ 4520 "Something went wrong... (this inclusion should always be satisfied)"; 4521 ~; 4522 } else { 4523 if(dbg>4){pause();} 4524 } 4525 } 4526 4527 if(size(reduction1[1]) == 0){ 4528 // We are done! The ring computed in the last step was normal. 4529 return(1); 4530 } else { 4531 return(0); 4532 } 4533 } 4534 4535 /////////////////////////////////////////////////////////////////////////////// 4536 4537 static proc degSubring(poly p, intvec @v){ 4538 // Computes the degree of a polynomial taking only some variables as variables 4539 // and the others as parameters. 4540 4541 // The degree is taken wrt the variables indicated in v. 4542 int i; // Counter 4543 int d = 0; // The degree 4544 int e; // Degree (auxiliar variable) 4545 for(i = 1; i <= size(p); i++){ 4546 e = sum(leadexp(p[i]), @v); 4547 if(e > d){d = e;} 4548 } 4549 return(d); 4550 } 4551 4552 /////////////////////////////////////////////////////////////////////////////// 4553 4554 static proc mapBackIdeal(ideal I, poly c, intvec @v){ 4555 // Modifies all polynomials in I so that a map x(i) -> y(i)/c can be 4556 // carried out. 4557 4558 // v indicates wicih variables x(i) of the ring will be mapped to y(i)/c. 4559 4560 int i; // counter 4561 for(i = 1; i <= ncols(I); i++){ 4562 I[i] = mapBackPoly(I[i], c, @v); 4563 } 4564 return(I); 4565 } 4566 4567 /////////////////////////////////////////////////////////////////////////////// 4568 4569 static proc mapBackPoly(poly p, poly c, intvec @v){ 4570 // Multiplies each monomial of p by a power of c so that a map x(i) -> y(i)/c 4571 // can be carried out. 4572 4573 // v indicates wicih variables x(i) of the ring will be mapped to y(i)/c. 4574 int i; // counter 4575 int e; // exponent 4576 int d = degSubring(p, @v); 4577 poly g = 0; 4578 for(i = 1; i <= size(p); i++){ 4579 e = sum(leadexp(p[i]), @v); 4580 g = g + p[i] * c^(d-e); 4581 } 4582 return(g); 4583 } 4584 4585 // Up to here: procedures for normal 4586 /////////////////////////////////////////////////////////////////////////////// 4587 4588 4589 /////////////////////////////////////////////////////////////////////////////// 4590 // From here: procedures for normalC 4591 4592 // We first define resp. copy some attributes to be used in proc normal and 4593 // static proc normalizationPrimes, and ..., to speed up computation in 4594 // special cases 4595 //NOTE: We use the following attributes: 4596 // 1 attrib(id,"isCohenMacaulay"); //--- Cohen Macaulay 4597 // 2 attrib(id,"isCompleteIntersection"); //--- complete intersection 4598 // 3 attrib(id,"isHypersurface"); //--- hypersurface 4599 // 4 attrib(id,"isEquidimensional"); //--- equidimensional ideal 4600 // 5 attrib(id,"isPrim"); //--- prime ideal 4601 // 6 attrib(id,"isRegInCodim2"); //--- regular in codimension 2 4602 // 7 attrib(id,"isIsolatedSingularity"); //--- isolated singularities 4603 // 8 attrib(id,"onlySingularAtZero"); //--- only singular at 0 4604 // 9 attrib(id,"isRadical"); //--- radical ideal 4605 //Recall: (attrib(id,"xy"),1) sets attrib xy to TRUE and 4606 // (attrib(id,"xy"),0) to FALSE 4607 4608 static proc getAttrib (ideal id) 4609 "USAGE: getAttrib(id); id=ideal 4610 COMPUTE: check attributes for id. If the attributes above are defined, 4611 take its value, otherwise define it and set it to 0 4612 RETURN: intvec of size 9, with entries 0 or 1, values of attributes defined 4613 above (in this order) 4614 EXAMPLE: no example 4615 " 4616 { 4617 int isCoM,isCoI,isHy,isEq,isPr,isReg,isIso,oSAZ,isRad; 4618 4619 if( typeof(attrib(id,"isCohenMacaulay"))=="int" ) 4620 { 4621 if( attrib(id,"isCohenMacaulay")==1 ) 4622 { isCoM=1; isEq=1; } 4623 } 4624 4625 if( typeof(attrib(id,"isCompleteIntersection"))=="int" ) 4626 { 4627 if(attrib(id,"isCompleteIntersection")==1) 4628 { isCoI=1; isCoM=1; isEq=1; } 4629 } 4630 4631 if( typeof(attrib(id,"isHypersurface"))=="int" ) 4632 { 4633 if(attrib(id,"isHypersurface")==1) 4634 { isHy=1; isCoI=1; isCoM=1; isEq=1; } 4635 } 4636 4637 if( typeof(attrib(id,"isEquidimensional"))=="int" ) 4638 { 4639 if(attrib(id,"isEquidimensional")==1) 4640 { isEq=1; } 4641 } 4642 4643 if( typeof(attrib(id,"isPrim"))=="int" ) 4644 { 4645 if(attrib(id,"isPrim")==1) 4646 { isPr=1; } 4647 } 4648 4649 if( typeof(attrib(id,"isRegInCodim2"))=="int" ) 4650 { 4651 if(attrib(id,"isRegInCodim2")==1) 4652 { isReg=1; } 4653 } 4654 4655 if( typeof(attrib(id,"isIsolatedSingularity"))=="int" ) 4656 { 4657 if(attrib(id,"isIsolatedSingularity")==1) 4658 { isIso=1; } 4659 } 4660 4661 if( typeof(attrib(id,"onlySingularAtZero"))=="int" ) 4662 { 4663 if(attrib(id,"onlySingularAtZero")==1) 4664 { oSAZ=1; } 4665 } 4666 4667 if( typeof(attrib(id,"isRad"))=="int" ) 4668 { 4669 if(attrib(id,"isRad")==1) 4670 { isRad=1; } 4671 } 4672 4673 intvec atr = isCoM,isCoI,isHy,isEq,isPr,isReg,isIso,oSAZ,isRad; 4674 return(atr); 4675 } 4676 4677 /////////////////////////////////////////////////////////////////////////////// 4678 4679 static proc setAttrib (ideal id, intvec atr) 4680 "USAGE: setAttrib(id,atr); id ideal, atr intvec 4681 COMPUTE: set attributes to id specified by atr 4682 RETURN: id, with assigned attributes from atr 4683 EXAMPLE: no example 4684 " 4685 { 4686 attrib(id,"isCohenMacaulay",atr[1]); //--- Cohen Macaulay 4687 attrib(id,"isCompleteIntersection",atr[2]); //--- complete intersection 4688 attrib(id,"isHypersurface",atr[3]); //--- hypersurface 4689 attrib(id,"isEquidimensional",atr[4]); //--- equidimensional ideal 4690 attrib(id,"isPrim",atr[5]); //--- prime ideal 4691 attrib(id,"isRegInCodim2",atr[6]); //--- regular in codimension 2 4692 attrib(id,"isIsolatedSingularity",atr[7]); //--- isolated singularities 4693 attrib(id,"onlySingularAtZero",atr[8]); //--- only singular at 0 4694 attrib(id,"isRadical",atr[9]); //--- radical ideal 4695 4696 return(id); 4697 } 4698 4699 /////////////////////////////////////////////////////////////////////////////// 4700 // copyAttribs is not used anywhere so far 4701 4702 static proc copyAttribs (ideal id1, ideal id) 4703 "USAGE: copyAttribs(id1,id); id1, id ideals 4704 COMPUTE: copy attributes from id1 to id 4705 RETURN: id, with assigned attributes from id1 4706 EXAMPLE: no example 4707 " 4708 { 4709 if( typeof(attrib(id1,"isCohenMacaulay"))=="int" ) 4710 { 4711 if( attrib(id1,"isCohenMacaulay")==1 ) 4712 { 4713 attrib(id,"isEquidimensional",1); 4714 } 4715 } 4716 else 4717 { 4718 attrib(id,"isCohenMacaulay",0); 4719 } 4720 4721 if( typeof(attrib(id1,"isCompleteIntersection"))=="int" ) 4722 { 4723 if(attrib(id1,"isCompleteIntersection")==1) 4724 { 4725 attrib(id,"isCohenMacaulay",1); 4726 attrib(id,"isEquidimensional",1); 4727 } 4728 } 4729 else 4730 { 4731 attrib(id,"isCompleteIntersection",0); 4732 } 4733 4734 if( typeof(attrib(id1,"isHypersurface"))=="int" ) 4735 { 4736 if(attrib(id1,"isHypersurface")==1) 4737 { 4738 attrib(id,"isCompleteIntersection",1); 4739 attrib(id,"isCohenMacaulay",1); 4740 attrib(id,"isEquidimensional",1); 4741 } 4742 } 4743 else 4744 { 4745 attrib(id,"isHypersurface",0); 4746 } 4747 4748 if( (typeof(attrib(id1,"isEquidimensional"))=="int") ) 4749 { 4750 if(attrib(id1,"isEquidimensional")==1) 4751 { 4752 attrib(id,"isEquidimensional",1); 4753 } 4754 } 4755 else 4756 { 4757 attrib(id,"isEquidimensional",0); 4758 } 4759 4760 if( typeof(attrib(id1,"isPrim"))=="int" ) 4761 { 4762 if(attrib(id1,"isPrim")==1) 4763 { 4764 attrib(id,"isEquidimensional",1); 4765 } 4766 } 4767 else 4768 { 4769 attrib(id,"isPrim",0); 4770 } 4771 4772 if( (typeof(attrib(id1,"isRegInCodim2"))=="int") ) 4773 { 4774 if(attrib(id1,"isRegInCodim2")==1) 4775 { 4776 attrib(id,"isRegInCodim2",1); 4777 } 4778 } 4779 else 4780 { 4781 attrib(id,"isRegInCodim2",0); 4782 } 4783 4784 if( (typeof(attrib(id1,"isIsolatedSingularity"))=="int") ) 4785 { 4786 if(attrib(id1,"isIsolatedSingularity")==1) 4787 { 4788 attrib(id,"isIsolatedSingularity",1); 4789 } 4790 } 4791 else 4792 { 4793 attrib(id,"isIsolatedSingularity",0); 4794 } 4795 4796 if( typeof(attrib(id1,"onlySingularAtZero"))=="int" ) 4797 { 4798 if(attrib(id1,"onlySingularAtZero")==1) 4799 { 4800 attrib(id,"isIsolatedSingularity",1); 4801 } 4802 } 4803 else 4804 { 4805 attrib(id,"onlySingularAtZero",0); 4806 } 4807 4808 if( typeof(attrib(id1,"isRad"))=="int" ) 4809 { 4810 if(attrib(id1,"isRad")==1) 4811 { 4812 attrib(id,"isRad",1); 4813 } 4814 } 4815 else 4816 { 4817 attrib(id,"isRad",0); 4818 } 4819 4820 return(id); 4821 } 4822 4823 proc normalC(ideal id, list #) 4824 "USAGE: normalC(id [,choose]); id = radical ideal, choose = optional string 4825 which may be a combination of \"equidim\", \"prim\", \"withGens\", 4826 \"isPrim\", \"noFac\".@* 4827 If choose is not given or empty, a default method is choosen@* 4828 If choose = \"prim\" resp. \"equidim\" normalC computes a prime resp. 4829 an equidimensional decomposition and then the normalization of each 4830 component; if choose = \"noFac\" factorization is avoided in the 4831 computation of the minimal associated primes; @* 4832 if choose = \"withGens\" the minimal associated primes P_i of id are 4833 computed and for each P_i, algebra generators of the integral closure 4834 of basering/P_i are computed as elements of its quotient field;@* 4835 \"isPrim\" disables \"equidim\" and \"prim\".@* 4836 ASSUME: The ideal must be radical, for non-radical ideals the output may 4837 be wrong (id=radical(id); makes id radical). However, if choose = 4838 \"prim\" the minimal associated primes of id are computed first 4839 and hence normalC computes the normalization of the radical of id. 4840 \"isPrim\" should only be used if id is known to be irreducible. 4841 RETURN: a list, say nor, of size 2 (resp. 3 if choose=\"withGens\"). 4842 The first list nor[1] consists of r rings, where r is the number 4843 of irreducible components if choose = \"prim\" (resp. >= no of 4844 equidimenensional components if choose = \"equidim\"). 4845 @format 4846 Each ring Ri=nor[1][i], i=1..r, contains two ideals with given 4847 names @code{norid} and @code{normap} such that @* 4848 - Ri/norid is the normalization of the i-th component, i.e. the 4849 integral closure in its field of fractions (as affine ring); 4850 - the direct sum of the rings Ri/norid is the normalization 4851 of basering/id; @* 4852 - @code{normap} gives the normalization map from basering/id to 4853 Ri/norid for each j.@* 4854 4855 If choose=\"withGens\", nor[2] is a list of size r of ideals Ii= 4856 nor[2][i] in the basering, generating the integral closure of 4857 basering/P_i in its quotient field, i=1..r, in two different ways: 4858 - Ii is given by polynomials 4859 g_1,...,g_k,g_k+1 such that the variables T(j) of the ring Ri 4860 satisfy T(1)=g_1/g_k+1,..,T(k)=g_k/g_k+1. Hence the g_j/g_k+1 4861 are algebra generators of the integral closure of basering/P_i 4862 as sub-algebra in the quotient field of basering/P_i. 4863 4864 nor[2] (resp. nor[3] if choose=\"withGens\") is a list of an intvec 4865 of size r, the delta invariants of the r components, and an integer, 4866 the total delta invariant of basering/id (-1 means infinite, and 0 4867 that basering/P_i resp. basering/input is normal). 4868 Return value -2 means that delta resp. delta of one of the components 4869 is not computed (which may happen if \"equidim\" is given) . 4870 @end format 4871 THEORY: The delta invariant of a reduced ring K[x1,...,xn]/id is 4872 dim_K(normalization(K[x1,...,xn]/id) / K[x1,...,xn]/id) 4873 We call this number also the delta invariant of id. 4874 We use the algorithm described in [G.-M. Greuel, G. Pfister: 4875 A SINGULAR Introduction to Commutative Algebra, 2nd Edition. 4876 Springer Verlag (2007)]. 4877 NOTE: To use the i-th ring type: @code{def R=nor[1][i]; setring R;}. 4878 @* Increasing/decreasing printlevel displays more/less comments 4879 (default: printlevel=0). 4880 @* Not implemented for local or mixed orderings and for quotient rings. 4881 @* If the input ideal id is weighted homogeneous a weighted ordering may 4882 be used (qhweight(id); computes weights). 4883 KEYWORDS: normalization; integral closure; delta invariant. 4884 EXAMPLE: example normalC; shows an example 4885 " 4886 { 4887 int i,j, wgens, withEqui, withPrim, isPrim, nfac; 4888 int y = printlevel-voice+2; 4889 int nvar = nvars(basering); 4890 int chara = char(basering); 4891 list result,prim,keepresult; 4892 4893 if ( ord_test(basering) != 1 ) 4894 { 4895 ""; 4896 "// Not implemented for this ordering,"; 4897 "// please change to global ordering!"; 4898 return(result); 4899 } 4900 4901 //--------------------------- define the method --------------------------- 4902 string method; //make all options one string in order to use 4903 //all combinations of options simultaneously 4904 for ( i=1; i <= size(#); i++ ) 4905 { 4906 if ( typeof(#[i]) == "string" ) 4907 { 4908 method = method + #[i]; 4909 } 4910 } 4911 4912 //--------------------------- choosen methods ----------------------- 4913 //we have the methods 4914 // "withGens": computes algebra generators for each irreducible component 4915 // the general case: either "equidim" or not (then applying minAssGTZ) 4916 4917 if ( find(method,"withgens") or find(method,"withGens")) 4918 { 4919 wgens=1; 4920 } 4921 if ( find(method,"equidim") ) 4922 { 4923 withEqui=1; 4924 } 4925 if ( find(method,"prim") ) 4926 { 4927 withPrim=1; 4928 } 4929 if ( find(method,"isprim") or find(method,"isPrim") ) 4930 { 4931 isPrim=1; 4932 } 4933 if ( find(method,"noFac") ) 4934 { 4935 nfac=1; 4936 } 4937 4938 //------------------ default method, may be changed -------------------- 4939 //Use a prime decomposition only for small no of variables otherwise equidim 4940 //Compute delta whenever possible. 4941 4942 if ( ((chara==0 || chara>30) && nvar>2 && !withPrim && !isPrim) || 4943 ((chara==0 || chara>30) && size(#) == 0) ) 4944 { 4945 withEqui=1; 4946 } 4947 kill #; 4948 list #; 4949 4950 //------- Special algorithm with computation of the generators, RETURN ------- 4951 //--------------------- method "withGens" ---------------------------------- 4952 //the integral closure is computed in proc primeClosure. In the general case 4953 //it is computed in normalizationPrimes. The main difference is that in 4954 //primeClosure the singular locus is only computed in the first iteration 4955 //that no attributes are used and that the generators are computed. 4956 //In primeClosure the (algebra) generators for each irreducible component 4957 //are computed in static proc closureGenerators 4958 4959 if( wgens ) 4960 { 4961 if( y >= 1 ) 4962 { ""; 4963 "// We use method 'withGens'"; 4964 } 4965 if ( isPrim ) 4966 { 4967 prim[1] = id; 4968 if( y >= 0 ) 4969 { 4970 ""; 4971 "// ** WARNING: result is correct if ideal is prime (not checked) **"; 4972 "// if procedure is called with string \"prim\", primality is checked"; 4973 } 4974 } 4975 else 4976 { 4977 if(y>=1) 4978 { "// compute minimal associated primes"; } 4979 4980 if( nfac ) 4981 { prim = minAssGTZ(id,1); } 4982 else 4983 { prim = minAssGTZ(id); } 4984 4985 if(y>=1) 4986 { 4987 prim;""; 4988 "// number of irreducible components is", size(prim); 4989 } 4990 } 4991 //----------- compute integral closure for every component ------------- 4992 int del; 4993 intvec deli; 4994 list Gens,l,resu,Resu; 4995 ideal gens; 4996 def R = basering; 4997 poly gg; 4998 4999 for(i=1; i<=size(prim); i++) 5000 { 5001 if(y>=1) 5002 { 5003 ""; pause(); ""; 5004 "// start computation of component",i; 5005 " --------------------------------"; 5006 } 5007 5008 if( defined(ker) ) { kill ker; } 5009 ideal ker = prim[i]; 5010 export(ker); 5011 l = R; 5012 l = primeClosure(l,1); //here the work is done 5013 //### ausprobieren ob primeClosure(l,1) schneller als primeClosure(l) 5014 // 1 bedeutet: krzester nzd 5015 5016 if ( l[size(l)] >= 0 && del >= 0 ) 5017 { 5018 del = del + l[size(l)]; 5019 } 5020 else 5021 { del = -1; } 5022 deli = l[size(l)],deli; 5023 5024 l = l[1..size(l)-1]; 5025 resu = list(l[size(l)]) + resu; 5026 gens = closureGenerators(l); //computes algebra(!) generators 5027 5028 //NOTE: gens[i]/gens[size(gens)] expresses the ith variable of resu[1] 5029 //(the normalization) as fraction of elements of the basering; 5030 //the variables of resu[1] are algebra generators. 5031 //gens[size(gens)] is a non-zero divisor of basering/i 5032 5033 //divide by the greatest common divisor: 5034 gg = gcd( gens[1],gens[size(gens)] ); 5035 for(j=2; j<=size(gens)-1; j++) 5036 { 5037 gg=gcd(gg,gens[j]); 5038 } 5039 for(j=1; j<=size(gens); j++) 5040 { 5041 gens[j]=gens[j]/gg; 5042 } 5043 Gens = list(gens) + Gens; 5044 5045 /* ### Da die gens Algebra-Erzeuger sind, ist reduce nach Bestimmung 5046 der Algebra-Variablen T(i) nicht zulssig! 5047 for(i=1;i<=size(gens)-1;i++) 5048 { 5049 gens[i]= reduce(gens[i],std(gens[size(gens)])); 5050 } 5051 for(i=size(gens)-1; i>=1; i--) 5052 { 5053 if(gens[i]==0) 5054 { gens = delete(gens,i); } 5055 } 5056 */ 5057 if( defined(ker) ) { kill ker; } 5058 } 5059 5060 if ( del >= 0 ) 5061 { 5062 int mul = iMult(prim); 5063 del = del + mul; 5064 } 5065 else 5066 { del = -1; } 5067 deli = deli[1..size(deli)-1]; 5068 Resu = resu,Gens,list(deli,del); 5069 int sr = size(resu); 5070 5071 if ( y >= 0 ) 5072 {""; 5073 "// 'normalC' created a list, say nor, of three lists: 5074 // nor[1] resp. nor[2] are lists of",sr,"ring(s) resp. ideal(s) 5075 // and nor[3] is a list of an intvec and an integer. 5076 // To see the result, type 5077 nor; 5078 // To access the i-th ring nor[1][i] give it a name, say Ri, and type e.g. 5079 def R1 = nor[1][1]; setring R1; norid; normap; 5080 // for the other rings type first setring r; (if r is the name of your 5081 // original basering) and then continue as for the first ring; 5082 // Ri/norid is the affine algebra of the normalization of the i-th 5083 // component r/P_i (where P_i is an associated prime of the input ideal) 5084 // and normap the normalization map from r to Ri/norid; 5085 // nor[2] is a list of",sr,"ideal(s), each ideal nor[2][i] consists of 5086 // elements g1..gk of r such that the gj/gk generate the integral 5087 // closure of r/P_i as sub-algebra in the quotient field of r/P_i, with 5088 // gj/gk being mapped by normap to the j-th variable of Ri; 5089 // nor[3] shows the delta-invariant of each component and of the input 5090 // ideal (-1 means infinite, and 0 that r/P_i resp. r/input is normal)."; 5091 } 5092 return(Resu); 5093 } 5094 5095 //-------- The general case without computation of the generators ----------- 5096 // (attrib(id,"xy"),1) sets attrib xy to TRUE and (attrib(id,"xy"),0) to FALSE 5097 // We use the following attributes: 5098 // attrib(id,"isCohenMacaulay"); //--- Cohen Macaulay 5099 // attrib(id,"isCompleteIntersection"); //--- complete intersection 5100 // attrib(id,"isHypersurface"); //--- hypersurface 5101 // attrib(id,"isEquidimensional",-1); //--- equidimensional ideal 5102 // attrib(id,"isPrim"); //--- prime ideal 5103 // attrib(id,"isRegInCodim2"); //--- regular in codimension 2 5104 // attrib(id,"isIsolatedSingularity"; //--- isolated singularities 5105 // attrib(id,"onlySingularAtZero"); //--- only singular at 0 5106 5107 //------------------- first set the attributes ---------------------- 5108 if( typeof(attrib(id,"isCohenMacaulay"))=="int" ) 5109 { 5110 if( attrib(id,"isCohenMacaulay")==1 ) 5111 { 5112 attrib(id,"isEquidimensional",1); 5113 } 5114 } 5115 else 5116 { 5117 attrib(id,"isCohenMacaulay",0); 5118 } 5119 5120 if( typeof(attrib(id,"isCompleteIntersection"))=="int" ) 5121 { 5122 if(attrib(id,"isCompleteIntersection")==1) 5123 { 5124 attrib(id,"isCohenMacaulay",1); 5125 attrib(id,"isEquidimensional",1); 5126 } 5127 } 5128 else 5129 { 5130 attrib(id,"isCompleteIntersection",0); 5131 } 5132 5133 if( typeof(attrib(id,"isHypersurface"))=="int" ) 5134 { 5135 if(attrib(id,"isHypersurface")==1) 5136 { 5137 attrib(id,"isCompleteIntersection",1); 5138 attrib(id,"isCohenMacaulay",1); 5139 attrib(id,"isEquidimensional",1); 5140 } 5141 } 5142 else 5143 { 5144 attrib(id,"isHypersurface",0); 5145 } 5146 5147 if( ! (typeof(attrib(id,"isEquidimensional"))=="int") ) 5148 { 5149 attrib(id,"isEquidimensional",0); 5150 } 5151 5152 if( typeof(attrib(id,"isPrim"))=="int" ) 5153 { 5154 if(attrib(id,"isPrim")==1) 5155 { 5156 attrib(id,"isEquidimensional",1); 5157 } 5158 } 5159 else 5160 { 5161 attrib(id,"isPrim",0); 5162 } 5163 5164 if( ! (typeof(attrib(id,"isRegInCodim2"))=="int") ) 5165 { 5166 attrib(id,"isRegInCodim2",0); 5167 } 5168 5169 if( ! (typeof(attrib(id,"isIsolatedSingularity"))=="int") ) 5170 { 5171 attrib(id,"isIsolatedSingularity",0); 5172 } 5173 5174 if( typeof(attrib(id,"onlySingularAtZero"))=="int" ) 5175 { 5176 if(attrib(id,"onlySingularAtZero")==1) 5177 { 5178 attrib(id,"isIsolatedSingularity",1); 5179 } 5180 } 5181 else 5182 { 5183 attrib(id,"onlySingularAtZero",0); 5184 } 5185 5186 //-------------- compute equidimensional decomposition -------------------- 5187 //If the method "equidim" is given, compute the equidim decomposition 5188 //and goto the next step (no normalization 5189 //ACHTUNG: equidim berechnet bei nicht reduzierten id die eingebetteten 5190 //Komponenten als niederdim Komponenten, waehrend diese bei primdecGTZ 5191 //nicht auftauchen: ideal(x,y)*xy 5192 //this is default for nvars > 2 and char = 0 or car > 30 5193 5194 if( withEqui ) 5195 { 5196 withPrim = 0; //this is used to check later that prim 5197 //contains equidim but not prime components 5198 if( y >= 1 ) 5199 { 5200 "// We use method 'equidim'"; 5201 } 5202 if( typeof(attrib(id,"isEquidimensional"))=="int" ) 5203 { 5204 if(attrib(id,"isEquidimensional")==1) 5205 { 5206 prim[1] = id; 5207 } 5208 else 5209 { 5210 prim = equidim(id); 5211 } 5212 } 5213 else 5214 { 5215 prim = equidim(id); 5216 } 5217 if(y>=1) 5218 { ""; 5219 "// number of equidimensional components:", size(prim); 5220 } 5221 if ( !nfac ) 5222 { 5223 intvec opt = option(get); 5224 option(redSB); 5225 for(j=1; j<=size(prim); j++) 5226 { 5227 keepresult = keepresult+facstd(prim[j]); 5228 } 5229 prim = keepresult; 5230 if ( size(prim) == 0 ) 5231 { 5232 prim=ideal(0); //Bug in facstd, liefert leere Liste bei 0-Ideal 5233 } 5234 5235 if(y>=1) 5236 { ""; 5237 "// number of components after application of facstd:", size(prim); 5238 } 5239 option(set,opt); 5240 } 5241 } 5242 5243 //------------------- compute associated primes ------------------------- 5244 //the case where withEqui = 0, here the min. ass. primes are computed 5245 //start with the computation of the minimal associated primes: 5246 5247 else 5248 { 5249 if( isPrim ) 5250 { 5251 if( y >= 0 ) 5252 { 5253 "// ** WARNING: result is correct if ideal is prime"; 5254 "// or equidimensional (not checked) **"; 5255 "// disable option \"isPrim\" to decompose ideal into prime"; 5256 "// or equidimensional components";""; 5257 } 5258 if( y >= 1 ) 5259 { 5260 "// We use method 'isPrim'";""; 5261 } 5262 prim[1]=id; 5263 } 5264 else 5265 { 5266 withPrim = 1; //this is used to check later that prim 5267 //contains prime but not equidim components 5268 if( y >= 1 ) 5269 { 5270 "// We use method 'prim'"; 5271 } 5272 5273 if( typeof(attrib(id,"isPrim"))=="int" ) 5274 { 5275 if(attrib(id,"isPrim")==1) 5276 { 5277 prim[1]=id; 5278 } 5279 else 5280 { 5281 if( nfac ) 5282 { prim=minAssGTZ(id,1); } //does not use factorizing groebner 5283 else 5284 { prim=minAssGTZ(id); } //uses factorizing groebner 5285 } 5286 } 5287 else 5288 { 5289 if( nfac ) 5290 { prim=minAssGTZ(id,1); } 5291 else 5292 { prim=minAssGTZ(id); } 5293 } 5294 if(y>=1) 5295 { ""; 5296 "// number of irreducible components:", size(prim); 5297 } 5298 } 5299 } 5300 5301 //----- for each component (equidim or irred) compute normalization ----- 5302 int sr, skr, del; 5303 intvec deli; 5304 int sp = size(prim); //size of list prim (# irred or equidim comp) 5305 5306 for(i=1; i<=sp; i++) 5307 { 5308 if(y>=1) 5309 { ""; 5310 "// computing the normalization of component",i; 5311 " ----------------------------------------"; 5312 } 5313 //-------------- first set attributes for components ------------------ 5314 attrib(prim[i],"isEquidimensional",1); 5315 if( withPrim ) 5316 { 5317 attrib(prim[i],"isPrim",1); 5318 } 5319 else 5320 { attrib(prim[i],"isPrim",0); } 5321 5322 if(attrib(id,"onlySingularAtZero")==1) 5323 { attrib(prim[i],"onlySingularAtZero",1); } 5324 else 5325 { attrib(prim[i],"onlySingularAtZero",0); } 5326 5327 if(attrib(id,"isIsolatedSingularity")==1) 5328 { attrib(prim[i],"isIsolatedSingularity",1); } 5329 else 5330 { attrib(prim[i],"isIsolatedSingularity",0); } 5331 5332 if( attrib(id,"isHypersurface")==1 ) 5333 { 5334 attrib(prim[i],"isHypersurface",1); 5335 attrib(prim[i],"isCompleteIntersection",1); 5336 attrib(prim[i],"isCohenMacaulay",1); 5337 } 5338 else 5339 { attrib(prim[i],"isHypersurface",0); } 5340 5341 if ( sp == 1) //the case of one component: copy attribs from id 5342 { 5343 if(attrib(id,"isRegInCodim2")==1) 5344 {attrib(prim[i],"isRegInCodim2",1); } 5345 else 5346 {attrib(prim[i],"isRegInCodim2",0); } 5347 5348 if(attrib(id,"isCohenMacaulay")==1) 5349 {attrib(prim[i],"isCohenMacaulay",1); } 5350 else 5351 {attrib(prim[i],"isCohenMacaulay",0); } 5352 5353 if(attrib(id,"isCompleteIntersection")==1) 5354 {attrib(prim[i],"isCompleteIntersection",1); } 5355 else 5356 {attrib(prim[i],"isCompleteIntersection",0); } 5357 } 5358 else 5359 { 5360 attrib(prim[i],"isRegInCodim2",0); 5361 attrib(prim[i],"isCohenMacaulay",0); 5362 attrib(prim[i],"isCompleteIntersection",0); 5363 } 5364 5365 //------ Now compute the normalization of each component --------- 5366 //note: for equidimensional components the "splitting tools" can 5367 //create further decomposition 5368 //We now start normalizationPrimes with 5369 //ihp = partial normalisation map = identity map = maxideal(1) 5370 //del = partial delta invariant = 0 5371 //deli= intvec of partial delta invariants of components 5372 //in normalizationPrimes all the work is done: 5373 5374 keepresult = normalizationPrimes(prim[i],maxideal(1),0,0); 5375 5376 for(j=1; j<=size(keepresult)-1; j++) 5377 { 5378 result=insert(result,keepresult[j]); 5379 } 5380 skr = size(keepresult); 5381 5382 //compute delta: 5383 if( del >= 0 && keepresult[skr][1] >=0 ) 5384 { 5385 del = del + keepresult[skr][1]; 5386 } 5387 else 5388 { 5389 del = -1; 5390 } 5391 deli = keepresult[skr][2],deli; 5392 5393 if ( y>=1 ) 5394 { 5395 "// delta of component",i; keepresult[skr][1]; 5396 } 5397 } 5398 sr = size(result); 5399 5400 // -------------- Now compute intersection multiplicities ------------- 5401 //intersection multiplicities of list prim, sp=size(prim). 5402 if ( y>=1 ) 5403 { 5404 "// Sum of delta for all components"; del; 5405 if ( sp>1 ) 5406 { 5407 "// Compute intersection multiplicities of the components"; 5408 } 5409 } 5410 5411 if ( sp > 1 ) 5412 { 5413 int mul = iMult(prim); 5414 if ( mul < 0 ) 5415 { 5416 del = -1; 5417 } 5418 else 5419 { 5420 del = del + mul; 5421 } 5422 } 5423 deli = deli[1..size(deli)-1]; 5424 result = result,list(deli,del); 5425 5426 //--------------- Finally print comments and return ------------------ 5427 if ( y >= 0) 5428 {""; 5429 "// 'normalC' created a list, say nor, of two lists: 5430 // nor[1] is a list of",sr,"ring(s), nor[2] a list of an intvec and an int. 5431 // To see the result, type 5432 nor; 5433 // To access the i-th ring nor[1][i] give it a name, say Ri, and type e.g. 5434 def R1 = nor[1][1]; setring R1; norid; normap; 5435 // and similair for the other rings nor[1][i]; 5436 // Ri/norid is the affine algebra of the normalization of the i-th component 5437 // r/P_i (where P_i is a prime or an equidimensional ideal of the input ideal) 5438 // and normap the normalization map from the basering to Ri/norid; 5439 // nor[2] shows the delta-invariant of each component and of the input 5440 // ideal (-1 means infinite, -2 that delta of a component was not computed)."; 5441 } 5442 return(result); 5443 } 5444 5445 example 5446 { "EXAMPLE:"; 5447 printlevel = printlevel+1; 5448 echo = 2; 5449 ring s = 0,(x,y),dp; 5450 ideal i = (x2-y3)*(x2+y2)*x; 5451 5452 list nor = normalC(i); 5453 5454 nor; 5455 // 2 branches have delta = 1, and 1 branch has delta = 0 5456 // the total delta invariant is 13 5457 5458 def R2 = nor[1][2]; setring R2; 5459 norid; normap; 5460 5461 echo = 0; 5462 printlevel = printlevel-1; 5463 pause(" hit return to continue"); echo=2; 5464 5465 ring r = 2,(x,y,z),dp; 5466 ideal i = z3-xy4; 5467 nor = normalC(i); nor; 5468 // the delta invariant is infinite 5469 // xy2z/z2 and xy3/z2 generate the integral closure of r/i as r/i-module 5470 // in its quotient field Quot(r/i) 5471 5472 // the normalization as affine algebra over the ground field: 5473 def R = nor[1][1]; setring R; 5474 norid; normap; 5475 5476 echo = 0; 5477 pause(" hit return to continue");echo = 2; 5478 5479 setring r; 5480 nor = normalC(i, "withGens", "prim"); // a different algorithm 5481 nor; 5482 } 5483 5484 ////////////////////////////////////////////////////////////////////////////// 5485 //closureRingtower seems not to be used anywhere 5486 static proc closureRingtower(list L) 5487 "USAGE: closureRingtower(list L); L a list of rings 5488 CREATE: rings R(1),...,R(n) such that R(i)=L[i] for all i 5489 EXAMPLE: example closureRingtower; shows an example 5490 " 5491 { 5492 int n=size(L); 5493 for (int i=1;i<=n;i++) 5494 { 5495 if (defined(R(i))) { 5496 string s="Fixed name R("+string(i)+") leads to conflict with existing " 5497 +"object having this name"; 5498 ERROR(s); 5499 } 5500 def R(i)=L[i]; 5501 export R(i); 5502 } 5503 5504 return(); 5505 } 5506 example 5507 { 5508 "EXAMPLE:"; echo=2; 5509 ring R=0,(x,y),dp; 5510 ideal I=x4,y4; 5511 list L=primeClosure(ReesAlgebra(I)[1]); 5512 L=delete(L,size(L)); 5513 L; 5514 closureRingtower(L); 5515 R(1); 5516 R(4); 5517 kill R(1),R(2),R(3),R(4); 5518 } 5519 5520 // Up to here: procedures for normalC 5521 /////////////////////////////////////////////////////////////////////////////// 5522 5523 /////////////////////////////////////////////////////////////////////////////// 5524 // From here: miscellaneous procedures 5525 5526 // Used for timing and comparing the different normalization procedures. 5527 // Option (can be entered in any order) 5528 // "normal" -> uses the new algortihm (normal) 5529 // "normalP" -> uses normalP 5530 // "normalC" -> uses normalC, without "withGens" option 5531 // "primCl" -> uses normalC, with option "withGens". 5532 // "111" -> checks the output of normalM using norTest. 5533 // "p" -> compares the output of norM with the output of normalP 5534 // ("normalP" option must also be set). 5535 // "pc" -> compares the output of norM with the output of normalC with 5536 // option "withGens" 5537 // ("primCl" option must also be set). 5538 proc timeNormal(ideal I, list #){ 5539 //--------------------------- define the method --------------------------- 5540 int isPrim, useRing; 5541 int decomp = -1; 5542 int norM, norC, norP, primCl; 5543 int checkP, check111, checkPC; 5544 int i; 5545 ideal U1, U2, W; 5546 poly c1, c2; 5547 int ch; 5548 string check; 5549 string method; //make all options one string in order to use 5550 //all combinations of options simultaneously 5551 for ( i=1; i <= size(#); i++ ) 5552 { 5553 if ( typeof(#[i]) == "string" ) 5554 { 5555 method = method + #[i]; 5556 } 5557 } 5558 if ( find(method, "normal")) 5559 {norM = 1;} 5560 if ( find(method, "normalP") and (char(basering) > 0)) 5561 {norP = 1;} 5562 if ( find(method, "normalC")) 5563 {norC = 1;} 5564 if ( find(method, "primCl")) 5565 {primCl = 1;} 5566 if ( find(method, "isprim") or find(method,"isPrim") ) 5567 {decomp = 0;} 5568 if ( find(method, "p") ) 5569 {checkP = 1;} 5570 if ( find(method, "pc") ) 5571 {checkPC = 1;} 5572 if ( find(method, "111") ) 5573 {check111 = 1;} 5574 5575 int tt; 5576 if(norM){ 5577 tt = timer; 5578 if(decomp == 0){ 5579 "Running normal(useRing, isPrim)..."; 5580 list a1 = normal(I, "useRing", "isPrim"); 5581 "Time normal(useRing, isPrim): ", timer - tt; 5582 } else { 5583 "Running normal(useRing)..."; 5584 list a1 = normal(I, "useRing"); 5585 "Time normal(useRing): ", timer - tt; 5586 } 5587 ""; 5588 } 5589 if(norP){ 5590 tt = timer; 5591 if(decomp == 0){ 5592 "Running normalP(isPrim)..."; 5593 list a2 = normalP(I, "isPrim"); 5594 "Time normalP(isPrim): ", timer - tt; 5595 } else { 5596 "Running normalP()..."; 5597 list a2 = normalP(I); 5598 "Time normalP(): ", timer - tt; 5599 } 5600 ""; 5601 } 5602 5603 if(norC){ 5604 tt = timer; 5605 if(decomp == 0){ 5606 "Running normalC(isPrim)..."; 5607 list a3 = normalC(I, "isPrim"); 5608 "Time normalC(isPrim): ", timer - tt; 5609 } else { 5610 "Running normalC()..."; 5611 list a3 = normalC(I); 5612 "Time normalC(): ", timer - tt; 5613 } 5614 ""; 5615 } 5616 5617 if(primCl){ 5618 tt = timer; 5619 if(decomp == 0){ 5620 "Running normalC(withGens, isPrim)..."; 5621 list a4 = normalC(I, "isPrim", "withGens"); 5622 "Time normalC(withGens, isPrim): ", timer - tt; 5623 } else { 5624 "Running normalC(withGens)..."; 5625 list a4 = normalC(I, "withGens"); 5626 "Time normalC(withGens): ", timer - tt; 5627 } 5628 ""; 5629 } 5630 5631 if(check111 and norM){ 5632 "Checking output with norTest..."; 5633 "WARNING: this checking only works if the original ideal was prime."; 5634 list norL = list(a1[1][1][3]); 5635 norTest(I, list(norL)); 5636 ""; 5637 } 5638 5639 if(checkP and norP and norM){ 5640 "Comparing with normalP output..."; 5641 "WARNING: this checking only works if the original ideal was prime."; 5642 U1 = a1[1][1][1]; 5643 c1 = a1[1][1][2]; 5644 U2 = a2[1][1]; 5645 c2 = a2[1][1][size(a2[1][1])]; 5646 W = changeDenominator(U1, c1, c2, groebner(I)); 5647 qring q = groebner(I); 5648 ideal U2 = fetch(r, U2); 5649 ideal W = fetch(r, W); 5650 ch = 0; 5651 if(size(reduce(U2, groebner(W))) == 0){ 5652 "U2 c U1"; 5653 ch = 1; 5654 } 5655 if(size(reduce(W, groebner(U2))) == 0){ 5656 "U1 c U2"; 5657 ch = ch + 1; 5658 } 5659 if(ch == 2){ 5660 "Output of normalP is equal."; 5661 } else { 5662 "ERROR: Output of normalP is different."; 5663 } 5664 ""; 5665 setring r; 5666 kill q; 5667 } 5668 5669 if(checkPC and norM and primCl){ 5670 "Comparing with primeClosure output..."; 5671 "WARNING: this checking only works if the original ideal was prime."; 5672 // primeClosure check 5673 U1 = a1[1][1][1]; 5674 c1 = a1[1][1][2]; 5675 U2 = a4[2][1]; 5676 c2 = a4[2][1][size(a4[2][1])]; 5677 W = changeDenominator(U1, c1, c2, groebner(I)); 5678 qring q = groebner(I); 5679 ideal U2 = fetch(r, U2); 5680 ideal W = fetch(r, W); 5681 ch = 0; 5682 if(size(reduce(U2, groebner(W))) == 0){ 5683 "U2 c U1"; 5684 ch = 1; 5685 } 5686 if(size(reduce(W, groebner(U2))) == 0){ 5687 "U1 c U2"; 5688 ch = ch + 1; 5689 } 5690 if(ch == 2){ 5691 "Output of normalC(withGens) is equal."; 5692 } else { 5693 "ERROR: Output of normalC(withGens) is different."; 5694 } 5695 ""; 5696 setring r; 5697 kill q; 5698 } 5699 } 5700 2444 5701 /////////////////////////////////////////////////////////////////////////// 2445 5702 proc norTest (ideal i, list nor, list #) 5703 "USAGE: norTest(i,nor,[n]); i=prime ideal, nor=list, n=optional integer 5704 ASSUME: nor is the resulting list of normal(i) (any options) or the result 5705 of normalP(i,"withRing"). In particular, the ring nor[1][1] contains 5706 the ideal norid and the map normap: basering/i --> nor[1][1]/norid. 5707 RETURN: an intvec v such that: 5708 @format 5709 v[1] = 1 if the normap is injective and 0 otherwise 5710 v[2] = 1 if the normap is finite and 0 otherwise 5711 v[3] = 1 if nor[1][1]/norid is normal and 0 otherwise 5712 @end format 5713 If n=1 (resp n=2) only v[1] (resp. v[2]) is computed and returned 5714 THEORY: The procedure can be used to test whether the computation of the 5715 normalization was correct: basering/i --> nor[1][1]/norid is the 5716 normalization of basering/i iff v=1,1,0. 5717 NOTE: For big examples it can be hard to fully test correctness; the 5718 partial test norTest(i,nor,2) is usually fast 5719 EXAMPLE: example norTest; shows an example 5720 " 5721 { 5722 //### Sollte erweitert werden auf den reduziblen Fall: einen neuen affinen 5723 // Ring nor[1][1]+...+nor[1][r] (direkte Summe) erzeugen, map dorthin 5724 // definieren und dann testen. 5725 5726 int prl = printlevel - voice + 2; 5727 int a,b,d; 5728 int n,ii; 5729 if (size(#) > 0) { n = #[1]; } 5730 5731 def BAS = basering; 5732 5733 //### make a copy of nor to have a cpoy of nor[1][1] (not a reference to) 5734 // in order not to overwrite norid and normap. 5735 // delete nor[2] (if it contains the module generators, which are not used) 5736 // s.t. newnor does not belong to a ring. 5737 5738 list newnor = nor; 5739 if ( size(newnor) == 3 ) 5740 { 5741 newnor = delete(newnor,2); 5742 } 5743 qring QAS = std(i); 5744 5745 def R = newnor[1][1]; 5746 setring R; 5747 int nva = nvars(R); 5748 string svars = varstr(R); 5749 string svar; 5750 5751 norid = interred(norid); 5752 5753 //--------- create new ring with one dp block keeping weights ------------ 5754 list LR = ringlist(R); 5755 list g3 = LR[3]; 5756 int n3 = size(g3); 5757 list newg3; 5758 intvec V; 5759 5760 //--------- check first whether variables Z(i),...,A(i) exist ----------- 5761 for (ii=90; ii>=65; ii--) 5762 { 5763 if ( find(svars,ASCII(ii)+"(") == 0 ) 5764 { 5765 svar = ASCII(ii); break; 5766 } 5767 } 5768 if ( size(svar) != 0 ) 5769 { 5770 for ( ii = 1; ii <= nva; ii++ ) 5771 { 5772 LR[2][ii] = svar+"("+string(ii)+")"; 5773 V[ii] = 1; 5774 } 5775 } 5776 else 5777 { 5778 for ( ii = 1; ii <= nva; ii++ ) 5779 { 5780 LR[2][ii] = "Z("+string(100*nva+ii)+")"; 5781 V[ii] = 1; 5782 } 5783 } 5784 5785 if ( g3[n3][1]== "c" or g3[n3][1] == "C" ) 5786 { 5787 list gm = g3[n3]; //last blockis module ordering 5788 newg3[1] = list("dp",V); 5789 newg3 = insert(newg3,gm,size(newg3)); 5790 } 5791 else 5792 { 5793 list gm = g3[1]; //first block is module ordering 5794 newg3[1] = list("dp",V); 5795 newg3 = insert(newg3,gm); 5796 } 5797 LR[3] = newg3; 5798 //LR;""; 5799 def newR = ring(LR); 5800 5801 setring newR; 5802 ideal norid = fetch(R,norid); 5803 ideal normap = fetch(R,normap); 5804 if( defined(lnorid) ) { kill lnorid; } //um ** redefinig zu beheben 5805 if( defined(snorid) ) { kill snorid; } //sollte nicht noetig sein 5806 5807 //----------- go to quotient ring for checking injectivity ------------- 5808 //"mstd"; 5809 list lnorid = mstd(norid); 5810 ideal snorid = lnorid[1]; 5811 //"size mstdnorid:", size(snorid),size(lnorid[2]); 5812 //"size string mstdnorid:", size(string(snorid)),size(string(lnorid[2])); 5813 qring QR = snorid; 5814 ideal qnormap = fetch(newR,normap); 5815 //ideal qnormap = imap(newR,normap); 5816 //ideal qnormap = imap(R,normap); 5817 map Qnormap = QAS,qnormap; //r/id --> R/norid 5818 5819 //------------------------ check injectivity --------------------------- 5820 //"injective:"; 5821 a = is_injective(Qnormap,QAS); //a. Test for injectivity of Qnormap 5822 dbprint ( prl, "injective: "+string(a) ); 5823 if ( n==1 ) { return (a); } 5824 a; 5825 5826 //------------------------ check finiteness --------------------------- 5827 setring newR; 5828 b = mapIsFinite(normap,BAS,lnorid[2]); //b. Test for finiteness of normap 5829 dbprint ( prl, "finite: "+string(b) ); 5830 if ( n==2 ) { return (intvec(a,b)); } 5831 b; 5832 5833 //------------------------ check normality --------------------------- 5834 list testnor = normal(lnorid[2],"isPrim","noFac"); 5835 //### Problem: bei mehrfachem Aufruf von norTest gibt es 5836 // ** redefining norid & ** redefining normap 5837 //Dies produziert Fehler, da alte norid und normap ueberschrieben werden 5838 //norid und normap werden innnerhalb von proc computeRing ueberschrieben 5839 //Die Kopie newR scheint das Problem zu loesen 5840 5841 printlevel=prl; 5842 d = testnor[size(testnor)][2]; //d = delta 5843 kill testnor; //### sollte ueberfluessig sein 5844 int d1 = (d==0); //d1=1 if delta=0 5845 dbprint ( prl, "delta: "+string(d) ); 5846 return(intvec(a,b,d1)); 5847 } 5848 example 5849 { "EXAMPLE:"; echo = 2; 5850 int prl = printlevel; 5851 printlevel = -1; 5852 ring r = 0,(x,y),dp; 5853 ideal i = (x-y^2)^2 - y*x^3; 5854 list nor = normal(i); 5855 norTest(i,nor); //1,1,1 means that normal was correct 5856 5857 ring s = 2,(x,y),dp; 5858 ideal i = (x-y^2)^2 - y*x^3; 5859 nor = normalP(i,"withRing"); 5860 norTest(i,nor); //1,1,1 means that normalP was correct 5861 printlevel = prl; 5862 } 5863 5864 /////////////////////////////////////////////////////////////////////////// 5865 // 5866 // EXAMPLES 5867 // 5868 /////////////////////////////////////////////////////////////////////////// 2446 5869 /* 2447 Examples: 2448 LIB"normal.lib"; 2449 //Huneke 2450 ring qr=31991,(a,b,c,d,e),dp; 5870 //commands for computing the normalization: 5871 // options for normal: "equidim", "prim" 5872 // "noDeco", "isPrim", "noFac" 5873 // (prim by default) 5874 // options for normalP: "withRing", "isPrim" or "noFac" 5875 // options for normalC: "equidim", "prim", "withGens", 5876 // "noDeco", "isPrim", "noFac" 5877 5878 //Commands for testing 'normal' 5879 list nor = normal(i); nor; 5880 list nor = normal(i,"isPrim");nor; 5881 list nor = normal(i,"equidim");nor; 5882 list nor = normal(i,"prim");nor; 5883 list nor = normal(i,"equidim","noFac");nor; 5884 list nor = normal(i,"prim","noFac");nor; 5885 5886 //Commands for testing 'normalP' in positive char 5887 list nor = normalP(i);nor; //withGens but no ringstructure 5888 list nor = normalP(i,"withRing"); nor; //compute the ringstructure 5889 list nor = normalP(i,"isPrim"); nor; //if i is known to be prime 5890 5891 //Commands for testing 'normalC' 5892 list nor = normal(i); nor; 5893 list nor = normal(i,"withGens");nor; 5894 list nor = normal(i,"isPrim");nor; 5895 list nor = normal(i,"equidim");nor; 5896 list nor = normal(i,"prim");nor; 5897 list nor = normal(i,"equidim","noFac");nor; 5898 list nor = normal(i,"prim","noFac");nor; 5899 5900 //Commands for testing correctness (i must be prime): 5901 list nor = normalP(i,"withRing","isPrim"); 5902 list nor = normal(i,"isPrim"); 5903 norTest(i,nor); //full test for not too big examples (1,1,1 => ok) 5904 norTest(i,nor,2); //partial test for big examples (1,1 => ok) 5905 factorize(i[1]); //checks for irreducibility 5906 5907 //----------------------Test Example for charp ------------------- 5908 //Zu tun: 5909 //### nach minor nur std statt mstd verwenden 5910 //***hat bei keinem Beisp etwas gebracht -> wieder zurueck 5911 //### wenn interred ok, dann wieder einsetzen (am Schluss) 5912 //### bottelnecks bei maps beheben 5913 //### minor verbessern 5914 //### preimage verbessern (Ist imm Kern map oder imap verwendet?) 5915 //### Gleich in Ordnung dp wechseln, ringlist verwenden 5916 //### interred ev nur zum Schluss 5917 // (z.B. wenn nacher std; wenn nacher minor: testen ) 5918 5919 //Zeiten mit normalV5.lib (mstd aktiv, interred inaktiv) 5920 5921 //SWANSON EXAMPLES: (Macaulay2, icFracP=normalP, icFractions<->normal) 5922 //--------------------------------------------------------------------- 5923 //1. Series Fp[x,y,u,v]/(x2v-y2u) 5924 //------------------------------- 5925 //characteristic p 2 3 5 7 11 13 17 37 97 5926 //icFracP 0.04 0.03 0.04 0.04 0.04 0.05 0.05 0.13 0.59 Mac 5927 //normalP 0 0 0 0 0 0 0 0 1 Sing 5928 //icFractions 0.08 0.09 0.09 0.09 0.14 0.15 0.15 0.15 0.15 Mac 5929 //normal 0 0 0 0 0 0 0 0 0 Sing 5930 5931 2. Series Fp[u, v, w, x, y, z]/u2x4+uvy4+v2z4 5932 //-------------------------------------------- 5933 //characteristic p 2 3 5 7 11 5934 //icFracP 0.07 0.22 9.67 143 12543 5935 //normalP 0 0 5 42 1566 5936 //icFractions 1.16 * * * * *: > 6h 5937 //normal 0 0 0 0 0 5938 5939 //3. Series Fp[u, v, w, x, y, z]/(u2xp+uvyp+v2zp) 5940 //----------------------------------------------- 5941 //characteristic p 2 3 5 7 11 13 17 19 23 5942 //icFracP 0.06 0.07 0.09 0.27 1.81 4.89 26 56 225 5943 //normalP 0 0 0 0 1 2 6 10 27 5944 //icFractions 0.16 1.49 75.00 4009 * * * * * 5945 //normal 0 0 2 836 5946 //### p=7 normal braucht 807 sec in: 5947 // ideal endid = phi1(endid); //### bottelneck' 5948 5949 //1. 5950 int p = 2; ring r = p,(u,v,x,y,z),dp; ideal i = x2v-y2u; 5951 //2. 5952 int p = 7; ring r=p,(u,v,w,x,y,z),dp; ideal i=u2x4+uvy4+v2z4; 5953 //3. 5954 int p=23; ring r=p,(u,v,w,x,y,z),dp; ideal i=u2*x^p+uv*y^p+v2*z^p; 5955 5956 //IRREDUCIBLE EXAMPLES: 5957 //--------------------- 5958 //timing for MacBookPro 2.2GHz Intel Core 2 Duo, 4GB Ram 5959 //Sing. ix86Mac-darwin version 3-1-0 (3100-2008101314) Oct 13 2008 14:46:59 5960 //if no time is given: < 1 sec 5961 5962 //Apply: 5963 list nor = normal(i,"isPrim"); nor; 5964 list nor = normalP(i,"withRing","isPrim"); nor; 5965 def R=nor[1][1]; setring R; norid; normap; 5966 setring r; 5967 norTest(i,nor); 5968 5969 int tt = timer; 5970 list nor = normalP(i,"withRing","isPrim"); nor; 5971 timer-tt; 5972 int tt = timer; 5973 list nor = normal(i,"isPrim"); 5974 timer-tt; 5975 5976 ring r=19,(x,y,u,v),dp; //delta -1 5977 ideal i=x2v-y2u; 5978 //norTest 2 sec 5979 5980 ring r=2,(y,x2,x1),lp; //delta -1 5981 ideal i=y^4+y^2*x2*x1+x2^3*x1^2+x2^2*x1^3; 5982 //### norid hat 1 Element nach interred 5983 5984 ring r = 11,(x,y,z),wp(2,1,2); //alles < 1 sec 5985 ideal i=z3 - xy4 + x2; //not reduced, delta =0 ok 5986 ideal i=y4+x5+y2x; //not reduced, delta -1 5987 //interred verkleinert norid 5988 5989 ring r=3,(u,v,x,y,z),dp; //delta -1 5990 ideal i=u2x3+uvy3+v2z3; 5991 5992 ring r=3,(u,v,x,y,z),dp; //delta -1 5993 ideal i=u2x4+uvy4+v2z4; 5994 //norTest(i,nor); 0 sec, norTest(i,nor) haengt! 5995 5996 ring r=5,(u,v,x,y,z),dp; //delta -1 5997 ideal i=u2x6+uvy6+v2z6; 5998 //normalP 5sec, normalC 1sec 5999 //V5: norTest(i,nor); 45 sec bei normalP, V6 12 sec 6000 //28 sec bei normal 6001 6002 ring r=5,(u,v,x,y,z),dp; //delta -1 6003 ideal i=u2x5+uvy5+v2z5; 6004 //normalP 1sec, normalC 1 sec, 6005 //norTest lange: minor(jacob(I),h,J) 193 (308)sec, haengt dann bei M = std(M); 6006 //norTest(i,nor,2); verwenden! 6007 //Sing 3.0-4 orig >9h! hngt bei Q = mstd(Q)[2]; 6008 6009 ring r=2,(y,x),wp(12,5); //delta 3 6010 ideal i=y5+y2x4+y2x+yx2+x12; 6011 //normalP 0 sec (Test 0 sec), normalC 2 sec (Test 2 sec) 6012 //normalC withGens (ohne interred) 0sec 6013 6014 ring r=2,(y,x),dp; //delta= 22 6015 ideal i=y9+y8x+y8+y5+y4x+y3x2+y2x3+yx8+x9; 6016 //normalP 1sec, interred verkleinert norid betraechtlich 6017 //normalC haengt bei minor, ideal im loop wird zu gross ### 6018 //interred bei normalC vergroeesert string um Faktor 4000! 6019 //withGens haengt bei interred in loop 4 (> 10 h) oder 6020 //(nach Ausschalten von interred) bei 6021 //int delt=vdim(std(modulo(f,ideal(p)))); (>?h) 6022 6023 //Leonard1: (1. Komponente von Leonard), delta -1 6024 ring r=2,(v,u,z,y,x),dp; 6025 ideal i = z3+zyx+y3x2+y2x3, uyx+z2,uz+z+y2x+yx2, u2+u+zy+zx, 6026 v3+vux+vz2+vzyx+vzx+uz3+uz2y+z3+z2yx2; 6027 //normalP 5 sec (withRing 9 sec), norTest(i,nor,2); 45 sec 6028 //normalC 102sec, 99sec 6029 //### Zeit wird bei ideal Ann = quotient(SM[2],SL[1]); und bei 6030 // f = quotient(p*J,J); verbraucht 6031 //withGens (ohne interred) 131sec, norTest(i,nor,2); 2min25sec 6032 //norTest(i,nor,2); 45 sec 6033 6034 ring r=2,(y,x),wp(25,21); //Leonard2, delta 232 6035 ring r=2,(y,x),dp; 6036 ideal i= 6037 y^21+y^20*x +y^18*(x^3+x+1) +y^17*(x^3+1) +y^16*(x^4+x) 6038 +y^15*(x^7+x^6+x^3+x+1) +y^14*x^7 +y^13*(x^8+x^7+x^6+x^4+x^3+1) 6039 +y^12*(x^9+x^8+x^4+1) +y^11*(x^11+x^9+x^8+x^5+x^4+x^3+x^2) 6040 +y^10*(x^12+x^9+x^8+x^7+x^5+x^3+x+1) 6041 +y^9*(x^14+x^13+x^10+x^9+x^8+x^7+x^6+x^3+x^2+1) 6042 +y^8*(x^13+x^9+x^8+x^6+x^4+x^3+x) +y^7*(x^16+x^15+x^13+x^12+x^11+x^7+x^3+x) 6043 +y^6*(x^17+x^16+x^13+x^9+x^8+x) +y^5*(x^17+x^16+x^12+x^7+x^5+x^2+x+1) 6044 +y^4*(x^19+x^16+x^15+x^12+x^6+x^5+x^3+1) 6045 +y^3*(x^18+x^15+x^12+x^10+x^9+x^7+x^4+x) 6046 +y^2*(x^22+x^21+x^20+x^18+x^13+x^12+x^9+x^8+x^7+x^5+x^4+x^3) 6047 +y*(x^23+x^22+x^20+x^17+x^15+x^14+x^12+x^9) 6048 +(x^25+x^23+x^19+x^17+x^15+x^13+x^11+x^5); 6049 //normalP: dp 2sec withRing 8sec, 6050 //wp 4sec, withRing:51sec Zeit in lin = subst(lin, var(ii), vip); in elimpart ), 6051 //norTest(i,nor,2): haengt bei mstd(norid); 6052 //### normalC: (m. interred): haengt bei endid = interred(endid); 6053 //GEFIXTES INTERRED ABWARTEN. Dann interred aktivieren 6054 //interred(norid) haengt u. mst(norid) zu lange 6055 //(o.interred): haengt bei haengt bei list SM = mstd(i); 6056 //ideal in der Mitte zu gross 6057 //i = Ideal (size 118, 13 var) fuer die neue Normalisierung 6058 6059 REDUCIBLE EXAMPLES: 6060 ------------------ 6061 //Apply: 6062 int tt = timer; 6063 list nor=normalP(i,"isPrim","withRing"); 6064 timer-tt; 6065 6066 list nor = normal(i); nor; 6067 list nor = normalC(i); nor; 6068 list nor = normalC(i, "withGens"); nor; 6069 list nor = normalP(i,"withRing"); nor; 6070 list nor = normalP(i); nor; 6071 def R=nor[1][1]; setring R; norid; normap; 6072 6073 //Leonhard 4 Komponenten, dim=2, delta: 0,0,0,-1 6074 ring r=2,(v,u,z,y,x),dp; //lp zu lange 6075 ideal i=z3+zyx+y3x2+y2x3, uyx+z2, v3+vuyx+vux+vzyx+vzx+uy3x2+uy2x+zy3x+zy2x2; 6076 //normalP: 19 sec, withRing: 22 sec 6077 //normalC ohne (mit) interred: 112 (113)sec, equidim: 99sec 6078 //normalC 1. mal 111 sec, (2.mal) 450sec!! 3.mal 172 sec 6079 //(unterschiedlich lange primdec, mit Auswirkungen) 6080 //char 19: normalC: 15sec , withGens: 14sec (o.interr.) 6081 6082 //----------------------Test Example for special cases ------------------- 6083 int tt = timer; 6084 list nor=normalP(i,"withRing");nor; 6085 //list nor=normalP(i,"withRing", "isPrim");nor; 6086 timer-tt; 6087 def R1 = nor[1][1]; setring R1; norid; normap; interred(norid); 6088 setring r; 6089 6090 int tt = timer; 6091 list nor=normal(i,"isPrim");nor; 6092 timer-tt; 6093 6094 ring r = 29,(x,y,z),dp; 6095 ideal i = x2y2,x2z2; //Nicht equidimensional, equidim reduziert nicht, ok 6096 ideal i = xyz*(z3-xy4); //### interred(norid) verkuerzt 6097 //je 0 sec 6098 6099 ideal j = x,y; 6100 ideal i = j*xy; 6101 equidim(i); 6102 //hat eingebettete Komponente, equidim rechnet wie in Beschreibung (ok) 6103 6104 ring r = 19,(x,y),dp; 6105 ideal i = x3-y4; //delta = 3 6106 ideal i = y*x*(x3-y4); //delta = 11; 0,0,3 6107 ideal i = (x2-y3)*(x3-y4); //delta = 13; 1,3 6108 ideal i = (x-y)*(x3+y2)*(x3-y4); //delta = 23; 0,1,3 6109 ideal i = (x-1)*(x3+y2)*(x2-y3); //delta = 16; 0,1,1 6110 ideal i = (x-y^2)^2 - y*x^3; //delta = 3 6111 //singularities at not only at 0, hier rechnet equidim falsch 6112 6113 // -------------------------- General Examples ---------------------------//Huneke, irred., delta=2 (Version 3-0-4: < 1sec) 6114 //Version 3-0-6 default: 1sec, mit gens 2sec, mit delta 5 sec 6115 //(prim,noFac):ca 7 Min, prim:ca 10 min(wg facstd) 6116 // 6117 // "equidim" < 1sec irred. 5sec 6118 // ring r=31991,(a,b,c,d,e),dp; 6119 ring r=2,(a,b,c,d,e),dp; //delta=2 2451 6120 ideal i= 2452 6121 5abcde-a5-b5-c5-d5-e5, … … 2458 6127 a4b2c-abc2d3-ab5e-b3c2de-ad5e+2a2bcde2+cd2e4, 2459 6128 b6c+bc6+a2b4e-3ab2c2de+c4d2e-a3cde2-abd3e2+bce5; 2460 2461 2462 //Vasconcelos (dauert laenger: 70 sec) 2463 ring r=32003,(x,y,z,w,t),dp; 2464 ideal i= 2465 x2+zw, 2466 y3+xwt, 2467 xw3+z3t+ywt2, 2468 y2w4-xy2z2t-w3t3; 2469 2470 //Theo1 2471 ring r=32003,(x,y,z),wp(2,3,6); 6129 //normalC: char 2, 31991: 0 sec (isPrim); char 2, equidim: 7 sec 6130 //norTest(i,nor,2); 1sec 6131 //normalP char 2: 1sec (isPrim) 6132 //size(norid); size(string(norid));21 1219 interred(norid): 21 1245 (0 sec) 6133 6134 int tt = timer; 6135 list nor=normalC(i);nor; 6136 timer-tt; 6137 6138 list nor = normalP(i,"isPrim"); 6139 6140 //Vasconcelos irred., delta -1 (dauert laenger) 6141 //auf macbook pro = 20 sec mit alter Version, 6142 //Sing 3-0-6: 6143 // Char 32003: "equidim" 30 sec, "noFac": 30sec 6144 //gens: nach 9 min abgebr (haengt in Lin = ideal(T*syzf);) !!!! Hans zu tun 6145 //Char 2: default (charp) 2 sec, normalC ca 30 sec 6146 //ring r=32003,(x,y,z,w,t),dp; //dim 2, dim s_locus 1 6147 ring r=2,(x,y,z,w,t),dp; //dim 2, dim s_locus 1 6148 ideal i= x2+zw, y3+xwt, xw3+z3t+ywt2, y2w4-xy2z2t-w3t3; 6149 //normalC: char 2: 22, sec (mit und ohne isPrim) 6150 //normalP char 2: 0sec (isPrim) o. interred 6151 //char 32003: ### haengt in ideal endid = phi1(endid); 6152 6153 //------------------------------------------------------- 6154 //kleine Beispiele: 6155 6156 //Theo1, irred, delta=-1 6157 //normalC: 1sec, normalP: 3 sec 6158 ring r=32003,(x,y,z),wp(2,3,6); //dim 2,dim slocus 1 2472 6159 ideal i=zy2-zx3-x6; 2473 2474 //Theo1a (CohenMacaulay and regular in codimension 2) 2475 ring r=32003,(x,y,z,u),wp(2,3,6,6); 6160 //normalC: char 2,19,32003: 0 sec (isPrim) 6161 //normalP (isPrim) char 2,19: 0sec, char 29: 1sec 6162 6163 //Theo1a, CohenMacaulay regular in codim 2, dim slocus=1, delta=0 6164 //normalC: 0 sec, normalP: haegt in K=preimage(R,phi,L); 6165 ring r=32003,(x,y,z,u),dp; 2476 6166 ideal i=zy2-zx3-x6+u2; 2477 2478 2479 //Theo2 2480 ring r=32003,(x,y,z),wp(3,4,12); 6167 //normalC: char 2,32003: 0 sec (isPrim) 6168 //normalP (isPrim) char 2: 0sec, char 19: haengt in K = preimage(Q,phi,L); 6169 6170 //Theo2, irreduzibel, reduziert, < 1sec, delta -1 6171 ring r=0,(x,y,z),wp(3,4,12); 2481 6172 ideal i=z*(y3-x4)+x8; 2482 2483 //Theo2a 2484 ring r=32003,(T(1..4)),wp(3,4,12,17); 6173 //normalC: char 2,32003,0: 0 sec (isPrim) 6174 //normalP (isPrim) char 2: 0 1sec, char 19: 1sec char 29: 7 sec 6175 6176 //Theo2a, reduiziert, 2-dim, dim_slocus=1, alte Version 3 sec, 6177 //normalP ca 30 sec, normalC ca 4sec, delta -1 6178 //ring r=32003,(T(1..4)),wp(3,4,12,17); 6179 //ring r=11,(T(1..4)),dp; 6180 ring r=11,(T(1..4)),wp(3,4,12,17); 2485 6181 ideal i= 2486 6182 T(1)^8-T(1)^4*T(3)+T(2)^3*T(3), … … 2488 6184 T(1)^7+T(1)^3*T(2)^3-T(1)^3*T(3)+T(2)*T(4), 2489 6185 T(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; 2490 2491 //Theo3 2492 ring r=32003,(x,y,z),wp(3,5,15); 6186 //normalC: char 2,32003: 0 sec (isPrim) 6187 //normalP (isPrim) char 2: 0sec, char 11 2se, char 19: 13sec 6188 //norTest 48sec in char11 6189 //### interred verkuerzt 6190 //char 29: haengt in K = preimage(Q,phi,L); 6191 6192 //Theo3, irred, 2-dim, 1-dim sing, < 1sec 6193 ring r=11,(x,y,z),wp(3,5,15); 2493 6194 ideal i=z*(y3-x5)+x10; 2494 2495 2496 //Theo4 2497 ring r=32003,(x,y,z),dp; 2498 ideal i=(x-y)*(x-z)*(y-z); 2499 2500 //Theo5 2501 ring r=32003,(x,y,z),wp(2,1,2); 2502 ideal i=z3-xy4; 6195 //normalC: char 2,0: 0 sec (withRing) 6196 //normalP (withRing) char 2,11: 0sec, char 19: 13sec norTest 12sec(char 11) 6197 6198 //Theo4 reducible, delta (0,0,0) -1 6199 ring r=29,(x,y,z),dp; 6200 ideal i=(x-y)*(x-z)*(y-z); 6201 //normalC: char 2,32003: 0 sec 6202 //normalP char withRing 2, 29: 0sec, 6sec 2503 6203 2504 6204 //Theo6 2505 6205 ring r=32003,(x,y,z),dp; 2506 6206 ideal i=x2y2+x2z2+y2z2; 2507 2508 ring r=32003,(a,b,c,d,e,f),dp; 6207 //normalC: char 2,32003: 0 sec 6208 //normalP char withRing 2, 29: 0sec, 4sec 6209 6210 //Sturmfels, CM, 15 componenten, alle glatt 6211 ring r=0,(b,s,t,u,v,w,x,y,z),dp; 6212 ideal i= bv+su, bw+tu, sw+tv, by+sx, bz+tx, sz+ty,uy+vx,uz+wx,vz+wy,bvz; 6213 //normalC car 11, 0: 1sec, normalP 0 sec 6214 6215 //riemenschneider, , dim 3, 5 Komp. delta (0,0,0,0,0), -1 6216 ring r=2,(p,q,s,t,u,v,w,x,y,z),wp(1,1,1,1,1,1,2,1,1,1); 6217 ideal i=xz,vx,ux,su,qu,txy,stx,qtx,uv2z-uwz,uv3-uvw,puv2-puw; 6218 //alles 0 sec in char 2 6219 6220 //4 Komponenten, alle glatt, 0sec 6221 ring r=11,(x,y,z,t),dp; 6222 ideal i=x2z+xzt,xyz,xy2-xyt,x2y+xyt; 6223 6224 //dim 3, 2 Komponenten delta (-1,0), -1 6225 ring r=2,(u,v,w,x,y,z),wp(1,1,1,3,2,1); 6226 ideal i=wx,wy,wz,vx,vy,vz,ux,uy,uz,y3-x2; 6227 //alles 0 sec in char 2 6228 //--------------------------------------------------------- 6229 int tt = timer; 6230 list nor=normalP(i,"normalC","withRing");nor; 6231 timer-tt; 6232 6233 //St_S/Y, 3 Komponenten, 2 glatt, 1 normal 6234 //charp haengt (in char 20) in K=preimage(R,phi,L); 6235 //ring r=32003,(b,s,t,u,v,w,x,y,z),dp; 6236 ring r=11,(b,s,t,u,v,w,x,y,z),dp; 6237 ideal i=wy-vz,vx-uy,tv-sw,su-bv,tuy-bvz;