Translation limit of the analogy (f shrank, x-scale did not -> m = inf): defect + remembered + point + exp APS 2531 CHA 1972 both 4503 G2 + defect + remembered + point + exp APS 2588 CHA 1997 both 4585 G2 + contra + remembered + point + exp APS 2773 CHA 2073 both 4846 Chandrupatla APS 2787 CHA 2441 both 5228 Per problem against Chandrupatla now SIGNIFICANT ON BOTH SETS: G2+contra+rem+pt+exp APS 98/18/37 p=1.5e-7, CHA 28/3/9 p=0.0026; defect+rem+pt+exp APS 86/20/47 p=9e-4, CHA 27/3/10 p=0.0076. NOT where predicted: fun9 only -1..-3; the gain is on the flat families (x^9 177 -> 161, x^19 339 -> 167). Server regression x2: 1179 passed, 1 failed = the paper-number check. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
623 lines
29 KiB
Python
623 lines
29 KiB
Python
"""The full sweep: every similarity function x every scale x every safeguard,
|
|
over both benchmark sets, against every baseline.
|
|
|
|
Purpose. Every claim in the paper so far rests on one configuration
|
|
(similarity = ratio) measured on eight hand-picked problems, with only two
|
|
configurations carried to the 199-problem benchmark. The convergence law of
|
|
stage 0c predicts the behaviour of ALL nine similarity functions; a law
|
|
confirmed on eight problems and one configuration is an anecdote. This sweep
|
|
is what turns it into evidence, and what would refute it if it is wrong.
|
|
|
|
Grid
|
|
similarity 9 (ratio sqrt cbrt rational ratio_soft exp_abs
|
|
rat_sq exp_sq cosine)
|
|
scale 4 (start bracket derived derived3)
|
|
safeguard 4 (none step bracket both)
|
|
= 144 configurations, plus 10 baselines, over 199 problems.
|
|
|
|
Cost model and reporting rules are the same as bench_full.py: evaluations of
|
|
f; failures charged the full budget; the 2x-bisection bound checked only on
|
|
solved runs; ITP reported both at its recommended constants and as a
|
|
per-problem oracle over a (kappa1, n0) grid.
|
|
|
|
Run: python -u sweep_full.py full sweep
|
|
python -u sweep_full.py --smoke a reduced grid, for the pre-flight
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import math
|
|
import os
|
|
import sys
|
|
import time
|
|
from multiprocessing import Pool
|
|
|
|
os.environ.setdefault("OMP_NUM_THREADS", "1")
|
|
|
|
from scipy.optimize._tstutils import (_APS_TESTS_DICTS,
|
|
_CHANDRUPATLA_TESTS_DICTS)
|
|
|
|
from simroot.baselines import (anderson_bjorck, best_of, bisection, brent,
|
|
brent_scipy, chandrupatla, chandrupatla_scipy,
|
|
dekker, illinois, itp, pegasus, regula_falsi,
|
|
ridders, toms748)
|
|
from simroot.baselines import BRENT_BASELINE, CHANDRUPATLA_BASELINE
|
|
from simroot.pure import PURE_SIMS, pure_root
|
|
|
|
XTOL = 1e-12
|
|
MAXFEV = 200
|
|
ACC = 1e-6
|
|
|
|
SCALES = ("start", "bracket", "derived", "derived3")
|
|
GUARD_MODES = ("none", "step", "bracket", "both", "project", "safe",
|
|
"credit")
|
|
ITP_GRID = [(fac, n0) for fac in (1.0, 0.1, 0.01, 1e-4)
|
|
for n0 in (0, 1, 2, 5)]
|
|
|
|
|
|
def load_problems():
|
|
"""(set, id, f, a, b, root). Rebuilt inside each worker so nothing that
|
|
has to cross a process boundary is a closure."""
|
|
out = []
|
|
for d in _APS_TESTS_DICTS:
|
|
a, b = d["bracket"]
|
|
args = d.get("args", ())
|
|
out.append(("APS", d["ID"],
|
|
(lambda ff, aa: lambda x: ff(x, *aa))(d["f"], args),
|
|
float(a), float(b), float(d["root"])))
|
|
for d in _CHANDRUPATLA_TESTS_DICTS:
|
|
a, b = d["bracket"]
|
|
out.append(("CHA", d["ID"], (lambda ff: lambda x: ff(x))(d["f"]),
|
|
float(a), float(b), float(d["root"])))
|
|
return out
|
|
|
|
|
|
def itp_oracle(f, a, b, xtol, maxfev):
|
|
best = None
|
|
for fac, n0 in ITP_GRID:
|
|
try:
|
|
x, n, conv = itp(f, a, b, xtol, maxfev,
|
|
kappa1=fac * 0.2 / (b - a), n0=n0)
|
|
except ValueError:
|
|
continue
|
|
if conv and (best is None or n < best[1]):
|
|
best = (x, n, True)
|
|
return best if best is not None else (0.5 * (a + b), maxfev, False)
|
|
|
|
|
|
# Competitors are the LIBRARY wherever SciPy ships the method (since 2026-09-21):
|
|
# Brent = brentq, Chandrupatla = elementwise.find_root. Until then they were the
|
|
# per-problem better of the library and ours, which let a tolerance slip in our
|
|
# Chandrupatla (a bracket twice as wide) leak into the reported numbers.
|
|
BASELINES = {
|
|
"bisection": bisection, "regula_falsi": regula_falsi,
|
|
"illinois": illinois, "pegasus": pegasus,
|
|
"anderson_bjorck": anderson_bjorck, "ridders": ridders,
|
|
"dekker": dekker,
|
|
"brent": BRENT_BASELINE, # the library alone (2026-09-21)
|
|
"chandrupatla": CHANDRUPATLA_BASELINE, # scipy elementwise.find_root
|
|
"toms748": toms748,
|
|
"itp": itp, "itp_oracle": itp_oracle,
|
|
}
|
|
|
|
|
|
def make_method(spec):
|
|
"""spec is ('base', name) or ('pure', similarity, scale, guard[, space]).
|
|
|
|
The optional 5th element is the SPACE the step is read in (PREREG
|
|
amendment 1, 2026-09-20): omitted or "x" reproduces the published grid
|
|
bit-for-bit, "log" is the logarithmic-march mode."""
|
|
if spec[0] == "base":
|
|
return BASELINES[spec[1]]
|
|
sim, scale, guard = spec[1], spec[2], spec[3]
|
|
space = spec[4] if len(spec) > 4 else "x"
|
|
prestep = spec[5] if len(spec) > 5 else "none"
|
|
points = spec[6] if len(spec) > 6 else "recent"
|
|
direction = spec[7] if len(spec) > 7 else "distance"
|
|
exponent = spec[8] if len(spec) > 8 else "none"
|
|
extrapolate = spec[9] if len(spec) > 9 else "none"
|
|
|
|
def m(f, a, b, xtol, maxfev):
|
|
return pure_root(f, a, b, xtol, maxfev, similarity=sim,
|
|
scale=scale, guard=guard, space=space, prestep=prestep,
|
|
points=points, direction=direction, exponent=exponent,
|
|
extrapolate=extrapolate)
|
|
return m
|
|
|
|
|
|
def label(spec):
|
|
if spec[0] == "base":
|
|
return spec[1]
|
|
tag = "pure"
|
|
if len(spec) > 4 and spec[4] != "x":
|
|
tag = spec[4]
|
|
if len(spec) > 6 and spec[6] != "recent":
|
|
tag = f"{tag}+shape"
|
|
if len(spec) > 7 and spec[7] != "distance":
|
|
tag = f"{tag}+dissim"
|
|
if len(spec) > 9 and spec[9] != "none":
|
|
# every extrapolation mode must be distinguishable in a results file
|
|
tag = f"{tag}+" + {"steps": "ext", "confirmed": "extC", "pattern": "extP",
|
|
"steps+results": "extR"}[spec[9]]
|
|
if len(spec) > 8 and spec[8] != "none":
|
|
# the exponent must be visible in the label: (far, none) is false position and
|
|
# (far, order) is the hypothesis, and a results file that cannot tell them apart
|
|
# is worthless
|
|
tag = f"{tag}+ord"
|
|
if len(spec) > 5 and spec[5] != "none":
|
|
# name the gate by WHICH gate it is: "progress" is a measured negative and must
|
|
# never be confused with "slope" in a results file
|
|
tag = f"{tag}+{spec[5]}" if tag != "pure" else spec[5]
|
|
return f"{tag}.{spec[1]}.{spec[2]}.{spec[3]}"
|
|
|
|
|
|
def evaluate(spec):
|
|
"""Run one configuration over all 199 problems. Returns a plain dict so
|
|
it can cross the process boundary."""
|
|
method = make_method(spec)
|
|
probs = load_problems()
|
|
res = {"label": label(spec), "spec": list(spec)}
|
|
for setname in ("APS", "CHA"):
|
|
total = solved = over = 0
|
|
n_probs = 0
|
|
per = {}
|
|
for s, pid, f, a, b, root in probs:
|
|
if s != setname:
|
|
continue
|
|
n_probs += 1
|
|
try:
|
|
x, n, conv = method(f, a, b, XTOL, MAXFEV)
|
|
except Exception:
|
|
x, n, conv = float("nan"), MAXFEV, False
|
|
# scipy hands back numpy scalars, whose booleans are numpy.bool_
|
|
# and do not serialise; coerce at the boundary rather than at the
|
|
# dump, so nothing numpy-shaped survives into the results
|
|
ok = bool(conv and math.isfinite(x) and abs(x - root) <= ACC)
|
|
n = int(n)
|
|
total += n if ok else MAXFEV
|
|
per[pid] = [n, ok]
|
|
if ok:
|
|
solved += 1
|
|
if n > 2 * math.ceil(math.log2(abs(b - a) / XTOL)) + 4:
|
|
over += 1
|
|
res[setname] = {"total": total, "solved": solved, "n": n_probs,
|
|
"over": over, "per": per}
|
|
return res
|
|
|
|
|
|
def _preflight_log_mode():
|
|
"""Fail LOUDLY if the log mode is not actually available.
|
|
|
|
`evaluate` catches every exception and charges the full budget, so a stale
|
|
deployment (an old simroot/pure.py without `space`) looks exactly like a method
|
|
that solves nothing: on 2026-09-20 that produced a whole sweep of 39800 = 199 x
|
|
MAXFEV before the cause was found. One call up front turns that into an error."""
|
|
x, _n, ok = pure_root(lambda t: t - 1.0, 0.0, 3.0, 1e-10, 100,
|
|
similarity="ratio", scale="derived3", guard="credit",
|
|
space="log")
|
|
if not (ok and abs(x - 1.0) < 1e-8):
|
|
raise SystemExit("log mode preflight FAILED: the mode is present but does not solve "
|
|
"a linear problem — refusing to run a sweep that would report zeros")
|
|
|
|
|
|
def build_grid_log(smoke):
|
|
"""The logarithmic-space grid (PREREG 2026-09-20). Baselines are NOT recomputed:
|
|
their numbers are already in sweep_full.json and re-running known expensive
|
|
controls is waste. Only the derived scales are admissible in u-space."""
|
|
_preflight_log_mode()
|
|
sims = ["ratio", "cbrt"] if smoke else sorted(PURE_SIMS)
|
|
guards = ("credit", "project") if smoke else GUARD_MODES
|
|
return [("pure", sim, sc, gu, "log")
|
|
for sim in sims for sc in ("derived", "derived3") for gu in guards]
|
|
|
|
|
|
def _preflight_extrap_mode():
|
|
"""Fail LOUDLY if extrapolate is not deployed (see _preflight_log_mode)."""
|
|
x, _n, ok = pure_root(lambda t: t - 1.0, 0.0, 3.0, 1e-10, 100, similarity="ratio",
|
|
scale="derived3", guard="project", extrapolate="steps")
|
|
if not (ok and abs(x - 1.0) < 1e-8):
|
|
raise SystemExit("extrapolate preflight FAILED: refusing to report zeros")
|
|
|
|
|
|
def build_grid_flat(smoke, gate="flat"):
|
|
"""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').
|
|
`gate` may be a tuple: every gate in it gets its own cell next to the same 'none'
|
|
(PREREG_flat_stick: flatstick and its ablation flatstickmid in one grid)."""
|
|
gates = gate if isinstance(gate, tuple) else (gate,)
|
|
for gt in gates:
|
|
x, _n, ok = pure_root(lambda t: t - 1.0, 0.0, 3.0, 1e-10, 100, similarity="ratio",
|
|
scale="derived3", guard="project", prestep=gt)
|
|
if not (ok and abs(x - 1.0) < 1e-8):
|
|
raise SystemExit(f"prestep={gt} 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",) + gates:
|
|
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",) + gates:
|
|
specs.append(("pure", sim, "derived3", gu, "x", pre, "recent",
|
|
"distance", "none", "none"))
|
|
return specs
|
|
|
|
|
|
DEFCONTRA_PRESTEPS = (
|
|
"none", "defect", "contra", "flatanalog", "flatanalogmem",
|
|
"defect+contra", "defect+flatanalog", "defect+flatanalogmem", "contra+flatanalog",
|
|
"contra+flatanalogmem", "defect+contra+flatanalog", "defect+contra+flatanalogmem")
|
|
|
|
|
|
def build_grid_defcontra(smoke):
|
|
"""PREREG_defect_contra_flat_2026-09-21: every composite of the decision (defect), the
|
|
sign contradiction (contra) and the flat regime (flatanalog / flatanalogmem), on the
|
|
proposed rule with and without G2."""
|
|
for pre in DEFCONTRA_PRESTEPS[1:]:
|
|
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 DEFCONTRA_PRESTEPS]
|
|
|
|
|
|
ORDERPT_PRESTEPS = (
|
|
"none", "flatanalog", "flatanalogpt", "flatanalogmem", "flatanalogmempt",
|
|
"defect+flatanalogmem", "defect+flatanalogmempt",
|
|
"contra+flatanalogmem", "contra+flatanalogmempt")
|
|
|
|
|
|
def build_grid_orderpt(smoke):
|
|
"""PREREG_flat_order_point_2026-09-21: midpoint / point-from-order twins with the same
|
|
entry, on the proposed rule with and without G2."""
|
|
for pre in ORDERPT_PRESTEPS[1:]:
|
|
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 ORDERPT_PRESTEPS]
|
|
|
|
|
|
EXPLIMIT_BASES = ("flatanalogpt", "flatanalogmempt", "defect+flatanalogmempt",
|
|
"contra+flatanalogmempt")
|
|
|
|
|
|
def build_grid_explimit(smoke):
|
|
"""PREREG_flat_exp_limit_2026-09-21: every order-point variant without / with the
|
|
translation limit (m = inf), on the proposed rule with and without G2."""
|
|
presteps = ("none",) + tuple(p for b in EXPLIMIT_BASES for p in (b, b + "+exp"))
|
|
for pre in presteps[1:]:
|
|
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):
|
|
"""PREREG_extrapolation_gates_2026-09-21: the same cells as build_grid_extrap, every
|
|
one in all five modes (none, A, G1, G2, G3)."""
|
|
for mode in ("confirmed", "pattern", "steps+results"):
|
|
x, _n, ok = pure_root(lambda t: t - 1.0, 0.0, 3.0, 1e-10, 100, similarity="ratio",
|
|
scale="derived3", guard="project", extrapolate=mode)
|
|
if not (ok and abs(x - 1.0) < 1e-8):
|
|
raise SystemExit(f"extrapolate={mode} preflight FAILED: refusing to report zeros")
|
|
modes = ("none", "steps", "confirmed", "pattern", "steps+results")
|
|
return [s[:9] + (m,) for s in build_grid_extrap(smoke) if s[9] == "none" for m in modes]
|
|
|
|
|
|
def build_grid_extrap(smoke):
|
|
"""PREREG 2026-09-21: step extrapolation (A) inside the method, every cell as a pair
|
|
(none, steps). Tent with every reading and every guard; all nine functions without
|
|
readings, so the law across the grid is visible with and without A."""
|
|
_preflight_extrap_mode()
|
|
guards = ("project", "credit") if smoke else GUARD_MODES
|
|
readings = [("none", "recent", "distance")] if smoke else [
|
|
("none", "recent", "distance"), ("slope", "recent", "distance"),
|
|
("slope", "shape", "distance"), ("slope", "recent", "dissimilar"),
|
|
("defect", "recent", "distance")]
|
|
specs = []
|
|
for gu in guards:
|
|
for pre, pts, dirn in readings:
|
|
for ex in ("none", "steps"):
|
|
specs.append(("pure", "ratio", "derived3", gu, "x", pre, pts, dirn,
|
|
"none", ex))
|
|
sims = ["sqrt"] if smoke else [s for s in sorted(PURE_SIMS) if s != "ratio"]
|
|
for sim in sims:
|
|
for gu in guards:
|
|
for ex in ("none", "steps"):
|
|
specs.append(("pure", sim, "derived3", gu, "x", "none", "recent",
|
|
"distance", "none", ex))
|
|
return specs
|
|
|
|
|
|
def _preflight_decision_mode():
|
|
"""Fail LOUDLY if the decision readings are not deployed (see _preflight_log_mode)."""
|
|
for md in ("band", "defect", "simpair"):
|
|
x, _n, ok = pure_root(lambda t: t - 1.0, 0.0, 3.0, 1e-10, 100,
|
|
similarity="ratio", scale="derived3", guard="credit",
|
|
prestep=md)
|
|
if not (ok and abs(x - 1.0) < 1e-8):
|
|
raise SystemExit(f"decision-mode preflight FAILED for prestep={md}: "
|
|
"refusing to run a sweep that would report zeros")
|
|
|
|
|
|
def build_grid_decision(smoke):
|
|
"""Slot 2 of PREREG 2026-09-21: the DECISION place. One thing moves against the
|
|
published cells — the reading in the gate — so 'none' and 'slope' are in the grid as
|
|
its own controls. 'band' is Chandrupatla's rule and is an instrument, not a claim."""
|
|
_preflight_decision_mode()
|
|
sims = ["ratio", "rational"] if smoke else sorted(PURE_SIMS)
|
|
guards = ("credit", "safe") if smoke else GUARD_MODES
|
|
modes = ("none", "slope", "band", "defect", "simpair")
|
|
return [("pure", sim, "derived3", gu, "x", md, "recent", "distance", "none")
|
|
for sim in sims for md in modes for gu in guards]
|
|
|
|
|
|
def _preflight_order_mode():
|
|
"""Fail LOUDLY if the per-place reading is not actually deployed.
|
|
|
|
Same lesson as _preflight_log_mode: `evaluate` swallows every exception and charges
|
|
MAXFEV, so a stale simroot/pure.py on the server reports a sweep of zeros instead of
|
|
an error. Checks BOTH new things — the far scale and the order exponent."""
|
|
for sc, ex in (("far", "none"), ("far", "order"), ("derived3", "order")):
|
|
x, _n, ok = pure_root(lambda t: t - 1.0, 0.0, 3.0, 1e-10, 100,
|
|
similarity="rational", scale=sc, guard="credit",
|
|
exponent=ex)
|
|
if not (ok and abs(x - 1.0) < 1e-8):
|
|
raise SystemExit(f"order-mode preflight FAILED for scale={sc} exponent={ex}: "
|
|
"refusing to run a sweep that would report zeros")
|
|
|
|
|
|
def build_grid_order(smoke):
|
|
"""Slot 1 of PREREG 2026-09-21: the similarity function read BY PLACE.
|
|
|
|
The exponent is the only thing that moves inside each (similarity, scale, guard)
|
|
triple, so (far, none) — which is false position exactly, Proposition 4 — is the
|
|
control for (far, order). Baselines are not recomputed; they are in sweep_full.json."""
|
|
_preflight_order_mode()
|
|
sims = ["rational", "ratio"] if smoke else sorted(PURE_SIMS)
|
|
guards = ("credit", "safe") if smoke else GUARD_MODES
|
|
return [("pure", sim, sc, gu, "x", "none", "recent", "distance", ex)
|
|
for sim in sims for sc in ("far", "derived3")
|
|
for ex in ("none", "order") for gu in guards]
|
|
|
|
|
|
def build_grid_cap(smoke):
|
|
"""Scale as a SELECTION between the two computed ones (PREREG 2026-09-21): identical to
|
|
the slope+dissimilar configuration except scale = derived3_cap, so one thing changes."""
|
|
sims = ["ratio", "sqrt"] if smoke else sorted(PURE_SIMS)
|
|
guards = ("credit", "safe") if smoke else GUARD_MODES
|
|
return [("pure", sim, "derived3_cap", gu, "x", "slope", "recent", "dissimilar")
|
|
for sim in sims for gu in guards]
|
|
|
|
|
|
def build_grid_combo(smoke):
|
|
"""A+B together (PREREG 2026-09-21 §2: licensed only because each mode alone improved
|
|
APS — A 2527 and B 2726 against the published 2806)."""
|
|
sims = ["ratio", "sqrt"] if smoke else sorted(PURE_SIMS)
|
|
guards = ("credit", "project") if smoke else GUARD_MODES
|
|
return [("pure", sim, "derived3", gu, "x", "slope", "shape", "dissimilar")
|
|
for sim in sims for gu in guards]
|
|
|
|
|
|
def build_grid_points(smoke):
|
|
"""Mode A (PREREG 2026-09-21): the triple chosen by shape, on top of the slope gate that
|
|
already reached the project target. Three-point scale only — a triple must exist."""
|
|
sims = ["ratio", "sqrt"] if smoke else sorted(PURE_SIMS)
|
|
guards = ("credit", "project") if smoke else GUARD_MODES
|
|
return [("pure", sim, "derived3", gu, "x", "slope", "shape", "distance")
|
|
for sim in sims for gu in guards]
|
|
|
|
|
|
def build_grid_direction(smoke):
|
|
"""Mode B (PREREG 2026-09-21): the far end read by dissimilarity, on top of the slope gate."""
|
|
sims = ["ratio", "sqrt"] if smoke else sorted(PURE_SIMS)
|
|
guards = ("credit", "project") if smoke else GUARD_MODES
|
|
return [("pure", sim, sc, gu, "x", "slope", "recent", "dissimilar")
|
|
for sim in sims for sc in ("derived", "derived3") for gu in guards]
|
|
|
|
|
|
def build_grid_slope(smoke):
|
|
"""The slope-stability gate grid (PREREG 2026-09-21). Only derived scales: there must be
|
|
a slope to judge. Baselines are not recomputed — they are in sweep_full.json."""
|
|
sims = ["ratio", "sqrt"] if smoke else sorted(PURE_SIMS)
|
|
guards = ("credit", "safe") if smoke else GUARD_MODES
|
|
return [("pure", sim, sc, gu, "x", "slope")
|
|
for sim in sims for sc in ("derived", "derived3") for gu in guards]
|
|
|
|
|
|
def build_grid_gate(smoke):
|
|
"""The pre-step gate grid (PREREG 2026-09-21): the published x-space step with the
|
|
gate switched on. Baselines are not recomputed - they are already in sweep_full.json."""
|
|
sims = ["ratio", "sqrt"] if smoke else sorted(PURE_SIMS)
|
|
guards = ("credit", "safe") if smoke else GUARD_MODES
|
|
return [("pure", sim, sc, gu, "x", "progress")
|
|
for sim in sims for sc in ("derived", "derived3") for gu in guards]
|
|
|
|
|
|
def build_grid(smoke):
|
|
specs = [("base", nm) for nm in BASELINES]
|
|
sims = sorted(PURE_SIMS)
|
|
scales = SCALES
|
|
guards = GUARD_MODES
|
|
if smoke:
|
|
sims = ["ratio", "exp_abs"]
|
|
scales = ("derived", "derived3")
|
|
guards = ("step", "both")
|
|
specs = [("base", nm) for nm in ("bisection", "brent", "toms748")]
|
|
for sim in sims:
|
|
for sc in scales:
|
|
for gu in guards:
|
|
specs.append(("pure", sim, sc, gu))
|
|
return specs
|
|
|
|
|
|
def main():
|
|
smoke = "--smoke" in sys.argv
|
|
logmode = "--log" in sys.argv # the u-space grid, written to its OWN file
|
|
gatemode = "--gate" in sys.argv # the pre-step gate grid, likewise
|
|
slopemode = "--slope" in sys.argv # the slope-stability gate grid
|
|
capmode = "--cap" in sys.argv # scale selected between the two computed ones
|
|
ordermode = "--order" in sys.argv # slot 1: the similarity read BY PLACE
|
|
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
|
|
flat2mode = "--flat2" in sys.argv # the flat gate, promise failed twice
|
|
creepmode = "--flatcreep" in sys.argv # the flat gate AND a creep
|
|
stickmode = "--flatstick" in sys.argv # the sticky flat regime + its midpoint ablation
|
|
exitmode = "--flatexit" in sys.argv # the sticky regime with an exit by similarity
|
|
judgemode = "--flatjudge" in sys.argv # one similarity judgment at entry and exit
|
|
analogmode = "--flatanalog" in sys.argv # entry by analogy with the run's own past
|
|
memmode = "--flatanalogmem" in sys.argv # the analogy remembered as a property of the run
|
|
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
|
|
expmode = "--explimit" in sys.argv # the translation limit of the analogy, m = inf
|
|
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_explimit(smoke) if expmode else
|
|
build_grid_orderpt(smoke) if ptmode else
|
|
build_grid_defcontra(smoke) if dcmode else
|
|
build_grid_flat(smoke, ("flatanalogmem", "flatanalog")) if memmode else
|
|
build_grid_flat(smoke, ("flatanalog", "flatstickexit")) if analogmode else
|
|
build_grid_flat(smoke, ("flatjudge", "flatstickexit")) if judgemode else
|
|
build_grid_flat(smoke, ("flatstickexit", "flatstickmid")) if exitmode else
|
|
build_grid_flat(smoke, ("flatstick", "flatstickmid")) if stickmode else
|
|
build_grid_flat(smoke, "flatcreep") if creepmode else
|
|
build_grid_flat(smoke, "flat2") if flat2mode else
|
|
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
|
|
build_grid_cap(smoke) if capmode else
|
|
build_grid_combo(smoke) if combomode else
|
|
build_grid_points(smoke) if pointsmode else
|
|
build_grid_direction(smoke) if dirmode else
|
|
build_grid_slope(smoke) if slopemode else
|
|
build_grid_gate(smoke) if gatemode else
|
|
build_grid_log(smoke) if logmode else build_grid(smoke))
|
|
t0 = time.time()
|
|
print(f"sweep: {len(specs)} configurations x 199 problems "
|
|
f"({'SMOKE' if smoke else 'FULL'}{', LOG-SPACE' if logmode else ''})", flush=True)
|
|
|
|
workers = max(1, min(8, (os.cpu_count() or 2) - 1))
|
|
with Pool(workers) as pool:
|
|
results = []
|
|
for i, r in enumerate(pool.imap_unordered(evaluate, specs), 1):
|
|
results.append(r)
|
|
if i % 10 == 0 or i == len(specs):
|
|
print(f" {i}/{len(specs)} done, "
|
|
f"{time.time() - t0:.0f}s elapsed", flush=True)
|
|
|
|
# the published sweep_full.json is what verify_article.py checks the paper
|
|
# 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:
|
|
base = ("sweep_explimit" if expmode else
|
|
"sweep_orderpt" if ptmode else
|
|
"sweep_defcontra" if dcmode else
|
|
"sweep_flatanalogmem" if memmode else
|
|
"sweep_flatanalog" if analogmode else
|
|
"sweep_flatjudge" if judgemode else
|
|
"sweep_flatexit" if exitmode else
|
|
"sweep_flatstick" if stickmode else
|
|
"sweep_flatcreep" if creepmode else
|
|
"sweep_flat2" if flat2mode else
|
|
"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
|
|
"sweep_cap" if capmode else
|
|
"sweep_combo" if combomode else
|
|
"sweep_points" if pointsmode else "sweep_direction")
|
|
out = f"{base}_smoke.json" if smoke else f"{base}.json"
|
|
with open(out, "w", encoding="utf8") as fh:
|
|
json.dump(results, fh)
|
|
print(f"wrote {out} ({time.time() - t0:.0f}s total)", flush=True)
|
|
report(results)
|
|
return
|
|
if slopemode:
|
|
out = "sweep_slope_smoke.json" if smoke else "sweep_slope.json"
|
|
with open(out, "w", encoding="utf8") as fh:
|
|
json.dump(results, fh)
|
|
print(f"\nwrote {out} ({time.time() - t0:.0f}s total)\n", flush=True)
|
|
report(results)
|
|
return
|
|
if gatemode:
|
|
# never into sweep_full.json: that file is what verify_article.py checks the
|
|
# paper against, and the smoke run of 2026-09-21 did land in sweep_smoke.json
|
|
# before this branch existed
|
|
out = "sweep_gate_smoke.json" if smoke else "sweep_gate.json"
|
|
with open(out, "w", encoding="utf8") as fh:
|
|
json.dump(results, fh)
|
|
print(f"\nwrote {out} ({time.time() - t0:.0f}s total)\n", flush=True)
|
|
report(results)
|
|
return
|
|
out = ("sweep_log_smoke.json" if smoke else "sweep_log.json") if logmode else \
|
|
("sweep_smoke.json" if smoke else "sweep_full.json")
|
|
with open(out, "w", encoding="utf8") as fh:
|
|
json.dump(results, fh)
|
|
print(f"\nwrote {out} ({time.time() - t0:.0f}s total)\n", flush=True)
|
|
report(results)
|
|
|
|
|
|
def report(results, top=20):
|
|
for setname in ("APS", "CHA"):
|
|
rows = sorted(results,
|
|
key=lambda r: (r[setname]["n"] - r[setname]["solved"],
|
|
r[setname]["total"]))
|
|
n = rows[0][setname]["n"]
|
|
print("=" * 84)
|
|
print(f"{setname}: {n} problems (top {top} of {len(rows)})")
|
|
print("=" * 84)
|
|
print(f"{'configuration':40s}{'solved':>9s}{'total fev':>12s}"
|
|
f"{'over 2x':>9s}")
|
|
print("-" * 84)
|
|
for r in rows[:top]:
|
|
d = r[setname]
|
|
print(f"{r['label']:40s}{d['solved']:>6d}/{d['n']:<3d}"
|
|
f"{d['total']:>12d}{d['over']:>9d}")
|
|
print()
|
|
|
|
# the law of stage 0c, tested across the whole grid: similarities whose
|
|
# (1 - S) has zero slope at 0 must be the slow ones whenever the scale is
|
|
# chosen rather than derived.
|
|
print("=" * 84)
|
|
print("THE STAGE-0C LAW ACROSS THE GRID")
|
|
print("=" * 84)
|
|
quad = ("rat_sq", "exp_sq", "cosine") # (1-S) ~ c2*z^2, slope c = 0
|
|
lin = ("ratio", "rational", "exp_abs") # (1-S) ~ z, slope c = 1
|
|
for scale in SCALES:
|
|
for group, name in ((lin, "slope c=1 (linear)"),
|
|
(quad, "slope c=0 (quadratic)")):
|
|
tot = solved = cnt = 0
|
|
for r in results:
|
|
if r["spec"][0] != "pure":
|
|
continue
|
|
sim, sc, gu = r["spec"][1], r["spec"][2], r["spec"][3]
|
|
if sc != scale or gu != "step" or sim not in group:
|
|
continue
|
|
cnt += 1
|
|
tot += r["APS"]["total"] + r["CHA"]["total"]
|
|
solved += r["APS"]["solved"] + r["CHA"]["solved"]
|
|
if cnt:
|
|
print(f" scale={scale:9s} {name:26s} "
|
|
f"mean total {tot / cnt:9.0f} "
|
|
f"mean solved {solved / cnt:6.1f}/199")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|