Article (canonical .md), step 2: abstract, introduction, a note in section 3, the close of 7.4, negative results 12-16, conclusion, future work and references 8-12 rewritten for the proposed method A'; two statements that could not be recomputed rephrased. verify_article: expected values updated to the regenerated sweeps, the gate cells renamed (progress.*; their CHA values had moved unnoticed, 2991 -> 3047, 2851 -> 2888, not quoted in the paper), and verify_flat_regime_and_oos() added - Sections 8-9, Tables 8-11, items 12-16 and the abstract, recomputed from server files and fresh diagnosis runs. Verifier on the server: 401 OK, 0 BAD, 'every number stated in the paper matches the sweep data'. Server regression x2: 1226 passed, 0 failed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
vvs
2026-09-21 20:56:58 +01:00
co-authored by Claude Opus 5
parent 8bf595d9be
commit 16b9ab87f1
6 changed files with 772 additions and 172 deletions
+155
View File
@@ -0,0 +1,155 @@
"""The frame of article/sim_numerics.md brought to the method it now proposes (A', Section 8):
abstract, introduction, a note in Section 3, the close of 7.4, new negative results 12-16,
conclusion, future work, references 8-12. Whole paragraphs are replaced by their unique
opening words; insertions go after a unique anchor. Nothing is written unless every anchor
matches exactly once.
python -u apply_article_frame.py
"""
from __future__ import annotations
PATH = "article/sim_numerics.md"
ABSTRACT_2 = (
"The derivation fixes a *base rule* before any benchmark is consulted: a similarity whose "
"approach to 1 is linear, the finest available data-derived scale, and a safeguard that "
"projects the step onto the admissible interval rather than replacing it. It is, explicitly, a "
"Newton step with a three-point divided-difference derivative, clipped to the bracket and "
"projected onto the bisection budget; the similarity function is scaffolding of the derivation "
"and does not appear in the final rule. It carries a proven worst case of twice bisection plus "
"one step and exactly one free constant, which we declare rather than argue away: the "
"multiplier of that budget. On the 154 problems of Alefeld, Potra and Shi it needs 2806 "
"evaluations of $f$ against 2820 for TOMS 748, 2889 for Brent and 2787 for Chandrupatla's "
"method — level in total — and beats Chandrupatla problem by problem 87 to 42 (exact sign test "
"$p=9\\cdot10^{-5}$). On the 45 wide-bracket problems of Chandrupatla it beats Brent and TOMS 748 "
"and loses to ITP and to Chandrupatla (3220 against 2896 and 2441). For every data-derived "
"scale, the ranking of the nine similarity functions matches the derived law without exception."
)
ABSTRACT_3 = (
"The wide-bracket gap turns out to be not the order of the model but a decision — when to give "
"the model up — and the decision is a similarity after all, of an unfamiliar kind: the similarity "
"of a run to its own past. A pure power is self-similar under zoom, so the dimensionless "
"configuration of the last three points recurs, while at a simple root it tends to the linear "
"prototype; the analogous pair yields the local order, $m=\\ln L_f/\\ln L_x$, and an exponential, "
"self-similar by translation, is its limit $m=\\infty$. Entering a halving regime when that "
"analogy holds with $m\\ge2$ — the condition under which a tangent step loses to a halving — "
"splitting at the point the order predicts, and leaving when the split looks linear, together "
"with four smaller readings of the same kind and one borrowed element, gives the method proposed "
"here, A′. On the two sets it needs 2438 and 2005 evaluations against Chandrupatla's 2787 and "
"2441 and beats him problem by problem on both, 103 to 30 and 29 to 7. The chain of decisions "
"that produced it was selected on those sets; tested once, after its code was frozen, on 240 "
"problems from six new families, it needs 3656 evaluations against Chandrupatla's 5717 and wins "
"177 problems to 28. Over 855 problems in six corpora it is ahead of Brent and TOMS 748 "
"everywhere and keeps its bound where they break theirs on 118 and 84 problems; against "
"Chandrupatla it is ahead in total on five corpora and level on the sixth. The lead is large on "
"multiple, fractional and nearly flat roots and a matter of per cent on simple ones."
)
INTRO_ADD = (
"\n\nThe paper proceeds in two stages. Sections 2–7 derive a base rule from the similarity alone, "
"measure it, and locate what it lacks: not a better model but a decision, when to stop trusting "
"the model it has. Section 8 supplies that decision with a similarity of the run to its own "
"past, and Section 9 tests the resulting method on four corpora it was not developed on, one of "
"them fixed after the method's code was frozen."
)
SEC3_ADD = (
" We call it the **base rule**; the method this paper proposes builds on it in Section 8."
)
SEC74_ADD = (
" Section 8 shows that the decision is reachable without a new model: by a similarity of the "
"run to its own past."
)
NEG_ADD = """
12. **Reading the unkept promise one step at a time does not pay.** The flag of §8.1 sees the flat regime, but a halving in place of each flagged step takes the canonical set from 2806 to 3029 and the wide-bracket set only from 3220 to 3198: a simple root far from convergence breaks its promises too. Requiring the promise to fail twice in a row keeps the canonical set (2803) but fires one step late, before the crossing, and replaces the most useful step of the cycle (wide brackets 3341); requiring a creep in one direction as well gives 2878 and 3354.
13. **A halving that sticks once begun wins the flat families and loses everything else.** Without an exit the flat families fall to 1057 — pure bisection's level — and the canonical set rises to 6897, because a false entry now lasts to the end of the run. Splitting at the order read from the failed promise, $(1-1/m)^m=r$, changes nothing: that order is $m=\\infty$ in 163 of 174 entries (6781).
14. **The model's own point cannot tell a flat root from a simple one.** Judging the evaluated point against the line through the bracket ends and against 0 — the exit judgment of §8.2 — also at *entry* gives 3009 and 2486 against 3125 and 2503 for the exit alone: the model aims at the root, so $f$ is small there by construction and looks flat at a simple root as readily as at a power. The same judgment works at a split, which the model did not choose.
15. **The decision reading "defect" does not transfer.** Combined with the regime it was the best configuration on the two development sets (§7.2's canonical record 2523 with the flat families of §8), and it passed every pre-registered criterion there. On new corpus 1 it did not: per problem 95/33/78 against Chandrupatla ($p=0.22$), losing the class of exponential flanks 9 to 26. It is therefore not part of A′.
16. **A component rejected alone can pay in combination.** Remembering the analogy for the run was rejected by its own pre-registration (canonical set 2814 against 2806 without the regime), and with the split of §8.3 it is the better form (with the step pattern, wide brackets 2117 against 2221 for the analogy read in one state). Composition was measured, not assumed, throughout — which is also why §7's readings (2) and (3), each an improvement, are not combined."""
CONCL_2 = (
"The base rule has one declared constant and carries a worst case of twice bisection plus one "
"step. On the canonical Alefeld–Potra–Shi set it is level with TOMS 748 and with Chandrupatla's "
"method in total and ahead of both problem by problem; on the wide-bracket set Chandrupatla is "
"genuinely stronger (2441 against 3220). §7.4 locates the cause: not the order of the model but "
"the decision to give it up, which Chandrupatla takes by halving and which no reading of a single "
"state takes correctly for our step.\n\n"
"That decision is a similarity too — of the run to its own past. A pure power repeats its "
"configuration under zoom, an exponential under translation, a simple root tends to the line; "
"the analogous pair reads the local order, the order decides between the model and a halving by "
"bisection's own $\\tfrac12$, and it says where to split. The method built on it, A′, is ahead of "
"Chandrupatla on both canonical sets in total and problem by problem, and on a corpus fixed after "
"its code was frozen it needs 36% fewer evaluations and wins 177 problems to 28. The claim the "
"measurements support is a lead over Brent and TOMS 748 everywhere, with the guarantee they do "
"not keep, and over Chandrupatla a lead that is large where roots are multiple, fractional or "
"nearly flat and small where they are simple — not superiority by the same margin everywhere. "
"`fun9`, near-cancelling terms and smooth applied equations are where it is behind or level."
)
FUTURE = (
"Three questions remain, all narrower than the one this section used to pose.\n\n"
"The first is the steep flank. Where the loss remains — `fun9`, the near-cancelling class, "
"4 − tan x at its pole — the base step approaches along a flank far steeper than its model, and "
"the half contradiction of §8.4 removes only part of the cost. The second is the one geometric "
"choice of §8.2, the Euclidean metric of the $(\\xi,\\varphi)$ plane: a metric derived from the "
"configuration's own sensitivity would remove it. The third is a comparison this paper does not "
"make: the modified Anderson–Björck method of [10], the most recent bracketing method we know of, "
"is not among the rivals; its own benchmark is corpus 2 here, so the comparison is ready to be run "
"under the rule every other one followed — pre-registered, on a corpus not yet seen."
)
REFS = """
8. G. Pólya, *How to Solve It*. Princeton, NJ: Princeton University Press, 1945.
9. T. J. Dekker, "Finding a zero by means of successive linear interpolation," in B. Dejon and P. Henrici (eds.), *Constructive Aspects of the Fundamental Theorem of Algebra*. London: Wiley-Interscience, 1969, pp. 37–51.
10. N. Ganchovski and A. Traykov, "Modified Anderson-Björck's method for solving non-linear equations in structural mechanics," *IOP Conf. Ser.: Mater. Sci. Eng.*, vol. 1276, 012010, 2023.
11. M. Galassi et al., *GNU Scientific Library Reference Manual*, 3rd ed. Network Theory, 2009; root-finding test suite `roots/test.c`.
12. J. Verzani et al., *Roots.jl*, Julia package; bracketing benchmark `test/benchmark-bracketing-methods.jl`, commit cf1d256, 2026."""
def replace_paragraph(text, opening, new):
lines = text.split("\n")
idx = [i for i, ln in enumerate(lines) if ln.startswith(opening)]
if len(idx) != 1:
raise SystemExit(f"paragraph opening found {len(idx)}x: {opening[:60]}")
lines[idx[0]] = new
return "\n".join(lines)
def insert_after(text, anchor, add):
if text.count(anchor) != 1:
raise SystemExit(f"anchor found {text.count(anchor)}x: {anchor[:60]}")
return text.replace(anchor, anchor + add)
def main():
with open(PATH, encoding="utf8") as fh:
text = fh.read()
text = replace_paragraph(text, "The derivation fixes the method before any benchmark is consulted:",
ABSTRACT_2)
text = replace_paragraph(text, "Reading the same similarity in one more place — which three points",
ABSTRACT_3)
text = insert_after(text, "The answer is sharp in both directions, and the negative half is as "
"informative as the positive half.", INTRO_ADD)
text = insert_after(text, "(iii) the negative results of §10; (iv) the measurements.", SEC3_ADD)
text = insert_after(text, "which is inverse quadratic interpolation — a different method rather "
"than another reading of this one.", SEC74_ADD)
text = insert_after(text, "on the flat families the right move is to halve, not to march.", NEG_ADD)
text = replace_paragraph(text, "The resulting rule has one declared constant", CONCL_2)
text = replace_paragraph(text, "The diagnosis of §7.4 leaves one question", FUTURE)
text = replace_paragraph(text, "What is open is a decision, not a model.", "")
text = insert_after(text, "*BIT*, vol. 11, pp. 168–174, 1971.", REFS)
with open(PATH, "w", encoding="utf8") as fh:
fh.write(text)
print("frame updated")
if __name__ == "__main__":
main()
+35
View File
@@ -0,0 +1,35 @@
"""Rephrase two statements of Section 8 that cannot be re-computed by verify_article.py.
python -u apply_article_verifiable.py
"""
from __future__ import annotations
PATH = "article/sim_numerics.md"
REPL = [
("A chance resemblance at a simple root reads $m\\approx1$; a pure power of order 5 reads 4.9.",
"Under an exact zoom a pure power of order $m$ reads exactly $m$; along a real run the "
"analogous pairs are only nearly homothetic and the reading scatters about the order, but the "
"regime asks only whether it reaches 2."),
("so the memory of this branch is *not* cleared by it (measured on the development corpora: 19 "
"evaluations with the memory kept, 65 without).",
"so the memory of this branch is *not* cleared by it; clearing it was measured on the "
"development corpora and was worse (recorded in the pre-registration amendment of this branch)."),
]
def main():
with open(PATH, encoding="utf8") as fh:
text = fh.read()
for old, _new in REPL:
if text.count(old) != 1:
raise SystemExit(f"found {text.count(old)}x: {old[:70]}")
for old, new in REPL:
text = text.replace(old, new)
with open(PATH, "w", encoding="utf8") as fh:
fh.write(text)
print("rephrased")
if __name__ == "__main__":
main()
+78
View File
@@ -0,0 +1,78 @@
"""Update the expected values in verify_article.py to the regenerated server sweeps (the same
numbers now written into the paper). Exact, counted replacements; nothing written otherwise.
python -u apply_verify_numbers.py
"""
from __future__ import annotations
PATH = "verify_article.py"
REPL = [
('("CHA", 47, 3220, 40)', '("CHA", 45, 3220, 40)', 1),
('("chandrupatla", 2, 2441), ("itp_oracle", 3, 2611),', '("chandrupatla", 2, 2441), ("itp_oracle", 3, 2647),', 1),
('("itp", 6, 2857), ("bisection", 16, 3090),', '("itp", 6, 2896), ("bisection", 16, 3090),', 1),
('("toms748", 164, 4000), ("brent", 226, 4115)]', '("toms748", 159, 4000), ("brent", 227, 4115)]', 1),
('row(rows, "CHA", "pure.cbrt.derived3.project")["total"], 4099)', 'row(rows, "CHA", "pure.cbrt.derived3.project")["total"], 4109)', 1),
('check("switch by benchmark set, both sets", switched, 6905)', 'check("switch by benchmark set, both sets", switched, 6915)', 1),
('want = {("derived3", "lin"): 6809, ("derived3", "quad"): 22294,', 'want = {("derived3", "lin"): 6893, ("derived3", "quad"): 22315,', 1),
('("derived", "lin"): 6906, ("derived", "quad"): 22167,', '("derived", "lin"): 6981, ("derived", "quad"): 22206,', 1),
('("bracket", "lin"): 10263, ("bracket", "quad"): 19137,', '("bracket", "lin"): 10279, ("bracket", "quad"): 19127,', 1),
('for sim, v in [("ratio", 6496), ("exp_abs", 6822), ("rational", 7038),', 'for sim, v in [("ratio", 6560), ("exp_abs", 6895), ("rational", 7118),', 1),
('("ratio_soft", 9502), ("sqrt", 10497), ("cbrt", 11941),', '("ratio_soft", 9578), ("sqrt", 10546), ("cbrt", 12002),', 1),
('("exp_sq", 14314), ("rat_sq", 15102), ("cosine", 16394)]:', '("exp_sq", 14307), ("rat_sq", 15102), ("cosine", 16394)]:', 1),
('for sc, v in [("derived3", 6496), ("derived", 6628), ("bracket", 9081),', 'for sc, v in [("derived3", 6560), ("derived", 6702), ("bracket", 9107),', 1),
('("slope.ratio.derived3.project", 2848, 3074)', '("slope.ratio.derived3.project", 2848, 3114)', 1),
('("pure+shape+slope.ratio.derived3.safe", 2527, 3108)', '("pure+shape+slope.ratio.derived3.safe", 2527, 3126)', 1),
('("pure+dissim+slope.ratio.derived3.project", 2726, 2785)', '("pure+dissim+slope.ratio.derived3.project", 2726, 2799)', 1),
('("pure+shape+dissim+slope.ratio.derived3.safe", 2884, 2859)', '("pure+shape+dissim+slope.ratio.derived3.safe", 2884, 2871)', 1),
('("log.ratio_soft.derived.safe", 6940, 3474)', '("log.ratio_soft.derived.safe", 6940, 3541)', 1),
('"both": (4522, 3675, 3387, 3216),', '"both": (4522, 3675, 3406, 3241),', 1),
('"bracket": (4606, 3542, 3571, 3303),', '"bracket": (4606, 3542, 3602, 3359),', 1),
('"project": (6932, 6364, 4794, 4559),', '"project": (6932, 6364, 4789, 4554),', 1),
('"safe": (5987, 5229, 4108, 3923),', '"safe": (5987, 5229, 4134, 3954),', 1),
('"step": (6435, 5551, 4257, 4022),', '"step": (6435, 5551, 4287, 4068),', 1),
('("ratio", "band", "project"): {"APS": 5432, "CHA": 3066},', '("ratio", "band", "project"): {"APS": 5432, "CHA": 3059},', 1),
('("ratio", "band", "credit"): {"CHA": 2899},', '("ratio", "band", "credit"): {"CHA": 2892},', 1),
('("ratio_soft", "simpair", "project"): {"CHA": 2868},', '("ratio_soft", "simpair", "project"): {"CHA": 2897},', 1),
('DECISION_RATES = {"band": 63.6, "defect": 7.0}', 'DECISION_RATES = {"band": 63.5, "defect": 6.6}', 1),
('check("flat: ours max", round(max(per[p][2] for p in flat), 2), 0.81)', 'check("flat: ours max", round(max(per[p][2] for p in flat), 2), 0.75)', 1),
('check("bracketing states in total", mo["neg_all"], 433)', 'check("bracketing states in total", mo["neg_all"], 431)', 1),
('check("total gap on the losing problems", sum(gap.values()), 244)', 'check("total gap on the losing problems", sum(gap.values()), 256)', 1),
('for k in ("fun3", "fun4", "fun5", "fun6")), 160)', 'for k in ("fun3", "fun4", "fun5", "fun6")), 172)', 1),
('check("m>=2 on flat states %", round(fl["CHA flat fun3-6"][2], 1), 5.8)', 'check("m>=2 on flat states %", round(fl["CHA flat fun3-6"][2], 1), 0.0)', 1),
('("fun6", 456, 235)):', '("fun6", 456, 228)):', 1),
('check("log item: x-space control CHA", xcell["CHA"]["total"], 3643)', 'check("log item: x-space control CHA", xcell["CHA"]["total"], 3695)', 1),
('("CHA", PROJ, 47),', '("CHA", PROJ, 45),', 1),
('by["pure.exp_abs.bracket.both"]["CHA"]["total"],\n 2733)', 'by["pure.exp_abs.bracket.both"]["CHA"]["total"],\n 2736)', 1),
('(CREDIT, "CHA", "itp_oracle", (2, 3, 35)),', '(CREDIT, "CHA", "itp_oracle", (2, 2, 36)),', 1),
('("itp_oracle", 5871), ("toms748", 6820), ("brent", 7004)):', '("itp_oracle", 5907), ("toms748", 6820), ("brent", 7004)):', 1),
('check("best constant-free configuration", top["label"], "defect.ratio.derived3.credit")',
'check("best constant-free configuration", top["label"],\n "defect+flatanalogmempt+exp+half.ratio.derived3.credit")', 1),
('check("its total over both sets", top["APS"]["total"] + top["CHA"]["total"], 6494)',
'check("its total over both sets", top["APS"]["total"] + top["CHA"]["total"], 6111)\n'
' d = cells["defect.ratio.derived3.credit"]\n'
' check("defect under the earned projection, both sets",\n'
' d["APS"]["total"] + d["CHA"]["total"], 6494)', 1),
('"sweep_direction.json": ("CHA", "pure+dissim+slope.ratio.derived3.safe", 2683),', '"sweep_direction.json": ("CHA", "pure+dissim+slope.ratio.derived3.safe", 2695),', 1),
('check("CHA vs Chandrupatla sign test p (rounded)", round(sign_p(w, l), 3), 0.006)',
'check("CHA vs Chandrupatla sign test p (rounded)", round(sign_p(w, l), 3), 0.006)', 1),
]
def main():
with open(PATH, encoding="utf8") as fh:
text = fh.read()
bad = [(o, n, text.count(o)) for o, _new, n in REPL if text.count(o) != n]
if bad:
for o, n, got in bad:
print(f"expected {n}, found {got}: {o[:90]}")
raise SystemExit("aborted, nothing written")
for o, new, _n in REPL:
text = text.replace(o, new)
with open(PATH, "w", encoding="utf8") as fh:
fh.write(text)
print(f"{len(REPL)} expected values updated")
if __name__ == "__main__":
main()
+28 -9
View File
@@ -8,9 +8,9 @@ V. Sitnikov
Bisection places the next iterate at the midpoint because it uses no information about the function's value. We replace that rule with a *similarity* rule: the step is proportional to how *dissimilar* the current outcome $f(x)$ is to the expectation $0$, measured by a similarity function $S:\mathbb{R}\to[0,1]$ with $S(0)=1$. We derive the contraction factor of the resulting iteration in closed form; it predicts a linear rate to four digits when $1-S$ has a non-zero slope at the origin, and a sublinear $e_n\sim C/n$ with a predicted $C$ when it does not, both confirmed. Three consequences follow. First, with the *ratio* similarity scaled by the far end — and with that combination only, of the five tested — the rule reproduces the false-position formula identically; so does the truncated linear similarity scaled by a divided difference over the *bracket ends*, which shows that the boundary of novelty runs through which points the difference is taken over. Second, any similarity fixed in advance with the scale also fixed yields at best linear convergence at a rate that is a property of the problem rather than of the method; on the eight standard problems of §2.2, five to eight of them fail. Third, the rate vanishes exactly when the scale equals the local scale of the value axis; reading that scale off the data — a divided difference, not a fitted coefficient — turns the step into $|f|/|f'|$ and the convergence superlinear. Bisection places the next iterate at the midpoint because it uses no information about the function's value. We replace that rule with a *similarity* rule: the step is proportional to how *dissimilar* the current outcome $f(x)$ is to the expectation $0$, measured by a similarity function $S:\mathbb{R}\to[0,1]$ with $S(0)=1$. We derive the contraction factor of the resulting iteration in closed form; it predicts a linear rate to four digits when $1-S$ has a non-zero slope at the origin, and a sublinear $e_n\sim C/n$ with a predicted $C$ when it does not, both confirmed. Three consequences follow. First, with the *ratio* similarity scaled by the far end — and with that combination only, of the five tested — the rule reproduces the false-position formula identically; so does the truncated linear similarity scaled by a divided difference over the *bracket ends*, which shows that the boundary of novelty runs through which points the difference is taken over. Second, any similarity fixed in advance with the scale also fixed yields at best linear convergence at a rate that is a property of the problem rather than of the method; on the eight standard problems of §2.2, five to eight of them fail. Third, the rate vanishes exactly when the scale equals the local scale of the value axis; reading that scale off the data — a divided difference, not a fitted coefficient — turns the step into $|f|/|f'|$ and the convergence superlinear.
The derivation fixes the method before any benchmark is consulted: a similarity whose approach to 1 is linear, the finest available data-derived scale, and a safeguard that projects the step onto the admissible interval rather than replacing it. What results is, explicitly, a Newton step with a three-point divided-difference derivative, clipped to the bracket and projected onto the bisection budget; the similarity function is scaffolding of the derivation and does not appear in the final rule. It carries a proven worst case of twice bisection plus one step, and exactly one free constant, which we declare rather than argue away: the multiplier of that budget. On the canonical set it does not matter — the total is the same for every multiplier from 1.25 to 4 — and on the wide-bracket set it does, moving the total from 2752 to 4006. On the 154 problems of Alefeld, Potra and Shi the rule needs 2806 evaluations of $f$ against 2820 for TOMS 748 — a margin of 0.5%, which is a tie — 2889 for Brent, and 2787 for Chandrupatla's method, 0.7% fewer in total; problem by problem it beats Chandrupatla 87 to 42 (exact sign test $p=9\cdot10^{-5}$) and Brent 102 to 40. On the 45 problems of Chandrupatla it beats Brent 30 to 4 and TOMS 748 31 to 8, and loses to ITP and to Chandrupatla (3220 against 2857 and 2441). A variant whose budget is earned step by step has no free constant and a tighter guarantee, bisection plus one step, at a price of 762 evaluations on the canonical set. For every data-derived scale, the ranking of the nine similarity functions matches the derived law without exception. The derivation fixes a *base rule* before any benchmark is consulted: a similarity whose approach to 1 is linear, the finest available data-derived scale, and a safeguard that projects the step onto the admissible interval rather than replacing it. It is, explicitly, a Newton step with a three-point divided-difference derivative, clipped to the bracket and projected onto the bisection budget; the similarity function is scaffolding of the derivation and does not appear in the final rule. It carries a proven worst case of twice bisection plus one step and exactly one free constant, which we declare rather than argue away: the multiplier of that budget. On the 154 problems of Alefeld, Potra and Shi it needs 2806 evaluations of $f$ against 2820 for TOMS 748, 2889 for Brent and 2787 for Chandrupatla's method — level in total — and beats Chandrupatla problem by problem 87 to 42 (exact sign test $p=9\cdot10^{-5}$). On the 45 wide-bracket problems of Chandrupatla it beats Brent and TOMS 748 and loses to ITP and to Chandrupatla (3220 against 2896 and 2441). For every data-derived scale, the ranking of the nine similarity functions matches the 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 2787; reading it instead on the choice of far end gives 5511 over both sets, and reading it in the decision to trust the model or halve lowers the canonical count further, to 2523. On the canonical set these records barely feel the multiplier — 2523 is the same for every multiplier from 1.25 to 4, 2527 for every one from 1.5 to 4 and 2541 at 1.25; under the constant-free earned budget the same readings gain far less (6494 over both sets against 6588). Where the similarity is read turns out to matter more than which similarity it is. The gap that remains on the wide-bracket set is taken apart on the same evaluations: about a quarter of it is the order of the model — a convex two-point step cannot carry the negative weight of quadratic interpolation — and two thirds is not a model at all but the decision when to give the model up, which Chandrupatla takes by bisecting on up to all of his steps and which no reading measured here takes correctly for ours. The wide-bracket gap turns out to be not the order of the model but a decision — when to give the model up — and the decision is a similarity after all, of an unfamiliar kind: the similarity of a run to its own past. A pure power is self-similar under zoom, so the dimensionless configuration of the last three points recurs, while at a simple root it tends to the linear prototype; the analogous pair yields the local order, $m=\ln L_f/\ln L_x$, and an exponential, self-similar by translation, is its limit $m=\infty$. Entering a halving regime when that analogy holds with $m\ge2$ — the condition under which a tangent step loses to a halving — splitting at the point the order predicts, and leaving when the split looks linear, together with four smaller readings of the same kind and one borrowed element, gives the method proposed here, A′. On the two sets it needs 2438 and 2005 evaluations against Chandrupatla's 2787 and 2441 and beats him problem by problem on both, 103 to 30 and 29 to 7. The chain of decisions that produced it was selected on those sets; tested once, after its code was frozen, on 240 problems from six new families, it needs 3656 evaluations against Chandrupatla's 5717 and wins 177 problems to 28. Over 855 problems in six corpora it is ahead of Brent and TOMS 748 everywhere and keeps its bound where they break theirs on 118 and 84 problems; against Chandrupatla it is ahead in total on five corpora and level on the sixth. The lead is large on multiple, fractional and nearly flat roots and a matter of per cent on simple ones.
--- ---
@@ -22,6 +22,8 @@ This paper asks a different question. Suppose the only thing available is a *sim
The answer is sharp in both directions, and the negative half is as informative as the positive half. The answer is sharp in both directions, and the negative half is as informative as the positive half.
The paper proceeds in two stages. Sections 2–7 derive a base rule from the similarity alone, measure it, and locate what it lacks: not a better model but a decision, when to stop trusting the model it has. Section 8 supplies that decision with a similarity of the run to its own past, and Section 9 tests the resulting method on four corpora it was not developed on, one of them fixed after the method's code was frozen.
--- ---
## 2. The similarity step rule ## 2. The similarity step rule
@@ -102,7 +104,7 @@ $$x' \;=\; x + \operatorname{sign}(x_\mathrm{far}-x)\cdot\min\!\Bigl(\frac{|f(x)
a Newton step with a three-point divided-difference derivative, clipped to the bracket and then projected as in §3.1. The similarity function does not appear in (4): it is scaffolding of the derivation, not machinery of the algorithm. a Newton step with a three-point divided-difference derivative, clipped to the bracket and then projected as in §3.1. The similarity function does not appear in (4): it is scaffolding of the derivation, not machinery of the algorithm.
We state this ourselves rather than leave it to be discovered, because it locates the contribution precisely. It is not a new family of methods. It is (i) a derivation that fixes every choice — which similarity, which scale, which safeguard — before any benchmark is consulted, and then predicts the ranking of all nine similarity functions correctly; (ii) a safeguard of ITP's projection type with ITP's truncation stage, and hence all three of its constants, removed; (iii) the negative results of §10; (iv) the measurements. We state this ourselves rather than leave it to be discovered, because it locates the contribution precisely. It is not a new family of methods. It is (i) a derivation that fixes every choice — which similarity, which scale, which safeguard — before any benchmark is consulted, and then predicts the ranking of all nine similarity functions correctly; (ii) a safeguard of ITP's projection type with ITP's truncation stage, and hence all three of its constants, removed; (iii) the negative results of §10; (iv) the measurements. We call it the **base rule**; the method this paper proposes builds on it in Section 8.
**Algorithm.** Given $[a,b]$ with $f(a)f(b)<0$ and tolerance $\varepsilon_x$: **Algorithm.** Given $[a,b]$ with $f(a)f(b)<0$ and tolerance $\varepsilon_x$:
@@ -393,7 +395,7 @@ That mechanism is right for `fun1` and *wrong as a statement about the whole gap
But 172 of the 256 — two thirds — sit on `fun3`–`fun6`, which are pure powers of order 3, 5, 9 and 19, and there *no* interpolating model works: our step removes 0.41–0.75 halvings of the bracket per evaluation, inverse quadratic interpolation from the same points only 0.01–0.17. Chandrupatla does not win those families with his model — his traced run bisects 92, 96, 100 and 100% of his steps. We lose them because our step is slower than bisection there and our guarantee, at most twice bisection, licenses exactly that. His band inside our step confirms it family by family: under the projection it takes `fun4`, `fun5`, `fun6` from 573, 456, 456 to 296, 239, 228 — against his own 297, 233, 233 — and costs +164, +111, +170, +144 on `fun1`, `fun2`, `fun8`, `fun9`, where it refuses steps that were good. But 172 of the 256 — two thirds — sit on `fun3`–`fun6`, which are pure powers of order 3, 5, 9 and 19, and there *no* interpolating model works: our step removes 0.41–0.75 halvings of the bracket per evaluation, inverse quadratic interpolation from the same points only 0.01–0.17. Chandrupatla does not win those families with his model — his traced run bisects 92, 96, 100 and 100% of his steps. We lose them because our step is slower than bisection there and our guarantee, at most twice bisection, licenses exactly that. His band inside our step confirms it family by family: under the projection it takes `fun4`, `fun5`, `fun6` from 573, 456, 456 to 296, 239, 228 — against his own 297, 233, 233 — and costs +164, +111, +170, +144 on `fun1`, `fun2`, `fun8`, `fun9`, where it refuses steps that were good.
So most of what remains is not the order of the model but the decision *when to give the model up*, and it is open because every detector measured so far confounds "the model is useless here" with something else: the band with "the configuration is not shaped for inverse quadratic interpolation", bracket progress with "the step has not moved the bracket yet" (4449 on the canonical set, §10), and the local order with nothing at all — $m\ge2$ is exactly the condition under which a tangent step loses to a halving, since it lands at $e(1-1/m)$, and it is clean (0.2% of canonical states) but blind: it reports $m\ge2$ on none of the states of families whose order is by construction 3 to 19. For the `fun1` part, three parameter-free ways round the model order have been measured and all three fail in the same way, buying the wide brackets at the price of the canonical set: a fixed fraction of the bracket (the cube-root similarity), a logarithmic change of variable, and the curvature-corrected scale of §10 item 5. The fourth way is to model the curvature directly, which is inverse quadratic interpolation — a different method rather than another reading of this one. So most of what remains is not the order of the model but the decision *when to give the model up*, and it is open because every detector measured so far confounds "the model is useless here" with something else: the band with "the configuration is not shaped for inverse quadratic interpolation", bracket progress with "the step has not moved the bracket yet" (4449 on the canonical set, §10), and the local order with nothing at all — $m\ge2$ is exactly the condition under which a tangent step loses to a halving, since it lands at $e(1-1/m)$, and it is clean (0.2% of canonical states) but blind: it reports $m\ge2$ on none of the states of families whose order is by construction 3 to 19. For the `fun1` part, three parameter-free ways round the model order have been measured and all three fail in the same way, buying the wide brackets at the price of the canonical set: a fixed fraction of the bracket (the cube-root similarity), a logarithmic change of variable, and the curvature-corrected scale of §10 item 5. The fourth way is to model the curvature directly, which is inverse quadratic interpolation — a different method rather than another reading of this one. Section 8 shows that the decision is reachable without a new model: by a similarity of the run to its own past.
On the re-scored wide-bracket set of Table 7 our shape reading (2159) is *worse* than bisection (2136); only the dissimilarity reading (1740) is clearly ahead, which is the same statement seen from the other end: where the step cannot march, the reading that helps least is the one that only improves the local model. On the re-scored wide-bracket set of Table 7 our shape reading (2159) is *worse* than bisection (2136); only the dissimilarity reading (1740) is clearly ahead, which is the same statement seen from the other end: where the step cannot march, the reading that helps least is the one that only improves the local model.
@@ -421,7 +423,7 @@ Nearness of configurations is one relation. An analogy in the full sense needs a
$$m=\frac{\ln L_f}{\ln L_x}.\tag{6}$$ $$m=\frac{\ln L_f}{\ln L_x}.\tag{6}$$
A chance resemblance at a simple root reads $m\approx1$; a pure power of order 5 reads 4.9. The regime is the one where a tangent step loses, $m\ge2$ (§8.1) — no new constant. On the traces of the base rule, at the moments the flag rises, the three conditions together hold on 3 of the 154 canonical problems, on all 20 flat problems, and on none of `fun2`, `fun8`, `fun9`. Under an exact zoom a pure power of order $m$ reads exactly $m$; along a real run the analogous pairs are only nearly homothetic and the reading scatters about the order, but the regime asks only whether it reaches 2. The regime is the one where a tangent step loses, $m\ge2$ (§8.1) — no new constant. On the traces of the base rule, at the moments the flag rises, the three conditions together hold on 3 of the 154 canonical problems, on all 20 flat problems, and on none of `fun2`, `fun8`, `fun9`.
**The analogy belongs to the run, the flag to the moment.** In the cycle the base rule runs on a pure power — undershoot, undershoot, crossing, a nearly empty step — the flag rises in the phases whose configuration does *not* recur (the empty step grows emptier every cycle), while the recurring phases have the flag down. Requiring both in one state delayed the entry on the flat problems to their thirteenth state on average. Once established, the analogy is therefore remembered for the run, and the regime is entered at the next unkept promise (eighth state on average). **The analogy belongs to the run, the flag to the moment.** In the cycle the base rule runs on a pure power — undershoot, undershoot, crossing, a nearly empty step — the flag rises in the phases whose configuration does *not* recur (the empty step grows emptier every cycle), while the recurring phases have the flag down. Requiring both in one state delayed the entry on the flat problems to their thirteenth state on average. Once established, the analogy is therefore remembered for the run, and the regime is entered at the next unkept promise (eighth state on average).
@@ -445,7 +447,7 @@ which is exact for a pure power and becomes the midpoint as $m\to\infty$. The or
**The repeated step pattern.** Two successive moves the same way, of similar length, mean the iterate creeps along a geometric series whose remainder is $\text{step}\cdot s/(1-s)$; the step is lengthened by $1/(1-s)$, with $s$ the similarity of successive step lengths, but only when the pattern of successive length ratios repeats with a period read from the data (the lag of highest mean similarity) and that similarity exceeds $\tfrac12$. **The repeated step pattern.** Two successive moves the same way, of similar length, mean the iterate creeps along a geometric series whose remainder is $\text{step}\cdot s/(1-s)$; the step is lengthened by $1/(1-s)$, with $s$ the similarity of successive step lengths, but only when the pattern of successive length ratios repeats with a period read from the data (the lag of highest mean similarity) and that similarity exceeds $\tfrac12$.
**The overshoot branch.** §8.1's inequality has a second branch, $m<\tfrac23$: a root of order below one, where the tangent step overshoots and the iterate oscillates about the root ($\sqrt{|x|}\operatorname{sign}x$: 84 evaluations of the base rule). The flag for it is the unkept promise *with* a sign change, $f_\text{new}/f_\text{old}\le-\tfrac14$, and an analogous pair reading $0<m\le\tfrac23$; the split (7) is again exact for a pure power. The exit judgment of §8.2 separates a flat root from a simple one; at a root of order below one $f$ is far from 0 on both sides and the exit fires falsely, so the memory of this branch is *not* cleared by it (measured on the development corpora: 19 evaluations with the memory kept, 65 without). **The overshoot branch.** §8.1's inequality has a second branch, $m<\tfrac23$: a root of order below one, where the tangent step overshoots and the iterate oscillates about the root ($\sqrt{|x|}\operatorname{sign}x$: 84 evaluations of the base rule). The flag for it is the unkept promise *with* a sign change, $f_\text{new}/f_\text{old}\le-\tfrac14$, and an analogous pair reading $0<m\le\tfrac23$; the split (7) is again exact for a pure power. The exit judgment of §8.2 separates a flat root from a simple one; at a root of order below one $f$ is far from 0 on both sides and the exit fires falsely, so the memory of this branch is *not* cleared by it; clearing it was measured on the development corpora and was worse (recorded in the pre-registration amendment of this branch).
**Borrowed: the tolerance step.** Once the root is reached from one side the bracket's far end can stay far: on $\sin$ over $[3,4]$ the base rule reaches $|f|\approx10^{-16}$ in 7 evaluations and then halves the remaining $1.3\cdot10^{-7}$ down to the tolerance in 17 more. Dekker [9] and Brent [2] step at least the tolerance; we do the same, $\varepsilon_x/2$ towards the far end, when the model's step is shorter — but only after the model has *kept* its previous promise ($r<\tfrac14$), because at the start of a run a slope dominated by a huge far value promises the root at an end. This element is not ours and is named as such. **Borrowed: the tolerance step.** Once the root is reached from one side the bracket's far end can stay far: on $\sin$ over $[3,4]$ the base rule reaches $|f|\approx10^{-16}$ in 7 evaluations and then halves the remaining $1.3\cdot10^{-7}$ down to the tolerance in 17 more. Dekker [9] and Brent [2] step at least the tolerance; we do the same, $\varepsilon_x/2$ towards the far end, when the model's step is shorter — but only after the model has *kept* its previous promise ($r<\tfrac14$), because at the start of a run a slope dominated by a huge far value promises the root at an end. This element is not ours and is named as such.
@@ -548,21 +550,33 @@ Only the last line of corpora is evidence for A′ in the strict sense; the firs
11. **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 looked like the right diagnosis of the flat families — for the same similarity, scale and safeguard ($(1+|z|)^{-2}$, two-point, *safe*) the wide-bracket set improves from 3695 to 3541 — but the canonical set gets worse, 5822 to 6940, against the 2806 of the base rule. An earlier version compared the 3541 with 4516, which is the total of a different configuration. A march needs a *ratio* of distances while an identity on narrow brackets needs an *absolute* unit, and no parameter-free unit provides both. §7.4 shows the diagnosis itself was wrong: on the flat families the right move is to halve, not to march. 11. **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 looked like the right diagnosis of the flat families — for the same similarity, scale and safeguard ($(1+|z|)^{-2}$, two-point, *safe*) the wide-bracket set improves from 3695 to 3541 — but the canonical set gets worse, 5822 to 6940, against the 2806 of the base rule. An earlier version compared the 3541 with 4516, which is the total of a different configuration. A march needs a *ratio* of distances while an identity on narrow brackets needs an *absolute* unit, and no parameter-free unit provides both. §7.4 shows the diagnosis itself was wrong: on the flat families the right move is to halve, not to march.
12. **Reading the unkept promise one step at a time does not pay.** The flag of §8.1 sees the flat regime, but a halving in place of each flagged step takes the canonical set from 2806 to 3029 and the wide-bracket set only from 3220 to 3198: a simple root far from convergence breaks its promises too. Requiring the promise to fail twice in a row keeps the canonical set (2803) but fires one step late, before the crossing, and replaces the most useful step of the cycle (wide brackets 3341); requiring a creep in one direction as well gives 2878 and 3354.
13. **A halving that sticks once begun wins the flat families and loses everything else.** Without an exit the flat families fall to 1057 — pure bisection's level — and the canonical set rises to 6897, because a false entry now lasts to the end of the run. Splitting at the order read from the failed promise, $(1-1/m)^m=r$, changes nothing: that order is $m=\infty$ in 163 of 174 entries (6781).
14. **The model's own point cannot tell a flat root from a simple one.** Judging the evaluated point against the line through the bracket ends and against 0 — the exit judgment of §8.2 — also at *entry* gives 3009 and 2486 against 3125 and 2503 for the exit alone: the model aims at the root, so $f$ is small there by construction and looks flat at a simple root as readily as at a power. The same judgment works at a split, which the model did not choose.
15. **The decision reading "defect" does not transfer.** Combined with the regime it was the best configuration on the two development sets (§7.2's canonical record 2523 with the flat families of §8), and it passed every pre-registered criterion there. On new corpus 1 it did not: per problem 95/33/78 against Chandrupatla ($p=0.22$), losing the class of exponential flanks 9 to 26. It is therefore not part of A′.
16. **A component rejected alone can pay in combination.** Remembering the analogy for the run was rejected by its own pre-registration (canonical set 2814 against 2806 without the regime), and with the split of §8.3 it is the better form (with the step pattern, wide brackets 2117 against 2221 for the analogy read in one state). Composition was measured, not assumed, throughout — which is also why §7's readings (2) and (3), each an improvement, are not combined.
--- ---
## 11. Conclusion ## 11. Conclusion
A root finder can be derived from a similarity function alone, and the derivation shows where the content of such a method actually sits. It is not in the shape of $S$ — nine shapes were tried and their ranking is dictated by a single number, the slope of $1-S$ at the origin. It is not in making the similarity change faster — that overshoots exactly as readily as flatness stagnates. It is in the *scale* against which similarity is judged: chosen, the method is brittle and merely linear; taken from the bracket, it is false position and three centuries old; read off the data, it is superlinear. And the safeguard that makes such a method safe must project the step, not replace it: replacing costs the order, projecting costs nothing on one benchmark and improves the method on the other. The projection's budget multiplier is a free constant, and we declare it: it does not move the canonical result and it does move the wide-bracket one; projecting onto a budget the steps earn instead removes it, at a measured price. A root finder can be derived from a similarity function alone, and the derivation shows where the content of such a method actually sits. It is not in the shape of $S$ — nine shapes were tried and their ranking is dictated by a single number, the slope of $1-S$ at the origin. It is not in making the similarity change faster — that overshoots exactly as readily as flatness stagnates. It is in the *scale* against which similarity is judged: chosen, the method is brittle and merely linear; taken from the bracket, it is false position and three centuries old; read off the data, it is superlinear. And the safeguard that makes such a method safe must project the step, not replace it: replacing costs the order, projecting costs nothing on one benchmark and improves the method on the other. The projection's budget multiplier is a free constant, and we declare it: it does not move the canonical result and it does move the wide-bracket one; projecting onto a budget the steps earn instead removes it, at a measured price.
The resulting rule has one declared constant and carries a worst case of twice bisection plus one step. On the canonical Alefeld–Potra–Shi set it is level with TOMS 748 — 2806 evaluations against 2820 is a margin of 0.5% and should be read as a tie — ahead of Brent by 2.9%, and level with Chandrupatla's method in the same sense: 0.7% more in total, while winning 87 of the problems to his 42 ($p=9\cdot10^{-5}$). On the wide-bracket set Chandrupatla is genuinely stronger (2441 against 3220), and that is where the declared multiplier matters. The constant-free variant trades 762 evaluations on the canonical set for no constant, a tighter guarantee and the better wide-bracket total. The claim the measurements support is parity with the best methods on the canonical set, with a problem-by-problem edge over all of them, and a measured deficit on very wide brackets whose cause §7.4 locates — not superiority overall. The base rule has one declared constant and carries a worst case of twice bisection plus one step. On the canonical Alefeld–Potra–Shi set it is level with TOMS 748 and with Chandrupatla's method in total and ahead of both problem by problem; on the wide-bracket set Chandrupatla is genuinely stronger (2441 against 3220). §7.4 locates the cause: not the order of the model but the decision to give it up, which Chandrupatla takes by halving and which no reading of a single state takes correctly for our step.
That decision is a similarity too — of the run to its own past. A pure power repeats its configuration under zoom, an exponential under translation, a simple root tends to the line; the analogous pair reads the local order, the order decides between the model and a halving by bisection's own $\tfrac12$, and it says where to split. The method built on it, A′, is ahead of Chandrupatla on both canonical sets in total and problem by problem, and on a corpus fixed after its code was frozen it needs 36% fewer evaluations and wins 177 problems to 28. The claim the measurements support is a lead over Brent and TOMS 748 everywhere, with the guarantee they do not keep, and over Chandrupatla a lead that is large where roots are multiple, fractional or nearly flat and small where they are simple — not superiority by the same margin everywhere. `fun9`, near-cancelling terms and smooth applied equations are where it is behind or level.
This is the same movement as in parameter-free similarity control [6], where membership functions are eliminated by normalising the input space from the data rather than by choosing widths. Here the object normalised is the value axis, and the price of choosing it by hand is measured rather than asserted. This is the same movement as in parameter-free similarity control [6], where membership functions are eliminated by normalising the input space from the data rather than by choosing widths. Here the object normalised is the value axis, and the price of choosing it by hand is measured rather than asserted.
### Future work ### Future work
The diagnosis of §7.4 leaves one question, and it is narrower than the one this section used to pose. An earlier version proposed a logarithmic change of variable to turn an additive step into a geometric march; that was measured and refuted (§10, item 11), and the step turned out to be a fraction of the bracket already. Three questions remain, all narrower than the one this section used to pose.
What is open is a decision, not a model. On two thirds of the remaining gap the right move is to halve, and Chandrupatla halves; our guarantee permits a step that is slower than halving, and nothing we have measured tells our step when it is. The condition itself is known exactly — a tangent step on an approach of local order $m$ lands at $e(1-1/m)$ and loses to a halving when $m\ge2$ — so the constant is bisection's $\tfrac12$ and not a choice. What is missing is a reading of $m$ that sees it: the three-point estimator reports $m\ge2$ on 0.2% of canonical states, which is the right silence, and on 5.8% of states of pure powers of order 3 to 19, which is blindness. Two successive residuals of the run itself carry the order more directly than a parabola through three points — on an order-$m$ approach under tangent steps their ratio settles at $(1-1/m)^m$, while at a simple root it goes to zero — and that is the reading we would test next, under the same rule as every other here: pre-registered, with the canonical set as the price it must not charge. The first is the steep flank. Where the loss remains — `fun9`, the near-cancelling class, 4 − tan x at its pole — the base step approaches along a flank far steeper than its model, and the half contradiction of §8.4 removes only part of the cost. The second is the one geometric choice of §8.2, the Euclidean metric of the $(\xi,\varphi)$ plane: a metric derived from the configuration's own sensitivity would remove it. The third is a comparison this paper does not make: the modified Anderson–Björck method of [10], the most recent bracketing method we know of, is not among the rivals; its own benchmark is corpus 2 here, so the comparison is ready to be run under the rule every other one followed — pre-registered, on a corpus not yet seen.
--- ---
@@ -576,3 +590,8 @@ What is open is a decision, not a model. On two thirds of the remaining gap the
5. C. Ridders, "A new algorithm for computing a single root of a real continuous function," *IEEE Trans. Circuits Syst.*, vol. 26, no. 11, pp. 979–980, 1979. 5. C. Ridders, "A new algorithm for computing a single root of a real continuous function," *IEEE Trans. Circuits Syst.*, vol. 26, no. 11, pp. 979–980, 1979.
6. V. Sitnikov, "Parameter-free similarity control," preprint, 2026. 6. V. Sitnikov, "Parameter-free similarity control," preprint, 2026.
7. M. Dowell and P. Jarratt, "A modified regula falsi method for computing the root of an equation," *BIT*, vol. 11, pp. 168–174, 1971. 7. M. Dowell and P. Jarratt, "A modified regula falsi method for computing the root of an equation," *BIT*, vol. 11, pp. 168–174, 1971.
8. G. Pólya, *How to Solve It*. Princeton, NJ: Princeton University Press, 1945.
9. T. J. Dekker, "Finding a zero by means of successive linear interpolation," in B. Dejon and P. Henrici (eds.), *Constructive Aspects of the Fundamental Theorem of Algebra*. London: Wiley-Interscience, 1969, pp. 37–51.
10. N. Ganchovski and A. Traykov, "Modified Anderson-Björck's method for solving non-linear equations in structural mechanics," *IOP Conf. Ser.: Mater. Sci. Eng.*, vol. 1276, 012010, 2023.
11. M. Galassi et al., *GNU Scientific Library Reference Manual*, 3rd ed. Network Theory, 2009; root-finding test suite `roots/test.c`.
12. J. Verzani et al., *Roots.jl*, Julia package; bracketing benchmark `test/benchmark-bracketing-methods.jl`, commit cf1d256, 2026.
+188 -118
View File
@@ -4,7 +4,7 @@ The proposed method (projection, multiplier declared):
OK APS place got 3 want 3 OK APS place got 3 want 3
OK APS total got 2806 want 2806 OK APS total got 2806 want 2806
OK APS solved got 153 want 153 OK APS solved got 153 want 153
BAD CHA place got 45 want 47 OK CHA place got 45 want 45
OK CHA total got 3220 want 3220 OK CHA total got 3220 want 3220
OK CHA solved got 40 want 40 OK CHA solved got 40 want 40
OK both sets got 6026 want 6026 OK both sets got 6026 want 6026
@@ -74,23 +74,23 @@ Chandrupatla:
OK CHA chandrupatla place got 2 want 2 OK CHA chandrupatla place got 2 want 2
OK CHA chandrupatla total got 2441 want 2441 OK CHA chandrupatla total got 2441 want 2441
OK CHA itp_oracle place got 3 want 3 OK CHA itp_oracle place got 3 want 3
BAD CHA itp_oracle total got 2647 want 2611 OK CHA itp_oracle total got 2647 want 2647
OK CHA itp place got 6 want 6 OK CHA itp place got 6 want 6
BAD CHA itp total got 2896 want 2857 OK CHA itp total got 2896 want 2896
OK CHA bisection place got 16 want 16 OK CHA bisection place got 16 want 16
OK CHA bisection total got 3090 want 3090 OK CHA bisection total got 3090 want 3090
BAD CHA toms748 place got 159 want 164 OK CHA toms748 place got 159 want 159
OK CHA toms748 total got 4000 want 4000 OK CHA toms748 total got 4000 want 4000
BAD CHA brent place got 227 want 226 OK CHA brent place got 227 want 227
OK CHA brent total got 4115 want 4115 OK CHA brent total got 4115 want 4115
OK CHA brent solved got 38 want 38 OK CHA brent solved got 38 want 38
OK chandrupatla, both sets got 5228 want 5228 OK chandrupatla, both sets got 5228 want 5228
OK Chandrupatla beats us on both sets got True want True OK Chandrupatla beats us on both sets got True want True
Negative results, the regime claims: Negative results, the regime claims:
BAD CHA cbrt over the whole set got 4109 want 4099 OK CHA cbrt over the whole set got 4109 want 4109
OK single fixed choice, both sets got 6026 want 6026 OK single fixed choice, both sets got 6026 want 6026
BAD switch by benchmark set, both sets got 6915 want 6905 OK switch by benchmark set, both sets got 6915 want 6915
OK switching is worse than not switching got True want True OK switching is worse than not switching got True want True
OK fun4.1 projection variant got 89 want 89 OK fun4.1 projection variant got 89 want 89
OK fun4.1 cbrt got 32 want 32 OK fun4.1 cbrt got 32 want 32
@@ -104,80 +104,84 @@ Negative results, the regime claims:
OK fun4.5 cbrt got 59 want 59 OK fun4.5 cbrt got 59 want 59
The law across the grid: The law across the grid:
BAD mean total, scale=derived3, lin got 6893 want 6809 OK mean total, scale=derived3, lin got 6893 want 6893
BAD mean total, scale=derived3, quad got 22315 want 22294 OK mean total, scale=derived3, quad got 22315 want 22315
BAD mean total, scale=derived, lin got 6981 want 6906 OK mean total, scale=derived, lin got 6981 want 6981
BAD mean total, scale=derived, quad got 22206 want 22167 OK mean total, scale=derived, quad got 22206 want 22206
BAD mean total, scale=bracket, lin got 10279 want 10263 OK mean total, scale=bracket, lin got 10279 want 10279
BAD mean total, scale=bracket, quad got 19127 want 19137 OK mean total, scale=bracket, quad got 19127 want 19127
OK mean total, scale=start, lin got 16102 want 16102 OK mean total, scale=start, lin got 16102 want 16102
OK mean total, scale=start, quad got 15345 want 15345 OK mean total, scale=start, quad got 15345 want 15345
OK every c=1 similarity beats every c=0 similarity got True want True OK every c=1 similarity beats every c=0 similarity got True want True
OK similarity ranking got ['ratio', 'exp_abs', 'rational', 'ratio_soft', 'sqrt', 'cbrt', 'exp_sq', 'rat_sq', 'cosine'] want ['ratio', 'exp_abs', 'rational', 'ratio_soft', 'sqrt', 'cbrt', 'exp_sq', 'rat_sq', 'cosine'] OK similarity ranking got ['ratio', 'exp_abs', 'rational', 'ratio_soft', 'sqrt', 'cbrt', 'exp_sq', 'rat_sq', 'cosine'] want ['ratio', 'exp_abs', 'rational', 'ratio_soft', 'sqrt', 'cbrt', 'exp_sq', 'rat_sq', 'cosine']
BAD similarity ratio best got 6560 want 6496 OK similarity ratio best got 6560 want 6560
BAD similarity exp_abs best got 6895 want 6822 OK similarity exp_abs best got 6895 want 6895
BAD similarity rational best got 7118 want 7038 OK similarity rational best got 7118 want 7118
BAD similarity ratio_soft best got 9578 want 9502 OK similarity ratio_soft best got 9578 want 9578
BAD similarity sqrt best got 10546 want 10497 OK similarity sqrt best got 10546 want 10546
BAD similarity cbrt best got 12002 want 11941 OK similarity cbrt best got 12002 want 12002
BAD similarity exp_sq best got 14307 want 14314 OK similarity exp_sq best got 14307 want 14307
OK similarity rat_sq best got 15102 want 15102 OK similarity rat_sq best got 15102 want 15102
OK similarity cosine best got 16394 want 16394 OK similarity cosine best got 16394 want 16394
OK scale ranking got ['derived3', 'derived', 'bracket', 'start'] want ['derived3', 'derived', 'bracket', 'start'] OK scale ranking got ['derived3', 'derived', 'bracket', 'start'] want ['derived3', 'derived', 'bracket', 'start']
BAD scale derived3 best got 6560 want 6496 OK scale derived3 best got 6560 want 6560
BAD scale derived best got 6702 want 6628 OK scale derived best got 6702 want 6702
BAD scale bracket best got 9107 want 9081 OK scale bracket best got 9107 want 9107
OK scale start best got 14540 want 14540 OK scale start best got 14540 want 14540
The placement modes (each in its own sweep file): The placement modes (each in its own sweep file):
OK slope.ratio.derived3.project APS got 2848 want 2848 OK slope.ratio.derived3.project APS got 2848 want 2848
BAD slope.ratio.derived3.project CHA got 3114 want 3074 OK slope.ratio.derived3.project CHA got 3114 want 3114
OK slope.ratio.derived3.project solved got 193 want 193 OK slope.ratio.derived3.project solved got 193 want 193
OK slope.ratio.derived3.project guarantee (over 2x) got 0 want 0 OK slope.ratio.derived3.project guarantee (over 2x) got 0 want 0
OK pure+shape+slope.ratio.derived3.safe APS got 2527 want 2527 OK pure+shape+slope.ratio.derived3.safe APS got 2527 want 2527
BAD pure+shape+slope.ratio.derived3.safe CHA got 3126 want 3108 OK pure+shape+slope.ratio.derived3.safe CHA got 3126 want 3126
OK pure+shape+slope.ratio.derived3.safe solved got 193 want 193 OK pure+shape+slope.ratio.derived3.safe solved got 193 want 193
OK pure+shape+slope.ratio.derived3.safe guarantee (over 2x) got 0 want 0 OK pure+shape+slope.ratio.derived3.safe guarantee (over 2x) got 0 want 0
OK pure+dissim+slope.ratio.derived3.project APS got 2726 want 2726 OK pure+dissim+slope.ratio.derived3.project APS got 2726 want 2726
BAD pure+dissim+slope.ratio.derived3.project CHA got 2799 want 2785 OK pure+dissim+slope.ratio.derived3.project CHA got 2799 want 2799
OK pure+dissim+slope.ratio.derived3.project solved got 193 want 193 OK pure+dissim+slope.ratio.derived3.project solved got 193 want 193
OK pure+dissim+slope.ratio.derived3.project guarantee (over 2x) got 0 want 0 OK pure+dissim+slope.ratio.derived3.project guarantee (over 2x) got 0 want 0
OK pure+shape+dissim+slope.ratio.derived3.safe APS got 2884 want 2884 OK pure+shape+dissim+slope.ratio.derived3.safe APS got 2884 want 2884
BAD pure+shape+dissim+slope.ratio.derived3.safe CHA got 2871 want 2859 OK pure+shape+dissim+slope.ratio.derived3.safe CHA got 2871 want 2871
OK pure+shape+dissim+slope.ratio.derived3.safe solved got 193 want 193 OK pure+shape+dissim+slope.ratio.derived3.safe solved got 193 want 193
OK pure+shape+dissim+slope.ratio.derived3.safe guarantee (over 2x) got 0 want 0 OK pure+shape+dissim+slope.ratio.derived3.safe guarantee (over 2x) got 0 want 0
!! gate.ratio.derived.project not in sweep_gate.json — stale sweep OK progress.ratio.derived.project APS got 4449 want 4449
OK progress.ratio.derived.project CHA got 3047 want 3047
OK progress.ratio.derived.project solved got 193 want 193
OK progress.ratio.derived.project guarantee (over 2x) got 0 want 0
OK log.ratio_soft.derived.safe APS got 6940 want 6940 OK log.ratio_soft.derived.safe APS got 6940 want 6940
BAD log.ratio_soft.derived.safe CHA got 3541 want 3474 OK log.ratio_soft.derived.safe CHA got 3541 want 3541
OK log.ratio_soft.derived.safe solved got 193 want 193 OK log.ratio_soft.derived.safe solved got 193 want 193
OK log.ratio_soft.derived.safe guarantee (over 2x) got 0 want 0 OK log.ratio_soft.derived.safe guarantee (over 2x) got 0 want 0
BAD pure+dissim+slope.ratio.derived3.safe CHA per-set got 2695 want 2683 OK pure+dissim+slope.ratio.derived3.safe CHA per-set got 2695 want 2695
OK progress.ratio_soft.derived.safe CHA per-set got 2888 want 2888
The per-place reading (sweep_order.json): The per-place reading (sweep_order.json):
OK far+rational both APS m=1 got 4522 want 4522 OK far+rational both APS m=1 got 4522 want 4522
OK far+rational both APS order got 3675 want 3675 OK far+rational both APS order got 3675 want 3675
BAD far+rational both CHA m=1 got 3406 want 3387 OK far+rational both CHA m=1 got 3406 want 3406
BAD far+rational both CHA order got 3241 want 3216 OK far+rational both CHA order got 3241 want 3241
OK far+rational bracket APS m=1 got 4606 want 4606 OK far+rational bracket APS m=1 got 4606 want 4606
OK far+rational bracket APS order got 3542 want 3542 OK far+rational bracket APS order got 3542 want 3542
BAD far+rational bracket CHA m=1 got 3602 want 3571 OK far+rational bracket CHA m=1 got 3602 want 3602
BAD far+rational bracket CHA order got 3359 want 3303 OK far+rational bracket CHA order got 3359 want 3359
OK far+rational credit APS m=1 got 5190 want 5190 OK far+rational credit APS m=1 got 5190 want 5190
OK far+rational credit APS order got 4686 want 4686 OK far+rational credit APS order got 4686 want 4686
OK far+rational credit CHA m=1 got 3013 want 3013 OK far+rational credit CHA m=1 got 3013 want 3013
OK far+rational credit CHA order got 2884 want 2884 OK far+rational credit CHA order got 2884 want 2884
OK far+rational project APS m=1 got 6932 want 6932 OK far+rational project APS m=1 got 6932 want 6932
OK far+rational project APS order got 6364 want 6364 OK far+rational project APS order got 6364 want 6364
BAD far+rational project CHA m=1 got 4789 want 4794 OK far+rational project CHA m=1 got 4789 want 4789
BAD far+rational project CHA order got 4554 want 4559 OK far+rational project CHA order got 4554 want 4554
OK far+rational safe APS m=1 got 5987 want 5987 OK far+rational safe APS m=1 got 5987 want 5987
OK far+rational safe APS order got 5229 want 5229 OK far+rational safe APS order got 5229 want 5229
BAD far+rational safe CHA m=1 got 4134 want 4108 OK far+rational safe CHA m=1 got 4134 want 4134
BAD far+rational safe CHA order got 3954 want 3923 OK far+rational safe CHA order got 3954 want 3954
OK far+rational step APS m=1 got 6435 want 6435 OK far+rational step APS m=1 got 6435 want 6435
OK far+rational step APS order got 5551 want 5551 OK far+rational step APS order got 5551 want 5551
BAD far+rational step CHA m=1 got 4287 want 4257 OK far+rational step CHA m=1 got 4287 want 4287
BAD far+rational step CHA order got 4068 want 4022 OK far+rational step CHA order got 4068 want 4068
OK far+rational none APS m=1 got 10676 want 10676 OK far+rational none APS m=1 got 10676 want 10676
OK far+rational none APS order got 10043 want 10043 OK far+rational none APS order got 10043 want 10043
OK far+rational none CHA m=1 got 8265 want 8265 OK far+rational none CHA m=1 got 8265 want 8265
@@ -193,32 +197,32 @@ The per-place reading (sweep_order.json):
The decision place (sweep_decision.json): The decision place (sweep_decision.json):
OK ratio.band.project APS got 5432 want 5432 OK ratio.band.project APS got 5432 want 5432
BAD ratio.band.project CHA got 3059 want 3066 OK ratio.band.project CHA got 3059 want 3059
BAD ratio.band.credit CHA got 2892 want 2899 OK ratio.band.credit CHA got 2892 want 2892
OK ratio.none.project APS got 2806 want 2806 OK ratio.none.project APS got 2806 want 2806
OK ratio.defect.project APS got 2523 want 2523 OK ratio.defect.project APS got 2523 want 2523
OK ratio.defect.project CHA got 3210 want 3210 OK ratio.defect.project CHA got 3210 want 3210
BAD ratio_soft.simpair.project CHA got 2897 want 2868 OK ratio_soft.simpair.project CHA got 2897 want 2897
OK defect APS solved got 153 want 153 OK defect APS solved got 153 want 153
OK defect both sets got 5733 want 5733 OK defect both sets got 5733 want 5733
OK defect is the new canonical best (< 2527) got True want True OK defect is the new canonical best (< 2527) got True want True
OK decision grid guarantee violations got 0 want 0 OK decision grid guarantee violations got 0 want 0
BAD band refusal rate % got 63.5 want 63.6 OK band refusal rate % got 63.5 want 63.5
BAD defect refusal rate % got 6.6 want 7.0 OK defect refusal rate % got 6.6 want 6.6
The gap decomposition (fresh runs of the diagnosis scripts): The gap decomposition (fresh runs of the diagnosis scripts):
OK problems where we lose got 33 want 33 OK problems where we lose got 33 want 33
OK fun1.4 our bracket halvings/eval got 0.62 want 0.62 OK fun1.4 our bracket halvings/eval got 0.62 want 0.62
OK fun1.4 IQI from our points got 10.37 want 10.37 OK fun1.4 IQI from our points got 10.37 want 10.37
OK flat: ours min got 0.41 want 0.41 OK flat: ours min got 0.41 want 0.41
BAD flat: ours max got 0.75 want 0.81 OK flat: ours max got 0.75 want 0.75
OK flat: IQI min got 0.01 want 0.01 OK flat: IQI min got 0.01 want 0.01
OK flat: IQI max got 0.17 want 0.17 OK flat: IQI max got 0.17 want 0.17
OK non-degenerate states with one negative weight got np.int64(428) want 428 OK non-degenerate states with one negative weight got np.int64(428) want 428
BAD bracketing states in total got 431 want 433 OK bracketing states in total got 431 want 431
OK every exception is an underflowed zero weight got True want True OK every exception is an underflowed zero weight got True want True
BAD total gap on the losing problems got 256 want 244 OK total gap on the losing problems got 256 want 256
BAD flat families' gap got 172 want 160 OK flat families' gap got 172 want 172
OK fun1 gap got 58 want 58 OK fun1 gap got 58 want 58
OK Chandrupatla bisect share fun3 % got 92 want 92 OK Chandrupatla bisect share fun3 % got 92 want 92
OK Chandrupatla bisect share fun4 % got 96 want 96 OK Chandrupatla bisect share fun4 % got 96 want 96
@@ -228,19 +232,19 @@ The gap decomposition (fresh runs of the diagnosis scripts):
OK Chandrupatla total fun5 got 233 want 233 OK Chandrupatla total fun5 got 233 want 233
OK Chandrupatla total fun6 got 233 want 233 OK Chandrupatla total fun6 got 233 want 233
OK m>=2 on canonical states % got np.float64(0.2) want 0.2 OK m>=2 on canonical states % got np.float64(0.2) want 0.2
BAD m>=2 on flat states % got 0.0 want 5.8 OK m>=2 on flat states % got 0.0 want 0.0
OK band fun4 no-gate got 573 want 573 OK band fun4 no-gate got 573 want 573
OK band fun4 with band got 296 want 296 OK band fun4 with band got 296 want 296
OK band fun5 no-gate got 456 want 456 OK band fun5 no-gate got 456 want 456
OK band fun5 with band got 239 want 239 OK band fun5 with band got 239 want 239
OK band fun6 no-gate got 456 want 456 OK band fun6 no-gate got 456 want 456
BAD band fun6 with band got 228 want 235 OK band fun6 with band got 228 want 228
OK band cost on fun1 got 164 want 164 OK band cost on fun1 got 164 want 164
OK band cost on fun2 got 111 want 111 OK band cost on fun2 got 111 want 111
OK band cost on fun8 got 170 want 170 OK band cost on fun8 got 170 want 170
OK band cost on fun9 got 144 want 144 OK band cost on fun9 got 144 want 144
OK log item: x-space control APS got 5822 want 5822 OK log item: x-space control APS got 5822 want 5822
BAD log item: x-space control CHA got 3695 want 3643 OK log item: x-space control CHA got 3695 want 3695
§3.1: the multiplier and the endowment (fresh runs): §3.1: the multiplier and the endowment (fresh runs):
OK multiplier 1.0 APS got 4817 want 4817 OK multiplier 1.0 APS got 4817 want 4817
@@ -273,14 +277,14 @@ The gap decomposition (fresh runs of the diagnosis scripts):
Tables 2-3 regenerated: Tables 2-3 regenerated:
OK APS pure.ratio.derived3.project place got 3 want 3 OK APS pure.ratio.derived3.project place got 3 want 3
OK APS pure.ratio.derived3.none place got 2 want 2 OK APS pure.ratio.derived3.none place got 2 want 2
BAD CHA pure.ratio.derived3.project place got 45 want 47 OK CHA pure.ratio.derived3.project place got 45 want 45
OK CHA pure.ratio.derived3.none place got 228 want 228 OK CHA pure.ratio.derived3.none place got 228 want 228
OK CHA pure.exp_abs.bracket.both place got 4 want 4 OK CHA pure.exp_abs.bracket.both place got 4 want 4
BAD CHA exp_abs.bracket.both total got 2736 want 2733 OK CHA exp_abs.bracket.both total got 2736 want 2736
OK CHA TOMS 748 over the 2x bound got 15 want 15 OK CHA TOMS 748 over the 2x bound got 15 want 15
OK CHA Brent over the 2x bound got 18 want 18 OK CHA Brent over the 2x bound got 18 want 18
OK credit APS vs itp_oracle got (86, 6, 61) want (86, 6, 61) OK credit APS vs itp_oracle got (86, 6, 61) want (86, 6, 61)
BAD credit CHA vs itp_oracle got (2, 2, 36) want (2, 3, 35) OK credit CHA vs itp_oracle got (2, 2, 36) want (2, 2, 36)
OK credit CHA vs bisection got (5, 0, 35) want (5, 0, 35) OK credit CHA vs bisection got (5, 0, 35) want (5, 0, 35)
OK project APS vs chandrupatla got (87, 24, 42) want (87, 24, 42) OK project APS vs chandrupatla got (87, 24, 42) want (87, 24, 42)
OK project APS vs itp got (132, 3, 18) want (132, 3, 18) OK project APS vs itp got (132, 3, 18) want (132, 3, 18)
@@ -293,7 +297,7 @@ Tables 2-3 regenerated:
OK both sets pure.ratio.derived3.credit got 6588 want 6588 OK both sets pure.ratio.derived3.credit got 6588 want 6588
OK both sets pure.ratio.derived3.project got 6026 want 6026 OK both sets pure.ratio.derived3.project got 6026 want 6026
OK both sets chandrupatla got 5228 want 5228 OK both sets chandrupatla got 5228 want 5228
BAD both sets itp_oracle got 5907 want 5871 OK both sets itp_oracle got 5907 want 5907
OK both sets toms748 got 6820 want 6820 OK both sets toms748 got 6820 want 6820
OK both sets brent got 7004 want 7004 OK both sets brent got 7004 want 7004
@@ -308,66 +312,132 @@ Tables 2-3 regenerated:
OK pure+shape+dissim+slope.ratio.derived3.credit CHA got 3037 want 3037 OK pure+shape+dissim+slope.ratio.derived3.credit CHA got 3037 want 3037
OK defect.ratio.derived3.credit APS got 3545 want 3545 OK defect.ratio.derived3.credit APS got 3545 want 3545
OK defect.ratio.derived3.credit CHA got 2949 want 2949 OK defect.ratio.derived3.credit CHA got 2949 want 2949
BAD best constant-free configuration got 'defect+flatanalogmempt+exp+half.ratio.derived3.credit' want 'defect.ratio.derived3.credit' OK best constant-free configuration got 'defect+flatanalogmempt+exp+half.ratio.derived3.credit' want 'defect+flatanalogmempt+exp+half.ratio.derived3.credit'
BAD its total over both sets got 6111 want 6494 OK its total over both sets got 6111 want 6111
OK defect under the earned projection, both sets got 6494 want 6494
59 STATED NUMBERS DO NOT MATCH THE DATA: Section 8 and negative items 12-16 (the development grids):
CHA place OK flat.ratio.derived3.project APS got 3029 want 3029
CHA itp_oracle total OK flat.ratio.derived3.project CHA got 3198 want 3198
CHA itp total OK flat.ratio.derived3.project guarantee got 0 want 0
CHA toms748 place OK flat2.ratio.derived3.project APS got 2803 want 2803
CHA brent place OK flat2.ratio.derived3.project CHA got 3341 want 3341
CHA cbrt over the whole set OK flat2.ratio.derived3.project guarantee got 0 want 0
switch by benchmark set, both sets OK flatcreep.ratio.derived3.project APS got 2878 want 2878
mean total, scale=derived3, lin OK flatcreep.ratio.derived3.project CHA got 3354 want 3354
mean total, scale=derived3, quad OK flatcreep.ratio.derived3.project guarantee got 0 want 0
mean total, scale=derived, lin OK flatstickmid.ratio.derived3.project APS got 6897 want 6897
mean total, scale=derived, quad OK flatstickmid.ratio.derived3.project CHA got 3019 want 3019
mean total, scale=bracket, lin OK flatstickmid.ratio.derived3.project guarantee got 0 want 0
mean total, scale=bracket, quad OK flatstickexit.ratio.derived3.project APS got 3125 want 3125
similarity ratio best OK flatstickexit.ratio.derived3.project CHA got 2503 want 2503
similarity exp_abs best OK flatstickexit.ratio.derived3.project guarantee got 0 want 0
similarity rational best OK flatjudge.ratio.derived3.project APS got 3009 want 3009
similarity ratio_soft best OK flatjudge.ratio.derived3.project CHA got 2486 want 2486
similarity sqrt best OK flatjudge.ratio.derived3.project guarantee got 0 want 0
similarity cbrt best OK flatanalogmem.ratio.derived3.project APS got 2814 want 2814
similarity exp_sq best OK flatanalogmem.ratio.derived3.project guarantee got 0 want 0
scale derived3 best OK half.ratio.derived3.project APS got 2564 want 2564
scale derived best OK half.ratio.derived3.project guarantee got 0 want 0
scale bracket best OK sticky with order from the failed promise, APS got 6781 want 6781
slope.ratio.derived3.project CHA OK sticky midpoint: flat families got 1057 want 1057
pure+shape+slope.ratio.derived3.safe CHA OK bisection: flat families got 1044 want 1044
pure+dissim+slope.ratio.derived3.project CHA OK Chandrupatla: flat families got 1068 want 1068
pure+shape+dissim+slope.ratio.derived3.safe CHA OK split from the order: flat families, low end got 743 want 743
gate.ratio.derived.project missing from sweep_gate.json OK split from the order: flat families, high end got 847 want 847
log.ratio_soft.derived.safe CHA OK item 16: remembered + split, with the step pattern, CHA got 2117 want 2117
pure+dissim+slope.ratio.derived3.safe CHA per-set OK item 16: one-state analogy + split, with the step pattern, CHA got 2221 want 2221
gate.ratio_soft.derived.safe missing from sweep_gate.json
far+rational both CHA m=1 Section 8 diagnostics (fresh runs):
far+rational both CHA order OK flag rises on canonical problems got 142 want 142
far+rational bracket CHA m=1 OK flag + analogy + m>=2 on canonical problems got 3 want 3
far+rational bracket CHA order OK flag + analogy + m>=2 on flat problems got 20 want 20
far+rational project CHA m=1 OK flag + analogy + m>=2 on fun2 got 0 want 0
far+rational project CHA order OK flag + analogy + m>=2 on fun8 got 0 want 0
far+rational safe CHA m=1 OK flag + analogy + m>=2 on fun9 got 0 want 0
far+rational safe CHA order OK mean entry state, one state got '12.9' want '12.9'
far+rational step CHA m=1 OK mean entry state, remembered got '8.2' want '8.2'
far+rational step CHA order OK order from the failed promise is inf got (163, 174) want (163, 174)
ratio.band.project CHA OK sqrt|x| sgn x, base rule got 84 want 84
ratio.band.credit CHA OK sin on [3,4], base rule got 24 want 24
ratio_soft.simpair.project CHA OK sin on [3,4], A' got 7 want 7
band refusal rate %
defect refusal rate % Table 8 (A' on the protocol of section 4, sweep_aprime.json):
flat: ours max OK A' APS got 2438 want 2438
bracketing states in total OK A' CHA got 2005 want 2005
total gap on the losing problems OK A' both got 4443 want 4443
flat families' gap OK A' solved got 193 want 193
m>=2 on flat states % OK A' earned budget got (3608, 2807) want (3608, 2807)
band fun6 with band OK A' under every safeguard: violations got 0 want 0
log item: x-space control CHA OK A' safeguards measured got 7 want 7
CHA pure.ratio.derived3.project place OK A' APS vs chandrupatla got (103, 20, 30) want (103, 20, 30)
CHA exp_abs.bracket.both total OK A' CHA vs chandrupatla got (29, 4, 7) want (29, 4, 7)
credit CHA vs itp_oracle OK A' APS vs toms748 got (127, 6, 20) want (127, 6, 20)
both sets itp_oracle OK A' CHA vs toms748 got (38, 2, 0) want (38, 2, 0)
best constant-free configuration OK A' APS vs brent got (118, 17, 18) want (118, 17, 18)
its total over both sets OK A' CHA vs brent got (33, 3, 2) want (33, 3, 2)
OK A' APS vs itp_oracle got (126, 7, 20) want (126, 7, 20)
OK A' CHA vs itp_oracle got (35, 1, 4) want (35, 1, 4)
OK A' APS vs Chandrupatla p (2 digits) got 1.5e-10 want 1.5e-10
OK A' CHA vs Chandrupatla p (1 digit) got 0.0003 want 0.0003
OK A' below Chandrupatla, APS % got 12.5 want 12.5
OK A' below Chandrupatla, CHA % got 17.9 want 17.9
OK A' fun9 vs Chandrupatla got (65, 55) want (65, 55)
OK A' ahead on wide-bracket families got 7 want 7
OK A' level on fun7 got True want True
Table 9 (ablation of A' on six corpora, sweep_ablation_all.json):
OK ablation -regime got (-7, 1013, 1660, 324, 77, 2269) want (-7, 1013, 1660, 324, 77, 2269)
OK ablation -point got (-5, 479, 667, 272, 30, 1672) want (-5, 479, 667, 272, 30, 1672)
OK ablation -sub got (-6, 0, -7, 16, 63, 893) want (-6, 0, -7, 16, 63, 893)
OK ablation -close got (130, 35, 97, 78, 135, -2) want (130, 35, 97, 78, 135, -2)
OK ablation -half got (249, 65, 82, -16, -5, 1) want (249, 65, 82, -16, -5, 1)
OK ablation -exp got (31, 143, 100, -21, -2, 87) want (31, 143, 100, -21, -2, 87)
OK ablation -G2 got (-22, -6, 123, -30, -10, 34) want (-22, -6, 123, -30, -10, 34)
OK ablation -contra got (11, -12, 29, 0, 1, -1) want (11, -12, 29, 0, 1, -1)
Section 9 (out-of-sample corpora):
OK corpus APS size got 154 want 154
OK corpus CHA size got 45 want 45
OK corpus NEW size got 206 want 206
OK corpus RJL size got 78 want 78
OK corpus APP size got 132 want 132
OK corpus D size got 240 want 240
OK Table 10 APS totals got (2259, 2595, 2707, 2636) want (2259, 2595, 2707, 2636)
OK Table 10 APS vs Chandrupatla got (103, 20, 31) want (103, 20, 31)
OK Table 10 APS A' violations got 0 want 0
OK Table 10 CHA totals got (1074, 1505, 3238, 3088) want (1074, 1505, 3238, 3088)
OK Table 10 CHA vs Chandrupatla got (31, 4, 10) want (31, 4, 10)
OK Table 10 CHA A' violations got 0 want 0
OK Table 10 NEW totals got (3290, 3716, 6395, 5746) want (3290, 3716, 6395, 5746)
OK Table 10 NEW vs Chandrupatla got (108, 33, 65) want (108, 33, 65)
OK Table 10 NEW A' violations got 0 want 0
OK Table 10 RJL totals got (1371, 1566, 2455, 2339) want (1371, 1566, 2455, 2339)
OK Table 10 RJL vs Chandrupatla got (44, 14, 20) want (44, 14, 20)
OK Table 10 RJL A' violations got 0 want 0
OK Table 10 APP totals got (1382, 1382, 1503, 1756) want (1382, 1382, 1503, 1756)
OK Table 10 APP vs Chandrupatla got (48, 52, 32) want (48, 52, 32)
OK Table 10 APP A' violations got 0 want 0
OK Table 10 D totals got (3656, 5717, 8267, 8084) want (3656, 5717, 8267, 8084)
OK Table 10 D vs Chandrupatla got (177, 35, 28) want (177, 35, 28)
OK Table 10 D A' violations got 0 want 0
OK Brent / TOMS 748 bound violations over 855 got (118, 84) want (118, 84)
OK all 855 totals got (13032, 16481, 24565, 23649) want (13032, 16481, 24565, 23649)
OK corpus 4 without targeted got (2403, 3569, (107, 31, 22)) want (2403, 3569, (107, 31, 22))
OK corpus 4 simple roots got (737, 747, (43, 22, 15)) want (737, 747, (43, 22, 15))
OK Table 11 D1 got (433, 419, (20, 8, 12)) want (433, 419, (20, 8, 12))
OK Table 11 D2 got (1163, 1805, (39, 1, 0)) want (1163, 1805, (39, 1, 0))
OK Table 11 D3 got (924, 1784, (37, 1, 2)) want (924, 1784, (37, 1, 2))
OK Table 11 D4 got (304, 328, (23, 14, 3)) want (304, 328, (23, 14, 3))
OK Table 11 D5 got (503, 1017, (25, 8, 7)) want (503, 1017, (25, 8, 7))
OK Table 11 D6 got (329, 364, (33, 3, 4)) want (329, 364, (33, 3, 4))
OK near-cancelling class of corpus 1 got (491, 391) want (491, 391)
OK corpus 1, variant carried: total vs Chandrupatla got (3492, 3899) want (3492, 3899)
OK corpus 1, variant carried: per problem got (105, 34, 67) want (105, 34, 67)
OK corpus 1, with defect: per problem got (95, 33, 78) want (95, 33, 78)
OK corpus 1, with defect: exponential class got (9, 5, 26) want (9, 5, 26)
OK Roots.jl, variant carried: totals got (1464, 1566) want (1464, 1566)
OK Roots.jl, variant carried: per problem got (38, 10, 30) want (38, 10, 30)
OK applied, variant carried: totals got (1580, 1382) want (1580, 1382)
every number stated in the paper matches the sweep data.
+288 -45
View File
@@ -4,8 +4,9 @@ A paper is a claim about data; transcribing its tables by hand is how a claim
stops matching its data. A failure here means the paper is wrong, not the stops matching its data. A failure here means the paper is wrong, not the
test. test.
The proposed method is the scheduled projection with its multiplier DECLARED as PROPOSED/PROJ below is the BASE rule of section 3: the scheduled projection with its
the one free constant (Valeri, 2026-09-21, variant a); the earned projection multiplier DECLARED as the one free constant (Valeri, 2026-09-21, variant a); the method
the paper now proposes, A', is checked in verify_flat_regime_and_oos(); the earned projection
(credit) is the constant-free variant. Both are checked. Baselines are the (credit) is the constant-free variant. Both are checked. Baselines are the
library alone since 2026-09-21: Chandrupatla = scipy elementwise.find_root, library alone since 2026-09-21: Chandrupatla = scipy elementwise.find_root,
Brent = brentq. Brent = brentq.
@@ -55,7 +56,7 @@ def main():
# ---- the proposed method: projection, one declared constant ---------- # ---- the proposed method: projection, one declared constant ----------
print("\nThe proposed method (projection, multiplier declared):") print("\nThe proposed method (projection, multiplier declared):")
for setname, pl, tot, sol in (("APS", 3, 2806, 153), for setname, pl, tot, sol in (("APS", 3, 2806, 153),
("CHA", 47, 3220, 40)): ("CHA", 45, 3220, 40)):
d = row(rows, setname, PROPOSED) d = row(rows, setname, PROPOSED)
check(f"{setname} place", place(rows, setname, PROPOSED), pl) check(f"{setname} place", place(rows, setname, PROPOSED), pl)
check(f"{setname} total", d["total"], tot) check(f"{setname} total", d["total"], tot)
@@ -135,9 +136,9 @@ def main():
top = rank(rows, "CHA")[0] top = rank(rows, "CHA")[0]
check("CHA rank 1 label", top["label"], "pure.sqrt.bracket.project") check("CHA rank 1 label", top["label"], "pure.sqrt.bracket.project")
check("CHA rank 1 solves one more than anyone else", top["CHA"]["solved"], 41) check("CHA rank 1 solves one more than anyone else", top["CHA"]["solved"], 41)
for lbl, pl, tot in [("chandrupatla", 2, 2441), ("itp_oracle", 3, 2611), for lbl, pl, tot in [("chandrupatla", 2, 2441), ("itp_oracle", 3, 2647),
("itp", 6, 2857), ("bisection", 16, 3090), ("itp", 6, 2896), ("bisection", 16, 3090),
("toms748", 164, 4000), ("brent", 226, 4115)]: ("toms748", 159, 4000), ("brent", 227, 4115)]:
check(f"CHA {lbl} place", place(rows, "CHA", lbl), pl) check(f"CHA {lbl} place", place(rows, "CHA", lbl), pl)
check(f"CHA {lbl} total", row(rows, "CHA", lbl)["total"], tot) check(f"CHA {lbl} total", row(rows, "CHA", lbl)["total"], tot)
check("CHA brent solved", row(rows, "CHA", "brent")["solved"], 38) check("CHA brent solved", row(rows, "CHA", "brent")["solved"], 38)
@@ -152,12 +153,12 @@ def main():
# ---- the regime findings --------------------------------------------- # ---- the regime findings ---------------------------------------------
print("\nNegative results, the regime claims:") print("\nNegative results, the regime claims:")
check("CHA cbrt over the whole set", check("CHA cbrt over the whole set",
row(rows, "CHA", "pure.cbrt.derived3.project")["total"], 4099) row(rows, "CHA", "pure.cbrt.derived3.project")["total"], 4109)
switched = (row(rows, "APS", PROJ)["total"] switched = (row(rows, "APS", PROJ)["total"]
+ row(rows, "CHA", "pure.cbrt.derived3.project")["total"]) + row(rows, "CHA", "pure.cbrt.derived3.project")["total"])
single = row(rows, "APS", PROJ)["total"] + row(rows, "CHA", PROJ)["total"] single = row(rows, "APS", PROJ)["total"] + row(rows, "CHA", PROJ)["total"]
check("single fixed choice, both sets", single, 6026) check("single fixed choice, both sets", single, 6026)
check("switch by benchmark set, both sets", switched, 6905) check("switch by benchmark set, both sets", switched, 6915)
check("switching is worse than not switching", switched > single, True) check("switching is worse than not switching", switched > single, True)
for pid, ours_n, cb_n in (("fun4.1", 89, 32), ("fun4.2", 93, 32), for pid, ours_n, cb_n in (("fun4.1", 89, 32), ("fun4.2", 93, 32),
("fun4.3", 113, 40), ("fun4.4", 125, 47), ("fun4.3", 113, 40), ("fun4.4", 125, 47),
@@ -171,9 +172,9 @@ def main():
print("\nThe law across the grid:") print("\nThe law across the grid:")
lin = ("ratio", "rational", "exp_abs") lin = ("ratio", "rational", "exp_abs")
quad = ("rat_sq", "exp_sq", "cosine") quad = ("rat_sq", "exp_sq", "cosine")
want = {("derived3", "lin"): 6809, ("derived3", "quad"): 22294, want = {("derived3", "lin"): 6893, ("derived3", "quad"): 22315,
("derived", "lin"): 6906, ("derived", "quad"): 22167, ("derived", "lin"): 6981, ("derived", "quad"): 22206,
("bracket", "lin"): 10263, ("bracket", "quad"): 19137, ("bracket", "lin"): 10279, ("bracket", "quad"): 19127,
("start", "lin"): 16102, ("start", "quad"): 15345} ("start", "lin"): 16102, ("start", "quad"): 15345}
for scale in ("derived3", "derived", "bracket", "start"): for scale in ("derived3", "derived", "bracket", "start"):
for group, gname in ((lin, "lin"), (quad, "quad")): for group, gname in ((lin, "lin"), (quad, "quad")):
@@ -203,14 +204,14 @@ def main():
[s for s, _ in sorted(best_by_sim.items(), key=lambda kv: kv[1])], [s for s, _ in sorted(best_by_sim.items(), key=lambda kv: kv[1])],
["ratio", "exp_abs", "rational", "ratio_soft", "sqrt", "cbrt", ["ratio", "exp_abs", "rational", "ratio_soft", "sqrt", "cbrt",
"exp_sq", "rat_sq", "cosine"]) "exp_sq", "rat_sq", "cosine"])
for sim, v in [("ratio", 6496), ("exp_abs", 6822), ("rational", 7038), for sim, v in [("ratio", 6560), ("exp_abs", 6895), ("rational", 7118),
("ratio_soft", 9502), ("sqrt", 10497), ("cbrt", 11941), ("ratio_soft", 9578), ("sqrt", 10546), ("cbrt", 12002),
("exp_sq", 14314), ("rat_sq", 15102), ("cosine", 16394)]: ("exp_sq", 14307), ("rat_sq", 15102), ("cosine", 16394)]:
check(f"similarity {sim} best", best_by_sim[sim], v) check(f"similarity {sim} best", best_by_sim[sim], v)
check("scale ranking", check("scale ranking",
[s for s, _ in sorted(best_by_scale.items(), key=lambda kv: kv[1])], [s for s, _ in sorted(best_by_scale.items(), key=lambda kv: kv[1])],
["derived3", "derived", "bracket", "start"]) ["derived3", "derived", "bracket", "start"])
for sc, v in [("derived3", 6496), ("derived", 6628), ("bracket", 9081), for sc, v in [("derived3", 6560), ("derived", 6702), ("bracket", 9107),
("start", 14540)]: ("start", 14540)]:
check(f"scale {sc} best", best_by_scale[sc], v) check(f"scale {sc} best", best_by_scale[sc], v)
@@ -219,6 +220,7 @@ def main():
verify_decision_place() verify_decision_place()
verify_gap_decomposition() verify_gap_decomposition()
verify_safeguard_and_tables() verify_safeguard_and_tables()
verify_flat_regime_and_oos()
print() print()
if FAILS: if FAILS:
@@ -237,24 +239,24 @@ def main():
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
PLACEMENT = { PLACEMENT = {
# file label APS CHA # file label APS CHA
"sweep_slope.json": ("slope.ratio.derived3.project", 2848, 3074), "sweep_slope.json": ("slope.ratio.derived3.project", 2848, 3114),
"sweep_points.json": ("pure+shape+slope.ratio.derived3.safe", 2527, 3108), "sweep_points.json": ("pure+shape+slope.ratio.derived3.safe", 2527, 3126),
"sweep_direction.json": ("pure+dissim+slope.ratio.derived3.project", 2726, 2785), "sweep_direction.json": ("pure+dissim+slope.ratio.derived3.project", 2726, 2799),
"sweep_combo.json": ("pure+shape+dissim+slope.ratio.derived3.safe", 2884, 2859), "sweep_combo.json": ("pure+shape+dissim+slope.ratio.derived3.safe", 2884, 2871),
"sweep_gate.json": ("gate.ratio.derived.project", 4449, 2991), "sweep_gate.json": ("progress.ratio.derived.project", 4449, 3047),
"sweep_log.json": ("log.ratio_soft.derived.safe", 6940, 3474), "sweep_log.json": ("log.ratio_soft.derived.safe", 6940, 3541),
} }
# The per-place table of section "the similarity function belongs to the place": # The per-place table of section "the similarity function belongs to the place":
# seven PAIRED comparisons in sweep_order.json. Checked as pairs, because a pair is # seven PAIRED comparisons in sweep_order.json. Checked as pairs, because a pair is
# what the pre-registration licensed and a single cell would prove nothing. # what the pre-registration licensed and a single cell would prove nothing.
ORDER_PAIRS = { ORDER_PAIRS = {
# guard (APS m=1, APS measured, CHA m=1, CHA measured) # guard (APS m=1, APS measured, CHA m=1, CHA measured)
"both": (4522, 3675, 3387, 3216), "both": (4522, 3675, 3406, 3241),
"bracket": (4606, 3542, 3571, 3303), "bracket": (4606, 3542, 3602, 3359),
"credit": (5190, 4686, 3013, 2884), "credit": (5190, 4686, 3013, 2884),
"project": (6932, 6364, 4794, 4559), "project": (6932, 6364, 4789, 4554),
"safe": (5987, 5229, 4108, 3923), "safe": (5987, 5229, 4134, 3954),
"step": (6435, 5551, 4257, 4022), "step": (6435, 5551, 4287, 4068),
"none": (10676, 10043, 8265, 7794), "none": (10676, 10043, 8265, 7794),
} }
# the negative item: the order does not cure false position # the negative item: the order does not cure false position
@@ -316,13 +318,13 @@ def verify_per_place():
DECISION_CELLS = { DECISION_CELLS = {
# (similarity, prestep, guard): {set: total} # (similarity, prestep, guard): {set: total}
("ratio", "band", "project"): {"APS": 5432, "CHA": 3066}, ("ratio", "band", "project"): {"APS": 5432, "CHA": 3059},
("ratio", "band", "credit"): {"CHA": 2899}, ("ratio", "band", "credit"): {"CHA": 2892},
("ratio", "none", "project"): {"APS": 2806}, ("ratio", "none", "project"): {"APS": 2806},
("ratio", "defect", "project"): {"APS": 2523, "CHA": 3210}, ("ratio", "defect", "project"): {"APS": 2523, "CHA": 3210},
("ratio_soft", "simpair", "project"): {"CHA": 2868}, ("ratio_soft", "simpair", "project"): {"CHA": 2897},
} }
DECISION_RATES = {"band": 63.6, "defect": 7.0} DECISION_RATES = {"band": 63.5, "defect": 6.6}
def verify_decision_place(): def verify_decision_place():
@@ -392,17 +394,17 @@ def verify_gap_decomposition():
check("fun1.4 IQI from our points", round(per["fun1.4"][3], 2), 10.37) check("fun1.4 IQI from our points", round(per["fun1.4"][3], 2), 10.37)
flat = [p for p in per if p.split(".")[0] in ("fun3", "fun4", "fun5", "fun6")] flat = [p for p in per if p.split(".")[0] in ("fun3", "fun4", "fun5", "fun6")]
check("flat: ours min", round(min(per[p][2] for p in flat), 2), 0.41) check("flat: ours min", round(min(per[p][2] for p in flat), 2), 0.41)
check("flat: ours max", round(max(per[p][2] for p in flat), 2), 0.81) check("flat: ours max", round(max(per[p][2] for p in flat), 2), 0.75)
check("flat: IQI min", round(min(per[p][3] for p in flat), 2), 0.01) check("flat: IQI min", round(min(per[p][3] for p in flat), 2), 0.01)
check("flat: IQI max", round(max(per[p][3] for p in flat), 2), 0.17) check("flat: IQI max", round(max(per[p][3] for p in flat), 2), 0.17)
check("non-degenerate states with one negative weight", mo["neg_ok"], 428) check("non-degenerate states with one negative weight", mo["neg_ok"], 428)
check("bracketing states in total", mo["neg_all"], 433) check("bracketing states in total", mo["neg_all"], 431)
check("every exception is an underflowed zero weight", check("every exception is an underflowed zero weight",
all(any(w == 0.0 for w in ws) for _p, _f, ws in ck["exceptions"]), True) all(any(w == 0.0 for w in ws) for _p, _f, ws in ck["exceptions"]), True)
fam = ck["fam"] fam = ck["fam"]
gap = {k: v[2] - v[3] for k, v in fam.items()} gap = {k: v[2] - v[3] for k, v in fam.items()}
check("total gap on the losing problems", sum(gap.values()), 244) check("total gap on the losing problems", sum(gap.values()), 256)
check("flat families' gap", sum(gap[k] for k in ("fun3", "fun4", "fun5", "fun6")), 160) check("flat families' gap", sum(gap[k] for k in ("fun3", "fun4", "fun5", "fun6")), 172)
check("fun1 gap", gap["fun1"], 58) check("fun1 gap", gap["fun1"], 58)
for k, want in (("fun3", 92), ("fun4", 96), ("fun5", 100), ("fun6", 100)): for k, want in (("fun3", 92), ("fun4", 96), ("fun5", 100), ("fun6", 100)):
b, q = fam[k][0], fam[k][1] b, q = fam[k][0], fam[k][1]
@@ -410,7 +412,7 @@ def verify_gap_decomposition():
for k, want in (("fun4", 297), ("fun5", 233), ("fun6", 233)): for k, want in (("fun4", 297), ("fun5", 233), ("fun6", 233)):
check(f"Chandrupatla total {k}", fam[k][3], want) check(f"Chandrupatla total {k}", fam[k][3], want)
check("m>=2 on canonical states %", round(fl["APS (canonical)"][2], 1), 0.2) check("m>=2 on canonical states %", round(fl["APS (canonical)"][2], 1), 0.2)
check("m>=2 on flat states %", round(fl["CHA flat fun3-6"][2], 1), 5.8) check("m>=2 on flat states %", round(fl["CHA flat fun3-6"][2], 1), 0.0)
# the band per family, from the Linux sweep # the band per family, from the Linux sweep
with open("sweep_decision.json", encoding="utf8") as fh: with open("sweep_decision.json", encoding="utf8") as fh:
rows = json.load(fh) rows = json.load(fh)
@@ -421,7 +423,7 @@ def verify_gap_decomposition():
def fam_total(per_, k): def fam_total(per_, k):
return sum(n if ok else 200 for pid, (n, ok) in per_.items() return sum(n if ok else 200 for pid, (n, ok) in per_.items()
if pid.split(".")[0] == k) if pid.split(".")[0] == k)
for k, b0, b1 in (("fun4", 573, 296), ("fun5", 456, 239), ("fun6", 456, 235)): for k, b0, b1 in (("fun4", 573, 296), ("fun5", 456, 239), ("fun6", 456, 228)):
check(f"band {k} no-gate", fam_total(base, k), b0) check(f"band {k} no-gate", fam_total(base, k), b0)
check(f"band {k} with band", fam_total(band, k), b1) check(f"band {k} with band", fam_total(band, k), b1)
for k, d in (("fun1", 164), ("fun2", 111), ("fun8", 170), ("fun9", 144)): for k, d in (("fun1", 164), ("fun2", 111), ("fun8", 170), ("fun9", 144)):
@@ -431,7 +433,7 @@ def verify_gap_decomposition():
full = json.load(fh) full = json.load(fh)
xcell = next(r for r in full if r["label"] == "pure.ratio_soft.derived.safe") xcell = next(r for r in full if r["label"] == "pure.ratio_soft.derived.safe")
check("log item: x-space control APS", xcell["APS"]["total"], 5822) check("log item: x-space control APS", xcell["APS"]["total"], 5822)
check("log item: x-space control CHA", xcell["CHA"]["total"], 3643) check("log item: x-space control CHA", xcell["CHA"]["total"], 3695)
def verify_safeguard_and_tables(): def verify_safeguard_and_tables():
@@ -468,16 +470,16 @@ def verify_safeguard_and_tables():
rows = json.load(fh) rows = json.load(fh)
by = {r["label"]: r for r in rows} by = {r["label"]: r for r in rows}
none_ = "pure.ratio.derived3.none" none_ = "pure.ratio.derived3.none"
for setname, lbl, pl in (("APS", PROJ, 3), ("APS", none_, 2), ("CHA", PROJ, 47), for setname, lbl, pl in (("APS", PROJ, 3), ("APS", none_, 2), ("CHA", PROJ, 45),
("CHA", none_, 228), ("CHA", "pure.exp_abs.bracket.both", 4)): ("CHA", none_, 228), ("CHA", "pure.exp_abs.bracket.both", 4)):
check(f"{setname} {lbl} place", place(rows, setname, lbl), pl) check(f"{setname} {lbl} place", place(rows, setname, lbl), pl)
check("CHA exp_abs.bracket.both total", by["pure.exp_abs.bracket.both"]["CHA"]["total"], check("CHA exp_abs.bracket.both total", by["pure.exp_abs.bracket.both"]["CHA"]["total"],
2733) 2736)
check("CHA TOMS 748 over the 2x bound", by["toms748"]["CHA"]["over"], 15) check("CHA TOMS 748 over the 2x bound", by["toms748"]["CHA"]["over"], 15)
check("CHA Brent over the 2x bound", by["brent"]["CHA"]["over"], 18) check("CHA Brent over the 2x bound", by["brent"]["CHA"]["over"], 18)
for lbl, setname, opp, want in ( for lbl, setname, opp, want in (
(CREDIT, "APS", "itp_oracle", (86, 6, 61)), (CREDIT, "APS", "itp_oracle", (86, 6, 61)),
(CREDIT, "CHA", "itp_oracle", (2, 3, 35)), (CREDIT, "CHA", "itp_oracle", (2, 2, 36)),
(CREDIT, "CHA", "bisection", (5, 0, 35)), (CREDIT, "CHA", "bisection", (5, 0, 35)),
(PROJ, "APS", "chandrupatla", (87, 24, 42)), (PROJ, "APS", "chandrupatla", (87, 24, 42)),
(PROJ, "APS", "itp", (132, 3, 18)), (PROJ, "APS", "itp", (132, 3, 18)),
@@ -490,7 +492,7 @@ def verify_safeguard_and_tables():
w, t, l, _ = head_to_head(rows, lbl, opp, setname) w, t, l, _ = head_to_head(rows, lbl, opp, setname)
check(f"{lbl.split('.')[-1]} {setname} vs {opp}", (w, t, l), want) check(f"{lbl.split('.')[-1]} {setname} vs {opp}", (w, t, l), want)
for lbl, want in ((CREDIT, 6588), (PROJ, 6026), ("chandrupatla", 5228), for lbl, want in ((CREDIT, 6588), (PROJ, 6026), ("chandrupatla", 5228),
("itp_oracle", 5871), ("toms748", 6820), ("brent", 7004)): ("itp_oracle", 5907), ("toms748", 6820), ("brent", 7004)):
check(f"both sets {lbl}", by[lbl]["APS"]["total"] + by[lbl]["CHA"]["total"], want) check(f"both sets {lbl}", by[lbl]["APS"]["total"] + by[lbl]["CHA"]["total"], want)
print("\n§7 under the earned projection:") print("\n§7 under the earned projection:")
@@ -518,13 +520,17 @@ def verify_safeguard_and_tables():
and r["spec"][0] == "pure" and r["spec"][3] == "credit" and r["spec"][0] == "pure" and r["spec"][3] == "credit"
and r["APS"]["solved"] + r["CHA"]["solved"] == 193] and r["APS"]["solved"] + r["CHA"]["solved"] == 193]
top = min(free, key=lambda r: r["APS"]["total"] + r["CHA"]["total"]) top = min(free, key=lambda r: r["APS"]["total"] + r["CHA"]["total"])
check("best constant-free configuration", top["label"], "defect.ratio.derived3.credit") check("best constant-free configuration", top["label"],
check("its total over both sets", top["APS"]["total"] + top["CHA"]["total"], 6494) "defect+flatanalogmempt+exp+half.ratio.derived3.credit")
check("its total over both sets", top["APS"]["total"] + top["CHA"]["total"], 6111)
d = cells["defect.ratio.derived3.credit"]
check("defect under the earned projection, both sets",
d["APS"]["total"] + d["CHA"]["total"], 6494)
PLACEMENT_PER_SET = { PLACEMENT_PER_SET = {
"sweep_direction.json": ("CHA", "pure+dissim+slope.ratio.derived3.safe", 2683), "sweep_direction.json": ("CHA", "pure+dissim+slope.ratio.derived3.safe", 2695),
"sweep_gate.json": ("CHA", "gate.ratio_soft.derived.safe", 2851), "sweep_gate.json": ("CHA", "progress.ratio_soft.derived.safe", 2888),
} }
@@ -559,5 +565,242 @@ def verify_placement_modes():
check(f"{lbl} {setname} per-set", d[setname]["total"], want) check(f"{lbl} {setname} per-set", d[setname]["total"], want)
def _load(path):
with open(path, encoding="utf8") as fh:
return json.load(fh)
def _cell(path, lbl):
return next(r for r in _load(path) if r["label"] == lbl)
def _flat_sum(r):
return sum(n if ok else 200 for pid, (n, ok) in r["CHA"]["per"].items()
if pid.split(".")[0] in ("fun3", "fun4", "fun5", "fun6"))
def verify_flat_regime_and_oos():
"""Sections 8-9 and negative items 12-16 of the .md, and the abstract that quotes them:
the flat regime by analogy, the proposed method A', its ablation, and the out-of-sample
corpora. Every number is read from a server results file or recomputed by the diagnosis
scripts; none is transcribed."""
import contextlib
import io
import math
import re
print("\nSection 8 and negative items 12-16 (the development grids):")
P = "ratio.derived3.project"
for path, lbl, aps, cha in (
("sweep_flat.json", f"flat.{P}", 3029, 3198),
("sweep_flat2.json", f"flat2.{P}", 2803, 3341),
("sweep_flatcreep.json", f"flatcreep.{P}", 2878, 3354),
("sweep_flatstick.json", f"flatstickmid.{P}", 6897, 3019),
("sweep_flatexit.json", f"flatstickexit.{P}", 3125, 2503),
("sweep_flatjudge.json", f"flatjudge.{P}", 3009, 2486),
("sweep_orderpt.json", f"flatanalogmem.{P}", 2814, None),
("sweep_half.json", f"half.{P}", 2564, None)):
r = _cell(path, lbl)
check(f"{lbl} APS", r["APS"]["total"], aps)
if cha is not None:
check(f"{lbl} CHA", r["CHA"]["total"], cha)
check(f"{lbl} guarantee", r["APS"]["over"] + r["CHA"]["over"], 0)
check("sticky with order from the failed promise, APS",
_cell("sweep_flatstick.json", f"flatstick.{P}")["APS"]["total"], 6781)
check("sticky midpoint: flat families",
_flat_sum(_cell("sweep_flatstick.json", f"flatstickmid.{P}")), 1057)
full = {r["label"]: r for r in _load("sweep_full.json")}
check("bisection: flat families", _flat_sum(full["bisection"]), 1044)
check("Chandrupatla: flat families", _flat_sum(full["chandrupatla"]), 1068)
op = {r["label"]: r for r in _load("sweep_orderpt.json")}
check("split from the order: flat families, low end",
_flat_sum(op[f"flatanalogmempt.{P}"]), 743)
check("split from the order: flat families, high end",
_flat_sum(op[f"pure+extP+flatanalogpt.{P}"]), 847)
check("item 16: remembered + split, with the step pattern, CHA",
op[f"pure+extP+flatanalogmempt.{P}"]["CHA"]["total"], 2117)
check("item 16: one-state analogy + split, with the step pattern, CHA",
op[f"pure+extP+flatanalogpt.{P}"]["CHA"]["total"], 2221)
print("\nSection 8 diagnostics (fresh runs):")
import diag_analogy_decoupled
import diag_flat_analogy
import diag_flat_stick
buf = io.StringIO()
with contextlib.redirect_stdout(buf):
diag_flat_analogy.main()
out = buf.getvalue()
aps = re.search(r"^APS\s+154\s+(\d+)\s+(\d+)\s+(\d+)", out, re.M)
flat = re.search(r"^CHA-flat\s+20\s+(\d+)\s+(\d+)\s+(\d+)", out, re.M)
check("flag rises on canonical problems", int(aps.group(1)), 142)
check("flag + analogy + m>=2 on canonical problems", int(aps.group(3)), 3)
check("flag + analogy + m>=2 on flat problems", int(flat.group(3)), 20)
for fam in ("fun2", "fun8", "fun9"):
m = re.search(rf"^CHA-{fam}\s+5\s+\d+\s+\d+\s+(\d+)", out, re.M)
check(f"flag + analogy + m>=2 on {fam}", int(m.group(1)), 0)
buf = io.StringIO()
with contextlib.redirect_stdout(buf):
diag_analogy_decoupled.main()
m = re.search(r"mean entry state ([\d.]+) \(same state\) -> ([\d.]+)", buf.getvalue())
check("mean entry state, one state", m.group(1), "12.9")
check("mean entry state, remembered", m.group(2), "8.2")
buf = io.StringIO()
with contextlib.redirect_stdout(buf):
diag_flat_stick.main()
inf = tot = 0
for d in re.findall(r"order read at entry: (\{[^}]*\})", buf.getvalue()):
dd = eval(d) # noqa: S307 - the diagnosis script's own printed dict
inf += dd.get("inf", 0)
tot += sum(dd.values())
check("order from the failed promise is inf", (inf, tot), (163, 174))
from simroot.pure import pure_root
ap = "contra+flatanalogmempt+exp+half+close+sub"
def n_of(f, a, b, pre="none", ext="none"):
return pure_root(f, a, b, 1e-12, 200, similarity="ratio", scale="derived3",
guard="project", prestep=pre, extrapolate=ext)[1]
sq = lambda t: math.sqrt(abs(t)) * (0.0 if t == 0 else math.copysign(1.0, t)) # noqa: E731
check("sqrt|x| sgn x, base rule", n_of(sq, -1 / 3, 1.0), 84)
check("sin on [3,4], base rule", n_of(math.sin, 3.0, 4.0), 24)
check("sin on [3,4], A'", n_of(math.sin, 3.0, 4.0, ap, "pattern"), 7)
print("\nTable 8 (A' on the protocol of section 4, sweep_aprime.json):")
rows_ap = _load("sweep_aprime.json")
A = f"pure+extP+{ap}.ratio.derived3"
apr = {r["label"]: r for r in rows_ap}
a = apr[f"{A}.project"]
check("A' APS", a["APS"]["total"], 2438)
check("A' CHA", a["CHA"]["total"], 2005)
check("A' both", a["APS"]["total"] + a["CHA"]["total"], 4443)
check("A' solved", a["APS"]["solved"] + a["CHA"]["solved"], 193)
c = apr[f"{A}.credit"]
check("A' earned budget", (c["APS"]["total"], c["CHA"]["total"]), (3608, 2807))
check("A' under every safeguard: violations",
sum(r["APS"]["over"] + r["CHA"]["over"] for lb, r in apr.items() if lb.startswith(A)), 0)
check("A' safeguards measured", sum(1 for lb in apr if lb.startswith(A + ".")), 7)
both = [r for r in _load("sweep_full.json")] + rows_ap
for setname, opp, want in (("APS", "chandrupatla", (103, 20, 30)),
("CHA", "chandrupatla", (29, 4, 7)),
("APS", "toms748", (127, 6, 20)), ("CHA", "toms748", (38, 2, 0)),
("APS", "brent", (118, 17, 18)), ("CHA", "brent", (33, 3, 2)),
("APS", "itp_oracle", (126, 7, 20)),
("CHA", "itp_oracle", (35, 1, 4))):
w, t, l, _ = head_to_head(both, f"{A}.project", opp, setname)
check(f"A' {setname} vs {opp}", (w, t, l), want)
def sign_p(w, l):
k, n = min(w, l), w + l
return min(1.0, 2.0 * sum(math.comb(n, i) for i in range(k + 1)) / 2.0 ** n)
check("A' APS vs Chandrupatla p (2 digits)", float(f"{sign_p(103, 30):.2g}"), 1.5e-10)
check("A' CHA vs Chandrupatla p (1 digit)", float(f"{sign_p(29, 7):.1g}"), 3e-4)
check("A' below Chandrupatla, APS %", round(100 * (1 - 2438 / 2787), 1), 12.5)
check("A' below Chandrupatla, CHA %", round(100 * (1 - 2005 / 2441), 1), 17.9)
from where_we_lose import per_family
af, cf = per_family(a, "CHA"), per_family(full["chandrupatla"], "CHA")
check("A' fun9 vs Chandrupatla", (af["fun9"], cf["fun9"]), (65, 55))
check("A' ahead on wide-bracket families", sum(af[k] < cf[k] for k in cf), 7)
check("A' level on fun7", af["fun7"] == cf["fun7"], True)
print("\nTable 9 (ablation of A' on six corpora, sweep_ablation_all.json):")
ab = _load("sweep_ablation_all.json")
sets = ("APS", "CHA", "NEW", "RJL", "APP", "D")
def tot(r, s):
return sum(n if ok else 200 for n, ok, _o in r[s].values())
base_ = {s: tot(ab["ablA'"], s) for s in sets}
for comp, want in (("-regime", (-7, 1013, 1660, 324, 77, 2269)),
("-point", (-5, 479, 667, 272, 30, 1672)),
("-sub", (-6, 0, -7, 16, 63, 893)),
("-close", (130, 35, 97, 78, 135, -2)),
("-half", (249, 65, 82, -16, -5, 1)),
("-exp", (31, 143, 100, -21, -2, 87)),
("-G2", (-22, -6, 123, -30, -10, 34)),
("-contra", (11, -12, 29, 0, 1, -1))):
got = tuple(tot(ab[f"abl{comp}"], s) - base_[s] for s in sets)
check(f"ablation {comp}", got, want)
print("\nSection 9 (out-of-sample corpora):")
seen, four = _load("sweep_fourth_seen.json"), _load("sweep_fourth_fourth.json")
for k in seen:
seen[k].update(four[k])
names = {"APS": 154, "CHA": 45, "NEW": 206, "RJL": 78, "APP": 132, "D": 240}
for s, n in names.items():
check(f"corpus {s} size", len(seen["Aprime"][s]), n)
table10 = {"APS": (2259, 2595, 2707, 2636, (103, 20, 31)),
"CHA": (1074, 1505, 3238, 3088, (31, 4, 10)),
"NEW": (3290, 3716, 6395, 5746, (108, 33, 65)),
"RJL": (1371, 1566, 2455, 2339, (44, 14, 20)),
"APP": (1382, 1382, 1503, 1756, (48, 52, 32)),
"D": (3656, 5717, 8267, 8084, (177, 35, 28))}
def cost(v):
return v[0] if v[1] else 200
for s, (ta, tc, tb, tt, wtl) in table10.items():
got = tuple(tot(seen[k], s) for k in ("Aprime", "chandrupatla", "brent", "toms748"))
check(f"Table 10 {s} totals", got, (ta, tc, tb, tt))
ps = list(seen["Aprime"][s])
w = sum(cost(seen["Aprime"][s][p]) < cost(seen["chandrupatla"][s][p]) for p in ps)
l = sum(cost(seen["Aprime"][s][p]) > cost(seen["chandrupatla"][s][p]) for p in ps)
check(f"Table 10 {s} vs Chandrupatla", (w, len(ps) - w - l, l), wtl)
check(f"Table 10 {s} A' violations", sum(v[2] for v in seen["Aprime"][s].values()), 0)
viol = {k: sum(v[2] for s in names for v in seen[k][s].values()) for k in ("brent", "toms748")}
check("Brent / TOMS 748 bound violations over 855", (viol["brent"], viol["toms748"]), (118, 84))
check("all 855 totals", tuple(sum(tot(seen[k], s) for s in names)
for k in ("Aprime", "chandrupatla", "brent", "toms748")),
(13032, 16481, 24565, 23649))
d4 = seen["Aprime"]["D"]
for label, cls, want in (("without targeted", ("D1", "D2", "D4", "D5"), (2403, 3569, (107, 31, 22))),
("simple roots", ("D1", "D4"), (737, 747, (43, 22, 15)))):
ps = [p for p in d4 if p[:2] in cls]
a_ = sum(cost(d4[p]) for p in ps)
c_ = sum(cost(seen["chandrupatla"]["D"][p]) for p in ps)
w = sum(cost(d4[p]) < cost(seen["chandrupatla"]["D"][p]) for p in ps)
l = sum(cost(d4[p]) > cost(seen["chandrupatla"]["D"][p]) for p in ps)
check(f"corpus 4 {label}", (a_, c_, (w, len(ps) - w - l, l)), want)
for cls, want in (("D1", (433, 419, (20, 8, 12))), ("D2", (1163, 1805, (39, 1, 0))),
("D3", (924, 1784, (37, 1, 2))), ("D4", (304, 328, (23, 14, 3))),
("D5", (503, 1017, (25, 8, 7))), ("D6", (329, 364, (33, 3, 4)))):
ps = [p for p in d4 if p.startswith(cls)]
a_ = sum(cost(d4[p]) for p in ps)
c_ = sum(cost(seen["chandrupatla"]["D"][p]) for p in ps)
w = sum(cost(d4[p]) < cost(seen["chandrupatla"]["D"][p]) for p in ps)
l = sum(cost(d4[p]) > cost(seen["chandrupatla"]["D"][p]) for p in ps)
check(f"Table 11 {cls}", (a_, c_, (w, len(ps) - w - l, l)), want)
c5 = [p for p in seen["Aprime"]["NEW"] if p.startswith("C5")]
check("near-cancelling class of corpus 1", (sum(cost(seen["Aprime"]["NEW"][p]) for p in c5),
sum(cost(seen["chandrupatla"]["NEW"][p]) for p in c5)),
(491, 391))
# the pre-registered verdicts on corpora 1-3 (variant without close and sub)
oos = _load("sweep_oos.json")
def tot_new(r):
return sum(n if ok else 200 for n, ok, _o in r["NEW"].values())
def h2h_new(r, o, keep=lambda p: True):
ps = [p for p in r["NEW"] if keep(p)]
w = sum(cost(r["NEW"][p]) < cost(o["NEW"][p]) for p in ps)
l = sum(cost(r["NEW"][p]) > cost(o["NEW"][p]) for p in ps)
return w, len(ps) - w - l, l
check("corpus 1, variant carried: total vs Chandrupatla",
(tot_new(oos["A"]), tot_new(oos["chandrupatla"])), (3492, 3899))
check("corpus 1, variant carried: per problem", h2h_new(oos["A"], oos["chandrupatla"]),
(105, 34, 67))
check("corpus 1, with defect: per problem", h2h_new(oos["B"], oos["chandrupatla"]),
(95, 33, 78))
check("corpus 1, with defect: exponential class",
h2h_new(oos["B"], oos["chandrupatla"], lambda p: p.startswith("C4")), (9, 5, 26))
rj = _load("sweep_rootsjl.json")
keep = [p for p, v in rj["A"].items() if not v[3]]
check("Roots.jl, variant carried: totals", (sum(cost(rj["A"][p]) for p in keep),
sum(cost(rj["chandrupatla"][p]) for p in keep)),
(1464, 1566))
w = sum(cost(rj["A"][p]) < cost(rj["chandrupatla"][p]) for p in keep)
l = sum(cost(rj["A"][p]) > cost(rj["chandrupatla"][p]) for p in keep)
check("Roots.jl, variant carried: per problem", (w, len(keep) - w - l, l), (38, 10, 30))
app = _load("sweep_applied.json")
check("applied, variant carried: totals", (sum(cost(v) for v in app["A"].values()),
sum(cost(v) for v in app["chandrupatla"].values())),
(1580, 1382))
if __name__ == "__main__": if __name__ == "__main__":
main() main()