Slot 2, the decision place: Chandrupatla's own acceptance band, put inside our step rule as an instrument, does NOT close the gap - CHA 3066 (project) / 2899 (credit) against his 2423, while APS doubles 2806 -> 5432, and the band is not idle (63.6% refusals). The fifth independent test of one conclusion: the remaining gap is the ORDER of the model the step is built on, not the place the similarity is read in. By the declared stop rule (M1 and M2 both false) the 'where is the similarity read' line is closed: all four places measured.

Not empty-handed: our own parameter-free reading 'defect' - refuse when |phi - xi| > min(xi, 1 - xi) - sets a new canonical best, APS 2523 at 153/154 (previous 2527, Chandrupatla 2785), guarantee intact (0 of 135 family cells), refusing on 7.0% of steps. It is a second point on the same trade, not a replacement: 5733 over both sets against 5511, because CHA gives back 3210. Also: _shape_ratios crashed on a missing third point, which evaluate would have turned into a silent sweep of zeros; the slope-gate pin was anchored on line spelling; and the server copy had drifted (stale relax/sor.py, test_relaxation.py absent - 746 tests instead of 755). All synced, 92/92 files identical by content, 755 pass on the server.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
vvs
2026-09-21 06:58:59 +01:00
co-authored by Claude Opus 5
parent 15b94242e0
commit 2357379c2d
15 changed files with 601 additions and 14 deletions
+44
View File
@@ -0,0 +1,44 @@
# FINDINGS — слот 2: похожесть в МЕСТЕ РЕШЕНИЯ
Пред-регистрация: `PREREG_decision_place_2026-09-21.md`. Сетка: 315 конфигураций × 199 задач,
сервер 161, `sweep_decision.json`, лог `results_sweep_decision.txt`. Якорь: `pure.ratio.derived3.project`
воспроизводит опубликованное 2806. Все числа ниже сверены `verify_article.py` на Linux.
## Вердикты
| # | предсказание | вердикт |
|---|---|---|
| **M1** | полоса Чандрупатлы в нашем шаге даёт CHA < 2683 | **ЛОЖНА** — 3066 (project), 2899 (credit); APS 2806 → **5432** |
| **M2** | наше чтение даёт CHA < 2683 | **ЛОЖНА** — лучшее 2868 (`simpair.ratio_soft.project`) |
| **M3** | APS не хуже 2527 | **ВЕРНА, и лучше** — `defect` даёт **2523** |
| **M4** | гарантия цела | **ВЕРНА** — 0 нарушений из 135 ячеек семейства |
| **M5** | чтения реально решают | **ВЕРНА** — defect 7.0%, simpair 26.8%, band 63.6%; контроль none 0.0% |
## Главное: место решения разрыва не держит
Собственная полоса приёма Чандрупатлы, вставленная в наш шаг, **не приближает** нас к его 2423 на
широких скобках и **удваивает** цену на канонических. Полоса не простаивает — отказывает на 63.6% шагов,
— значит, решение принималось и не окупилось. Это **пятое независимое подтверждение** одной причины:
остаток разрыва есть **порядок модели**, на которой построен шаг, а не место, где читается похожесть.
## Приобретение: новый рекорд на APS
`defect.ratio.derived3.project`: **153/154, 2523**, over2x = 0, ноль констант. Правило: делить, если
`|φ−ξ| > min(ξ, 1−ξ)` — конфигурация менее похожа на линейную, чем точка смещена от центра. Отказывает
на 7.0% шагов, реже всех трёх чтений.
⚠️ Это **вторая точка того же обмена**, а не замена: на двух наборах 5733 против 5511, потому что CHA
3210 против 2683.
## По правилу остановки
M1 и M2 обе ложны ⇒ **линия «где стоит похожесть» закрыта полностью.** Измерены все четыре места:
длина шага (слот 1), направление (dissimilar), точки модели (shape), решение (слот 2).
## Найдено по ходу
- `_shape_ratios` падал на `None` в третьей точке (первые шаги); `evaluate` превратил бы это в тихую
сетку нулей. Исправлено в единственном определении, закреплено тестом.
- Пин `test_T2_the_gate_carries_no_constant` был привязан к написанию строки; переведён на условие.
- Регрессия, запущенная в переднем плане по ssh, умерла вместе с соединением. Теперь только
`run_regression.sh` через `setsid nohup` с маркером конца.
+69
View File
@@ -0,0 +1,69 @@
# PREREG — слот 2: похожесть в МЕСТЕ РЕШЕНИЯ (доверять модели или делить)
Составлено до прогона. Продолжение `PREREG_similarity_per_slot_2026-09-21.md` §4; слот 1 уже измерен
(`FINDINGS_similarity_per_slot.md`), и его результат сюда не переносится.
## 1. Почему именно это место
Измеренная причина всего остатка разрыва: **порядок модели** — 0.93 половинения на пробу против 2.26
у Чандрупатлы. Пять беспараметрических обходов в *месте длины шага* провалились. Но Чандрупатла
выигрывает не длиной шага: он **отказывается** от своей модели на 72% шагов, по безразмерной полосе
приёма
1 − √(1 − ξ) < φ < √ξ, ξ = (x−u)/(v−u), φ = (f(x)−f(u))/(f(v)−f(u))
У нас в этом месте похожести **нет вовсе**: знаковый гейт по наклону (слот 1 прошлой сессии) и
проекция предохранителя, то есть ремонт **после** шага. Это последнее непроверенное место, где
похожесть могла бы стоять.
## 2. Что читается в этом месте (все чтения безразмерны и без констант)
`ξ` и `φ` — отношения ПОЛОЖЕНИЙ и ЗНАЧЕНИЙ в тройке; для линейной `f` они равны. Оба инвариантны к
аффинному масштабированию `x` и `f`, то есть это та же безразмерная валюта, в которой написана полоса
Чандрупатлы.
| режим | правило | чей |
|---|---|---|
| `prestep="band"` | делить, если `φ` вне `(1−√(1−ξ), √ξ)` | **ЧАНДРУПАТЛЫ, 1997** — диагностика, не наша заявка |
| `prestep="defect"` | делить, если `|φ−ξ| > min(ξ, 1−ξ)` | наше: дефект линейности против смещения от центра, обе величины посчитаны |
| `prestep="simpair"` | делить, если `S(|φ−ξ|) < S(z)` | наше: похожесть конфигурации на линейную против похожести точки к корню |
Никакого меню: `simpair` берёт **ту же** `S`, что и шаг, — минимальный выбор, а не подбор пары
функций по месту. Перебор `S` по местам остался бы тем же изъяном, что жёсткая константа.
## 3. Зачем в сетке чужое чтение
`band` — **измерительный прибор, а не предложение**. Он отвечает на один вопрос: лежит ли остаток
разрыва в месте решения. Если наш шаг с ЕГО полосой закрывает разрыв — место найдено, и дальше
осмысленно искать своё беспараметрическое чтение. Если не закрывает — место решения тоже не держит
разрыв, и вывод «дело в порядке модели» усиливается пятой независимой проверкой. В статью `band`
может войти только под именем Чандрупатлы.
## 4. Точка отсчёта и цели
| величина | текущее | цель |
|---|---|---|
| APS-154 | 2527 (лучшее наше) | **≤ 2527** |
| CHA-45 по-наборно | 2683 | **< 2683**, Chandrupatla 2423 |
| два набора | 5511 | **< 5511** |
| решено | 193/199 | ≥ 193 |
| гарантия `over2x` | 0 | **0** в семействе гарантии (project/safe/credit) |
## 5. Предсказания и фальсификаторы
| # | Предсказание | ФАЛЬСИФИКАТОР → вывод |
|---|---|---|
| **M1** | с чужой полосой (`band`) CHA опускается ниже 2683 | не опускается → **место решения разрыва не держит**; пятое независимое подтверждение, что дело в порядке модели, и линия закрывается по правилу остановки |
| **M2** | хотя бы одно НАШЕ чтение (`defect`/`simpair`) даёт CHA < 2683 | ни одно → своего беспараметрического чтения в этом месте нет; `band` остаётся чужим и в статью как наше не идёт |
| **M3** | APS не хуже 2527 | хуже → обмен «широкие за счёт узких», шестой раз |
| **M4** | гарантия цела | нарушена → немедленное закрытие |
| **M5** | чтение реально РЕШАЕТ: доля отказов не 0% и не 100% | ~0% или ~100% → это не решение, а переобозначение; результат ячейки ничего не значит и так и пишется |
**Правило остановки:** M1 и M2 ложны ⇒ **линия «где стоит похожесть» закрывается полностью**: все
четыре места (длина, направление, точки модели, решение) измерены, и остаток разрыва объяснён
порядком модели, а не размещением. M1 верна, M2 ложна ⇒ место найдено, но своего чтения нет — это
открытая задача, а не результат.
🔴 **Запрет:** `band` нельзя ни назвать нашим, ни оставить в предлагаемом методе. Он входит в прогон
как контроль и выходит либо в диагностику, либо в «Отрицательные результаты» со ссылкой на
Chandrupatla 1997.
+83
View File
@@ -0,0 +1,83 @@
"""Verdicts M1-M5 for PREREG 2026-09-21 slot 2 (the DECISION place).
python -u analyze_decision.py
"""
from __future__ import annotations
import json
import math
from scipy.optimize._tstutils import (_APS_TESTS_DICTS,
_CHANDRUPATLA_TESTS_DICTS)
from simroot.pure import pure_root
REF = {"APS": 2527, "CHA": 2683, "BOTH": 5511, "CHA_theirs": 2423, "APS_theirs": 2785}
MODES = ("none", "slope", "band", "defect", "simpair")
FAMILY = ("project", "safe", "credit")
def main():
with open("sweep_decision.json", encoding="utf8") as fh:
res = json.load(fh)
by = {(r["spec"][1], r["spec"][5], r["spec"][3]): r for r in res}
print("M1/M2 the readings, ratio similarity, per guard "
"(band is CHANDRUPATLA'S rule, not ours)")
print(f"{'guard':<9} " + " ".join(f"{m:>17}" for m in MODES))
for gu in ("none", "step", "bracket", "both", "project", "safe", "credit"):
cells = []
for m in MODES:
r = by.get(("ratio", m, gu))
cells.append(f"{r['APS']['total']:7d}/{r['CHA']['total']:<5d}"
f"{r['APS']['solved'] + r['CHA']['solved']:>4}" if r else " " * 17)
print(f"{gu:<9} " + " ".join(cells))
print(" (cells are APS/CHA solved-of-199)\n")
print("Best per set by the paper's rule, restricted to the GUARANTEE family")
for setname in ("APS", "CHA"):
rows = [r for r in res if r["spec"][3] in FAMILY]
rows.sort(key=lambda r: (r[setname]["n"] - r[setname]["solved"], r[setname]["total"]))
for r in rows[:4]:
print(f" {setname} {r['label']:<34} {r[setname]['solved']}/{r[setname]['n']} "
f"{r[setname]['total']:6d} over2x={r[setname]['over']} "
f"(ours {REF[setname]}, theirs {REF[setname + '_theirs']})")
print("\nBoth sets, guarantee family")
rows = [r for r in res if r["spec"][3] in FAMILY]
rows.sort(key=lambda r: (398 - r["APS"]["solved"] - r["CHA"]["solved"],
r["APS"]["total"] + r["CHA"]["total"]))
for r in rows[:4]:
print(f" {r['label']:<34} {r['APS']['solved'] + r['CHA']['solved']}/199 "
f"{r['APS']['total'] + r['CHA']['total']:6d} (reference {REF['BOTH']})")
print("\nM4 guarantee violations inside the family: ", end="")
fam = [r for r in res if r["spec"][3] in FAMILY]
print(sum(r["APS"]["over"] + r["CHA"]["over"] for r in fam), f"of {len(fam)} cells")
print("\nM5 does each reading actually DECIDE? refusals / evaluations, "
"over both benchmark sets")
probs = [(float(d["bracket"][0]), float(d["bracket"][1]),
(lambda ff, aa: lambda t: ff(t, *aa))(d["f"], d.get("args", ())))
for d in _APS_TESTS_DICTS]
probs += [(float(d["bracket"][0]), float(d["bracket"][1]),
(lambda ff: lambda t: ff(t))(d["f"])) for d in _CHANDRUPATLA_TESTS_DICTS]
for m in MODES:
ref = nfev = 0
for a, b, f in probs:
st = {}
try:
_x, n, _c = pure_root(f, a, b, 1e-12, 200, similarity="ratio",
scale="derived3", guard="project", prestep=m,
stats=st)
except Exception:
continue
ref += st.get("pre_refused", 0)
nfev += int(n)
rate = 100.0 * ref / max(nfev, 1)
verdict = "DECIDES" if 0.0 < rate < 100.0 else "RELABELLING — result meaningless"
print(f" {m:<9} {ref:6d}/{nfev:6d} = {rate:5.1f}% {verdict}")
if __name__ == "__main__":
main()
Binary file not shown.
+39
View File
@@ -624,6 +624,45 @@ the \emph{slope} reading the same exponent is harmful, $2806\to2854$, which is
the same statement read from the other side --- a function that does not belong the same statement read from the other side --- a function that does not belong
to a place does not become right by being applied there. to a place does not become right by being applied there.
\subsection{The decision place, and the one test that settles the gap}
\label{sec:decision}
Three places have now been measured: the step length, the far end, and the
points the model is built on. The fourth is the \emph{decision} --- whether the
local model deserves this evaluation or halving is the better use of it.
Chandrupatla's method is strong exactly there: it refuses its model on most
steps by the acceptance band $1-\sqrt{1-\xi}<\varphi<\sqrt{\xi}$, where
$\xi=(x-u)/(v-u)$ and $\varphi=(f(x)-f(u))/(f(v)-f(u))$ are ratios of positions
and of values, equal for a linear $f$. Our method has no similarity in this
place at all: a sign gate and a projection that repairs \emph{after} the step.
Three readings of that place were measured, each on quantities already in hand
and each without a constant. Two are ours: refuse when the configuration is
less like a linear one than the iterate is off-centre,
$|\varphi-\xi|>\min(\xi,1-\xi)$ (``defect''); and refuse when the
configuration's similarity to linear falls below the iterate's similarity to
the root, $S(|\varphi-\xi|)<S(z)$, with the \emph{same} $S$ in both places
(``simpair''). The third is \emph{Chandrupatla's own band}, placed inside our
step rule. It is not a proposal; it is an instrument, and it answers the only
question that matters here --- whether the remaining gap lives in this place.
It does not. With Chandrupatla's band in our step, the wide-bracket set costs
$3066$ under the projection guard and $2899$ under credit, against his $2423$,
while the canonical set rises from $2806$ to $5432$. The band is not idle ---
it refuses $63.6\%$ of steps --- so this is a decision that was taken and did
not pay. That is the fifth independent test of the same conclusion: the gap is
the \emph{order of the model} the step is built on, not the place where the
similarity is read.
Our own readings do not close it either (best $2868$ on the wide-bracket set),
but ``defect'' sets a new best on the canonical set: $\mathbf{2523}$ at
$153/154$, below the $2527$ of reading~(2) and below every method measured,
with the guarantee intact and no constant. It refuses only $7.0\%$ of steps,
the fewest of the three. Over both sets it costs $5733$ against the $5511$ of
reading~(3), because it gives back on the wide brackets ($3210$) what it gains
on the canonical problems --- so it is a second point on the same trade, not a
replacement.
\subsection{Six problems of the two sets are scored unsolved for every method} \subsection{Six problems of the two sets are scored unsolved for every method}
\label{sec:fun7} \label{sec:fun7}
+91
View File
@@ -0,0 +1,91 @@
sweep: 315 configurations x 199 problems (FULL)
10/315 done, 1s elapsed
20/315 done, 1s elapsed
30/315 done, 1s elapsed
40/315 done, 1s elapsed
50/315 done, 2s elapsed
60/315 done, 2s elapsed
70/315 done, 2s elapsed
80/315 done, 2s elapsed
90/315 done, 2s elapsed
100/315 done, 2s elapsed
110/315 done, 3s elapsed
120/315 done, 3s elapsed
130/315 done, 3s elapsed
140/315 done, 3s elapsed
150/315 done, 3s elapsed
160/315 done, 4s elapsed
170/315 done, 4s elapsed
180/315 done, 4s elapsed
190/315 done, 4s elapsed
200/315 done, 4s elapsed
210/315 done, 5s elapsed
220/315 done, 5s elapsed
230/315 done, 5s elapsed
240/315 done, 5s elapsed
250/315 done, 5s elapsed
260/315 done, 5s elapsed
270/315 done, 5s elapsed
280/315 done, 6s elapsed
290/315 done, 6s elapsed
300/315 done, 6s elapsed
310/315 done, 6s elapsed
315/315 done, 7s elapsed
wrote sweep_decision.json (7s total)
====================================================================================
APS: 154 problems (top 20 of 315)
====================================================================================
configuration solved total fev over 2x
------------------------------------------------------------------------------------
defect.ratio.derived3.none 153/154 2523 0
defect.ratio.derived3.project 153/154 2523 0
pure.ratio.derived3.none 153/154 2806 0
pure.ratio.derived3.project 153/154 2806 0
slope.ratio.derived3.none 153/154 2848 0
slope.ratio.derived3.project 153/154 2848 0
slope.ratio.derived3.step 153/154 3020 0
slope.ratio.derived3.safe 153/154 3020 0
pure.ratio.derived3.step 153/154 3036 0
pure.ratio.derived3.safe 153/154 3036 0
defect.ratio.derived3.step 153/154 3131 0
defect.ratio.derived3.safe 153/154 3131 0
defect.exp_abs.derived3.none 153/154 3262 0
defect.exp_abs.derived3.project 153/154 3262 0
pure.exp_abs.derived3.none 153/154 3264 0
pure.exp_abs.derived3.project 153/154 3264 0
pure.exp_abs.derived3.step 153/154 3312 0
pure.exp_abs.derived3.safe 153/154 3312 0
slope.exp_abs.derived3.step 153/154 3322 0
slope.exp_abs.derived3.safe 153/154 3322 0
====================================================================================
CHA: 45 problems (top 20 of 315)
====================================================================================
configuration solved total fev over 2x
------------------------------------------------------------------------------------
simpair.ratio_soft.derived3.none 40/45 2868 0
simpair.ratio_soft.derived3.project 40/45 2868 0
simpair.ratio_soft.derived3.step 40/45 2878 0
simpair.ratio_soft.derived3.safe 40/45 2878 0
simpair.exp_abs.derived3.none 40/45 2885 0
simpair.exp_abs.derived3.project 40/45 2885 0
simpair.ratio_soft.derived3.bracket 40/45 2887 0
simpair.ratio.derived3.credit 40/45 2890 0
band.ratio.derived3.credit 40/45 2899 0
simpair.ratio.derived3.safe 40/45 2901 0
simpair.ratio.derived3.step 40/45 2901 0
slope.ratio.derived3.step 40/45 2903 0
slope.ratio.derived3.safe 40/45 2903 0
simpair.ratio_soft.derived3.both 40/45 2904 0
simpair.ratio.derived3.none 40/45 2910 0
simpair.ratio.derived3.project 40/45 2910 0
simpair.exp_abs.derived3.step 40/45 2911 0
simpair.exp_abs.derived3.safe 40/45 2911 0
band.ratio_soft.derived3.step 40/45 2911 0
band.ratio_soft.derived3.safe 40/45 2911 0
====================================================================================
THE STAGE-0C LAW ACROSS THE GRID
====================================================================================
scale=derived3 slope c=1 (linear) mean total 7930 mean solved 193.0/199
scale=derived3 slope c=0 (quadratic) mean total 20090 mean solved 193.0/199
+4
View File
@@ -0,0 +1,4 @@
#!/bin/bash
# Frozen runner for PREREG 2026-09-21 slot 2 (the DECISION place).
cd "$HOME/sim-numerics" || exit 1
exec ~/torchenv/bin/python -u sweep_full.py --decision
+9
View File
@@ -0,0 +1,9 @@
#!/bin/bash
# Frozen regression runner: detached, logged, with an explicit end marker, so an ssh
# drop cannot kill it (2026-09-21: a foreground pytest over ssh died with the connection).
cd "$HOME/sim-numerics" || exit 1
for pass in 1 2; do
echo "=== PASS $pass ==="
~/torchenv/bin/python -m pytest tests -q -p no:cacheprovider 2>&1 | tail -4
done
echo "=== REGRESSION DONE ==="
+80 -9
View File
@@ -157,6 +157,66 @@ def _read_z(resid, sc, exponent, m):
return z return z
def _shape_ratios(x, fx, u, fu, v, fv):
"""(xi, phi) for the triple, or None when it is degenerate.
The two dimensionless ratios the DECISION place is written in (PREREG 2026-09-21,
slot 2): xi of positions, phi of values, equal for a linear f. _shape_defect is
|phi - xi| of these same two; both callers must read one definition, or the step
place and the decision place could silently disagree about what the triple is.
A missing point (the first steps of a run have no third evaluation yet) is a
degenerate triple, not an error: returning None here is what keeps every caller from
raising inside the loop, where `evaluate` would swallow it and charge the full budget
- the failure mode that produced a whole sweep of 39800 on 2026-09-20."""
if x is None or u is None or v is None:
return None
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 xi, ph
def _decide_refuse(mode, S, z, x, fx, u, fu, v, fv):
"""The DECISION place: does the local model deserve this evaluation, or is halving
the better use of it? Returns True to refuse the similarity step.
Three readings, all of quantities already in hand and all without a constant:
"band" Chandrupatla's 1997 acceptance band, 1 - sqrt(1-xi) < phi < sqrt(xi).
NOT OURS. It is in the grid as an INSTRUMENT: it answers whether the
remaining gap lives in this place at all. It must never be presented as
part of the proposed method.
"defect" refuse when the configuration is less like a linear one than the iterate
is off-centre: |phi - xi| > min(xi, 1 - xi). Two computed dimensionless
quantities compared; no threshold.
"simpair" refuse when the configuration's similarity to linear is below the
iterate's similarity to the root: S(|phi - xi|) < S(z). The SAME S is
used in both places on purpose - pairing a different S per place would be
a menu, and a menu is the same fault as a hardcoded constant.
A degenerate triple carries no decision, so the step is allowed and the safeguard
keeps it honest; refusing on missing information would be a guess.
"""
r = _shape_ratios(x, fx, u, fu, v, fv)
if r is None:
return False
xi, ph = r
if mode == "band":
if not (0.0 < xi < 1.0):
return True
return not (1.0 - math.sqrt(1.0 - xi) < ph < math.sqrt(xi))
defect = abs(ph - xi)
if mode == "defect":
return defect > min(abs(xi), abs(1.0 - xi))
if mode == "simpair":
return S(defect) < S(z)
return False
def _shape_defect(x, fx, u, fu, v, fv): def _shape_defect(x, fx, u, fu, v, fv):
"""|phi - xi| for the triple, or None when it is degenerate. """|phi - xi| for the triple, or None when it is degenerate.
@@ -164,13 +224,8 @@ def _shape_defect(x, fx, u, fu, v, fv):
VALUES; both are invariant under affine rescaling of x and of f. For a linear f they 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 — 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.""" the same dimensionless currency Chandrupatla's acceptance band is written in."""
if v == u or fv == fu: r = _shape_ratios(x, fx, u, fu, v, fv)
return None return None if r is None else abs(r[1] - r[0])
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): def _pick_triple(x, fx, x_prev, f_prev, x_prev2, f_prev2, A, FA, B, FB, far):
@@ -549,8 +604,14 @@ def pure_root(f, a, b, xtol, maxfev, similarity="ratio", scale="derived",
"{'derived3', 'derived3_cap', 'bracket', 'far'}") "{'derived3', 'derived3_cap', 'bracket', 'far'}")
if space not in SPACES: if space not in SPACES:
raise ValueError(f"unknown space {space!r}") raise ValueError(f"unknown space {space!r}")
if prestep not in ("none", "progress", "slope"): if prestep not in ("none", "progress", "slope", "band", "defect", "simpair"):
raise ValueError(f"unknown prestep {prestep!r}") raise ValueError(f"unknown prestep {prestep!r}")
if prestep in ("band", "defect", "simpair") and scale not in (
"derived3", "derived3_cap", "derived3_m", "bracket", "far"):
# the decision reads a TRIPLE; under the two-point scale there is no third point
# to read a configuration from, and reading one from elsewhere would hide that
raise ValueError("prestep in {'band','defect','simpair'} needs a three-point "
"history (scale derived3*/bracket/far)")
if points not in POINT_RULES: if points not in POINT_RULES:
raise ValueError(f"unknown points rule {points!r}") raise ValueError(f"unknown points rule {points!r}")
if direction not in DIRECTIONS: if direction not in DIRECTIONS:
@@ -754,7 +815,17 @@ def pure_root(f, a, b, xtol, maxfev, similarity="ratio", scale="derived",
if exponent == "order" else None) if exponent == "order" else None)
z_now = _read_z(abs(fx), sc, exponent, m_loc) z_now = _read_z(abs(fx), sc, exponent, m_loc)
step = None step = None
if prestep == "slope": if prestep in ("band", "defect", "simpair"):
# THE DECISION PLACE (PREREG 2026-09-21, slot 2). Same slot as the
# slope gate, a different reading of it: the question is not whether
# the slope has settled but whether the CONFIGURATION deserves the
# model. The triple is the recency triple, so only the reading
# changes against the slope-gate cells.
if _decide_refuse(prestep, S, z_now, x, fx, x_prev, f_prev,
x_prev2, f_prev2):
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 # 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 # local slope, so the question of trust is whether that slope has
# SETTLED: two consecutive estimates of opposite sign mean the local # SETTLED: two consecutive estimates of opposite sign mean the local
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+29 -3
View File
@@ -204,6 +204,29 @@ def build_grid_log(smoke):
for sim in sims for sc in ("derived", "derived3") for gu in guards] for sim in sims for sc in ("derived", "derived3") for gu in guards]
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(): def _preflight_order_mode():
"""Fail LOUDLY if the per-place reading is not actually deployed. """Fail LOUDLY if the per-place reading is not actually deployed.
@@ -310,10 +333,12 @@ def main():
slopemode = "--slope" in sys.argv # the slope-stability gate grid slopemode = "--slope" in sys.argv # the slope-stability gate grid
capmode = "--cap" in sys.argv # scale selected between the two computed ones capmode = "--cap" in sys.argv # scale selected between the two computed ones
ordermode = "--order" in sys.argv # slot 1: the similarity read BY PLACE 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
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_order(smoke) if ordermode else specs = (build_grid_decision(smoke) if decmode else
build_grid_order(smoke) if ordermode else
build_grid_cap(smoke) if capmode else build_grid_cap(smoke) if capmode else
build_grid_combo(smoke) if combomode else build_grid_combo(smoke) if combomode else
build_grid_points(smoke) if pointsmode else build_grid_points(smoke) if pointsmode else
@@ -336,8 +361,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 ordermode or capmode or combomode or pointsmode or dirmode: if decmode or ordermode or capmode or combomode or pointsmode or dirmode:
base = ("sweep_order" if ordermode else base = ("sweep_decision" if decmode else
"sweep_order" if ordermode else
"sweep_cap" if capmode else "sweep_cap" if capmode else
"sweep_combo" if combomode else "sweep_combo" if combomode else
"sweep_points" if pointsmode else "sweep_direction") "sweep_points" if pointsmode else "sweep_direction")
+86
View File
@@ -0,0 +1,86 @@
"""Pins for PREREG 2026-09-21 slot 2: the reading in the DECISION place."""
from __future__ import annotations
import math
import pytest
from simroot.pure import (PURE_SIMS, _decide_refuse, _shape_defect, _shape_ratios,
pure_root)
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: (t - 1.0) ** 3, 0.0, 10.0),
(lambda t: math.sin(t) - 0.5, 0.0, 1.5),
)
S = PURE_SIMS["ratio"]
def test_one_definition_of_the_triple():
"""The step place and the decision place must not disagree about the configuration."""
args = (2.0, 8.0, 1.0, 1.0, 3.0, 27.0)
xi, ph = _shape_ratios(*args)
assert _shape_defect(*args) == pytest.approx(abs(ph - xi))
def test_a_linear_configuration_is_never_refused():
"""For a linear f, xi == phi, so every reading must trust the model."""
f = lambda t: 3.0 * t - 6.0 # noqa: E731
args = (1.0, f(1.0), 0.0, f(0.0), 4.0, f(4.0))
for mode in ("band", "defect", "simpair"):
assert _decide_refuse(mode, S, 0.5, *args) is False
def test_band_is_chandrupatlas_rule_verbatim():
"""Pinned against the published inequality, not against our own restatement."""
for xi, ph in ((0.5, 0.5), (0.25, 0.3), (0.9, 0.2), (0.1, 0.9)):
# build a triple realising exactly these ratios: u=0, v=1, fu=0, fv=1
args = (xi, ph, 0.0, 0.0, 1.0, 1.0)
want = not (1.0 - math.sqrt(1.0 - xi) < ph < math.sqrt(xi))
assert _decide_refuse("band", S, 0.5, *args) is want
def test_a_degenerate_triple_allows_the_step():
"""No information is not a reason to refuse; the safeguard carries the bound."""
for mode in ("band", "defect", "simpair"):
assert _decide_refuse(mode, S, 0.5, 1.0, 2.0, 0.0, 5.0, 0.0, 5.0) is False
assert _decide_refuse(mode, S, 0.5, 1.0, 2.0, 3.0, 5.0, 3.0, 9.0) is False
def test_readings_actually_decide_somewhere():
"""M5 in miniature: a reading that never fires or always fires is a relabelling."""
fired = {m: 0 for m in ("band", "defect", "simpair")}
total = 0
for xi in (0.05, 0.2, 0.4, 0.6, 0.8, 0.95):
for ph in (0.02, 0.15, 0.45, 0.7, 0.98):
total += 1
for m in fired:
fired[m] += _decide_refuse(m, S, 0.5, xi, ph, 0.0, 0.0, 1.0, 1.0)
for m, k in fired.items():
assert 0 < k < total, (m, k, total)
@pytest.mark.parametrize("f,a,b", PROBS)
@pytest.mark.parametrize("mode", ("band", "defect", "simpair"))
def test_every_reading_still_solves_with_the_guarantee(f, a, b, mode):
x, n, conv = pure_root(f, a, b, 1e-10, 300, similarity="ratio", scale="derived3",
guard="safe", prestep=mode)
assert conv
assert min(a, b) <= x <= max(a, b)
bound = 2 * math.ceil(math.log2(abs(b - a) / 1e-10)) + 4
assert n <= bound
@pytest.mark.parametrize("f,a,b", PROBS)
def test_default_untouched_by_slot_two(f, a, b):
assert (pure_root(f, a, b, 1e-12, 200, similarity="ratio", scale="derived3",
guard="safe")
== pure_root(f, a, b, 1e-12, 200, similarity="ratio", scale="derived3",
guard="safe", prestep="none"))
def test_two_point_scale_refuses_a_triple_reading():
for mode in ("band", "defect", "simpair"):
with pytest.raises(ValueError):
pure_root(lambda t: t, 0.0, 1.0, 1e-9, 50, scale="derived", prestep=mode)
+6 -2
View File
@@ -41,8 +41,12 @@ def test_T1_the_published_path_is_bit_identical_with_the_gate_off():
def test_T2_the_gate_carries_no_constant(): def test_T2_the_gate_carries_no_constant():
src = inspect.getsource(P.pure_root) src = inspect.getsource(P.pure_root)
start = src.index('if prestep == "slope":') # anchor on the CONDITION, never on the whole line: on 2026-09-21 the slot-2 readings
end = src.index('if step is None and prestep == "progress"', start) # were inserted ahead of this gate and turned the line into
# `if step is None and prestep == "slope":`, which broke a pin that was testing
# something else entirely. A pin about constants must not depend on line spelling.
start = src.index('prestep == "slope":')
end = src.index('prestep == "progress"', start)
code = "\n".join(line.split("#", 1)[0] for line in src[start:end].splitlines()) code = "\n".join(line.split("#", 1)[0] for line in src[start:end].splitlines())
literals = set(re.findall(r"(?<![\w.])\d+\.\d+(?![\w.])", code)) literals = set(re.findall(r"(?<![\w.])\d+\.\d+(?![\w.])", code))
assert literals <= {"0.0", "0.5"}, f"constants in the gate: {literals}" assert literals <= {"0.0", "0.5"}, f"constants in the gate: {literals}"
+59
View File
@@ -202,6 +202,7 @@ def main():
verify_placement_modes() verify_placement_modes()
verify_per_place() verify_per_place()
verify_decision_place()
print() print()
if FAILS: if FAILS:
@@ -297,6 +298,64 @@ def verify_per_place():
for r in fam), 0) for r in fam), 0)
DECISION_CELLS = {
# (similarity, prestep, guard): {set: total}
("ratio", "band", "project"): {"APS": 5432, "CHA": 3066},
("ratio", "band", "credit"): {"CHA": 2899},
("ratio", "none", "project"): {"APS": 2806},
("ratio", "defect", "project"): {"APS": 2523, "CHA": 3210},
("ratio_soft", "simpair", "project"): {"CHA": 2868},
}
DECISION_RATES = {"band": 63.6, "defect": 7.0}
def verify_decision_place():
print("\nThe decision place (sweep_decision.json):")
if not os.path.exists("sweep_decision.json"):
print(" !! sweep_decision.json absent — section 'decision place' unverifiable")
FAILS.append("missing sweep_decision.json")
return
with open("sweep_decision.json", encoding="utf8") as fh:
rows = json.load(fh)
by = {(r["spec"][1], r["spec"][5], r["spec"][3]): r for r in rows}
for k, sets in DECISION_CELLS.items():
r = by.get(k)
if r is None:
FAILS.append(f"decision cell {k} missing")
print(f" !! {k} missing — stale sweep")
continue
for setname, want in sets.items():
check(f"{'.'.join(k)} {setname}", r[setname]["total"], want)
d = by[("ratio", "defect", "project")]
check("defect APS solved", d["APS"]["solved"], 153)
check("defect both sets", d["APS"]["total"] + d["CHA"]["total"], 5733)
check("defect is the new canonical best (< 2527)", d["APS"]["total"] < 2527, True)
fam = [r for r in rows if r["spec"][3] in ("project", "safe", "credit")]
check("decision grid guarantee violations", sum(r["APS"]["over"] + r["CHA"]["over"]
for r in fam), 0)
# the refusal rates are recomputed, not transcribed
from scipy.optimize._tstutils import _APS_TESTS_DICTS, _CHANDRUPATLA_TESTS_DICTS
from simroot.pure import pure_root
probs = [(float(q["bracket"][0]), float(q["bracket"][1]),
(lambda ff, aa: lambda t: ff(t, *aa))(q["f"], q.get("args", ())))
for q in _APS_TESTS_DICTS]
probs += [(float(q["bracket"][0]), float(q["bracket"][1]),
(lambda ff: lambda t: ff(t))(q["f"])) for q in _CHANDRUPATLA_TESTS_DICTS]
for mode, want in DECISION_RATES.items():
ref = nfev = 0
for a, b, f in probs:
st = {}
try:
_x, n, _c = pure_root(f, a, b, 1e-12, 200, similarity="ratio",
scale="derived3", guard="project", prestep=mode,
stats=st)
except Exception:
continue
ref += st.get("pre_refused", 0)
nfev += int(n)
check(f"{mode} refusal rate %", round(100.0 * ref / nfev, 1), want)
PLACEMENT_PER_SET = { PLACEMENT_PER_SET = {
"sweep_direction.json": ("CHA", "pure+dissim+slope.ratio.derived3.safe", 2683), "sweep_direction.json": ("CHA", "pure+dissim+slope.ratio.derived3.safe", 2683),
"sweep_gate.json": ("CHA", "gate.ratio_soft.derived.safe", 2851), "sweep_gate.json": ("CHA", "gate.ratio_soft.derived.safe", 2851),