Files
sim-numerics/diag_model_order_checks.py
T
vvsandClaude Opus 5 de1f8f726d The new sections move into the canonical text, article/sim_numerics.md (Valeri's decision): section 7 'Where the similarity is read' with 7.1 per-place similarity, 7.2 the decision place, 7.3 the fun7 scoring artefact, 7.4 the gap decomposition; negative results 8-11 appended so items 1-7 keep their numbers; abstract paragraph; Future work rewritten (the refuted log transform removed); item 6 now says aps.13.00 is a scoring artefact, not a method failure. Translated into the .md's revised names: code 'ratio' = the tent max(0,1-|z|), code 'rational' = the ratio similarity 1/(1+|z|); the proposed method stays the .md's (tent, 3-point, projection).
Found on the way: negative item 'log change of variable' compared 3474 with 4516, the total of a DIFFERENT configuration; the honest pair is the same configuration in x, CHA 3643 -> 3474, APS 5822 -> 6940. Fixed in both texts. The gap-decomposition numbers were only traced to saved logs; they are now RECOMPUTED by verify_article.py from fresh runs of the diagnosis scripts (which return their values): 216 checks OK on Linux, 762 tests pass twice.

Open, for Valeri: the .md still says the projection's doubling is 'not a tuning constant', which simroot/pure.py (project_credit) refutes and which is why the .tex proposes credit; the .md's Tables 2-3 predate Chandrupatla's own method as a baseline (2785 APS, first place), so its 'parity' abstract is out of date; Brent 2890/4101 in the .md against 2889/4099 in the current sweep.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 07:48:55 +01:00

87 lines
3.5 KiB
Python

"""Two checks on diag_model_order.py before its result may be stated.
C1 WHAT Chandrupatla does on the problems where we lose, by family: the share of his
steps that are bisections, from the traced mirror whose evaluation count is asserted
equal to the original's. If the flat families are won by bisecting, the gap there
is not a better model on his side.
C2 the 5 states where "exactly one negative Lagrange weight" failed: print them. The
sign argument is exact in real arithmetic, so each exception must be a
floating-point degeneracy (a weight that underflowed to 0, or f values so close
that a difference cancelled) - or the argument is wrong and must be withdrawn.
python -u diag_model_order_checks.py
"""
from __future__ import annotations
import math
from collections import defaultdict
from scipy.optimize._tstutils import _CHANDRUPATLA_TESTS_DICTS
from diag_model_order import ACC, MAXFEV, OURS, XTOL, ch_cost, iqi
from explain_chandrupatla import chandrupatla_traced
from simroot.baselines import chandrupatla
from simroot.pure import pure_root
def main():
fam = defaultdict(lambda: [0, 0, 0, 0, 0]) # bisect, iqi, ours n, ch n, problems
exceptions = []
for d in _CHANDRUPATLA_TESTS_DICTS:
pid = str(d["ID"])
f = d["f"]
a, b = (float(v) for v in d["bracket"])
r = float(d["root"])
st = {"trace": []}
x, n, conv = pure_root(f, a, b, XTOL, MAXFEV, stats=st, **OURS)
if not (conv and abs(float(x) - r) <= ACC):
continue
ch = ch_cost(f, a, b, r)
if ch is None or n <= ch:
continue
_xc, nc, okc, tr = chandrupatla_traced(f, a, b, XTOL, MAXFEV)
_xo, no, _oko = chandrupatla(f, a, b, XTOL, MAXFEV)
assert nc == no, f"mirror drifted on {pid}: {nc} vs {no}"
k = pid.split(".")[0]
cell = fam[k]
cell[0] += tr["bisect"]
cell[1] += tr["iqi"]
cell[2] += n
cell[3] += ch
cell[4] += 1
for s in st["trace"]:
if s["xp2"] is None:
continue
pts = ((s["x"], s["fx"]), (s["xp"], s["fp"]), (s["xp2"], s["fp2"]))
fs = [p[1] for p in pts]
if not (min(fs) < 0.0 < max(fs)):
continue
_xq, w = iqi(*pts)
if w is not None and sum(v < 0.0 for v in w) != 1:
exceptions.append((pid, fs, w))
print("C1 Chandrupatla on the problems where we lose, by family")
print(f" {'family':<6} {'probs':>5} {'ours':>6} {'CH':>6} {'gap':>5} "
f"{'CH bisect share':>16}")
tot_gap = 0
for k in sorted(fam):
bi, iq, on, cn, p = fam[k]
tot_gap += on - cn
share = 100.0 * bi / max(bi + iq, 1)
print(f" {k:<6} {p:5d} {on:6d} {cn:6d} {on - cn:5d} {share:15.0f}%")
print(f" total gap on the losing problems: {tot_gap}")
print(f"\nC2 the {len(exceptions)} states breaking 'exactly one negative weight'")
for pid, fs, w in exceptions:
tiny = min(abs(v) for v in fs)
print(f" {pid:<8} f = [{', '.join(f'{v:.3e}' for v in fs)}] "
f"w = [{', '.join(f'{v:.3e}' for v in w)}] "
f"zero weights: {sum(v == 0.0 for v in w)} min|f| {tiny:.1e}")
# for verify_article.py: {family: (bisect, iqi, ours n, ch n, problems)} and the
# number of exceptions, each of which must be a weight that underflowed to zero
return {"fam": dict(fam), "exceptions": exceptions}
if __name__ == "__main__":
main()