back to table · edit · history · where entries came from · files · download
3926 bytes, as of the version from 2026-10-16 08:41 (current). Recorded here, not run.
"""Check T458 for its definition repair; writes nothing to NumberDB.
Run: sage -python repair_checks.py table.json
Place the table's attached generate.py beside this script. The default input
is T458-document-before.json. Output is a JSON report. Checks of degree,
range, closed forms, and stored string/dilaton identities do not call the
generator. A separate comparison recomputes every value using that generator.
The dimension argument is Afandi, arXiv:2209.14131v1, Sections 1.1 and 3:
psi_i has complex codimension one and the stack has dimension 3g-3+n.
Permuting marked points preserves the integral but does not impose its degree.
"""
import numberdb.sage as numberdb
from sage.rings.rational_field import QQ
from itertools import combinations_with_replacement
from math import factorial, prod
from pathlib import Path
import json
import sys
path = Path(sys.argv[1]) if len(sys.argv) > 1 else Path(__file__).with_name('T458-document-before.json')
doc = json.loads(path.read_text())
assert list(doc['Parameters']) == ['g', 'n', 'd']
assert 'non-decreasing' in doc['Parameters']['d']['constraints']
assert r'\sum_i d_i=3g-3+n' in doc['Parameters']['d']['constraints']
assert 'Sorting only chooses a representative of the symmetric integral.' in doc['Comments']['profiles']
rows = {}
for gs, ns in doc['Numbers'].items():
for nstr, ds_values in ns.items():
for dstr, raw in ds_values.items():
g, n, ds = int(gs), int(nstr), tuple(map(int, dstr.split(',')))
assert len(ds) == n and tuple(sorted(ds)) == ds and min(ds) >= 0
assert g >= 0 and 2*g-2+n > 0 and sum(ds) == 3*g-3+n
assert isinstance(raw, str) and '.' not in raw
key = (g, ds)
assert key not in rows
parts = raw.split('/')
assert len(parts) in (1, 2)
rows[key] = QQ(int(parts[0])) / QQ(int(parts[1]) if len(parts) == 2 else 1)
expected = set()
for g in range(6):
for n in range(1, 6):
if 2*g-2+n <= 0:
continue
degree = 3*g-3+n
expected.update((g, ds) for ds in combinations_with_replacement(range(degree+1), n) if sum(ds) == degree)
assert set(rows) == expected and len(rows) == 494
counts = {'rows_and_constraints': len(rows), 'range': len(expected), 'genus_zero': 0,
'one_point': 0, 'one_positive_exponent': 0, 'string': 0, 'dilaton': 0}
for (g, ds), value in rows.items():
n = len(ds)
if g == 0:
assert value == QQ(factorial(n-3))/QQ(prod(factorial(d) for d in ds))
counts['genus_zero'] += 1
if g > 0 and n == 1:
assert value == QQ(1)/(QQ(24)**g*factorial(g))
counts['one_point'] += 1
if g > 0 and sum(d > 0 for d in ds) == 1:
assert value == QQ(1)/(QQ(24)**g*factorial(g))
counts['one_positive_exponent'] += 1
if 0 in ds and 2*g-2+(n-1) > 0:
rest = list(ds); rest.remove(0)
rhs = QQ(0)
for j, d in enumerate(rest):
if d:
lowered = rest.copy(); lowered[j] -= 1
rhs += rows[g, tuple(sorted(lowered))]
assert value == rhs
counts['string'] += 1
if 1 in ds and 2*g-2+(n-1) > 0:
rest = list(ds); rest.remove(1)
assert value == (2*g-3+n)*rows[g, tuple(rest)]
counts['dilaton'] += 1
examples = [(0, (0, 0, 0), QQ(1)), (1, (1,), QQ(1)/QQ(24)),
(5, (5, 5, 5), QQ(41873)/QQ(255467520))]
for g, ds, value in examples:
assert rows[g, ds] == value
counts['Macaulay2_documented_examples'] = len(examples)
from generate import intersection
for (g, ds), value in rows.items():
assert intersection(g, ds) == value, (g, ds)
counts['attached_generator_recomputed'] = len(rows)
print(json.dumps({'table': 'T458', 'passed': True, 'checks': counts,
'scope': 'Independent range, closed-form and stored-identity checks; full recomputation with the existing attached generator.'}, indent=2))