files / problems / kissing-5d / compute / verify_configs.py

2.3 KB · on GitHub

#!/usr/bin/env python3
"""Replay the four published 40-point codes and Cohn–Rajagopal Table 2.1."""

from __future__ import annotations

import json
import sys
from fractions import Fraction
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parent))

from configs import CONFIGS, _dot, _norm2, ip_histogram, is_kissing

# Cohn–Rajagopal arXiv:2412.00937v3, Table 2.1: unordered pair counts.
# Columns: -1, -4/5, -3/4, -1/2, -3/10, -1/4, 0, 1/5, 1/2
PUBLISHED = {
    "D5": {
        Fraction(-1): 20,
        Fraction(-1, 2): 240,
        Fraction(0): 280,
        Fraction(1, 2): 240,
    },
    "L5": {
        Fraction(-1): 12,
        Fraction(-3, 4): 32,
        Fraction(-1, 2): 192,
        Fraction(-1, 4): 32,
        Fraction(0): 272,
        Fraction(1, 2): 240,
    },
    "Q5": {
        Fraction(-1): 10,
        Fraction(-4, 5): 30,
        Fraction(-1, 2): 180,
        Fraction(-3, 10): 60,
        Fraction(0): 250,
        Fraction(1, 5): 10,
        Fraction(1, 2): 240,
    },
    "R5": {
        Fraction(-1): 6,
        Fraction(-4, 5): 30,
        Fraction(-3, 4): 20,
        Fraction(-1, 2): 144,
        Fraction(-3, 10): 60,
        Fraction(-1, 4): 28,
        Fraction(0): 242,
        Fraction(1, 5): 10,
        Fraction(1, 2): 240,
    },
}


def _fmt(h):
    return {f"{t.numerator}/{t.denominator}": c for t, c in h.items()}


def main() -> int:
    report = {}
    ok = True
    for name, builder in CONFIGS.items():
        pts = builder()
        norms = {_norm2(p) for p in pts}
        hist = ip_histogram(pts)
        kissing = is_kissing(pts)
        match = hist == PUBLISHED[name]
        n = len(pts)
        status = {
            "n": n,
            "squared_norms": [f"{x.numerator}/{x.denominator}" for x in sorted(norms)],
            "kissing": kissing,
            "histogram": _fmt(hist),
            "matches_CR_table_2_1": match,
        }
        report[name] = status
        print(f"{name}: n={n} kissing={kissing} table={match}")
        if n != 40 or not kissing or not match or norms != {2}:
            ok = False
            print("  FAIL", status)
    out = Path(__file__).resolve().parent / "verify_configs.json"
    out.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n")
    print("wrote", out)
    return 0 if ok else 1


if __name__ == "__main__":
    raise SystemExit(main())