Valeri's decisions (1) competitors from the library, (2) variant a. (1) Chandrupatla is scipy.optimize.elementwise.find_root, Brent is brentq, no more per-problem best_of. Our Chandrupatla stopped on a bracket twice as wide as every other method (the factor the protocol corrects for ITP); fixed (+0.5*xtol) in baselines.py and in the two copies found by grep (stage16_blend, stage19_modern) and the traced mirror, and pinned: ours == library on every problem. Regenerating sweep_full.json changed exactly three rows - chandrupatla APS 2785->2787, CHA 2423->2441, brent CHA 4099->4115 - and nothing else (diff_sweeps.py: 0 unexpected).

(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>
This commit is contained in:
vvs
2026-09-21 10:53:00 +01:00
co-authored by Claude Opus 5
parent de90c7a089
commit 1b6c626f67
32 changed files with 950 additions and 186 deletions
+10 -9
View File
@@ -2,7 +2,9 @@
The published tables predate Chandrupatla's own method as a baseline (it is first on
Alefeld-Potra-Shi) and name the projection variant as proposed, while the code and
verify_article.py have since fixed the credit safeguard as the proposed method. This
the proposed method is the scheduled projection with its multiplier declared (Valeri,
2026-09-21, variant a), the earned projection the constant-free variant. Baselines are
the library alone (Chandrupatla = scipy elementwise.find_root, Brent = brentq). This
prints the rows and head-to-head counts from the data, with the SAME ranking function the
verifier uses, so nothing in the new tables is transcribed by hand.
@@ -10,12 +12,11 @@ verifier uses, so nothing in the new tables is transcribed by hand.
"""
from __future__ import annotations
from report_sweep import PROPOSED, TUNED, head_to_head, load, place
from report_sweep import CREDIT, PROPOSED, TUNED, head_to_head, load, place
PROJ = "pure.ratio.derived3.project"
NONE = "pure.ratio.derived3.none"
NAMES = {PROPOSED: "**proposed: tent, 3-point, credit**",
PROJ: "projection variant (tent, 3-point, projection)",
NAMES = {PROPOSED: "**proposed: tent, 3-point, projection ($c=2$)**",
CREDIT: "constant-free variant: earned projection",
NONE: "the same rule with no safeguard at all",
"chandrupatla": "Chandrupatla", "toms748": "TOMS 748", "brent": "Brent",
"dekker": "Dekker", "itp_oracle": "ITP, per-problem oracle",
@@ -24,10 +25,10 @@ NAMES = {PROPOSED: "**proposed: tent, 3-point, credit**",
"regula_falsi": "false position",
"pure.sqrt.bracket.project": "similarity, $1-\\sqrt{|z|}$, bracket scale, projection",
"pure.exp_abs.bracket.both": "similarity, $e^{-|z|}$, bracket scale, both guards"}
APS_ROWS = ("chandrupatla", PROJ, NONE, "toms748", "brent", "dekker", "itp_oracle",
APS_ROWS = ("chandrupatla", CREDIT, NONE, "toms748", "brent", "dekker", "itp_oracle",
"ridders", PROPOSED, "itp", "illinois", "bisection", "regula_falsi")
CHA_ROWS = ("pure.sqrt.bracket.project", "chandrupatla", "itp_oracle",
"pure.exp_abs.bracket.both", "itp", PROPOSED, "bisection", PROJ, NONE,
"pure.exp_abs.bracket.both", "itp", PROPOSED, "bisection", CREDIT, NONE,
"toms748", "brent")
OPPONENTS = ("chandrupatla", "toms748", "brent", "itp", "itp_oracle", "bisection")
@@ -47,7 +48,7 @@ def main():
over = "—" if k in ("regula_falsi",) else str(d["over"])
print(f"| {place(rows, setname, k)} | {NAMES[k]} | {tuned} | "
f"{d['solved']}/{n} | {d['total']} | {over} |")
for lbl in (PROPOSED, PROJ):
for lbl in (PROPOSED, CREDIT):
print(f"\nhead to head, {lbl} (wins/ties/losses on problems both solve)")
for setname in ("APS", "CHA"):
cells = []
@@ -55,7 +56,7 @@ def main():
w, t, l, _ = head_to_head(rows, lbl, opp, setname)
cells.append(f"{opp} {w}/{t}/{l}")
print(f" {setname}: " + ", ".join(cells))
for lbl in (PROPOSED, PROJ, "chandrupatla", "toms748", "brent", "itp_oracle"):
for lbl in (PROPOSED, CREDIT, "chandrupatla", "toms748", "brent", "itp_oracle"):
d = by[lbl]
print(f" both sets {lbl:34s} {d['APS']['total'] + d['CHA']['total']}")