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) при **нуле** настроечных констант, то есть существующий
|
||||
алгоритм уже делает то, чего мы добиваемся, и объяснение его преимущества — отдельная задача
|
||||
(качество пробы, `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