back to table · edit · history · where entries came from · files · download
1923 bytes, as of the version from 2026-11-01 21:32 (current). Recorded here, not run.
"""Export exact Monster class metadata from CTblLib 1.3.11.
Run with Sage; provide ctbllib-1.3.11.tar.gz and utils-1.01.tar.gz beside this script.
The utils dependency is loaded only in the disposable process.
"""
import numberdb.sage as numberdb
from sage.interfaces.gap import gap
from pathlib import Path
import tempfile,tarfile,json,hashlib
HERE=Path(__file__).resolve().parent
with tempfile.TemporaryDirectory() as directory:
for name in ['ctbllib-1.3.11.tar.gz','utils-1.01.tar.gz']:
with tarfile.open(HERE/name) as archive: archive.extractall(directory,filter='data')
for name in ['utils','ctbllib']:
path=next(Path(directory).glob(name+'*'))
gap.eval('SetPackagePath("'+name+'", "'+str(path)+'");;')
assert gap.eval('LoadPackage("ctbllib");')=='true'
gap.eval('t:=CharacterTable("M");;')
names=json.loads(gap.eval('ClassNames(t);').replace('\n',''))
orders=[int(x) for x in gap('OrdersClassRepresentatives(t)').sage()]
chosen=[i for i,n in enumerate(orders) if n<=10]
assert chosen==list(range(33))
power={str(p): [int(x) for x in gap('PowerMap(t,%d)'%p).sage()] for p in [2,3,5,7]}
chars=[[int(x) for x in gap('List(Irr(t){[1..15]},chi->chi[%d])'%(i+1)).sage()] for i in chosen]
result={'source':'CTblLib 1.3.11, CharacterTable("M"), ATLAS ordering', 'gap_version':gap.eval('GAPInfo.Version;').strip('"'),'ctbllib_version':gap.eval('PackageInfo("ctbllib")[1].Version;').strip('"'),'utils_version':gap.eval('PackageInfo("utils")[1].Version;').strip('"'),'archive_sha256':{n:hashlib.sha256((HERE/n).read_bytes()).hexdigest() for n in ['ctbllib-1.3.11.tar.gz','utils-1.01.tar.gz']},'class_names':[n.upper() for n in names],'class_orders':orders,'power_maps':{p:{names[i].upper():names[a[i]-1].upper() for i in chosen} for p,a in power.items()},'first15_characters':{names[i].upper():chars[i] for i in chosen}}
print(json.dumps(result,indent=2))