// $Id: sing.lib,v 1.1.1.1 1997-04-25 15:13:27 obachman Exp $ //system("random",787422842); //(GMG+BM) /////////////////////////////////////////////////////////////////////////////// LIBRARY: sing.lib PROCEDURES FOR SINGULARITIES deform(i); infinitesimal deformations of ideal i dim_slocus(i); dimension of singular locus of ideal i is_active(f,id); is poly f an active element mod id? (id ideal/module) is_ci(i); is ideal i a complete intersection? is_is(i); is ideal i an isolated singularity? is_reg(f,id); is poly f a regular element mod id? (id ideal/module) is_regs(i[,id]); are gen's of ideal i regular sequence modulo id? milnor(i); milnor number of ideal i; (assume i is ICIS in nf) nf_icis(i); generic combinations of generators; get ICIS in nf slocus(i); ideal of singular locus of ideal i Tjurina(i); SB of Tjurina module of ideal i (assume i is ICIS) tjurina(i); Tjurina number of ideal i (assume i is ICIS) T1(i); T1-module of ideal i T2((i); T2-module of ideal i T12(i); T1- and T2-module of ideal i LIB "inout.lib"; LIB "random.lib"; /////////////////////////////////////////////////////////////////////////////// proc deform (ideal id) USAGE: deform(id); id = ideal or poly RETURN: matrix, columns are kbase of infinitesimal deformations EXAMPLE: example deform; shows an example { list L=T1(id,""); return(L[2]*kbase(std(L[1]))); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),ds; ideal i=xy,xz,yz; matrix T=deform(i);print(T); print(deform(x3+y5+z2)); } /////////////////////////////////////////////////////////////////////////////// proc dim_slocus (ideal i) USAGE: dim_slocus(i); i ideal or poly RETURN: dimension of singular locus of i EXAMPLE: example dim_slocus; shows an example { return(dim(std(slocus(i)))); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),ds; ideal i= x5+y6+z6,x2+2y2+3z2; dim_slocus(i); } /////////////////////////////////////////////////////////////////////////////// proc is_active (poly f, id) USAGE: is_active(f,id); f poly, id ideal or module RETURN: 1 if f is an active element modulo id (i.e. dim(id)=dim(id+f*R^n)+1, if id is a submodule of R^n) resp. 0 if f is not active. The basering may be a quotient ring NOTE: regular parameters are active but not vice versa (id may have embedded components). proc is_reg tests whether f is a regular parameter EXAMPLE: example is_active; shows an example { if( size(id)==0 ) { return(1); } if( typeof(id)=="ideal" ) { ideal m=f; } if( typeof(id)=="module" ) { module m=f*freemodule(rank(id)); } return(dim(std(id))-dim(std(id+m))); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),ds; ideal i=yx3+y,yz3+y3z; poly f=x; is_active(f,i); qring q = std(x4y5); poly f=x; module m=[yx3+x,yx3+y3x]; is_active(f,m); } /////////////////////////////////////////////////////////////////////////////// proc is_ci (ideal i) USAGE: is_ci(i); i ideal RETURN: intvec = sequence of dimensions of ideals (j[1],...,j[k]), for k=1,...,size(j), where j is minimal base of i. i is a complete intersection if last number equals nvars-size(i) NOTE: dim(0-ideal) = -1. You may first apply simplify(i,10); in order to delete zeroes and multiples from set of generators EXAMPLE: example is_ci; shows an example { int n; intvec dimvec; ideal id; i=minbase(i); int s = ncols(i); //--------------------------- compute dimensions ------------------------------ for( n=1; n<=s; n++ ) { id = i[1..n]; dimvec[n] = dim(std(id)); } n = dimvec[s]; //--------------------------- output ------------------------------------------ if( defined(printlevel) ) { if( n+s !=nvars(basering) ) { dbprint(printlevel,"// no complete intersection"); } if( n+s ==nvars(basering) ) { dbprint(printlevel,"// complete intersection of dim "+string(n)); } dbprint(printlevel,"// dim-sequence:"); } if( voice==2 ) { if( n+s !=nvars(basering)) {"// no complete intersection"; } if( n+s ==nvars(basering)) {"// complete intersection of dim",n;} "// dim-sequence:"; } return(dimvec); } example { "EXAMPLE:"; echo = 2; int printlevel=2; // this forces the proc to display comments export printlevel; ring r=32003,(x,y,z),ds; ideal i=x4+y5+z6,xyz,yx2+xz2+zy7; is_ci(i); i=xy,yz; is_ci(i); kill printlevel; } /////////////////////////////////////////////////////////////////////////////// proc is_is (ideal i) USAGE: is_is(id); id ideal or poly RETURN: intvec = sequence of dimensions of singular loci of ideals generated by id[1]..id[i], k = 1..size(id); dim(0-ideal) = -1; id defines an isolated singularity if last number is 0 EXAMPLE: example is_is; shows an example { int l; intvec dims; ideal j; //--------------------------- compute dimensions ------------------------------ for( l=1; l<=ncols(i); l++ ) { j = i[1..l]; dims[l] = dim(std(slocus(j))); } if( voice==2 ) {"// dim of singular locus =",dims[size(dims)],"dim-sequence:"; "// isolated singularity if last number is 0"; } return(dims); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),ds; ideal i=x2y,x4+y5+z6,yx2+xz2+zy7; is_is(i); // isolated singularity if last number is 0 poly f=xy+yz; is_is(f); // isolated singularity if last number is 0 } /////////////////////////////////////////////////////////////////////////////// proc is_reg (poly f, id) USAGE: is_reg(f,id); f poly, id ideal or module RETURN: 1 if multiplication with f is injective modulo id, 0 otherwise NOTE: let R be the basering and id a submodule of R^n. The procedure checks injectivity of multiplication with f on R^n/id. The basering may be a //**quotient ring EXAMPLE: example is_reg; shows an example { if( f==0 ) { return(0); } int d,ii; def q = quotient(id,ideal(f)); id=std(id); d=size(q); for( ii=1; ii<=d; ii++ ) { if( reduce(q[ii],id)!=0 ) { return(0); } } return(1); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y),ds; ideal i=x8,y8;ideal j=(x+y)^4; i=intersect(i,j); poly f=xy; is_reg(f,i); } /////////////////////////////////////////////////////////////////////////////// proc is_regs (ideal i, list #) USAGE: is_regs(i[,id]); i poly, id ideal or module (default: id=0) RETURN: 1 if generators of i are a regular sequence modulo id, 0 otherwise NOTE: let R be the basering and id a submodule of R^n. The procedure checks injectivity of multiplication with i[k] on R^n/id+i[1..k-1]. The basering may be a quotient ring EXAMPLE: example is_regs; shows an example { if( size(#)==0 ) { ideal id; } else { def id=#[1]; } if( size(i)==0 ) { return(0); } int d,ii,r; d=size(i); if( typeof(id)=="ideal" ) { ideal m=1; } if( typeof(id)=="module" ) { module m=freemodule(rank(id)); } for( ii=1; ii<=d; ii++ ) { if( voice==2 ) { "// checking whether element",ii,"is regular mod 1 ..",ii-1; } if( is_reg(i[ii],id)==0 ) { if( voice==2 ) { "// elements 1 ..",ii-1,"are regular,", ii,"is not regular mod 1 ..",ii-1; } return(0); } id=id+i[ii]*m; } if( voice==2 ) { "// elements are a regular sequence of length",d; } return(1); } example { "EXAMPLE:"; echo = 2; ring r1=32003,(x,y,z),ds; ideal i=x8,y8,(x+y)^4; is_regs(i); module m=[x,0,y]; i=x8,(x+z)^4;; is_regs(i,m); } /////////////////////////////////////////////////////////////////////////////// proc milnor (ideal i) USAGE: milnor(i); i ideal or poly RETURN: Milnor number of i, if i is ICIS (isolated complete intersection singularity) in generic form, resp. -1 if not NOTE: use proc nf_icis to put generators in generic form EXAMPLE: example milnor; shows an example { i = simplify(i,10); //delete zeroes and multiples from set of generators int n = size(i); int l,q,m_nr; ideal t; intvec disc; //---------------------------- hypersurface case ------------------------------ if( n==1 ) { i = std(jacob(i[1])); m_nr = vdim(i); if( m_nr<0 and voice==2 ) { "// no isolated singularity"; } return(m_nr); } //------------ isolated complete intersection singularity (ICIS) -------------- for( l=n; l>0; l=l-1) { t = minor(jacob(i),l); i[l] = 0; q = vdim(std(i+t)); disc[l]= q; if( q ==-1 ) { if( voice==2 ) { "// not in generic form or no ICIS; use proc nf_icis to put"; "// generators in generic form and then try milnor again!"; } return(q); } m_nr = q-m_nr; } //---------------------------- change sign ------------------------------------ if (m_nr < 0) { m_nr=-m_nr; } if( voice==2 ) { "//sequence of discriminant numbers:",disc; } return(m_nr); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),ds; ideal j=x5+y6+z6,x2+2y2+3z2,xyz+yx; milnor(j); poly f=x7+y7+(x-y)^2*x2y2+z2; milnor(f); } /////////////////////////////////////////////////////////////////////////////// proc nf_icis (ideal i) USAGE: nf_icis(i); i ideal RETURN: ideal = generic linear combination of generators of i if i is an ICIS (isolated complete intersection singularity), return i if not NOTE: this proc is useful in connection with proc milnor EXAMPLE: example nf_icis; shows an example { i = simplify(i,10); //delete zeroes and multiples from set of generators int p,b = 100,0; int n = size(i); matrix mat=freemodule(n); //---------------------------- test: complete intersection? ------------------- intvec sl = is_ci(i); if( n+sl[n] != nvars(basering) ) { if( voice==2 ) { "// no complete intersection"; } return(i); } //--------------- test: isolated singularity in generic form? ----------------- sl = is_is(i); if ( sl[n] != 0 ) { if( voice==2 ) { "// no isolated singularity"; } return(i); } //------------ produce generic linear combinations of generators -------------- int prob; while ( sum(sl) != 0 ) { prob=prob+1; p=p-25; b=b+10; i = genericid(i,p,b); // proc genericid from random.lib sl = is_is(i); } if( voice==2 ) { "// ICIS in generic form after",prob,"genericity loop(s)";} return(i); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),ds; ideal i=x3+y4,z4+yx; nf_icis(i); ideal j=x3+y4,xy,yz; nf_icis(j); } /////////////////////////////////////////////////////////////////////////////// proc slocus (ideal i) USAGE: slocus(i); i dieal RETURN: ideal of singular locus of i NOTE: this proc considers lower dimensional components as singular EXAMPLE: example slocus; shows an example { int cod = nvars(basering)-dim(std(i)); i = i+minor(jacob(i),cod); return(i); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),ds; ideal i= x5+y6+z6,x2+2y2+3z2; dim(std(slocus(i))); } /////////////////////////////////////////////////////////////////////////////// proc Tjurina (id, list #) USAGE: Tjurina(id[,]); id ideal or poly (assume: id=ICIS) RETURN: Tjurina(id): standard basis of Tjurina-module of id, displays Tjurina number Tjurina(id,...): If a second argument is present (of any type) return a list of 4 objects: [1]=Tjurina number (int), [2]=basis of miniversal deformation (module), [3]=SB of Tjurina module (module), [4]=Tjurina module (module) NOTE: if id is a poly the output will be of type ideal rather than module EXAMPLE: example Tjurina; shows an example { //---------------------------- initialisation --------------------------------- def i = simplify(id,10); int tau,n = 0,size(i); if( size(ideal(i))==1 ) { def m=i; } // hypersurface case else { def m=i*freemodule(n); } // complete intersection case //--------------- compute Tjurina module, Tjurina number etc ------------------ def t1 = jacob(i)+m; // Tjurina module/ideal def st1 = std(t1); // SB of Tjurina module/ideal tau = vdim(st1); // Tjurina number def kB = kbase(st1); // basis of miniversal deformation if( voice==2 ) { "// Tjurina number =",tau; } if( size(#)>0 ) { return(tau,kB,st1,t1); } return(st1); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),ds; poly f = x5+y6+z7+xyz; // singularity T[5,6,7] list T = Tjurina(f,""); show(T[1]); // Tjurina number, should be 16 show(T[2]); // basis of miniversal deformation show(T[3]); // SB of Tjurina ideal show(T[4]); ""; // Tjurina ideal ideal j=x2+y2+z2,x2+2y2+3z2; show(kbase(Tjurina(j))); // basis of miniversal deformation hilb(Tjurina(j)); // Hilbert series of Tjurina module } /////////////////////////////////////////////////////////////////////////////// proc tjurina (ideal i) USAGE: tjurina(id); id ideal or poly (assume: id=ICIS) RETURN: int = Tjurina number of id EXAMPLE: example tjurina; shows an example { return(vdim(Tjurina(i))); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),(c,ds); ideal j=x2+y2+z2,x2+2y2+3z2; tjurina(j); } /////////////////////////////////////////////////////////////////////////////// proc T1 (ideal id, list #) USAGE: T1(id[,]); id = ideal or poly RETURN: T1(id): T1-module of id or T1-ideal if id is a poly. This is a presentation of 1st order deformations of P/id, if P is the basering. T1(id,...): If a second argument is present (of any type) return a list of 3 modules: [1]= presentation of infinitesimal deformations of id (=T1(id)) [2]= generators of normal bundle of id, lifted to P [3]= module of relations of [2], lifted to P ([2]*[3]=0 mod id) The list contains all non-easy objects which must be computed anyway to get T1(id). The situation is described in detail in the procedure T1_expl from library explain.lib NOTE: T1(id) itself is usually of minor importance, nevertheless, from it all relevant information can be obtained. Since no standard basis is computed, the user has first to compute a standard basis before applying vdim or hilb etc.. For example, matrix([2])*(kbase(std([1]))) represents a basis of 1st order semiuniversal deformation of id (use proc 'deform', to get this in a direct and convenient way). If the input is weighted homogeneous with weights w1,...,wn, use ordering wp(w1..wn), even in the local case, which is equivalent but faster than ws(w1..wn). For a complete intersection the proc Tjurina is faster EXAMPLE: example T1; shows an example { ideal J=simplify(id,10); //--------------------------- hypersurface case ------------------------------- if( size(J)<2 ) { ideal t1=J[1],jacob(J[1]); module nb=[1]; module pnb; if( size(#)>0 ) { return(t1*gen(1),nb,pnb); } return(t1); } //--------------------------- presentation of J ------------------------------- int rk; def P=basering; module jac, t1; jac=jacob(J); // jacobian matrix of J converted to module res(J,2,A); // compute presentation of J t1=transpose(A(2)); // transposed 1st syzygy module of J //---------- go to quotient ring mod J and compute normal bundle -------------- qring R=std(J); module jac=fetch(P,jac); module t1=fetch(P,t1); res(t1,3,B); // resolve t1, B(2)=(J/J^2)*=normal_bdl t1=lift(B(2),jac)+B(3); // pres. of normal_bdl/trivial_deformations rk=rank(t1); //-------------------------- pull back to basering ---------------------------- setring P; t1 = fetch(R,t1)+J*freemodule(rk); // T1-module, presentation of T1 if( size(#)>0 ) { module B2 = fetch(R,B(2)); // (generators of) normal bundle module B3 = fetch(R,B(3)); // presentation of normal bundle return(t1,B2,B3); } return(t1); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),(c,ds); ideal i=xy,xz,yz; module T=T1(i); vdim(std(T)); // Tjurina number = dim_K(T1), should be 3 list L=T1(i,""); module kB = kbase(std(L[1])); print(L[2]*kB); // basis of 1st order miniversal deformation size(L[1]); // number of generators of T1-module show(L[2]); // (generators of) normal bundle print(L[3]); // relation matrix of normal bundle (mod i) print(L[2]*L[3]); // should be 0 (mod i) } /////////////////////////////////////////////////////////////////////////////// proc T2 (ideal id, list #) USAGE: T2(id[,]); id = ideal RETURN: T2(id): T2-module of id . This is a presentation of the module of obstructions of R=P/id, if P is the basering. T2(id,...): If a second argument is present (of any type) return a list of 6 modules and 1 ideal: [1]= presentation of module of obstructions (=T2(id)) [2]= standard basis of id (ideal) [3]= module of relations of id (=1st syzygy module of id) [4]= presentation of [3] (=2nd syzygy module of id) [5]= lifting of Koszul relations kos, kos=module([3]*matrix([5])) [6]= generators of Hom_P([3]/kos,R), lifted to P [7]= relations of Hom_P([3]/kos,R), lifted to P The list contains all non-easy objects which must be computed anyway to get T2(id). The situation is described in detail in the procedure T2_expl from library explain.lib NOTE: Since no standard basis is computed, the user has first to compute a standard basis before applying vdim or hilb etc.. If the input is weighted homogeneous with weights w1,...,wn, use ordering wp(w1..wn), even in the local case, which is equivalent but faster than ws(w1..wn). Use proc miniversal to get equations of miniversal deformation; EXAMPLE: example T2; shows an example { //--------------------------- initialisation ---------------------------------- def P = basering; ideal J = simplify(id,10); module kos,L0,t2; int n,rk; //------------------- presentation of non-trivial syzygies -------------------- res(J,3,A); // resolve J, A(2)=syz kos = koszul(2,J); // module of Koszul relations L0 = lift(A(2),kos); // lift Koszul relations to syz t2 = L0+A(3); // presentation of syz/kos ideal J0 = std(J); // standard basis of J //*** sollte bei der Berechnung von res mit anfallen, zu aendern!! //---------------------- fetch to quotient ring mod J ------------------------- qring R = J0; // make P/J the basering module A2' = transpose(fetch(P,A(2))); // dual of syz module t2 = transpose(fetch(P,t2)); // dual of syz/kos res(t2,3,B); // resolve t2 t2 = lift(B(2),A2')+B(3); // presentation of T2 rk = rank(t2); //--------------------- fetch back to basering ------------------------------- setring P; t2 = fetch(R,t2)+J*freemodule(rk); if( size(#)>0 ) { module B2 = fetch(R,B(2)); // generators of Hom_P(syz/kos,R) module B3 = fetch(R,B(3)); // relations of Hom_P(syz/kos,R) return(t2,J0,A(2),A(3),L0,B2,B3); } return(t2); } example { "EXAMPLE:"; echo = 2; ring r = 32003,(x,y),(c,dp); ideal j = x6-y4,x6y6,x2y4-x5y2; module T= std(T2(j)); vdim(T);hilb(T); ring r1=0,(x,y,z),dp; ideal id=xy,xz,yz; list L=T2(id,""); vdim(std(L[1])); // vdim of T2 L[4]; // 2nd syzygy module of ideal } /////////////////////////////////////////////////////////////////////////////// proc T12 (ideal i, list #) USAGE: T12(i[,any]); i = ideal DISPLAY: dim T1 and dim T2 of i RETURN: T12(i): list of 2 modules: presentation of T1-module =T1(i) , 1st order deformations presentation of T2-module =T2(i) , obstructions of R=P/i T12(i,...): If a second argument is present (of any type) return a list of 9 modules, matrices, integers: [1]= presentation of T1 (module) [2]= presentation of T2 (module) [3]= matrix, whose cols present infinitesimal deformations [4]= matrix, whose cols are generators of relations of i [5]= matrix, presenting Hom_P([4]/kos,R), lifted to P [6]= standard basis of T1-module [7]= standard basis of T2-module [8]= vdim of T1 [9]= vdim of T2 NOTE: Use proc miniversal from deform.lib to get miniversal deformation of i, the list contains all objects used by proc miniversal EXAMPLE: example T12; shows an example { //--------------------------- initialisation ---------------------------------- int n,r1,r2,d1,d2; def P = basering; i = simplify(i,10); if (size(i)<2) { "// hypersurface, use proc 'Tjurina'"; //return([1]); } module jac,t1,t2,kos,sbt1,sbt2; matrix L3,L4,L5; ideal i0 = std(i); //-------------------- presentation of non-trivial syzygies ------------------- list I= res(i,3); // resolve i L4 = matrix(I[2]); // syz(i) jac = jacob(i); // jacobi ideal t1 = transpose(I[2]); // dual of syzygies kos = koszul(2,i); // koszul-relations t2 = lift(I[2],kos)+I[3]; // presentation of syz/kos //--------------------- fetch to quotient ring mod i ------------------------- qring Ox = i0; // make P/i the basering module jac = fetch(P,jac); module t1 = fetch(P,t1); // Hom(syz,R) module t2 = transpose(fetch(P,t2)); // Hom(syz/kos,R) list resS = res(t1,3); list resR = res(t2,3); t2 = lift(resR[2],t1)+resR[3]; // presentation of T2 r2 = rank(t2); t1 = lift(resS[2],jac)+resS[3]; // presentation of T1 r1 = rank(t1); matrix L3 = resS[2]; matrix L5 = resR[2]; //------------------------ pull back to basering ------------------------------ setring P; t1 = fetch(Ox,t1)+i*freemodule(r1); t2 = fetch(Ox,t2)+i*freemodule(r2); sbt1 = std(t1); d1 = vdim(sbt1); sbt2=std(t2); d2 = vdim(sbt2); "// dim T1 = ",d1; "// dim T2 = ",d2; if ( size(#)>0) { L3 = fetch(Ox,L3)*kbase(sbt1); L5 = fetch(Ox,L5); return(t1,t2,L3,L4,L5,sbt1,sbt2,d1,d2); } return(t1,t2); } example { "EXAMPLE:"; echo = 2; ring r=200,(x,y,z,u,v),(c,ws(4,3,2,3,4)); ideal i=xz-y2,yz2-xu,xv-yzu,yu-z3,z2u-yv,zv-u2; //a cyclic quotient singularity list L = T12(i,1); print(L[3]); } ///////////////////////////////////////////////////////////////////////////////