back to table · edit · history · where entries came from · files · download
5002 bytes, as of the version from 2026-10-27 21:54 (current). Recorded here, not run.
"""Kontsevich–Zorich sum of Lyapunov exponents -- numberdb.org/T562.
Run with SageMath (install numberdb once with sage -pip install numberdb):
sage -python generate.py # verify every stored entry
sage -python generate.py --fill # fill the existing draft only
sage -python checks.py # exact independent checks
--fill requires NUMBERDB_API_KEY. It writes entries and attached files; it
never offers, reviews, or makes a draft public. NUMBERDB_KEY_FROM_STDIN=1
reads a token from stdin; NUMBERDB_PUBLISH=1 is the runner's --fill alias.
Exact data: Eskin–Kontsevich–Zorich, Publ. Math. IHES 120 (2014),
Corollary 2 and Appendix A, p. 326, exact sum column (not experimental
individual exponents). doi:10.1007/s10240-013-0060-3, arXiv:1112.5872.
All 25 classified components in genera 2..4. The table domain is unbounded;
this transcription refuses unsupported nonhyperelliptic cases. Hyperelliptic
values beyond this range can be computed by hyperelliptic_sum().
H(2,2,2)^even = 737/333 is confirmed from EMZ Appendix B.2 configuration
constants, resolving the conflicting 166/75 in Chen–Möller Section 6.9.
See source-notes.md and checks.py. No floating point or rounding is used.
"""
import os
import sys
from fractions import Fraction
import numberdb.sage as numberdb
from sage.rings.integer_ring import ZZ
from sage.rings.rational_field import QQ
# The source's ascending zero profiles are reordered, without changing labels.
ROWS = (
(2, (2,), 'hyp', '4/3'),
(2, (1, 1), 'hyp', '3/2'),
(3, (4,), 'hyp', '9/5'),
(3, (4,), 'odd', '8/5'),
(3, (3, 1), 'connected', '7/4'),
(3, (2, 2), 'hyp', '2'),
(3, (2, 2), 'odd', '5/3'),
(3, (2, 1, 1), 'connected', '11/6'),
(3, (1, 1, 1, 1), 'connected', '53/28'),
(4, (6,), 'hyp', '16/7'),
(4, (6,), 'even', '2'),
(4, (6,), 'odd', '13/7'),
(4, (5, 1), 'connected', '2'),
(4, (4, 2), 'even', '32/15'),
(4, (4, 2), 'odd', '29/15'),
(4, (4, 1, 1), 'connected', '1137/550'),
(4, (3, 3), 'hyp', '5/2'),
(4, (3, 3), 'nonhyp', '2'),
(4, (3, 2, 1), 'connected', '25/12'),
(4, (3, 1, 1, 1), 'connected', '66/31'),
(4, (2, 2, 2), 'even', '737/333'),
(4, (2, 2, 2), 'odd', '2'),
(4, (2, 2, 1, 1), 'connected', '5045/2358'),
(4, (2, 1, 1, 1, 1), 'connected', '131/60'),
(4, (1, 1, 1, 1, 1, 1), 'connected', '839/377'),
)
DATA = {(g, mu, c): QQ(Fraction(v).numerator) / QQ(Fraction(v).denominator)
for g, mu, c, v in ROWS}
def hyperelliptic_sum(g, zeros=1):
"""EKZ Corollary 1: one zero of order 2g-2, or two zeros of order g-1."""
g = ZZ(g)
if g < 2 or zeros not in (1, 2):
raise ValueError('Use an integer genus >= 2 and zeros=1 or 2.')
return QQ(g*g) / QQ(2*g-1) if zeros == 1 else QQ(g+1) / QQ(2)
def lyapunov_sum(g, mu, component):
"""Return the exact component sum; mu must be a non-increasing profile."""
g = ZZ(g)
mu = tuple(ZZ(m) for m in mu)
if g < 2 or not mu or sum(mu) != 2*g-2 or min(mu) < 1:
raise ValueError('The positive zero orders must sum to 2g-2, with g >= 2.')
if tuple(sorted(mu, reverse=True)) != mu:
raise ValueError('Use non-increasing zero orders.')
try:
return DATA[(g, mu, component)]
except KeyError:
raise ValueError('No transcribed value for this component; do not infer one.') from None
class LyapunovSums(numberdb.Generator):
table = 'T562'
parameters = ('g', 'mu', 'component')
type = 'Q'
rigour = 'exact'
digits = 100 # Exact rationals have no finite-precision claim.
files = ('generate.py', 'checks.py', 'check.py', 'argument-selection.md',
'source-notes.md', 'source-column.json', 'T561.json', 'sources.json',
'skill-evidence.json', 'numerical-evidence.json')
def enumerate(self):
for g, mu, component, _ in ROWS:
yield {'g': g, 'mu': ','.join(map(str, mu)), 'component': component}
def value(self, params, digits=100):
g = ZZ(params['g'])
mu = tuple(ZZ(x) for x in params['mu'].split(','))
component = params['component']
value = lyapunov_sum(g, mu, component)
if (g, mu, component) == (4, (2, 2, 2), 'even'):
return {'number': value, 'comment': r'The value $737/333$ in CITE{EKZ}, Appendix A, follows from the cylinder configurations in CITE{EMZ}, Appendix B.2; it differs from $166/75$ printed in CITE{CM}, Section 6.9.'}
return value
if __name__ == '__main__':
if os.environ.get('NUMBERDB_KEY_FROM_STDIN') == '1':
numberdb.configure(api_key=sys.stdin.read().strip())
generator = LyapunovSums()
if '--fill' in sys.argv or os.environ.get('NUMBERDB_PUBLISH') == '1':
print(generator.publish(message='Store 25 exact component sums with source reconciliation and independent checks'))
else:
report = generator.verify(sample=None)
print(report)
sys.exit(0 if report.ok else 1)