repair_checks.py

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))