Files
sim-numerics/tests/test_points_direction.py
T

107 lines
4.6 KiB
Python

"""Gates P1-P5 for the two new places similarity is read (PREREG_points_and_direction_2026-09-21).
mode A points="shape" — WHICH three points the model is built on, chosen by the shape
of the configuration (argmin |phi - xi|) instead of by recency
mode B direction="dissimilar" — WHICH end is "far", read as the end whose |f| is larger
(less similar to zero) instead of the geometrically distant one
Inertness is a declared failure of the EXPERIMENT, not a pass: if a mode changes nothing, its
numbers are not evidence either way, so the counters are pinned here.
"""
from __future__ import annotations
import inspect
import math
import re
import pytest
from simroot import pure as P
SMOOTH = [
(lambda t: t ** 3 - 2.0 * t - 5.0, 2.0, 3.0),
(lambda t: math.exp(t) - 5.0, 0.0, 3.0),
(lambda t: t ** 2 - 2.0, 0.5, 2.0),
(lambda t: math.cos(t) - t, 0.0, 1.0),
(lambda t: t ** 3 - t + 0.2, -2.0, 2.0),
]
def test_P1_defaults_are_bit_identical_to_the_published_path():
for f, a, b in SMOOTH:
for guard in ("credit", "project", "safe", "step"):
base = P.pure_root(f, a, b, 1e-12, 300, similarity="ratio",
scale="derived3", guard=guard)
same = P.pure_root(f, a, b, 1e-12, 300, similarity="ratio", scale="derived3",
guard=guard, points="recent", direction="distance")
assert base == same, (guard, base, same)
def test_P2_neither_rule_carries_a_constant():
src = inspect.getsource(P._pick_triple) + inspect.getsource(P._shape_defect)
code = "\n".join(line.split("#", 1)[0] for line in src.splitlines())
literals = set(re.findall(r"(?<![\w.])\d+\.\d+(?![\w.])", code))
assert literals == set(), f"constants in the triple rule: {literals}"
body = inspect.getsource(P.pure_root)
start = body.index('if direction == "dissimilar":')
end = body.index('if scale in ("derived", "derived_rho")', start)
dcode = "\n".join(line.split("#", 1)[0] for line in body[start:end].splitlines())
assert set(re.findall(r"(?<![\w.])\d+\.\d+(?![\w.])", dcode)) == set()
def test_P3_the_counters_report_whether_a_mode_is_inert():
changed = 0
for f, a, b in SMOOTH:
st = {}
_x, _n, ok = P.pure_root(f, a, b, 1e-12, 300, similarity="ratio", scale="derived3",
guard="credit", points="shape", stats=st)
assert ok and "triple_changed" in st
changed += st["triple_changed"]
assert changed >= 1, "mode A never changed the triple on any probe problem — inert"
dchanged = 0
for f, a, b in SMOOTH:
st = {}
_x, _n, ok = P.pure_root(f, a, b, 1e-12, 300, similarity="ratio", scale="derived3",
guard="credit", direction="dissimilar", stats=st)
assert ok and "dir_changed" in st
dchanged += st["dir_changed"]
assert dchanged >= 1, "mode B never changed the far end — inert"
def test_P4_degenerate_triples_are_dropped_not_divided_by():
assert P._shape_defect(1.0, 1.0, 2.0, 5.0, 2.0, 7.0) is None # equal abscissae
assert P._shape_defect(1.0, 1.0, 2.0, 5.0, 3.0, 5.0) is None # equal values
d = P._shape_defect(1.0, 1.0, 0.0, 0.0, 2.0, 2.0) # exactly linear
assert d is not None and d == pytest.approx(0.0)
assert P._pick_triple(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0) is None
def test_P5_no_mode_adds_an_evaluation():
for f, a, b in SMOOTH:
st = {}
_x, n, ok = P.pure_root(f, a, b, 1e-12, 300, similarity="ratio", scale="derived3",
guard="credit", points="shape", direction="dissimilar",
stats=st)
assert ok
assert st["triple_changed"] <= n - 2 and st["dir_changed"] <= n - 2, (st, n)
def test_modes_are_validated():
with pytest.raises(ValueError):
P.pure_root(lambda t: t, -1.0, 1.0, 1e-10, 100, points="whatever")
with pytest.raises(ValueError):
P.pure_root(lambda t: t, -1.0, 1.0, 1e-10, 100, direction="whatever")
with pytest.raises(ValueError): # a triple needs the three-point scale
P.pure_root(lambda t: t, -1.0, 1.0, 1e-10, 100, scale="derived", points="shape")
def test_both_modes_still_solve():
for f, a, b in SMOOTH:
for kw in ({"points": "shape"}, {"direction": "dissimilar"},
{"points": "shape", "direction": "dissimilar"}):
x, _n, ok = P.pure_root(f, a, b, 1e-12, 300, similarity="ratio",
scale="derived3", guard="credit", **kw)
assert ok and abs(f(x)) < 1e-6, (kw, a, b, x)