Files
sim-numerics/tests/test_phase_detector.py

145 lines
5.8 KiB
Python

"""Pins the phase detector as REFUTED.
The rho correction was derived, implemented and measured; it failed on all
three criteria set before it was run. These tests exist so nobody adopts it
later on the strength of the derivation alone, and so that if someone repairs
it the tests fail loudly and the claim gets re-examined.
"""
from __future__ import annotations
import math
import os
import sys
import pytest
from scipy.optimize._tstutils import _CHANDRUPATLA_TESTS_DICTS
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from simroot.pure import pure_root
from stage5_three_point import PROBLEMS, order_of
XTOL = 1e-12
MAXFEV = 200
ACC = 1e-6
def total(scale, sim="ratio"):
t = 0
for _n, f, a, b, root in PROBLEMS:
x, n, conv = pure_root(f, a, b, XTOL, MAXFEV, similarity=sim,
scale=scale, guard="project")
t += n if (conv and abs(x - root) <= 1e-8) else MAXFEV
return t
def med_order(scale, sim="ratio"):
ps = [order_of(lambda f_, a_, b_, xt, mx: pure_root(
f_, a_, b_, XTOL, MAXFEV, similarity=sim, scale=scale, guard="project"),
f, a, b, root) for _n, f, a, b, root in PROBLEMS]
ps = [p for p in ps if math.isfinite(p) and 0.5 < p < 5.0]
return sorted(ps)[len(ps) // 2] if ps else float("nan")
def test_rho_makes_the_standard_problems_worse():
plain, rho = total("derived3"), total("derived3_rho")
assert rho > plain * 1.4, (plain, rho)
def test_rho_destroys_the_order_it_was_meant_to_preserve():
"""The correction was supposed to vanish near the root. It does not."""
assert med_order("derived3") > 1.7
assert med_order("derived3_rho") < 1.3
def test_rho_does_not_capture_the_family_it_was_built_for():
"""fun3/fun4/fun5 are where cbrt beats us 2.6x. The detector was built to
recover that and recovers essentially none of it."""
fam = [d for d in _CHANDRUPATLA_TESTS_DICTS
if d["ID"].startswith(("fun3.", "fun4.", "fun5."))]
def t(sim, scale):
s = 0
for d in fam:
a, b = float(d["bracket"][0]), float(d["bracket"][1])
x, n, conv = pure_root(d["f"], a, b, XTOL, MAXFEV,
similarity=sim, scale=scale, guard="project")
s += n if (conv and abs(x - float(d["root"])) <= ACC) else MAXFEV
return s
plain, rho, cb = t("ratio", "derived3"), t("ratio", "derived3_rho"), t("cbrt", "derived3")
assert cb < 0.6 * plain, (cb, plain) # the regime is real
assert rho > 0.9 * plain, (rho, plain) # the detector does not reach it
def test_the_refuted_scales_are_still_reachable_and_still_converge():
"""Refuted is not broken: the experiment must stay reproducible."""
for scale in ("derived_rho", "derived3_rho"):
x, n, conv = pure_root(lambda t: t * t - 2.0, 0.0, 2.0, XTOL, MAXFEV,
scale=scale, guard="project")
assert conv and abs(x - math.sqrt(2.0)) <= 1e-8
def test_the_proposed_configuration_uses_neither_refuted_variant():
"""Guards against a refuted variant quietly becoming the default."""
from report_sweep import PROPOSED
assert "_rho" not in PROPOSED
assert "_m" not in PROPOSED
# --------------------------------------------------------------------------
# the m correction: derivation sound, estimator not
# --------------------------------------------------------------------------
def test_m_preserves_the_order_and_the_small_set_which_is_why_it_deceives():
"""Unlike rho, the m correction passes both of the tests a hand-picked
set can show. Pinned precisely because that is what makes it dangerous."""
assert med_order("derived3_m") > 1.7
assert total("derived3_m") <= total("derived3")
def test_m_loses_on_the_full_benchmark():
"""And fails the only test that matters. If this ever flips, the
estimator has been improved and the refutation must be revisited."""
import json
if not os.path.exists(os.path.join(
os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
"sweep_full.json")):
pytest.skip("sweep not present")
from scipy.optimize._tstutils import _APS_TESTS_DICTS
plain = m = 0
for d in _APS_TESTS_DICTS:
a, b = float(d["bracket"][0]), float(d["bracket"][1])
args = d.get("args", ())
f = (lambda ff, aa: lambda t: ff(t, *aa))(d["f"], args)
root = float(d["root"])
for scale, acc in (("derived3", "p"), ("derived3_m", "m")):
try:
x, n, conv = pure_root(f, a, b, XTOL, MAXFEV,
similarity="ratio", scale=scale,
guard="project")
except Exception:
x, n, conv = float("nan"), MAXFEV, False
good = conv and math.isfinite(x) and abs(x - root) <= ACC
if acc == "p":
plain += n if good else MAXFEV
else:
m += n if good else MAXFEV
assert m > plain, (m, plain)
def test_the_local_order_estimator_declines_when_the_model_does_not_apply():
"""theta outside (0,1) means the power-law picture does not describe the
data; the estimator must return 1 rather than clamp a value into range."""
from simroot.pure import _local_order
# a straight line: f'' = 0, theta = 0, m must be exactly 1
lin = lambda t: 3.0 * t - 6.0
assert _local_order(3.0, lin(3.0), 2.0, lin(2.0), 1.0, lin(1.0)) == 1.0
# missing third point
assert _local_order(1.0, 1.0, 0.5, 0.5, None, None) == 1.0
# repeated nodes
assert _local_order(1.0, 1.0, 1.0, 1.0, 1.0, 1.0) == 1.0
# a double root at 0: f = t^2 has theta = 1/2, so m = 2
sq = lambda t: t * t
m = _local_order(1e-3, sq(1e-3), 2e-3, sq(2e-3), 3e-3, sq(3e-3))
assert abs(m - 2.0) < 1e-6, m