PREREG_roots_jl outcome (server): variant A does NOT transfer by the stop rule on the Roots.jl / ModAB benchmark. 78 out-of-sample problems: total 1464 vs Chandrupatla 1566 (-6.5%, R1 holds), per problem 38/10/30 p=0.4 (R2 fails), guarantee held and all solved (R3); strict f24-f91 the same picture (1340 vs 1454, 35/6/25 p=0.25). B does not transfer either (32/11/35). Same structure as the first new corpus: multiple/flat roots 331 vs 481 (10:3); the rest 1133 vs 1085, per problem 28/10/27 - parity. Largest loss f32 (4 - tan x near the pole, 41 vs 12). Against Brent and TOMS748 A wins (47/25 p=0.013, 55/20 p=6e-5); they break the 2x-bisection bound on 11 and 9 problems, A on none.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
"""PREREG_roots_jl_2026-09-21: variants A, B, the plain rule and the three library rivals on
|
||||
the Roots.jl / ModAB bracketing benchmark (corpus_roots_jl.py).
|
||||
|
||||
python -u sweep_rootsjl.py run -> sweep_rootsjl.json, then the verdicts
|
||||
python -u sweep_rootsjl.py --report verdicts only
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import math
|
||||
import sys
|
||||
from multiprocessing import Pool
|
||||
|
||||
from corpus_roots_jl import build, solved
|
||||
from sweep_full import MAXFEV, XTOL, make_method
|
||||
from sweep_oos import CONFIGS as OOS_CONFIGS
|
||||
from sweep_oos import sign_p
|
||||
|
||||
NAMES = ("base", "A", "B", "chandrupatla", "brent", "toms748")
|
||||
|
||||
|
||||
def evaluate(name):
|
||||
method = make_method(OOS_CONFIGS[name])
|
||||
probs, _ = build()
|
||||
res = {}
|
||||
for pid, f, a, b, ins in probs:
|
||||
try:
|
||||
x, n, conv = method(f, a, b, XTOL, MAXFEV)
|
||||
x = float(x)
|
||||
except Exception:
|
||||
x, n, conv = float("nan"), MAXFEV, False
|
||||
ok = bool(conv and solved(f, x))
|
||||
over = ok and int(n) > 2 * math.ceil(math.log2(abs(b - a) / XTOL)) + 4
|
||||
res[pid] = [int(n), ok, bool(over), bool(ins)]
|
||||
return name, res
|
||||
|
||||
|
||||
def cost(v):
|
||||
return v[0] if v[1] else MAXFEV
|
||||
|
||||
|
||||
def report(R):
|
||||
keep_main = lambda pid, v: not v[3]
|
||||
keep_strict = lambda pid, v: not v[3] and int(pid[1:]) >= 24
|
||||
keep_ins = lambda pid, v: v[3]
|
||||
ch = R["chandrupatla"]
|
||||
for title, keep in (("MAIN (78 out-of-sample)", keep_main),
|
||||
("STRICT (f24-f91, out-of-sample)", keep_strict),
|
||||
("IN-SAMPLE overlaps (13, for reference)", keep_ins)):
|
||||
print(f"\n== {title}")
|
||||
for k in NAMES:
|
||||
r = R[k]
|
||||
sel = {p: v for p, v in r.items() if keep(p, v)}
|
||||
print(f" {k:<14} total {sum(cost(v) for v in sel.values()):6d} "
|
||||
f"solved {sum(v[1] for v in sel.values()):3d}/{len(sel)} "
|
||||
f"violations {sum(v[2] for v in sel.values())}")
|
||||
for v_name in ("A", "B"):
|
||||
r = R[v_name]
|
||||
sel = [p for p, v in r.items() if keep(p, v)]
|
||||
tot = sum(cost(r[p]) for p in sel)
|
||||
tot_ch = sum(cost(ch[p]) for p in sel)
|
||||
w = sum(cost(r[p]) < cost(ch[p]) for p in sel)
|
||||
l = sum(cost(r[p]) > cost(ch[p]) for p in sel)
|
||||
t = len(sel) - w - l
|
||||
viol = sum(r[p][2] for p in sel)
|
||||
sv, sc = sum(r[p][1] for p in sel), sum(ch[p][1] for p in sel)
|
||||
r1, r2, r3 = tot < tot_ch, w > l and sign_p(w, l) < 0.05, viol == 0 and sv >= sc
|
||||
line = (f" {v_name}: R1 {'✓' if r1 else '✗'} ({tot} vs {tot_ch}) R2 {'✓' if r2 else '✗'} "
|
||||
f"({w}/{t}/{l} p={sign_p(w, l):.2g}) R3 {'✓' if r3 else '✗'} (viol {viol}, "
|
||||
f"solved {sv} vs {sc})")
|
||||
if keep is keep_main:
|
||||
line += " -> " + ("TRANSFERS" if r1 and r2 and r3 else "does NOT transfer")
|
||||
print(line)
|
||||
for rn in ("brent", "toms748"):
|
||||
o = R[rn]
|
||||
w2 = sum(cost(r[p]) < cost(o[p]) for p in sel)
|
||||
l2 = sum(cost(r[p]) > cost(o[p]) for p in sel)
|
||||
print(f" vs {rn:<8} total {tot} vs {sum(cost(o[p]) for p in sel)} "
|
||||
f"per problem {w2}/{len(sel) - w2 - l2}/{l2} p={sign_p(w2, l2):.2g}")
|
||||
print("\nPER PROBLEM, out-of-sample (A / B / Chandrupatla / Brent / TOMS748), * = unsolved:")
|
||||
for p, v in R["A"].items():
|
||||
if v[3]:
|
||||
continue
|
||||
cells = []
|
||||
for k in ("A", "B", "chandrupatla", "brent", "toms748"):
|
||||
c = R[k][p]
|
||||
cells.append(f"{c[0]}{'' if c[1] else '*'}")
|
||||
print(f" {p}: " + " / ".join(cells))
|
||||
|
||||
|
||||
def main():
|
||||
if "--report" not in sys.argv:
|
||||
with Pool(len(NAMES)) as pool:
|
||||
R = dict(pool.map(evaluate, NAMES))
|
||||
with open("sweep_rootsjl.json", "w", encoding="utf8") as fh:
|
||||
json.dump(R, fh)
|
||||
with open("sweep_rootsjl.json", encoding="utf8") as fh:
|
||||
R = json.load(fh)
|
||||
report(R)
|
||||
print("rootsjl done")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user