#!/usr/bin/env python3
"""
verify_P109.py -- Addendum 109: NNNLO Weinberg-angle 600-cell loop.

This verifier checks the Weinberg-angle numerics in
109_Addendum_WeinbergNNNLO.tex: lambda powers, LO/NLO/NNLO values, the golden
target 3/(8 phi), 600-cell combinatorics, c6=-24/5, the NLO+c6 path, and the
estimated c8 residual.

The rounded NLO+c6 arithmetic reproduces. The flagged issue is that the paper
calls c6 an NNNLO coefficient in the same loop expansion that contains c4, but
the advertised -0.006% gap is obtained only by skipping the NNLO c4 term. The
full expansion through c6 gives a much worse gap. Exact, non-rounded values
also shift the required c6 and c8 estimates.
"""

from __future__ import annotations

import math
import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parent))
class Verifier:
    """Output shim: identical tolerance semantics to verify_common.Verifier,
    modern [PASS]/[FAIL] check-line output format."""

    def __init__(self, name):
        self.PASS = 0
        self.FAIL = 0
        self.n = 0
        print(name)

    def _mark(self, ok, desc):
        self.n += 1
        if ok:
            self.PASS += 1
        else:
            self.FAIL += 1
        print(f"  [{'PASS' if ok else 'FAIL'}] {self.n:>2}. {desc}")

    def check(self, label, computed, claimed, *, rel=1e-3, abs_tol=None, detail=""):
        if abs_tol is not None:
            ok = abs(computed - claimed) <= abs_tol
            err_detail = f"abs err={abs(computed - claimed):.6g}, tol={abs_tol:.6g}"
        else:
            if claimed == 0:
                ok = abs(computed) <= (rel or 1e-12)
                err_detail = f"abs value={abs(computed):.6g}, tol={rel:.6g}"
            else:
                err = (computed - claimed) / abs(claimed)
                ok = abs(err) <= (rel or 0)
                err_detail = f"rel err={100 * err:+.6g}%, tol={100 * (rel or 0):.6g}%"
        self._mark(ok, label + (f" -- {detail}" if detail else ""))
        print(f"        computed: {computed}   claimed: {claimed}   ({err_detail})")
        return ok

    def record(self, label, ok, computed="", claimed="", detail=""):
        ok = bool(ok)
        self._mark(ok, label + (f" -- {detail}" if detail else ""))
        if computed != "" or claimed != "":
            print(f"        computed: {computed}   claimed: {claimed}")
        return ok

    def summary(self):
        print(f"\n{'='*60}\nRESULT: {self.PASS} PASS / {self.FAIL} FAIL")
        return 0 if self.FAIL == 0 else 1


v = Verifier("P109 -- Weinberg NNNLO 600-cell")

ROOT = Path(__file__).resolve().parents[1]
TEX = (ROOT / "109_Addendum_WeinbergNNNLO.tex").read_text()

PI = math.pi
PHI = (1.0 + math.sqrt(5.0)) / 2.0
LAM = math.sin(PI / 14.0)
BASE = 1.0 / (1.0 + PI)
TARGET = 3.0 / (8.0 * PHI)
C4 = -74.0 / 25.0
C6 = -24.0 / 5.0


def gap_pct(value: float) -> float:
    return 100.0 * (value - TARGET) / TARGET


lo = BASE
nlo = BASE * (1.0 - 4.0 * LAM**2 / 5.0)
nnlo = BASE * (1.0 - 4.0 * LAM**2 / 5.0 + C4 * LAM**4)
nlo_plus_c6 = BASE * (1.0 - 4.0 * LAM**2 / 5.0 + C6 * LAM**6)
full_through_c6 = BASE * (1.0 - 4.0 * LAM**2 / 5.0 + C4 * LAM**4 + C6 * LAM**6)
delta_c6 = C6 * LAM**6 / (1.0 + PI)

v.check("lambda", LAM, 0.22252, rel=5e-5)
v.check("lambda^2", LAM**2, 0.04952, rel=9e-5)
v.check("lambda^4", LAM**4, 2.452e-3, rel=9e-5)
v.check("lambda^6", LAM**6, 1.214e-4, rel=2e-4)
v.check("lambda^8", LAM**8, 6.01e-6, rel=3e-4)

v.check("golden target 3/(8phi)", TARGET, 0.23176, rel=2e-5)
v.check("LO sin^2 theta_W", lo, 0.24145, rel=2e-5)
v.check("LO gap percent", gap_pct(lo), 4.22, rel=1e-2)
v.check("NLO sin^2 theta_W", nlo, 0.23189, rel=1e-5)
v.check("NLO gap percent", gap_pct(nlo), 0.0542, rel=8e-4)
v.check("NNLO sin^2 theta_W", nnlo, 0.23014, rel=2e-5)
v.check("NNLO gap percent", gap_pct(nnlo), -0.70, rel=4e-3)

v.check("600-cell cells per vertex", 600.0 / 120.0, 5.0, rel=1e-12)
v.check("600-cell edges per vertex", 720.0 / 120.0, 6.0, rel=1e-12)
v.check("G2 Weyl half-order", 12.0 / 2.0, 6.0, rel=1e-12)
v.check("600-cell edge length 1/phi", 1.0 / PHI, 0.6180, rel=6e-5)
v.check("c6 = -hvee*(E/V)/N_Fano", -(4.0 * 6.0) / 5.0, C6, rel=1e-12)
v.check("NNNLO c6 shift", delta_c6, -1.408e-4, rel=8e-4)
v.check("NLO plus c6 value", nlo_plus_c6, 0.23175, rel=2e-5)
v.check("NLO plus c6 gap percent", gap_pct(nlo_plus_c6), -0.0065, rel=6e-3)
v.check("NLO plus c6 improvement factor", abs((nlo - TARGET) / (nlo_plus_c6 - TARGET)), 8.3, rel=2e-2)

required_c6_exact = -(nlo - TARGET) * (1.0 + PI) / LAM**6
v.check(
    "required c6 from exact NLO gap",
    required_c6_exact,
    -4.43,
    rel=5e-3,
    detail="Expected fail: -4.43 follows from rounded delta=0.00013; exact formulas give about -4.29.",
)
v.check(
    "c6 discrepancy using exact required c6",
    100.0 * (C6 - required_c6_exact) / abs(required_c6_exact),
    -8.4,
    rel=2e-2,
    detail="Expected fail: exact values give about -11.9%; -8.4% uses the rounded -4.43 required coefficient.",
)
v.check(
    "full expansion through c6 value",
    full_through_c6,
    0.23175,
    rel=2e-5,
    detail="Expected fail: including the NNLO c4 term as the expansion formula says gives about 0.229995, not the advertised NLO+c6 near-hit.",
)
v.check(
    "full expansion through c6 gap percent",
    gap_pct(full_through_c6),
    -0.0065,
    rel=6e-3,
    detail="Expected fail: the full c2+c4+c6 path has about -0.76% gap.",
)

c8_exact = -(nlo_plus_c6 - TARGET) * (1.0 + PI) / LAM**8
v.check(
    "c8 needed from exact NLO+c6 residual",
    c8_exact,
    9.6,
    rel=3e-2,
    detail="Expected fail: using exact residual gives about 10.33; 9.6 follows from the rounded 1.4e-5 residual.",
)
v.check("face-density c8 prediction", 4.0 * (1200.0 / 120.0) / 5.0, 8.0, rel=1e-12)

v.record(
    "c6 is derived by an explicit Jordan-loop enumeration",
    False,
    computed="paper multiplies hvee(G2), E600/V600, and 1/N_Fano, but does not enumerate loop diagrams or prove this weighting rule",
    claimed="600-cell Jordan loop derives c6",
    detail="Expected proof-status fail.",
)
v.record(
    "P105-1 is closed by P109",
    "Conjecture~P105-1 remains open" not in TEX,
    computed="paper explicitly leaves all-orders closure open",
    claimed="first NNNLO step toward proving P105-1",
    detail="Expected status note: the near-hit is not an exact closure.",
)

sys.exit(v.summary())
