PREREG_half_contra outcome: ACCEPTED (server = smoke in every projection cell; 0 violations in the guaranteed family).

'half': the step promises the root in the half near x (S >= 1/2) while the bracket line puts it in the far half (smaller |f| at the far end) -> halve.
  half alone                                  APS 2806 -> 2564 (!)  CHA 3220 -> 3202
  G2 + contra + rem + point + exp + half      APS 2773 -> 2559  CHA 2073 -> 2047  both 4606 (all of H1-H4; goal kept)
     per problem vs Chandrupatla: APS 98/17/38 p=2.7e-7, CHA 27/6/7 p=8e-4
  contra + rem + point + exp + half (no G2)   APS 2551  CHA 2044  both 4595 (H2 fails by 24)
  with defect it does not combine (APS 2531 -> 2651): the two refuse overlapping steps.
fun9: 77 -> 68 (Chandrupatla 55); fun9.5 24 -> 16.
Server regression x2: 1204 passed, 1 failed = the paper-number check.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
vvs
2026-09-21 19:24:31 +01:00
co-authored by Claude Opus 5
parent 3d74b4531b
commit bbb16ec81c
8 changed files with 101 additions and 5 deletions
+14
View File
@@ -0,0 +1,14 @@
== no G2
half APS 2806->2564 CHA 3220->3202 fun9 105->94 H1 ✓ H2 ✓ H3 ✓ H4 ✓ GOAL no vsCh APS 98/18/37 p=1.5e-07 CHA 8/6/26 p=0.0029
fun1:106 fun2:141 fun3:353 fun4:548 fun5:452 fun6:456 fun7:1000 fun8:52 fun9:94
defect+flatanalogmempt+exp+half APS 2531->2651 CHA 1972->2005 fun9 74->67 H1 ✓ H2 ✗ H3 ✗ H4 ✓ GOAL kept vsCh APS 85/20/48 p=0.0017 CHA 26/5/9 p=0.006
fun1:104 fun2:144 fun3:145 fun4:173 fun5:161 fun6:154 fun7:1000 fun8:57 fun9:67
contra+flatanalogmempt+exp+half APS 2792->2551 CHA 2020->2044 fun9 77->68 H1 ✓ H2 ✗ H3 ✓ H4 ✓ GOAL kept vsCh APS 99/16/38 p=1.9e-07 CHA 27/6/7 p=0.00082
fun1:103 fun2:141 fun3:145 fun4:173 fun5:208 fun6:154 fun7:1000 fun8:52 fun9:68
== G2
half APS 2782->2574 CHA 3169->3058 fun9 94->83 H1 ✓ H2 ✓ H3 ✓ H4 ✓ GOAL no vsCh APS 97/19/37 p=2.2e-07 CHA 9/6/25 p=0.009
fun1:101 fun2:146 fun3:322 fun4:442 fun5:456 fun6:456 fun7:1000 fun8:52 fun9:83
defect+flatanalogmempt+exp+half APS 2588->2680 CHA 1997->2002 fun9 74->67 H1 ✓ H2 ✗ H3 ✗ H4 ✓ GOAL kept vsCh APS 84/21/48 p=0.0022 CHA 26/5/9 p=0.006
fun1:98 fun2:145 fun3:147 fun4:173 fun5:161 fun6:154 fun7:1000 fun8:57 fun9:67
contra+flatanalogmempt+exp+half APS 2773->2559 CHA 2073->2047 fun9 77->68 H1 ✓ H2 ✓ H3 ✓ H4 ✓ GOAL kept vsCh APS 98/17/38 p=2.7e-07 CHA 27/6/7 p=0.00082
fun1:98 fun2:147 fun3:147 fun4:173 fun5:208 fun6:154 fun7:1000 fun8:52 fun9:68
+12
View File
@@ -10,6 +10,9 @@ TOTALS (evaluations of f, failures charged 200)
+ defect + rem. + ORDER POINT 2532 2164 4696 + defect + rem. + ORDER POINT 2532 2164 4696
+ G2 + contra + rem. + pt + EXP 2773 2073 4846 + G2 + contra + rem. + pt + EXP 2773 2073 4846
+ defect + rem. + pt + EXP 2531 1972 4503 + defect + rem. + pt + EXP 2531 1972 4503
+ half (alone) 2564 3202 5766
+ G2 + contra + rem + pt + exp + HALF 2559 2047 4606
+ contra + rem + pt + exp + HALF 2551 2044 4595
Chandrupatla 2787 2441 5228 Chandrupatla 2787 2441 5228
Brent 2889 4115 7004 Brent 2889 4115 7004
TOMS748 2820 4000 6820 TOMS748 2820 4000 6820
@@ -26,6 +29,9 @@ PER PROBLEM, ours against each rival: wins/ties/losses (sign-test p)
+ defect + rem. + ORDER POINT Chandrupatla 86/20/47 p=0.00091 Brent 101/12/40 p=2.9e-07 TOMS748 107/11/35 p=1.1e-09 + defect + rem. + ORDER POINT Chandrupatla 86/20/47 p=0.00091 Brent 101/12/40 p=2.9e-07 TOMS748 107/11/35 p=1.1e-09
+ G2 + contra + rem. + pt + EXP Chandrupatla 98/18/37 p=1.5e-07 Brent 112/8/33 p=3e-11 TOMS748 98/15/40 p=8.5e-07 + G2 + contra + rem. + pt + EXP Chandrupatla 98/18/37 p=1.5e-07 Brent 112/8/33 p=3e-11 TOMS748 98/15/40 p=8.5e-07
+ defect + rem. + pt + EXP Chandrupatla 86/20/47 p=0.00091 Brent 101/12/40 p=2.9e-07 TOMS748 107/11/35 p=1.1e-09 + defect + rem. + pt + EXP Chandrupatla 86/20/47 p=0.00091 Brent 101/12/40 p=2.9e-07 TOMS748 107/11/35 p=1.1e-09
+ half (alone) Chandrupatla 98/18/37 p=1.5e-07 Brent 116/7/30 p=3.9e-13 TOMS748 117/9/27 p=1.5e-14
+ G2 + contra + rem + pt + exp + HALF Chandrupatla 98/17/38 p=2.7e-07 Brent 114/8/31 p=2.3e-12 TOMS748 118/7/28 p=2.4e-14
+ contra + rem + pt + exp + HALF Chandrupatla 99/16/38 p=1.9e-07 Brent 115/8/30 p=6.2e-13 TOMS748 117/8/28 p=3.9e-14
CHA CHA
proposed rule Chandrupatla 9/5/26 p=0.006 Brent 30/4/4 p=6.2e-06 TOMS748 31/1/8 p=0.00029 proposed rule Chandrupatla 9/5/26 p=0.006 Brent 30/4/4 p=6.2e-06 TOMS748 31/1/8 p=0.00029
+ G2 (step pattern) Chandrupatla 10/3/27 p=0.0076 Brent 30/2/6 p=7e-05 TOMS748 31/1/8 p=0.00029 + G2 (step pattern) Chandrupatla 10/3/27 p=0.0076 Brent 30/2/6 p=7e-05 TOMS748 31/1/8 p=0.00029
@@ -37,6 +43,9 @@ PER PROBLEM, ours against each rival: wins/ties/losses (sign-test p)
+ defect + rem. + ORDER POINT Chandrupatla 20/3/17 p=0.74 Brent 30/2/6 p=7e-05 TOMS748 34/1/5 p=2.4e-06 + defect + rem. + ORDER POINT Chandrupatla 20/3/17 p=0.74 Brent 30/2/6 p=7e-05 TOMS748 34/1/5 p=2.4e-06
+ G2 + contra + rem. + pt + EXP Chandrupatla 28/3/9 p=0.0026 Brent 31/3/4 p=3.5e-06 TOMS748 37/1/2 p=2.8e-09 + G2 + contra + rem. + pt + EXP Chandrupatla 28/3/9 p=0.0026 Brent 31/3/4 p=3.5e-06 TOMS748 37/1/2 p=2.8e-09
+ defect + rem. + pt + EXP Chandrupatla 27/3/10 p=0.0076 Brent 30/2/6 p=7e-05 TOMS748 35/1/4 p=3.4e-07 + defect + rem. + pt + EXP Chandrupatla 27/3/10 p=0.0076 Brent 30/2/6 p=7e-05 TOMS748 35/1/4 p=3.4e-07
+ half (alone) Chandrupatla 8/6/26 p=0.0029 Brent 33/3/2 p=3.7e-08 TOMS748 33/0/7 p=4.2e-05
+ G2 + contra + rem + pt + exp + HALF Chandrupatla 27/6/7 p=0.00082 Brent 33/3/2 p=3.7e-08 TOMS748 38/1/1 p=1.5e-10
+ contra + rem + pt + exp + HALF Chandrupatla 27/6/7 p=0.00082 Brent 34/4/0 p=1.2e-10 TOMS748 38/1/1 p=1.5e-10
CHA PER FAMILY (ours / Chandrupatla) CHA PER FAMILY (ours / Chandrupatla)
fun1 fun2 fun3 fun4 fun5 fun6 fun7 fun8 fun9 fun1 fun2 fun3 fun4 fun5 fun6 fun7 fun8 fun9
@@ -50,4 +59,7 @@ CHA PER FAMILY (ours / Chandrupatla)
+ defect + rem. + ORDER POINT 99 144 132 141 177 339 1000 57 75 + defect + rem. + ORDER POINT 99 144 132 141 177 339 1000 57 75
+ G2 + contra + rem. + pt + EXP 98 146 147 158 208 187 1000 52 77 + G2 + contra + rem. + pt + EXP 98 146 147 158 208 187 1000 52 77
+ defect + rem. + pt + EXP 100 144 123 146 161 167 1000 57 74 + defect + rem. + pt + EXP 100 144 123 146 161 167 1000 57 74
+ half (alone) 106 141 353 548 452 456 1000 52 94
+ G2 + contra + rem + pt + exp + HALF 98 147 147 173 208 154 1000 52 68
+ contra + rem + pt + exp + HALF 103 141 145 173 208 154 1000 52 68
Chandrupatla 103 152 305 297 233 233 1000 63 55 Chandrupatla 103 152 305 297 233 233 1000 63 55
+18 -2
View File
@@ -764,7 +764,7 @@ def pure_root(f, a, b, xtol, maxfev, similarity="ratio", scale="derived",
# category variables below then carry the same string the old tests compared. # category variables below then carry the same string the old tests compared.
if "+" in prestep: if "+" in prestep:
parts = prestep.split("+") parts = prestep.split("+")
cats = ({"defect"}, {"contra"}, {"exp"}, {"flatanalog", "flatanalogmem", "flatanalogpt", cats = ({"defect"}, {"contra"}, {"exp"}, {"half"}, {"flatanalog", "flatanalogmem", "flatanalogpt",
"flatanalogmempt"}) "flatanalogmempt"})
if (len(parts) != len(set(parts)) or any(not any(p in c for c in cats) for p in parts) if (len(parts) != len(set(parts)) or any(not any(p in c for c in cats) for p in parts)
or any(sum(p in c for p in parts) > 1 for c in cats)): or any(sum(p in c for p in parts) > 1 for c in cats)):
@@ -776,7 +776,7 @@ def pure_root(f, a, b, xtol, maxfev, similarity="ratio", scale="derived",
elif prestep not in ("none", "progress", "slope", "band", "defect", "simpair", "flat", elif prestep not in ("none", "progress", "slope", "band", "defect", "simpair", "flat",
"flat2", "flatcreep", "flatstick", "flatstickmid", "flatstickexit", "flat2", "flatcreep", "flatstick", "flatstickmid", "flatstickexit",
"flatjudge", "flatanalog", "flatanalogmem", "contra", "flatjudge", "flatanalog", "flatanalogmem", "contra",
"flatanalogpt", "flatanalogmempt"): "flatanalogpt", "flatanalogmempt", "half"):
raise ValueError(f"unknown prestep {prestep!r}") raise ValueError(f"unknown prestep {prestep!r}")
parts = prestep.split("+") parts = prestep.split("+")
pre_dec = next((p for p in parts if p in ("band", "defect", "simpair")), "none") pre_dec = next((p for p in parts if p in ("band", "defect", "simpair")), "none")
@@ -787,6 +787,7 @@ def pure_root(f, a, b, xtol, maxfev, similarity="ratio", scale="derived",
flat_pt = pre_flat in ("flatanalogpt", "flatanalogmempt") flat_pt = pre_flat in ("flatanalogpt", "flatanalogmempt")
pre_contra = "contra" in parts pre_contra = "contra" in parts
pre_exp = "exp" in parts # PREREG_flat_exp_limit: translation similarity, m = inf pre_exp = "exp" in parts # PREREG_flat_exp_limit: translation similarity, m = inf
pre_half = "half" in parts # PREREG_half_contra: the half promised vs the bracket
if pre_dec != "none" and scale not in ( if pre_dec != "none" and scale not in (
"derived3", "derived3_cap", "derived3_m", "bracket", "far"): "derived3", "derived3_cap", "derived3_m", "bracket", "far"):
# the decision reads a TRIPLE; under the two-point scale there is no third point # the decision reads a TRIPLE; under the two-point scale there is no third point
@@ -1115,6 +1116,21 @@ def pure_root(f, a, b, xtol, maxfev, similarity="ratio", scale="derived",
if loc != 0.0 and (loc > 0.0) != (brk > 0.0): if loc != 0.0 and (loc > 0.0) != (brk > 0.0):
step = 0.5 * (A + B) - x step = 0.5 * (A + B) - x
pre_refused += 1 pre_refused += 1
if step is None and pre_half:
# PREREG_half_contra 2026-09-21. Two models of which half holds the
# root. The step: S >= 1/2 means a step of at most half the way to
# the far end - the root promised in the half NEAR x. The bracket
# line: the root lies nearer the end with the smaller |f| - if that is
# the far end, in the FAR half. When they disagree the promise 'the
# root is here' is not taken (fun9: a slope dominated by f(81) = 1e35
# gives S ~ 1 at 20.25) and this evaluation halves. 1/2 is the
# bisection constant itself; no threshold.
f_far = FB if far == B else FA
if S(z_now) >= 0.5 and abs(f_far) < abs(fx):
step = 0.5 * (A + B) - x
pre_refused += 1
if stats is not None:
stats['half_refused'] = stats.get('half_refused', 0) + 1
if step is None and prestep == "flatjudge": if step is None and prestep == "flatjudge":
# PREREG_flat_judge 2026-09-21. Enter only when the unkept promise # PREREG_flat_judge 2026-09-21. Enter only when the unkept promise
# AND the point itself looks flat (judged at its evaluation, below); # AND the point itself looks flat (judged at its evaluation, below);
+26 -3
View File
@@ -303,6 +303,26 @@ def build_grid_explimit(smoke):
for gu in guards for ext in ("none", "pattern") for pre in presteps] for gu in guards for ext in ("none", "pattern") for pre in presteps]
HALF_BASES = ("none", "defect+flatanalogmempt+exp", "contra+flatanalogmempt+exp")
def build_grid_half(smoke):
"""PREREG_half_contra_2026-09-21: each base without / with the half contradiction, on
the proposed rule with and without G2."""
presteps = tuple(p for b in HALF_BASES
for p in (b, "half" if b == "none" else b + "+half"))
for pre in presteps:
if pre == "none":
continue
x, _n, ok = pure_root(lambda t: t - 1.0, 0.0, 3.0, 1e-10, 100, similarity="ratio",
scale="derived3", guard="project", prestep=pre)
if not (ok and abs(x - 1.0) < 1e-8):
raise SystemExit(f"prestep={pre} preflight FAILED: refusing to report zeros")
guards = ("project", "credit") if smoke else GUARD_MODES
return [("pure", "ratio", "derived3", gu, "x", pre, "recent", "distance", "none", ext)
for gu in guards for ext in ("none", "pattern") for pre in presteps]
def build_grid_extrap2(smoke): def build_grid_extrap2(smoke):
"""PREREG_extrapolation_gates_2026-09-21: the same cells as build_grid_extrap, every """PREREG_extrapolation_gates_2026-09-21: the same cells as build_grid_extrap, every
one in all five modes (none, A, G1, G2, G3).""" one in all five modes (none, A, G1, G2, G3)."""
@@ -483,10 +503,12 @@ def main():
dcmode = "--defcontra" in sys.argv # defect x contra x flat regime, composites dcmode = "--defcontra" in sys.argv # defect x contra x flat regime, composites
ptmode = "--orderpt" in sys.argv # split at the point from the pair's order ptmode = "--orderpt" in sys.argv # split at the point from the pair's order
expmode = "--explimit" in sys.argv # the translation limit of the analogy, m = inf expmode = "--explimit" in sys.argv # the translation limit of the analogy, m = inf
halfmode = "--half" in sys.argv # the half promised by the step vs the bracket
combomode = "--combo" in sys.argv # modes A and B together combomode = "--combo" in sys.argv # modes A and B together
pointsmode = "--points" in sys.argv # mode A: triple by shape pointsmode = "--points" in sys.argv # mode A: triple by shape
dirmode = "--direction" in sys.argv # mode B: far end by dissimilarity dirmode = "--direction" in sys.argv # mode B: far end by dissimilarity
specs = (build_grid_explimit(smoke) if expmode else specs = (build_grid_half(smoke) if halfmode else
build_grid_explimit(smoke) if expmode else
build_grid_orderpt(smoke) if ptmode else build_grid_orderpt(smoke) if ptmode else
build_grid_defcontra(smoke) if dcmode else build_grid_defcontra(smoke) if dcmode else
build_grid_flat(smoke, ("flatanalogmem", "flatanalog")) if memmode else build_grid_flat(smoke, ("flatanalogmem", "flatanalog")) if memmode else
@@ -523,8 +545,9 @@ def main():
# the published sweep_full.json is what verify_article.py checks the paper # the published sweep_full.json is what verify_article.py checks the paper
# against, so the log grid never writes into it # against, so the log grid never writes into it
if expmode or ptmode or dcmode or memmode or analogmode or judgemode or exitmode or stickmode or creepmode or flat2mode or flatmode or ext2mode or extmode or decmode or ordermode or capmode or combomode or pointsmode or dirmode: if halfmode or expmode or ptmode or dcmode or memmode or analogmode or judgemode or exitmode or stickmode or creepmode or flat2mode or flatmode or ext2mode or extmode or decmode or ordermode or capmode or combomode or pointsmode or dirmode:
base = ("sweep_explimit" if expmode else base = ("sweep_half" if halfmode else
"sweep_explimit" if expmode else
"sweep_orderpt" if ptmode else "sweep_orderpt" if ptmode else
"sweep_defcontra" if dcmode else "sweep_defcontra" if dcmode else
"sweep_flatanalogmem" if memmode else "sweep_flatanalogmem" if memmode else
+1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+4
View File
@@ -24,6 +24,7 @@ def main():
dc = load("sweep_defcontra.json") dc = load("sweep_defcontra.json")
op = load("sweep_orderpt.json") op = load("sweep_orderpt.json")
ex = load("sweep_explimit.json") ex = load("sweep_explimit.json")
hf = load("sweep_half.json")
rivals = {"Chandrupatla": full["chandrupatla"], "Brent": full["brent"], rivals = {"Chandrupatla": full["chandrupatla"], "Brent": full["brent"],
"TOMS748": full["toms748"]} "TOMS748": full["toms748"]}
ours = { ours = {
@@ -37,6 +38,9 @@ def main():
"+ defect + rem. + ORDER POINT": op["defect+flatanalogmempt.ratio.derived3.project"], "+ defect + rem. + ORDER POINT": op["defect+flatanalogmempt.ratio.derived3.project"],
"+ G2 + contra + rem. + pt + EXP": ex["pure+extP+contra+flatanalogmempt+exp.ratio.derived3.project"], "+ G2 + contra + rem. + pt + EXP": ex["pure+extP+contra+flatanalogmempt+exp.ratio.derived3.project"],
"+ defect + rem. + pt + EXP": ex["defect+flatanalogmempt+exp.ratio.derived3.project"], "+ defect + rem. + pt + EXP": ex["defect+flatanalogmempt+exp.ratio.derived3.project"],
"+ half (alone)": hf["half.ratio.derived3.project"],
"+ G2 + contra + rem + pt + exp + HALF": hf["pure+extP+contra+flatanalogmempt+exp+half.ratio.derived3.project"],
"+ contra + rem + pt + exp + HALF": hf["contra+flatanalogmempt+exp+half.ratio.derived3.project"],
} }
print("TOTALS (evaluations of f, failures charged 200)") print("TOTALS (evaluations of f, failures charged 200)")
print(f" {'method':<32} {'APS':>6} {'CHA':>6} {'both':>6}") print(f" {'method':<32} {'APS':>6} {'CHA':>6} {'both':>6}")
+25
View File
@@ -424,3 +424,28 @@ def test_the_exp_limit_leaves_simple_roots_alone():
guard="project", prestep=p)[1] guard="project", prestep=p)[1]
for p in ("defect+flatanalogmempt", "defect+flatanalogmempt+exp")] for p in ("defect+flatanalogmempt", "defect+flatanalogmempt+exp")]
assert n[0] == n[1], n assert n[0] == n[1], n
# ---- PREREG_half_contra_2026-09-21: the half promised by the step vs the bracket ----
@pytest.mark.parametrize("f,a,b", PROBS)
@pytest.mark.parametrize("guard", ("project", "credit"))
@pytest.mark.parametrize("pre", ("half", "defect+flatanalogmempt+exp+half",
"contra+flatanalogmempt+exp+half"))
def test_the_guarantee_holds_with_half(f, a, b, guard, pre):
x, n, ok = pure_root(f, a, b, XTOL, MAXFEV, similarity="ratio", scale="derived3",
guard=guard, prestep=pre)
assert ok and min(a, b) <= x <= max(a, b)
half = math.ceil(math.log2(abs(b - a) / XTOL))
assert n <= (2 * half + 3 if guard == "project" else half + 4), n
def test_half_is_silent_on_a_line_and_breaks_the_fun9_flank():
"""Measured before pinning: on [2e-4, 81] the flank costs 24 -> 16 in the best cell."""
st = {}
pure_root(lambda t: 3.0 * t - 1.0, -2.0, 5.0, XTOL, MAXFEV, similarity="ratio",
scale="derived3", guard="project", prestep="half", stats=st)
assert st.get("half_refused", 0) == 0
n = [pure_root(_fun9, 0.0002, 81.0, XTOL, MAXFEV, similarity="ratio", scale="derived3",
guard="project", prestep=p)[1]
for p in ("defect+flatanalogmempt+exp", "defect+flatanalogmempt+exp+half")]
assert n[1] < n[0], n