Revision 1, step 1: one scoring criterion, the correct order, and the internal inconsistencies.
Point 1. The base step's order is Muller's 1.839, not 2: the derivative of the parabola through
the last three points errs by f'''/6 (x_n - x_{n-1})(x_n - x_{n-2}) = O(e_{n-1} e_{n-2}).
order_high_precision.py (3000 digits, to 1e-2900): 1.840 on cos x - x, e^x - 2, x^3 - x - 2,
sin x - 1/2; 2.000 only on x^2 - 2; two-point 1.618. The double-precision medians (2.000, 1.94)
are removed from the text.
Point 3. Every protocol number is re-scored under the criterion of section 9 - a sign change
within 1e-6 or f(x) == 0. rescore_uniform.py re-runs all 2779 distinct configurations of the 25
protocol sweeps on APS and CHA (the runs did not keep x) -> sweep_uniform.json, same row format;
it reproduces the APS/CHA lines of Table 10 exactly (built-in check). verify_article.py,
audit_similarity_places.py and the gap diagnostics read the re-scored data; the multiplier and
endowment measurements score by the same criterion. Table 7 (two criteria side by side) is gone;
7.3 now explains why the criterion is a sign change. Consequences stated in the text: the base
rule 2634 / 2357 against Chandrupatla 2595 / 1505 (1.5% behind on APS, no longer "level"); A'
2259 / 1074 (12.9% and 28.6% below Chandrupatla); the defect reading 2351 is second to the
shape reading 2337, not the record; the remembered analogy is level with no regime (2633 vs
2634) under this criterion; Table 9a's range is 19% to 425%.
Point 8. report_sweep.head_to_head counts every problem, failures charged (it counted only the
problems both methods solved, which is why Table 8 rows summed to 153 and 40). Family-level
comparisons added (A' vs Chandrupatla 8/1/6 of 15 and 7/0/2 of 9 families, not significant), and
an independence paragraph in section 9.
Point 11. sweep_itp.py: ITP (recommended constants and per-problem oracle) on all six corpora ->
Table 10; behind A' on every corpus, 0 bound violations.
Points 7, 9, 10 and the internals: the 2x bound is ours, not the rivals' promise; the law
predicts the group order only; "outside the proven bracket" explained (narrowest bracket of all
observed signs); 7.4's fun1 paragraph corrected (five costs under safe; the unguarded numbers
belong to fun1.4, fun1.5 and to fun3.1, fun5.1 separately); Table 1's last cell; the corpus-4
composition and odd multiplicities stated, also in the abstract.
build_tex.py: pdflatex output decoded with errors="replace" (a UTF-8 character cut by TeX's log
wrap crashed the build). Table 10 column widths rebalanced.
Checks: verify_article on the server 500 OK / 0 BAD (467 existing with the new values, 33 new);
regression x2 on the server 1232 passed, 0 failed; PDF 28 pages, 0 errors, 0 undefined, 0 overfull.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
"""Numbers the revised text needs beyond verify_article.py's existing checks, all under the
|
||||
paper's single criterion (sweep_uniform.json, sweep_fourth_*.json, sweep_itp.json), plus the
|
||||
two small fresh runs the re-scoring cannot supply. Run on Linux; stdout is kept as
|
||||
results_numbers_uniform.txt and every number quoted from it is checked by verify_article.py.
|
||||
|
||||
python -u numbers_uniform.py
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import math
|
||||
from collections import defaultdict
|
||||
|
||||
from rescore_uniform import load_uniform
|
||||
|
||||
PROJ = "pure.ratio.derived3.project"
|
||||
CREDIT = "pure.ratio.derived3.credit"
|
||||
APRIME = "pure+extP+contra+flatanalogmempt+exp+half+close+sub.ratio.derived3.project"
|
||||
|
||||
|
||||
def cost(v):
|
||||
return v[0] if v[1] else 200
|
||||
|
||||
|
||||
def sign_p(w, l):
|
||||
k, n = min(w, l), w + l
|
||||
return 1.0 if n == 0 else min(1.0, 2.0 * sum(math.comb(n, i) for i in range(k + 1)) / 2.0 ** n)
|
||||
|
||||
|
||||
def rank(rows, s):
|
||||
return [r["label"] for r in sorted(rows, key=lambda r: (r[s]["n"] - r[s]["solved"], r[s]["total"]))]
|
||||
|
||||
|
||||
def family(pid):
|
||||
"""APS: the function number (aps.NN.MM); CHA: funN; the unit of dependence."""
|
||||
return ".".join(pid.split(".")[:2]) if pid.startswith("aps") else pid.split(".")[0]
|
||||
|
||||
|
||||
def families(a, b, s):
|
||||
"""Family-level comparison: per family the total of a against the total of b."""
|
||||
ta, tb = defaultdict(int), defaultdict(int)
|
||||
for p in a[s]["per"]:
|
||||
ta[family(p)] += cost(a[s]["per"][p])
|
||||
tb[family(p)] += cost(b[s]["per"][p])
|
||||
w = sum(ta[k] < tb[k] for k in ta)
|
||||
l = sum(ta[k] > tb[k] for k in ta)
|
||||
return w, len(ta) - w - l, l, dict(ta), dict(tb)
|
||||
|
||||
|
||||
def main():
|
||||
full = load_uniform("sweep_full.json")
|
||||
by = {r["label"]: r for r in full}
|
||||
for s in ("APS", "CHA"):
|
||||
rk = rank(full, s)
|
||||
print(f"{s} places: " + ", ".join(
|
||||
f"{lb} {rk.index(lb) + 1}" for lb in (
|
||||
"chandrupatla", "pure.ratio.derived3.none", PROJ, "toms748", "brent", "dekker",
|
||||
"itp_oracle", "ridders", CREDIT, "itp", "illinois", "bisection", "regula_falsi",
|
||||
"pure.exp_abs.bracket.both", "pure.exp_abs.bracket.bracket",
|
||||
"pure.exp_abs.bracket.credit")))
|
||||
for lb in ("dekker", "illinois", "regula_falsi", "brent", "toms748",
|
||||
"pure.ratio.derived3.none", "pure.exp_abs.bracket.both"):
|
||||
r = by[lb][s]
|
||||
print(f" {lb:<28} solved {r['solved']}/{r['n']} total {r['total']} over {r['over']}")
|
||||
# Corollary 2: best over scales, step guard (Table 4's individual ranking)
|
||||
best = {}
|
||||
for r in full:
|
||||
if r["spec"][0] == "pure" and r["spec"][3] == "step":
|
||||
best[r["spec"][1]] = min(best.get(r["spec"][1], 10 ** 9),
|
||||
r["APS"]["total"] + r["CHA"]["total"])
|
||||
print("best over scales (step guard):", dict(sorted(best.items(), key=lambda kv: kv[1])))
|
||||
|
||||
# revision point 8: families as the unit
|
||||
ap = {r["label"]: r for r in load_uniform("sweep_aprime.json")}[APRIME]
|
||||
for name, a in (("base rule", by[PROJ]), ("A'", ap)):
|
||||
for s in ("APS", "CHA"):
|
||||
w, t, l, ta, tb = families(a, by["chandrupatla"], s)
|
||||
print(f"{name} vs Chandrupatla by family, {s}: {w}/{t}/{l} of {w + t + l} families,"
|
||||
f" p={sign_p(w, l):.2g}")
|
||||
if name == "A'" and s == "CHA":
|
||||
print(" per family A' / Chandrupatla:",
|
||||
{k: (ta[k], tb[k]) for k in sorted(ta)})
|
||||
for s in ("APS", "CHA"):
|
||||
ps = list(a[s]["per"])
|
||||
w = sum(cost(a[s]["per"][p]) < cost(by["chandrupatla"][s]["per"][p]) for p in ps)
|
||||
l = sum(cost(a[s]["per"][p]) > cost(by["chandrupatla"][s]["per"][p]) for p in ps)
|
||||
print(f"{name} vs Chandrupatla by problem, {s}: {w}/{len(ps) - w - l}/{l}"
|
||||
f" p={sign_p(w, l):.2g}")
|
||||
# Table 6: the 60 paired (function, safeguard) cells of the far-end reading
|
||||
order = load_uniform("sweep_order.json")
|
||||
cells = {}
|
||||
for r in order:
|
||||
sim, sc, gu = r["spec"][1], r["spec"][2], r["spec"][3]
|
||||
ex = r["spec"][8] if len(r["spec"]) > 8 else "none"
|
||||
if sc == "far":
|
||||
cells[(sim, gu, ex)] = r["APS"]["total"] + r["CHA"]["total"]
|
||||
pairs = [(k[0], k[1]) for k in cells if k[2] == "none" and (k[0], k[1], "order") in cells]
|
||||
cheaper = sum(cells[(s_, g, "order")] < cells[(s_, g, "none")] for s_, g in pairs)
|
||||
print(f"far-end reading, measured order cheaper in {cheaper} of {len(pairs)} cells")
|
||||
fp = [r for r in order if r["spec"][1] == "rational" and r["spec"][2] == "far"
|
||||
and r["spec"][3] == "none"]
|
||||
for r in fp:
|
||||
print(f" false position reading {r['spec'][8]}: APS solved {r['APS']['solved']} "
|
||||
f"total {r['APS']['total']}")
|
||||
# negative item 9: the capped scale
|
||||
cap = {r["label"]: r for r in load_uniform("sweep_cap.json")}
|
||||
dire = {r["label"]: r for r in load_uniform("sweep_direction.json")}
|
||||
for lb in ("pure+dissim+slope.ratio.derived3_cap.project",
|
||||
"pure+dissim+slope.ratio.derived3_cap.safe"):
|
||||
r = cap[lb]
|
||||
print(f"cap {lb}: {r['APS']['total']} / {r['CHA']['total']} solved "
|
||||
f"{r['APS']['solved'] + r['CHA']['solved']}")
|
||||
for lb in ("pure+dissim+slope.ratio.derived3.project", "pure+dissim+slope.ratio.derived3.safe"):
|
||||
r = dire[lb]
|
||||
print(f"control {lb}: {r['APS']['total']} / {r['CHA']['total']}")
|
||||
# Table 1a: which canonical problems the multiplier moves
|
||||
from simroot.pure import pure_root
|
||||
from stage12_validation import load, per_problem
|
||||
probs = [p for p in load() if p[0] == "APS"]
|
||||
runs = {}
|
||||
for fac in (1.25, 1.5, 2.0):
|
||||
runs[fac] = per_problem(lambda f, a, b, xt, mx, _f=fac: pure_root(
|
||||
f, a, b, xt, mx, similarity="ratio", scale="derived3", guard="project",
|
||||
budget_factor=_f), probs, 200, criterion="sign")
|
||||
moved = {p: (runs[1.25][p][0], runs[1.5][p][0], runs[2.0][p][0]) for p in runs[2.0]
|
||||
if len({runs[1.25][p][0], runs[1.5][p][0], runs[2.0][p][0]}) > 1}
|
||||
print("canonical problems moved by the multiplier (1.25, 1.5, 2):", moved)
|
||||
# negative item 5: the phase detector (scale derived3_m) on the full benchmark
|
||||
allp = load()
|
||||
for sc in ("derived3", "derived3_m"):
|
||||
pp = per_problem(lambda f, a, b, xt, mx, _s=sc: pure_root(
|
||||
f, a, b, xt, mx, similarity="ratio", scale=_s, guard="project"), allp, 200,
|
||||
criterion="sign")
|
||||
t = {"APS": 0, "CHA": 0}
|
||||
for s_, pid, *_ in allp:
|
||||
t[s_] += pp[pid][0]
|
||||
print(f"phase detector item: scale {sc}: APS {t['APS']} CHA {t['CHA']} "
|
||||
f"both {t['APS'] + t['CHA']}")
|
||||
print("numbers uniform done")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user