73 lines
2.8 KiB
Python
73 lines
2.8 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 best_of, chandrupatla, chandrupatla_scipy
|
|
from simroot.pure import pure_root
|
|
from sweep_full import ACC, MAXFEV, XTOL, load_problems
|
|
|
|
CHA_BASE = best_of(chandrupatla, chandrupatla_scipy)
|
|
|
|
|
|
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()
|