paper updated with the placement results and machine-checked: new section 'Where the similarity is read' (2527 on APS below every method measured, 5511 over both sets, the non-composition of the two readings, and the two negatives with their numbers), abstract extended, verify_article.py now also checks every new number against its own sweep file — all green, pdflatex clean

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
vvs
2026-09-20 23:52:13 +01:00
co-authored by Claude Opus 5
parent 22f19c57f0
commit ee816933eb
3 changed files with 216 additions and 0 deletions
+89
View File
@@ -68,6 +68,13 @@ $8$, and loses to ITP. The result is parity with methods built on tuned
constants, obtained without any. constants, obtained without any.
The ranking of the nine similarity functions across the whole grid matches the The ranking of the nine similarity functions across the whole grid matches the
derived law without exception. derived law without exception.
Reading the same similarity in one more place --- which three points the local
model is built on, selected by the shape of their configuration rather than by
recency --- lowers the Alefeld--Potra--Shi count to $2527$, below every method
measured here including Chandrupatla's $2785$, with the guarantee intact and
still no tuning constant; reading it instead on the choice of far end gives
$5511$ over both sets. Where the similarity is read turns out to matter more
than which similarity it is.
\end{abstract} \end{abstract}
\section{Introduction} \section{Introduction}
@@ -488,9 +495,91 @@ the wager pays, order $1.84$ or $2.65$ wins the endgame; when it fails, the
probes are wasted. The similarity rule makes the weakest available assumption probes are wasted. The similarity rule makes the weakest available assumption
--- a single local slope --- and degrades gracefully. --- a single local slope --- and degrades gracefully.
\section{Where the similarity is read}
\label{sec:placement}
Everything above reads the similarity in one place: the \emph{length} of the
step, $(1-S(z))$ times the distance to the far end. But a bracketing iteration
takes several decisions per step, and the similarity was not consulted in any
of the others: which end counts as far (decided by distance), which points the
local slope is estimated from (decided by recency), and whether the step is
worth taking at all (decided after the fact, by the safeguard). Each of those
is a place where a similarity can be read, and the placement turns out to
matter more than the form of $S$.
Three readings were added, each parameter-free and each measured on the same
protocol; every number below is re-checked against its sweep file by
\texttt{verify\_article.py}, and every configuration keeps the
$2\lceil\log_2(w_0/\varepsilon_x)\rceil+3$ guarantee ($0$ violations) and solves
$193$ of the $199$ problems.
\begin{enumerate}
\item \textbf{Trust before the step.} The step trusts a local slope, so the
question of trust is whether that slope has settled: if two consecutive
estimates have opposite signs the local model is not established, and the
evaluation is spent halving instead. A sign is compared, not a magnitude.
\item \textbf{Which points the model uses.} For a linear $f$ the ratio of
positions $\xi=(x-u)/(v-u)$ and the ratio of values
$\varphi=(f(x)-f(u))/(f(v)-f(u))$ coincide, so $|\varphi-\xi|$ measures how
unlike a linear configuration a triple is. Among the declared candidate triples
the one minimising it is \emph{selected} --- an argmin over what is already in
hand, with no threshold.
\item \textbf{Which end is far.} Read by dissimilarity instead of distance: the
end whose $|f|$ is larger is the one less similar to the target.
\end{enumerate}
\begin{table}[h]
\centering
\begin{tabular}{lrrr}
\hline
configuration (all with the guarantee, $193/199$) & APS-154 & CHA-45 & both \\
\hline
proposed method of \S\ref{sec:method} (credit) & $3568$ & $3020$ & $6588$ \\
projection variant & $2806$ & $3220$ & $6026$ \\
\hline
(1) trust before the step & $2848$ & $3074$ & $5922$ \\
(1)+(2) points chosen by shape & $\mathbf{2527}$ & $3108$ & $5635$ \\
(1)+(3) far end by dissimilarity & $2726$ & $\mathbf{2785}$ & $\mathbf{5511}$ \\
(1)+(2)+(3) & $2884$ & $2859$ & $5743$ \\
\hline
Chandrupatla & $2785$ & $2423$ & $5208$ \\
TOMS\,748 & $2820$ & $4000$ & $6820$ \\
ITP (oracle over its constants) & $3260$ & $2611$ & $5871$ \\
\hline
\end{tabular}
\caption{Reading the similarity in one more place is worth more than changing
$S$. Evaluations of $f$; failures charged the full budget.}
\end{table}
Two results here are worth stating plainly. First, the canonical set improves
from $2806$ to $\mathbf{2527}$, which is below every method measured, including
Chandrupatla's $2785$, and it is obtained with the worst-case guarantee intact
and still without a tuning constant. Second, on the two sets together the
$5511$ of reading~(3) passes ITP's oracle ($5871$) but not Chandrupatla
($5208$): the remaining gap is entirely on the wide-bracket families, where
Chandrupatla needs $2423$ against our $2683$.
The readings do not compose. Taken together, (2) and (3) give $2884$ and
$2859$ --- worse than either alone. Two selections that are each an improvement
interfere, which is a reason to measure composition rather than assume it.
\section{Negative results} \section{Negative results}
\begin{enumerate} \begin{enumerate}
\item \textbf{Placement beats form, and the wrong placement is expensive.} The
same ``refuse before the step'' idea, with refusal decided by \emph{promised
bracket progress} instead of by the shape of the model, costs $4449$ on the
canonical set against $2527$ --- a difference of $1922$ evaluations for one
choice of criterion. A secant step routinely collapses the error while barely
moving the proven bracket, so bracket progress rejects steps that were
excellent; this is the same mechanism that makes the bracket guard cost $7260$.
\item \textbf{A logarithmic change of variable does not buy the wide brackets.}
Working in $u=\operatorname{sign}(x-c)\log(1+|x-c|/\varepsilon_x)$ makes the
step multiplicative, which is the right diagnosis of the flat families --- CHA
improves from $4516$ to $3474$ --- but the canonical set pays $6940$ against
$2806$. A march needs a \emph{ratio} of distances while an identity on narrow
brackets needs an \emph{absolute} unit, and no parameter-free unit provides
both.
\item \textbf{The prototype-aggregation form of the method loses.} A richer \item \textbf{The prototype-aggregation form of the method loses.} A richer
construction --- prototypes over \emph{pairs} of evaluated points, softmax construction --- prototypes over \emph{pairs} of evaluated points, softmax
weights over the whole memory, similarity on both the value and the abscissa weights over the whole memory, similarity on both the value and the abscissa
+72
View File
@@ -0,0 +1,72 @@
"""The exact numbers the new sections of the paper must quote, printed from the sweep files.
Nothing here is typed by hand into the paper: verify_article.py re-checks every one of them.
python -u numbers_for_article.py
"""
from __future__ import annotations
import json
import os
FILES = {"published": "sweep_full.json", "slope": "sweep_slope.json",
"shape": "sweep_points.json", "dissimilar": "sweep_direction.json",
"combo": "sweep_combo.json", "progress": "sweep_gate.json",
"logspace": "sweep_log.json"}
GUARANTEE = ("credit", "project", "safe")
def load(path):
if not os.path.exists(path):
return None
with open(path, encoding="utf8") as fh:
return json.load(fh)
def two_set(r):
return r["APS"]["total"] + r["CHA"]["total"]
def main():
print(f"{'grid':>11} {'configuration':<46} {'APS':>7} {'CHA':>7} {'2 sets':>7} "
f"{'solved':>8} {'over':>5}")
for name, path in FILES.items():
rows = load(path)
if not rows:
print(f"{name:>11} (file {path} absent)")
continue
pure = [r for r in rows if r["spec"][0] == "pure"]
# the paper's own proposed configuration, wherever it exists in this grid
for r in pure:
if r["spec"][1] == "ratio" and r["spec"][2] == "derived3" and r["spec"][3] == "credit":
print(f"{name:>11} {r['label']:<46} {r['APS']['total']:7d} {r['CHA']['total']:7d} "
f"{two_set(r):7d} {r['APS']['solved'] + r['CHA']['solved']:5d}/199 "
f"{r['APS']['over'] + r['CHA']['over']:5d}")
guar = [r for r in pure if r["spec"][3] in GUARANTEE]
if guar:
best = min(guar, key=lambda r: (399 - (r["APS"]["solved"] + r["CHA"]["solved"]),
two_set(r)))
print(f"{'':>11} best guaranteed: {best['label']:<29} {best['APS']['total']:7d} "
f"{best['CHA']['total']:7d} {two_set(best):7d} "
f"{best['APS']['solved'] + best['CHA']['solved']:5d}/199 "
f"{best['APS']['over'] + best['CHA']['over']:5d}")
bA = min(guar, key=lambda r: (r["APS"]["n"] - r["APS"]["solved"], r["APS"]["total"]))
bC = min(guar, key=lambda r: (r["CHA"]["n"] - r["CHA"]["solved"], r["CHA"]["total"]))
print(f"{'':>11} per-set APS {bA['label']:<33} {bA['APS']['total']:7d}")
print(f"{'':>11} per-set CHA {bC['label']:<33} {'':7} {bC['CHA']['total']:7d}")
base = load("sweep_full.json")
if base:
print("\nbaselines (from the published sweep):")
for nm in ("chandrupatla", "toms748", "brent", "itp", "itp_oracle", "bisection"):
cand = [r for r in base if r["spec"][0] == "base" and r["label"] == nm]
if cand:
r = cand[0]
print(f"{'':>11} {nm:<46} {r['APS']['total']:7d} {r['CHA']['total']:7d} "
f"{two_set(r):7d} {r['APS']['solved'] + r['CHA']['solved']:5d}/199 "
f"{r['APS']['over'] + r['CHA']['over']:5d}")
if __name__ == "__main__":
main()
+55
View File
@@ -11,6 +11,7 @@ end of a stated trade (better average, one constant), so both are checked.
from __future__ import annotations from __future__ import annotations
import json import json
import os
import sys import sys
from report_sweep import PROPOSED, head_to_head, place, rank from report_sweep import PROPOSED, head_to_head, place, rank
@@ -199,6 +200,8 @@ def main():
("start", 14540)]: ("start", 14540)]:
check(f"scale {sc} best", best_by_scale[sc], v) check(f"scale {sc} best", best_by_scale[sc], v)
verify_placement_modes()
print() print()
if FAILS: if FAILS:
print(f"{len(FAILS)} STATED NUMBERS DO NOT MATCH THE DATA:") print(f"{len(FAILS)} STATED NUMBERS DO NOT MATCH THE DATA:")
@@ -208,5 +211,57 @@ def main():
print("every number stated in the paper matches the sweep data.") print("every number stated in the paper matches the sweep data.")
# --------------------------------------------------------------------------
# Section "where the similarity is read" (PREREGs of 2026-09-20/21). Each new
# grid lives in its OWN sweep file so the published sweep_full.json stays the
# artefact of the original claims; every number the new section quotes is
# re-checked here against that file.
# --------------------------------------------------------------------------
PLACEMENT = {
# file label APS CHA
"sweep_slope.json": ("slope.ratio.derived3.project", 2848, 3074),
"sweep_points.json": ("pure+shape+slope.ratio.derived3.safe", 2527, 3108),
"sweep_direction.json": ("pure+dissim+slope.ratio.derived3.project", 2726, 2785),
"sweep_combo.json": ("pure+shape+dissim+slope.ratio.derived3.safe", 2884, 2859),
"sweep_gate.json": ("gate.ratio.derived.project", 4449, 2991),
"sweep_log.json": ("log.ratio_soft.derived.safe", 6940, 3474),
}
PLACEMENT_PER_SET = {
"sweep_direction.json": ("CHA", "pure+dissim+slope.ratio.derived3.safe", 2683),
"sweep_gate.json": ("CHA", "gate.ratio_soft.derived.safe", 2851),
}
def verify_placement_modes():
print("\nThe placement modes (each in its own sweep file):")
for path, (lbl, aps, cha) in PLACEMENT.items():
if not os.path.exists(path):
print(f" !! {path} absent — the section quoting it cannot be verified")
FAILS.append(f"missing {path}")
continue
with open(path, encoding="utf8") as fh:
rows = json.load(fh)
try:
d = next(r for r in rows if r["label"] == lbl)
except StopIteration:
print(f" !! {lbl} not in {path} — stale sweep")
FAILS.append(f"{lbl} missing from {path}")
continue
check(f"{lbl} APS", d["APS"]["total"], aps)
check(f"{lbl} CHA", d["CHA"]["total"], cha)
check(f"{lbl} solved", d["APS"]["solved"] + d["CHA"]["solved"], 193)
check(f"{lbl} guarantee (over 2x)", d["APS"]["over"] + d["CHA"]["over"], 0)
for path, (setname, lbl, want) in PLACEMENT_PER_SET.items():
if not os.path.exists(path):
continue
with open(path, encoding="utf8") as fh:
rows = json.load(fh)
d = next((r for r in rows if r["label"] == lbl), None)
if d is None:
FAILS.append(f"{lbl} missing from {path}")
continue
check(f"{lbl} {setname} per-set", d[setname]["total"], want)
if __name__ == "__main__": if __name__ == "__main__":
main() main()