3 refactor topdata #8

Merged
julian merged 3 commits from 3-refactor-topdata into master 2026-07-24 20:01:15 +02:00
Showing only changes of commit effad33c6e - Show all commits
+40 -40
View File
@@ -3,22 +3,23 @@ import logging
import os
import json
from datetime import datetime, timezone
import re
# Logger
logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.DEBUG) # or logging.DEBUG to see both
logging.basicConfig(level=logging.DEBUG)
# For grep-commands
import re
find_zs = re.compile('z\d+')
find_ls = re.compile('l\d+')
find_index_z = re.compile('\d+')
find_zs = re.compile(r'z\d+')
find_ls = re.compile(r'l\d+')
find_index_z = re.compile(r'\d+')
class Polytope:
"""
Class representing a lattice polytope. Objects contain a list of defining points
and a list of points in the convex hull of the polytope. Points inside codimension
are excluded from the convex hull and stored in a separate list.
one are excluded from the convex hull and stored in a separate list.
"""
#############################
@@ -70,6 +71,8 @@ class ToricPolytope(Polytope):
toric polytope describing the original family's ambient space.
Example: For the mirror quintic, the vertices are e_1, ..., e_4, -e_1-...-e_4.
For CICYs, a nef-partition must be provided, defaulting to hypersurface if none given.
"""
##############################
@@ -111,7 +114,7 @@ class ToricPolytope(Polytope):
raise ValueError("Invalid nef partition: {}".format(nef_partition))
self.nef_partition = nef_partition
else:
self.nef_partition = [range(len(self.relevant_lattice_points) - 1)] # Default to a trivial partition if none is provided
self.nef_partition = [list(range(len(self.relevant_lattice_points) - 1))] # Default to a trivial partition if none is provided
def set_Mori_cone(self, lvec = None):
"""
@@ -127,14 +130,13 @@ class ToricPolytope(Polytope):
raise ValueError("All rows in lvec must have the same length.")
elif len(lvec[0]) != len(self.relevant_lattice_points):
raise ValueError("The length of the l-vectors is invalid.")
elif matrix(matrix(default_Mori_cone.rays()).stack(matrix(lvec))).rank() != matrix(default_Mori_cone.rays()).rank():
elif matrix(default_Mori_cone.rays()).stack(matrix(lvec)).rank() != matrix(default_Mori_cone.rays()).rank():
raise ValueError("The provided l-vectors are not in the linear span of the original Mori cone.")
else:
self.Mori_cone = Cone(lvec)
if len(matrix(self.Mori_cone.rays()).kernel().gens()) > 0:
logger.warning("Non-simplicial Mori-cone encountered.")
logger.info("Using the first %d linearly independent vectors.", len(self.Mori_cone.rays()))
self.Mori_cone = Cone(
transpose(
transpose(self.Mori_cone.rays())
@@ -144,7 +146,8 @@ class ToricPolytope(Polytope):
).kernel().gens()
).transpose()
)
logger.info("Using the first %d linearly independent vectors.", len(self.Mori_cone.rays()))
self.lvec = matrix(self.Mori_cone.rays())
def __init__(
@@ -161,11 +164,22 @@ class ToricPolytope(Polytope):
self.set_triangulation(no_triangulation)
self.set_nef_partition(nef_partition)
self.cy_dimension = self.dimension - len(self.nef_partition)
self.fan = self.triangulation.fan(self.origin)
self.ToricVariety = ToricVariety(self.fan)
self.set_Mori_cone(lvec = lvec)
self.model_name = model_name if model_name else "Unnamed Model"
logger.info(
"Initialised %s: %s%d with h21 = %d.",
self.model_name,
"CY" if len(self.nef_partition) == 1 else "CICY",
self.cy_dimension,
len(list(self.lvec)),
)
###############################
# Discriminant Computation
###############################
@@ -264,6 +278,7 @@ class ToricPolytope(Polytope):
except:
# In one-parameter cases there may be nothing to eliminate.
polynomials = equation_system
logger.debug("No elimination needed for the equation system: %s", equation_system)
try:
if len(lambda_symbols) == 0:
@@ -295,20 +310,22 @@ class ToricPolytope(Polytope):
codim = total_relation_blocks - 1 - index
discriminants.append([polynomial, codim])
def disc(self, only_strong_coupling=False, no_triangulation=0):
def disc(self, only_strong_coupling=False):
"""
Computes the A-discriminant for the toric polytope (following Aspinwall, Plesser, Wang),
which gives the singular loci of the moduli space in Batyrev coordinates.
Parameters:
- only_strong_coupling: If True, only gives loci arising from edges (one-dimensional faces).
- no_triangulation: Index of the triangulation to use.
which gives the singular loci of the moduli space in Batyrev coordinates. There is an option
to only compute strong coupling discriminant factors, so those coming from dependencies
in one-dimensional faces.
Returns:
A list of tuples [disc_i, codim_i] of discriminant factors disc_i
coming from a relation inside a face of codimension codim_i.
"""
logger.info("Computing discriminant for %s", self.model_name)
if only_strong_coupling:
logger.info("Restricting to strong-coupling loci (codimension-1 faces).")
all_linear_dependencies_among_points = self._collect_linear_dependencies(only_strong_coupling)
self._append_origin_weight(all_linear_dependencies_among_points)
a_vars, z_vars, lambda_vars, a_row, mori_matrix = self._setup_discriminant_symbols()
@@ -344,6 +361,9 @@ class ToricPolytope(Polytope):
# Insert an empty codimension-0 entry for compatibility with prior behavior.
discriminants = [[]] + discriminants
logger.info("Found %d discriminant factors.", len(discriminants))
logger.info("Discriminant factors: %s", discriminants)
return discriminants
##############################
@@ -482,7 +502,7 @@ class ToricPolytope(Polytope):
messages.append("Possible elliptic fibration in the divisor class dual to t{}.".format(i))
if messages:
logger.info("\n\n--- Elliptic fibrations --------------------------\n" + "\n".join(messages))
logger.info("\n\n--- Elliptic fibrations --------------------------\n%s", "\n".join(messages))
return messages
@@ -609,11 +629,7 @@ class ToricPolytope(Polytope):
def _write_output_json(self, output):
"""
Writes the given output dictionary (from _get_output, i.e. exactly what is
logged) to data/<model_name>.json (relative to the repository root), if a
model_name is given. Plain JSON, so it is directly loadable in Python
(json.load), C++ (e.g. nlohmann::json), or any other language without any
custom parsing code; lvec loads back as a plain list of lists, e.g. lvec[0].
"""
logged) to data/<model_name>.json."""
if not self.model_name:
logger.info("No model_name given, skipping writing topological data to JSON.")
return None
@@ -631,24 +647,9 @@ class ToricPolytope(Polytope):
def topdata(self):
"""
Computes topological data for hypersurfaces and CICYs in toric ambient spaces.
For hypersurfaces, nef_partition should remain untouched (=0).
For CICYs with d polynomials, a nef_partition has to be supplied:
its format should be a list of d lists as in the examples below
which is a decomposition of the N points of $(polytope); the number
should corresponds to an enumeration of the points of $(polytope) with
the inner point omitted.
Conditions for possible fibrations are:
- elliptic: if t_i^n = 0 and t_i^{n-1} != 0
- K3 (only 3-folds): if c2.t_i = 24
Input: - (for CICYs:) nef-partition
- (optional:) set of l-vectors to be used
- (optional:) index of triangulation
Computes topological data for hypersurfaces and CICYs in toric ambient spaces
and saves the result to /data/topdata/<model_name>.json if a model_name is provided.
"""
no_polys = len(self.nef_partition)
self.cy_dimension = self.dimension - no_polys
# Each point gives a toric divisor, each "column" gives one linear relation
self.no_divs = len(self.relevant_lattice_points) - self.dimension - 1
@@ -731,7 +732,6 @@ class ToricPolytopeCICY(ToricPolytope):
def __init__(self, CICY, no_triangulation=0, model_name=None, lvec=None):
points, nef_partition = self._CICY_to_points(CICY)
print(points, nef_partition)
super().__init__(
points,
no_triangulation=no_triangulation,