(2) The proposed method is again the scheduled projection (2806/3220/6026), its budget multiplier DECLARED as the one free constant: the canonical total is the same for every multiplier 1.25-4, the wide-bracket one is not. The earned projection is the constant-free variant (3568/3020/6588). What the old tables hid: problem by problem the proposed rule beats Chandrupatla on the canonical set 87/24/42, exact sign test p = 9e-5, while trailing him by 0.7% in total; on the wide-bracket set he is genuinely stronger (26 to 9, p = 0.006). Gap decomposition recomputed with the library: 244 (was 262), 160 of it on the flat families (two thirds), fun1 58 (a quarter, not a third as the abstract said). Also corrected on the way: the 'subsumed by Chandrupatla' pin claimed he is better on the worst single problem - true only with the looser tolerance (84 against the credit rule's 83 once fixed); §8.3 still called zero slack degenerate, which Table 1a refutes; §5.2's Brent figure is our pure-Python implementation and now says so. verify_article.py 286/286, 802 tests pass twice. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
72 lines
3.0 KiB
Python
72 lines
3.0 KiB
Python
"""On wide brackets we spend what bisection spends. WHO caps us — the step rule or the guard?
|
|
|
|
Measured (diag_fun1_endgame.py): on the same function our cost grows with the bracket width
|
|
(7, 12, 19, 59, 63 against Chandrupatla's 8, 12, 15, 24, 44) while our observed ORDER is
|
|
higher than theirs, so the endgame is not the problem. 59 evaluations on a 2e4-wide bracket
|
|
is what bisection needs (log2(2e16) ~ 54), i.e. we degrade to one halving per evaluation.
|
|
|
|
Two candidate causes, and they are distinguishable by a run:
|
|
* the STEP RULE cannot march (the similarity step is an absolute length), or
|
|
* the GUARANTEE's projection clamps the accepted step to a halving-sized move.
|
|
|
|
So the same runs are repeated with each guard, including guard="none" (no guarantee at all).
|
|
If "none" marches, the guard is the cap; if it also crawls, the step rule is.
|
|
|
|
python -u diag_who_caps_us.py
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import math
|
|
|
|
from scipy.optimize._tstutils import _CHANDRUPATLA_TESTS_DICTS
|
|
|
|
from simroot.baselines import CHANDRUPATLA_BASELINE
|
|
from simroot.baselines import bisection, chandrupatla, chandrupatla_scipy
|
|
from simroot.pure import pure_root
|
|
from sweep_full import ACC, MAXFEV, XTOL
|
|
|
|
GUARDS = ("none", "step", "project", "safe", "credit")
|
|
|
|
|
|
def main():
|
|
print(f"{'problem':<9} {'width':>10} {'bisect':>7} {'CH':>5} " +
|
|
" ".join(f"{g:>8}" for g in GUARDS))
|
|
for d in _CHANDRUPATLA_TESTS_DICTS:
|
|
pid = str(d["ID"])
|
|
if not (pid.startswith("fun1.") or pid in ("fun3.1", "fun5.1", "fun4.3")):
|
|
continue
|
|
f = d["f"]
|
|
a, b = (float(v) for v in d["bracket"])
|
|
root = float(d["root"])
|
|
ok = lambda x, c: bool(c and math.isfinite(float(x)) # noqa: E731
|
|
and (abs(float(x) - root) <= ACC or f(float(x)) == 0.0))
|
|
_xb, nb, cb = bisection(f, a, b, XTOL, MAXFEV)
|
|
best = None
|
|
for impl in (CHANDRUPATLA_BASELINE,): # the library alone (2026-09-21)
|
|
try:
|
|
xc, nc, cc = impl(f, a, b, XTOL, MAXFEV)
|
|
except Exception:
|
|
continue
|
|
if ok(xc, cc) and (best is None or nc < best):
|
|
best = int(nc)
|
|
cells = []
|
|
for g in GUARDS:
|
|
try:
|
|
x, n, c = pure_root(f, a, b, XTOL, MAXFEV, similarity="ratio",
|
|
scale="derived3", guard=g, prestep="slope",
|
|
direction="dissimilar")
|
|
cells.append(f"{n:8d}" if ok(x, c) else f"{n:7d}✗")
|
|
except Exception:
|
|
cells.append(f"{'err':>8}")
|
|
print(f"{pid:<9} {abs(b - a):10.3g} {nb:7d} {best if best else 0:5d} " +
|
|
" ".join(cells))
|
|
|
|
print("\nlegend: ✗ = the run did not reach the root (an unguarded method may not)")
|
|
print("if guard='none' marches where 'safe'/'project' crawl, the GUARANTEE is the cap;")
|
|
print("if 'none' crawls too, the STEP RULE is the cap.")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|