two more places for similarity: points='shape' (WHICH triple the model uses, argmin |phi-xi| over declared candidates — select, never weight) and direction='dissimilar' (the far end read by |f| rather than by distance); defaults bit-identical, P1-P5 pinned (7 green), inertness counters make an inert mode a failed EXPERIMENT rather than a pass; each grid writes to its own file

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
vvs
2026-09-20 23:39:41 +01:00
co-authored by Claude Opus 5
parent e4769be9a3
commit 04ee5c89b9
6 changed files with 320 additions and 8 deletions
+87 -6
View File
@@ -121,6 +121,47 @@ GUARDS = ("none", "bracket", "step", "both", "project", "safe", "credit")
SPACES = ("x", "log")
POINT_RULES = ("recent", "shape")
DIRECTIONS = ("distance", "dissimilar")
def _shape_defect(x, fx, u, fu, v, fv):
"""|phi - xi| for the triple, or None when it is degenerate.
xi = (x - u)/(v - u) is a ratio of POSITIONS, phi = (fx - fu)/(fv - fu) a ratio of
VALUES; both are invariant under affine rescaling of x and of f. For a linear f they
are equal, so their gap measures how unlike a linear configuration the triple is —
the same dimensionless currency Chandrupatla's acceptance band is written in."""
if v == u or fv == fu:
return None
xi = (x - u) / (v - u)
ph = (fx - fu) / (fv - fu)
if not (math.isfinite(xi) and math.isfinite(ph)):
return None
return abs(ph - xi)
def _pick_triple(x, fx, x_prev, f_prev, x_prev2, f_prev2, A, FA, B, FB, far):
"""SELECT the triple whose configuration is least unlike a linear one (PREREG
2026-09-21, mode A). Candidates are declared, not searched: the recency triple, the
recent point with the far bracket end, and the two proven bracket ends. Returns
((xu, fu), (xv, fv)) or None when nothing is admissible."""
far_f = FB if far == B else FA
cands = (((x_prev, f_prev), (x_prev2, f_prev2)),
((x_prev, f_prev), (far, far_f)),
((A, FA), (B, FB)))
best, best_d = None, None
for u, v in cands:
if u[0] is None or v[0] is None:
continue
d = _shape_defect(x, fx, u[0], u[1], v[0], v[1])
if d is None or x == u[0] or x == v[0]:
continue
if best_d is None or d < best_d:
best, best_d = (u, v), d
return best
def _log_map(t, c, s):
"""u = sign(t - c) * log1p(|t - c| / s). An ADDITIVE step in u is a
MULTIPLICATIVE step in x, which is what the wide-bracket families need: the
@@ -413,7 +454,8 @@ def _local_order(x2, f2, x1, f1, x0, f0):
def pure_root(f, a, b, xtol, maxfev, similarity="ratio", scale="derived",
guard="step", stats=None, budget_factor=2.0,
budget_extra=None, endowment=1.0, space="x", prestep="none"):
budget_extra=None, endowment=1.0, space="x", prestep="none",
points="recent", direction="distance"):
"""The pure similarity root finder.
similarity : key into PURE_SIMS
@@ -469,6 +511,14 @@ def pure_root(f, a, b, xtol, maxfev, similarity="ratio", scale="derived",
raise ValueError(f"unknown space {space!r}")
if prestep not in ("none", "progress", "slope"):
raise ValueError(f"unknown prestep {prestep!r}")
if points not in POINT_RULES:
raise ValueError(f"unknown points rule {points!r}")
if direction not in DIRECTIONS:
raise ValueError(f"unknown direction {direction!r}")
if points == "shape" and scale not in ("derived3", "derived3_rho", "derived3_m"):
# the triple only exists for the three-point scale; selecting one under a
# two-point scale would change nothing and hide that
raise ValueError("points='shape' requires a three-point scale (derived3*)")
if prestep == "slope" and scale not in ("derived", "derived3"):
# there is no slope to judge under a chosen or bracket scale; judging something
# else would hide that, so the call fails instead
@@ -501,11 +551,15 @@ def pure_root(f, a, b, xtol, maxfev, similarity="ratio", scale="derived",
sg.credit = endowment
forced = 0
pre_refused = 0
triple_changed = 0
dir_changed = 0
slope = 0.0
slope_prev = None
if stats is not None:
stats['forced'] = 0
stats['pre_refused'] = 0
stats['triple_changed'] = 0
stats['dir_changed'] = 0
while abs(B - A) > xtol:
if sg.bisect_before_step(abs(B - A)):
@@ -516,11 +570,38 @@ def pure_root(f, a, b, xtol, maxfev, similarity="ratio", scale="derived",
sg.note_step(x_new - x)
else:
far = B if abs(B - x) >= abs(A - x) else A
if direction == "dissimilar":
# PREREG 2026-09-21, mode B: the far end read by SIMILARITY instead of
# geometry — the end whose |f| is larger is the one LESS similar to zero,
# i.e. the one the root is further from. Two values already in hand are
# compared; no constant.
far_sim = B if abs(FB) >= abs(FA) else A
if far_sim != far:
dir_changed += 1
far = far_sim
if scale in ("derived", "derived_rho"):
slope = ((fx - f_prev) / (x - x_prev)) if x != x_prev else 0.0
sc = abs(slope) * abs(far - x)
elif scale in ("derived3", "derived3_rho", "derived3_m"):
slope = _slope3(x, fx, x_prev, f_prev, x_prev2, f_prev2)
if points == "shape":
# PREREG 2026-09-21, mode A: which THREE points the model is built
# on, chosen by the SHAPE of the configuration instead of by recency.
# For a linear f the position ratio and the value ratio coincide, so
# |phi - xi| is a dimensionless measure of how unlike a linear
# configuration a triple is; the triple minimising it is SELECTED
# (the corpus rule is select, never weight). argmin over the declared
# candidates needs no threshold.
pick = _pick_triple(x, fx, x_prev, f_prev, x_prev2, f_prev2,
A, FA, B, FB, far)
if pick is None:
slope = _slope3(x, fx, x_prev, f_prev, x_prev2, f_prev2)
else:
(xu, fu), (xv, fv) = pick
if xu != x_prev or xv != x_prev2:
triple_changed += 1
slope = _slope3(x, fx, xu, fu, xv, fv)
else:
slope = _slope3(x, fx, x_prev, f_prev, x_prev2, f_prev2)
sc = abs(slope) * abs(far - x)
if scale == "derived3_m":
# REFUTED as an improvement - kept for reproducibility.
@@ -665,7 +746,7 @@ def pure_root(f, a, b, xtol, maxfev, similarity="ratio", scale="derived",
if x_new == x or x_new == x_prev:
# the bracket can no longer be split in floating point
if stats is not None:
stats['forced'] = forced; stats['pre_refused'] = pre_refused
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
w_before = abs(B - A)
@@ -677,7 +758,7 @@ def pure_root(f, a, b, xtol, maxfev, similarity="ratio", scale="derived",
x, fx = x_new, fnew
if fnew == 0.0:
if stats is not None:
stats['forced'] = forced; stats['pre_refused'] = pre_refused
stats['forced'] = forced; stats['pre_refused'] = pre_refused; stats['triple_changed'] = triple_changed; stats['dir_changed'] = dir_changed
return x_new, g.n, True
if FA * fnew < 0.0:
B, FB = x_new, fnew
@@ -686,9 +767,9 @@ def pure_root(f, a, b, xtol, maxfev, similarity="ratio", scale="derived",
if guard == "credit":
sg.note_shrink(w_before, abs(B - A))
if stats is not None:
stats['forced'] = forced; stats['pre_refused'] = pre_refused
stats['forced'] = forced; stats['pre_refused'] = pre_refused; stats['triple_changed'] = triple_changed; stats['dir_changed'] = dir_changed
return 0.5 * (A + B), g.n, True
except _Budget:
if stats is not None:
stats['forced'] = forced; stats['pre_refused'] = pre_refused
stats['forced'] = forced; stats['pre_refused'] = pre_refused; stats['triple_changed'] = triple_changed; stats['dir_changed'] = dir_changed
return x, g.n, False