back to table · edit · history · where entries came from · files · download
4311 bytes, as of the version from 2026-10-25 17:54 (current). Recorded here, not run.
"""Orders of the automorphism groups of the Niemeier lattices -- numberdb.org/T496.
Run with SageMath (or a compatible modular Sage installation):
sage -pip install numberdb
sage -python generate.py # verify all stored entries
sage -python generate.py --fill # write entries to this existing draft
sage -python checks.py # independent arithmetic/source checks
For authenticated draft access set NUMBERDB_API_KEY, or pipe the key on stdin
with NUMBERDB_KEY_FROM_STDIN=1. Filling requires the key and does not publish
or offer the draft for review. The table is the complete set of 24 classes.
The input borcherds-norm0.txt is the unchanged file downloaded from
https://math.berkeley.edu/~reb/lattices/norm0 . Its first field is the Coxeter
number, fifth the root system, and sixth the quotient order |O(L)/W(R)|.
For the rootless Leech lattice W(R) is trivial. Chenevier (2020), Section 5.2,
independently identifies all 23 nontrivial-root quotients; Example 1.3 and
Table C.5 identify the Leech group. The computation uses exact integer
products of Weyl-group orders. No enumeration of a huge automorphism group
and no floating-point arithmetic is required.
"""
import os
import re
import sys
from pathlib import Path
import numberdb.sage as numberdb
from sage.rings.integer_ring import ZZ
HERE = Path(__file__).resolve().parent
def source_rows():
rows = []
for line in (HERE / 'borcherds-norm0.txt').read_text().splitlines():
fields = line.split()
h, root, quotient = int(fields[0]), fields[4], ZZ(fields[5])
key = 'Leech' if root == 'None' else root.upper()
parts = [(t.upper(), int(n), int(m or 1))
for t, n, m in re.findall(r'([ade])(\d+)(?:\^(\d+))?', root)]
if root != 'None':
reconstructed = ''.join(t.lower() + str(n) + ('^' + str(m) if m > 1 else '')
for t, n, m in parts)
assert reconstructed == root
assert sum(n*m for _, n, m in parts) == 24
rows.append((key, h, parts, quotient))
assert len(rows) == len({r[0] for r in rows}) == 24
return rows
def factorial_z(n):
result = ZZ(1)
for k in range(2, n + 1):
result *= k
return result
def weyl_order(letter, rank):
if letter == 'A':
return factorial_z(rank + 1)
if letter == 'D':
return ZZ(2)**(rank - 1) * factorial_z(rank)
return ZZ({6: 51840, 7: 2903040, 8: 696729600}[rank])
def order_of(row):
_, _, components, quotient = row
order = quotient
for letter, rank, multiplicity in components:
order *= weyl_order(letter, rank)**multiplicity
return order
class NiemeierAutomorphismOrders(numberdb.Generator):
table = 'T496'
parameters = ('root_system',)
type = 'Z'
rigour = 'exact'
files = ('generate.py', 'checks.py', 'check.py', 'borcherds-norm0.txt',
'source-notes.md', 'independent-quotients.json')
def enumerate(self):
for key, _, _, _ in source_rows():
yield {'root_system': key}
def value(self, params, digits):
row = next(r for r in source_rows() if r[0] == params['root_system'])
value = order_of(row)
if row[0] == 'Leech':
return {'number': value, 'comment':
r'The Leech lattice $\Lambda_{24}$ has no roots. Its full '
r'automorphism group is $\mathrm{Co}_0=2.\mathrm{Co}_1$.'}
if row[0] == 'E8^3':
return {'number': value, 'comment':
r'The orthogonal direct sum $E_8\oplus E_8\oplus E_8$.'}
return value
if __name__ == '__main__':
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
gen = NiemeierAutomorphismOrders()
if '--fill' in sys.argv or os.environ.get('NUMBERDB_PUBLISH') == '1':
print(gen.publish(message='Compute all 24 exact orders; check quotient groups, positive-root heights and the mass formula'))
else:
report = gen.verify(sample=None)
print(report)
sys.exit(0 if report.ok else 1)