-- collect all information necessary -- for the calculation of the saturated -- prelog chow ring of Y in degree 3 restart -- the Kuenneth formula kuenneth = (Ring1,Ring2) -> ( gens12 := gens Ring1|gens Ring2; Ring12gen := ZZ[gens12,Degrees=>apply(gens12,degree)]; I12 := sub(ideal Ring1,Ring12gen)+sub(ideal Ring2,Ring12gen); assert isHomogeneous I12; Ring12 := Ring12gen/I12; Ring12.dim = Ring1.dim + Ring2.dim; makeZZbasisGb(Ring12); Ring12.Rfirst = Ring1; Ring12.Rsecond = Ring2; return Ring12 ) -- calculate the push forward im a Kuenneth situation -- -- given X -> X' and Y -> Y' -- produce X x Y -> X' x Y' -- caveat: uses that the bases of the rings -- are monomials iotaLowKuenneth = (Ring12up,Ring12low,iotaLow1,iotaLow2) -> ( matrix{apply(flatten entries ZZbasis(Ring12up),i->( coeff = coefficients(i,Variables => flatten entries sub(vars Ring12up.Rfirst,Ring12up)); mFirst = (sub(coeff#0,Ring12up.Rfirst))_0_0; mSecond = (sub(coeff#1,Ring12up.Rsecond))_0_0; ( sub(push(mFirst,iotaLow1),Ring12low)* sub(push(mSecond,iotaLow2),Ring12low) ) ))} ) -- make an ideal from a dual soccle generator -- Rgen : a ring -- Rgen.dsg : the dual soccle generator idealFromDSG = (Rgen) -> ( d := sum degree(Rgen.dsg); sum apply(d+2,i->( bb := basis(i,Rgen); bbOrth := transpose basis(d-i,Rgen); ideal (bb*syz sub(contract(bbOrth,contract(bb,Rgen.dsg)),ZZ)) )) ) -- store ZZ-bases for a list of degrees in a ring, -- using groebner basis -- -- !! Caveat: these might only be generating sets, !! -- !! not bases !! makeZZbasisGb = (R) -> apply(R.dim+1,i->( R#("ZZbasis",i) = basis(i,R) )) -- return all generators ZZbasis = (R) -> matrix{flatten apply(R.dim+1,i->flatten entries R#("ZZbasis",i))} -- calculate a list the dimensions of the graded pieces gradedDim = (R) -> apply(R.dim+1,i->rank source R#("ZZbasis",i)) -- The intersection rings used as building blocks -- S = IP^1 x IP^1 -- as first factor RSfirst = ZZ[r1,r2]/ideal(r1^2,r2^2) RSfirst.dim = 2 makeZZbasisGb(RSfirst) -- as second factor RSsecond = ZZ[R1,R2]/ideal(R1^2,R2^2) RSsecond.dim = 2 makeZZbasisGb(RSsecond) -- L_C -- the generators RLCfirstGen = ZZ[e,h,f,Degrees=>{1,1,2}] RLCsecondGen = ZZ[E,H,F,Degrees=>{1,1,2}] -- map from first to second factor fLC12 = map(RLCsecondGen,RLCfirstGen,vars RLCsecondGen) -- the dual soccle generator RLCfirstGen.dsg = h^3-6*h*e^2-30*e^3-e*f RLCsecondGen.dsg = fLC12(RLCfirstGen.dsg) -- the ideal ILCfirst = idealFromDSG(RLCfirstGen) ILCsecond = fLC12(ILCfirst) -- the rings RLCfirst = RLCfirstGen/ILCfirst RLCfirst.dim = 3 makeZZbasisGb(RLCfirst) RLCsecond = RLCsecondGen/ILCsecond RLCsecond.dim = 3 makeZZbasisGb(RLCsecond) -- TEST: are the dimensions as expected? assert ({1,2,2,1} == gradedDim(RLCfirst)) assert ({1,2,2,1} == gradedDim(RLCsecond)) -- the pull-backs to S iotaUpSLCfirst = sub(matrix{{3*(r1+r2),(r1+r2),r1*r2}},RSfirst) iotaUpSLCsecond = sub(matrix{{3*(R1+R2),(R1+R2),R1*R2}},RSsecond) -- TEST: (notice the syntax) assert (3*(r1+r2) == sub(e,iotaUpSLCfirst)) assert (R1+R2 == sub(H,iotaUpSLCsecond)) -- make a vector with resprect to the given ZZ-basis toVector = (zz) -> ( if zz == 0 then return 0; d := sum degree zz; R := ring zz; sub(fold((a,b)->(a||b), apply(R.dim+1,i->( if i!=d then return transpose(R#("ZZbasis",i)*0); zz // R#("ZZbasis",i) )) ),ZZ) ) -- calculate the push forward -- zz : an element in the source ring -- iotaLowMatrix : a matrix of elements in the target ring. push = (zz,iotaLowMatrix) -> (iotaLowMatrix*toVector(zz))_0_0 -- TEST : does the vector give back the element? assert (0==ZZbasis(RSfirst)*toVector(r1+r2) - matrix{{r1+r2}}) assert (0==ZZbasis(RSfirst)*toVector(r1*r2) - matrix{{r1*r2}}) -- the push-forward from S iotaLowSLCfirst = matrix{{2*h-e,h^2-3*f,h^2-3*f,h^3}} iotaLowSLCsecond = matrix{{2*H-E,H^2-3*F,H^2-3*F,H^3}} -- TEST: is the push forward ok in examples? assert (push(1_RSfirst,iotaLowSLCfirst) == 2*h-e) assert (push(r1+r2,iotaLowSLCfirst) == 2*h^2-6*f) -- test push pull formula testPushPull = (ioUp,ioLow) -> ( Rup = ring ioUp; Rlow = ring ioLow; fold((a,b)->(a and b), apply( flatten entries ZZbasis(Rlow), i->( push(sub(i,ioUp),ioLow) ==i*push(1_Rup,ioLow) ) ) )) -- TEST: push pull for S --> L_C assert testPushPull(iotaUpSLCfirst,iotaLowSLCfirst) assert testPushPull(iotaUpSLCsecond,iotaLowSLCsecond) -- Q -- the generators RQfirstGen = ZZ[s,l,Degrees=>{1,2}] RQsecondGen = ZZ[S,L,Degrees=>{1,2}] -- map from first to second factor fQ12 = map(RQsecondGen,RQfirstGen,vars RQsecondGen) -- the dual soccle generator RQfirstGen.dsg = 2*s^3+s*l RQsecondGen.dsg = fQ12(RQfirstGen.dsg) -- the ideals IQfirst = idealFromDSG(RQfirstGen) IQsecond = fQ12(IQfirst) -- the rings RQfirst = RQfirstGen/IQfirst RQfirst.dim = 3 makeZZbasisGb(RQfirst) RQsecond = RQsecondGen/IQsecond RQsecond.dim = 3 makeZZbasisGb(RQsecond) -- TEST: are the dimensions as expected? assert ({1,1,1,1} == gradedDim(RQfirst)) assert ({1,1,1,1} == gradedDim(RQsecond)) -- the pull-backs to S iotaUpSQfirst = matrix{{r1+r2,r1*r2}} iotaUpSQsecond = matrix{{R1+R2,R1*R2}} -- TEST: (notice the syntax) assert (r1+r2 == sub(s,iotaUpSQfirst)) assert (R1*R2 == sub(L,iotaUpSQsecond)) -- the push forwards iotaLowSQfirst = matrix{{s,l,l,s*l}} iotaLowSQsecond = matrix{{S,L,L,S*L}} -- TEST: the push pull formula assert testPushPull(iotaUpSQfirst,iotaLowSQfirst) assert testPushPull(iotaUpSQsecond,iotaLowSQsecond) -- N RN = ZZ[nu,r1,r2,R1,R2]/ideal( r1^2,r2^2,R1^2,R2^2, (nu-r1-r2)*(nu+R1+R2) ) RN.dim = 5 makeZZbasisGb(RN) -- TEST: are the dimensions as expected? assert ({1, 5, 10, 10, 5, 1} == gradedDim(RN)) -- LCxQ RLCxQ = kuenneth(RLCfirst,RQsecond) -- QxLC RQxLC = kuenneth(RQfirst,RLCsecond) -- SxS RSxS = kuenneth(RSfirst,RSsecond) iotaLowSxSLCxQ = iotaLowKuenneth(RSxS,RLCxQ,iotaLowSLCfirst,iotaLowSQsecond) iotaLowSxSQxLC = iotaLowKuenneth(RSxS,RQxLC,iotaLowSQfirst,iotaLowSLCsecond) -- the pullbacks. -- -- iotaUp#(i,j) will return a ring map from Y_j to Y_i iotaUp = new MutableHashTable -- iotaLow#(i,j) will return a ring map from Y_i to Y_j iotaLow = new MutableHashTable ------------------ -- Y1 = LC x LC -- ------------------ -- the generators RY1gen = ZZ[D,e,h,f,E,H,F,Degrees=>{3,1,1,2,1,1,2}] -- the dual soccle generator RY1gen.dsg = ( sub(RLCfirstGen.dsg,RY1gen)*sub(RLCsecondGen.dsg,RY1gen) +D*(30*e^2*E + 30*e*E^2 + 6*e*E*h + 6*e*E*H + E*f + e*F) -6*D^2 ) -- the ideal IY1 = idealFromDSG(RY1gen) -- TEST assert isHomogeneous IY1 -- the ring Y1 = RY1gen/IY1 Y1.dim = 6 makeZZbasisGb(Y1) Y1.Rfirst = RLCfirst Y1.Rsecond = RLCsecond -- TEST: is the dimension as expected? assert ({1,4,8,11,8,4,1} == gradedDim(Y1)) -------- -- Y2 -- -------- -- the module generators of N use RN gensRN = { nu*R2, nu*R1*R2, nu*R1, nu*r2*R2, nu*r2*R1*R2, nu*r2*R1, nu*r2, nu*r1*R2, nu*r1*R1*R2, nu*r1*R1, nu*r1*r2*R2, nu*r1*r2*R1*R2, nu*r1*r2*R1, nu*r1*r2, nu*r1, nu, r1*r2,sub(1,RN), r2*R2, r2*R1*R2, r2*R1,r1*R2, r1*R1*R2, r1*R1, r1*r2*R2, r1*r2*R1*R2, r1*r2*R1, r2, r1, R2, R1, R1*R2 } N = symbol N -- the generators RY2gen = ZZ[e,h,f,S,L,apply(gensRN,i->N_i), Degrees => {1,1,2,1,2}|apply(gensRN,i->1+sum degree i), MonomialOrder => Lex] -- push forward to ring without relations iotaLowNY2gen = matrix{apply(flatten entries ZZbasis(RN),i->N_i)} -- relations on the exceptional divisor idealNY2 = ideal mingens ideal flatten apply(gensRN,i->apply(gensRN,j-> push(i,iotaLowNY2gen)*push(j,iotaLowNY2gen) +push(nu*i*j,iotaLowNY2gen) )) -- pullback from LCxQ to SxS -- (but lifted to the rings of Y2 and N) iotaUpSxSLCxQ = ( sub(iotaUpSLCfirst,RN)| sub(iotaUpSQsecond,RN)| matrix{{32:0}} ) -- relations comming from restrictions idealRestrictionY2 = ideal flatten apply(flatten entries (sub(vars RLCfirst,RY2gen)|sub(vars RQsecond,RY2gen)), i->(apply(gensRN,j->( i*push(j,iotaLowNY2gen) -push(sub(i,iotaUpSxSLCxQ)*j,iotaLowNY2gen) )))) -- the ideal without kernel IY2noKer = sub(ILCfirst,RY2gen)+sub(IQsecond,RY2gen)+idealNY2+idealRestrictionY2 -- relations comming from the kernel CH(SxS) -> CH(N) + CH(LxQ) use RN; chQ2 = nu-r1-r2+R1+R2 topY2 = sub(h^3*S*L,RY2gen)+push(r1*r2*R1*R2*nu,iotaLowNY2gen) % IY2noKer IY2ker = ideal apply(flatten entries ZZbasis(RSxS),i->( j = ( sub(push(i,iotaLowSxSLCxQ),RY2gen) -push(chQ2*sub(i,RN),iotaLowNY2gen) ); -- TEST: is the relation homogeneous assert isHomogeneous j; -- TEST: does the relation intersect to zero with -- all other elements (modulo the ideals so far) assert (0 == contract((j*basis(6-sum degree j,RY2gen)) % IY2noKer,topY2)); j )); -- the ideal IY2 = IY2noKer+IY2ker; -- TEST assert isHomogeneous IY2 -- the ring Y2 = RY2gen/IY2 Y2.dim = 6 makeZZbasisGb(Y2) -- TEST: are the dimensions as expected? assert (gradedDim(Y2) == ({0}|gradedDim RSxS|{0})+gradedDim RLCxQ) assert (gradedDim(Y2) == {1, 4, 9, 12, 9, 4, 1}) -------- -- Y3 -- -------- M = symbol M -- the generators RY3gen = ZZ[s,l,E,H,F,apply(gensRN,i->M_i), Degrees => {1,2,1,1,2}|apply(gensRN,i->1+sum degree i), MonomialOrder => Lex] -- the natural section is differend since the normal bundle is twisted nu3 = nu-r1-r2+R1+R2 -- push forward to ring without relations iotaLowNY3gen = matrix{apply(flatten entries ZZbasis(RN),i->M_i)} -- relations on the exceptional divisor idealNY3 = ideal mingens ideal flatten apply(gensRN,i->apply(gensRN,j-> push(i,iotaLowNY3gen)*push(j,iotaLowNY3gen) +push(nu3*i*j,iotaLowNY3gen) )) -- pullback from LCxQ to SxS -- (but lifted to the rings of Y2 and N) iotaUpSxSQxLC = ( sub(iotaUpSQfirst,RN)| sub(iotaUpSLCsecond,RN)| matrix{{32:0}} ) -- relations comming from restrictions idealRestrictionY3 = ideal flatten apply(flatten entries (sub(vars RQfirst,RY3gen)|sub(vars RLCsecond,RY3gen)), i->(apply(gensRN,j->( i*push(j,iotaLowNY3gen) -push(sub(i,iotaUpSxSQxLC)*j,iotaLowNY3gen) )))) -- the ideal without kernel IY3noKer = sub(IQfirst,RY3gen)+sub(ILCsecond,RY3gen)+idealNY3+idealRestrictionY3 -- relations comming from the kernel CH(SxS) -> CH(N) + CH(LxQ) use RN; chQ3 = nu3+r1+r2-R1-R2 -- is ist ok here? topY3 = sub(s*l*H^3,RY3gen)+push(r1*r2*R1*R2*nu,iotaLowNY3gen) % IY3noKer IY3ker = ideal apply(flatten entries ZZbasis(RSxS),i->( j = ( sub(push(i,iotaLowSxSQxLC),RY3gen) -push(chQ3*sub(i,RN),iotaLowNY3gen) ); -- TEST: is the relation homogeneous assert isHomogeneous j; -- TEST: does the relation intersect to zero with -- all other elements (modulo the ideals so far) assert (0 == contract((j*basis(6-sum degree j,RY3gen)) % IY3noKer,topY3)); j )); -- the ideal IY3 = IY3noKer+IY3ker; -- TEST assert isHomogeneous IY3 -- the ring Y3 = RY3gen/IY3 Y3.dim = 6 makeZZbasisGb(Y3) -- TEST: are the dimensions as expected? assert (gradedDim(Y3) == ({0}|gradedDim RSxS|{0})+gradedDim RQxLC) assert (gradedDim(Y3) == {1, 4, 9, 12, 9, 4, 1}) ---------------- -- Y4 = Q x Q -- ---------------- -- the ring Y4 = kuenneth(RQfirst,RQsecond) -- TEST: are the dimension as expected? assert ({1, 2, 3, 4, 3, 2, 1} == gradedDim(Y4)) ----------------------- -- the intersections -- ----------------------- Y12 = kuenneth(RLCfirst,RSsecond) Y13 = kuenneth(RSfirst,RLCsecond) Y23 = RN Y24 = kuenneth(RSfirst,RQsecond) Y34 = kuenneth(RQfirst,RSsecond) Y123 = RSxS Y234 = RSxS -- the pull backs iotaUp = new MutableHashTable -- the push forwards iotaLow = new MutableHashTable --------------------------- ------ push + pull -------- -- triple intersections --- --------------------------- ----------------- -- Y123 -> Y12 -- ----------------- -- pull back iotaUp#({1,2,3},{1,2}) = sub(iotaUpSLCfirst,Y123)|sub(vars RSsecond,Y123) -- push forward iotaLow#({1,2,3},{1,2}) = iotaLowKuenneth(Y123,Y12,iotaLowSLCfirst,ZZbasis(RSsecond)) -- TEST: is the push pull formula ok? assert testPushPull(iotaUp#({1,2,3},{1,2}),iotaLow#({1,2,3},{1,2})) ----------------- -- Y123 -> Y23 -- ----------------- -- class of image use Y23; imageY123Y23 = nu+R1+R2 -- is this OK? -- push forward iotaLow#({1,2,3},{2,3}) = matrix{apply(flatten entries ZZbasis(Y123),i->imageY123Y23*sub(i,Y23))} -- pull back use Y123; iotaUp#({1,2,3},{2,3}) = matrix{ apply(gens Y23,i->sub(contract(sub(nu,Y23),imageY123Y23*i),Y123)) } -- TEST: is the push pull formula ok? assert testPushPull(iotaUp#({1,2,3},{2,3}),iotaLow#({1,2,3},{2,3})) ----------------- -- Y123 -> Y13 -- ----------------- -- pull back iotaUp#({1,2,3},{1,3}) = sub(vars RSfirst,Y123)|sub(iotaUpSLCsecond,Y123) -- push forward iotaLow#({1,2,3},{1,3}) = iotaLowKuenneth(Y123,Y13,ZZbasis(RSfirst),iotaLowSLCsecond) -- TEST: is the push pull formula ok? assert testPushPull(iotaUp#({1,2,3},{1,3}),iotaLow#({1,2,3},{1,3})) ----------------- -- Y234 -> Y23 -- ----------------- -- class of image use Y23; imageY234Y23 = nu-r1-r2 -- is this OK? -- push forward iotaLow#({2,3,4},{2,3}) = matrix{apply(flatten entries ZZbasis(Y234),i->imageY234Y23*sub(i,Y23))} -- pull back use Y234; iotaUp#({2,3,4},{2,3}) = matrix{ apply(gens Y23,i->sub(contract(sub(nu,Y23),imageY234Y23*i),Y234)) } -- TEST: is the push pull formula ok? assert testPushPull(iotaUp#({2,3,4},{2,3}),iotaLow#({2,3,4},{2,3})) ----------------- -- Y234 -> Y24 -- ----------------- -- pull back iotaUp#({2,3,4},{2,4}) = sub(vars RSfirst,Y234)|sub(iotaUpSQsecond,Y234) -- push forward iotaLow#({2,3,4},{2,4}) = iotaLowKuenneth(Y234,Y24,ZZbasis(RSfirst),iotaLowSQsecond) -- TEST: is the push pull formula ok? assert testPushPull(iotaUp#({2,3,4},{2,4}),iotaLow#({2,3,4},{2,4})) ----------------- -- Y234 -> Y34 -- ----------------- -- pull back iotaUp#({2,3,4},{3,4}) = sub(iotaUpSQfirst,Y234)|sub(vars RSsecond,Y234) -- push forward iotaLow#({2,3,4},{3,4}) = iotaLowKuenneth(Y234,Y34,iotaLowSQfirst,ZZbasis(RSsecond)) -- TEST: is the push pull formula ok? assert testPushPull(iotaUp#({2,3,4},{3,4}),iotaLow#({2,3,4},{3,4})) --------------------------- ------ push + pull -------- -- double intersections --- --------------------------- ---------------- -- Y12 --> Y1 -- ---------------- -- the pullback Y12 --> Y1 use Y12; iotaUp#({1,2},{1}) = ( matrix{{e*R1*R2+3*f*(R1+R2)}}| -- is this OK? sub(vars RLCfirst,Y12)| sub(iotaUpSLCsecond,Y12) ) -- TEST: are the degrees ok? assert (degrees source vars Y1 == degrees source iotaUp#({1,2},{1})) -- TEST: are the entries homogenoeus? assert isHomogeneous iotaUp#({1,2},{1}) -- TEST: are the number of variables and their degrees correct? assert isHomogeneous sub(vars Y1,iotaUp#({1,2},{1})) -- the push forward Y12 -> Y1 iotaLow#({1,2},{1}) = iotaLowKuenneth(Y12,Y1,ZZbasis(RLCfirst),iotaLowSLCsecond) -- TEST: is the push pull formula ok? assert testPushPull(iotaUp#({1,2},{1}),iotaLow#({1,2},{1})) ---------------- -- Y13 --> Y1 -- ---------------- -- the pullback Y13 --> Y1 use Y13; iotaUp#({1,3},{1}) = ( matrix{{r1*r2*E+3*(r1+r2)*F}}| -- is this OK? sub(iotaUpSLCfirst,Y13)| sub(vars RLCsecond,Y13) ) -- TEST: are the degrees ok? assert (degrees source vars Y1 == degrees source iotaUp#({1,3},{1})) -- TEST: are the entries homogenoeus? assert isHomogeneous iotaUp#({1,3},{1}) -- TEST: are the number of variables and their degrees correct? assert isHomogeneous sub(vars Y1,iotaUp#({1,3},{1})) -- the push forward Y13 -> Y1 iotaLow#({1,3},{1}) = iotaLowKuenneth(Y13,Y1,iotaLowSLCfirst,ZZbasis(RLCsecond)) -- TEST: is the push pull formula ok? assert testPushPull(iotaUp#({1,3},{1}),iotaLow#({1,3},{1})) --------------- -- Y23 -> Y2 -- --------------- -- the pullback use Y23; iotaUp#({2,3},{2}) = ( sub(iotaUpSLCfirst,Y23)| sub(iotaUpSQsecond,Y23)| matrix{apply(gensRN,i->-nu*i)} ) -- TEST: is the pullback consistent with the ideals? assert (sub(vars RY2gen,iotaUp#({2,3},{2}))==sub(vars Y2,iotaUp#({2,3},{2}))) assert (0==sub(IY2,iotaUp#({2,3},{2}))) -- (detects for example the sign before nu*i above) -- the push forward use Y2; iotaLow#({2,3},{2}) = matrix{apply( (flatten entries ZZbasis(Y23)),i->( sub(push(i,iotaLowNY2gen),Y2) ))} -- TEST: is the push pull formula ok? assert testPushPull(iotaUp#({2,3},{2}),iotaLow#({2,3},{2})) --------------- -- Y12 -> Y2 -- --------------- -- LC x S -> LC x Q -> Y2 -- the pullback use Y12; iotaUp#({1,2},{2}) = ( sub(vars RLCfirst,Y12)| sub(iotaUpSQsecond,Y12)| matrix{apply(gensRN,i->push(sub(i,iotaUp#({1,2,3},{2,3})),iotaLow#({1,2,3},{1,2})))} ) -- push forward to LCxQ iotaLowY12LCxQ = iotaLowKuenneth(Y12,RLCxQ,ZZbasis(RLCfirst),iotaLowSQsecond) -- the push forward iotaLow#({1,2},{2}) = matrix{apply(flatten entries ZZbasis(Y12),i-> ( sub(push(i,iotaLowY12LCxQ),Y2) -push(sub(sub(i,iotaUp#({1,2,3},{1,2})),Y23),iotaLow#({2,3},{2})) ) )} -- TEST: is the push pull formula ok? assert testPushPull(iotaUp#({1,2},{2}),iotaLow#({1,2},{2})) -- (detects "-push(.."-part in iotaLow#({1,2},{2})) -- TEST: is the push pull formula ok? assert testPushPull(iotaUp#({2,3},{2}),iotaLow#({2,3},{2})) -- TEST: do the pull backs commute? assert ( 0==( sub(iotaUp#({1,2},{2}),iotaUp#({1,2,3},{1,2})) -sub(iotaUp#({2,3},{2}),iotaUp#({1,2,3},{2,3})) ) ) -- TEST: do the push forwards commute? apply(flatten entries ZZbasis(Y123),i->( assert( push(push(i,iotaLow#({1,2,3},{1,2})),iotaLow#({1,2},{2})) ==push(push(i,iotaLow#({1,2,3},{2,3})),iotaLow#({2,3},{2})) ) )); --------------- -- Y24 -> Y2 -- --------------- -- S x Q -> LC x Q -> Y2 -- the pullback use Y24; iotaUp#({2,4},{2}) = ( sub(iotaUpSLCfirst,Y24)| sub(vars RQsecond,Y24)| matrix{apply(gensRN,i->push(sub(i,iotaUp#({2,3,4},{2,3})),iotaLow#({2,3,4},{2,4})))} ) -- push forward to LCxQ iotaLowY24LCxQ = iotaLowKuenneth(Y24,RLCxQ,iotaLowSLCfirst,ZZbasis(RQsecond)) -- the push forward iotaLow#({2,4},{2}) = matrix{apply(flatten entries ZZbasis(Y24),i-> ( sub(push(i,iotaLowY24LCxQ),Y2) -push(sub(sub(i,iotaUp#({2,3,4},{2,4})),Y23),iotaLow#({2,3},{2})) ) )} -- TEST: is the push pull formula ok? assert testPushPull(iotaUp#({2,4},{2}),iotaLow#({2,4},{2})) -- TEST: do the pull backs commute? assert ( 0==( sub(iotaUp#({2,4},{2}),iotaUp#({2,3,4},{2,4})) -sub(iotaUp#({2,3},{2}),iotaUp#({2,3,4},{2,3})) ) ) -- TEST: do the push forwards commute? apply(flatten entries ZZbasis(Y234),i->( assert( push(push(i,iotaLow#({2,3,4},{2,4})),iotaLow#({2,4},{2})) ==push(push(i,iotaLow#({2,3,4},{2,3})),iotaLow#({2,3},{2})) ) )); --------- -- Y3 --- --------- --------------- -- Y23 -> Y3 -- --------------- -- the pullback use Y23; iotaUp#({2,3},{3}) = ( sub(iotaUpSQfirst,Y23)| sub(iotaUpSLCsecond,Y23)| matrix{apply(gensRN,i->-nu3*i)} ) -- TEST: is the pullback consistent with the ideals? assert (sub(vars RY3gen,iotaUp#({2,3},{3}))==sub(vars Y3,iotaUp#({2,3},{3}))) assert (0==sub(IY3,iotaUp#({2,3},{3}))) -- (detects for example the sign before nu*i above) -- the push forward use Y3; iotaLow#({2,3},{3}) = matrix{apply( (flatten entries ZZbasis(Y23)),i->( sub(push(i,iotaLowNY3gen),Y3) ))} -- TEST: is the push pull formula ok? assert testPushPull(iotaUp#({2,3},{3}),iotaLow#({2,3},{3})) --------------- -- Y13 -> Y3 -- --------------- -- S x LC -> Q x LC -> Y3 -- the pullback use Y13; iotaUp#({1,3},{3}) = ( sub(iotaUpSQfirst,Y13)| sub(vars RLCsecond,Y13)| matrix{apply(gensRN,i->push(sub(i,iotaUp#({1,2,3},{2,3})),iotaLow#({1,2,3},{1,3})))} ) -- push forward to QxLC iotaLowY13QxLC = iotaLowKuenneth(Y13,RQxLC,iotaLowSQfirst,ZZbasis(RLCsecond)) -- the push forward iotaLow#({1,3},{3}) = matrix{apply(flatten entries ZZbasis(Y13),i-> ( sub(push(i,iotaLowY13QxLC),Y3) -push(sub(sub(i,iotaUp#({1,2,3},{1,3})),Y23),iotaLow#({2,3},{3})) ) )} -- TEST: is the push pull formula ok? assert testPushPull(iotaUp#({1,3},{3}),iotaLow#({1,3},{3})) -- TEST: do the pull backs commute? assert ( 0==( sub(iotaUp#({1,3},{3}),iotaUp#({1,2,3},{1,3})) -sub(iotaUp#({2,3},{3}),iotaUp#({1,2,3},{2,3})) ) ) -- TEST: do the push forwards commute? apply(flatten entries ZZbasis(Y123),i->( assert( push(push(i,iotaLow#({1,2,3},{1,3})),iotaLow#({1,3},{3})) ==push(push(i,iotaLow#({1,2,3},{2,3})),iotaLow#({2,3},{3})) ) )); --------------- -- Y34 -> Y3 -- --------------- -- Q x S -> Q x LC -> Y3 -- the pullback use Y34; iotaUp#({3,4},{3}) = ( sub(vars RQfirst,Y34)| sub(iotaUpSLCsecond,Y34)| matrix{apply(gensRN,i->push(sub(i,iotaUp#({2,3,4},{2,3})),iotaLow#({2,3,4},{3,4})))} ) -- push forward to LCxQ iotaLowY34QxLC = iotaLowKuenneth(Y34,RQxLC,ZZbasis(RQfirst),iotaLowSLCsecond) -- the push forward iotaLow#({3,4},{3}) = matrix{apply(flatten entries ZZbasis(Y34),i-> ( sub(push(i,iotaLowY34QxLC),Y3) -push(sub(sub(i,iotaUp#({2,3,4},{3,4})),Y23),iotaLow#({2,3},{3})) ) )} -- TEST: is the push pull formula ok? assert testPushPull(iotaUp#({3,4},{3}),iotaLow#({3,4},{3})) -- TEST: do the pull backs commute? assert ( 0==( sub(iotaUp#({3,4},{3}),iotaUp#({2,3,4},{3,4})) -sub(iotaUp#({2,3},{3}),iotaUp#({2,3,4},{2,3})) ) ) -- TEST: do the push forwards commute? apply(flatten entries ZZbasis(Y234),i->( assert( push(push(i,iotaLow#({2,3,4},{3,4})),iotaLow#({3,4},{3})) ==push(push(i,iotaLow#({2,3,4},{2,3})),iotaLow#({2,3},{3})) ) )); ---------------- -- Y34 --> Y4 -- ---------------- -- QxS \in QxQ -- the pullback Y34 --> Y4 iotaUp#({3,4},{4}) = ( sub(vars RQfirst,Y34)| sub(iotaUpSQsecond,Y34) ) -- TEST: are the degrees ok? assert (degrees source vars Y4 == degrees source iotaUp#({3,4},{4})) -- TEST: are the entries homogenoeus? assert isHomogeneous iotaUp#({3,4},{4}) -- TEST: are the number of variables and their degrees correct? assert isHomogeneous sub(vars Y4,iotaUp#({3,4},{4})) -- the push forward Y34 -> Y4 iotaLow#({3,4},{4}) = iotaLowKuenneth(Y34,Y4,ZZbasis(RQfirst),iotaLowSQsecond) -- TEST: is the push pull formula ok? assert testPushPull(iotaUp#({3,4},{4}),iotaLow#({3,4},{4})) ---------------- -- Y24 --> Y4 -- ---------------- -- SxQ \in QxQ -- the pullback Y24 --> Y4 iotaUp#({2,4},{4}) = ( sub(iotaUpSQfirst,Y24)| sub(vars RQsecond,Y24) ) -- TEST: are the degrees ok? assert (degrees source vars Y4 == degrees source iotaUp#({2,4},{4})) -- TEST: are the entries homogenoeus? assert isHomogeneous iotaUp#({2,4},{4}) -- TEST: are the number of variables and their degrees correct? assert isHomogeneous sub(vars Y4,iotaUp#({2,4},{4})) -- the push forward Y24 -> Y4 iotaLow#({2,4},{4}) = iotaLowKuenneth(Y24,Y4,iotaLowSQfirst,ZZbasis(RQsecond)) -- TEST: is the push pull formula ok? assert testPushPull(iotaUp#({2,4},{4}),iotaLow#({2,4},{4})) end ---------------- restart time load"prelogVxVparts.m2" -- used 22.5259 seconds