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"