explained, with numbers: Chandrupatla wins the probe by REFUSING its model cheaply, not by trusting it — it accepts the interpolation on only 28% of steps, its gate costs zero evaluations (read from data already in hand) and its refusal branch still halves the bracket; ours repairs 77.5% of evaluations after the fact and drops to 0.92 halvings/eval on fun8/fun9, worse than bisection. In similarity terms: their similarity is a PRE-step GATE on dimensionless ratios (a neighbourhood of the linear configuration), ours is an IN-step SCALE on the residual magnitude — the PLACEMENT of the reading matters more than its form
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -88,3 +88,51 @@
|
|||||||
Chandrupatla-1997 (2423 против наших 4516) при **нуле** настроечных констант, то есть существующий
|
Chandrupatla-1997 (2423 против наших 4516) при **нуле** настроечных констант, то есть существующий
|
||||||
алгоритм уже делает то, чего мы добиваемся, и объяснение его преимущества — отдельная задача
|
алгоритм уже делает то, чего мы добиваемся, и объяснение его преимущества — отдельная задача
|
||||||
(качество пробы, `stage4_why.py`), а не новая шкала шага.
|
(качество пробы, `stage4_why.py`), а не новая шкала шага.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 🟢 ЧЕМ Chandrupatla выигрывает пробу — измерено, и это переводится на язык похожести
|
||||||
|
|
||||||
|
Инструмент: `explain_chandrupatla.py` (лог `results_explain_chandrupatla.txt`). Трассируемая копия
|
||||||
|
опубликованной процедуры; её верность **проверена** — совпадение с оригиналом по числу вызовов и
|
||||||
|
исходу на всех 45 задачах. Метрика пробы беспараметрическая: **половинок скобки на вызов**
|
||||||
|
`= log₂(w₀/xtol)/nfev`, деление пополам = 1.0.
|
||||||
|
|
||||||
|
| величина (45 задач CHA) | Chandrupatla | наш `ratio.derived3.credit` |
|
||||||
|
|---|---|---|
|
||||||
|
| вызовов всего (провал = 200) | **1488** | 2073 |
|
||||||
|
| **половинок на вызов** | **2.310** | 1.422 |
|
||||||
|
| модель принята | **28.0 % шагов** | — |
|
||||||
|
| сторож ремонтировал | — | **77.5 % вызовов** |
|
||||||
|
|
||||||
|
Семейства `fun8`/`fun9`: у них 8–15 вызовов при 3–5 половинках, у нас 44–50 вызовов при **0.92** —
|
||||||
|
то есть **хуже деления пополам**, при 93 % ремонтов.
|
||||||
|
|
||||||
|
### Ответ
|
||||||
|
|
||||||
|
**Он выигрывает не тем, что больше доверяет модели, а тем, что дешевле от неё отказывается.**
|
||||||
|
Интерполяция принимается лишь в 28 % шагов; в остальных 72 % он делит пополам. Гейт считается из уже
|
||||||
|
имеющихся `x1,x2,x3,f1,f2,f3` — **ноль новых вызовов**, а ветвь отказа сама снимает половину скобки.
|
||||||
|
Наш отказ **платный**: шаг сделан, лёг плохо, сторож ремонтирует, ремонт — это вызов.
|
||||||
|
|
||||||
|
### Перевод
|
||||||
|
|
||||||
|
| | где читается похожесть | на чём | цена отказа |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Chandrupatla | **до** шага, как **ГЕЙТ** | на форме конфигурации: `ξ = (x1−x2)/(x3−x2)`, `φ = (f1−f2)/(f3−f2)` — два отношения, инвариантные к масштабу по `x` и по `f`; полоса `1−√(1−ξ) < φ < √ξ` есть окрестность **линейной** конфигурации (для линейной `f` точно `φ = ξ`, и она внутри полосы) | **0 вызовов** |
|
||||||
|
| наш метод | **внутри** шага, как **МАСШТАБ** | на величине остатка `\|f\|/σ` | **1 вызов** |
|
||||||
|
|
||||||
|
**Следствие, которое дороже самого объяснения:** решает не форма функции похожести, а **её место в
|
||||||
|
алгоритме**. Похожесть, прочитанная ДО шага на отношениях, стоит ноль и отсекает недостоверную
|
||||||
|
модель; похожесть, прочитанная ВНУТРИ шага на величине, требует сторожа, и сторож платит. Это
|
||||||
|
дополняет закон корпуса «рассуждение платит тем больше, чем хуже похожесть»: здесь **расположение
|
||||||
|
чтения важнее его формы**.
|
||||||
|
|
||||||
|
### Что из этого следует как проверяемый шаг (пред-регистрировать до реализации)
|
||||||
|
|
||||||
|
Добавить в наш метод **предшаговый гейт на отношениях** — читать похожесть конфигурации к
|
||||||
|
хорошо обусловленной ДО того, как шаг сделан, и при отказе сразу делить пополам, вместо
|
||||||
|
масштабированного шага с последующим ремонтом. Новой константы это не вводит: границы полосы у
|
||||||
|
Чандрупатлы выведены из требования «проба модели не должна выйти за скобку» — того же требования,
|
||||||
|
которое наш проекционный сторож выполняет, но **после** факта. Цель замера: довести долю ремонтов с
|
||||||
|
77.5 % к уровню их 72 % отказов **без** роста цены на APS-154.
|
||||||
|
|||||||
@@ -0,0 +1,149 @@
|
|||||||
|
"""Why Chandrupatla wins the probe — measured, and stated in similarity terms.
|
||||||
|
|
||||||
|
ANALYSIS ONLY. The traced copy below mirrors `simroot.baselines.chandrupatla` so its
|
||||||
|
decisions can be counted; it is NEVER used for a ranking number, and its fidelity is
|
||||||
|
asserted against the original (identical evaluation count on all 45 problems). If that
|
||||||
|
assert fails, the mirror has drifted and nothing here may be believed.
|
||||||
|
|
||||||
|
The reading being tested:
|
||||||
|
|
||||||
|
Chandrupatla = similarity(configuration, well-conditioned configuration) used as a
|
||||||
|
GATE on a model step, with bisection as the refusal branch.
|
||||||
|
ours = similarity(residual, 0) used as a SCALE for the step, with the
|
||||||
|
safeguard bolted on afterwards.
|
||||||
|
|
||||||
|
* the decision variable is t in (0,1): the probe is a FRACTION of the bracket, so the
|
||||||
|
method is scale-free by construction (what the logarithmic attempt tried to buy);
|
||||||
|
* the gate is written in two RATIOS, xi = (x1-x2)/(x3-x2) and phi = (f1-f2)/(f3-f2),
|
||||||
|
both invariant under affine rescaling of x and of f — relations, not magnitudes;
|
||||||
|
* for a LINEAR f, phi = xi exactly, and that point lies strictly inside the band
|
||||||
|
1 - sqrt(1-xi) < phi < sqrt(xi), so the band is a neighbourhood of the linear
|
||||||
|
configuration: the model is trusted exactly where the data still look linear enough.
|
||||||
|
|
||||||
|
Metric for "probe quality", parameter-free and comparable across methods:
|
||||||
|
halvings per evaluation = log2(w0 / xtol) / nfev
|
||||||
|
Bisection is 1.0 by definition; more is better.
|
||||||
|
|
||||||
|
python -u explain_chandrupatla.py
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import math
|
||||||
|
|
||||||
|
from simroot.baselines import Counter, chandrupatla
|
||||||
|
from simroot.pure import pure_root
|
||||||
|
from sweep_full import ACC, MAXFEV, XTOL, load_problems
|
||||||
|
|
||||||
|
|
||||||
|
def chandrupatla_traced(f, a, b, xtol, maxfev):
|
||||||
|
"""Mirror of the published routine plus counters. Returns (x, nfev, ok, trace)."""
|
||||||
|
g = Counter(f, maxfev)
|
||||||
|
trace = {"iqi": 0, "bisect": 0, "gate_rejected": 0, "no_third_point": 0}
|
||||||
|
x1, x2 = b, a
|
||||||
|
f1 = f2 = 0.0
|
||||||
|
try:
|
||||||
|
f1, f2 = g(x1), g(x2)
|
||||||
|
if f1 == 0.0:
|
||||||
|
return x1, g.n, True, trace
|
||||||
|
if f2 == 0.0:
|
||||||
|
return x2, g.n, True, trace
|
||||||
|
x3, f3 = x2, f2
|
||||||
|
t = 0.5
|
||||||
|
while True:
|
||||||
|
x = x1 + t * (x2 - x1)
|
||||||
|
fx = g(x)
|
||||||
|
if (fx > 0.0) == (f1 > 0.0):
|
||||||
|
x3, f3 = x1, f1
|
||||||
|
x1, f1 = x, fx
|
||||||
|
else:
|
||||||
|
x3, f3 = x2, f2
|
||||||
|
x2, f2 = x1, f1
|
||||||
|
x1, f1 = x, fx
|
||||||
|
xm, fm = (x1, f1) if abs(f1) < abs(f2) else (x2, f2)
|
||||||
|
if fm == 0.0:
|
||||||
|
return xm, g.n, True, trace
|
||||||
|
tol = 2.0 * 2.22e-16 * abs(xm) + xtol
|
||||||
|
span = abs(x2 - x1)
|
||||||
|
if span == 0.0:
|
||||||
|
return xm, g.n, True, trace
|
||||||
|
tl = tol / span
|
||||||
|
if tl > 0.5:
|
||||||
|
return xm, g.n, True, trace
|
||||||
|
t = 0.5
|
||||||
|
took_iqi = False
|
||||||
|
if x3 != x2 and f3 != f2:
|
||||||
|
xi = (x1 - x2) / (x3 - x2)
|
||||||
|
ph = (f1 - f2) / (f3 - f2)
|
||||||
|
if 0.0 < xi < 1.0 and 1.0 - math.sqrt(1.0 - xi) < ph < math.sqrt(xi):
|
||||||
|
d1, d2, d3 = f1 - f2, f1 - f3, f2 - f3
|
||||||
|
if d1 != 0.0 and d2 != 0.0 and d3 != 0.0:
|
||||||
|
t = (f1 / d1) * (f3 / (-d3)) + \
|
||||||
|
((x3 - x1) / (x2 - x1)) * (f1 / d2) * (f2 / d3)
|
||||||
|
took_iqi = True
|
||||||
|
else:
|
||||||
|
trace["gate_rejected"] += 1
|
||||||
|
else:
|
||||||
|
trace["no_third_point"] += 1
|
||||||
|
if not math.isfinite(t):
|
||||||
|
t = 0.5
|
||||||
|
took_iqi = False
|
||||||
|
if t < tl:
|
||||||
|
t = tl
|
||||||
|
elif t > 1.0 - tl:
|
||||||
|
t = 1.0 - tl
|
||||||
|
trace["iqi" if took_iqi else "bisect"] += 1
|
||||||
|
except Exception:
|
||||||
|
return float("nan"), g.n, False, trace
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
probs = [p for p in load_problems() if p[0] == "CHA"]
|
||||||
|
print(f"CHA problems: {len(probs)} metric: halvings per evaluation "
|
||||||
|
f"= log2(w0/xtol)/nfev (bisection = 1.0)\n")
|
||||||
|
print(f"{'problem':<16} {'CH nfev':>8} {'CH h/ev':>8} {'gate ok%':>9} "
|
||||||
|
f"{'ours nfev':>10} {'ours h/ev':>10} {'forced%':>8}")
|
||||||
|
|
||||||
|
agg = {"ch_n": 0, "our_n": 0, "ch_h": [], "our_h": [], "gate": [], "forced": []}
|
||||||
|
drift = 0
|
||||||
|
for _s, pid, f, a, b, root in probs:
|
||||||
|
w0 = abs(b - a)
|
||||||
|
decades = math.log2(w0 / XTOL)
|
||||||
|
|
||||||
|
x_ref, n_ref, ok_ref = chandrupatla(f, a, b, XTOL, MAXFEV)
|
||||||
|
x_t, n_t, ok_t, tr = chandrupatla_traced(f, a, b, XTOL, MAXFEV)
|
||||||
|
if (n_ref, ok_ref) != (n_t, ok_t):
|
||||||
|
drift += 1
|
||||||
|
steps = tr["iqi"] + tr["bisect"]
|
||||||
|
gate_ok = 100.0 * tr["iqi"] / steps if steps else float("nan")
|
||||||
|
|
||||||
|
stats = {}
|
||||||
|
x_o, n_o, ok_o = pure_root(f, a, b, XTOL, MAXFEV, similarity="ratio",
|
||||||
|
scale="derived3", guard="credit", stats=stats)
|
||||||
|
forced = 100.0 * stats.get("forced", 0) / max(n_o, 1)
|
||||||
|
|
||||||
|
ch_h = decades / n_ref if n_ref else float("nan")
|
||||||
|
our_h = decades / n_o if n_o else float("nan")
|
||||||
|
agg["ch_n"] += n_ref if ok_ref else MAXFEV
|
||||||
|
agg["our_n"] += n_o if ok_o else MAXFEV
|
||||||
|
if ok_ref:
|
||||||
|
agg["ch_h"].append(ch_h)
|
||||||
|
agg["gate"].append(gate_ok)
|
||||||
|
if ok_o:
|
||||||
|
agg["our_h"].append(our_h)
|
||||||
|
agg["forced"].append(forced)
|
||||||
|
print(f"{pid:<16} {n_ref:8d} {ch_h:8.3f} {gate_ok:8.1f}% "
|
||||||
|
f"{n_o:10d} {our_h:10.3f} {forced:7.1f}%")
|
||||||
|
|
||||||
|
mean = lambda v: sum(v) / len(v) if v else float("nan") # noqa: E731
|
||||||
|
print(f"\nmirror fidelity: {'OK' if drift == 0 else f'DRIFTED on {drift} problems'}")
|
||||||
|
print(f"totals (failures charged {MAXFEV}): Chandrupatla {agg['ch_n']}, ours {agg['our_n']}")
|
||||||
|
print(f"halvings per evaluation: Chandrupatla {mean(agg['ch_h']):.3f}, "
|
||||||
|
f"ours {mean(agg['our_h']):.3f}")
|
||||||
|
print(f"Chandrupatla accepted the model on {mean(agg['gate']):.1f}% of steps "
|
||||||
|
f"(the rest it REFUSED and halved)")
|
||||||
|
print(f"our safeguard had to repair {mean(agg['forced']):.1f}% of evaluations")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
CHA problems: 45 metric: halvings per evaluation = log2(w0/xtol)/nfev (bisection = 1.0)
|
||||||
|
|
||||||
|
problem CH nfev CH h/ev gate ok% ours nfev ours h/ev forced%
|
||||||
|
fun1.1 8 4.983 100.0% 25 1.595 20.0%
|
||||||
|
fun1.2 12 3.586 55.6% 47 0.916 93.6%
|
||||||
|
fun1.3 15 3.099 41.7% 50 0.930 94.0%
|
||||||
|
fun1.4 24 2.256 33.3% 58 0.934 93.1%
|
||||||
|
fun1.5 44 1.684 17.1% 78 0.950 84.6%
|
||||||
|
fun2.1 9 4.431 66.7% 12 3.323 25.0%
|
||||||
|
fun2.2 23 2.311 25.0% 57 0.932 94.7%
|
||||||
|
fun2.3 29 2.062 19.2% 63 0.949 95.2%
|
||||||
|
fun2.4 42 1.740 10.3% 77 0.949 77.9%
|
||||||
|
fun2.5 49 1.627 10.9% 83 0.961 65.1%
|
||||||
|
fun3.1 44 0.959 0.0% 46 0.917 93.5%
|
||||||
|
fun3.2 46 0.961 0.0% 48 0.921 93.8%
|
||||||
|
fun3.3 61 0.888 8.6% 58 0.934 65.5%
|
||||||
|
fun3.4 69 0.881 13.6% 64 0.950 65.6%
|
||||||
|
fun3.5 82 0.903 7.6% 58 1.277 1.7%
|
||||||
|
fun4.1 44 0.959 0.0% 46 0.917 93.5%
|
||||||
|
fun4.2 46 0.961 0.0% 48 0.921 93.8%
|
||||||
|
fun4.3 56 0.967 5.7% 58 0.934 75.9%
|
||||||
|
fun4.4 67 0.907 7.8% 64 0.950 51.6%
|
||||||
|
fun4.5 80 0.926 5.2% 78 0.950 51.3%
|
||||||
|
fun5.1 44 0.959 0.0% 46 0.917 93.5%
|
||||||
|
fun5.2 44 0.970 0.0% 46 0.928 93.5%
|
||||||
|
fun5.3 45 0.963 0.0% 47 0.922 93.6%
|
||||||
|
fun5.4 47 0.971 0.0% 49 0.932 93.9%
|
||||||
|
fun5.5 48 0.972 0.0% 50 0.933 94.0%
|
||||||
|
fun6.1 44 0.959 0.0% 46 0.917 93.5%
|
||||||
|
fun6.2 44 0.970 0.0% 46 0.928 93.5%
|
||||||
|
fun6.3 45 0.963 0.0% 47 0.922 91.5%
|
||||||
|
fun6.4 47 0.971 0.0% 49 0.932 91.8%
|
||||||
|
fun6.5 48 0.972 0.0% 50 0.933 92.0%
|
||||||
|
fun7.1 8 5.273 40.0% 9 4.687 66.7%
|
||||||
|
fun7.2 8 5.334 40.0% 8 5.334 62.5%
|
||||||
|
fun7.3 11 3.938 37.5% 10 4.332 70.0%
|
||||||
|
fun7.4 18 2.536 40.0% 13 3.511 53.8%
|
||||||
|
fun7.5 19 2.455 43.8% 13 3.588 38.5%
|
||||||
|
fun8.1 10 4.086 71.4% 44 0.929 93.2%
|
||||||
|
fun8.2 11 3.768 62.5% 45 0.921 93.3%
|
||||||
|
fun8.3 13 3.310 60.0% 47 0.916 93.6%
|
||||||
|
fun8.4 14 3.187 45.5% 48 0.930 93.8%
|
||||||
|
fun8.5 15 3.080 41.7% 36 1.283 63.9%
|
||||||
|
fun9.1 8 4.983 100.0% 16 2.491 25.0%
|
||||||
|
fun9.2 9 4.605 83.3% 45 0.921 93.3%
|
||||||
|
fun9.3 11 3.912 62.5% 47 0.916 93.6%
|
||||||
|
fun9.4 13 3.432 60.0% 48 0.930 93.8%
|
||||||
|
fun9.5 14 3.300 45.5% 50 0.924 94.0%
|
||||||
|
|
||||||
|
mirror fidelity: OK
|
||||||
|
totals (failures charged 200): Chandrupatla 1488, ours 2073
|
||||||
|
halvings per evaluation: Chandrupatla 2.310, ours 1.422
|
||||||
|
Chandrupatla accepted the model on 28.0% of steps (the rest it REFUSED and halved)
|
||||||
|
our safeguard had to repair 77.5% of evaluations
|
||||||
Reference in New Issue
Block a user