"""The compiled library simbracket must BE the proposed method A': the same iterate and the same evaluation count as simroot.pure.pure_root, bit for bit, on every problem of the six corpora (all 91 Roots.jl problems, not only the 78), at the paper's tolerance, at a looser one, and with the budget cut so that the exhaustion path is exercised too. """ from __future__ import annotations import math import random import pytest simbracket = pytest.importorskip("simbracket") from simroot.pure import pure_root # noqa: E402 from sweep_full import APRIME # noqa: E402 def reference(f, a, b, xtol, maxfev): return pure_root(f, a, b, xtol, maxfev, similarity="ratio", scale="derived3", guard="project", prestep=APRIME, extrapolate="pattern") def problems(): from corpus_applied import build as b_app from corpus_fourth import build as b_four from corpus_new import build as b_new from corpus_roots_jl import build as b_rjl from sweep_full import load_problems out = [(f"{s}:{pid}", f, a, b) for s, pid, f, a, b, _r in load_problems()] out += [(f"NEW:{pid}", f, a, b) for _c, pid, f, a, b, _r in b_new()[0]] out += [(f"RJL:{pid}", f, a, b) for pid, f, a, b, _ins in b_rjl()[0]] out += [(f"APP:{pid}", f, a, b) for pid, f, a, b in b_app()[0]] out += [(f"D:{pid}", f, a, b) for _c, pid, f, a, b, _r in b_four()[0]] return out def run(method, f, a, b, xtol, maxfev): import scipy.optimize._tstutils as T T._f6_cache.clear() random.seed(20260921) try: x, n, ok = method(f, a, b, xtol, maxfev) return ("ok", float(x).hex() if not math.isnan(x) else "nan", int(n), bool(ok)) except Exception as e: # noqa: BLE001 - the exception TYPE is part of the behaviour return ("raise", type(e).__name__) PROBS = problems() def test_the_compiled_module_is_the_one_under_test(): import simbracket._core as core assert core.__file__.endswith((".pyd", ".so")), core.__file__ def test_the_corpora_are_all_there(): # the 855 problems of the six corpora plus the 13 Roots.jl problems that overlap the # development sets assert len(PROBS) == 855 + 13 assert len({p[0] for p in PROBS}) == len(PROBS) @pytest.mark.parametrize("xtol,maxfev", ((1e-12, 200), (1e-8, 200), (1e-12, 12))) def test_bit_identical_to_the_reference_on_every_problem(xtol, maxfev): bad = [] for pid, f, a, b in PROBS: r = run(reference, f, a, b, xtol, maxfev) c = run(simbracket.find_root, f, a, b, xtol, maxfev) if r != c: bad.append((pid, r, c)) assert not bad, f"{len(bad)} differ, first: {bad[:5]}" def test_errors_match_the_reference(): f = lambda t: t - 0.3 # noqa: E731 for args in ((f, 0.5, 1.0, 1e-12, 200), (f, 0.0, 1.0, 0.0, 200)): with pytest.raises(ValueError): reference(*args) with pytest.raises(ValueError): simbracket.find_root(*args) def test_the_bound_is_kept_and_reported(): f = lambda t: t ** 19 # noqa: E731 x, n, ok = simbracket.find_root(f, -10.0, 100.0, 1e-12, 500) assert ok and n <= simbracket.evaluation_bound(-10.0, 100.0, 1e-12) assert simbracket.evaluation_bound(-10.0, 100.0, 1e-12) == \ 2 * math.ceil(math.log2(110.0 / 1e-12)) + 3