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 os
import json import json
from datetime import datetime, timezone from datetime import datetime, timezone
import re
# Logger
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.DEBUG) # or logging.DEBUG to see both logging.basicConfig(level=logging.DEBUG)
# For grep-commands # For grep-commands
import re find_zs = re.compile(r'z\d+')
find_zs = re.compile('z\d+') find_ls = re.compile(r'l\d+')
find_ls = re.compile('l\d+') find_index_z = re.compile(r'\d+')
find_index_z = re.compile('\d+')
class Polytope: class Polytope:
""" """
Class representing a lattice polytope. Objects contain a list of defining points 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 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. 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. 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)) raise ValueError("Invalid nef partition: {}".format(nef_partition))
self.nef_partition = nef_partition self.nef_partition = nef_partition
else: 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): 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.") raise ValueError("All rows in lvec must have the same length.")
elif len(lvec[0]) != len(self.relevant_lattice_points): elif len(lvec[0]) != len(self.relevant_lattice_points):
raise ValueError("The length of the l-vectors is invalid.") 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.") raise ValueError("The provided l-vectors are not in the linear span of the original Mori cone.")
else: else:
self.Mori_cone = Cone(lvec) self.Mori_cone = Cone(lvec)
if len(matrix(self.Mori_cone.rays()).kernel().gens()) > 0: if len(matrix(self.Mori_cone.rays()).kernel().gens()) > 0:
logger.warning("Non-simplicial Mori-cone encountered.") 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( self.Mori_cone = Cone(
transpose( transpose(
transpose(self.Mori_cone.rays()) transpose(self.Mori_cone.rays())
@@ -144,7 +146,8 @@ class ToricPolytope(Polytope):
).kernel().gens() ).kernel().gens()
).transpose() ).transpose()
) )
logger.info("Using the first %d linearly independent vectors.", len(self.Mori_cone.rays()))
self.lvec = matrix(self.Mori_cone.rays()) self.lvec = matrix(self.Mori_cone.rays())
def __init__( def __init__(
@@ -161,11 +164,22 @@ class ToricPolytope(Polytope):
self.set_triangulation(no_triangulation) self.set_triangulation(no_triangulation)
self.set_nef_partition(nef_partition) self.set_nef_partition(nef_partition)
self.cy_dimension = self.dimension - len(self.nef_partition)
self.fan = self.triangulation.fan(self.origin) self.fan = self.triangulation.fan(self.origin)
self.ToricVariety = ToricVariety(self.fan) self.ToricVariety = ToricVariety(self.fan)
self.set_Mori_cone(lvec = lvec) 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 # Discriminant Computation
############################### ###############################
@@ -264,6 +278,7 @@ class ToricPolytope(Polytope):
except: except:
# In one-parameter cases there may be nothing to eliminate. # In one-parameter cases there may be nothing to eliminate.
polynomials = equation_system polynomials = equation_system
logger.debug("No elimination needed for the equation system: %s", equation_system)
try: try:
if len(lambda_symbols) == 0: if len(lambda_symbols) == 0:
@@ -295,20 +310,22 @@ class ToricPolytope(Polytope):
codim = total_relation_blocks - 1 - index codim = total_relation_blocks - 1 - index
discriminants.append([polynomial, codim]) 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), Computes the A-discriminant for the toric polytope (following Aspinwall, Plesser, Wang),
which gives the singular loci of the moduli space in Batyrev coordinates. 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
Parameters: in one-dimensional faces.
- only_strong_coupling: If True, only gives loci arising from edges (one-dimensional faces).
- no_triangulation: Index of the triangulation to use.
Returns: Returns:
A list of tuples [disc_i, codim_i] of discriminant factors disc_i A list of tuples [disc_i, codim_i] of discriminant factors disc_i
coming from a relation inside a face of codimension codim_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) all_linear_dependencies_among_points = self._collect_linear_dependencies(only_strong_coupling)
self._append_origin_weight(all_linear_dependencies_among_points) self._append_origin_weight(all_linear_dependencies_among_points)
a_vars, z_vars, lambda_vars, a_row, mori_matrix = self._setup_discriminant_symbols() 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. # Insert an empty codimension-0 entry for compatibility with prior behavior.
discriminants = [[]] + discriminants discriminants = [[]] + discriminants
logger.info("Found %d discriminant factors.", len(discriminants))
logger.info("Discriminant factors: %s", discriminants)
return discriminants return discriminants
############################## ##############################
@@ -482,7 +502,7 @@ class ToricPolytope(Polytope):
messages.append("Possible elliptic fibration in the divisor class dual to t{}.".format(i)) messages.append("Possible elliptic fibration in the divisor class dual to t{}.".format(i))
if messages: 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 return messages
@@ -609,11 +629,7 @@ class ToricPolytope(Polytope):
def _write_output_json(self, output): def _write_output_json(self, output):
""" """
Writes the given output dictionary (from _get_output, i.e. exactly what is 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 logged) to data/<model_name>.json."""
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].
"""
if not self.model_name: if not self.model_name:
logger.info("No model_name given, skipping writing topological data to JSON.") logger.info("No model_name given, skipping writing topological data to JSON.")
return None return None
@@ -631,24 +647,9 @@ class ToricPolytope(Polytope):
def topdata(self): def topdata(self):
""" """
Computes topological data for hypersurfaces and CICYs in toric ambient spaces. Computes topological data for hypersurfaces and CICYs in toric ambient spaces
For hypersurfaces, nef_partition should remain untouched (=0). and saves the result to /data/topdata/<model_name>.json if a model_name is provided.
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
""" """
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 # Each point gives a toric divisor, each "column" gives one linear relation
self.no_divs = len(self.relevant_lattice_points) - self.dimension - 1 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): def __init__(self, CICY, no_triangulation=0, model_name=None, lvec=None):
points, nef_partition = self._CICY_to_points(CICY) points, nef_partition = self._CICY_to_points(CICY)
print(points, nef_partition)
super().__init__( super().__init__(
points, points,
no_triangulation=no_triangulation, no_triangulation=no_triangulation,