58 lines
2.0 KiB
Python
58 lines
2.0 KiB
Python
"""Stage 0e - how much is the parameter-free safeguard costing?
|
|
|
|
derived.ratio is, algebraically, the Newton/secant step:
|
|
|
|
S = 1 - |z|, z = |f| / (|f'_secant| * (far - x))
|
|
step = (1 - S)*(far - x) = |f| / |f'_secant|
|
|
|
|
so it should be superlinear (order ~1.618) and land near Brent. It measured
|
|
150 evaluations over the eight problems against Brent's 82. The gap has to
|
|
come from somewhere, and the only extra machinery it carries is the
|
|
safeguard: a secant step often shrinks the ERROR fast while barely moving the
|
|
proven BRACKET, so the "did the bracket halve" test fires and buys a bisection
|
|
step that the search did not need.
|
|
|
|
This measures the price directly: the same method with the safeguard on and
|
|
off, side by side.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import math
|
|
|
|
from simroot.baselines import bisection, brent
|
|
from stage0d_derived_similarity import FAST_SIMS, PROBLEMS, derived_step
|
|
|
|
XTOL = 1e-12
|
|
MAXFEV = 200
|
|
|
|
|
|
def main():
|
|
methods = [("bisection", lambda f, a, b: bisection(f, a, b, XTOL, MAXFEV)),
|
|
("brent [reference]", lambda f, a, b: brent(f, a, b, XTOL, MAXFEV))]
|
|
for s in FAST_SIMS:
|
|
for gu in (True, False):
|
|
methods.append((
|
|
f"derived.{s}" + (".guard" if gu else ".raw"),
|
|
(lambda ss, g: lambda f, a, b: derived_step(
|
|
f, a, b, XTOL, MAXFEV, sim=ss, guard=g))(s, gu)))
|
|
|
|
width = max(len(n) for n, _ in methods) + 1
|
|
header = (f"{'method':{width}s}" +
|
|
"".join(f"{p[0][:13]:>15s}" for p in PROBLEMS) +
|
|
f"{'TOTAL':>8s}{'FAIL':>6s}")
|
|
print(header)
|
|
print("-" * len(header))
|
|
for name, fn in methods:
|
|
cells, total, fails = [], 0, 0
|
|
for _, f, a, b, root in PROBLEMS:
|
|
x, n, conv = fn(f, a, b)
|
|
ok = conv and abs(x - root) <= 1e-8
|
|
cells.append(f"{n:>15d}" if ok else f"{'FAIL(' + str(n) + ')':>15s}")
|
|
total += n
|
|
fails += 0 if ok else 1
|
|
print(f"{name:{width}s}" + "".join(cells) + f"{total:>8d}{fails:>6d}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|