Files
sim-numerics/tests/test_modern_repairs.py

112 lines
4.7 KiB
Python

"""The objection that the comparison stopped at 1973, and what it settled.
Two things came out of running it, and they scope the claim exactly:
the credit projection is the best repair known for the false-position
family - better than 1971, 1972, 1973, 1995 and 2011 on evaluations,
solved count and worst case at once, and the only one that reaches the
193-of-199 ceiling;
and it is NOT better than a purpose-built acceptance test: swapped into
Chandrupatla's own interpolation it costs 7627 where his test costs 5209.
So the safeguard is a good DEFAULT for a rule that has none, not a
replacement for one that has a good one. Both halves are pinned.
"""
from __future__ import annotations
import math
import os
import sys
import pytest
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from simroot.baselines import chandrupatla
from stage18_bulletproof import falsi_driver, load_roots
from stage19_modern import chandrupatla_guard, falsi_modern, score
PROBS = load_roots()
XTOL, MAXFEV = 1e-12, 200
def falsi(repair):
return score(lambda f, a, b, xt, mx: falsi_driver(f, a, b, xt, mx, repair),
PROBS)
def modern(variant):
return score(lambda f, a, b, xt, mx: falsi_modern(f, a, b, xt, mx, variant),
PROBS)
# --------------------------------------------------------------------------
# the half that holds
# --------------------------------------------------------------------------
@pytest.mark.parametrize("name,getter", [
("illinois-1971", lambda: falsi("illinois")),
("pegasus-1972", lambda: falsi("pegasus")),
("anderson-1973", lambda: falsi("anderson")),
("ford-1995", lambda: modern("ford")),
("galdino-2011", lambda: modern("galdino")),
])
def test_credit_beats_every_published_repair_on_all_three_axes(name, getter):
c_t, c_s, c_w = falsi("credit")
t, s, w = getter()
assert c_t < t, (name, c_t, t)
assert c_s > s, (name, c_s, s)
assert c_w < w, (name, c_w, w)
def test_no_published_repair_reaches_the_ceiling():
"""193 of 199 is what bisection, Chandrupatla and TOMS 748 reach. Fifty
years of repairs of the false-position family stop at 176."""
assert falsi("credit")[1] == 193
for g in (lambda: falsi("illinois"), lambda: falsi("pegasus"),
lambda: falsi("anderson"), lambda: modern("ford"),
lambda: modern("galdino")):
assert g()[1] <= 176
# --------------------------------------------------------------------------
# the half that does not - pinned so the claim is never overstated
# --------------------------------------------------------------------------
def test_the_pluggable_chandrupatla_reproduces_the_published_one():
"""Without this the swap below compares against a different algorithm."""
a = score(lambda f, x, y, xt, mx: chandrupatla_guard(f, x, y, xt, mx,
"own"), PROBS)
b = score(lambda f, x, y, xt, mx: chandrupatla(f, x, y, xt, mx), PROBS)
assert a[:2] == b[:2], (a, b)
def test_credit_rescues_chandrupatlas_interpolation_but_loses_to_his_test():
"""The sharp test. Same interpolation, same bookkeeping, only the guard
differs. Credit turns an unguarded rule that solves 165 into one that
solves 193 - and Chandrupatla's own acceptance test does the same job for
a third fewer evaluations."""
own = score(lambda f, a, b, xt, mx: chandrupatla_guard(f, a, b, xt, mx,
"own"), PROBS)
cred = score(lambda f, a, b, xt, mx: chandrupatla_guard(f, a, b, xt, mx,
"credit"), PROBS)
none = score(lambda f, a, b, xt, mx: chandrupatla_guard(f, a, b, xt, mx,
"none"), PROBS)
assert cred[1] > none[1] and cred[0] < none[0] # it rescues
assert own[0] < cred[0] # and is beaten
assert own[1] == cred[1] == 193
def test_the_scope_sentence_the_paper_may_use():
"""A default safeguard for a rule that has none - not a replacement for a
purpose-built one. Both directions asserted together so neither can be
quoted alone."""
c_t, c_s, _cw = falsi("credit")
best_published = min(falsi(r)[0] for r in ("illinois", "pegasus",
"anderson"))
best_published = min(best_published, modern("ford")[0],
modern("galdino")[0])
assert c_t < best_published # best repair known
own = score(lambda f, a, b, xt, mx: chandrupatla_guard(f, a, b, xt, mx,
"own"), PROBS)
assert own[0] < c_t # and not the best guard