check_coxeter.py

back to table · edit · history · where entries came from · files · download

3877 bytes, as of the version from 2026-10-25 17:24 (current). Recorded here, not run.

"""Verify the identity moved to Formulas in numberdb.org/T495.

Run: sage -pip install numberdb
     sage -python check_coxeter.py T495-table.json coxeter-table.json
The JSON files are fresh GET /api/table documents. This script writes no table.
The relation P_W(1)=|W| follows directly from its defining finite sum.
For ADE root lattices the norm-2 vectors are exactly the roots, so their
isometries are root-system automorphisms. The Weyl group acts simply
transitively on chambers; the stabilizer of a chosen chamber permutes its
simple roots through the Dynkin-diagram automorphisms. Hence the orders
multiply. We check that product against every stored ADE root-lattice row.
"""
import json
from collections import Counter
from math import factorial
import pathlib
import sys
import numberdb.sage as numberdb
from sage.combinat.root_system.cartan_type import CartanType
from sage.rings.integer_ring import ZZ
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
from sage.env import SAGE_VERSION

base=pathlib.Path(__file__).resolve().parent
path=pathlib.Path(sys.argv[1]) if len(sys.argv)>1 else base/'T495-table.json'
companion=pathlib.Path(sys.argv[2]) if len(sys.argv)>2 else base/'coxeter-table.json'
d=json.loads(path.read_text()); c=json.loads(companion.read_text())
R=PolynomialRing(ZZ,'t')

def value(v):
    return ZZ(v['number'] if isinstance(v,dict) else v)

def tree_automorphism_order(graph):
    # A rooted tree is determined by the multiset of its rooted branches.
    # Equal branches may be permuted, contributing multiplicity factorials.
    # Orbit-stabilizer at one vertex recovers the unrooted tree's order.
    assert graph.is_tree()
    def rooted(v, parent=None):
        branches=[rooted(w,v) for w in graph.neighbors(v) if w!=parent]
        signature=tuple(sorted(sig for sig,count in branches))
        count=1
        for sig,subcount in branches: count*=subcount
        for multiplicity in Counter(sig for sig,num in branches).values():
            count*=factorial(multiplicity)
        return signature,count
    vertices=list(graph)
    sig,fixed=rooted(vertices[0])
    orbit=sum(rooted(v)[0]==sig for v in vertices)
    return ZZ(fixed*orbit)

# A2 is an independently known hexagonal-lattice control: six Weyl elements,
# a two-element diagram symmetry group, and twelve lattice isometries.
rows=[]
for family in ['A','D','E']:
    for rank,v in d['Numbers'][family].items():
        n=int(rank); ct=CartanType([family,n])
        # Finite Weyl-group order is the product of fundamental degrees.
        roots=ct.root_system().root_lattice().positive_roots()
        heights=[int(root.height()) for root in roots]
        # The number of positive roots of height k equals the number of
        # exponents at least k. Recover the exponents from that partition.
        counts=[heights.count(k) for k in range(1,max(heights)+1)]
        exponents=[sum(count>=i for count in counts) for i in range(1,n+1)]
        degrees=[e+1 for e in exponents]
        order=ZZ(1)
        for degree in degrees: order*=degree
        diagram=ct.dynkin_diagram().to_undirected()
        factor=tree_automorphism_order(diagram)
        assert order*factor==value(v),(family,n,order,factor,value(v))
        label=family+rank
        if label in c['Numbers']:
            p=c['Numbers'][label]
            p=p['number'] if isinstance(p,dict) else p
            assert R(p)(1)==order,(label,'Poincare evaluation')
        if label=='A2': assert (order,factor,value(v))==(6,2,12)
        rows.append({'type':label,'weyl_order':str(order),'diagram_order':int(factor),'stored_order':str(value(v)),'companion_checked':label in c['Numbers']})
print(json.dumps({'sage_version':SAGE_VERSION,'root_rows_checked':len(rows),'companion_polynomials_checked':sum(r['companion_checked'] for r in rows),'all_passed':True,'rows':rows},indent=2))