gc(0): # Start by defining a few procedures that are convenient when # computing in the representation ring of a torus. # setuptorus(n,m) sets up an (n+1)-dimensional torus with # characters x0,...,xn. The representation ring is identified # with the Laurent series ring Z[xi,1/xi, i=0..n]. The canonical # representation sum(x.i,i=0..N) is denoted by V[1]. Its symmetric # powers are denoted by V[k]. setuptorus:=proc(N,M) local genf,i,k; genf:=expand(convert(series( 1/product('1-x.i*t',i=0..N),t,M+1),polynom)); for i from 0 to M do V[i]:=sort(coeff(genf,t,i)) od; i:='i'; dualsubstring:=seq(x.i=x.i^(-1),i=0..N); variables :=[seq(x.i,i=0..N),seq(x.i^(-1),i=0..N)]; ranksubstring:=seq(x.i=1,i=0..N); lprint(`dimension =`,N,`, maximal degree =`,M); end: # dualrep(C) returns the dual representation, and # rank(C) returns the dimension of C dualrep:=proc(C) sort(expand(subs(dualsubstring,C))) end: rank :=proc(C) sort(expand(subs(ranksubstring,C))) end: # A monomial ideal is represented formally by the sum of its # monomial generators in a given degree. Hence x0+x1 is the # (linear part of the) ideal generated by x0 and x1. # simpleweights(A) returns the sum of one-dimensional # representations, one for each occurring weight in A. For # example, simpleweights(V[j]*V[k]) should return V[j+k]. # This is useful for computing twists of a monomial ideal: # if I sub V[d], then simpleweights(I*V[1]) is the ideal I in # degree d+1. simpleweights:=proc(p) local mon; expand(p); if p=0 then RETURN(0) fi; coeffs(",variables,'mon'); convert([mon],`+`); end: # twistup(J,k) returns the ideal J in degree k higher. twistup:=proc(J,k) simpleweights(J*V[k]) end: # Usual operations in the representation ring are taken # care of by standard algebraic operations like +, -, * # in conjunction with dualrep. Hom:=proc(A,B) sort(expand(dualrep(A)*B)) end: # permut(elem,lis) is the action of a permutation "elem" # on a list "lis". The permutation is represented as a # product of disjoint cycles, as a list of lists. (As in # the Maple "group" package). permut:=proc(elem,ls) local k,res,m,cyc,i,top; res:=ls; for m from 1 to nops(elem) do cyc:=elem[m]; top:=res[cyc[1]]; for i from 1 to nops(cyc)-1 do res:=subsop(cyc[i]=res[cyc[i+1]],res) od; res:=subsop(cyc[i]=top,res): od; res end: # Let C^* -> T be the one-parameter subgroup given by weights # w0,w1,w2,w3. Thus the character xi restricts to t^(wi), i=0..3 # We need to find the products of all weights at each fixpoint. prodwts:=proc(f) local t,cof,mon,res,i; cof:=[coeffs(f,variables,mon)]; mon:=subs(x0=t^w0,x1=t^w1,x2=t^w2,x3=t^w3,[mon]); res:=1; for i from 1 to nops(mon) do res:=res*subs(t=1,diff(mon[i],t))^cof[i] od; res end: ############################################################### # Start by studying the fixpoints in given P^3. We go up to degree # 9 only because we want to compute the number of twisted cubics on # a general degree 9 hypersurface in P^7. For the Calabi-Yau three- # folds it would suffice with M=5. M:=9: setuptorus(3,M); # The eight types of fixpoints: # Cohen-Macaulay types 1--4, with tangent spaces and global sections: EE[1]:=x0*x1+x1*x2+x2*x3: EE[2]:=x0*x1+x1*x2+x0*x2: EE[3]:=x0*x1+x2^2+x0*x2: EE[4]:=x0^2+x0*x1+x1^2: for i to 4 do F[i]:=expand(EE[i]*V[1]-simpleweights(EE[i]*V[1])): TH[i]:=expand(Hom(F[i],EE[i])*V[1]-Hom(F[i],F[i])-Hom(EE[i],EE[i])+1): OC[1,i]:=V[1]: for j from 2 to M do OC[j,i]:=V[j]-twistup(EE[i],j-2) od: od: # Non Cohen-Macaulay types 5--8, with tangent spaces and global sections: beta:=expand(x0*(x0+x1+x2)): # the same net "beta" of quadrics q :=[x1*x2*x3,x1*x2^2,x2^2*x3,x2^3]: # four different cubic forms TI :=expand((x1+x2+x3)/x0+x3/x1+x3/x2): # tangent space of I at beta VF :=subs(x0=0,twistup(x1^2+x1*x2+x2^2,1)):# singular cubics through x1=x2=0 for i from 5 to 8 do Id[i] :=twistup(beta,1)+q[i-4]: # ideal in degree 3 TH[i] :=TI+expand(VF/q[i-4]-1+q[i-4]/(x0*x1*x2)): # (formula (x.x)) OC[1,i]:=V[1]: OC[2,i]:=V[2]-beta: for j from 3 to M do OC[j,i]:=V[j]-twistup(Id[i],j-3) od: od: # Isotropy groups: the permutations of the variables x0,x1,x2,x3 # that leave each T-fixpoint fixed. Permutations are products of # disjoint cycles, all are sugroups of the symmetric group S4. with(group): # use "group" package isot[1]:=permgroup(4,{[[1,4],[2,3]]}): # switch x0<->x3 and x1<->x2 isot[2]:=permgroup(4,{[[1,2]],[[1,2,3]]}): # all perms of x0,x1,x2 isot[3]:=permgroup(4,{[]}): # no isotropy isot[4]:=permgroup(4,{[[1,2]],[[3,4]]}): # switch x0<->x1 or x2<->x3 isot[5]:=permgroup(4,{[[2,3]]}): # symmetric in x1 and x2 isot[6]:=permgroup(4,{[]}): # no isotropy isot[7]:=permgroup(4,{[]}): # no isotropy isot[8]:=permgroup(4,{[]}): # no isotropy # To generate all fixpoints, we move the 8 given ones with one # representatives for each coset of the isotropy group. S4:=permgroup(4,{[[1,2]],[[1,2,3,4]]}): # symmetric group on x0,x1,x2,x3 for i to 8 do orb[i]:=cosets(S4,isot[i]) od:# repr. modulo isotropy # To prepare input in Bott's formula, here is the part of the denominator # which comes from deformations within the fixed P^3. for i from 1 to 8 do den[i]:=prodwts(TH[i]) od: # For the numerators, we need the weight products of the spaces of # global sections of various twists. Here they are up to degree M=9: for i from 1 to 8 do for j from 1 to M do EEE[j,i]:=prodwts(OC[j,i]) od: od: #################################################################### # Here follows the actual coding of Bott's formula. If "degrs" is a # list of degrees, the number of twisted cubics on the corresponding # complete intersection in P^N is returned. See examples at the end. numberoftwistedcubics:=proc(N,degrs) local genf,WG,i,k,kk,j,fire,W4,P3,C,PN,rest,lis,result, TG,sstring,z,t,W,num,contP3; # Construct "random" weight vector # (WG := 4, 11, 17, 32, 55, 95, 160, 267) WG:=4,11; for i to N-1 do WG:=WG,WG[i]+WG[i+1]+2*i od; # Generate all invariant P^3-s, i.e. all 4-element subsets # of the variables x0,...,xN. Do this via a generating function: genf :=expand(product('1+z.i*t','i'=1..N+1)): fours :=convert(coeff(genf,t,4),list): # products of 4 vars. PN :=coeff(genf,t,N+1): # product of all vars. sstring:=seq(z.i=i,i=1..N+1): # vars. -> indices # Numerator and fraction: for i from 1 to 8 do num[i]:=product(EEE[degrs[k],i],k=1..nops(degrs)); fra[i]:=unapply(num[i]/den[i],w0,w1,w2,w3); od: # Summation over all fixpoints in a given P3 (generic weights): contP3:=0; for i to 8 do for j to nops(orb[i]) do contP3:=contP3+fra[i](op(permut(orb[i][j],[w0,w1,w2,w3]))) od od; contP3:=unapply(contP3,w0,w1,w2,w3); # Main loop, over "fours", the set of 4-element subsets: result:=0: # initialize result for P3 in fours do # P3 represents 4 variables C:=PN/P3: # C is the remaining vars. fire:=subs(sstring,convert(P3,list)): # just the indices of m rest:=subs(sstring,convert(C,list)): # the remaining indices TG:=product(product(WG[fire[k]]-WG[rest[kk]], k=1..4),kk=1..N-3): # tangent space of Grass(3,N) W:=seq(WG[fire[k]],k=1..4): k:='k': result:=result+contP3(W)/TG: # 1/TG is a common factor od: result; end: numberoftwistedcubics(4,[5]); numberoftwistedcubics(5,[3,3]); numberoftwistedcubics(5,[4,2]); numberoftwistedcubics(6,[3,2,2]); numberoftwistedcubics(7,[2,2,2,2]); numberoftwistedcubics(7,[9]); quit;