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:
@@ -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` с маркером конца.
|
||||
@@ -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.
|
||||
@@ -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.
@@ -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
|
||||
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}
|
||||
\label{sec:fun7}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -157,6 +157,66 @@ def _read_z(resid, sc, exponent, m):
|
||||
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):
|
||||
"""|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
|
||||
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)
|
||||
r = _shape_ratios(x, fx, u, fu, v, fv)
|
||||
return None if r is None else abs(r[1] - r[0])
|
||||
|
||||
|
||||
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'}")
|
||||
if space not in SPACES:
|
||||
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}")
|
||||
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:
|
||||
raise ValueError(f"unknown points rule {points!r}")
|
||||
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)
|
||||
z_now = _read_z(abs(fx), sc, exponent, m_loc)
|
||||
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
|
||||
# local slope, so the question of trust is whether that slope has
|
||||
# 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
@@ -204,6 +204,29 @@ def build_grid_log(smoke):
|
||||
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():
|
||||
"""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
|
||||
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
|
||||
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_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_combo(smoke) if combomode 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
|
||||
# against, so the log grid never writes into it
|
||||
if ordermode or capmode or combomode or pointsmode or dirmode:
|
||||
base = ("sweep_order" if ordermode else
|
||||
if decmode or ordermode or capmode or combomode or pointsmode or dirmode:
|
||||
base = ("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")
|
||||
|
||||
@@ -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)
|
||||
@@ -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():
|
||||
src = inspect.getsource(P.pure_root)
|
||||
start = src.index('if prestep == "slope":')
|
||||
end = src.index('if step is None and prestep == "progress"', start)
|
||||
# anchor on the CONDITION, never on the whole line: on 2026-09-21 the slot-2 readings
|
||||
# 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())
|
||||
literals = set(re.findall(r"(?<![\w.])\d+\.\d+(?![\w.])", code))
|
||||
assert literals <= {"0.0", "0.5"}, f"constants in the gate: {literals}"
|
||||
|
||||
@@ -202,6 +202,7 @@ def main():
|
||||
|
||||
verify_placement_modes()
|
||||
verify_per_place()
|
||||
verify_decision_place()
|
||||
|
||||
print()
|
||||
if FAILS:
|
||||
@@ -297,6 +298,64 @@ def verify_per_place():
|
||||
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 = {
|
||||
"sweep_direction.json": ("CHA", "pure+dissim+slope.ratio.derived3.safe", 2683),
|
||||
"sweep_gate.json": ("CHA", "gate.ratio_soft.derived.safe", 2851),
|
||||
|
||||
Reference in New Issue
Block a user