diff --git a/PREREG_flat_judge_2026-09-21.md b/PREREG_flat_judge_2026-09-21.md new file mode 100644 index 0000000..b9af8cd --- /dev/null +++ b/PREREG_flat_judge_2026-09-21.md @@ -0,0 +1,52 @@ +# PREREG — плоский режим: одно суждение похожести на входе и на выходе + +Составлено до кода и до прогона, ветка `signfix-and-gates`. Валерий: «нужно решать задачу так, чтобы +и на канонических, и на широких скобках был выигрыш». + +## Основание (`sweep_flatexit.json`, разбор `where_we_lose.py`, без нового прогона) + +| | канонические | широкие | fun1 | fun2 | fun3–6 | fun8 | fun9 | +|---|---|---|---|---|---|---|---| +| Чандрупатла | 2787 | 2441 | 103 | 152 | 1068 | 63 | 55 | +| предложенный метод | 2806 | 3220 | 99 | 141 | 1823 | 52 | 105 | +| + залипание с выходом | 3125 | 2503 | 147 | 158 | 1057 | 72 | 69 | + +- Плоские семейства после выхода — **на уровне Чандрупатлы** (−11 в сумме). +- Весь остаток проигрыша — ложные входы на простых корнях: канонические +319, fun1 +48, fun2 +17, + fun8 +20. Флаг «несбывшееся обещание» входит в 134 из 154 канонических задач. +- Потолок при безошибочном входе: широкие ≈ 1057 + (99 + 141 + 1000 + 52 + 55…105) = 2404…2454 + против 2441 — **запас тонкий, записан заранее**. + +## Правило (новых констант нет) + +Режим `prestep="flatjudge"`. После **каждого** вычисления f в новой точке x, до сдвига скобки, +суждение похожести по двум предсказаниям: +- линейное: L(x) = FA + (FB − FA)(x − A)/(B − A) — прямая через концы скобки; +- плоское: 0. + +`плоско` — если |f(x)| < |f(x) − L(x)|; `линейно` — если |f(x) − L(x)| < |f(x)|; равенство — ни то, +ни другое. На середине L = (FA + FB)/2 — это ровно суждение выхода из `flatstickexit`. + +- **Вход:** последний шаг был шагом модели, знак не сменился, r ≥ ¼ (флаг) **и** в этой точке + суждение — `плоско`. +- **В режиме:** каждый шаг — середина. +- **Выход:** на середине суждение — `линейно`. + +Предохранитель применяется к шагу как всегда. + +## Проверка + +Решение принимается **по смоуку** (он считает предложенный метод на всех 199 задачах); сервер — +только для подтверждения числа, если прошло. Ячейки: предложенный метод и он же с Г2 (повтор рисунка +шагов), `none / flatjudge / flatstickexit`. + +| # | ПРОЙДЕНО, если | +|---|---| +| **J1** | широкие скобки **ниже Чандрупатлы** (2441) | +| **J2** | канонические **ниже Чандрупатлы** (2787) | +| **J3** | гарантия: 0 нарушений, решено ≥ 193 | +| **J4** | сообщается: число входов на канонических и неплоских широких против `flatstickexit` | + +**Цель задачи (Валерий): J1 и J2 одновременно** — выигрыш на обоих наборах. Принимается вариант, +выполнивший J1, J2, J3; без Г2 или с Г2 — сообщаются оба. +Если не выполнено: сообщается, какой набор и на сколько не дотянул, и в каких семействах. diff --git a/where_we_lose.py b/where_we_lose.py new file mode 100644 index 0000000..be5a9cc --- /dev/null +++ b/where_we_lose.py @@ -0,0 +1,60 @@ +"""Where the proposed rule still loses to Chandrupatla, per family, from results already +on disk (no new run). Cells: the proposed rule, + sticky/exit, and the decision-place +records, if the files hold them. + + python -u where_we_lose.py +""" +from __future__ import annotations + +import json +import os +from collections import defaultdict + +MAXFEV = 200 + + +def load(p): + with open(p, encoding="utf8") as fh: + return {r["label"]: r for r in json.load(fh)} + + +def fam(pid): + return pid.split(".")[0] if not pid.startswith("aps") else "aps" + + +def per_family(r, s): + out = defaultdict(int) + for pid, (n, ok) in r[s]["per"].items(): + out[fam(pid)] += n if ok else MAXFEV + return out + + +def main(): + full = load("sweep_full.json") + cells = {"chandrupatla": full["chandrupatla"], + "proposed": full["pure.ratio.derived3.project"]} + if os.path.exists("sweep_flatexit.json"): + cells["+exit"] = load("sweep_flatexit.json")["flatstickexit.ratio.derived3.project"] + for path in ("sweep_decision.json", "sweep_order.json", "sweep_points.json", + "sweep_combo.json", "sweep_slope.json"): + if not os.path.exists(path): + continue + for lab, r in load(path).items(): + if lab.endswith("ratio.derived3.project") and lab not in cells and ( + "defect" in lab or "shape" in lab or "slope" in lab): + cells[lab] = r + print(f"{'cell':<45} {'APS':>6} {'CHA':>6} {'both':>6}") + for k, r in cells.items(): + print(f"{k:<45} {r['APS']['total']:6d} {r['CHA']['total']:6d} " + f"{r['APS']['total'] + r['CHA']['total']:6d}") + ch = per_family(cells["chandrupatla"], "CHA") + print("\nCHA per family (Chandrupatla | proposed | +exit):") + pr = per_family(cells["proposed"], "CHA") + ex = per_family(cells["+exit"], "CHA") if "+exit" in cells else {} + for f in sorted(ch): + print(f" {f:<6} {ch[f]:5d} | {pr[f]:5d} | {ex.get(f, 0):5d} " + f"(+exit - Chandrupatla {ex.get(f, 0) - ch[f]:+d})") + + +if __name__ == "__main__": + main()