#!/usr/bin/env python3
"""
verify_P012.py -- Paper 12: five-fold convergence of c=3/4.

This verifier checks the base alpha formula, the rational c-search, the
continuous optimum, the comparison table, the moment correction, and the
spectral perturbation estimates in 12_Paper_FiveFoldConvergence.tex.

The main search result c=3/4 reproduces. The flagged issues are stale
comparison factors in the search table and proof/status overreach: several
"independent derivations" are interpretations or imported assumptions rather
than independent derivations, Z3 topology does not by itself forbid a fourth
family, and the wave-equation route inherits the earlier wave-equation
problem from Papers 2/3.
"""

from __future__ import annotations

import math
import statistics
import sys
from pathlib import Path

PASS = FAIL = 0
_N = 0


def check(n, desc, cond):
    global PASS, FAIL
    ok = bool(cond); PASS += ok; FAIL += (not ok)
    print(f"  [{'PASS' if ok else 'FAIL'}] {n:>2}. {desc}")
    return ok


class Verifier:
    """Target-style output adapter; check/record numerics are unchanged."""

    def __init__(self, name):
        print(name)

    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}%"
        return self.record(label, ok, computed, claimed,
                           err_detail + (f"; {detail}" if detail else ""))

    def record(self, label, ok, computed="", claimed="", detail=""):
        global _N
        ok = bool(ok)
        desc, extra = label, detail
        if not ok and detail:
            desc, extra = f"{label} -- {detail}", ""
        _N += 1
        check(_N, desc, ok)
        if computed != "" or claimed != "":
            print(f"       computed: {computed}")
            print(f"       claimed : {claimed}")
        if extra:
            print(f"       {extra}")
        return ok

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


v = Verifier("P012 -- Five-Fold c=3/4 Convergence")

ROOT = Path(__file__).resolve().parents[2]
TEX = (ROOT / "toe" / "12_Paper_FiveFoldConvergence.tex").read_text()

PI = math.pi
ALPHA_EXP_INV = 137.035999
BASE = 5.0**4 * (1.0 / PI - 1.0 / 10.0)
MU0 = 4.0 * PI**3 + PI**2 + PI
MU1 = 16.0 * PI**3 / 5.0 + 3.0 * PI**2 / 4.0 + 2.0 * PI / 3.0
ALPHA = 1.0 / MU0
X = MU1 * ALPHA**2


def rel_error(c: float) -> float:
    value = BASE * (1.0 + c * X)
    return abs((value - ALPHA_EXP_INV) / ALPHA_EXP_INV)


def pct(value: float, target: float) -> float:
    return 100.0 * (value - target) / abs(target)


best = []
for a in range(1, 21):
    for b in range(1, 21):
        c = a / b
        best.append((rel_error(c), c, a, b))
best.sort()
best_err = best[0][0]
c_req = (ALPHA_EXP_INV / BASE - 1.0) / X

v.check("base alpha inverse", BASE, 136.443679, rel=2e-9)
v.check("rho integral mu0", MU0, 137.036303776, rel=2e-12)
v.check("mu1", MU1, 108.71668, rel=4e-8)
v.check("rho integral relative precision percent", abs(pct(MU0, ALPHA_EXP_INV)), 0.0002, rel=2e-1)
v.check("base formula percent gap", abs(pct(BASE, ALPHA_EXP_INV)), 0.43, rel=6e-3)
v.check("mu1 alpha^2", X, 0.00579, rel=2e-4)
v.check("3/4 correction term", 0.75 * X, 0.00434, rel=5e-4)
v.check("corrected alpha inverse with c=3/4", BASE * (1.0 + 0.75 * X), 137.036112, rel=3e-9)
v.check("c=3/4 relative error", rel_error(0.75), 8.4e-7, rel=2e-2)
v.check("rational scan best c", best[0][1], 0.75, rel=1e-12)
v.check("continuous optimum c", c_req, 0.749857, rel=8e-7)
v.check("distance from 3/4", abs(0.75 - c_req), 1.43e-4, rel=5e-3)

for label, c, claimed_factor, tol in [
    ("2/3", 2.0 / 3.0, 570.0, 3e-2),
    ("4/5", 4.0 / 5.0, 860.0, 3e-2),
    ("5/6", 5.0 / 6.0, 290.0, 3e-2),
    ("7/9", 7.0 / 9.0, 150.0, 5e-2),
    ("1", 1.0, 1700.0, 3e-2),
]:
    factor = rel_error(c) / best_err
    v.check(
        f"search table worse factor c={label}",
        factor,
        claimed_factor,
        rel=tol,
        detail="Expected fail for stale rows where the table factor does not follow from the displayed formula.",
    )

v.check("Interpretation I dimension ratio", 3.0 / 4.0, 0.75, rel=1e-12)
v.check("Interpretation II complement", 2.0 - 5.0 / 4.0, 0.75, rel=1e-12)
v.check("Interpretation III prime ratio", 3.0 / 2.0**2, 0.75, rel=1e-12)
v.check("Interpretation IV family ratio", 3.0 / 4.0, 0.75, rel=1e-12)
v.check("full spectral factor", 1.0 / (1.0 - X), 1.00582, rel=3e-6)
v.check("boundary spectral factor", 1.0 / (1.0 - 0.75 * X), 1.00436, rel=2e-6)
v.check("first-order boundary factor", 1.0 + 0.75 * X, 1.00434, rel=2e-6)
v.check(
    "first-order vs nonperturbative boundary difference percent",
    100.0 * ((1.0 / (1.0 - 0.75 * X)) - (1.0 + 0.75 * X)) / (1.0 / (1.0 - 0.75 * X)),
    0.02,
    rel=5e-2,
    detail="Expected fail: the relative difference is about 0.0019%, not 0.02%.",
)
v.check("second-order term", (0.75**2) * X**2, 1.9e-5, rel=1e-2)

vals = [0.75, 0.75, 0.75, 0.75, c_req]
v.check("sample standard deviation across five methods", statistics.stdev(vals), 0.000064, rel=2e-2)
v.check("random-chance estimate (1/400)^4", (1.0 / 400.0) ** 4, 1e-10, rel=7e-1)

v.record(
    "wave-equation derivation is independent and established",
    False,
    computed="the route depends on the earlier nonlinear wave equation and kappa exponent, which previous verifiers flagged as not deriving rho_cubic as a valid equilibrium",
    claimed="Method II independently derives c=3/4",
    detail="Expected proof-status fail.",
)
v.record(
    "Z3 family topology forbids additional representation copies",
    False,
    computed="Z3 gives three irreducible characters/charges, but does not by itself prove no additional copied families or a topological no-fourth-family theorem",
    claimed="fourth family topologically forbidden",
    detail="Expected proof-status fail.",
)
v.record(
    "five derivations are logically independent derivations rather than post-hoc interpretations",
    False,
    computed="Methods I/III/IV are different readings of the same 3-vs-4 ratio, Method V is the fitted search, and Method II imports the kappa exponent",
    claimed="logical independence of five derivations",
    detail="Expected proof-status fail: the arithmetic convergence is real, but independence is not established by the proof sketch.",
)

sys.exit(v.summary())
