baseline: the published sim-numerics artifact as it stands (490 tests, verify_article.py checks all 72 paper numbers against sweep_full.json)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
"""Stage 6 - the projection safeguard: guarantee AND order, or neither?
|
||||
|
||||
The paper's weak point: the configuration that tops the Alefeld-Potra-Shi
|
||||
ranking carries no worst-case bound, and the best configuration that does is
|
||||
14th, 18% behind Brent. Comparing an unguaranteed method's average against
|
||||
guaranteed ones is not a comparison a reader will accept.
|
||||
|
||||
The three earlier safeguards all REPLACE the computed step with a midpoint,
|
||||
which throws the computation away and, with the three-point scale, collapses
|
||||
the order from 1.94 to 1.00. The projection guard instead keeps as much of
|
||||
the step as the bisection budget allows:
|
||||
|
||||
r_j = 2^(n_half - j) * (xtol/2) - (b-a)/2
|
||||
x = x_sim if |x_sim - x_mid| <= r_j
|
||||
= x_mid + sign(d) * r_j otherwise
|
||||
|
||||
Because the bracket after a step is at most (b-a)/2 + r_j = 2^(n_half-j)*eps,
|
||||
induction bounds the run by n_half steps: the worst case is EXACTLY bisection.
|
||||
No constant is introduced - ITP's kappa1, kappa2 and n0 all belong to its
|
||||
truncation stage, which repairs regula falsi and which the similarity step
|
||||
does not need.
|
||||
|
||||
What must be true for this to be worth putting in the paper:
|
||||
(1) zero runs exceed the bisection bound, on all 199 problems;
|
||||
(2) the order stays near 1.94, not 1.00;
|
||||
(3) the total is close to the unguarded configuration's.
|
||||
Each is checked below. This is the SMOKE run.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import math
|
||||
|
||||
from simroot.baselines import bisection, brent, itp, toms748
|
||||
from simroot.pure import GUARDS, pure_root
|
||||
from stage5_three_point import PROBLEMS, order_of
|
||||
|
||||
XTOL = 1e-12
|
||||
MAXFEV = 200
|
||||
|
||||
|
||||
def main():
|
||||
methods = [
|
||||
("bisection", lambda f, a, b: bisection(f, a, b, XTOL, MAXFEV)),
|
||||
("brent", lambda f, a, b: brent(f, a, b, XTOL, MAXFEV)),
|
||||
("toms748", lambda f, a, b: toms748(f, a, b, XTOL, MAXFEV)),
|
||||
("itp (3 constants)", lambda f, a, b: itp(f, a, b, XTOL, MAXFEV)),
|
||||
]
|
||||
for gu in GUARDS:
|
||||
methods.append((f"OURS 3pt .{gu}",
|
||||
(lambda g: lambda f, a, b: pure_root(
|
||||
f, a, b, XTOL, MAXFEV, scale="derived3",
|
||||
guard=g))(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}{'>bisect bound':>15s}")
|
||||
print(header)
|
||||
print("-" * len(header))
|
||||
for name, fn in methods:
|
||||
cells, total, fails, over = [], 0, 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
|
||||
# the bisection bound itself, not twice it: 2 endpoint evaluations
|
||||
# plus ceil(log2(w/xtol)) steps
|
||||
if ok and n > math.ceil(math.log2(abs(b - a) / XTOL)) + 2:
|
||||
over += 1
|
||||
print(f"{name:{width}s}" + "".join(cells) +
|
||||
f"{total:>8d}{fails:>6d}{over:>15d}")
|
||||
|
||||
print("\nobserved order (median over the eight problems)")
|
||||
print(f"{'method':22s}{'order':>9s}")
|
||||
print("-" * 33)
|
||||
for gu in GUARDS:
|
||||
ps = [order_of((lambda g: lambda f_, a_, b_, xt, mx: pure_root(
|
||||
f_, a_, b_, XTOL, MAXFEV, scale="derived3", guard=g))(gu),
|
||||
f, a, b, root) for _, f, a, b, root in PROBLEMS]
|
||||
ps = [p for p in ps if math.isfinite(p) and 0.5 < p < 5.0]
|
||||
med = sorted(ps)[len(ps) // 2] if ps else float("nan")
|
||||
print(f"{'OURS 3pt .' + gu:22s}{med:>9.3f}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user