#!/usr/bin/env python3
"""
verify_P003.py -- Paper 03: Mathematical Foundations.

This verifier checks the numerical and algebraic claims in
toe/03_Paper_MathematicalFoundations.tex. Paper 3 repeats much of Paper 2's
cubic-density framework, but adds some explicit proof statements.

The main reproducible values are m0, m1, E_self, kappa=alpha^(5/4), and the
final geometric-series mass-log approximation. The audit flags the theorem
that still states E_norm=1 despite the proof computing 13.177, the wave
equation/Neumann equilibrium problem, an overbroad moment-ratio theorem, an
alpha-source mismatch in beta_QED, and an algebraic replacement of (1+x) by
1/(1-x) in the mass-log derivation.
"""

import math
import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parent))
from verify_common import Verifier as _BaseVerifier, CheckResult


class Verifier(_BaseVerifier):
    """Output-layer normalization only: same checks, modern [PASS]/[FAIL] format."""

    def __init__(self, name: str):
        self.name = name
        self.results = []
        print(name)

    def record(self, label, ok, computed="", claimed="", detail=""):
        self.results.append(CheckResult(label, ok, computed, claimed, detail))
        n = len(self.results)
        note, info = "", detail
        if not ok and "Expected" in detail:
            i = detail.find("Expected")
            note = " -- " + detail[i:]
            info = detail[:i].rstrip().rstrip(";")
        print(f"  [{'PASS' if ok else 'FAIL'}] {n:>2}. {label}{note}")
        if computed != "" or claimed != "":
            print(f"        computed: {computed}")
            print(f"        claimed : {claimed}")
        if info:
            print(f"        {info}")
        return ok

    def summary(self):
        passed = sum(r.ok for r in self.results)
        failed = len(self.results) - passed
        print(f"\n{'='*60}\nRESULT: {passed} PASS / {failed} FAIL")
        return 1 if failed else 0


v = Verifier("P003 -- Mathematical Foundations")

PI = math.pi
A3 = 16 * PI**3
A2 = 3 * PI**2
A1 = 2 * PI

MU0 = 4 * PI**3 + PI**2 + PI
MU1 = A3 / 5 + A2 / 4 + A1 / 3
ALPHA = 1 / MU0
ALPHA_EXP = 1 / 137.035999084


def mu(n: int) -> float:
    return A3 / (n + 4) + A2 / (n + 3) + A1 / (n + 2)


def rho_prime(x: float) -> float:
    return 48 * PI**3 * x**2 + 6 * PI**2 * x + 2 * PI


def rho_second(x: float) -> float:
    return 96 * PI**3 * x + 6 * PI**2


energy = 0.5 * (
    (48 * PI**3) ** 2 / 5
    + (6 * PI**2) ** 2 / 3
    + (2 * PI) ** 2
    + 2 * (48 * PI**3) * (6 * PI**2) / 4
    + 2 * (48 * PI**3) * (2 * PI) / 3
    + 2 * (6 * PI**2) * (2 * PI) / 2
)
e_self = energy / MU0**2
delta_e = e_self - 4 * PI
kappa = ALPHA ** (5 / 4)

v.check("mu0 = 4*pi^3 + pi^2 + pi", MU0, 137.036303776, rel=1e-12)
v.check("mu1", MU1, 108.716684, rel=3e-9)
v.check("beta_geom = mu1/mu0", MU1 / MU0, 0.793342208, rel=5e-10)
v.check("Dirichlet energy E[rho]", energy, 247444.809832, rel=2e-12)
v.check("m0^2", MU0**2, 18778.952536, abs_tol=0.005)
v.check("E_self = E/m0^2", e_self, 13.176712972, rel=5e-8)
v.check(
    "Theorem 3.1 E_norm[rho] = 1",
    e_self,
    1.0,
    rel=1e-10,
    detail="Expected fail: the proof itself computes E_self ~= 13.177 and says it is not 1.",
)
v.check("Delta E = E_self - 4*pi", delta_e, 0.610342358, rel=5e-7)
v.check("23*kappa*4*pi gap approximation", 23 * kappa * 4 * PI, delta_e, rel=1.1e-2)
v.check("gap-to-amplitude safety factor", delta_e / (0.002 * e_self), 23.0, rel=2e-2)
v.check("E_min(t) for A=kappa approx 0.002", e_self * (1 - 0.002), 13.151, rel=2e-4)
v.check("E_max(t) for A=kappa approx 0.002", e_self * (1 + 0.002), 13.203, rel=2e-4)

v.check("kappa = alpha^(5/4)", kappa, 0.002132826, rel=1e-7)
v.check("kappa_obs vs alpha^(5/4) relative error", abs(0.0022 - kappa) / 0.0022, 0.0305, rel=2e-2)
n_opt = math.log(0.0022) / math.log(ALPHA)
v.check("n_opt from ln(kappa_obs)/ln(alpha)", n_opt, 1.243698, rel=5e-6)
v.check("5/4 exponent relative distance from n_opt percent", 100 * abs(1.25 - n_opt) / n_opt, 0.51, rel=2e-2)
v.record(
    "5/4 minimizes alpha^n over all exponents",
    False,
    computed=f"real optimum n={n_opt:.6f}",
    claimed="n=5/4 minimizes among power laws",
    detail="Expected fail: 5/4 is a good simple fraction, not the unconstrained minimizer.",
)
v.check("characteristic action 1/alpha^(5/2)", ALPHA ** (-5 / 2), 2.2e5, rel=1e-2)

v.check(
    "rho_cubic satisfies Neumann boundary at x=0",
    rho_prime(0.0),
    0.0,
    abs_tol=1e-12,
    detail="Expected fail: rho'(0)=2*pi.",
)
v.check(
    "rho_cubic satisfies Neumann boundary at x=1",
    rho_prime(1.0),
    0.0,
    abs_tol=1e-12,
    detail="Expected fail: rho'(1) is nonzero.",
)
v.check(
    "rho_cubic is static equilibrium of stated wave equation at x=1/2",
    rho_second(0.5),
    0.0,
    abs_tol=1e-12,
    detail="Expected fail: the written equation leaves rho_cubic'' at zeroth order.",
)
v.record(
    "linearization drops the eta*rho_cubic'' term correctly",
    False,
    computed="eta_tt = eta_xx - kappa*eta*rho_cubic'' plus residual terms",
    claimed="eta_tt = (1-kappa) eta_xx",
    detail="Expected fail: the displayed first-order equation does not imply the next line.",
)
v.check("fundamental frequency omega_1", PI * math.sqrt(1 - kappa), 3.136, rel=1e-3)
v.check("log-energy period 2*pi/omega_1", 2 * PI / (PI * math.sqrt(1 - kappa)), 2.0, rel=2e-3)

v.check("mu2", mu(2), 90.175963, rel=5e-9)
v.check("mu3", mu(3), 77.062931, rel=5e-6)
v.check("mu1/mu0", mu(1) / mu(0), 0.7933, rel=1e-4)
v.check("mu2/mu1", mu(2) / mu(1), 0.8295, rel=1e-4)
v.check("mu3/mu2", mu(3) / mu(2), 0.8546, rel=1e-4)
v.check(
    "moment-ratio theorem lower bound at n=0",
    mu(1) / mu(0),
    0.83,
    abs_tol=0.03,
    detail="Expected fail: the theorem says ratios are about 0.83-0.86 for n=0,1,2,... but n=0 is 0.7933.",
)
v.check(
    "moment-ratio theorem upper bound at n=3",
    mu(4) / mu(3),
    0.86,
    abs_tol=0.0,
    detail="Expected fail: ratios soon exceed 0.86 and tend to 1.",
)

beta_geom = MU1 / MU0
beta_qed_geom = 2 * ALPHA**2 / (3 * PI)
beta_qed_exp = 2 * ALPHA_EXP**2 / (3 * PI)
ratio_geom_alpha = beta_geom / beta_qed_geom
ratio_exp_alpha = beta_geom / beta_qed_exp
log_ratio = math.log(1.221e19 / (5.110e-4))
c_emp = ratio_exp_alpha / log_ratio
c_formula = 10 * MU0**3 / (MU0**2 + MU1)

v.check(
    "beta_QED from displayed 2/(3*pi*mu0^2)",
    beta_qed_geom,
    1.130029e-5,
    rel=1e-6,
    detail="Expected fail: 1.130029e-5 is the experimental-alpha value, not the geometric-mu0 formula.",
)
v.check(
    "beta ratio from displayed geometric beta_QED",
    ratio_geom_alpha,
    70205.483,
    rel=1e-6,
    detail="Expected fail: the quoted ratio again uses experimental alpha.",
)
v.check("beta ratio using experimental alpha", ratio_exp_alpha, 70205.483, rel=1e-6)
v.check("mass hierarchy log using rounded P3 masses", log_ratio, 51.527840, rel=2e-6)
v.check("C extracted from rounded P3 masses", c_emp, 1362.477, rel=5e-5)
v.check("C_formula exact", c_formula, 1362.475, rel=5e-7)
v.check(
    "C/C_formula table value",
    c_emp / c_formula,
    1.000015,
    rel=2e-6,
    detail="Expected fail: the ratio is about 1.000001 with the stated formulas.",
)
v.check(
    "C relative error percent",
    100 * abs(c_emp - c_formula) / c_emp,
    0.015,
    rel=1e-2,
    detail="Expected fail: the percent error is about 0.0001%, not 0.015%.",
)

x = MU1 * ALPHA**2
mass_log_from_c = (3 * PI * MU1 / 20) * (1 + x)
mass_log_geometric_series = (3 * PI * MU1 / 20) / (1 - x)
v.check("mass-log formula from substituting C gives (1+x)", mass_log_from_c, 51.528124, rel=5e-8)
v.check(
    "algebraic step (1+x) = 1/(1-x)",
    1 + x,
    1 / (1 - x),
    rel=1e-12,
    detail="Expected fail: this is only an approximation; it changes the mass-log by about 0.00335%.",
)
v.check("geometric-series mass-log RHS", mass_log_geometric_series, 51.529851, rel=5e-8)
v.check("geometric-series relative error percent", 100 * abs(mass_log_geometric_series - log_ratio) / log_ratio, 0.0039, rel=5e-2)

sys.exit(v.summary())
