diff --git a/CYToolsM2/DanilovKhovanskii.m2 b/CYToolsM2/DanilovKhovanskii.m2 new file mode 100644 index 0000000..d884e45 --- /dev/null +++ b/CYToolsM2/DanilovKhovanskii.m2 @@ -0,0 +1,1416 @@ +newPackage( + "DanilovKhovanskii", + Version => "0.1", + Date => "6 April 2023", + Headline => "Computing Hodge-Deligne polynomials of toric hypersurfaces", + Authors => {{ Name => "", Email => "", HomePage => ""}}, + PackageExports => {"Polyhedra", "StringTorics"}, + AuxiliaryFiles => false, + DebuggingMode => true + ) + +export {"Cheap", + "vdot", + "torusFactor", + "stdVector", + "manyMatricesToLargeMatrix", + "manyPolyhedraToLargeMatrix", + "manyPolyhedraToLargeOne", + "ehrhartNumerator", + "ehrhartNumeratorQuicker", + "computeSumqeZ", + "getSparseeZ", + "eZ2hZ", + "toeZMatrix", + "matchCones", + "fanRayList", + "makeConeToFaceDict", + "makeConeTable", + "computeHodgeDeligne", + "computeHodgeDeligneInPToric", + "computeHodgeDeligneAffineAndTorus", + "computeHodgeDeligneTorusCI", + "FaceInfo", + "EmptyValue"} + +-* Code section *- +stdVector = method();--index from 0 +stdVector (ZZ, ZZ) := (n, i) -> ( + for j from 0 to n - 1 list (if j == i then 1 else 0) + ) + +manyMatricesToLargeMatrix = method(); +manyMatricesToLargeMatrix List := Ms -> ( + r := #Ms; + transpose matrix prepend(for i from 1 to numrows(Ms#0) + r list 0, flatten for i from 0 to r - 1 list ( + for j from 0 to numcols(Ms#i) - 1 list ( + entries((Ms#i)_j) | stdVector(r, i) + ) + )) + ) + +manyPolyhedraToLargeMatrix = method(); +manyPolyhedraToLargeMatrix List := Ps -> ( + Ms := for P in Ps list vertices P; + manyMatricesToLargeMatrix(Ms) + ) + +manyPolyhedraToLargeOne = method(); +manyPolyhedraToLargeOne List := Ps -> ( + c := #Ps; + convexHull manyPolyhedraToLargeMatrix(Ps) + ) + +ehrhartNumerator = method(); +ehrhartNumerator Polyhedron := P -> ( + d := dim P; + t := getSymbol "t"; + R := QQ[t]; + f := 1 + sum for i from 1 to d list ( + a := #latticePoints(i * P); + a * R_0^i + ); + g := f * (1 - R_0)^(d + 1); + for i from 0 to d list ( + lift(coefficient(R_0^i, g), ZZ) + ) + ) + +ehrhartNumeratorQuicker = method(); +ehrhartNumeratorQuicker Polyhedron := P -> ( + d := dim P; + Ps := for i from 1 to ceiling(d / 2) list i * P; + l := prepend(1, for i from 1 to ceiling(d / 2) list ( + #latticePoints(Ps#(i - 1)) + )); + --The coefficients of the Ehrhart numerator of reflexive polytopes + --is symmetric: c_i = c_{d-i}. + if isReflexive P then ( + hs1 := prepend(1, for i from 1 to ceiling(d / 2) list ( + sum for j from max(0, i - d - 1) to i list (-- print(i, j); + (-1)^(i - j) * binomial(d + 1, i - j) * l#(j) + ) + ) + ); + hs2 := for i from ceiling(d / 2) + 1 to d list ( + hs1#(d - i) + ); + return join(hs1, hs2); + ); + --Instead of using #latticePoints(i * P) for ceiling(d / 2) < i <= d, + --one can use #interiorLatticePoints(i * P) for 0 < i <= floor (d / 2). + lint := for i from 1 to floor(d / 2) list ( + #interiorLatticePoints(Ps#(i - 1)) + ); + prepend(1, for i from 1 to d list ( + if i <= ceiling(d / 2) then ( + sum for j from max(0, i - d - 1) to i list (-- print(i, j); + (-1)^(i - j) * binomial(d + 1, i - j) * l#(j) + ) + ) + else ( + sum for j from max(1, i - d - 1) to d + 1 - i list (-- print(i, j); + (-1)^(d + 1 - i - j) * binomial(d + 1, d + 1 - i - j) * lint#(j - 1) + ) + ) + )) + ) + +computeSumqeZ = method();--from 4.6 of Danilov and Khovanskii [though that may need a factor of (-1)^d in front of \psi_{d+1}(\Delta)] +computeSumqeZ (Polyhedron, List, ZZ) := (P, psi, p) -> ( + d := dim P; + --ehrhart(P) computes lattice points in first d dilations to figure out polynomial, so just find lattice points + (-1)^(d - 1) * ((-1)^p * binomial(d, p + 1) + psi_(p+1)) + ) + +eZ2hZ = method(); +eZ2hZ (Polyhedron, MutableHashTable) := (P, eZ) -> ( + hZ := new MutableHashTable; + if isSimplicial normalFan P then (--not exactly right + for key in keys eZ do hZ#key = (-1)^(key#0 + key#1) * eZ#key; + ) + else ( + error "Not enough information. Can only recover Hodge numbers from the Hodge Deligne polynomial for smooth and/or simplicial varieties." + ); + hZ + ) + +eZ2hZ (Polyhedron, HashTable) := (P, eZ) -> ( + hZ := new MutableHashTable; + if isSimplicial normalFan P then (--not exactly right + for key in keys eZ do hZ#key = (-1)^(key#0 + key#1) * eZ#key; + ) + else ( + error "Not enough information. Can only recover Hodge numbers from the Hodge Deligne polynomial for smooth and/or simplicial varieties." + ); + new HashTable from hZ + ) + +getSparseeZ = method(); +getSparseeZ (MutableHashTable, Sequence) := (eZ, pq) -> ( + if eZ#?pq then eZ#pq else 0 + ) + +getSparseeZ (HashTable, Sequence) := (eZ, pq) -> ( + if eZ#?pq then eZ#pq else 0 + ) + +toeZMatrix = method(Options => {EmptyValue => 0}); +toeZMatrix HashTable := opts -> H -> ( + --assume indexing starts at 0 + nr := 0; + nc := 0; + for mn in keys H do ( + if mn#0 > nr then nr = mn#0; + if mn#1 > nc then nc = mn#1; + ); + M := matrix for n from 0 to nc list ( + for m from 0 to nr list ( + if H#?(m, n) then H#(m, n) else opts.EmptyValue + ) + ); + M + ) + +toeZMatrix MutableHashTable := opts -> H -> ( + --assume indexing starts at 0 + nr := 0; + nc := 0; + for mn in keys H do ( + if mn#0 > nr then nr = mn#0; + if mn#1 > nc then nc = mn#1; + ); + M := matrix for n from 0 to nc list ( + for m from 0 to nr list ( + if H#?(m, n) then H#(m, n) else opts.EmptyValue + ) + ); + M + ) + +vdot = method(); +vdot (List, List) := (a, b) -> if #a == #b then ( + sum for i from 0 to #a-1 list a#i*b#i) else (error "Lengths not compatible.") + +torusFactor = method(); +torusFactor (MutableHashTable, ZZ, ZZ) := (eZ, d, D) -> (--d = dimension of polytope; D = dimension of lattice + dt := D - d; + eZproduct := new MutableHashTable from {}; + if dt == 0 then (--print("no torus factors"); + eZproduct = eZ + ) + else (print("torus factors: " | dt); + for p from 0 to D - 1 do ( + for q from 0 to D - 1 do ( + eZproduct#(p, q) = sum for i from 0 to dt list ( + (-1)^(dt - i) * binomial(dt, i) * getSparseeZ(eZ, (p - i, q - i)) + ); + ); + ); + ); + new HashTable from eZproduct + ) + +torusFactor (HashTable, ZZ, ZZ) := (eZ, d, D) -> (--d = dimension of polytope; D = dimension of lattice + dt := D - d; + eZproduct := new MutableHashTable from {}; + if dt == 0 then (--print("no torus factors"); + eZproduct = eZ + ) + else (print("torus factors: " | dt); + for p from 0 to D - 1 do ( + for q from 0 to D - 1 do ( + eZproduct#(p, q) = sum for i from 0 to dt list ( + (-1)^(dt - i) * binomial(dt, i) * getSparseeZ(eZ, (p - i, q - i)) + ); + ); + ); + ); + new HashTable from eZproduct + ) + +matchCones = method(); +matchCones (Cone, HashTable) := (c, Pcones) -> ( + a := true; + i := dim c; + d := max keys Pcones; + cnew := c; + while (a and i <= d) do ( + j := 0; + l := #Pcones#i; + while (a and j < l) do (--print(i, j, l); + if contains(Pcones#i#j, c) then ( + a = false; + cnew = Pcones#i#j; + ); + j = j + 1; + ); + i = i + 1; + ); + if a then error "No match found."; + cnew + ) + +fanRayList = method();--does not return lineality generators +--assume rays C is a subset of rays F +fanRayList (Cone, Fan) := (C, F) -> ( + rys := rays F; + linF := linealitySpace F; + nrys := numcols rys; + rs := rays C; + linC := linealitySpace C; + nrs := numcols rs; + --subs := subsets(0..numcols rys - 1, nrs); + --print(rys, linF, rs, linC);--, subs); + sort flatten if linF == 0 then ( + for r from 0 to nrs - 1 list ( + for ry from 0 to nrys - 1 list ( + if rs_r == rys_ry then ry else continue + --if image (rys_s | linF) == image (rs | linC) then s else continue + ) + ) + ) + else ( + for r from 0 to nrs - 1 list ( + for ry from 0 to nrys - 1 list ( + if minors(numcols linF + 1, linF | rs_{r} - rys_{ry}) == 0 then ry else continue + --if image (rys_s | linF) == image (rs | linC) then s else continue + ) + ) + ) + ) + +makeConeToFaceDict = method(); +makeConeToFaceDict (Polyhedron, Fan) := (P, Pfan) -> ( + rys := rays Pfan; + vs := vertices P; + dots := entries (transpose rys * vs);-- print(rys, vs, dots); + rys2vs := for r in dots list ( + mindot := r#0; + minvs := {0}; + for v from 1 to #r - 1 do ( + if r#v < mindot then ( + mindot = r#v; + minvs = {v}; + ) + else if r#v == mindot then ( + minvs = append(minvs, v); + ); + ); + minvs + );-- print(rys2vs); + new HashTable from flatten for i from 0 to dim Pfan list ( + for c in cones(i, Pfan) list ( + --dual face of c = intersection over rays in c of vertices in + --facets dual to each ray + c => if #c == 0 then ( + for v from 0 to numcols vs - 1 list v + ) + else ( + minvs := rys2vs#(c#0); + for r from 1 to #c - 1 do ( + minvs = for v in minvs list ( + if any(rys2vs#(c#r), x -> x == v) then v else continue + ); + ); + minvs + ) + ) + ) + ) + +makeConeTable = method(); +makeConeTable Fan := F -> ( + Fdim := dim F; + new HashTable from for i from 0 to Fdim list ( + Fdim - i => facesAsCones(i, F) + --i => cones(i, F) + ) + ) + +coneInPfanToFaceInP = method(); +--c is a list of rays in the cone +coneInPfanToFaceInP (List, Polyhedron, HashTable) := (c, P, ConeToFaceDict) -> ( + vlist := ConeToFaceDict#c; + (convexHull (vertices P)_(vlist), vlist) + ) + +coneInPfanToFaceInP (Cone, Polyhedron, Fan, HashTable) := (c, P, Pfan, ConeToFaceDict) -> ( + cl := fanRayList(c, Pfan); + vlist := ConeToFaceDict#cl; + (convexHull (vertices P)_(vlist), vlist) + ) + +coneInP'fanToConeInPfan = method(); +coneInP'fanToConeInPfan (Cone, HashTable) := (c, Pcones) -> ( + c1 := matchCones(c, Pcones); + c1 + ) + +coneInP'fanToFaceInP = method(); +coneInP'fanToFaceInP (Cone, Sequence) := (c, PFanConesDict) -> ( + (P, Pfan, Pcones, ConeToFaceDict) := PFanConesDict; + c1 := coneInP'fanToConeInPfan(c, Pcones); + coneInPfanToFaceInP(c1, P, Pfan, ConeToFaceDict) + ) + +computeHodgeDeligne = method(Options => {FaceInfo => {true, new HashTable, -1, ()}}); +--FaceInfo: first entry = true, if this is the full polytope, and = Sequence containing information about the full poltyope if not; +--second = data from lower-dimensional faces; +--third = dimension of ambient variety (will usually, but not always, be the number of rows of the vertex matrix) +--Note: Won't work if P is neither prime nor full-dimensional. +computeHodgeDeligne Polyhedron := opts -> P -> ( + --Store information about the normal fan, Pfan, or a simplicial subdivision thereof, P'fan. + topdim := opts.FaceInfo#0; + (Pfan, P'fan) := if #opts.FaceInfo#3 == 0 then ( + Pfan2 := normalFan P; + P'fan2 := if isSimplicial Pfan2 then (print("Pfan is simplicial"); + Pfan2 + ) + else (print("Pfan is not simplicial"); + rys := entries transpose rays Pfan2; + cs := maxCones Pfan2; + VP2 := normalToricVariety(rys, cs);--needs to be over ZZ? + VP'2 := makeSimplicial(VP2, Strategy => 1); + fan VP'2 + ); + (Pfan2, P'fan2) + ) + else opts.FaceInfo#3; + + --determine dimension of P and of the ambient space + d := dim P; + FanDim := dim P'fan; + D := opts.FaceInfo#2; + if D == -1 then ( + D = FanDim; + ); print("poly dim = "| d | ", ambient dim = " | D, topdim); + + eZ := new MutableHashTable; + eZbar := new MutableHashTable; + --For now, assume P is full dimensional (X has no torus factors). + --If dim P != dim X then (eZ = computeHodgeDeligne(restrict P) * (x*y - 1)^(dim X - dim P)) else + --This is implemented at the very end. + + --Base cases + if d == 0 then (--hypersurface is empty + return (new HashTable from eZ, new HashTable from eZbar, new HashTable from {}) + ) + else if d == 1 then (--print("dim(Z) = 0"); --hypersurface in 1-dimension is a collection of points + --always simplicial? + eZ#(0,0) = #latticePoints(P) - 1; + eZbar#(0,0) = #latticePoints(P) - 1; -- print(eZ#(0,0), eZbar#(0,0)); + eZ = torusFactor(eZ, d, D); + eZbar = torusFactor(eZbar, d, D); + return (new HashTable from eZ, new HashTable from eZbar, new HashTable from {}) + );-- print("not 0 or 1"); + + --Begin by computing eZ of the varieties corresponding to each cone of the [subdivided] normal fan, P'fan. + --This is known by induction. Build up from lowest dimension, 1. + eZcones := new MutableHashTable from opts.FaceInfo#1; + eZfaces := new MutableHashTable; + --print(opts.FaceInfo#1); print(eZcones); + --print("eZcones: " | #eZcones | " , keys(eZcones): " | #(keys eZcones)); + if #(keys eZcones) == 0 then (--print("no face info"); + Pcones := makeConeTable Pfan; + P'cones := makeConeTable P'fan; + ConeToFaceDict := makeConeToFaceDict(P, Pfan); + for n from 1 to d - 1 do ( + for i from 0 to #(P'cones#(FanDim - n)) - 1 do (--print(n, i, rays P'cones#(FanDim - n)#i); + (F, Fverts) := coneInP'fanToFaceInP(P'cones#(FanDim - n)#i, (P, Pfan, Pcones, ConeToFaceDict));-- print(Fverts, vertices F); + eZcones2 := new HashTable from flatten for k from 1 to n - 1 list ( + for l from 0 to #(P'cones#(FanDim - k)) - 1 list (-- print(Pfaces#(FanDim - k)#l#0, Pfaces#(FanDim - n)#i#0, isSubset(Pfaces#(FanDim - k)#l#0, Pfaces#(FanDim - n)#i#0)); + if contains(P'cones#(FanDim - k)#l, P'cones#(FanDim - n)#i) and eZcones#?(P'cones#(FanDim - k)#l) then P'cones#(FanDim - k)#l => eZcones#(P'cones#(FanDim - k)#l) else continue + ) + --for k in keys eZcones list (print(k, Pfaces#(FanDim - n)#i#0); + --if isSubset(k, Pfaces#(FanDim - n)#i#0) then (print("yes"); k => eZcones#k) else continue + );-- print("face ready"); print(eZcones2); + Fdim := dim F; + e := if eZfaces#?Fverts then (print("eZ_F already known"); + eZfaces#Fverts + ) + else ( + e2 := computeHodgeDeligne(F, FaceInfo => {false, eZcones2, Fdim, (Pfan, P'fan)}); + eZfaces#Fverts = e2#0;-- print(eZfaces#Fverts); + eZfaces#Fverts + );-- print(e); + eZcones#(P'cones#(FanDim - n)#i) = torusFactor(e, Fdim, n); + --eZcones#(Pfaces#(FanDim - n)#i#0) = e#0;--print(e); + + --Need to account for torus factors. + --The dimension of the ambient torus is n. The dimension of the Newton polytope is dim F. + --eZcones#(P'cones#(FanDim - n)#i) = torusFactor(e#0, dim F, n); print(dim F, n); + ); print("done " | n); + ); + );-- print("faces done");--Hodge-Deligne numbers of the face. + + --A couple of Lefschetz-type theorems and Gysin homomorphisms give eZ#(p, q) for p + q > d - 1 + --in terms of eT^d#(p + 1, q + 1) + --For p + q > d - 1, eZ#(p, q) is 0 for p != q and is (-1)^(d + p + 1) * binomial(d, p + 1) for p == q. + for p from floor(d / 2) to d - 1 do eZ#(p, p) = (-1)^(d + p + 1) * binomial(d, p + 1); --print("p + q > d - 1"); + + --This gives eZbar for p + q > d - 1. + --Poincare dualtiy then gives eZbar#(d - 1 - p, d - 1 - q) = eZbar#(p, q). + --Since eZbar#(p, q) is then known for p + q < d - 1, one can compute obtains eZ#(p, q) for p + q < d - 1. + --Where to stop? + for p from 0 to d - 1 do ( + for q from d - p to d - 1 do (--print(p,q); + eZbar#(p, q) = getSparseeZ(eZ, (p, q)) + sum ( + for k in keys eZcones list getSparseeZ(eZcones#k, (p, q)) + ); --print"a"; + eZbar#(d - 1 - p, d - 1 - q) = eZbar#(p, q); --print"b"; + eZ#(d - 1 - p, d - 1 - q) = eZbar#(d - 1 - p, d - 1 - q) - sum ( + for k in keys eZcones list getSparseeZ(eZcones#k, (d - 1 - p, d - 1 - q)) + ); --print"c"; + ); + ); --print("p + q < d - 1"); + + --The last remaining number, eZ#(p, d - 1 - p), is then the difference Sum_q eZ#(p, q) - Sum_{q != d - 1 - p} eZ#(p, q). + --Sum_q eZ#(p, q) can be calculated from the number of lattice points in the interior of each face. + psi := ehrhartNumeratorQuicker(P); + for p from 0 to d - 1 do ( + eZ#(p, d - 1 - p) = computeSumqeZ(P, psi, p) - sum ( + for q from 0 to d - 1 list ( + if q == d - 1 - p then continue else getSparseeZ(eZ, (p, q)) + ) + ); + eZbar#(p, d - 1 - p) = eZ#(p, d - 1 - p) + sum ( + for k in keys eZcones list getSparseeZ(eZcones#k, (p, d - 1 - p)) + ); + ); --print("p + q = d - 1"); + --hZ := eZ2hZ(P, eZ); + eZ = torusFactor(eZ, d, D); + eZbar = torusFactor(eZbar, d, D); + if topdim then (print("topdim = true"); + for k in keys(eZcones) do ( + eZcones#k = torusFactor(eZcones#k, d, D); + ); + ); + (new HashTable from eZ, new HashTable from eZbar, new HashTable from eZcones) + ) + +computeHodgeDeligne CYPolytope := opts -> P -> ( + PM := polytope(P, "M"); + PMfan := normalFan PM; + PM'fan := fan reflexiveToSimplicialToricVariety PM; + computeHodgeDeligne(PM, FaceInfo => {true, new HashTable, dim PM, (PMfan, PM'fan)}) + ) + +computeHodgeDeligne CalabiYauInToric := opts -> X -> computeHodgeDeligne(cyPolytope(X)) + +--check non-degeneracy; not the same as for CYPolytope! +computeHodgeDeligne ToricDivisor := opts -> D -> computeHodgeDeligne(polytope(D), opts) + +computeHodgeDeligne NormalToricVariety := opts -> V -> ( + D := sum for i from 0 to #rays(V) - 1 list ( + V_i + ); + computeHodgeDeligne(polytope(D), opts) + ) + +--For (a hypersurface in) a toric variety that is a subset of the projective normal toric variety that has polytope P. +--Not tested. +computeHodgeDeligneInPToric = method(); +computeHodgeDeligneInPToric (Polyhedron, List) := (P, whichCones) -> ( + (eZ, eZbar, eZcones) := computeHodgeDeligne(P); + eZtoric := new MutableHashTable from {}; + for k in keys eZ do (print(k);--maybe not eZ; need to switch to indexing by cones + eZtoric#k = eZ#k + sum for c in whichCones list getSparseeZ(eZcones#c, k); + ); + new HashTable from eZtoric + ) + +--For a hypersurface in T^n x C^r. +--Cheap option can be (but is not currently) used for complete intersections. +--not Cheap option not finished yet. +computeHodgeDeligneAffineAndTorus = method(Options => {Cheap => false}); +computeHodgeDeligneAffineAndTorus (Polyhedron, ZZ, ZZ) := opts -> (P, n, r) -> ( + eZtoric := new MutableHashTable from {}; + subs := subsets(r); + if opts.Cheap then ( print("Cheap"); + for s in subs do (--lambda_j == 0 <-> j in s + vs := vertices P; print(vs); + newP := convexHull vs_(for i from 0 to numcols vs - 1 list ( + if (a := true; + for j in s do (--column i must have not have std vector e_j + a = (a and vs_(n + j, i) == 1) + ); print(i, a); + a + ) + then i else continue + ) + ); + D := n + r - #s;--work in T^n x C^(r - #s) + (eZ, eZbar, eZcones) := computeHodgeDeligne(newP, FaceInfo => {false, new HashTable, D, ()}); + for k in keys(eZ) do (print(k); + eZtoric#k = getSparseeZ(eZtoric, k) + eZ#k + ); print("done subset:" | toString(s)); + ); + ) + else ( + for s in subs do ( + vs := vertices P; print(vs); + H := {}; + newP := intersection(P, H);--finish... + D := n + r - #s;--work in T^n x C^(r - #s) + (eZ, eZbar, eZcones) := computeHodgeDeligne(newP, FaceInfo => {false, new HashTable, D, ()}); + eZ#s = eZ; + for k in keys(eZ) do (print(k); + eZtoric#k = getSparseeZ(eZtoric, k) + eZ#k + ); print("done subset:" | toString(s)); + ); + ); + new HashTable from eZtoric + ) + +--For a hypersurface in T^n x C^r. Takes a matrix instead of a polyhedron. +--Cheap option is currently the routine used for complete intersections. +--not Cheap option not finished yet. +computeHodgeDeligneAffineAndTorus (Matrix, ZZ, ZZ) := opts -> (M, n, r) -> ( + eZtoric := new MutableHashTable from {}; + subs := subsets(r); + if opts.Cheap then (print("Cheap"); + for s in subs do (--lambda_j == 0 <-> j in s + newM := entries M_(for i from 0 to numcols M - 1 list ( + if all(s, j -> M_(n + j, i) == 0) then i else continue + ) + ); + --delete rows in s + newM = matrix for r from 0 to #newM - 1 list ( + if all(s, j -> n + j != r) then newM#r else continue + ); print(newM); + newP := convexHull newM; + D := n + r - #s;--work in T^n x C^(r - #s) + (eZ, eZbar, eZcones) := computeHodgeDeligne(newP, FaceInfo => {false, new HashTable, D, ()}); print(eZ); + for k in keys(eZ) do (print(k); + eZtoric#k = getSparseeZ(eZtoric, k) + eZ#k + ); print("done subset:" | toString(s)); + ); + ) + else ( + for s in subs do ( + newP := convexHull M;--finish... + D := n + r - #s;--work in T^n x C^(r - #s) + (eZ, eZbar, eZcones) := computeHodgeDeligne(newP, FaceInfo => {false, new HashTable, D, ()}); + eZ#s = eZ; + for k in keys(eZ) do (print(k); + eZtoric#k = getSparseeZ(eZtoric, k) + eZ#k + ); print("done subset:" | toString(s)); + ); + ); + new HashTable from eZtoric + ) + +--For a complete intersection of hypersurfaces, Y, in a torus, T^n. +computeHodgeDeligneTorusCI = method(); +computeHodgeDeligneTorusCI List := Ps -> ( + a := true; + nr := numrows vertices Ps#0; + for P in Ps do ( + if not class(P) === Polyhedron then a = false + else if not numrows vertices P == nr then a = false else continue + ); + if not a then error("Polyhedra do not sit in the same lattice. Make sure their vertex matrices have the same number of rows."); + n := nr; + r := #Ps; + M := manyPolyhedraToLargeMatrix(Ps); print(M); + eZtoric := computeHodgeDeligneAffineAndTorus(M, n, r, Cheap => true); print("eZtoric#(0, 0) = " | eZtoric#(0,0)); + eZCI := new MutableHashTable from {}; + for p from 0 to n - r do ( + for q from 0 to n - r do (print("(p, q) = " | toString(p, q)); + if p == q then ( + eZCI#(p, q) = (-1)^(n + p) * binomial(n, p) - eZtoric#(p + r - 1, q + r - 1) + ) + else ( + eZCI#(p, q) = -eZtoric#(p + r - 1, q + r - 1) + ) + ); + ); + (new HashTable from eZCI, eZtoric) + ) + + +-* Documentation section *- +beginDocumentation() + +doc /// +Key + DanilovKhovanskii +Headline + Computing Hodge-Deligne polynomials of toric hypersurfaces +Description + Text +References +Caveat +SeeAlso +/// + +doc /// +Key + computeHodgeDeligne + (computeHodgeDeligne, Polyhedron) + (computeHodgeDeligne, CYPolytope) + (computeHodgeDeligne, CalabiYauInToric) + (computeHodgeDeligne, ToricDivisor) + (computeHodgeDeligne, NormalToricVariety) +Headline + compute the Hodge-Deligne polynomial of a hypersurface in a torus. +Usage + computeHodgeDeligne(P) +Inputs + P:Polyhedron + a lattice polytope +Outputs + :Sequence + of three HashTables $e_Z$, $e_{\bar{Z}}$, and all of the $e_{Z_\Gamma}$ for $\Gamma \leq P$ a face +Description + Text + The Hodge-Deligne polynomial encodes information + Example + P = convexHull matrix {{-1, 4, -1, -1, 0, -1}, {-1, -1, 4, 0, -1, -1}, {-1, -1, -1, 1, 1, 1}} + latticePoints(P) + (eZ, eZbar, eZcones) = computeHodgeDeligne(P) + eZ + eZbar +Caveat +SeeAlso + computeHodgeDeligneInPToric + computeHodgeDeligneTorusCI +/// + +doc /// +Key + stdVector + (stdVector, ZZ, ZZ) +Headline + create the i-th standard basis vector in an n-dimensional vector space +Usage + stdVector(n, i) +Inputs + n:ZZ + the dimension of the vector space + i:ZZ + the index of the basis vector to create (from 0 to n - 1) +Outputs + :List + of 0's in every position except the i-th one, which contains a 1 +Description + Text + Given a basis of a vector space, any vector in that vector space can be expressed as a linear combination of the basis vectors. + The coefficients in this linear combination may be arranged into a list, which is also sometimes referred to as the vector. + When written in this form, the basis vectors themselves take the form of a list with a 1 at the position corresponding to itself and 0's elsewhere. + Example + e0 = stdVector(3, 0) + print transpose matrix {e0} + e1 = stdVector(3, 1) + print transpose matrix {e1} + e2 = stdVector(3, 2) + print transpose matrix {e2} +Caveat +SeeAlso + vdot +/// + +doc /// +Key + manyMatricesToLargeMatrix + (manyMatricesToLargeMatrix, List) +Headline + convert a list of matrices into one large matrix such that the convex hull of the new matrix is the polyhedron desired for computing the Hodge-Deligne numbers of a complete intersection. +Usage + manyMatricesToLargeMatrix(L) +Inputs + L:List + of matrices with the same number of rows +Outputs + :Matrix + if there are n matrices, each with m rows, this is the matrix with m + n rows whose first m rows contain the input matrices as adjacent blocks while the last n rows contains blocks of the same size, with the i-th block having 1's in the i-th row and 0's elsewhere. +Description + Text + The computation of the Hodge-Deligne numbers of a complete intersection of hypersurfaces in a torus employs an ancilliary hypersurface in a higher-dimensional torus. + Namely, this hypersurface is defined by a regular function whose Newton polytope can be obtained from the Newton polytopes associated to the original collection of hypersurfaces. + When the Newton polytopes are expressed as convex hulls of their vertices, and those vertices are put into a matrix as columns, the procedure to construct the Newton polytope of the higher-dimensional hypersurface reduces to the procedure performed by this method. + Example + M2 = transpose matrix {{0,0},{2,0},{0,2}} + M3 = transpose matrix {{0,0},{3,0},{0,3}} + M = manyMatricesToLargeMatrix({M2, M3}) +Caveat +SeeAlso + manyPolyhedraToLargeMatrix + manyPolyhedraToLargeOne + computeHodgeDeligne + computeHodgeDeligneAffineAndTorus + computeHodgeDeligneTorusCI +/// + +doc /// +Key + manyPolyhedraToLargeMatrix + (manyPolyhedraToLargeMatrix, List) +Headline + convert a list of polyhedra into one large matrix such that the convex hull of the matrix is the polyhedron desired for computing the Hodge-Deligne numbers of a complete intersection. +Usage + manyPolyhedraToLargeMatrix(L) +Inputs + L:List + of polyhedra in the same ambient space +Outputs + :Matrix + if there are n polyhedra, each sitting in a space of dimension m, this is the matrix with m + n rows whose first m rows contain the matrices of the vertices of the input polyhedra (obtained as vertices(L#i)) as adjacent blocks while the last n rows contains blocks of the same size, with the i-th block having 1's in the i-th row and 0's elsewhere. +Description + Text + The computation of the Hodge-Deligne numbers of a complete intersection of hypersurfaces in a torus employs an ancilliary hypersurface in a higher-dimensional torus. + Namely, this hypersurface is defined by a regular function whose Newton polytope can be obtained from the Newton polytopes associated to the original collection of hypersurfaces. + Applying convexHull to the output matrix of this method will give the Newton polytope of the higher-dimensional hypersurface. + Example + P2 = convexHull transpose matrix {{0,0},{2,0},{0,2}} + P3 = convexHull transpose matrix {{0,0},{3,0},{0,3}} + M = manyPolyhedraToLargeMatrix({P2, P3}) +Caveat +SeeAlso + manyMatricesToLargeMatrix + manyPolyhedraToLargeOne + computeHodgeDeligne + computeHodgeDeligneAffineAndTorus + computeHodgeDeligneTorusCI +/// + +doc /// +Key + manyPolyhedraToLargeOne + (manyPolyhedraToLargeOne, List) +Headline + convert a list of polyhedra into the higher-dimensional polyhedron desired for computing the Hodge-Deligne numbers of a complete intersection. +Usage + manyPolyhedraToLargeOne(L) +Inputs + L:List + of polyhedra in the same ambient space +Outputs + :Matrix + if there are n polyhedra, each sitting in a space of dimension m, this is the matrix with m + n rows whose first m rows contain the matrices of the vertices of the input polyhedra (obtained as vertices(L#i)) as adjacent blocks while the last n rows contains blocks of the same size, with the i-th block having 1's in the i-th row and 0's elsewhere. +Description + Text + The computation of the Hodge-Deligne numbers of a complete intersection of hypersurfaces in a torus employs an ancilliary hypersurface in a higher-dimensional torus. + Namely, this hypersurface is defined by a regular function whose Newton polytope can be obtained from the Newton polytopes associated to the original collection of hypersurfaces. + Applying convexHull to the output matrix of this method will give the Newton polytope of the higher-dimensional hypersurface. + Example + P2 = convexHull transpose matrix {{0,0},{2,0},{0,2}} + P3 = convexHull transpose matrix {{0,0},{3,0},{0,3}} + P = manyPolyhedraToLargeOne({P2, P3}) +Caveat +SeeAlso + manyMatricesToLargeMatrix + manyPolyhedraToLargeMatrix + computeHodgeDeligne + computeHodgeDeligneAffineAndTorus + computeHodgeDeligneTorusCI +/// + +doc /// +Key + ehrhartNumerator + (ehrhartNumerator, Polyhedron) +Headline + compute the numerator of the rational function expression for the Ehrhart series of a polytope +Usage + ehrhartNumerator(P) +Inputs + P:Polyhedron +Outputs + :List + the coefficients of the numerator, with the i-th position corresponding to the i-th power of t (beginning from 0) +Description + Text + The Ehrhart series of a polytope, P, in which the coefficient of $t^i$ is the number of lattice points in the i-th dilation of P, can be expressed as a rational function with a certain form. + Namely, one has $Ehr_P(t) = \frac{h^*(t)}{(1-t)^{dim(P)+1}}$, where $h^*(t)$ is a polynomial of degree $dim(P)$. + Example + R = QQ[x] + P = convexHull transpose matrix {{1,1},{1,-1},{-1,1},{-1,-1}} + eNum = ehrhartNumerator(P) + h = sum for i from 0 to #eNum - 1 list ( + eNum#i * x^i + ) + a = 1 + sum for i from 1 to 10 list ( + #latticePoints(i * P) * x^i + ) + assert((a * (1 - x)^3)%x^11 == h) +Caveat +SeeAlso + ehrhartNumeratorQuicker + computeSumqeZ + computeHodgeDeligne +/// + +doc /// +Key + ehrhartNumeratorQuicker + (ehrhartNumeratorQuicker, Polyhedron) +Headline + compute the numerator of the rational function expression for the Ehrhart series of a polytope +Usage + ehrhartNumeratorQuicker(P) +Inputs + P:Polyhedron +Outputs + :List + the coefficients of the numerator, with the i-th position corresponding to the i-th power of t (beginning from 0) +Description + Text + The Ehrhart series of a polytope, P, in which the coefficient of $t^i$ is the number of lattice points in the i-th dilation of P, can be expressed as a rational function with a certain form. + Namely, one has $Ehr_P(t) = \frac{h^*(t)}{(1-t)^{dim(P)+1}}$, where $h^*(t)$ is a polynomial of degree $dim(P)$. + Example + R = QQ[x] + P = convexHull transpose matrix {{1,1},{1,-1},{-1,1},{-1,-1}} + eNum = ehrhartNumeratorQuicker(P) + h = sum for i from 0 to #eNum - 1 list ( + eNum#i * x^i + ) + a = 1 + sum for i from 1 to 10 list ( + #latticePoints(i * P) * x^i + ) + assert((a * (1 - x)^3)%x^11 == h) +Caveat +SeeAlso + ehrhartNumerator + computeSumqeZ + computeHodgeDeligne +/// + +doc /// +Key + computeSumqeZ + (computeSumqeZ, Polyhedron, List, ZZ) +Headline + compute $\sum_q e^{p,q}(Z)$ for $Z$ a hypersurface in a torus and any integer $p$ +Usage + computeSumqeZ(P, L, p) +Inputs + P:Polyhedron + a lattice polytope + L:List + a list representing the Ehrhart numerator of P + p:ZZ + the index of the Hodge-Deligne numbers that is held fixed in the sum +Outputs + :ZZ + the sum $\sum_q e^{p,q}(Z)$, where $Z$ is a hypersurface defined by a regular function whose polytope is P +Description + Text + The value of $\sum_q e^{p,q}(Z)$ for $Z$ a hypersurface in a torus can be computed from Euler-Poincare$\e'$ characteristics of sheaves of differential forms. + It is used in one of the last step of the Danilov-Khovanskii algorithms to compute $e^{p,q}(Z)$ for $p + q = d - 1$, since for fixed $p$, all other $e^{p,q}(Z)$'s will have been computed and $e^{p,d-1-p}(Z) = \sum_q e^{p,q}(Z) - \sum_{q\neqd-1-p} e^{p,q}(Z)$. + Example + P = convexHull transpose matrix {{1,1},{1,-1},{-1,1},{-1,-1}} + psi = ehrhartNumerator(P) + computeSumqeZ(P, psi, 0) + computeSumqeZ(P, psi, 1) +Caveat +SeeAlso + ehrhartNumerator + ehrhartNumeratorQuicker + computeHodgeDeligne +/// + +doc /// +Key + eZ2hZ + (eZ2hZ, Polyhedron, HashTable) + (eZ2hZ, Polyhedron, MutableHashTable) +Headline + convert Hodge-Deligne numbers to Hodge numbers for smooth, projective varities +Usage + eZ2hZ(P, eZ) +Inputs + P:Polyhedron + eZ:HashTable + or @ofClass MutableHashTable@ + the Hodge-Deligne numbers of a variety +Outputs + :HashTable +Description + Text + If $Z$ is a smooth, projective variety, then $e^{p,q}(Z) = (-1)^{p+q} h^{p,q}(Z)$. + Example + PN = convexHull transpose matrix {{1, 0, 0}, {0, 1, 0}, {-1, -1, -2}, {0, 0, 1}, {0, 0, -1}} + PM = polar PN + (eZ, eZbar, eZcones) = computeHodgeDeligne(PM) + hZ = eZ2hZ(PM, eZ) + hZbar = eZ2hZ(PM, eZbar) +Caveat +SeeAlso + toeZMatrix + computeHodgeDeligne + computeHodgeDeligneInPToric + computeHodgeDeligneAffineAndTorus + computeHodgeDeligneTorusCI +/// + +doc /// +Key + getSparseeZ + (getSparseeZ, HashTable, Sequence) + (getSparseeZ, MutableHashTable, Sequence) +Headline + given HashTable(or MutableHashTable) and a key, if the key is in a key-value pair, return the corresponding value; else, return 0 +Usage + getSparseeZ(eZ, pq) +Inputs + eZ:HashTable + or @ofClass MutableHashTable@ + pq:Sequence + a pair of integers +Outputs + :ZZ +Description + Text + Since it is neither possible nor desirable to store the values of $e^{p,q}(Z)$, and all but a finite number of them are 0, this function allows the user to fetch the value of $e^{p,q}(Z)$ for any pair $(p, q)$. + Example + P = convexHull transpose matrix {{1,1},{1,-1},{-1,1},{-1,-1}} + (eZ, eZbar, eZcones) = computeHodgeDeligne(P) + getSparseeZ(eZ, (0, 0)) + getSparseeZ(eZ, (1, 1)) + getSparseeZ(eZ, (2, 2)) +Caveat +SeeAlso + computeHodgeDeligne + computeHodgeDeligneInPToric + computeHodgeDeligneAffineAndTorus + computeHodgeDeligneTorusCI +/// + +doc /// +Key + toeZMatrix + (toeZMatrix, HashTable) + (toeZMatrix, MutableHashTable) +Headline + convert the eZ HashTable (or MutableHashTable) into a Matrix +Usage + toeZMatrix(eZ) +Inputs + eZ:HashTable + or @ofClass MutableHashTable@ + the Hodge-Deligne numbers of a variety +Outputs + :Matrix +Description + Text + This methods puts the Hodge-Deligne numbers HashTable in a nicer format that resembles a Hodge diamond. + Example + PN = convexHull transpose matrix {{1, 0, 0}, {0, 1, 0}, {-1, -1, -2}, {0, 0, 1}, {0, 0, -1}} + PM = polar PN + (eZ, eZbar, eZcones) = computeHodgeDeligne(PM) + hZ = eZ2hZ(PM, eZ) + hZbar = eZ2hZ(PM, eZbar) + toeZMatrix(eZ) + toeZMatrix(eZbar) + toeZMatrix(hZ) + toeZMatrix(hZbar) +Caveat +SeeAlso + eZ2hZ + computeHodgeDeligne + computeHodgeDeligneInPToric + computeHodgeDeligneAffineAndTorus + computeHodgeDeligneTorusCI +/// + +doc /// +Key + vdot + (vdot, List, List) +Headline + compute the vector dot product of two Lists +Usage + vdot(L1, L2) +Inputs + L1:List + a list of elements in a ring, R + L2:List + a list of elements in a ring, R +Outputs + :RingElement +Description + Text + The dot product operation takes as input two vectors (stored here as lists) and returns a scalar (in the same ring as the list elements). + Example + v1 = {1, 2, 3} + v2 = {2, 3, 4} + s = vdot(v1, v2) +Caveat +SeeAlso + stdVector +/// + +doc /// +Key + torusFactor + (torusFactor, HashTable, ZZ, ZZ) + (torusFactor, MutableHashTable, ZZ, ZZ) +Headline + compute the Hodge-Deligne numbers for a variety that is a product of a torus and another variety, whose Hodge-Deligne numbers are given +Usage + torusFactor(eZ, d, D) +Inputs + eZ:HashTable + or @ofClass MutableHashTable@ + the Hodge-Deligne numbers of the variety in the product + d:ZZ + the dimension of the polytope + D:ZZ + the dimension of the lattice +Outputs + :HashTable + or @ofClass MutableHashTable@ + the Hodge-Deligne numbers of the product variety +Description + Text + The Hodge-Deligne polynomial of a product of varieties is the product of the Hodge-Deligne polynomial of the varieties. + In the case of projective normal toric varieties constructed from lattice polytopes, a polytope that is not full-dimensional gives rise to a variety that is a product of a torus and a second variety whose dimension is equal to that of the polytope. + Example + P = stdSimplex(2) + (eZ, eZbar, eZcones) = computeHodgeDeligne(P) + Q = convexHull transpose matrix {{0, 0}, {1, 0}, {0, 1}} + (eZ1, eZbar1, eZcones1) = computeHodgeDeligne(Q) + torusFactor(Q, 2, 3) +Caveat +SeeAlso + computeHodgeDeligne + computeHodgeDeligneInPToric + computeHodgeDeligneAffineAndTorus + computeHodgeDeligneTorusCI +/// + +doc /// +Key + computeHodgeDeligneInPToric + (computeHodgeDeligneInPToric, Polyhedron, List) +Headline + compute the Hodge-Deligne numbers of a hypersurface in a toric variety that is a subset of the projective normal toric variety that has a given polytope. +Usage + computeHodgeDeligneInPToric(P, whichFaces) +Inputs + P:Polyhedron + a lattice polytope + whichFaces:List + the subset of faces of P corresponding to the toric subvariety +Outputs + :HashTable + the Hodge-Deligne numbers of the toric subvariety +Description + Text + The faces of the polytope P correspond to torus orbits, the union of a a subset of which is a toric variety contained in the toric variety corresponding to P. + The Hodge-Deligne numbers of this disjoint union is the sum of the Hodge-Deligne numbers of the component tori. + Example + P = convexHull transpose matrix {{0, 0}, {1, 0}, {0, 1}} + Pfan = normalFan P + rys = rays Pfan + cs = {{0}, {2}} + Cs = for c in cs list coneFromVData(rys_c) + --eZ = computeHodgeDeligneInPToric(P, Cs) +Caveat +SeeAlso + computeHodgeDeligne + computeHodgeDeligneAffineAndTorus + computeHodgeDeligneTorusCI +/// + +doc /// +Key + computeHodgeDeligneAffineAndTorus + (computeHodgeDeligneAffineAndTorus, Polyhedron, ZZ, ZZ) + (computeHodgeDeligneAffineAndTorus, Matrix, ZZ, ZZ) +Headline + compute the Hodge-Deligne numbers of a hypersurface in $T^n \times C^r$ defined by a regular function with Newton polytope equal to P +Usage + computeHodgeDeligneAffineAndTorus(P, n, r) +Inputs + P:Polyhedron + a lattice polytope + n:ZZ + the dimension of the torus + r:ZZ + the dimension of the affine space +Outputs + :HashTable + the Hodge-Deligne numbers of the hypersurface +Description + Text + $T^n \times C^r$ is a toric variety that can be decomposed into $2^r$ tori. + The Hodge-Deligne polynomial of a hypersurface in $T^n \times C^r$ is then the sum of the Hodge-Deligne polynomials of the components in each of these tori. + Example + P2 = convexHull transpose matrix {{0,0},{2,0},{0,2}} + P3 = convexHull transpose matrix {{0,0},{3,0},{0,3}} + M = manyPolyhedraToLargeMatrix({P2, P3}) + n = 2 + r = 2 + computeHodgeDeligneAffineAndTorus(M, n, r, Cheap => true) +Caveat +SeeAlso + computeHodgeDeligne + computeHodgeDeligneInPToric + computeHodgeDeligneTorusCI +/// + +doc /// +Key + computeHodgeDeligneTorusCI + (computeHodgeDeligneTorusCI, List) +Headline + compute the Hodge-Deligne numbers of a complete intersection of hypersurfaces in a torus +Usage + computeHodgeDeligneTorusCI(Ps) +Inputs + Ps:List + a List of lattice polytopes in the same lattice +Outputs + :HashTable + the Hodge-Deligne numbers of a the complete intersection + :HashTable + the Hodge-Deligne numbers of a the auxiliary hypersurface used in the calculation +Description + Text + The complete intersection of a complete intersection of hypersurfaces in a torus can be computed indirectly from the Hodge-Deligne numbers of a related hypersurfaces in $T^n \times C^r$. + Example + P2 = convexHull transpose matrix {{0,0},{2,0},{0,2}} + P3 = convexHull transpose matrix {{0,0},{3,0},{0,3}} + (eZCI, eZtoric) = computeHodgeDeligneTorusCI({P2, P3}) +Caveat +SeeAlso + computeHodgeDeligne + computeHodgeDeligneInPToric + computeHodgeDeligneAffineAndTorus +/// + +-* Test section *- +TEST /// -* [insert short title for this test] *- + R = QQ[x] + P = convexHull transpose matrix {{1,1},{1,-1},{-1,1},{-1,-1}} + eNum = ehrhartNumerator(P) + eNum2 = ehrhartNumeratorQuicker(P) + h = sum for i from 0 to #eNum - 1 list ( + eNum#i * x^i + ) + a = 1 + sum for i from 1 to 10 list ( + #latticePoints(i * P) * x^i + ) + assert((a * (1 - x)^3)%x^11 == h) +/// + +TEST /// + P = convexHull transpose matrix {{1,1},{1,-1},{-1,1},{-1,-1}} + psi = ehrhartNumerator(P) + assert (computeSumqeZ(P, psi, 0) == -8) + assert (computeSumqeZ(P, psi, 1) == 0) + (eZ, eZbar, eZcones) = computeHodgeDeligne(P) + assert (eZ === new HashTable from {(0,0) => -7, (1,0) => -1, (0,1) => -1, (1,1) => 1}) + assert (eZbar === new HashTable from {(0,0) => 1, (1,0) => -1, (0,1) => -1, (1,1) => 1}) +/// + +TEST /// + PN = convexHull transpose matrix {{1, 0, 0}, {0, 1, 0}, {-1, -1, -2}, {0, 0, 1}, {0, 0, -1}} + PM = polar PN + isReflexive PN + isReflexive PM + latticePoints PM + faces(1,PN) + psi = ehrhartNumerator(PM) + assert (computeSumqeZ(PM, psi, 0) == 33) + assert (computeSumqeZ(PM, psi, 1) == 27) + assert (computeSumqeZ(PM, psi, 2) == 2) + (eZ, eZbar, eZcones) = computeHodgeDeligne(PM) + -- assert eZ === new HashTable from {(0,0) => 19, (1,0) => 7, (0,1) => 7, (2,0) => 1, (1,1) => 14, (0,2) => 1, (2,2) => 1}) + assert (eZ === new HashTable from {(0,0) => 20, (1,0) => 12, (0,1) => 12, (2,0) => 1, (1,1) => 15, (0,2) => 1, (2,2) => 1}) + assert (eZbar === new HashTable from {(0,0) => 1, (1,0) => 0, (0,1) => 0, (2,0) => 1, (1,1) => 20, (0,2) => 1, (2,1) => 0, (1,2) => 0, (2,2) => 1}) +/// + +TEST /// + topes = kreuzerSkarke 3; + Q = cyPolytope topes_50 + assert(hh^(1,1) Q == 3) + assert(hh^(1,2) Q == 73) + PM = polytope(Q, "M") + vertices PM + isReflexive PM + (eZ, eZbar, eZcones) = computeHodgeDeligne(PM); + assert(eZbar === new HashTable from {(0,0) => 1, (1,0) => 0, (0,1) => 0, (1,1) => 3, (2,0) => 0, (0,2) => 0, (3,0) => -1, (2,1) => -73, (0,3) => -1, (1,2) => -73, (1,3) => 0, (2,2) => 3, + (3,1) => 0, (2,3) => 0, (3,2) => 0, (3,3) => 1}) + + Q = cyPolytope topes_70 + assert(hh^(1,1) Q == 3) + assert(hh^(1,2) Q == 75) + PM = polytope(Q, "M") + vertices PM + isReflexive PM + (eZ, eZbar, eZcones) = computeHodgeDeligne(PM); + assert(eZbar === new HashTable from {(0,0) => 1, (1,0) => 0, (0,1) => 0, (1,1) => 3, (2,0) => 0, (0,2) => 0, (3,0) => -1, (2,1) => -75, (0,3) => -1, (1,2) => -75, (1,3) => 0, (2,2) => 3, + (3,1) => 0, (2,3) => 0, (3,2) => 0, (3,3) => 1}) + + matrix for i from 0 to 3 list ( + for j from 0 to 3 list( + (-1)^(i + j) * eZbar#(i,j) + ) + ) +/// + +TEST /// + P = convexHull transpose matrix {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}, {-1, 0, 0}, {0, -1, 0}, {0, 0, -1}} + (eZ, eZbar, eZcones) = computeHodgeDeligne(P) + assert (eZ === new HashTable from {(0,0) => 5, (1,0) => 0, (0,1) => 0, (2,0) => 1, (1,1) => 0, (0,2) => 1, (2,2) => 1}) + assert (eZbar === new HashTable from {(0,0) => 1, (1,0) => 0, (0,1) => 0, (2,0) => 1, (1,1) => 8, (0,2) => 1, (2,1) => 0, (1,2) => 0, (2,2) => 1}) +/// + +TEST /// + d = 2 + Q2 = 2 * stdSimplex(d)--not full dimensional + Q2fan = normalFan Q2 + Q2cones = makeConeTable Q2fan + rys = rays Q2fan + lS = linealitySpace Q2fan + for k in keys Q2cones do ( + for C in Q2cones#k do ( + assert(coneFromVData(rys_(fanRayList(C, Q2fan)), lS) == matchCones(C, Q2cones)); + ); + ); + (eZ, eZbar, eZcones) = computeHodgeDeligne(Q2) + assert(eZ === new HashTable from {(0,0) => 5, (0,1) => 0, (1,0) => 0, (2,0) => 0, (0,2) => 0, (1,1) => -6, (2,1) => 0, (1,2) => 0, (2,2) => 1}) + + Q3 = 3 * stdSimplex(d) + Q3fan = normalFan Q3 + Q3cones = makeConeTable Q3fan + rys = rays Q3fan + lS = linealitySpace Q3fan + for k in keys Q3cones do ( + for C in Q3cones#k do ( + assert(coneFromVData(rys_(fanRayList(C, Q3fan)), lS) == matchCones(C, Q3cones)); + ); + ); + (eZ, eZbar, eZcones) = computeHodgeDeligne(Q3) + assert(eZ === new HashTable from {(0,0) => 8, (0,1) => 1, (1,0) => 1, (2,0) => 0, (0,2) => 0, (1,1) => -9, (2,1) => -1, (1,2) => -1, (2,2) => 1}) + + --computeHodgeDeligneTorusCI({Q2, Q3}, d) + --Q2 = 2 * stdSimplex(5) + --Q3 = 3 * stdSimplex(5) + --eZCI = computeHodgeDeligneTorusCI({Q2, Q3}) + --assert(eZCI === new HashTable from {(0,0) => 58, (1,0) => 0, (0,1) => 0, (1,1) => 105, (0,2) => 0, (2,0) => 0, (3,0) => 0, (0,3) => 0, (2,1) => 40, (1,2) => 40, (3,1) => 5, (1,3) => 5, + -- (2,2) => -16, (3,2) => 20, (2,3) => 20, (3,3) => 14}) +/// + +TEST /// + P2 = convexHull transpose matrix {{0,0},{2,0},{0,2}} + P3 = convexHull transpose matrix {{0,0},{3,0},{0,3}} + PP = convexHull transpose matrix {{0,0,0,0},{0,0,1,0},{2,0,1,0},{0,2,1,0},{0,0,0,1},{3,0,0,1},{0,3,0,1}} + Q = manyPolyhedraToLargeOne({P2, P3}) + Q2 = convexHull (vertices Q)_{0,1,2,3} + Q3 = convexHull (vertices Q)_{0,4,5,6} + assert(PP == Q) + (eZ, eZbar, eZcones) = computeHodgeDeligne(Q2, FaceInfo => {true, new HashTable, 3, ()}) + assert(eZ === new HashTable from {(0,0) => 6, (1,0) => 0, (0,1) => 0, (2,0) => 0, (1,1) => -3, (0,2) => 0, (2,2) => 1}) + (eZ, eZbar, eZcones) = computeHodgeDeligne(Q3, FaceInfo => {true, new HashTable, 3, ()}) + assert(eZ === new HashTable from {(0,0) => 9, (1,0) => 1, (0,1) => 1, (2,0) => 0, (1,1) => -3, (0,2) => 0, (2,2) => 1}) + (eZ, eZbar, eZcones) = computeHodgeDeligne(Q, FaceInfo => {true, new HashTable, 4, ()}) + assert(eZ === new HashTable from {(0,0) => -15, (0,1) => -1, (1,0) => -1, (2,0) => 0, (1,1) => 1, (0,2) => 0, (3,0) => 0, (2,1) => 0, (0,3) => 0, (1,2) => 0, + (2,2) => -4, (3,3) => 1}) + P = PP + d = dim P + for i from 0 to d - 1 do ( + print("codim = " | i); + fs := faces(i, P); + Fs := facesAsPolyhedra(i, P); + for j from 0 to #fs - 1 do ( + print("vertices = " | toString(fs#j#0), ehrhartNumeratorQuicker(Fs#j), ehrhartNumerator(Fs#j)); + for k from 1 to d - i do ( + print(k | ": " | #latticePoints(k * Fs#j)) + ); + ); + ) + (eZCI, eZtoric) = computeHodgeDeligneTorusCI({P2, P3}) + assert(eZCI === new HashTable from {(0,0) => 6}) +/// + +TEST /// + P2 = convexHull transpose matrix {{0,0,0},{1,0,0},{0,1,0}} + P1 = convexHull transpose matrix {{0,0,0}, {0,0,1}} + Q1 = P2 + P1 + Q2 = 2 * P2 + 3 * P1 + (eZCI, eZtoric) = computeHodgeDeligneTorusCI({Q1, Q2}) + assert(eZCI#(0, 1) == -3) + assert(eZCI#(1, 0) == -3) + + V1 = toricProjectiveSpace(1) + dim(V1) + V2 = toricProjectiveSpace(2) + dim(V2) + V = V1 ** V2 + dim(V) + rays(V) + HH^0(V, OO_V(3, 2)) + Q1 = polytope(3 * V_0 + 2 * V_2) + #latticePoints(Q1) + Q2 = polytope(V_0 + V_2) + computeHodgeDeligneTorusCI({Q1, Q2}) + assert(eZCI#(0, 1) == -3) + assert(eZCI#(1, 0) == -3) + HH^0(V, OO_V(1, 1)) +/// + +TEST/// + topes = kreuzerSkarke(3); + Q = cyPolytope topes_25 + X = makeCY Q + V = ambient X + Vfan = fan V + #rays V + D = sum for i from 0 to 6 list V_i + P = polytope D + isReflexive P + Pfan = normalFan P + isSimplicial V + isSimplicial Vfan + isSimplicial Pfan + (eZ, eZbar, eZconesCY) = computeHodgeDeligne(P) + assert(eZbar === new HashTable from {(0,0) => 1, (1,0) => 0, (0,1) => 0, (1,1) => 2, + (2,0) => 0, (0,2) => 0, (3,0) => -1, (2,1) => -66, (0,3) => -1, + (1,2) => -66, (1,3) => 0, (2,2) => 2, (3,1) => 0, (2,3) => 0, (3,2) + => 0, (3,3) => 1}) + --a non-fine subdivision fan will give h^(1,1) = 2, h^(1,2) = 66 + (eZCY, eZbarCY, eZconesCY) = computeHodgeDeligne(Q) + assert(eZbarCY === new HashTable from {(0,0) => 1, (1,0) => 0, (0,1) => 0, (1,1) => 3, + (2,0) => 0, (0,2) => 0, (3,0) => -1, (2,1) => -69, (0,3) => -1, + (1,2) => -69, (1,3) => 0, (2,2) => 3, (3,1) => 0, (2,3) => 0, (3,2) + => 0, (3,3) => 1}) + assert(eZ === eZCY) +/// + +TEST /// + topes = kreuzerSkarke(3); + Q = cyPolytope topes_25 + X = makeCY Q + V = ambient X + Vfan = fan V + #rays V + D = sum for i from 0 to 6 list V_i + P = polytope D + d= dim P + for i from 0 to d - 1 do ( + print("codim = " | i); + fs := faces(i, P); + Fs := facesAsPolyhedra(i, P); + for j from 0 to #fs - 1 do ( + assert(ehrhartNumeratorQuicker(Fs#j) == ehrhartNumerator(Fs#j)); + ); + ) +/// + + +end-- + +-* Development section *- +restart +debug needsPackage "DanilovKhovanskii" +check "DanilovKhovanskii" + +uninstallPackage "DanilovKhovanskii" +restart +installPackage "DanilovKhovanskii" +viewHelp "DanilovKhovanskii" diff --git a/CYToolsM2/IntegerEquivalences.m2 b/CYToolsM2/IntegerEquivalences.m2 new file mode 100644 index 0000000..a5b66b4 --- /dev/null +++ b/CYToolsM2/IntegerEquivalences.m2 @@ -0,0 +1,825 @@ +newPackage( + "IntegerEquivalences", + Version => "0.1", + Date => "13 Jan 2024", + Headline => "finding invertible integral matrices preserving points, linear forms and ideals", + Authors => {{ Name => "", Email => "", HomePage => ""}}, + AuxiliaryFiles => false, + DebuggingMode => true + ) + +export { + "findEquivalence", + "MatchingData", + "equivalenceIdeal", + "extendToMatrix", -- extendToMatrix(List of integers) ==> Matrix (over ZZ). + "factorsByType", + "idealsByBetti", + "genericLinearMap", -- genericLinearMap(R). Constructs two new rings, T, U, a matrix A over T nxn, n = numgens R, and phi = map(U, U, transpose A). + "invertibleMatrixOverZZ", + "matches", + "hessian", -- place in Core? + "hessianMatches", + "selectLinear", + "matchingData", + "allSigns", + "signedPermutations", + "cartesian", + "singularPoints", + "singularPointMatches", + "singularMatches", + "tryEquivalences", + "RowVector", + "ColumnVector", + "Unknown", + "CONSISTENT", + "INCONSISTENT", + "INDETERMINATE", + "SignedPermutations", + "Permutations" + } + +importFrom_"LLLBases"{"gcdLLL"}; + +extendToMatrix = method() +extendToMatrix List := Matrix => L -> ( + if not all(L, a -> instance(a, ZZ)) + then error "expected a list of integers"; + (g, A) := gcdLLL L; -- coming from LLLBases. + transpose A + -- TODO: should this insure that the matrix has determinant 1 (not -1)? + -- I don't really need that... + ) + +genericLinearMap = method(Options => {Variable => null}) +genericLinearMap Ring := Sequence => opts -> R -> ( + -- R should be a polynomial ring in n >= 1 variables. + n := numgens R; + if n == 0 then ( + kk := coefficientRing R; -- TODO: if none, this should give a better error message + A := map(kk^0, kk^0, {}); + return (A, id_R); + ); + K := coefficientRing R; + t := if opts.Variable === null then getSymbol "t" else opts.Variable; + T := K[t_(1,1)..t_(n,n)]; + U := T [gens R, Join => false]; + A = map(T^n,,transpose genericMatrix(T, T_0, n, n)); + phi := map(U, U, transpose A); + (A, phi) + ) + +-- MatchingData: is a list of elements each f the form +-- L => {M0, M1, ..., Ms} +-- where L is a list of: +-- RingElement: a polynomial in the original ring RZ or RQ. +-- Ideal: an ideal in the original ring. +-- Matrix: either a row vector or column vector, over ZZ or QQ (or RZ or RQ) +-- and each list Mi has the same length as L, and the same types of its elements. +MatchingData = new Type of List + +matchingData = method() +matchingData List := LMs -> ( + if not all(LMs, x -> instance(x, Option) or (instance(x, List) and #x === 3)) + then error "expected each element to be Item => Item, or a list {type, ItemList, ItemList}"; + ans := new MatchingData from LMs; + if not isWellDefined ans then error "expected matching data to match. Set `debugLevel=1` to investigate"; + ans + ) + +MatchingData | MatchingData := MatchingData => (md1, md2) -> ( + matchingData join(toList md1, toList md2) + ) + +-- helper function for validMatchingItem. +-- Input: either source or one of the targets of the matching data. +-- Output: a list of types. +itemType = L -> ( + -- L is a list or a single element of the following form + -- returns a list of RingElement, Ideal, RowVector, ColumnVector. + if not instance(L, List) then L = {L}; + for elem in L list ( + if instance(elem, RingElement) then RingElement + else if instance(elem, Ideal) then Ideal + else ( + if instance(elem, Matrix) then ( + if numrows elem === 1 then RowVector + else if numcols elem === 1 then ColumnVector + else Unknown + ) else + Unknown + )) + ) + +-- helper function for (isWellDefined, MatchingData) +-- Input: one element (an Option, source and possible targets) of the matching data +-- which index this data sits at (used for error messages if debugLevel > 0) +-- Output: Boolean, whether this item is valid. +validMatchingItem = (LM,i) -> ( + -- TODO: if typ is null, then L should be a RingElement, Ideal or row or column Matrix, and M should be the same type + if instance(LM, Option) then ( + if not (instance(LM#0, RingElement) or instance(LM#0, Ideal) or instance(LM#0, Matrix)) + or class LM#0 =!= class LM#1 + then ( + if debugLevel > 0 then + << "excepted each item of Option to be the same type: an Ideal, RingElement or row or column matrix" << endl; + return false; + ); + -- todo: make sure matrices are row or column matrices. + return true; + ); + (typ, L, M) := (LM#0, LM#1, LM#2); + if typ =!= SignedPermutations and typ =!= Permutations then ( + if debugLevel > 0 then + << "expected first entry of list to be SignedPermutations or Permutations, instead, received " + << toString typ << endl; + return false; + ); + + if not instance(L, List) or not instance(M, List) then ( + if debugLevel > 0 then + << "expected elements in source " << i << " to be lists" << endl; + return false; + ); + -- M should be a list, same length and types as L. + Ltype := itemType L; + Mtype := itemType M; + if any(Ltype, x -> x === Unknown) then ( + if debugLevel > 0 then << "one element in source is unknown" << endl; + return false; + ); + if Mtype =!= Ltype then ( + if debugLevel > 0 then << "in source " << i << ", target doesn't match source = " << Ltype << " obtaining instead " << Mtype << endl; + return false; + ); + true + ) + +isWellDefined MatchingData := Boolean => LMs -> ( + for i from 0 to #LMs-1 do ( + LM := LMs#i; + if not instance(LM, Option) and not (instance(LM, List) and #LM === 3) then ( + if debugLevel > 0 then << "elements of list must be of the form {type, List, List}" << endl; + return false; + ); + if not validMatchingItem(LM,i) then return false; + ); + true + ) + +-- Used in creating MatchingData: use permutations or signedPermutations. +allSigns = method() +allSigns List := L -> ( + if #L <= 0 then return {{}}; + if #L == 1 then return {{L#0}, {-L#0}}; + flatten for q in allSigns(drop(L, 1)) list {prepend(L#0, q), prepend(-L#0, q)} + ) + +signedPermutations = method() +signedPermutations List := List => L -> ( + flatten for p in permutations L list allSigns p + ) + +cartesian = method() +cartesian List := (Ls) -> ( + -- cartesian product of Ls: one element from each + -- so the result is a list of lists. + if #Ls == 1 then return for p in Ls#0 list {p}; + Ls1 := cartesian drop(Ls,1); + flatten for p in Ls#0 list for q in Ls1 list prepend(p, q) + ) + +matches = method() +matches MatchingData := List => (MD) -> ( + -- for each element of the MatchingData, we make the list of all possible targets + src := flatten for elem in MD list + if instance(elem, Option) then elem#0 else elem#1; + -- now create targets. This means making all permutations, signed or not, and taking cartesian products. + targs := cartesian for elem in MD list ( + if instance(elem, Option) then {elem#1} + else if elem#0 === SignedPermutations then signedPermutations elem#2 + else if elem#0 === Permutations then permutations elem#2 + ); + targs = targs/flatten; + (src, targs) + ) + +selectLinear = method() +selectLinear MatchingData := MatchingData => (MD) -> ( + -- ASSUMPTION: the base ring for Ideals and RingElement's is standard graded polynomial ring. + -- we keep only the ring elements that are linear. + -- for each ideal, we take only the linear elements. + -- We keep all row and column matrices. + matchingData for elem in MD list ( + if instance(elem, Option) then ( + if instance(elem#0, RingElement) then ( + if degree elem#0 === {1} then elem else continue + ) else if instance(elem#0, Ideal) then ( + elem0 := select(elem#0_*, f -> degree f === {1}); + if #elem0 === 0 then continue; + elem1 := select(elem#1_*, f -> degree f === {1}); + ideal elem0 => ideal elem1 + ) else if instance(elem#0, Matrix) then elem + ) else ( + if instance(elem#1#0, RingElement) then ( + if degree elem#1#0 === {1} then elem else continue + ) + else if instance(elem#1#0, Ideal) then ( + elem1 = for x in elem#1 list + select(x_*, f -> degree f === {1}); + if #elem1#0 === 0 then continue; + elem2 := for x in elem#2 list + select(x_*, f -> degree f === {1}); + {elem#0, elem1/ideal, elem2/ideal} + ) + else elem + )) + ) + +invertibleMatrixOverZZ = method() +invertibleMatrixOverZZ(Matrix, Ideal) := Sequence => (A, J) -> ( + -- returns (determinacy, A0), or (INCONSISTENT, null) or ...? + if J == 1 then + (INCONSISTENT, null) + else ( + A0 := A % J; + detA0 := (det A0) % J; + suppA0 := support A0; + if suppA0 === {} then ( + -- In this case we either have an integer matrix, or a rational matrix. + if liftable(detA0, ZZ) and all(flatten entries A0, f -> liftable(f, ZZ)) then + return (CONSISTENT, sub(A0, ZZ)); + return (INCONSISTENT, sub(A0, QQ)); + ); + jc := decompose J; + if isPrime J then return (INDETERMINATE, jc); + possibles := for j in jc list ( + ans := invertibleMatrixOverZZ(A0, j); + if ans#0 == CONSISTENT then return ans else ans + ); + if all(possibles, a -> a#0 === INCONSISTENT) then ( + ans := select(1, possibles, a -> instance(a#1, Matrix)); + if #ans > 0 then return ans#0 else return (INCONSISTENT, null); + ) + else + return (INDETERMINATE, jc); + ) + ) + +equivalenceIdeal = method() +equivalenceIdeal(List, List, Ring, Sequence) := Ideal => (List1, List2, RQ, Aphi) -> ( + if itemType List1 =!= itemType List2 then + error("expected two lists to have the same list of types, they are: " + | toString itemType List1 | " and " | toString itemType List2); + (A,phi) := Aphi; + U := target phi; + if U =!= source phi then error "expected ring map with same source and target"; + if #List1 == 0 then return ideal(0_U); + B := coefficientRing U; + toU := map(U, RQ, vars U); + toB := map(B, U); + List1 = List1/(I -> if ring I =!= RQ then toU (sub(I, RQ)) else toU I); + List2 = List2/(I -> if ring I =!= RQ then toU (sub(I, RQ)) else toU I); + -- List1 and List2 are lists with the same length, consisting of RingElement's, Ideal's, Matrices. + -- List1 and List2 should each have RingElement's and Ideal's in the same spot. + ids := for i from 0 to #List1-1 list ( + if instance(List1#i, RingElement) then ( + ideal toB (last coefficients(phi List1#i - List2#i)) + ) + else if instance(List1#i, Ideal) then ( + ideal toB (last coefficients((gens phi List1#i) % List2#i)) + ) + else if instance(List1#i, Matrix) then ( + rowvec := (numrows List1#i === 1); + -- if rowvec is false, then this must be a column vector. + if rowvec then + ideal toB last coefficients sub(List2#i * (transpose A) - List1#i, U) + else + ideal toB last coefficients sub((transpose A) * List1#i - List2#i, U) + ) + ); + sum ids + ) + +tryEquivalences = method() +tryEquivalences(MatchingData, Ring, Sequence) := (MD, RQ, Aphi) -> ( + (A,phi) := Aphi; + badJs := {}; + inconsistentMatrix := null; + (src, tar) := matches MD; + for i from 0 to #tar-1 do ( + << "doing " << i << endl; + J := trim equivalenceIdeal(src, tar#i, RQ, Aphi); + ans := invertibleMatrixOverZZ(A, J); + if ans#0 == CONSISTENT then return ans; + if ans#0 == INCONSISTENT and instance(ans#1, Matrix) then inconsistentMatrix = ans#1; + if ans#0 == INDETERMINATE then ( + badJs = join(badJs, ans#1); + ); + ); + if #badJs > 0 then return (INDETERMINATE, badJs); + (INCONSISTENT, inconsistentMatrix) + ) + +------------------------------- +-- Finding matching data of (L1,F1), (L2,F2) +-- using singular loci and hessian factorizations +------------------------------- +factors = method() +factors RingElement := (F) -> ( + facs := factor F; + facs//toList/toList/reverse + ) + +factorsByType = method() +factorsByType RingElement := HashTable => F -> ( + facs := factors F; + faclist := for fx in facs list (fx#0, sum first exponents fx#1, fx#1); + H := partition(x -> {x#0, x#1}, faclist); + hashTable for k in keys H list k => for x in H#k list x_2 + ) + +idealsByBetti = method() +idealsByBetti(List, List) := MatchingData => (J1s, J2s) -> ( + H1 := partition(J -> betti gens J, J1s); + H2 := partition(J -> betti gens J, J2s); + if sort keys H1 =!= sort keys H2 then return {}; + matchingData for k in sort keys H1 list ( + if #H1#k === 1 then H1#k#0 => H2#k#0 else {Permutations, H1#k, H2#k} + ) + ) + +-- TODO: place in M2 Core? +hessian = method() +hessian RingElement := F -> diff(vars ring F, diff(transpose vars ring F, F)) + +hessianMatches = method() +hessianMatches(RingElement, RingElement) := MatchingData => (F1, F2) -> ( + fac1 := factorsByType(det hessian F1); + fac2 := factorsByType(det hessian F2); + keys1 := sort select(keys fac1, k -> k =!= {1,0}); -- remove constant + keys2 := sort select(keys fac2, k -> k =!= {1,0}); -- remove constant + if keys1 =!= keys2 then return matchingData{}; -- no matches. + matchingData for k in keys1 list {SignedPermutations, fac1#k, fac2#k} + ) + +-- Note: the returned value over a finite field is fine, and over QQ, all denominators and lcms have been cleared +-- TODO: maybe this should be used if the ideal is generated by linears, and of codim = number of vars - 1? +-- IE: modify a MatchingData to change this. +singularPoints = method() +singularPoints RingElement := List => F -> ( + if not isHomogeneous F then error "expected homogeneous polynomial"; + R := ring F; + kk := coefficientRing R; + n := numgens R; + singlocus := trim saturate(ideal F + ideal jacobian F); + if singlocus == 1 then return matchingData{}; + comps := (decompose singlocus); + comps0 := select(comps, c -> codim c == n-1 and degree c === 1); -- zero-dimensional rational points + comps1 := select(comps, c -> not(codim c == n-1 and degree c === 1)); -- the rest + comps1 = comps1/trim; + if #comps1 != 0 then + << "other singular components: " << netList comps1 << endl; + for c in comps0 list ( + pt := (vars R) % c; + vs := support pt; + if #vs != 1 then error "internal error: number of variables is not 1"; + pt = sub(pt, vs#0 => 1_kk); + pt = flatten entries pt; + if kk === QQ then ( + g := gcd pt; + pt = 1/g * pt + ); + transpose matrix{pt} + ) + ) +singularPointMatches = method() +singularPointMatches(RingElement, RingElement) := MatchingData => (F1, F2) -> ( + pts1 := singularPoints F1; + pts2 := singularPoints F2; + if #pts1 =!= #pts2 then return null; -- no matches. + matchingData{{SignedPermutations, pts1, pts2}} + ) + +-- NOT DONE YET!! +singularMatches = method() +singularMatches(RingElement, RingElement) := MatchingData => (F1, F2) -> ( + sing1 := trim saturate(ideal F1 + ideal jacobian F1); + sing2 := trim saturate(ideal F2 + ideal jacobian F2); + if sing1 == 1 then return matchingData{}; + comps1 := (decompose sing1)/trim; + comps2 := (decompose sing2)/trim; + idealsByBetti(comps1, comps2) + ) + +findEquivalence = method() +findEquivalence(List, List) := (LF1, LF2) -> ( + (L1, F1) := toSequence LF1; + (L2, F2) := toSequence LF2; + R := ring L1; + -- TODO: check that R is the ring of all 4 of these. + -- TODO: check that coefficient ring is ZZ, QQ, finite field, or what else is allowed? + RQ := R; + toRQ := identity; + if coefficientRing R === ZZ then ( + RQ = QQ (monoid R); -- change ZZ to QQ, leave finite fields alone. + toRQ = map(RQ, R, vars RQ); + ); + L1 = toRQ L1; + L2 = toRQ L2; + F1 = toRQ F1; + F2 = toRQ F2; + (A, phi) := genericLinearMap RQ; + md := hessianMatches(F1, F2) | + singularMatches(F1, F2) | + matchingData {L1 => L2, F1 => F2}; +-- linmd := selectLinear md; + --result := tryEquivalences(linmd, RQ, (A,phi)); + -- if result is INDETERMINATE, try the entire matching data + -- TODO: if we get a consistent match, try that first! + -- only if that fails should we move on to this. + tryEquivalences(md, RQ, (A, phi)) + -- if result#0 =!= INCONSISTENT then ( + -- result2 := tryEquivalences(md, RQ, (A,phi)); + -- (result, result2) + -- ) + -- else result + ) + +TEST /// +-- These 3 forms were generated from h11=5 database, with: +-- {(2249, 0), (2255, 0), (2270, 0)} +-- L1 = c2Form Xs#(2249,0) +-- L2 = c2Form Xs#(2255,0) +-- L3 = c2Form Xs#(2270,0) +-- F1 = cubicForm Xs#(2249,0) +-- F2 = cubicForm Xs#(2255,0) +-- F3 = cubicForm Xs#(2270,0) + +-* + restart + needsPackage "IntegerEquivalences" +*- +-- This is supposed to test formation of matchingData + debug needsPackage "IntegerEquivalences" + RZ = ZZ[a,b,c,d,e] + RQ = QQ (monoid RZ) + (A,phi) = genericLinearMap RQ + use RQ + L1 = 12*a+10*b+34*c-4*d+4*e + L2 = -4*a+12*b+18*c+28*d+4*e + L3 = -4*a+12*b+26*c+10*d+20*e + F1 = b^3-6*a^2*c-3*b^2*c+3*b*c^2+c^3+6*a^2*d+12*a*c*d+6*c^2*d-12*a*d^2- + 12*c*d^2+8*d^3-6*a^2*e+12*a*c*e+12*a*e^2-12*c*e^2-8*e^3 + F2 = 8*a^3-12*a^2*b+6*a*b^2-12*a^2*c+12*a*b*c-6*b^2*c+6*a*c^2-3*c^3- + 12*a^2*d+12*a*b*d-6*b^2*d+12*a*c*d-6*c^2*d+6*a*d^2-6*c*d^2- + 2*d^3+12*c*d*e+6*d^2*e-12*c*e^2-8*e^3 + F3 = 8*a^3-12*a^2*b+6*a*b^2-12*a^2*c+12*a*b*c-6*b^2*c+6*a*c^2-c^3+ + 3*c^2*d-3*c*d^2+d^3-6*c*e^2-4*e^3 + + findEquivalence({L1, F1}, {L2, F2}) + findEquivalence({L3, F3}, {L2, F2}) + + FT1 = factorsByType det hessian F1 + FT2 = factorsByType det hessian F2 + FT3 = factorsByType det hessian F3 + + md = hessianMatches(F1, F2) + md = md | matchingData{L1 => L2} + tryEquivalences(md, RQ, (A,phi)) + + md = hessianMatches(F1, F3) + md = md | matchingData{L1 => L3} | singularPointMatches(F1, F3) + tryEquivalences(md, RQ, (A,phi)) + + md = hessianMatches(F2, F3) + md = md | matchingData{L2 => L3} + tryEquivalences(md, RQ, (A,phi)) + + + + srcs = flatten {FT1#{1,1}, FT1#{2,1}, L1} + targs = flatten \ (cartesian {signedPermutations FT2#{1,1}, signedPermutations FT2#{2,1}, {L2}}) + for t in targs list ( + A % trim equivalenceIdeal(srcs, t, RQ, (A,phi)) + ) + + srcs = flatten {FT1#{1,1}, FT1#{2,1}, L1} + targs = flatten \ (cartesian {signedPermutations FT3#{1,1}, signedPermutations FT3#{2,1}, {L3}}) + for t in targs list ( + A0 = A % trim equivalenceIdeal(srcs, t, RQ, (A,phi)); + A0 = try lift(A0, QQ) else continue; + A0 = try lift(A0, ZZ) else continue; + f := map(RQ, RQ, (transpose A0)**QQ); + {A0, f(F1) - F3, f(L1) - L3} + ) + + srcs = flatten {FT2#{1,1}, FT2#{2,1}, L2} + targs = flatten \ (cartesian {signedPermutations FT3#{1,1}, signedPermutations FT3#{2,1}, {L3}}) + for t in targs list ( + A0 = A % trim equivalenceIdeal(srcs, t, RQ, (A,phi)); + A0 = try lift(A0, QQ) else continue; + A0 = try lift(A0, ZZ) else continue; + f := map(RQ, RQ, (transpose A0)**QQ); + {A0, f(F2) - F3, f(L2) - L3} + ) + + singularPointMatches(F1, F2) + singularMatches(F1, F2) + equivalenceIdeal({transpose matrix{{2,0,0,1,1}}}, {transpose matrix{{0,0,-2,2,1}}}, RQ, (A,phi)) + equivalenceIdeal({transpose matrix{{2,0,0,1,1}}}, {transpose matrix{{0,0,2,-2,-1}}}, RQ, (A,phi)) + + md = hessianMatches(F1, F2) | singularMatches(F1, F2) | matchingData {L1 => L2, F1 => F2} + matches md + selectLinear md + tryEquivalences(oo, RQ, (A,phi)) + tryEquivalences(md, RQ, (A,phi)) + -- XXX +/// + +TEST /// +-* + restart + needsPackage "IntegerEquivalences" +*- + A = extendToMatrix{10,15,6} + assert(A * transpose matrix{{10,15,6}} == transpose matrix{{0,0,1}}) + assert(abs det A == 1) + + A = extendToMatrix{10,15,1} + assert(A * transpose matrix{{10,15,1}} == transpose matrix{{0,0,1}}) + assert(abs det A == 1) + + A = extendToMatrix{10,15,0} + assert(A * transpose matrix{{10,15,0}} == transpose matrix{{0,0,5}}) -- 5 is gcd! + assert(abs det A == 1) +/// + +TEST /// +-* + restart + needsPackage "IntegerEquivalences" +*- + -- trivial case + R = ZZ[] + (A, phi) = genericLinearMap R + assert(numRows A == 0 and numcols A == 0) + assert(ring A === coefficientRing target phi) + assert(source phi === target phi) + + R = ZZ[a..d] + (A, phi) = genericLinearMap R + assert(numRows A == 4 and numcols A == 4) + assert(ring A === coefficientRing target phi) + assert(source phi === target phi) + + (A, phi) = genericLinearMap(R, Variable => symbol s) + assert(numRows A == 4 and numcols A == 4) + assert(ring A === coefficientRing target phi) + assert(source phi === target phi) + use ring A + assert(A_(0,0) == s_(1,1)) + + RQ = QQ (monoid R) + (A, phi) = genericLinearMap RQ + assert(numRows A == 4 and numcols A == 4) + assert(ring A === coefficientRing target phi) + assert(source phi === target phi) + + R = ZZ[a] + (A, phi) = genericLinearMap R + assert(numRows A == 1 and numcols A == 1) + assert(ring A === coefficientRing target phi) + assert(source phi === target phi) + + R = ZZ/101[a..d] + (A, phi) = genericLinearMap R + U = target phi + assert(source phi === U) + assert(ring A === coefficientRing U) + for i from 0 to 3 do + assert(phi U_i == (A^{i} * (transpose vars U))_(0,0)) + + R = ZZ[a..d] + (A, phi) = genericLinearMap R + U = target phi + assert(source phi === U) + assert(ring A === coefficientRing U) + for i from 0 to 3 do + assert(phi U_i == (A^{i} * (transpose vars U))_(0,0)) + + R = QQ[a..e] + (A, phi) = genericLinearMap R + U = target phi + assert(source phi === U) + assert(ring A === coefficientRing U) + for i from 0 to numgens R - 1 do + assert(phi U_i == (A^{i} * (transpose vars U))_(0,0)) +/// + +TEST /// +-* + restart + needsPackage "IntegerEquivalences" +*- + RZ = ZZ[a,b,c] + F1 = 3*a^2*b-3*a*b^2+b^3+6*a^2*c-6*a*c^2+2*c^3 + L1 = 24*a+10*b+8*c + F2 = F1 + L2 = L1 + + use ring L1 + findEquivalence({L1, F1}, {L1 - 2*a, F1+2*a^3}) + + M1 = a + M2 = b + M3 = c + N1 = a+b + N2 = a+c + N3 = 2*b+c + + md = matchingData { + F1 => F2, + L1 => L2, + {Permutations, {ideal M1, ideal M2}, {ideal N1, ideal N2}}, + {SignedPermutations, {M1,M2,M3}, {N1,N2,N3}}, + matrix{{1,2,3}} => matrix{{1,-2,1}} + } + assert isWellDefined md + matches md + netList first matches md + netList last matches md + + md = matchingData { + F1 => F2, + L1 => L2, + {Permutations, {ideal(M1, M2^2), ideal(M2,M3^2)}, {ideal(N1,N2^2), ideal(N2,N3^2)}}, + {SignedPermutations, {M1,M2,M3}, {N1,N2,N3}}, + matrix{{1,2,3}} => matrix{{1,-2,1}} + } + assert isWellDefined md + matches md + netList first matches md + netList last matches md + + md1 = selectLinear md + + assert try (matchingData { + {F1, F2}, + {Permutations, {L1}, {L2}}, + {SignedPermutations, {M1,M2,M3}, {N1,N2,N3}}, + {matrix{{1,2,3}}, matrix{{1,-2,1}}} + }; false + ) else true + + assert try ( + matchingData { + F1 => F2, + L1 => L2, + {M1,M2,M3} => {{N1,N2,N3,N1}}, + matrix{{1,2,3}} => matrix{{1,-2,1}} + }; + false + ) else true; + +/// + +TEST /// +-* + restart + needsPackage "IntegerEquivalences" +*- + assert(# signedPermutations{1,2,3} === 48) + assert(# permutations{1,2,3} === 6) + assert(cartesian{{1,2}} == {{1}, {2}}) + assert(cartesian{{1,2}, {3,4}} === {{1, 3}, {1, 4}, {2, 3}, {2, 4}}) + assert(cartesian{{1,2},{3,4},{5,6}} === {{1, 3, 5}, {1, 3, 6}, {1, 4, 5}, {1, 4, 6}, {2, 3, 5}, {2, 3, 6}, {2, 4, 5}, {2, 4, 6}}) + assert(cartesian{{1,2},{3},{5,6}} === {{1, 3, 5}, {1, 3, 6}, {2, 3, 5}, {2, 3, 6}}) + assert(cartesian{{1,2},{},{5,6}} === {}) +/// + +TEST /// +-* + restart + needsPackage "IntegerEquivalences" +*- + RZ = ZZ[a,b,c] + RQ = QQ (monoid RZ) + (A,phi) = genericLinearMap RQ + + -- Here is how we construct these polynomials (using h11=3 database). + --(L1, F1) = (c2Form Xs#(26,0), cubicForm Xs#(26,0)) + --(L2, F2) = (c2Form Xs#(37,0), cubicForm Xs#(37,0)) + use RQ + (L1, F1) = (10*a+28*b+26*c,a^3-3*a^2*b-3*a*b^2-2*b^3-3*a^2*c+6*a*b*c+6*b^2*c+3*a*c^2+6*b*c^2-c^3) + (L2, F2) = (16*a+10*b+26*c,-2*a^3-3*a^2*b-3*a*b^2+b^3+6*a*b*c-3*b^2*c+6*a*c^2+3*b*c^2-c^3) + + MD = matchingData { + L1 => L2, + F1 => F2 + } + (src, tars) = matches MD + J = equivalenceIdeal(src, tars#0, RQ, (A,phi)) + A % J + assert(first invertibleMatrixOverZZ(A, J) == INCONSISTENT) + +/// + +TEST /// +-* + restart + needsPackage "IntegerEquivalences" +*- + RZ = ZZ[a,b,c] + RQ = QQ (monoid RZ) + (A,phi) = genericLinearMap RQ + + -- Here is how we construct these polynomials (using h11=3 database). + --(L1, F1) = (c2Form Xs#(26,0), cubicForm Xs#(26,0)) + --(L2, F2) = (c2Form Xs#(37,0), cubicForm Xs#(37,0)) + + use RZ + (L1, F1) = (8*a-4*b+36*c,2*a^3-3*a^2*b-3*a*b^2+8*b^3-6*a^2*c+6*a*b*c-6*b^2*c+6*a*c^2) + (L2, F2) = (-4*a+8*b+36*c,8*a^3-3*a^2*b-3*a*b^2+2*b^3-6*a^2*c+6*a*b*c-6*b^2*c+6*b*c^2) + findEquivalence({L1, F1}, {L2, F2}) + + --factorsByType det hessian F1 + + MD = matchingData { + L1 => L2, + F1 => F2 + } + (src, tars) = matches MD + J = equivalenceIdeal(src, tars#0, RQ, (A,phi)) + A % J + assert(first invertibleMatrixOverZZ(A, J) == CONSISTENT) + +/// + +TEST /// +-* + restart + needsPackage "IntegerEquivalences" +*- +/// + +end-- + +-* Documentation section *- +beginDocumentation() + +doc /// +Key + IntegerEquivalences +Headline +Description + Text + Tree + Example + CannedExample +Acknowledgement +Contributors +References +Caveat +SeeAlso +Subnodes +/// + +doc /// +Key +Headline +Usage +Inputs +Outputs +Consequences + Item +Description + Text + Example + CannedExample + Code + Pre +ExampleFiles +Contributors +References +Caveat +SeeAlso +/// + +-* Test section *- +TEST /// -* [insert short title for this test] *- +-- test code and assertions here +-- may have as many TEST sections as needed +/// + +end-- + +-* Development section *- +restart +needsPackage "IntegerEquivalences" +check "IntegerEquivalences" + +uninstallPackage "IntegerEquivalences" +restart +installPackage "IntegerEquivalences" +viewHelp "IntegerEquivalences" diff --git a/CYToolsM2/StringTorics.m2 b/CYToolsM2/StringTorics.m2 new file mode 100644 index 0000000..19de784 --- /dev/null +++ b/CYToolsM2/StringTorics.m2 @@ -0,0 +1,1167 @@ +newPackage( + "StringTorics", + Version => "0.7", -- bumped on 12 April. + Date => "12 April 2024", + Authors => { + {Name => "Mike Stillman", + Email => "mike@math.cornell.edu", + HomePage => "http://pi.math.cornell.edu/~mike"} + }, + Headline => "toric variety functions for string theory", + DebuggingMode => true, + AuxiliaryFiles => true, + PackageExports => { + "FourTiTwo", -- where is this used? + "SimplicialComplexes", + "NormalToricVarieties", + "Schubert2", + "Polyhedra", + "ReflexivePolytopesDB", + "CohomCalg", + "Topcom", + "Triangulations", + "InverseSystems", + "IntegerEquivalences" + }, + PackageImports => { + "LLLBases" + } + ) + +export { + -- Types defined here + "CYPolytope", -- rename to CYReflexivePair? How about CYPolytope? + "CalabiYauInToric", + "CYToolsCY3", -- we should have a superclass for CalabiYauInToric, CYToolsCY3 + "TopologicalDataOfCY3", + + -- CYPolytope, CalabiYauInToric + "InteriorFacets", + "ID", + "cyPolytope", + "dump", + "label", + + "cyData", + "makeCY", + "calabiYau", -- versions might include: + -- calabiYau(CYPolytope, Triangulation, Ring => RZ, Label => (a,i)) + -- The following are all taking the CY3 from a database: + -- all take Ring as optional argument. + -- calabiYau(String, CYPolytope, Label) -- from database, given Q + -- calabiYau(String, Label) -- from database, uses Q from same database. + -- calabiYau(String, Function, Label) -- from database, uses Q from same database. + -- calabiYau(Database, CYPolytope, Label) -- from database, given Q. + -- calabiYau(Database, Label) -- from database, uses Q from same database. + -- calabiYau(Database, Function, Label) -- takes Q from Function, label. + + "basisIndices", + "restrictTriangulation", -- restrict triangulation to each 2-face + "picardRing", + + "isFavorable", + + -- Extra polyhedral facilities, for lattice points and faces of a Polyhedron + -- how much of this shoiuld be exported?? + "vertexMatrix", + "vertexList", + "faceDimensionHash", + "faceList", + "dualFace", + "minimalFace", + "latticePointList", + "latticePointHash", + "interiorLatticePointList", + "annotatedFaces", + "automorphisms", + + -- current triangulation code + "findAllFRSTs", + "findAllCYs", + "findAllConnectedStarFine", + "findStarFineGraph", + + -- older triangulation code (still useful?) + "Origin", + "pointConfiguration", + "regularStarTriangulation", + "reflexiveToSimplicialToricVariety", + "reflexiveToSimplicialToricVarietyCleanDegrees", + "allZeros", + "augmentWithOrigin", + + -- This set maybe should be included in NormalToricVarieties? + "singularCones", + "singularLocusInToric", + "normalToricVarietyFromGLSM", + + -- Interfacing with Sage triangulations, triangulations from elsewhere + "readSageTriangulations", + "sortTriangulation", + "matchNonZero", + "applyPermutation", + "checkFan", + "sageTri", + + -- IntersectionNumbers + "intersectionNumbers", + "toricIntersectionNumbers", + "c2", + "intersectionForm", + "cubicForm", + "c2Form", + "intersectionNumbersOfCY", -- possibly not for export + + -- Cones of curves + "toricMoriCone", + "toricMoriConeCap", + + -- gvInvariants + "gvInvariants", + "gvCone", + "partitionGVConeByGV", + "classifyExtremalCurves", + "extremalRayGVs", + + -- remove these gvInvariant functions? + "classifyExtremalCurve", + "gvInvariantsAndCone", + -- "gvRay", + "findLinearMaps", + + + -- Invariants + "hubschInvariants", + "PointCounter", + "pointCounter", + "pointCounts", + "invariantsH11H12", + "invariantContents", + "hessianInvariants", + "singularContents", + "cubicConductorInvariants", -- rename? + "cubicLinearConductorInvariants", -- rename? + "singularContentsQuartic", -- rename? + "aronhold", + + -- Topology + "topologicalData", + "isEquivalent", + "invariants", + "mapIsIsomorphism", + "partitionByTopology", + + -- TopologySet's -- for determining equivalence + "TopologySet", + "topologySet", + "representatives", + "equivalences", + "IgnoreSingles", + "separateIfDifferent", + + + -- CompleteIntersectionInToric's + "completeIntersection", + "CompleteIntersectionInToric", + "Ambient", + "CI", + "Equations", + "equations", + "LineBundle", + "lineBundle", + "LinearForm", + "Basis", + + + -- Creating databases of polytopes (with precomputed data). + "hodgeNumbers", -- of KSEntry: gives (h11, h12) from KSEntry. Should be in ReflexivePolytopesDB? + "createCYDatabase", + "addToCYDatabase", + "readCYDatabase", + "readCYs", + "readCYPolytopes", + "combineCYDatabases", + "processCYPolytopes", + + -- Cohomology + "toricCohomologySetup", + "cohomologyBasis", + "CohomologySetup", + "cohomologyMatrix", + "cohomologyMatrixRank", + "genericCohomologyMatrix", + + -- new attempt at faster cohomology of line bundles in toric varieties. + -- want the Laurent monomials. + "toricOrthants", + "H1orthants", + "normalDegrees", + "normalDegree", + "setOfColumns", + "getFraction", + "findTope", + "cohomologyFractions", + + -- cohomology for complete intersections in torics + --TODO clean up this interface! + "cohomologyVector", -- currently calls CohomCalg, but shouold take an optional argument? + "cohomologyFromLES", + "collectLineBundles", + "cohomologyOmega1", + "removeUnusedVariables", + "example0912'3524", + "exampleP111122'44", + "cohom", + "nextBundle", + "basicCohomologies", + "hodgeDiamond", + "hodgeVector", + + -- CY hypersurface cohomology info from polyhedral information + "subcomplex", + "complexWithInteriorFacesRemoved", + -- The following are the ones we care about + "hodgeCY", -- debugging only? + "hodgeOfCYToricDivisor", + "hodgeOfCYToricDivisors", + "h11OfCY", + "h21OfCY", + + + -- new formula + "hodgeVectorViaTheorem", -- TODO: is likely not correct currently. + "tentativeHodgeVector", -- deprecated + + -- Topology of a CY3-fold. + -- input: reflexive poytope, and triangulation. + -- Some functions to have here: + -- type: CY3ToricHypersurface. + -- h11 X + -- h12, h21 X + -- intersectionNumbers X + -- topology X (returns an object of TopologicalDataOfCY3) + + -- Gopakumar-Vafa invariants + -- computed using Andres' computeGV code in C++ + + -- Flop chains, Mori cones + + "IntersectionNumbers", + "MoriHilbertGens", + "Automorphisms", + "FilePrefix", + "Executable", + "Mori", + "Count", + "Hodge", + "NTFE", + "PicardRing" + } + +--- kludge to access parts of the 'Core' +hasAttribute = value Core#"private dictionary"#"hasAttribute"; +getAttribute = value Core#"private dictionary"#"getAttribute"; +ReverseDictionary = value Core#"private dictionary"#"ReverseDictionary"; + +------------------------------------ +-- New types ----------------------- +------------------------------------ + +TopologicalDataOfCY3 = new Type of List + -- contains c2, cubic intersection form, h11, h12 + +CompleteIntersectionInToric = new Type of HashTable + +CYPolytope = new Type of HashTable +CalabiYauInToric = new Type of HashTable +CYToolsCY3 = new Type of HashTable + +LineBundle = new Type of HashTable + +lineBundle = method() +equations = method() + +dump = method(Options => true) +isFavorable = method(); +h11OfCY = method() -- deprecate this +h21OfCY = method() -- deprecate this +findAllFRSTs = method() + +-- Utility function +dotProduct = method() +dotProduct(List, List) := (v,w) -> ( + if #v =!= #w then error "expected vectors of the same length"; + sum for i from 0 to #v-1 list v#i * w#i + ) + +findEquivalence(CalabiYauInToric, CalabiYauInToric) := (X1, X2) -> ( + findEquivalence({c2Form X1, cubicForm X1}, {c2Form X2, cubicForm X2}) + ) + +load (currentFileDirectory | "StringTorics/MyPolyhedra.m2") +load (currentFileDirectory | "StringTorics/CYPolytope.m2") +load (currentFileDirectory | "StringTorics/CalabiYauInToric.m2") +load (currentFileDirectory | "StringTorics/IntersectionNumbers.m2") +load (currentFileDirectory | "StringTorics/Invariants.m2") +load (currentFileDirectory | "StringTorics/Topology.m2") +load (currentFileDirectory | "StringTorics/ToricCompleteIntersections.m2") -- has some util code, but not much. TODO: clean that up. +load (currentFileDirectory | "StringTorics/DatabaseCreation.m2") +load (currentFileDirectory | "StringTorics/Extras.m2") + + findAllConnectedStarFine = method() + findAllConnectedStarFine Triangulation := (T) -> ( + stars := new MutableHashTable; + stars#T = 0; + starcount := 1; + oldTODO := {T}; + radius := 0; + while #oldTODO > 0 do ( + radius = radius + 1; + newTODO := flatten for t1 in oldTODO list for n in neighbors t1 list ( + oldone := stars#t1; + t := n#1; + if isStar t and not stars#?t and isRegularTriangulation t then( + << "adding new triangulation " << starcount << " at radius " << radius << " with circuit " << n#0 << " from " << oldone << endl; + stars#t = starcount; + starcount = starcount + 1; + t + ) + else continue + ); + oldTODO = newTODO; + ); + keys stars + ) + + findStarFineGraph = method() + findStarFineGraph Triangulation := (T) -> ( + -- this version returns the determined graph of the FRST's. + -- 3 things are returned: + -- 1. a list of triangulations + -- 2. a hash table: for each triangulation index: key is a list of {tri#, affine circuit used to get to that} + stars := new MutableHashTable; + edges := new MutableList; + stars#T = 0; + starcount := 1; + oldTODO := {T}; + radius := 0; + while #oldTODO > 0 do ( + radius = radius + 1; + newTODO := flatten for t1 in oldTODO list for n in neighbors t1 list ( + newOneIsNew := false; + oldone := stars#t1; + t := n#1; + alreadyThere := stars#?t; + if not alreadyThere then ( + if isStar t and isRegularTriangulation t then ( + stars#t = starcount; + starcount = starcount + 1; + newOneIsNew = true; + ) + else continue + ); -- this is the case when we don't need to add an edge, nor place tri onto the newTODO list. + -- at this point both t and oldone are good. So let's add an edge. + edges#(#edges) = {oldone, stars#t, n#0}; + if newOneIsNew then t else continue + ); + oldTODO = newTODO; + ); + starsInv := hashTable for k in keys stars list stars#k => k; + starsList := for i from 0 to starcount-1 list starsInv#i; + (starsList, new List from edges) + ) + +protect nextVar +protect nextFinalVar +--------------------------------------------------- +singularLocusInToric = method() +singularLocusInToric(Ideal, Ideal) := (I, B) -> ( + -- I: an ideal in the Cox ring, where B is the irrelevant ideal. + -- return: a list of (codim Sing locus, groebner basis) for each max cone + -- TODO: this I think only works in the smooth case so far. FIX THIS. + -- find singular locus on each open set. + c := codim I; + Is := for b in B_* list ( + sub(I, for x in support b list x => 1) + ); + for J in Is list ( + singJ := J + minors(c, jacobian J); + (codim singJ, gens gb singJ) + ) + ) + +--------------------------------------------------- + +allzeros0 = (F, topvar, pt, lo, hi) -> ( + -- F is a polynomial in a poly ring (e.g. QQ[a,b,c]) + -- topvar + if topvar == -1 then (return if F == 0 then {pt} else {}); + R := ring F; + flatten for v from lo to hi list ( + G := sub(F, R_topvar => v); + pt1 := prepend(v, pt); + allzeros0(G, topvar-1, pt1, lo, hi) + ) + ) +allzeros1 = (F, topvar, pt, lo, hi, f) -> ( + -- F is a polynomial in a poly ring (e.g. QQ[a,b,c]) + -- topvar + if topvar == -1 then (if F == 0 then f pt; return null); + R := ring F; + for v from lo to hi do ( + G := sub(F, R_topvar => v); + pt1 := prepend(v, pt); + allzeros1(G, topvar-1, pt1, lo, hi, f) + ) + ) +allZeros = method() +allZeros(RingElement, Sequence) := (F, lohi) -> ( + (lo,hi) := lohi; + allzeros0(F, numgens ring F - 1, {}, lo, hi) + ) +allZeros(RingElement, ZZ, Sequence) := (F, topvar, lohi) -> ( + (lo,hi) := lohi; + allzeros0(F, topvar, {}, lo, hi) + ) +allZeros(RingElement, ZZ, Sequence, Function) := (F, topvar, lohi, f) -> ( + (lo,hi) := lohi; + allzeros1(F, topvar, {}, lo, hi, f) + ) + +reflexiveToSimplicialToricVariety = method(Options => { + CoefficientRing => QQ, + Variable => getSymbol "x" + }) + +reflexiveToSimplicialToricVariety Polyhedron := opts -> (P1) -> ( + -- P1 is a reflexive polytope in the M lattice. + -- Creates a simplicial toric variety via a triangulation + -- of the normal fan of P1, using all of lattice points of (polar P1). + -- Returns: a normal toric variety, whch uses all + -- lattice points in the triangulation. + P2 := polar P1; + (LP,tri) := regularStarTriangulation(dim P2-2,P2); + normalToricVariety(LP,tri,opts) + ) + +-- Subroutines for reflexiveToSimplicialToricVarietyCleanDegrees +-- These might be generally useful too? + findFirstUnitVectors = method() + findFirstUnitVectors Matrix := List => (M) -> ( + -- returns the indices of the the columns which are unit vectors, + -- if there are two or more columns corresponding to the same unit vector, take the first. + -- the result is in increasing list of integers. + e := entries transpose M; + unitposition := (col) -> if all(col, a -> a >= 0) and sum col === 1 then position(col, a -> a === 1) else null; + H := partition(c -> unitposition e_c, toList(0..numcols M-1)); + ks := select(keys H, k -> k =!= null); + sort for k in ks list min(H#k) + ) + + -- extend the nice unit vectors to a list p of n columns (n = numrows M) + -- so that det M_p = 1 or -1. + -- compute the inverse A of this n x n matrix. + -- then compute A^-1 * M, and return this list of columns. + -- TODO: don't use subsets... + findInvertibleSubmatrix = method(Options => {Limit => 10000}) + findInvertibleSubmatrix(Matrix, List) := List => opts -> (M, p) -> ( + -- M is a matrix over the integers + -- p is a list of column indices of M (indices run from 0 to numcols M - 1) + -- Find a list q containing p (if possible), of column indices, + -- s.t. det(M_q) = 1 or -1. + -- Return q, or null, if one cannot be found. + S := set toList(0..numcols M - 1); + others := sort toList(S - set p); + needed := numrows M - #p; + if binomial(#others, needed) > opts.Limit then return null; + -- really: do some random choices of q containing p. + trythese := subsets(others, needed); + tried := 0; + for q1 in trythese do ( + q := join(q1,p); + tried = tried+1; + if abs det(M_q) == 1 then ( + if debugLevel >= 1 then ( + << "found suitable set of columns after " << tried << " step" + << if tried == 1 then "" else "s" << endl; + ); + return sort q; + ); + ); + << "tried all determinants: none had unit determinant" << endl; + null + ) + +reflexiveToSimplicialToricVarietyCleanDegrees = method(Options => options reflexiveToSimplicialToricVariety) +reflexiveToSimplicialToricVarietyCleanDegrees Polyhedron := Sequence => opts -> (P1) -> ( + -- returns (V, q) where + -- V is essentially reflexiveToSimplicialToricVariety P1 + -- except that the degrees of the ring have been cleaned up + -- AND + -- a list of column indices (or of rays) in ascending order, + -- whose degrees form a basis, in fact the identity matrix. + -- null is returned if no such q can be found, or the algorithm + -- doesn't find it. + -- Note: we don't really need ring V0 here... + P2 := polar P1; + (LP,tri) := regularStarTriangulation(dim P2-2,P2); + D := transpose syz matrix transpose LP; + print D; + p := findFirstUnitVectors D; + q := findInvertibleSubmatrix(D, p); + if q === null then null + else ( + A := D_q; + D' := A^-1 * D; + (normalToricVariety(LP, tri, WeilToClass => D', opts), q) + ) + ) + +augmentWithOrigin = method() +augmentWithOrigin Matrix := (A) -> ( + -- A is a matrix over ZZ + -- add column of 0's, then add in a first row of 1's. + n := numColumns A; + zeros := matrix {numRows A : {0}}; + ones := matrix {{(n+1) : 1}}; + ones || (A | zeros) + ) + +augmentBack = (A) -> ( + -- A is a matrix over ZZ + -- add in a last row of 1's. Also add in one column of zeros + n := numColumns A; + zeros1 := matrix{numRows A : {0}}; + zeros0 := matrix {1+numRows A : {0}}; + ones := matrix {{n+1 : 1}}; + ((A | zeros1) || ones) --| zeros0 + ) + +readSageTriangulations = method() +readSageTriangulations String := (str) -> ( + -- " [[array([0, 1, 2, 3]), array([0, 1, 3, 4]), array([1, 2, 3, 4]), array([2, 3, 4, 5]), array([2, 3, 5, 8]), array([2, 5, 6, 7]), array([2, 5, 7, 8]), array([0, 2, 3, 8]), array([0, 2, 6, 7]), array([0, 2, 7, 8]), array([0, 1, 4, 7]), array([0, 1, 6, 7]), array([0, 3, 4, 8]), array([0, 4, 7, 8]), array([1, 4, 6, 7]), array([4, 5, 6, 7]), array([3, 4, 5, 8]), array([4, 5, 7, 8]), array([0, 1, 2, 6]), array([1, 2, 4, 6]), array([2, 4, 5, 6])], [array([0, 1, 2, 3]), array([0, 1, 3, 4]), array([1, 2, 3, 5]), array([1, 3, 4, 5]), array([2, 3, 5, 8]), array([2, 5, 6, 7]), array([2, 5, 7, 8]), array([0, 2, 3, 8]), array([0, 2, 6, 7]), array([0, 2, 7, 8]), array([0, 1, 4, 7]), array([0, 1, 6, 7]), array([0, 3, 4, 8]), array([0, 4, 7, 8]), array([1, 4, 6, 7]), array([4, 5, 6, 7]), array([3, 4, 5, 8]), array([4, 5, 7, 8]), array([0, 1, 2, 6]), array([1, 2, 5, 6]), array([1, 4, 5, 6])], [array([0, 1, 2, 3]), array([0, 1, 3, 4]), array([1, 2, 3, 5]), array([1, 3, 4, 5]), array([2, 3, 5, 8]), array([2, 5, 6, 8]), array([5, 6, 7, 8]), array([0, 2, 3, 8]), array([0, 2, 6, 8]), array([0, 6, 7, 8]), array([0, 1, 4, 7]), array([0, 1, 6, 7]), array([0, 3, 4, 8]), array([0, 4, 7, 8]), array([1, 4, 6, 7]), array([4, 5, 6, 7]), array([3, 4, 5, 8]), array([4, 5, 7, 8]), array([0, 1, 2, 6]), array([1, 2, 5, 6]), array([1, 4, 5, 6])], [array([0, 1, 2, 3]), array([0, 1, 3, 4]), array([1, 2, 3, 4]), array([2, 3, 4, 5]), array([2, 3, 5, 8]), array([2, 5, 6, 8]), array([5, 6, 7, 8]), array([0, 2, 3, 8]), array([0, 2, 6, 8]), array([0, 6, 7, 8]), array([0, 1, 4, 7]), array([0, 1, 6, 7]), array([0, 3, 4, 8]), array([0, 4, 7, 8]), array([1, 4, 6, 7]), array([4, 5, 6, 7]), array([3, 4, 5, 8]), array([4, 5, 7, 8]), array([0, 1, 2, 6]), array([1, 2, 4, 6]), array([2, 4, 5, 6])], [array([0, 1, 2, 3]), array([0, 1, 3, 4]), array([1, 2, 3, 5]), array([1, 3, 4, 5]), array([2, 3, 5, 6]), array([3, 5, 6, 8]), array([5, 6, 7, 8]), array([0, 2, 3, 6]), array([0, 3, 6, 8]), array([0, 6, 7, 8]), array([0, 1, 4, 7]), array([0, 1, 6, 7]), array([0, 3, 4, 8]), array([0, 4, 7, 8]), array([1, 4, 6, 7]), array([4, 5, 6, 7]), array([3, 4, 5, 8]), array([4, 5, 7, 8]), array([0, 1, 2, 6]), array([1, 2, 5, 6]), array([1, 4, 5, 6])], [array([0, 1, 2, 5]), array([0, 1, 4, 5]), array([0, 2, 3, 5]), array([0, 3, 4, 5]), array([2, 3, 5, 8]), array([2, 5, 6, 8]), array([5, 6, 7, 8]), array([0, 2, 3, 8]), array([0, 2, 6, 8]), array([0, 6, 7, 8]), array([0, 1, 4, 7]), array([0, 1, 6, 7]), array([0, 3, 4, 8]), array([0, 4, 7, 8]), array([1, 4, 6, 7]), array([4, 5, 6, 7]), array([3, 4, 5, 8]), array([4, 5, 7, 8]), array([0, 1, 2, 6]), array([1, 2, 5, 6]), array([1, 4, 5, 6])], [array([0, 1, 2, 3]), array([0, 1, 3, 4]), array([1, 2, 3, 4]), array([2, 3, 4, 5]), array([2, 3, 5, 6]), array([3, 5, 6, 8]), array([5, 6, 7, 8]), array([0, 2, 3, 6]), array([0, 3, 6, 8]), array([0, 6, 7, 8]), array([0, 1, 4, 7]), array([0, 1, 6, 7]), array([0, 3, 4, 8]), array([0, 4, 7, 8]), array([1, 4, 6, 7]), array([4, 5, 6, 7]), array([3, 4, 5, 8]), array([4, 5, 7, 8]), array([0, 1, 2, 6]), array([1, 2, 4, 6]), array([2, 4, 5, 6])], [array([0, 1, 2, 4]), array([0, 2, 3, 5]), array([0, 2, 4, 5]), array([0, 3, 4, 5]), array([2, 3, 5, 8]), array([2, 5, 6, 7]), array([2, 5, 7, 8]), array([0, 2, 3, 8]), array([0, 2, 6, 7]), array([0, 2, 7, 8]), array([0, 1, 4, 7]), array([0, 1, 6, 7]), array([0, 3, 4, 8]), array([0, 4, 7, 8]), array([1, 4, 6, 7]), array([4, 5, 6, 7]), array([3, 4, 5, 8]), array([4, 5, 7, 8]), array([0, 1, 2, 6]), array([1, 2, 4, 6]), array([2, 4, 5, 6])], [array([0, 1, 2, 5]), array([0, 1, 4, 5]), array([0, 2, 3, 5]), array([0, 3, 4, 5]), array([2, 3, 5, 6]), array([3, 5, 6, 8]), array([5, 6, 7, 8]), array([0, 2, 3, 6]), array([0, 3, 6, 8]), array([0, 6, 7, 8]), array([0, 1, 4, 7]), array([0, 1, 6, 7]), array([0, 3, 4, 8]), array([0, 4, 7, 8]), array([1, 4, 6, 7]), array([4, 5, 6, 7]), array([3, 4, 5, 8]), array([4, 5, 7, 8]), array([0, 1, 2, 6]), array([1, 2, 5, 6]), array([1, 4, 5, 6])], [array([0, 1, 2, 5]), array([0, 1, 4, 5]), array([0, 2, 3, 5]), array([0, 3, 4, 5]), array([2, 3, 5, 8]), array([2, 5, 6, 7]), array([2, 5, 7, 8]), array([0, 2, 3, 8]), array([0, 2, 6, 7]), array([0, 2, 7, 8]), array([0, 1, 4, 7]), array([0, 1, 6, 7]), array([0, 3, 4, 8]), array([0, 4, 7, 8]), array([1, 4, 6, 7]), array([4, 5, 6, 7]), array([3, 4, 5, 8]), array([4, 5, 7, 8]), array([0, 1, 2, 6]), array([1, 2, 5, 6]), array([1, 4, 5, 6])], [array([0, 1, 2, 4]), array([0, 2, 3, 5]), array([0, 2, 4, 5]), array([0, 3, 4, 5]), array([2, 3, 5, 8]), array([2, 5, 6, 8]), array([5, 6, 7, 8]), array([0, 2, 3, 8]), array([0, 2, 6, 8]), array([0, 6, 7, 8]), array([0, 1, 4, 7]), array([0, 1, 6, 7]), array([0, 3, 4, 8]), array([0, 4, 7, 8]), array([1, 4, 6, 7]), array([4, 5, 6, 7]), array([3, 4, 5, 8]), array([4, 5, 7, 8]), array([0, 1, 2, 6]), array([1, 2, 4, 6]), array([2, 4, 5, 6])], [array([0, 1, 2, 4]), array([0, 2, 3, 5]), array([0, 2, 4, 5]), array([0, 3, 4, 5]), array([2, 3, 5, 6]), array([3, 5, 6, 8]), array([5, 6, 7, 8]), array([0, 2, 3, 6]), array([0, 3, 6, 8]), array([0, 6, 7, 8]), array([0, 1, 4, 7]), array([0, 1, 6, 7]), array([0, 3, 4, 8]), array([0, 4, 7, 8]), array([1, 4, 6, 7]), array([4, 5, 6, 7]), array([3, 4, 5, 8]), array([4, 5, 7, 8]), array([0, 1, 2, 6]), array([1, 2, 4, 6]), array([2, 4, 5, 6])]] " + s1 := replace("array", "", str); + s2 := replace("\\(", "", s1); + s3 := replace("\\)", "", s2); + s4 := replace("\\[", "{", s3); + s5 := replace("\\]", "}", s4); + value s5 + ) + +sortTriangulation = method() +sortTriangulation List := (T) -> sort for t in T list sort t + +matchNonZero = method() +matchNonZero(Matrix, Matrix) := (A,B) -> ( + eA := entries transpose A; + Ah := hashTable for i from 0 to #eA-1 list ( + if all(eA#i, x -> x == 0) then continue else eA#i => i + ); + eB := entries transpose B; + Bh := hashTable for i from 0 to #eB-1 list ( + if all(eB#i, x -> x == 0) then continue else eB#i => i + ); + if set keys Ah =!= set keys Bh then ( + error "non-zero columns are different"; + ); + AtoB := for e in eA list if Bh#?e then Bh#e else -1; + BtoA := for e in eB list if Ah#?e then Ah#e else -1; + (AtoB, BtoA) + ) + +applyPermutation = method() +applyPermutation(List, ZZ) := (P, i) -> if i >= 0 and i < #P then P#i else -1 +applyPermutation(List, List) := (P, L) -> sort for f in L list applyPermutation(P,f) + +--------------------------------------- +-- Code for toric varieties packages -- +--------------------------------------- + + singularCones = method() + singularCones(ZZ, NormalToricVariety) := (coneDim, X) -> ( + rys := transpose matrix rays X; + which := orbits(X, coneDim); + select(which, f -> ( + I := trim minors(#f, rys_f); + I != 1)) + ) + singularCones(ZZ, NormalToricVariety, Thing) := (coneDim, X, notused) -> ( + -- This version also returns the multiplicity, for non smooth cones. + rys := transpose matrix rays X; + which := orbits(X, coneDim); + for f in which list ( + I := trim minors(#f, rys_f); + if I == 1 then continue; + f => I_0 + ) + ) + + QQCartierCoefficients = method () + QQCartierCoefficients ToricDivisor := List => D -> ( + X := variety D; + rayMatrix := QQ ** matrix rays X; + coeffs := QQ ** transpose (matrix {entries D}); + apply (max X, sigma -> coeffs^sigma // rayMatrix^sigma) + ); + + monomialsToLatticePoints = method() + monomialsToLatticePoints(ToricDivisor, List) := List => (D, monoms) -> ( + -- given a list of monomials in the Cox ring, returns their corresponding lattice point in the M lattice. + -- Maybe we do not need D? Just the toric variety itself? + X := variety D; + if not isProjective X then + error "--expected the underlying toric variety to be projective"; + degs := QQ ** transpose matrix rays X; + deginverse := transpose(id_(QQ^(numrows degs)) // degs); + coeff := matrix vector D; + for mon in monoms list ( + flatten entries sub(deginverse * (transpose matrix{first exponents mon} - coeff), ZZ) + ) + ) + + normalToricVarietyFromGLSM = method(Options=>options normalToricVariety) + normalToricVarietyFromGLSM(Matrix, List) := opts -> (GLSM, maxCones) -> ( + -- create rays from GLSM degrees (which will then be the output of + rays := entries syz GLSM; + normalToricVariety(rays, maxCones, opts, WeilToClass => GLSM) + ) + normalToricVarietyFromGLSM(Matrix, MonomialIdeal) := opts -> (GLSM, SRIdeal) -> ( + -- this switch to dual should be much simpler than this... + n := numColumns GLSM; -- also should be the number of variables of the ring SRIdeal + allvars := set toList(0..n-1); + maxcones := (dual SRIdeal)_*/(f -> sort toList(allvars - (support f)/index//set)); + normalToricVarietyFromGLSM(GLSM, maxcones, opts) + ) + + -- This function isn't used anywhere?? + pointConfiguration = method(Options => {Homogenize=>false, Origin => false}); + pointConfiguration(ZZ,Polyhedron) := opts -> (maxdim, P2) -> ( + LP := select(latticePointList P2, lp -> dim(P2, minimalFace(P2, lp)) <= maxdim); + A := transpose matrix LP; + if opts.Origin then + A = A | matrix for i from 1 to numRows A list {0}; + if opts.Homogenize then + A = A || matrix {for i from 1 to numColumns A list 0}; + A + ) + +-- TODO: what should this be returning?? Probably a Triangulation object. +-- But with or without the cone vertex?? +regularStarTriangulation = method() +regularStarTriangulation Polyhedron := (P2) -> ( + LP := drop(latticePointList P2, -1); + A := transpose matrix LP; + tri := max regularFineTriangulation A; + -- Now, this is not a star triangulation... But we think we can make it so in the + -- following way. + facetlist := (faceList(dim P2-1, P2))/(f -> latticePointList(P2,f)); + newtri := sort flatten for f in tri list ( + fac := select(facetlist, g -> #((set f) * (set g)) == dim P2); + for g in fac list sort toList ((set f) * (set g)) + ); + (LP,newtri) + ) + +regularStarTriangulation(ZZ,Polyhedron) := (maxdim, P2) -> ( + LP := select(latticePointList P2, lp -> dim(P2, minimalFace(P2, lp)) <= maxdim); + A := transpose matrix LP; + A = A | matrix for i from 1 to numRows A list {0}; + tri := topcomRegularFineTriangulation A; + -- Now, this is not a star triangulation... But we think we can make it so in the + -- following way. + H := latticePointHash P2; + fullset := set for lp in LP list H#lp; + facetlist := faceList(dim P2-1, P2); + facetlist = facetlist/(f -> ( + sort toList(set latticePointList(P2,f) * fullset) + )); + newtri := sort flatten for f in tri list ( + fac := select(facetlist, g -> #((set f) * (set g)) == dim P2); + for g in fac list sort toList ((set f) * (set g)) + ); + (LP,newtri) + ) + + sageTri = " [[array([0, 1, 2, 3]), array([0, 1, 3, 4]), array([1, 2, 3, 4]), array([2, 3, 4, 5]), +array([2, 3, 5, 8]), array([2, 5, 6, 7]), array([2, 5, 7, 8]), +array([0, 2, 3, 8]), array([0, 2, 6, 7]), array([0, 2, 7, 8]), +array([0, 1, 4, 7]), array([0, 1, 6, 7]), array([0, 3, 4, 8]), +array([0, 4, 7, 8]), array([1, 4, 6, 7]), array([4, 5, 6, 7]), +array([3, 4, 5, 8]), array([4, 5, 7, 8]), array([0, 1, 2, 6]), +array([1, 2, 4, 6]), array([2, 4, 5, 6])], [array([0, 1, 2, 3]), +array([0, 1, 3, 4]), array([1, 2, 3, 5]), array([1, 3, 4, 5]), +array([2, 3, 5, 8]), array([2, 5, 6, 7]), array([2, 5, 7, 8]), + array([0, 2, 3, 8]), array([0, 2, 6, 7]), array([0, 2, 7, 8]), + array([0, 1, 4, 7]), array([0, 1, 6, 7]), array([0, 3, 4, 8]), + array([0, 4, 7, 8]), array([1, 4, 6, 7]), array([4, 5, 6, 7]), + array([3, 4, 5, 8]), array([4, 5, 7, 8]), array([0, 1, 2, 6]), + array([1, 2, 5, 6]), array([1, 4, 5, 6])], [array([0, 1, 2, 3]), + array([0, 1, 3, 4]), array([1, 2, 3, 5]), array([1, 3, 4, 5]), + array([2, 3, 5, 8]), array([2, 5, 6, 8]), array([5, 6, 7, 8]), + array([0, 2, 3, 8]), array([0, 2, 6, 8]), array([0, 6, 7, 8]), + array([0, 1, 4, 7]), array([0, 1, 6, 7]), array([0, 3, 4, 8]), + array([0, 4, 7, 8]), array([1, 4, 6, 7]), array([4, 5, 6, 7]), + array([3, 4, 5, 8]), array([4, 5, 7, 8]), array([0, 1, 2, 6]), + array([1, 2, 5, 6]), array([1, 4, 5, 6])], [array([0, 1, 2, 3]), + array([0, 1, 3, 4]), array([1, 2, 3, 4]), array([2, 3, 4, 5]), + array([2, 3, 5, 8]), array([2, 5, 6, 8]), array([5, 6, 7, 8]), + array([0, 2, 3, 8]), array([0, 2, 6, 8]), array([0, 6, 7, 8]), array([0, 1, 4, 7]), array([0, 1, 6, 7]), + array([0, 3, 4, 8]), array([0, 4, 7, 8]), array([1, 4, 6, 7]), array([4, 5, 6, 7]), array([3, 4, 5, 8]), + array([4, 5, 7, 8]), array([0, 1, 2, 6]), array([1, 2, 4, 6]), array([2, 4, 5, 6])], [array([0, 1, 2, 3]), + array([0, 1, 3, 4]), array([1, 2, 3, 5]), array([1, 3, 4, 5]), array([2, 3, 5, 6]), array([3, 5, 6, 8]), + array([5, 6, 7, 8]), array([0, 2, 3, 6]), array([0, 3, 6, 8]), array([0, 6, 7, 8]), array([0, 1, 4, 7]), + array([0, 1, 6, 7]), array([0, 3, 4, 8]), array([0, 4, 7, 8]), array([1, 4, 6, 7]), array([4, 5, 6, 7]), + array([3, 4, 5, 8]), array([4, 5, 7, 8]), array([0, 1, 2, 6]), array([1, 2, 5, 6]), array([1, 4, 5, 6])], +[array([0, 1, 2, 5]), array([0, 1, 4, 5]), array([0, 2, 3, 5]), array([0, 3, 4, 5]), array([2, 3, 5, 8]), + array([2, 5, 6, 8]), array([5, 6, 7, 8]), array([0, 2, 3, 8]), array([0, 2, 6, 8]), array([0, 6, 7, 8]), + array([0, 1, 4, 7]), array([0, 1, 6, 7]), array([0, 3, 4, 8]), array([0, 4, 7, 8]), array([1, 4, 6, 7]), + array([4, 5, 6, 7]), array([3, 4, 5, 8]), array([4, 5, 7, 8]), array([0, 1, 2, 6]), array([1, 2, 5, 6]), + array([1, 4, 5, 6])], [array([0, 1, 2, 3]), array([0, 1, 3, 4]), array([1, 2, 3, 4]), array([2, 3, 4, 5]), + array([2, 3, 5, 6]), array([3, 5, 6, 8]), array([5, 6, 7, 8]), array([0, 2, 3, 6]), array([0, 3, 6, 8]), + array([0, 6, 7, 8]), array([0, 1, 4, 7]), array([0, 1, 6, 7]), array([0, 3, 4, 8]), array([0, 4, 7, 8]), + array([1, 4, 6, 7]), array([4, 5, 6, 7]), array([3, 4, 5, 8]), array([4, 5, 7, 8]), array([0, 1, 2, 6]), + array([1, 2, 4, 6]), array([2, 4, 5, 6])], [array([0, 1, 2, 4]), array([0, 2, 3, 5]), array([0, 2, 4, 5]), + array([0, 3, 4, 5]), array([2, 3, 5, 8]), array([2, 5, 6, 7]), array([2, 5, 7, 8]), array([0, 2, 3, 8]), + array([0, 2, 6, 7]), array([0, 2, 7, 8]), array([0, 1, 4, 7]), array([0, 1, 6, 7]), array([0, 3, 4, 8]), + array([0, 4, 7, 8]), array([1, 4, 6, 7]), array([4, 5, 6, 7]), array([3, 4, 5, 8]), array([4, 5, 7, 8]), + array([0, 1, 2, 6]), array([1, 2, 4, 6]), array([2, 4, 5, 6])], [array([0, 1, 2, 5]), array([0, 1, 4, 5]), + array([0, 2, 3, 5]), array([0, 3, 4, 5]), array([2, 3, 5, 6]), array([3, 5, 6, 8]), array([5, 6, 7, 8]), + array([0, 2, 3, 6]), array([0, 3, 6, 8]), array([0, 6, 7, 8]), array([0, 1, 4, 7]), array([0, 1, 6, 7]), + array([0, 3, 4, 8]), array([0, 4, 7, 8]), array([1, 4, 6, 7]), array([4, 5, 6, 7]), array([3, 4, 5, 8]), + array([4, 5, 7, 8]), array([0, 1, 2, 6]), array([1, 2, 5, 6]), array([1, 4, 5, 6])], [array([0, 1, 2, 5]), + array([0, 1, 4, 5]), array([0, 2, 3, 5]), array([0, 3, 4, 5]), array([2, 3, 5, 8]), array([2, 5, 6, 7]), + array([2, 5, 7, 8]), array([0, 2, 3, 8]), array([0, 2, 6, 7]), array([0, 2, 7, 8]), array([0, 1, 4, 7]), + array([0, 1, 6, 7]), array([0, 3, 4, 8]), array([0, 4, 7, 8]), array([1, 4, 6, 7]), array([4, 5, 6, 7]), + array([3, 4, 5, 8]), array([4, 5, 7, 8]), array([0, 1, 2, 6]), array([1, 2, 5, 6]), array([1, 4, 5, 6])], +[array([0, 1, 2, 4]), array([0, 2, 3, 5]), array([0, 2, 4, 5]), array([0, 3, 4, 5]), array([2, 3, 5, 8]), + array([2, 5, 6, 8]), array([5, 6, 7, 8]), array([0, 2, 3, 8]), array([0, 2, 6, 8]), array([0, 6, 7, 8]), + array([0, 1, 4, 7]), array([0, 1, 6, 7]), array([0, 3, 4, 8]), array([0, 4, 7, 8]), array([1, 4, 6, 7]), + array([4, 5, 6, 7]), array([3, 4, 5, 8]), array([4, 5, 7, 8]), array([0, 1, 2, 6]), array([1, 2, 4, 6]), + array([2, 4, 5, 6])], [array([0, 1, 2, 4]), array([0, 2, 3, 5]), array([0, 2, 4, 5]), array([0, 3, 4, 5]), + array([2, 3, 5, 6]), array([3, 5, 6, 8]), array([5, 6, 7, 8]), array([0, 2, 3, 6]), array([0, 3, 6, 8]), + array([0, 6, 7, 8]), array([0, 1, 4, 7]), array([0, 1, 6, 7]), array([0, 3, 4, 8]), array([0, 4, 7, 8]), + array([1, 4, 6, 7]), array([4, 5, 6, 7]), array([3, 4, 5, 8]), array([4, 5, 7, 8]), array([0, 1, 2, 6]), + array([1, 2, 4, 6]), array([2, 4, 5, 6])]] " + +load (currentFileDirectory | "StringTorics/LineBundleCohomology.m2") + +----------------------- +-- Examples ----------- +----------------------- +example0912'3524 = () -> (value /// () -> ( + R := QQ[v1, v2, v3, v4, v5, v6, v1s, v7, v8, v9, v10]; + SR := {{v3,v9},{v5,v9},{v7,v10},{v1,v2,v3}, + {v4,v1s,v8},{v4,v7,v8},{v4,v8,v9}, + {v5,v6,v1s},{v5,v6,v10},{v1,v2,v6,v1s}}; + SR = monomialIdeal(SR/product); + GLSM := transpose matrix {{3, 3, 3, 3, 0}, {2, 2, 2, 2, 0}, + {1, 0, 0, 0, 0}, {0, 0, 1, 0, 0}, {0, 0, 0, 1, 0}, + {0, 1, 0, 0, 0}, {0, 1, 1, 0, 0}, {0, 0, 1, 0, 1}, + {0, 0, 1, 0, 0}, {0,-1,-1, 1,-1}, {0, 0, 0, 0, 1}}; + normalToricVarietyFromGLSM(GLSM, SR) + ) + /// + ) + +exampleP11222'8 = () -> (value /// () -> ( + -- P^4_{11222}[8] + -- Actually: we desingularize the ZZ/2 - singularity of this + rays := {{-1,-2,-2,-2}, + {1,0,0,0}, + {0,1,0,0}, + {0,0,1,0}, + {0,0,0,1}, + {0,-1,-1,-1}}; + maxcones := { + {0, 2, 3, 4}, + {0, 2, 3, 5}, + {0, 2, 4, 5}, + {0, 3, 4, 5}, + {1, 2, 3, 4}, + {1, 2, 3, 5}, + {1, 2, 4, 5}, + {1, 3, 4, 5}}; + GLSM := transpose matrix { + {1,0}, {1,0}, {2,1}, {2,1}, {2,1}, {0,1}}; + normalToricVariety(rays, maxcones, WeilToClass => GLSM) + ) + /// + ) + +exampleP111122'44 = () -> (value /// () -> ( + rays := {{-1,-1,-1,-2,-2}, + {1,0,0,0,0}, + {0,1,0,0,0}, + {0,0,1,0,0}, + {0,0,0,1,0}, + {0,0,0,0,1}}; + maxcones := { + {0, 1, 2, 3, 4}, + {0, 1, 2, 3, 5}, + {0, 1, 2, 4, 5}, + {0, 1, 3, 4, 5}, + {0, 2, 3, 4, 5}, + {1, 2, 3, 4, 5}}; + GLSM := transpose matrix { + {1}, {1}, {1}, {1}, {2}, {2}}; + normalToricVariety(rays, maxcones, WeilToClass => GLSM) + ) + /// + ) + + findAllFRSTs NormalToricVariety := (V) -> findAllFRSTs transpose matrix rays V + findAllFRSTs Matrix := List => (A) -> ( + A1 := A | map(target A, (ring source A)^1, 0); + Ts := allTriangulations(A1, Fine => true, RegularOnly => true); + if #Ts === 0 or #Ts#0 == 0 then ( + count := 0; + while count < 10 and (#Ts === 0 or #Ts#0 == 0) do ( + Ts = allTriangulations(A1, Fine => true, RegularOnly => true); + count = count + 1; + ); + --if #Ts == 0 then error "no triangulation could be found"; + << "WARNING: TOPCOM failed to find triangulations, then found them after " << + count << " attempt(s)" << endl; + ); + --<< "Ts = (before selection): " << netList Ts << endl; + Ts1 := select(Ts, isStar); + --<< "Ts1 = (after): " << netList Ts1 << endl; + assert all(Ts1, tri -> all(max tri, s -> s#-1 == numcols A)); + Ts1/(t -> (entries transpose A, (max t)/(s -> drop(s, -1)))) + ) + findAllFRSTs Polyhedron := List => (P) -> ( + L := latticePointList P; + assert all(L#-1, a -> a == 0); + L = drop(L, -1); + A := transpose matrix L; + findAllFRSTs A + ) + + +-- Being rewritten 22 Aug 2023. +-- findAllCYs = method(Options => {Ring => null}) -- opts.Ring: ZZ[h11 variables]. +-- findAllCYs CYPolytope := List => opts -> Q -> ( +-- Ts := findAllFRSTs Q; +-- RZ := if opts#Ring === null then ( +-- a := getSymbol "a"; +-- h11 := hh^(1,1) Q; +-- ZZ[a_1 .. a_h11] +-- ) +-- else ( +-- opts#Ring +-- ); +-- for i from 0 to #Ts - 1 list cyData(Q, Ts#i, ID => i, Ring => RZ) +-- ) + + +-- keys: id, cypolytopedata, triangulation, cache. The id is what? (id of polytope, which triangulation) +-- write date: for cypolytopedata, just writes the id. +-- read data: given id, need to be able to get at which polytope it is. +-- maybe a table with id => CYPolytope, or a function which takes an integer and returns +-- the CYPolytope object to use, with this id. +-- construct one from a CYPolytope, id, triangulation. +-- what is in the cache? +-- ambient toric +-- CYInToric? +-- abstract toric variety (depends on base) +-- abstract variety for CY3 (depends on base) +-- intersectionNumbers +-- cubicForm (string or polynomial? or intersection numbers only?) +-- c2Form (string or list or polynomial?) +-- mori cone info? +-- gv invariants? + + +---------------------------------------------------------------- + + +---------------------------------------------------------------- +-- FRST Triangulations (Fine, regular, star triangulations) ---- +---------------------------------------------------------------- + +reflexiveToSimplicialToricVariety Polyhedron := opts -> (P1) -> ( + -- P1 is a reflexive polytope in the M lattice. + -- Creates a simplicial toric variety via a triangulation + -- of the normal fan of P1, using all of lattice points of (polar P1). + -- Returns: a normal toric variety, whch uses all + -- lattice points in the triangulation. + P2 := polar P1; + (LP,tri) := regularStarTriangulation(dim P2-2,P2); + normalToricVariety(LP,tri,opts) + ) + + +load (currentFileDirectory | "StringTorics/GVInvariants.m2") + +-- This file refers to many of the method names defined earlier, applied to CYToolsCY3 +load (currentFileDirectory | "StringTorics/CYTools.m2") + +beginDocumentation() + +-- Problems +-- . how to determine favorable? +-- . which toric variety do we want? +-- . want a smooth one +-- . want to compute h^11(X) using cohomcalg, but +-- examples can be too big +-- . triangulations can be too big +-- . what else can be too big? + +load (currentFileDirectory | "StringTorics/doc.m2") +load (currentFileDirectory | "StringTorics/test.m2") + +end-- + +restart + uninstallAllPackages() + +restart + installPackage "IntegerEquivalences" -- works, lots of warnings + installPackage "DanilovKhovanskii" + installPackage "StringTorics" + + + check IntegerEquivalences -- 8 checks, finishes to completion. + check DanilovKhovanskii -- 10 checks, finishes, 3 take some time + check StringTorics -- 35 tests, finishes to completion. 3 tests take > 10 sec. + +restart +needsPackage "StringTorics" +path = append(path, "......") +needsPackage("StringTorics", FileName => "/Users/.../StringTorics.m2") +restart +uninstallPackage "StringTorics" +restart +installPackage "StringTorics" +viewHelp oo + +restart +needsPackage "StringTorics" +check oo -- all tests currently check. + +-- Generation of some examples +L = kreuzerSkarke(20, Limit => 100, Access=>"wget") +L = kreuzerSkarke(15, Limit => 100) +L = kreuzerSkarke(13, Limit => 100) +L = kreuzerSkarke(10, Limit => 100) +A = matrix L_50 +P = convexHull A +isReflexive P +X = reflexiveToSimplicialToricVariety P + max X + # rays X + sr = dual monomialIdeal X + for i from 0 to #L-1 list ( + elapsedTime X = reflexiveToSimplicialToricVariety convexHull matrix L_i; + if # rays X > 64 then continue; + elapsedTime S = try ring X else null; + if S === null then continue; + sr = elapsedTime dual monomialIdeal X; + if numgens sr > 64 then continue; + i + ) + Xs = for i from 0 to #L-1 list ( + elapsedTime X = reflexiveToSimplicialToricVariety convexHull matrix L_i + ) + + tally apply(Xs, X -> # rays X) + select(Xs, X -> elapsedTime try (ring X; true) else false) -- h11=13, h11=15: all ok here... + tally apply(Xs, X -> numgens elapsedTime dual monomialIdeal X) + tally apply(Xs, X -> # rays X) + positions(Xs, X -> numgens elapsedTime dual monomialIdeal X < 64) + max Xs_28 + debug CohomCalg + print toCohomCalg Xs_28 -- h11 = 15 + + -- h11 = 15: + positions(Xs, X -> numgens elapsedTime dual monomialIdeal X == 39) -- h11=15 indices: 51, 66. + max Xs_51 + rays Xs_51 + print toCohomCalg Xs_51 + + -- h11 = 15: + positions(Xs, X -> numgens elapsedTime dual monomialIdeal X == 24) -- h11=10 indices: 6. + max Xs_6 + rays Xs_6 + print toCohomCalg Xs_6 + + +str = getKreuzerSkarke(4,100,Limit=>10) +time polytopes = parseKS str; +#polytopes +time for p in polytopes list (p_0, matrixFromString p_1); + + +str = getKreuzerSkarke(50,100,Limit=>4000); +str = getKreuzerSkarke(50,100,Limit=>0) +str = getKreuzerSkarke(4,4,Limit=>10) +str = getKreuzerSkarke(4,8,Limit=>10) +for i from 1 to 20 list parseKS getKreuzerSkarke(4,i,Limit=>10) +for i from 21 to 30 list parseKS getKreuzerSkarke(4,i,Limit=>10) +for i from 31 to 40 list parseKS getKreuzerSkarke(4,i,Limit=>10) +join oo +flatten oo +netList oo + +-- Experiments for Batyrev formula +restart +needsPackage "StringTorics" +getKreuzerSkarke(3,57) +polytopes = parseKS oo; +netList polytopes +polystr = polytopes_2 +A = matrixFromString polystr_1 +P = convexHull A +P2 = polar P + +-- Part 1: +# latticePoints(P2) == 8 + +-- Part2: facets of P2 +faces1 = faces(1, P2) + +F = faces1_0 +vertices F +latticePoints F + +for f in faces1 list ((# latticePoints f) - numColumns vertices F) +F = faces1_3 +hyperplanes F +(first (hyperplanes F)) * vertices F +H = for f in faces(1,F) list hyperplanes f +latticePoints F +for p in oo list H_0_0 * p + +-- Need a function: given a lattice point, and a polytope, is the point in the polytope? + -- Is it on the boundary? +L = latticePoints F +interiorLatticePoints F +for p in L list contains(F,p) +for f in faces(1,P2) list interiorLatticePoints f +for f in faces(2,P2) list interiorLatticePoints f +F22 = faces(2,P2) +first oo +polar oo +vertices oo + +F2 = faces(2,P) +#F22 +#F2 +faces(4,P) +faces(1,P2) +# faces(2,P2) +# faces(3,P) +faces(3,P2) +faces(2,P) + +-- Ben's code for morigenerators, translated into M2. +moriGenerators = method() +moriGenerators(List, List) := (rays, cones) -> ( + -- rays: a list of points in ZZ^n + -- cones: a list of lists of size n, each element is a subset of 0..n-1, + -- representing the simplicial cones of a fan with rays 'rays' + n := #(rays#0); + cones := cones/set; + -- assert: all rays have length n, and all cones have n as well + walls := select(subsets(n,2), x -> # toList (cones#(x_0) * cones#(x_1)) == n-1); + commons := for x in walls list toList (cones#(x_0) + cones#(x_1)); + walls + ) +rays25 = {{2, -1, -1, -1}, {-1, 0, -1, -1}, {-1, 1, -1, -1}, {-1, 0, + 4, -1}, {-1, 1, 0, -1}, {-1, 0, -1, 0}, {-1, 1, -1, 4}, {-1, 0, 4, + 0}, {-1, 1, 0, 4}, {-1, 1, 0, 3}, {-1, 1, -1, 3}, {-1, 1, 0, + 2}, {-1, 1, -1, 2}, {-1, 1, 0, 1}, {-1, 1, -1, 1}, {-1, 1, 0, + 0}, {-1, 1, -1, 0}, {0, 0, 1, 1}, {0, 0, 0, 1}, {0, 0, -1, 1}, {0, + 0, 1, 0}, {0, 0, -1, 0}, {0, 0, 1, -1}, {0, 0, 0, -1}, {0, + 0, -1, -1}, {-1, 0, 3, 0}, {-1, 0, 2, 0}, {-1, 0, 1, 0}, {-1, 0, + 0, 0}, {-1, 0, 3, -1}, {-1, 0, 2, -1}, {-1, 0, 1, -1}, {-1, 0, + 0, -1}}; +cones25 = {{0, 7, 9, 11}, {0, 6, 9, 11}, {6, 7, 9, 11}, {0, 4, 10, + 12}, {0, 5, 10, 12}, {4, 5, 10, 12}, {0, 4, 7, 15}, {0, 4, 6, + 15}, {4, 6, 7, 15}, {0, 2, 4, 16}, {0, 2, 5, 16}, {2, 4, 5, + 16}, {6, 7, 8, 17}, {7, 8, 9, 17}, {6, 7, 8, 9}, {0, 6, 8, + 17}, {0, 8, 9, 17}, {0, 6, 8, 9}, {0, 6, 7, 17}, {0, 7, 9, + 17}, {0, 6, 7, 18}, {3, 4, 5, 6}, {5, 6, 10, 19}, {4, 5, 6, + 10}, {5, 6, 18, 19}, {0, 4, 6, 10}, {0, 6, 10, 19}, {0, 6, 18, + 19}, {0, 5, 10, 19}, {0, 5, 18, 19}, {7, 11, 13, 20}, {6, 7, 11, + 13}, {7, 13, 15, 20}, {6, 7, 13, 15}, {0, 11, 13, 20}, {0, 6, 11, + 13}, {0, 13, 15, 20}, {0, 6, 13, 15}, {0, 7, 11, 20}, {0, 7, 15, + 20}, {5, 12, 14, 21}, {4, 5, 12, 14}, {5, 14, 16, 21}, {4, 5, 14, + 16}, {0, 4, 12, 14}, {0, 12, 14, 21}, {0, 4, 14, 16}, {0, 14, 16, + 21}, {0, 5, 12, 21}, {0, 5, 16, 21}, {2, 3, 4, 22}, {2, 3, 4, + 5}, {3, 4, 7, 22}, {3, 4, 6, 7}, {0, 2, 4, 22}, {0, 4, 7, 22}, {0, + 2, 3, 22}, {0, 3, 7, 22}, {0, 2, 3, 23}, {1, 2, 5, 24}, {1, 2, + 23, 24}, {0, 2, 5, 24}, {0, 2, 23, 24}, {0, 1, 5, 24}, {0, 1, 23, + 24}, {6, 7, 18, 25}, {3, 6, 7, 25}, {0, 7, 18, 25}, {0, 3, 7, + 25}, {6, 18, 25, 26}, {3, 6, 25, 26}, {0, 18, 25, 26}, {0, 3, 25, + 26}, {6, 18, 26, 27}, {3, 6, 26, 27}, {0, 18, 26, 27}, {0, 3, 26, + 27}, {6, 18, 27, 28}, {3, 6, 27, 28}, {0, 18, 27, 28}, {0, 3, 27, + 28}, {5, 6, 18, 28}, {3, 5, 6, 28}, {0, 5, 18, 28}, {0, 3, 5, + 28}, {2, 3, 23, 29}, {2, 3, 5, 29}, {0, 3, 5, 29}, {0, 3, 23, + 29}, {2, 23, 29, 30}, {2, 5, 29, 30}, {0, 5, 29, 30}, {0, 23, 29, + 30}, {2, 23, 30, 31}, {2, 5, 30, 31}, {0, 5, 30, 31}, {0, 23, 30, + 31}, {2, 23, 31, 32}, {2, 5, 31, 32}, {0, 5, 31, 32}, {0, 23, 31, + 32}, {1, 2, 23, 32}, {1, 2, 5, 32}, {0, 1, 5, 32}, {0, 1, 23, + 32}}; + +-- Investigate cohomology cones +-- fano(4,10): +B = ideal V +S = (coefficientRing ring B)[gens ring B, DegreeRank=>numgens ring B] +B = sub(B,S) +Ext^2(comodule B, S) + -- get x_0*x_1*x_6, x_0*x_5*x_6 + -- remember: allow these to be as negative as desired, rest of the variables must be positive. + -- Still: get a cone in RR^n (n is 7 here). + degs = degrees ring V + for i from 0 to numgens ring V list if (x_0*x_1*x_6)%x_i == 0 then - degs_i else degs_i + + +--------------------------------------------------- +-- remove code below this line (18 May 2019) !!! -- +--------------------------------------------------- + +-- This changes the function from ReflexivePolytopesDB +parseKS String := (str) -> ( + -- result is a List of pairs of strings. + locA := regex("Result:\n", str); + locB := regex("#NF", str); + if locB === null then locB = regex("Exceeded", str); + --if locA === null or locB === null then error "data not in correct Kreuzer-Skarke format"; + firstloc := if locA === null then 0 else locA#0#0 + locA#0#1; + lastloc := if locB === null then #str else locB#0#0; + --firstloc := locA#0#0 + locA#0#1; + --lastloc := locB#0#0; + cys := substring(firstloc, lastloc-firstloc, str); + cys = lines cys; + cys = select(cys, s -> #s > 0); + starts := positions(cys, s -> s#0 != " "); + starts = append(starts, #cys); + for i from 0 to #starts-2 list ( + cys_(starts#i) | " id:" | i | "\n" | demark("\n", cys_{starts#i+1 .. starts#(i+1)-1}) + ) + ) + +-- expect that str is something like: +str = ///4 5 M:53 5 N:9 5 H:3,43 [-80] id:0 + 1 0 2 4 -10 + 0 1 3 5 -9 + 0 0 4 0 -4 + 0 0 0 8 -8 + /// + +matrixFromKS = method() +matrixFromKS String := (str) -> ( + matrixFromString concatenate between("\n", drop(lines str, 1)) + ) + +matrixFromKSEntry = method() +matrixFromKSEntry String := (str) -> ( + matrixFromString concatenate between("\n", drop(lines str, 1)) + ) + +/// + assert(matrixFromKS str == matrix {{1, 0, 2, 4, -10}, {0, 1, 3, 5, -9}, {0, 0, 4, 0, -4}, {0, 0, 0, 8, -8}}) +/// + + diff --git a/CYToolsM2/StringTorics/CYPolytope.m2 b/CYToolsM2/StringTorics/CYPolytope.m2 new file mode 100644 index 0000000..d3d24b5 --- /dev/null +++ b/CYToolsM2/StringTorics/CYPolytope.m2 @@ -0,0 +1,455 @@ +--------------------------------------- +-- CYPolytope --------------------- +--------------------------------------- +-- This type can be written to disk, and tries to retain computations computed already. +-- It does not retain Polyhedron objects, but hopefully it recreates these quickly. +-- + +CYPolytopeFields = { + "rays" => {value, toString, List} + } + +-- These are the cache fields that we write to a string via 'dump' +CYPolytopeCache = { + -- these fields do not need to exist. + "face dimensions" => {value, toString, List}, + "id" => {value, toString, ZZ}, + "favorable" => {value, toString, Boolean}, + "h11" => {value, toString, ZZ}, + "h21" => {value, toString, ZZ}, + "basis indices" => {value, toString, List}, + "glsm" => {value, toString, List}, + "annotated faces" => {value, toString, List}, + "automorphisms" => {value, toString, List}, + "autPermutations" => {value, toString, List}, + "triangulations" => {value, toString, List} + } + +cyPolytope = method(Options => {ID => null, InteriorFacets => false}) + +-- This is the main creation function. Other functions call this. +-- Goal: this function does NOT change vertices list +-- TODO: currently it is NOT this! + +-- vertices: A list of the integer coordinates (also a list) +cyPolytope List := CYPolytope => opts -> vertices -> ( + cyPolytope(transpose matrix vertices, opts) + ) + +cyPolytope Polyhedron := opts -> P2 -> ( + topdim := if opts.InteriorFacets then dim P2 - 1 else dim P2 - 2; + LP := latticePointList P2; + LPdim := for lp in LP list dim(P2, minimalFace(P2, lp)); + -- now remove the ones that are in facets (or the origin): + LP = for i from 0 to #LP-1 list if LPdim#i <= topdim then LP#i else continue; + LPdim = for i from 0 to #LP-1 list if LPdim#i <= topdim then LPdim#i else continue; + cyData := new CYPolytope from { + symbol cache => new CacheTable, + "rays" => LP, + }; + cyData.cache#"face dimensions" = LPdim; + if opts.ID =!= null then cyData.cache#"id" = opts.ID; + cyData + ) + +-- This version contains ALL lattice points +-- cyPolytope Polyhedron := opts -> P2 -> ( +-- LP := latticePointList P2; +-- LPdim := for lp in LP list dim(P2, minimalFace(P2, lp)); +-- -- now remove the ones that are in facets (or the origin): +-- LP = for i from 0 to #LP-1 list if LPdim#i <= 3 then LP#i else continue; +-- LPdim = for i from 0 to #LP-1 list if LPdim#i <= 3 then LPdim#i else continue; +-- cyData := new CYPolytope from { +-- symbol cache => new CacheTable, +-- "rays" => LP, +-- }; +-- cyData.cache#"face dimensions" = LPdim; +-- if opts.ID =!= null then cyData.cache#"id" = opts.ID; +-- cyData +-- ) + +-- vertices: Matrix whose columns are the vertices of the reflexive polytope. +cyPolytope Matrix := CYPolytope => opts -> vertices -> ( + P2 := convexHull vertices; + cyPolytope(P2, opts) + ) +cyPolytope KSEntry := CYPolytope => opts -> tope -> ( + -- KSEntry is a Kreuzer-Skarke polytope entry, returned from + -- ReflexivePolytopesDB functions. + P1 := convexHull matrix tope; + P2 := polar P1; + cyPolytope(P2, opts) + ) + +cyPolytope String := CYPolytope => opts -> str -> ( + L := lines str; + if L#0 != "CYPolytopeData" then error "string is not in proper format"; + fields := hashTable for i from 1 to #L-1 list getKeyPair L#i; + -- First get the main elements (these are required!): + required := for field in CYPolytopeFields list ( + k := field#0; + readFcn := field#1#0; + if fields#?k then k => readFcn fields#k else error("expected key "|k) + ); + cyData := new CYPolytope from prepend(symbol cache => new CacheTable, required); + -- now read in the cache values (including "id" value, if any) + for field in CYPolytopeCache do ( + k := field#0; + readFcn := field#1#0; + if fields#?k then cyData.cache#k = readFcn fields#k; + ); + if opts.ID =!= null then cyData.cache#"id" = opts.ID; -- just for compatibility with other constructors... + cyData + ) + +-- todo: translation function: {1, 2, 3, 6} ==> "1 2 3 6" (and viceversa) +-- todo: translation function: {{1,3},{4,7},{6,7,8}} ==> "1 3;4 7;6 7 8;" or "1 3;4 7;6 7 8" (white space is not relevant after or before a ;) +-- Format +-- CYPolytope +-- rays: 1 0 0; 1 0 -1; 1 1 1 +-- face dimensions: 0 0 0 +-- id: 12 +-- favorable: true +-- h11: 5 +-- h21: 20 +-- basis indices: 0 1 2 3 +-- glsm: 1 1 1; 1 2 3 + +-- Then need to be able to set fields +-- +-- Need a isWellFormed function. Checks that the correct fields are +-- present, and the lengths of the various integer vectors and lists +-- are compatible. + +dump CYPolytope := String => {} >> opts -> (Q) -> ( + s1 := "CYPolytopeData\n"; + strs := for field in CYPolytopeFields list ( + k := field#0; + writerFunction := field#1#1; + if not Q#?k then error("expected key: "|k#0); + " " | k | ":" | writerFunction(Q#k) | "\n" + ); + strs2 := for field in CYPolytopeCache list ( + k := field#0; + writerFunction := field#1#1; + if not Q.cache#?k then continue; + " " | k | ":" | writerFunction(Q.cache#k) | "\n" + ); + strs = join({s1}, strs, strs2); + concatenate strs + ) + +getKeyPair = method() +getKeyPair String := Sequence => str -> ( + str1 := replace("^ *", "", str); + result := separate(" *: *", str1); -- separate at colon, ignoring white space around colon. + if #result != 2 then error("expected a key and a value for "|str); + toSequence result + ) + +findTwoFaceInteriorDivisors = method() +findTwoFaceInteriorDivisors CYPolytope := List => Q -> ( + -- returns a list of: + -- {i, {g, ind}} + -- {i:nonfavorable divisor index, {g:genus of 2-face, ind:index of 2-face in annotatedFaces Q}} + A := annotatedFaces Q; + on1skeleton := set sort unique flatten for x in A list if x#0 <= 1 then x#2 else continue; + A2 := positions(A, x -> x#0 == 2 and x#3 > 0 and x#4 > 0); + flatten for a in A2 list ( + thisface := A#a; -- note thisface#2 is the list of all lattice point indices on this face. + -- thisface#4 is the genus of this face. + nonfavs := sort toList(set thisface#2 - on1skeleton); + for x in nonfavs list {x, {thisface#4, a}} + ) + ) + +-- choosing basis indices: if any non-favorable rays, try to choose them! +-- then we can simply replace that generator with the g+1 that sum to it. + +findSuitableSet = (setstotry, Z) -> ( + for g in setstotry do if abs det(Z_g) == 1 then return g; + null + ) + +-- This has been subsumed below? +-- computeBasis = method() +-- computeBasis CYPolytope := List => Q -> ( +-- -- first find 2-face interiors with g>0. +-- -- our plan is to find a basis including these, so that we can +-- -- easily just replace them with the divisors of the form (i, j), 0 <= j <= g, for i non-favorable. +-- nonfavsList := findTwoFaceInteriorDivisors Q; +-- nonfavs := for f in nonfavsList list f#0; -- list of indices of non-favorable divisors. +-- M := transpose matrix rays Q; +-- Z := transpose LLL syz M; +-- rest := sort toList(set(0..numcols Z-1) - set nonfavs); +-- setstotry := for f in subsets(rest, numrows Z - #nonfavs) list (f | nonfavs); -- really want to do these 1 by 1...? +-- good := findSuitableSet(setstotry, Z); +-- if good === null then error "rats: cannot find basis set including all the non-favorables"; +-- H := hashTable nonfavsList; +-- flatten for i in good list if not H#?i then i else ( +-- g := H#i#0; -- genus of the 2-face +-- for j from 0 to g list (i,j) +-- ) +-- ) + +cySetGLSM = method() +-- Delete this version? +-- cySetGLSM CYPolytope := (cyData) -> ( +-- if cyData.cache#?"glsm" then return; +-- mLP := transpose matrix cyData#"rays"; +-- D := transpose syz mLP; +-- p := findFirstUnitVectors D; -- TODO: p,q computation can be slow! +-- q := findInvertibleSubmatrix(D, p); +-- if q === null then error ("oops, can't find a good GLSM matrix"); -- hasn't happened yet. HAS NOW!! +-- GLSM := (D_q)^-1 * D; +-- cyData.cache#"glsm" = entries transpose GLSM; +-- cyData.cache#"basis indices" = q +-- ) +cySetGLSM CYPolytope := Q -> ( + if Q.cache#?"glsm" then return; + mLP := transpose matrix rays Q; + D := transpose syz mLP; -- use LLL? + -- D := transpose LLL syz M; -- which line should we use? + nonfavsList := findTwoFaceInteriorDivisors Q; + -- TODO: should nonfavsList be stashed into Q? + nonfavs := for f in nonfavsList list f#0; -- list of indices of non-favorable divisors. + rest := sort toList(set(0..numcols D-1) - set nonfavs); + setstotry := for f in subsets(rest, numrows D - #nonfavs) list (f | nonfavs); -- really want to do these 1 by 1...? + good := findSuitableSet(setstotry, D); + if good === null then error "rats: cannot find basis set including all the non-favorables"; + H := hashTable nonfavsList; + basind := flatten for i in good list if not H#?i then i else ( + g := H#i#0; -- genus of the 2-face + for j from 0 to g list (i,j) + ); + GLSM := (D_good)^-1 * D; + Q.cache#"basis indices" = basind; + Q.cache#"toric basis indices" = good; + Q.cache#"glsm" = entries transpose GLSM; + ) + +cySetH11H21 = cyData -> ( + -- this version is only for CY 3-fold hypersurfaces... + -- P:ReflexivePolytope + -- P := polytope cyData; + A := annotatedFaces cyData; -- polytope on N side. + A0 := for x in A list if x#0 == 0 then drop(x,1) else continue; -- annotatedFaces(0, P); + A1 := for x in A list if x#0 == 1 then drop(x,1) else continue; -- annotatedFaces(1, P); + A2 := for x in A list if x#0 == 2 then drop(x,1) else continue; -- annotatedFaces(2, P); + A3 := for x in A list if x#0 == 3 then drop(x,1) else continue; -- annotatedFaces(3, P); + npM := A/(x -> x#4)//sum + 1; + npN := A/(x -> x#3)//sum; -- origin is included in the dim 4 face. + -- points in facets (on M side) -- this is part of h21 + -- points in facets (on N side) -- this is part of h11 + facetInteriorsM := A0/(v -> v#3)//sum; + facetInteriorsN := A3/(v -> v#2)//sum; + -- points interior to 2-faces (times their genus) (on M-side) + -- points interior to 2-faces (times their genus) (on N-side) + twoFacesM := A1/(v -> v#2 * v#3)//sum; + twoFacesN := A2/(v -> v#2 * v#3)//sum; + -- now set the h11, h21. + h11 := npN - 5 - facetInteriorsN + twoFacesN; + h21 := npM - 5 - facetInteriorsM + twoFacesM; + cyData.cache#"h11" = h11; + cyData.cache#"h21" = h21; + cyData.cache#"favorable" = (twoFacesN == 0); + (h11, h21) + ) + +rays CYPolytope := List => cyData -> cyData#"rays" +dim CYPolytope := List => cyData -> dim polytope(cyData, "N") +degrees CYPolytope := List => cyData -> ( + if not cyData.cache#?"glsm" then cySetGLSM cyData; + cyData.cache#"glsm" + ) +basisIndices = method() +basisIndices CYPolytope := List => cyData -> ( + if not cyData.cache#?"basis indices" then cySetGLSM cyData; + cyData.cache#"basis indices" + ) +-- h11OfCY CYPolytope := ZZ => cyData -> ( +-- if not cyData.cache#?"h11" then cySetH11H21 cyData; +-- cyData.cache#"h11" +-- ) +-- h21OfCY CYPolytope := ZZ => cyData -> ( +-- if not cyData.cache#?"h21" then cySetH11H21 cyData; +-- cyData.cache#"h21" +-- ) +isFavorable CYPolytope := Boolean => cyData -> ( + if not cyData.cache#?"favorable" then cySetH11H21 cyData; + cyData.cache#"favorable" + ) +annotatedFaces CYPolytope := cyData -> ( + if not cyData.cache#?"annotated faces" then + cyData.cache#"annotated faces" = annotatedFaces polytope(cyData, "N"); + cyData.cache#"annotated faces" + ) +polytope(CYPolytope, String) := Polyhedron => (cyData, which) -> ( + if which === "N" then ( + if not cyData.cache#?"N polytope" then ( + LP := cyData#"rays"; + LPdim := cyData.cache#"face dimensions"; + verts := for i from 0 to #LP - 1 list if LPdim#0 == 0 then LP#i else continue; + cyData.cache#"N polytope" = convexHull transpose matrix verts + ); + cyData.cache#"N polytope" + ) + else if which === "M" then ( + if not cyData.cache#?"M polytope" then ( + cyData.cache#"M polytope" = polar polytope(cyData, "N"); + ); + cyData.cache#"M polytope" + ) + else + error "expected second argument to be either \"M\" or \"N\"" + ) +polytope CYPolytope := Polyhedron => cyData -> polytope(cyData, "N") + +polar CYPolytope := cyData -> cyPolytope polytope(cyData, "M") + +findAllFRSTs CYPolytope := List => cyData -> ( + if not cyData.cache#?"triangulations" then + cyData.cache#"triangulations" = (findAllFRSTs(transpose matrix rays cyData))/last; + cyData.cache#"triangulations" + ) + +normalizeByAutomorphisms = method() +normalizeByAutomorphisms(List, List) := (gPerms, T) -> ( + -- gPerms should be a list of permutations of 0..#rays-1, for a CYPolytoe Q. + -- T should be a list of list of integer indices into the rays of Q. + first sort for g in gPerms list ( + sort for t in T list sort g_t + ) + ) + +findAllCYs = method(Options => {Ring => null, NTFE => true, Automorphisms => true}) -- opts.Ring: ZZ[h11 variables]. +findAllCYs CYPolytope := List => opts -> Q -> ( + Ts := findAllFRSTs Q; + RZ := if opts#Ring === null then ( + a := getSymbol "a"; + h11 := hh^(1,1) Q; + ZZ[a_1 .. a_h11] + ) + else ( + opts#Ring + ); + Xs := for i from 0 to #Ts - 1 list cyData(Q, Ts#i, Ring => RZ); -- we set the ID below. + -- If NTFE and UseAutomorphisms: + gPerms := if opts.Automorphisms then + automorphismsAsPermutations Q + else + {splice{0..#rays Q - 1}}; -- only the identity permutation + -- f is the function we use to partition the Xs. + f := if opts.NTFE then + (X -> normalizeByAutomorphisms(gPerms, restrictTriangulation(2, X))) + else + (X -> normalizeByAutomorphisms(gPerms, max X)); + H := partition(f, Xs); + count := 0; + Xs = for k in keys H list ( + X := H#k#0; -- take the first one + X.cache#"id" = count; + count = count+1; + X); + Xs + ) + +hh(Sequence, CYPolytope) := (pq, Q) -> ( + cySetH11H21 Q; + (p,q) := pq; + if p > q then (p, q) = (q, p); + if p == 0 then ( + if q == 3 or q == 0 then 1 else 0 + ) + else if p == 1 then ( + if q == 1 then Q.cache#"h11" + else if q == 2 then Q.cache#"h21" + else 0 + ) + else if p == 2 then ( + if q == 2 then Q.cache#"h11" else 0 + ) + else if p == 3 then ( + if q == 3 then 1 + else 0 + ) + ) + + +isomorphisms(CYPolytope, CYPolytope) := (P, Q) -> ( + isomorphisms(polytope P, polytope Q, annotatedFaces P, annotatedFaces Q) + ) + +automorphisms CYPolytope := Q -> ( + if not Q.cache#?"automorphisms" then Q.cache#"automorphisms" = ( + P := polytope(Q, "N"); + auts := isomorphisms(Q, Q); + sort for x in auts list entries x + ); + Q.cache#"automorphisms" + ) + +automorphismsAsPermutations = method() +automorphismsAsPermutations CYPolytope := Q -> ( + if not Q.cache#?"autPermutations" then Q.cache#"autPermutations" = ( + G := automorphisms Q; + raysQ := rays Q; + raysMatrices := for v in rays Q list transpose matrix {v}; + raysHash := hashTable for i from 0 to #raysMatrices - 1 list raysMatrices#i => i; + for g in G list ( + m := matrix g; + for v in raysMatrices list raysHash#(m * v) + ) + ); + Q.cache#"autPermutations" + ) + + -- nrows := numrows vertexMatrix P; + -- if nrows != dim P or nrows != dim Q or nrows != numrows vertexMatrix Q + -- then error "expected polytoeps to be full dimensional and same dimension"; + + -- -- Step 1. Find a facet of P with the smallest size. + -- annCYP := annotatedFaces CYP; + -- facetsP := for f in annCYP list if f#0 != nrows-1 then continue else f#1; + -- minsizeP := facetsP/length//min; + -- facetsMinsizeP := select(facetsP, f -> #f === minsizeP); + -- facetA := first facetsMinsizeP; + + -- -- Step 2. Find all facets of Q with this smallest size minsizeP, or return {}. + -- annCYQ := annotatedFaces CYQ; + -- facetsQ := for f in annCYQ list if f#0 != nrows-1 then continue else f#1; + -- minsizeQ := facetsQ/length//min; + -- if minsizeQ =!= minsizeP then ( + -- error "debug me"; + -- return {}; + -- ); + -- facetsMinsizeQ := select(facetsQ, f -> #f === minsizeP); + + -- -- Now find a subset of nrows elements if facetA which are full dimensional + -- -- TODO: don't assume facetA is norws! + -- if #facetA > nrows then ( + -- -- we need to take a subset of these of size nrows that have full rank. + -- -- we then call these facetA again. We don't actually need facetA again, + -- -- the only thing we use is Ainv. + -- C := ((vertexMatrix P)_facetA) ** QQ; + -- facetA = facetA _ (columnRankProfile mutableMatrix C); + -- if #facetA != nrows then error "my logic is missing a case"; + -- ); + -- A := (vertexMatrix P)_facetA; + -- Ainv := (A ** QQ)^-1; + + -- -- now we loop through all possible maps from facetA to other facets, + -- -- and if it gives an integer matrix, we add it to the list. + -- vertsP := (vertexList P)/(v -> transpose matrix {v}); + -- vertsQ := (vertexList Q)/(v -> transpose matrix {v}); + -- hashQ := hashTable for i from 0 to #vertsQ-1 list vertsQ#i => i; + -- elapsedTime isos := flatten for f in facetsMinsizeQ list ( + -- for perm in partialPermutations(f, nrows) list ( + -- B := (vertexMatrix Q)_perm; + -- M := B * Ainv; + -- try (M = lift(M, ZZ)) else continue; + -- if all(vertsP, v -> hashQ#?(M * v)) then M else continue + -- ) + -- ); + -- return isos; + -- ) diff --git a/CYToolsM2/StringTorics/CYTools.m2 b/CYToolsM2/StringTorics/CYTools.m2 new file mode 100644 index 0000000..398e5bb --- /dev/null +++ b/CYToolsM2/StringTorics/CYTools.m2 @@ -0,0 +1,415 @@ +-- In this file, we have code to interface with CYTools as well as the CYTools databases for +-- e.g. CY3's with h11=4. + +CYFromCYToolsDB = new Type of HashTable +cyFromCYToolsDB = method() +cyFromCYToolsDB(String, Sequence, Ring) := (DB, lab, RZ) -> ( + -- DIR should be a directory where to find the files containing computed info. + result := new CYToolsCY3 from { + "Directory" => DB, + "Label" => lab, + cache => new CacheTable + }; + result.cache.PicardRing = RZ; + result + ) + +getCYFilePrefix = method() +getCYFilePrefix CYToolsCY3 := X -> ( + (h21,polynum,cynum) := label X; + nm := X#"Directory" | "h21_"|h21|"/poly_"|polynum|"/CY_"|cynum + ) + +getPolytopeFilePrefix = method() +getPolytopeFilePrefix CYToolsCY3 := X -> ( + (h21,polynum,cynum) := label X; + nm := X#"Directory" | "h21_"|h21|"/poly_"|polynum + ) + +findH21s = DIR -> ( + names := select(readDirectory DIR, s -> match("h21_", s)); + sort for n in names list (m := regex("h21_([0-9]+)", n); value substring(m_1, n)) + ) +findPolys = (DIR, h12) -> ( + DIRNAME := DIR | "h21_" | h12 | "/"; + names := select(readDirectory DIRNAME, s -> match("poly_", s)); + sort for n in names list (m := regex("poly_([0-9]+)", n); value substring(m_1, n)) + ) +findCYs = (DIR, h12, polyid) -> ( + DIRNAME := DIR | "h21_" | h12 | "/poly_" | polyid | "/" ; + --print DIRNAME; + --print readDirectory DIRNAME; + names := select(readDirectory DIRNAME, s -> match("CY_", s)); + sort for n in names list (m := regex("CY_([0-9]+)", n); value substring(m_1, n)) + ) + +findAllCYToolsCY3s = method() +findAllCYToolsCY3s(String, Ring) := (DB, RZ) -> ( + -- RZ must be a ring over ZZ with #vars being h11 of the CY. + -- all of these are expected to have the same h11. + hashTable flatten flatten for h21 in findH21s DB list + for pol in findPolys(DB, h21) list + for cy in findCYs(DB, h21, pol) list + (h21, pol, cy) => cyFromCYToolsDB(DB, (h21, pol, cy), RZ) + ) + +label CYToolsCY3 := X -> X#"Label" + +picardRing CYToolsCY3 := X -> X.cache.PicardRing + +hh(Sequence, CYToolsCY3) := (pq, X) -> ( + lab := label X; + if pq === (1,1) then + numgens picardRing X + else if pq === (1,2) or pq === (2,1) then + lab#0 + else + error "hh only implemented for hh^(1,1) and hh^(1,2), hh^(2,1)" + ) + +c2Form CYToolsCY3 := X -> ( + filename := (getCYFilePrefix X) | "/c2.dat"; + if not fileExists filename then error "c2.dat doesn't exist for this CY"; + coeffs := value get filename; -- format is one line, with e.g. [28, 12, 10, -6] + RZ := picardRing X; + sum for i from 0 to numgens RZ - 1 list coeffs#i * RZ_i + ) + + +cubicForm CYToolsCY3 := X -> ( + filename := (getCYFilePrefix X) | "/IntersectionVariety.dat"; + if not fileExists filename then error "IntersectionVariety.dat doesn't exist for this CY"; + use picardRing X; + value get filename -- result is a polynomial + ) + +isFavorable CYToolsCY3 := X -> ( + filename := (getPolytopeFilePrefix X) | "/favorable.dat"; + if not fileExists filename then error "favorable.dat doesn't exist for this CY"; + contents := get filename; + if match("True", contents) then true + else if match("False", contents) then false + else error "cannot parse data in favorable.dat" + ) + +-- TODO: should we keep this? Problem: some of the database files have it, some don't +-- isToric = method() +-- isToric CYToolsCY3 := X -> ( +-- filename := (getCYFilePrefix X) | "/toric.dat"; +-- if not fileExists filename then error "toric.dat doesn't exist for this CY"; +-- contents := get filename; +-- if match("True", contents) then true +-- else if match("False", contents) then false +-- else error "cannot parse data in toric.dat" +-- ) + +invariantsAll CYToolsCY3 := X -> invariantsAll(c2Form X, cubicForm X, hh^(1,1) X, hh^(1,2) X) +invariantsAllX CYToolsCY3 := X -> invariantsAll(c2Form X, cubicForm X, hh^(1,1) X, hh^(1,2) X) + +hasGVInvariants = method() +hasGVInvariants CYToolsCY3 := X -> ( + filename := (getCYFilePrefix X) | "/GVs.dat"; + fileExists filename + ) + +gvInvariants CYToolsCY3 := optsUnused -> X -> ( + -- this just grabs the ones that are in the data base. + filename := (getCYFilePrefix X) | "/GVs.dat"; + if not fileExists filename then error "GVs.dat doesn't exist for this CY"; + Ls := lines get filename; + Ls/value/(x -> toList drop(x, -1) => x#-1)//hashTable + ) + +partitionGVConeByGV CYToolsCY3 := HashTable => opts -> X -> ( + -- return null if we cannot computr GV invariants (i.e. if non-favorable). + if not hasGVInvariants X then return null; + gv := gvInvariants(X, opts); -- TODO: stash this? + C := posHull transpose matrix ((keys gv)/toList); + gvX := entries transpose rays C; + partition(f -> if gv#?(toSequence f) then gv#(toSequence f) else 0, gvX) + ) + +heft CYToolsCY3 := List => X -> ( + filename := (getCYFilePrefix X) | "/gradingVec.dat"; + if not fileExists filename then error "gradingVec.dat doesn't exist for this CY"; + contents := get filename; + contents = replace("\\[ +", "[", contents); + toList value replace(" +", ",",contents) + ) + +gvInvariantsAndCone(CYToolsCY3, ZZ) := Sequence => opts -> (X, D) -> ( + -- D is the degree bound to start with. We could start with 5, or DegreeLimit/2 or DegreeLimit/4, or ... + -- returns a hash table of computed GV invariants, and the cone generated by all curves with nonzero GV invariant. + if not hasGVInvariants X then return null; + degvec := heft X; + gv := gvInvariants(X, opts); + keysgv := keys gv; + H := hashTable for k in keysgv list k => dotProduct(k, degvec); + firstSet := select(keys H, k -> H#k <= D); + if debugLevel > 0 then << "The number of curves in the first set: " << #firstSet << endl; + C := posHull transpose matrix (firstSet); + Cdual := dualCone C; + HC := transpose rays Cdual; + curves := for k in keys H list if H#k > D and H#k <= opts.DegreeLimit then transpose matrix {k} else continue; + set2 := select(curves, c -> any(flatten entries (HC * c), a -> a < 0)); + if debugLevel > 0 then << "The number of curves not in the first cone: " << #set2 << endl; + C2 := if #set2 == 0 then C else posHull (rays C | matrix{set2}); + if debugLevel > 0 and #set2 == 0 then ( + << "CY " << label X << " C = " << rays C << endl + ) + else + << "*differs* CY " << label X << " C1 = " << rays C << " and C2 = " << rays C2 << endl; + (gv, C2) + ) + +partitionGVConeByGV(CYToolsCY3, ZZ) := HashTable => opts -> (X, D) -> ( + -- return null if we cannot compute GV invariants (i.e. if non-favorable). + if not hasGVInvariants X then return null; + (gv, C) := gvInvariantsAndCone(X, D, opts); + gvX := entries transpose rays C; + partition(f -> if gv#?f then gv#f else 0, gvX) + ) + +partitionGVConeByGV(CYToolsCY3) := HashTable => opts -> (X) -> ( + -- return null if we cannot computr GV invariants (i.e. if non-favorable). + if not hasGVInvariants X then return null; + deg := opts.DegreeLimit; + D := if deg <= 10 then deg else D = 10; + (gv, C) := gvInvariantsAndCone(X, D, opts); + gvX := entries transpose rays C; + partition(f -> if gv#?f then gv#f else 0, gvX) + ) + +moriConeCap = method() +moriConeCap CYToolsCY3 := Cone => X -> ( + -- the columns are the extremal rays of the cone + filename := (getCYFilePrefix X) | "/mori_gens.dat"; + if not fileExists filename then return "mori_gens.dat doesn't exist for this CY"; + contents := get filename; + contents = replace("\\[ +", "[", contents); + contents = replace(" *\\] *", "]", contents); + contents = replace(" +", ",",contents); + mori := (lines contents)/value/toList; + posHull transpose matrix mori + ) + +rays CYToolsCY3 := List => X -> ( + filename := (getPolytopeFilePrefix X) | "/points.dat"; + if not fileExists filename then return "points.dat doesn't exist for this CY"; + rys := (lines get filename)/value/toList; -- format: one ray per line (with comma between values), first one is origin + if not all(rys#0, a -> a == 0) then error "my logic is wrong: the first element should be the origin"; + drop(rys, 1) --remove the origin. + ) + +max CYToolsCY3 := List => X -> ( + filename := (getCYFilePrefix X) | "/simplices.dat"; + if not fileExists filename then return "simplices.dat doesn't exist for this CY"; + rys := (lines get filename)/value/toList; -- format: one ray per line (with comma between values), first one is origin + rys + ) + +basisIndices CYToolsCY3 := List => X -> ( + filename := (getPolytopeFilePrefix X) | "/basis.dat"; + if not fileExists filename then return "basis.dat doesn't exist for this CY"; + basIndices := toList value get filename; -- format: one ray per line (with comma between values), first one is origin + basIndices + ) + +cyPolytope CYToolsCY3 := opts -> X -> ( + pts := rays X; + P2 := convexHull transpose matrix pts; + Q := cyPolytope(P2, ID => (label X)_1); + X.cache.CYPolytope = Q; + --assert(hh^(1,1) X == hh^(1,1) Q); + --assert(hh^(1,2) X == hh^(1,2) Q); + Q + ) + +/// +-- Let's try this +-* + restart + debug needsPackage "StringTorics" + needs "CYTools.m2" +*- + DB = "~/Dropbox/Collaboration/Physics-Liam/Inequivalent CYs/h11_4Toric/" + RZ = ZZ[x0,x1,x2,x3] -- these much match what is in the file in the DB + Xs = findAllCYToolsCY3s(DB, RZ); + #keys Xs == 1760 + picardRing Xs#(60,155,0) + X = Xs#(60,155,0) + assert(label X === (60, 155, 0)) + assert(hh^(1,1) X == 4) + assert(hh^(1,2) X == 60) + getCYFilePrefix X + getPolytopeFilePrefix X + c2Form X + cubicForm X + moriConeCap X + gvCone(X, 5) + moriConeCap X + oo == ooo + + --gvInvariants X + --gvcone = posHull transpose matrix keys oo -- takes a while. + --rays gvcone + + allXs = sort keys Xs + --allXs = torsionfrees -- these are the ones we consider + allT = topologySet(allXs, Xs); + info allT -- 2014 possibly different topologies + + allT1 = combineIfSame(allT, X -> (c2Form X, cubicForm X)) + + identicals = sort first for x in allT1#"Sets" list ( + for x1 in x list if #x1 > 1 then x1 else continue + ) + + info allT1 + + elapsedTime allT2 = separateIfDifferent(allT1, invariantsAllX) -- 260 seconds + info allT2 + allT2#"Sets"/length//tally + select( allT2#"Sets", x -> length x == 2)/sort//sort + X = Xs#(94, 804, 0) + gvs = elapsedTime gvInvariants X; + #gvs + elapsedTime posHull transpose matrix keys gvs + rays oo + + actionable = select(allT2#"Sets", x -> #x > 1); + actionable#0 -- {{(68, 397, 0)}, {(68, 353, 0)}, {(68, 393, 0)}, {(68, 350, 1)}} + actionable#1 + combineListByGV(actionable#0, Xs) + + X = Xs#(68,397,0) + + gvs = gvInvariants X; + #gvs + degvec = heft X + tally for v in keys gvs list dotProduct(v, degvec) + select(keys gvs, v -> dotProduct(v, degvec) <= 2) + C2 = posHull transpose matrix oo + rays C2 + dim C2 + HC = transpose rays dualCone C2; + M = transpose matrix keys gvs; + HC * M + C = elapsedTime posHull transpose matrix keys gvs; -- ouch. + + X = Xs#(68,353,0) + X = Xs#(68, 393, 0) + X = Xs#(68, 350, 1) + + gvs = gvInvariants X; + #gvs + degvec = heft X + tally for v in keys gvs list dotProduct(v, degvec) + select(keys gvs, v -> dotProduct(v, degvec) <= 2) + C2 = posHull transpose matrix oo + dim C2 == 4 -- at least full dimensional + rays C2 + HC = transpose rays dualCone C2 + min flatten entries (HC * transpose matrix keys gvs) == 0 + + gvcone = (X, degbound) -> ( + degvec := heft X; + gvs := gvInvariants X; + gv1 := select(keys gvs, v -> dotProduct(v, degvec) <= degbound); + M := transpose matrix gv1; + C := posHull M; + if dim C < 4 then << "dim C is " << dim C << endl; + HC := transpose rays dualCone C; + minval := min flatten entries (HC * transpose matrix keys gvs); + if minval < 0 then + << "CY " << label X << " need to go higher in degree" << endl; + (rays C, minval) + ) + + gvcone(Xs#(68, 353, 0), 2) + gvcone(Xs#(68, 353, 0), 4) + + for lab in flatten {{(40, 9, 0)}, {(40, 7, 0)}, {(40, 9, 1)}, {(40, 9, 2)}} list + gvcone(Xs#lab, 2) + + for a in actionable list + for lab in flatten a list (ans := gvcone(Xs#lab, 2); print (a => ans); a => ans) + netList actionable + + gvcone(Xs#(86, 712, 0), 5) + + info allT2 + allT2#"Sets"/length//tally + select(allT2#"Sets", x -> #x == 14) + + set52 = set {(52, 28, 0), + (52, 28, 1), + (52, 28, 2), + (52, 29, 0), + (52, 31, 0), + (52, 31, 1), + (52, 37, 0), + (52, 37, 1), + (52, 37, 2), + (52, 40, 0), + (52, 42, 0), + (52, 42, 1), + (52, 42, 2), + (52, 42, 3)} + +for x in allT2#"Sets" list if (set flatten x) * set52 =!= set {} then x + +for lab in allXs list ( + if any(values gvInvariants Xs#lab, a -> instance(a, RR)) then (print lab; lab) else continue + ) + + << "doing " << lab << endl; c := gvcone(Xs#lab, 2); << c << endl << endl; c); +for lab in allXs list (<< "doing " << lab << endl; c := gvcone(Xs#lab, 2); << c << endl << endl; c); + +values gvInvariants Xs#(56, 77, 0); + +gvOK = for lab in sort toList (set allXs - set {(56, 77, 0), (64, 248, 0), (64, 266, 0), (66, 319, 0), (68, 394, 0), (68, 394, 1), (86, 705, 0), (86, 712, 0), (86, 712, 1), (94, 870, 0), (94, 874, 0), (102, 995, 0), (102, 995, 1), (118, 1109, 0)}) list lab + +GV2 = for lab in gvOK list (<< "doing " << lab << endl; c := gvcone(Xs#lab, 2); << c << endl << endl; c); +GV5 = for i from 0 to #gvOK-1 list ( + lab := gvOK#i; + if GV2#i#1 >= 0 then GV2#i else (c := gvcone(Xs#lab, 5); << c << endl << endl; c) + ) +GV5/(x -> x#1 >= 0)//tally + +GV10 = for i from 0 to #gvOK-1 list ( + lab := gvOK#i; + if GV5#i#1 >= 0 then GV5#i else (c := gvcone(Xs#lab, 10); << c << endl << endl; c) + ); + +GV10/(x -> x#1 >= 0)//tally + +GV15 = for i from 0 to #gvOK-1 list ( + lab := gvOK#i; + if GV10#i#1 >= 0 then GV10#i else (c := gvcone(Xs#lab, 5); << c << endl << endl; c) + ); + +GV15/(x -> x#1 >= 0)//tally + +GV20 = for i from 0 to #gvOK-1 list ( + lab := gvOK#i; + if GV15#i#1 >= 0 then GV15#i else (c := gvcone(Xs#lab, 5); << c << endl << endl; c) + ); + +GV20/(x -> x#1 >= 0)//tally + + lab in gvOK list (<< "doing " << lab << endl; c := gvcone(Xs#lab, 2); << c << endl << endl; c); + +-- Let's create a series of partitioned GV cones: use up to degree D1, compute up to degree D2 > D1. +-- Find cone hyperplanes for those of degree <= D1. Find which of the rays of degree bound <= D2 are not in this cone. +-- Add them, and recompute the cone. +-- After having the cone computed, find the rays, and compute the GV invariants of the smallest point along each ray. + +allXs#0 -- return hashtable: gv value => list of rays. + +allXs = sort keys Xs; +for lab in gvOK list + partitionGVConeByGV(Xs#lab, 5) + +/// + diff --git a/CYToolsM2/StringTorics/CalabiYauInToric.m2 b/CYToolsM2/StringTorics/CalabiYauInToric.m2 new file mode 100644 index 0000000..668cbec --- /dev/null +++ b/CYToolsM2/StringTorics/CalabiYauInToric.m2 @@ -0,0 +1,336 @@ +-------------------------------------------------------------- +-- CalabiYauInToric (soon to change back to CalabiYauInToric? ---------- +-------------------------------------------------------------- + +CalabiYauInToric.synonym = "Calabi-Yau hypersurface in a normal toric variety" +CalabiYauInToric.GlobalAssignHook = globalAssignFunction +CalabiYauInToric.GlobalReleaseHook = globalReleaseFunction +expression CalabiYauInToric := X -> if hasAttribute(X, ReverseDictionary) + then expression toString getAttribute(X, ReverseDictionary) else + (describe X)#0 +net CalabiYauInToric := X -> net expression X +describe CalabiYauInToric := X -> Describe ( + "A Calabi-Yau "|dim X|"-fold hypersurface with h11="|hh^(1,1) X|" and h21="|hh^(1,2) X |" in a "|(dim X + 1)|"-dimensional toric variety" + ) + +CYPolytope.synonym = "Calabi-Yau reflexive polytope" +CYPolytope.GlobalAssignHook = globalAssignFunction +CYPolytope.GlobalReleaseHook = globalReleaseFunction +expression CYPolytope := X -> if hasAttribute (X, ReverseDictionary) + then expression getAttribute (X, ReverseDictionary) else + (describe X)#0 +describe CYPolytope := X -> Describe (expression CYPolytope) ( + expression rays X, expression max X) + + +CYDataFields = { + -- first entry: true means it must exist and be in the main hash table + -- false: it might exist, and is in the cache table. + "polytope data" => {value, Q -> toString Q.cache#"id", CYPolytope}, + "triangulation" => {value, toString, List} + } + +-- These are the cache fields that we write to a string via 'dump' +CYDataCache = { + -- first entry: true means it must exist and be in the main hash table + -- false: it might exist, and is in the cache table. + "id" => {value, toString, ZZ}, + "c2" => {value, toString, List}, + "intersection numbers" => {value, toString, List}, + "toric intersection numbers" => {value, toString, List}, + "toric mori cone cap" => {value, toString, List} + } + +setCYIntersectionRing = (X, R) -> ( + -- X is a CalabiYauInToric + -- R is a polynomial ring, or null (if not, an error is raised). + n := hh^(1,1) X; + if R =!= null then ( + if not instance(R, PolynomialRing) or numgens R != n then + error ("expected polynomial ring with "|n|" variables"); + X.cache.PicardRing = R; + ) + else ( + a := getSymbol "a"; + X.cache.PicardRing = ZZ[a_1..a_n]; + ); + ) + +calabiYau = method(Options => {ID => null, Ring => null}) +-- TODO, BUG!! The triang needs to indices in the Q rays. +calabiYau(CYPolytope, List) := CalabiYauInToric => opts -> (Q, triang) -> ( + X := new CalabiYauInToric from { + symbol cache => new CacheTable, + "polytope data" => Q, + "triangulation" => triang + }; + if opts.ID =!= null then X.cache#"id" = opts.ID; + setCYIntersectionRing(X, opts#Ring); + X + ) + +cyData = method(Options => options calabiYau) +cyData(CYPolytope, List) := opts -> (Q, triang) -> calabiYau(Q, triang, opts) + +picardRing = method() +picardRing CalabiYauInToric := X -> X.cache.PicardRing + +cyData(String, Function) := +calabiYau(String, Function) := CalabiYauInToric => opts -> (str, F) -> ( + -- F is a function which takes an id of a CYPolytope and returns the CYPolytope + -- The string is the value taken from a CY database . + L := lines str; + if L#0 != "CYData" then error "string is not in proper format"; + fields := hashTable for i from 1 to #L-1 list getKeyPair L#i; + -- First get the main elements (these are required!): + polytopeid := value fields#"polytope data"; + required := for field in CYDataFields list ( + k := field#0; + if k === "polytope data" then ( + "polytope data" => F polytopeid + ) + else ( + readFcn := field#1#0; + if fields#?k then k => readFcn fields#k else error("expected key "|k) + )); + X := new CalabiYauInToric from prepend(symbol cache => new CacheTable, required); + -- now read in the cache values (including "id" value, if any) + for field in CYDataCache do ( + k := field#0; + readFcn := field#1#0; + if fields#?k then X.cache#k = readFcn fields#k; + ); + if opts.ID =!= null then X.cache#"id" = opts.ID; -- just for compatibility with other constructors... + setCYIntersectionRing(X, opts#Ring); + X + ) + +dump CalabiYauInToric := String => {} >> opts -> X -> ( + s1 := "CYData\n"; + strs := for field in CYDataFields list ( + k := field#0; + writerFunction := field#1#1; + if not X#?k then error("expected key: "|k#0); + " " | k | ":" | writerFunction(X#k) | "\n" + ); + strs2 := for field in CYDataCache list ( + k := field#0; + writerFunction := field#1#1; + if not X.cache#?k then continue; + " " | k | ":" | writerFunction(X.cache#k) | "\n" + ); + strs = join({s1}, strs, strs2); + concatenate strs + ) + +makeCY = method(Options => {ID => null, Ring => null}) +makeCY CYPolytope := CalabiYauInToric => opts -> Q -> ( + P2 := polytope Q; + (LP,tri) := regularStarTriangulation(dim P2-2,P2); + if rays Q =!= LP then error "I have a lattice point mismatch"; + cyData(Q, tri, opts) + ) + +makeCY(List, List) := CalabiYauInToric => opts -> (pts, triangulation) -> ( + -- We keep the translation around? + Q := cyPolytope pts; + -- now we need the translation from old vertices to new. + H := hashTable for i from 0 to #rays Q - 1 list (rays Q)#i => i; + mapping := hashTable for i from 0 to #pts-1 list ( + p := pts#i; + if all(p,a -> a == 0) then continue; -- leave out the origin + if H#?p then i => H#p else + error("lattice point found which is likely interior to a facet: "|(toString p)) + ); + tri := sort for t in triangulation list ( + sort for t1 in drop(t,1) list mapping#t1 + ); + Q.cache#"vertex translation" = mapping; + cyData(Q, tri, opts) + ) + + +normalToricVariety CalabiYauInToric := opts -> X -> ( + if not X.cache.?NormalToricVariety then X.cache.NormalToricVariety = ( + Q := X#"polytope data"; + T := X#"triangulation"; + GLSM := transpose matrix degrees Q; + normalToricVariety(rays Q, T, opts, WeilToClass => matrix GLSM) + ); + X.cache.NormalToricVariety + -- TODO: this fails if the class group is torsion! (Fails: later it gives an inscrutable error...) + ) + +rays CalabiYauInToric := X -> rays cyPolytope X +max CalabiYauInToric := X -> X#"triangulation" + +-- TODO: triangulation is used with 2 different pieces of data: +-- with, without cone point! Change this to use only one point. +-- Also: there are 4 matrices one can imagine: A, A0 (A with origin), Ah, A0h... +-- We need to be consistent about these! +-- TODO: do we really need this? +triangulation CalabiYauInToric := Triangulation => opts -> X -> ( + if not opts.Homogenize then error "Homogenize flag is not used in this method"; + if not X.cache#?"triangulation" then ( + rys := X#"polytope data"#"rays"; + d := #rys#0; + B := (transpose matrix rys) | matrix{d:{0}}; + X.cache#"triangulation" = triangulation(B, for t in X#"triangulation" list append(t, #rys)); -- TODO: BUG?? where is "triangulation" key? In cache?? + ); + X.cache#"triangulation" + ) + +cyPolytope CalabiYauInToric := opts -> X -> X#"polytope data" +dim CalabiYauInToric := X -> dim ambient X - 1 +polytope CalabiYauInToric := X -> polytope cyPolytope X +polytope(CalabiYauInToric, String) := (X, which) -> polytope(cyPolytope X, which) +basisIndices CalabiYauInToric := List => X -> basisIndices cyPolytope X +degrees CalabiYauInToric := List => X -> degrees cyPolytope X + +ambient CalabiYauInToric := X -> normalToricVariety X + +label = method() +label CYPolytope := Q -> if Q.cache#?"id" then Q.cache#"id" else "" +label CalabiYauInToric := X -> (label cyPolytope X, if X.cache#?"id" then X.cache#"id" else "") + +hh(Sequence, CalabiYauInToric) := (pq, X) -> hh^pq cyPolytope X + +isFavorable CalabiYauInToric := Boolean => X -> isFavorable cyPolytope X + +abstractVariety CalabiYauInToric := opts -> X -> ( + -- Store this with X. + V := ambient X; + aX := completeIntersection(V, {-toricDivisor V}); + abstractVariety(aX, base()) + ) +abstractVariety(CalabiYauInToric, AbstractVariety) := opts -> (X, pt) -> ( + -- Store this with X? + -- Check: pt is of dimension zero? + V := ambient X; + aX := completeIntersection(V, {-toricDivisor V}); + abstractVariety(aX, pt) + ) + +-- restrictTriangulation: returns a List of +-- {2-face indices, +-- all indices of points in in this 2-face, +-- the triangles in this 2-face, +-- genus of this face} +-- TODO: need also a function which returns just: triangles, genus information. +restrictTriangulation = method() +restrictTriangulation CalabiYauInToric := List => (X) -> ( + -- given X, we use its annotated faces and its triangulation, to write down the triangulations of the 2-faces + -- of the corresponding reflexive polytope in the N lattice side. + Q := cyPolytope X; + F := annotatedFaces Q; + twofaces := for x in F list if x#0 =!= 2 then continue else {x#1, x#2, x#4}; + T := max X; -- triangulation + for t2 in twofaces list ( + a := set t2#1; -- these are the indices we want. + atri := sort unique for t in T list ( + b := sort toList(a * set t); + if #b == 3 then b else continue + ); + {t2#0, t2#1, atri, t2#2} + ) + ) + +restrictTriangulation(ZZ, CalabiYauInToric) := List => (d, X) -> ( + -- given X, we use its annotated faces and its triangulation, to + -- write down the triangulations of the dim d-faces of the + -- corresponding reflexive polytope in the N lattice side. + Q := cyPolytope X; + F := annotatedFaces Q; + dfaces := for x in F list if x#0 =!= d then continue else x#2; + T := max X; -- triangulation + sort unique flatten for td in dfaces list ( + a := set td; -- these are the indices we want. + atri := sort unique for t in T list ( + b := sort toList(a * set t); + if #b == d+1 then b else continue + ); + atri + ) + ) + +lineBundle(CalabiYauInToric, List) := (X, deg) -> ( + if not all(deg, x -> instance(x, ZZ)) or #deg =!= degreeLength ring ambient X + then error("expected multidegree of length "|degreeLength ring ambient X); + new LineBundle from { + symbol cache => new CacheTable, + symbol variety => X, + symbol degree => deg + } + ) + +degree LineBundle := L -> L.degree +variety LineBundle := L -> L.variety + +installMethod(symbol _, OO, CalabiYauInToric, LineBundle => + (OO,X) -> lineBundle(X, (degree 1_(ring ambient X))) + ) + +LineBundle Sequence := (L, deg) -> ( + lineBundle(variety L, degree L + toList deg) + ) + +equations CalabiYauInToric := List => X -> ( + if not X.cache.?Equations then X.cache.Equations = ( + V := ambient X; + {random(degree(-toricDivisor V), ring V)} -- TODO: (1) allow tuned equations, (2) do the random call more efficiently. + ); + X.cache.Equations + ) + +toricMoriCone = method() +toricMoriConeCap = method() + +setToricMoriConeCap = method() +setToricMoriConeCap(CalabiYauInToric, List) := List => (Y, Xs) -> ( + -- does nothing if Y is not favorable + -- Xs are all of the CY3's equivalent to Y (including Y), but NO others. + --myNTFE := restrictTriangulation Y; + --myXs := select(Xs, X0 -> restrictTriangulation X0 === myNTFE); + if not isFavorable Y then null + else + Y.cache#"toric mori cone cap" = sort entries transpose rays dualCone posHull matrix{for X in Xs list rays dualCone toricMoriCone X} + ) +setToricMoriConeCap CalabiYauInToric := List => Y -> ( + -- Xs are all of the CY3's equivalent to Y (including Y), possibly includes others too? + if not isFavorable Y then return null; + Q := cyPolytope Y; + Xs := findAllCYs(Q, NTFE => false, Automorphisms => false); + myNTFE := restrictTriangulation Y; + myXs := select(Xs, X0 -> restrictTriangulation X0 === myNTFE); + Y.cache#"toric mori cone cap" = sort entries transpose rays dualCone posHull matrix{for X in myXs list rays dualCone toricMoriCone X}; + ) + +toricMoriConeCap CalabiYauInToric := List => Y -> ( + if not isFavorable Y then return null; + if not Y.cache#?"toric mori cone cap" then setToricMoriConeCap Y; + Y.cache#"toric mori cone cap" + ) + +/// + -- Let's test restrictTriangulation, automorphisms and getting only triangulations + -- unique up to linear automorphism of the lattice polytope. + topes = kreuzerSkarke(3, Limit => 20); + topes_15 + tope = KSEntry "4 7 M:74 7 N:8 7 H:3,63 [-120] id:15 + 1 0 0 0 -3 -3 3 + 0 1 1 1 1 -2 -2 + 0 0 3 0 3 0 -6 + 0 0 0 3 -3 -6 6 + " + Q = cyPolytope tope + Xs = findAllCYs Q + #Xs + auts = for e in automorphisms Q list matrix e + rayvecs = for v in rays Q list transpose matrix {v} + rayHash = hashTable for i from 0 to #rayvecs - 1 list rayvecs#i => i + g = auts#0 + perms = for g in auts list + for v in rayvecs list rayHash#(g*v) + sort unique flatten restrictTriangulation(3, Xs#0) + sort for x in oo list sort perms_0_x +/// diff --git a/CYToolsM2/StringTorics/DatabaseCreation.m2 b/CYToolsM2/StringTorics/DatabaseCreation.m2 new file mode 100644 index 0000000..7942f61 --- /dev/null +++ b/CYToolsM2/StringTorics/DatabaseCreation.m2 @@ -0,0 +1,2756 @@ +---------------------------------- +-- Code for creating data bases -- +---------------------------------- +label KSEntry := ZZ => (ks) -> ( + str := toString ks; + ans := regex("id:([0-9]+)", str); + if ans === null or #ans != 2 then + null + else + value substring(str, ans#1#0, ans#1#1) + ) + +hodgeNumbers = method() +hodgeNumbers KSEntry := (ks) -> ( + str := toString ks; + ans := regex("H:([0-9]+),([0-9]+)", str); + if #ans != 3 then error "expected 3 matches"; + (value substring(str, ans#1#0, ans#1#1), + value substring(str, ans#2#0, ans#2#1)) + ) + +combineCYDatabases = method() +combineCYDatabases(Database, Database) := (db1, db2) -> ( + -- appends all keys of db2 to db1 + for k in keys db2 do db1#k = db2#k; + ) +combineCYDatabases(String, String) := (dbname1, dbname2) -> ( + -- appends all keys of db2 to db1 + db1 := openDatabaseOut dbname1; + db2 := openDatabase dbname2; + combineCYDatabases(db1, db2); + close db1; + close db2; + ) +combineCYDatabases List := (dbL) -> ( + -- either all elements are String filename's or are databases. + for i from 1 to #dbL-1 do combineCYDatabases(dbL#0, dbL#i) + ) + +addToCYDatabase = method(Options => {NTFE => true, "CYs" => true}) + +-- This function adds the CYPolytope 'ks' to the database, if it is not there yet. +-- Actually, it only looks at the ID label in the 'ks' entry, not at the polytope itself. +-- Under default conditions, all NTFE triangulations are found, and all corresponding CY's +-- are placed into the data base. +-- This function returns the CYPolytope found or created. +addToCYDatabase(String, KSEntry) := CYPolytope => opts -> (dbfilename, ks) -> ( + lab := label ks; + F := openDatabaseOut dbfilename; + if not F#?(toString lab) then ( + << "computing for polytope " << lab << endl; + Q := cyPolytope(ks, ID => lab); -- note that the polytope data is really that of the dual to topes#i. + -- now fill it with data we want + basisIndices Q; -- compute them + isFavorable Q; -- compute h11, h21, favorability. + annotatedFaces Q; -- compute annotated faces + automorphisms Q; + automorphismsAsPermutations Q; + findAllFRSTs Q; + -- now write it + F#(toString lab) = dump Q; + ) + else ( + Q = cyPolytope F#(toString lab); + ); + close F; + if opts#"CYs" then addToCYDatabase(dbfilename, Q, NTFE => opts.NTFE); + Q + ) + +processCYPolytopes = method() +processCYPolytopes(String, ZZ, Sequence) := (dbfilenamePrefix, h11, lohi) -> ( + elapsedTime topes := kreuzerSkarke(h11, Limit => 200000); + mytopes := take(topes, toList lohi); + dbname := dbfilenamePrefix | "-" | lohi#0 | "-" | lohi#1 | ".dbm"; + elapsedTime createCYDatabase(dbname, mytopes); + ) + +--addToCYDatabase = method(Options => {NTFE => false}) + +-- Delete this older version (which doesn't compute toric mori cone caps) +-- This only adds the CY's coming from Q. +-- addToCYDatabase(String, CYPolytope) := opts -> (dbfilename, Q) -> ( +-- elapsedTime Xs := findAllCYs Q; -- TODO: check: is findALlCYs still correct. +-- << " " << #Xs << " triangulations total" << endl; +-- if opts.NTFE then ( +-- elapsedTime H := partition(restrictTriangulation, Xs); +-- << " " << #(keys H) << " NTFE triangulations" << endl; +-- Xs = (keys H)/(k -> H#k#0); -- only take one triangulation that matches +-- -- let's relabel these Xs +-- ); +-- F := openDatabaseOut dbfilename; +-- for X in Xs do ( +-- computeIntersectionNumbers X; -- this should load all of the data we want +-- F#(toString label X) = dump X; +-- ); +-- close F; +-- ) + +addToCYDatabase(String, CYPolytope) := opts -> (dbfilename, Q) -> ( + -- This version also finds "moriConeCap" which is a cone containing the actual mori cone: it is the + -- intersection of all mori cones coming from triangulations equivalent to the given one. + elapsedTime Xs := findAllCYs Q; -- TODO: check: is findALlCYs still correct. + -- << " " << #Xs << " triangulations total" << endl; + -- if opts.NTFE then ( + -- elapsedTime H := partition(restrictTriangulation, Xs); + -- << " " << #(keys H) << " NTFE triangulations" << endl; + -- Xs = (keys H)/(k -> H#k#0); -- only take one triangulation that matches + -- Xs = for k in keys H list ( + -- X := H#k#0; + -- setToricMoriConeCap(X, H#k); + -- X + -- ) + -- -- let's relabel these Xs? + -- ); + F := openDatabaseOut dbfilename; + for X in Xs do ( + setToricMoriConeCap X; + computeIntersectionNumbers X; -- this should load all of the data we want + F#(toString label X) = dump X; + ); + close F; + ) + +addToCYDatabase(String, List) := opts ->(dbfilename, topes) -> ( + for tope in topes do addToCYDatabase(dbfilename, tope, opts); + ) + +addToCYDatabase(String, String, List) := opts ->(dbfilename, dbQfilename, topeLabels) -> ( + for lab in topeLabels do ( + << "polytope " << lab << endl; + Q := cyPolytope(dbQfilename, lab); + elapsedTime addToCYDatabase(dbfilename, Q, opts); + ); + ) + +createCYDatabase = method(Options => { + Limit => 100000, + NTFE => true, + "CYs" => true}) +createCYDatabase(String, ZZ, List) := opts -> (dbfileprefix, h11, range) -> ( + topes := kreuzerSkarke(h11, Limit => opts.Limit); + (lo, hi) := toSequence range; + hi = hi-1; + filename := dbfileprefix | "-range-"|lo|"-"|hi|".dbm"; + addToCYDatabase(filename, topes_{lo..hi}, NTFE => opts.NTFE, "CYs" => opts#"CYs") + ) +-- createCYDatabase = method() + +-- createCYDatabase(String, List) := (dbfilename, topes) -> ( +-- -- open data base file +-- F := openDatabaseOut dbfilename; +-- -- loop through topes, create CYPolytope, populate it, write it to data base. +-- elapsedTime for i from 0 to #topes - 1 do elapsedTime ( +-- lab := label topes_i; +-- if lab === null then lab = i; -- else print "using label"; +-- << "computing for polytope " << lab << endl; +-- V := cyPolytope(topes#i, ID => lab); -- note that the polytope data is really that of the dual to topes#i. +-- -- now fill it with data we want +-- basisIndices V; -- compute them +-- isFavorable V; -- compute h11, h21, favorability. +-- annotatedFaces V; -- compute annotated faces +-- automorphisms V; +-- -- now write it +-- F#(toString lab) = dump V; +-- ); +-- close F; +-- ) + + +-- addToCYDatabase(String, CYPolytope) := opts -> (dbfilename, Q) -> ( +-- elapsedTime Xs := findAllCYs Q; -- TODO: check: is findALlCYs still correct. +-- << " " << #Xs << " triangulations total" << endl; +-- if opts.NTFE then ( +-- elapsedTime H := partition(restrictTriangulation, Xs); +-- << " " << #(keys H) << " NTFE triangulations" << endl; +-- Xs = (keys H)/(k -> H#k#0); -- only take one triangulation that matches +-- -- let's relabel these Xs +-- ); +-- F := openDatabaseOut dbfilename; +-- for X in Xs do ( +-- computeIntersectionNumbers X; -- this should load all of the data we want +-- F#(toString label X) = dump X; +-- ); +-- close F; +-- ) + +-- addToCYDatabase(String, CYPolytope) := opts -> (dbfilename, Q) -> ( +-- -- This version also finds "moriConeCap" which is a cone containing the actual mori cone: it is the +-- -- intersection of all mori cones coming from triangulations equivalent to the given one. +-- elapsedTime Xs := findAllCYs Q; -- TODO: check: is findALlCYs still correct. +-- << " " << #Xs << " triangulations total" << endl; +-- if opts.NTFE then ( +-- elapsedTime H := partition(restrictTriangulation, Xs); +-- << " " << #(keys H) << " NTFE triangulations" << endl; +-- Xs = (keys H)/(k -> H#k#0); -- only take one triangulation that matches +-- Xs = for k in keys H list ( +-- X := H#k#0; +-- setToricMoriConeCap(X, H#k); +-- X +-- ) +-- -- let's relabel these Xs? +-- ); +-- F := openDatabaseOut dbfilename; +-- for X in Xs do ( +-- computeIntersectionNumbers X; -- this should load all of the data we want +-- F#(toString label X) = dump X; +-- ); +-- close F; +-- ) + +-- addToCYDatabase(String, Database, ZZ) := opts -> (dbfilename, topesDB, i) -> ( +-- << "-- doing polytope " << i << endl; +-- Q := cyPolytope(topesDB#(toString i), ID => i); +-- addToCYDatabase(dbfilename, Q, opts); +-- ) + +readCYDatabase = method(Options => {Ring => null}) +readCYDatabase String := Sequence => opts -> (dbname) -> ( + F := openDatabase dbname; + labs := (keys F)/value; + Qlabels := sort select(labs, lab -> instance(lab, ZZ)); + Xlabels := sort select(labs, lab -> instance(lab, Sequence)); + Qs := hashTable for lab in Qlabels list lab => cyPolytope F#(toString lab); + Xs := hashTable for lab in Xlabels list lab => cyData(F#(toString lab), i -> Qs#i, opts); + close F; + (Qs, Xs) + ) + +readCYPolytopes = method() +readCYPolytopes String := HashTable => dbname -> ( + F := openDatabase dbname; + labs := (keys F)/value; + Qlabels := sort select(labs, lab -> instance(lab, ZZ)); + Qs := hashTable for lab in Qlabels list lab => cyPolytope F#(toString lab); + close F; + Qs + ) + +readCYs = method(Options => {Ring => null}) +readCYs(String, HashTable) := HashTable => opts -> (dbname, Qs) -> ( + F := openDatabase dbname; + labs := (keys F)/value; + Xlabels := sort select(labs, lab -> instance(lab, Sequence)); + Xs := hashTable for lab in Xlabels list lab => cyData(F#(toString lab), i -> Qs#i, opts); + close F; + Xs + ) + +------------------------------------------------------- +-- Read one example from a database or database file -- +------------------------------------------------------- +cyPolytope(String, ZZ) := CYPolytope => opts -> (dbfilename, topeid) -> ( + db := openDatabase dbfilename; + Q := cyPolytope(db, topeid, opts); + close db; + Q + ) + +cyPolytope(Database, ZZ) := CYPolytope => opts -> (db, topeid) -> ( + k := toString topeid; + if not db#?k then error("polytope with label "|k|" does not exist"); + cyPolytope(db#k, opts) + ) + +-- Check: this is not quite correct. +calabiYau(Database, CYPolytope, Sequence) := CalabiYauInToric => opts -> (db, Q, lab) -> ( + -- lab should be (polytopelab, triangulationlabel). + -- polytopelab should match label of Q. + if first lab =!= label Q then error "incorrect label"; + k := toString lab; + if not db#?k then error("polytope with label "|k|" does not exist"); + calabiYau(db#k, lab -> Q, opts) + ) + +calabiYau(Database, Sequence) := CalabiYauInToric => opts -> (db, lab) -> ( + -- lab should be (polytopelab, triangulationlabel). + -- first retrieve CYPolytope, and then CalabiYauInToric. + if #lab < 2 then error "expected well-formed label"; + Q := cyPolytope(db, first lab); + k := toString lab; + if not db#?k then error("CY with label "|k|" does not exist"); + calabiYau(db#k, lab -> Q, opts) + ) + +calabiYau(String, CYPolytope, Sequence) := CalabiYauInToric => opts -> (dbfilename, Q, lab) -> ( + db := openDatabase dbfilename; + X := calabiYau(db, Q, lab, opts); + close db; + X + ) + +calabiYau(String, Sequence) := CalabiYauInToric => opts -> (dbfilename, lab) -> ( + db := openDatabase dbfilename; + X := calabiYau(db, lab, opts); + close db; + X + ) + + +/// + -- h11=4 database use, 19 June 2023. + -- XXX In construction +-* + restart + needsPackage "StringTorics" +*- + R = ZZ[a,b,c,d] + RQ = QQ (monoid R); + (Qs, Xs) = readCYDatabase("mike-ntfe-h11-4.dbm", Ring => R); + assert(#keys Qs == 1197) -- includes torsions and nonfavorables. + assert(#keys Xs == 1994) -- note, none of the torsion Qs are in here yet. + + peek Xs#(20,0).cache + ByH12 = partition(k -> hh^(1,2) Xs#k, keys Xs); + -- by H12 value, 1994 examples are split into 86 groups. + -- largest group is h12=64, at 195 in that group. + 86 == # hashTable for x in keys ByH12 list x => #ByH12#x + + -- Now let's divide by invariants to see how to separate them all. + debug StringTorics -- invariantsAll isn't exported! + elapsedTime IHall = partition(x -> elapsedTime invariantsAll x, values Xs); + -- 1126 different groups here. + assert(#keys IHall == 1126) + (values IHall)/(x -> #x)//tally + -- 723 different classes have exactly one element in them. + -- largest class is 51 elements. + -- of course, these all might be equivalent! (Probably not, but who knows...) + -- Tally{1 => 723} + 2 => 221 + 3 => 109 + 4 => 31 + 5 => 8 + 6 => 13 + 7 => 3 + 8 => 5 + 9 => 1 + 10 => 5 + 11 => 1 + 12 => 2 + 13 => 2 + 28 => 1 + 51 => 1 + -- Now leave off inverse system invariant: get the same numbers. + -- How many of these can be determined to be equivalent? + -- Well, the 723 that are by themselves we can ignore. + set2 = select(values IHall, k -> #k > 1); + set3 = set2/(x -> (x/label//sort)) + count = 0; + set4 = for Ls in set3 list ( + << "--- doing " << count << " with " << Ls << endl; + count = count + 1; + ans := elapsedTime partitionByTopology(Ls, Xs, 15); + print ans; + ans + ) + set5 = for x in set4 list ( + for k in keys x list {k} | (x#k / first) + ) + set5len = for x in set5 list (x/length) + #set5len + #select(set5len, x -> #x == 1) -- 340 of the 403 have one class. + -- 53 sets have 2 classes + -- 8 sets have 3 classes + -- 2 sets have 4 classes + -- so total number of topologies is likely: 723 + 340 + 53*2 + 8*3 + 2*4 = 1201 + set6 = for x in set5 list (x/sort/first//sort) + set7 = sort select(set6, x -> #x > 1) + #set7 == 63 -- these are sets we still would like to separate by invariants of that is possible + -- range on number of topologies: + -- low end: 723 + 340 + 63 == 1126 + -- hi end: 723 + 340 + 138 == 1201 + for ks in set7 list netList transpose {for k in ks list factor det hessian cubicForm Xs#k} + for ks in set7 list netList transpose {for k in ks list factor cubicForm Xs#k} + + -- Here we just play some and try to separate these + + -- Let's try to separate some of these now, and then we can try to automate it + -- XXX 19 June 2023. + (L1, F1) = (c2Form Xs#(1182,0), cubicForm Xs#(1182,0)) + (L2, F2) = (c2Form Xs#(1183,2), cubicForm Xs#(1183,2)) + + (L1, F1) = (c2Form Xs#(1143,0), cubicForm Xs#(1143,0)) + (L2, F2) = (c2Form Xs#(1145,0), cubicForm Xs#(1145,0)) + + (L1, F1) = (c2Form Xs#(1123,0), cubicForm Xs#(1123,0)) + (L2, F2) = (c2Form Xs#(1124,0), cubicForm Xs#(1124,0)) + + (L1, F1) = (c2Form Xs#(1123,0), cubicForm Xs#(1123,0)) + (L2, F2) = (c2Form Xs#(1124,0), cubicForm Xs#(1124,0)) + + (A,phi) = genericLinearMap RQ + T = source phi; + I0 = sub(ideal last coefficients (phi sub(L1,T) - sub(L2,T)), ring A) + A0 = A % I0 + phi0 = map(T,T,A0) + trim(I0 + sub(ideal last coefficients (phi0 sub(F1,T) - sub(F2,T)), ring A)) + + + for k from 0 to #set7-1 list ( + (lab1,lab2) = toSequence set7#k_{0,1}; -- only do the first 2. + I := getEquivalenceIdeal(lab1, lab2, Xs); + << "k = " << k << " ideal " << netList I_* << endl; + I + ) + + (lab1,lab2) = toSequence set7#0_{0,1} + getEquivalenceIdeal(lab1,lab2, Xs) + getEquivalenceIdealHelper((L1,F1),(L2,F2),A,phi) +/// + +/// + -- Example of construction of database for: h11=3, all h12's. + -- Note, #232 is not favorable. + restart + needsPackage "StringTorics" + topes = kreuzerSkarke(3, Limit => 1000); + assert(#topes == 244) + elapsedTime createCYDatabase("foo-ntfe-h11-3.dbm", topes) + + -- Now let's add in all the CY's total, including all triangulations. + Qs = readCYPolytopes "foo-ntfe-h11-3.dbm"; + elapsedTime for Q in values Qs do addToCYDatabase("foo-ntfe-h11-3.dbm", Q, NTFE => true); + + -- How to access all of the polytopes and CY's at once. + -- We create a hashtable for each, keys are their labels, and values are the CYPolytope and CalabiYauInToric's. + Qs = readCYPolytopes "foo-ntfe-h11-3.dbm"; + for k in sort keys Qs do assert instance(Qs#k, CYPolytope) + + Xs = readCYs("foo-ntfe-h11-3.dbm", Qs); + for k in sort keys Xs do assert instance(Xs#k, CalabiYauInToric) + + -- or both at the same time.. + (Qs1, Xs1) = readCYDatabase "foo-ntfe-h11-3.dbm"; + assert(Qs1 === Qs) + assert(Xs1 === Xs) + + -- given all the3 Qs, how to access just some Xs (e.g. for a specific Q). + F = openDatabase "foo-ntfe-h11-3.dbm" + Qs = readCYPolytopes "foo-ntfe-h11-3.dbm"; + for k in sort keys F list ( + if not match("\\(6,", k) then continue else cyData(F#(toString k), i -> Qs#i) + ) + oo/label + close F +/// + +/// + -- Example of creation of h11=4 database of those triangulations which are NTFE (not 2-face equivalent). + -- One data base per (h11,h12) pair too. +-* + restart + needsPackage "StringTorics" +*- + + createNTFEDatabase = (dbname, topes) -> ( + createCYDatabase(dbname, topes); + Qs := readCYPolytopes dbname; + elapsedTime for Q in values Qs do addToCYDatabase(dbname, Q, NTFE => true); + ) + createAllNTFEDatabases = (h12s, topes) -> ( + for i in h12s do ( + dbname = "cys-ntfe-h11-4-h12-"|i|".dbm"; + << "starting on " << dbname << endl; + ourtopes = select(topes, ks -> last hodgeNumbers ks == i); + createNTFEDatabase(dbname, ourtopes); + ); + ) + + + topes = kreuzerSkarke(4, Limit => 10000); + createAllNTFEDatabases({28, 34}, topes) + assert(#topes == 1197) + h12s = topes/hodgeNumbers/last//unique//sort + h12s == {28, 34, 36, 37, 40, 42, 44, 46, 48, 49, 50, 52, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 76, 77, 78, 79, 80, 81, 82, 84, 85, 86, 88, + 89, 90, 91, 92, 93, 94, 96, 97, 98, 100, 101, 102, 104, 106, + 108, 109, 110, 112, 114, 116, 118, 120, 121, 122, 124, 126, + 128, 130, 136, 142, 144, 148, 154, 162, 166, 178, 190, 194, + 202, 208, 214, 226, 238} + + createAllNTFEDatabases(h12s, topes) + +/// + +/// +-* + restart + debug needsPackage "StringTorics" +*- + + -- Example analysis of topologies for h11=4. + topes = kreuzerSkarke(4, Limit => 10000); + assert(#topes == 1197) + h12s = topes/hodgeNumbers/last//unique//sort + h12s == {28, 34, 36, 37, 40, 42, 44, 46, 48, 49, 50, 52, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 76, 77, 78, 79, 80, 81, 82, 84, 85, 86, 88, + 89, 90, 91, 92, 93, 94, 96, 97, 98, 100, 101, 102, 104, 106, + 108, 109, 110, 112, 114, 116, 118, 120, 121, 122, 124, 126, + 128, 130, 136, 142, 144, 148, 154, 162, 166, 178, 190, 194, + 202, 208, 214, 226, 238} + + db4name = (h12) -> "cys-ntfe-h11-4-h12-"|h12|".dbm" + RZ = ZZ[a,b,c,d]; + DB = hashTable for h in h12s list h => readCYDatabase(db4name h, Ring => RZ); + + (Qs, Xs) = DB#56 + H = partition(invariants2, values Xs) + tops = hashTable for k in keys H list k => ((H#k)/label) + INV = for k in sort keys tops list k => partitionByTopology(tops#k, Xs, 15) + + keys Xs + F1 = cubicForm Xs#(73,0) + F2 = cubicForm Xs#(80,3) + L1 = c2Form Xs#(73,0) + L2 = c2Form Xs#(80,3) + + + (Qs, Xs) = DB#97 + (Qs, Xs) = DB#94 + H = partition(invariants2, values Xs) + tops = hashTable for k in keys H list k => ((H#k)/label) + INV = for k in sort keys tops list k => partitionByTopology(tops#k, Xs, 15) + hashTable INV + + unfavorables = sort flatten for h in h12s list ( + Qs = readCYPolytopes(db4name h); + for Q in values Qs list if not isFavorable Q then label Q else continue + ) + unfavorables === {796, 800, 803, 1059, 1060, 1064, 1065, 1134, 1135, 1151, 1153, 1155} + nontorsionfrees = sort flatten for h in h12s list ( + (Qs, Xs) = readCYDatabase(db4name h); + for X in values Xs list ( + V := normalToricVariety(rays X, max X); + if classGroup V =!= ZZ^4 then label X else continue + ) + ) + -- all unfavorables have torsion toric class group: + nontorsionfrees == {(0, 0), (3, 0), (4, 0), (5, 0), (12, 0), (15, 0), + (796, 0), (796, 1), (800, 0), (803, 0), (1059, 0), (1060, 0), (1064, 0), + (1065, 0), (1134, 0), (1135, 0), (1151, 0), (1153, 0), (1155, 0), (1155, 1)} + + + -- analyze one h12 + findDistincts= (h12) -> ( + (Qs, Xs) = DB#h12; + H = partition(invariants2, values Xs); + tops = hashTable for k in keys H list k => ((H#k)/label); + INV = for k in sort keys tops list k => partitionByTopology(tops#k, Xs, 15); + (INV, Qs, Xs) + ) + (INV, Qs, Xs) = findDistincts 28; + netList INV + + (INV, Qs, Xs) = findDistincts 34; -- only one here + netList INV + + (INV, Qs, Xs) = findDistincts 36; -- polytopes 3,4,5: all have class group torsion. + netList INV + + (INV, Qs, Xs) = findDistincts 37; + netList INV -- only one + + (INV, Qs, Xs) = findDistincts 40; -- 2 diff topologies, different invariants2 + netList INV + + (INV, Qs, Xs) = findDistincts 44; -- has a torsion polytope. + netList INV + + (INV, Qs, Xs) = findDistincts 46; + netList INV -- (17,0), (19,1) are seemingly different. + F1 = cubicForm Xs#(17,0) + F2 = cubicForm Xs#(19,1) + sing = (F) -> ideal F + ideal jacobian F + linears = (I) -> (J := ideal select(I_*, f -> part(1, f) != 0); if J == 0 then trim ideal 0_(ring I) else J) + linearcontent = (I) -> trim sum for f in (linears I)_* list content f + betti res sub(sing F1, RQ) + betti res sub(sing F2, RQ) + + betti res sub(saturate sing F1, RQ) + betti res sub(saturate sing F2, RQ) + primaryDecomposition sub(saturate sing F1, RQ) + primaryDecomposition sub(saturate sing F2, RQ) + see ideal gens gb saturate sing F1 + see ideal gens gb saturate sing F2 -- these have different linear parts (252a, 1512a). SHows they are different. + + select(sort keys DB, h12 -> # keys last DB#h12 > 1) + + (INV, Qs, Xs) = findDistincts 48; + netList INV -- all 3 are distinct + + (INV, Qs, Xs) = findDistincts 49; + netList INV -- all 6 are distinct + + (INV, Qs, Xs) = findDistincts 50; + netList INV -- only 1. + + (INV, Qs, Xs) = findDistincts 52; -- alot here, it seems + netList INV -- one group of 6, one of 4, one of 3, 17 of 1 each. + F1 = cubicForm Xs#(33,0) + F2 = cubicForm Xs#(41,0) + F3 = cubicForm Xs#(41,1) + F4 = cubicForm Xs#(44,0) + F5 = cubicForm Xs#(48,0) + F6 = cubicForm Xs#(49,4) + see linears ideal gens gb saturate sing F1 + see linears ideal gens gb saturate sing F2 + see linears ideal gens gb saturate sing F3 + see linears ideal gens gb saturate sing F4 + see linears ideal gens gb saturate sing F5 + see linears ideal gens gb saturate sing F6 + trim content F1 + trim content F2 + trim content F3 + trim content F4 + trim content F5 + trim content F6 + see linearcontent ideal gens gb saturate sing F1 + see linearcontent ideal gens gb saturate sing F2 + see linearcontent ideal gens gb saturate sing F3 + see linearcontent ideal gens gb saturate sing F4 + see linearcontent ideal gens gb saturate sing F5 + see linearcontent ideal gens gb saturate sing F6 + + F1 = cubicForm Xs#(35,0) + F2 = cubicForm Xs#(38,0) + F3 = cubicForm Xs#(39,0) -- F1 and F3 look pretty similar? TODO: I can't prove they are the same or different yet! + F4 = cubicForm Xs#(53,0) + + for p in {3,5,7,11, 13} list (pointCount(F1, p), pointCount(F3, p)) + decompose sub(sing F1, RQ) + decompose sub(ideal gens gb saturate sing F1, RQ) + decompose sub(ideal gens gb saturate sing F3, RQ) + + invariants2 Xs#(35,0) + invariants2 Xs#(39,0) + partitionGVConeByGV(Xs#(35, 0), DegreeLimit => 25) -- simplicial (4 generators, GV's: -2, 8, 10, 64). + partitionGVConeByGV(Xs#(39, 0), DegreeLimit => 25) -- 5 gens, GV: -2,-2,10,64,128. + -- Question: how to distinguish F1, F3? (F2, F4 are different and diff from F1, F3). + + L1 = c2Form Xs#(35,0) + L3 = c2Form Xs#(39,0) + + decompose sub((ideal(L1) + sing F1), RQ) + decompose sub((ideal(L3) + sing F3), RQ) + decompose sub(ideal(L3, F3), RQ) + + -- Next one to try + (INV, Qs, Xs) = findDistincts 54; + netList INV + F1 = cubicForm Xs#(64,0) + F2 = cubicForm Xs#(64,1) + see linears ideal gens gb saturate sing F1 + see linears ideal gens gb saturate sing F2 -- very different... + + -- Next one to try + (INV, Qs, Xs) = findDistincts 55; + netList INV + F1 = cubicForm Xs#(67,0) + F2 = cubicForm Xs#(69,0) + see linears ideal gens gb saturate sing F1 + see linears ideal gens gb saturate sing F2 -- different linear part contents. + + -- Next one to try. All ones that cannot be matched are distinct. + (INV, Qs, Xs) = findDistincts 56; + netList INV -- lots. 2: 2 diff, 1: 3 diff, 18: 1 only... + -- set1 + F1 = cubicForm Xs#(73,0) + F2 = cubicForm Xs#(80,3) + see linears ideal gens gb saturate sing F1 + see linears ideal gens gb saturate sing F2 -- different linear part contents. + -- set2 + F1 = cubicForm Xs#(75,0) + F2 = cubicForm Xs#(75,1) + F3 = cubicForm Xs#(75,3) + see linears ideal gens gb saturate sing F1 + see linears ideal gens gb saturate sing F2 + see linears ideal gens gb saturate sing F3 -- all different via linear part contents + -- set3 + F1 = cubicForm Xs#(72,0) + F2 = cubicForm Xs#(80,2) + see linears ideal gens gb saturate sing F1 + see linears ideal gens gb saturate sing F2 -- different linear part contents. + + -- Next one to try + (INV, Qs, Xs) = findDistincts 57; -- 1 only. + netList INV + + -- Next one to try + (INV, Qs, Xs) = findDistincts 58; + netList INV -- 1: 9 different!, 1: 4 diff, 26: 1 diff + -- set1 + F1 = cubicForm Xs#(92,0) + F2 = cubicForm Xs#(93,0) + F3 = cubicForm Xs#(96,0) + F4 = cubicForm Xs#(97,0) + F5 = cubicForm Xs#(105,0) + F6 = cubicForm Xs#(105,2) + F7 = cubicForm Xs#(112,0) + F8 = cubicForm Xs#(120,0) + F9 = cubicForm Xs#(120,2) + linearcontent ideal gens gb saturate sing F1 + linearcontent ideal gens gb saturate sing F2 + linearcontent ideal gens gb saturate sing F3 + linearcontent ideal gens gb saturate sing F4 + linearcontent ideal gens gb saturate sing F5 + linearcontent ideal gens gb saturate sing F6 + linearcontent ideal gens gb saturate sing F7 + linearcontent ideal gens gb saturate sing F8 + linearcontent ideal gens gb saturate sing F9 + -- all are distinct except possibly F3, F7 + decompose sub(ideal gens gb saturate sing F3, RQ) + decompose sub(ideal gens gb saturate sing F7, RQ) -- 1 point vs 3 points. So F3, F7, therefore all, are distinct. + -- set2 + F1 = cubicForm Xs#(98,0) + F2 = cubicForm Xs#(109,0) + F3 = cubicForm Xs#(110,0) + F4 = cubicForm Xs#(110,1) + see linears ideal gens gb saturate sing F1 + see linears ideal gens gb saturate sing F2 + see linears ideal gens gb saturate sing F3 + see linears ideal gens gb saturate sing F4 -- all different via linear part contents + + -- Next one to try + (INV, Qs, Xs) = findDistincts 59; + netList INV -- 3, all distinct + + -- Next one to try + (INV, Qs, Xs) = findDistincts 60; + netList INV -- + -- set1 + F1 = cubicForm Xs#(133,0) + F2 = cubicForm Xs#(137,0) + F3 = cubicForm Xs#(140,0) + F4 = cubicForm Xs#(146,0) + F5 = cubicForm Xs#(148,0) + F6 = cubicForm Xs#(148,1) + linearcontent ideal gens gb saturate sing F1 + linearcontent ideal gens gb saturate sing F2 + linearcontent ideal gens gb saturate sing F3 + linearcontent ideal gens gb saturate sing F4 + linearcontent ideal gens gb saturate sing F5 + linearcontent ideal gens gb saturate sing F6 -- all distinct linear content! + -- set2 + F1 = cubicForm Xs#(144,0) + F2 = cubicForm Xs#(158,0) + linearcontent ideal gens gb saturate sing F1 + linearcontent ideal gens gb saturate sing F2 -- all distinct linear content! + -- set3 + F1 = cubicForm Xs#(140,1) + F2 = cubicForm Xs#(142,0) + linearcontent ideal gens gb saturate sing F1 + linearcontent ideal gens gb saturate sing F2 -- all distinct linear content! + -- set4 + F1 = cubicForm Xs#(129,0) + F2 = cubicForm Xs#(135,0) + F3 = cubicForm Xs#(139,0) + F4 = cubicForm Xs#(149,0) + linearcontent ideal gens gb saturate sing F1 + linearcontent ideal gens gb saturate sing F2 + linearcontent ideal gens gb saturate sing F3 + linearcontent ideal gens gb saturate sing F4 -- all distinct linear content! + -- set5 + F1 = cubicForm Xs#(135,1) + F2 = cubicForm Xs#(138,0) + F3 = cubicForm Xs#(149,2) + linearcontent ideal gens gb saturate sing F1 + linearcontent ideal gens gb saturate sing F2 -- how to tell F1, F2 apart? + linearcontent ideal gens gb saturate sing F3 + decompose sub(ideal gens gb saturate sing F1, RQ) + decompose sub(ideal gens gb saturate sing F2, RQ) -- stil todo: are F1, F2 equivalent? + + -- Next one to try + (INV, Qs, Xs) = findDistincts 61; + netList INV -- + F1 = cubicForm Xs#(163,2) + F2 = cubicForm Xs#(164,0) + F3 = cubicForm Xs#(166,0) + F4 = cubicForm Xs#(166,1) + F5 = cubicForm Xs#(166,2) + F6 = cubicForm Xs#(169,0) + F7 = cubicForm Xs#(169,1) + linearcontent ideal gens gb saturate sing F1 + linearcontent ideal gens gb saturate sing F2 + linearcontent ideal gens gb saturate sing F3 + linearcontent ideal gens gb saturate sing F4 + linearcontent ideal gens gb saturate sing F5 + linearcontent ideal gens gb saturate sing F6 + linearcontent ideal gens gb saturate sing F7 -- all distinct linear content! + + -- Next one to try + (INV, Qs, Xs) = findDistincts 62; + netList INV -- + -- set1 + F1 = cubicForm Xs#(172,0) + F2 = cubicForm Xs#(173,0) + F3 = cubicForm Xs#(179,0) + F4 = cubicForm Xs#(179,2) + F5 = cubicForm Xs#(180,0) + F6 = cubicForm Xs#(192,1) + linearcontent ideal gens gb saturate sing F1 + linearcontent ideal gens gb saturate sing F2 + linearcontent ideal gens gb saturate sing F3 + linearcontent ideal gens gb saturate sing F4 + linearcontent ideal gens gb saturate sing F5 + linearcontent ideal gens gb saturate sing F6 -- all distinct linear content! + -- set2 + F1 = cubicForm Xs#(181,1) + F2 = cubicForm Xs#(191,0) + linearcontent ideal gens gb saturate sing F1 + linearcontent ideal gens gb saturate sing F2 -- how to tell F1, F2 apart? + -- set3 + F1 = cubicForm Xs#(182,0) + F2 = cubicForm Xs#(182,1) + linearcontent ideal gens gb saturate sing F1 + linearcontent ideal gens gb saturate sing F2 -- how to tell F1, F2 apart? + + -- Next one to try + (INV, Qs, Xs) = findDistincts 63; + netList INV -- only 1 + + -- Next one to try + (INV, Qs, Xs) = findDistincts 64; + netList INV -- LOTS!! TODO: start here. Actually, maybe I should start over and incorporate the linear content into the invariants. + + + + H = partition(invariants2, values Xs) + tops = hashTable for k in keys H list k => ((H#k)/label) + INV = for k in sort keys tops list k => partitionByTopology(tops#k, Xs, 15) + hashTable INV + + h12s == {28, 34, 36, 37, 40, 42, 44, 46, 48, 49, 50, 52, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 76, 77, 78, 79, 80, 81, 82, 84, 85, 86, 88, + 89, 90, 91, 92, 93, 94, 96, 97, 98, 100, 101, 102, 104, 106, + 108, 109, 110, 112, 114, 116, 118, 120, 121, 122, 124, 126, + 128, 130, 136, 142, 144, 148, 154, 162, 166, 178, 190, 194, + 202, 208, 214, 226, 238} + +/// + +/// + -- An attempt to automate the following: + -- 1. create one hash table with all of the Qs, Xs. + -- 2. separate the Xs via invariants. + -- 3. for each invariant, use topology to separate. + +-* + restart + debug needsPackage "StringTorics" +*- + + -- Example analysis of topologies for h11=4. + --topes = kreuzerSkarke(4, Limit => 10000); + --assert(#topes == 1197) + --h12s = topes/hodgeNumbers/last//unique//sort + h12s = {28, 34, 36, 37, 40, 42, 44, 46, 48, 49, 50, 52, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 76, 77, 78, 79, 80, 81, 82, 84, 85, 86, 88, + 89, 90, 91, 92, 93, 94, 96, 97, 98, 100, 101, 102, 104, 106, + 108, 109, 110, 112, 114, 116, 118, 120, 121, 122, 124, 126, + 128, 130, 136, 142, 144, 148, 154, 162, 166, 178, 190, 194, + 202, 208, 214, 226, 238} + + nontorsionfrees = {(0, 0), (3, 0), (4, 0), (5, 0), (12, 0), (15, 0), + (796, 0), (796, 1), (800, 0), (803, 0), (1059, 0), (1060, 0), (1064, 0), + (1065, 0), (1134, 0), (1135, 0), (1151, 0), (1153, 0), (1155, 0), (1155, 1)} + + db4name = (h12) -> "cys-ntfe-h11-4-h12-"|h12|".dbm" + RZ = ZZ[a,b,c,d]; + RQ = QQ (monoid RZ); + DB = hashTable for h in h12s list h => readCYDatabase("../m2-examples/"|db4name h, Ring => RZ); + Qs = new MutableHashTable + Xs = new MutableHashTable + for a in keys DB do ( + (Q1s, X1s) = DB#a; + for q in sort keys Q1s do Qs#q = Q1s#q; + for k in sort keys X1s do if not member(k, nontorsionfrees) then Xs#k = X1s#k; + ); + Xs = new HashTable from Xs; + Qs = new HashTable from Qs; + sort keys Qs + sort keys Xs + #oo == 1994 -- 2014 total for all + assert(# sort keys Xs == 2014 - #nontorsionfrees) + + elapsedTime H = partition(invariants3, values Xs); + H1 = hashTable for k in keys H list k => (H#k)/label; + elapsedTime INV = for k in sort keys H1 list k => partitionByTopology(H1#k, Xs, 15); + -- number of different topologies + tally for k in sort keys H1 list #H1#k + elapsedTime INV = for k in sort keys H1 list k => partitionByTopology(H1#k, Xs, 15); + tally for k in INV list #(keys last k) + INV1 = select(INV, k -> #(keys last k) >= 2); + netList INV1 + + -- separate topologies: + -- output is a list of lists {S0, S1, S2, ..., Sr} + -- each CY in Si is not equivalent to any in Sj, i!=j. + -- each pair of CY's in a specific Si are not proved to be distinct (but are likely distinct?) + -- every CY in h11=4 database is knoqn to be equivalent to one of these + -- (Question: or are they all there in one of these lists?) + TOP1 = for k in INV list for a in keys last k list ( + prepend(a, ((last k)#a)/first) + ); + netList(TOP1/(a -> a/(a1->#a1))) + + REPS = for k in INV list ( + H := last k; -- a hash table + K := keys H; + if #K == 1 then continue + else K) + + ONEONLY = for k in INV list ( + H := last k; -- a hash table + K := keys H; + if #K == 1 then first K else continue) + + -- So: 1994 total different NTFE h11=4 CY's, with torsion free class groups (all of these are favorable) + -- Of these: + #TOP1 + TOP1/(a -> a/(a1->#a1)//sum)//sum == 1994 + #ONEONLY == 904 -- the number that are by themselves. + #REPS == 118 + # flatten REPS == 287 + + REPS = {{(14, 1), (14, 0)}, + {(38, 4), (53, 0), (30, 0), (38, 0)}, + {(35, 0), (39, 0)}, + {(80, 6), (80, 2)}, + {(96, 0), (126, 0)}, + {(148, 1), (141, 0)}, + {(140, 0), (144, 0)}, + {(135, 0), (134, 3)}, + {(135, 1), (138, 0)}, + {(180, 0), (179, 2)}, + {(241, 0), (210, 0), (258, 0)}, + {(265, 0), (250, 0), (265, 1), (236, 0), (228, 1)}, + {(290, 1), (258, 1)}, + {(235, 0), (262, 0)}, + {(225, 2), (260, 2)}, + {(265, 2), (235, 1)}, + {(265, 3), (228, 0)}, + {(250, 1), (254, 2)}, + {(249, 1), (246, 0)}, + {(227, 0), (261, 0)}, + {(209, 3), (284, 1), (261, 1)}, + {(240, 3), (278, 1)}, + {(319, 0), (313, 0)}, + {(316, 0), (322, 0)}, + {(334, 2), (328, 1), (329, 0)}, + {(331, 0), (337, 1), (339, 3)}, + {(334, 1), (329, 1)}, + {(339, 5), (337, 0)}, + {(385, 2), (385, 3)}, + {(364, 1), (377, 0)}, + {(356, 0), (395, 6)}, + {(378, 0), (378, 2), (379, 1), (395, 2)}, + {(379, 0), (379, 3)}, + {(383, 0), (356, 1)}, + {(397, 0), (350, 0)}, + {(387, 4), (387, 0)}, + {(377, 2), (364, 0)}, + {(416, 0), (441, 0), (438, 0), (450, 4)}, + {(400, 0), (403, 0), (405, 0), (414, 0)}, + {(436, 0), (433, 0)}, + {(419, 0), (419, 2)}, + {(436, 1), (433, 1)}, + {(451, 0), (455, 1)}, + {(475, 1), (481, 1)}, + {(473, 0), (478, 0)}, + {(458, 5), (458, 1)}, + {(458, 3), (458, 0)}, + {(508, 0), (514, 0)}, + {(512, 1), (505, 0)}, + {(507, 0), (519, 3)}, + {(526, 1), (527, 0), (518, 3), (522, 0)}, + {(524, 0), (518, 0)}, + {(529, 0), (510, 0)}, + {(550, 0), (538, 0)}, + {(532, 0), (573, 0)}, + {(556, 0), (562, 0)}, + {(553, 0), (548, 1), (554, 0)}, + {(552, 0), (551, 2)}, + {(559, 0), (577, 0)}, + {(540, 0), (545, 0)}, + {(588, 0), (586, 0)}, + {(616, 0), (606, 0)}, + {(650, 0), (650, 1), (667, 1), (650, 3), (656, 0), (666, 9), (630, 0)}, + {(643, 0), (649, 0), (626, 0)}, + {(628, 0), (653, 0)}, + {(647, 0), (669, 0)}, + {(688, 1), (685, 0)}, + {(687, 0), (684, 1)}, + {(693, 0), (694, 0)}, + {(712, 0), (714, 0), (706, 0), (707, 0), (709, 0)}, + {(716, 3), (705, 0)}, + {(715, 0), (704, 0)}, + {(738, 3), (737, 1)}, + {(731, 0), (740, 1)}, + {(764, 0), (764, 1)}, + {(773, 7), (773, 0)}, + {(770, 1), (774, 5)}, + {(771, 0), (771, 1)}, + {(781, 2), (781, 1)}, + {(815, 0), (810, 0), (851, 0), (884, 0), (820, 0), (869, 0)}, + {(884, 7), (881, 0), (884, 2)}, + {(835, 2), (806, 0), (822, 0)}, + {(878, 0), (885, 1), (886, 0)}, + {(879, 9), (808, 0), (845, 0), (896, 0), (865, 0), (879, 3), (896, 3)}, + {(825, 0), (862, 0)}, + {(863, 0), (887, 0)}, + {(876, 0), (854, 0)}, + {(900, 0), (901, 0)}, + {(913, 2), (913, 1)}, + {(935, 17), (938, 0)}, + {(938, 3), (933, 0)}, + {(919, 0), (938, 4)}, + {(930, 1), (934, 0), (922, 0)}, + {(932, 0), (916, 0), (917, 0)}, + {(922, 1), (930, 0)}, + {(938, 11), (933, 5)}, + {(935, 0), (937, 0), (915, 0), (924, 0), (935, 5)}, + {(943, 0), (953, 0), (958, 0)}, + {(960, 0), (962, 0)}, + {(1002, 0), (987, 0), (988, 0), (996, 1)}, + {(987, 5), (1004, 0), (994, 0)}, + {(976, 0), (989, 0)}, + {(993, 0), (997, 0)}, + {(983, 0), (998, 2)}, + {(979, 0), (1005, 3), (1002, 2)}, + {(1000, 0), (986, 0)}, + {(1023, 0), (1027, 2)}, + {(1039, 0), (1028, 0)}, + {(1051, 0), (1048, 5)}, + {(1078, 1), (1077, 3), (1082, 3)}, + {(1067, 0), (1068, 0)}, + {(1085, 0), (1082, 0), (1086, 0)}, + {(1090, 2), (1094, 4)}, + {(1090, 0), (1094, 0)}, + {(1121, 0), (1122, 0)}, + {(1123, 0), (1124, 0)}, + {(1148, 0), (1149, 0)}, + {(1183, 2), (1182, 0)}} + REPS = REPS/sort + + for S in REPS list (#S - # (S/(lab -> invariants4 Xs#lab)//unique)) + for S in REPS list {#S, # (S/(lab -> invariants4 Xs#lab)//unique)} + + #REPS == 118 -- this is the number of sets that we don't know yet how to separate + -- without use of GV's (which is heuristic). + + sort REPS#0 + X1 = Xs#(14,0) + X2 = Xs#(14,1) + invariants4 X1 + invariants4 X2 + F1 = cubicForm X1 + F2 = cubicForm X2 + sing = (F) -> trim saturate(F + ideal jacobian F) + decompose(sub(sing F1, RQ)) + sing F2 + +/// + +/// + -- 2 Jan 2023. + -- An attempt to automate the following: + -- 1. create one hash table with all of the Qs, Xs. + -- 2. separate the Xs via invariants4 (all the ones except point counts) + -- 3. for each invariant, use topology to separate. +-* + restart + debug needsPackage "StringTorics" +*- + + -- Example analysis of topologies for h11=4. + --topes = kreuzerSkarke(4, Limit => 10000); + --assert(#topes == 1197) + --h12s = topes/hodgeNumbers/last//unique//sort + h12s = {28, 34, 36, 37, 40, 42, 44, 46, 48, 49, 50, 52, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 76, 77, 78, 79, 80, 81, 82, 84, 85, 86, 88, + 89, 90, 91, 92, 93, 94, 96, 97, 98, 100, 101, 102, 104, 106, + 108, 109, 110, 112, 114, 116, 118, 120, 121, 122, 124, 126, + 128, 130, 136, 142, 144, 148, 154, 162, 166, 178, 190, 194, + 202, 208, 214, 226, 238} + + nontorsionfrees = {(0, 0), (3, 0), (4, 0), (5, 0), (12, 0), (15, 0), + (796, 0), (796, 1), (800, 0), (803, 0), (1059, 0), (1060, 0), (1064, 0), + (1065, 0), (1134, 0), (1135, 0), (1151, 0), (1153, 0), (1155, 0), (1155, 1)} + + db4name = (h12) -> "cys-ntfe-h11-4-h12-"|h12|".dbm" + RZ = ZZ[a,b,c,d]; + RQ = QQ (monoid RZ); + DB = hashTable for h in h12s list h => readCYDatabase("../m2-examples/"|db4name h, Ring => RZ); + Qs = new MutableHashTable + Xs = new MutableHashTable + for a in keys DB do ( + (Q1s, X1s) = DB#a; + for q in sort keys Q1s do Qs#q = Q1s#q; + for k in sort keys X1s do if not member(k, nontorsionfrees) then Xs#k = X1s#k; + ); + Xs = new HashTable from Xs; + Qs = new HashTable from Qs; + #(keys Xs) == 1994 -- 2014 total for all, including torsions. + assert(# sort keys Xs == 2014 - #nontorsionfrees) + + elapsedTime H = partition(invariants4, values Xs); -- 135 sec + H1 = hashTable for k in keys H list k => (H#k)/label; + elapsedTime INV = for k in sort keys H1 list k => partitionByTopology(H1#k, Xs, 15); -- 751 sec + -- number of different topologies + +----------------------------------- + -- new code: let's first see which ones are identical. + -- XXXX + # keys Xs == 1994 + Diff1 = partition(lab -> (X := Xs#lab; {c2Form X, cubicForm X}), sort keys Xs); + select(pairs Diff1, kv -> # kv#1 > 1) + + elapsedTime H = partition(lab -> ( + X := Xs#lab; + elapsedTime join({hh^(1,1) X, hh^(1,2) X}, invariantsAll Xs#lab) + ), sort keys Xs); -- 295 sec + #(keys H) == 1294 -- this leaves out h11, h12. + #(keys H) == 1300 -- this has h11, h12. Interesting. + + elapsedTime INV = for k in sort keys H list k => partitionByTopology(H#k, Xs, 15); -- 751 sec + -- number of different topologies: is at least 1300, at most XXX + + elapsedTime H4 = partition(lab -> elapsedTime invariants4 Xs#lab, sort keys Xs); + #(keys H4) == 1040 + + REPS = for k in INV list ( + H := last k; -- a hash table + K := keys H; + if #K == 1 then continue + else K) + + # select(INV, k -> #k#1 == 1) == 1248 + # select(INV, k -> #k#1 == 2) == 47 + # select(INV, k -> #k#1 == 3) == 5 + # select(INV, k -> #k#1 > 3) == 0 + + #REPS==52 + -- # different topologies is bounded above by 1248 + 2*47 + 3*5 == 1357 + -- bounded below by 1248 + 52 = 1300 + + REPS#0 + hashTable invariantsAll Xs#(254,5) + hashTable invariantsAll Xs#(228,1) + hashTable invariantsAll Xs#(REPS#2#0) +---------------------------------- + + + -- separate topologies: + -- output is a list of lists {S0, S1, S2, ..., Sr} + -- each CY in Si is not equivalent to any in Sj, i!=j. + -- each pair of CY's in a specific Si are not proved to be distinct (but are likely distinct?) + -- every CY in h11=4 database is knoqn to be equivalent to one of these + -- (Question: or are they all there in one of these lists?) + TOP1 = for k in INV list for a in keys last k list ( + prepend(a, ((last k)#a)/first) + ); + netList(TOP1/(a -> a/(a1->#a1))) + + REPS = for k in INV list ( + H := last k; -- a hash table + K := keys H; + if #K == 1 then continue + else K) + + ONEONLY = for k in INV list ( + H := last k; -- a hash table + K := keys H; + if #K == 1 then first K else continue) + + #INV == 1040 + #ONEONLY == 932 + #REPS = 108 + + netList REPS + REPS = { + {(14, 1), (14, 0)}, + {(53, 0), (38, 0)}, + {(35, 0), (39, 0)}, + {(30, 0), (38, 4)}, + {(80, 6), (80, 2)}, + {(96, 0), (126, 0)}, + {(135, 1), (138, 0)}, + {(180, 0), (179, 2)}, + {(265, 0), (250, 0), (265, 1), (236, 0), (228, 1)}, + {(235, 0), (262, 0)}, + {(225, 2), (260, 2)}, + {(265, 2), (235, 1)}, + {(265, 3), (228, 0)}, + {(250, 1), (254, 2)}, + {(249, 1), (246, 0)}, + {(210, 0), (258, 0)}, + {(209, 3), (284, 1), (261, 1)}, + {(240, 3), (278, 1)}, + {(319, 0), (313, 0)}, + {(316, 0), (322, 0)}, + {(334, 2), (328, 1), (329, 0)}, + {(331, 0), (337, 1), (339, 3)}, + {(334, 1), (329, 1)}, + {(339, 5), (337, 0)}, + {(385, 2), (385, 3)}, + {(364, 1), (377, 0)}, + {(356, 0), (395, 6)}, + {(379, 1), (395, 2), (378, 0)}, + {(383, 0), (356, 1)}, + {(397, 0), (350, 0)}, + {(387, 4), (387, 0)}, + {(377, 2), (364, 0)}, + {(416, 0), (441, 0), (438, 0)}, + {(400, 0), (403, 0), (405, 0), (414, 0)}, + {(436, 0), (433, 0)}, + {(419, 0), (419, 2)}, + {(436, 1), (433, 1)}, + {(451, 0), (455, 1)}, + {(473, 0), (478, 0)}, + {(458, 5), (458, 1)}, + {(458, 3), (458, 0)}, + {(508, 0), (514, 0)}, + {(512, 1), (505, 0)}, + {(507, 0), (519, 3)}, + {(526, 1), (527, 0), (518, 3), (522, 0)}, + {(524, 0), (518, 0)}, + {(529, 0), (510, 0)}, + {(550, 0), (538, 0)}, + {(556, 0), (562, 0)}, + {(553, 0), (554, 0)}, + {(552, 0), (551, 2)}, + {(559, 0), (577, 0)}, + {(540, 0), (545, 0)}, + {(588, 0), (586, 0)}, + {(616, 0), (606, 0)}, + {(650, 0), (650, 1), (667, 1), (650, 3), (656, 0), (666, 9), (630, 0)}, + {(643, 0), (649, 0), (626, 0)}, + {(628, 0), (653, 0)}, + {(647, 0), (669, 0)}, + {(688, 1), (685, 0)}, + {(687, 0), (684, 1)}, + {(693, 0), (694, 0)}, + {(712, 0), (714, 0), (706, 0), (707, 0), (709, 0)}, + {(716, 3), (705, 0)}, + {(715, 0), (704, 0)}, + {(738, 3), (737, 1)}, + {(731, 0), (740, 1)}, + {(773, 7), (773, 0)}, + {(770, 1), (774, 5)}, + {(771, 0), (771, 1)}, + {(781, 2), (781, 1)}, + {(815, 0), (810, 0), (851, 0), (884, 0), (820, 0), (869, 0)}, + {(884, 7), (881, 0), (884, 2)}, + {(835, 2), (806, 0), (822, 0)}, + {(878, 0), (885, 1), (886, 0)}, + {(879, 9), (808, 0), (845, 0), (896, 0), (865, 0), (879, 3), (896, 3)}, + {(825, 0), (862, 0)}, + {(863, 0), (887, 0)}, + {(876, 0), (854, 0)}, + {(900, 0), (901, 0)}, + {(935, 17), (938, 0)}, + {(938, 3), (933, 0)}, + {(930, 1), (934, 0), (922, 4)}, + {(932, 0), (916, 0), (917, 0)}, + {(922, 1), (930, 0)}, + {(938, 11), (933, 5)}, + {(935, 0), (937, 0), (915, 0), (924, 0), (935, 5)}, + {(943, 0), (953, 0), (958, 0)}, + {(960, 0), (962, 0)}, + {(987, 0), (988, 0), (1002, 0)}, + {(987, 5), (1004, 0), (994, 0)}, + {(976, 0), (989, 0)}, + {(993, 0), (997, 0)}, + {(983, 0), (998, 2)}, + {(979, 0), (1005, 3), (1002, 2)}, + {(1000, 0), (986, 0)}, + {(1023, 0), (1027, 2)}, + {(1039, 0), (1028, 0)}, + {(1051, 0), (1048, 5)}, + {(1078, 1), (1077, 3), (1082, 3)}, + {(1067, 0), (1068, 0)}, + {(1085, 0), (1082, 0), (1086, 0)}, + {(1090, 2), (1094, 4)}, + {(1090, 0), (1094, 0)}, + {(1121, 0), (1122, 0)}, + {(1123, 0), (1124, 0)}, + {(1148, 0), (1149, 0)}, + {(1183, 2), (1182, 0)}} + REPS = REPS/sort; + netList REPS + -- The ones in REPS are the ones we need to separate (if they are truly different!). + + sing = F -> trim(ideal F + ideal jacobian F) + toQQ = I -> sub(I, RQ) + + --- REPS#0 + LFs = for lab in REPS#0 list (X := Xs#lab; {toQQ c2Form X, toQQ cubicForm X}) + netList LFs + + F0 = LFs#0#1 + F1 = LFs#1#1 + for a in {-2,-2,-2,-2}..{2,2,2,2} list if sub(F0, matrix{a}) == 0 then a else continue + for a in {-2,-2,-2,-2}..{2,2,2,2} list if sub(F1, matrix{a}) == 0 then a else continue + saturate sing F0 + saturate sing F1 + factor(F0 - F1) + + findLinearMaps(List, List) := List => (LF1, LF2) -> ( + -- not complete... + (L1,F1) := toSequence LF1; + (L2,F2) := toSequence LF2; + RQ :=ring L1; + n := numgens RQ; + t := symbol t; + T := QQ[t_(1,1)..t_(n,n)]; + TR := T (monoid RQ); + M := genericMatrix(T, n, n); + phi := map(TR, TR, M) + ) + + phi = findLinearMaps(LFs#0, LFs#1) + T = target phi + TC = coefficientRing T + phi + + (L1,F1) = toSequence (LFs#0/(g -> sub(g, T))) + (L2,F2) = toSequence (LFs#1/(g -> sub(g, T))) + L1 = L1/2 + L2 = L2/2 + -- now we make the ideals for each key, and each permutation. + I1 = trim sub(ideal last coefficients (phi L1 - L2), TC) + I2 = trim sub(ideal last coefficients (phi F1 - F2), TC) + I = trim(I1 + I2); + Tp = ZZ/101[t_(1,1), t_(1,2), t_(1,3), t_(1,4), t_(2,1), t_(2,2), t_(2,3), t_(2,4), t_(3,1), t_(3,2), t_(3,3), t_(3,4), t_(4,1), t_(4,2), t_(4,3), t_(4,4)] + psi = map(Tp, TC, gens Tp) + J = psi I + gbTrace=3 + gens gb(J, DegreeLimit => 10); + ids := for k in keys gv1 list ( + perms := permutations(#gv1#k); + mat1 := transpose matrix gv1#k; + mat2 := transpose matrix gv2#k; + for p in perms list ( + I := trim ideal (M * mat1 - mat2_p); + if I == 1 then continue else I + ) + ); + topval := ids/(x -> #x - 1); + zeroval := ids/(x -> 0); + fullIdeals := for a in zeroval .. topval list ( + J := trim sum for i from 0 to #ids-1 list ids#i#(a#i); + if J == 1 then continue else J + ); + Ms := for i in fullIdeals list M % i; + --newMs := select(Ms, m -> (d := det m; d == 1 or d == -1)); + --if any(newMs, m -> support m =!= {}) then << "some M is not reduced to a constant" << endl; + Ms + ) + + hessian = (F) -> diff(vars ring F, diff(transpose vars ring F, F)) + + positions(REPS, x -> #x == 5) == {8, 62, 86} + + LFs = for lab in REPS#0 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) + netList for a in LFs list (betti res sing toQQ a#1) + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) + + LFs = for lab in REPS#1 list (X := Xs#lab; {c2Form X, cubicForm X}); + for a in LFs list (decompose sing toQQ a#1) + for a in LFs list (betti res sing toQQ a#1) -- different. + + LFs = for lab in REPS#2 list (X := Xs#lab; {c2Form X, cubicForm X}); + for a in LFs list (decompose sing toQQ a#1) + for a in LFs list (betti res sing toQQ a#1) + for a in LFs list (saturate sing2 ideal a) -- different + + LFs = for lab in REPS#3 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) + netList for a in LFs list (betti res sing toQQ a#1) + netList for a in LFs list (saturate sing2 ideal a) -- could be the same + netList for a in LFs list (factor det hessian toQQ a#1) -- contents of hessians are distinct, so I think these must be distinct. + + LFs = for lab in REPS#4 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) + netList for a in LFs list (betti res sing toQQ a#1) + netList for a in LFs list (saturate sing2 ideal a) + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same. + + LFs = for lab in REPS#5 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- different + netList for a in LFs list (betti res sing toQQ a#1) -- actually all 4 invariants are different! + netList for a in LFs list (saturate sing2 ideal a) + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#6 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) + netList for a in LFs list (factor det hessian toQQ a#1) -- seem to have different contents, so different... + + LFs = for lab in REPS#7 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#8 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,2,4 might be the same? 1,3 are diff. + + LFs = for lab in REPS#9 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#10 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- different + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#11 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#12 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- hessians have different content + + LFs = for lab in REPS#13 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same. + + LFs = for lab in REPS#14 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same. + + LFs = for lab in REPS#15 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- different content + + LFs = for lab in REPS#16 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- (0,2), 1 + netList for a in LFs list (betti res sing toQQ a#1) -- 0,1,2 all different + netList for a in LFs list (saturate sing2 ideal a) -- all different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#17 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different content + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#18 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same + + LFs = for lab in REPS#19 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same + + LFs = for lab in REPS#20 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- 0, (1,2) + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 1,2 could be same + + LFs = for lab in REPS#21 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1,2 could all be same + + LFs = for lab in REPS#22 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be the same + + LFs = for lab in REPS#23 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be the same + + LFs = for lab in REPS#24 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- different + + LFs = for lab in REPS#25 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same. + + LFs = for lab in REPS#26 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- different + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- different + + LFs = for lab in REPS#27 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- (0,1), 2 + netList for a in LFs list (saturate sing2 ideal a) -- all different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#28 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same (can check) + + LFs = for lab in REPS#29 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same + + LFs = for lab in REPS#30 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same + + LFs = for lab in REPS#31 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same + + LFs = for lab in REPS#32 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- (0,2), 1 + netList for a in LFs list (saturate sing2 ideal a) -- all different + netList for a in LFs list (factor det hessian toQQ a#1) -- all different + + LFs = for lab in REPS#33 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- (0,1,2), 3 + netList for a in LFs list (saturate sing2 ideal a) -- (0,1), 2, 3 + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be the same. + + LFs = for lab in REPS#34 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same. + + LFs = for lab in REPS#35 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same. + + LFs = for lab in REPS#36 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same. + + LFs = for lab in REPS#37 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same. + + LFs = for lab in REPS#38 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same. + + LFs = for lab in REPS#39 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- different + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- different + + LFs = for lab in REPS#40 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- different + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#41 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- different + netList for a in LFs list (betti res sing toQQ a#1) -- different + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#42 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- different + netList for a in LFs list (betti res sing toQQ a#1) -- different + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#43 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- different + netList for a in LFs list (betti res sing toQQ a#1) -- different + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#44 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- (0,1,2), 3 + netList for a in LFs list (saturate sing2 ideal a) -- all 4 different. + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#45 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- different contents + + LFs = for lab in REPS#46 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same + + LFs = for lab in REPS#47 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- different contents + + LFs = for lab in REPS#48 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- different contents + + LFs = for lab in REPS#49 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- different contents + + LFs = for lab in REPS#50 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same + + LFs = for lab in REPS#51 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same + + LFs = for lab in REPS#52 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same + + LFs = for lab in REPS#53 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- different contents + + LFs = for lab in REPS#54 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same + + LFs = for lab in REPS#55 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- (0,1,3,4), 2, (5,6) + netList for a in LFs list (betti res sing toQQ a#1) -- (0,3,4), 1, 2, 5, 6 + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,3,4 could be same + + LFs = for lab in REPS#56 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1,2 could all be same + + LFs = for lab in REPS#57 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could all be same + + LFs = for lab in REPS#58 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could all be same + + LFs = for lab in REPS#59 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#60 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- different + netList for a in LFs list (betti res sing toQQ a#1) --different + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#61 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#62 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- 0, (1,2,3,4) + netList for a in LFs list (factor det hessian toQQ a#1) -- (1,2,3,4) could be same + + LFs = for lab in REPS#63 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same + + LFs = for lab in REPS#64 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- different contents + + LFs = for lab in REPS#65 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- different + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#66 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#67 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- different + netList for a in LFs list (betti res sing toQQ a#1) -- dofferent + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#68 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#69 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- different + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#70 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#71 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- (0,1,3), (2,5), 4 + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,1,3) could be same, (2,5) could be same. + + LFs = for lab in REPS#72 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- all 3 different + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- all different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#73 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- (0,2), 1 + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,2) could be same. + + LFs = for lab in REPS#74 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- all 3 different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#75 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- (0,4,6), (1,2,3), 5. + netList for a in LFs list (betti res sing toQQ a#1) -- (0,4,6), 5, (1,2), 3, 5. + netList for a in LFs list (saturate sing2 ideal a) -- (0,6) rest distinct. + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,6) possibly same + + LFs = for lab in REPS#76 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#77 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 possibly same. ACTUALLY: they are identical!! How did that get through? Totally different polytopes, exact same L, F... + + LFs = for lab in REPS#78 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 possibly same. + + LFs = for lab in REPS#79 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 possibly same. + + LFs = for lab in REPS#80 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- different + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#81 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 possibly same + + LFs = for lab in REPS#82 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- (0,1), 2 + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 possibly same + + LFs = for lab in REPS#83 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) --(0,2), 1 + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,2 possibly same + + LFs = for lab in REPS#84 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 possibly same + + LFs = for lab in REPS#85 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 possibly same + + LFs = for lab in REPS#86 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- (0,3), (1,4), 2. + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,3) and (1,4) possibly same + + LFs = for lab in REPS#87 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- (0,2), 1 + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,2) possibly same + + LFs = for lab in REPS#88 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#89 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- all 3 different + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#90 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- 0, (1,2) + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- (1,2) could be same. + + LFs = for lab in REPS#91 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,1) could be same. + + LFs = for lab in REPS#92 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,1) could be same. + + LFs = for lab in REPS#93 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,1) could be same. + + LFs = for lab in REPS#94 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,1,2) could be same. + + LFs = for lab in REPS#95 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,1) could be same. + + LFs = for lab in REPS#96 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- different + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#97 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- different + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#98 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#99 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- (0,2), 1 + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,2) could be same. + + LFs = for lab in REPS#100 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,1) could be same. + + LFs = for lab in REPS#101 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,1,2) could be same. + + LFs = for lab in REPS#102 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,1) could be same. + + LFs = for lab in REPS#103 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,1) could be same. + + LFs = for lab in REPS#104 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,1) could be same. + + LFs = for lab in REPS#105 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,1) could be same. + + LFs = for lab in REPS#106 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,1) could be same. + + LFs = for lab in REPS#107 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,1) could be same. + + + -- REP#8 + LFs = for lab in REPS#8 list (X := Xs#lab; {c2Form X, cubicForm X}) + F0 = LFs#0#1 + F1 = LFs#1#1 + F2 = LFs#2#1 + F3 = LFs#3#1 + F4 = LFs#4#1 + L0 = LFs#0#0 + L1 = LFs#1#0 + L2 = LFs#2#0 + L3 = LFs#3#0 + L4 = LFs#4#0 + + -- STEP 1 singular locus over QQ. All have 1 singular point over QQ. + decompose sing toQQ F0 + decompose sing toQQ F2 + decompose sing toQQ F4 + + decompose sing toQQ F1 -- different + + decompose sing toQQ F3 -- different + + betti res inverseSystem toQQ F0 + betti res inverseSystem toQQ F2 + betti res inverseSystem toQQ F4 + + sing2 = I -> trim(I + minors(2, jacobian I)) + s0 = saturate sing2 ideal LFs#0 + s1 = saturate sing2 ideal LFs#2 + s2 = saturate sing2 ideal LFs#4 + + factor det hessian toQQ F0 + factor det hessian toQQ F2 + factor det hessian toQQ F4 + + -- promising: each of these have 5 ppints. + decompose minors(3, hessian toQQ F0) + decompose minors(3, hessian toQQ F2) + decompose minors(3, hessian toQQ F4) + + ---------------------------------------------------- + -- NOT DONE YET + positions(REPS, x -> #x == 6) == {71} + LFs = for lab in REPS#71 list (X := Xs#lab; {c2Form X, cubicForm X}) + F0 = LFs#0#1 + F1 = LFs#1#1 + F2 = LFs#2#1 + F3 = LFs#3#1 + F4 = LFs#4#1 + F5 = LFs#5#1 + L0 = LFs#0#0 + L1 = LFs#1#0 + L2 = LFs#2#0 + L3 = LFs#3#0 + L4 = LFs#4#0 + L5 = LFs#5#0 + + -- STEP 1 singular locus over QQ. All have 1 singular point over QQ. + decompose sing toQQ F0 + decompose sing toQQ F1 + decompose sing toQQ F2 + decompose sing toQQ F3 + decompose sing toQQ F4 + decompose sing toQQ F5 + + -- (F0,F1,F2,F3,F4,F5) doesn't separate them at all. + -- STEP 2: inverse systems + betti res inverseSystem toQQ F0 + betti res inverseSystem toQQ F1 + betti res inverseSystem toQQ F2 + betti res inverseSystem toQQ F3 + betti res inverseSystem toQQ F4 + betti res inverseSystem toQQ F5 + + -- all the same still! + + -- STEP 3. jacobian over ZZ + sing2 = I -> trim(I + minors(2, jacobian I)) + s0 = saturate sing2 ideal LFs#0 + s1 = saturate sing2 ideal LFs#1 + s2 = saturate sing2 ideal LFs#2 + s3 = saturate sing2 ideal LFs#3 + s4 = saturate sing2 ideal LFs#4 + s5 = saturate sing2 ideal LFs#5 + + s0_0, s1_0, s3_0 + s2_0, s5_0 + s4_0 + -- (F0,F1,F3), (F2,F5), F4. + -- NOT DONE: the stuff below this doesn't yet separate these 3. + + Rp = ZZ/467[a,b,c,d] + saturate sub(sing2 ideal LFs#2, Rp) + saturate sub(sing2 ideal LFs#5, Rp) + + factor det hessian toQQ F0 + factor det hessian toQQ F1 + factor det hessian toQQ F3 + + factor det hessian toQQ F2 + factor det hessian toQQ F5 + + factor det hessian toQQ F4 + + -- TODO: still need to separate both of these groups. + decompose minors(2, hessian toQQ F0) + decompose minors(2, hessian toQQ F1) + decompose minors(2, hessian toQQ F3) + + decompose minors(2, hessian toQQ F2) + decompose minors(2, hessian toQQ F5) + s0 = gens gb saturate sing F0 + s1 = gens gb saturate sing F1 + s1 = saturate sing2 ideal LFs#1 + s2 = saturate sing2 ideal LFs#2 + s3 = saturate sing2 ideal LFs#3 + s4 = saturate sing2 ideal LFs#4 + s5 = saturate sing2 ideal LFs#5 + + --------------------------------------------- + -- REPS#55 + positions(REPS, x -> #x == 7) == {55, 75} + LFs = for lab in REPS#55 list (X := Xs#lab; {c2Form X, cubicForm X}) + F0 = LFs#0#1 + F1 = LFs#1#1 + F2 = LFs#2#1 + F3 = LFs#3#1 + F4 = LFs#4#1 + F5 = LFs#5#1 + F6 = LFs#6#1 + L0 = LFs#0#1 + L1 = LFs#1#0 + L2 = LFs#2#0 + L3 = LFs#3#0 + L4 = LFs#4#0 + L5 = LFs#5#0 + L6 = LFs#6#0 + + -- STEP 1 singular locus over QQ + decompose sing toQQ F0 + decompose sing toQQ F1 + decompose sing toQQ F3 + decompose sing toQQ F4 + + decompose sing toQQ F2 + + decompose sing toQQ F5 -- 2 pts, irred over QQ + decompose sing toQQ F6 + -- (F0,F1,F3,F4), F2, (F5,F6) + + -- STEP 2 inverse system + betti res inverseSystem toQQ F0 + betti res inverseSystem toQQ F1 -- distinct from F0,F3,F4. + betti res inverseSystem toQQ F3 + betti res inverseSystem toQQ F4 + + betti res inverseSystem toQQ F2 + + betti res inverseSystem toQQ F5 + betti res inverseSystem toQQ F6 -- F6 distinct from F5. + -- (F0,F3,F4), F1, F2, F5, F6. + + -- STEP 3. jacobian over ZZ + sing2 = I -> trim(I + minors(2, jacobian I)) + s0 = saturate sing2 ideal LFs#0 + s3 = saturate sing2 ideal LFs#3 + s4 = saturate sing2 ideal LFs#4 + + s5 = saturate sing2 ideal LFs#5 + + s6 = saturate sing2 ideal LFs#6 + + s1 = saturate sing2 ideal LFs#1 -- different from F0 + + s2 = saturate sing2 ideal LFs#2 + + s0_0, s3_0, s4_0, s1_0, s2_0, s5_0, s6_0 + -- (F0,F3,F4), F1, F2, F5, F6. Same as step 1+2. + + -- STEP 4. Separate F0, F3, F4 + factor det hessian toQQ F0 + factor det hessian toQQ F3 + factor det hessian toQQ F4 -- all similar structure... + + -- first compare F0, F3: F0, F3 are equiv over QQ, not ZZ. + (A, phi) = genericLinearMap RQ + use target phi + start1 = {{b+3*c, a+d}, + {3*c+2*d, a}, + {a+2*c, a+b-c+d}} + start2 = {{b+3*c, a+d}, + {3*c+2*d, a+b-c+d}, + {a+2*c, a}} + signs = (toList((set{-1,1}) ** set{-1,1} ** set{-1,1}))/splice/toList -- note: not all these signs are needed... + chsigns = (L, sgn) -> for i from 0 to #L-1 list {L#i#0, sgn#i * L#i#1} + set1 = for sgn in signs list chsigns(start1, sgn) + set2 = for sgn in signs list chsigns(start2, sgn) + allsets = join(set1, set2) + netList for L in allsets list ( + (A0, phi0) = linearEquationConstraints(A, phi, append(L, {sub(F0, target phi), sub(F3, target phi)}), {}); + if A0 == 0 then continue; + phi1 = map(RQ, RQ, transpose sub(A0, QQ)); + {A0, det A0, phi1 toQQ(LFs#0#0) - toQQ LFs#3#0, phi1 toQQ LFs#0#1 - toQQ LFs#3#1} + ) + + -- second compare F0, F4: -- to see yet: F0, F4 are equiv over ZZ, but X0, X4 are equiv over QQ. + (A, phi) = genericLinearMap RQ + use target phi + factor det hessian toQQ F0 + factor det hessian toQQ F4 + start1 = {{b+3*c, c+d}, + {3*c+2*d, d}, + {a+2*c, a-b-c}} + start2 = {{b+3*c, c+d}, + {3*c+2*d, a-b-c}, + {a+2*c, d}} + signs = (toList((set{-1,1}) ** set{-1,1} ** set{-1,1}))/splice/toList -- note: not all these signs are needed... + chsigns = (L, sgn) -> for i from 0 to #L-1 list {L#i#0, sgn#i * L#i#1} + set1 = for sgn in signs list chsigns(start1, sgn) + set2 = for sgn in signs list chsigns(start2, sgn) + allsets = join(set1, set2) + netList for L in allsets list ( + (A0, phi0) = linearEquationConstraints(A, phi, append(L, {sub(F0, target phi), sub(F4, target phi)}), {}); + if A0 == 0 then continue; + phi1 = map(RQ, RQ, transpose sub(A0, QQ)); + {A0, det A0, phi1 toQQ(LFs#0#0) - toQQ LFs#4#0, phi1 toQQ LFs#0#1 - toQQ LFs#4#1} + ) + + -- second compare F0 to F3 -- only equiv over QQ. + (A, phi) = genericLinearMap RQ + use target phi + factor det hessian toQQ F3 + factor det hessian toQQ F4 + start1 = {{a+d, c+d}, + {a, d}, + {a+b-c+d, a-b-c}} + start2 = {{a+d, c+d}, + {a, a-b-c}, + {a+b-c+d, d}} + signs = (toList((set{-1,1}) ** set{-1,1} ** set{-1,1}))/splice/toList -- note: not all these signs are needed... + chsigns = (L, sgn) -> for i from 0 to #L-1 list {L#i#0, sgn#i * L#i#1} + set1 = for sgn in signs list chsigns(start1, sgn) + set2 = for sgn in signs list chsigns(start2, sgn) + allsets = join(set1, set2) + netList for L in allsets list ( + (A0, phi0) = linearEquationConstraints(A, phi, append(L, {sub(F3, target phi), sub(F4, target phi)}), {}); + if A0 == 0 then continue; + phi1 = map(RQ, RQ, transpose sub(A0, QQ)); + {A0, det A0, phi1 toQQ(LFs#3#0) - toQQ LFs#4#0, phi1 toQQ LFs#3#1 - toQQ LFs#4#1} + ) + + -- Upshot: these 7 are all distinct. + + -- REPS#75 + positions(REPS, x -> #x == 7) == {55, 75} + LFs = for lab in REPS#75 list (X := Xs#lab; {toQQ c2Form X, toQQ cubicForm X}) + F1 = LFs#0#1 + F2 = LFs#1#1 + F3 = LFs#2#1 + F4 = LFs#3#1 + F5 = LFs#4#1 + F6 = LFs#5#1 + F7 = LFs#6#1 + + LFZs = for lab in REPS#75 list (X := Xs#lab; {c2Form X, cubicForm X}) + FZ1 = LFZs#0#1 + FZ2 = LFZs#1#1 + FZ3 = LFZs#2#1 + FZ4 = LFZs#3#1 + FZ5 = LFZs#4#1 + FZ6 = LFZs#5#1 + FZ7 = LFZs#6#1 + + -- STEP 1: consider singular loci over QQ. + -- one singular point + decompose sing F1 + decompose sing F5 + decompose sing F7 + -- two singular points + decompose sing F4 + decompose sing F2 + decompose sing F3 + -- three singular points + decompose sing F6 + -- at this point: (F1,F5,F7), (F2,F3,F4), F6. ones in parens might be equivalent. + + -- STEP 2: inverse systems (over QQ) + betti res inverseSystem F1 + betti res inverseSystem F5 + betti res inverseSystem F7 + + betti res inverseSystem F4 -- F4 on its own + + betti res inverseSystem F2 + betti res inverseSystem F3 -- F2, F3 have different singular loci mod 19. + + betti res inverseSystem F6 -- F6 + -- at this point: (F1,F5,F7), F4, (F2,F3), F6. ones in parens might be equivalent. + + -- STEP 3: singular locus of (L,F) over ZZ + sing2 = I -> trim(I + minors(2, jacobian I)) + s1 = saturate sing2 ideal LFZs#0 + s5 = saturate sing2 ideal LFZs#4 -- this shows that F5 is different from (F1, F7). + s7 = saturate sing2 ideal LFZs#6 + + s4 = saturate sing2 ideal LFZs#3 + s2 = saturate sing2 ideal LFZs#1 + s3 = saturate sing2 ideal LFZs#2 -- this shows that F2 is different from F3. + -- (it also show separately that F4 is distinct from F2 and F3). + -- at this point: (F1,F7), F5, F4, F2, F3, F6. + + -- STEP 4: separate F1, F7. This one is a bit tricky, as in fact F1 and F7 are equivalent over ZZ! + -- But they are not equivalent when the c2 form is taken into account. + -- For this one, we compute the Hessian of F1, F7. + factor det hessian F1 -- (b+2*d)*(b+3*d)^2*(a+b+2*d)*(-20736) + factor det hessian F7 -- (a-d)*(a+c)^2*(a-b)*(-20736) + -- this shows that we seek a matrix over ZZ (or QQ, if we are interested) + -- with b+3d --> \pm (a+c) + -- with b+2d --> \pm (a-d) OR \pm (a-b) + -- with a+b+2d --> \pm (a-d) OR \pm (a-b) [but for the other linear form]. + -- note: this fixes phi(a), phi(b), phi(d), leaving phi(c) not known. + -- and F1 is linear in c. + -- all the choices: + (A, phi) = genericLinearMap RQ + use target phi + start1 = {{b+3*d, a+c}, {b+2*d, a-d}, {a+b+2*d, a-b}} + start2 = {{b+3*d, a+c}, {b+2*d, a-b}, {a+b+2*d, a-d}} + signs = (toList((set{-1,1}) ** set{-1,1} ** set{-1,1}))/splice/toList -- note: not all these signs are needed... + chsigns = (L, sgn) -> for i from 0 to #L-1 list {L#i#0, sgn#i * L#i#1} + set1 = for sgn in signs list chsigns(start1, sgn) + set2 = for sgn in signs list chsigns(start2, sgn) + allsets = join(set1, set2) + netList for L in allsets list ( + (A0, phi0) = linearEquationConstraints(A, phi, append(L, {sub(F1, target phi), sub(F7, target phi)}), {}); + if A0 == 0 then continue; + phi1 = map(RQ, RQ, transpose sub(A0, QQ)); + {A0, det A0, phi1 (LFs#0#0) - LFs#6#0, phi1 (LFs#0#1) - LFs#6#1} + ) + -- this shows that F1, F7 are in fact equivalent over ZZ, but X1, X7 are distinct topologically. + -- it also shows there is a matrix over QQ, with det 1, which does map L1 to L7, F1 to F7. +/// + +/// + -- Example use of a constructed data base. + restart + debug needsPackage "StringTorics" + RZ = ZZ[a,b,c] + F = openDatabase "../m2-examples/foo-h11-3.dbm" -- note: + Xlabels = sort select(keys F, k -> (a := value k; instance(a, Sequence))) + Qlabels = sort select(keys F, k -> (a := value k; instance(a, ZZ))) + assert(#Xlabels == 526) + assert(#Qlabels == 244) + elapsedTime Qs = for k in Qlabels list cyPolytope(F#k, ID => value k); + elapsedTime Xs = for k in Xlabels list cyData(F#k, i -> Qs#i, Ring => RZ); + assert(Xs/label === Xlabels/value) + close F + + Xs = hashTable for x in Xs list (label x) => x; + + -- these are the ones we will consider. + torsionfrees = for lab in sort keys Xs list ( + X := Xs#lab; + V := normalToricVariety(rays X, max X); + if classGroup V === ZZ^3 then lab else continue + ) + + -- 6 polytopes are not torsion free (i.e. classGroup is not torsion free) + nontorsionfrees = for lab in sort keys Xs list ( + X := Xs#lab; + V := normalToricVariety(rays X, max X); + if classGroup V != ZZ^3 then lab else continue + ) + nontorsionfrees == {(0, 0), (9, 0), (9, 1), (10, 0), (10, 1), (10, 2), (55, 0), (62, 0), (232, 0)} + + nonFavorables = select(sort keys Xs, lab -> not isFavorable cyPolytope Xs#lab) + favorables = select(sort keys Xs, lab -> isFavorable cyPolytope Xs#lab) + + elapsedTime H = partition(lab -> ( + X := Xs#lab; + elapsedTime netList join({"h11" => hh^(1,1) X, "h12" => hh^(1,2) X}, invariantsAll Xs#lab) + ), sort torsionfrees); -- 18 sec + #(keys H) == 195 + H + + + elapsedTime INV = for k in sort keys H list k => partitionByTopology(H#k, Xs, 15); --34 sec + + REPS = for k in INV list ( + H := last k; -- a hash table + K := keys H; + if #K == 1 then continue + else k#0 => K) + #REPS == 9 + + positions(INV, k -> #(keys (k#1)) > 1) + netList INV_{26, 56, 63, 64, 76, 120, 121, 156, 182} + REPS = for k in INV list ( + H := last k; -- a hash table + K := keys H; + if #K == 1 then continue + else K) + + X1 = Xs#(34,0) + X2 = Xs#(37,0) + L1 = c2Form X1 + L2 = c2Form X2 + F1 = cubicForm X1 + F2 = cubicForm X2 + + hashTable invariantsAll X1, hashTable invariantsAll X2 + + + + -- XXXX + elapsedTime H1 = partition(lab -> topologicalData Xs#lab, torsionfrees); -- take one from each. + netList (values H1) + SAME = hashTable for k in keys H1 list (first H1#k) => drop(H1#k, 1) + + labelYs = sort keys SAME -- these have non-equal topological data + #labelYs == 286 -- if torsionfrees is used + #labelYs == 291 -- all are equivalent to one of these, so there are 291 possible different topologies + -- (but probably less than this). + + --elapsedTime INV = partition(lab -> invariants Xs#lab, labelYs); -- 98 sec (FIXME: about 200 seconds now, with slow pointCount code) + elapsedTime INV = partition(lab -> invariants2 Xs#lab, labelYs); -- 6 seconds + + #INV == 165 -- torsionfrees, invariants2. + -- #INV == 168 -- for both invariants, invariants2 + + -- This selects the different topologies, except it can't tell about (52,0), (53,0). + (keys INV)/(x -> #INV#x)//tally + + RESULT1 = hashTable for k in sort keys INV list ( + labs := INV#k; + k => partitionByTopology(labs, Xs, 15) + ) + + labs = INV#{3, 99, 0, 2, 1, 1, 1, 1} + gvInvariants(Xs#(labs#0), DegreeLimit => 15) + gvCone(Xs#(labs#0), DegreeLimit => 15) + + TODO = select(keys RESULT1, k -> #(keys RESULT1#k) > 1) + DONE = select(keys RESULT1, k -> #(keys RESULT1#k) == 1) + hashTable for k in DONE list k => RESULT1#k + TODO = hashTable for k in TODO list k => RESULT1#k + + -- try comparing (26,0), (37,0) + partitionByTopology({(26,0), (37,0)}, Xs, 25) + partitionGVConeByGV(Xs#(26,0), DegreeLimit => 20) + partitionGVConeByGV(Xs#(37,0), DegreeLimit => 20) -- this makes them appear distinct. + F26 = cubicForm Xs#(26,0) + F37 = cubicForm Xs#(37,0) + L26 = c2Form Xs#(26,0) + L37 = c2Form Xs#(37,0) + + RQ = QQ[a,b,c] + F1 = sub(F26, RQ) + L1 = sub(L26, RQ) + F2 = sub(F37, RQ) + L2 = sub(L37, RQ) + decompose ideal(F1, L1) + decompose ideal(F2, L2) + + mons3 = basis(3, RQ) + coeffsF1 = flatten entries last coefficients(F1, Monomials => mons3) + coeffsF2 = flatten entries last coefficients(F2, Monomials => mons3) + needsPackage "EllipticCurves" + toWeierstrass(RingElement, List) := (F, pt) -> ( + R := ring F; + kk := coefficientRing R; + if numgens R =!= 3 or #pt != 3 then error "expected ring in 3 variables and point in 3-space"; + mons3 := basis(3, R); + coeffsF := flatten entries last coefficients(F, Monomials => mons3); + toWeierstrass(coeffsF, pt, kk) + ) + jInvariant toWeierstrass(F1, {2, 3, -4}) + jInvariant toWeierstrass(F2, {1, 1, -1}) + + TOANALYZE = for k in sort keys RESULT1 list ( + if #RESULT1#k == 1 then continue; + k => (FINISH ME !!!!!!!!!!!!!!!!!!!!!!!! + + select(sort keys RESULT1, k -> #(keys RESULT1#k) > 1) + + tally for k in keys RESULT1 list #RESULT1#k -- all 1's, meaning that in each case, all elements of + -- INV#k are equivalent. + + ALLTOPS = (keys RESULT1)/(k -> ( + for x in keys RESULT1#k list x => join(RESULT1#k#x, SAME#x) + ))//flatten//hashTable + +/// + +---------------------------------------------------------- +-- Newer version of last example ------------------------- +---------------------------------------------------------- + + +/// + -- Example use of a constructed data base. + restart + debug needsPackage "StringTorics" + RZ = ZZ[a,b,c] + F = openDatabase "../m2-examples/foo-ntfe-h11-3.dbm" -- note: + Xlabels = sort select(keys F, k -> (a := value k; instance(a, Sequence))) + Qlabels = sort select(keys F, k -> (a := value k; instance(a, ZZ))) + assert(#Xlabels == 306) + assert(#Qlabels == 244) + elapsedTime Qs = for k in Qlabels list cyPolytope(F#k, ID => value k); + elapsedTime Xs = for k in Xlabels list cyData(F#k, i -> Qs#i, Ring => RZ); + assert(Xs/label === Xlabels/value) + close F + + Xs = hashTable for x in Xs list (label x) => x; + + -- these are the ones we will consider. + torsionfrees = for lab in sort keys Xs list ( + X := Xs#lab; + V := normalToricVariety(rays X, max X); + if classGroup V === ZZ^3 then lab else continue + ) + + -- 6 polytopes are not torsion free (i.e. classGroup is not torsion free) + nontorsionfrees = for lab in sort keys Xs list ( + X := Xs#lab; + V := normalToricVariety(rays X, max X); + if classGroup V != ZZ^3 then lab else continue + ) + nontorsionfrees == {(0, 0), (9, 0), (10, 0), (55, 0), (62, 0), (232, 0)} + + nonFavorables = select(sort keys Xs, lab -> not isFavorable cyPolytope Xs#lab) + favorables = select(sort keys Xs, lab -> isFavorable cyPolytope Xs#lab) + + -- XXXX + elapsedTime H1 = partition(lab -> topologicalData Xs#lab, torsionfrees); -- take one from each. + netList (values H1) + SAME = hashTable for k in keys H1 list (first H1#k) => drop(H1#k, 1) + + labelYs = sort keys SAME -- these have non-equal topological data + #labelYs == 286 -- if torsionfrees is used + #labelYs == 291 -- all are equivalent to one of these, so there are 291 possible different topologies + -- (but probably less than this). + + --elapsedTime INV = partition(lab -> invariants Xs#lab, labelYs); -- 98 sec (FIXME: about 200 seconds now, with slow pointCount code) + elapsedTime INV = partition(lab -> invariants2 Xs#lab, labelYs); -- 6 seconds + + #INV == 165 -- torsionfrees, invariants2. + -- #INV == 168 -- for both invariants, invariants2 + + -- This selects the different topologies, except it can't tell about (52,0), (53,0). + (keys INV)/(x -> #INV#x)//tally + + RESULT1 = hashTable for k in sort keys INV list ( + labs := INV#k; + k => partitionByTopology(labs, Xs, 15) + ) + + labs = INV#{3, 99, 0, 2, 1, 1, 1, 1} + gvInvariants(Xs#(labs#0), DegreeLimit => 15) + gvCone(Xs#(labs#0), DegreeLimit => 15) + + TODO = select(keys RESULT1, k -> #(keys RESULT1#k) > 1) + DONE = select(keys RESULT1, k -> #(keys RESULT1#k) == 1) + hashTable for k in DONE list k => RESULT1#k + TODO = hashTable for k in TODO list k => RESULT1#k + + -- try comparing (26,0), (37,0) + partitionByTopology({(26,0), (37,0)}, Xs, 25) + partitionGVConeByGV(Xs#(26,0), DegreeLimit => 20) + partitionGVConeByGV(Xs#(37,0), DegreeLimit => 20) -- this makes them appear distinct. + F26 = cubicForm Xs#(26,0) + F37 = cubicForm Xs#(37,0) + L26 = c2Form Xs#(26,0) + L37 = c2Form Xs#(37,0) + + RQ = QQ[a,b,c] + F1 = sub(F26, RQ) + L1 = sub(L26, RQ) + F2 = sub(F37, RQ) + L2 = sub(L37, RQ) + decompose ideal(F1, L1) + decompose ideal(F2, L2) + + mons3 = basis(3, RQ) + coeffsF1 = flatten entries last coefficients(F1, Monomials => mons3) + coeffsF2 = flatten entries last coefficients(F2, Monomials => mons3) + needsPackage "EllipticCurves" + toWeierstrass(RingElement, List) := (F, pt) -> ( + R := ring F; + kk := coefficientRing R; + if numgens R =!= 3 or #pt != 3 then error "expected ring in 3 variables and point in 3-space"; + mons3 := basis(3, R); + coeffsF := flatten entries last coefficients(F, Monomials => mons3); + toWeierstrass(coeffsF, pt, kk) + ) + jInvariant toWeierstrass(F1, {2, 3, -4}) + jInvariant toWeierstrass(F2, {1, 1, -1}) + + TOANALYZE = for k in sort keys RESULT1 list ( + if #RESULT1#k == 1 then continue; + k => (FINISH ME !!!!!!!!!!!!!!!!!!!!!!!! + + select(sort keys RESULT1, k -> #(keys RESULT1#k) > 1) + + tally for k in keys RESULT1 list #RESULT1#k -- all 1's, meaning that in each case, all elements of + -- INV#k are equivalent. + + ALLTOPS = (keys RESULT1)/(k -> ( + for x in keys RESULT1#k list x => join(RESULT1#k#x, SAME#x) + ))//flatten//hashTable + +/// + + +---------------------------------------------------------------- +-- Reading and writing polytopes, simplices, cy_classes files -- +---------------------------------------------------------------- +readPolytopes = method() +readPolytopes String := filename -> ( + contents := lines get filename; + hashTable for L in contents list ( + v := toList value L; + lab := v#0; + i := 1; + pts := while i+3 <= #v list ( + ans := for j from 0 to 3 list v#(i+j); + i = i + 4; + ans); + lab => pts + ) + ) + +readSimplices = method() +readSimplices String := filename -> ( + contents := lines get filename; + hashTable for L in contents list ( + v := toList value L; + labX := v#0; + labQ := v#1; + i := 2; + simplices := while i+3 <= #v list ( + ans := for j from 0 to 3 list v#(i+j)-1; + i = i + 4; + ans); + labX => {labQ, simplices} + ) + ) + +readEquivalences = method() +readEquivalences String := List => filename -> ( + contents := lines get filename; + for L in contents list ( + v := value ("{"|L|"}"); + i := 0; + equivsets := while i < #v list ( + ans := while i < #v and v#i != -1 list (a := v#i; i=i+1; a); + if i < #v then i = i+1; + ans + ); + equivsets + ) + ) + +cyPolytope(HashTable, ZZ):= CYPolytope => opts -> (vertexData, ind) -> ( + cyPolytope(transpose matrix vertexData#ind, ID => ind) + ) +-- This function should not change the order of points? But it does. + +/// + + restart + debug needsPackage "StringTorics" + DIRNAME = "~/Dropbox/Collaboration/Physics-Liam/Inequivalent CYs/cy_classes/" + + Ps = readPolytopes(DIRNAME|"polytopes_h11=2.dat") + Ss = readSimplices(DIRNAME|"simplices_h11=2.dat") + Es = readEquivalences(DIRNAME|"cy_classes_h11=2.dat") + cyPolytope(Ps, 3) + + readPolytopes(DIRNAME|"polytopes_h11=3.dat") + readSimplices(DIRNAME|"simplices_h11=3.dat") + readEquivalences(DIRNAME|"cy_classes_h11=3.dat") + + Ps = readPolytopes(DIRNAME|"polytopes_h11=4.dat"); + Ss = readSimplices(DIRNAME|"simplices_h11=4.dat"); + Es = readEquivalences(DIRNAME|"cy_classes_h11=4.dat"); + + Ps = readPolytopes(DIRNAME|"polytopes_h11=5.dat"); + Ss = readSimplices(DIRNAME|"simplices_h11=5.dat"); + Es = readEquivalences(DIRNAME|"cy_classes_h11=5.dat"); + + Qs = new MutableHashTable + Xs = new MutableHashTable + RZ = ZZ[a,b,c,d] + elapsedTime X = makeCY(13, (Ps, Ss), Qs, Xs, Ring => RZ) -- this sets Qs#899, Xs#13. + elapsedTime X = makeCY(12, (Ps, Ss), Qs, Xs, Ring => RZ) -- this sets Qs#899, Xs#13. + peek Qs#899 .cache + + elapsedTime Qs = for lab in sort keys Ps list cyPolytope(Ps#lab, ID => lab); + + Ps#3, rays Q -- these are in different orders! + Q = cyPolytope(Ps#3, ID => 3) + latticePointList polytope(Q, "N") + rays Q + calabiYau(13, Ps, Ss) -- + Ss#13 + Q = cyPolytope(Ps#(Ss#13#0), ID => Ss#13#0) + label Q === 899 + rays Q + Q.cache#"face dimensions" + Ps#899 + netList annotatedFaces Q + get (DIRNAME|"simplices_h11=2.dat") + get (DIRNAME|"cy_classes_h11=4.dat") + Q = cyPolytope oo + hh^(1,2) Q + isReflexive polytope Q + vertices polytope Q + netList annotatedFaces Q +/// + +makeCY(ZZ, Sequence, MutableHashTable, MutableHashTable) := opts -> (labX, PSs, Qs, Xs) -> ( + if Xs#?labX then return Xs#labX; + (Ps, Ss) := PSs; + polytopeid := Ss#labX#0; + P := Ps#polytopeid; + S := Ss#labX; + if not Qs#?polytopeid then ( + Qs#polytopeid = cyPolytope(P, ID => polytopeid); + ); + Q := Qs#polytopeid; + -- now place into the cache the translation for rays? + ---translate1 := hashTable for i from 0 to #Ps - 1 list Ps#i => i; + translate2 := hashTable for i from 0 to #(rays Q) - 1 list (rays Q)#i => i; + fromOldToNew := for i from 0 to #P-1 list translate2#(P#i); + tri := sort for T in S#1 list sort for t1 in T list fromOldToNew#t1; + X := calabiYau(Q, tri, ID => labX, Ring => opts#Ring); + Xs#labX = X; + X + ) + diff --git a/CYToolsM2/StringTorics/Extras.m2 b/CYToolsM2/StringTorics/Extras.m2 new file mode 100644 index 0000000..8669c89 --- /dev/null +++ b/CYToolsM2/StringTorics/Extras.m2 @@ -0,0 +1,284 @@ +------------------------------------------------ +-- TODO: what to do with the code below this? -- for now, placed it here... +-- i.e. it is older code, but potentially useful +------------------------------------------------ + +protect MYRING +--------------------------------------------------- +-- Simplicial complex-like code +subcomplex = method() +subcomplex(NormalToricVariety, List) := (V, D) -> ( + if not V.?MYRING then ( + x := getSymbol "x"; + V.MYRING = (ZZ/32003) (monoid([x_0..x_(#rays V-1)])); + ); + S := V.MYRING; + faces := unique for f in max V list sort toList (set D * set f); + -- Next we take these faces, and make monomials out of them. + monoms := flatten for f in faces list (1_S * product (f/(i -> S_i))); + simplicialComplex monoms + ) +subcomplex(NormalToricVariety, List) := (V, D) -> ( + if not V.?MYRING then ( + x := getSymbol "x"; + V.MYRING = (ZZ/32003) (monoid([x_0..x_(#rays V-1)])); + ); + S := V.MYRING; + R := (coefficientRing S)(monoid[for d in D list S_d]); + trD := hashTable for i from 0 to #D-1 list D#i => i; + faces := unique for f in max V list sort toList (set D * set f); + facesTr := for f in faces list (f/(i -> trD#i)); + -- Next we take these faces, and make monomials out of them. + monoms := flatten for f in facesTr list (1_R * product (f/(i -> R_i))); + simplicialComplex monoms + ) +skeleton(ZZ, SimplicialComplex) := (d,C) -> ( + S := ring C; + fac := flatten entries facets C; + fac1 := for f in fac list (support f)/index//sort; + print fac1; + subfacs := unique flatten for f in fac1 list subsets(f, d+1); + simplicialComplex for f in subfacs list (1_S * product(f/(i -> S_i))) + ) +simplicialComplex NormalToricVariety := (V) -> ( + if not isSimplicial V then error "expected a simplicial polytope"; + S := ring V; + simplicialComplex for f in max V list (1_S * product(f/(i -> S_i))) + ) +subcomplex(SimplicialComplex, List) := (C,D) -> ( + S := ring C; + if not all(D, v -> instance(v,S)) then + D = D/(i -> S_i); + elems := toList (set gens S - D); + if #elems == 0 then return C; + J := monomialIdeal elems; + simplicialComplex(J + monomialIdeal C) + ) + +-* +decompose SimplicialComplex := C -> ( + -- return a list of sub-complexes corresponding to the + -- connected components of C + S := ring C; + V := faces(0,C); + G := graph(V, for e in faces(1,C) list support e); + comps := connectedComponents G; + for comp in comps list subcomplex(C,comp) + ) +*- + +/// + S = QQ[x_0..x_6] + C = simplicialComplex {x_0*x_1, x_2*x_3*x_4, x_0*x_2, x_5*x_6} + decompose C +/// + +-- fac := flatten entries facets C; +-- fac = fac/support/(v -> v/index//sort); +-- faces := unique for f in fac list sort toList (set D * set f); +-- -- Next we take these faces, and make monomials out of them. +-- simplicialComplex flatten for f in faces list (1_S * product (f/(i -> S_i))) +-- ) +--------------------------------------------------- +hodgeOfCYToricDivisor = method(); + +------------------------------------------- +-- Newer code ----------------------------- +------------------------------------------- +hodgeCY = (P, pt) -> ( + -- pt should be a lattice point: list of integers, a point in P2 = polar P. + --if dim P != 4 then error "expected a 4d reflexive polytope"; + pt = for a in pt list if instance(a,QQ) then lift(a,ZZ) else a; + if not all(pt, i -> instance(i,ZZ)) + then error "expected a list of integers"; + P2 := polar P; + L := latticePointHash P2; + if not L#?pt then error "point provided is not a lattice point of the dual polytope"; + f := minimalFace(P2, pt); + i := dim(P2,f); + dualf := dualFace(P2, f); + g := # interiorLatticePointList(P, dualf); + result := new MutableList from splice{1,(dim P-2):0}; +-- if i == 0 then {1,0,g} +-- else if i == 1 then {1,g,0} +-- else if i == 2 then {1+g,0,0}; + if i >= 0 and i <= dim P-2 then result#(dim P - 2 - i) = result#(dim P - 2 - i) + g + else return null; + toList result + ) + +hodgeOfCYToricDivisors = method() +hodgeOfCYToricDivisors Polyhedron := (P) -> ( + P2 := polar P; + L := latticePointList P2; + -- only go to #L-2, since the origin is L#(#L-1) + hashTable for i from 0 to #L-2 list i => hodgeCY(P, L#i) + ) + +hodgeOfCYToricDivisor(Polyhedron,List) := (P,pt) -> hodgeCY(P, pt) + +h11OfCY Polyhedron := (P1) -> ( + elapsedTime np := 1 + #(latticePointList polar P1) - 1; -- -1 for the origin + elapsedTime A0 := annotatedFaces(0,P1); + elapsedTime A1 := annotatedFaces(1,P1); + t := A0/last//sum; + t1 := A1/(v -> v#2 * v#3)//sum; + np - dim P1 - 1 - t + t1 + ) + +h21OfCY Polyhedron := (P1) -> ( + np := 1 + #(latticePointList P1) - 1; -- -1 for the origin + A2 := annotatedFaces(2,P1); + A3 := annotatedFaces(3,P1); + t := A3/(v -> v#2)//sum; + t1 := A2/(v -> v#2 * v#3)//sum; + np - 5 - t + t1 + ) + +isFavorable Polyhedron := (P1) -> ( + -- This is from the Batyrev formula for h^11, + -- The term ell^*(theta) * ell^*(theta^*) gives new divisors. + -- here theta is an edge of P, theta^* is a (dim P)-2 face of (polar P) + -- and ell^* is the number of interior lattice points. + A1 := annotatedFaces(1,P1); + t1 := A1/(v -> v#2 * v#3)//sum; + t1 == 0 + ) + +complexWithInteriorEdgesRemoved = method() +complexWithInteriorEdgesRemoved(SimplicialComplex,Polyhedron,ZZ) := (C,P2,facedim) -> ( + LPs := latticePointList P2; + edgeList := faces(1,C); + badEdges := select(edgeList, e -> ( + f := (support e)/index; + fpts := f/(i -> LPs#i); + dim(P2,minimalFace(P2,fpts)) >= facedim) + ); + if #badEdges == 0 then C else simplicialComplex(monomialIdeal C + monomialIdeal badEdges) + ) + +complexWithInteriorFacesRemoved = method() +complexWithInteriorFacesRemoved(SimplicialComplex,Polyhedron,ZZ) := (C,P2,facedim) -> ( + LPs := latticePointList P2; + facelist := flatten for i from 0 to dim P2-1 list faces(i,C); + badfaces := select(facelist, e -> ( + f := (support e)/index; + fpts := f/(i -> LPs#i); + dim(P2,minimalFace(P2,fpts)) >= facedim) + ); + if #badfaces == 0 then C else simplicialComplex(monomialIdeal C + monomialIdeal badfaces) + ) + +tentativeHodgeVector = method() + +-- V: a normal toric variety corresponding to a fine star +-- triangulation of P2 using all of the non-zero lattice points of P2, +-- except possibly those that are interior to 3d faces. +-- P2: reflexive polytope of dimension 4. +-- D is a list of indices into 'latticePointList P2' +-- OUTPUT: +-- the vector {h^0(D, OO_D), h^1(D, OO_D), h^2(D, OO_D)}, where +-- D is considered to be the sum of the effective toric divisors +-- in the input D. + +hodgeVectorViaTheorem = method() +hodgeVectorViaTheorem(NormalToricVariety, Polyhedron, List) := (V,P2,D) -> ( + -- we assume that the list of rays of V is identical to the first + -- elements of latticePointsList P2: + if debugLevel >= 1 then << "starting tentativeHodgeVector" << endl; + if rays V != take(latticePointList P2, # rays V) then + error "logic error: we need to translate from rays V to lattice points of P2"; + (h0,h1,h2) := (0,0,0); + Delta' := subcomplex(V,D); + Delta := complexWithInteriorFacesRemoved(Delta',P2,3); + deltaIndices := hashTable for i from 0 to #D-1 list D#i => i; -- need to use these indices when dealing with Delta',Delta. + h0 = 1 + rank HH_0(Delta); + h1 = rank HH_1(Delta); + h2 = rank HH_2(Delta); + if debugLevel >= 1 then + << "orig h: " << {h0,h1,h2} << endl; + -- Contribution #1: loop over all vertices of P2 + -- for each element v of the set D also a verte x of P2: + -- add in genus(P2,{v}) to h2 + vertsP2 := (faceList(0,P2))/first; -- indices of vertices in P2 + vertsKD := sort toList (set vertsP2 * set D); + if debugLevel >= 1 then << "about to do vertex contributions" << endl; + for v in vertsKD do ( + g := genus(P2, {v}); + if debugLevel >= 1 and g > 0 then + << "vertex: " << v << " adding " << g << " to h2" << endl; + h2 = h2 + g; + ); + -- Contribution #2: loop over all edges of P2 that meet D in some way + -- note: {edge, lattice pts on edge, genus} + edgeGenera := for e in faceList(1,P2) list {e, latticePointList(P2,e), genus(P2,e)}; + if debugLevel >= 2 then print netList edgeGenera; + for e in edgeGenera do ( + g := e#2; + if g == 0 then continue; + if isSubset(e#1, D) then ( + if debugLevel >= 1 and g > 0 then + << "edge: " << e << " adding " << g << " to h2" << endl; + h2 = h2 + g + ) + else ( + nelems := #((set e#1) * (set D)); + nvertices := #((set e#0) * (set D)); + if nelems > 0 then ( + eindices := for i in e#1 list if deltaIndices#?i then deltaIndices#i else continue; + Delta1 := subcomplex(Delta,eindices); + if debugLevel >= 1 then + << "edge: " << e#1 << " nvertices: " << nvertices << " Delta1: " << Delta1 << endl; + amt := (1 + rank HH_0(Delta1) - nvertices) * g; + if debugLevel >= 1 then + << " : " << e << " adding " << amt << " to h1" << endl; + h1 = h1 + amt + ); + ); + ); + faceGenera := for t in faceList(2,P2) list {t, latticePointList(P2,t), interiorLatticePointList(P2,t), genus(P2,t)}; + if debugLevel >= 2 then print netList faceGenera; + if debugLevel >= 1 then << "in facGenera" << endl; + for t in faceGenera do ( + g := t#3; + if g > 0 then ( + nverts := #((set t#0) * (set D)); + nlattice := #((set t#1) * (set D)); + ninterior := #((set t#2) * (set D)); + -- 3 cases: + if nlattice == 0 then ( + -- do nothing + ) + else if nlattice > 0 and nlattice == ninterior then ( + if debugLevel >= 1 and g > 0 then + << "2face: " << t#0 << " adding " << g << " to h0" << endl; + h0 = h0 + g; + ) + else if nlattice == #t#1 then ( -- the whole face t is in D + if debugLevel >= 1 and g > 0 then + << "2face: " << t#0 << " adding " << g << " to h2" << endl; + h2 = h2 + g; + ) + else ( + tindices := for i in t#1 list if deltaIndices#?i then deltaIndices#i else continue; + KDf := subcomplex(Delta,tindices); -- K_D \cap f + df := sort toList(set t#1 - set t#2); -- boundary(f), as a list of lattice points + comps := decompose KDf; -- each connected component y of K_D \cap f + comps1 := for c in comps list ( + dfindices := for i in df list if deltaIndices#?i then deltaIndices#i else continue; + c1 := subcomplex(c,dfindices); + -- now remove all edges that go in the interior of the 2-face + -- y \cap df, for each y + c2 := complexWithInteriorEdgesRemoved(c1,P2,2); + c2); + n1 := sum for c in comps1 list rank HH_0(c); + if debugLevel >= 1 and g > 0 and n1 > 0 then + << "2face: " << t#0 << " adding " << n1*g << " to h1" << endl; + h1 = h1 + n1*g; + ) + ); + ); + {h0,h1,h2} + ) + +tentativeHodgeVector(NormalToricVariety, Polyhedron, List) := (V, P2, D) -> hodgeVectorViaTheorem(V,P2,D) diff --git a/CYToolsM2/StringTorics/Flops.m2 b/CYToolsM2/StringTorics/Flops.m2 new file mode 100644 index 0000000..222eb80 --- /dev/null +++ b/CYToolsM2/StringTorics/Flops.m2 @@ -0,0 +1,203 @@ +-- Notes to self: +-- Naomi's code is /Users/mike/src/stringtorics/naomi-flop-code/Flop Code: +-- Jakob's code is in + +-- Code for constructing potential flops of a CY Hypersurface, or something +-- constructed from that bvia a sequence of flops. + +-- given a curve, gv invariant, topology. Return the new topology. + +-- Determine the types of arguments for: + +-- find_nilpotent +-- find_nilpotent_outside_inf +-- is_symmetric_flop +-- find_all_flops + +-- what about: +-- toric_curves.compute + +-- two_face_triags.all_two_face_triangulations(p) + +-- determine if a curve is gv nilpotent +-- determine if a nilpotent ray is "outside the infinity cone" +-- perform a flop + + +---- given: +---- Input: CY3, as given by h11, h12, c2, cubic, and also non-zero GV classes up to some cutoff. +---- Input: a curve class, representing a flop. +---- Output: a new CY3 +---- negate the curve class, take all effective curves other than that. What if a curve class has 0 gv's? +---- use the gv of the flopped curve. + +debug needsPackage "StringTorics" + +-- Let's write a flop function +CY3 = new Type of HashTable +makeCY3 = method(Options => {GV => null, + NegatedCurves => null, + Heft => null, + DegreeLimit => null, + Label => null, + MoriCone => null + }) +makeCY3(ZZ, ZZ, RingElement, RingElement) := opts -> (h11val, h12val, L, F) -> ( + X := new CY3 from { + cache => new CacheTable, + h11 => h11val, + h12 => h12val, + c2Form => L, -- maybe store list of ints? + cubicForm => F -- maybe store intnums? (for basis). + }; + if opts#NegatedCurves =!= null then X.cache.NegatedCurves = opts#NegatedCurves; + if opts#GV =!= null then X.cache.GV = opts#GV; -- should be a hash table: curve classes => integers. + if opts#MoriCone =!= null then X.cache.MoriCone = opts#MoriCone; -- should be a hash table: curve classes => integers. + if opts#Heft =!= null then X.cache.Heft = opts#Heft; + if opts#DegreeLimit =!= null then X.cache.DegreeLimit = opts#DegreeLimit; + if opts#Label =!= null then X.cache.Label = opts#Label; + X + ) + +-- TODO: have a function which checks that C defines a flop. + +performFlop = method() +performFlop(CY3, List) := CY3 => (X, C) -> ( + if gcd C != 1 then error "expected a primitive curve class"; + -- perform a flop + L := X#c2Form; + F := X#cubicForm; + R := ring L; + linform := sum for i from 0 to numgens R - 1 list C_i * R_i; + n := X.cache#GV#C; -- is this correct? Maybe not. -- TODO: look at the entire ray. + -- make the new GV table. + GV1 := hashTable for kv in pairs X.cache#GV list ( + (curve, gvnum) := kv; + primcurve := curve // gcd curve; + if primcurve == C then (-curve,gvnum) else (curve,gvnum) + ); + mori := entries transpose rays posHull transpose matrix keys GV1; -- can be made faster. + -- WARNING: We assume that all extremal rays have non-zero gv invariant. + makeCY3(X#h11, X#h12, L + 2*n*linform, F - n * linform^3, + Label => splice{X, {"flop via ", C}}, + MoriCone => mori, + NegatedCurves => join(X.cache.NegatedCurves, C), + -- The following are take directly from X. + GV => X.cache.GV, + Heft => X.cache#Heft, + DegreeLimit => X.cache#DegreeLimit + ) + ) + + -- TODO: change to use NegatedCurves + gvRay(CY3, List) := List => opts -> (X, C) -> ( + contentC := gcd C; + if contentC =!= 1 then C = C // contentC; + degvector := X.cache#Heft; + GVHash := X.cache#GV; + deglimit := X.cache#DegreeLimit; + d := dotProduct(degvector, C); + for i from 1 to floor(deglimit/d) list ( + iC:= i*C; + if GVHash#?iC then GVHash#iC else 0 + ) + ) + + heftFunction = method() + heftFunction CalabiYauInToric := X -> ( + mori := hilbertBasisGenerators toricMoriCone(ambient X, basisIndices X); + sum entries transpose rays dualCone posHull transpose matrix mori + ) + + dot = method() + dot(List, List) := (v,w) -> ( + if #v =!= #w then error "expected vectors of the same size"; + sum for i from 0 to #v-1 list v#i * w#i + ) + +end-- +-- Right now, we will do it on an example with h11=3. + +-- load this in dir m2-examples. +restart +load "../Flops.m2" + -- debug for e.g. hilbertBasisGenerators. + RZ = ZZ[a,b,c]; + (Qs, Xs) = readCYDatabase("../Databases/cys-ntfe-h11-3.dbm", Ring => RZ); + #Qs + #Xs + +-- Step 1. Find all gv invariants up to a degree bound. + X1 = Xs#(53,0) + gvX1 = hashTable for kv in pairs gvInvariants(X1, DegreeLimit => 20) list (toList kv#0, kv#1) + X1 = makeCY3(hh^(1,1) X1, hh^(1,2) X1, c2Form X1, cubicForm X1, + GV => gvX1, + MoriCone => toricMoriConeCap X1, + DegreeLimit => 20, + Heft => heft X1) + + X1.cache.GV#{0,1,0} + X1#h11 + X1#h12 + X1#c2Form + gvRay(X1, {0,1,0}) + + X2 = performFlop(X1, {0,1,0}) + for c in X2.cache.MoriCone list c => gvRay(X2, c) + + + X3 = performFlop(X2, {1,0,0}) + X3.cache.MoriCone + GV = gvInvariants(X, DegreeLimit => 20) + GVcone = (keys GV)/toList//matrix//transpose//posHull + rays GVcone + -- Question: what is the degree limit method? + + + deglimit = 20 + hf = heftFunction X + assert(hf == {1,1,3}) + (keys GV)/(v -> dot(toList v, hf)) + allGV = (keys GV)/toList//set + select(keys allGV, v -> dot(v, hf) <= deglimit // 2) + allrays = unique for v in keys allGV list ( + c := gcd v; + for v1 in v list v1//c + ) + goodray = x -> ( + d := dot(x, hf); + topval := floor(deglimit/d); + all(splice{1..topval}, i -> member(i * x, allGV)) + ) + H = partition(goodray, allrays); + rays posHull transpose matrix H#true + matrix{hf} * oo + matrix{hf} * transpose matrix H#false + for x in oo list ( + d := dot(x, hf); + topval := floor(deglimit/d); + if not all(splice{1..topval}, i -> member(i * x, allGV)) + then continue + else x + ) + rays posHull transpose matrix oo + + for k in keys allGV list ( + -- we will select all of the ones + ) + +-- Design: What should a GVInvariants class look like? +-- 1. Has hash table as it does now. +-- 2. Knows its degree limit, and grading vector. +-- 3. Can compute "infinity cone": actually, should be done for 2 or 3 different degrees, +-- then compare them? +-- 4. Compute ray of GV values out some distance. +-- This should use special features of the code? Does it work on non-extremal rays? +-- 5. Determine what kind of extremal ray a ray is: +-- 1. nilpotent (type I) +-- 2. nilpotent (type II0, type IIg) +-- 3. potent ray. +-- 4. is a ray in the closure of the infinity cone? Or can we not consider this possibility? +-- 6. Find non-zero-gv cone (the Mori cone in the case when the CY3 is general in moduli. +-- Handle negated curve rays. +-- For non-general CY3's it is possible for a curve to be effective, but have gv ray all 0's. diff --git a/CYToolsM2/StringTorics/GVInvariants.m2 b/CYToolsM2/StringTorics/GVInvariants.m2 new file mode 100644 index 0000000..bed5b88 --- /dev/null +++ b/CYToolsM2/StringTorics/GVInvariants.m2 @@ -0,0 +1,669 @@ +--------------------------------------- +-- gvInvariants +-- Gopakumar-Vafa invariants (similar to Gromov-Witten invariants) +-- Contains code to call the external C++ program `computeGV` from CYTools +-- This requires computing some information first (intersection numbers, mori cone cap, etc). +--------------------------------------- + +toricMoriCone(NormalToricVariety, List) := Cone => (V, basisIndices) -> ( + IV := intersectionRing (abstractVariety V); + Cs := matrix for x in orbits(V, 1) list ( + c := product(x, i -> IV_i); + for j in basisIndices list integral(c * IV_j) + ); + posHull transpose lift(Cs, QQ) -- TODO: lift to ZZ? + ) + +toricMoriCone CalabiYauInToric := Cone => X -> ( + -- TODO: handle toric mori cones of non-favorables + if isFavorable X then toricMoriCone(ambient X, basisIndices X) + ) + +hilbertBasisGenerators = method() +hilbertBasisGenerators Cone := List => C -> ( + for x in hilbertBasis C list flatten entries x + ) + +-- This function returns a very large heft vector. Not so good! +-- TODO: this appears to be computing the toricMoriCone, which it is not using!? +heft CalabiYauInToric := List => X -> ( + C := toricMoriCone X; + heft1 := sum entries transpose rays dualCone C; + Ccap := posHull transpose matrix toricMoriConeCap X; + heft2 := sum entries transpose rays dualCone Ccap; + heft2 + ) + +-- TODO: use findProgram/runProgram methods in M2 to handle access to computeGV. +gvInvariants = method(Options => { + Mori => null, -- null means: compute rays of the Mori cone of V (in ZZ^(h11)) + Heft => null, -- null means: compute it + DegreeLimit => infinity, + Precision => 150, + FilePrefix => "foo", + Executable => "~/src/git-from-others/cytools-private/external/gv/computeGV-good/computeGV", + KeepFiles => true + }) + +-- The function to write the data needed by the computeGV program +gvInput = (moriGenerators, heftval, GLSM, intersectionnums, degreelimit, prec) -> ( + -- moriGenerators: list of lists. Hilbert basis of the cone of + -- irreducible curves induced from the toric variety. + -- heftval: list of ints + -- GLSM: list of list of ints + -- intersectionnums: list of triples of ints + -- degreelimit: infinity or positive integer + -- prec: positive integer + str1 := toString moriGenerators; + str3 := toString heftval; + str4 := toString GLSM; + str5 := toString intersectionnums; + str6 := toString ({ + if degreelimit === infinity then -1 else degreelimit, + prec, + 0, + 300000 + }); + concatenate between("\n", {str1, toString {}, str3, str4, toString {}, str5, str6}) + ) + +filenameCounter := 0; -- TODO: not used? or change to use it? + +-- TODO: use findProgram/runProgram to get this... +-- TODO: Also: there should be one function which calls computeGV. +-- Here there are two... +gvInvariants(NormalToricVariety, List) := HashTable => opts -> (V, basisIndices) -> ( + -- Compute intersection numbers for X in V (using this basis) + -- Compute mori cone (if needed) (?? requires basis too...) + -- Compute a vector which dots positively with all these generators. + -- Then write the file + -- Execute the command + -- Read the results, and return them + intersectionnums := for t in intersectionNumbersOfCY(V, basisIndices) list append(t#0, t#1); + -- X := completeIntersection(V, {-toricDivisor V}); + -- Xa := abstractVariety(X, base()); + -- IX := intersectionRing Xa; + -- intersectionnums := for x in pairs intersectionNumbers(IX, basisIndices) list append(x#0, x#1); + -- H := hashTable for i from 0 to #basisIndices-1 list basisIndices#i => i; + -- intersectionnums := for x in pairs CY3NonzeroMultiplicities V list ( + -- if isSubset(x#0, basisIndices) then + -- append(sort for a in x#0 list H#a, x#1) + -- else + -- continue + -- ); + mori := if opts.Mori =!= null then + opts.Mori + else + hilbertBasisGenerators toricMoriCone(V, basisIndices); + heft := if opts.Heft =!= null then opts.Heft else ( + sum entries transpose rays dualCone posHull transpose matrix mori + ); + -- OK, now we have computed everything we need. Write it to a file + infile := opts.FilePrefix | "-input"; + outfile := opts.FilePrefix | "-output"; + infile << gvInput(mori, heft, transpose degrees ring V, intersectionnums, + opts.DegreeLimit, opts.Precision) << close; + inputLine := opts.Executable | " <" | infile | " >" | outfile; + print inputLine; + error "GV invariant computation: not yet re-installed"; + run inputLine; + -- Get the output, package as a hash table + (lines get outfile)/value//hashTable + ) + +gvInvariants CalabiYauInToric := HashTable => opts -> X -> ( + if not isFavorable X then return null; + intersectionnums := for t in intersectionNumbers X list append(t#0, t#1); + -- mori := if opts.Mori =!= null then + -- opts.Mori + -- else + -- hilbertBasisGenerators toricMoriCone(ambient X, basisIndices X); + mori := if opts.Mori =!= null then + opts.Mori + else + hilbertBasisGenerators posHull transpose matrix toricMoriConeCap X; + heft := if opts.Heft =!= null then opts.Heft else ( + sum entries transpose rays dualCone posHull transpose matrix mori + ); + -- OK, now we have computed everything we need. Write it to a file + infile := temporaryFileName(); -- opts.FilePrefix | "-input" + outfile := temporaryFileName(); -- opts.FilePrefix | "-output" | filenameCounter; + infile << gvInput(mori, heft, transpose degrees X, intersectionnums, + opts.DegreeLimit, opts.Precision) << close; + inputLine := opts.Executable | " <" | infile | " >" | outfile; + print inputLine; + error "GV invariant computation: not yet re-installed"; + run inputLine; -- TODO: run this as a program and if it crashes, return something reasonable. + -- Get the output, package as a hash table + contents := get outfile; + if #contents == 0 then return null; + (lines contents)/value//hashTable + ) + +-- Not used anymore?? See `extremalRayGVs` +gvRay = method(Options => options gvInvariants) +gvRay(CalabiYauInToric, List) := HashTable => opts -> (X, curveClass) -> ( + -- This doesn't seem to be correct + if not isFavorable X then return null; + degvec := heft X; + grad := dotProduct(degvec, curveClass); + << "using DegreeLimit: " << 4*grad << endl; + return gvInvariants(X,Mori => {curveClass}, DegreeLimit => 4 * grad, Heft => {0,1,0,0}) + ) + +gvCone = method(Options => options gvInvariants) +gvCone CalabiYauInToric := Cone => opts -> X -> ( + if not isFavorable X then return null; + gv := gvInvariants(X, opts); + if gv === null then return null; + posHull transpose matrix ((keys gv)/toList) + ) + +gvInvariantsAndCone = method(Options => options gvInvariants) +gvInvariantsAndCone(CalabiYauInToric, ZZ) := Sequence => opts -> (X, D) -> ( + -- D is the degree bound to start with. We could start with 5, or DegreeLimit/2 or DegreeLimit/4, or ... + if not isFavorable X then return null; + degvec := heft X; + gv := gvInvariants(X, opts); + if gv === null then return null; + keysgv := keys gv; + H := hashTable for k in keysgv list k => dotProduct(k, degvec); + firstSet := select(keys H, k -> H#k <= D); + if debugLevel > 0 then << "The number of curves in the first set: " << #firstSet << endl; + C := posHull transpose matrix (firstSet); + Cdual := dualCone C; + HC := transpose rays Cdual; + curves := for k in keys H list if H#k > D then transpose matrix {k} else continue; + set2 := select(curves, c -> any(flatten entries (HC * c), a -> a < 0)); + if debugLevel > 0 then << "The number of curves not in the first cone: " << #set2 << endl; + C2 := if #set2 == 0 then C else posHull (rays C | matrix{set2}); + if debugLevel > 0 and #set2 == 0 then ( + << "CY " << label X << " C = " << rays C << endl + ) + else + << "*differs* CY " << label X << " C1 = " << rays C << " and C2 = " << rays C2 << endl; + (gv, C2) + ) + +partitionGVConeByGV = method(Options => options gvInvariants) +partitionGVConeByGV CalabiYauInToric := HashTable => opts -> X -> ( + -- return null if we cannot computr GV invariants (i.e. if non-favorable). + if not isFavorable X then return null; + gv := gvInvariants(X, opts); -- TODO: stash this? + if gv === null then return null; + C := posHull transpose matrix ((keys gv)/toList); + gvX := entries transpose rays C; + partition(f -> if gv#?(toSequence f) then gv#(toSequence f) else 0, gvX) + ) + +partitionGVConeByGV(CYToolsCY3, ZZ) := HashTable => opts -> (X, D) -> ( + -- return null if we cannot computr GV invariants (i.e. if non-favorable). + (gv, C) := gvInvariantsAndCone(X, D, opts); + gvX := entries transpose rays C; + partition(f -> if gv#?f then gv#f else 0, gvX) + ) + +-- TODO: move to Topology.m2? file? +findLinearMaps = method() +findLinearMaps(HashTable, HashTable) := List => (gv1, gv2) -> ( + -- gv1, gv2: result of partitionGVConeByGV + if sort keys gv1 =!= sort keys gv2 then return {}; + for k in keys gv1 do if #gv1#k =!= #gv2#k then return {}; + for k in keys gv1 do if #gv1#k >= 7 then return {}; -- do not waste time (1) trying to separate these? + n := # (first values gv1)_0; -- we should check if all the values are lists of integers of this size. + t := symbol t; + T := QQ[t_(1,1)..t_(n,n)]; + M := genericMatrix(T, n, n); + -- now we make the ideals for each key, and each permutation. + ids := for k in keys gv1 list ( + perms := permutations(#gv1#k); + mat1 := transpose matrix gv1#k; + mat2 := transpose matrix gv2#k; + for p in perms list ( + I := trim ideal (M * mat1 - mat2_p); + if I == 1 then continue else I + ) + ); + topval := ids/(x -> #x - 1); + zeroval := ids/(x -> 0); + fullIdeals := for a in zeroval .. topval list ( + J := trim sum for i from 0 to #ids-1 list ids#i#(a#i); + if J == 1 then continue else J + ); + Ms := for i in fullIdeals list M % i; + --newMs := select(Ms, m -> (d := det m; d == 1 or d == -1)); + --if any(newMs, m -> support m =!= {}) then << "some M is not reduced to a constant" << endl; + Ms + ) + +gvRay(HashTable, List, ZZ, List) := opts -> (GVHash, C, deglimit, degvector) -> ( + contentC := gcd C; + if contentC =!= 1 then C = C // contentC; + d := dotProduct(degvector, C); + rayC := for i from 1 to floor(deglimit/d) list ( + Cseq := toSequence(i*C); + if GVHash#?Cseq then GVHash#Cseq else 0 + ); + rayC + ) + +count = 0; -- used to give a unique index to each ZERO ray. + +classifyExtremalCurve = method() + +classifyExtremalCurve List := rayC -> ( + -- rayC: a list of the gv invariants along the ray of a toric mori cone extremal curve. + -- these are either extremal on the CY, or not effective on the CY. + if #rayC <= 2 then return {"OTHER", rayC}; + if all(2..#rayC-1, i -> rayC#i == 0) then ( + -- only first two, possibly, are non-zero. + if rayC#0 == 0 and rayC#1 == 0 then (count=count+1; return {"ZERO", count}); + if rayC#0 == -2 or rayC#1 == -2 then return {"TYPEIII0", rayC}; + if rayC#0 >= 0 and rayC#1 >= 0 then return {"FLOP", rayC}; -- these could be type IIIg as well? + if rayC#0 < 0 or rayC#1 < 0 then return {"TYPEIIIg", rayC}; -- + ) + else return {"TYPEII", rayC} + ) + +classifyExtremalCurve(HashTable, List, ZZ, List) := (GVHash, C, deglimit, degvector) -> ( + rayC := gvRay(GVHash, C, deglimit, degvector); + if #rayC <= 2 then return {"OTHER", rayC}; + if all(2..#rayC-1, i -> rayC#i == 0) then ( + -- only first two, possibly, are non-zero. + if rayC#0 == 0 and rayC#1 == 0 then (count=count+1; return {"ZERO", count}); + if rayC#0 == -2 or rayC#1 == -2 then return {"TYPEIII0", {rayC#0, rayC#1}}; + if rayC#0 >= 0 and rayC#1 >= 0 then return {"FLOP", {rayC#0, rayC#1}}; + if rayC#0 < 0 or rayC#1 < 0 then return {"TYPEIIIg", {rayC#0, rayC#1}}; + ) + else return {"TYPEII", {rayC#0, rayC#1, rayC#2, "..."}} + ) + +gvTopMoriConeCapDegree = method() +gvTopMoriConeCapDegree CalabiYauInToric := X -> ( + if not isFavorable X then error "expected a favorable polytope"; + degvec := heft X; + max for c in toricMoriConeCap X list dotProduct(degvec, c) + ) + +classifyExtremalCurves = method(Options => { + Verbose => 0, + DegreeLimit => null, + MoriHilbertGens => null + }) +classifyExtremalCurves(HashTable, List, ZZ, List) := (GVHash, Cs, deglimit, degvector) -> ( + partition(c -> classifyExtremalCurve(GVHash, c, deglimit, degvector), Cs) + ) + +classifyExtremalCurves CalabiYauInToric := opts -> X -> ( + if not isFavorable X then error "expected favorable CY3-fold"; + mori := if opts.MoriHilbertGens === null then toricMoriConeCap X else opts.MoriHilbertGens; + deglimit := 3 * gvTopMoriConeCapDegree X; + if opts.Verbose > 1 then << "*** mori cone cap degree limit is " << deglimit << " ***" << endl; + degvec := if opts.DegreeLimit === null then heft X else opts.DegreeLimit; + gvX := gvInvariants(X, DegreeLimit => deglimit); + partition(c -> classifyExtremalCurve(gvX, c, deglimit, degvec), mori) + ) + +-- Good one here, I think. +extremalRayGVs = method(Options => {Limit => 4, Heft => null}) +extremalRayGVs(CalabiYauInToric, List) := opts -> (X, curveClass) -> ( + if not isFavorable X then return null; -- later, maybe we can modify this... + degvec := if opts.Heft =!= null then opts.Heft else heft X; + deglimit := opts.Limit * dotProduct(degvec, curveClass); + gvHash := gvInvariants(X,Mori => {curveClass}, DegreeLimit => deglimit, Heft => degvec); + for i from 1 to opts.Limit list ( + c := toSequence(i * curveClass); + if gvHash#?c then gvHash#c else 0 + ) + ) + +classifyExtremalCurves CalabiYauInToric := opts -> X -> ( + if not isFavorable X then error "expected favorable CY3-fold"; + if not X.cache#?"toric mori cone gvs" then ( + mori := toricMoriConeCap X; + val := hashTable for c in mori list ( + gvs := extremalRayGVs(X, c, Limit => 4); + c => classifyExtremalCurve gvs + ); + X.cache#"toric mori cone gvs" = partition(c -> val#c, mori) + ); + X.cache#"toric mori cone gvs" + ) + +extremalCurveInvariant = method() +extremalCurveInvariant CalabiYauInToric := X -> ( + gv := classifyExtremalCurves X; + sort for a in pairs gv list {a#0, #a#1} + ) + + + + +------------------------------------------------------------------------- +-- some tests ----------------------------------------------------------- + + +/// + restart + debug needsPackage "StringTorics" -- the debug is because some functions are not yet exported. + DB3 = "../Databases/cys-ntfe-h11-3.dbm" + DB3 = "./StringTorics/Databases/cys-ntfe-h11-3.dbm" + RZ = ZZ[a,b,c] + RQ = QQ (monoid RZ); + (Qs, Xs) = readCYDatabase(DB3, Ring => RZ); + + moris = for k in sort keys Xs list ( + X = Xs#k; + if not isFavorable X then continue; -- only handles favorable polytopes and CY3's. + classifyExtremalCurves(X, Verbose => 2) + ); + + moris/keys/sort//unique + degvec = heft X; + deglimit = max for c in toricMoriConeCap X list 3 * dotProduct(degvec, c); + << "degree limit for " << k << " is " << deglimit << endl; + gvX = gvInvariants(X, DegreeLimit => deglimit); + moriClass = sort for c in toricMoriConeCap X list + classifyExtremalCurve(gvX, c, deglimit, degvec); + print netList (ans := prepend(k, moriClass)); + moriClass + ) + + restart + debug needsPackage "StringTorics" -- the debug is because some functions are not yet exported. + DB4 = "../Databases/cys-ntfe-h11-4.dbm" + RZ = ZZ[a,b,c,d] + RQ = QQ (monoid RZ); + (Qs, Xs) = readCYDatabase(DB4, Ring => RZ); + + X = Xs#(137,0) + for k in sort keys Xs list ( + deglimit = 14 + degvec = heft X + gvX = gvInvariants(X, DegreeLimit => deglimit); + + netList for c in toricMoriConeCap X list + sort classifyExtremalCurve(gvX, c, deglimit, degvec) + + for k in sort keys Xs list ( + X = Xs#k; + if not isFavorable X then continue; -- only handles favorable polytopes and CY3's. + deglimit = 14; + degvec = heft X; + gvX = gvInvariants(X, DegreeLimit => deglimit); + moriClass = sort for c in toricMoriConeCap X list + classifyExtremalCurve(gvX, c, deglimit, degvec); + print moriClass; + moriClass + ) + moricap = toricMoriConeCap X + for c in toricMoriConeCap X list + c => gvRay(gvX, c, 22, heft X) + netList oo + + +/// + +/// + restart + debug needsPackage "StringTorics" + DB4 = "../Databases/cys-ntfe-h11-4.dbm" + RZ = ZZ[a,b,c,d] + RQ = QQ (monoid RZ); + (Qs, Xs) = readCYDatabase(DB4, Ring => RZ); + + moris = for k in sort keys Xs list elapsedTime ( + X = Xs#k; + if not isFavorable X then continue; -- only handles favorable polytopes and CY3's. + mori1 = classifyExtremalCurves(X, Verbose => 2); + print netList {mori1}; + mori1 + ); + + + X = Xs#(34,0) + assert isFavorable X + classifyExtremalCurves(Xs#(34,0), Verbose => 2) + classifyExtremalCurves(Xs#(35,0), Verbose => 2) + mori = toricMoriConeCap X; + deglimit = 3 * gvTopMoriConeCapDegree X; + deglimit + degvec = heft X; + gvX = gvInvariants(X, DegreeLimit => deglimit) + partition(c -> classifyExtremalCurve(gvX, c, deglimit, degvec), mori) +/// + +/// +-- Good test, TODO: place this back in once GVinvariants are working again. +-* + restart + needsPackage "StringTorics" +*- + -- hh^(1,1) == 3 + -- label (5,0) + rys = {{-1, -1, 1, 0}, {-1, -1, 1, 1}, {-1, -1, 2, 1}, {-1, 3, -2, -1}, {1, -1, 0, 0}, {2, -1, 0, 0}, {-1, 1, 0, 0}} + cones4 = {{0, 1, 2, 4}, {0, 1, 2, 6}, {0, 1, 3, 4}, {0, 1, 3, 6}, {0, 2, 4, 5}, {0, 2, 5, 6}, {0, 3, 4, 5}, {0, 3, 5, 6}, {1, 2, 4, 5}, {1, 2, 5, 6}, {1, 3, 4, 5}, {1, 3, 5, 6}} + Q = cyPolytope(rys, ID => 5) + label Q + assert(rays Q == rys) + assert(hh^(1,1) Q == 3) + assert(hh^(1,2) Q == 57) + + RZ = ZZ[a,b,c] + Xs = findAllCYs(Q, Ring => RZ) + X = Xs#0 + label X == (5,0) + assert(max X === cones4) + assert(rays X === rys) + + -- OK, now we are ready to test functions in this file + C = toricMoriCone X; + heft1 = sum entries transpose rays dualCone C + + rays toricMoriCone X + morirays = toricMoriConeCap X + assert(sort morirays === sort {{0, 0, 1}, {0, 1, 0}, {1, -1, 0}, {1, 0, -1}}) + assert(morirays === {{0, 0, 1}, {0, 1, 0}, {1, -1, 0}, {1, 0, -1}}) -- not required. + heft X-- why not {2,1,1}?? + + gv = gvInvariants(X, DegreeLimit => 15) + (keys oo)/toList//matrix//transpose//posHull//rays + gv#(0,1,1) + + assert(extremalRayGVs(X, {0,0,1}, Limit => 5) == {60, 0, 0, 0, 0}) + assert(extremalRayGVs(X, {0,1,0}, Limit => 5) == {6, 0, 0, 0, 0}) + assert(extremalRayGVs(X, {1,-1,0}, Limit => 5) == {252, -9252, 848628, -114265008, 18958064400}) + assert(extremalRayGVs(X, {1,0,-1}, Limit => 5) == {56, -272, 3240, -58432, 1303840}) + + assert(extremalRayGVs(X, {1,-1,-3}, Heft => {5,1,1}, Limit => 5) == {0,0,0,0,0}) -- all zeros... + + -- Note: if the curve class is in the interior, the answer from extremalRayGVs is NOT correct. + -- Also: a zero vector means either that the curve class is not effective on X, + -- or that there is an elliptic ruled surface of some sort on X. If one jiggles this X, + -- such surfaces go away, ie. in general moduli, an extrmeal ray has zero GV's iff + -- every class along that curve ray is NOT effective. + + -------------- + -- gvCone ---- + -- this is the cone of all non-zero GV curves. This either matches the Mori cone, or is possibly + -- a subset (as some rays can contain effective curves, all of whose GV invariants (in the ray) + -- are zero. + -------------- + assert(set entries transpose rays gvCone X == set toricMoriConeCap X) -- for this example, + -- the intersection of the Mori cones for the various simplicial + -- toric varieties (which is always contains the Mori cone of X), + -- all has non-zero GV invariants, so if one believes the GV + -- computation, this is exactly the Mori cone of X, so we know the + -- nef/Kahler cone for X too + +-- gvInvariantsAndCone(X, 15)-- doesn't work at the momemnt... BUG -- remove? + + partitionGVConeByGV X -- not completely what we want? + + classifyExtremalCurve extremalRayGVs(X, {0,0,1}, Limit => 5) + classifyExtremalCurve extremalRayGVs(X, {0,1,0}, Limit => 5) + classifyExtremalCurve extremalRayGVs(X, {1,-1,0}, Limit => 5) + classifyExtremalCurve extremalRayGVs(X, {1,0,-1}, Limit => 5) + + classifyExtremalCurves X + heft X + + debug needsPackage "StringTorics" -- for gvTopMoriConeCapDegree + assert(gvTopMoriConeCapDegree X == 2) -- not exported +/// + + +/// +-- Tests of this code, 15 Jan 2023. Removed from tests, since it used created databases... +-* + restart + needsPackage "StringTorics" +*- + DBNAME = "../Databases/cys-ntfe-h11-5.dbm" + DBNAME = "./Databases/cys-ntfe-h11-5.dbm" + DBNAME = "./StringTorics/Databases/cys-ntfe-h11-5.dbm" + RZ = ZZ[a,b,c,d,e] + RQ = QQ (monoid RZ); +-- needs "../FindEquivalence.m2" + (A,phi) = genericLinearMap RQ + elapsedTime (Qs, Xs) = readCYDatabase(DBNAME, Ring => RZ); + REPS = value get "./Analysis/inequiv-reps-h11-5" + SETS = new HashTable from { + {{{4,1},{4,1}},{{5,1}}} => {50,55,65,66,70,72,73,80,85,91,92,95,96,100,103,116,117,186,193}, + {{{5,1}},{{5,1}}} => {7,9,10,14,22,23,24,27,31,36,37,49,51,56,71,93,99,101,102,108,115,130}, + {{{4,1},{4,1},{4,1}},{{5,1}}} => {52,77,155,171,180,217}, + {{{5,1}},{{1,1},{1,1},{3,1}}} => {18,25,32,35,41,59,60,75,111,112,142,143,153,154,178,188,208,215,221,226,227}, + {{{4,2}},{{1,1},{2,1},{2,1}}} => {79}, + {{{4,1}},{{1,1},{1,1},{1,1},{1,2}}} => {118,129,137,138,144,145,190,191,200}, + {{{5,1}},{{1,1},{1,1},{1,1},{1,1},{1,1}}} => {8,28,61,86,88,89,120,131,132,136,146,149,158,160,166,173,201,202,205,207,211,213,218,219,220,224,225}, + {{{4,1},{4,1},{4,1}},{{1,1},{1,1},{1,1},{1,1},{1,1}}} => {124,156,168}, + {{{4,1},{4,1}},{{1,1},{4,1}}} => {44,47,177}, + {{{3,2},{4,1}},{{1,1},{1,2},{2,1}}} => {135,164}, + {{{4,2}},{{5,1}}} => {6,15}, + {{{5,1}},{{1,1},{4,1}}} => {0,3,4,5,11,13,17,21,29,30,34,38,39,40,42,45,57,68,81,83,90,94,98,104,107,109,110,114,119,128,140,163,169,172,195,212,223}, + {{{4,2}},{{1,1},{1,1},{3,1}}} => {48,105}, + {{{4,1},{4,1},{4,1}},{{1,1},{4,1}}} => {62,63,127,151}, + {{{3,2},{4,1}},{{1,1},{4,1}}} => {53,54,76,122,134}, + {{{3,2},{4,1}},{{1,2},{3,1}}} => {78}, + {{{4,1}},{{5,1}}} => {1,2,19,20,26,64,67,97,121,123}, + {{{4,2}},{{1,1},{4,1}}} => {69,82,113,147,152,189,199,206,214}, + {{{4,1}},{{1,1},{1,2},{2,1}}} => {84,139,161,162,197}, + {{{4,1}},{{1,2},{3,1}}} => {159,179,181,182,183,184,192,194,198}, + {{{4,1}},{{1,1},{4,1}}} => {12,43,187,216}, + {{{3,2}},{{1,1},{1,2},{2,1}}} => {125,126,148,165,175,185,196,204}, + {{{4,1},{4,1},{4,1},{4,1}},{{5,1}}} => {222}, + {{{3,2}},{{1,1},{4,1}}} => {74,106,141,157,174,210}, + {{{3,2}},{{1,2},{3,1}}} => {46}, + {{{4,1},{4,1},{4,1},{4,1}},{{1,1},{4,1}}} => {16}, + {{{4,1},{4,1}},{{1,1},{1,1},{1,1},{2,1}}} => {133,170,209}, + {{{5,1}},{{1,1},{1,1},{1,1},{2,1}}} => {33,58}, + {{{2,2}},{{1,3},{2,1}}} => {87}, + {{{4,2}},{{1,1},{1,1},{1,1},{2,1}}} => {150,167,176,203}} + (sort keys SETS)/(k -> {k#0, k#1, #SETS#k, SETS#k})//netList + -- column one: structure of sing locus + -- column 2: factorization of Hessian. + -- column 3: # of REP sets + -- column 4: list of indices into REPS. + + -- We can use this collection to test IntegerEquivalences package: + -- Goal: for each set of labels REPS#i, determine if these are the same topology or different. + -- Note: some are very easy, some I can't yet do. + + -- example: REPS#87 {(1835, 0), (1864, 0), (1876, 0)} + -- example: REPS#222 + (X1, X2, X3) = REPS#87/(lab -> Xs#lab)//toSequence + (L1, F1) = (c2Form X1, cubicForm X1) + (L2, F2) = (c2Form X2, cubicForm X2) + (L3, F3) = (c2Form X3, cubicForm X3) + + (X1, X2) = REPS#222/(lab -> Xs#lab)//toSequence + (L1, F1) = (c2Form X1, cubicForm X1) + (L2, F2) = (c2Form X2, cubicForm X2) + + hessianMatches(F1, F2) | singularPointMatches(sub(F1, RQ), sub(F2, RQ)) | matchingData{L1 => L2, F1 => F2} + selectLinear oo | matchingData{L1 => L2, F1 => F2} + tryEquivalences(oo, RQ, (A, phi)) + + GV1 = classifyExtremalCurves X1 + GV2 = classifyExtremalCurves X2 + netList {GV1, GV2} + + (X1, X2) = REPS#44/(lab -> Xs#lab)//toSequence + (L1, F1) = (c2Form X1, cubicForm X1) + (L2, F2) = (c2Form X2, cubicForm X2) + + hessianMatches(F1, F2) | singularPointMatches(sub(F1, RQ), sub(F2, RQ)) | matchingData{L1 => L2, F1 => F2} + selectLinear oo | matchingData{L1 => L2, F1 => F2} + tryEquivalences(oo, RQ, (A, phi)) + + GV1 = classifyExtremalCurves X1 + GV2 = classifyExtremalCurves X2 + netList {GV1, GV2} + + + (X1, X2) = REPS#45/(lab -> Xs#lab)//toSequence + (L1, F1) = (c2Form X1, cubicForm X1) + (L2, F2) = (c2Form X2, cubicForm X2) + + hessianMatches(F1, F2) | singularPointMatches(sub(F1, RQ), sub(F2, RQ)) | matchingData{L1 => L2, F1 => F2} + selectLinear oo | matchingData{L1 => L2, F1 => F2} + tryEquivalences(oo, RQ, (A, phi)) + + GV1 = classifyExtremalCurves X1 + GV2 = classifyExtremalCurves X2 + netList {GV1, GV2} + + (X1, X2) = REPS#46/(lab -> Xs#lab)//toSequence + (L1, F1) = (c2Form X1, cubicForm X1) + (L2, F2) = (c2Form X2, cubicForm X2) + + hessianMatches(F1, F2) | singularPointMatches(sub(F1, RQ), sub(F2, RQ)) | matchingData{L1 => L2, F1 => F2} + selectLinear oo | matchingData{L1 => L2, F1 => F2} + tryEquivalences(oo, RQ, (A, phi)) + + GV1 = classifyExtremalCurves X1 + GV2 = classifyExtremalCurves X2 + netList {GV1, GV2} + + matchingData{transpose matrix GV1#{"FLOP", {1,0,0,0}} => transpose matrix GV2#{"FLOP", {1,0,0,0}}} + matchingData{{Permutations, transpose matrix GV1#{"FLOP", {3,0,0,0}}, transpose matrix GV2#{"FLOP", {1,0,0,0}}} + + -- hessians which should be straightforward + set1 = SETS#{{{5,1}}, {{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}} + elapsedTime for a in take(set1,6) list ( + if #REPS#a != 2 then continue; + << "DOING " << a << endl; + (X1, X2) = REPS#a/(lab -> Xs#lab)//toSequence; + (L1, F1) = (c2Form X1, cubicForm X1); + (L2, F2) = (c2Form X2, cubicForm X2); + md := hessianMatches(F1, F2) | {L1 => L2} | {F1 => F2}; + md1 := selectLinear md; + ans := tryEquivalences(md1 | {F1 => F2}, RQ, (A, phi)); + --if ans#0 === INCONSISTENT then {{first a}, {last a}} else if ans#0 === CONSISTENT then {first a, last a, ans#1} else {a, ans} + print (a => ans); + ans + ) + -- if a pair are the same, make a list {first, second, matrix} + -- if a pair is not the same, make {{first}, {second}} + + set1 = SETS#{{{5,1}}, {{1, 1}, {1, 1}, {1, 1}, {2, 1}}} -- {33, 58} both distinct. + set1 = SETS#{{{4,1},{4,1}}, {{1, 1}, {1, 1}, {1, 1}, {2, 1}}} -- {133, 170, 209} distinct pairs + set1 = SETS#{{{5,1}}, {{1, 1}, {1, 1}, {3, 1}}} -- + elapsedTime for a in take(set1,6) list ( + if #REPS#a != 2 then ( + << "DEFERRING " << a << " " << REPS#a << endl; + continue; + ); + << "DOING " << a << " " << REPS#a << endl; + (X1, X2) = REPS#a/(lab -> Xs#lab)//toSequence; + (L1, F1) = (c2Form X1, cubicForm X1); + (L2, F2) = (c2Form X2, cubicForm X2); + md := hessianMatches(F1, F2) | {L1 => L2} | {F1 => F2}; + md1 := selectLinear md; + ans := tryEquivalences(md1 | {F1 => F2}, RQ, (A, phi)); + --if ans#0 === INCONSISTENT then {{first a}, {last a}} else if ans#0 === CONSISTENT then {first a, last a, ans#1} else {a, ans} + print (a => ans); + ans + ) + +/// diff --git a/CYToolsM2/StringTorics/IntersectionNumbers.m2 b/CYToolsM2/StringTorics/IntersectionNumbers.m2 new file mode 100644 index 0000000..7eb4136 --- /dev/null +++ b/CYToolsM2/StringTorics/IntersectionNumbers.m2 @@ -0,0 +1,645 @@ +------------------------------------------------- +-- Intersection numbers for Calabi-Yau 3-folds -- +------------------------------------------------- +-- currently is functional only for hypersurfaces +-- in a toric 4-fold. Also, the polytope must be favorable. +-- TODO: remove favorable hypothesis +-- TODO: allow 4D CY's? +-- TODO: allow CI CY's in a Fano toric. + +intersectionNumbers = method() +-- intersectionNumbers = method(Options => {Indices => null}) -- Indices: which elements to keep. +-- -- these will be reordered 0, 1, ...,, #opts.Indices-1. +-- -- default for CalabiYauInToric is `basisIndices X` + +------------------------ +-- New code, Nov/Dec 2022. +-- This will replace the older code below, which uses the intersection ring. +-- However, we want to keep that code to check the results. +-- Also, the interface is currently totally different. +-- +-- TODO: +-- this function should stash its value in X? +-- we need to stash: +-- (a) intersectionNumbers (using basis, translating to 0, 1, ...): HashTable, lkeys are triples of ints +-- and values are integer intersection numbers. +-- (b) intersectionNumbers (full, using all toric divisors) +-- (c) c2 (a list of c2.D_(i1), ... where i1, ... is the basis of toric divisors. +-- (d) c2 (full) +-- Functions we need here: +-- the ring RZ should be given when X is created? If not, M2 will create one? +-- cubicForm X +-- c2 X +-- to/from intersection number tables and cubic form (for testing easily with older code). +-- computeIntersectionNumbers(A, basis, T2) +-- computeIntersectionNumbers(X) -- stashes results into X, +-- intersectionNumbers X -- stashes value if not yet computed. +-- c2 X -- stashes value if not yet computed. +-- intersectionNumbers(X, Basis => Full) +-- c2(X, Basis => Full) +-- dump(X): should dump these values +-- cyData(String, ...): should read these values +-- topology X -- returns TopologicalDataOfCY3: h11, h12, c2, cubicForm. + +-- dump: make sure we write out info about c2, intersectionNumbers as well. +-- and can read these back in. +-- also write out two face triangulation... +-- +-- topologicalData: return a type with (h11, h12, intersectionnumbers, c2 list) +-- no ring involved. +------------------------ + +-- toBasisIntersectionNumbers: An internal function for computeIntersectionNumbers +-* +toBasisIntersectionNumbers = (toricIntersectionNumbers, basIndices) -> ( + H := hashTable for i from 0 to #basIndices-1 list basIndices#i => i; + for t in toricIntersectionNumbers list ( + if isSubset(t#0, basIndices) then t#0/(a -> H#a)//sort => t#1 else continue + ) + ) +*- + +toBasisIntersectionNumbers = (toricIntersectionNumbers, basIndices, nonfavsHash) -> ( + -- toricIntersectionNumbers: list of {i,j,k} => intersection number. + -- basIndices: list of divisors and nonfavorable divisors making up the basis for Pic X. + -- e.g. {0,1,2,(5,0),(5,1),(5,2)} + -- nonfavsHash: hashtable, keys are nonfavorable toric divisors (so integers), and the value + -- is the list {genus of 2-face, index of 2-face}. This last is used to determine if two + -- nonfavorable toric divisors lie on the same 2-face (if not, they definitely have intersection 0). + -- Result: list of {i,j,k} => num, now they are all integers in the range 0..#basIndices-1. + -- and num is a non-zero integer. All other triple intersections are zero. + allBasisDivisors := set sort unique (basIndices/(x -> if instance(x, ZZ) then x else x#0)); + basisIndex := hashTable for i from 0 to #basIndices-1 list basIndices#i => i; + flatten for t in toricIntersectionNumbers list ( + if not isSubset(t#0, allBasisDivisors) then continue else ( + nonfavs := select(t#0, i -> nonfavsHash#?i); + if #nonfavs === 0 then {t#0/(a -> basisIndex#a)//sort => t#1} + else ( + if nonfavs/(i -> nonfavsHash#i#1)//unique//length > 1 then continue; + g := nonfavsHash#(nonfavs#0)#0; -- they are all the same 2-face, so should all have the same genus. + for ell from 0 to g list ( + tnew := sort for t1 in t#0 list if nonfavsHash#?t1 then basisIndex#(t1,ell) else basisIndex#t1; + if t#1 % (1+g) != 0 then error "internal error: logic is messed up here!"; + tnew => (t#1 // (1+g)) + ) + ) + ) + ) + ) + +-- computeToricIntersectionNumbers: An internal function for computeIntersectionNumbers +-- this is the workhorse function for computing intersection numbers on X. +computeToricIntersectionNumbers = method() +computeToricIntersectionNumbers(Matrix, List) := (A, T2) -> ( + intnums1 := hashTable flatten for t in T2 list for s in t#2 list s => t#3+1; + E := sort unique flatten for t in T2 list flatten for s in t#2 list subsets(s, 2); + -- get intersection numbers {i,i,j} or {i,j,j} + intnums2 := hashTable flatten for e in E list ( + (i,j) := toSequence e; + -- find intersection numbers for {i,i,j}, {i,j,j}. + A1 := A_e; + b := sum for k from 0 to numcols A - 1 list ( + if k == i or k == j then continue else ( + t := sort{i,j,k}; + (if intnums1#?t then intnums1#t else 0) * A_{k} + ) + ); + x := flatten entries solve(A1,-b); -- this is done over ZZ. I think that is fine here... + -- TODO: check that x is correct: A1*x == -b? + select({{i,i,j} => x#0, {i,j,j} => x#1}, x -> x#1 != 0) + ); + -- Now we get the triple intersection numbers. + intnums3 := hashTable for i from 0 to numcols A - 1 list ( + b := sum for k from 0 to numcols A - 1 list ( + if k == i then continue else ( + t := sort{i,i,k}; + (if intnums2#?t then (intnums2#t) else 0) * A_{k} + ) + ); + x := flatten entries solve(A_{i},-b); -- this is done over ZZ. I think that is fine here... + -- TODO: check that x is correct: A_{i}*x == -b? + if x#0 == 0 then continue else {i,i,i} => x#0 + ); + for x in sort join(pairs intnums1, pairs intnums2, pairs intnums3) list x#0 => x#1 + --FIXME: this should return a list of {i,j,k} => a, not ({i,j,k},a) + -- (to match intersectionNumbers) + ) + +-- computeC2: An internal function for computeIntersectionNumbers +computeC2 = method() +-- computeC2(List, List) := (toricIntersectionNumbers, basIndices) -> ( +-- topval := toricIntersectionNumbers/first/max//max; +-- H := hashTable toricIntersectionNumbers; +-- for a in basIndices list ( +-- -- add up all intersection numbers {a,i,j}, i ( + topval := toricIntersectionNumbers/first/max//max; + H := hashTable toricIntersectionNumbers; + for a in basIndices list ( + -- add up all intersection numbers {a,i,j}, i ( + if not X.cache#?"toric intersection numbers" then ( + Q := cyPolytope X; + basIndices := basisIndices Q; + A := transpose matrix rays Q; + nonfavs := hashTable findTwoFaceInteriorDivisors Q; + T2 := restrictTriangulation X; + result := computeToricIntersectionNumbers(A, T2); + X.cache#"toric intersection numbers" = result; + --X.cache#"intersection numbers" = toBasisIntersectionNumbers(result, Q.cache#"toric basis indices"); + X.cache#"intersection numbers" = toBasisIntersectionNumbers(result, basIndices, nonfavs); + X.cache#"c2" = computeC2(result, basIndices, nonfavs); + --X.cache#"c2" = computeC2(result, basIndices); + ); + --{result, toBasisIntersectionNumbers(result, basIndices)} + ) + +-------------------------------------------- +-- intersection number interface routines -- +-------------------------------------------- +intersectionNumbers CalabiYauInToric := X -> ( + computeIntersectionNumbers X; + X.cache#"intersection numbers" + --intersectionNumbersOfCY(ambient X, basisIndices X) + ) + +toricIntersectionNumbers = method() +toricIntersectionNumbers CalabiYauInToric := X -> ( + computeIntersectionNumbers X; + X.cache#"toric intersection numbers" + ) + +c2 = method(); +c2 CalabiYauInToric := X -> ( + computeIntersectionNumbers X; + X.cache#"c2" + ) + +-- maybe: toricIntersectionNumbers, c2, c2Form, intersectionForm. +-- +-- intersectionNumbers X, intersectionNumbers(X, Full => true), intersectionForm X +-- c2 X, c2Form X. + +-- TODO: if X is not favorable, need to redo the basis, and intersection numbers (and also then the c2 form) + +TEST /// +-* + restart + debug needsPackage "StringTorics" +*- + vs = {{-1, -1, -1, 0}, {-1, -1, 0, 0}, {-1, -1, 1, -1}, {-1, 0, -1, 0}, {0, -1, 2, -1}, {0, 0, -1, 0}, {0, 1, -1, 0}, {1, 1, -1, 1}, {1, 1, 0, 1}} + cones4 = {{0, 1, 2, 3}, {0, 1, 2, 4}, {0, 1, 3, 7}, {0, 1, 4, 7}, {0, 2, 3, 5}, {0, 2, 4, 5}, {0, 3, 5, 7}, {0, 4, 5, 7}, {1, 2, 3, 8}, {1, 2, 4, 8}, {1, 3, 7, 8}, {1, 4, 7, 8}, {2, 3, 5, 6}, {2, 3, 6, 8}, {2, 4, 5, 6}, {2, 4, 6, 8}, {3, 5, 6, 7}, {3, 6, 7, 8}, {4, 5, 6, 7}, {4, 6, 7, 8}} + Q = cyPolytope(vs, ID => 1000) + rays Q == vs + X = calabiYau(Q, cones4, ID => 0) + rays X == vs + max X == cones4 + + debug needsPackage "StringTorics" -- for toRingElement?? TODO: export that? + elapsedTime intersectionNumbers X + toRingElement(oo, picardRing X) + elapsedTime toricIntersectionNumbers X + assert(intersectionNumbers X === intersectionNumbersOfCY X) + elapsedTime c2 X + c2Form X + cubicForm X + + elapsedTime intersectionNumbers X + elapsedTime intersectionNumbersOfCY X + + elapsedTime topologicalData X + + -- F = openDatabase "polytopes-h11-5.dbm" + -- V = cyPolytope F#"1000" + -- close F + -- X = makeCY(V, ID => label V, Ring => (RZ = ZZ[a,b,c,d,e])) + + -- elapsedTime intersectionNumbers X + -- toRingElement(oo, X.cache#"pic ring") + -- elapsedTime toricIntersectionNumbers X + -- assert(intersectionNumbers X === intersectionNumbersOfCY X) + -- elapsedTime c2 X + -- c2Form X + -- cubicForm X + + -- elapsedTime intersectionNumbers X + -- elapsedTime intersectionNumbersOfCY X + + -- elapsedTime topologicalData(X, ZZ[a..e]) +/// + +----------------------------------------------- +-- Utility functions -------------------------- +-- Used to translate between data formats ----- +----------------------------------------------- +exponentToProduct = exp -> ( + -- exp is a list of integers, e.g. {0,3,1} + -- result is expanded to a product, e.g. {1,1,1,2} + -- the result includes integers in 0..#exp - 1, in ascending order. + -- e.g. + -- exponentToProduct {0,3,1} == {1,1,1,2} + flatten for i from 0 to #exp-1 list toList(exp#i : i) + ) + +productToExponents = (prod, nvars) -> ( + -- prod is a list of ascending integers, in range 0..nvars-1 + -- e.g. {0,1,1,2,4} + -- this is translated to an exponent vector, + -- e.g. + -- productToExponents({0,1,1,2,4}, 6) == {1,2,1,0,1,0} + -- this could be faster if needed + T := tally prod; + for i from 0 to nvars - 1 list if T#?i then T#i else 0 + ) + +multinomial = exp -> ( + -- exp is an exponent vector + -- returns an integer + -- e.g. + -- multinomial {1,0,2} == 3 + -- multinomial {1, 1, 1} == 6 + n := sum exp; + den := product for i from 0 to #exp - 1 list (exp#i)!; + n! // den + ) + +toCOO = method() +toCOO RingElement := (F) -> ( + sort for f1 in listForm F list ( + e := first f1; -- exponents + c := last f1; -- coeff + d := multinomial e; + e' := exponentToProduct e; + e' => if c % d ==0 then c//d else c/d -- TODO: not the exponent vector!! + ) + ) + +toRingElement = method() +toRingElement(List, Ring) := (f, RZ) -> ( + if #f == 0 then return 0_RZ; + n := sum f#0#0; + sum for f1 in f list ( + e' := f1#0; -- list of variable products, e.g. {0,1,1,2} + c := f1#1; -- coeff (an integer, currently envisioned) + e := productToExponents(e', numgens RZ); + d := multinomial e; + d * c * RZ_e + ) + ) + +c2Form = method() +c2Form CalabiYauInToric := RingElement => X -> ( + RZ := picardRing X; + ((vars RZ) * transpose matrix {c2 X})_(0,0) + ) + +cubicForm = method() +cubicForm CalabiYauInToric := RingElement => X -> ( + RZ := picardRing X; + toRingElement(intersectionNumbers X, RZ) + ) + +TEST /// +-- test of the (currently internal) routines: exponentsToProduct, +-- productToExponents, multinomial, toCOO, toRingElement. + debug StringTorics + assert(exponentToProduct {} == {}) + assert(exponentToProduct {3} == {0, 0, 0}) + assert(exponentToProduct {0, 3, 1} == {1, 1, 1, 2}) + assert(exponentToProduct {1, 2, 1, 0, 1, 0, 0, 0} == {0, 1, 1, 2, 4}) + assert(exponentToProduct {1, 1, 1, 1, 1} == {0, 1, 2, 3, 4}) + + assert(productToExponents({}, 0) == {}) + assert(productToExponents({}, 3) == {0, 0, 0}) + assert(productToExponents({0, 0, 0}, 1) == {3}) + assert(productToExponents({1, 1, 1, 2}, 3) == {0, 3, 1}) + assert(productToExponents({0, 1, 2, 3, 4}, 5) == {1, 1, 1, 1, 1}) + assert(productToExponents({0, 1, 1, 2, 4}, 8) == {1, 2, 1, 0, 1, 0, 0, 0}) + + assert(multinomial {3, 0, 0} == 1) + assert(multinomial {1,0,2} == 3) + assert(multinomial {1, 1, 1} == 6) + + RZ = ZZ[a,b,c] + F = (a+2*b+3*c)^3 + G = toCOO F + F' = toRingElement(G, RZ) + assert(F == F') + G' = toCOO F' + assert(G === G') + + L = 3*a+c + toCOO L + assert(toRingElement(toCOO L, RZ) == L) + + L = 1_RZ + toCOO L + assert(toRingElement(toCOO L, RZ) == L) + + L = 0_RZ + toCOO L + assert(toRingElement(toCOO L, RZ) == L) +/// + + +TEST /// +-- As it turns out, 'monoms' is much faster than first creating the basis, +-- and applying exponentToProduct to (the exponent vector of) every monomial +-- e.g. on MES's Apple M1 Max, 2022, doing nv = 81 the latter way gives .32 + 1.6 seconds +-- instead of .25 seconds. + debug StringTorics + elapsedTime assert(# monoms(3, 0, 10) == binomial(13,3)) + elapsedTime assert(# monoms(3, 0, 12) == binomial(15,3)) + elapsedTime assert(# monoms(3, 0, 20) == binomial(23,3)) + elapsedTime assert(# monoms(3, 0, 50) == binomial(53,3)) + elapsedTime assert(# monoms(3, 0, 80) == binomial(83,3)) -- .25 seconds + elapsedTime assert(# monoms(3, 0, 200) == binomial(203,3)) -- 1.5 seconds + + -- commented out so 'check' doesn't take too long + --elapsedTime assert(# monoms(3, 0, 300) == binomial(303,3)) -- 5.2 seconds + --elapsedTime assert(# monoms(3, 0, 400) == binomial(403,3)) -- 14.2 seconds + --elapsedTime assert(# monoms(3, 0, 495) == binomial(498,3)) -- 31 seconds + --elapsedTime assert(# monoms(3, 0, 490) == binomial(493,3)) -- 36 seconds, why longer? + + RZ = ZZ[t_1..t_20] + elapsedTime B = flatten entries basis(3, RZ); + #B + mons1 = B/(b -> exponentToProduct first exponents b) + mons2 = monoms(3, 0, 19) + mons1 === mons2 -- in the same order + + -- nv = 81 gives the timing above. + -- the order should be the same, For testing, we use a smaller value of nv. + nv = 10 + RZ = ZZ[t_1..t_nv] + elapsedTime B = flatten entries basis(3, RZ); + assert(#B == binomial(nv+2, 3)) + elapsedTime mons1 = B/(b -> exponentToProduct first exponents b); + elapsedTime mons2 = monoms(3, 0, nv-1); + assert(mons1 === mons2) -- in the same order +/// + +------------------------------------ +-- Intersection numbers via intersection ring in Schubert2 +-- This is an alternate method, slower than intersectionNumbers, +-- but that can be used to test intersectionNumbers. + +-- Alternate to intersectionNumbers, slower. But easier code. Only +-- works for the case when the ambient toric variety has no torsion in +-- the Class group. + +-- Simple subroutine for finding the list of indices for possible intersections. +-- e.g. if in the resulting list, {0,1,1} appears, then this will represent the +-- product H_0 . H_1 . H_1 (which is an integer) +monoms = (deg, lo, hi) -> ( + -- input: deg, lo, hi: all integers + -- output: a list of lists of integers all of length 'deg', + -- sorted in ascending order. + if deg == 0 then {{}} + else if lo === hi then {splice{deg:lo}} + else + flatten for i from lo to hi list ( + L1 := monoms(deg-1, i, hi); + for t in L1 list prepend(i, t) + ) + ) + +intersectionNumbersOfCY = method() + +intersectionNumbersOfCY(Ring, List) := HashTable => (IX, basisIndices) -> ( + -- IX: should be a ring produced for Schubert2, having 'integral' function for top degree elements. + -- basisIndices is a subList of {0, ..., numgens IX - 1}. + -- WARNING: this is cubic in number of generators of IX. This can be improved, + -- using the toric structure of X as a hypersurface in a toric V. + -- TODO WARNING: the 3 in here is for 3-folds...! + mons := monoms(3, 0, #basisIndices-1); + bas := for i in basisIndices list IX_i; + for t in mons list ( + m := integral product(t, i -> bas_i); + a := lift(integral product(t, i -> bas_i), ZZ); + if a === 0 then continue else t => a + ) + ) + +intersectionNumbersOfCY(NormalToricVariety, List) := (V, basisIndices) -> ( + X := completeIntersection(V, {-toricDivisor V}); + Xa := abstractVariety(X, base()); + IX := intersectionRing Xa; + intersectionNumbersOfCY(IX, basisIndices) + ) +intersectionNumbersOfCY CalabiYauInToric := X -> ( + intersectionNumbersOfCY(ambient X, basisIndices X) + ) + +-- end of intersectionNumbersOfCY, alternate slower method for +-- computing intersection numbers of a CY 3-fold. +------------------------------------------ + +TEST /// + -- Let's test the basis intersection numbers code at slightly higher h11... + -- TODO: This fails, as it uses old naming... +-* + restart + needsPackage "StringTorics" +*- + topes = kreuzerSkarke(7, Limit => 50); + assert(#topes == 50) + topes_30 + -- Here it is: + ks = KSEntry "4 10 M:33 10 N:12 8 H:7,29 [-44] id:30 + 1 0 0 1 -1 1 -1 -1 -2 0 + 0 1 1 0 -2 0 -2 2 -1 1 + 0 0 2 0 -4 2 -2 2 -2 2 + 0 0 0 2 -2 2 -2 0 -2 2 + " +-- A = matrix ks + Q = cyPolytope ks + elapsedTime Xs1 = findAllCYs(Q, Automorphisms => false, NTFE => false, Ring => ZZ[a_0..a_6]); + -- need a way to get one FRST, or perhaps a smaller number than "all". + Xs = findAllCYs Q; + X = Xs#0 + + toricMoriConeCap X + + -- TODO: add this in once GV invariants are back online: + -- classifyExtremalCurves X + + #Xs + X = first Xs + peek X + V = ambient X + assert isWellDefined V + assert isProjective V + assert isSimplicial V + + debug StringTorics + coo = intersectionNumbers X + RZ = ZZ[t_0..t_6] + F = toRingElement(coo, RZ) + assert(sort coo === sort toCOO F) +/// + +TEST /// + -- Let's see how high we can go with this simplistic routine. +-* + restart + debug needsPackage "StringTorics" +*- + debug needsPackage "StringTorics" -- for toRingElement + h11 = 20 + topes = kreuzerSkarke(h11, Limit => 50); + assert(#topes == 50) + + -- BUG: this is not giving h11=20... reason: topes_30 not favorable! + A = matrix topes_25 + P1 = convexHull A + P2 = polar P1 + annotatedFaces P2 + elapsedTime P = cyPolytope topes_25 -- reflexivePolytope A + isFavorable P + hh^(1,1) P == 20 + hh^(1,2) P == 12 + + elapsedTime X = makeCY P + elapsedTime coo = intersectionNumbers X; -- 4 seconds at h11=20. 3.2 seconds of this is computing the intersection ring. + assert(#coo == 175) + + RZ = ZZ[t_0..t_(h11-1)] + F = toRingElement(coo, RZ) + assert(sort coo === sort toCOO F) +/// + + +------------------------------ +-- REMOVE: tripleProductsCY -- +------------------------------ +-- This code is no longer simpler than current code. +-- Simpler code, used to debug the algorithm/implementation above. +tripleProductsCY = method() +tripleProductsCY NormalToricVariety := (V) -> ( + elapsedTime AV := abstractVariety(V, point); + IV := intersectionRing AV; + h := sum gens IV; -- Calabi-Yau hyperplane class in V. + J := ideal select((ideal IV)_*, f -> size f == 1); + forceGB gens J; + gens gb J; + A := (ring J)/J; + monoms := ideal basis(3, A); + elapsedTime JV := sub(monoms,IV); + elapsedTime (JVh := h ** (gens JV)); + flatJVh := flatten entries JVh; + hashTable for i from 0 to numgens monoms - 1 list ( + m := monoms_i; + d := integral(flatJVh#i); + if d > 0 then m => d else continue + ) + ) + +------------------------------ +-- REMOVE: possibleNonZeros -- +------------------------------ +possibleNonZeros = (V) -> ( + -- assumption currently: V has dim 4, is reflexive, and X is the anti-canonical CY3 divisor. + -- returns a list of lists of 3 integers (0 <= i1 <= i2 <= i3 <= N-1) + -- where N = #rays V. + -- and all triples other than those on this list must have triple intersection + -- on X being zero. + P2 := convexHull transpose matrix rays V; + F := annotatedFaces P2; + faces2 := select(F, f -> f#0 == 2); + faces2 = faces2/(x -> x#2); -- this is a list of all 2-faces in the polytope, + -- with which rays are on each face. + -- any triple not supported on a 2-face will have triple intersection zero. + triangles := (max V)/(t -> subsets(t,3))//flatten//unique; + edges := (max V)/(t -> subsets(t,2))//flatten//unique//sort; + triples := sort flatten for f in faces2 list select(triangles, t -> isSubset(t,f)); + singles := for i from 0 to # rays V - 1 list {i,i,i}; + doubles := sort flatten for f in faces2 list select(edges, t -> isSubset(t,f)); + doubles = unique flatten for x in doubles list {{x#0,x#0,x#1},{x#0,x#1,x#1}}; + {singles,doubles,triples} + ) + +-------------------------------------- +-- REMOVE: CY3NonzeroMultiplicities -- +-------------------------------------- + CY3NonzeroMultiplicities = method() + CY3NonzeroMultiplicities NormalToricVariety := (V) -> ( + RAYS := transpose matrix rays V; + P2 := convexHull RAYS; + (singles,doubles,triples) := toSequence possibleNonZeros V; + doubles = doubles/unique/sort//unique; + singles = singles/unique/sort//unique; + mult3 := new MutableHashTable from for x in triples list ( + x => 1 + genus(P2, minimalFace(P2, (rays V)_x)) + ); + multvec := ij -> ( + for ell from 0 to #rays V-1 list ( + if member(ell,ij) then 0 + else ( + s := sort append(ij,ell); + if mult3#?s then mult3#s else 0 + )) + ); + for d in doubles do ( + RHS := - RAYS * transpose (matrix{multvec d}); + vals := flatten entries solve(RAYS_d, RHS); + d1 := prepend(d#0,d); + d2 := append(d,d#1); + if vals#0 != 0 then mult3#d1 = vals#0; + if vals#1 != 0 then mult3#d2 = vals#1; + ); + for d in singles do ( + s := {d#0,d#0}; + RHS := - RAYS * transpose (matrix{multvec s}); + vals := flatten entries solve(RAYS_d, RHS); + if vals#0 != 0 then mult3#{d#0,d#0,d#0} = vals#0; + ); + new HashTable from mult3 + ) + +------------------------------ +-- REMOVE: CY3Intersections -- +------------------------------ +CY3Intersections = method() +CY3Intersections(NormalToricVariety, List) := (V, indexOfDs) -> ( + H := CY3NonzeroMultiplicities V; + loc := new HashTable from for i from 0 to #indexOfDs-1 list indexOfDs#i => i; + tr := k -> sort for k1 in k list loc#k1; + new Array from for kv in pairs H list ( + if not isSubset(kv#0, indexOfDs) then continue; + new Array from append(tr kv#0, kv#1) + ) + ) + diff --git a/CYToolsM2/StringTorics/Invariants.m2 b/CYToolsM2/StringTorics/Invariants.m2 new file mode 100644 index 0000000..e9818c3 --- /dev/null +++ b/CYToolsM2/StringTorics/Invariants.m2 @@ -0,0 +1,604 @@ +------------------------------------------------------------ +-- This file contains various invariants coming from the -- +-- cubic intersection form, and c2 form. ------------------- +------------------------------------------------------------ +-- Invariants include: +-- invariantsHubsch -- Hubsch invariants of L, F. + +-- 1. simple ones: content(L),content(F) (h11, h12 are either passed in, or not considered). +-- 2. Hubsch invariants +-- 3. Point counts +-- 4. Shape of (a ZZ-factorization of) the Hessian (and its content). +-- 5. Singularity info the cubic +-- 6. Singularity info of the intersection of the linear form and cubic. +-- 7. values of invariants (at leat for h11=3, maybe h11=4, what about higher? +-- Each invariants type can be called with (L, F, h11, h12), (L, F), or a CalabiYauInToric, or CYToolsCY3 +-- Point counting though requires a PointCount class in addition (otherwise, too slow). + +--------------------------------------- +-- Hubsch invariants ------------------ +--------------------------------------- +hubsch1 = X -> ( + -- X is a CalabYauInToric + N := hh^(1,1) X; + i := hashTable intersectionNumbers X; + gcdAll := gcd toSequence values i; + gcdDistincts := gcd toSequence( + flatten for A from 0 to N-3 list + flatten for B from A+1 to N-2 list + for C from B+1 to N-1 list ( + triple := sort {A,B,C}; + if i#?triple then i#triple else 0 + )); + gcdPairs := gcd toSequence( + -- this includes singles + flatten for A from 0 to N-1 list for B from 0 to N-1 list ( + triple := sort {A,A,B}; + if i#?triple then i#triple else 0 + )); + gcdPairs2 := gcd toSequence( + -- this includes singles + flatten for A from 0 to N-1 list flatten for B from 0 to N-1 list ( + triple1 := sort {A,A,B}; + triple2 := sort {A,B,B}; + val1 := if i#?triple1 then i#triple1 else 0; + val2 := if i#?triple2 then i#triple2 else 0; + {val1 + val2, val1 - val2} + )); + gcdSingles := gcd toSequence( + for A from 0 to N-1 list ( + triple := sort {A,A,A}; + if i#?triple then i#triple else 0 + )); + --return (gcdAll, gcdDistincts, gcdPairs, gcdSingles, gcdPairs); + d1 := gcdAll; + d2 := gcd(gcdPairs, 2*gcdAll); + d3 := gcd(gcdSingles, 3*gcdPairs2, 6*gcdAll); + (d1, d2, d3) + ) + +quadlinear = X -> ( + N := hh^(1,1) X; + i := hashTable intersectionNumbers X; + L := -2 * c2 X; -- p1 + ifcn := triple -> (triple = sort triple; if i#?triple then i#triple else 0); + unique for abcd in (0,0,0,0)..(N-1,N-1,N-1,N-1) list ( + (a,b,c,d) := abcd; + val := ifcn {a,b,c} * L#d + ifcn {b,c,d} * L#a + ifcn {c,d,a} * L#b + ifcn {d,a,b} * L#c; + if val != 0 then sort{a,b,c,d} => val else continue + ) + ) + +hubsch2 = X -> ( + N := hh^(1,1) X; + H := hashTable quadlinear X; + hfcn := ind -> (ind = sort ind; if H#?ind then H#ind else 0); + d4 := gcd(values H); + onedouble := gcd for k in keys H list if #unique k <= 3 then H#k else continue; + d5 := gcd(onedouble, 2*d4); + triples := for k in keys H list if any(values tally k, val -> val >= 3) then k else continue; + onetriple := if #triples > 0 then gcd for k in triples list H#k else 0; + d6part2 := toSequence for acd in (0,0,0)..(N-1,N-1,N-1) list ( + (a,c,d) := acd; + gcd(hfcn {a,a,c,d} + hfcn {a,c,c,d}, hfcn {a,a,c,d} - hfcn {a,c,c,d}) + ); + d6part2 = gcd d6part2; + d6 := gcd(onetriple, 3*d6part2, 6*d4); + -- Now for d7... + d7part1 := gcd for a from 0 to N-1 list hfcn {a,a,a,a}; + -- 2(2 \pm 3 \pm ). + d7part2s := for ad in (0,0)..(N-1,N-1) list ( + (a,d) := ad; + (a,d) => 2 * {2 * hfcn {a,a,a,d} + 3 * hfcn {a,a,d,d} + hfcn {a,d,d,d}, + 2 * hfcn {a,a,a,d} + 3 * hfcn {a,a,d,d} - hfcn {a,d,d,d}, + 2 * hfcn {a,a,a,d} - 3 * hfcn {a,a,d,d} + hfcn {a,d,d,d}, + 2 * hfcn {a,a,a,d} - 3 * hfcn {a,a,d,d} - hfcn {a,d,d,d}} + ); + d7part2 := gcd for ad in (0,0)..(N-1,N-1) list ( + (a,d) := ad; + 2 * gcd(2 * hfcn {a,a,a,d} + 3 * hfcn {a,a,d,d} + 2 * hfcn {a,d,d,d}, + 2 * hfcn {a,a,a,d} + 3 * hfcn {a,a,d,d} - 2 * hfcn {a,d,d,d}, + 2 * hfcn {a,a,a,d} - 3 * hfcn {a,a,d,d} + 2 * hfcn {a,d,d,d}, + 2 * hfcn {a,a,a,d} - 3 * hfcn {a,a,d,d} - 2 * hfcn {a,d,d,d}) + ); + d7part3 := gcd for acd in (0,0,0)..(N-1,N-1,N-1) list ( + (a,c,d) := acd; + 12 * gcd( + hfcn {a,a,c,d} + hfcn {a,c,c,d} + hfcn {a,c,d,d}, + hfcn {a,a,c,d} + hfcn {a,c,c,d} - hfcn {a,c,d,d}, + hfcn {a,a,c,d} - hfcn {a,c,c,d} + hfcn {a,c,d,d}, + hfcn {a,a,c,d} - hfcn {a,c,c,d} - hfcn {a,c,d,d}) + ); + --<< (d7part1, d7part2, d7part3, 24*d4) << endl; + d7 := gcd(d7part1, d7part2, d7part3, 24*d4); + (d4, d5, d6, d7) + ) + +hubschInvariants = method() +hubschInvariants CalabiYauInToric := X -> join(hubsch1 X, hubsch2 X, {gcd c2 X}) + +--------------------------------------- +-- Point counts ----------------------- +--------------------------------------- +allPrimitivePoints = (ht, n) -> ( + -- all nonzero primitive integer points in n-space, whose first + -- nonzero value is > 0 + -- and whose gcd is 1, with entries a satisfying |a| <= ht + ) + +allPointsToHeight = (ht, n) -> ( + -- all points in ZZ^n, with each entry a s.t. |a| <= ht. + pts := for a from -ht to ht list {a}; + if n === 1 then return pts; + if n === 0 then return {{}}; + if n < 0 then error "internal logic error"; + b := allPointsToHeight(ht, n-1); + flatten for a from -ht to ht list (b/(b1 -> prepend(a, b1))) + ) + +allPrimitivePointsToHeight = (ht, n) -> ( + pts := allPointsToHeight(ht, n); + for p in pts list ( + nonzero := select(1, p, a -> a != 0); + if #nonzero == 0 then continue; + --if nonzero#0 < 0 then continue; + if gcd p != 1 then continue; + p + ) + ) + +allPoints = (p, n) -> ( + -- all points in kk = ZZ//p in kk^n + pts := for a from 0 to p-1 list {a}; + if n === 1 then return pts; + if n === 0 then return {{}}; + if n < 0 then error "internal logic error"; + b := allPoints(p, n-1); + flatten for a from 0 to p-1 list (b/(b1 -> prepend(a, b1))) + ) + +allProjectivePoints = (p, n) -> ( + -- all points in n-space (with p elements in the field) with first non-zero value = 1, except 0. + flatten for i from 1 to n list ( + -- collect all the points with first non-zero value at location i+1. + firstPart := splice{(i-1): 0, 1}; + --print firstPart; + for pt in allPoints(p, n-i) list join(firstPart, pt) + )) + +createPointMaps = method(Options => {Projective => true}) +createPointMaps(ZZ, Ring) := opts -> (p, R) -> ( + pts := if opts.Projective then allProjectivePoints(p, numgens R) else allPoints(p, numgens R); + kk := ZZ/p; + for pt in pts list map(kk, R, pt) + ) +createPointMaps(Sequence, Ring) := opts -> (pr, R) -> ( + (p,r) := pr; + q := p^r; + pts0 := if opts.Projective then allProjectivePoints(q, numgens R) else allPoints(q, numgens R); + -- now for each one we translate to GF(p,nr); + t := local t; + kk := GF(p^r, Variable => t); + print kk_0; + H := new MutableList; + H#0 = 0_kk; + H#1 = kk_0; -- the variable; + for i from 2 to q-1 do H#i = kk_0 * H#(i-1); + for pt0 in pts0 list ( + pt := for a in pt0 list H#a; + map(kk, R, pt) + ) + ) + +PointCounter = new Type of HashTable +pointCounter = method(Options=> { +-- "Primes" => {2,3,5,7,11,13,(2,2),(3,2),(2,3),(2,4)}, -- h11=3 gives 166 diff. +-- "Primes" => {2,3,5,7,11,13,(2,2),(3,2),(2,3),17}, -- h11=3 gives 167 diff + "Primes" => {2,3,5,7,11,13,(2,2),(3,2),(2,3),17,19}, -- h11=3 gives 168 diff +-- "Primes" => {2,3,5,7,11,13,(2,2),(3,2),(2,3),17,19,23,29,31,37}, -- h11=3 still gives 168 diff +-- "Primes" => {2,3,5,7,11,13,(2,2),(3,2),(2,3),(2,4),17,19,23,(5,2),(3,3),29}, + Projective => true + }) +pointCounter Ring := PointCounter => opts -> RZ -> ( + -- we expect that RZ is a polynomial ring over ZZ, in n variables. + -- each element of LprimePowers is a prime or a sequence (p,r). + -- In the latter case we find points over GF(p^r), in the former, over ZZ/p. + n := numgens RZ; + LprimePowers := opts#"Primes"; + Lmaps := for pr in LprimePowers list createPointMaps(pr, RZ, Projective => opts.Projective); + PC := new PointCounter from { + symbol Ring => RZ, + "Primes" => LprimePowers, + "Elements" => Lmaps + }; + PC + ) + +pointCounts = method() +pointCounts(PointCounter, RingElement, RingElement) := List => (PC, L, F) -> ( + -- We return a list with 3 lists in it: + cL := polynomialContent L; + cF := polynomialContent F; + if cL != 1 then ( + L = L // cL; + --<< "content L = " << cL << " and L/cL = " << L << endl; + ); + if cF != 1 then ( + F = F // cF; + --<< "content F = " << cF << " and F/cF = " << F << endl; + ); + R := PC.Ring; + if R =!= ring L or R =!= ring F then error "expected elements to be over the same ring"; + elems := PC#"Elements"; + for eachset in elems list ( + nzerosL := 0; + nzerosF := 0; + nzerosBothLandF := 0; + for phi in eachset list ( + a := phi L; + b := phi F; + if a == 0 then nzerosL = nzerosL + 1; + if b == 0 then nzerosF = nzerosF + 1; + if a == 0 and b ==0 then nzerosBothLandF = nzerosBothLandF + 1; + ); + {nzerosL, nzerosF, nzerosBothLandF} + ) + ) +pointCounts(PointCounter, CalabiYauInToric) := List => (PC, X) -> ( + elapsedTime pointCounts(PC, c2Form X, cubicForm X) + ) +TEST /// +-* + restart + debug needsPackage "StringTorics" +*- + debug StringTorics -- for allPoints, createPointMaps + assert( + allPoints(3, 2) + === + {{0, 0}, {0, 1}, {0, 2}, {1, 0}, {1, 1}, {1, 2}, {2, 0}, {2, 1}, {2, 2}} + ) + + assert(allPoints(3,1) === {{0}, {1}, {2}}) + + allPoints(4, 3) + + R = ZZ[a,b] + createPointMaps(3, R) + createPointMaps(3, R, Projective => false) + createPointMaps((2,2), R) + createPointMaps((2,2), R, Projective => false) + createPointMaps((2,3), ZZ[a,b,c]) + + R = ZZ[a,b,c]; + elapsedTime PC = pointCounter(R, "Primes" => {2,3,5,7,11,13,(2,2),(3,2),(2,3)}); + transpose matrix pointCounts(PC, a+b, a^3+b^3+c^3-3*a*b*c) + transpose matrix pointCounts(PC, a+b, a^3+b^3+c^3-4*a*b*c) +/// + +invariantsH11H12 = method() +invariantsH11H12 CalabiYauInToric := X -> List => {hh^(1,1) X, hh^(1,2) X} + +invariantsContents = method() +invariantsContents CalabiYauInToric := List => X -> { + polynomialContent c2Form X, + polynomialContent cubicForm X + } + +----------------------------- +-- Hessian invariants ------- +----------------------------- +hessianInvariants = method() +hessianInvariants CalabiYauInToric := X -> ( + factorShape det hessian cubicForm X + ) + +----------------------------- +-- Singular set invariants -- +----------------------------- + +linearcontent := (I) -> ( + if I == 0 then return 0; + lins := select(I_*, f -> f != 0 and first degree f <= 1); + if #lins == 0 then return 0; + gcd for ell in lins list (trim content ell)_0 + ); + +contentToDegree := (d, I) -> ( + if I == 0 then return 0; + lins := select(I_*, f -> f != 0 and first degree f <= d); + if #lins == 0 then return 0; + gcd for ell in lins list (trim content ell)_0 + ); + +cubicConductorInvariants = method() +cubicConductorInvariants CalabiYauInToric := X -> ( + F := cubicForm X; + jac := ideal F + ideal jacobian F; + jacsat := saturate jac; + {integerPart jacsat, linearcontent jacsat} + ) + +cubicLinearConductorInvariants = method() +cubicLinearConductorInvariants CalabiYauInToric := X -> ( + L := c2Form X; + F := cubicForm X; + I := ideal(L,F); + jac := I + minors(2, jacobian I); + jacsat := saturate jac; + integerPart jacsat + ) + +singularContents = method() +singularContents CalabiYauInToric := (X) -> ( + F := cubicForm X; + F = F // polynomialContent F; + jac := ideal F + ideal jacobian F; + jacsat := saturate jac; + H := partition(f -> first degree f, jacsat_*); + degs := sort keys H; + prevgcd := 0; + done := false; + for i from 0 to max degs list ( + if prevgcd == 1 then break; + if not H#?i then prevgcd + else ( + gcd1 := gcd((H#i)/polynomialContent); + prevgcd = gcd(gcd1, prevgcd); + prevgcd + )) + ) + +singularContents Ideal := (J) -> ( + if not isHomogeneous J then error "expected homogeneous ideal"; + -- Also expect: coefficients are ZZ. + -- Grading is singly graded. + H := partition(f -> first degree f, J_*); + degs := sort keys H; + prevgcd := 0; + done := false; + for i from 0 to max degs list ( + if prevgcd == 1 then break; + if not H#?i then prevgcd + else ( + gcd1 := gcd((H#i)/polynomialContent); + prevgcd = gcd(gcd1, prevgcd); + prevgcd + )) + ) + +singularContentsQuartic = method() +singularContentsQuartic CalabiYauInToric := (X) -> ( + << "singularContentsQuartic: doing " << label X << endl; + F := cubicForm X; + F = F // polynomialContent F; + L := c2Form X; + L = L // polynomialContent L; + F = F*L; + jac := ideal F + ideal jacobian F; + jacsat := saturate jac; + singularContents jacsat + ) + +---------------------------------------------------------------------------------- + +--Ternary cubic form for +-- a*x^3 + b*y^3 + c*z^3 + 3*d*x^2*y + 3*e*y^2*z + 3*f*z^2*x + 3*g*x*y^2 + +-- 3*h*y*z^2 + 3*i*z*x^2 + 6*j*x*y*z + +aronholdS = method() +aronholdS RingElement := F -> ( + -- F should be a cubic in 3 variables. + S := ring F; + KK := coefficientRing S; + if numgens S =!= 3 then error "expected polynomial in 3 variables"; + if first degree F != 3 then error "expected cubic polynomial"; + t := local t; + S1 := KK[t_(1,0)..t_(4,2)]; + DM := genericMatrix(S1, 3, 4); + Fproduct := product for i from 1 to 4 list sub(F, {S_0 => t_(i,0), S_1 => t_(i,1), S_2 => t_(i,2)}); + f1 := diff((det DM_{3,0,1}), Fproduct); + f2 := diff((det DM_{2,3,0}), f1); + f3 := diff((det DM_{1,2,3}), f2); + f4 := diff((det DM_{0,1,2}), f3); + ans := 1/31104 * f4; + lift(ans, KK) + ) + +aronholdT = method() +aronholdT RingElement := F -> ( + -- F should be a cubic in 3 variables. + S := ring F; + KK := coefficientRing S; + if numgens S =!= 3 then error "expected polynomial in 3 variables"; + if first degree F != 3 then error "expected cubic polynomial"; + t := local t; + S1 := KK[t_(1,0)..t_(6,2)]; + DM := genericMatrix(S1, 3, 6); + G := product for i from 1 to 6 list sub(F, {S_0 => t_(i,0), S_1 => t_(i,1), S_2 => t_(i,2)}); + g1 := elapsedTime diff((det DM_{3,4,5}), G); + g2 := elapsedTime diff((det DM_{3,4,5}), g1); + g3 := elapsedTime diff((det DM_{2,0,5}), g2); + g4 := elapsedTime diff((det DM_{1,2,4}), g3); + g5 := elapsedTime diff((det DM_{0,1,3}), g4); + g6:= elapsedTime diff((det DM_{0,1,2}), g5); + lift(1/279936 * g6, KK) + ) + +-- j-invariant is: j = 1728*(4S)^3/((4S)^3 - T^2) (from https://www.notzeb.com/aronhold.html) +-- still need to check that. + +aronhold = method() +aronhold RingElement := List => F -> ( + -- formulas taken from https://www.notzeb.com/aronhold.html, checked by a test in this file. + H := hashTable toCOO F; + hf := a -> if H#?a then H#a else 0; + -- F = a*x^3 + b*y^3 + c*z^3 + 3*d*x^2*y + 3*e*y^2*z + 3*f*z^2*x + + -- 3*g*x*y^2 + 3*h*y*z^2 + 3*i*z*x^2 + 6*j*x*y*z + a := hf {0,0,0}; -- x^3 + b := hf {1,1,1}; -- y^3 + c := hf {2,2,2}; + d := hf {0,0,1}; -- x^2*y + e := hf {1,1,2}; -- y^2*z + f := hf {0,2,2}; -- z^2*x + g := hf {0,1,1}; + h := hf {1,2,2}; + i := hf {0,0,2}; + j := hf {0,1,2}; + S := a*g*e*c - a*g*h^2 - a*j*b*c + a*j*e*h + a*f*b*h - a*f*e^2 - + d^2*e*c + d^2*h^2 + d*i*b*c - d*i*e*h + d*g*j*c - d*g*f*h - + 2*d*j^2*h + 3*d*j*f*e - d*f^2*b - i^2*b*h + i^2*e^2 - + i*g^2*c + 3*i*g*j*h - i*g*f*e - 2*i*j^2*e + i*j*f*b + + g^2*f^2 - 2*g*j^2*f + j^4; + T := a^2*b^2*c^2 - 3*a^2*e^2*h^2 - 6*a^2*b*e*h*c + 4*a^2*b*h^3 + 4*a^2*e^3*c - + 6*a*d*g*b*c^2 + 18*a*d*g*e*h*c - 12*a*d*g*h^3 + 12*a*d*j*b*h*c - 24*a*d*j*e^2*c + + 12*a*d*j*e*h^2 - 12*a*d*f*b*h^2 + 6*a*d*f*b*e*c + 6*a*d*f*e^2*h + + 6*a*i*g*b*h*c - 12*a*i*g*e^2*c + 6*a*i*g*e*h^2 + 12*a*i*j*b*e*c + + 12*a*i*j*e^2*h - 6*a*i*f*b^2*c + 18*a*i*f*b*e*h - 24*a*g^2*j*h*c - + 24*a*i*j*b*h^2 - 12*a*i*f*e^3 + 4*a*g^3*c^2 - 12*a*g^2*f*e*c + + 24*a*g^2*f*h^2 + 36*a*g*j^2*e*c + 12*a*g*j^2*h^2 + 12*a*g*j*f*b*c - + 60*a*g*j*f*e*h - 12*a*g*f^2*b*h + 24*a*g*f^2*e^2 - 20*a*j^3*b*c - + 12*a*j^3*e*h + 36*a*j^2*f*b*h + 12*a*j^2*f*e^2 - 24*a*j*f^2*b*e + + 4*a*f^3*b^2 + 4*d^3*b*c^2 - 12*d^3*e*h*c + 8*d^3*h^3 + 24*d^2*i*e^2*c - + 12*d^2*i*e*h^2 + 12*d^2*g*j*h*c + 6*d^2*g*f*e*c - 24*d^2*j^2*h^2 - + 12*d^2*i*b*h*c - 3*d^2*g^2*c^2 - 24*g^2*j^2*f^2 + 24*g*j^4*f - + 12*d^2*g*f*h^2 + 12*d^2*j^2*e*c - 24*d^2*j*f*b*c - 27*d^2*f^2*e^2 + + 36*d^2*j*f*e*h + 24*d^2*f^2*b*h + 24*d*i^2*b*h^2 - 12*d*i^2*b*e*c - + 12*d*i^2*e^2*h + 6*d*i*g^2*h*c - 60*d*i*g*j*e*c + 36*d*i*g*j*h^2 + + 18*d*i*g*f*b*c - 6*d*i*g*f*e*h + 36*d*i*j^2*b*c - 12*d*i*j^2*e*h - + 60*d*i*j*f*b*h + 36*d*i*j*f*e^2 + 6*d*i*f^2*b*e + 12*d*g^2*j*f*c - + 12*d*g*j^3*c - 12*d*g*j^2*f*h + 36*d*g*j*f^2*e - 12*d*g*f^3*b + + 24*d*j^4*h + 12*d*j^2*f^2*b + 4*i^3*b^2*c + 24*i^2*g^2*e*c - + 27*i^2*g^2*h^2 - 36*d*j^3*f*e - 12*i^3*b*e*h + 8*i^3*e^3 - 24*i^2*g*j*b*c + + 36*i^2*g*j*e*h + 6*i^2*g*f*b*h + 12*i^2*j^2*b*h - 3*i^2*f^2*b^2 - + 12*d*g^2*f^2*h - 12*i^2*g*f*e^2 - 24*i^2*j^2*e^2 + 12*i^2*j*f*b*e - + 12*i*g^3*f*c + 12*i*g^2*j^2*c + 36*i*g^2*j*f*h - 12*i*g^2*f^2*e - + 36*i*g*j^3*h - 12*i*g*j^2*f*e + 12*i*g*j*f^2*b + 24*i*j^4*e - + 12*i*j^3*f*b + 8*g^3*f^3 - 8*j^6; + {S, T} + ) + +/// -- TEST: takes too long + debug StringTorics -- for aronholdS, aronholdT. + KK = QQ[a,b,c,d,e,f,g,h,i,j] + + S = a*g*e*c - a*g*h^2 - a*j*b*c + a*j*e*h + a*f*b*h - a*f*e^2 - + d^2*e*c + d^2*h^2 + d*i*b*c - d*i*e*h + d*g*j*c - d*g*f*h - + 2*d*j^2*h + 3*d*j*f*e - d*f^2*b - i^2*b*h + i^2*e^2 - + i*g^2*c + 3*i*g*j*h - i*g*f*e - 2*i*j^2*e + i*j*f*b + + g^2*f^2 - 2*g*j^2*f + j^4 + + T = a^2*b^2*c^2 - 3*a^2*e^2*h^2 - 6*a^2*b*e*h*c + 4*a^2*b*h^3 + 4*a^2*e^3*c - + 6*a*d*g*b*c^2 + 18*a*d*g*e*h*c - 12*a*d*g*h^3 + 12*a*d*j*b*h*c - 24*a*d*j*e^2*c + + 12*a*d*j*e*h^2 - 12*a*d*f*b*h^2 + 6*a*d*f*b*e*c + 6*a*d*f*e^2*h + + 6*a*i*g*b*h*c - 12*a*i*g*e^2*c + 6*a*i*g*e*h^2 + 12*a*i*j*b*e*c + + 12*a*i*j*e^2*h - 6*a*i*f*b^2*c + 18*a*i*f*b*e*h - 24*a*g^2*j*h*c - + 24*a*i*j*b*h^2 - 12*a*i*f*e^3 + 4*a*g^3*c^2 - 12*a*g^2*f*e*c + + 24*a*g^2*f*h^2 + 36*a*g*j^2*e*c + 12*a*g*j^2*h^2 + 12*a*g*j*f*b*c - + 60*a*g*j*f*e*h - 12*a*g*f^2*b*h + 24*a*g*f^2*e^2 - 20*a*j^3*b*c - + 12*a*j^3*e*h + 36*a*j^2*f*b*h + 12*a*j^2*f*e^2 - 24*a*j*f^2*b*e + + 4*a*f^3*b^2 + 4*d^3*b*c^2 - 12*d^3*e*h*c + 8*d^3*h^3 + 24*d^2*i*e^2*c - + 12*d^2*i*e*h^2 + 12*d^2*g*j*h*c + 6*d^2*g*f*e*c - 24*d^2*j^2*h^2 - + 12*d^2*i*b*h*c - 3*d^2*g^2*c^2 - 24*g^2*j^2*f^2 + 24*g*j^4*f - + 12*d^2*g*f*h^2 + 12*d^2*j^2*e*c - 24*d^2*j*f*b*c - 27*d^2*f^2*e^2 + + 36*d^2*j*f*e*h + 24*d^2*f^2*b*h + 24*d*i^2*b*h^2 - 12*d*i^2*b*e*c - + 12*d*i^2*e^2*h + 6*d*i*g^2*h*c - 60*d*i*g*j*e*c + 36*d*i*g*j*h^2 + + 18*d*i*g*f*b*c - 6*d*i*g*f*e*h + 36*d*i*j^2*b*c - 12*d*i*j^2*e*h - + 60*d*i*j*f*b*h + 36*d*i*j*f*e^2 + 6*d*i*f^2*b*e + 12*d*g^2*j*f*c - + 12*d*g*j^3*c - 12*d*g*j^2*f*h + 36*d*g*j*f^2*e - 12*d*g*f^3*b + + 24*d*j^4*h + 12*d*j^2*f^2*b + 4*i^3*b^2*c + 24*i^2*g^2*e*c - + 27*i^2*g^2*h^2 - 36*d*j^3*f*e - 12*i^3*b*e*h + 8*i^3*e^3 - 24*i^2*g*j*b*c + + 36*i^2*g*j*e*h + 6*i^2*g*f*b*h + 12*i^2*j^2*b*h - 3*i^2*f^2*b^2 - + 12*d*g^2*f^2*h - 12*i^2*g*f*e^2 - 24*i^2*j^2*e^2 + 12*i^2*j*f*b*e - + 12*i*g^3*f*c + 12*i*g^2*j^2*c + 36*i*g^2*j*f*h - 12*i*g^2*f^2*e - + 36*i*g*j^3*h - 12*i*g*j^2*f*e + 12*i*g*j*f^2*b + 24*i*j^4*e - + 12*i*j^3*f*b + 8*g^3*f^3 - 8*j^6 + + R = KK[x,y,z] + F = a*x^3 + b*y^3 + c*z^3 + 3*d*x^2*y + 3*e*y^2*z + 3*f*z^2*x + 3*g*x*y^2 + 3*h*y*z^2 + 3*i*z*x^2 + 6*j*x*y*z + + assert(aronholdS F == S) + elapsedTime assert(aronholdT F == T) -- 21 seconds, but comes out correct. + + (S,T) = toSequence aronhold F; + assert(aronholdS F == S) + assert(aronholdT F == T) -- aronholdT is really too intensive for impatient people. +/// + +hesseForm = method() +hesseForm RingElement := F -> ( + R := ring F; + if numgens R != 3 or first degree F =!= 3 or not isHomogeneous F + then error "expected homogeneous cubic in a ring with 3 variables"; + -- TODO: this doesn't check that the degrees are all 1 yet... + + ) + +TEST /// +-- from cubicForm Xs#(12,0) + RQ = QQ[a,b,c] + F = -a^3+9*a^2*b-9*a*b^2+3*b^3+3*a^2*c-3*a*c^2+c^3 + factor det hessian F + -- 3 factors: + a --> a, a-c -> b, a-b -> c + phi = map(RQ, RQ, {a, a-c, a-b}) + phi^-1 F -- same! + phi F +/// + +end-- + +-- notes on Elsenhans-Jahnel: Computing invariants of cubic surfaces (2020). + +-- Aronhold invariants S, T of cubic plane curves. +S = ZZ/32003[x_1..z_4] +DM = transpose genericMatrix(S, 4, 3) + +C = x_1^3 + y_1^3 + z_1^3 - 7 * x_1 * y_1 * z_1 +F4 = product for i from 1 to 4 list sub(F, {x_1 => x_i, y_1 => y_i, z_1 => z_i}); +size F4 +diff((det DM_{3,0,1}), F4); +diff((det DM_{2,3,0}), oo); +diff((det DM_{1,2,3}), oo); +diff((det DM_{0,1,2}), oo); + + +KK = QQ[a,b,c,d,e,f,g,h,i,j] +S4 = KK[x_1..z_4] +DM = transpose genericMatrix(S4, 4, 3) + +F = a*x_1^3 + b*y_1^3 + c*z_1^3 + 3*d*x_1^2*y_1 + 3*e*y_1^2*z_1 + 3*f*z_1^2*x_1 + 3*g*x_1*y_1^2 + 3*h*y_1*z_1^2 + 3*i*z_1*x_1^2 + 6*j*x_1*y_1*z_1 + +-- Compute S +F4 = product for i from 1 to 4 list sub(F, {x_1 => x_i, y_1 => y_i, z_1 => z_i}); +size F4 +diff((det DM_{3,0,1}), F4); +diff((det DM_{2,3,0}), oo); +diff((det DM_{1,2,3}), oo); +diff((det DM_{0,1,2}), oo); +aronholdS = 1/31104 * oo + +F = a*x^3 + b*y^3 + c*z^3 + 3*d*x^2*y + 3*e*y^2*z + 3*f*z^2*x + 3*g*x*y^2 + 3*h*y*z^2 + 3*i*z*x^2 + 6*j*x*y*z + + +aronholdS == a*g*e*c - a*g*h^2 - a*j*b*c + a*j*e*h + a*f*b*h - a*f*e^2 - d^2*e*c + d^2*h^2 + d*i*b*c - d*i*e*h + d*g*j*c - d*g*f*h - 2*d*j^2*h + 3*d*j*f*e - d*f^2*b - i^2*b*h + i^2*e^2 - i*g^2*c + 3*i*g*j*h - i*g*f*e - 2*i*j^2*e + i*j*f*b + g^2*f^2 - 2*g*j^2*f + j^4 + +restart +debug needsPackage "StringTorics" + +KK = QQ[a,b,c,d,e,f,g,h,i,j] +S4 = KK[x,y,z] +F = a*x^3 + b*y^3 + c*z^3 + 3*d*x^2*y + 3*e*y^2*z + 3*f*z^2*x + 3*g*x*y^2 + 3*h*y*z^2 + 3*i*z*x^2 + 6*j*x*y*z +aronholdS F +aronholdS(13*6*x*y*z) + +G = elapsedTime aronholdT F; +DM = genericMatrix(ring G, 3, 6) +elapsedTime diff((det DM_{3,4,5}), G); +elapsedTime diff((det DM_{3,4,5}), oo); +elapsedTime diff((det DM_{2,0,5}), oo); +elapsedTime diff((det DM_{1,2,4}), oo); +elapsedTime diff((det DM_{0,1,3}), oo); +elapsedTime diff((det DM_{0,1,2}), oo); + + diff --git a/CYToolsM2/StringTorics/LineBundleCohomology.m2 b/CYToolsM2/StringTorics/LineBundleCohomology.m2 new file mode 100644 index 0000000..7b89e59 --- /dev/null +++ b/CYToolsM2/StringTorics/LineBundleCohomology.m2 @@ -0,0 +1,620 @@ +-- several things here: +-- 1. line bundle cohomology on V (NormalToricVarieties, cohomcalg) +-- 2. basis as lists of (annotated) Laurent monomials) +-- 3. matrix of multiplication by F. +-- 4. compute ranks of matrices. What should be stashed? bases -- probably, matrices -- not sure, ranks -- not sure + +---------------------------------------------------------------- +-- Cohomology of line bundles: obtaining a basis of fractions -- +---------------------------------------------------------------- +toricCohomologySetup = method() +toricCohomologySetup NormalToricVariety := (X) -> ( + if not X.cache#?CohomologySetup then ( + -- part 1: compute free res of B^* (over ZZ^n) + R := ring X; + R1 := (coefficientRing R)(monoid[gens R, DegreeRank=>numgens R]); + B1 := monomialIdeal sub(ideal X, vars R1); + B1' := dual B1; + C := resolution comodule B1'; + -- part 2: take the (fine) degrees in there, and place them depending on HH^i, in a hash table + -- part 3: create multi-graded rings for each of these + -- finally, stash this info into the cache table of X. + -- outside of this: make a function that takes a degree (or an OO(D)?), and i, and computes the fractions for HH^i(V, OO(V)). + rawDegs := sort flatten for j from 0 to length C list (degrees C_j)/(x -> (sum x - j,x)); + rawDegsWithRings := for x in rawDegs list ( + -- x is (i, I), where I has length n is an array of 0 and 1's. + Ra := if all(x#1, i -> i == 0) then R else ( + ds := degrees R; + degs := for i from 0 to #x#1-1 list if x#1#i == 0 then ds_i else -ds_i; + (coefficientRing R)(monoid[generators R, Degrees=>degs]) + ); + (x#0, x#1, Ra) + ); + H := partition(x -> x#0, rawDegsWithRings); + X.cache#CohomologySetup = applyPairs(H, x -> (x#0, (x#1/(y -> drop(y,1))))); + ); + X.cache#CohomologySetup + ) +cohomologyBasis = method() +cohomologyBasis(ZZ, NormalToricVariety, List) := (i,X,L) -> ( + H := toricCohomologySetup X; + L = -L; + KR := frac ring X; + if not H#?i then return {}; + degs := H#i; + flatten for x in degs list ( + -- x is (I, R), I is a vector of 0,1's of length n = numgens R, and R is a multigraded ring + (I,Ra) := x; + deg := degree(Ra_I); + ---M := transpose matrix degrees Ra | transpose matrix{-L+deg}; + ---result := (normaliz(M, 5))#"gen"; + ---elems0 := if result === null then {} else entries result; + ---elems1 := select(elems0, v -> v#-1 == 1); + ---elems2 := elems1/(v -> drop(v,-1)); + ---exps := elems2; + --<< "L=" << L << " deg=" << deg << " -L-deg=" << -L-deg << endl; + elems := flatten entries basis(-L-deg, Ra); + --print elems; + exps := elems/exponents/first; + -- now need to place these into frac R. + for e in exps list ( + e1 := for i from 0 to #I-1 list if I#i == 0 then e#i else - e#i - 1; + KR_e1 + ) + ) + ) +genericCohomologyMatrix = method() + +-- Compute the map HH^i(V, OO_V(D+K)) --> HH^i(V, OO_V(D)) +-- as a mutable matrix, over a finite field. +-- given V, i, and D. +-- the map is given by multiplication by a random form F of HH^0(OO_V(K)). +-- Caveat: it is extemely unlikely, but could happen that the generic rank +-- does not occur: the actual generic rank could potentially be larger than +-- the rank of this matrix. +-- +genericCohomologyMatrix(ZZ, NormalToricVariety, List) := (i,V,D) -> ( + K := degree toricDivisor V; + basis1 := cohomologyBasis(1, V, D+K); + basis2 := cohomologyBasis(1, V, D); + basis0 := first entries basis(-K, ring V); + hash1 := hashTable for i from 0 to #basis1-1 list basis1#i => i; + hash2 := hashTable for i from 0 to #basis2-1 list basis2#i => i; + M := mutableMatrix(ZZ/32003, #basis2, #basis1); + for p in basis0 do ( + c := random ring M; + for k in keys hash1 do ( + m := p * k; + if hash2#?m then M_(hash2#m, hash1#k) = c; + ) + ); + M + ) + +cohomologyMatrix = method() +cohomologyMatrix(ZZ, NormalToricVariety, List, RingElement) := (i,V,D,F) -> ( + -- Create the map HH^i(V, D - degree F) --> HH^i(V, D), induced by mult by F (in Cox ring). + kk := coefficientRing ring F; + deg := degree F; -- F should be an element of the Cox ring. + basis1 := cohomologyBasis(i, V, D-deg); + basis2 := cohomologyBasis(i, V, D); + basis0 := terms F; + hash1 := hashTable for i from 0 to #basis1-1 list basis1#i => i; + hash2 := hashTable for i from 0 to #basis2-1 list basis2#i => i; + M := mutableMatrix(kk, #basis2, #basis1); + for tm in basis0 do ( + c := leadCoefficient tm; + p := leadMonomial tm; + for k in keys hash1 do ( + m := p * k; + if hash2#?m then M_(hash2#m, hash1#k) = c; + ) + ); + (M, basis2, basis1) + ) + +cohomologyMatrixRank = method() +cohomologyMatrixRank(ZZ, NormalToricVariety, List, RingElement) := (i,V,deg,F) -> ( + z := cohomologyMatrix(i,V,deg,F); + nrows := #z#1; + ncols := #z#2; + rk := rank z#0; + (nrows, ncols, rk) + ) + +-- The above code doesn't work on larger examples. Let's see if we can do better. +toricOrthants = method() +toricOrthants NormalToricVariety := (X) -> ( + -- part 1: compute free res of B^* (over ZZ^n) + R := ring X; + R1 := (coefficientRing R)(monoid[gens R, DegreeRank=>numgens R]); + B1 := monomialIdeal sub(ideal X, vars R1); + B1' := dual B1; + C := resolution comodule B1'; + -- part 2: take the (fine) degrees in there, and place them depending on HH^i, in a hash table + -- part 3: create multi-graded rings for each of these + -- finally, stash this info into the cache table of X. + -- outside of this: make a function that takes a degree (or an OO(D)?), and i, and computes the fractions for HH^i(V, OO(V)). + rawDegs := sort flatten for j from 0 to length C list (degrees C_j)/(x -> (sum x - j,x)); + rawDegs/(x -> (x#0, positions(x#1, i -> i != 0))) + ) + +H1orthants = method() +H1orthants NormalToricVariety := (X) -> ( + R := ring X; + R1 := (coefficientRing R)(monoid[gens R, DegreeRank=>numgens R]); + B1 := monomialIdeal sub(ideal X, vars R1); + B1' := dual B1; + R2 := (coefficientRing R)(monoid[gens R]); + B1'' := sub(B1', R2); + I := ideal select(flatten entries gens B1'', m -> degree m === {2}); + C := resolution(I, DegreeLimit=>1); + C1 := for i from 1 to length C list sub(C.dd_i, R1); + C2 := new MutableList; + C2#0 = map(target C1_0,, C1_0); + for i from 1 to length C1-1 do + C2#i = map(source C2#(i-1),, C1#i); + degs := flatten for phi in toList C2 list degrees source phi; + return for d in degs list positions(d, a -> a != 0); + -- part 2: take the (fine) degrees in there, and place them depending on HH^i, in a hash table + -- part 3: create multi-graded rings for each of these + -- finally, stash this info into the cache table of X. + -- outside of this: make a function that takes a degree (or an OO(D)?), and i, and computes the fractions for HH^i(V, OO(V)). + rawDegs := sort flatten for j from 0 to length C list (degrees C_j)/(x -> (sum x - j,x)); + rawDegs/(x -> (x#0, positions(x#1, i -> i != 0))) + ) + +-- goal: given V, find a permutation P, a d x d invertible (over ZZ) matrix Q, s.t. QAP = [-I | C] +-- where A == transpose matrix degrees ring V (assuming we can compute that ring! If not, we need to fix that later). +normalDegrees = method() +normalDegrees NormalToricVariety := (V) -> ( + if not V.cache.?normalDegrees then V.cache.normalDegrees = ( + S := ring V; + A := transpose matrix degrees S; + d := numRows A; + n := numColumns A; -- also numgens S. + good := select(1, max V, a -> (d := det A_a; d == 1 or d == -1)); + if good === {} then error "cannot find maximal cone with volume 1"; + cols := good#0; -- ordered list of d column indices of the (d x n) matrix A. + others := sort toList (set (0..n - 1) - set cols); + perm := join(cols, others); -- or is the inverse permutation!? + permInv := hashTable for i from 0 to #perm-1 list perm#i => i; + permInv = for i from 0 to #perm-1 list permInv#i; + Q := A_cols; + Anew := Q^-1 * A_perm; + C := Anew_{d..n-1}; + -- newdeg: take a degree in ZZ^d (old basis, using A), and change it to + -- a degree in ZZ^d, wrt the new basis. + newdeg := (deg1) -> flatten entries (Q^-1 * transpose matrix {deg1}); + -- newneg: take a subset of {0..n-1} (i.e. columns of A), and return the sorted + -- list of the corresponding columns of Anew. + newneg := (neg1) -> sort for x in neg1 list permInv#x; + -- mon is a row vector 0..n-1 w.r.t the new set of columns in Anew. + -- this function translates it back to a row vector w.r.t A, + -- and then provides a monomial in S (all with respect to the original + -- set of variables). + tofrac := (mon) -> ( + v1 := flatten entries (mon^permInv); + product for i from 0 to #v1-1 list ( + if v1_i > 0 then + S_i^(v1_i) + else if v1_i < 0 then + (1/S_i^(-v1_i)) + else 1_S + )); + -- A is a map ZZ^n --> ZZ^d + -- Anew is as well. + -- These induce an isomorphism ZZ^d (old) --> ZZ^d (new). + {Anew, perm, Q, newdeg, newneg, tofrac, permInv} + ); + V.cache.normalDegrees#0 + ) + +normalDegree = method() +normalDegree(NormalToricVariety, List) := (V, deg1) -> ( + normalDegrees V; -- we don't use the value, just the cached values. + V.cache.normalDegrees#3 deg1 + ) + +setOfColumns = method() +setOfColumns(NormalToricVariety, List) := (V, cols) -> ( + normalDegrees V; -- we don't use the value, just the cached values. + V.cache.normalDegrees#4 cols + ) + +getFraction = method() +getFraction(NormalToricVariety, List) := (V, mon) -> ( + normalDegrees V; -- we don't use the value, just the cached values. + V.cache.normalDegrees#5 mon + ) + +-- This one is now correct, I think. +findTope = method() +findTope(Matrix, List, List) := (normalA, normalNeg, normalDeg) -> ( + n := numColumns normalA; + d := numRows normalA; + C := normalA_{d..n-1}; + I := id_(ZZ^(n-d)); + alpha := if #normalNeg == 0 then normalDeg else + normalDeg + flatten entries sum(normalNeg, p -> normalA_p); + -- create hyperplanes matrix M, RHS b, polytope will be Mx <= b + hypers := mutableMatrix(C || -I); + RHS := mutableMatrix transpose matrix{join(alpha, toList(n-d: 0))}; + --return (hypers, RHS); + for p in normalNeg do ( + rowMult(hypers, p, -1); + rowMult(RHS, p, -1); + ); + (polyhedronFromHData(matrix hypers, matrix RHS), hypers, RHS) + ) + +cohomologyFractions = method() +cohomologyFractions(NormalToricVariety, List, List) := (V, negativeSet, deg) -> ( + -- returns a list of fractions in Ring S. + Anew := normalDegrees V; + d := numRows Anew; + n := numColumns Anew; + normalNeg := setOfColumns_V negativeSet; + beta := normalDegree(V, deg); + normalNegDegree := (sum for i in normalNeg list flatten entries Anew_i); + gamma := beta + normalNegDegree; + P := first findTope(Anew, normalNeg, beta); + if not isCompact P then error "Your negative set doesn't correspond to a cohomology cone"; + if isEmpty P then return {}; + LP := latticePoints P; + C := Anew_{d..n-1}; + for lp in LP list ( + mon := (transpose matrix{gamma} - C * lp) || lp; + (V.cache.normalDegrees#5 mon)/(product(negativeSet, i -> (ring V)_i)) + ) + ) + +-------------------------------------------------------------- +-- Cohomology for complete intersections in toric varieties -- +-------------------------------------------------------------- + +cohomologyVector = method() +cohomologyVector(NormalToricVariety, ToricDivisor) := (Y,D) -> cohomologyVector(Y, degree D) +cohomologyVector(NormalToricVariety, List) := (Y, D) -> (cohomCalg(Y, {D}); first Y.cache.CohomCalg#D) + +cohomology(ZZ, NormalToricVariety, List, RingElement) := opts -> (i,X,deg,F) -> ( + (nrows, ncols, rk1) := cohomologyMatrixRank(i, X, deg, F); + (nrows2, ncols2, rk2) := cohomologyMatrixRank(i+1, X, deg, F); + nrows-rk1 + ncols2 - rk2 + ) + +cohomology(ZZ, CompleteIntersectionInToric, List, RingElement) := opts -> (i,X,deg,F) -> ( + if dim X != dim ambient X - 1 then error "cohomology for line bundles of CI's of codimension >= 2 is not yet handled"; + V := ambient X; + (nrows, ncols, rk1) := cohomologyMatrixRank(i, V, deg, F); + (nrows2, ncols2, rk2) := cohomologyMatrixRank(i+1, V, deg, F); + nrows-rk1 + ncols2 - rk2 + ) + +cohomologyVector(CompleteIntersectionInToric, List, RingElement) := (X, deg, F) -> ( + -- TODO: allow full complete intersection here... Not just a hypersurface. + -- require currently that X has codim 1 in a toric variety + if dim X != dim ambient X - 1 then error "cohomology for line bundles of CI's of codimension >= 2 is not yet handled"; + V := ambient X; + rks := for i from 0 to dim ambient X list cohomologyMatrixRank(i, V, deg, F); + -- rks is a list of (nrows, ncols, rk). + for j from 0 to dim X list ( + (nrows1, ncols1, rk1) := rks#j; + (nrows2, ncols2, rk2) := rks#(j+1); + nrows1 - rk1 + ncols2 - rk2 + ) + ) + +cohomology(ZZ, CalabiYauInToric, List, RingElement) := opts -> (i,X,deg,F) -> ( + V := ambient X; + (nrows, ncols, rk1) := cohomologyMatrixRank(i, V, deg, F); + (nrows2, ncols2, rk2) := cohomologyMatrixRank(i+1, V, deg, F); + nrows-rk1 + ncols2 - rk2 + ) + +cohomologyVector(CalabiYauInToric, List, RingElement) := (X, deg, F) -> ( + V := ambient X; + rks := for i from 0 to dim ambient X list cohomologyMatrixRank(i, V, deg, F); + -- rks is a list of (nrows, ncols, rk). + for j from 0 to 3 list ( + (nrows1, ncols1, rk1) := rks#j; + (nrows2, ncols2, rk2) := rks#(j+1); + nrows1 - rk1 + ncols2 - rk2 + ) + ) + +cohomologyVector LineBundle := List => L -> ( + X := variety L; + Fs := equations X; + if #Fs =!= 1 then error "alas, complete intersection line bundle cohomology not yet implemented"; + cohomologyVector(X, degree L, Fs#0) + ) + +hh(ZZ, LineBundle) := ZZ => (i,L) -> ( + X := variety L; + Fs := equations X; + cohomology(i, X, degree L, Fs#0) + ) + +ScriptedFunctor ^* := (scriptedfun) -> if scriptedfun === hh then cohomologyVector else null + +------------------------------------------- +-- Cohomology from short exact sequences -- +------------------------------------------- +cohomologyFromLES = method() +cohomologyFromLES Matrix := (M) -> ( + les := flatten entries M; + eqns := trim splitLES les; + M % eqns + ) + +splitLES = L -> ( + alternatingSum := (P) -> (sign := 1; sum for i from 0 to #P-1 list (result := sign * P#i; sign = -sign; result)); + pos := positions(L, x -> x == 0); + if #pos == 0 then return ideal alternatingSum L; + pos = {-1}|pos|{#L}; + ideal for i from 1 to #pos-1 list ( + alternatingSum L_{pos#(i-1)+1..pos#i-1} + ) + ) +removeUnusedVariables = method() +removeUnusedVariables List := (L) -> ( + -- L is a list of matrices + R := ring L#0; + keepthese := L/support/set//sum//toList//sort; + A := (coefficientRing R)[keepthese]; + phi := map(A,R); + for m in L list phi m + ) + +collectLineBundles = method() +collectLineBundles(NormalToricVariety, List, List) := (Y, CI, Ds) -> ( + -- Y is a projective normal toric variety + -- CI is a list of multidegrees, i.e. elements in Cl(Y). + -- Ds is another such list + -- Result: a list of (r, {...}) of cohomologies that need to be computed, where r is the number of + -- CI divisors being used (0 <= r <= #CI). + N := #CI; + degRank := # rays Y - dim Y; + koszuls := for v in subsets CI list ( + if #v > 0 then degree(-sum v) else toList(degRank:0) + ); + rsort unique flatten for D in Ds list ( + d := if instance(D, ToricDivisor) then degree D else D; + for h in koszuls list (h+d) + ) + ) + +-------------------------------------------- +-- Complete Intersection in Toric Variety -- +-------------------------------------------- +initializeCohomologies = method(Options => {Symbol => getSymbol "a"}) +initializeCohomologies(CompleteIntersectionInToric, ZZ, ZZ) := opts -> (X, nlinebundles, nbundles) -> ( + -- remember that for each line bundle, we need (#CI-1) * (dim Y + 1) + (dim X + 1) variables + -- and for each new bundle, we need (dim X + 1) variables + nvars := nlinebundles * ((#X.CI - 1) * (dim X.Ambient + 1) + dim X + 1) + nbundles * (dim X + 1); + A := QQ(monoid [VariableBaseName=>opts#Symbol, Variables => 3*nvars+1200]); + X.cache.ring = A; + X.cache.cohom = new MutableHashTable; + X.cache.nextVar = 0; -- before a call to one of the routines here, nextVar == nextFinalVar, but this + -- is used to 'reserve' variables while determining LES relations. + -- After a set of cohomology vectors is completed, then they are 'squashed down': the variables appearing + -- (that are not finalized) are placed starting at nextFinalVar. + X.cache.nextFinalVar = 0; -- variables before this are finalized, and appear in some cohomology + ) +basicCohomologies = method(Options=>{Limit=>null}) +basicCohomologies(CompleteIntersectionInToric) := opts -> (X) -> ( + -- these include all the D_i's, and 00_X too + -- all that is needed on Y to get Omega_X^1... + N := #X.CI; + Y := ambient X; + dimY := dim Y; + dimX := dim X; + if not X.cache.?ring then + initializeCohomologies(X, #(rays Y) + 1, 2); + ndegrees := #(rays Y) - dimY; + Ds := prepend(Y_0-Y_0, for i from 0 to #(rays Y)-1 list (-Y_i)); + Ds = join(Ds, for h in X.CI list -h); + Ds = Ds/degree; + linebundles := collectLineBundles(Y, X.CI, Ds); + cohomCalg(Y, linebundles); -- actually computes the cohomologies needed over Y, cohoms is a MutableHashTable. + for d in Ds do cohomologyVector(X, d); + X.cache.cohom + ) +nextLineBundle = method() +nextLineBundle CompleteIntersectionInToric := (X) -> ( + -- returns a list of (#CI-1) cohom vectors of length: dim Y + 1 + -- and the last one has the same length, but is zero above dim X. + Y := X.Ambient; + CI := X.CI; + nvecs := #CI-1; + A := X.cache.ring; + firstvecs := for i from 0 to #CI-2 list ( + result := flatten entries genericMatrix(A, A_(X.cache.nextVar), 1, dim Y + 1); + X.cache.nextVar = X.cache.nextVar + dim Y + 1; + result + ); + lastvec := flatten entries genericMatrix(A, A_(X.cache.nextVar), 1, dim X + 1); + lastvec = join(lastvec, toList(#CI : 0)); + X.cache.nextVar = X.cache.nextVar + dim X + 1; + append(firstvecs, lastvec) + ) +nextBundle = method() +nextBundle CompleteIntersectionInToric := (X) -> ( + -- returns a single list, of length: dim X + 1, representing the + -- cohomoogies of a sheaf or vector bundle on X. + A := X.cache.ring; + result := flatten entries genericMatrix(A, A_(X.cache.nextVar), 1, dim X + 1); + X.cache.nextVar = X.cache.nextVar + dim X + 1; + result + ) +finalizeVariables = (X, L) -> ( + -- X is a CompleteIntersectionInToric + -- L: List of Matrix + -- each one should be a matrix over X.cache.ring. + -- Returned value: L': a list of matrices over the same ring, + -- where the variables have been moved + -- up to not waste ring indeterminants. + -- This updates X.cache.nextFinalVar, X.cache.nextVar as well. + -- YYY + R := ring L#0; + firstvar := X.cache.nextFinalVar; + -- We make a list of the variables that actually occur here + keepthese := L/support/set//sum; + keepthese = keepthese - set for i from 0 to firstvar-1 list X.cache.ring_i; + keepthese = sort toList keepthese; + -- now we create a ring map that maps these existing variables to their compacted counterpart + phi := map(R,R,for v from 0 to #keepthese-1 list (keepthese#v => R_(firstvar + v))); + X.cache.nextVar = X.cache.nextFinalVar = firstvar + #keepthese; + for m in L list phi m + ) +-- Interface for cohomology in toric complete intersections + +cohomologyVector(CompleteIntersectionInToric, List) := (X, degreeD) -> ( + if not X.cache.?cohom then basicCohomologies X; + if not X.cache.cohom#?degreeD then X.cache.cohom#degreeD = ( + CI := X.CI; + N := #CI; + Y := ambient X; + dimY := dim Y; + linebundles := collectLineBundles(Y, CI, {degreeD}); + cohoms := cohomCalg(Y, linebundles); -- actually computes the cohomologies needed over Y, cohoms is a MutableHashTable. + -- Next step is to create the short exact sequences we need. + H0 := partition(s -> #s, subsets CI); + H := applyPairs(H0, (r,v) -> (r, if r > 0 then apply(v, v0 -> degreeD - degree sum v0) else apply(v, v0->degreeD))); + -- H is a hash table: keys are 0..#CI, values: lists of degrees of line bundles at that step in Koszul complex. + -- Compute all of these cohomologies: + H1 := applyPairs(H, (r,v) -> (r, sum for v1 in v list cohomologyVector(Y,v1))); + -- Now create a ring with #CI*(dim Y + 1) number of variables + -- L contains the ansatz cohomology vectors for the syzygy vector bundles + L := reverse nextLineBundle X; + ses := prepend(matrix transpose{H1#N, H1#(N-1), L#(N-1)}, + reverse for i from 0 to N-2 list matrix transpose{L#(i+1), H1#i, L#i}); + J := trim (sum for s in ses list splitLES flatten entries s); + ses1 := for s in ses list (s%J); + if debugLevel > 0 then << "exact sequences: " << ses1 << endl; + M := (last ses1)_{2}; + M = first finalizeVariables(X,{M}); + result := take(flatten entries M, dim X + 1); + if all(result, x -> liftable(x, ZZ)) + then result = result/(x -> lift(x,ZZ)); + result + ); + X.cache.cohom#degreeD + ) +cohomologyVector(CompleteIntersectionInToric, ToricDivisor) := (X, D) -> cohomologyVector(X, degree D) +cohomologyVector CompleteIntersectionInToric := (X) -> cohomologyVector(X, 0 * (ambient X)_0) + +cohomologyOmega1 = method() +cohomologyOmega1(CompleteIntersectionInToric) := (X) -> ( + -- Need to make 2 ses's, and two cohom vectors for dim X + -- + if not X.cache.?cohom then basicCohomologies X; + if not X.cache.cohom#?"omega1" then X.cache.cohom#"omega1" = ( + dimX := dim X; + Y := ambient X; + CI := X.CI; + ndegrees := #(rays Y) - dim Y; + cohoms := basicCohomologies X; + cohomOOX := cohomologyVector(X, degree (0*Y_0)); + spot1 := sum for i from 0 to #(rays Y)-1 list cohomologyVector(X, - degree Y_i); + spot2 := sum for h in CI list cohomologyVector(X, - degree h); + -- note: we computed all the cohomologies above, now we consider vec1, vec2 + -- these are created after the above 4 lines, so that when we call finalizeVariables + --in cohomologyVector, they don't conflict with our choice of vec1 and and vec2 variables. + vec1 := nextBundle X; + vec2 := nextBundle X; + ses1 := { + vec1, + spot1, + ndegrees * cohomOOX}; + ses2 := { + spot2, + vec1, + vec2 + }; + sess := {transpose matrix ses1, transpose matrix ses2}; + J1 := ideal(vec2_0 - cohomOOX_1, vec2_(dimX) - cohomOOX_(dimX-1)); + J := trim (J1 + (sum for s in sess list splitLES flatten entries s)); + sess = for s in sess list (s%J); + if debugLevel > 0 then << "exact sequences: " << sess << endl; + M := (last sess)_{2}; + M = first finalizeVariables(X,{M}); + vec := flatten entries M; + if all(vec, x -> liftable(x,ZZ)) + then vec = vec/(x -> lift(x,ZZ)); + vec + ); + X.cache.cohom#"omega1" + ) + +hodgeDiamond = method() +hodgeDiamond CompleteIntersectionInToric := (X) -> ( + -- Assumptions: Y is smooth? + -- Certainly want: X is smooth. + -- if dimX <= 3, then we only need Omega1_X + -- if dimX == 4, then we can either use Omega2_X, or the topological Euler characteristic + dimX := dim X; + if dimX >= 4 then << "warning: not yet implemented for dimension >= 4, -1's mean not computed" << endl; + Y := ambient X; + vec1 := cohomologyOmega1 X; + vec0 := cohomologyVector(X, degree(0*Y_0)); + matrix for p from 0 to dimX list for q from 0 to dimX list ( + if p == 0 then vec0_q + else if q == 0 then vec0_p + else if p == 1 then vec1_q + else if q == 1 then vec1_p + else if p == dimX then vec0_(dimX-q) + else if q == dimX then vec0_(dimX-p) + else if p == dimX-1 then vec1_(dimX-q) + else if q == dimX-1 then vec1_(dimX-p) + else -1 + ) + ) + +-- Ds are toric divisors in a toric variety +-- Computes the cohomology vector of the intersection +-- of these divisors. +hodgeVector = method() +hodgeVector List := (Ds) -> ( + if #Ds == 0 then error "expected at least one divisor"; + V := variety Ds#0; + if not all(Ds, D -> instance(D,ToricDivisor) and variety D === V) + then error "expected divisors all on the same toric variety"; + D := completeIntersection(V, Ds); + cohomologyVector(D, degree (V_0-V_0)) + ) + +-- The following uses cohomology matrix and bases to compute +-- the cohomology dimensions. This gets exact values, based on specific +-- polynomials in the Cox ring, however it needs specific polynomials. + +makeCohomMatrix = method() +makeCohomMatrix(ZZ, NormalToricVariety, RingElement, RingElement) := (i,V,F,G) -> ( + (m1, base1, base2) := cohomologyMatrix(i,V,-degree F, G); + (m2, base3, base4) := cohomologyMatrix(i,V,-degree G, F); + if base2 != base4 then error "hmm, expected bases to be identical for columns"; + (matrix m1 || matrix m2, join(base1, base3), base2) + ) +cohomVectorOfCodim2 = method() +cohomVectorOfCodim2(NormalToricVariety, RingElement, RingElement) := (V,F,G) -> ( + maps := for i from 0 to dim V list makeCohomMatrix(i,V,F,G); + rks := for i from 0 to dim V list (#maps_i_1, rank maps_i_0, #maps_i_2); + if rks_0 != (0,0,0) then << "warning: expected H^0 part to be all zero" << endl; + if rks_1_2 != rks_1_1 then << "warning: expected H^1 map to be an inclusion" << endl; + if rks_(dim V)_1 != rks_(dim V)_0 then << "warning: expected H^" << dim V << " map to be a surjection" << endl; + for i from 0 to dim V - 2 list ( + rks_(i+1)_0 + rks_(i+2)_2 - rks_(i+1)_1 - rks_(i+2)_1 + if i == 0 then 1 else 0 + ) + ) +hodgeVector(List, List) := (Ds, Fs) -> ( + -- Ds: list of (effective) divisor classes on a toric variety + -- Fs: list of polynomials, one for each class. + -- currently: these are limited to #Ds == #Fs == 2 + -- invariant: degree Ds_i == degree Fs_i, all i. + if #Ds =!= 2 or #Fs =!= 2 then error "expected codimension 2 complete intersection in a toric variety"; + if degree Ds_0 =!= degree Fs_0 or degree Ds_1 =!= degree Fs_1 then + error "expected polynomials to be in the given divisor classes"; + V := variety Ds_0; + cohomVectorOfCodim2(V, Fs_0, Fs_1) + ) diff --git a/CYToolsM2/StringTorics/MyPolyhedra.m2 b/CYToolsM2/StringTorics/MyPolyhedra.m2 new file mode 100644 index 0000000..96df06a --- /dev/null +++ b/CYToolsM2/StringTorics/MyPolyhedra.m2 @@ -0,0 +1,481 @@ +-- also defined: +-- (1) dim(P,f) +-- (2) genus(P,f) + +-- functions from Polyhedra which we use here: +-- latticePoints P -- a different order than 'latticePoints P' +-- vertices P -- a different order than 'vertexList P' ! +-- faces(d,P) -- only in faceDimensionHash +-- polar P -- used often +-- dim P -- used often + +-- Our plan: stash into a Polyhedron, the information here +protect TCILatticePointList +protect TCIVertexList +protect TCIVertexMatrix +protect TCIFaceDimensionHash +protect TCIInteriorLatticeHash +protect TCILatticePointHash + +vertexList = method() +vertexList Polyhedron := (cacheValue symbol TCIVertexList) (P -> ( + verts := vertices P; + verts = try lift(verts,ZZ) else verts; + --if liftable(verts,ZZ) then verts = lift(verts,ZZ); + sort entries transpose verts + )) + +vertexMatrix = method() +vertexMatrix Polyhedron := (cacheValue symbol TCIVertexMatrix) (P -> ( + transpose matrix vertexList P + )) + +faceDimensionHash = method() +if Polyhedra#Options#Version == "1.3" then ( -- version of Polyhedra in M2 <= 1.9.2 + faceDimensionHash Polyhedron := (cacheValue symbol TCIFaceDimensionHash) ((P) -> ( + L := vertexList P; + vertexHash := hashTable for i from 0 to #L - 1 list (L#i => i); + hashTable flatten for i from 0 to dim P list for f in faces(dim P-i,P) list ( + -- USING INFO FROM POLYHEDRA + verts := vertices f; + --if liftable(verts,ZZ) then verts = lift(verts,ZZ); + verts = try lift(verts,ZZ) else verts; + (sort for v in entries transpose verts list vertexHash#v) => i + ) + )) +) else ( + faceDimensionHash Polyhedron := (cacheValue symbol TCIFaceDimensionHash) ((P) -> ( + L := vertexList P; + M := vertices P; -- different ordering, possibly, and also a matrix over QQ + M = try lift(M,ZZ) else M; + --if liftable(M,ZZ) then M = lift(M,ZZ); + verticesQ := entries transpose M; + vertexHash := hashTable for i from 0 to #L - 1 list (L#i => i); + hashTable flatten for i from 0 to dim P list for f in faces(dim P-i,P) list ( + -- USING INFO FROM POLYHEDRA + verts := first f; + if #(last f) > 0 then error "expected a polytope, but received a polyhedron"; + newverts := sort for v in verticesQ_verts list vertexHash#v; + newverts => i + ) + )) +) + +dim(Polyhedron, List) := (P,f) -> (faceDimensionHash P)#f + +faceList = method() +faceList(ZZ,Polyhedron) := (dimF,P) -> ( + H := faceDimensionHash P; + sort select(keys H, f -> H#f === dimF) + ) +faceList Polyhedron := P -> ( + H := faceDimensionHash P; + (pairs H)/((k,v) -> (v,k))//sort/last + ) + +dualFace = method() +dualFace(Polyhedron, List) := (P,f) -> ( + -- f is a sorted list of integer indices of the vertices, giving a face of P + -- returns a face of 'polar P', as a list of integer indices of the vertices of 'polar P' + V1 := vertexMatrix P; + V2 := transpose vertexMatrix polar P; + vp := V1_f; + g := positions(entries (V2 * vp), + x -> all(x, x1 -> x1 == -1)); + assert(sort g === g); + g + ) + +-- pts is a list of lattice points in P, or a single lattice point. +-- returns the minimal face of P (as sorted list of vertex indices) containing pts +minimalFace = method() +minimalFace(Polyhedron, List) := (P, pts) -> ( + if all(pts, x -> instance(x,ZZ)) then pts = {pts}; + V2 := transpose vertexMatrix polar P; + dualfaceverts := positions(entries (V2 * transpose matrix pts), + x -> all(x, x1 -> x1 == -1)); + dualFace(polar P, dualfaceverts) + ) + +latticePointList = method() +latticePointList Polyhedron := (cacheValue symbol TCILatticePointList) (P -> ( + -- this reorders the lattice points via dimension of smallest face containing them + Q := P; -- use Q for calling functions in Polyhedra, just for doc... + lp := latticePoints Q; + -- the following is our putative list of lattice points. + L := sort for p in lp list flatten entries lift(p,ZZ); + -- now we reorder this list, and set: + -- TCILatticePointList + -- TCILatticePointHash + -- TCIInteriorLatticeHash + L1 := sort for i from 0 to #L-1 list ( + f := minimalFace(P, L#i); + {dim(P,f), L#i, f} + ); + --L1 := sort for i from 0 to #L-1 list {faceDim(P,minimalFace(P,L#i)),L#i}; + L2 := L1/(x -> x#1); -- select the actual lattice point + -- now set the hash tables: + -- lattice point => index + H0 := hashTable for i from 0 to #L2-1 list L2#i => i; + P.cache.TCILatticePointHash = H0; + -- face => interior lattice points + H1 := partition(x -> last x, L1); -- partition on minimal face + H2 := applyPairs(H1, (k,v) -> (k,v/(v1 -> H0#(v1#1)))); + P.cache.TCIInteriorLatticeHash = H2; + L2 + )) +latticePointList(Polyhedron, List) := (P,f) -> ( + -- f is a sorted list of integer indices of the vertices, giving a face of P + -- returns the list of indices of lattice point on f. + V1 := vertexMatrix P; + LP1 := matrix latticePointList P; + V2 := vertexMatrix polar P; + g := dualFace(P,f); + positions(entries(LP1 * V2_g), x -> all(x, x1 -> x1 == -1)) + ) + +latticePointHash = method() +latticePointHash Polyhedron := P -> ( + latticePointList P; + P.cache.TCILatticePointHash + ) + +-- f is a sorted list of integer indices of the vertices, giving a face of P +-- returns the list of indices of lattice points in the relative interior of f. +interiorLatticePointList = method() +interiorLatticePointList(Polyhedron, List) := (P,f) -> ( + L := latticePointList P; + H := P.cache.TCIInteriorLatticeHash; + if H#?f then H#f else {} + ) + +-- number of interior points in the dual face +genus(Polyhedron, List) := (P,f) -> # interiorLatticePointList(polar P, dualFace(P,f)) + +annotatedFaces = method() +annotatedFaces Polyhedron := List => (P1) -> ( + P2 := polar P1; + sort for f in faceList P1 list ( + {dim(P1,f), + f, + latticePointList(P1,f), + # interiorLatticePointList(P1,f), + # interiorLatticePointList(P2, dualFace(P1,f)) + } + ) + ) +-- Returns a list for each face of P1 of dimension i: +-- {faceIndices, all lattice pts, #interior lattice pts, #interior lattice pts in dual face of P2} +annotatedFaces(ZZ,Polyhedron) := List => (i,P1) -> ( + P2 := polar P1; + sort for f in faceList(i,P1) list ( + {f, + latticePointList(P1,f), + # interiorLatticePointList(P1,f), + # interiorLatticePointList(P2, dualFace(P1,f)) + } + ) + ) + +-- -- private function for `isomorphisms` +-- findCombinatorialData = (aP, i) -> ( +-- -- aP: List, coming from annotated faces. +-- -- i: integer index: for a given vertex. +-- -- returns: list, of +-- -- {genus, edges: genus => number, 2faces: {#vertices, genus} => number}, 3faces: {#vertices, genus} => ZZ +-- -- these are counts for all faces containing i +-- -- or, maybe one hash table, {#vertices, genus} => count +-- -- #vertices can be 1,2,3. +-- sort for x in aP list if member(i, x#1) then {x#0, #x#1, x#3, x#4} else continue +-- ) + +-- -- private function for `isomorphisms` +-- findPossibleMatchings = (matchings) -> ( +-- -- matchings: List of (alpha, beta), alpha and beta lists of integers of the same length >= 1. +-- -- returns a list of {i1 => j1, ..., ir => jr}. +-- -- the possible matchings. +-- if #matchings === 0 then error "incorrect logic on my part, apparently"; +-- hd := matchings#0; +-- hdmatchings0 := permutations(#hd#0); +-- hdmatchings := for p in hdmatchings0 list for i from 0 to #hd#0-1 list hd#0#i => hd#1#(p#i); +-- if #matchings === 1 then return hdmatchings; +-- tl := drop(matchings, 1); +-- restmatchings := findPossibleMatchings tl; +-- Ps := permutations hd#1; +-- flatten for p in hdmatchings list for q in restmatchings list ( +-- sort join(p,q) +-- ) +-- ) + +-- /// +-- findPossibleMatchings{({0,1,2}, {0,1,2})} +-- findPossibleMatchings{({0,3}, {0,1})} +-- /// + +-- checkPossibleMatching = (A, perm, verticesP, verticesQ) -> ( +-- -- A is a n x n generic matrix over n^2 variables. +-- -- perm is a list {i1 => j1, ...} of indices into verticesP to indices into verticesQ +-- trim sum for ab in perm list ( +-- a := transpose matrix{verticesP _ (first ab)}; +-- b := transpose matrix{verticesP _ (last ab)}; +-- ideal (A * a - b) +-- ) +-- ) + +-- matchings = method() +-- matchings(List, List, ZZ) := (aP, aQ, nvertices) -> ( +-- HP := partition(i -> findCombinatorialData(aP, i), toList(0..nvertices - 1)); +-- HQ := partition(i -> findCombinatorialData(aQ, i), toList(0..nvertices - 1)); +-- if sort keys HP =!= sort keys HQ then ( +-- << "note: vertex data does not match" << endl; +-- return {}; +-- ); +-- if not all(keys HP, k -> #HP#k == #HQ#k) then ( +-- << "note: vertex number data does not match" << endl; +-- return {}; +-- ); +-- matchings := for k in keys HP list ( +-- HP#k, HQ#k +-- ); +-- matchings +-- ) + +-- isomorphisms = method() +-- isomorphisms(Polyhedron, Polyhedron) := (P, Q) -> ( +-- -- for now, we assume both are full dimensional? +-- vP := vertexList P; +-- vQ := vertexList Q; +-- n := #vP#0; -- TODO: check that all vP, vQ elements have the same length, n == dim P == dim Q +-- if #vP =!= #vQ then return {}; +-- -- Step 1: get numerical invariants for each vertex. +-- aP := annotatedFaces P; +-- aQ := annotatedFaces Q; +-- HP := partition(i -> findCombinatorialData(aP, i), toList(0..#vP - 1)); +-- HQ := partition(i -> findCombinatorialData(aQ, i), toList(0..#vQ - 1)); +-- if sort keys HP =!= sort keys HQ then ( +-- << "note: vertex data does not match" << endl; +-- return {}; +-- ); +-- if not all(keys HP, k -> #HP#k == #HQ#k) then ( +-- << "note: vertex number data does not match" << endl; +-- return {}; +-- ); +-- matchings := for k in keys HP list ( +-- HP#k, HQ#k +-- ); +-- possibles := findPossibleMatchings matchings; +-- if #possibles > 1000 then ( +-- << "#possibles == " << #possibles << endl; +-- return isomorphisms2(P, Q) +-- ); +-- --return {possibles, matchings, HP, HQ}; +-- t := getSymbol "t"; +-- R := QQ[t_(0,0)..t_(n-1,n-1)]; +-- A := genericMatrix(R, n, n); +-- As := for p in possibles list ( +-- J := checkPossibleMatching(A, p,vP, vQ); +-- if J == 1 then continue; -- not an isomorphism! +-- A0 := A % J; +-- A0 = try lift(A0, ZZ) else null; +-- if A0 === null then continue; +-- (A0, p/last) +-- ); +-- As +-- ) + +-- private function for isomorphisms2 +partialPermutations = (elems, num) -> ( + if num == 1 then return elems/(a -> {a}); + flatten for i from 0 to #elems-1 list for p in partialPermutations(drop(elems,{i,i}), num-1) + list + prepend(elems#i, p) + ) + +-- TODO: isomorphisms and isomorphisms2 should be combined in a smarter way: +-- use the known matches to restrict the possible maps. +-- then use this on only some of the vertices? +-- Vague description because I don't know how best to fix it yet. +-- isomorphisms2 = method() +-- isomorphisms2(Polyhedron, Polyhedron) := (P, Q) -> ( +-- -- here we don't bother with matchings. +-- -- instead we first find a set of n vertices which do not lie on a hyperplane. +-- -- and then we compute all possible matrices +-- VP := vertexMatrix P; +-- VQ := vertexMatrix Q; +-- m := numcols VP; +-- HP := hashTable for i from 0 to m-1 list (vertexList P)#i => i; +-- HQ := hashTable for i from 0 to m-1 list (vertexList Q)#i => i; +-- if m =!= numcols VQ then return {}; +-- n := numrows VP; +-- if n =!= numrows VQ then error "expected polytopes in the same space"; +-- indepset := for p in subsets(#vertexList P, n) list if det VP_p != 0 then break p; +-- t := getSymbol "t"; +-- R := QQ[t_(0,0)..t_(n-1,n-1)]; +-- A := genericMatrix(R, n, n); +-- VP0 := VP_indepset; +-- for q in partialPermutations(splice{0..#vertexList Q - 1}, n) list ( +-- J := trim ideal(A * VP0 - VQ_q); +-- if J == 1 then continue; +-- A0 := A % J; +-- A0 = try lift(A0, ZZ) else null; +-- if A0 === null then continue; +-- if abs(det A0) != 1 then continue; +-- newverts := entries transpose(A0 * VP); +-- if any(newverts, v -> not HQ#?v) then continue; +-- perm := for v in newverts list HQ#v; +-- (A0, perm) +-- ) +-- ) + +-- Based on code in CYTools. +-- Assumption: P, Q are full rank polyhedra (i.e. dim = #rows of vertices matrix). +-- Idea: find a facet of P with the smallest cardinality. +-- find a subset of these vertices that define a full dimensional set. +-- for each + +isomorphisms = method() +-- isomorphisms(Polyhedron, Polyhedron) := (P, Q) -> ( +-- nrows := numrows vertexMatrix P; +-- if nrows != dim P or nrows != dim Q or nrows != numrows vertexMatrix Q +-- then error "expected polytoeps to be full dimensional and same dimension"; + +-- -- Step 1. Find a facet of P with the smallest size. +-- facetsP := (annotatedFaces(3, P))/first; +-- minsizeP := facetsP/length//min; +-- facetsMinsizeP := select(facetsP, f -> #f === minsizeP); +-- facetA := first facetsMinsizeP; + +-- -- Step 2. Find all facets of Q with this smallest size minsizeP, or return {}. +-- facetsQ := (annotatedFaces(3, Q))/first; +-- minsizeQ := facetsQ/length//min; +-- if minsizeQ =!= minsizeP then return {}; +-- facetsMinsizeQ := select(facetsQ, f -> #f === minsizeP); + +-- -- Now find a subset of nrows elements if facetA which are full dimensional +-- if #facetA > nrows then ( +-- -- we need to take a subset of these of size nrows that have full rank. +-- -- we then call these facetA again. We don't actually need facetA again, +-- -- the only thing we use is Ainv. +-- C := ((vertexMatrix P)_facetA) ** QQ; +-- facetA = facetA _ (columnRankProfile mutableMatrix C); +-- if #facetA != nrows then error "my logic is missing a case"; +-- ); +-- A := (vertexMatrix P)_facetA; +-- Ainv := (A ** QQ)^-1; + +-- -- now we loop through all possible maps from facetA to other facets, +-- -- and if it gives an integer matrix, we add it to the list. +-- vertsP := (vertexList P)/(v -> transpose matrix {v}); +-- vertsQ := (vertexList Q)/(v -> transpose matrix {v}); +-- hashQ := hashTable for i from 0 to #vertsQ-1 list vertsQ#i => i; +-- elapsedTime isos := flatten for f in facetsMinsizeQ list ( +-- for perm in partialPermutations(f, nrows) list ( +-- B := (vertexMatrix Q)_perm; +-- M := B * Ainv; +-- try (M = lift(M, ZZ)) else continue; +-- if all(vertsP, v -> hashQ#?(M * v)) then M else continue +-- ) +-- ); +-- isos +-- ) + +isomorphisms(Polyhedron, Polyhedron, List, List) := (P, Q, annotatedFacesP, annotatedFacesQ) -> ( + nrows := numrows vertexMatrix P; + if nrows != dim P or nrows != dim Q or nrows != numrows vertexMatrix Q + then error "expected polytoeps to be full dimensional and same dimension"; + + -- Step 1. Find a facet of P with the smallest size. + facetsP := for f in annotatedFacesP list if f#0 != nrows-1 then continue else f#1; + minsizeP := facetsP/length//min; + facetsMinsizeP := select(facetsP, f -> #f === minsizeP); + facetA := first facetsMinsizeP; + + -- Step 2. Find all facets of Q with this smallest size minsizeP, or return {}. + facetsQ := for f in annotatedFacesQ list if f#0 != nrows-1 then continue else f#1; + minsizeQ := facetsQ/length//min; + if minsizeQ =!= minsizeP then return {}; + facetsMinsizeQ := select(facetsQ, f -> #f === minsizeP); + + -- Now find a subset of nrows elements if facetA which are full dimensional + if #facetA > nrows then ( + -- we need to take a subset of these of size nrows that have full rank. + -- we then call these facetA again. We don't actually need facetA again, + -- the only thing we use is Ainv. + C := ((vertexMatrix P)_facetA) ** QQ; + facetA = facetA _ (columnRankProfile mutableMatrix C); + if #facetA != nrows then error "my logic is missing a case"; + ); + A := (vertexMatrix P)_facetA; + Ainv := (A ** QQ)^-1; + + -- now we loop through all possible maps from facetA to other facets, + -- and if it gives an integer matrix, we add it to the list. + vertsP := (vertexList P)/(v -> transpose matrix {v}); + vertsQ := (vertexList Q)/(v -> transpose matrix {v}); + hashQ := hashTable for i from 0 to #vertsQ-1 list vertsQ#i => i; + isos := flatten for f in facetsMinsizeQ list ( + for perm in partialPermutations(f, nrows) list ( + B := (vertexMatrix Q)_perm; + M := B * Ainv; + try (M = lift(M, ZZ)) else continue; + if all(vertsP, v -> hashQ#?(M * v)) then M else continue + ) + ); + isos + ) + +isomorphisms(Polyhedron, Polyhedron) := (P, Q) -> + isomorphisms(P, Q, annotatedFaces P, annotatedFaces Q) + +automorphisms = method() +automorphisms Polyhedron := P -> isomorphisms(P, P) + +/// + restart + debug needsPackage "StringTorics" + topes = kreuzerSkarke 3; + Q = cyPolytope topes_20 + Q = cyPolytope topes_0 + P = polytope(Q, "N") + vertexList P + annotatedFaces P + + isomorphisms3(Q,Q) +-- code I'm working on now + elapsedTime isomorphisms3(P, P) + elapsedTime isomorphisms(P,P) + + (Qs, Xs) = readCYDatabase "../Databases/cys-ntfe-h11-3.dbm"; + (Qs, Xs) = readCYDatabase "../Databases/cys-ntfe-h11-4.dbm"; + (Qs, Xs) = readCYDatabase "../Databases/cys-ntfe-h11-5.dbm"; + + -- This one is long, I think because the annotated faces for P is not stashed. + elapsedTime for lab in sort keys Qs list ( + automorphisms Qs#lab + ); + + elapsedTime for lab in sort keys Qs list ( + P := polytope Qs#lab; + annotatedFaces P); + + +-- older code + netList isomorphisms(P,P) + isomorphisms2(P,P) + first oo + netList oo + + for tope in topes list ( + Q := cyPolytope tope; + P := polytope(Q, "N"); + ans := isomorphisms(P, P); + if ans == null then + << "--- tope: " << label Q << " TOO LARGE FOR NOW" << endl; + else + << "--- tope: " << label Q << " #aut=" << #ans << " auts: " << netList ans << endl; + ans + ); + +/// +end-- + diff --git a/CYToolsM2/StringTorics/ShellFiles.m2 b/CYToolsM2/StringTorics/ShellFiles.m2 new file mode 100644 index 0000000..c06844c --- /dev/null +++ b/CYToolsM2/StringTorics/ShellFiles.m2 @@ -0,0 +1,84 @@ +blocks = method() +blocks(ZZ, ZZ, ZZ) := (ntotal, nperrun, nperfile) -> ( + -- returns list of (filenum, lo, hi), -- starting at lo=0, hi=ntotal-1. + count := 0; + filenum := 0; + thisfile := nperfile; + while count < ntotal list ( + if thisfile == nperfile then ( + filenum = filenum + 1; + thisfile = 0; + ); + lo := count; + hi := min(ntotal-1, lo + nperrun-1); + count = hi+1; + thisfile = thisfile + 1; + {filenum, lo, hi} + ) + ) + +blocks(ZZ, ZZ, ZZ, ZZ) := (abslo, hi, nperrun, nperfile) -> ( + -- returns list of (filenum, lo, hi), -- starting at lo=0, hi=ntotal-1. + count := 0; + filenum := 0; + thisfile := nperfile; + ntotal := hi-abslo+1; + while count < ntotal list ( + if thisfile == nperfile then ( + filenum = filenum + 1; + thisfile = 0; + ); + lo := count; + hi = min(ntotal-1, lo + nperrun-1); + count = hi+1; + thisfile = thisfile + 1; + {filenum, lo + abslo, hi + abslo} + ) + ) + +createShellFiles = method(Options => { + Processes => null, -- number of different M2 calls in each file + Count => null, -- number of elements per M2 run. + Range => {0, -1} + }) +createShellFiles(String, String) := opts -> (prefixstr, m2str) -> ( + nperrun := opts.Count; + nperfile := opts.Processes; + lo := opts.Range#0; + hi := opts.Range#1; + groups := blocks(lo, hi, nperrun, nperfile); + -- each file will have nperfile lines, plus an echo at the end? + thisfile := -1; + F := null; + for b in groups do ( + if b#0 != thisfile then ( + if F =!= null then close F; + F = openOut(prefixstr|"shell-set-"|b#0|".sh"); + thisfile = b#0; + ); + lo1 := b#1; + hi1 := b#2; + str := replace("@lo@", toString lo1, m2str); + str = replace("@hi@", toString hi1, str); + str = replace("@prefix@", toString prefixstr, str); + F << str << " &" << endl; + ); + if F =!= null and isOpen F then close F; + ) + + +end-- + restart + needs "../ShellFiles.m2" + m2str = ///M2 -e 'needsPackage "StringTorics"' -e 'createCYDatabase("@prefix@",3,{@lo@,@hi@})' -e 'exit 0' /// + m2str = ///M2 -e 'needs "ShellFiles.m2"' -e 'testit(@prefix@,{@lo@,@hi@})' -e 'exit 0' /// + +blocks(224, 10, 12) +blocks(0, 223, 10, 12) +netList blocks(0, 37123, 1000, 10) +createShellFiles("./Foo3/", "callme(@prefix@, @lo@, @hi@)", + Processes => 10, Count => 1000, Range => {0,17000}) + + m2str = ///M2 --stop -e 'needsPackage "StringTorics"' -e 'createCYDatabase("@prefix@",3,{@lo@,@hi@})' -e 'exit 0' /// +createShellFiles("./Foo3/", m2str, + Processes => 10, Count => 5, Range => {0,243}) diff --git a/CYToolsM2/StringTorics/Topology.m2 b/CYToolsM2/StringTorics/Topology.m2 new file mode 100644 index 0000000..ba2d5d0 --- /dev/null +++ b/CYToolsM2/StringTorics/Topology.m2 @@ -0,0 +1,1376 @@ +-- Code to compute the topology of a CY 3-fold. +-- Also contains code to help determine whether two CY3's are homeomorphic +-- (this appears to be equivalent to being diffeomorphic). + +topologicalData = method() +-- topologicalData CalabiYauInToric := TopologicalDataOfCY3 => X -> ( +-- -- TODO: this does not consider torision in H_2(X, ZZ) or H_3(X, ZZ) +-- << "calling topologicalData" << endl; +-- elapsedTime new TopologicalDataOfCY3 from { +-- "h11" => hh^(1,1) cyPolytope X, +-- "h21" => hh^(2,1) cyPolytope X, +-- "c2" => c2 X, +-- "intersection numbers" => intersectionNumbers X +-- } +-- ) + +topologicalData CalabiYauInToric := TopologicalDataOfCY3 => X -> ( + -- TODO: this does not consider torision in H_2(X, ZZ) or H_3(X, ZZ) + new TopologicalDataOfCY3 from { + c2Form X, + cubicForm X, + hh^(1,1) X, + hh^(1,2) X + } + ) + -- << "calling topologicalData" << endl; + -- elapsedTime new TopologicalDataOfCY3 from { + -- "h11" => hh^(1,1) cyPolytope X, + -- "h21" => hh^(2,1) cyPolytope X, + -- "c2" => c2 X, + -- "intersection numbers" => intersectionNumbers X + -- } + -- ) + + +-- this is the older, alternate version of this function. +-- this is to be removed. +-- topologicalData(CalabiYauInToric, Ring) := TopologicalDataOfCY3 => (X, RZ) -> ( +-- V := ambient X; +-- Q := X#"polytope data"; +-- P := polytope Q; +-- data := elapsedTime topologyOfCY3(V, basisIndices X); +-- -- this data above computes intersection numbers for all toric divisors. +-- -- So we consider only the ones whose indices are contained in basis indices: +-- new TopologicalDataOfCY3 from { +-- "h11" => elapsedTime hh^(1,1) Q, +-- "h21" => elapsedTime hh^(2,1) Q, +-- "c2" => sub(data_3, vars RZ), +-- "cubic intersection form" => sub(data_2, vars RZ) +-- } +-- ) + +isEquivalent = method() +isEquivalent(Sequence, Sequence, Matrix) := Boolean => (LF1, LF2, A) -> ( + (L1,F1) := LF1; + (L2,F2) := LF2; + R := ring L1; + if R =!= ring F1 or R =!= ring L2 or R =!= ring F2 then + error "excepted c2 and cubic forms to be in the same ring"; + phi := map(R, R, A); + phi L1 == L2 and phi F1 == F2 + ) +isEquivalent(CalabiYauInToric, CalabiYauInToric, Matrix) := Boolean => (X1, X2, A) -> ( + -- X1, X2 are CalabiYauInToric's (of the same h11 = h11(X1) = h11(X2)). + -- A is an h11 x h11 matrix over ZZ, with determinant 1 or -1. + -- if the topological data of X1, X2 are equivalent via A, then true is returned. + if hh^(1,2) X1 =!= hh^(1,2) X2 then return false; + if hh^(1,1) X1 =!= hh^(1,1) X2 then return false; + LF1 := (c2Form X1, cubicForm X1); + LF2 := (c2Form X2, cubicForm X2); + isEquivalent(LF1, LF2, A) + ) + +------------------------------------ +-- Separating a set of topologies -- +------------------------------------ +-- This takes a set of labels (and matrices defining equivalences) +-- "Sets" field: is a list of buckets. Two topologies in different buckets are definitely not the same. +-- Each bucket is a list of lists. +-- Two topologies in one element of this list are definitely the same. +-- Two topologies in different elements of this list are possibly the same possibly different. +-- two types of routines: +-- separate: this will only create new number of buckets (by separating buckets which are there. +-- combine: this will only coalesce sets in any given bucket. +-- (adding in matrices that show this). +-- note: TODO: if two sets are combined, we need to multiply all the matrices of one set by the new change of basis matrix. +TopologySet = new Type of MutableHashTable + +-- TODO XXX: T#"Sets"#i is a list of {lab, {lab2, map2}, {lab3,map3}, ...} +-- mapj is a matrix over the integers of size h11 x h11. +topologySet = method() +topologySet(List, HashTable) := TopologySet => (labels, Xs) -> ( + new TopologySet from { + "Sets" => {for k in labels list {k}}, + "CYHash" => Xs + } + ) + +info TopologySet := T -> ( + << "Total number of objects considered: " << T#"Sets"/(x -> (x/length//sum))//sum << endl; + << "Number of known different topologies: " << #T#"Sets" << endl; + << "Maximum possible # of different topologies: " << T#"Sets"/(x -> length x)//sum << endl; + << "Largest number in one set: " << T#"Sets"/(x -> (x/length//max))//max << endl; + t := T#"Sets"/length//tally; + for i in keys t do ( + if i == 1 then + << " Number of buckets with 1 class " << t#1 << endl + else + << " Number of buckets with "|i|" classes " << t#i << endl; + ); + -- bigones := for i in keys t list if i >= 10 then t#i else continue; + -- if #bigones > 0 then + -- << " Number of buckets with >= 10 classes " << sum bigones << endl; + ) + +representatives = method(Options => {IgnoreSingles => true}) +representatives TopologySet := opts -> T -> ( + -- NOTE: ignores those with only one class in a bucket! + sort for t1 in T#"Sets" list if opts.IgnoreSingles and #t1 == 1 then continue else t1/first//sort + ) +equivalences = method(Options => {IgnoreSingles => true}) +equivalences TopologySet := opts -> T -> ( + hashTable flatten for t1 in T#"Sets" list for t2 in t1 list ( + if #t2 == 1 and opts.IgnoreSingles then continue; + (first t2) => drop(t2, 1) + ) + ) + +separateIfDifferent = method() +separateIfDifferent(TopologySet, Function) := (T, fun) -> ( + -- fun takes a CalabiYauInToric, and returns some value. + -- if fun X1 =!= fun X2, then X1 and X2 are distinct topologies. + -- if the same, then nothing is asserted. + Xs := T#"CYHash"; + -- the 'flatten' on the next line makes one list of all definitely distinct topologies + newsets := flatten for L in T#"Sets" list ( + -- L is a list of labels, all are equivalent (so maybe only one, but always >= 1). + if #L === 1 then {L} + else ( + -- TODO: is this correct? XXX Just changed, not fixed.... + P := partition(lab -> fun Xs#(first lab), L); + values P + ) + ); + new TopologySet from { + "Sets" => newsets, + "CYHash" => T#"CYHash" + } + ) + +combineIfSame = method() +combineIfSame(TopologySet, Function) := (T, fun) -> ( + -- fun takes a CalabiYauInToric, and returns some value. + -- if fun X1 === fun X2, then X1 and X2 are the same topology + -- if different, then nothing is asserted. + Xs := T#"CYHash"; + -- the 'flatten' on the next line makes one list of all definitely distinct topologies + newsets := for L in T#"Sets" list ( + -- L is a list of labels, all are equivalent (so maybe only one, but always >= 1). + P := partition(lab -> fun Xs#(first lab), L); + (values P)/flatten + -- TODO XXX: the previous line should add in identity maps + ); + new TopologySet from { + "Sets" => newsets, + "CYHash" => T#"CYHash" + } + ) + +-- REMOVE THIS ONE: use combineByGV... +separateByGV = method(Options => {DegreeLimit => 15}) +-- separateByGV TopologySet := opts -> T -> ( +-- Xs := T#"CYHash"; +-- newSets := for Ls in T#"Sets" list ( +-- L1s := Ls/first; -- these are the ones we want to split up +-- Indices := hashTable for i from 0 to #Ls-1 list first Ls#i => i; +-- << "----------------" << endl; +-- print L1s; +-- print Indices; +-- << "----------------" << endl; +-- P := partitionByTopology(L1s, Xs, opts.DegreeLimit); +-- newlist := for k in keys P list {k}|(P#k); +-- newlist +-- -- what is the best way to get the ones that are the same into the same set? +-- ); +-- new TopologySet from { +-- "CYHash" => Xs, +-- "Sets" => newSets +-- } +-- ) + +combineBucketByGV = method(Options => {DegreeLimit => 15}) +combineBucketByGV(List, HashTable) := opts -> (Ls, Xs) -> ( + if #Ls === 1 then Ls + else ( + L1s := Ls/first; -- these are the ones we want to split up + L1rest := hashTable for L in Ls list ( + {first L, drop(L, 1)} + ); + -- print L1s; + -- << "----------------" << endl; + P := partitionByTopology(L1s, Xs, opts.DegreeLimit); + newlist := for k in keys P list ( + {k} | P#k | L1rest#k | flatten for x in P#k list L1rest#(first x) + ); +-- if #(keys P) > 1 then error "debug me"; + newlist + )) + +combineByGV = method(Options => {DegreeLimit => 15}) +combineByGV TopologySet := opts -> T -> ( + Xs := T#"CYHash"; + newSets := for Ls in T#"Sets" list ( + combineBucketByGV(Ls, Xs, DegreeLimit => opts.DegreeLimit) + ); + new TopologySet from { + "CYHash" => Xs, + "Sets" => newSets + } + ) + + +findMapsFROMBELOW = (top1, top2, A, phi, RQ) -> ( + TR := target phi; + n := numgens TR; + T := coefficientRing TR; + toTR := f -> sub(f, TR); + toQQ := f -> sub(f, RQ); + evalphi := (F,G) -> trim sub(ideal last coefficients((phi toTR F) - toTR G), T); + (L1, F1, h11, h12) := toSequence top1; + (L2, F2, l11, l12) := toSequence top2; + RZ := ring L1; + if RZ =!= ring F1 or RZ =!= ring L2 or RZ =!= ring F2 then error "expected polynomials over the same ring"; + if h11 != l11 or h12 != l12 then return null; + I := (evalphi(L1, L2) + evalphi(F1, F2)); + if I == 1 then return null; + -- first see if there is a unique solution. + -- if codim I === n*n and degree I === 1 then ( + -- A0 := A % I; + -- if support A0 === {} then ( + -- A0 = lift(A0, QQ); + -- phi0 := map(RQ, RQ, transpose A0); + -- if phi0 toQQ L1 != toQQ L2 or phi0 toQQ F1 != toQQ F2 then error "map is not correct!"; + -- return (A0, phi0) + -- ); + -- ); + -- now let's look through all of the components for a smooth point. + compsI := decompose I; + As := for c in compsI list A % c; + As = for a in As list try lift(a, ZZ) else continue; -- grab the ones that lift. + As = select(As, a -> (d := det a; d == 1 or d == -1)); + if #As > 0 then ( + A0 := As#0; + phi0 := map(RZ, RZ, transpose A0); + if phi0 L1 != L2 or phi0 F1 != F2 then error "map is not correct!"; + (A0, phi0) + ) + else ( + if any(compsI, c -> codim c < n*n or degree c =!= 1) then ( + << "warning: there might be a map in this case!" << endl; + << netList compsI << endl; + << "----------------------------------" << endl; + compsI + ) + else null + ) + ) + +separateAndCombineViaAnsatz = method() +separateAndCombineViaAnsatz(TopologySet, HashTable, Ring) := TopologySet => (tops, Ts, RQ) -> ( + ) +separateAndCombineViaAnsatz(List, HashTable, Ring) := List => (Ls, Ts, RQ) -> ( + -- Ls: is a list of labels. + -- Ts: is a hash table containing for each lab in labels, the (c2, cubic, h11, h12) of Xs#lab. + -- restL#lab is a list of either pairs: {lab, matrix}, or of simply: labels. + -- RQ is QQ[h11 variables]. + -- Result: list of distinct topologies found, and in each list: each element is a list of equivalent topologies. + (A, phi) := genericLinearMap RQ; + if #Ls === 1 then return Ls; + distinctTops := new MutableHashTable; -- label => list of {label, matrix}, those with the same topology + for i in Ls do ( + Ti := Ts#i; + prev := keys distinctTops; + isFound := false; + for j in prev do ( + Tj := Ts#j; + ans := findMaps(Tj, Ti, A, phi, RQ); -- either a matrix of integers or null, or "unknown" + if ans === null then ( + -- Ti is distinct from Tj + ) + else if class first ans === Matrix then ( + -- we have a match! + (A0, phi0) := ans; + -- The following seems to be a redundant check! + if all(flatten entries A0, a -> liftable(a, ZZ)) + then ( + isFound = true; + distinctTops#j = append(distinctTops#j, {i, lift(A0, ZZ)}); + break; + ) + ) + else ( + << (i,j) << " might be the same, might not *** " << endl; + ) + ); + if not isFound then ( + distinctTops#i = {}; + << "found new top: " << i << endl; + ); + ); + -- take distinctTops, so something with them.... + ) + +-- partitionH113sByTopology(List, HashTable, Ring) := HashTable => (Ls, Ts, RQ) -> ( +-- -- Ls is a list of labels to separate. +-- -- Ts is a hash table of label => {c2, cubicform, h11, h12} +-- -- This function first separates these by the invariants: invariantsAll. +-- -- The for each pair in each set, it attempts to find a map between them. +-- -- output: a hashtable, keys are labels, values are lists of {label, matrix} +-- (A, phi) := genericLinearMap RQ; +-- if #Ls === 1 then return hashTable {Ls#0 => {}}; +-- H := partition(lab -> invariantsAll toSequence Ts#lab, Ls); +-- distinctTops := new MutableHashTable; -- label => list of {label, matrix}, those with the same topology +-- for i in Ls do ( +-- Ti := Ts#i; +-- -- now we attempt to match this with each key of distinctTops +-- << "trying " << i << endl; +-- prev := keys distinctTops; +-- isFound := false; +-- for j in prev do ( +-- Tj := Ts#j; +-- ans := findMaps(Tj, Ti, A, phi, RQ); +-- --if j == (115,0) and i == (120,0) then error "debug me"; +-- if ans === null then ( +-- -- Ti is distinct from Tj +-- ) +-- else if class first ans === Matrix then ( +-- -- we have a match! +-- (A0, phi0) := ans; +-- if all(flatten entries A0, a -> liftable(a, ZZ)) +-- then ( +-- isFound = true; +-- distinctTops#j = append(distinctTops#j, {i, lift(A0, ZZ)}); +-- break; +-- ) +-- ) +-- else ( +-- << (i,j) << " might be the same, might not" << endl; +-- ) +-- ); +-- if not isFound then ( +-- distinctTops#i = {}; +-- << "found new top: " << i << endl; +-- ); +-- ); +-- new HashTable from distinctTops +-- ) + + +-- REMOVE? This is the start of a union-find algorithm. But we are not using it, I think. +-- combineSet = (Ls, binfun) -> ( +-- -- binfun(X1,X2) should return a matrix if these are the same topology, null if we don't know. +-- -- note: the number of newsets is identical. We might just be coalescing elements in one set. +-- -- NOTE: currently the matrix is lost, we need to be able to keep it! +-- upnode := new MutableList from 0..#Ls-1; +-- nodesize := new MutableList from (#Ls : 1); +-- find := x -> ( +-- root := x; +-- while upnode#root != root do root = upnode#root; +-- while upnode#x != root do ( +-- par := upnode#x; +-- upnode#x = root; +-- x = par; +-- ); +-- root +-- ); +-- union := (x,y) -> ( +-- x = find x; +-- y = find y; +-- if x === y then return; +-- if nodesize#x < nodesize#y then ( +-- (x,y) = (y,x); +-- ); +-- upnode#y = x; +-- nodesize#x = nodesize#x + nodesize#y; +-- nodesize#y = 0; +-- ); +-- for i from 0 to #Ls - 2 do +-- for j from i+1 to #Ls - 1 do ( +-- aij := binfun(Ls#i,Ls#j); +-- if aij =!= null then union(i,j); +-- ); +-- P := partition(x -> find x, toList(0..#Ls-1)); +-- for p in values P list (for p1 in p list Ls#p1) +-- ) + +-- doit = (T) -> ( +-- Xs := T#"CYHash"; +-- combineSet((T#"Sets"#0), (lab1,lab2) -> ( +-- X1 := Xs#(first lab1); +-- X2 := Xs#(first lab2); +-- c2Form X1 == c2Form X2 and cubicForm X1 == cubicForm X2 +-- )) +-- ) + + +/// + -- Analyze h11=3 examples +restart +debug needsPackage "StringTorics" + RZ = ZZ[a,b,c] + RQ = QQ (monoid RZ); + --(Qs, Xs) = readCYDatabase("../m2-examples/foo-cys-ntfe-h11-3.dbm", Ring => RZ); + (Qs, Xs) = readCYDatabase("./Databases/cys-ntfe-h11-3.dbm", Ring => RZ); + -- First, let's only consider those with torsion free class group. + torsions = for k in keys Qs list ( + istor := prune coker matrix rays Qs#k != ZZ^3; + if istor then k else continue + ) + + allXs = sort select(keys Xs, x -> not member(x#0, torsions)) + allXs = sort keys Xs + allT = topologySet(allXs, Xs); + + allT1 = combineIfSame(allT, X -> (c2Form X, cubicForm X)) + info allT1 + + elapsedTime allT = separateIfDifferent(allT, invariantsAll) -- 17 sec + info allT + + elapsedTime allT3 = separateByGV allT2 -- 44 sec + info allT3 + + onestocheck = for x in allT3#"Sets" list if #x == 1 then continue else ( + x/first + ) + + flatten for x in onestocheck list ( + flatten for y in subsets(x, 2) list ( + print y; + ans := getEquivalenceIdeal(y#0, y#1, Xs); + print ans; + ans + ) + ) + +/// + +/// +restart +debug needsPackage "StringTorics" + R = ZZ[a,b,c,d] + RQ = QQ (monoid R); + (Qs, Xs) = readCYDatabase("mike-ntfe-h11-4.dbm", Ring => R); + + allT = topologySet(sort keys Xs, Xs); + #allT#"Sets" == 1 + #allT#"Sets"#0 == 1994 + info allT + + allT1 = combineIfSame(allT, X -> (c2Form X, cubicForm X)) + -- only 14 are the same as any other, and if two are the same, they also have same hh^(1,2). + -- (checked this explicitly). + info allT1 -- note very few are the same! + netList allT1#"Sets" + for x in allT1#"Sets" list (x/length)//tally + + elapsedTime allT2 = separateIfDifferent(allT1, invariantsAll) -- 270 sec + elapsedTime allT3 = separateByGV allT2 -- 870 sec + info allT3 + + for x in allT3#"Sets" list if #x == 1 then continue else ( + x/first + ) + onestocheck = { + {(163, 2), (163, 3)}, + {(811, 0), (882, 3)}, + {(387, 1), (387, 3)}, + {(339, 1), (337, 1)}, + {(1001, 0), (982, 0)}, + {(436, 1), (433, 1)}, + {(364, 0), (344, 1)}, + {(1094, 2), (1090, 2)}, + {(246, 0), (249, 1)}, + {(1147, 0), (1146, 0)}, + {(436, 0), (433, 0)}, + {(831, 0), (806, 0)}, + {(1121, 0), (1122, 0)}, + {(1067, 0), (1076, 0)}, + {(930, 6), (927, 2)}, + {(981, 0), (997, 0)}, + {(364, 1), (377, 0)}, + {(455, 0), (451, 0)}, + {(403, 0), (408, 2)}, + {(1090, 0), (1094, 0)}, + {(714, 0), (707, 0), (695, 5), (709, 0)}, + {(991, 0), (998, 3)}, + {(1002, 1), (979, 0), (1005, 4)}, + {(716, 3), (705, 0)}, + {(851, 0), (814, 0), (810, 0)}, + {(1123, 0), (1124, 0)}, + {(478, 1), (473, 0)}, + {(1085, 0), (1082, 0), (1086, 0)}, + {(334, 1), (329, 1)}, + {(316, 0), (322, 0)}, + {(1004, 0), (994, 0)}, + {(265, 1), (250, 0), (254, 5), (228, 1)}, + {(647, 0), (645, 0)}, + {(529, 0), (510, 0)}, + {(935, 4), (915, 0)}, + {(628, 0), (653, 3)}, + {(943, 0), (958, 0)}, + {(329, 0), (334, 0)}, + {(319, 0), (321, 0), (302, 0)}, + {(875, 0), (854, 0)}, + {(1183, 2), (1182, 0)}, + {(449, 2), (419, 0)}, + {(383, 0), (356, 1)}, + {(250, 1), (213, 1)}, + {(938, 3), (933, 0)}, + {(1082, 5), (1077, 3)}, + {(668, 1), (649, 1), (626, 0)}, + {(80, 3), (72, 0), (80, 6)}, + {(616, 0), (606, 0)}, + {(540, 0), (545, 0)}, + {(331, 0), (337, 0), (339, 2)}, + {(397, 0), (350, 0)}, + {(900, 0), (901, 0)}, + {(930, 1), (927, 8)}, + {(559, 0), (577, 0)}, + {(938, 10), (933, 4)}, + {(931, 0), (932, 2)}, + {(884, 0), (820, 0)}, + {(650, 3), (656, 1), (630, 0)}, + {(976, 0), (989, 0)}, + {(552, 0), (551, 2)}, + {(924, 0), (937, 0)}} + + 176 == # flatten for x in onestocheck list flatten for y in subsets(x,2) list y + + flatten for x in onestocheck list ( + flatten for y in subsets(x, 2) list ( + print y; + ans := getEquivalenceIdeal(y#0, y#1, Xs); + print ans; + ans + ) + ) + select(oo, i -> numgens i > 1) + getEquivalenceIdeal((163, 2), (163, 3), Xs) + getEquivalenceIdeal((1123,0),(1124,0), Xs) + + lab1 = (163,2) + lab2 = (163,3) + X1 = Xs#lab1; + X2 = Xs#lab2; + LF1 = (c2Form X1, cubicForm X1); + LF2 = (c2Form X2, cubicForm X2); + RQ = QQ (monoid ring LF1_0); + (A,phi) = genericLinearMap RQ; + T = target phi; + B = ring A; + LF1' = LF1/(f -> sub(f, T)); + LF2' = LF2/(f -> sub(f, T)); + I0 = sub(ideal last coefficients(phi LF1'_0 - LF2'_0), B); + A0 = A % I0; + phi0 = map(T, T, A0); + I1 = sub(ideal last coefficients (phi0 LF1'_1 - LF2'_1), B) + gens gb(I0 + I1) + + select(allT3#"Sets", x -> #x > 1) + -- now we need to check that (hopefully) each set is not homeomorphic to any other set. + -- It seems that now an ansatz might work? + + TbyH12s = separateIfDifferent(allT, X -> hh^(1,2) X); + info TbyH12s + #TbyH12s#"Sets" + for x in TbyH12s#"Sets" list #x + + + smallset = select(sort keys Xs, lab -> hh^(1,2) Xs#lab == 148) -- + T = topologySet(sort smallset, Xs) + allTsame = combineIfSame(T, X -> (c2Form X, cubicForm X)) + info allTsame + elapsedTime T1 = separateIfDifferent(allTsame, X -> invariantsAll X) + info T1 + netList T1#"Sets" + T2 = separateByGV T1 + +/// + + getEquivalenceIdealHelper = (LF1, LF2, A, phi) -> ( + T := target phi; + B := ring A; + LF1' := LF1/(f -> sub(f, T)); + LF2' := LF2/(f -> sub(f, T)); + I0 := sub(ideal last coefficients(phi LF1'_0 - LF2'_0), B); + A0 := A % I0; + phi0 := map(T, T, transpose A0); + trim(I0 + sub(ideal last coefficients (phi0 LF1'_1 - LF2'_1), B)) + ) + + getEquivalenceIdeal = method() + getEquivalenceIdeal(Thing, Thing, HashTable) := Sequence => (lab1, lab2, Xs) -> ( + X1 := Xs#lab1; + X2 := Xs#lab2; + LF1 := (c2Form X1, cubicForm X1); + LF2 := (c2Form X2, cubicForm X2); + RQ := QQ (monoid ring LF1_0); + (A,phi) := genericLinearMap RQ; + (getEquivalenceIdealHelper(LF1, LF2, A, phi), A) + ) + +------------------------------------ + + +factors = method() +factors RingElement := (F) -> ( + facs := factor F; + facs//toList/toList/reverse + ) + +invariants = method() +invariants List := (f) -> ( + RQ := QQ[gens ring first f]; + facs := select((factors f_1 )/toList/last, g -> support g != {}); + l1 := sub(f_0, RQ); + f1 := sub(f_1, RQ); + d := dim saturate ideal jacobian f1; + nc := # decompose ideal(l1, f1); + singZ := flatten entries gens gb saturate(ideal(f_1) + ideal jacobian f_1); + badp := select(singZ, a -> support leadTerm a === {}); + badp = if badp === {} then 0 else first badp; + {badp, (trim content f_0)_0, (trim content f_1)_0, #facs, d, nc, f_2, f_3} + ) + + + +pointCount = method() +pointCount(RingElement, ZZ) := ZZ => (F, p) -> ( + -- F is a polynomial in 3 variables (FIXME: any number of variables) + -- p is a prime number + kk := ZZ/p; + R := kk (monoid ring F); + Fp := sub(F, R); + allpts := allPoints(p, numgens ring F); + allmaps := allpts/(pt -> map(kk, R, pt)); + ans1 := # for a in allpts list (phi := map(kk, R, a); if phi Fp == 0 then a else continue); + --ans2 := # for x in (0,0,0)..(p-1,p-1,p-1) list if sub(Fp, matrix{{x}}) == 0 then x else continue; + --if ans1 != ans2 then << "My previous code was incorrect" << endl; + ans1 + ) + +allPointMaps = method() +allPointMaps(ZZ, Ring) := (p, R) -> ( + N := numgens R; + K := ZZ/p; + pts := allPoints(p,N); + for a in pts list map(K, R, a) + ) + + + +-- allPointMaps(ZZ, ZZ, Ring) := (p, n, R) -> ( +-- N := numgens R; +-- K := GF(p,n); +-- pts := allPoints(p,N); +-- for a in pts list map(K, R, a) +-- ) + +-- pointCount = method() +-- pointCount(RingElement, RingElement, List) := ZZ => (L, F, pts) -> ( +-- -- pts is a list of list of ring maps +-- -- each list is generally all of the points in k^N, for k = ZZ/p, p = 2,3,5,7,11,13, maybe k = GF 4, ... + +-- -- F is a polynomial in 3 variables (FIXME: any number of variables) +-- -- p is a prime number +-- kk := ZZ/p; +-- R := kk (monoid ring F); +-- Fp := sub(F, R); +-- allpts := allPoints(p, numgens ring F); +-- allmaps := allpts/(pt -> map(kk, R, pt)); +-- ans1 := # for a in allpts list (phi := map(kk, R, a); if phi Fp == 0 then a else continue); +-- --ans2 := # for x in (0,0,0)..(p-1,p-1,p-1) list if sub(Fp, matrix{{x}}) == 0 then x else continue; +-- --if ans1 != ans2 then << "My previous code was incorrect" << endl; +-- ans1 +-- ) + +invariants CalabiYauInToric := List => X -> ( + L := c2Form X; + F := cubicForm X; + h11 := hh^(1,1) X; + h12 := hh^(1,2) X; + RZ := ring L; + if ring F =!= RZ then + error "expected same rings for c2 and cubic form"; + if coefficientRing RZ =!= ZZ then + error "expected c2 and cubic form ring to be a polynomial ring over ZZ"; + RQ := QQ[gens RZ]; + facs := select((factors F)/toList/last, g -> support g != {}); + LQ := sub(L, RQ); + FQ := sub(F, RQ); + d := dim saturate ideal jacobian FQ; + nc := # decompose ideal(LQ, FQ); + singZ := flatten entries gens gb saturate(ideal(F) + ideal jacobian F); + badp := select(singZ, a -> support leadTerm a === {}); + badp = if badp === {} then 0 else sub(first badp, ZZ); + ptcounts := for p in {2, 3, 5, 7, 11} list pointCount(F, p); + {h11, h12, ptcounts, badp, (trim content L)_0, (trim content F)_0, #facs, d, nc} + ) + +invariants0 = method() +invariants0 CalabiYauInToric := List => X -> ( + L := c2Form X; + F := cubicForm X; + h11 := hh^(1,1) X; + h12 := hh^(1,2) X; + contentL := (trim content L)_0; + contentF := (trim content F)_0; + {h11, h12} | {contentL, contentF} + ) + +invariants1 = method() +invariants1 CalabiYauInToric := List => X -> ( + L := c2Form X; + F := cubicForm X; + h11 := hh^(1,1) X; + h12 := hh^(1,2) X; + contentL := (trim content L)_0; + contentF := (trim content F)_0; + ptcounts := for p in {2, 3, 5, 7, 11} list pointCount(F, p); + {h11, h12} | ptcounts | {contentL, contentF} + ) + +invariants2 = method() +invariants2 CalabiYauInToric := List => X -> ( + L := c2Form X; + F := cubicForm X; + h11 := hh^(1,1) X; + h12 := hh^(1,2) X; + RZ := ring L; + if ring F =!= RZ then + error "expected same rings for c2 and cubic form"; + if coefficientRing RZ =!= ZZ then + error "expected c2 and cubic form ring to be a polynomial ring over ZZ"; + RQ := QQ[gens RZ]; + facs := select((factors F)/toList/last, g -> support g != {}); + LQ := sub(L, RQ); + FQ := sub(F, RQ); + d := dim saturate ideal jacobian FQ; + nc := # decompose ideal(LQ, FQ); + singZ := flatten entries gens gb saturate(ideal(F) + ideal jacobian F); + badp := select(singZ, a -> support leadTerm a === {}); + badp = if badp === {} then 0 else sub(first badp, ZZ); + {h11, h12, badp, (trim content L)_0, (trim content F)_0, #facs, d, nc} + ) + +invariants3 = method() +invariants3 CalabiYauInToric := List => X -> ( + -- these are some invariants only involving the cubic form, not the c2 form... + -- (but currently also involving h11 and h12. + F := cubicForm X; + h11 := hh^(1,1) X; + h12 := hh^(1,2) X; + RZ := ring F; + if coefficientRing RZ =!= ZZ then + error "expected c2 and cubic form ring to be a polynomial ring over ZZ"; + RQ := QQ[gens RZ]; + facs := select((factors F)/toList/last, g -> support g != {}); + FQ := sub(F, RQ); + d := dim saturate ideal jacobian FQ; + singFZ := ideal gens gb saturate(ideal(F) + ideal jacobian F); + sing := (F) -> ideal F + ideal jacobian F; + linearcontent := (I) -> ( + if I == 0 then return 0; + lins := select(I_*, f -> f != 0 and first degree f <= 1); + if #lins == 0 then return 0; + gcd for ell in lins list (trim content ell)_0 + ); + lincontent := linearcontent saturate sing F; + singZ := flatten entries gens gb saturate(ideal(F) + ideal jacobian F); + badp := select(singZ, a -> support leadTerm a === {}); + badp = if badp === {} then 0 else sub(first badp, ZZ); + {h11, h12, badp, (trim content F)_0, #facs, d, lincontent} + ) + +invariants4 = method() +invariants4 CalabiYauInToric := List => X -> ( + L := c2Form X; + F := cubicForm X; + h11 := hh^(1,1) X; + h12 := hh^(1,2) X; + RZ := ring L; + if ring F =!= RZ then + error "expected same rings for c2 and cubic form"; + if coefficientRing RZ =!= ZZ then + error "expected c2 and cubic form ring to be a polynomial ring over ZZ"; + RQ := QQ[gens RZ]; + facs := select((factors F)/toList/last, g -> support g != {}); + LQ := sub(L, RQ); + FQ := sub(F, RQ); + d := dim saturate ideal jacobian FQ; + sing := (F) -> ideal F + ideal jacobian F; + linearcontent := (I) -> ( + if I == 0 then return 0; + lins := select(I_*, f -> f != 0 and first degree f <= 1); + if #lins == 0 then return 0; + gcd for ell in lins list (trim content ell)_0 + ); + lincontent := linearcontent saturate sing F; + nc := # decompose ideal(LQ, FQ); + singZ := flatten entries gens gb saturate(ideal(F) + ideal jacobian F); + badp := select(singZ, a -> support leadTerm a === {}); + badp = if badp === {} then 0 else sub(first badp, ZZ); + {h11, h12, badp, (trim content L)_0, (trim content F)_0, #facs, d, nc, lincontent} + ) + +-- This one contains the best info we have to date (which isn't quite good enough). +polynomialContent = method() + +-- Assumption: F is a polynomial over ZZ (not over a field). +-- Outout: the integer content of F. +polynomialContent RingElement := F -> (trim content F)_0 + +integerPart = method() +integerPart Ideal := (I) -> ( + -- expected: I is an ideal in a polynomial ring over ZZ. + gs := select(flatten entries gens gb I, f -> support f === {}); + if #gs == 0 then 0 + else if #gs == 1 then lift(gs_0, ZZ) + else error "internal error: somehow have two generators in ZZ in this GB" + ) + +--factorShape = method() +-- This one is WRONG: lift(xxx, ZZ) could be positive or negative. Those cannot be different. +-- factorShape RingElement := F -> ( +-- facs := factors F; +-- sort for x in facs list if support x#1 == {} then +-- {0, lift(x#1, ZZ)} +-- else +-- {first degree x#1, x#0} +-- ) + +factorShape = method() +factorShape RingElement := F -> ( + facs := factors F; + sort for x in facs list if support x#1 == {} then + {0, abs lift(x#1, ZZ)} + else + {first degree x#1, x#0} + ) + +-- factorShape RingElement := F -> ( +-- facs := factors F; +-- con := trim content F; +-- con = con_0; +-- posfactors := sort for x in facs list if support x#1 == {} then +-- continue +-- else +-- {first degree x#1, x#0}; +-- prepend({0, con}, posfactors) +-- ) + + +invariantsAllX = method() +invariantsAllX(RingElement, RingElement, ZZ, ZZ) := (L, F, h11, h12) -> ( + RZ := ring L; + if ring F =!= RZ then + error "expected same rings for c2 and cubic form"; + if coefficientRing RZ =!= ZZ then + error "expected c2 and cubic form ring to be a polynomial ring over ZZ"; + RQ := QQ[gens RZ]; + toQQ := F -> sub(F, vars RQ); + sing := (cod, I) -> trim(I + minors(cod, jacobian I)); + linearcontent := (I) -> ( + if I == 0 then return 0; + lins := select(I_*, f -> f != 0 and first degree f <= 1); + if #lins == 0 then return 0; + gcd for ell in lins list (trim content ell)_0 + ); + FQ := toQQ F; + LQ := toQQ L; + inv0 := polynomialContent L; + inv1 := polynomialContent F; + -- dimension and degree of each component of the singular loci over QQ. +-- inv2 := sort for c in decompose sing_1 ideal FQ list {codim c, degree c}; +-- inv3 := sort for c in decompose sing_2 ideal(LQ, FQ) list {codim c, degree c}; +-- inv4 := betti res saturate sing_1 ideal FQ; + -- inverse system of FQ +-- inv5 := betti res inverseSystem FQ; -- not clear this one is worthwhile + -- integer parts of singular loci. + conductF := integerPart saturate sing_1 ideal F; + conductLF := integerPart saturate sing_2 ideal(L,F); + inv6 := conductF; + inv7 := conductLF; + inv8 := factorShape det hessian F; + inv9 := linearcontent saturate sing_1 F; + hashTable {"h11" => h11, + "h12" => h12, + "c(L)" => inv0, + "c(F)" => inv1, +-- "comps sing FQ" => inv2, +-- "comps sing LFQ" => inv3, +-- "bettti sing LFQ" => inv4, +-- "betti inv F" => inv5, + "conduct(F)" => inv6, + "conduct(L,F)}" => inv7, + "hessian shape" => inv8, + "lincontent sing F" => inv9 + } + ) + +invariantsAll = method() +invariantsAll(RingElement, RingElement, ZZ, ZZ) := (L, F, h11, h12) -> ( + RZ := ring L; + if ring F =!= RZ then + error "expected same rings for c2 and cubic form"; + if coefficientRing RZ =!= ZZ then + error "expected c2 and cubic form ring to be a polynomial ring over ZZ"; + RQ := QQ[gens RZ]; + toQQ := F -> sub(F, vars RQ); + sing := (cod, I) -> trim(I + minors(cod, jacobian I)); + linearcontent := (I) -> ( + if I == 0 then return 0; + lins := select(I_*, f -> f != 0 and first degree f <= 1); + if #lins == 0 then return 0; + gcd for ell in lins list (trim content ell)_0 + ); + FQ := toQQ F; + LQ := toQQ L; + inv0 := polynomialContent L; + inv1 := polynomialContent F; + -- dimension and degree of each component of the singular loci over QQ. + inv2 := sort for c in decompose sing_1 ideal FQ list {codim c, degree c}; + inv3 := sort for c in decompose sing_2 ideal(LQ, FQ) list {codim c, degree c}; + inv4 := betti res saturate sing_1 ideal FQ; + -- inverse system of FQ +-- inv5 := betti res inverseSystem FQ; -- not clear this one is worthwhile + -- integer parts of singular loci. + conductF := integerPart saturate sing_1 ideal F; + conductLF := integerPart saturate sing_2 ideal(L,F); + inv6 := conductF; + inv7 := conductLF; + inv8 := factorShape det hessian F; + inv9 := linearcontent saturate sing_1 F; + hashTable {"h11" => h11, + "h12" => h12, + "c(L)" => inv0, + "c(F)" => inv1, + "comps sing FQ" => inv2, + "comps sing LFQ" => inv3, + "bettti sing LFQ" => inv4, +-- "betti inv F" => inv5, + "conduct(F)" => inv6, + "conduct(L,F)}" => inv7, + "hessian shape" => inv8, + "lincontent sing F" => inv9 + } + ) + +invariantsAll CalabiYauInToric := X -> invariantsAll(c2Form X, cubicForm X, hh^(1,1) X, hh^(1,2) X) + +mapIsIsomorphism = method() +mapIsIsomorphism(Matrix, CalabiYauInToric, CalabiYauInToric) := +mapIsIsomorphism(Matrix, CYToolsCY3, CYToolsCY3) := Boolean => (M, X1, X2) -> ( + -- M is a matrix over the base field, a possible map giving + -- an isomorphism of topologies. + -- T1, T2 are two topologies. + F1 := cubicForm X1; + F2 := cubicForm X2; + RZ := ring F1; + if RZ =!= ring F2 then error "expected the same picard ring"; + phi := map(RZ, RZ, M); + (phi c2Form X1 == c2Form X2) and (phi F1 == F2) + ) + +partitionByTopology = method() +partitionByTopology List := LGVs -> ( + -- LGVs is a list of X => gvPartition. + -- output: a hashtable, keys are labels, values are lists of {label, matrix} + labels := for x in LGVs list label first x; + hashXs := hashTable for y in LGVs list (label first y) => y; + distinctTops := new MutableHashTable; -- label => list of labels. + for i in labels do ( + Xi := first hashXs#i; + GVi := last hashXs#i; + << "trying " << i << endl; + prev := keys distinctTops; + isFound := false; + for j in prev do ( + Xj := first hashXs#j; + GVj := last hashXs#j; + -- compare CY's i, j + Ms := findLinearMaps(GVj, GVi); + if Ms === {} then continue; + Ms = Ms/(m -> lift(m, ZZ)); + Ms = select(Ms, m -> (d := det m; d === 1 or d === -1)); + isIsos := Ms/(m -> mapIsIsomorphism(m, Xj, Xi)); + if any(isIsos, x -> true) then ( + mi := position(isIsos, x -> true); + << "found isomorphism" << endl; + distinctTops#j = append(distinctTops#j, {i, Ms#mi}); + isFound = true; + break; + )); + if not isFound then ( + distinctTops#i = {}; + << "found new top: " << topologicalData Xi << endl; + ); + ); + new HashTable from distinctTops + ) + +partitionByTopology(List, HashTable, ZZ) := (Ls, Xs, degreelimit) -> ( + -- output: a hashtable, keys are labels, values are lists of {label, matrix} + labels := Ls; + if #Ls === 1 then return hashTable {Ls#0 => {}}; + hashXs := Xs; + GVs := hashTable for lab in labels list lab => partitionGVConeByGV(hashXs#lab, DegreeLimit => degreelimit); + distinctTops := new MutableHashTable; -- invariants => list of labels. + for i in labels do ( + Xi := hashXs#i; + GVi := GVs#i; + << "trying " << i << endl; + prev := keys distinctTops; + isFound := false; + if GVi === null then prev = {}; -- we cannot use GV with non-favorables currently. + for j in prev do ( + Xj := hashXs#j; + GVj := GVs#j; + if GVj === null then continue; -- we cannot use GV with non-favorables currently. + -- compare CY's i, j + Ms := findLinearMaps(GVj, GVi); + if Ms === {} then continue; + --Ms = Ms/(m -> lift(m, ZZ)); + Ms = for m in Ms list try lift(m, ZZ) else continue; + Ms = select(Ms, m -> (d := det m; d === 1 or d === -1)); + isIsos := Ms/(m -> mapIsIsomorphism(m, Xj, Xi)); + if any(isIsos, x -> x == true) then ( + mi := position(isIsos, x -> x == true); + << "found isomorphism from " << j << " to " << i << ": " << Ms#mi << endl; + distinctTops#j = append(distinctTops#j, {i, Ms#mi}); + isFound = true; + break; + )); + if not isFound then ( + distinctTops#i = {}; + << "found new top: " << i << endl; + ); + ); + new HashTable from distinctTops + ) + +linearEquationConstraints = method() +linearEquationConstraints(Matrix, RingMap, List, List) := Sequence => (A, phi, Ls, pts) -> ( + -- each entry of Ls is a list/sequence of length 2: {F, G} + -- where F, G are polynomials in a ring R, (A, phi) are obtained from + -- genericLinearMap. We return the ideal of constraints in T + -- for which phi(F) = G, for all pairs {F,G} in Ls. + -- We also return A0, phi0 corresponding to these constraints. + T := ring A; + A0 := A; + TR := target phi; + I := sum for L in Ls list ideal sub(last coefficients(phi L_0 - L_1), T); + if I != 0 then A0 = sub(A, T) % (trim I); + J := sum for pq in pts list minors(2, + (A0 * (transpose matrix {pq#1})) | transpose matrix {pq#0}); + J1 := if J != 0 then I+J else I; + if J != 0 then A0 = A0 % (trim J1); + (A0, map(TR, TR, transpose A0), trim ideal gens gb J1) + ) + +linearEquationConstraintsIdeal = method() +linearEquationConstraintsIdeal(Matrix, RingMap, List, List) := Sequence => (A, phi, Ls, pts) -> ( + -- each entry of Ls is a list/sequence of length 2: {F, G} + -- where F, G are polynomials in a ring R, (A, phi) are obtained from + -- genericLinearMap. We return the ideal of constraints in T + -- for which phi(F) = G, for all pairs {F,G} in Ls. + -- We also return A0, phi0 corresponding to these constraints. + T := ring A; + A0 := A; + TR := target phi; + I := sum for L in Ls list ideal sub(last coefficients(phi L_0 - L_1), T); + I) + +TEST /// + debug StringTorics + R = QQ[a..d] + (A, phi) = genericLinearMap R + TR = target phi + assert(source phi === TR) + assert(ring A === coefficientRing TR) + for i from 0 to 3 do + assert(phi TR_i == (A^{i} * (transpose vars TR))_(0,0)) + + linearEquationConstraints(A, phi, {}, { + {{1,0,0,0}, {1,1,0,0}}, + {{0,1,0,0}, {1,1,3,7}}, + {{0,0,1,0}, {5,6,-2,8}}, + {{0,0,0,1}, {0,1,0,0}}} + ) + + F1 = -2*a^3-6*a^2*b+6*b^2*c-12*a^2*d+12*a*b*d+12*b^2*d+36*b*c*d+30*a*d^2+60*b*d^2+54*c*d^2+76*d^3 + F7 = -2*a^3+6*a^2*b-6*a*b^2+2*b^3-6*a*c^2-4*c^3+6*a^2*d-6*a*d^2+2*d^3 + + (A0, phi0, I1) = linearEquationConstraints(A, phi, { + {b+2*d, a-d}, + {b+3*d, a+c}, + {a+b+2*d, a-b}, + {F1, F7} + }, { + } + ) + phi0 F1 == F7 + + -- this one isn't correct yet. + (A0, phi0, I1) = linearEquationConstraints(A, phi, { + {b+2*d, a-d}, + {b+3*d, a+c}, + {a+b+2*d, a-b} + }, { + {{0,0,1,0}, {1,1,-1,1}} + } + ) +-- + + A0 % sub(trim ideal last coefficients(phi0 F1 - F7), coefficientRing TR) +/// + +findMaps = (top1, top2, A, phi, RQ) -> ( + TR := target phi; + n := numgens TR; + T := coefficientRing TR; + toTR := f -> sub(f, TR); + toQQ := f -> sub(f, RQ); + evalphi := (F,G) -> trim sub(ideal last coefficients((phi toTR F) - toTR G), T); + (L1, F1, h11, h12) := toSequence top1; + (L2, F2, l11, l12) := toSequence top2; + RZ := ring L1; + if RZ =!= ring F1 or RZ =!= ring L2 or RZ =!= ring F2 then error "expected polynomials over the same ring"; + if h11 != l11 or h12 != l12 then return null; + I := (evalphi(L1, L2) + evalphi(F1, F2)); + if I == 1 then return null; + -- first see if there is a unique solution. + -- if codim I === n*n and degree I === 1 then ( + -- A0 := A % I; + -- if support A0 === {} then ( + -- A0 = lift(A0, QQ); + -- phi0 := map(RQ, RQ, transpose A0); + -- if phi0 toQQ L1 != toQQ L2 or phi0 toQQ F1 != toQQ F2 then error "map is not correct!"; + -- return (A0, phi0) + -- ); + -- ); + -- now let's look through all of the components for a smooth point. + compsI := decompose I; + As := for c in compsI list A % c; + As = for a in As list try lift(a, ZZ) else continue; -- grab the ones that lift. + As = select(As, a -> (d := det a; d == 1 or d == -1)); + if #As > 0 then ( + A0 := As#0; + phi0 := map(RZ, RZ, transpose A0); + if phi0 L1 != L2 or phi0 F1 != F2 then error "map is not correct!"; + (A0, phi0) + ) + else ( + if any(compsI, c -> codim c < n*n or degree c =!= 1) then ( + << "warning: there might be a map in this case!" << endl; + << netList compsI << endl; + << "----------------------------------" << endl; + compsI + ) + else null + ) + ) + + +findIsomorphism = method() +findIsomorphism(CalabiYauInToric, CalabiYauInToric) := (X1, X2) -> ( + (L1, F1, h11, h12) := (c2Form X1, cubicForm X1, hh^(1,1) X1, hh^(1,2) X1); + (L2, F2, l11, l12) := (c2Form X2, cubicForm X2, hh^(1,1) X2, hh^(1,2) X2); + if h11 != l11 or h12 != l12 then return null; + findIsomorphism((L1,F1), (L2,F2)) + ) + +findIsomorphism(Sequence, Sequence) := (LF1, LF2) -> ( + (L1, F1) := LF1; + (L2, F2) := LF2; + RZ := ring L1; + if RZ =!= ring F1 or RZ =!= ring L2 or RZ =!= ring F2 then error "expected polynomials over the same ring"; + RQ := QQ (monoid RZ); + (A, phi) := genericLinearMap RQ; + TR := target phi; + n := numgens TR; + T := coefficientRing TR; + toTR := f -> sub(f, TR); + toQQ := f -> sub(f, RQ); + -- Two ways we can use mappinginfo: + -- the first is simple: we take phi(F) = G. + -- the second is when we want one ideal to map to another: + -- each generator of the first ideal must map to an element of the second ideal. + evalPhi := (F,G) -> sub(ideal last coefficients((phi toTR F) - toTR G), T); + evalPhiIdeal := (I1,I2) -> sub(ideal last coefficients((phi toTR I1) % toTR I2), T); + I := (evalPhi(L1, L2) + evalPhi(F1, F2)); + if I == 1 then return null; -- this isn't so good: if we have trouble finding this, + -- we must deal with that. + -- first see if there is a unique solution. + -- if codim I === n*n and degree I === 1 then ( + -- A0 := A % I; + -- if support A0 === {} then ( + -- A0 = lift(A0, QQ); + -- phi0 := map(RQ, RQ, transpose A0); + -- if phi0 toQQ L1 != toQQ L2 or phi0 toQQ F1 != toQQ F2 then error "map is not correct!"; + -- return (A0, phi0) + -- ); + -- ); + -- now let's look through all of the components for a smooth point. + compsI := decompose I; + As := for c in compsI list A % c; + As = for a in As list try lift(a, ZZ) else continue; -- grab the ones that lift. + As = select(As, a -> (d := det a; d == 1 or d == -1)); + if #As > 0 then ( + A0 := As#0; + phi0 := map(RZ, RZ, transpose A0); + if phi0 L1 != L2 or phi0 F1 != F2 then error "internal logic error: map is not correct!"; + (A0, phi0) + ) + else ( + if any(compsI, c -> codim c < n*n or degree c =!= 1) then ( + << "warning: there might be a map in this case!" << endl; + << netList compsI << endl; + << "----------------------------------" << endl; + compsI + ) + else null + ) + ) + +determineIsomorphism = method() +determineIsomorphism(Sequence, Matrix, RingMap, Ring) := (Ts, A, phi, RQ) -> ( + -- Ts is a Sequence (Ti, Tj), where each Ti, Tj is a List: + -- {h11, h12, c2 form, cubic form} + -- The latter two are in RZ = ZZ[n vars], and + -- RQ = QQ[same n vars] + -- A is n x n generic matrix over a coeff ring `coefficientRing T`, over QQ. + -- T = (this coeff ring)[same n vars]. + -- phi : T --> T, given by x |--> Ax, or perhaps (transpose A)*x. TODO: GET THIS RIGHT! + -- Returns either an n x n invertible matrix A0 over ZZ, or null. + -- s.t. if phi0 : x |-> A0*x, then phi0 maps the c2 form L1 to L2, cubic form F1 to F2. + -- If no such map exists, null is returned. If there may be a map, but we can't + -- conclusively find one, then an ideal in the variables of A is returned. + + ) + +partitionH113sByTopology = method() +partitionH113sByTopology(List, HashTable, Ring) := HashTable => (Ls, Ts, RQ) -> ( + -- Ls is a list of labels to separate. + -- Ts is a hash table of label => {c2, cubicform, h11, h12} + -- This function first separates these by the invariants: invariantsAll. + -- The for each pair in each set, it attempts to find a map between them. + -- output: a hashtable, keys are labels, values are lists of {label, matrix} + (A, phi) := genericLinearMap RQ; + if #Ls === 1 then return hashTable {Ls#0 => {}}; + H := partition(lab -> invariantsAll toSequence Ts#lab, Ls); + distinctTops := new MutableHashTable; -- label => list of {label, matrix}, those with the same topology + for i in Ls do ( + Ti := Ts#i; + -- now we attempt to match this with each key of distinctTops + << "trying " << i << endl; + prev := keys distinctTops; + isFound := false; + for j in prev do ( + Tj := Ts#j; + ans := findMaps(Tj, Ti, A, phi, RQ); + --if j == (115,0) and i == (120,0) then error "debug me"; + if ans === null then ( + -- Ti is distinct from Tj + ) + else if class first ans === Matrix then ( + -- we have a match! + (A0, phi0) := ans; + if all(flatten entries A0, a -> liftable(a, ZZ)) + then ( + isFound = true; + distinctTops#j = append(distinctTops#j, {i, lift(A0, ZZ)}); + break; + ) + ) + else ( + << (i,j) << " might be the same, might not" << endl; + ) + ); + if not isFound then ( + distinctTops#i = {}; + << "found new top: " << i << endl; + ); + ); + new HashTable from distinctTops + ) + + +------------------------------------------------------------------------- +-- TODO: remove the following code (any reason to keep it?) +topologyOfCY3 = method(Options => { + Variable => "x", + Ring => null + }) + +topologyOfCY3(NormalToricVariety, List) := opts -> (V, basisIndices) -> ( + -- input: + -- V: a simplicial resolution of a Fano toric 4-fold + -- X is a (general) anti-canonical section of V. + -- basisIndices: list of integer indicesas to which V_i will be in the + -- basis of Pic X that you choose. + -- output: a hash table containing: + -- a. triple intersection numbers (a hash table, H#{a,b,c}, with 0 <= a <= b <= c < h11(X)) + -- b. the h11 numbers: c2(X) . D_i, 0 <= i < h11 + -- c. the integers h11, h12 + -- d. the cubic form C(x,y,z) in a polynomial ring ZZ[x_0, ..., x_(h11-1)] + -- e. a linear form L(x,y,z) in the same ring, representing c2(X).D_i + -- + P := convexHull transpose matrix rays V; + h11 := h21OfCY P; -- we want h11 of `polar P`. + h21 := h11OfCY P; + if #basisIndices != h11 then error("expected "|h11|" indices"); + H := CY3NonzeroMultiplicities V; + -- basisInv := new MutableHashTable; + -- for i from 0 to #basisIndices-1 do basisInv#(basisIndices#i) = i; + -- H3 := hashTable for x in keys H list ( + -- if isSubset(x, basisIndices) then ( + -- x' := apply(x, i -> basisInv#i); + -- x' => H#x + -- ) else continue + -- ); + -- Now let's get the cubic form and the linear form directly from the intersection theory. + -- For larger h11, this method will need to change. + x := getSymbol opts.Variable; + pt := base(x_0..x_(h11-1)); + A := intersectionRing pt; -- over QQ + R := if opts#Ring =!= null then opts#Ring else ZZ (monoid A); + if numgens R =!= h11 then error("expected a ring with "|toString h11|" variables"); + + X := completeIntersection(V, {-toricDivisor V}); + Xa := abstractVariety(X, pt); + IX := intersectionRing Xa; + h := sum(h11, i -> A_i * IX_(basisIndices#i)); + C := sub(integral(h^3), vars R); + L := integral((chern_2 tangentBundle Xa) * h); + L = sub(L, vars R); + (h11, h21, C, L) + ) + +hh(Sequence, TopologicalDataOfCY3) := (pq, T) -> ( + (p,q) := pq; + if p > q then (p, q) = (q, p); + if p == 0 then ( + if q == 3 or q == 0 then 1 else 0 + ) + else if p == 1 then ( + if q == 1 then T#2 + else if q == 2 then T#3 + else 0 + ) + else if p == 2 then ( + if q == 1 then T#3 + else if q == 2 then T#2 + else 0 + ) + else if p == 3 then ( + if q == 3 then 1 + else 0 + ) + ) + +c2Form TopologicalDataOfCY3 := T -> T#0 +cubicForm TopologicalDataOfCY3 := T -> T#1 +----- end of removing code TODO ----------------------------- diff --git a/CYToolsM2/StringTorics/ToricCompleteIntersections.m2 b/CYToolsM2/StringTorics/ToricCompleteIntersections.m2 new file mode 100644 index 0000000..0f87bc1 --- /dev/null +++ b/CYToolsM2/StringTorics/ToricCompleteIntersections.m2 @@ -0,0 +1,310 @@ +-- Need: better Hodge numbers, and also cohomologies (for complete intersections) +-- Also: can we be do better at getting the entire Picard group? + +------------------------------------------------------------------------------------ +-- link to Schubert2, as well as the ability to deal with complete intersections --- +------------------------------------------------------------------------------------ + +-------------------------------------------------------- +-- Code for complete intersections in toric varieties -- +-------------------------------------------------------- +completeIntersection = method(Options => { + Equations => true, + Basis => null, -- a list of integer indices of rays taht form a basis + Variables => null -- variable names for each basis element + }) + +completeIntersection(NormalToricVariety, List) := opts -> (Y,CIeqns) -> ( + if not all(CIeqns, d -> instance(d, ToricDivisor)) + then error "expected a list of toric divisors"; + if not all(CIeqns, d -> variety d === Y) + then error "expected a list of toric divisors on the given toric variety"; + eqns := if opts.Equations then ( + S := ring Y; + for D in CIeqns list random(degree D, S) + ) else + null; + B := if opts.Basis =!= null then ( + symbs := for i from 0 to #opts.Basis - 1 list opts.Variables_i; + base toSequence symbs + ); -- set to null if not being set + X := new CompleteIntersectionInToric from { + symbol Ambient => Y, + symbol CI => CIeqns, -- these are the degrees + symbol Equations => eqns, + symbol Basis => opts.Basis, + symbol Base => B, + symbol cache => new CacheTable + }; + X + ) + + +dim CompleteIntersectionInToric := (X) -> dim X.Ambient - #X.CI +ambient CompleteIntersectionInToric := (X) -> X.Ambient + +equations CompleteIntersectionInToric := List => X -> ( + X.Equations + ) + +lineBundle(CompleteIntersectionInToric, List) := (X, deg) -> ( + if not all(deg, x -> instance(x, ZZ)) or #deg =!= degreeLength ring ambient X + then error("expected multidegree of length "|degreeLength ring ambient X); + new LineBundle from { + symbol cache => new CacheTable, + symbol variety => X, + symbol degree => deg + } + ) + +degree LineBundle := L -> L.degree +variety LineBundle := L -> L.variety + +installMethod(symbol _, OO, CompleteIntersectionInToric, LineBundle => + (OO,X) -> lineBundle(X, (degree 1_(ring ambient X))) + ) + +LineBundle Sequence := (L, deg) -> ( + lineBundle(variety L, degree L + toList deg) + ) + + +abstractVariety(CompleteIntersectionInToric, AbstractVariety) := opts -> (X,B) -> ( + if not X.cache#?(abstractVariety, B) then X.cache#(abstractVariety, B) = ( + aY := abstractVariety(ambient X, B); + -- Question: how best to define F?? + bundles := X.CI/(d -> OO d); + F := bundles#0; + for i from 1 to #bundles-1 do F = F ++ bundles#i; + aF := abstractSheaf(ambient X, B, F); + sectionZeroLocus aF + ); + X.cache#(abstractVariety, B) + ) + +abstractVariety(CompleteIntersectionInToric) := opts -> (X) -> ( + if not X.cache#?(abstractVariety) then X.cache#(abstractVariety) = ( + aY := abstractVariety(ambient X, X.Base); + -- Question: how best to define F?? + bundles := X.CI/(d -> OO d); + F := bundles#0; + for i from 1 to #bundles-1 do F = F ++ bundles#i; + aF := abstractSheaf(ambient X, X.Base, F); + Xa := sectionZeroLocus aF; + X.cache.LinearForm = if X.Basis =!= null then ( + I := intersectionRing Xa; + coeffsI := coefficientRing I; -- this should be thevariables for the basis + sum for i from 0 to #X.Basis - 1 list coeffsI_i * I_(X.Basis#i) + ); + Xa + ); + X.cache#(abstractVariety) + ) + +linearForm = method() +linearForm CompleteIntersectionInToric := RingElement => X -> ( + Xa := abstractVariety X; + X.cache.LinearForm + ) + +intersectionRing CompleteIntersectionInToric := X -> ( + Xa := abstractVariety X; + intersectionRing Xa + ) + +intersectionForm = method() +intersectionForm CompleteIntersectionInToric := RingElement => X -> ( + if X.Basis === null then error "expected a basis to have been given"; + h := linearForm X; + integral(h^(dim X)) + ) + +-- todo: this makes most sense for 3-folds...? +c2Form CompleteIntersectionInToric := RingElement => X -> ( + Xa := abstractVariety X; + c2element := chern_2 tangentBundle Xa; -- I want a curve class here... + h := linearForm X; + integral(h^(dim X - first degree c2element) * c2element) + ) + +TEST /// +-* + restart +*- + debug needsPackage "StringTorics" -- remove 'debug' + -- Let's consider smooth toric surfaces. + for i from 0 to 4 list ( + V = smoothFanoToricVariety(2, 1); + picardGroup V + ) + V = smoothFanoToricVariety(2, 2) + transpose matrix degrees ring V + X = completeIntersection(V, {-toricDivisor V}, Basis => {0,3}, Variables => {symbol a, symbol b}) + linearForm X + intersectionForm X + linearForm X + hh^* OO_X(0,0) -- X is an elliptic curve + hh^*(OO_X(-1,1)) + + L = OO_X(-1,1) + assert(hh^0(L) == 1) + assert(hh^1(L) == 0) + assert(hh^* L == {1,0}) + intersectionForm X + chern_1 tangentBundle abstractVariety X + c2Form X +/// + +TEST /// +-* +restart +*- + debug needsPackage "StringTorics" -- remove 'debug' + + -* -- code to generate this example + topes = kreuzerSkarke(3, Limit => 50); + A = matrix topes_30 + P = convexHull A + (V, basisElems) = reflexiveToSimplicialToricVarietyCleanDegrees(P, CoefficientRing => ZZ/32003) + *- + + verts = {{-1, -1, 0, 0}, {-1, -1, 0, 1}, {-1, -1, 2, 0}, {-1, 0, 0, 0}, {1, -1, -1, 1}, {1, 2, -1, -1}, {-1, -1, 1, 0}} + maxcones = {{0, 1, 3, 4}, {0, 1, 3, 6}, {0, 1, 4, 6}, {0, 3, 4, 5}, {0, 3, 5, 6}, {0, 4, 5, 6}, {1, 2, 3, 5}, {1, 2, 3, 6}, {1, 2, 4, 5}, {1, 2, 4, 6}, {1, 3, 4, 5}, {2, 3, 5, 6}, {2, 4, 5, 6}} + V = normalToricVariety(verts, maxcones, CoefficientRing => ZZ/32003) + glsm = transpose matrix degrees ring V + basiselems = {0, 5, 6} + X = completeIntersection(V, {-toricDivisor V}, Basis => {0, 5, 6}, Variables => {symbol a, symbol b, symbol c}) + assert(dim X == 3) + intersectionRing X + h = linearForm X + integral(h^3) + assert(intersectionForm X == a^3-6*a^2*b+6*a*b^2+12*b^3-9*a^2*c+24*a*b*c+21*a*c^2-24*b*c^2-16*c^3) + assert(c2Form X == 10*a + 60*b + 8*c) + + X = completeIntersection(V, {-toricDivisor V}, Basis => {0, 5, 6}, Variables => symbol a) + + D = completeIntersection(V, {-toricDivisor V, V_0}, Basis => {0, 5, 6}, Variables => {symbol a, symbol b, symbol c}) + dim D == 2 + saturate(ideal equations D, ideal V) + intersectionRing D + intersectionForm D + c2Form D + chern_2 tangentBundle abstractVariety D + + L = OO_X(1,1,2) + assert(hh^* L == {8, 17, 0, 0}) -- TODO: recheck these numbers! + assert(variety L === X) + assert(degree L == {1,1,2}) + + needsPackage "DanilovKhovanskii" + computeHodgeDeligne(-toricDivisor V) + oo#1 + matrix for i from 0 to dim X list for j from 0 to dim X list (-1)^(i+j) * oo#(i,j) + + -- want to be able to turn this into a CalabiYauInToric... + -- then we can check computations against each other too. + +/// + +TEST /// +-* +restart +*- + debug needsPackage "StringTorics" -- remove 'debug' + V = kleinschmidt(3, {2,1}, CoefficientRing => ZZ/101) + rays V + max V + picardGroup V + isSmooth V + transpose matrix degrees ring V + X = completeIntersection(V, {-toricDivisor V}, Basis => {3,0}, Variables => {a,b}) + dim X == 2 + hh^*(OO_X(0,0)) == {1, 0, 1} + F = first equations X + saturate(ideal F + ideal jacobian F, ideal V) -- X is smooth + -- hh^*(OO_V(-1,3)) -- ouch! needs to work... +/// + + +TEST /// +-- DanilovKhovanskii +-* +restart +*- + debug needsPackage "StringTorics" -- remove 'debug' + needsPackage "DanilovKhovanskii" + V = kleinschmidt(3, {2,1}, CoefficientRing => ZZ/101) + rays V + max V + picardGroup V + isSmooth V + transpose matrix degrees ring V + X = completeIntersection(V, {-toricDivisor V}, Basis => {3,0}, Variables => {a,b}) + dim X == 2 + hh^*(OO_X(0,0)) == {1, 0, 1} + F = first equations X + saturate(ideal F + ideal jacobian F, ideal V) -- X is smooth + -- hh^*(OO_V(-1,3)) -- ouch! needs to work... + + computeHodgeDeligne(-toricDivisor V) + oo#1 + matrix for i from 0 to dim X list for j from 0 to dim X list oo#(i,j) + + +/// + +----------------------------- +-- Place elsewhere ---------- +----------------------------- +variety(CalabiYauInToric, Ring) := CompleteIntersectionInToric => (X, kk) -> ( + if not X.cache#?(variety, kk) then X.cache#(variety, kk) = ( + V := normalToricVariety X; + X1 := completeIntersection(V, { - toricDivisor V}); + X1.cache.CalabiYauInToric = X; + X1); + X.cache#(variety, kk) + ) +variety CalabiYauInToric := X -> variety(X, QQ) + +/// + -- how compatible with CalabiYauInToric is this? + -- I guess we need to know if the triangulation comes from a triangulation of the polytope... + +-* +restart +*- + debug needsPackage "StringTorics" -- remove 'debug' + + -* -- code to generate this example + topes = kreuzerSkarke(3, Limit => 50); + A = matrix topes_30 + P = convexHull A + (V, basisElems) = reflexiveToSimplicialToricVarietyCleanDegrees(P, CoefficientRing => ZZ/32003) + *- + + verts = {{-1, -1, 0, 0}, {-1, -1, 0, 1}, {-1, -1, 2, 0}, {-1, 0, 0, 0}, {1, -1, -1, 1}, {1, 2, -1, -1}, {-1, -1, 1, 0}} + maxcones = {{0, 1, 3, 4}, {0, 1, 3, 6}, {0, 1, 4, 6}, {0, 3, 4, 5}, {0, 3, 5, 6}, {0, 4, 5, 6}, {1, 2, 3, 5}, {1, 2, 3, 6}, {1, 2, 4, 5}, {1, 2, 4, 6}, {1, 3, 4, 5}, {2, 3, 5, 6}, {2, 4, 5, 6}} + V = normalToricVariety(verts, maxcones, CoefficientRing => ZZ/32003) + glsm = transpose matrix degrees ring V + basiselems = {0, 5, 6} + X = completeIntersection(V, {-toricDivisor V}, Basis => {0, 5, 6}, Variables => {symbol a, symbol b, symbol c}) + + -- we need a function that determines if this is a Batryev CY3. + -- and to return the corresponding CalabiYauInToric... + transpose matrix rays V + P = convexHull oo + vertices P + Q = cyPolytope P + rays Q + X1 = first findAllCYs Q + hodgeDiamond X1 + hodgeDiamond X + hh^(1,2) X1 == 69 + + needsPackage "DanilovKhovanskii" + computeHodgeDeligne (-toricDivisor V) -- this is not the correct answer I think! + oo#1 + matrix for i from 0 to dim X list for j from 0 to dim X list (-1)^(i+j) * oo#(i,j) + assert(hh^(1,2) Q == 69) + assert(hh^(1,1) Q == 3) +/// diff --git a/CYToolsM2/StringTorics/doc.m2 b/CYToolsM2/StringTorics/doc.m2 new file mode 100644 index 0000000..2bf3485 --- /dev/null +++ b/CYToolsM2/StringTorics/doc.m2 @@ -0,0 +1,1234 @@ +doc /// + Key + StringTorics + Headline + toric variety functions useful for investigations in string theory + Description + Text + This package uses the software packages TOPCOM, CohomCalg, and PALP, together + with facilities already present in Macaulay2, to provide the following + functionality. + Text + @SUBSECTION "Examples of use"@ + Text + @UL { + {TO "Example use", ", a first example showing basic usage of this package"} + }@ + Text + @SUBSECTION "Reflexive polytopes"@ + Text + In this package, a key type is @TO CYPolytope@. Objects of this class + contain information about a reflexive polytope. It also stores + Calabi-Yau data associated to this polytope that is independent of the + triangulation of the polytope used. + Text + @UL { + TO CYPolytope, + TO (annotatedFaces, CYPolytope), + TO basisIndices, + TO (isFavorable, CYPolytope), + TO (polar, CYPolytope), + TO (degrees, CYPolytope) + }@ + Text + @SUBSECTION "Routines to access the Kreuzer-Skarke database"@ + Text + @UL { + {TO "kreuzerSkarke"}, + {TO "kreuzerSkarkeDim3"} + }@ + Text + @SUBSECTION "Triangulations"@ + Text + @UL { + TO "facilities available for working with triangulations", + TO regularFineStarTriangulation, + TO allTriangulations, + TO generateTriangulations + }@ + Text + @SUBSECTION "Calabi Yau hypersurfaces in toric varieties"@ + Text + @UL { + {TO "CalabiYauInToric"}, + {TO "makeCY"}, + {TO "findAllCYs"} + }@ + + Text + @SUBSECTION "Creating and using CYDatabase's"@ + + A CYDatabase is a file which contains precomputed data about a collection of + (reflexive) 4D-polytopes and the resulting Calabi Yau hypersurfaces. + Text + @UL { + TO addToCYDatabase, + TO combineCYDatabases, + TO readCYDatabase, + TO readCYPolytopes, + TO readCYs + }@ + Text + @SUBSECTION "Cohomology"@ + Text + @UL { + TO "cohomology of line bundles on toric varieties", + TO cohomologyVector, + TO toricOrthants, + TO cohomologyBasis, + TO cohomologyMatrix, + TO cohomologyMatrixRank + }@ + Caveat + SeeAlso + "installing StringTorics" +/// + +doc /// + Key + CYPolytope + Headline + polytope data for a Calabi-Yau 3-fold hypersurface in a toric variety + Description + Text + SeeAlso + CalabiYauInToric +/// + +doc /// + Key + CalabiYauInToric + Headline + a Calabi-Yau 3-fold hypersurface in a simplicial toric variety + Description + Text + SeeAlso + CYPolytope +/// + +/// + Key + Headline + Usage + Inputs + Outputs + Consequences + Item + Description + Text + Example + Caveat + SeeAlso +/// + +/// + Key + cyPolytope + Headline + create a reflexive polytope pair + Usage + cyPolytope ks + cyPolytope vertexlist + cyPolytope m + cyPolytope P + cyPolytope str + Inputs + ks:KSEntry + vertexList:List + m:Matrix + the vertices are the columns + Q:CYPolytope + or @ofClass Polyhedron@ + ID => ZZ + :ZZ + a label for this polytope (TODO: is this a string or integer?) + Outputs + :CYPolytope + + Description + Text + topes = kreuzerSkarke(3, Limit => 50); + topes_40 + matrix topes_40 + Q = cyPolytope topes_40 -- this is a polytope + rays Q + Q1 = cyPolytope matrix topes_40 + Q2 = cyPolytope rays Q1 + verts = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}, {-1, 0, -1}, {0, -1, 0}, {-1, 0, 0}, {-1, 1, 0}} + QN = cyPolytope verts + netList annotatedFaces QN + vertices polytope(QN, "N") + vertices polytope(QN, "M") + latticePoints polytope(QN, "N") + latticePoints polytope(QN, "M") + polar QN + rays oo + netList annotatedFaces QN + netList annotatedFaces polar QN + PN = convexHull transpose matrix verts + PM = polar PN + vertices PM + + isReflexive P + vertices P -- notice these are in a different order + + netList annotatedFaces Q + rays smoothFanoToricVariety(3, 12) -- this is how we obtained these vertices. + Example + Caveat + SeeAlso +/// + +/// + Key + annotatedFaces + Headline + a list of faces of a reflexive polytope together with lattice point information + Usage + annotatedFaces Q + Inputs + Q:CYPolytope + or @ofClass Polyhedron@ + Outputs + :List + each entry is a list containing: the dimension of the face, the indices of the + vertices, the indices of all (boundary) lattice points in the face, the number + of interior points in the face, and the number of interior points in the dual face + Description + Text + verts = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}, {-1, 0, -1}, {0, -1, 0}, {-1, 0, 0}, {-1, 1, 0}} + QN = cyPolytope verts + netList annotatedFaces QN + vertices polytope(QN, "N") + vertices polytope(QN, "M") + latticePoints polytope(QN, "N") + latticePoints polytope(QN, "M") + polar QN + rays oo + netList annotatedFaces QN + netList annotatedFaces polar QN + PN = convexHull transpose matrix verts + PM = polar PN + vertices PM + + isReflexive P + vertices P -- notice these are in a different order + + netList annotatedFaces Q + rays smoothFanoToricVariety(3, 12) -- this is how we obtained these vertices. + Example + Caveat + SeeAlso +/// + +-* + Text + @SUBSECTION "Additional polyhedral functions"@ + Text + @UL { + {} + }@ + + Text + @UL { + {} + }@ + Text + @UL { + {} + }@ +*- + +doc /// + Key + "Example use" + Headline + An example of using the functionality of the package + Description + Text + Let's analyze one particular toric variety, and the corresponding + Calabi-Yau hypersurface. + + First, take an example from the Kreuzer-Skarke database. Note: you need to be online + in order for this to work! + Example + polytopes = kreuzerSkarke(5, 57, Limit=>200, Access => "wget"); + #polytopes == 197 + Text + There are 197 reflexive polytopes in 4 dimensions, whose + (resolution of an) anti-canonical divisor X (a Calabi-Yau), + has $h^{1,1}(X) = 5$, and $h^{1,2}(X) = 57$. + + Let's consider the 11th one on this list. + Example + polytopes_10 + A = matrix (polytopes_10) + Text + The Calabi-Yau is (the resolution of) an anti-canonical hypersurface + in the 4 dimensional projective toric variety whose polytope is $P_1$ + in the $M$ lattice. + + This polytope has 10 vertices, 7 facets, and 56 lattice points: + the origin and 55 on the boundary. + Example + P1 = convexHull A + fVector P1 + vertices P1 + matrix{latticePoints P1} + + # latticePointList P1 + vertexList P1 + transpose matrix latticePointList P1 + Text + Now let's take the dual polytope (in the $N$-lattice) + Example + P2 = polar P1 + Text + The following comand returns the list of non-zero lattice points, and + the vertices appear first on this list. + Example + latticePointList P2 + transpose matrix latticePointList P2 + vertexMatrix P2 + V0 = normalToricVariety normalFan P1 + isSimplicial V0 + isSmooth V0 + V = reflexiveToSimplicialToricVariety P1 + isSimplicial V + isSmooth V + rays V == (latticePointList P2)_{0..#rays V-1} + Text + This is the simplicial toric variety we want! Actually, any other + simplicial toric variety will work too (i.e. any other fine star regular + triangulation of the point configuration {\tt latticePointList P2}. + Text + The Calabi-Yau $X$ is an anti-canonical divisor in $V$ (the same as the + pull-back of an anti-canonical divisor in $V_0$, which is ample, to $V$ + (the result is no longer ample). + Batryev (based on Danilov-Khovanskii) has provided formulae for the Hodge numbers + of such a hypersurface. The formula for $h^{1,1}(X)$ and $h^{2,1}(X)$, for $X$ + the desingularization of a hypersurface in a Fano toric variety of dimension 4, + depends only on the polytope. + Example + h11OfCY P1 + h21OfCY P1 + Text + The reflexive polytope is called favorable if $H^{1,1}(X)$ is generated by the + images of toric divisors on $V$. + Example + isFavorable P1 + Text + Intersection ring of $X$ + Text + First, let's work on $X$, which is a sufficiently generic hypersurface of $V$ + in the divisor class $|-K_V|$. + Example + KV = toricDivisor V + X = completeIntersection(V, {-KV}) + Text + The Hodge diamond of $X$, as long as $X$ is sufficiently generic, + is determined via Danilov-Khovanskii (reference: ...). However, + the following works whenever $X$ is a smooth hypersurface of $V$. + Example + hodgeDiamond X + Text + Thus $h^{1,1}(X) = 5$ and $h^{1,2}(X) = 57$. + + We can do intersection theory on $X$ and $V$. Note that $V$ is not smooth, but + since it is simplicial, as long as we work over the rationals, not the integers, + the intersection ring is well-defined. Since $X$ is smooth (or assumed to be), + the intersection ring of $X$ is well-defined. + + The way we do all of this is we first create the abstract variety of a point. + We include some parameters here (we will use them below). Then, we define + abstract varieties for $V$ and $X$. These are designed to work well with the + intersection theory implemented in Macaulay2 (the package @TO "Schubert2"@). + An abstract variety contains information about its intersection ring (or, the numerical + intersection ring), the chern class of its tangent bundle, and how to integrate + a cycle on the variety. + Example + pt = base(symbol a, symbol b, symbol c, symbol d, symbol e) + Va = abstractVariety(V, pt) + Xa = abstractVariety(X, pt) + IX = intersectionRing Xa + Text + For example, the (restrictions to $X$) of the 9 toric prime divisors: + Example + gens IX + integral(t_2*t_3*t_4) + integral(t_2^3) + Text + The advantage of putting parameters into the base, is that we can generate + formulas. For example, the euler characteristic of $L = OO_X(aD_4+bD_5+cD_6+dD_7+eD_8)$ + ($L$ is a line bundle with the given element as first Chern class. Note + that $D_4, \ldots, D_8$ generate the intersection ring) can be found using + the following code, which invokes Hirzebruch-Riemann-Roch to find the euler + characteristic. + Example + L = a*t_4 + b*t_5 + c*t_6 + d*t_7 + e*t_8 + F1 = chi OO(L) + 6*(F1-1) + SeeAlso +/// + +doc /// + Key + "Example: (3,3) hypersurface in P2 x P2" + Headline + the bicubic threefold + Description + Text + Let's analyze one particular toric variety, and the corresponding + Calabi-Yau hypersurface. + + First, let's construct this toric variety, and the corresponding Calabi-Yau + 3-fold. Let $V = \PP^2 \times \PP^2$, and let $X \subset V$ be defined + by a random $(3,3)$ form in 6 variables. + Example + P2 = toricProjectiveSpace 2 + V0 = P2 ** P2 + isSmooth V0 + RZ = QQ[a,b] + Q = cyPolytope(rays V0) + isFavorable Q + hh^(1,1) Q + hh^(1,2) Q + Text + $Q \subset N \otimes \RR$ is the reflexive polytope in the $N = \ZZ^3$ lattice, and + + We now create the Calabi-Yau. The ring here should be in $h^(1,1)(X)$ variables (over the integers, or + the rationals. + Example + X = makeCY(Q, Ring => RZ) + normalToricVariety(X, CoefficientRing => ZZ/32003) + dim X + describe X + cubicForm X + c2Form X + Text + Hirzebruch-Riemann-Roch gives the following for the euler characteristic of OO(a,b). + Example + aX = abstractVariety(X, base(a,b)) + basisIndices X + intersectionRing aX + chi OO(a * t_0 + b*t_1) + 1/6 * cubicForm X + 1/12 * c2Form X + Text + Now let's investigate the cohomology of line bundles $\mathcal{O}_X(a,b)$. + Very few cohomologies are non-zero on the ambient $V = \PP^2 \times \PP^2$. + Example + V = ambient X + netList toricOrthants V + Text + For $a,b \ge 0$, $H^0(\mathcal{O}_X(a,b)) = H^0(\mathcal{O}_V(a,b)) = S_{ab}$, where $S$ is the Cox ring of $V$, + and is zero outside of this range. + Example + S = ring V + describe S + cohomologyBasis(2, V, {-4,0}) + cohoms = hashTable flatten for a from -6 to 6 list for b from -6 to 6 list elapsedTime (a,b) => (hh^*(OO_X(a,b))) + matrix for a from -6 to 6 list for b from -6 to 6 list (cohoms#(a,b))_0 + matrix for a from -6 to 6 list for b from -6 to 6 list (cohoms#(a,b))_1 + matrix for a from -6 to 6 list for b from -6 to 6 list (cohoms#(a,b))_2 + matrix for a from -6 to 6 list for b from -6 to 6 list (cohoms#(a,b))_3 + for a from 0 to 10 list a => hh^*(OO_X(0,a)) + + cohomologyBasis(2, V, {-6,3}) + cohomologyBasis(2, V, {-3,6}) + cohomologyMatrix(2, V, {-3, 6}, first equations X) + matrix first oo + rank oo + for a from -3 to 3 list cohomologyBasis(2, V, {a,0}) + for a from -3 to 3 list cohomologyBasis(2, V, {-3,a-3}) + +/// + +/// +-- scratch work trying to understand cohomology for bicubics. + fcn = (b) -> (10 * binomial(b-3 + 2, 2), binomial(b+2,2)) + fcn 100 + fcn 1000 + + T = ZZ/101[x,y,z] + C = res ideal random(T^1, T^{10:-3}) + C.dd_2 + + hh^*(OO_X(-3,3)) + hh^*(OO_X(-3,4)) -- 15 of these + + fcn = (a,b) -> ( + binomial(-a+2,2) * binomial(b-1,2), + binomial(-a-1,2) * binomial(b+2,2)) + fcn(0,3) + fcn(0,4) + matrix first cohomologyMatrix(2, V, {-3,4}, first equations X) + fcn(-3,4) + fcn(-3,3) + fcn(-3,2) + for b from 3 to 20 list fcn(-3,b) + for b from 3 to 20 list fcn(-4,b) + for b from 3 to 20 list fcn(-5,b) + for b from 3 to 20 list fcn(-6,b) + binomial(-a+2,2) * binomial(b-1,2) - + binomial(-a-1,2) * binomial(b+2,2) + + t = symbol t + R = ZZ/101[t_0..t_9] + M = matrix{{t_0, t_1, t_2, t_3, t_4, t_5, t_6, t_7, t_8, t_9, 0, 0, 0, 0, 0}, + {0, t_0, 0, t_1, t_2, 0, t_3, t_4, t_5, 0, t_6, t_7, t_8, t_9, 0}, + {0,0, t_0, 0, t_1, t_2, 0, t_3, t_4, t_5, 0, t_6, t_7, t_8, t_9} + } + minimalBetti coker M + C = res coker M + + S = ZZ/101[a,b,c] + phi = map(S, R, random(S^1, S^{10:-3})) + C = res coker phi M + +/// + +/// + Key + "Example: the tetraquadric Calabi-Yau 3-fold" + Headline + the tetraquadric + Description + Text + Let's analyze one particular toric variety, and the corresponding + Calabi-Yau hypersurface. + + First, let's construct this toric variety, and the corresponding Calabi-Yau + 3-fold. Let $V = \PP^1 \times \PP^1 \times \PP^1 \times \PP^1$, and let $X \subset V$ be defined + by a random $(2,2,2,2)$ form in 8 variables. + Example + P1 = toricProjectiveSpace 1 + V0 = P1 ** P1 ** P1 ** P1 + isSmooth V0 + RZ = ZZ[a..d] + Q = cyPolytope(rays V0) + isFavorable Q + hh^(1,1) Q + hh^(1,2) Q + Text + $Q \subset N \otimes \RR$ is the reflexive polytope in the $N = \ZZ^4$ lattice, and + + We now create the Calabi-Yau. The ring here should be in $h^(1,1)(X)$ variables (over the integers, or + the rationals. + Example + X = makeCY(Q, Ring => RZ) + V = normalToricVariety(X, CoefficientRing => ZZ/32003) + dim X + describe X + cubicForm X + c2Form X + Text + Eventually, put in the GV invariants and flop matrices one finds. + + + Example + M1 = matrix"-1,0,0,0;2,1,0,0;2,0,1,0;2,0,0,1" + for a in {0,0,0}..{3,3,3} list a => hh^*(OO_X(-1,a#0,a#1,a#2)) + GV = gvInvariants(X, DegreeLimit => 10); + hh^*(OO_X(-1,2,2,2)) + hh^*(OO_X(-1,2,2,3)) + hh^*(OO_X(-2,2,2,2)) + hh^*(OO_X(-2,4,4,3)) + F = first equations X + cohomologyBasis(1, V, {-4,2,2,2}) + cohomologyBasis(1, V, {-2,4,4,4}) + cohomologyMatrix(1, V, {-2,4,4,4}, F) + hh^*(OO_X(-4,5,0,0)) + (m, tar, src) = cohomologyMatrix(1, V, {-2,4,4,4}, F) + matrix m; + #tar + #src + rank m +/// + +/// +-- scratch work for tetraquadric example. + Text + The following won't be in this tutorial. + Example + S = ZZ/32003[x_1,y_1,x_2,y_2,x_3,y_3, Degrees => {2:{1,0,0}, 2:{0,1,0}, 2:{0,0,1}}] + G0 = random({2,2,2}, S) + G1 = random({2,2,2}, S) + G2 = random({2,2,2}, S) + syz matrix{{G0,G1,G2}} + degrees source oo + + A = symbol A + C = symbol C + S = ZZ/32003[x_1,y_1,A_1..C_3, Degrees => {2:{1,0},9:{0,1}}] + G0 = x_1^2 * A_1 + x_1*y_1 * A_2 + y_1^2 * A_3 + G1 = x_1^2 * B_1 + x_1*y_1 * B_2 + y_1^2 * B_3 + G2 = x_1^2 * C_1 + x_1*y_1 * C_2 + y_1^2 * C_3 + syz matrix{{G0,G1,G2}} + syz matrix{{G0,G1,G2,0},{0,G0,G1,G2}} + M = coker matrix{{G0,G1,G2,0},{0,G0,G1,G2}} + res M +o67_{0} +o67_{1} + T = ZZ/32003[a,b,c] + syz matrix{{a,b,c,0},{0,a,b,c}} +/// + +/// + Key + + Headline + Usage + Inputs + Outputs + Consequences + Description + Text + This is the first way to use the package. Grab a reflexive polytope from the Kreuzer-Skarke database. + Example + restart + needsPackage "StringTorics" + topes = kreuzerSkarke(3, Limit => 100); + Q = cyPolytope(topes_50, ID => 50) + RZ = ZZ[x,y,z] + X = makeCY(Q, Ring => RZ, ID => 0) + label X + V = normalToricVariety(X, CoefficientRing => ZZ/101) + V === ambient X + assert(coefficientRing ring ambient X === ZZ/101) + L = OO_X(1,2,3) + L = OO_X(1,2,-1) + hh^* L + cubicForm X + c2Form X + intersectionNumbers X + basisIndices X + dim X + aX = abstractVariety(X, base(x,y,z)) + use intersectionRing aX + + L = OO_X(1,2,-33) + hh^* L + chi OO(t_0 + 2*t_1 - 33*t_2) + + for d in (-2,-2,-2)..(2,2,2) list d => hh^* OO_X(d) + chi(OO(x * t_0 + y * t_1 + z * t_2)) + RQ = ring oo + assert( + 1/6 * sub(cubicForm X, RQ) + 1/12 * sub(c2Form X, RQ) + == + chi(OO(x * t_0 + y * t_1 + z * t_2)) + ) + + -- Method #2 to use the package. + p1 = toricProjectiveSpace 1 + V0 = p1 ** p1 ** p1 ** p1 + isSimplicial V0 + max V0 + RZ = ZZ[a,b,c,d] + Q1 = cyPolytope(rays V0, ID => 0) + X = makeCY(Q1, ID => 0, Ring => RZ) + V = normalToricVariety(X, CoefficientRing => ZZ/101) + isWellDefined V + L = OO_X(2,1,-1,-2) + hh^* L + equations X + + describe X + equations X + X = calabiYauHypersurface V -- not written yet. + X = toricCompleteIntersection(V, {-toricDivisor V}, Equations => generic) + -- should detect it is CY? + + P2 = convexHull transpose matrix rays V + isReflexive P2 + isSimplicial P2 + V1 = cyPolytope(rays V, ID => 0) + degrees V1 + peek V1.cache + X1 = cyData(V1, max V) + X = variety(X1, ZZ/32003) + hh^*(OO_X(1,1,1,1)) + cyData X + + topes = kreuzerSkarke(3, Limit => 100) + ks = topes_70 + V0 = normalToricVariety(ks, CoefficientRing => ZZ/101) + Xs = makeCYs V0 + ambient Xs_0 -- a simplicial normal toric variety + + normalToricVariety KSEntry := opts -> ks -> ( + polytopeData := cyPolytope ks; + normalToricVariety(rays polytopeData + ) + + V0 = normalToricVariety(ks, CoefficientRing => ZZ/101) + Xs = findAllCYs V0 -- creates CalabiYauInToric's + X = findOneCY V0 -- choose one triangulation + ambient Xs_0 -- gives a simplicial toric variety (over same coefficient ring). + + V0 = cyPolytope ks + for a in annotatedFaces V0 list if a#0 != dim V0 - 1 then continue else a# + select(annotatedFaces V0, a -> a#0 == dim V0 - 1) + PN = convexHull transpose matrix rays V0 + PN2 = polytope(ks, "N") + + +-- Usage #1. + Q = cyPolytope(tope, ID => label) + Xs = findAllCYs(Q, Ring => RZ) -- labels them + X = makeCY(Q, ID => lab, Ring => RZ) + -- given an X = Xs_0 say + -- really want line bundles on X, cohomology on X. But might also want equations. Where to put those? + +-- Usage #2. Start with a toric variety constructed elsewhere. +-- Case A: it is simplicial, from reflexive. +-- Case B: it is not simplicial, but is from reflexive. + X = cyHypersurface(V, Ring => RZ, Equations => ...) + V = ambient X + + Caveat + SeeAlso +/// + + + +doc /// + Key + hodgeOfCYToricDivisor + (hodgeOfCYToricDivisor,Polyhedron,List) + Headline + compute the cohomology vector of an (irreducible) toric divisor on a CY hypersurface + Usage + hodgeOfCYToricDivisor(P,pt) + Inputs + P:Polyhedron + Any polytope will do, although so far it has only been tested on + reflexive polytopes. + pt:List + a lattice point in the polar dual polytope {\tt polar P} + Outputs + :List + The list of $\{ h^0(X,OO_D), h^1(X,OO_D), h^2(X,OO_D) \}$, + where $D$ is the intersection of the toric divisor corresponding + to the lattice point with a hypersurface $X$ corresponding to + an anti-canonical divisor on the toric 4-fold $V$ corresoponding . + Description + Text + We assume that $P$ is a reflexive 4-dimensional polytope, and let $V_0$ be the 4-dimensional + toric variety corresponding to $P$ (i.e. corresponding to the normal fan of $P$). Let $V$ + be a simplicial resolution of $V_0$, corresponding to a star triangulation of the polar dual + $P^o$, which is fine, i.e. involves all of the lattice points of $P^o$. Let $X \subset V$ be + the inverse image of an anti-canonical divisor on $V_0$. Note that from Batyrev, it turns + out that $X$ is a smooth Calabi-Yau 3-fold. Finally, a lattice point $pt$ + of $P^o$ corresponds to a toric divisor on $V$. Let $D$ be the intersection of this divisor + with $X$. + + This function computes the vector of cohomologies of the structure sheaf of the surface $D$. + + As an example, the following example is taken from the Kreuzer-Skarke database of 4D reflexive + polytopes. + + Example + polystr = "Kreuzer-Skarke: 4 12 M:24 12 N:16 11 H:11,19 [-16] + 1 0 0 0 0 1 2 1 0 -2 0 -2 + 0 1 0 0 0 0 -2 -1 1 2 -1 0 + 0 0 1 0 0 -1 0 -1 -1 1 -1 1 + 0 0 0 1 -1 0 1 1 -1 0 1 -2 + " + A = matrix first kreuzerSkarke polystr + P = convexHull A + Text + This polytope has 12 vertices, 33 edges, 32 2-faces, and 11 facets. + Example + # faceList(0,P) + # faceList(1,P) + # faceList(2,P) + # faceList(3,P) + fVector P + Text + + Note that only the faces which contain interior lattice points, or whose dual does, is included. + So 6 of the 33 edges of the polytope have an interior vertex along that edge. + + There are 15 non-zero lattice points in the dual, meaning that the + toric 4-fold has 15 toric divisors on it (each is a 3-fold, and also toric). + It turn out that they all are rigid, in the sense that in each case, + $h^0(OO_D) = 1$, $h^1(OO_D) = 0$, $h^2(OO_D) = 0$. + Example + # latticePointList polar P + hodgeOfCYToricDivisors P + Text + The Hodge numbers $h^{1,1}(X)$ and $h^{2,1}(X)$ can be computed using + information about $P$ only, not the specific triangulation used. + Example + isFavorable P + h11OfCY P + h21OfCY P + Caveat + This function currently only works for 4-d reflexive polytopes. However, the + formulas work for other dimensions, and these should be included. + SeeAlso +/// + +/// + Key + "computing sheaf cohomology of specific Calabi-Yau hypersurfaces in toric varieties" + Headline + facilities available for computing sheaf cohomology + Description + Text + Example + Caveat + SeeAlso + +/// + +doc /// + Key + "facilities available for working with triangulations" + Headline + facilities available for working with triangulations + Description + Text + In this introduction, we consider triangulations of the following square + in the plane. + Example + square = transpose matrix{{1,1},{-1,1},{-1,-1},{1,-1}} + regularFineTriangulation square + assert(# allTriangulations square == 2) + Text + Now consider all of the lattice points of the square. + Example + P = convexHull square + LP = latticePointList P + sq9 = transpose matrix LP + Text + We could have entered sq9 by hand as so: + Example + sq9 = matrix {{-1, -1, 1, 1, -1, 0, 0, 1, 0}, + {-1, 1, -1, 1, 0, -1, 1, 0, 0}} + Text + We first show some functions from Topcom that are useful. + Example + t1 = regularFineTriangulation sq9 + regularTriangulationWeights t1 + fineStarTriangulation(sq9, max t1) + delaunaySubdivision sq9 -- not a triangulation (4 squares). + orientedCircuits sq9 -- many of these are not useful when considering only fine triangulations. + Text + Let's generate all of the triangulations of the square. + Really, we want all triangulations which are fine (involve all the lattice points) + and are star (involve the origin), and are regular. + Example + regularFineStarTriangulation sq9 -- leaves out 8, the index of the origin in sq9. + Ts = allTriangulations sq9; + #Ts + Ts = Ts/max; + # select(Ts, t -> isFine(sq9,t)) + # select(Ts, t -> isStar(sq9,t)) + # select(Ts, t -> isStar(sq9,t) and isFine(sq9,t)) + # select(Ts, t -> isFine(sq9,t) and isRegularTriangulation(sq9,t)) + Text + Regular triangulations and subdivisions can be computed. + In this example, we take the first 5 fine triangulations found above, + find weights (they are all regular triangulations) giving these triangulations, + then reconstruct the triangulation using @TO regularSubdivision@. + These are the same as the triangulations we started with. + Example + fineT = take(select(Ts, isFine_sq9), 5) + wts = for t in fineT list regularTriangulationWeights(sq9, t) + fineT2 = for w in wts list regularSubdivision(sq9, matrix{w}) + fineT == fineT2 + Text + We might want to check that these are indeed triangulations. + I am not completely convinced that @TO topcomIsTriangulation@ always gives a + correct answer, so we also implement a slower routine @TO naiveIsTriangulation@. + Example + starT = first select(Ts, t -> isStar(sq9,t)) + naiveIsTriangulation(sq9, starT) + topcomIsTriangulation(sq9, starT) + notSq9 = matrix {{-1, -1, 1, 1, -1, 0, 0, 2, 0}, + {-1, 1, -1, 1, 0, -1, 1, 0, 0}} + naiveIsTriangulation(notSq9, starT) + topcomIsTriangulation(notSq9, starT) + debug Triangulations + isTriangulation(notSq9, starT) + Text + All regular triangulations fit into a polytope, whose vertices are the + GKZ volume vectors (for each lattice point, consider the sum of the volumes + of the simplices containing the point as a vertex). This gives a vector in + $\Z^d$, where $d$ is the number of lattice points, which is computed by the method + @TO volumeVector@. + Example + volume convexHull sq9 + tri = fineT_0 + for f in tri list volume convexHull(sq9_f) + sum oo == volume convexHull sq9 + volumeVector(sq9, tri) + volumeVector(sq9, starT) + Text + Sometimes we want to generate only some of the triangulations, as there can be + a huge number of them. Unfortunately, the topcom functions do not allow this + functionality. Instead, use @TO generateTriangulations@. Note that this function + only generates fine triangulations. + Example + T4 = generateTriangulations(sq9, Limit => 100); + T3 = select(Ts, t -> isFine(sq9,t)); + assert(set (T4/max) === set T3) + SeeAlso + generateTriangulations + "Topcom::allTriangulations" +/// + + +/// + Key + vertexMatrix + Headline + Usage + Inputs + Outputs + Consequences + Description + Text + Example + Caveat + SeeAlso +/// + +doc /// + Key + "cohomology of line bundles on toric varieties" + Headline + introduction to computing line bundle cohomologies in Macaulay2 + Description + Text + Example + topes = kreuzerSkarke(3, Access=>"wget"); + topes_9 + A = matrix topes_11 + P = convexHull A + P2 = polar P + V = reflexiveToSimplicialToricVariety P + S = ring V -- the Cox ring + GLSM = transpose matrix degrees S + SR = dual monomialIdeal V + assert isSimplicial V + assert isSmooth V + picardGroup V === ZZ^3 + Text + As an example, let's compute the cohomology of the line bundle $OO_V(-2,3,-4)$. + Example + D = 2*V_1 + 3*V_0 - 4*V_6 + degree D + for i from 0 to 4 list HH^i(V, OO(D)) + for i from 0 to 4 list rank HH^i(V, OO(D)) + cohomologyVector(V, {-2,3,-4}) + cohomologyVector(V, D) + hashTable for i from 0 to # rays V - 1 list i => cohomologyVector(V, V_i) + Text + @SUBSECTION "Bases of cohomology groups"@ + Text + We now delve a bit deeper into the bases of these cohomology groups. + + There are a number of pointed orthants in $\ZZ^n$, where $n$ is the number of rays, + which support cohomology. + Example + netList toricOrthants V + cohomologyBasis(1, V, {2, 1, 0}) + HH^1(V, OO_V(2,1,0)) + for i from 0 to 3 list cohomologyBasis(i, V, {2, 1, 0}) + for i from 0 to 3 list rank HH^i(V, OO_V(2, 1, 0)) + + for i from 0 to 3 list cohomologyBasis(i, V, {2, 1, -2}) + for i from 0 to 3 list cohomologyBasis(i, V, {2, 1, -3}) + Text + @SUBSECTION "Cohomology on Calabi-Yau hypersurfaces"@ + Text + SeeAlso +/// + +------------------------------------------------ +-- Database creation and retrieval functions --- +------------------------------------------------ +doc /// + Key + addToCYDatabase + (addToCYDatabase, String, List) + Headline + create or append to a database file and populate it with CYPolytope's and possibly CalabiYauInToric's + Usage + addToCYDatabase(filename, topes) + Inputs + filename:String + the desired name of the data base file. If the file doesn't exist it is created, + otherwise the name should be the name of an existing data base file, and this file + is modified + topes:List + of @ofClass KSEntry@'s, a list of Kreuzer-Skarke type entries for some polytopes + "CYs" => Boolean + if true, then also all Calabi Yau hypersurfaces are computed and added to the database. + NTFE => Boolean + if true, then triangulations which are identical on the set of 2-faces are considered the + same, and only one is placed into the data base. + Consequences + Item + For each polytope corresponding to an entry in the {\tt topes} list, + a @ofClass CYPolytope@ is created, and various information about it is computed + and then stored in the data base file for later use + Description + Text + A CYDatabase file is a database file whose contents are precomputed data + about some @TO CYPolytope@'s and @TO CalabiYauInToric@'s. Since some information takes + non-trivial time to construct, we precompute this data, and then we can later pull up + this data via the functions @TO readCYDatabase@, @TO "readCYPolytopes"@, and @TO readCYs@. + Text + The CYPolytope corresponding to each item of the {\tt topes} list is constructed + and some basic data is computed (e.g. information about the faces of the polytopes, whether the + polytope is favorable, and degree information about it. This data is then stored in the + database for later retrieval. + Example + filename = "foo-remove-me.dbm" + if fileExists filename then removeFile filename + topes = kreuzerSkarke(2, Limit => 4) + addToCYDatabase(filename, topes_{1,2,3}) + Example + F = openDatabase filename + F#"1" + Q = cyPolytope F#"1" + hh^(1,1) Q + hh^(1,2) Q + isFavorable Q + Text + As a data base file, all keys of {\tt F} are strings, and the values are strings too. + Example + sort keys F + Text + Close the database file when done with it. + Example + close F + Text + For this example, we also delete this database file. + Example + removeFile filename + SeeAlso + addToCYDatabase + readCYDatabase + readCYs +/// + +-- (addToCYDatabase, String, Database, ZZ) do we want this one? +/// + Key + (addToCYDatabase, String, CYPolytope) + Headline + add data for every Calabi-Yau hypersurface coming from a given (reflexive) CYPolytope + Usage + addToCYDatabase(filename, Q) + Inputs + Q:CYPolytope + Consequences + Item + Data for all triangulations, or all 2-face inequivalent triangulations is placed into + the database with file name {\tt filename} + Description + Text + Example + filename = "foo-remove-me.dbm" + if fileExists filename then removeFile filename + topes = kreuzerSkarke(2, Limit => 3) + addToCYDatabase(filename, topes, "CYs" => false) + Text + Example + Qs = readCYPolytopes(filename) + addToCYDatabase(filename, Qs#0, NTFE => true) + addToCYDatabase(filename, Qs#1, NTFE => true) + addToCYDatabase(filename, Qs#2, NTFE => true) + readCYs(filename, Qs) + R = ZZ[x,y] + (Qs, Xs) = readCYDatabase(filename, Ring => R) + Qs + Xs + + R = ZZ[a,b,c,d] + (Qs, Xs) = readCYDatabase("./m2-examples/cys-ntfe-h11-4-h12-100.dbm", Ring => R); + #(keys Qs) + #(keys Xs) + Xs + debug StringTorics + partition(k -> invariantsAll Xs#k, keys Xs) + SeeAlso +/// + +/// + Key + Headline + Usage + Inputs + Outputs + Consequences + Item + Description + Text + Example + SeeAlso +/// + + + +/// +-* + restart + needsPackage "StringTorics" +*- + topes = kreuzerSkarke(5, Limit=>10, Access=>"wget") + + A = matrix topes_9 + P = convexHull A + P2 = polar P + LP = matrix{latticePoints P2} + elems2 = regularSubdivision(LP, matrix{{1/2, 1/10, 10, 3, 2, 8, 12, 7/8, 9/11, 1}}) + hts = for i from 0 to numcols LP-1 list random 100 + elems3 = regularSubdivision(LP, matrix{hts}) + elems = regularFineTriangulation LP + for e in elems list latticeVolume convexHull LP_e + for e in elems2 list latticeVolume convexHull LP_e + sum for e in elems3 list latticeVolume convexHull LP_e + sort unique flatten elems == toList(0..numcols LP-1) + sort unique flatten elems2 == toList(0..numcols LP-1) + sort unique flatten elems3 == toList(0..numcols LP-1) + -- I would like to check that these are well-defined triangulations + latticeVolume P + latticeVolume P2 + + vertices P -- matrix over QQ + vertexList P -- list (over ZZ or QQ?), different order than 'vertices' + vertexMatrix P + faceList + faceDimensionHash + minimalFace + latticePoints P -- list of single column matrices, over ZZ + latticePointList P + latticePointHash + interiorLatticePoints + interiorLatticePointList + faces(3,P) + faceList(1,P) + vertices P2 + matrix{latticePoints P2} + +/// + +/// +-* + restart + needsPackage "StringTorics" +*- + topes = kreuzerSkarke(80, Limit=>10, Access=>"wget") + A = matrix topes_9 + P = convexHull A + P2 = polar P + vertices P -- matrix over QQ + vertexList P -- list (over ZZ or QQ?), different order than 'vertices' + vertexMatrix P + faceList + faceDimensionHash + minimalFace + latticePoints P -- list of single column matrices, over ZZ + latticePointList P + latticePointHash + interiorLatticePoints + interiorLatticePointList + faces(3,P) + faceList(1,P) + vertices P2 + matrix{latticePoints P2} + +/// + +------------------------------------------------------------ +-- Routines for complete intersections in toric varieties -- +-- Some functionality is only for hypersurfaces! ----------- +------------------------------------------------------------ + +/// + Key + CompleteIntersectionInToric + Headline + a complete intersection in a projective toric variety + Description + Text + Functions for this type include allowing intersection theory on the induced + intersection ring + Text + @SUBSECTION "Line bundles and cohomology on complete intersections in toric varieties"@ + Text + @UL { + -- {TO ""}, + -- {TO ""}, + -- {TO ""} + }@ + Text + Here is an example of using these facilities. We consider a hypersurface in a normal toric + variety. + Example + needsPackage "StringTorics" + V = smoothFanoToricVariety(3, 10, CoefficientRing => ZZ/32003) + rays V + max V + dual monomialIdeal V + X = completeIntersection(V, {-toricDivisor V}) + dim X == 2 + -- TODO: would like to check smoothness (one way: saturate(ideal minors(1, jacobian ideal equations X), ideal V)) + -- TODO: codim + Example + pt = base(a,b,c) + Xa = abstractVariety(X, pt) + IX = intersectionRing Xa + numgens IX + L = OO_X(1,0,0) + hh^* L + hh^1 L + hh^10 L + Caveat + SeeAlso +/// + + + + + +-* +/// + Key + Headline + Usage + Inputs + Outputs + Consequences + Description + Text + Example + Caveat + SeeAlso +/// +*- + + +/// +Andreas Schachner to Everyone (Apr 14, 2023, 9:53 AM) +https://arxiv.org/pdf/2112.12106.pdf +You to Everyone (Apr 14, 2023, 10:00 AM) +{{-1, 0, 0, 0}, {1, 0, 0, 0}, {0, -1, 0, 0}, {0, 1, 0, 0}, {0, 0, -1, 0}, {0, 0, 1, 0}, {0, 0, 0, -1}, {0, 0, 0, 1}} +Andreas Schachner to Everyone (Apr 14, 2023, 10:54 AM) +https://cyjax.readthedocs.io/en/latest/ +Nathaniel MacFadden to Everyone (Apr 14, 2023, 10:58 AM) +https://docs.python.org/3/library/doctest.html +Nathaniel MacFadden to Everyone (Apr 14, 2023, 11:07 AM) +https://developers.google.com/optimization/mip/mip_example +Nathaniel MacFadden to Everyone (Apr 14, 2023, 11:19 AM) +https://www.scipopt.org/ +Nathaniel MacFadden to Everyone (Apr 14, 2023, 11:26 AM) +GLOP +https://developers.google.com/optimization/lp/lp_advanced +/// diff --git a/CYToolsM2/StringTorics/other/DatabaseCreation2.m2 b/CYToolsM2/StringTorics/other/DatabaseCreation2.m2 new file mode 100644 index 0000000..398403f --- /dev/null +++ b/CYToolsM2/StringTorics/other/DatabaseCreation2.m2 @@ -0,0 +1,2491 @@ +---------------------------------- +-- Code for creating data bases -- +---------------------------------- +label KSEntry := ZZ => (ks) -> ( + str := toString ks; + ans := regex("id:([0-9]+)", str); + if ans === null or #ans != 2 then + null + else + value substring(str, ans#1#0, ans#1#1) + ) + +hodgeNumbers = method() +hodgeNumbers KSEntry := (ks) -> ( + str := toString ks; + ans := regex("H:([0-9]+),([0-9]+)", str); + if #ans != 3 then error "expected 3 matches"; + (value substring(str, ans#1#0, ans#1#1), + value substring(str, ans#2#0, ans#2#1)) + ) + +createCYDatabase = method() + +-- functions needed: +-- 1. given a (dbfilename, KSEntry), add that polytope to the db. +-- 2. given a (dbfilename, KSEntry, Q), add all the NTFE CY's to th edata base. +-- 3. combine 1, 2. + +createCYDatabase(String, List) := (dbfilename, topes) -> ( + -- open data base file + F := openDatabaseOut dbfilename; + -- loop through topes, create CYPolytope, populate it, write it to data base. + elapsedTime for i from 0 to #topes - 1 do elapsedTime ( + lab := label topes_i; + if lab === null then lab = i; -- else print "using label"; + << "computing for polytope " << lab << endl; + V := cyPolytope(topes#i, ID => lab); -- note that the polytope data is really that of the dual to topes#i. + -- now fill it with data we want + basisIndices V; -- compute them + isFavorable V; -- compute h11, h21, favorability. + annotatedFaces V; -- compute annotated faces + automorphisms V; + -- now write it + F#(toString lab) = dump V; + ); + close F; + ) + +addToCYDatabase = method(Options => {NTFE => false}) + +addToCYDatabase(String, CYPolytope) := opts -> (dbfilename, Q) -> ( + elapsedTime Xs := findAllCYs Q; -- TODO: check: is findALlCYs still correct. + << " " << #Xs << " triangulations total" << endl; + if opts.NTFE then ( + elapsedTime H := partition(restrictTriangulation, Xs); + << " " << #(keys H) << " NTFE triangulations" << endl; + Xs = (keys H)/(k -> H#k#0); -- only take one triangulation that matches + -- let's relabel these Xs + ); + F := openDatabaseOut dbfilename; + for X in Xs do ( + computeIntersectionNumbers X; -- this should load all of the data we want + F#(toString label X) = dump X; + ); + close F; + ) + + +addToCYDatabase(String, Database, ZZ) := opts -> (dbfilename, topesDB, i) -> ( + << "-- doing polytope " << i << endl; + Q := cyPolytope(topesDB#(toString i), ID => i); + addToCYDatabase(dbfilename, Q, opts); + ) + +--- XXX, options: Replace=>true, Label=>null, computeCYs=>true. +addToCYDatabase(String, KSEntry) := CYPolytope => opts -> (dbfilename, ks) -> ( + lab := label ks; + F := openDatabaseOut dbfilename; + if not F#?(toString lab) then ( + if lab === null then lab = i; -- else print "using label"; + << "computing for polytope " << lab << endl; + Q := cyPolytope(ks, ID => lab); -- note that the polytope data is really that of the dual to topes#i. + -- now fill it with data we want + basisIndices Q; -- compute them + isFavorable Q; -- compute h11, h21, favorability. + annotatedFaces Q; -- compute annotated faces + automorphisms Q; + -- now write it + F#(toString lab) = dump Q; + ) + else + Q = cyPolytope F#(toString lab); + close F; + Q + ) + +addToCYDatabase = method() -- add a KSEntry polytope or list of such to a dbfile. +addCYsToCYDatabase = method() +addPolytopeAndCYs + +addPolytopeAndCYsToCYDatabase = method() + +-- XXX +addToCYDatabase(String, CYPolytope) := opts -> (dbfilename, Q) -> ( + -- This version also finds "moriConeCap" which is a cone containing the actual mori cone: it is the + -- intersection of all mori cones coming from triangulations equivalent to the given one. + elapsedTime Xs := findAllCYs Q; -- TODO: check: is findALlCYs still correct. + << " " << #Xs << " triangulations total" << endl; + if opts.NTFE then ( + elapsedTime H := partition(restrictTriangulation, Xs); + << " " << #(keys H) << " NTFE triangulations" << endl; + Xs = (keys H)/(k -> H#k#0); -- only take one triangulation that matches + Xs = for k in keys H list ( + X := H#k#0; + setToricMoriConeCap(X, H#k); + X + ) + -- let's relabel these Xs? + ); + F := openDatabaseOut dbfilename; + for X in Xs do ( + computeIntersectionNumbers X; -- this should load all of the data we want + F#(toString label X) = dump X; + ); + close F; + ) +addPolytopeAndCYsToCYDatabase(String, KSEntry) := opts -> (dbfilename, ks) -> ( + Q := addToCYDatabase(dbfilename,ks); + addCYsToCYDatabase(dbfilename, Q); + ) +--- + +readCYDatabase = method(Options => {Ring => null}) +readCYDatabase String := Sequence => opts -> (dbname) -> ( + F := openDatabase dbname; + labs := (keys F)/value; + Qlabels := sort select(labs, lab -> instance(lab, ZZ)); + Xlabels := sort select(labs, lab -> instance(lab, Sequence)); + Qs := hashTable for lab in Qlabels list lab => cyPolytope F#(toString lab); + Xs := hashTable for lab in Xlabels list lab => cyData(F#(toString lab), i -> Qs#i, opts); + close F; + (Qs, Xs) + ) + +readCYPolytopes = method() +readCYPolytopes String := HashTable => (dbname) -> ( + F := openDatabase dbname; + labs := (keys F)/value; + Qlabels := sort select(labs, lab -> instance(lab, ZZ)); + Qs := hashTable for lab in Qlabels list lab => cyPolytope F#(toString lab); + close F; + Qs + ) + +readCYs = method(Options => {Ring => null}) +readCYs(String, HashTable) := HashTable => opts -> (dbname, Qs) -> ( + F := openDatabase dbname; + labs := (keys F)/value; + Xlabels := sort select(labs, lab -> instance(lab, Sequence)); + Xs := hashTable for lab in Xlabels list lab => cyData(F#(toString lab), i -> Qs#i, opts); + close F; + Xs + ) + +/// + -- h11=4 database use, 19 June 2023. + -- XXX In construction +-* + restart + needsPackage "StringTorics" +*- + R = ZZ[a,b,c,d] + RQ = QQ (monoid R); + (Qs, Xs) = readCYDatabase("mike-ntfe-h11-4.dbm", Ring => R); + assert(#keys Qs == 1197) -- includes torsions and nonfavorables. + assert(#keys Xs == 1994) -- note, none of the torsion Qs are in here yet. + + peek Xs#(20,0).cache + ByH12 = partition(k -> hh^(1,2) Xs#k, keys Xs); + -- by H12 value, 1994 examples are split into 86 groups. + -- largest group is h12=64, at 195 in that group. + 86 == # hashTable for x in keys ByH12 list x => #ByH12#x + + -- Now let's divide by invariants to see how to separate them all. + debug StringTorics -- invariantsAll isn't exported! + elapsedTime IHall = partition(x -> elapsedTime invariantsAll x, values Xs); + -- 1126 different groups here. + assert(#keys IHall == 1126) + (values IHall)/(x -> #x)//tally + -- 723 different classes have exactly one element in them. + -- largest class is 51 elements. + -- of course, these all might be equivalent! (Probably not, but who knows...) + -- Tally{1 => 723} + 2 => 221 + 3 => 109 + 4 => 31 + 5 => 8 + 6 => 13 + 7 => 3 + 8 => 5 + 9 => 1 + 10 => 5 + 11 => 1 + 12 => 2 + 13 => 2 + 28 => 1 + 51 => 1 + -- Now leave off inverse system invariant: get the same numbers. + -- How many of these can be determined to be equivalent? + -- Well, the 723 that are by themselves we can ignore. + set2 = select(values IHall, k -> #k > 1); + set3 = set2/(x -> (x/label//sort)) + count = 0; + set4 = for Ls in set3 list ( + << "--- doing " << count << " with " << Ls << endl; + count = count + 1; + ans := elapsedTime partitionByTopology(Ls, Xs, 15); + print ans; + ans + ) + set5 = for x in set4 list ( + for k in keys x list {k} | (x#k / first) + ) + set5len = for x in set5 list (x/length) + #set5len + #select(set5len, x -> #x == 1) -- 340 of the 403 have one class. + -- 53 sets have 2 classes + -- 8 sets have 3 classes + -- 2 sets have 4 classes + -- so total number of topologies is likely: 723 + 340 + 53*2 + 8*3 + 2*4 = 1201 + set6 = for x in set5 list (x/sort/first//sort) + set7 = sort select(set6, x -> #x > 1) + #set7 == 63 -- these are sets we still would like to separate by invariants of that is possible + -- range on number of topologies: + -- low end: 723 + 340 + 63 == 1126 + -- hi end: 723 + 340 + 138 == 1201 + for ks in set7 list netList transpose {for k in ks list factor det hessian cubicForm Xs#k} + for ks in set7 list netList transpose {for k in ks list factor cubicForm Xs#k} + + -- Here we just play some and try to separate these + + -- Let's try to separate some of these now, and then we can try to automate it + -- XXX 19 June 2023. + (L1, F1) = (c2Form Xs#(1182,0), cubicForm Xs#(1182,0)) + (L2, F2) = (c2Form Xs#(1183,2), cubicForm Xs#(1183,2)) + + (L1, F1) = (c2Form Xs#(1143,0), cubicForm Xs#(1143,0)) + (L2, F2) = (c2Form Xs#(1145,0), cubicForm Xs#(1145,0)) + + (L1, F1) = (c2Form Xs#(1123,0), cubicForm Xs#(1123,0)) + (L2, F2) = (c2Form Xs#(1124,0), cubicForm Xs#(1124,0)) + + (L1, F1) = (c2Form Xs#(1123,0), cubicForm Xs#(1123,0)) + (L2, F2) = (c2Form Xs#(1124,0), cubicForm Xs#(1124,0)) + + (A,phi) = genericLinearMap RQ + T = source phi; + I0 = sub(ideal last coefficients (phi sub(L1,T) - sub(L2,T)), ring A) + A0 = A % I0 + phi0 = map(T,T,A0) + trim(I0 + sub(ideal last coefficients (phi0 sub(F1,T) - sub(F2,T)), ring A)) + + + for k from 0 to #set7-1 list ( + (lab1,lab2) = toSequence set7#k_{0,1}; -- only do the first 2. + I := getEquivalenceIdeal(lab1, lab2, Xs); + << "k = " << k << " ideal " << netList I_* << endl; + I + ) + + (lab1,lab2) = toSequence set7#0_{0,1} + getEquivalenceIdeal(lab1,lab2, Xs) + getEquivalenceIdealHelper((L1,F1),(L2,F2),A,phi) +/// + +/// + -- Example of construction of database for: h11=3, all h12's. + -- Note, #232 is not favorable. + restart + needsPackage "StringTorics" + topes = kreuzerSkarke(3, Limit => 1000); + assert(#topes == 244) + elapsedTime createCYDatabase("foo-ntfe-h11-3.dbm", topes) + + -- Now let's add in all the CY's total, including all triangulations. + Qs = readCYPolytopes "foo-ntfe-h11-3.dbm"; + elapsedTime for Q in values Qs do addToCYDatabase("foo-ntfe-h11-3.dbm", Q, NTFE => true); + + -- How to access all of the polytopes and CY's at once. + -- We create a hashtable for each, keys are their labels, and values are the CYPolytope and CalabiYauInToric's. + Qs = readCYPolytopes "foo-ntfe-h11-3.dbm"; + for k in sort keys Qs do assert instance(Qs#k, CYPolytope) + + Xs = readCYs("foo-ntfe-h11-3.dbm", Qs); + for k in sort keys Xs do assert instance(Xs#k, CalabiYauInToric) + + -- or both at the same time.. + (Qs1, Xs1) = readCYDatabase "foo-ntfe-h11-3.dbm"; + assert(Qs1 === Qs) + assert(Xs1 === Xs) + + -- given all the3 Qs, how to access just some Xs (e.g. for a specific Q). + F = openDatabase "foo-ntfe-h11-3.dbm" + Qs = readCYPolytopes "foo-ntfe-h11-3.dbm"; + for k in sort keys F list ( + if not match("\\(6,", k) then continue else cyData(F#(toString k), i -> Qs#i) + ) + oo/label + close F +/// + +/// + -- Example of creation of h11=4 database of those triangulations which are NTFE (not 2-face equivalent). + -- One data base per (h11,h12) pair too. +-* + restart + needsPackage "StringTorics" +*- + + createNTFEDatabase = (dbname, topes) -> ( + createCYDatabase(dbname, topes); + Qs := readCYPolytopes dbname; + elapsedTime for Q in values Qs do addToCYDatabase(dbname, Q, NTFE => true); + ) + createAllNTFEDatabases = (h12s, topes) -> ( + for i in h12s do ( + dbname = "cys-ntfe-h11-4-h12-"|i|".dbm"; + << "starting on " << dbname << endl; + ourtopes = select(topes, ks -> last hodgeNumbers ks == i); + createNTFEDatabase(dbname, ourtopes); + ); + ) + + + topes = kreuzerSkarke(4, Limit => 10000); + createAllNTFEDatabases({28, 34}, topes) + assert(#topes == 1197) + h12s = topes/hodgeNumbers/last//unique//sort + h12s == {28, 34, 36, 37, 40, 42, 44, 46, 48, 49, 50, 52, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 76, 77, 78, 79, 80, 81, 82, 84, 85, 86, 88, + 89, 90, 91, 92, 93, 94, 96, 97, 98, 100, 101, 102, 104, 106, + 108, 109, 110, 112, 114, 116, 118, 120, 121, 122, 124, 126, + 128, 130, 136, 142, 144, 148, 154, 162, 166, 178, 190, 194, + 202, 208, 214, 226, 238} + + createAllNTFEDatabases(h12s, topes) + +/// + +/// +-* + restart + debug needsPackage "StringTorics" +*- + + -- Example analysis of topologies for h11=4. + topes = kreuzerSkarke(4, Limit => 10000); + assert(#topes == 1197) + h12s = topes/hodgeNumbers/last//unique//sort + h12s == {28, 34, 36, 37, 40, 42, 44, 46, 48, 49, 50, 52, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 76, 77, 78, 79, 80, 81, 82, 84, 85, 86, 88, + 89, 90, 91, 92, 93, 94, 96, 97, 98, 100, 101, 102, 104, 106, + 108, 109, 110, 112, 114, 116, 118, 120, 121, 122, 124, 126, + 128, 130, 136, 142, 144, 148, 154, 162, 166, 178, 190, 194, + 202, 208, 214, 226, 238} + + db4name = (h12) -> "cys-ntfe-h11-4-h12-"|h12|".dbm" + RZ = ZZ[a,b,c,d]; + DB = hashTable for h in h12s list h => readCYDatabase(db4name h, Ring => RZ); + + (Qs, Xs) = DB#56 + H = partition(invariants2, values Xs) + tops = hashTable for k in keys H list k => ((H#k)/label) + INV = for k in sort keys tops list k => partitionByTopology(tops#k, Xs, 15) + + keys Xs + F1 = cubicForm Xs#(73,0) + F2 = cubicForm Xs#(80,3) + L1 = c2Form Xs#(73,0) + L2 = c2Form Xs#(80,3) + + + (Qs, Xs) = DB#97 + (Qs, Xs) = DB#94 + H = partition(invariants2, values Xs) + tops = hashTable for k in keys H list k => ((H#k)/label) + INV = for k in sort keys tops list k => partitionByTopology(tops#k, Xs, 15) + hashTable INV + + unfavorables = sort flatten for h in h12s list ( + Qs = readCYPolytopes(db4name h); + for Q in values Qs list if not isFavorable Q then label Q else continue + ) + unfavorables === {796, 800, 803, 1059, 1060, 1064, 1065, 1134, 1135, 1151, 1153, 1155} + nontorsionfrees = sort flatten for h in h12s list ( + (Qs, Xs) = readCYDatabase(db4name h); + for X in values Xs list ( + V := normalToricVariety(rays X, max X); + if classGroup V =!= ZZ^4 then label X else continue + ) + ) + -- all unfavorables have torsion toric class group: + nontorsionfrees == {(0, 0), (3, 0), (4, 0), (5, 0), (12, 0), (15, 0), + (796, 0), (796, 1), (800, 0), (803, 0), (1059, 0), (1060, 0), (1064, 0), + (1065, 0), (1134, 0), (1135, 0), (1151, 0), (1153, 0), (1155, 0), (1155, 1)} + + + -- analyze one h12 + findDistincts= (h12) -> ( + (Qs, Xs) = DB#h12; + H = partition(invariants2, values Xs); + tops = hashTable for k in keys H list k => ((H#k)/label); + INV = for k in sort keys tops list k => partitionByTopology(tops#k, Xs, 15); + (INV, Qs, Xs) + ) + (INV, Qs, Xs) = findDistincts 28; + netList INV + + (INV, Qs, Xs) = findDistincts 34; -- only one here + netList INV + + (INV, Qs, Xs) = findDistincts 36; -- polytopes 3,4,5: all have class group torsion. + netList INV + + (INV, Qs, Xs) = findDistincts 37; + netList INV -- only one + + (INV, Qs, Xs) = findDistincts 40; -- 2 diff topologies, different invariants2 + netList INV + + (INV, Qs, Xs) = findDistincts 44; -- has a torsion polytope. + netList INV + + (INV, Qs, Xs) = findDistincts 46; + netList INV -- (17,0), (19,1) are seemingly different. + F1 = cubicForm Xs#(17,0) + F2 = cubicForm Xs#(19,1) + sing = (F) -> ideal F + ideal jacobian F + linears = (I) -> (J := ideal select(I_*, f -> part(1, f) != 0); if J == 0 then trim ideal 0_(ring I) else J) + linearcontent = (I) -> trim sum for f in (linears I)_* list content f + betti res sub(sing F1, RQ) + betti res sub(sing F2, RQ) + + betti res sub(saturate sing F1, RQ) + betti res sub(saturate sing F2, RQ) + primaryDecomposition sub(saturate sing F1, RQ) + primaryDecomposition sub(saturate sing F2, RQ) + see ideal gens gb saturate sing F1 + see ideal gens gb saturate sing F2 -- these have different linear parts (252a, 1512a). SHows they are different. + + select(sort keys DB, h12 -> # keys last DB#h12 > 1) + + (INV, Qs, Xs) = findDistincts 48; + netList INV -- all 3 are distinct + + (INV, Qs, Xs) = findDistincts 49; + netList INV -- all 6 are distinct + + (INV, Qs, Xs) = findDistincts 50; + netList INV -- only 1. + + (INV, Qs, Xs) = findDistincts 52; -- alot here, it seems + netList INV -- one group of 6, one of 4, one of 3, 17 of 1 each. + F1 = cubicForm Xs#(33,0) + F2 = cubicForm Xs#(41,0) + F3 = cubicForm Xs#(41,1) + F4 = cubicForm Xs#(44,0) + F5 = cubicForm Xs#(48,0) + F6 = cubicForm Xs#(49,4) + see linears ideal gens gb saturate sing F1 + see linears ideal gens gb saturate sing F2 + see linears ideal gens gb saturate sing F3 + see linears ideal gens gb saturate sing F4 + see linears ideal gens gb saturate sing F5 + see linears ideal gens gb saturate sing F6 + trim content F1 + trim content F2 + trim content F3 + trim content F4 + trim content F5 + trim content F6 + see linearcontent ideal gens gb saturate sing F1 + see linearcontent ideal gens gb saturate sing F2 + see linearcontent ideal gens gb saturate sing F3 + see linearcontent ideal gens gb saturate sing F4 + see linearcontent ideal gens gb saturate sing F5 + see linearcontent ideal gens gb saturate sing F6 + + F1 = cubicForm Xs#(35,0) + F2 = cubicForm Xs#(38,0) + F3 = cubicForm Xs#(39,0) -- F1 and F3 look pretty similar? TODO: I can't prove they are the same or different yet! + F4 = cubicForm Xs#(53,0) + + for p in {3,5,7,11, 13} list (pointCount(F1, p), pointCount(F3, p)) + decompose sub(sing F1, RQ) + decompose sub(ideal gens gb saturate sing F1, RQ) + decompose sub(ideal gens gb saturate sing F3, RQ) + + invariants2 Xs#(35,0) + invariants2 Xs#(39,0) + partitionGVConeByGV(Xs#(35, 0), DegreeLimit => 25) -- simplicial (4 generators, GV's: -2, 8, 10, 64). + partitionGVConeByGV(Xs#(39, 0), DegreeLimit => 25) -- 5 gens, GV: -2,-2,10,64,128. + -- Question: how to distinguish F1, F3? (F2, F4 are different and diff from F1, F3). + + L1 = c2Form Xs#(35,0) + L3 = c2Form Xs#(39,0) + + decompose sub((ideal(L1) + sing F1), RQ) + decompose sub((ideal(L3) + sing F3), RQ) + decompose sub(ideal(L3, F3), RQ) + + -- Next one to try + (INV, Qs, Xs) = findDistincts 54; + netList INV + F1 = cubicForm Xs#(64,0) + F2 = cubicForm Xs#(64,1) + see linears ideal gens gb saturate sing F1 + see linears ideal gens gb saturate sing F2 -- very different... + + -- Next one to try + (INV, Qs, Xs) = findDistincts 55; + netList INV + F1 = cubicForm Xs#(67,0) + F2 = cubicForm Xs#(69,0) + see linears ideal gens gb saturate sing F1 + see linears ideal gens gb saturate sing F2 -- different linear part contents. + + -- Next one to try. All ones that cannot be matched are distinct. + (INV, Qs, Xs) = findDistincts 56; + netList INV -- lots. 2: 2 diff, 1: 3 diff, 18: 1 only... + -- set1 + F1 = cubicForm Xs#(73,0) + F2 = cubicForm Xs#(80,3) + see linears ideal gens gb saturate sing F1 + see linears ideal gens gb saturate sing F2 -- different linear part contents. + -- set2 + F1 = cubicForm Xs#(75,0) + F2 = cubicForm Xs#(75,1) + F3 = cubicForm Xs#(75,3) + see linears ideal gens gb saturate sing F1 + see linears ideal gens gb saturate sing F2 + see linears ideal gens gb saturate sing F3 -- all different via linear part contents + -- set3 + F1 = cubicForm Xs#(72,0) + F2 = cubicForm Xs#(80,2) + see linears ideal gens gb saturate sing F1 + see linears ideal gens gb saturate sing F2 -- different linear part contents. + + -- Next one to try + (INV, Qs, Xs) = findDistincts 57; -- 1 only. + netList INV + + -- Next one to try + (INV, Qs, Xs) = findDistincts 58; + netList INV -- 1: 9 different!, 1: 4 diff, 26: 1 diff + -- set1 + F1 = cubicForm Xs#(92,0) + F2 = cubicForm Xs#(93,0) + F3 = cubicForm Xs#(96,0) + F4 = cubicForm Xs#(97,0) + F5 = cubicForm Xs#(105,0) + F6 = cubicForm Xs#(105,2) + F7 = cubicForm Xs#(112,0) + F8 = cubicForm Xs#(120,0) + F9 = cubicForm Xs#(120,2) + linearcontent ideal gens gb saturate sing F1 + linearcontent ideal gens gb saturate sing F2 + linearcontent ideal gens gb saturate sing F3 + linearcontent ideal gens gb saturate sing F4 + linearcontent ideal gens gb saturate sing F5 + linearcontent ideal gens gb saturate sing F6 + linearcontent ideal gens gb saturate sing F7 + linearcontent ideal gens gb saturate sing F8 + linearcontent ideal gens gb saturate sing F9 + -- all are distinct except possibly F3, F7 + decompose sub(ideal gens gb saturate sing F3, RQ) + decompose sub(ideal gens gb saturate sing F7, RQ) -- 1 point vs 3 points. So F3, F7, therefore all, are distinct. + -- set2 + F1 = cubicForm Xs#(98,0) + F2 = cubicForm Xs#(109,0) + F3 = cubicForm Xs#(110,0) + F4 = cubicForm Xs#(110,1) + see linears ideal gens gb saturate sing F1 + see linears ideal gens gb saturate sing F2 + see linears ideal gens gb saturate sing F3 + see linears ideal gens gb saturate sing F4 -- all different via linear part contents + + -- Next one to try + (INV, Qs, Xs) = findDistincts 59; + netList INV -- 3, all distinct + + -- Next one to try + (INV, Qs, Xs) = findDistincts 60; + netList INV -- + -- set1 + F1 = cubicForm Xs#(133,0) + F2 = cubicForm Xs#(137,0) + F3 = cubicForm Xs#(140,0) + F4 = cubicForm Xs#(146,0) + F5 = cubicForm Xs#(148,0) + F6 = cubicForm Xs#(148,1) + linearcontent ideal gens gb saturate sing F1 + linearcontent ideal gens gb saturate sing F2 + linearcontent ideal gens gb saturate sing F3 + linearcontent ideal gens gb saturate sing F4 + linearcontent ideal gens gb saturate sing F5 + linearcontent ideal gens gb saturate sing F6 -- all distinct linear content! + -- set2 + F1 = cubicForm Xs#(144,0) + F2 = cubicForm Xs#(158,0) + linearcontent ideal gens gb saturate sing F1 + linearcontent ideal gens gb saturate sing F2 -- all distinct linear content! + -- set3 + F1 = cubicForm Xs#(140,1) + F2 = cubicForm Xs#(142,0) + linearcontent ideal gens gb saturate sing F1 + linearcontent ideal gens gb saturate sing F2 -- all distinct linear content! + -- set4 + F1 = cubicForm Xs#(129,0) + F2 = cubicForm Xs#(135,0) + F3 = cubicForm Xs#(139,0) + F4 = cubicForm Xs#(149,0) + linearcontent ideal gens gb saturate sing F1 + linearcontent ideal gens gb saturate sing F2 + linearcontent ideal gens gb saturate sing F3 + linearcontent ideal gens gb saturate sing F4 -- all distinct linear content! + -- set5 + F1 = cubicForm Xs#(135,1) + F2 = cubicForm Xs#(138,0) + F3 = cubicForm Xs#(149,2) + linearcontent ideal gens gb saturate sing F1 + linearcontent ideal gens gb saturate sing F2 -- how to tell F1, F2 apart? + linearcontent ideal gens gb saturate sing F3 + decompose sub(ideal gens gb saturate sing F1, RQ) + decompose sub(ideal gens gb saturate sing F2, RQ) -- stil todo: are F1, F2 equivalent? + + -- Next one to try + (INV, Qs, Xs) = findDistincts 61; + netList INV -- + F1 = cubicForm Xs#(163,2) + F2 = cubicForm Xs#(164,0) + F3 = cubicForm Xs#(166,0) + F4 = cubicForm Xs#(166,1) + F5 = cubicForm Xs#(166,2) + F6 = cubicForm Xs#(169,0) + F7 = cubicForm Xs#(169,1) + linearcontent ideal gens gb saturate sing F1 + linearcontent ideal gens gb saturate sing F2 + linearcontent ideal gens gb saturate sing F3 + linearcontent ideal gens gb saturate sing F4 + linearcontent ideal gens gb saturate sing F5 + linearcontent ideal gens gb saturate sing F6 + linearcontent ideal gens gb saturate sing F7 -- all distinct linear content! + + -- Next one to try + (INV, Qs, Xs) = findDistincts 62; + netList INV -- + -- set1 + F1 = cubicForm Xs#(172,0) + F2 = cubicForm Xs#(173,0) + F3 = cubicForm Xs#(179,0) + F4 = cubicForm Xs#(179,2) + F5 = cubicForm Xs#(180,0) + F6 = cubicForm Xs#(192,1) + linearcontent ideal gens gb saturate sing F1 + linearcontent ideal gens gb saturate sing F2 + linearcontent ideal gens gb saturate sing F3 + linearcontent ideal gens gb saturate sing F4 + linearcontent ideal gens gb saturate sing F5 + linearcontent ideal gens gb saturate sing F6 -- all distinct linear content! + -- set2 + F1 = cubicForm Xs#(181,1) + F2 = cubicForm Xs#(191,0) + linearcontent ideal gens gb saturate sing F1 + linearcontent ideal gens gb saturate sing F2 -- how to tell F1, F2 apart? + -- set3 + F1 = cubicForm Xs#(182,0) + F2 = cubicForm Xs#(182,1) + linearcontent ideal gens gb saturate sing F1 + linearcontent ideal gens gb saturate sing F2 -- how to tell F1, F2 apart? + + -- Next one to try + (INV, Qs, Xs) = findDistincts 63; + netList INV -- only 1 + + -- Next one to try + (INV, Qs, Xs) = findDistincts 64; + netList INV -- LOTS!! TODO: start here. Actually, maybe I should start over and incorporate the linear content into the invariants. + + + + H = partition(invariants2, values Xs) + tops = hashTable for k in keys H list k => ((H#k)/label) + INV = for k in sort keys tops list k => partitionByTopology(tops#k, Xs, 15) + hashTable INV + + h12s == {28, 34, 36, 37, 40, 42, 44, 46, 48, 49, 50, 52, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 76, 77, 78, 79, 80, 81, 82, 84, 85, 86, 88, + 89, 90, 91, 92, 93, 94, 96, 97, 98, 100, 101, 102, 104, 106, + 108, 109, 110, 112, 114, 116, 118, 120, 121, 122, 124, 126, + 128, 130, 136, 142, 144, 148, 154, 162, 166, 178, 190, 194, + 202, 208, 214, 226, 238} + +/// + +/// + -- An attempt to automate the following: + -- 1. create one hash table with all of the Qs, Xs. + -- 2. separate the Xs via invariants. + -- 3. for each invariant, use topology to separate. + +-* + restart + debug needsPackage "StringTorics" +*- + + -- Example analysis of topologies for h11=4. + --topes = kreuzerSkarke(4, Limit => 10000); + --assert(#topes == 1197) + --h12s = topes/hodgeNumbers/last//unique//sort + h12s = {28, 34, 36, 37, 40, 42, 44, 46, 48, 49, 50, 52, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 76, 77, 78, 79, 80, 81, 82, 84, 85, 86, 88, + 89, 90, 91, 92, 93, 94, 96, 97, 98, 100, 101, 102, 104, 106, + 108, 109, 110, 112, 114, 116, 118, 120, 121, 122, 124, 126, + 128, 130, 136, 142, 144, 148, 154, 162, 166, 178, 190, 194, + 202, 208, 214, 226, 238} + + nontorsionfrees = {(0, 0), (3, 0), (4, 0), (5, 0), (12, 0), (15, 0), + (796, 0), (796, 1), (800, 0), (803, 0), (1059, 0), (1060, 0), (1064, 0), + (1065, 0), (1134, 0), (1135, 0), (1151, 0), (1153, 0), (1155, 0), (1155, 1)} + + db4name = (h12) -> "cys-ntfe-h11-4-h12-"|h12|".dbm" + RZ = ZZ[a,b,c,d]; + RQ = QQ (monoid RZ); + DB = hashTable for h in h12s list h => readCYDatabase("../m2-examples/"|db4name h, Ring => RZ); + Qs = new MutableHashTable + Xs = new MutableHashTable + for a in keys DB do ( + (Q1s, X1s) = DB#a; + for q in sort keys Q1s do Qs#q = Q1s#q; + for k in sort keys X1s do if not member(k, nontorsionfrees) then Xs#k = X1s#k; + ); + Xs = new HashTable from Xs; + Qs = new HashTable from Qs; + sort keys Qs + sort keys Xs + #oo == 1994 -- 2014 total for all + assert(# sort keys Xs == 2014 - #nontorsionfrees) + + elapsedTime H = partition(invariants3, values Xs); + H1 = hashTable for k in keys H list k => (H#k)/label; + elapsedTime INV = for k in sort keys H1 list k => partitionByTopology(H1#k, Xs, 15); + -- number of different topologies + tally for k in sort keys H1 list #H1#k + elapsedTime INV = for k in sort keys H1 list k => partitionByTopology(H1#k, Xs, 15); + tally for k in INV list #(keys last k) + INV1 = select(INV, k -> #(keys last k) >= 2); + netList INV1 + + -- separate topologies: + -- output is a list of lists {S0, S1, S2, ..., Sr} + -- each CY in Si is not equivalent to any in Sj, i!=j. + -- each pair of CY's in a specific Si are not proved to be distinct (but are likely distinct?) + -- every CY in h11=4 database is knoqn to be equivalent to one of these + -- (Question: or are they all there in one of these lists?) + TOP1 = for k in INV list for a in keys last k list ( + prepend(a, ((last k)#a)/first) + ); + netList(TOP1/(a -> a/(a1->#a1))) + + REPS = for k in INV list ( + H := last k; -- a hash table + K := keys H; + if #K == 1 then continue + else K) + + ONEONLY = for k in INV list ( + H := last k; -- a hash table + K := keys H; + if #K == 1 then first K else continue) + + -- So: 1994 total different NTFE h11=4 CY's, with torsion free class groups (all of these are favorable) + -- Of these: + #TOP1 + TOP1/(a -> a/(a1->#a1)//sum)//sum == 1994 + #ONEONLY == 904 -- the number that are by themselves. + #REPS == 118 + # flatten REPS == 287 + + REPS = {{(14, 1), (14, 0)}, + {(38, 4), (53, 0), (30, 0), (38, 0)}, + {(35, 0), (39, 0)}, + {(80, 6), (80, 2)}, + {(96, 0), (126, 0)}, + {(148, 1), (141, 0)}, + {(140, 0), (144, 0)}, + {(135, 0), (134, 3)}, + {(135, 1), (138, 0)}, + {(180, 0), (179, 2)}, + {(241, 0), (210, 0), (258, 0)}, + {(265, 0), (250, 0), (265, 1), (236, 0), (228, 1)}, + {(290, 1), (258, 1)}, + {(235, 0), (262, 0)}, + {(225, 2), (260, 2)}, + {(265, 2), (235, 1)}, + {(265, 3), (228, 0)}, + {(250, 1), (254, 2)}, + {(249, 1), (246, 0)}, + {(227, 0), (261, 0)}, + {(209, 3), (284, 1), (261, 1)}, + {(240, 3), (278, 1)}, + {(319, 0), (313, 0)}, + {(316, 0), (322, 0)}, + {(334, 2), (328, 1), (329, 0)}, + {(331, 0), (337, 1), (339, 3)}, + {(334, 1), (329, 1)}, + {(339, 5), (337, 0)}, + {(385, 2), (385, 3)}, + {(364, 1), (377, 0)}, + {(356, 0), (395, 6)}, + {(378, 0), (378, 2), (379, 1), (395, 2)}, + {(379, 0), (379, 3)}, + {(383, 0), (356, 1)}, + {(397, 0), (350, 0)}, + {(387, 4), (387, 0)}, + {(377, 2), (364, 0)}, + {(416, 0), (441, 0), (438, 0), (450, 4)}, + {(400, 0), (403, 0), (405, 0), (414, 0)}, + {(436, 0), (433, 0)}, + {(419, 0), (419, 2)}, + {(436, 1), (433, 1)}, + {(451, 0), (455, 1)}, + {(475, 1), (481, 1)}, + {(473, 0), (478, 0)}, + {(458, 5), (458, 1)}, + {(458, 3), (458, 0)}, + {(508, 0), (514, 0)}, + {(512, 1), (505, 0)}, + {(507, 0), (519, 3)}, + {(526, 1), (527, 0), (518, 3), (522, 0)}, + {(524, 0), (518, 0)}, + {(529, 0), (510, 0)}, + {(550, 0), (538, 0)}, + {(532, 0), (573, 0)}, + {(556, 0), (562, 0)}, + {(553, 0), (548, 1), (554, 0)}, + {(552, 0), (551, 2)}, + {(559, 0), (577, 0)}, + {(540, 0), (545, 0)}, + {(588, 0), (586, 0)}, + {(616, 0), (606, 0)}, + {(650, 0), (650, 1), (667, 1), (650, 3), (656, 0), (666, 9), (630, 0)}, + {(643, 0), (649, 0), (626, 0)}, + {(628, 0), (653, 0)}, + {(647, 0), (669, 0)}, + {(688, 1), (685, 0)}, + {(687, 0), (684, 1)}, + {(693, 0), (694, 0)}, + {(712, 0), (714, 0), (706, 0), (707, 0), (709, 0)}, + {(716, 3), (705, 0)}, + {(715, 0), (704, 0)}, + {(738, 3), (737, 1)}, + {(731, 0), (740, 1)}, + {(764, 0), (764, 1)}, + {(773, 7), (773, 0)}, + {(770, 1), (774, 5)}, + {(771, 0), (771, 1)}, + {(781, 2), (781, 1)}, + {(815, 0), (810, 0), (851, 0), (884, 0), (820, 0), (869, 0)}, + {(884, 7), (881, 0), (884, 2)}, + {(835, 2), (806, 0), (822, 0)}, + {(878, 0), (885, 1), (886, 0)}, + {(879, 9), (808, 0), (845, 0), (896, 0), (865, 0), (879, 3), (896, 3)}, + {(825, 0), (862, 0)}, + {(863, 0), (887, 0)}, + {(876, 0), (854, 0)}, + {(900, 0), (901, 0)}, + {(913, 2), (913, 1)}, + {(935, 17), (938, 0)}, + {(938, 3), (933, 0)}, + {(919, 0), (938, 4)}, + {(930, 1), (934, 0), (922, 0)}, + {(932, 0), (916, 0), (917, 0)}, + {(922, 1), (930, 0)}, + {(938, 11), (933, 5)}, + {(935, 0), (937, 0), (915, 0), (924, 0), (935, 5)}, + {(943, 0), (953, 0), (958, 0)}, + {(960, 0), (962, 0)}, + {(1002, 0), (987, 0), (988, 0), (996, 1)}, + {(987, 5), (1004, 0), (994, 0)}, + {(976, 0), (989, 0)}, + {(993, 0), (997, 0)}, + {(983, 0), (998, 2)}, + {(979, 0), (1005, 3), (1002, 2)}, + {(1000, 0), (986, 0)}, + {(1023, 0), (1027, 2)}, + {(1039, 0), (1028, 0)}, + {(1051, 0), (1048, 5)}, + {(1078, 1), (1077, 3), (1082, 3)}, + {(1067, 0), (1068, 0)}, + {(1085, 0), (1082, 0), (1086, 0)}, + {(1090, 2), (1094, 4)}, + {(1090, 0), (1094, 0)}, + {(1121, 0), (1122, 0)}, + {(1123, 0), (1124, 0)}, + {(1148, 0), (1149, 0)}, + {(1183, 2), (1182, 0)}} + REPS = REPS/sort + + for S in REPS list (#S - # (S/(lab -> invariants4 Xs#lab)//unique)) + for S in REPS list {#S, # (S/(lab -> invariants4 Xs#lab)//unique)} + + #REPS == 118 -- this is the number of sets that we don't know yet how to separate + -- without use of GV's (which is heuristic). + + sort REPS#0 + X1 = Xs#(14,0) + X2 = Xs#(14,1) + invariants4 X1 + invariants4 X2 + F1 = cubicForm X1 + F2 = cubicForm X2 + sing = (F) -> trim saturate(F + ideal jacobian F) + decompose(sub(sing F1, RQ)) + sing F2 + +/// + +/// + -- 2 Jan 2023. + -- An attempt to automate the following: + -- 1. create one hash table with all of the Qs, Xs. + -- 2. separate the Xs via invariants4 (all the ones except point counts) + -- 3. for each invariant, use topology to separate. +-* + restart + debug needsPackage "StringTorics" +*- + + -- Example analysis of topologies for h11=4. + --topes = kreuzerSkarke(4, Limit => 10000); + --assert(#topes == 1197) + --h12s = topes/hodgeNumbers/last//unique//sort + h12s = {28, 34, 36, 37, 40, 42, 44, 46, 48, 49, 50, 52, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 76, 77, 78, 79, 80, 81, 82, 84, 85, 86, 88, + 89, 90, 91, 92, 93, 94, 96, 97, 98, 100, 101, 102, 104, 106, + 108, 109, 110, 112, 114, 116, 118, 120, 121, 122, 124, 126, + 128, 130, 136, 142, 144, 148, 154, 162, 166, 178, 190, 194, + 202, 208, 214, 226, 238} + + nontorsionfrees = {(0, 0), (3, 0), (4, 0), (5, 0), (12, 0), (15, 0), + (796, 0), (796, 1), (800, 0), (803, 0), (1059, 0), (1060, 0), (1064, 0), + (1065, 0), (1134, 0), (1135, 0), (1151, 0), (1153, 0), (1155, 0), (1155, 1)} + + db4name = (h12) -> "cys-ntfe-h11-4-h12-"|h12|".dbm" + RZ = ZZ[a,b,c,d]; + RQ = QQ (monoid RZ); + DB = hashTable for h in h12s list h => readCYDatabase("../m2-examples/"|db4name h, Ring => RZ); + Qs = new MutableHashTable + Xs = new MutableHashTable + for a in keys DB do ( + (Q1s, X1s) = DB#a; + for q in sort keys Q1s do Qs#q = Q1s#q; + for k in sort keys X1s do if not member(k, nontorsionfrees) then Xs#k = X1s#k; + ); + Xs = new HashTable from Xs; + Qs = new HashTable from Qs; + #(keys Xs) == 1994 -- 2014 total for all, including torsions. + assert(# sort keys Xs == 2014 - #nontorsionfrees) + + elapsedTime H = partition(invariants4, values Xs); -- 135 sec + H1 = hashTable for k in keys H list k => (H#k)/label; + elapsedTime INV = for k in sort keys H1 list k => partitionByTopology(H1#k, Xs, 15); -- 751 sec + -- number of different topologies + +----------------------------------- + -- new code: let's first see which ones are identical. + -- XXXX + # keys Xs == 1994 + Diff1 = partition(lab -> (X := Xs#lab; {c2Form X, cubicForm X}), sort keys Xs); + select(pairs Diff1, kv -> # kv#1 > 1) + + elapsedTime H = partition(lab -> ( + X := Xs#lab; + elapsedTime join({hh^(1,1) X, hh^(1,2) X}, invariantsAll Xs#lab) + ), sort keys Xs); -- 295 sec + #(keys H) == 1294 -- this leaves out h11, h12. + #(keys H) == 1300 -- this has h11, h12. Interesting. + + elapsedTime INV = for k in sort keys H list k => partitionByTopology(H#k, Xs, 15); -- 751 sec + -- number of different topologies: is at least 1300, at most XXX + + elapsedTime H4 = partition(lab -> elapsedTime invariants4 Xs#lab, sort keys Xs); + #(keys H4) == 1040 + + REPS = for k in INV list ( + H := last k; -- a hash table + K := keys H; + if #K == 1 then continue + else K) + + # select(INV, k -> #k#1 == 1) == 1248 + # select(INV, k -> #k#1 == 2) == 47 + # select(INV, k -> #k#1 == 3) == 5 + # select(INV, k -> #k#1 > 3) == 0 + + #REPS==52 + -- # different topologies is bounded above by 1248 + 2*47 + 3*5 == 1357 + -- bounded below by 1248 + 52 = 1300 + + REPS#0 + hashTable invariantsAll Xs#(254,5) + hashTable invariantsAll Xs#(228,1) + hashTable invariantsAll Xs#(REPS#2#0) +---------------------------------- + + + -- separate topologies: + -- output is a list of lists {S0, S1, S2, ..., Sr} + -- each CY in Si is not equivalent to any in Sj, i!=j. + -- each pair of CY's in a specific Si are not proved to be distinct (but are likely distinct?) + -- every CY in h11=4 database is knoqn to be equivalent to one of these + -- (Question: or are they all there in one of these lists?) + TOP1 = for k in INV list for a in keys last k list ( + prepend(a, ((last k)#a)/first) + ); + netList(TOP1/(a -> a/(a1->#a1))) + + REPS = for k in INV list ( + H := last k; -- a hash table + K := keys H; + if #K == 1 then continue + else K) + + ONEONLY = for k in INV list ( + H := last k; -- a hash table + K := keys H; + if #K == 1 then first K else continue) + + #INV == 1040 + #ONEONLY == 932 + #REPS = 108 + + netList REPS + REPS = { + {(14, 1), (14, 0)}, + {(53, 0), (38, 0)}, + {(35, 0), (39, 0)}, + {(30, 0), (38, 4)}, + {(80, 6), (80, 2)}, + {(96, 0), (126, 0)}, + {(135, 1), (138, 0)}, + {(180, 0), (179, 2)}, + {(265, 0), (250, 0), (265, 1), (236, 0), (228, 1)}, + {(235, 0), (262, 0)}, + {(225, 2), (260, 2)}, + {(265, 2), (235, 1)}, + {(265, 3), (228, 0)}, + {(250, 1), (254, 2)}, + {(249, 1), (246, 0)}, + {(210, 0), (258, 0)}, + {(209, 3), (284, 1), (261, 1)}, + {(240, 3), (278, 1)}, + {(319, 0), (313, 0)}, + {(316, 0), (322, 0)}, + {(334, 2), (328, 1), (329, 0)}, + {(331, 0), (337, 1), (339, 3)}, + {(334, 1), (329, 1)}, + {(339, 5), (337, 0)}, + {(385, 2), (385, 3)}, + {(364, 1), (377, 0)}, + {(356, 0), (395, 6)}, + {(379, 1), (395, 2), (378, 0)}, + {(383, 0), (356, 1)}, + {(397, 0), (350, 0)}, + {(387, 4), (387, 0)}, + {(377, 2), (364, 0)}, + {(416, 0), (441, 0), (438, 0)}, + {(400, 0), (403, 0), (405, 0), (414, 0)}, + {(436, 0), (433, 0)}, + {(419, 0), (419, 2)}, + {(436, 1), (433, 1)}, + {(451, 0), (455, 1)}, + {(473, 0), (478, 0)}, + {(458, 5), (458, 1)}, + {(458, 3), (458, 0)}, + {(508, 0), (514, 0)}, + {(512, 1), (505, 0)}, + {(507, 0), (519, 3)}, + {(526, 1), (527, 0), (518, 3), (522, 0)}, + {(524, 0), (518, 0)}, + {(529, 0), (510, 0)}, + {(550, 0), (538, 0)}, + {(556, 0), (562, 0)}, + {(553, 0), (554, 0)}, + {(552, 0), (551, 2)}, + {(559, 0), (577, 0)}, + {(540, 0), (545, 0)}, + {(588, 0), (586, 0)}, + {(616, 0), (606, 0)}, + {(650, 0), (650, 1), (667, 1), (650, 3), (656, 0), (666, 9), (630, 0)}, + {(643, 0), (649, 0), (626, 0)}, + {(628, 0), (653, 0)}, + {(647, 0), (669, 0)}, + {(688, 1), (685, 0)}, + {(687, 0), (684, 1)}, + {(693, 0), (694, 0)}, + {(712, 0), (714, 0), (706, 0), (707, 0), (709, 0)}, + {(716, 3), (705, 0)}, + {(715, 0), (704, 0)}, + {(738, 3), (737, 1)}, + {(731, 0), (740, 1)}, + {(773, 7), (773, 0)}, + {(770, 1), (774, 5)}, + {(771, 0), (771, 1)}, + {(781, 2), (781, 1)}, + {(815, 0), (810, 0), (851, 0), (884, 0), (820, 0), (869, 0)}, + {(884, 7), (881, 0), (884, 2)}, + {(835, 2), (806, 0), (822, 0)}, + {(878, 0), (885, 1), (886, 0)}, + {(879, 9), (808, 0), (845, 0), (896, 0), (865, 0), (879, 3), (896, 3)}, + {(825, 0), (862, 0)}, + {(863, 0), (887, 0)}, + {(876, 0), (854, 0)}, + {(900, 0), (901, 0)}, + {(935, 17), (938, 0)}, + {(938, 3), (933, 0)}, + {(930, 1), (934, 0), (922, 4)}, + {(932, 0), (916, 0), (917, 0)}, + {(922, 1), (930, 0)}, + {(938, 11), (933, 5)}, + {(935, 0), (937, 0), (915, 0), (924, 0), (935, 5)}, + {(943, 0), (953, 0), (958, 0)}, + {(960, 0), (962, 0)}, + {(987, 0), (988, 0), (1002, 0)}, + {(987, 5), (1004, 0), (994, 0)}, + {(976, 0), (989, 0)}, + {(993, 0), (997, 0)}, + {(983, 0), (998, 2)}, + {(979, 0), (1005, 3), (1002, 2)}, + {(1000, 0), (986, 0)}, + {(1023, 0), (1027, 2)}, + {(1039, 0), (1028, 0)}, + {(1051, 0), (1048, 5)}, + {(1078, 1), (1077, 3), (1082, 3)}, + {(1067, 0), (1068, 0)}, + {(1085, 0), (1082, 0), (1086, 0)}, + {(1090, 2), (1094, 4)}, + {(1090, 0), (1094, 0)}, + {(1121, 0), (1122, 0)}, + {(1123, 0), (1124, 0)}, + {(1148, 0), (1149, 0)}, + {(1183, 2), (1182, 0)}} + REPS = REPS/sort; + netList REPS + -- The ones in REPS are the ones we need to separate (if they are truly different!). + + sing = F -> trim(ideal F + ideal jacobian F) + toQQ = I -> sub(I, RQ) + + --- REPS#0 + LFs = for lab in REPS#0 list (X := Xs#lab; {toQQ c2Form X, toQQ cubicForm X}) + netList LFs + + F0 = LFs#0#1 + F1 = LFs#1#1 + for a in {-2,-2,-2,-2}..{2,2,2,2} list if sub(F0, matrix{a}) == 0 then a else continue + for a in {-2,-2,-2,-2}..{2,2,2,2} list if sub(F1, matrix{a}) == 0 then a else continue + saturate sing F0 + saturate sing F1 + factor(F0 - F1) + + findLinearMaps(List, List) := List => (LF1, LF2) -> ( + -- not complete... + (L1,F1) := toSequence LF1; + (L2,F2) := toSequence LF2; + RQ :=ring L1; + n := numgens RQ; + t := symbol t; + T := QQ[t_(1,1)..t_(n,n)]; + TR := T (monoid RQ); + M := genericMatrix(T, n, n); + phi := map(TR, TR, M) + ) + + phi = findLinearMaps(LFs#0, LFs#1) + T = target phi + TC = coefficientRing T + phi + + (L1,F1) = toSequence (LFs#0/(g -> sub(g, T))) + (L2,F2) = toSequence (LFs#1/(g -> sub(g, T))) + L1 = L1/2 + L2 = L2/2 + -- now we make the ideals for each key, and each permutation. + I1 = trim sub(ideal last coefficients (phi L1 - L2), TC) + I2 = trim sub(ideal last coefficients (phi F1 - F2), TC) + I = trim(I1 + I2); + Tp = ZZ/101[t_(1,1), t_(1,2), t_(1,3), t_(1,4), t_(2,1), t_(2,2), t_(2,3), t_(2,4), t_(3,1), t_(3,2), t_(3,3), t_(3,4), t_(4,1), t_(4,2), t_(4,3), t_(4,4)] + psi = map(Tp, TC, gens Tp) + J = psi I + gbTrace=3 + gens gb(J, DegreeLimit => 10); + ids := for k in keys gv1 list ( + perms := permutations(#gv1#k); + mat1 := transpose matrix gv1#k; + mat2 := transpose matrix gv2#k; + for p in perms list ( + I := trim ideal (M * mat1 - mat2_p); + if I == 1 then continue else I + ) + ); + topval := ids/(x -> #x - 1); + zeroval := ids/(x -> 0); + fullIdeals := for a in zeroval .. topval list ( + J := trim sum for i from 0 to #ids-1 list ids#i#(a#i); + if J == 1 then continue else J + ); + Ms := for i in fullIdeals list M % i; + --newMs := select(Ms, m -> (d := det m; d == 1 or d == -1)); + --if any(newMs, m -> support m =!= {}) then << "some M is not reduced to a constant" << endl; + Ms + ) + + hessian = (F) -> diff(vars ring F, diff(transpose vars ring F, F)) + + positions(REPS, x -> #x == 5) == {8, 62, 86} + + LFs = for lab in REPS#0 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) + netList for a in LFs list (betti res sing toQQ a#1) + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) + + LFs = for lab in REPS#1 list (X := Xs#lab; {c2Form X, cubicForm X}); + for a in LFs list (decompose sing toQQ a#1) + for a in LFs list (betti res sing toQQ a#1) -- different. + + LFs = for lab in REPS#2 list (X := Xs#lab; {c2Form X, cubicForm X}); + for a in LFs list (decompose sing toQQ a#1) + for a in LFs list (betti res sing toQQ a#1) + for a in LFs list (saturate sing2 ideal a) -- different + + LFs = for lab in REPS#3 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) + netList for a in LFs list (betti res sing toQQ a#1) + netList for a in LFs list (saturate sing2 ideal a) -- could be the same + netList for a in LFs list (factor det hessian toQQ a#1) -- contents of hessians are distinct, so I think these must be distinct. + + LFs = for lab in REPS#4 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) + netList for a in LFs list (betti res sing toQQ a#1) + netList for a in LFs list (saturate sing2 ideal a) + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same. + + LFs = for lab in REPS#5 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- different + netList for a in LFs list (betti res sing toQQ a#1) -- actually all 4 invariants are different! + netList for a in LFs list (saturate sing2 ideal a) + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#6 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) + netList for a in LFs list (factor det hessian toQQ a#1) -- seem to have different contents, so different... + + LFs = for lab in REPS#7 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#8 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,2,4 might be the same? 1,3 are diff. + + LFs = for lab in REPS#9 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#10 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- different + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#11 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#12 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- hessians have different content + + LFs = for lab in REPS#13 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same. + + LFs = for lab in REPS#14 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same. + + LFs = for lab in REPS#15 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- different content + + LFs = for lab in REPS#16 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- (0,2), 1 + netList for a in LFs list (betti res sing toQQ a#1) -- 0,1,2 all different + netList for a in LFs list (saturate sing2 ideal a) -- all different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#17 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different content + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#18 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same + + LFs = for lab in REPS#19 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same + + LFs = for lab in REPS#20 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- 0, (1,2) + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 1,2 could be same + + LFs = for lab in REPS#21 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1,2 could all be same + + LFs = for lab in REPS#22 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be the same + + LFs = for lab in REPS#23 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be the same + + LFs = for lab in REPS#24 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- different + + LFs = for lab in REPS#25 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same. + + LFs = for lab in REPS#26 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- different + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- different + + LFs = for lab in REPS#27 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- (0,1), 2 + netList for a in LFs list (saturate sing2 ideal a) -- all different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#28 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same (can check) + + LFs = for lab in REPS#29 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same + + LFs = for lab in REPS#30 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same + + LFs = for lab in REPS#31 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same + + LFs = for lab in REPS#32 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- (0,2), 1 + netList for a in LFs list (saturate sing2 ideal a) -- all different + netList for a in LFs list (factor det hessian toQQ a#1) -- all different + + LFs = for lab in REPS#33 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- (0,1,2), 3 + netList for a in LFs list (saturate sing2 ideal a) -- (0,1), 2, 3 + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be the same. + + LFs = for lab in REPS#34 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same. + + LFs = for lab in REPS#35 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same. + + LFs = for lab in REPS#36 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same. + + LFs = for lab in REPS#37 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same. + + LFs = for lab in REPS#38 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same. + + LFs = for lab in REPS#39 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- different + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- different + + LFs = for lab in REPS#40 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- different + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#41 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- different + netList for a in LFs list (betti res sing toQQ a#1) -- different + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#42 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- different + netList for a in LFs list (betti res sing toQQ a#1) -- different + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#43 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- different + netList for a in LFs list (betti res sing toQQ a#1) -- different + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#44 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- (0,1,2), 3 + netList for a in LFs list (saturate sing2 ideal a) -- all 4 different. + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#45 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- different contents + + LFs = for lab in REPS#46 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same + + LFs = for lab in REPS#47 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- different contents + + LFs = for lab in REPS#48 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- different contents + + LFs = for lab in REPS#49 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- different contents + + LFs = for lab in REPS#50 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same + + LFs = for lab in REPS#51 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same + + LFs = for lab in REPS#52 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same + + LFs = for lab in REPS#53 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- different contents + + LFs = for lab in REPS#54 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same + + LFs = for lab in REPS#55 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- (0,1,3,4), 2, (5,6) + netList for a in LFs list (betti res sing toQQ a#1) -- (0,3,4), 1, 2, 5, 6 + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,3,4 could be same + + LFs = for lab in REPS#56 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1,2 could all be same + + LFs = for lab in REPS#57 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could all be same + + LFs = for lab in REPS#58 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could all be same + + LFs = for lab in REPS#59 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#60 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- different + netList for a in LFs list (betti res sing toQQ a#1) --different + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#61 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#62 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- 0, (1,2,3,4) + netList for a in LFs list (factor det hessian toQQ a#1) -- (1,2,3,4) could be same + + LFs = for lab in REPS#63 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 could be same + + LFs = for lab in REPS#64 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- different contents + + LFs = for lab in REPS#65 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- different + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#66 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#67 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- different + netList for a in LFs list (betti res sing toQQ a#1) -- dofferent + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#68 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#69 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- different + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#70 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#71 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- (0,1,3), (2,5), 4 + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,1,3) could be same, (2,5) could be same. + + LFs = for lab in REPS#72 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- all 3 different + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- all different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#73 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- (0,2), 1 + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,2) could be same. + + LFs = for lab in REPS#74 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- all 3 different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#75 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- (0,4,6), (1,2,3), 5. + netList for a in LFs list (betti res sing toQQ a#1) -- (0,4,6), 5, (1,2), 3, 5. + netList for a in LFs list (saturate sing2 ideal a) -- (0,6) rest distinct. + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,6) possibly same + + LFs = for lab in REPS#76 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#77 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 possibly same. ACTUALLY: they are identical!! How did that get through? Totally different polytopes, exact same L, F... + + LFs = for lab in REPS#78 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 possibly same. + + LFs = for lab in REPS#79 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 possibly same. + + LFs = for lab in REPS#80 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- different + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#81 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 possibly same + + LFs = for lab in REPS#82 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- (0,1), 2 + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 possibly same + + LFs = for lab in REPS#83 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) --(0,2), 1 + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,2 possibly same + + LFs = for lab in REPS#84 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 possibly same + + LFs = for lab in REPS#85 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- 0,1 possibly same + + LFs = for lab in REPS#86 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- (0,3), (1,4), 2. + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,3) and (1,4) possibly same + + LFs = for lab in REPS#87 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- (0,2), 1 + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,2) possibly same + + LFs = for lab in REPS#88 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#89 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- all 3 different + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#90 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- 0, (1,2) + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- (1,2) could be same. + + LFs = for lab in REPS#91 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,1) could be same. + + LFs = for lab in REPS#92 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,1) could be same. + + LFs = for lab in REPS#93 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,1) could be same. + + LFs = for lab in REPS#94 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,1,2) could be same. + + LFs = for lab in REPS#95 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,1) could be same. + + LFs = for lab in REPS#96 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- different + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#97 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- different + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#98 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- different + netList for a in LFs list (factor det hessian toQQ a#1) -- + + LFs = for lab in REPS#99 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- (0,2), 1 + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,2) could be same. + + LFs = for lab in REPS#100 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,1) could be same. + + LFs = for lab in REPS#101 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,1,2) could be same. + + LFs = for lab in REPS#102 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,1) could be same. + + LFs = for lab in REPS#103 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,1) could be same. + + LFs = for lab in REPS#104 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,1) could be same. + + LFs = for lab in REPS#105 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,1) could be same. + + LFs = for lab in REPS#106 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,1) could be same. + + LFs = for lab in REPS#107 list (X := Xs#lab; {c2Form X, cubicForm X}); + netList for a in LFs list (decompose sing toQQ a#1) -- + netList for a in LFs list (betti res sing toQQ a#1) -- + netList for a in LFs list (saturate sing2 ideal a) -- + netList for a in LFs list (factor det hessian toQQ a#1) -- (0,1) could be same. + + + -- REP#8 + LFs = for lab in REPS#8 list (X := Xs#lab; {c2Form X, cubicForm X}) + F0 = LFs#0#1 + F1 = LFs#1#1 + F2 = LFs#2#1 + F3 = LFs#3#1 + F4 = LFs#4#1 + L0 = LFs#0#0 + L1 = LFs#1#0 + L2 = LFs#2#0 + L3 = LFs#3#0 + L4 = LFs#4#0 + + -- STEP 1 singular locus over QQ. All have 1 singular point over QQ. + decompose sing toQQ F0 + decompose sing toQQ F2 + decompose sing toQQ F4 + + decompose sing toQQ F1 -- different + + decompose sing toQQ F3 -- different + + betti res inverseSystem toQQ F0 + betti res inverseSystem toQQ F2 + betti res inverseSystem toQQ F4 + + sing2 = I -> trim(I + minors(2, jacobian I)) + s0 = saturate sing2 ideal LFs#0 + s1 = saturate sing2 ideal LFs#2 + s2 = saturate sing2 ideal LFs#4 + + factor det hessian toQQ F0 + factor det hessian toQQ F2 + factor det hessian toQQ F4 + + -- promising: each of these have 5 ppints. + decompose minors(3, hessian toQQ F0) + decompose minors(3, hessian toQQ F2) + decompose minors(3, hessian toQQ F4) + + ---------------------------------------------------- + -- NOT DONE YET + positions(REPS, x -> #x == 6) == {71} + LFs = for lab in REPS#71 list (X := Xs#lab; {c2Form X, cubicForm X}) + F0 = LFs#0#1 + F1 = LFs#1#1 + F2 = LFs#2#1 + F3 = LFs#3#1 + F4 = LFs#4#1 + F5 = LFs#5#1 + L0 = LFs#0#0 + L1 = LFs#1#0 + L2 = LFs#2#0 + L3 = LFs#3#0 + L4 = LFs#4#0 + L5 = LFs#5#0 + + -- STEP 1 singular locus over QQ. All have 1 singular point over QQ. + decompose sing toQQ F0 + decompose sing toQQ F1 + decompose sing toQQ F2 + decompose sing toQQ F3 + decompose sing toQQ F4 + decompose sing toQQ F5 + + -- (F0,F1,F2,F3,F4,F5) doesn't separate them at all. + -- STEP 2: inverse systems + betti res inverseSystem toQQ F0 + betti res inverseSystem toQQ F1 + betti res inverseSystem toQQ F2 + betti res inverseSystem toQQ F3 + betti res inverseSystem toQQ F4 + betti res inverseSystem toQQ F5 + + -- all the same still! + + -- STEP 3. jacobian over ZZ + sing2 = I -> trim(I + minors(2, jacobian I)) + s0 = saturate sing2 ideal LFs#0 + s1 = saturate sing2 ideal LFs#1 + s2 = saturate sing2 ideal LFs#2 + s3 = saturate sing2 ideal LFs#3 + s4 = saturate sing2 ideal LFs#4 + s5 = saturate sing2 ideal LFs#5 + + s0_0, s1_0, s3_0 + s2_0, s5_0 + s4_0 + -- (F0,F1,F3), (F2,F5), F4. + -- NOT DONE: the stuff below this doesn't yet separate these 3. + + Rp = ZZ/467[a,b,c,d] + saturate sub(sing2 ideal LFs#2, Rp) + saturate sub(sing2 ideal LFs#5, Rp) + + factor det hessian toQQ F0 + factor det hessian toQQ F1 + factor det hessian toQQ F3 + + factor det hessian toQQ F2 + factor det hessian toQQ F5 + + factor det hessian toQQ F4 + + -- TODO: still need to separate both of these groups. + decompose minors(2, hessian toQQ F0) + decompose minors(2, hessian toQQ F1) + decompose minors(2, hessian toQQ F3) + + decompose minors(2, hessian toQQ F2) + decompose minors(2, hessian toQQ F5) + s0 = gens gb saturate sing F0 + s1 = gens gb saturate sing F1 + s1 = saturate sing2 ideal LFs#1 + s2 = saturate sing2 ideal LFs#2 + s3 = saturate sing2 ideal LFs#3 + s4 = saturate sing2 ideal LFs#4 + s5 = saturate sing2 ideal LFs#5 + + --------------------------------------------- + -- REPS#55 + positions(REPS, x -> #x == 7) == {55, 75} + LFs = for lab in REPS#55 list (X := Xs#lab; {c2Form X, cubicForm X}) + F0 = LFs#0#1 + F1 = LFs#1#1 + F2 = LFs#2#1 + F3 = LFs#3#1 + F4 = LFs#4#1 + F5 = LFs#5#1 + F6 = LFs#6#1 + L0 = LFs#0#1 + L1 = LFs#1#0 + L2 = LFs#2#0 + L3 = LFs#3#0 + L4 = LFs#4#0 + L5 = LFs#5#0 + L6 = LFs#6#0 + + -- STEP 1 singular locus over QQ + decompose sing toQQ F0 + decompose sing toQQ F1 + decompose sing toQQ F3 + decompose sing toQQ F4 + + decompose sing toQQ F2 + + decompose sing toQQ F5 -- 2 pts, irred over QQ + decompose sing toQQ F6 + -- (F0,F1,F3,F4), F2, (F5,F6) + + -- STEP 2 inverse system + betti res inverseSystem toQQ F0 + betti res inverseSystem toQQ F1 -- distinct from F0,F3,F4. + betti res inverseSystem toQQ F3 + betti res inverseSystem toQQ F4 + + betti res inverseSystem toQQ F2 + + betti res inverseSystem toQQ F5 + betti res inverseSystem toQQ F6 -- F6 distinct from F5. + -- (F0,F3,F4), F1, F2, F5, F6. + + -- STEP 3. jacobian over ZZ + sing2 = I -> trim(I + minors(2, jacobian I)) + s0 = saturate sing2 ideal LFs#0 + s3 = saturate sing2 ideal LFs#3 + s4 = saturate sing2 ideal LFs#4 + + s5 = saturate sing2 ideal LFs#5 + + s6 = saturate sing2 ideal LFs#6 + + s1 = saturate sing2 ideal LFs#1 -- different from F0 + + s2 = saturate sing2 ideal LFs#2 + + s0_0, s3_0, s4_0, s1_0, s2_0, s5_0, s6_0 + -- (F0,F3,F4), F1, F2, F5, F6. Same as step 1+2. + + -- STEP 4. Separate F0, F3, F4 + factor det hessian toQQ F0 + factor det hessian toQQ F3 + factor det hessian toQQ F4 -- all similar structure... + + -- first compare F0, F3: F0, F3 are equiv over QQ, not ZZ. + (A, phi) = genericLinearMap RQ + use target phi + start1 = {{b+3*c, a+d}, + {3*c+2*d, a}, + {a+2*c, a+b-c+d}} + start2 = {{b+3*c, a+d}, + {3*c+2*d, a+b-c+d}, + {a+2*c, a}} + signs = (toList((set{-1,1}) ** set{-1,1} ** set{-1,1}))/splice/toList -- note: not all these signs are needed... + chsigns = (L, sgn) -> for i from 0 to #L-1 list {L#i#0, sgn#i * L#i#1} + set1 = for sgn in signs list chsigns(start1, sgn) + set2 = for sgn in signs list chsigns(start2, sgn) + allsets = join(set1, set2) + netList for L in allsets list ( + (A0, phi0) = linearEquationConstraints(A, phi, append(L, {sub(F0, target phi), sub(F3, target phi)}), {}); + if A0 == 0 then continue; + phi1 = map(RQ, RQ, transpose sub(A0, QQ)); + {A0, det A0, phi1 toQQ(LFs#0#0) - toQQ LFs#3#0, phi1 toQQ LFs#0#1 - toQQ LFs#3#1} + ) + + -- second compare F0, F4: -- to see yet: F0, F4 are equiv over ZZ, but X0, X4 are equiv over QQ. + (A, phi) = genericLinearMap RQ + use target phi + factor det hessian toQQ F0 + factor det hessian toQQ F4 + start1 = {{b+3*c, c+d}, + {3*c+2*d, d}, + {a+2*c, a-b-c}} + start2 = {{b+3*c, c+d}, + {3*c+2*d, a-b-c}, + {a+2*c, d}} + signs = (toList((set{-1,1}) ** set{-1,1} ** set{-1,1}))/splice/toList -- note: not all these signs are needed... + chsigns = (L, sgn) -> for i from 0 to #L-1 list {L#i#0, sgn#i * L#i#1} + set1 = for sgn in signs list chsigns(start1, sgn) + set2 = for sgn in signs list chsigns(start2, sgn) + allsets = join(set1, set2) + netList for L in allsets list ( + (A0, phi0) = linearEquationConstraints(A, phi, append(L, {sub(F0, target phi), sub(F4, target phi)}), {}); + if A0 == 0 then continue; + phi1 = map(RQ, RQ, transpose sub(A0, QQ)); + {A0, det A0, phi1 toQQ(LFs#0#0) - toQQ LFs#4#0, phi1 toQQ LFs#0#1 - toQQ LFs#4#1} + ) + + -- second compare F0 to F3 -- only equiv over QQ. + (A, phi) = genericLinearMap RQ + use target phi + factor det hessian toQQ F3 + factor det hessian toQQ F4 + start1 = {{a+d, c+d}, + {a, d}, + {a+b-c+d, a-b-c}} + start2 = {{a+d, c+d}, + {a, a-b-c}, + {a+b-c+d, d}} + signs = (toList((set{-1,1}) ** set{-1,1} ** set{-1,1}))/splice/toList -- note: not all these signs are needed... + chsigns = (L, sgn) -> for i from 0 to #L-1 list {L#i#0, sgn#i * L#i#1} + set1 = for sgn in signs list chsigns(start1, sgn) + set2 = for sgn in signs list chsigns(start2, sgn) + allsets = join(set1, set2) + netList for L in allsets list ( + (A0, phi0) = linearEquationConstraints(A, phi, append(L, {sub(F3, target phi), sub(F4, target phi)}), {}); + if A0 == 0 then continue; + phi1 = map(RQ, RQ, transpose sub(A0, QQ)); + {A0, det A0, phi1 toQQ(LFs#3#0) - toQQ LFs#4#0, phi1 toQQ LFs#3#1 - toQQ LFs#4#1} + ) + + -- Upshot: these 7 are all distinct. + + -- REPS#75 + positions(REPS, x -> #x == 7) == {55, 75} + LFs = for lab in REPS#75 list (X := Xs#lab; {toQQ c2Form X, toQQ cubicForm X}) + F1 = LFs#0#1 + F2 = LFs#1#1 + F3 = LFs#2#1 + F4 = LFs#3#1 + F5 = LFs#4#1 + F6 = LFs#5#1 + F7 = LFs#6#1 + + LFZs = for lab in REPS#75 list (X := Xs#lab; {c2Form X, cubicForm X}) + FZ1 = LFZs#0#1 + FZ2 = LFZs#1#1 + FZ3 = LFZs#2#1 + FZ4 = LFZs#3#1 + FZ5 = LFZs#4#1 + FZ6 = LFZs#5#1 + FZ7 = LFZs#6#1 + + -- STEP 1: consider singular loci over QQ. + -- one singular point + decompose sing F1 + decompose sing F5 + decompose sing F7 + -- two singular points + decompose sing F4 + decompose sing F2 + decompose sing F3 + -- three singular points + decompose sing F6 + -- at this point: (F1,F5,F7), (F2,F3,F4), F6. ones in parens might be equivalent. + + -- STEP 2: inverse systems (over QQ) + betti res inverseSystem F1 + betti res inverseSystem F5 + betti res inverseSystem F7 + + betti res inverseSystem F4 -- F4 on its own + + betti res inverseSystem F2 + betti res inverseSystem F3 -- F2, F3 have different singular loci mod 19. + + betti res inverseSystem F6 -- F6 + -- at this point: (F1,F5,F7), F4, (F2,F3), F6. ones in parens might be equivalent. + + -- STEP 3: singular locus of (L,F) over ZZ + sing2 = I -> trim(I + minors(2, jacobian I)) + s1 = saturate sing2 ideal LFZs#0 + s5 = saturate sing2 ideal LFZs#4 -- this shows that F5 is different from (F1, F7). + s7 = saturate sing2 ideal LFZs#6 + + s4 = saturate sing2 ideal LFZs#3 + s2 = saturate sing2 ideal LFZs#1 + s3 = saturate sing2 ideal LFZs#2 -- this shows that F2 is different from F3. + -- (it also show separately that F4 is distinct from F2 and F3). + -- at this point: (F1,F7), F5, F4, F2, F3, F6. + + -- STEP 4: separate F1, F7. This one is a bit tricky, as in fact F1 and F7 are equivalent over ZZ! + -- But they are not equivalent when the c2 form is taken into account. + -- For this one, we compute the Hessian of F1, F7. + factor det hessian F1 -- (b+2*d)*(b+3*d)^2*(a+b+2*d)*(-20736) + factor det hessian F7 -- (a-d)*(a+c)^2*(a-b)*(-20736) + -- this shows that we seek a matrix over ZZ (or QQ, if we are interested) + -- with b+3d --> \pm (a+c) + -- with b+2d --> \pm (a-d) OR \pm (a-b) + -- with a+b+2d --> \pm (a-d) OR \pm (a-b) [but for the other linear form]. + -- note: this fixes phi(a), phi(b), phi(d), leaving phi(c) not known. + -- and F1 is linear in c. + -- all the choices: + (A, phi) = genericLinearMap RQ + use target phi + start1 = {{b+3*d, a+c}, {b+2*d, a-d}, {a+b+2*d, a-b}} + start2 = {{b+3*d, a+c}, {b+2*d, a-b}, {a+b+2*d, a-d}} + signs = (toList((set{-1,1}) ** set{-1,1} ** set{-1,1}))/splice/toList -- note: not all these signs are needed... + chsigns = (L, sgn) -> for i from 0 to #L-1 list {L#i#0, sgn#i * L#i#1} + set1 = for sgn in signs list chsigns(start1, sgn) + set2 = for sgn in signs list chsigns(start2, sgn) + allsets = join(set1, set2) + netList for L in allsets list ( + (A0, phi0) = linearEquationConstraints(A, phi, append(L, {sub(F1, target phi), sub(F7, target phi)}), {}); + if A0 == 0 then continue; + phi1 = map(RQ, RQ, transpose sub(A0, QQ)); + {A0, det A0, phi1 (LFs#0#0) - LFs#6#0, phi1 (LFs#0#1) - LFs#6#1} + ) + -- this shows that F1, F7 are in fact equivalent over ZZ, but X1, X7 are distinct topologically. + -- it also shows there is a matrix over QQ, with det 1, which does map L1 to L7, F1 to F7. +/// + +/// + -- Example use of a constructed data base. + restart + debug needsPackage "StringTorics" + RZ = ZZ[a,b,c] + F = openDatabase "../m2-examples/foo-h11-3.dbm" -- note: + Xlabels = sort select(keys F, k -> (a := value k; instance(a, Sequence))) + Qlabels = sort select(keys F, k -> (a := value k; instance(a, ZZ))) + assert(#Xlabels == 526) + assert(#Qlabels == 244) + elapsedTime Qs = for k in Qlabels list cyPolytope(F#k, ID => value k); + elapsedTime Xs = for k in Xlabels list cyData(F#k, i -> Qs#i, Ring => RZ); + assert(Xs/label === Xlabels/value) + close F + + Xs = hashTable for x in Xs list (label x) => x; + + -- these are the ones we will consider. + torsionfrees = for lab in sort keys Xs list ( + X := Xs#lab; + V := normalToricVariety(rays X, max X); + if classGroup V === ZZ^3 then lab else continue + ) + + -- 6 polytopes are not torsion free (i.e. classGroup is not torsion free) + nontorsionfrees = for lab in sort keys Xs list ( + X := Xs#lab; + V := normalToricVariety(rays X, max X); + if classGroup V != ZZ^3 then lab else continue + ) + nontorsionfrees == {(0, 0), (9, 0), (9, 1), (10, 0), (10, 1), (10, 2), (55, 0), (62, 0), (232, 0)} + + nonFavorables = select(sort keys Xs, lab -> not isFavorable cyPolytope Xs#lab) + favorables = select(sort keys Xs, lab -> isFavorable cyPolytope Xs#lab) + + elapsedTime H = partition(lab -> ( + X := Xs#lab; + elapsedTime netList join({"h11" => hh^(1,1) X, "h12" => hh^(1,2) X}, invariantsAll Xs#lab) + ), sort torsionfrees); -- 18 sec + #(keys H) == 195 + H + + + elapsedTime INV = for k in sort keys H list k => partitionByTopology(H#k, Xs, 15); --34 sec + + REPS = for k in INV list ( + H := last k; -- a hash table + K := keys H; + if #K == 1 then continue + else k#0 => K) + #REPS == 9 + + positions(INV, k -> #(keys (k#1)) > 1) + netList INV_{26, 56, 63, 64, 76, 120, 121, 156, 182} + REPS = for k in INV list ( + H := last k; -- a hash table + K := keys H; + if #K == 1 then continue + else K) + + X1 = Xs#(34,0) + X2 = Xs#(37,0) + L1 = c2Form X1 + L2 = c2Form X2 + F1 = cubicForm X1 + F2 = cubicForm X2 + + hashTable invariantsAll X1, hashTable invariantsAll X2 + + + + -- XXXX + elapsedTime H1 = partition(lab -> topologicalData Xs#lab, torsionfrees); -- take one from each. + netList (values H1) + SAME = hashTable for k in keys H1 list (first H1#k) => drop(H1#k, 1) + + labelYs = sort keys SAME -- these have non-equal topological data + #labelYs == 286 -- if torsionfrees is used + #labelYs == 291 -- all are equivalent to one of these, so there are 291 possible different topologies + -- (but probably less than this). + + --elapsedTime INV = partition(lab -> invariants Xs#lab, labelYs); -- 98 sec (FIXME: about 200 seconds now, with slow pointCount code) + elapsedTime INV = partition(lab -> invariants2 Xs#lab, labelYs); -- 6 seconds + + #INV == 165 -- torsionfrees, invariants2. + -- #INV == 168 -- for both invariants, invariants2 + + -- This selects the different topologies, except it can't tell about (52,0), (53,0). + (keys INV)/(x -> #INV#x)//tally + + RESULT1 = hashTable for k in sort keys INV list ( + labs := INV#k; + k => partitionByTopology(labs, Xs, 15) + ) + + labs = INV#{3, 99, 0, 2, 1, 1, 1, 1} + gvInvariants(Xs#(labs#0), DegreeLimit => 15) + gvCone(Xs#(labs#0), DegreeLimit => 15) + + TODO = select(keys RESULT1, k -> #(keys RESULT1#k) > 1) + DONE = select(keys RESULT1, k -> #(keys RESULT1#k) == 1) + hashTable for k in DONE list k => RESULT1#k + TODO = hashTable for k in TODO list k => RESULT1#k + + -- try comparing (26,0), (37,0) + partitionByTopology({(26,0), (37,0)}, Xs, 25) + partitionGVConeByGV(Xs#(26,0), DegreeLimit => 20) + partitionGVConeByGV(Xs#(37,0), DegreeLimit => 20) -- this makes them appear distinct. + F26 = cubicForm Xs#(26,0) + F37 = cubicForm Xs#(37,0) + L26 = c2Form Xs#(26,0) + L37 = c2Form Xs#(37,0) + + RQ = QQ[a,b,c] + F1 = sub(F26, RQ) + L1 = sub(L26, RQ) + F2 = sub(F37, RQ) + L2 = sub(L37, RQ) + decompose ideal(F1, L1) + decompose ideal(F2, L2) + + mons3 = basis(3, RQ) + coeffsF1 = flatten entries last coefficients(F1, Monomials => mons3) + coeffsF2 = flatten entries last coefficients(F2, Monomials => mons3) + needsPackage "EllipticCurves" + toWeierstrass(RingElement, List) := (F, pt) -> ( + R := ring F; + kk := coefficientRing R; + if numgens R =!= 3 or #pt != 3 then error "expected ring in 3 variables and point in 3-space"; + mons3 := basis(3, R); + coeffsF := flatten entries last coefficients(F, Monomials => mons3); + toWeierstrass(coeffsF, pt, kk) + ) + jInvariant toWeierstrass(F1, {2, 3, -4}) + jInvariant toWeierstrass(F2, {1, 1, -1}) + + TOANALYZE = for k in sort keys RESULT1 list ( + if #RESULT1#k == 1 then continue; + k => (FINISH ME !!!!!!!!!!!!!!!!!!!!!!!! + + select(sort keys RESULT1, k -> #(keys RESULT1#k) > 1) + + tally for k in keys RESULT1 list #RESULT1#k -- all 1's, meaning that in each case, all elements of + -- INV#k are equivalent. + + ALLTOPS = (keys RESULT1)/(k -> ( + for x in keys RESULT1#k list x => join(RESULT1#k#x, SAME#x) + ))//flatten//hashTable + +/// + +---------------------------------------------------------- +-- Newer version of last example ------------------------- +---------------------------------------------------------- + + +/// + -- Example use of a constructed data base. + restart + debug needsPackage "StringTorics" + RZ = ZZ[a,b,c] + F = openDatabase "../m2-examples/foo-ntfe-h11-3.dbm" -- note: + Xlabels = sort select(keys F, k -> (a := value k; instance(a, Sequence))) + Qlabels = sort select(keys F, k -> (a := value k; instance(a, ZZ))) + assert(#Xlabels == 306) + assert(#Qlabels == 244) + elapsedTime Qs = for k in Qlabels list cyPolytope(F#k, ID => value k); + elapsedTime Xs = for k in Xlabels list cyData(F#k, i -> Qs#i, Ring => RZ); + assert(Xs/label === Xlabels/value) + close F + + Xs = hashTable for x in Xs list (label x) => x; + + -- these are the ones we will consider. + torsionfrees = for lab in sort keys Xs list ( + X := Xs#lab; + V := normalToricVariety(rays X, max X); + if classGroup V === ZZ^3 then lab else continue + ) + + -- 6 polytopes are not torsion free (i.e. classGroup is not torsion free) + nontorsionfrees = for lab in sort keys Xs list ( + X := Xs#lab; + V := normalToricVariety(rays X, max X); + if classGroup V != ZZ^3 then lab else continue + ) + nontorsionfrees == {(0, 0), (9, 0), (10, 0), (55, 0), (62, 0), (232, 0)} + + nonFavorables = select(sort keys Xs, lab -> not isFavorable cyPolytope Xs#lab) + favorables = select(sort keys Xs, lab -> isFavorable cyPolytope Xs#lab) + + -- XXXX + elapsedTime H1 = partition(lab -> topologicalData Xs#lab, torsionfrees); -- take one from each. + netList (values H1) + SAME = hashTable for k in keys H1 list (first H1#k) => drop(H1#k, 1) + + labelYs = sort keys SAME -- these have non-equal topological data + #labelYs == 286 -- if torsionfrees is used + #labelYs == 291 -- all are equivalent to one of these, so there are 291 possible different topologies + -- (but probably less than this). + + --elapsedTime INV = partition(lab -> invariants Xs#lab, labelYs); -- 98 sec (FIXME: about 200 seconds now, with slow pointCount code) + elapsedTime INV = partition(lab -> invariants2 Xs#lab, labelYs); -- 6 seconds + + #INV == 165 -- torsionfrees, invariants2. + -- #INV == 168 -- for both invariants, invariants2 + + -- This selects the different topologies, except it can't tell about (52,0), (53,0). + (keys INV)/(x -> #INV#x)//tally + + RESULT1 = hashTable for k in sort keys INV list ( + labs := INV#k; + k => partitionByTopology(labs, Xs, 15) + ) + + labs = INV#{3, 99, 0, 2, 1, 1, 1, 1} + gvInvariants(Xs#(labs#0), DegreeLimit => 15) + gvCone(Xs#(labs#0), DegreeLimit => 15) + + TODO = select(keys RESULT1, k -> #(keys RESULT1#k) > 1) + DONE = select(keys RESULT1, k -> #(keys RESULT1#k) == 1) + hashTable for k in DONE list k => RESULT1#k + TODO = hashTable for k in TODO list k => RESULT1#k + + -- try comparing (26,0), (37,0) + partitionByTopology({(26,0), (37,0)}, Xs, 25) + partitionGVConeByGV(Xs#(26,0), DegreeLimit => 20) + partitionGVConeByGV(Xs#(37,0), DegreeLimit => 20) -- this makes them appear distinct. + F26 = cubicForm Xs#(26,0) + F37 = cubicForm Xs#(37,0) + L26 = c2Form Xs#(26,0) + L37 = c2Form Xs#(37,0) + + RQ = QQ[a,b,c] + F1 = sub(F26, RQ) + L1 = sub(L26, RQ) + F2 = sub(F37, RQ) + L2 = sub(L37, RQ) + decompose ideal(F1, L1) + decompose ideal(F2, L2) + + mons3 = basis(3, RQ) + coeffsF1 = flatten entries last coefficients(F1, Monomials => mons3) + coeffsF2 = flatten entries last coefficients(F2, Monomials => mons3) + needsPackage "EllipticCurves" + toWeierstrass(RingElement, List) := (F, pt) -> ( + R := ring F; + kk := coefficientRing R; + if numgens R =!= 3 or #pt != 3 then error "expected ring in 3 variables and point in 3-space"; + mons3 := basis(3, R); + coeffsF := flatten entries last coefficients(F, Monomials => mons3); + toWeierstrass(coeffsF, pt, kk) + ) + jInvariant toWeierstrass(F1, {2, 3, -4}) + jInvariant toWeierstrass(F2, {1, 1, -1}) + + TOANALYZE = for k in sort keys RESULT1 list ( + if #RESULT1#k == 1 then continue; + k => (FINISH ME !!!!!!!!!!!!!!!!!!!!!!!! + + select(sort keys RESULT1, k -> #(keys RESULT1#k) > 1) + + tally for k in keys RESULT1 list #RESULT1#k -- all 1's, meaning that in each case, all elements of + -- INV#k are equivalent. + + ALLTOPS = (keys RESULT1)/(k -> ( + for x in keys RESULT1#k list x => join(RESULT1#k#x, SAME#x) + ))//flatten//hashTable + +/// diff --git a/CYToolsM2/StringTorics/other/FindEquivalence.m2 b/CYToolsM2/StringTorics/other/FindEquivalence.m2 new file mode 100644 index 0000000..7f51016 --- /dev/null +++ b/CYToolsM2/StringTorics/other/FindEquivalence.m2 @@ -0,0 +1,1173 @@ +------------------------------------------------------- +-- OLD: replaced with IntegerEquivalences package ----- +-- TO BE REMOVED, do not use -------------------------- +------------------------------------------------------- +debug needsPackage "StringTorics" +-- routine to take saturation of singF, and its components, to their images + +-- TODO: add in A as an argument, allow column matrices as well. +-- Then this can be used with findMaps from gv invariants too. +equivalenceIdeal = method() +equivalenceIdeal(List, List, RingMap) := Ideal => (List1, List2, phi) -> ( + TR := target phi; -- TODO: check: this is also source phi. + if #List1 == 0 then return ideal(0_TR); + RQ := ring List1_0; + B := coefficientRing TR; + toTR := map(TR, RQ, vars TR); + toB := map(B, TR); + List1 = List1/(I -> if ring I =!= RQ then toTR (sub(I, RQ)) else toTR I); + List2 = List2/(I -> if ring I =!= RQ then toTR (sub(I, RQ)) else toTR I); + -- List1 and List2 are lists with the same length, consisting of RingElement's and Ideal's. + -- List1 and List2 should each have RingElement's and Ideal's in the same spot. + ids := for i from 0 to #List1-1 list ( + if instance(List1#i, RingElement) then ( + if not instance(List2#i, RingElement) then + error "expected both lists to consist of Ideal's and RingElement's in the same spots"; + ideal toB (last coefficients(phi List1#i - List2#i)) + ) else if instance(List1#i, Ideal) then ( + if not instance(List2#i, Ideal) then + error "expected both lists to consist of Ideal's and RingElement's in the same spots"; + ideal toB (last coefficients((gens phi List1#i) % List2#i)) + ) + ); + sum ids + ) + +equivalenceIdealMain = method() +equivalenceIdealMain(Thing, Thing, HashTable, Sequence) := Ideal => (lab1, lab2, Xs, Aphi) -> ( + X1 := Xs#lab1; + X2 := Xs#lab2; + (L1, F1) := (c2Form X1, cubicForm X1); + (L2, F2) := (c2Form X2, cubicForm X2); + (A,phi) := Aphi; + equivalenceIdeal({L1, F1}, {L2, F2}, phi) + ) + +factorsByType = method() +factorsByType RingElement := HashTable => F -> ( + facs := factors F; + faclist := for fx in facs list (fx#0, sum first exponents fx#1, fx#1); + H := partition(x -> {x#0, x#1}, faclist); + hashTable for k in keys H list k => for x in H#k list x_2 + ) + +-- TODO: make V2 +idealsByBetti = method() +idealsByBetti(List, List) := List => (J1s, J2s) -> ( + H1 := partition(J -> betti gens J, J1s); + H2 := partition(J -> betti gens J, J2s); + if sort keys H1 =!= sort keys H2 then return {}; + list1 := flatten for k in sort keys H1 list H1#k; + list2perms := cartesian for k in sort keys H2 list permutations H2#k; + (list1, list2perms) + ) + +idealsByBettiV2 = method() +idealsByBettiV2(List, List) := List => (J1s, J2s) -> ( + H1 := partition(J -> betti gens J, J1s); + H2 := partition(J -> betti gens J, J2s); + if sort keys H1 =!= sort keys H2 then return {}; + for k in sort keys H1 list ( + H1#k => permutations H2#k + )) + +-- TODO: this takes too much time, it seems. If there are 4 factors, it creates 384 things to compute. +-- each is easy, but they add up. +hessianMatches = method() +hessianMatches(Thing, Thing, HashTable, Sequence) := List => (lab1, lab2, Xs, Aphi) -> ( + (A,phi) := Aphi; + X1 := Xs#lab1; + X2 := Xs#lab2; + (L1, F1) := (c2Form X1, cubicForm X1); + (L2, F2) := (c2Form X2, cubicForm X2); + fac1 := factorsByType(det hessian F1); + fac2 := factorsByType(det hessian F2); + keyset1 := sort for k in sort keys fac1 list if k === {1,0} then (cH1 = fac1#k; continue) else k; + keyset2 := sort for k in sort keys fac2 list if k === {1,0} then (cH2 = fac2#k; continue) else k; + if keyset1 === {{1,4}} then return "Do not use Hessian method on irreducible polynomials of degree > 4"; + if keyset1 =!= keyset2 then error "expected same factors and their degrees"; + list1 := flatten for k in keyset1 list fac1#k; + list2 := for k in keyset2 list fac2#k; + list2perms := cartesian for fs in list2 list signedPermutations fs; + (list1, list2perms) + ) + +singularLocusMatches = method() +singularLocusMatches(Thing, Thing, HashTable, Sequence) := List => (lab1, lab2, Xs, Aphi) -> ( + (A,phi) := Aphi; + X1 := Xs#lab1; + X2 := Xs#lab2; + (L1, F1) := (c2Form X1, cubicForm X1); + (L2, F2) := (c2Form X2, cubicForm X2); + RQ := QQ (monoid ring L1); + FQ1 = sub(F1, RQ); + FQ2 = sub(F2, RQ); + sing1 := trim saturate(ideal FQ1 + ideal jacobian FQ1); + sing2 := trim saturate(ideal FQ2 + ideal jacobian FQ2); + if sing1 == 1 then return {}; + comps1 := (decompose sing1)/trim; + comps2 := (decompose sing2)/trim; + (list1, list2perms) := idealsByBetti(comps1, comps2); + (join({L1, F1, sing1}, list1), cartesian{{{L2, F2, sing2}}, list2perms}) + ) + +checkFormatV2 = method() +-- TODO: format has changed. Fix this function! +checkFormatV2(List, List) := (list1, list2perms) -> ( + -- TODO: list1 can be a single Ideal or RingElement or list of... + -- TODO: + n := #list1; + list1Type := for a in list1 list ( + if instance(a, RingElement) then RingElement + else if instance(a, Ideal) then Ideal); + for list2a in list2perms do ( + assert(#list2 == n); + list2Type := for a in list2a list ( + if instance(a, RingElement) then RingElement + else if instance(a, Ideal) then Ideal); + assert(list1Type === list2Type); + ); + ) +hessianMatchesV2 = method() +hessianMatchesV2(Thing, Thing, HashTable, Sequence) := List => (lab1, lab2, Xs, Aphi) -> ( + -- XXXX WORK ON THIS + (A,phi) := Aphi; + X1 := Xs#lab1; + X2 := Xs#lab2; + (L1, F1) := (c2Form X1, cubicForm X1); + (L2, F2) := (c2Form X2, cubicForm X2); + fac1 := factorsByType(det hessian F1); + fac2 := factorsByType(det hessian F2); + keyset1 := sort for k in sort keys fac1 list if k === {1,0} then (cH1 = fac1#k; continue) else k; + keyset2 := sort for k in sort keys fac2 list if k === {1,0} then (cH2 = fac2#k; continue) else k; + if keyset1 =!= keyset2 then error "expected same factors and their degrees"; + ans := for k in keyset1 list + fac1#k => signedPermutations fac2#k; + --checkFormatV2 ans; -- not functional yet? Check that... + ans + ) + +singularLocusMatchesV2 = method() +singularLocusMatchesV2(Thing, Thing, HashTable, Sequence) := List => (lab1, lab2, Xs, Aphi) -> ( + -- XXXX WORK ON THIS + -- returns a list of pairs: + -- L1 => {L2a, L2b, ...} + -- where L1 and each L2i have the same length, + -- and every element is a RingElement, or an ideal + -- possible todo: allow a point in H^2 as well. + (A,phi) := Aphi; + X1 := Xs#lab1; + X2 := Xs#lab2; + (L1, F1) := (c2Form X1, cubicForm X1); + (L2, F2) := (c2Form X2, cubicForm X2); + RQ := QQ (monoid ring L1); + FQ1 = sub(F1, RQ); + FQ2 = sub(F2, RQ); + sing1 := trim saturate(ideal FQ1 + ideal jacobian FQ1); + sing2 := trim saturate(ideal FQ2 + ideal jacobian FQ2); + if sing1 == 1 then return {}; + comps1 := (decompose sing1)/trim; + comps2 := (decompose sing2)/trim; + ans := append(idealsByBettiV2(comps1, comps2), {sing1} => {sing2}); + -- checkFormatV2 ans; -- not functional yet? Check that... + ans + ) + +-- singularAndHessianMatches = method() +-- singularAndHessianMatches(Thing, Thing, HashTable, Sequence) := List => (lab1, lab2, Xs, Aphi) -> ( +-- (A,phi) := Aphi; +-- X1 := Xs#lab1; +-- X2 := Xs#lab2; +-- (L1, F1) := (c2Form X1, cubicForm X1); +-- (L2, F2) := (c2Form X2, cubicForm X2); +-- RQ := QQ (monoid ring L1); +-- FQ1 = sub(F1, RQ); +-- FQ2 = sub(F2, RQ); +-- fac1 := factorsByType(det hessian F1); +-- fac2 := factorsByType(det hessian F2); +-- keyset1 := sort for k in sort keys fac1 list if k === {1,0} then continue else k; +-- keyset2 := sort for k in sort keys fac2 list if k === {1,0} then continue else k; +-- --if keyset1 === {{1,4}} then return "Do not use Hessian method on irreducible polynomials of degree > 4"; +-- if keyset1 =!= keyset2 then error "expected same factors and their degrees"; +-- list1 := flatten for k in keyset1 list fac1#k; +-- list2 := for k in keyset2 list fac2#k; +-- list2perms := cartesian for fs in list2 list signedPermutations fs; +-- hessPart := (list1, list2perms); +-- sing1 := trim saturate(ideal FQ1 + ideal jacobian FQ1); +-- sing2 := trim saturate(ideal FQ2 + ideal jacobian FQ2); +-- if sing1 == 1 then return {}; +-- comps1 := (decompose sing1)/trim; +-- comps2 := (decompose sing2)/trim; +-- (list1, list2perms) = idealsByBetti(comps1, comps2); +-- singPart := (join({L1, F1, sing1}, list1), cartesian{{{L2, F2, sing2}}, list2perms}); +-- secondPart := flatten for a in singPart#1 list for b in hessPart#1 list (a | b); +-- ((singPart#0 | hessPart#0), secondPart) +-- ) + +equivalenceByHessian = method() +-- equivalenceByHessian(Thing, Thing, HashTable, Sequence) := List => (lab1, lab2, Xs, Aphi) -> ( +-- (A,phi) := Aphi; +-- X1 := Xs#lab1; +-- X2 := Xs#lab2; +-- (L1, F1) := (c2Form X1, cubicForm X1); +-- (L2, F2) := (c2Form X2, cubicForm X2); +-- (list1, list2perms) := hessianMatches(lab1, lab2, Xs, Aphi); +-- badJs := {}; +-- ans := for i from 0 to #list2perms-1 do ( +-- << "doing " << i << endl; +-- J := trim equivalenceIdeal(join({L1,F1},list1), join({L2,F2},list2perms#i), phi); +-- if J == 1 then continue; +-- << "doing " << i << " not <1>" << endl; +-- A0 := A % J; +-- -- check A0 is integer +-- if support A0 =!= {} then badJs = append(badJs, J); +-- try (A0 = lift(A0, ZZ)) else continue; +-- if det A0 != 1 and det A0 != -1 then continue; +-- break A0 +-- ); +-- if ans === null and #badJs > 0 then return badJs; +-- ans +-- ) + +invertibleMatrixOverZZ = method() +invertibleMatrixOverZZ(Matrix, Ideal) := Sequence => (A, J) -> ( + -- returns (determinacy, A0), or (INCONSISTENT, null) or ...? + if J == 1 then + (INCONSISTENT, null) + else ( + A0 := A % J; + detA0 := (det A0) % J; + if liftable(detA0, ZZ) and all(flatten entries A0, f -> liftable(f, ZZ)) then + (CONSISTENT, sub(A0, ZZ)); + (INDETERMINATE, J) + ) + ) + +invertibleMatrixOverZZ(Matrix, Ideal) := Sequence => (A, J) -> ( + -- returns (determinacy, A0), or (INCONSISTENT, null) or ...? + if J == 1 then + (INCONSISTENT, null) + else ( + A0 := A % J; + detA0 := (det A0) % J; + suppA0 := support A0; + if suppA0 === {} then ( + -- In this case we either have an integer matrix, or a rational matrix. + if liftable(detA0, ZZ) and all(flatten entries A0, f -> liftable(f, ZZ)) then + return (CONSISTENT, sub(A0, ZZ)); + return (INCONSISTENT, sub(A0, QQ)); + ); + jc := decompose J; + if isPrime J then return (INDETERMINATE, jc); + possibles := for j in jc list ( + ans := invertibleMatrixOverZZ(A0, j); + if ans#0 == CONSISTENT then return ans else ans + ); + if all(possibles, a -> a#0 === INCONSISTENT) then ( + ans := select(1, possibles, a -> instance(a#1, Matrix)); + if #ans > 0 then return ans#0 else return (INCONSISTENT, null); + ) + else + return (INDETERMINATE, jc); + ) + ) + + findMatrix5 = method(Options => {Pair => {0,1}}) + findMatrix5(CalabiYauInToric, CalabiYauInToric, List, Sequence) := opts -> (X1, X2, pts2, Aphi) -> ( + -- pts2 is a list of possible entries {p,q} for the first 2 columns of a matrix A0 + (A, phi) := Aphi; + F1 := cubicForm X1; + L1 := c2Form X1; + F2 := cubicForm X2; + L2 := c2Form X2; + F1 = F1 // polynomialContent F1; + F2 = F2 // polynomialContent F2; + L1 = L1 // polynomialContent L1; + L2 = L2 // polynomialContent L2; + L1' := sub(L1, target phi); + L2' := sub(L2, target phi); + F1' := sub(F1, target phi); + F2' := sub(F2, target phi); + result := null; + count := 0; + i1 := opts.Pair#0; + j1 := opts.Pair#1; + for pq in pts2 do ( + count = count+1; + A1 := matrix {for i from 0 to 4 list + if i == i1 then transpose matrix{pq#0} + else if i == j1 then transpose matrix{pq#1} + else A_{i} + }; + --A1 = (transpose matrix{pq#0, pq#1}) | A_{2,3,4}; + psi1 := map(target phi, target phi, transpose A1); + Ja := ideal last coefficients (psi1 L1' - L2'); + Jb := ideal last coefficients (psi1 F1' - F2'); + J := sub(Ja + Jb, ring A1); + (cons, A0) := invertibleMatrixOverZZ(A1, J); + if cons === CONSISTENT then (result = (cons, A0); break); + if cons === INCONSISTENT then (continue); + if cons === INDETERMINATE then ( + error "debug me"; + << "found indeterminate case" << endl; continue + ); + ); + if result === null then return null; + A0 := result#1; + if isEquivalent(X1, X2, transpose A0) then << "** Found one ** " << toString A0 << endl; + << "took " << count << " tries" << endl; + result + ) + +tryEquivalences = method() +tryEquivalences(List, List, Sequence) := (list1, list2perms, Aphi) -> ( + badJs := {}; + inconsistentMatrix := null; + for i from 0 to #list2perms-1 do ( + << "doing " << i << endl; + J := trim equivalenceIdeal(list1, list2perms#i, phi); + ans := invertibleMatrixOverZZ(A, J); + if ans#0 == CONSISTENT then return ans; + if ans#0 == INCONSISTENT and instance(ans#1, Matrix) then inconsistentMatrix = ans#1; + if ans#0 == INDETERMINATE then ( + badJs = join(badJs, ans#1); + ); + ); + if #badJs > 0 then return (INDETERMINATE, badJs); + (INCONSISTENT, inconsistentMatrix) + ) + +equivalenceByHessian(Thing, Thing, HashTable, Sequence) := List => (lab1, lab2, Xs, Aphi) -> ( + << "Calling new code" << endl; + (A,phi) := Aphi; + X1 := Xs#lab1; + X2 := Xs#lab2; + (L1, F1) := (c2Form X1, cubicForm X1); + (L2, F2) := (c2Form X2, cubicForm X2); + (list1, list2perms) := hessianMatches(lab1, lab2, Xs, Aphi); + list1 = join(list1, {L1, F1}); + list2perms = for list2 in list2perms list join(list2, {L2, F2}); + tryEquivalences(list1, list2perms, Aphi) + ) + +-- invertibleMatrixOverZZ(A0, J): +-- check to see if A0 is an invertible matrix over ZZ (modulo J). +-- (det A0 % J) == 1, or -1. +-- if not return (INDETERMINATE, null) +-- if support A0 is {}, then lift to QQ, then to ZZ. +-- if lifts: return (CONSISTENT, A0). +-- +-- if A0 is a matrix over ZZ: +-- create it over ZZ +-- if det A0 != 1, -1 (perhaps mod J?) then return (INCONSISTENT, null) +-- make sure (A - A0) % J == 0. If so, then return (CONSISTENT, A0) + +-- I want a function which, given an equivalence ideal, returns either INCONSISTENT, CONSISTENT (solution over ZZ). +-- if J == 1 then INCONSISTENT +-- else: +-- try A0 = A % J. +-- (consistency, A0) = invertibleMapOverZZ(A0, J) +-- if consistency != INDETERMINATE then return (consistency, A0); +-- if A0 is not a matrix over ZZ: +-- cJ = decompose J -- we need one of these to succeed +-- for each j in cJ do: +-- A0 := A % j +-- if A0 is a matrix over ZZ +-- +equivalenceBySingularLocus = method() +-- equivalenceBySingularLocus(Thing, Thing, HashTable, Sequence) := List => (lab1, lab2, Xs, Aphi) -> ( +-- (A,phi) := Aphi; +-- X1 := Xs#lab1; +-- X2 := Xs#lab2; +-- (L1, F1) := (c2Form X1, cubicForm X1); +-- (L2, F2) := (c2Form X2, cubicForm X2); +-- (list1, list2perms) := singularLocusMatches(lab1, lab2, Xs, Aphi); +-- badJs := {}; +-- ans := for i from 0 to #list2perms-1 do ( +-- J := trim equivalenceIdeal(join({L1,F1},list1), join({L2,F2},list2perms#i), phi); +-- if J == 1 then continue; +-- A0 := A % J; +-- -- check A0 is integer +-- if support A0 =!= {} then badJs = append(badJs, J); +-- try (A0 = lift(A0, ZZ)) else continue; +-- if det A0 != 1 and det A0 != -1 then continue; +-- break A0 +-- ); +-- if ans === null and #badJs > 0 then return badJs; +-- ans +-- ) + +equivalenceBySingularLocus(Thing, Thing, HashTable, Sequence) := List => (lab1, lab2, Xs, Aphi) -> ( + (A,phi) := Aphi; + X1 := Xs#lab1; + X2 := Xs#lab2; + (L1, F1) := (c2Form X1, cubicForm X1); + (L2, F2) := (c2Form X2, cubicForm X2); + (list1, list2perms) := singularLocusMatches(lab1, lab2, Xs, Aphi); + list1 = join(list1, {L1, F1}); + list2perms = for list2 in list2perms list join(list2, {L2, F2}); + tryEquivalences(list1, list2perms, Aphi) + ) + +-- This is not working well... i.e. no working examples yet! +-- equivalenceBySingularLocusAndHessian = method() +-- equivalenceBySingularLocusAndHessian(Thing, Thing, HashTable, Sequence) := List => (lab1, lab2, Xs, Aphi) -> ( +-- << "Calling new code" << endl; +-- (A,phi) := Aphi; +-- X1 := Xs#lab1; +-- X2 := Xs#lab2; +-- (L1, F1) := (c2Form X1, cubicForm X1); +-- (L2, F2) := (c2Form X2, cubicForm X2); +-- (list1, list2perms) := singularAndHessianMatches(lab1, lab2, Xs, Aphi); +-- tryEquivalences(list1, list2perms, Aphi) +-- ) + +equivalenceByGVCone = method(Options => {DegreeLimit => 15}) +equivalenceByGVCone(Thing, Thing, HashTable, Sequence) := Matrix => opts -> (lab1, lab2, Xs, Aphi) -> ( + -- return value of null means they might still be the same, we just don't know. + X1 := Xs#lab1; + X2 := Xs#lab2; + gv1 := partitionGVConeByGV(X1, opts); + gv2 := partitionGVConeByGV(X1, opts); + if gv1 === null or gv2 === null then return null; + findLinearMaps(gv1, gv2) -- what does this return? Not what we want, certainly! + -- let's put in the L1->L2, F1->F2 equations, maybe det+1, det-1 too, and stop when we find a match. + ) +-* +equivalenceIdealSingularSet = method() +equivalenceIdealSingularComponents = method() + + equivalenceIdealsSingularLocus = method() + equivalenceIdealsSingularLocus(Sequence, Sequence, RingMap) := List => (LF1, LF2, phi) -> ( + -- returns a list of ideals in target phi (=== source phi). + (L1, F1) := LF1; + (L2, F2) := LF2; -- TODO: the rings of all 4 of these polynomials should be the same, and be RZ. + RZ := ring L1; + RQ := QQ (monoid RZ); + toRQ := map(RQ, RZ); + -- Get singular locus and components (over QQ) of F1. + singF1 := saturate(ideal F1 + ideal jacobian F1); + singF1Q := trim toRQ singF1; + compsS1 := (decompose singF1Q)/trim; + -- Get singular locus and components (over QQ) of F2. + singF2 := saturate(ideal F2 + ideal jacobian F2); + singF2Q := trim toRQ singF2; + compsS2 := (decompose singF2Q)/trim; + -- From invariants, we expect singF1Q, singF2Q to have the same degree generators (and their number). + -- TODO: should we check this? + -- Similarly, we expect compsS1, compsS2 to have the same number of components, and same degree gens each. + if betti singF2Q != betti singF1Q then ( + << "degrees of generators of sing loci ideals differ: returning no ideals" << endl; + return {}; + ); + error "debug me"; + ) + + equivalenceIdealsSingularLocus(Thing, Thing, HashTable, RingMap) := List => (lab1, lab2, Xs, phi) -> ( + X1 := Xs#lab1; + X2 := Xs#lab2; + (L1, F1) := (c2Form X1, cubicForm X1); + (L2, F2) := (c2Form X2, cubicForm X2); + equivalenceIdealsSingularLocus((L1,F1), (L2,F2), phi) + ) +*- + +allSigns = method() +allSigns List := L -> ( + if #L <= 0 then return {{}}; + if #L == 1 then return {{L#0}, {-L#0}}; + flatten for q in allSigns(drop(L, 1)) list {prepend(L#0, q), prepend(-L#0, q)} + ) + +signedPermutations = method() +signedPermutations List := List => L -> ( + flatten for p in permutations L list allSigns p + ) + +cartesian = method() +cartesian List := (Ls) -> ( + -- cartesian product of Ls: one element from each + -- so the result is a list of lists. + if #Ls == 1 then return for p in Ls#0 list p; + Ls1 := cartesian drop(Ls,1); + flatten for p in Ls#0 list for q in Ls1 list join(p, q) + ) + +TEST /// + R = ZZ[a,b,c,d] + assert(allSigns{1,2,3} === {{1, 2, 3}, {-1, 2, 3}, {1, -2, 3}, {-1, -2, 3}, {1, 2, -3}, {-1, 2, -3}, {1, -2, -3}, {-1, -2, -3}}) + assert(allSigns{} === {{}}) + assert(allSigns{a+b,a+c} === {{a+b, a+c}, {-a-b, a+c}, {a+b, -a-c}, {-a-b, -a-c}}) + + assert(signedPermutations {a,b} === {{a, b}, {-a, b}, {a, -b}, {-a, -b}, {b, a}, {-b, a}, {b, -a}, {-b, -a}}) + + assert( + cartesian{signedPermutations{a,b}, permutations{c,d}} + == + {{a, b, c, d}, {a, b, d, c}, {-a, b, c, d}, {-a, b, d, c}, + {a, -b, c, d}, {a, -b, d, c}, {-a, -b, c, d}, {-a, -b, d, c}, + {b, a, c, d}, {b, a, d, c}, {-b, a, c, d}, {-b, a, d, c}, + {b, -a, c, d}, {b, -a, d, c}, {-b, -a, c, d}, {-b, -a, d, c}} + ) + +/// + +------------------------------- +-- Given a list of labels, and the hash table Xs, and (A,phi) (do we really need this last one??) +-- Returns a list of 2 lists: +-- The firt is a list {L0, L1, ..., Ld}, where each Li is a list of labels (and possible (label, matrix). +-- such that for each i, the labels in Li are all equivalent (there is a matrix over ZZ of unit det which +-- maps one to the other, +-- for each i != j, any label in Li is NOT equivalent to any in Lj. +-- The second is a list of labels where we don't know if they are equiv or not equiv to any one of the above sets. +-- +-- Maybe: allow an initial result to be created +separateAndCombineByFcn = method() +separateAndCombineByFcn(List, HashTable, Sequence, Function) := (Ls, Xs, Aphi, F) -> ( + -- F: (X,Y) --> List (of {CONSISTENT, ...}, {INCONSISTENT, ...}, {INDETERMINATE, ...}. + resultList := new MutableList; + resultUnknowns := {}; + for lab in Ls do ( + known := false; + hasbad := false; + i := 0; + for i from 0 to #resultList-1 do ( + lab0 := first resultList#i; + ans := F(lab0, lab, Xs, Aphi); + if first ans === CONSISTENT then ( + -- then we know this one, and can stash it, and go on to the next one. + << "-- note: " << lab << " and " << lab0 << " are equivalent via: " << ans#1 << endl; + resultList#i = append(resultList#i, lab); + known = true; + break; + ) + else if first ans =!= INCONSISTENT then ( + hasbad = true; + ); + ); + if not known then ( + if not hasbad then ( + << "-- note: " << lab << " is not equivalent to ones before" << endl; + resultList#(#resultList) = {lab} + ) + else ( + << "-- note: " << lab << " is inconclusive" << endl; + resultUnknowns = append(resultUnknowns, lab); + ) + ); + ); + {toList resultList, resultUnknowns} + ) + +end-- + +-- Tests of this code, 12 Jan 2023. +TEST /// +-* + restart + needsPackage "StringTorics" +*- + DBNAME = "../Databases/cys-ntfe-h11-5.dbm" + DBNAME = "./Databases/cys-ntfe-h11-5.dbm" + RZ = ZZ[a,b,c,d,e] + RQ = QQ (monoid RZ); + needs "../FindEquivalence.m2" + (A,phi) = genericLinearMap RQ + elapsedTime (Qs, Xs) = readCYDatabase(DBNAME, Ring => RZ); + REPS = value get "inequiv-reps-h11-5" + SETS = new HashTable from { + {{{4,1},{4,1}},{{5,1}}} => {50,55,65,66,70,72,73,80,85,91,92,95,96,100,103,116,117,186,193}, + {{{5,1}},{{5,1}}} => {7,9,10,14,22,23,24,27,31,36,37,49,51,56,71,93,99,101,102,108,115,130}, + {{{4,1},{4,1},{4,1}},{{5,1}}} => {52,77,155,171,180,217}, + {{{5,1}},{{1,1},{1,1},{3,1}}} => {18,25,32,35,41,59,60,75,111,112,142,143,153,154,178,188,208,215,221,226,227}, + {{{4,2}},{{1,1},{2,1},{2,1}}} => {79}, + {{{4,1}},{{1,1},{1,1},{1,1},{1,2}}} => {118,129,137,138,144,145,190,191,200}, + {{{5,1}},{{1,1},{1,1},{1,1},{1,1},{1,1}}} => {8,28,61,86,88,89,120,131,132,136,146,149,158,160,166,173,201,202,205,207,211,213,218,219,220,224,225}, + {{{4,1},{4,1},{4,1}},{{1,1},{1,1},{1,1},{1,1},{1,1}}} => {124,156,168}, + {{{4,1},{4,1}},{{1,1},{4,1}}} => {44,47,177}, + {{{3,2},{4,1}},{{1,1},{1,2},{2,1}}} => {135,164}, + {{{4,2}},{{5,1}}} => {6,15}, + {{{5,1}},{{1,1},{4,1}}} => {0,3,4,5,11,13,17,21,29,30,34,38,39,40,42,45,57,68,81,83,90,94,98,104,107,109,110,114,119,128,140,163,169,172,195,212,223}, + {{{4,2}},{{1,1},{1,1},{3,1}}} => {48,105}, + {{{4,1},{4,1},{4,1}},{{1,1},{4,1}}} => {62,63,127,151}, + {{{3,2},{4,1}},{{1,1},{4,1}}} => {53,54,76,122,134}, + {{{3,2},{4,1}},{{1,2},{3,1}}} => {78}, + {{{4,1}},{{5,1}}} => {1,2,19,20,26,64,67,97,121,123}, + {{{4,2}},{{1,1},{4,1}}} => {69,82,113,147,152,189,199,206,214}, + {{{4,1}},{{1,1},{1,2},{2,1}}} => {84,139,161,162,197}, + {{{4,1}},{{1,2},{3,1}}} => {159,179,181,182,183,184,192,194,198}, + {{{4,1}},{{1,1},{4,1}}} => {12,43,187,216}, + {{{3,2}},{{1,1},{1,2},{2,1}}} => {125,126,148,165,175,185,196,204}, + {{{4,1},{4,1},{4,1},{4,1}},{{5,1}}} => {222}, + {{{3,2}},{{1,1},{4,1}}} => {74,106,141,157,174,210}, + {{{3,2}},{{1,2},{3,1}}} => {46}, + {{{4,1},{4,1},{4,1},{4,1}},{{1,1},{4,1}}} => {16}, + {{{4,1},{4,1}},{{1,1},{1,1},{1,1},{2,1}}} => {133,170,209}, + {{{5,1}},{{1,1},{1,1},{1,1},{2,1}}} => {33,58}, + {{{2,2}},{{1,3},{2,1}}} => {87}, + {{{4,2}},{{1,1},{1,1},{1,1},{2,1}}} => {150,167,176,203}} + (sort keys SETS)/(k -> {k#0, k#1, #SETS#k, SETS#k})//netList + -- column one: structure of sing locus + -- column 2: factorization of Hessian. + -- column 3: # of REP sets + -- column 4: list of indices into REPS. + + -- We can use this collection to test FindEquivalence.m2 code: + -- Goal: for each set of labels REPS#i, determine if these are the same topology or different. + -- Note: some are very easy, some I can't yet do. +/// + +TEST /// +-* + restart + needsPackage "StringTorics" +*- + DBNAME = "../Databases/cys-ntfe-h11-5.dbm" + RZ = ZZ[a,b,c,d,e] + RQ = QQ (monoid RZ); + needs "../FindEquivalence.m2" + load "../FindEquivalence.m2" + (A,phi) = genericLinearMap RQ + elapsedTime (Qs, Xs) = readCYDatabase(DBNAME, Ring => RZ); + + -- Test of: idealsByBettiV2 -- XXX + lab1 = (879,0) + lab2 = (910,0) + X1 = Xs#lab1; + X2 = Xs#lab2; + (L1, F1) = (c2Form X1, cubicForm X1); + (L2, F2) = (c2Form X2, cubicForm X2); + --RQ := QQ (monoid ring L1); + FQ1 = sub(F1, RQ); + FQ2 = sub(F2, RQ); + sing1 = trim saturate(ideal FQ1 + ideal jacobian FQ1); + sing2 = trim saturate(ideal FQ2 + ideal jacobian FQ2); + comps1 = (decompose sing1)/trim; + comps2 = (decompose sing2)/trim; + (list1, list2perms) = idealsByBetti(comps1, comps2) + + comps1 = {ideal (d, c, b, a), ideal (e, d, b, a)} + comps2 = {ideal (d, c, b, a), ideal (e, d, b, a)} + val = idealsByBettiV2(comps1, comps2) + ans = {{comps1_0, comps1_1} => {comps2, reverse comps2}} -- this is because comps1, comps2 have 2 ideals of same type. + assert(ans === val) + + singularLocusMatches(lab1, lab2, Xs, (A,phi)) + singularLocusMatchesV2(lab1, lab2, Xs, (A,phi)) + netList for x in oo list {x#0, netList x#1} + + idealsByBettiV2 -- +/// + +TEST /// +-* + restart + needsPackage "StringTorics" +*- + DBNAME = "../Databases/cys-ntfe-h11-5.dbm" + RZ = ZZ[a,b,c,d,e] + RQ = QQ (monoid RZ); + needs "../FindEquivalence.m2" + load "../FindEquivalence.m2" + (A,phi) = genericLinearMap RQ + elapsedTime (Qs, Xs) = readCYDatabase(DBNAME, Ring => RZ); + +-- Here is a potentially hard one: +-- Actually, we can find a map between them, this is done below. + (lab1, lab2) = toSequence {(133, 0), (165, 0)} -- EQUIVALENT! + X1 = Xs#lab1; + X2 = Xs#lab2; + (L1, F1) = (c2Form X1, cubicForm X1); + (L2, F2) = (c2Form X2, cubicForm X2); + FQ1 = sub(F1, RQ); + FQ2 = sub(F2, RQ); + sing1 = trim saturate(ideal FQ1 + ideal jacobian FQ1); + sing2 = trim saturate(ideal FQ2 + ideal jacobian FQ2); + comps1 = (decompose sing1)/trim; + comps2 = (decompose sing2)/trim; + classifyExtremalCurves X1, classifyExtremalCurves X2 + + -- These give no information + L1 + L2 + Rp = (ZZ/3) (monoid RQ) + F1p = sub(F1, Rp) + F2p = sub(F2, Rp) + factor det hessian F1p + factor det hessian F2p + sing1 = trim saturate(ideal F1p + ideal jacobian F1p); + sing2 = trim saturate(ideal F2p + ideal jacobian F2p); + + needsPackage "LLLBases" + (cL1, M1) = gcdLLL ((listForm L1)/last) + f1 = map(RZ, RZ, transpose M1) + f1 L1 + L1 = f1 L1 + F1 = f1 F1 + + (cL2, M2) = gcdLLL ((listForm L2)/last) + f2 = map(RZ, RZ, transpose M2) + f2 L2 + L2 = f2 L2 + F2 = f2 F2 + + use RZ + sing1 = trim saturate(ideal F1 + ideal jacobian F1); + sing2 = trim saturate(ideal F2 + ideal jacobian F2); + factor leadCoefficient sing1_0 + F1e = sub(F1, e => 0) + F2e = sub(F2, e => 0) + SZ = ZZ[a,b,c,d] + SQ = QQ (monoid SZ) + F1e = sub(F1e, SZ) + F2e = sub(F2e, SZ) + factor det hessian F1e + factor det hessian F2e + polynomialContent det hessian F1e + polynomialContent det hessian F2e + (A1, phi1) = genericLinearMap SQ + J = ideal last coefficients(phi1 (sub(F1e, target phi1)) - sub(F2e, target phi1)) + --gbTrace=3 + --gb J; + sing1 = saturate (ideal F1e + ideal jacobian F1e) + sing2 = saturate (ideal F2e + ideal jacobian F2e) + factor leadCoefficient sing1_0 + factor leadCoefficient sing2_0 + sing1 : (sing1 : 17) + sing2 : (sing2 : 17) + + sing1 : (sing1 : 19) + sing2 : (sing2 : 19) + + sing1 : (sing1 : 173) + sing2 : (sing2 : 173) + + sing1 : (sing1 : 89) + sing2 : (sing2 : 89) + + Sp = (ZZ/89) (monoid SZ) + (Ap, phip) = genericLinearMap Sp + sub(F1e, target phip) + J = ideal last coefficients(phip (sub(F1e, target phip)) - sub(F2e, target phip)) + see J + J1 = trim sub( sing1 : (sing1 : 89), Sp) + J2 = trim sub( sing2 : (sing2 : 89), Sp) + J' = ideal last coefficients(phip (gens sub(J1, target phip)) % gens sub(J2, target phip)) + J = J + J' + J = sub(J, coefficientRing ring J) + elapsedTime gbJ = groebnerBasis J; + see ideal gbJ + comps = decompose ideal gbJ -- 8 components, but 4 don't have a point over ZZ/89. The other 4 have a unique point. + A1 = sub(Ap % comps_0, ZZ) + fp = map(SZ, SZ, transpose A1) + fp F1e - F2e + + -- let's try map that leaves e fixed: + use RZ + fR = map(RZ, RZ, {-b-c, c, -a, d, e}) + fR F1 - F2 + + U = source phi + T = coefficientRing U + use T; use U + fR = map(U, U, {-b-c + t_(1,1)*e, c + t_(1,2)*e, -a + t_(1,3)*e, d + t_(1,4)*e, e}) + trim ideal last coefficients(fR sub(F1, U) - sub(F2, U)) + fU = map(U, U, fR.matrix % oo) + fU sub(F1, U) - sub(F2, U) + + A1 = sub(A1, coefficientRing source phi) + A2 = (transpose A1 | transpose matrix{{t_(1,1), t_(1,2), t_(1,3), t_(1,4)}}) || matrix{{0,0,0,0,1}} + psi = map(source phi, source phi, transpose A2) + use target psi + psi (e) + psi F1 + psi sub(F1, source psi) - sub(F2, source psi) +/// + + +TEST /// +-* + restart + needsPackage "StringTorics" +*- + DBNAME = "../Databases/cys-ntfe-h11-5.dbm" + RZ = ZZ[a,b,c,d,e] + RQ = QQ (monoid RZ); + needs "../FindEquivalence.m2" + load "../FindEquivalence.m2" + (A,phi) = genericLinearMap RQ + elapsedTime (Qs, Xs) = readCYDatabase(DBNAME, Ring => RZ); + +-- Here is a potentially hard one: +-- Actually, we can find a map between them, this is done below. + (lab1, lab2) = toSequence {(159, 2), (219, 2)} + X1 = Xs#lab1; + X2 = Xs#lab2; + (L1, F1) = (c2Form X1, cubicForm X1); + (L2, F2) = (c2Form X2, cubicForm X2); + FQ1 = sub(F1, RQ); + FQ2 = sub(F2, RQ); + sing1 = trim saturate(ideal FQ1 + ideal jacobian FQ1) + sing2 = trim saturate(ideal FQ2 + ideal jacobian FQ2) + comps1 = (decompose sing1)/trim + comps2 = (decompose sing2)/trim + classifyExtremalCurves X1, classifyExtremalCurves X2 + + needsPackage "LLLBases" + (cL1, M1) = gcdLLL ((listForm L1)/last) + f1 = map(RZ, RZ, transpose M1) + f1 L1 + L1 = f1 L1 + F1 = f1 F1 + + (cL2, M2) = gcdLLL ((listForm L2)/last) + f2 = map(RZ, RZ, transpose M2) + f2 L2 + L2 = f2 L2 + F2 = f2 F2 + + use RZ + sing1 = trim saturate(ideal F1 + ideal jacobian F1); + sing2 = trim saturate(ideal F2 + ideal jacobian F2); + factor leadCoefficient sing1_0 + F1e = sub(F1, e => 0) + F2e = sub(F2, e => 0) + SZ = ZZ[a,b,c,d] + SQ = QQ (monoid SZ) + F1e = sub(F1e, SZ) + F2e = sub(F2e, SZ) + factor det hessian F1e + factor det hessian F2e + polynomialContent det hessian F1e + polynomialContent det hessian F2e + (A1, phi1) = genericLinearMap SQ + J = ideal last coefficients(phi1 (sub(F1e, target phi1)) - sub(F2e, target phi1)) + --gbTrace=3 + --gb J; + sing1 = saturate (ideal F1e + ideal jacobian F1e) + sing2 = saturate (ideal F2e + ideal jacobian F2e) + factor leadCoefficient sing1_0 + factor leadCoefficient sing2_0 + sing1 : (sing1 : 4243) + sing2 : (sing2 : 4243) + + sing1 : (sing1 : 11) + sing2 : (sing2 : 11) + + sing1 : (sing1 : 31) + sing2 : (sing2 : 31) + + Sp = (ZZ/31) (monoid SZ) + (Ap, phip) = genericLinearMap Sp + sub(F1e, target phip) + J = ideal last coefficients(phip (sub(F1e, target phip)) - sub(F2e, target phip)) + see J + J1 = trim sub( sing1 : (sing1 : 31), Sp) + J2 = trim sub( sing2 : (sing2 : 31), Sp) + J' = ideal last coefficients(phip (gens sub(J1, target phip)) % gens sub(J2, target phip)) + J = J + J' + J = sub(J, coefficientRing ring J) + elapsedTime gbJ = groebnerBasis J; -- 23 sec + see ideal gbJ + comps = decompose ideal gbJ -- 8 components, but 4 don't have a point over ZZ/89. The other 4 have a unique point. + A1 = sub(Ap % comps_4, ZZ) + A1 = 1/6 * A1 + A1 = sub(A1, ZZ) + fp = map(Sp, Sp, transpose sub(A1, coefficientRing Sp) ) + fp sub(F1e, Sp) - sub(F2e, Sp) + fZZ = map(SZ, SZ, transpose A1) + fZZ F1e - F2e -- 0 + + -- let's try map that leaves e fixed: + use RZ + fR = map(RZ, RZ, {-b-c, c, -a, d, e}) + fR F1 - F2 + + U = source phi + T = coefficientRing U + use T; use U + A = (A1 | transpose matrix{{t_(1,1), t_(1,2), t_(1,3), t_(1,4)}} ) || matrix{{0,0,0,0,1}} + fU = map(U, U, transpose A) + trim ideal last coefficients(fU sub(F1, U) - sub(F2, U)) + fU = map(U, U, fU.matrix % oo) + fU sub(F1, U) - sub(F2, U) + + A1 = sub(A1, coefficientRing source phi) + A2 = (transpose A1 | transpose matrix{{t_(1,1), t_(1,2), t_(1,3), t_(1,4)}}) || matrix{{0,0,0,0,1}} + psi = map(source phi, source phi, transpose A2) + use target psi + psi (e) + psi F1 + psi sub(F1, source psi) - sub(F2, source psi) +/// + +-- In this file, we work on code for finding n x n integer invertible matrices A +-- such that phi L1 = L2, phi F1 = F2, +-- where: phi (x) = i-th row of (transpose A)*x (CHECK). +-- and L1, L2 are c2-forms for CY3's X1, X2 +-- and F1, F2 are cubic forms for X1, X2. + +findEquivalenceIdeals -- might come up with several ideals, any which could work. +findEquivalence -- uses findEquivalenceIdeals, checks to find integer solutions for each component. + -- returns only one of these if found. + -- if cannot solve, return list of ideals, ones that cannot be solved. + -- if no solutions at all, return null. + -- if find a solution, return the matrix. + +partitionCY3sByEquivalence + -- input: a list of CY3 labels, and a hash table Xs + -- output: a list of lists + -- each of the sublists has the form: + -- {{label, {label, matrix}, ...} + -- also returns the unknown ones? + + -- e.g.: if input is a list {lab1, lab2} + -- it calls findEquivalence on these two CY's + -- if null: returns {{lab1}, {lab2}} -- these are distinct topologies + -- if a matrix A0: returns {{lab1, {lab2, A0}} + -- if an ideal: returns {{{lab1, lab2}}} -- uughh... indicating that these may be same. + +isEquivalent = method() +isEquivalent(Sequence, Sequence, Matrix) := Boolean => (LF1, LF2, A) -> ( + (L1,F1) := LF1; + (L2,F2) := LF2; + R := ring L1; + if R =!= ring F1 or R =!= ring L2 or R =!= ring F2 then + error "excepted c2 and cubic forms to be in the same ring"; + phi := map(R, R, A); + phi L1 == L2 and phi F1 == F2 + ) +isEquivalent(CYToolsCY3, CYToolsCY3, Matrix) := +isEquivalent(CalabiYauInToric, CalabiYauInToric, Matrix) := Boolean => (X1, X2, A) -> ( + -- X1, X2 are CalabiYauInToric's (of the same h11 = h11(X1) = h11(X2)). + -- A is an h11 x h11 matrix over ZZ, with determinant 1 or -1. + -- if the topological data of X1, X2 are equivalent via A, then true is returned. + if hh^(1,2) X1 =!= hh^(1,2) X2 then return false; + if hh^(1,1) X1 =!= hh^(1,1) X2 then return false; + LF1 := (c2Form X1, cubicForm X1); + LF2 := (c2Form X2, cubicForm X2); + isEquivalent(LF1, LF2, A) + ) + +-- not: mapIsIsomorphism is essentially identical (but works with CYToolsCY3, CalabiYauInToric + +genericLinearMap = method(Options => {Variable => null}) +genericLinearMap Ring := opts -> R -> ( + -- R should be a polynomial ring in n variables. + n := numgens R; + K := coefficientRing R; + t := if opts.Variable === null then getSymbol "t" else opts.Variable; + T := K[t_(1,1)..t_(n,n)]; + TR := T [gens R, Join => false]; + A := map(T^n,,transpose genericMatrix(T, T_0, n, n)); + phi := map(TR, TR, transpose A); + (A, phi) + ) + +-- linearEquationConstraints, linearEquationConstraintsIdeal: not quite what we want. + +-- findMaps: keep this one? +-- findIsomorphism -- same, I think, or close. +-- determineIsomorphism + + getEquivalenceIdealHelper = (LF1, LF2, A, phi) -> ( + T := target phi; + B := ring A; + LF1' := LF1/(f -> sub(f, T)); + LF2' := LF2/(f -> sub(f, T)); + I0 := sub(ideal last coefficients(phi LF1'_0 - LF2'_0), B); + A0 := A % I0; + phi0 := map(T, T, transpose A0); + trim(I0 + sub(ideal last coefficients (phi0 LF1'_1 - LF2'_1), B)) + ) + + getEquivalenceIdeal = method() + getEquivalenceIdeal(Thing, Thing, HashTable) := Sequence => (lab1, lab2, Xs) -> ( + X1 := Xs#lab1; + X2 := Xs#lab2; + LF1 := (c2Form X1, cubicForm X1); + LF2 := (c2Form X2, cubicForm X2); + RQ := QQ (monoid ring LF1_0); + (A,phi) := genericLinearMap RQ; + (getEquivalenceIdealHelper(LF1, LF2, A, phi), A) + ) + +--------------------------------------------- +-- examples for h11=4 +end-- +restart +load "../FindEquivalence.m2" + +DB4 = "../Databases/cys-ntfe-h11-4.dbm" +RZ = ZZ[a,b,c,d] +RQ = QQ (monoid RZ); +(Qs, Xs) = readCYDatabase(DB4, Ring => RZ); +allXs = sort keys Xs; +(A, phi) = genericLinearMap RQ; + + h12 = 70 + thisXs = select(sort keys Xs, lab -> hh^(1,2) Xs#lab == h12) + elapsedTime thisInvSet = partition(lab -> invariantsAll(Xs#lab), thisXs); + reps = select(keys thisInvSet, k -> #thisInvSet#k > 1) + netList select(values thisInvSet, k -> #k > 1) + + thisInvSet#(reps#1) + + equivalenceIdealsSingularLocus ((418,0), (434,0), Xs, phi) + tally apply(sort keys Xs, lab -> hh^(1,2) Xs#lab) + saturate (ideal F1 + ideal jacobian F1) + sub(oo, RQ) + decompose oo + + + ideal last coefficients (phi gens sub(singF1Q, source phi) % sub(singF2Q, source phi)) + +(A, phi) = genericLinearMap RQ +equivalenceIdealMain((418,0),(434,0),Xs,(A,phi)) -- this is meant to be tacked on to others? + +(L1,F1) = (c2Form Xs#(418,0), cubicForm Xs#(418,0)) +(L2,F2) = (c2Form Xs#(434,0), cubicForm Xs#(434,0)) + +gens gb equivalenceIdeals({L1, F1, ideal(b,c,d)}, {L2, F2, ideal(d,c,a-b)}, phi) + + +S1 = trim sub(ideal F1 + ideal jacobian F1, RQ) +S2 = trim sub(ideal F2 + ideal jacobian F2, RQ) + +gens gb equivalenceIdeals({L1, F1, ideal(b,c,d)}, {L2, F2, ideal(d,c,a-b)}, phi) + +decompose ideal gens gb equivalenceIdeals({S1, L1, F1}, {S2, L2, F2}, phi) +for j in oo list A % j +oo/det +A % ideal oo + +-- These are the same, which we can determine with GV's +(X1, X2) = ((422, 0), (431, 0))/(lab -> Xs#lab) +(L1,F1) = (c2Form X1, cubicForm X1) +(L2,F2) = (c2Form X2, cubicForm X2) +--elapsedTime ideal gens gb equivalenceIdeals({L1, F1}, {L2, F2}, phi); +gv1 = partitionGVConeByGV(X1, DegreeLimit => 15) +gv2 = partitionGVConeByGV(X2, DegreeLimit => 15) +findLinearMaps(gv1, gv2) +phi0 = map(RZ, RZ, sub(first oo, ZZ)) +phi0 L1 - L2 +phi0 F1 - F2 + +equivalenceIdealSingularSet(X1, X2, phi) + +-- Hessians -- + these = thisInvSet#(reps#2) -- {(425, 6), (430, 11)} +(A,phi) = genericLinearMap RQ +(X1, X2) = these/(lab -> Xs#lab)//toSequence +elapsedTime equivalenceIdealsHessian(these#0, these#1, Xs, (A, phi)); +elapsedTime equivalenceByHessian(these#0, these#1, Xs, (A, phi)) + these = thisInvSet#(reps#3) -- {(425, 6), (430, 11)} + reps#3 + ours = take(these, 2) + (list1, list2p) = singularLocusMatches(ours#0, ours#1, Xs, (A, phi)) + for J in flatten for p in list2p list decompose trim equivalenceIdeal(list1, p, phi) list A % J + equivalenceBySingularLocus(ours#0, ours#1, Xs, (A, phi)) + +reps#0 -- use sing locus + +for ours in subsets(thisInvSet#(reps#0), 2) list equivalenceBySingularLocus(ours#0, ours#1, Xs, (A, phi)) + +for ours in subsets(thisInvSet#(reps#1), 2) list equivalenceByHessian(ours#0, ours#1, Xs, (A, phi)) -- neither works yet + +for ours in subsets(thisInvSet#(reps#1), 2) list equivalenceByHessian(ours#0, ours#1, Xs, (A, phi)) -- neither works yet + +for ours in subsets(thisInvSet#(reps#2), 2) list equivalenceByHessian(ours#0, ours#1, Xs, (A, phi)) +for ours in subsets(thisInvSet#(reps#3), 2) list equivalenceByHessian(ours#0, ours#1, Xs, (A, phi)) -- works, but should use a better algorithm than just trying all pairs? + +reps#4 +#thisInvSet#(reps#4) +for ours in subsets(thisInvSet#(reps#4), 2) list equivalenceByHessian(ours#0, ours#1, Xs, (A, phi)) +for ours in subsets(thisInvSet#(reps#4), 2) list equivalenceBySingularLocus(ours#0, ours#1, Xs, (A, phi)) + +reps#5 -- neither should work here +#thisInvSet#(reps#5) +for ours in subsets(thisInvSet#(reps#5), 2) list equivalenceByHessian(ours#0, ours#1, Xs, (A, phi)) +for ours in subsets(thisInvSet#(reps#5), 2) list equivalenceBySingularLocus(ours#0, ours#1, Xs, (A, phi)) + +rep = reps#6 -- this one is subtle: the ideals are nontrivial. BUG? Did I do decompose above? +#thisInvSet#(rep) +for ours in subsets(thisInvSet#(rep), 2) list equivalenceByHessian(ours#0, ours#1, Xs, (A, phi)) +for ours in subsets(thisInvSet#(rep), 2) list equivalenceBySingularLocus(ours#0, ours#1, Xs, (A, phi)) + +rep = reps#7 +#thisInvSet#(rep) +for ours in subsets(thisInvSet#(rep), 2) list equivalenceByHessian(ours#0, ours#1, Xs, (A, phi)) +for ours in subsets(thisInvSet#(rep), 2) list equivalenceBySingularLocus(ours#0, ours#1, Xs, (A, phi)) -- shows they are different. + +rep = reps#8 +#thisInvSet#(rep) +for ours in subsets(thisInvSet#(rep), 2) list equivalenceByHessian(ours#0, ours#1, Xs, (A, phi)) -- shows there are 2 classes of 2 each... Takes longer than I would prefer. +for ours in subsets(thisInvSet#(rep), 2) list equivalenceBySingularLocus(ours#0, ours#1, Xs, (A, phi)) -- + +rep = reps#9 -- neither works +#thisInvSet#(rep) +for ours in subsets(thisInvSet#(rep), 2) list equivalenceByHessian(ours#0, ours#1, Xs, (A, phi)) -- +for ours in subsets(thisInvSet#(rep), 2) list equivalenceBySingularLocus(ours#0, ours#1, Xs, (A, phi)) -- + +rep = reps#10 -- all 4 are equiv, both methods work +#thisInvSet#(rep) +for ours in subsets(thisInvSet#(rep), 2) list equivalenceByHessian(ours#0, ours#1, Xs, (A, phi)) -- +for ours in subsets(thisInvSet#(rep), 2) list equivalenceBySingularLocus(ours#0, ours#1, Xs, (A, phi)) -- + +rep = reps#11 -- all 2 are equiv, both work +#thisInvSet#(rep) +for ours in subsets(thisInvSet#(rep), 2) list equivalenceByHessian(ours#0, ours#1, Xs, (A, phi)) -- +for ours in subsets(thisInvSet#(rep), 2) list equivalenceBySingularLocus(ours#0, ours#1, Xs, (A, phi)) -- + +rep = reps#12 +#thisInvSet#(rep) +for ours in subsets(thisInvSet#(rep), 2) list equivalenceByHessian(ours#0, ours#1, Xs, (A, phi)) -- gives ideal, using decompose would work here +for ours in subsets(thisInvSet#(rep), 2) list equivalenceBySingularLocus(ours#0, ours#1, Xs, (A, phi)) -- works + +rep = reps#13 +thisset = thisInvSet#(rep) -- 28 in this set +for i from 1 to 27 list (ans := equivalenceByHessian(thisset#0, thisset#i, Xs, (A, phi)); print ans; ans) -- fast, all equiv to first one. + +rep = reps#14 +#thisInvSet#(rep) +for ours in subsets(thisInvSet#(rep), 2) list equivalenceByHessian(ours#0, ours#1, Xs, (A, phi)) -- gives ideal, using decompose would work here +for ours in subsets(thisInvSet#(rep), 2) list equivalenceBySingularLocus(ours#0, ours#1, Xs, (A, phi)) -- works + +rep = reps#14 -- one that goes to ellipse. +#thisInvSet#(rep) +for ours in subsets(thisInvSet#(rep), 2) list equivalenceByHessian(ours#0, ours#1, Xs, (A, phi)) +for ours in subsets(thisInvSet#(rep), 2) list equivalenceBySingularLocus(ours#0, ours#1, Xs, (A, phi)) + +rep = reps#15 -- hessian and sing locus do not work here +#thisInvSet#(rep) +for ours in subsets(thisInvSet#(rep), 2) list equivalenceByHessian(ours#0, ours#1, Xs, (A, phi)) +for ours in subsets(thisInvSet#(rep), 2) list equivalenceBySingularLocus(ours#0, ours#1, Xs, (A, phi)) + +rep = reps#16 -- hessian and sing locus do not work here +#thisInvSet#(rep) +for ours in subsets(thisInvSet#(rep), 2) list equivalenceByHessian(ours#0, ours#1, Xs, (A, phi)) +for ours in subsets(thisInvSet#(rep), 2) list equivalenceBySingularLocus(ours#0, ours#1, Xs, (A, phi)) + +rep = reps#17 -- hessian and sing locus do not work here +#thisInvSet#(rep) +for ours in subsets(thisInvSet#(rep), 2) list equivalenceByHessian(ours#0, ours#1, Xs, (A, phi)) +for ours in subsets(thisInvSet#(rep), 2) list equivalenceBySingularLocus(ours#0, ours#1, Xs, (A, phi)) + +rep = reps#18 -- hessian and sing locus do not work here +#thisInvSet#(rep) +for ours in subsets(thisInvSet#(rep), 2) list equivalenceByHessian(ours#0, ours#1, Xs, (A, phi)) +for ours in subsets(thisInvSet#(rep), 2) list equivalenceBySingularLocus(ours#0, ours#1, Xs, (A, phi)) + +rep = reps#19 +#thisInvSet#(rep) +for ours in subsets(thisInvSet#(rep), 2) list equivalenceByHessian(ours#0, ours#1, Xs, (A, phi)) -- nope +for ours in subsets(thisInvSet#(rep), 2) list equivalenceBySingularLocus(ours#0, ours#1, Xs, (A, phi)) -- works + +rep = reps#20 -- this one is interesting: but it seems like adding in det + 1, det - 1 is a good plan. +#thisInvSet#(rep) +for ours in subsets(thisInvSet#(rep), 2) list equivalenceByHessian(ours#0, ours#1, Xs, (A, phi)) -- +for ours in subsets(thisInvSet#(rep), 2) list equivalenceBySingularLocus(ours#0, ours#1, Xs, (A, phi)) -- + +-- all the same +for ours in subsets(thisInvSet#(rep), 2) list equivalenceByGVCone(ours#0, ours#1, Xs, (A, phi)) -- + diff --git a/CYToolsM2/StringTorics/other/FindEquivalencesV2.m2 b/CYToolsM2/StringTorics/other/FindEquivalencesV2.m2 new file mode 100644 index 0000000..06bc1a6 --- /dev/null +++ b/CYToolsM2/StringTorics/other/FindEquivalencesV2.m2 @@ -0,0 +1,455 @@ +------------------------------------------------------- +-- OLD: replaced with IntegerEquivalences package ----- +-- TO BE REMOVED, do not use -------------------------- +------------------------------------------------------- + +debug needsPackage "StringTorics" -- let's arrange this so it doesn't need "debug"... + -- debug needed for (at least): genericLinearMap. + +-- MatchingData: is a list of elements each f the form +-- L => {M0, M1, ..., Ms} +-- where L is a list of: +-- RingElement: a polynomial in the original ring RZ or RQ. +-- Ideal: an ideal in the original ring. +-- Matrix: either a row vector or column vector, over ZZ or QQ (or RZ or RQ) +-- and each list Mi has the same length as L, and the same types of its elements. +MatchingData = new Type of List + +matchingData = method() +matchingData List := LMs -> ( + ans := new MatchingData from LMs; + if not isWellDefined ans then error "expected matching data to match. Set `debugLevel=1` to investigate"; + ans + ) + +-- helper function for validMatchingItem. +-- Input: either source or one of the targets of the matching data. +-- Output: a list of types. +itemType = L -> ( + -- L is a list or a single element of the following form + -- returns a list of RingElement, Ideal, RowVector, ColumnVector. + if not instance(L, List) then L = {L}; + for elem in L list ( + if instance(elem, RingElement) then RingElement + else if instance(elem, Ideal) then Ideal + else ( + if instance(elem, Matrix) then ( + if numrows elem === 1 then RowVector + else if numcols elem === 1 then ColumnVector + else Unknown + ) else + UNKNOWN + )) + ) + +-- helper function for (isWellDefined, MatchingData) +-- Input: one element (an Option, source and possible targets) of the matching data +-- which index this data sits at (used for error messages if debugLevel > 0) +-- Output: Boolean, whether this item is valid. +validMatchingItem = (LM,i) -> ( + L := LM#0; + M := LM#1; + -- M should be a list of lists, all same length and type as L. + Ltype := itemType L; + M' := if instance(M, List) then M else {M}; + Mtypes := for m in M' list itemType m; + if any(Ltype, x -> x === UNKNOWN) then ( + if debugLevel > 0 then << "one element in source is unknown" << endl; + return false; + ); + for x in Mtypes do ( + if x =!= Ltype then ( + if debugLevel > 0 then << "in source " << i << ", target doesn't match source = " << Ltype << " obtaining instead " << x << endl; + error "debug me"; + return false; + ); + ); + true + ) + +isWellDefined MatchingData := Boolean => LMs -> ( + for i from 0 to #LMs-1 do ( + LM := LMs#i; + if not instance(LM, Option) then ( + if debugLevel > 0 then << "elements of list must be of the form L => M" << endl; + return false; + ); + if not validMatchingItem(LM,i) then return false; + ); + true + ) + +matches = method() +matches MatchingData := List => (MD) -> ( + targets := cartesian (MD/(x -> if instance(x#1, List) then x#1 else {x#1})); + src := MD/first//flatten//toList; + (src, targets/flatten//toList) + -- XXX this is being tested now. + ) + +-- Used in creating MatchingData: use permutations or signedPermutations. +allSigns = method() +allSigns List := L -> ( + if #L <= 0 then return {{}}; + if #L == 1 then return {{L#0}, {-L#0}}; + flatten for q in allSigns(drop(L, 1)) list {prepend(L#0, q), prepend(-L#0, q)} + ) + +signedPermutations = method() +signedPermutations List := List => L -> ( + flatten for p in permutations L list allSigns p + ) + +cartesian = method() +cartesian List := (Ls) -> ( + -- cartesian product of Ls: one element from each + -- so the result is a list of lists. + if #Ls == 1 then return for p in Ls#0 list {p}; + Ls1 := cartesian drop(Ls,1); + flatten for p in Ls#0 list for q in Ls1 list prepend(p, q) + ) + +invertibleMatrixOverZZ = method() +invertibleMatrixOverZZ(Matrix, Ideal) := Sequence => (A, J) -> ( + -- returns (determinacy, A0), or (INCONSISTENT, null) or ...? + if J == 1 then + (INCONSISTENT, null) + else ( + A0 := A % J; + detA0 := (det A0) % J; + suppA0 := support A0; + if suppA0 === {} then ( + -- In this case we either have an integer matrix, or a rational matrix. + if liftable(detA0, ZZ) and all(flatten entries A0, f -> liftable(f, ZZ)) then + return (CONSISTENT, sub(A0, ZZ)); + return (INCONSISTENT, sub(A0, QQ)); + ); + jc := decompose J; + if isPrime J then return (INDETERMINATE, jc); + possibles := for j in jc list ( + ans := invertibleMatrixOverZZ(A0, j); + if ans#0 == CONSISTENT then return ans else ans + ); + if all(possibles, a -> a#0 === INCONSISTENT) then ( + ans := select(1, possibles, a -> instance(a#1, Matrix)); + if #ans > 0 then return ans#0 else return (INCONSISTENT, null); + ) + else + return (INDETERMINATE, jc); + ) + ) + +equivalenceIdeal = method() +equivalenceIdeal(List, List, Ring, Sequence) := Ideal => (List1, List2, RQ, Aphi) -> ( + if itemType List1 =!= itemType List2 then + error("expected two lists to have the same list of types, they are: " + | toString itemType List1 | " and " | toString itemType List2); + (A,phi) := Aphi; + TR := target phi; -- TODO: check: this is also source phi. + if TR =!= source phi then error "expected ring map with same source and target"; + if #List1 == 0 then return ideal(0_TR); + B := coefficientRing TR; + toTR := map(TR, RQ, vars TR); + toB := map(B, TR); + List1 = List1/(I -> if ring I =!= RQ then toTR (sub(I, RQ)) else toTR I); + List2 = List2/(I -> if ring I =!= RQ then toTR (sub(I, RQ)) else toTR I); + -- List1 and List2 are lists with the same length, consisting of RingElement's, Ideal's, Matrices. + -- List1 and List2 should each have RingElement's and Ideal's in the same spot. + ids := for i from 0 to #List1-1 list ( + if instance(List1#i, RingElement) then ( + ideal toB (last coefficients(phi List1#i - List2#i)) + ) + else if instance(List1#i, Ideal) then ( + ideal toB (last coefficients((gens phi List1#i) % List2#i)) + ) + else if instance(List1#i, Matrix) then ( + rowvec := (numrows List1#i === 1); + -- if rowvec is false, then this must be a column vector. + if rowvec then + ideal toB last coefficients sub(List2#i * (transpose A) - List1#i, TR) + else + ideal toB last coefficients sub((transpose A) * List1#i - List2#i, TR) + ) + ); + sum ids + ) + +tryEquivalencesV2 = method() +tryEquivalencesV2(MatchingData, Ring, Sequence) := (MD, RQ, Aphi) -> ( + (A,phi) := Aphi; + badJs := {}; + inconsistentMatrix := null; + (src, tar) := matches MD; + for i from 0 to #tar-1 do ( + << "doing " << i << endl; + J := trim equivalenceIdeal(src, tar#i, RQ, Aphi); + ans := invertibleMatrixOverZZ(A, J); + if ans#0 == CONSISTENT then return ans; + if ans#0 == INCONSISTENT and instance(ans#1, Matrix) then inconsistentMatrix = ans#1; + if ans#0 == INDETERMINATE then ( + badJs = join(badJs, ans#1); + ); + ); + if #badJs > 0 then return (INDETERMINATE, badJs); + (INCONSISTENT, inconsistentMatrix) + ) + +factorsByType = method() +factorsByType RingElement := HashTable => F -> ( + facs := factors F; + faclist := for fx in facs list (fx#0, sum first exponents fx#1, fx#1); + H := partition(x -> {x#0, x#1}, faclist); + hashTable for k in keys H list k => for x in H#k list x_2 + ) + +idealsByBettiV2 = method() +idealsByBettiV2(List, List) := List => (J1s, J2s) -> ( + H1 := partition(J -> betti gens J, J1s); + H2 := partition(J -> betti gens J, J2s); + if sort keys H1 =!= sort keys H2 then return {}; + for k in sort keys H1 list ( + H1#k => permutations H2#k + ) + ) + +-* +hessianMatchesV2 = method() +hessianMatchesV2(Thing, Thing, HashTable, Sequence) := List => (lab1, lab2, Xs, Aphi) -> ( + -- XXXX WORK ON THIS + (A,phi) := Aphi; + X1 := Xs#lab1; + X2 := Xs#lab2; + (L1, F1) := (c2Form X1, cubicForm X1); + (L2, F2) := (c2Form X2, cubicForm X2); + fac1 := factorsByType(det hessian F1); + fac2 := factorsByType(det hessian F2); + keyset1 := sort for k in sort keys fac1 list if k === {1,0} then (cH1 = fac1#k; continue) else k; + keyset2 := sort for k in sort keys fac2 list if k === {1,0} then (cH2 = fac2#k; continue) else k; + if keyset1 =!= keyset2 then error "expected same factors and their degrees"; + ans := for k in keyset1 list + fac1#k => signedPermutations fac2#k + checkFormat ans; + ans + ) + +singularLocusMatchesV2 = method() +singularLocusMatchesV2(Thing, Thing, HashTable, Sequence) := List => (lab1, lab2, Xs, Aphi) -> ( + -- XXXX WORK ON THIS + -- returns a list of pairs: + -- L1 => {L2a, L2b, ...} + -- where L1 and each L2i have the same length, + -- and every element is a RingElement, or an ideal + -- possible todo: allow a point in H^2 as well. + (A,phi) := Aphi; + X1 := Xs#lab1; + X2 := Xs#lab2; + (L1, F1) := (c2Form X1, cubicForm X1); + (L2, F2) := (c2Form X2, cubicForm X2); + RQ := QQ (monoid ring L1); + FQ1 = sub(F1, RQ); + FQ2 = sub(F2, RQ); + sing1 := trim saturate(ideal FQ1 + ideal jacobian FQ1); + sing2 := trim saturate(ideal FQ2 + ideal jacobian FQ2); + if sing1 == 1 then return {}; + comps1 := (decompose sing1)/trim; + comps2 := (decompose sing2)/trim; + ans := append(idealsByBettiV2(comps1, comps2), {sing1} => {sing2}); + checkFormat ans; + ans + ) + +equivalenceByHessian(Thing, Thing, HashTable, Sequence) := List => (lab1, lab2, Xs, Aphi) -> ( + << "Calling new code" << endl; + (A,phi) := Aphi; + X1 := Xs#lab1; + X2 := Xs#lab2; + (L1, F1) := (c2Form X1, cubicForm X1); + (L2, F2) := (c2Form X2, cubicForm X2); + (list1, list2perms) := hessianMatches(lab1, lab2, Xs, Aphi); + list1 = join(list1, {L1, F1}); + list2perms = for list2 in list2perms list join(list2, {L2, F2}); + tryEquivalences(list1, list2perms, Aphi) + ) +*- + +end-- + +restart +load "FindEquivalencesV2.m2" + +DBNAME = "./Databases/cys-ntfe-h11-3.dbm" +RZ = ZZ[a,b,c] +RQ = QQ (monoid RZ); +elapsedTime (Qs, Xs) = readCYDatabase(DBNAME, Ring => RZ); + +F1 = 3*a^2*b-3*a*b^2+b^3+6*a^2*c-6*a*c^2+2*c^3 +L1 = 24*a+10*b+8*c +F2 = F1 +L2 = L1 +M1 = a +M2 = b +M3 = c +N1 = a+b +N2 = a+c +N3 = 2*b+c + +debugLevel = 1 +matchingData { + F1 => F2, + L1 => L2, + {M1,M2,M3} => {{N1,N2,N3}}, + matrix{{1,2,3}} => matrix{{1,-2,1}} + } + +TEST /// + needs "FindEquivalencesV2.m2" + assert(# signedPermutations{1,2,3} === 48) + assert(# permutations{1,2,3} === 6) + assert(cartesian{{1,2}} == {{1}, {2}}) + assert(cartesian{{1,2}, {3,4}} === {{1, 3}, {1, 4}, {2, 3}, {2, 4}}) + assert(cartesian{{1,2},{3,4},{5,6}} === {{1, 3, 5}, {1, 3, 6}, {1, 4, 5}, {1, 4, 6}, {2, 3, 5}, {2, 3, 6}, {2, 4, 5}, {2, 4, 6}}) + assert(cartesian{{1,2},{3},{5,6}} === {{1, 3, 5}, {1, 3, 6}, {2, 3, 5}, {2, 3, 6}}) +/// + +TEST /// + factor det hessian F1 + factorsByType det hessian F1 +/// + +TEST /// + restart + needs "FindEquivalencesV2.m2" + RZ = ZZ[a,b,c] + RQ = QQ (monoid RZ) + (A,phi) = genericLinearMap RQ + + -- Here is how we construct these polynomials (using h11=3 database). + --(L1, F1) = (c2Form Xs#(26,0), cubicForm Xs#(26,0)) + --(L2, F2) = (c2Form Xs#(37,0), cubicForm Xs#(37,0)) + + (L1, F1) = (10*a+28*b+26*c,a^3-3*a^2*b-3*a*b^2-2*b^3-3*a^2*c+6*a*b*c+6*b^2*c+3*a*c^2+6*b*c^2-c^3) + (L2, F2) = (16*a+10*b+26*c,-2*a^3-3*a^2*b-3*a*b^2+b^3+6*a*b*c-3*b^2*c+6*a*c^2+3*b*c^2-c^3) + + MD = matchingData { + L1 => L2, + F1 => F2 + } + (src, tars) = matches MD + J = equivalenceIdeal(src, tars#0, RQ, (A,phi)) + A % J + assert(first invertibleMatrixOverZZ(A, J) == INCONSISTENT) +/// + +TEST /// + restart + needs "FindEquivalencesV2.m2" + RZ = ZZ[a,b,c] + RQ = QQ (monoid RZ) + (A,phi) = genericLinearMap RQ + + -- Here is how we construct these polynomials (using h11=3 database). + -- (L1, F1) = (c2Form Xs#(190,0), cubicForm Xs#(190,0)) + -- (L2, F2) = (c2Form Xs#(193,0), cubicForm Xs#(193,0)) + + (L1, F1) = (8*a-4*b+36*c,2*a^3-3*a^2*b-3*a*b^2+8*b^3-6*a^2*c+6*a*b*c-6*b^2*c+6*a*c^2) + (L2, F2) = (-4*a+8*b+36*c,8*a^3-3*a^2*b-3*a*b^2+2*b^3-6*a^2*c+6*a*b*c-6*b^2*c+6*b*c^2) + factorsByType det hessian F1 + + MD = matchingData { + L1 => L2, + F1 => F2 + } + (src, tars) = matches MD + J = equivalenceIdeal(src, tars#0, RQ, (A,phi)) + A % J + assert(first invertibleMatrixOverZZ(A, J) == CONSISTENT) +/// + + +/// + restart + needs "FindEquivalencesV2.m2" + + DBNAME = "./Databases/cys-ntfe-h11-3.dbm" + RZ = ZZ[a,b,c] + RQ = QQ (monoid RZ); + elapsedTime (Qs, Xs) = readCYDatabase(DBNAME, Ring => RZ); + (A,phi) = genericLinearMap RQ + + labs = {(183, 0), (194, 1), (195, 0), (197, 0)} + factorsByType det hessian cubicForm Xs#(labs#0) + factorsByType det hessian cubicForm Xs#(labs#1) +/// + + (L1, F1) = (c2Form Xs#(54,0), cubicForm Xs#(54,0)) + (L2, F2) = (c2Form Xs#(234,0), cubicForm Xs#(234,0)) + + + + FQ1 = sub(F1, RQ) + FQ2 = sub(F2, RQ) + sing1 = trim saturate(ideal FQ1 + ideal jacobian FQ1) + sing2 = trim saturate(ideal FQ2 + ideal jacobian FQ2) + if sing1 == 1 then return {}; + comps1 := (decompose sing1)/trim; + comps2 := (decompose sing2)/trim; + idealsByBettiV2(comps1, comps2) + ans := append(idealsByBettiV2(comps1, comps2), {sing1} => {sing2}); + + +/// + +MD = matchingData { + F1 => F2, + L1 => L2, + {M1,M2,M3} => permutations {N1,N2,N3}, + matrix{{1,2,3}} => matrix{{1,-2,1}} + } +(src,tar) = matches MD +(A, phi) = genericLinearMap RQ +J = equivalenceIdeal(src, tar#0, RQ, (A,phi)) +tryEquivalencesV2(MD, RQ, (A,phi)) + +debugLevel = 1 +MD1 = matchingData { + a+2*b+3*c => a-b + } +MD2 = matchingData { + transpose matrix{{1,2,3}} => transpose matrix{{1,-1,0}} + } + +(src, tar) = matches MD1 + +J1 = equivalenceIdeal(src, tar#0, RQ, (A,phi)) + + +(src, tar) = matches MD2 +J2 = equivalenceIdeal(src, tar#0, RQ, (A,phi)) +J1 == J2 + +MD3 = matchingData { + a+2*b+3*c => a-b, + a-b => c, + c => a+b+c + } +(src, tar) = matches MD3 +J = equivalenceIdeal(src, tar#0, RQ, (A,phi)) +J + ideal((det A) - 1) +A % oo + + + +cartesian (MD/(x -> if instance(x#1, List) then x#1 else {x#1})) + +MD = matchingData { + F1 => F2, + L1 => L2, + {M1,M2,M3} => signedPermutations {N1,N2,N3}, + matrix{{1,2,3}} => matrix{{1,-2,1}} + } +cartesian (MD/(x -> if instance(x#1, List) then x#1 else {x#1})) + +MD/(x -> x#0)//flatten +MD/(x -> x#1) +netList oo + diff --git a/CYToolsM2/StringTorics/test.m2 b/CYToolsM2/StringTorics/test.m2 new file mode 100644 index 0000000..24d822a --- /dev/null +++ b/CYToolsM2/StringTorics/test.m2 @@ -0,0 +1,1683 @@ +TEST /// + -- XX TODO: being worked on now 29 June 2023 + -- Checking the methods for CYPolytope's + -- We eventually want to test this for: favorable, non-favorable, torsion V. + +-* + restart + needsPackage "StringTorics" +*- + debug needsPackage "StringTorics" + + tope = KSEntry "4 13 M:34 13 N:12 10 H:7,29 [-44] id:40 + 1 0 0 0 0 -2 -2 1 2 1 2 2 -2 + 0 1 0 0 0 2 1 -1 -2 -2 0 -2 0 + 0 0 1 -1 0 -1 0 -1 1 0 1 -1 1 + 0 0 0 0 1 1 2 1 -2 -1 -2 0 0 + " + Q = cyPolytope(tope, ID => 40) + assert isFavorable Q + basisIndices Q + Q.cache#"toric basis indices" + Q.cache#"basis indices" + transpose matrix degrees Q + X = makeCY Q + toricIntersectionNumbers X + intersectionNumbers X + assert(c2 X === {-4, 10, 12, 10, 18, 0, 10}) + cubicForm X + c2Form X + assert(ring cubicForm X === ring c2Form X) + + nonfavTope = KSEntry "4 7 M:28 7 N:11 7 H:7,27 [-40] id:9 + 1 0 3 0 -1 -3 -6 + 0 1 2 0 0 -2 -5 + 0 0 4 1 0 -2 -8 + 0 0 0 2 2 2 -4 + " + + Q2 = cyPolytope nonfavTope + assert not isFavorable Q2 + assert(hh^(1,1) Q2 == 7) + assert(hh^(1,2) Q2 == 27) + -- the following will need to change... + assert(basisIndices Q2 === {0, 1, 2, 3, 4, (9, 0), (9, 1)}) -- this could change if the algorithm changes. + Q2.cache#"toric basis indices" === {0, 1, 2, 3, 4, 9} + findTwoFaceInteriorDivisors Q2 + netList annotatedFaces Q2 + assert( + rays Q2 === {{-1, -1, 1, -1}, + {-1, -1, 1, 1}, + {-1, -1, 2, -1}, + {-1, 0, 1, -1}, + {-1, 3, -1, 0}, + {1, 0, -1, 0}, + {3, -1, -2, 1}, + {-1, -1, 1, 0}, + {1, -1, 0, 0}, + {-1, 1, 0, 0}} + ) + Xs = findAllCYs Q2; -- what if I only want the NTFE ones? FIX. + #Xs + (netList toricIntersectionNumbers Xs#0, netList intersectionNumbers Xs#0) + c2 Xs#0 -- fix me + intersectionNumbers Xs#0 -- fix me + ring cubicForm Xs#0 === ring c2Form Xs#0 + c2Form Xs#0 + + vertices polytope(Q2, "M") + vertices polytope(Q2, "N") -- notice these are NOT in the order of the rays of Q2! + transpose matrix degrees Q2 + + transpose matrix rays Q2 + + cubicForm Xs#0 +/// + +/// + -- Checking on the interface of the package. +-* + restart + needsPackage "StringTorics" +*- + debug needsPackage "StringTorics" + topes = kreuzerSkarke(5, Limit => 10000); + #topes == 4990 + A = matrix topes_40 -- this will be vertices of a polytope in the M lattice + -- We need to get to a triangulation of the dual polytope... + X0 = cyPolytope topes_40 + X = makeCY(X0, Ring => (RZ = ZZ[s_1..s_5])) + + -- X = calabiYau(A, Lattice => "M") -- A must define a reflexive polytope. + + V = ambient X + aX = abstractVariety(X, base(a,b,c,d,e)) + intersectionRing aX -- defines integral. + intersectionRing V -- defines integral. + topX = topologicalData X + cubicForm topX + isFavorable cyPolytope X + + intersectionNumbers X + toricIntersectionNumbers X + c2 X + cubicForm X + c2Form X +/// + +TEST /// +-* + restart + needsPackage "StringTorics" +*- + str4 = " 1 0 0 0 1 1 0 -1 -1 -2 -4 + 0 1 1 0 -2 2 3 -1 -4 1 -1 + 0 0 2 0 -2 4 4 -1 -4 -2 -4 + 0 0 0 1 0 -2 -2 2 2 0 2 + " + A = matrixFromString str4 + P = convexHull A + V = reflexiveToSimplicialToricVariety P + X = completeIntersection(V, {-toricDivisor V}) + pt = base(a,b,c) + Xa = abstractVariety(X, pt) + I = intersectionRing Xa + a*t_1 + hodgeDiamond X + assert(h11OfCY P == 6) + assert(h21OfCY P == 50) + a*t_1 -- should still work... +/// + + +TEST /// +-* + restart +*- + debug needsPackage "StringTorics" + -- augmentWithOrigin + mat = " 1 0 0 1 -3 3 3 -3 5 + 0 1 0 0 2 -4 -6 4 -8 + 0 0 1 0 2 -2 -2 0 -4 + 0 0 0 2 0 -4 -6 6 -6 " + A = matrixFromString mat; + assert( + augmentWithOrigin A + == + matrix { + {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, + {1, 0, 0, 1, -3, 3, 3, -3, 5, 0}, + {0, 1, 0, 0, 2, -4, -6, 4, -8, 0}, + {0, 0, 1, 0, 2, -2, -2, 0, -4, 0}, + {0, 0, 0, 2, 0, -4, -6, 6, -6, 0} + } + ) +/// + + +TEST /// + -- readSageTriangulation + Ts = readSageTriangulations sageTri + + -- let's also switch to a different choice of rays + -- Bstr is the lattice points (a.k.a. rays) used by Cody's code in Sage. + Bstr = "[ 1 -1 -1 1 -1 -1 -1 1 1 0] +[ 0 1 0 -1 1 0 0 -1 -1 0] +[-1 0 0 0 1 1 0 0 0 0] +[ 2 0 0 1 -1 -1 -1 -1 0 0]" + -- rays coming from M2 + Amat = matrix {{-1, -1, -1, -1, -1, 1, 1, 1, 1}, {0, 0, 0, 1, 1, -1, -1, -1, 0}, {0, 0, 1, 0, 1, 0, 0, 0, -1}, {-1, 0, -1, 0, -1, -1, 0, 1, 2}} + Bmat = matrixFromString Bstr + + (fromM2, toM2) = matchNonZero(Amat, Bmat) + applyPermutation(toM2, Ts) + + assert( + applyPermutation(toM2, {0,1,2,3}) + == + {1,3,7,8} + ) +/// + +-- commenting this out. It should really be a test in ReflexivePolytopesDB +/// + L1 = kreuzerSkarke(5,57, Access => "wget"); + assert(#L1 == 197) + + L2 = kreuzerSkarke(5,57, Access => "curl"); + assert(#L2 == 197) + + assert(L1 === L2) +/// + +TEST /// + -- XXX TODO: This test should be in Triangulations? + -- Test functionality of triangulations, part 1. Basic tests + -- +-* +restart +needsPackage "StringTorics" +*- + -- WARNING: currently, we use the polar dual of a convex polytope to determine + -- minimal faces, etc. However, for this to work, the convex polytope + -- MUST contain the origin in the interior. + -- Here are the functions that won't work if this is not the case: + --polar P -- doesn't work as expected, since the origin is not an interior point of the polytope. + -- minimalFace(P, pts) + -- dualFace(P,f) + -- latticePointList(P,f) + -- genus(P,f) + -- annotatedFaces P + -- annotatedFaces(i,P) + -- TODO: it would be possible to get all of these to work, except genus, and dualFace, + -- by implementing them a bit differently. Is it worth it? Most polytopes of interest will contain + -- the origin in the interior? + + A = transpose matrix{{0,0,0},{0,0,1},{0,1,0},{0,1,1},{1,0,0},{1,0,1},{1,1,0},{1,1,1}} + A1 = matrix{{8:1}} || A + P = convexHull A + assert(dim P == 3) + + vertices P + latticePoints P + faces P + faces(1,P) + + LP = latticePointList P + assert(set LP === set {{1, 1, 1}, {0, 1, 1}, {1, 0, 1}, {1, 1, 0}, {0, 0, 1}, {0, 1, 0}, {1, 0, 0}, {0, 0, 0}}) + assert(set vertexList P === set {{0, 0, 0}, {0, 0, 1}, {0, 1, 0}, {0, 1, 1}, {1, 0, 0}, {1, 0, 1}, {1, 1, 0}, {1, 1, 1}}) + assert(entries transpose vertexMatrix P == vertexList P) + + assert(# faceList P == 27) + faceDimensionHash P + for f in faceList P do assert (2^(dim(P,f)) === #f) + assert(faceList(0,P) == for i from 0 to 7 list {i}) + + Amat = transpose matrix LP + tri = regularFineTriangulation Amat + assert naiveIsTriangulation tri + assert topcomIsTriangulation(Amat, max tri) + + -- check what happens if Amat is homoogenized: + AmatH = Amat || matrix{{8:1}} + naiveIsTriangulation(AmatH, max tri) -- this should be false...? TODO: this is a bug!! + assert not topcomIsTriangulation(AmatH, max tri) -- good! it complains that the index sets are not full dimensional (I think that is good?) + + assert(affineCircuits tri == affineCircuits(Amat, max tri)) + for x in affineCircuits tri list bistellarFlip(tri, x) + neighbors tri + + generateTriangulations tri + allTriangulations(Amat, RegularOnly => false, ConnectedToRegular => false, Fine => false) + + generateTriangulations(tri, RegularOnly => true) + assert(# allTriangulations Amat == 74) + assert(# generateTriangulations(tri, RegularOnly => true) == 74) + + -- let's check that this is a triangulation. + -- part of what we are checking: calls relative to homogenization are correct, and types make sense. + -- part 1: for each oriented circuit + circs = orientedCircuits transpose matrix LP + assert(circs == { + {{0, 4}, {1, 2}}, {{0, 4, 5}, {1, 6}}, {{0, 4, 6}, {2, 5}}, {{0, 5}, {1, 3}}, + {{0, 5, 6}, {3, 4}}, {{0, 6}, {2, 3}}, {{0, 7}, {1, 2, 3}}, {{0, 7}, {1, 6}}, + {{0, 7}, {2, 5}}, {{0, 7}, {3, 4}}, {{0, 7}, {4, 5, 6}}, {{1, 2, 7}, {3, 4}}, + {{1, 3, 7}, {2, 5}}, {{1, 6}, {2, 3, 7}}, {{1, 6}, {2, 5}}, {{1, 6}, {3, 4}}, + {{1, 7}, {4, 5}}, {{2, 5}, {3, 4}}, {{2, 7}, {4, 6}}, {{3, 7}, {5, 6}} + } + ) + Ts = generateTriangulations(tri, RegularOnly => true) + assert(Ts/isWellDefined//unique == {true}) + + -- it is possible that another triangulation would be output. + -- the following is more like possible code to decide if a subset is a triangulation. + -- It works currently, so I'll keep it... + assert(max tri == {{0, 1, 2, 3}, {1, 2, 3, 4}, {1, 3, 4, 5}, {2, 3, 4, 6}, {3, 4, 5, 6}, {4, 5, 6, 7}}) + for c in circs list ( + n1 := # select(max tri, t -> isSubset(c#0, t)); + n2 := # select(max tri, t -> isSubset(c#1, t)); + ok := n1 == 0 or n2 == 0 or n1 == #(max tri) or n2 == #(max tri); + (n1,n2,ok) + ) + + walls = tri//max/(x -> subsets(x, #x-1))//flatten + nfacets = tally walls + facs = (faces(1,P))/first + walls = partition(k -> nfacets#k, keys nfacets) + facs = for f in facs list latticePointList(P, f) + for w in walls#1 list ( + # select(facs, f -> isSubset(w, f)) + ) + for w in walls#2 list ( + # select(facs, f -> isSubset(w, f)) + ) + + walls#2 -- 6 walls here. Compute the vector for each. + matrix {for w in walls#2 list ( + --w = {2,3,4} -- a wall + circ := select(max tri, t -> isSubset(w, t)); + others := circ/(c -> toList(set c - set w)); + elems := (flatten others) | w; + print elems; + id_(ZZ^8)_elems * syz AmatH_elems + )} + --id_(ZZ^8)_{1,6,2,3,4} * syz AmatH_{1,6,2,3,4} +/// + +TEST /// + -- XXX + -- simple test of the polyhedral functions here: on the cube with the origin as its only + -- interior point + needsPackage "StringTorics" + P = hypercube 3 + assert isCompact P -- These functions fail if P is not a polytope. + assert( + vertices P == matrix(QQ, { + {-1, 1, -1, 1, -1, 1, -1, 1}, + {-1, -1, 1, 1, -1, -1, 1, 1}, + {-1, -1, -1, -1, 1, 1, 1, 1} + }) + ) + vertices2 = vertexList P + vertices3 = entries transpose vertexMatrix P + assert(vertices2 == vertices3) + + LP = latticePointList P + LP2 = transpose entries lift(matrix {latticePoints P}, ZZ) + assert(set LP === set LP2) + assert(27 == # LP) + assert(27 == # LP2) + + assert(# faceList P == 27) + faceDimensionHash P + for f in faceList P do assert (2^(dim(P,f)) === #f) + assert(faceList(0,P) == for i from 0 to 7 list {i}) + + hashTable for pt in LP list pt => minimalFace(P, pt) + for pt in LP do ( + f := minimalFace(P, pt); + assert(2^(# select(pt, v -> v == 0)) == #f) + ) + P2 = polar P + for f in faceList P list (f, dualFace(P, f)) + faces P + faceList P + assert(set((flatten values faces P)/first) === set faceList P) + for f in faceList P list ( + latticePointList(P, f) + ) + + -- annotatedFaces + netList annotatedFaces P + for p in annotatedFaces P do ( + f := p#1; + assert(p#0 == dim(P,f)); + lps := latticePointList(P, f); + assert(p#2 == lps); + assert(p#3 == # interiorLatticePointList(P,f)); + assert(p#4 == genus(P,f)) + ) + +-* + TODO: BUG!! These give segfaults on my Apple M1. + debugLevel = 3 + regularFineTriangulation vertices P + regularStarTriangulation P -- it is a shame that this returns something different from regularFineTriangulation. +*- +/// + +TEST /// + -- Test of triangulation code +-* + restart + needsPackage "StringTorics" +*- + -- XXX + topes = kreuzerSkarke 3; + A = matrix topes_30 + Q = cyPolytope topes_30 + hh^(1,1) Q + P1 = polytope(Q, "M") + P2 = polytope(Q, "N") + vertices P1 + vertices P2 + P2 == polytope Q + findAllFRSTs P2 + Amat = transpose matrix latticePointList polytope Q + assert(Amat == transpose matrix {{-1, -1, 0, 0}, {-1, -1, 0, 1}, {-1, -1, 2, 0}, {-1, 0, 0, 0}, {1, -1, -1, 1}, {1, 2, -1, -1}, {-1, -1, 1, 0}, {0, 0, 0, 0}}) +/// + +TEST /// + -- Test of triangulation code +-* + restart + needsPackage "Triangulations" +*- + Amat = transpose matrix {{-1, -1, 0, 0}, {-1, -1, 0, 1}, {-1, -1, 2, 0}, {-1, 0, 0, 0}, {1, -1, -1, 1}, {1, 2, -1, -1}, {-1, -1, 1, 0}, {0, 0, 0, 0}} + regularSubdivision(Amat, matrix{{0,0,1,3,6,9,20,30}}) -- seems incorrect. + TRI = regularFineTriangulation Amat -- is this including the origin automatically? + wts = regularTriangulationWeights TRI + -- check that this is a triangulation! + TRI2 = regularSubdivision(Amat, matrix{{2, 4, 2, 0, 0, 0, 0, 0}}) -- good! + TRI = TRI//max/sort//sort + TRI2 = TRI2/sort//sort + assert(TRI === TRI2) -- works! + assert topcomIsTriangulation(Amat, TRI) + assert naiveIsTriangulation(Amat, TRI) + + -- let's check 'affineCircuits' + C = affineCircuits(Amat, TRI) + 4! * volumeVector(Amat, TRI) + bistellarFlip(TRI, C_0) === null + bistellarFlip(TRI, C_1) === null + + TRI2 = bistellarFlip(TRI, C_2) + wts2 = regularTriangulationWeights(Amat, TRI2) + assert(wts2 == {1, 1, 2, 0, 0, 0, 0, 0}) -- doesn't really need to be the same. + TRI2' = regularSubdivision(Amat, matrix {wts2}) -- good! + assert(TRI2 == TRI2') + + TRI3 = bistellarFlip(TRI, C_3) + wts3 = regularTriangulationWeights(Amat, TRI3) + TRI3' = regularSubdivision(Amat, matrix {wts3}) -- good! + assert(TRI3 == TRI3') + + bistellarFlip(TRI, C_4) === null + + bistellarFlip(TRI, C_5) === null + + TRI6 = bistellarFlip(TRI, C_6) + wts6 = regularTriangulationWeights(Amat, TRI6) + assert(wts6 == {-1, 3, 2, 0, 0, 0, 0, 0}) -- doesn't need to be the case. + TRI6' = regularSubdivision(Amat, matrix{wts6}) -- good! + assert(TRI6' == TRI6) + + 4! * volumeVector(Amat, TRI) + 4! * volumeVector(Amat, bistellarFlip(TRI, C_2)) + 4! * volumeVector(Amat, bistellarFlip(TRI, C_3)) + 4! * volumeVector(Amat, bistellarFlip(TRI, C_6)) +/// + +TEST /// + -- Test functionality of triangulations, part 2. reflexive polytope in 4D + -- We try one with h11=3 + needsPackage "StringTorics" + tope = "4 13 M:64 13 N:8 7 H:3,51 [-96] + 1 0 0 2 -2 0 -1 -1 0 2 2 -3 -3 + 0 1 1 3 -5 2 0 0 2 4 4 -6 -6 + 0 0 4 0 -4 5 4 -1 0 1 0 -4 -5 + 0 0 0 4 -4 1 -1 -1 1 5 5 -5 -5" + A = matrix first kreuzerSkarke tope + P = convexHull A + P2 = polar P + V = reflexiveToSimplicialToricVariety P + assert isFavorable P + assert isCompact P + assert isCompact P2 + -- regularFineTriangulation (from topcom) + -- regularFineStarTriangulation + -- isRegularTriangulation (from topcom) + nonzeroLP = transpose matrix drop(latticePointList P2,-1) + LP = transpose matrix latticePointList P2 + chirotope nonzeroLP + + regularFineTriangulation nonzeroLP + regularFineTriangulation LP + regularStarTriangulation P2 +/// + +TEST /// + -- this is an example of a polytope with 200 lattice points. + tope = "4 12 M:72 12 N:276 12 H:200,50 [300] + 1 0 0 0 -14 -1 -17 -4 -5 -9 -15 -29 + 0 1 0 0 -9 -1 -11 -2 -4 -6 -10 -20 + 0 0 1 0 -3 0 -4 -2 -2 -4 -6 -10 + 0 0 0 1 -1 1 -1 1 2 2 2 2" + A = matrix first kreuzerSkarke tope + P = convexHull A + P2 = polar P + elapsedTime faces P2; + elapsedTime halfspaces P2 + LP = latticePoints P2 + # faces(1,P2) + elapsedTime regularFineTriangulation matrix transpose latticePointList P2; + V = reflexiveToSimplicialToricVariety P + rays V + max V +/// + +TEST /// + -- testing triangulations of fans + -- Our plan: start with example #26 from Kreuzer-Skarke with h11=5, h12=57 + -- this one has a number of triangulations. + -- How do we create Amat? This is the way: + -- 4 11 M:58 11 N:10 8 H:5,51 [-92] + -- XXXXXXXXXX This test is failing May 2022. +-* + restart +*- + needsPackage "StringTorics" + mat = " 1 1 1 -1 0 1 1 -1 -3 -1 -3 + 0 2 0 0 0 0 2 -2 -2 -2 -4 + 0 0 2 -2 0 -2 2 2 -2 4 2 + 0 0 0 0 1 -2 0 2 0 2 2" + A = matrixFromString mat + P1 = convexHull A -- (extremal) vertices in RR^4 + P2 = polar P1 + LP = latticePoints P2 -- these will be the origin, the extremal vertices of P2 and possibly some more. + Amat = matrix {select(LP, x -> x != 0)} + elapsedTime allTRIS = generateTriangulations(Amat, RegularOnly => true); -- removed in commit 33e77a592d2890c7ebf134e13b95d5915a624039 + + -- now let's change these to sage indexing + Bstr = "[ 1 -1 -1 1 -1 -1 -1 1 1 0] + [ 0 1 0 -1 1 0 0 -1 -1 0] + [-1 0 0 0 1 1 0 0 0 0] + [ 2 0 0 1 -1 -1 -1 -1 0 0]" + -- rays coming from M2 + Bmat = matrixFromString Bstr + + (fromM2, toM2) = matchNonZero(Amat, Bmat) + + Ts = readSageTriangulations sageTri + -- checkFan is no longer available. + --elapsedTime for T in Ts do time checkFan(Bmat, T) -- this takes a while (24 seconds), too long for testing + --elapsedTime checkFan(Bmat, Ts_5) + applyPermutation(fromM2, allTRIS/max) + + -- the following are all in this list + time TRI = regularFineStarTriangulation Amat -- this appears to not be returning regular triangulations? + Amat0 = Amat | transpose matrix{{0,0,0,0}}; + wts = regularTriangulationWeights(Amat0, TRI) + regularSubdivision(Amat0, matrix{wts}) + assert(oo == TRI) + + -- make a toric variety from one of the triangulations: (fine regular star...) + -- elapsedTime assert({(true, true, true)} === + -- unique for T in allTRIS list ( + -- X = normalToricVariety(entries transpose Amat, max T); + -- time (isWellDefined X, isSimplicial X, isComplete X, isProjective X) + -- ) + -- ) +/// + +TEST /// + -- analyze polytopes with h11=30, h12=50. + -- grabbed 3000 examples, but there are more! +-* + restart + needsPackage "StringTorics" +*- + -- one of the "favorable" examples + -- 4 7 M:51 7 N:45 7 H:30,50 [-40] + mat = " 1 0 0 0 0 -4 -10 + 0 1 0 0 2 2 -10 + 0 0 1 0 -3 -7 5 + 0 0 0 1 2 2 -4" + + A = matrixFromString mat + P1 = convexHull A -- (extremal) vertices in RR^4 + P2 = polar P1 + LP = latticePoints P2 -- these will be the origin, the extremal vertices of P2 and possibly some more. + Amat = matrix {select(LP, x -> x != 0)} + + elapsedTime regularStarTriangulation P2; + elapsedTime TRI = regularFineStarTriangulation Amat; + assert(sort unique flatten TRI == toList(0..numcols Amat)) +/// + +TEST /// + -- 4 10 M:105 10 N:71 10 H:50,80 [-60] + mat = " 1 0 0 0 -1 -1 -1 -5 -15 -15 + 0 1 0 0 0 -2 -2 -6 -8 -16 + 0 0 1 0 1 1 0 -2 -6 -6 + 0 0 0 1 -1 1 2 4 0 8" + + A = matrixFromString mat + P1 = convexHull A -- (extremal) vertices in RR^4 + P2 = polar P1 + LP = latticePoints P2 -- these will be the origin, the extremal vertices of P2 and possibly some more. + Amat = matrix {select(LP, x -> x != 0)} + + elapsedTime TRI = regularFineStarTriangulation Amat; + assert(sort unique flatten TRI == toList(0..numcols Amat)) +/// + +TEST /// + -- creating simplicial toric varieties from data base + -- 4 10 M:105 10 N:71 10 H:50,80 [-60] + mat = " 1 0 0 0 -1 -1 -1 -5 -15 -15 + 0 1 0 0 0 -2 -2 -6 -8 -16 + 0 0 1 0 1 1 0 -2 -6 -6 + 0 0 0 1 -1 1 2 4 0 8" + + A = matrixFromString mat + P1 = convexHull A + P2 = polar P1 + (LP,tri) = regularStarTriangulation P2 + V = normalToricVariety(LP,tri) + assert isSimplicial V + assert not isSmooth V + --assert elapsedTime isWellDefined V -- this currently takes some time + + (LP,tri) = regularStarTriangulation(2,P2) + V = normalToricVariety(LP,tri) + assert isSimplicial V + assert not isSmooth V + --assert isWellDefined V -- this currently takes some time + + V1 = reflexiveToSimplicialToricVariety P1 + assert isSimplicial V + assert not isSmooth V +/// + +TEST /// + -- toric complete intersection cohomology code + -- YYY +-* + restart + needsPackage "StringTorics" +*- + mat = " 1 1 1 -1 0 1 1 -1 -3 -1 -3 + 0 2 0 0 0 0 2 -2 -2 -2 -4 + 0 0 2 -2 0 -2 2 2 -2 4 2 + 0 0 0 0 1 -2 0 2 0 2 2" + A = matrixFromString mat + P = convexHull A + V = reflexiveToSimplicialToricVariety P + KV = toricDivisor V + X = completeIntersection(V, {-KV}) + hodgeDiamond X + assert(h11OfCY P == 5) + assert(h21OfCY P == 51) + assert(cohomologyVector X == {1,0,0,1}) + cohomologyVector(X, degree(V_0+V_1+V_2)) + allsums = drop(subsets for i from 0 to #rays V - 1 list V_i, 1); + allsums = allsums/sum; + elapsedTime for i from 0 to 100 list cohomologyVector(X, degree allsums_i) + for i from 0 to 10 list cohomologyVector(X, 2 * degree allsums_i) +/// + +-- example: regular star triangulations +/// +-* + restart +*- + needsPackage "StringTorics" + mat = " 1 1 1 -1 0 1 1 -1 -3 -1 -3 + 0 2 0 0 0 0 2 -2 -2 -2 -4 + 0 0 2 -2 0 -2 2 2 -2 4 2 + 0 0 0 0 1 -2 0 2 0 2 2" + A = matrixFromString mat + P = convexHull A + V = reflexiveToSimplicialToricVariety P + pts = transpose matrix rays V + pts = pts || matrix{{numColumns pts : 1}} + T = max V -- triangulation + -- is this list correct, or do we need to "homogenize 'pts'? + annotatedFaces polar P + ac = select(affineCircuits(pts,T), x -> #x#0 > 1 and #x#1 > 1) + ac = unique(ac/sort//sort) + netList oo + volumeVector(pts, T) + ac#0 + T1 = flip(T,ac#0) + volumeVector(pts, T1) + checkFan(pts, T1) + checkFan(pts, T) + isRegularTriangulation(pts,T) + isRegularTriangulation(pts,T1) + triS = new MutableHashTable from {T=>true} + ac = select(affineCircuits(pts,T), x -> #x#0 > 1 and #x#1 > 1) + newT = for a in ac list (t := flip(T,a); if t === null then continue else t) + Ts = join({T},newT) + Ts/(t -> volumeVector(pts,t))/sum + Ts/(t -> elapsedTime checkFan(pts,t)) + Ts/(t -> sort unique flatten t) + Ts/(t -> isRegularTriangulation(pts,t)) + unique oo +/// + +TEST /// +-* + restart +*- + -- from Kreuzer-Skarke database + -- 4 9 M:32 9 N:11 8 H:6,30 [-48] + polystr = " 1 0 1 1 -1 1 0 -1 -2 + 0 1 0 0 0 -2 -2 2 2 + 0 0 2 0 -2 -2 -2 2 2 + 0 0 0 2 -2 2 1 0 -1" + + A = matrixFromString polystr + P1 = convexHull A + P2 = polar P1 + + elapsedTime LP1 = latticePointList P1 + V1 = vertexList P1 + assert(take(LP1,#V1) == V1) + + elapsedTime LP2 = latticePointList P2 + V2 = vertexList P2 + assert(take(LP2,#V2) == V2) + + elapsedTime assert(faceList(0,P1) == for i from 0 to 8 list {i}) + assert(# faceList(1,P1) == 22) + assert(# faceList(2,P1) == 21) + assert(# faceList(3,P1) == 8) + + elapsedTime assert(faceList(0,P2) == for i from 0 to 7 list {i}) + assert(# faceList(1,P2) == 21) + assert(# faceList(2,P2) == 22) + assert(# faceList(3,P2) == 9) + +-* + faceList(4,P1) -- what should this do? + assert(faceList(-1,P1) == {{}}) -- not correct yet + faceList(4,P2) -- what should this do? + assert(faceList(-1,P2) == {{}}) -- not correct yet +*- + + -- now test dual faces... + dualfaces = for f in faceList(1,P2) list dualFace(P2,f) + origfaces = for g in dualfaces list dualFace(P1,g) + assert(origfaces == faceList(1,P2)) + for g in dualfaces do assert(2 == dim(P1,g)) + + -- now test lattice point containment + -- for each face, want the lattice points on that face + faceList(1,P2) + for f in faceList(1,P2) list f => latticePointList(P2,f) + for f in faceList(2,P2) list f => latticePointList(P2,f) + -- now test interior lattice points + -- need to run through all lattice points, and find max face containing it + -- check this against Polyhedra code + H = latticePointHash P2 + + (vertexMatrix P2)_{0} + Q = convexHull oo + vertexList Q + vertexMatrix Q + + latticePoints Q + -- TODO: fix the following bug. This results when using these functions in cases when + -- the polytope isn't e.g. reflexive, or really, doesn't have the origin in the interior... + -- latticePointList Q -- fails, since polar Q isn't really what should be used here... + + for f in (faceList P2)_{0} do ( + Q := convexHull (vertexMatrix P2)_f; + lp := (latticePoints Q)/(m -> flatten entries m); + lpi := latticePointList(P2,f); + lpi2 := lp/(p -> H#p); + assert(lpi == sort lpi2) + ) + + H = latticePointHash P1 + for f in faceList P1 do ( + Q := convexHull (vertexMatrix P1)_f; + lp := (latticePoints Q)/(m -> flatten entries m); + lpi := latticePointList(P1,f); + lpi2 := lp/(p -> H#p); + assert(lpi == sort lpi2) + ) + + -- test interior lattice point code + lpi = (latticePointHash P1)#{-2, 2, 2, -1} + assert(minimalFace(P1, {-2,2,2,-1}) == {0}) + + assert(interiorLatticePointList(P1, {0,2,3,5,7}) == {24, 26, 28}) + + hashTable for f in faceList(2,P2) list ( + f => {dim(P2,f), + latticePointList(P2,f), + # interiorLatticePointList(P2,f), + # interiorLatticePointList(P1, dualFace(P2,f))} + ) + allinfo = sort for f in faceList P2 list ( + {dim(P2,f), + f, + latticePointList(P2,f), + # interiorLatticePointList(P2,f), + # interiorLatticePointList(P1, dualFace(P2,f)) + } + ) + allinfo'ans = { + {0, {0}, {0}, 1, 0}, + {0, {1}, {1}, 1, 0}, + {0, {2}, {2}, 1, 0}, + {0, {3}, {3}, 1, 0}, + {0, {4}, {4}, 1, 0}, + {0, {5}, {5}, 1, 0}, + {0, {6}, {6}, 1, 0}, + {0, {7}, {7}, 1, 0}, + {1, {0, 1}, {0, 1}, 0, 1}, + {1, {0, 2}, {0, 2}, 0, 0}, + {1, {0, 3}, {0, 3}, 0, 0}, + {1, {0, 5}, {0, 5}, 0, 0}, + {1, {0, 6}, {0, 6}, 0, 0}, + {1, {1, 2}, {1, 2}, 0, 0}, + {1, {1, 4}, {1, 4, 8}, 1, 0}, + {1, {1, 5}, {1, 5}, 0, 1}, + {1, {1, 6}, {1, 6}, 0, 0}, + {1, {1, 7}, {1, 7}, 0, 1}, + {1, {2, 3}, {2, 3}, 0, 0}, + {1, {2, 4}, {2, 4}, 0, 0}, + {1, {2, 5}, {2, 5}, 0, 1}, + {1, {3, 4}, {3, 4}, 0, 0}, + {1, {3, 6}, {3, 6}, 0, 0}, + {1, {4, 5}, {4, 5}, 0, 0}, + {1, {4, 6}, {4, 6}, 0, 0}, + {1, {4, 7}, {4, 7}, 0, 1}, + {1, {5, 6}, {5, 6, 9}, 1, 3}, + {1, {5, 7}, {5, 7}, 0, 1}, + {1, {6, 7}, {6, 7}, 0, 1}, + {2, {0, 1, 2}, {0, 1, 2}, 0, 0}, + {2, {0, 1, 3, 4}, {0, 1, 3, 4, 8}, 0, 1}, + {2, {0, 1, 5}, {0, 1, 5}, 0, 0}, + {2, {0, 1, 6}, {0, 1, 6}, 0, 1}, + {2, {0, 2, 3}, {0, 2, 3}, 0, 1}, + {2, {0, 2, 5}, {0, 2, 5}, 0, 0}, + {2, {0, 3, 6}, {0, 3, 6}, 0, 1}, + {2, {0, 5, 6}, {0, 5, 6, 9}, 0, 1}, + {2, {1, 2, 4}, {1, 2, 4, 8}, 0, 1}, + {2, {1, 2, 5}, {1, 2, 5}, 0, 0}, + {2, {1, 4, 7}, {1, 4, 7, 8}, 0, 1}, + {2, {1, 5, 6}, {1, 5, 6, 9}, 0, 0}, + {2, {1, 5, 7}, {1, 5, 7}, 0, 0}, + {2, {1, 6, 7}, {1, 6, 7}, 0, 0}, + {2, {2, 3, 4}, {2, 3, 4}, 0, 1}, + {2, {2, 3, 5, 6}, {2, 3, 5, 6, 9}, 0, 1}, + {2, {2, 4, 5}, {2, 4, 5}, 0, 1}, + {2, {3, 4, 6}, {3, 4, 6}, 0, 1}, + {2, {4, 5, 6}, {4, 5, 6, 9}, 0, 0}, + {2, {4, 5, 7}, {4, 5, 7}, 0, 0}, + {2, {4, 6, 7}, {4, 6, 7}, 0, 0}, + {2, {5, 6, 7}, {5, 6, 7, 9}, 0, 1}, + {3, {0, 1, 2, 3, 4}, {0, 1, 2, 3, 4, 8}, 0, 1}, + {3, {0, 1, 2, 5}, {0, 1, 2, 5}, 0, 1}, + {3, {0, 1, 3, 4, 6, 7}, {0, 1, 3, 4, 6, 7, 8}, 0, 1}, + {3, {0, 1, 5, 6}, {0, 1, 5, 6, 9}, 0, 1}, + {3, {0, 2, 3, 5, 6}, {0, 2, 3, 5, 6, 9}, 0, 1}, + {3, {1, 2, 4, 5, 7}, {1, 2, 4, 5, 7, 8}, 0, 1}, + {3, {1, 5, 6, 7}, {1, 5, 6, 7, 9}, 0, 1}, + {3, {2, 3, 4, 5, 6}, {2, 3, 4, 5, 6, 9}, 0, 1}, + {3, {4, 5, 6, 7}, {4, 5, 6, 7, 9}, 0, 1}, + {4, {0, 1, 2, 3, 4, 5, 6, 7}, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 1, 0} + } + assert(allinfo == allinfo'ans) + assert(allinfo == annotatedFaces P2) + + hodgeOfCYToricDivisors P1 + hodgeOfCYToricDivisors P2 + elapsedTime hashTable for p in latticePointList P2 list p => hodgeCY(P1, p) + elapsedTime hashTable for p in latticePointList P1 list p => hodgeCY(P2, p) + + netList annotatedFaces(0,P1) + netList annotatedFaces(3,P2) + netList annotatedFaces(1,P1) + netList annotatedFaces(2,P1) + netList annotatedFaces(3,P1) +/// + +TEST /// + -- Test of h11 and h21 formulae for an example from Kreuzer-Skarke database. + -- as well as minimalFace, dim, genus, isFavorable. +-* + restart +*- + -- from Kreuzer-Skarke database + -- 4 9 M:32 9 N:11 8 H:6,30 [-48] + polystr = " 1 0 1 1 -1 1 0 -1 -2 + 0 1 0 0 0 -2 -2 2 2 + 0 0 2 0 -2 -2 -2 2 2 + 0 0 0 2 -2 2 1 0 -1" + + A = matrixFromString polystr + P1 = convexHull A + P2 = polar P1 + + elapsedTime assert(h11OfCY P1 == 6) + elapsedTime assert(h11OfCY P2 == 30) + elapsedTime assert(h21OfCY P1 == 30) + elapsedTime assert(h21OfCY P2 == 6) + + assert isFavorable P1 + assert not isFavorable P2 + + for f in faceList P2 list {dim(P2,f), genus(P2,f)} + minfaces = for lp in latticePointList P2 list dim(P2,minimalFace(P2,lp)) + assert(minfaces == {0,0,0,0,0,0,0,0,1,1,4}) +/// + +TEST /// + -- We work on one example in 4 dimensions, where we know the answers (or have computed them elsewhere). + -- Second polytope (index 1) on h11=3 Kreuzer-Skarke list of 4d reflexive polytopes for h11=3. + -- 4 5 M:48 5 N:8 5 H:3,45 [-84] + str = " 1 0 2 4 -8 + 0 1 5 3 -9 + 0 0 6 0 -6 + 0 0 0 6 -6 + " + M = matrixFromString str + assert(M == matrix {{1, 0, 2, 4, -8}, {0, 1, 5, 3, -9}, {0, 0, 6, 0, -6}, {0, 0, 0, 6, -6}}) + + P = convexHull M + assert(# latticePointList P == 48) + assert(# latticePointList polar P == 8) + assert(h11OfCY P == 3) + assert(h21OfCY P == 45) + assert(h11OfCY polar P == 45) + assert(h21OfCY polar P == 3) + + -- Now compute all of the cohomologies of the (irreducible) toric divisors + LP = latticePointList polar P + assert(#LP == 8) + LP = drop(LP, -1) + cohoms = for v in LP list hodgeOfCYToricDivisor(P, v) + cohomH = hodgeOfCYToricDivisors P + cohoms1 = for v from 0 to #LP-1 list cohomH#v -- last LP is the origin, which isn't one of these divisors + assert(cohoms == cohoms1) + assert isFavorable P + + -- Now compute all of the cohomologies of the (irreducible) toric divisors for the polar dual + LP = latticePointList P + LP = drop(LP, -1) + cohoms = for v in LP list hodgeOfCYToricDivisor(polar P, v) + cohomH = hodgeOfCYToricDivisors polar P + cohoms1 = for v from 0 to #LP-1 list cohomH#v + assert(cohoms == cohoms1) + assert not isFavorable polar P +/// + +TEST /// + -- id=0 h11=11 + -- 4 13 M:23 13 N:16 13 H:11,18 [-14] + str = " 1 0 0 0 -1 1 0 0 0 1 -1 1 -2 + 0 1 0 0 1 -1 0 1 1 -1 1 -2 0 + 0 0 1 0 1 -1 0 1 0 0 -1 -2 2 + 0 0 0 1 -1 1 -1 -1 -1 1 1 0 -1 + " + + P = convexHull matrixFromString str -- last first eg11 + P2 = polar P + assert(h11OfCY P == 11) + assert(h21OfCY P == 18) + assert(h11OfCY polar P == 18) + assert(h21OfCY polar P == 11) + + -- Now compute all of the cohomologies of the (irreducible) toric divisors + LP = latticePointList polar P + LP = drop(LP, -1) + assert(#LP == 15) + + --elapsedTime cohoms = for v in LP list hodgeOfCYToricDivisor(P, v) + cohomH = hodgeOfCYToricDivisors P + cohoms1 = for v from 0 to #LP-2 list cohomH#v + + -- the following line is too slow, and + cohoms = for v in drop(LP,-1) list hodgeOfCYToricDivisor(P, v) + assert(cohoms == cohoms1) + assert isFavorable P + + -- Now compute all of the cohomologies of the (irreducible) toric divisors for the polar dual + LP = latticePointList P + LP = drop(LP, -1) + assert(#LP == 22) + elapsedTime cohoms = for v in LP list hodgeOfCYToricDivisor(polar P, v) + cohomH = hodgeOfCYToricDivisors polar P + cohoms1 = for v from 0 to #LP-1 list cohomH#v + assert(cohoms == cohoms1) + -- the following line is too slow, and +-- cohoms = for v in LP list hodgeOfCYToricDivisor(P, v) -- actually, gives an error here... +-- assert(cohoms == cohoms1) + assert isFavorable polar P +/// + +TEST /// +-* +restart +*- +str = " 1 0 0 0 -11 -3 -1 -3 + 0 1 0 0 -6 -2 -2 -6 + 0 0 1 0 -2 -2 -2 -2 + 0 0 0 1 -2 2 4 6 " +M = matrixFromString str +P = convexHull M +vertexMatrix P +lp = latticePointList polar P +sort for v in vertexList P list (latticePointHash P)#v + +assert try (hodgeOfCYToricDivisor(P,{0,0,0,1}); false) else true -- {0,0,0,1} is not a lattice point +for p in lp list p => hodgeOfCYToricDivisor(P,p) +hodgeOfCYToricDivisors P + +assert(h11OfCY(P) == 90) +assert(h21OfCY(P) == 50) +assert(h11OfCY(polar P) == 50) +assert(h21OfCY(polar P) == 90) +/// + +---------------------------- +-- tests from MyPolyhedra -- +---------------------------- + +TEST /// + debug needsPackage "StringTorics" + A = transpose matrix {{-1,-1,2},{-1,0,1},{-1,1,1},{0,-1,2},{0,1,1},{1,-1,3},{1,0,-1},{1,1,-2}} + tri = regularFineTriangulation A + volumeVector(augmentWithOrigin A, max tri) + P = convexHull A + + A = transpose matrix {{-1, 0, -1, -1}, {-1, 0, 0, -1}, {-1, 1, 2, -1}, {-1, 1, 2, 0}, {1, -1, -1, -1}, {1, -1, -1, 1}, {1, 0, -1, 2}, {1, 0, 1, 2}} + C = transpose matrix latticePointList polar convexHull A + tri = regularFineTriangulation C + + elapsedTime delaunaySubdivision C -- takes 20 seconds?! (now 8 seconds) + isRegularTriangulation tri + P2 = polar convexHull A + regularStarTriangulation P2 + volume P2 +/// + + +TEST /// + A = transpose matrix {{1, 0, 0, 0}, {1, 2, 0, 0}, {1, 0, 2, 0}, {0, 0, 0, 1}, {0, 4, 0, 1}, {0, 0, 4, 1}, {-2, -4, -6, -3}, {-2, -6, -6, -3}, {-2, -6, -4, -3}} + P = convexHull A + P2 = polar P + + -- triangulations + A1 = transpose matrix latticePointList P + tri = regularFineTriangulation A1 + -- isRegularTriangulation tri -- TODO: this takes forever, is that new? + + debugLevel = 3 + tri = regularStarTriangulation P + normalToricVariety(drop(latticePointList P,-1), max tri) + -- elapsedTime isWellDefined oo -- ouch, pretty long (4/27/20) (96 sec) + + -- vertices + vertexList P + vertexMatrix P + vertexList P2 + vertexMatrix P2 + + -- latticePoints + latticePointList P + latticePointList P2 + + -- interior lattice points + debug StringTorics + hash1 = hashTable for f in faceList P list f => interiorLatticePointList(P, f) + hash2 = hashTable select(pairs hash1, (k,v) -> #v > 0) + hash3 = P.cache.TCIInteriorLatticeHash + assert(hash2 === hash3) + + -- faces + faceDimensionHash P + faceList P + faceList(0, P) + faceList(1, P) + faceList(2, P) + faceList(3, P) + faceList(4, P) + + FL1 = for f in faceList P list dualFace(P,f) + FL2 = for f in FL1 list dualFace(polar P,f) + FL3 = for f in FL2 list dualFace(P,f) + assert(FL1 == FL3) + assert(faceList P == FL2) + + time for f in faceList P list dim(P,f) + time for f in faceList P list latticePointList(P,f) + time for lp in latticePointList P list minimalFace(P,lp) + time for f in faceList P list genus(P,f) + + netList annotatedFaces P + for i from 0 to 4 list netList annotatedFaces(i,P) +/// + + + +TEST /// -- medium size (h^11 = 15) example +-* + restart + needsPackage "StringTorics" +*- + topes = kreuzerSkarke(15, Limit=>10, Access=>"wget") + A1 = matrix topes_8 + P = convexHull A1 + P2 = polar P + A = transpose matrix latticePointList P2 + + elapsedTime tri = regularStarTriangulation P2; + A2 = transpose matrix first tri + assert(A2 == submatrix(A, 0..numcols A-2)) + tri = tri_1/(x -> append(x, numcols A - 1)) + isFine(A, tri) + isStar(A, tri) + wts = regularTriangulationWeights(A, tri) + elapsedTime regularSubdivision(A, matrix{wts}) -- this is slower than we would like + assert(oo == tri) -- both oo, tri should be already sorted. + + circs = affineCircuits(A, tri) + circs0 = select(circs, x -> not member(numcols A - 1, flatten x)) + for c in circs0 list bistellarFlip(tri, c) + bistellarFlip(tri, circs0_1) + + elapsedTime tris = generateTriangulations(A, tri, Limit => 50); + tris/isFine_A//tally + tris/isStar_A//tally + elapsedTime(tris/regularTriangulationWeights_A); + + elapsedTime tri = regularFineTriangulation A; -- topcom, fast. + -- elapsedTime tris = allTriangulations(A, Fine => true); -- pretty long, how many are there? + + ans = {{0, 2, 3, 5, 17}, {0, 2, 3, 9, 17}, {0, 2, 5, 15, 17}, {0, 2, 6, 9, 17}, {0, 2, 6, 13, 17}, + {0, 2, 7, 13, 17}, {0, 2, 7, 15, 17}, {0, 3, 5, 11, 17}, {0, 3, 9, 11, 17}, {0, 5, 6, 11, 17}, + {0, 5, 6, 13, 17}, {0, 5, 13, 15, 17}, {0, 6, 9, 11, 17}, {0, 7, 13, 15, 17}, {1, 2, 3, 9, 17}, + {1, 2, 3, 10, 17}, {1, 2, 4, 10, 17}, {1, 2, 4, 12, 17}, {1, 2, 6, 9, 17}, {1, 2, 6, 12, 17}, + {1, 3, 5, 10, 17}, {1, 3, 5, 11, 17}, {1, 3, 9, 11, 17}, {1, 4, 5, 10, 17}, {1, 4, 5, 12, 17}, + {1, 5, 6, 11, 17}, {1, 5, 6, 12, 17}, {1, 6, 9, 11, 17}, {2, 3, 5, 10, 17}, {2, 4, 5, 10, 17}, + {2, 4, 5, 16, 17}, {2, 4, 12, 16, 17}, {2, 5, 7, 15, 17}, {2, 5, 7, 16, 17}, {2, 6, 12, 13, 17}, + {2, 7, 12, 13, 17}, {2, 7, 12, 16, 17}, {4, 5, 12, 14, 17}, {4, 5, 14, 16, 17}, {4, 8, 12, 14, 17}, + {4, 8, 12, 16, 17}, {4, 8, 14, 16, 17}, {5, 6, 12, 14, 17}, {5, 6, 13, 14, 17}, {5, 7, 13, 14, 17}, + {5, 7, 13, 15, 17}, {5, 7, 14, 16, 17}, {6, 8, 12, 13, 17}, {6, 8, 12, 14, 17}, {6, 8, 13, 14, 17}, + {7, 8, 12, 13, 17}, {7, 8, 12, 16, 17}, {7, 8, 13, 14, 17}, {7, 8, 14, 16, 17}} + startri = regularFineStarTriangulation(A, ConeIndex => 17) -- last column of A is the origin + assert(ans == startri) +/// + +TEST /// +-- This test is failing: May 2022. It isn't a complete test anyway... +-- Test of intersection number computations. +-- This requires that V be favorable? +-- Remove this test? In any case, make sure intersection numbers are bombproof! +-* + restart + needsPackage "StringTorics" +*- + debug StringTorics + + topes = kreuzerSkarke(3, Limit => 50); + A = matrix topes_30 + P = convexHull A + (V, basisElems) = reflexiveToSimplicialToricVarietyCleanDegrees(P, CoefficientRing => ZZ/32003) + basisElems -- for the moment, we ignore this, and write down all of the elements... + GLSM = transpose matrix degrees ring V + X = completeIntersection(V, {-toricDivisor V}) + Xa = abstractVariety(X, base()) + IX = intersectionRing Xa + elemsToConsider = toList(0..numcols GLSM-1); + triples = (subsets(elemsToConsider, 3))/sort//sort; + Htriples = hashTable for a in triples list ( + (i,j,k) := toSequence a; + val := integral(IX_i * IX_j * IX_k); + if val == 0 then continue else {i,j,k} => val + ) + + + -- Now we try the code above + (singles, doubles, triples) = toSequence possibleNonZeros V + + Htriples = hashTable for a in join(singles, doubles, triples) list ( + (i,j,k) := toSequence a; + val := integral(IX_i * IX_j * IX_k); + if val == 0 then continue else {i,j,k} => val + ) + + -- assert(triples === (keys Htriples)/sort//sort) -- failing. And it shouldn't be correct anyway...? + + elapsedTime tripleProductsCY V + elapsedTime CY3NonzeroMultiplicities V -- much slower for small h11... + + ans = toSequence topologyOfCY3(V, basisElems) + (h11, h21, C, L) = ans + + -- What was this supposed to do? + -- hashTable for x in keys H3 list ( + -- if isSubset(x, basisElems) then x => H3#x else continue + -- ) + + (h11, h21, C, L) = toSequence topologyOfCY3(V, basisElems) + (h11', h21', C', L') = toSequence topologyOfCY3(V, {0,1,2}, Ring => ring C) + A = ring C; + M = GLSM_{0,1,2} + phi1 = map(A, A, flatten entries((M) * transpose vars A)) + L' == phi1 L + C' == phi1 C + netList {L, L', phi1 L, phi1 L'} + +/// + + +/// + -- Favorable h11=5 polytope. + -- This is too long for a test +-* + restart +*- + needsPackage "StringTorics" + topes = kreuzerSkarke(5, Limit => 20); + + A = matrix topes_3 + P = convexHull A + assert isReflexive P + h11OfCY P == 5 + h11OfCY polar P == 29 + h21OfCY P == 29 + assert isFavorable P + assert not isFavorable polar P + + P2 = polar P + vertices P2 + transpose matrix latticePointList P2 + netList annotatedFaces P2 + + V = reflexiveToSimplicialToricVariety P + classGroup V + transpose matrix degrees ring V + +-- elapsedTime Qs = for tope in topes list cyPolytope(tope); + elapsedTime Qs = for i from 0 to #topes -1 list cyPolytope(topes#i, ID => i); + Qs/isFavorable -- takes .1 - .2 seconds per polytope. Why so long? + favorables = positions(Qs, isFavorable) + + RZ = ZZ[a,b,c,d,e] + + elapsedTime Xs = flatten for i in favorables list elapsedTime findAllCYs Qs#i; + XH = hashTable for X in Xs list label X => X; + topXH = hashTable for k in keys XH list elapsedTime k => topologicalData(XH#k, RZ); + UtopXH = partition(k -> topXH#k, keys topXH) + hashTable select(pairs UtopXH, k -> hh^(1,2) k#0 == 39) + +/// + +/// + -- THIS TEST CURRENTLY FAILS (Aug 2022). + -- Non favorable example. + -- Either implement functionality for this situation, or give reasonable error messages! + -- XXX start here Aug 2022. + -- this is an h11=5 polytope. Let's make sure everything seems ok with it + -- reason: it is seemingly becoming an h11=4 polytope? + -- Actually: it is a torsion grading. +-* + restart +*- + needsPackage "StringTorics" + topes = kreuzerSkarke(5, Limit => 50); + A = matrix topes_1 + P = convexHull A + assert isReflexive P + h11OfCY P == 5 + h11OfCY polar P == 29 + h21OfCY P == 29 + + P2 = polar P + vertices P2 + latticePoints P2 + netList annotatedFaces P2 + methods reflexivePolytope + + V = reflexiveToSimplicialToricVariety P + degrees ring V -- fails, + classGroup V + picardGroup V + h11OfCY P + + Q = cyPolytope topes_1 + -- Q = reflexivePolytope A -- really the dual of A. + vertices polytope Q + netList annotatedFaces Q -- annotated faces of the dual of A. + peek Q.cache + assert(h11OfCY Q == 5) + assert(h21OfCY Q == 29) + assert(dim Q == 4) + assert not isFavorable Q -- i.e. whether the dual has any points interior to a 2-face, whose dual does too. + isFavorable polar Q + X = makeCY Q -- BUG/TODO: should allow CoefficientRing at least... + V = ambient X -- TODO: need a way to make this directly from Q... + Xs = findAllFRSTs Q -- only one here, not surprisingly... + ring V -- BUG: get inscrutable error. Probably due to a placed GLSM charge matrix... + + RZ = ZZ[a,b,c,d] + topologicalData(X, RZ) -- fails with bad error message. + abstractVariety X -- fails for similar reason... (bad glsm matrix added...?) +/// + +/// + -- analyzing the triangulations related to one via bistellar flip. + -- CURRENT WORK: grabbing all FRST's starting with one. This test isn't really a test, and currently FAILS. + -- The method below using bistellar flips seems to work better than topcom. + -- Although, it is still much slower than it needs to be (don't need to use any circuit twice when moving from one to another...) + + -- my TODO: + -- keep track of circuits used, and don't use one twice...? + -- make sure that all but (2,2) flips do not change the 2-faces (I think this is clear, but check anyway). + -- maybe: get the graph of all such. +-* + restart + needsPackage "StringTorics" +*- + topes = kreuzerSkarke(6, Limit => 10) + Q = cyPolytope(topes_7, ID => 7) + X = makeCY Q + assert isFavorable Q + elapsedTime Xs = findAllCYs Q; + assert(#Xs == 21) + PXs = partition(X -> restrictTriangulation X, Xs) + assert(#keys PXs == 4) -- at most 4 different topologies + + sampleXs = for k in keys PXs list PXs#k#0; -- a list of 4 CY's that have the 4 different topologies. + sampleXsGV = for X in sampleXs list partitionGVConeByGV(X, DegreeLimit => 20) + for p in subsets({0,1,2,3}, 2) list p => findLinearMaps(sampleXsGV#(p#0), sampleXsGV#(p#1)) + + -- this shows that 2 of the 4 are likely the same. We next compute the topology of these 4 X's + -- and see if that is in fact the case. + + -- So now we compute the topologies of the 4 potentially different CY's. + RZ = ZZ[x_1..x_6] + elapsedTime topOfXs = sampleXs/(X -> topologicalData(X, RZ)); + debug StringTorics -- FIXME: this should not be needed + cubics = topOfXs/cubicForm + c2s = topOfXs/c2 + + -- each matrix in Ms determines a topological isomrphism of sampleXs#0 and sampleXs#2: + Ms = findLinearMaps(sampleXsGV#1, sampleXsGV#3) + Ms = Ms/(m -> lift(m, ZZ)) + assert all(Ms, m -> det m == 1 or det m == -1) + phis = for m in Ms list map(RZ, RZ, m) + for phi in phis do assert(phi(cubics_1) == cubics_3 and phi(c2s_1) == c2s_3) + + -- the others appear that they might be different. + -- in fact, we can show that these are not the same, by looking at + -- the jacobian locus of each cubic. + RQ = QQ[gens RZ] + for f in cubics list (fQ = sub(f, RQ); decompose saturate ideal jacobian fQ) + netList oo -- shows that 0, 1, 3 are all unique (not related by invertible integral change of basis). + + + + + + Qs = for i from 0 to #topes-1 list cyPolytope(topes_i, ID => i) + Qs/isFavorable + + topes = kreuzerSkarke(7, Limit => 10) + topes = kreuzerSkarke(8, Limit => 10) + + Qs = for i from 0 to #topes-1 list cyPolytope(topes_i, ID => i) + Qs/isFavorable + --A = transpose matrix rays Qs_0 + A = transpose matrix rays Qs_7 + --A = transpose matrix rays Qs_6 + A = A | transpose matrix{{0,0,0,0}} + t0 = regularFineTriangulation A + t1 = triangulation(A, fineStarTriangulation(A, max t0, ConeIndex => numcols A - 1)) + isWellDefined t0 + gkzVector t0 + volume convexHull A + + isWellDefined t1 + gkzVector t1 + volume convexHull A + + elapsedTime Ts = allTriangulations(A, Fine => true); -- 387 triangulations this takes quite a while. Which example has 387? + elapsedTime aaTs = allTriangulations(A, RegularOnly => false); -- 1278 triangulations + Ts = Ts/(t -> triangulation(A, t)) + Ts/ isRegularTriangulation //tally -- all 387 are regular (as they should be). + Ts/isStar//tally + # (Ts/isFine) + elapsedTime Xs = findAllCYs Qs_7; + + RZ = ZZ[x_1..x_6] + Q = Qs_7 + X = cyData(Q, max t1) + elapsedTime findAllConnectedStarFine t1; -- for h11=7, Qs_7 + elapsedTime findStarFineGraph t1 + annotatedFaces Q + restrictTriangulation X + Xs = findAllCYs Q + PXs = partition(X -> restrictTriangulation X, Xs) + X0s = PXs#((keys PXs)#0) + X0s/(X -> topologicalData(X, RZ))//unique + X1s = PXs#((keys PXs)#1) + X1s/(X -> topologicalData(X, RZ))//unique + X2s = PXs#((keys PXs)#2) + X2s/(X -> topologicalData(X, RZ))//unique + X3s = PXs#((keys PXs)#3) + X3s/(X -> topologicalData(X, RZ))//unique + + gv0 = partitionGVConeByGV(X0s_0, DegreeLimit => 20) + gv1 = partitionGVConeByGV(X1s_0, DegreeLimit => 20) + gv2 = partitionGVConeByGV(X2s_0, DegreeLimit => 20) + gv3 = partitionGVConeByGV(X3s_0, DegreeLimit => 20) + + partitionGVConeByGV(X0s_0, DegreeLimit => 30) + partitionGVConeByGV(X1s_0, DegreeLimit => 30) + partitionGVConeByGV(X2s_0, DegreeLimit => 30) + partitionGVConeByGV(X3s_0, DegreeLimit => 30) + + findLinearMaps(gv0, gv2) + findLinearMaps(gv0, gv1) + findLinearMaps(gv0, gv3) + findLinearMaps(gv1, gv2) + findLinearMaps(gv1, gv3) + findLinearMaps(gv2, gv3) + + T = QQ[t_(1,1) .. t_(6,6)] + M = genericMatrix(T, 6, 6) + + gv0, gv2 + id1 = trim ideal(M * transpose matrix{gv0#1#0} - transpose matrix{gv2#1#0}) + id2 = trim ideal(M * transpose matrix{gv0#2#0} - transpose matrix{gv2#2#0}) + id4 = (p) -> ( + trim ideal(M * transpose matrix gv0#4 - (transpose matrix gv2#4)_p) + ) + id8 = (p) -> ( + trim ideal(M * transpose matrix gv0#8 - (transpose matrix gv2#8)_p) + ) + + id4s = for p in permutations 4 list (I := id4 p; if I != 1 then p => I else continue) + id8s = for p in permutations 2 list (I := id8 p; if I != 1 then p => I else continue) + ids = flatten for x in id4s list for y in id8s list trim(id1 + id2 + x#1 + y#1) + ids = select(ids, i -> i != 1) + Ms = ids/(i -> M % i) -- 4 matrices here! + for m in Ms list det m + Ms = for m in Ms list lift(m, ZZ) + phis = for m in Ms list map(RZ, RZ, m) + psis = for m in Ms list map(RZ, RZ, m^-1) + Ms + trim(id1 + id2 + id4s#0#1 + id8s#0#1) + + T0 = topologicalData(X0s#0, RZ) + T2 = topologicalData(X2s#0, RZ) + F0 = cubicForm T0 + F2 = cubicForm T2 + L0 = c2 T0 + L2 = c2 T2 + + phis_0 L0 - L2 + phis_0 F0 - F2 + + phis_1 L0 - L2 + phis_1 F0 - F2 + + phis_2 L0 - L2 + phis_2 F0 - F2 + + phis_3 L0 - L2 + phis_3 F0 - F2 + + m0 = Ms#0 -- order 2 + m1 = Ms#1 -- order 4 + m2 = Ms#2 -- order 2 + m3 = Ms#3 -- order 4 + for i from 1 to 8 list (m0*m1)^i -- order 2 + for i from 1 to 8 list (m0*m2)^i -- order 2 + for i from 1 to 8 list (m0*m3)^i -- order 2 + for i from 1 to 8 list (m1*m2)^i -- order 2 + for i from 1 to 8 list (m1*m3)^i -- order 2 + for i from 1 to 8 list (m2*m3)^i -- order 2 + for i from 1 to 8 list (m1*m2*m3)^i -- order 2 + for i from 1 to 8 list (m0*m2*m3)^i -- order 4 + for i from 1 to 8 list (m0*m1*m2*m3)^i -- order 1 + for i from 1 to 8 list m3^i + + -- it looks like X0, X2 are the same topology, X1, X3 are not, and so there arr 3 distinct topologies... + T1 = topologicalData(X1s#0, RZ) + T3 = topologicalData(X3s#0, RZ) + L1 = c2 T1 + F1 = cubicForm T1 + L3 = c2 T3 + F3 = cubicForm T3 + + ideal gens gb saturate(ideal F0 + ideal jacobian F0) + RQ = QQ[gens RZ] + F0Q = sub(F0, RQ) + saturate ideal jacobian F0Q + decompose oo -- 4 singular points of the projective cubic + + F1Q = sub(F1, RQ) + saturate ideal jacobian F1Q + decompose oo -- singular locus is quadric in P3 and a point + + F3Q = sub(F3, RQ) + saturate ideal jacobian F3Q + decompose oo -- point union 2 points union conic in a plane + +/// + +TEST /// +-* + restart + needsPackage "StringTorics" +*- + topes = kreuzerSkarke(5, Limit => 10); + Qs = for i from 0 to #topes-1 list cyPolytope(topes#i, ID => i) + for tope in topes list isFavorable convexHull matrix tope + Q = cyPolytope(topes_8, ID => 8) + Ts = findAllFRSTs Q + RZ = ZZ[a,b,c,d,e] + Xs = findAllCYs(Q, Ring => RZ) + + assert((for X in Xs list label X) === {(8,0)}) -- (X#"polytope data".cache#"id", X.cache#"id") -- id of each example. + for X in Xs list intersectionNumbers X + + for X in Xs list topologicalData X + assert(# unique oo == 1) + + Vs = Xs/ambient + assert all(Vs, isSimplicial) +/// + +TEST /// +-- XXX +-* + restart + needsPackage "StringTorics" +*- + topes = kreuzerSkarke(3, Limit => 50); + Q = cyPolytope(topes_30, ID => 30) + Ts = findAllFRSTs Q + RZ = ZZ[a,b,c] + Xs = for i from 0 to #Ts-1 list calabiYau(Q, Ts#i, ID => i, Ring => RZ) + assert(#Xs == #Ts) + vertices polytope Q + label Q + assert((for X in Xs list label X) === {(30, 0), (30, 1)}) + X = Xs#0 + V = ambient X + assert isSimplicial V + assert isProjective V + intersectionNumbers X + intersectionNumbersOfCY X + oo === ooo + intersectionNumbersOfCY(V, basisIndices Q) + + assert(hh^(1,1) X == 3) + assert(hh^(1,2) X == 69) + + elapsedTime T = topologicalData X + hh^(1,1) T + hh^(1,2) T + + -- TODO: add these 4 lines back in (but they should be made in to a test) + -- partitionGVConeByGV(X, DegreeLimit => 10) + -- partitionGVConeByGV(X, DegreeLimit => 20) + -- hilbertBasis gvCone(X, DegreeLimit => 20) + -- gv = gvInvariants(X, DegreeLimit => 20); +/// + + +TEST /// +-- XXX +-* + restart + needsPackage "StringTorics" +*- + -- Test the routines of this package on the example X given here (h11=3, h12=69) + topes = kreuzerSkarke(3, Limit => 50); + A = matrix topes_30 + P = cyPolytope(topes_30, ID => 30) + hh^(1,1) P == 3 + hh^(1,2) P == 69 + X = makeCY(P, Ring => (RZ = ZZ[x,y,z]), ID => 0) + -- findAllFRSTs P + -- X = cyData(P, first oo, ID => 0) + + assert(hh^(1,1) X == 3) + assert(hh^(1,2) X == 69) + assert(dim X == 3) + elapsedTime topologicalData X + dump X + dump cyPolytope X + elapsedTime restrictTriangulation X + + assert(dim X == 3) + assert isFavorable X + rays X + max X + V = ambient X -- give the normal toric variety. Works now, sort of. Problems though: TODO: cache it, allow options? degrees might be different... + assert(rays V === rays X) + assert(max V === max X) + + intersectionNumbers X + toricIntersectionNumbers X + c2 X + cubicForm X + c2Form X + + elapsedTime topologicalData X -- cache this result? + + ambient X -- give the normal toric variety. Works now. + aX = abstractVariety X -- give the abstract variety. -- TODO: should stash the value...? + abstractVariety(X, base(a,b,c)) -- give the abstract variety + IX = intersectionRing aX + + -- TODO: How is this computed? + rays toricMoriCone X + hilbertBasis toricMoriCone X + + -- TODO: gvInvariants still goes through intersection ring + -- TODO: add this line in + -- gvInvariants(X, DegreeLimit => 10) + + -- TODO: add tests for line bundles on X, and their cohomology. +/// + +/// -- NOT TESTED. +-* + restart + needsPackage "StringTorics" +*- + -- Testing interface for calabiYau, cyPolytope, in presence of databases. + DB = (currentDirectory) | "Databases/cys-ntfe-h11-5.dbm" + RZ = ZZ[x_0..x_4] + --elapsedTime (Qs, Xs) = readCYDatabase(DB, Ring => RZ); -- takes 13 seconds. + --# sort keys Xs == 13635 + + -- reading examples direcly from the database + db = openDatabase DB + # sort keys db === 18625 + X = calabiYau(db, (4782,0), Ring => RZ) + close db + Q = cyPolytope X + peek Q.cache + netList annotatedFaces cyPolytope X + + Q = cyPolytope(DB, 4782) + + db = openDatabase DB + Xlabs = select(keys db, lab -> (lab = value lab; instance(lab, Sequence) and lab#0 == 4510)) + Xlabs = Xlabs/value + close db + X1 = calabiYau(DB, Xlabs#0, Ring => RZ) + X1' = calabiYau(DB, Xlabs#0, Ring => RZ) + X1 === X1' + cyPolytope X1 === cyPolytope X1' + + Q = cyPolytope X1 + X2 = calabiYau(DB, Xlabs#1, Ring => RZ) + Q2 = cyPolytope X2 + Q === Q2 + assert(Q.cache === Q2.cache) + automorphisms Q + netList restrictTriangulation X, netList restrictTriangulation X2 +/// + +/// -- TODO: this test isn't finding the database file. +-* + restart + needsPackage "StringTorics" +*- + -- Testing interface for calabiYau, cyPolytope, in presence of databases. + debug needsPackage "StringTorics" + -- TODO: this line doesn't work in tests, since the + DB = "./Databases/cys-ntfe-h11-3.dbm" + RZ = ZZ[a,b,c] + elapsedTime (Qs, Xs) = readCYDatabase(DB, Ring => RZ); + Q = Qs#6 + Xs = findAllCYs(Q, NTFE => false) + G = automorphisms Q + tri1 = restrictTriangulation_2 Xs#0 + gtri1 = normalizeByAutomorphisms(Q, tri1) + + tri2 = restrictTriangulation_2 Xs#0 + gtri2 = normalizeByAutomorphisms(Q, tri2) + gtri1 === tri1 + gtri2 === tri2 + gtri1 === gtri2 + #Xs + # unique{gtri1, gtri2} + # findAllCYs(Qs#31, NTFE => false, Automorphisms => false) == 6 + # findAllCYs(Qs#31, NTFE => false, Automorphisms => true) == 1 + # findAllCYs(Qs#31, NTFE => true, Automorphisms => false) == 6 + # findAllCYs(Qs#31, NTFE => true, Automorphisms => true) == 1 + for lab in sort keys Qs list ( + Q = Qs#lab; + elapsedTime {# findAllCYs(Q, NTFE => false, Automorphisms => false), + # findAllCYs(Q, NTFE => false, Automorphisms => true), + # findAllCYs(Q, NTFE => true, Automorphisms => false), + # findAllCYs(Q, NTFE => true, Automorphisms => true) + }) + Q = Qs#31 +/// diff --git a/CYToolsM2/installThese.m2 b/CYToolsM2/installThese.m2 new file mode 100644 index 0000000..7e9966e --- /dev/null +++ b/CYToolsM2/installThese.m2 @@ -0,0 +1,15 @@ +restart +uninstallAllPackages() +restart +installPackage "IntegerEquivalences" +restart +installPackage "StringTorics" +restart +installPackage "DanilovKhovanskii" + +-- Currently, GV invariants code not functional here, until we can get computeGV compiled and placed here... +-- I have commented out a few tests that use this. All the following tests run. +restart +check "IntegerEquivalences" +check "StringTorics" +check "DanilovKhovanskii"