back to table · edit · history · where entries came from · files · download
6066 bytes, as of the version from 2026-10-25 17:54 (current). Recorded here, not run.
"""Independent checks for numberdb.org/T496.
sage -python checks.py checks locally. With NUMBERDB_CHECK_STORED=1 it also
reads the authenticated draft and verifies its entries independently.
The checks deliberately do not call the generator's order_of or weyl_order
when building the independent answers. Weyl orders use Sage's positive-root
heights, quotient orders use Chenevier's separately transcribed group
identifications, and the mass uses Bernoulli numbers.
"""
import json
import os
import re
import sys
from functools import lru_cache
from pathlib import Path
import numberdb.sage as numberdb
from sage.rings.integer_ring import ZZ
from sage.rings.rational_field import QQ
from sage.arith.misc import bernoulli
from sage.combinat.root_system.root_system import RootSystem
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
from generate import NiemeierAutomorphismOrders
from check import exactness, measure, agrees_with, names_its_rings
HERE = Path(__file__).resolve().parent
QUOTIENTS = json.loads((HERE/'independent-quotients.json').read_text())
def number_only(value):
return value['number'] if isinstance(value, dict) else value
@lru_cache(None)
def root_height_order(letter, rank):
result = QQ(1)
for root in RootSystem([letter, rank]).root_lattice().positive_roots():
h = root.height()
result *= QQ(h+1)/QQ(h)
assert result.denominator() == 1
return ZZ(result)
def independent_order(key):
a, b, _ = QUOTIENTS[key]
result = ZZ(a)*ZZ(b)
if key != 'Leech':
for component in re.finditer(r'([ADE])(\d+)(?:\^(\d+))?', key):
t, n, m = component.groups()
result *= root_height_order(t, int(n))**int(m or 1)
return result
def mass(dimension):
result = abs(QQ(bernoulli(dimension//2))) / ZZ(dimension)
for j in range(1, dimension//2):
result *= abs(QQ(bernoulli(2*j))) / ZZ(4*j)
return result
def validate(values):
# Known controls are run before this method is trusted for rank 24.
assert root_height_order('A', 2) == 6
assert root_height_order('D', 4) == 192
assert mass(8) == QQ(1)/ZZ(696729600)
assert mass(16) == QQ(1)/(ZZ(2)*ZZ(696729600)**2) + QQ(1)/(ZZ(2)**15*ZZ(20922789888000))
assert set(values) == set(QUOTIENTS)
assert not exactness(values)
assert not agrees_with(values, independent_order)
total = sum((QQ(1)/v for v in values.values()), QQ(0))
assert total == mass(24)
# The mass check must reject one miscopied order and an omitted row.
wrong = dict(values)
wrong['A1^24'] += 1
assert sum((QQ(1)/v for v in wrong.values()), QQ(0)) != mass(24)
assert total - QQ(1)/values['Leech'] != mass(24)
assert values['E8^3'] == ZZ(6)*ZZ(696729600)**3
# Independently enumerate the allowable nonempty ADE root systems.
by_h = {}
for t, ranks in [('A',range(1,25)),('D',range(4,25)),('E',[6,7,8])]:
for n in ranks:
h = n+1 if t=='A' else 2*n-2 if t=='D' else {6:12,7:18,8:30}[n]
by_h.setdefault(h,[]).append((t,n))
possibilities = set()
def enumerate_rank(items, index, remaining, parts):
if index == len(items):
if remaining == 0:
possibilities.add(''.join(t+str(n)+('^'+str(m) if m>1 else '') for t,n,m in parts))
return
t,n = items[index]
for multiplicity in range(remaining//n+1):
enumerate_rank(items,index+1,remaining-n*multiplicity,
parts+([(t,n,multiplicity)] if multiplicity else []))
for components in by_h.values():
enumerate_rank(components,0,24,[])
assert possibilities == set(values)-{'Leech'}
return {'entries':len(values),'mass':str(total),'mass_formula':str(mass(24)),
'independent_orders_matched':24,'ADE_root_systems':len(possibilities),
'positive_controls':['A2 order 6','D4 order 192','rank-8 mass','rank-16 mass'],
'negative_controls':['one order increased by 1','Leech row omitted'],
'measurement':measure(values)}
def check_corpus(values, documents):
sporadic = documents['T77']['Numbers']
assert values['Leech'] == 2*ZZ(number_only(sporadic['Co1']))
assert values['A1^24'] == ZZ(2)**24*ZZ(number_only(sporadic['M24']))
assert values['A2^12'] == ZZ(6)**12*2*ZZ(number_only(sporadic['M12']))
assert values['Leech'] == ZZ(number_only(documents['T495']['Numbers']['Lambda']['24']))
ring = PolynomialRing(ZZ,'t')
compared = []
for key, polynomial in documents['T257']['Numbers'].items():
m=re.fullmatch(r'([ADE])(\d+)',key)
if m:
assert ring(number_only(polynomial))(1) == root_height_order(m[1],int(m[2]))
compared.append(key)
return {'sporadic_relations':3,'classical_Leech_overlap':True,'stored_Coxeter_polynomials':compared}
def main():
assert not names_its_rings(str(HERE/'generate.py'))
gen = NiemeierAutomorphismOrders()
values = {p['root_system']:number_only(gen.value(p,100)) for p in gen.enumerate()}
report = {'local':validate(values)}
if (HERE/'corpus.json').exists():
report['corpus']=check_corpus(values,json.loads((HERE/'corpus.json').read_text()))
if os.environ.get('NUMBERDB_CHECK_STORED') == '1':
if os.environ.get('NUMBERDB_KEY_FROM_STDIN') == '1':
token=sys.stdin.read().strip()
if '=' in token and token.split('=',1)[0].isupper():
token=token.split('=',1)[1].strip().strip('\"\'')
os.environ['NUMBERDB_API_KEY']=token
saved=numberdb.table('T496')
stored={k:ZZ(number_only(v)) for k,v in saved['Numbers'].items()}
report['stored']=validate(stored)
documents={tid:numberdb.table(tid) for tid in ['T77','T495','T257']}
report['stored_corpus']=check_corpus(stored,documents)
verified=gen.verify(sample=None)
assert verified.ok
report['verify']=str(verified)
print(json.dumps(report,indent=2))
return report
if __name__=='__main__':
main()