From 16b9ab87f1537c9c7e3b84dbd4c863ad83391f5a Mon Sep 17 00:00:00 2001 From: Valeri Sitnikov Date: Mon, 21 Sep 2026 20:56:58 +0100 Subject: [PATCH] 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 --- apply_article_frame.py | 155 +++++++++++++++++ apply_article_verifiable.py | 35 ++++ apply_verify_numbers.py | 78 +++++++++ article/sim_numerics.md | 37 +++- results_verify_article.txt | 306 ++++++++++++++++++++------------- verify_article.py | 333 +++++++++++++++++++++++++++++++----- 6 files changed, 772 insertions(+), 172 deletions(-) create mode 100644 apply_article_frame.py create mode 100644 apply_article_verifiable.py create mode 100644 apply_verify_numbers.py diff --git a/apply_article_frame.py b/apply_article_frame.py new file mode 100644 index 0000000..26aebb3 --- /dev/null +++ b/apply_article_frame.py @@ -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() diff --git a/apply_article_verifiable.py b/apply_article_verifiable.py new file mode 100644 index 0000000..6b0a22a --- /dev/null +++ b/apply_article_verifiable.py @@ -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() diff --git a/apply_verify_numbers.py b/apply_verify_numbers.py new file mode 100644 index 0000000..3e6cb76 --- /dev/null +++ b/apply_verify_numbers.py @@ -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() diff --git a/article/sim_numerics.md b/article/sim_numerics.md index 6b46b0b..1cf8f7c 100644 --- a/article/sim_numerics.md +++ b/article/sim_numerics.md @@ -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. -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 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 @@ -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. -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$: @@ -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. -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. @@ -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}$$ -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). @@ -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 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=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 with band got 296 want 296 OK band fun5 no-gate got 456 want 456 OK band fun5 with band got 239 want 239 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 fun2 got 111 want 111 OK band cost on fun8 got 170 want 170 OK band cost on fun9 got 144 want 144 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): 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: OK APS pure.ratio.derived3.project place got 3 want 3 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.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 Brent over the 2x bound got 18 want 18 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 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) @@ -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.project got 6026 want 6026 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 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 defect.ratio.derived3.credit APS got 3545 want 3545 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' - BAD its total over both sets got 6111 want 6494 + OK best constant-free configuration got 'defect+flatanalogmempt+exp+half.ratio.derived3.credit' want 'defect+flatanalogmempt+exp+half.ratio.derived3.credit' + 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: - CHA place - CHA itp_oracle total - CHA itp total - CHA toms748 place - CHA brent place - CHA cbrt over the whole set - switch by benchmark set, both sets - mean total, scale=derived3, lin - mean total, scale=derived3, quad - mean total, scale=derived, lin - mean total, scale=derived, quad - mean total, scale=bracket, lin - mean total, scale=bracket, quad - similarity ratio best - similarity exp_abs best - similarity rational best - similarity ratio_soft best - similarity sqrt best - similarity cbrt best - similarity exp_sq best - scale derived3 best - scale derived best - scale bracket best - slope.ratio.derived3.project CHA - pure+shape+slope.ratio.derived3.safe CHA - pure+dissim+slope.ratio.derived3.project CHA - pure+shape+dissim+slope.ratio.derived3.safe CHA - gate.ratio.derived.project missing from sweep_gate.json - log.ratio_soft.derived.safe CHA - pure+dissim+slope.ratio.derived3.safe CHA per-set - gate.ratio_soft.derived.safe missing from sweep_gate.json - far+rational both CHA m=1 - far+rational both CHA order - far+rational bracket CHA m=1 - far+rational bracket CHA order - far+rational project CHA m=1 - far+rational project CHA order - far+rational safe CHA m=1 - far+rational safe CHA order - far+rational step CHA m=1 - far+rational step CHA order - ratio.band.project CHA - ratio.band.credit CHA - ratio_soft.simpair.project CHA - band refusal rate % - defect refusal rate % - flat: ours max - bracketing states in total - total gap on the losing problems - flat families' gap - m>=2 on flat states % - band fun6 with band - log item: x-space control CHA - CHA pure.ratio.derived3.project place - CHA exp_abs.bracket.both total - credit CHA vs itp_oracle - both sets itp_oracle - best constant-free configuration - its total over both sets +Section 8 and negative items 12-16 (the development grids): + OK flat.ratio.derived3.project APS got 3029 want 3029 + OK flat.ratio.derived3.project CHA got 3198 want 3198 + OK flat.ratio.derived3.project guarantee got 0 want 0 + OK flat2.ratio.derived3.project APS got 2803 want 2803 + OK flat2.ratio.derived3.project CHA got 3341 want 3341 + OK flat2.ratio.derived3.project guarantee got 0 want 0 + OK flatcreep.ratio.derived3.project APS got 2878 want 2878 + OK flatcreep.ratio.derived3.project CHA got 3354 want 3354 + OK flatcreep.ratio.derived3.project guarantee got 0 want 0 + OK flatstickmid.ratio.derived3.project APS got 6897 want 6897 + OK flatstickmid.ratio.derived3.project CHA got 3019 want 3019 + OK flatstickmid.ratio.derived3.project guarantee got 0 want 0 + OK flatstickexit.ratio.derived3.project APS got 3125 want 3125 + OK flatstickexit.ratio.derived3.project CHA got 2503 want 2503 + OK flatstickexit.ratio.derived3.project guarantee got 0 want 0 + OK flatjudge.ratio.derived3.project APS got 3009 want 3009 + OK flatjudge.ratio.derived3.project CHA got 2486 want 2486 + OK flatjudge.ratio.derived3.project guarantee got 0 want 0 + OK flatanalogmem.ratio.derived3.project APS got 2814 want 2814 + OK flatanalogmem.ratio.derived3.project guarantee got 0 want 0 + OK half.ratio.derived3.project APS got 2564 want 2564 + OK half.ratio.derived3.project guarantee got 0 want 0 + OK sticky with order from the failed promise, APS got 6781 want 6781 + OK sticky midpoint: flat families got 1057 want 1057 + OK bisection: flat families got 1044 want 1044 + OK Chandrupatla: flat families got 1068 want 1068 + OK split from the order: flat families, low end got 743 want 743 + OK split from the order: flat families, high end got 847 want 847 + OK item 16: remembered + split, with the step pattern, CHA got 2117 want 2117 + OK item 16: one-state analogy + split, with the step pattern, CHA got 2221 want 2221 + +Section 8 diagnostics (fresh runs): + OK flag rises on canonical problems got 142 want 142 + OK flag + analogy + m>=2 on canonical problems got 3 want 3 + OK flag + analogy + m>=2 on flat problems got 20 want 20 + OK flag + analogy + m>=2 on fun2 got 0 want 0 + OK flag + analogy + m>=2 on fun8 got 0 want 0 + OK flag + analogy + m>=2 on fun9 got 0 want 0 + OK mean entry state, one state got '12.9' want '12.9' + OK mean entry state, remembered got '8.2' want '8.2' + OK order from the failed promise is inf got (163, 174) want (163, 174) + OK sqrt|x| sgn x, base rule got 84 want 84 + OK sin on [3,4], base rule got 24 want 24 + OK sin on [3,4], A' got 7 want 7 + +Table 8 (A' on the protocol of section 4, sweep_aprime.json): + OK A' APS got 2438 want 2438 + OK A' CHA got 2005 want 2005 + OK A' both got 4443 want 4443 + OK A' solved got 193 want 193 + OK A' earned budget got (3608, 2807) want (3608, 2807) + OK A' under every safeguard: violations got 0 want 0 + OK A' safeguards measured got 7 want 7 + OK A' APS vs chandrupatla got (103, 20, 30) want (103, 20, 30) + OK A' CHA vs chandrupatla got (29, 4, 7) want (29, 4, 7) + OK A' APS vs toms748 got (127, 6, 20) want (127, 6, 20) + OK A' CHA vs toms748 got (38, 2, 0) want (38, 2, 0) + OK A' APS vs brent got (118, 17, 18) want (118, 17, 18) + 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. diff --git a/verify_article.py b/verify_article.py index 08229ce..34480fb 100644 --- a/verify_article.py +++ b/verify_article.py @@ -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 test. -The proposed method is the scheduled projection with its multiplier DECLARED as -the one free constant (Valeri, 2026-09-21, variant a); the earned projection +PROPOSED/PROJ below is the BASE rule of section 3: the scheduled projection with its +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 library alone since 2026-09-21: Chandrupatla = scipy elementwise.find_root, Brent = brentq. @@ -55,7 +56,7 @@ def main(): # ---- the proposed method: projection, one declared constant ---------- print("\nThe proposed method (projection, multiplier declared):") for setname, pl, tot, sol in (("APS", 3, 2806, 153), - ("CHA", 47, 3220, 40)): + ("CHA", 45, 3220, 40)): d = row(rows, setname, PROPOSED) check(f"{setname} place", place(rows, setname, PROPOSED), pl) check(f"{setname} total", d["total"], tot) @@ -135,9 +136,9 @@ def main(): top = rank(rows, "CHA")[0] 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) - for lbl, pl, tot in [("chandrupatla", 2, 2441), ("itp_oracle", 3, 2611), - ("itp", 6, 2857), ("bisection", 16, 3090), - ("toms748", 164, 4000), ("brent", 226, 4115)]: + for lbl, pl, tot in [("chandrupatla", 2, 2441), ("itp_oracle", 3, 2647), + ("itp", 6, 2896), ("bisection", 16, 3090), + ("toms748", 159, 4000), ("brent", 227, 4115)]: check(f"CHA {lbl} place", place(rows, "CHA", lbl), pl) check(f"CHA {lbl} total", row(rows, "CHA", lbl)["total"], tot) check("CHA brent solved", row(rows, "CHA", "brent")["solved"], 38) @@ -152,12 +153,12 @@ def main(): # ---- the regime findings --------------------------------------------- print("\nNegative results, the regime claims:") 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"] + row(rows, "CHA", "pure.cbrt.derived3.project")["total"]) single = row(rows, "APS", PROJ)["total"] + row(rows, "CHA", PROJ)["total"] 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) for pid, ours_n, cb_n in (("fun4.1", 89, 32), ("fun4.2", 93, 32), ("fun4.3", 113, 40), ("fun4.4", 125, 47), @@ -171,9 +172,9 @@ def main(): print("\nThe law across the grid:") lin = ("ratio", "rational", "exp_abs") quad = ("rat_sq", "exp_sq", "cosine") - want = {("derived3", "lin"): 6809, ("derived3", "quad"): 22294, - ("derived", "lin"): 6906, ("derived", "quad"): 22167, - ("bracket", "lin"): 10263, ("bracket", "quad"): 19137, + want = {("derived3", "lin"): 6893, ("derived3", "quad"): 22315, + ("derived", "lin"): 6981, ("derived", "quad"): 22206, + ("bracket", "lin"): 10279, ("bracket", "quad"): 19127, ("start", "lin"): 16102, ("start", "quad"): 15345} for scale in ("derived3", "derived", "bracket", "start"): 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])], ["ratio", "exp_abs", "rational", "ratio_soft", "sqrt", "cbrt", "exp_sq", "rat_sq", "cosine"]) - for sim, v in [("ratio", 6496), ("exp_abs", 6822), ("rational", 7038), - ("ratio_soft", 9502), ("sqrt", 10497), ("cbrt", 11941), - ("exp_sq", 14314), ("rat_sq", 15102), ("cosine", 16394)]: + for sim, v in [("ratio", 6560), ("exp_abs", 6895), ("rational", 7118), + ("ratio_soft", 9578), ("sqrt", 10546), ("cbrt", 12002), + ("exp_sq", 14307), ("rat_sq", 15102), ("cosine", 16394)]: check(f"similarity {sim} best", best_by_sim[sim], v) check("scale ranking", [s for s, _ in sorted(best_by_scale.items(), key=lambda kv: kv[1])], ["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)]: check(f"scale {sc} best", best_by_scale[sc], v) @@ -219,6 +220,7 @@ def main(): verify_decision_place() verify_gap_decomposition() verify_safeguard_and_tables() + verify_flat_regime_and_oos() print() if FAILS: @@ -237,24 +239,24 @@ def main(): # -------------------------------------------------------------------------- PLACEMENT = { # file label APS CHA - "sweep_slope.json": ("slope.ratio.derived3.project", 2848, 3074), - "sweep_points.json": ("pure+shape+slope.ratio.derived3.safe", 2527, 3108), - "sweep_direction.json": ("pure+dissim+slope.ratio.derived3.project", 2726, 2785), - "sweep_combo.json": ("pure+shape+dissim+slope.ratio.derived3.safe", 2884, 2859), - "sweep_gate.json": ("gate.ratio.derived.project", 4449, 2991), - "sweep_log.json": ("log.ratio_soft.derived.safe", 6940, 3474), + "sweep_slope.json": ("slope.ratio.derived3.project", 2848, 3114), + "sweep_points.json": ("pure+shape+slope.ratio.derived3.safe", 2527, 3126), + "sweep_direction.json": ("pure+dissim+slope.ratio.derived3.project", 2726, 2799), + "sweep_combo.json": ("pure+shape+dissim+slope.ratio.derived3.safe", 2884, 2871), + "sweep_gate.json": ("progress.ratio.derived.project", 4449, 3047), + "sweep_log.json": ("log.ratio_soft.derived.safe", 6940, 3541), } # 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 # what the pre-registration licensed and a single cell would prove nothing. ORDER_PAIRS = { # guard (APS m=1, APS measured, CHA m=1, CHA measured) - "both": (4522, 3675, 3387, 3216), - "bracket": (4606, 3542, 3571, 3303), + "both": (4522, 3675, 3406, 3241), + "bracket": (4606, 3542, 3602, 3359), "credit": (5190, 4686, 3013, 2884), - "project": (6932, 6364, 4794, 4559), - "safe": (5987, 5229, 4108, 3923), - "step": (6435, 5551, 4257, 4022), + "project": (6932, 6364, 4789, 4554), + "safe": (5987, 5229, 4134, 3954), + "step": (6435, 5551, 4287, 4068), "none": (10676, 10043, 8265, 7794), } # the negative item: the order does not cure false position @@ -316,13 +318,13 @@ def verify_per_place(): DECISION_CELLS = { # (similarity, prestep, guard): {set: total} - ("ratio", "band", "project"): {"APS": 5432, "CHA": 3066}, - ("ratio", "band", "credit"): {"CHA": 2899}, + ("ratio", "band", "project"): {"APS": 5432, "CHA": 3059}, + ("ratio", "band", "credit"): {"CHA": 2892}, ("ratio", "none", "project"): {"APS": 2806}, ("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(): @@ -392,17 +394,17 @@ def verify_gap_decomposition(): 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")] 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 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("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", all(any(w == 0.0 for w in ws) for _p, _f, ws in ck["exceptions"]), True) fam = ck["fam"] gap = {k: v[2] - v[3] for k, v in fam.items()} - check("total gap on the losing problems", sum(gap.values()), 244) - check("flat families' gap", sum(gap[k] for k in ("fun3", "fun4", "fun5", "fun6")), 160) + 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")), 172) check("fun1 gap", gap["fun1"], 58) for k, want in (("fun3", 92), ("fun4", 96), ("fun5", 100), ("fun6", 100)): 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)): 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 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 with open("sweep_decision.json", encoding="utf8") as fh: rows = json.load(fh) @@ -421,7 +423,7 @@ def verify_gap_decomposition(): def fam_total(per_, k): return sum(n if ok else 200 for pid, (n, ok) in per_.items() 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} with band", fam_total(band, k), b1) for k, d in (("fun1", 164), ("fun2", 111), ("fun8", 170), ("fun9", 144)): @@ -431,7 +433,7 @@ def verify_gap_decomposition(): full = json.load(fh) 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 CHA", xcell["CHA"]["total"], 3643) + check("log item: x-space control CHA", xcell["CHA"]["total"], 3695) def verify_safeguard_and_tables(): @@ -468,16 +470,16 @@ def verify_safeguard_and_tables(): rows = json.load(fh) by = {r["label"]: r for r in rows} 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)): 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"], - 2733) + 2736) 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) for lbl, setname, opp, want in ( (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)), (PROJ, "APS", "chandrupatla", (87, 24, 42)), (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) check(f"{lbl.split('.')[-1]} {setname} vs {opp}", (w, t, l), want) 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) 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["APS"]["solved"] + r["CHA"]["solved"] == 193] top = min(free, key=lambda r: r["APS"]["total"] + r["CHA"]["total"]) - check("best constant-free configuration", top["label"], "defect.ratio.derived3.credit") - check("its total over both sets", top["APS"]["total"] + top["CHA"]["total"], 6494) + check("best constant-free configuration", top["label"], + "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 = { - "sweep_direction.json": ("CHA", "pure+dissim+slope.ratio.derived3.safe", 2683), - "sweep_gate.json": ("CHA", "gate.ratio_soft.derived.safe", 2851), + "sweep_direction.json": ("CHA", "pure+dissim+slope.ratio.derived3.safe", 2695), + "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) +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__": main()