(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>
74 lines
2.9 KiB
Python
74 lines
2.9 KiB
Python
"""WHERE the remaining gap to Chandrupatla on the wide-bracket set actually is.
|
|
|
|
Measure before proposing: our best guaranteed configuration reaches CHA 2683 against
|
|
Chandrupatla's 2423. Rather than invent a mechanism, this locates the loss per problem and
|
|
per family, and reports for each problem what the two methods spend, so the next
|
|
pre-registration can name a mechanism that addresses the measured loss.
|
|
|
|
python -u diag_cha_gap.py
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import math
|
|
from collections import defaultdict
|
|
|
|
from simroot.baselines import CHANDRUPATLA_BASELINE
|
|
from simroot.baselines import best_of, chandrupatla, chandrupatla_scipy
|
|
from simroot.pure import pure_root
|
|
from sweep_full import ACC, MAXFEV, XTOL, load_problems
|
|
|
|
CHA_BASE = CHANDRUPATLA_BASELINE # the library alone (2026-09-21)
|
|
|
|
|
|
def ours(f, a, b):
|
|
st = {}
|
|
x, n, ok = pure_root(f, a, b, XTOL, MAXFEV, similarity="ratio", scale="derived3",
|
|
guard="safe", prestep="slope", direction="dissimilar", stats=st)
|
|
return x, n, ok, st
|
|
|
|
|
|
def main():
|
|
rows = []
|
|
fam_loss = defaultdict(lambda: [0, 0, 0]) # family -> [ours, theirs, count]
|
|
tot_o = tot_c = 0
|
|
print(f"{'problem':<12} {'ours':>6} {'CH':>6} {'diff':>6} {'w0/xtol decades':>16} "
|
|
f"{'refused%':>9} {'forced%':>8} {'ok':>4}")
|
|
for s, pid, f, a, b, root in load_problems():
|
|
if s != "CHA":
|
|
continue
|
|
x_o, n_o, ok_o, st = ours(f, a, b)
|
|
x_c, n_c, ok_c = CHA_BASE(f, a, b, XTOL, MAXFEV)
|
|
ok_o = bool(ok_o and math.isfinite(x_o) and abs(x_o - root) <= ACC)
|
|
ok_c = bool(ok_c and math.isfinite(float(x_c)) and abs(float(x_c) - root) <= ACC)
|
|
c_o = n_o if ok_o else MAXFEV
|
|
c_c = n_c if ok_c else MAXFEV
|
|
tot_o += c_o
|
|
tot_c += c_c
|
|
fam = pid.split(".")[0]
|
|
fam_loss[fam][0] += c_o
|
|
fam_loss[fam][1] += c_c
|
|
fam_loss[fam][2] += 1
|
|
rows.append((c_o - c_c, pid, c_o, c_c))
|
|
print(f"{pid:<12} {c_o:6d} {c_c:6d} {c_o - c_c:+6d} "
|
|
f"{math.log2(abs(b - a) / XTOL):16.1f} "
|
|
f"{100.0 * st.get('pre_refused', 0) / max(n_o, 1):8.1f}% "
|
|
f"{100.0 * st.get('forced', 0) / max(n_o, 1):7.1f}% "
|
|
f"{'' if ok_o else 'OURS FAIL':>4}")
|
|
|
|
print(f"\ntotals: ours {tot_o}, Chandrupatla {tot_c}, gap {tot_o - tot_c:+d}")
|
|
print("\nper family (ours / theirs / gap):")
|
|
for fam in sorted(fam_loss, key=lambda k: -(fam_loss[k][0] - fam_loss[k][1])):
|
|
o, c, n = fam_loss[fam]
|
|
print(f" {fam:<8} n={n} {o:6d} / {c:6d} gap {o - c:+6d}")
|
|
print("\nthe five problems that cost us most:")
|
|
for d, pid, o, c in sorted(rows, reverse=True)[:5]:
|
|
print(f" {pid:<10} ours {o:4d} CH {c:4d} gap {d:+5d}")
|
|
print("\nthe five where we are ahead:")
|
|
for d, pid, o, c in sorted(rows)[:5]:
|
|
print(f" {pid:<10} ours {o:4d} CH {c:4d} gap {d:+5d}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|