"""Pins for PREREG 2026-09-21 slot 2: the reading in the DECISION place.""" from __future__ import annotations import math import pytest from simroot.pure import (PURE_SIMS, _decide_refuse, _shape_defect, _shape_ratios, pure_root) PROBS = ( (lambda t: t ** 3 - 2.0 * t - 5.0, 1.0, 4.0), (lambda t: math.exp(t) - 2.0, 0.0, 3.0), (lambda t: (t - 1.0) ** 3, 0.0, 10.0), (lambda t: math.sin(t) - 0.5, 0.0, 1.5), ) S = PURE_SIMS["ratio"] def test_one_definition_of_the_triple(): """The step place and the decision place must not disagree about the configuration.""" args = (2.0, 8.0, 1.0, 1.0, 3.0, 27.0) xi, ph = _shape_ratios(*args) assert _shape_defect(*args) == pytest.approx(abs(ph - xi)) def test_a_linear_configuration_is_never_refused(): """For a linear f, xi == phi, so every reading must trust the model.""" f = lambda t: 3.0 * t - 6.0 # noqa: E731 args = (1.0, f(1.0), 0.0, f(0.0), 4.0, f(4.0)) for mode in ("band", "defect", "simpair"): assert _decide_refuse(mode, S, 0.5, *args) is False def test_band_is_chandrupatlas_rule_verbatim(): """Pinned against the published inequality, not against our own restatement.""" for xi, ph in ((0.5, 0.5), (0.25, 0.3), (0.9, 0.2), (0.1, 0.9)): # build a triple realising exactly these ratios: u=0, v=1, fu=0, fv=1 args = (xi, ph, 0.0, 0.0, 1.0, 1.0) want = not (1.0 - math.sqrt(1.0 - xi) < ph < math.sqrt(xi)) assert _decide_refuse("band", S, 0.5, *args) is want def test_a_degenerate_triple_allows_the_step(): """No information is not a reason to refuse; the safeguard carries the bound.""" for mode in ("band", "defect", "simpair"): assert _decide_refuse(mode, S, 0.5, 1.0, 2.0, 0.0, 5.0, 0.0, 5.0) is False assert _decide_refuse(mode, S, 0.5, 1.0, 2.0, 3.0, 5.0, 3.0, 9.0) is False def test_readings_actually_decide_somewhere(): """M5 in miniature: a reading that never fires or always fires is a relabelling.""" fired = {m: 0 for m in ("band", "defect", "simpair")} total = 0 for xi in (0.05, 0.2, 0.4, 0.6, 0.8, 0.95): for ph in (0.02, 0.15, 0.45, 0.7, 0.98): total += 1 for m in fired: fired[m] += _decide_refuse(m, S, 0.5, xi, ph, 0.0, 0.0, 1.0, 1.0) for m, k in fired.items(): assert 0 < k < total, (m, k, total) @pytest.mark.parametrize("f,a,b", PROBS) @pytest.mark.parametrize("mode", ("band", "defect", "simpair")) def test_every_reading_still_solves_with_the_guarantee(f, a, b, mode): x, n, conv = pure_root(f, a, b, 1e-10, 300, similarity="ratio", scale="derived3", guard="safe", prestep=mode) assert conv assert min(a, b) <= x <= max(a, b) bound = 2 * math.ceil(math.log2(abs(b - a) / 1e-10)) + 4 assert n <= bound @pytest.mark.parametrize("f,a,b", PROBS) def test_default_untouched_by_slot_two(f, a, b): assert (pure_root(f, a, b, 1e-12, 200, similarity="ratio", scale="derived3", guard="safe") == pure_root(f, a, b, 1e-12, 200, similarity="ratio", scale="derived3", guard="safe", prestep="none")) def test_two_point_scale_refuses_a_triple_reading(): for mode in ("band", "defect", "simpair"): with pytest.raises(ValueError): pure_root(lambda t: t, 0.0, 1.0, 1e-9, 50, scale="derived", prestep=mode)