Flat regime (PREREG_flat_regime): the unkept-promise flag - after a model step that did not cross the root, r = f_new/f_old >= 1/4, the tangent-versus-halving break-even at m = 2 - RECOGNISES the regime (stage 1: 53.6% of model steps flagged on the flat families against 21.6% on APS and 17.0% on fun1; recall ten times the m>=2 estimator's 5.8%) and cuts the wide-bracket set by 350-490 wherever the budget does not already bind: safe 3390 -> 3037, step 3524 -> 3037, unguarded 4104 -> 3198.
NOT accepted into the proposed rule by the stop rule: under the projection the flat families are already budget-bound (CHA 3220 -> 3198 only) while the false flags on APS cost 2806 -> 3029 (Z2 fails); with G2 both sets fail. The per-problem edge over Chandrupatla on APS turns into 26/72/55. Guarantee intact in every cell. Next candidate, not pre-registered: require the promise to fail twice in a row. Regression on the branch: 918 pass (twice); the one red test is the paper-number check awaiting the paper update. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
"""Verdicts Z1-Z5 of PREREG_flat_regime_2026-09-21.md (stage 2) from sweep_flat.json.
|
||||
|
||||
python -u analyze_flat.py
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
|
||||
from analyze_extrap import FAMILY, FLAT, fam_sum, h2h, load, sign_p
|
||||
|
||||
|
||||
def main():
|
||||
rows = load("sweep_flat.json")
|
||||
cha = {r["label"]: r for r in load("sweep_full.json")}["chandrupatla"]
|
||||
cell = {}
|
||||
for r in rows:
|
||||
s = r["spec"]
|
||||
cell[(s[1], s[3], s[9], s[5])] = r
|
||||
print("tent, 3-point, pairs (no gate -> flat gate) APS CHA both flat fun3-6")
|
||||
for gu in ("none", "step", "bracket", "both", "project", "safe", "credit"):
|
||||
for ext in ("none", "pattern"):
|
||||
a, b = cell[("ratio", gu, ext, "none")], cell[("ratio", gu, ext, "flat")]
|
||||
print(f" {gu:<8} {'+G2' if ext == 'pattern' else ' '} "
|
||||
f"{a['APS']['total']:5d}->{b['APS']['total']:<5d} {a['CHA']['total']:5d}->"
|
||||
f"{b['CHA']['total']:<5d} {a['APS']['total'] + a['CHA']['total']:5d}->"
|
||||
f"{b['APS']['total'] + b['CHA']['total']:<5d} {fam_sum(a, FLAT):5d}->"
|
||||
f"{fam_sum(b, FLAT):<5d} solved {b['APS']['solved'] + b['CHA']['solved']} "
|
||||
f"over {b['APS']['over'] + b['CHA']['over']}")
|
||||
print("\nVERDICTS")
|
||||
for ext, name in (("none", "proposed rule"), ("pattern", "proposed rule + G2")):
|
||||
a, b = cell[("ratio", "project", ext, "none")], cell[("ratio", "project", ext, "flat")]
|
||||
fam = [r for k, r in cell.items() if k[3] == "flat" and k[1] in FAMILY]
|
||||
viol = sum(r["APS"]["over"] + r["CHA"]["over"] for r in fam)
|
||||
low = sum(1 for r in fam if r["APS"]["solved"] + r["CHA"]["solved"] < 193)
|
||||
z1 = b["CHA"]["total"] < a["CHA"]["total"]
|
||||
z2 = b["APS"]["total"] <= a["APS"]["total"]
|
||||
z3 = viol == 0 and low == 0
|
||||
z4 = fam_sum(b, FLAT) < fam_sum(a, FLAT)
|
||||
w, t, l = h2h(b, cha, "APS")
|
||||
print(f" {name:<20} APS {a['APS']['total']}->{b['APS']['total']} (Z2 {'✓' if z2 else '✗'}) "
|
||||
f"CHA {a['CHA']['total']}->{b['CHA']['total']} (Z1 {'✓' if z1 else '✗'}) "
|
||||
f"Z3 {'✓' if z3 else '✗'} ({viol} viol, {low} cells <193) Z4 {'✓' if z4 else '✗'} "
|
||||
f"both {b['APS']['total'] + b['CHA']['total']} vs Chandrupatla APS {w}/{t}/{l} "
|
||||
f"p={sign_p(w, l):.2g}" + (" ACCEPTED" if z1 and z2 and z3 else " not accepted"))
|
||||
print("\nnine functions, projection, no gate -> flat gate, both sets:")
|
||||
for sim in sorted({k[0] for k in cell}):
|
||||
a, b = cell[(sim, "project", "none", "none")], cell[(sim, "project", "none", "flat")]
|
||||
print(f" {sim:<11} {a['APS']['total'] + a['CHA']['total']:6d} -> "
|
||||
f"{b['APS']['total'] + b['CHA']['total']:6d}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,32 @@
|
||||
sweep: 140 configurations x 199 problems (FULL)
|
||||
wrote sweep_flat.json (7s total)
|
||||
tent, 3-point, pairs (no gate -> flat gate) APS CHA both flat fun3-6
|
||||
none 2806->3029 4104->3198 6910->6227 2707->1758 solved 193 over 0
|
||||
none +G2 2782->3089 3863->3214 6645->6303 2474->1749 solved 193 over 0
|
||||
step 3036->3086 3524->3037 6560->6123 2111->1612 solved 193 over 0
|
||||
step +G2 3089->3098 3529->3077 6618->6175 2106->1609 solved 193 over 0
|
||||
bracket 7260->7144 3604->3604 10864->10748 1730->1730 solved 193 over 0
|
||||
bracket +G2 6837->6801 3650->3650 10487->10451 1717->1717 solved 193 over 0
|
||||
both 7239->7118 3515->3515 10754->10633 1529->1529 solved 193 over 0
|
||||
both +G2 7130->7109 3463->3463 10593->10572 1504->1504 solved 193 over 0
|
||||
project 2806->3029 3220->3198 6026->6227 1823->1758 solved 193 over 0
|
||||
project +G2 2782->3089 3169->3214 5951->6303 1780->1749 solved 193 over 0
|
||||
safe 3036->3086 3390->3037 6426->6123 1977->1612 solved 193 over 0
|
||||
safe +G2 3089->3098 3392->3077 6481->6175 1969->1609 solved 193 over 0
|
||||
credit 3568->4208 3020->3038 6588->7246 1044->1064 solved 193 over 0
|
||||
credit +G2 3799->4403 3064->3053 6863->7456 1044->1064 solved 193 over 0
|
||||
|
||||
VERDICTS
|
||||
proposed rule APS 2806->3029 (Z2 ✗) CHA 3220->3198 (Z1 ✓) Z3 ✓ (0 viol, 0 cells <193) Z4 ✓ both 6227 vs Chandrupatla APS 26/72/55 p=0.0017 not accepted
|
||||
proposed rule + G2 APS 2782->3089 (Z2 ✗) CHA 3169->3214 (Z1 ✗) Z3 ✓ (0 viol, 0 cells <193) Z4 ✓ both 6303 vs Chandrupatla APS 27/70/56 p=0.0019 not accepted
|
||||
|
||||
nine functions, projection, no gate -> flat gate, both sets:
|
||||
cbrt 18003 -> 18270
|
||||
cosine 19741 -> 15910
|
||||
exp_abs 6652 -> 7104
|
||||
exp_sq 19786 -> 14298
|
||||
rat_sq 19793 -> 14565
|
||||
ratio 6026 -> 6227
|
||||
ratio_soft 9352 -> 9690
|
||||
rational 6823 -> 7777
|
||||
sqrt 13388 -> 13608
|
||||
@@ -0,0 +1,9 @@
|
||||
group model steps flagged share
|
||||
APS 1275 276 21.6%
|
||||
CHA fun1 47 8 17.0%
|
||||
CHA flat fun3-6 1251 670 53.6%
|
||||
CHA fun7 0 0 0.0%
|
||||
CHA other 174 63 36.2%
|
||||
|
||||
F1 flat > APS and flat > fun1: 53.6% vs 21.6% / 17.0% -> PASS
|
||||
bar: m>=2 fires 0.2% canonical / 5.8% flat
|
||||
+19
-1
@@ -665,7 +665,7 @@ def pure_root(f, a, b, xtol, maxfev, similarity="ratio", scale="derived",
|
||||
"{'derived3', 'derived3_cap', 'bracket', 'far'}")
|
||||
if space not in SPACES:
|
||||
raise ValueError(f"unknown space {space!r}")
|
||||
if prestep not in ("none", "progress", "slope", "band", "defect", "simpair"):
|
||||
if prestep not in ("none", "progress", "slope", "band", "defect", "simpair", "flat"):
|
||||
raise ValueError(f"unknown prestep {prestep!r}")
|
||||
if prestep in ("band", "defect", "simpair") and scale not in (
|
||||
"derived3", "derived3_cap", "derived3_m", "bracket", "far"):
|
||||
@@ -718,6 +718,7 @@ def pure_root(f, a, b, xtol, maxfev, similarity="ratio", scale="derived",
|
||||
dir_changed = 0
|
||||
slope = 0.0
|
||||
slope_prev = None
|
||||
last_model = False # was the step just evaluated the model's own? (flat gate)
|
||||
if stats is not None:
|
||||
stats['forced'] = 0
|
||||
stats['pre_refused'] = 0
|
||||
@@ -725,6 +726,7 @@ def pure_root(f, a, b, xtol, maxfev, similarity="ratio", scale="derived",
|
||||
stats['dir_changed'] = 0
|
||||
|
||||
while abs(B - A) > xtol:
|
||||
model_target = None
|
||||
if sg.bisect_before_step(abs(B - A)):
|
||||
x_new = 0.5 * (A + B)
|
||||
forced += 1
|
||||
@@ -886,6 +888,18 @@ def pure_root(f, a, b, xtol, maxfev, similarity="ratio", scale="derived",
|
||||
x_prev2, f_prev2):
|
||||
step = 0.5 * (A + B) - x
|
||||
pre_refused += 1
|
||||
if (step is None and prestep == "flat" and last_model
|
||||
and f_prev != 0.0 and fx / f_prev >= 0.25):
|
||||
# PREREG_flat_regime 2026-09-21. The last step was the model's
|
||||
# own, it did not cross the root (r > 0), and it left r = f/f_prev
|
||||
# >= 1/4 of |f|. Under a tangent step on an order-m approach
|
||||
# r = (1 - 1/m)^m, and the step loses to a halving from m = 2 on,
|
||||
# where r = (1 - 1/2)^2 = 1/4: bisection's 1/2, carried through
|
||||
# the same formula, not a chosen number. So the model is losing
|
||||
# here, and this evaluation is spent halving; the next step is
|
||||
# the model's again and is judged by its own result.
|
||||
step = 0.5 * (A + B) - x
|
||||
pre_refused += 1
|
||||
if step is None and prestep == "slope":
|
||||
# PRE-STEP GATE ON SHAPE (PREREG 2026-09-21). The step trusts the
|
||||
# local slope, so the question of trust is whether that slope has
|
||||
@@ -941,6 +955,7 @@ def pure_root(f, a, b, xtol, maxfev, similarity="ratio", scale="derived",
|
||||
reach = abs(far - x)
|
||||
step = (longer if abs(longer) <= reach
|
||||
else math.copysign(reach, step))
|
||||
model_target = x + step # the model's own proposal
|
||||
if stats is not None and "trace" in stats:
|
||||
# DIAGNOSTIC HOOK, behaviour-neutral: records the state each
|
||||
# step was taken from, so another model can be evaluated on the
|
||||
@@ -978,6 +993,9 @@ def pure_root(f, a, b, xtol, maxfev, similarity="ratio", scale="derived",
|
||||
stats['forced'] = forced; stats['pre_refused'] = pre_refused; stats['triple_changed'] = triple_changed; stats['dir_changed'] = dir_changed
|
||||
return x_new, g.n, abs(B - A) <= xtol
|
||||
|
||||
# the flat gate judges only the model's own steps: a midpoint from a gate or a
|
||||
# step moved by the safeguard says nothing about the model
|
||||
last_model = model_target is not None and x_new == model_target
|
||||
w_before = abs(B - A)
|
||||
fnew = g(x_new)
|
||||
sg.j += 1 # one step of the bisection budget is spent
|
||||
|
||||
File diff suppressed because one or more lines are too long
+29
-3
@@ -219,6 +219,29 @@ def _preflight_extrap_mode():
|
||||
raise SystemExit("extrapolate preflight FAILED: refusing to report zeros")
|
||||
|
||||
|
||||
def build_grid_flat(smoke):
|
||||
"""PREREG_flat_regime_2026-09-21 stage 2: the flat gate (prestep='flat') in pairs,
|
||||
on the proposed rule and on the proposed rule with G2 (extrapolate='pattern')."""
|
||||
x, _n, ok = pure_root(lambda t: t - 1.0, 0.0, 3.0, 1e-10, 100, similarity="ratio",
|
||||
scale="derived3", guard="project", prestep="flat")
|
||||
if not (ok and abs(x - 1.0) < 1e-8):
|
||||
raise SystemExit("prestep=flat preflight FAILED: refusing to report zeros")
|
||||
guards = ("project", "credit") if smoke else GUARD_MODES
|
||||
specs = []
|
||||
for gu in guards:
|
||||
for ext in ("none", "pattern"):
|
||||
for pre in ("none", "flat"):
|
||||
specs.append(("pure", "ratio", "derived3", gu, "x", pre, "recent",
|
||||
"distance", "none", ext))
|
||||
sims = ["sqrt"] if smoke else [s for s in sorted(PURE_SIMS) if s != "ratio"]
|
||||
for sim in sims:
|
||||
for gu in guards:
|
||||
for pre in ("none", "flat"):
|
||||
specs.append(("pure", sim, "derived3", gu, "x", pre, "recent",
|
||||
"distance", "none", "none"))
|
||||
return specs
|
||||
|
||||
|
||||
def build_grid_extrap2(smoke):
|
||||
"""PREREG_extrapolation_gates_2026-09-21: the same cells as build_grid_extrap, every
|
||||
one in all five modes (none, A, G1, G2, G3)."""
|
||||
@@ -388,10 +411,12 @@ def main():
|
||||
decmode = "--decision" in sys.argv # slot 2: the reading in the DECISION place
|
||||
extmode = "--extrap" in sys.argv # A in the method: step extrapolation
|
||||
ext2mode = "--extrap2" in sys.argv # gates G1-G3 on the lengthening
|
||||
flatmode = "--flat" in sys.argv # the flat-regime gate
|
||||
combomode = "--combo" in sys.argv # modes A and B together
|
||||
pointsmode = "--points" in sys.argv # mode A: triple by shape
|
||||
dirmode = "--direction" in sys.argv # mode B: far end by dissimilarity
|
||||
specs = (build_grid_extrap2(smoke) if ext2mode else
|
||||
specs = (build_grid_flat(smoke) if flatmode else
|
||||
build_grid_extrap2(smoke) if ext2mode else
|
||||
build_grid_extrap(smoke) if extmode else
|
||||
build_grid_decision(smoke) if decmode else
|
||||
build_grid_order(smoke) if ordermode else
|
||||
@@ -417,8 +442,9 @@ def main():
|
||||
|
||||
# the published sweep_full.json is what verify_article.py checks the paper
|
||||
# against, so the log grid never writes into it
|
||||
if ext2mode or extmode or decmode or ordermode or capmode or combomode or pointsmode or dirmode:
|
||||
base = ("sweep_extrap2" if ext2mode else
|
||||
if flatmode or ext2mode or extmode or decmode or ordermode or capmode or combomode or pointsmode or dirmode:
|
||||
base = ("sweep_flat" if flatmode else
|
||||
"sweep_extrap2" if ext2mode else
|
||||
"sweep_extrap" if extmode else
|
||||
"sweep_decision" if decmode else
|
||||
"sweep_order" if ordermode else
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
"""Pins for PREREG_flat_regime_2026-09-21.md: the flat gate (prestep='flat')."""
|
||||
from __future__ import annotations
|
||||
|
||||
import math
|
||||
|
||||
import pytest
|
||||
|
||||
from simroot.pure import pure_root
|
||||
|
||||
XTOL, MAXFEV = 1e-12, 200
|
||||
PROBS = (
|
||||
(lambda t: t ** 3 - 2.0 * t - 5.0, 1.0, 4.0),
|
||||
(lambda t: math.exp(t) - 2.0, 0.0, 3.0),
|
||||
(lambda t: 6.0 * (t - 2.0) ** 5, 0.0, 10.0),
|
||||
(lambda t: t ** 19, -10.0, 100.0),
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("f,a,b", PROBS)
|
||||
@pytest.mark.parametrize("guard", ("project", "credit", "safe"))
|
||||
def test_the_default_is_untouched(f, a, b, guard):
|
||||
ref = pure_root(f, a, b, XTOL, MAXFEV, similarity="ratio", scale="derived3", guard=guard)
|
||||
off = pure_root(f, a, b, XTOL, MAXFEV, similarity="ratio", scale="derived3", guard=guard,
|
||||
prestep="none")
|
||||
assert ref == off
|
||||
|
||||
|
||||
@pytest.mark.parametrize("f,a,b", PROBS)
|
||||
@pytest.mark.parametrize("guard", ("project", "credit"))
|
||||
@pytest.mark.parametrize("ext", ("none", "pattern"))
|
||||
def test_the_guarantee_holds_with_the_gate(f, a, b, guard, ext):
|
||||
x, n, ok = pure_root(f, a, b, XTOL, MAXFEV, similarity="ratio", scale="derived3",
|
||||
guard=guard, prestep="flat", extrapolate=ext)
|
||||
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_the_gate_never_fires_where_the_model_is_exact():
|
||||
"""On a straight line the model's step lands on the root: r = 0, never >= 1/4."""
|
||||
st = {}
|
||||
pure_root(lambda t: 3.0 * t - 1.0, -2.0, 5.0, XTOL, MAXFEV, similarity="ratio",
|
||||
scale="derived3", guard="project", prestep="flat", stats=st)
|
||||
assert st["pre_refused"] == 0
|
||||
|
||||
|
||||
def test_the_gate_fires_on_a_pure_power():
|
||||
"""On x^9 the tangent step leaves (8/9)^9 = 0.35 of |f| on the same side."""
|
||||
st = {}
|
||||
pure_root(lambda t: t ** 9, -1.0, 2.0, XTOL, MAXFEV, similarity="ratio",
|
||||
scale="derived3", guard="project", prestep="flat", stats=st)
|
||||
assert st["pre_refused"] > 0
|
||||
Reference in New Issue
Block a user