From 04ee5c89b93924abd5eb4bbafd042a11d3282ec6 Mon Sep 17 00:00:00 2001 From: Valeri Sitnikov Date: Sun, 20 Sep 2026 23:39:41 +0100 Subject: [PATCH] =?UTF-8?q?two=20more=20places=20for=20similarity:=20point?= =?UTF-8?q?s=3D'shape'=20(WHICH=20triple=20the=20model=20uses,=20argmin=20?= =?UTF-8?q?|phi-xi|=20over=20declared=20candidates=20=E2=80=94=20select,?= =?UTF-8?q?=20never=20weight)=20and=20direction=3D'dissimilar'=20(the=20fa?= =?UTF-8?q?r=20end=20read=20by=20|f|=20rather=20than=20by=20distance);=20d?= =?UTF-8?q?efaults=20bit-identical,=20P1-P5=20pinned=20(7=20green),=20iner?= =?UTF-8?q?tness=20counters=20make=20an=20inert=20mode=20a=20failed=20EXPE?= =?UTF-8?q?RIMENT=20rather=20than=20a=20pass;=20each=20grid=20writes=20to?= =?UTF-8?q?=20its=20own=20file?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5 --- PREREG_points_and_direction_2026-09-21.md | 87 ++++++++++++++++++ simroot/pure.py | 93 +++++++++++++++++-- sweep_direction_smoke.json | 1 + sweep_full.py | 40 +++++++- sweep_points_smoke.json | 1 + tests/test_points_direction.py | 106 ++++++++++++++++++++++ 6 files changed, 320 insertions(+), 8 deletions(-) create mode 100644 PREREG_points_and_direction_2026-09-21.md create mode 100644 sweep_direction_smoke.json create mode 100644 sweep_points_smoke.json create mode 100644 tests/test_points_direction.py diff --git a/PREREG_points_and_direction_2026-09-21.md b/PREREG_points_and_direction_2026-09-21.md new file mode 100644 index 0000000..b88a4ec --- /dev/null +++ b/PREREG_points_and_direction_2026-09-21.md @@ -0,0 +1,87 @@ +# PREREG — похожесть в двух ещё незанятых местах: СОСТАВ ТОЧЕК и НАПРАВЛЕНИЕ + +Составлено до реализации. Основание — `FINDINGS_slope_gate.md`: решает **валюта и место** чтения +похожести. Одна и та же идея «отказывайся до шага» дала 4449 вызовов на APS при отказе по прогрессу +скобки и 2848 при отказе по форме модели — разница 1601 вызов. Карта мест решения показала два +незанятых: + +| место | чем решается сейчас | +|---|---| +| **состав точек для модели** | **давностью**: `x_prev2 ← x_prev ← x ← x_new`, всегда три последних | +| **направление** (какой конец «дальний») | **расстоянием**: `far = B if \|B−x\| ≥ \|A−x\| else A` | + +--- + +## 1. Режим A — состав точек по ФОРМЕ (`points="shape"`) + +Оценка наклона строится на тройке точек. Сейчас тройка берётся по давности, даже если она +плохо обусловлена. Brent, TOMS 748 и Chandrupatla все **управляют составом точек** — это часть их +конструкции, а у нас этого места нет вовсе. + +**Признак — та же валюта, что уже сработала: форма конфигурации, безразмерно.** Для тройки +`(x, u, v)` считаются два отношения в духе Chandrupatla: + + ξ = (x − u)/(v − u) — отношение ПОЗИЦИЙ + φ = (f(x) − f(u))/(f(v) − f(u)) — отношение ЗНАЧЕНИЙ + +Для линейной `f` выполняется `φ = ξ` точно, поэтому `|φ − ξ|` — безразмерная мера непохожести +конфигурации на линейную. Правило: **argmin |φ − ξ|** по объявленному списку кандидатов. + +**Список кандидатов объявляется здесь и не расширяется по результату:** + + T1 = (x, x_prev, x_prev2) — нынешнее правило давности + T2 = (x, x_prev, far) — свежая точка плюс дальний конец скобки + T3 = (x, A, B) — оба конца доказанной скобки + +Вырожденные (совпадающие абсциссы или значения) выбрасываются. Порога нет: это **argmin по +имеющимся вариантам**, а не сравнение с числом. Правило корпуса «select, never weight» соблюдено — +тройка **выбирается**, оценки не взвешиваются. + +## 2. Режим B — направление по НЕПОХОЖЕСТИ (`direction="dissimilar"`) + +Сейчас «дальний» конец — геометрически более удалённый. Похожесть даёт другой ответ: дальним считать +конец, чьё `|f|` **больше**, то есть менее похожее на ноль. Ни константы, ни порога — сравнение двух +имеющихся величин. + +**Режимы независимы и мерятся отдельно** (правило «менять одно за раз»); комбинация A+B мерится +третьим прогоном только если оба по отдельности не ухудшили APS. + +## 3. Цели + +Точка отсчёта — уже достигнутое гейтом на наклоне (`slope.ratio.derived3.project`): +APS **2848**, CHA **3074**, два набора **5922**, 193/199, `over2x = 0`. + +| величина | цель | +|---|---| +| APS-154 | **≤ 2848** (не хуже текущего; идеально — вернуть 2806) | +| CHA-45 | **≤ 2857** (недобранная цель ITP; сейчас 2903 по-наборно) | +| два набора | **< 5922** | +| решено | ≥ 193/199 | +| гарантия `2⌈log₂(w/xtol)⌉+3` | `over2x = 0` | + +## 4. Предсказания и фальсификаторы + +| # | Предсказание | ФАЛЬСИФИКАТОР → вывод | +|---|---|---| +| **A1** | режим A не ухудшает APS (≤2848) и улучшает CHA (<2903) | ухудшает APS → состав точек не то место, режим отвергается | +| **A2** | выбор тройки **не инертен**: отличается от давностной в ≥5 % шагов | <1 % → режим ничего не меняет, замер НЕ является свидетельством ни за, ни против | +| **B1** | режим B не ухудшает APS (≤2848) | ухудшает → направление по непохожести отвергается | +| **B2** | выбор конца отличается от геометрического в ≥5 % шагов | <1 % → инертен, замер пуст | +| **C** | гарантия цела в обоих режимах | нарушена → немедленное закрытие режима | + +**Правило остановки:** APS ухудшился или гарантия нарушена ⇒ режим не принимается. Инертность (A2/B2) +⇒ результат не толкуется как подтверждение: это отсутствие эксперимента, а не его исход. + +## 5. Гейты реализации (тесты ДО рейтинга) + +| # | Условие | Проверка | +|---|---|---| +| **P1** | `points="recent"` и `direction="distance"` дают побитово прежний результат | равенство кортежей на наборе задач и сторожей | +| **P2** | в обоих признаках нет констант | греп по коду (без комментариев): только `0.0`, `0.5`, `1.0` | +| **P3** | счётчики `stats['triple_changed']`, `stats['dir_changed']` считают неинертность | тест на обоих | +| **P4** | вырожденные тройки отбрасываются, а не дают деление на ноль | тест на совпадающих абсциссах и значениях | +| **P5** | ни один режим не добавляет вызовов `f` | число вызовов ≤ число шагов + 2 | + +**Дисциплина:** аудит после правки и до запуска; смоук ×2 локально; свипы в свои файлы +(`sweep_points.json`, `sweep_direction.json`), `sweep_full.json` не трогать; числа только с Linux; +замороженные копии; числа показываются немедленно. diff --git a/simroot/pure.py b/simroot/pure.py index 5198f77..d456c21 100644 --- a/simroot/pure.py +++ b/simroot/pure.py @@ -121,6 +121,47 @@ GUARDS = ("none", "bracket", "step", "both", "project", "safe", "credit") SPACES = ("x", "log") +POINT_RULES = ("recent", "shape") +DIRECTIONS = ("distance", "dissimilar") + + +def _shape_defect(x, fx, u, fu, v, fv): + """|phi - xi| for the triple, or None when it is degenerate. + + xi = (x - u)/(v - u) is a ratio of POSITIONS, phi = (fx - fu)/(fv - fu) a ratio of + 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) + + +def _pick_triple(x, fx, x_prev, f_prev, x_prev2, f_prev2, A, FA, B, FB, far): + """SELECT the triple whose configuration is least unlike a linear one (PREREG + 2026-09-21, mode A). Candidates are declared, not searched: the recency triple, the + recent point with the far bracket end, and the two proven bracket ends. Returns + ((xu, fu), (xv, fv)) or None when nothing is admissible.""" + far_f = FB if far == B else FA + cands = (((x_prev, f_prev), (x_prev2, f_prev2)), + ((x_prev, f_prev), (far, far_f)), + ((A, FA), (B, FB))) + best, best_d = None, None + for u, v in cands: + if u[0] is None or v[0] is None: + continue + d = _shape_defect(x, fx, u[0], u[1], v[0], v[1]) + if d is None or x == u[0] or x == v[0]: + continue + if best_d is None or d < best_d: + best, best_d = (u, v), d + return best + + def _log_map(t, c, s): """u = sign(t - c) * log1p(|t - c| / s). An ADDITIVE step in u is a MULTIPLICATIVE step in x, which is what the wide-bracket families need: the @@ -413,7 +454,8 @@ def _local_order(x2, f2, x1, f1, x0, f0): def pure_root(f, a, b, xtol, maxfev, similarity="ratio", scale="derived", guard="step", stats=None, budget_factor=2.0, - budget_extra=None, endowment=1.0, space="x", prestep="none"): + budget_extra=None, endowment=1.0, space="x", prestep="none", + points="recent", direction="distance"): """The pure similarity root finder. similarity : key into PURE_SIMS @@ -469,6 +511,14 @@ def pure_root(f, a, b, xtol, maxfev, similarity="ratio", scale="derived", raise ValueError(f"unknown space {space!r}") if prestep not in ("none", "progress", "slope"): raise ValueError(f"unknown prestep {prestep!r}") + if points not in POINT_RULES: + raise ValueError(f"unknown points rule {points!r}") + if direction not in DIRECTIONS: + raise ValueError(f"unknown direction {direction!r}") + if points == "shape" and scale not in ("derived3", "derived3_rho", "derived3_m"): + # the triple only exists for the three-point scale; selecting one under a + # two-point scale would change nothing and hide that + raise ValueError("points='shape' requires a three-point scale (derived3*)") if prestep == "slope" and scale not in ("derived", "derived3"): # there is no slope to judge under a chosen or bracket scale; judging something # else would hide that, so the call fails instead @@ -501,11 +551,15 @@ def pure_root(f, a, b, xtol, maxfev, similarity="ratio", scale="derived", sg.credit = endowment forced = 0 pre_refused = 0 + triple_changed = 0 + dir_changed = 0 slope = 0.0 slope_prev = None if stats is not None: stats['forced'] = 0 stats['pre_refused'] = 0 + stats['triple_changed'] = 0 + stats['dir_changed'] = 0 while abs(B - A) > xtol: if sg.bisect_before_step(abs(B - A)): @@ -516,11 +570,38 @@ def pure_root(f, a, b, xtol, maxfev, similarity="ratio", scale="derived", sg.note_step(x_new - x) else: far = B if abs(B - x) >= abs(A - x) else A + if direction == "dissimilar": + # PREREG 2026-09-21, mode B: the far end read by SIMILARITY instead of + # geometry — the end whose |f| is larger is the one LESS similar to zero, + # i.e. the one the root is further from. Two values already in hand are + # compared; no constant. + far_sim = B if abs(FB) >= abs(FA) else A + if far_sim != far: + dir_changed += 1 + far = far_sim if scale in ("derived", "derived_rho"): slope = ((fx - f_prev) / (x - x_prev)) if x != x_prev else 0.0 sc = abs(slope) * abs(far - x) elif scale in ("derived3", "derived3_rho", "derived3_m"): - slope = _slope3(x, fx, x_prev, f_prev, x_prev2, f_prev2) + if points == "shape": + # PREREG 2026-09-21, mode A: which THREE points the model is built + # on, chosen by the SHAPE of the configuration instead of by recency. + # For a linear f the position ratio and the value ratio coincide, so + # |phi - xi| is a dimensionless measure of how unlike a linear + # configuration a triple is; the triple minimising it is SELECTED + # (the corpus rule is select, never weight). argmin over the declared + # candidates needs no threshold. + pick = _pick_triple(x, fx, x_prev, f_prev, x_prev2, f_prev2, + A, FA, B, FB, far) + if pick is None: + slope = _slope3(x, fx, x_prev, f_prev, x_prev2, f_prev2) + else: + (xu, fu), (xv, fv) = pick + if xu != x_prev or xv != x_prev2: + triple_changed += 1 + slope = _slope3(x, fx, xu, fu, xv, fv) + else: + slope = _slope3(x, fx, x_prev, f_prev, x_prev2, f_prev2) sc = abs(slope) * abs(far - x) if scale == "derived3_m": # REFUTED as an improvement - kept for reproducibility. @@ -665,7 +746,7 @@ def pure_root(f, a, b, xtol, maxfev, similarity="ratio", scale="derived", if x_new == x or x_new == x_prev: # the bracket can no longer be split in floating point if stats is not None: - stats['forced'] = forced; stats['pre_refused'] = pre_refused + stats['forced'] = forced; stats['pre_refused'] = pre_refused; stats['triple_changed'] = triple_changed; stats['dir_changed'] = dir_changed return x_new, g.n, abs(B - A) <= xtol w_before = abs(B - A) @@ -677,7 +758,7 @@ def pure_root(f, a, b, xtol, maxfev, similarity="ratio", scale="derived", x, fx = x_new, fnew if fnew == 0.0: if stats is not None: - stats['forced'] = forced; stats['pre_refused'] = pre_refused + stats['forced'] = forced; stats['pre_refused'] = pre_refused; stats['triple_changed'] = triple_changed; stats['dir_changed'] = dir_changed return x_new, g.n, True if FA * fnew < 0.0: B, FB = x_new, fnew @@ -686,9 +767,9 @@ def pure_root(f, a, b, xtol, maxfev, similarity="ratio", scale="derived", if guard == "credit": sg.note_shrink(w_before, abs(B - A)) if stats is not None: - stats['forced'] = forced; stats['pre_refused'] = pre_refused + stats['forced'] = forced; stats['pre_refused'] = pre_refused; stats['triple_changed'] = triple_changed; stats['dir_changed'] = dir_changed return 0.5 * (A + B), g.n, True except _Budget: if stats is not None: - stats['forced'] = forced; stats['pre_refused'] = pre_refused + stats['forced'] = forced; stats['pre_refused'] = pre_refused; stats['triple_changed'] = triple_changed; stats['dir_changed'] = dir_changed return x, g.n, False diff --git a/sweep_direction_smoke.json b/sweep_direction_smoke.json new file mode 100644 index 0000000..c92fad4 --- /dev/null +++ b/sweep_direction_smoke.json @@ -0,0 +1 @@ +[{"label": "pure+dissim+slope.ratio.derived3.project", "spec": ["pure", "ratio", "derived3", "project", "x", "slope", "recent", "dissimilar"], "APS": {"total": 2726, "solved": 153, "n": 154, "over": 0, "per": {"aps.01.00": [8, true], "aps.02.00": [35, true], "aps.02.01": [12, true], "aps.02.02": [28, true], "aps.02.03": [20, true], "aps.02.04": [16, true], "aps.02.05": [42, true], "aps.02.06": [17, true], "aps.02.07": [49, true], "aps.02.08": [50, true], "aps.02.09": [12, true], "aps.03.00": [16, true], "aps.03.01": [15, true], "aps.03.02": [17, true], "aps.04.00": [16, true], "aps.04.01": [40, true], "aps.04.02": [13, true], "aps.04.03": [15, true], "aps.04.04": [17, true], "aps.04.05": [13, true], "aps.04.06": [13, true], "aps.04.07": [14, true], "aps.04.08": [16, true], "aps.04.09": [14, true], "aps.04.10": [14, true], "aps.04.11": [15, true], "aps.04.12": [16, true], "aps.04.13": [20, true], "aps.05.00": [8, true], "aps.06.00": [7, true], "aps.06.01": [8, true], "aps.06.02": [9, true], "aps.06.03": [9, true], "aps.06.04": [9, true], "aps.06.05": [10, true], "aps.06.06": [10, true], "aps.06.07": [10, true], "aps.06.08": [13, true], "aps.06.09": [13, true], "aps.07.00": [10, true], "aps.07.01": [11, true], "aps.07.02": [15, true], "aps.08.00": [3, true], "aps.08.01": [10, true], "aps.08.02": [12, true], "aps.08.03": [15, true], "aps.08.04": [11, true], "aps.09.00": [8, true], "aps.09.01": [10, true], "aps.09.02": [14, true], "aps.09.03": [13, true], "aps.09.04": [16, true], "aps.09.05": [19, true], "aps.09.06": [21, true], "aps.10.00": [13, true], "aps.10.01": [12, true], "aps.10.02": [41, true], "aps.10.03": [34, true], "aps.10.04": [16, true], "aps.11.00": [5, true], "aps.11.01": [5, true], "aps.11.02": [5, true], "aps.11.03": [5, true], "aps.12.00": [9, true], "aps.12.01": [10, true], "aps.12.02": [9, true], "aps.12.03": [10, true], "aps.12.04": [10, true], "aps.12.05": [10, true], "aps.12.06": [10, true], "aps.12.07": [10, true], "aps.12.08": [10, true], "aps.12.09": [10, true], "aps.12.10": [10, true], "aps.12.11": [10, true], "aps.12.12": [10, true], "aps.12.13": [9, true], "aps.12.14": [9, true], "aps.12.15": [9, true], "aps.12.16": [9, true], "aps.12.17": [9, true], "aps.12.18": [9, true], "aps.13.00": [13, false], "aps.14.00": [15, true], "aps.14.01": [15, true], "aps.14.02": [15, true], "aps.14.03": [15, true], "aps.14.04": [15, true], "aps.14.05": [15, true], "aps.14.06": [15, true], "aps.14.07": [15, true], "aps.14.08": [15, true], "aps.14.09": [15, true], "aps.14.10": [15, true], "aps.14.11": [15, true], "aps.14.12": [15, true], "aps.14.13": [15, true], "aps.14.14": [15, true], "aps.14.15": [15, true], "aps.14.16": [15, true], "aps.14.17": [15, true], "aps.14.18": [15, true], "aps.14.19": [15, true], "aps.14.20": [15, true], "aps.14.21": [15, true], "aps.14.22": [15, true], "aps.14.23": [15, true], "aps.14.24": [15, true], "aps.14.25": [15, true], "aps.14.26": [15, true], "aps.14.27": [15, true], "aps.14.28": [15, true], "aps.14.29": [15, true], "aps.14.30": [15, true], "aps.14.31": [15, true], "aps.14.32": [15, true], "aps.14.33": [15, true], "aps.14.34": [15, true], "aps.14.35": [15, true], "aps.14.36": [15, true], "aps.14.37": [15, true], "aps.14.38": [15, true], "aps.14.39": [15, true], "aps.15.00": [20, true], "aps.15.01": [21, true], "aps.15.02": [21, true], "aps.15.03": [20, true], "aps.15.04": [21, true], "aps.15.05": [21, true], "aps.15.06": [21, true], "aps.15.07": [21, true], "aps.15.08": [21, true], "aps.15.09": [22, true], "aps.15.10": [21, true], "aps.15.11": [22, true], "aps.15.12": [23, true], "aps.15.13": [23, true], "aps.15.14": [22, true], "aps.15.15": [23, true], "aps.15.16": [22, true], "aps.15.17": [23, true], "aps.15.18": [23, true], "aps.15.19": [23, true], "aps.15.20": [23, true], "aps.15.21": [24, true], "aps.15.22": [26, true], "aps.15.23": [27, true], "aps.15.24": [27, true], "aps.15.25": [26, true], "aps.15.26": [27, true], "aps.15.27": [30, true], "aps.15.28": [41, true], "aps.15.29": [28, true], "aps.15.30": [28, true]}}, "CHA": {"total": 2785, "solved": 40, "n": 45, "over": 0, "per": {"fun1.1": [7, true], "fun1.2": [12, true], "fun1.3": [30, true], "fun1.4": [46, true], "fun1.5": [57, true], "fun2.1": [9, true], "fun2.2": [26, true], "fun2.3": [14, true], "fun2.4": [43, true], "fun2.5": [49, true], "fun3.1": [61, true], "fun3.2": [70, true], "fun3.3": [71, true], "fun3.4": [79, true], "fun3.5": [91, true], "fun4.1": [71, true], "fun4.2": [74, true], "fun4.3": [73, true], "fun4.4": [75, true], "fun4.5": [99, true], "fun5.1": [68, true], "fun5.2": [62, true], "fun5.3": [61, true], "fun5.4": [75, true], "fun5.5": [76, true], "fun6.1": [57, true], "fun6.2": [53, true], "fun6.3": [51, true], "fun6.4": [53, true], "fun6.5": [56, true], "fun7.1": [13, false], "fun7.2": [46, false], "fun7.3": [14, false], "fun7.4": [11, false], "fun7.5": [13, false], "fun8.1": [10, true], "fun8.2": [9, true], "fun8.3": [11, true], "fun8.4": [11, true], "fun8.5": [11, true], "fun9.1": [8, true], "fun9.2": [11, true], "fun9.3": [14, true], "fun9.4": [15, true], "fun9.5": [16, true]}}}, {"label": "pure+dissim+slope.ratio.derived.project", "spec": ["pure", "ratio", "derived", "project", "x", "slope", "recent", "dissimilar"], "APS": {"total": 3232, "solved": 153, "n": 154, "over": 0, "per": {"aps.01.00": [9, true], "aps.02.00": [17, true], "aps.02.01": [12, true], "aps.02.02": [31, true], "aps.02.03": [12, true], "aps.02.04": [38, true], "aps.02.05": [40, true], "aps.02.06": [11, true], "aps.02.07": [39, true], "aps.02.08": [38, true], "aps.02.09": [29, true], "aps.03.00": [15, true], "aps.03.01": [55, true], "aps.03.02": [16, true], "aps.04.00": [23, true], "aps.04.01": [27, true], "aps.04.02": [17, true], "aps.04.03": [17, true], "aps.04.04": [42, true], "aps.04.05": [14, true], "aps.04.06": [14, true], "aps.04.07": [15, true], "aps.04.08": [16, true], "aps.04.09": [17, true], "aps.04.10": [16, true], "aps.04.11": [16, true], "aps.04.12": [16, true], "aps.04.13": [16, true], "aps.05.00": [10, true], "aps.06.00": [8, true], "aps.06.01": [10, true], "aps.06.02": [12, true], "aps.06.03": [11, true], "aps.06.04": [10, true], "aps.06.05": [13, true], "aps.06.06": [14, true], "aps.06.07": [15, true], "aps.06.08": [15, true], "aps.06.09": [15, true], "aps.07.00": [13, true], "aps.07.01": [13, true], "aps.07.02": [14, true], "aps.08.00": [3, true], "aps.08.01": [10, true], "aps.08.02": [12, true], "aps.08.03": [30, true], "aps.08.04": [14, true], "aps.09.00": [11, true], "aps.09.01": [12, true], "aps.09.02": [13, true], "aps.09.03": [14, true], "aps.09.04": [16, true], "aps.09.05": [20, true], "aps.09.06": [21, true], "aps.10.00": [9, true], "aps.10.01": [16, true], "aps.10.02": [24, true], "aps.10.03": [10, true], "aps.10.04": [18, true], "aps.11.00": [5, true], "aps.11.01": [15, true], "aps.11.02": [16, true], "aps.11.03": [15, true], "aps.12.00": [11, true], "aps.12.01": [12, true], "aps.12.02": [12, true], "aps.12.03": [12, true], "aps.12.04": [12, true], "aps.12.05": [12, true], "aps.12.06": [12, true], "aps.12.07": [12, true], "aps.12.08": [12, true], "aps.12.09": [12, true], "aps.12.10": [12, true], "aps.12.11": [12, true], "aps.12.12": [12, true], "aps.12.13": [11, true], "aps.12.14": [11, true], "aps.12.15": [11, true], "aps.12.16": [11, true], "aps.12.17": [11, true], "aps.12.18": [11, true], "aps.13.00": [51, false], "aps.14.00": [17, true], "aps.14.01": [17, true], "aps.14.02": [17, true], "aps.14.03": [17, true], "aps.14.04": [17, true], "aps.14.05": [17, true], "aps.14.06": [17, true], "aps.14.07": [17, true], "aps.14.08": [17, true], "aps.14.09": [17, true], "aps.14.10": [17, true], "aps.14.11": [17, true], "aps.14.12": [17, true], "aps.14.13": [17, true], "aps.14.14": [17, true], "aps.14.15": [17, true], "aps.14.16": [17, true], "aps.14.17": [17, true], "aps.14.18": [17, true], "aps.14.19": [17, true], "aps.14.20": [17, true], "aps.14.21": [17, true], "aps.14.22": [17, true], "aps.14.23": [17, true], "aps.14.24": [17, true], "aps.14.25": [17, true], "aps.14.26": [17, true], "aps.14.27": [17, true], "aps.14.28": [17, true], "aps.14.29": [17, true], "aps.14.30": [17, true], "aps.14.31": [17, true], "aps.14.32": [17, true], "aps.14.33": [17, true], "aps.14.34": [17, true], "aps.14.35": [17, true], "aps.14.36": [17, true], "aps.14.37": [17, true], "aps.14.38": [17, true], "aps.14.39": [17, true], "aps.15.00": [32, true], "aps.15.01": [31, true], "aps.15.02": [31, true], "aps.15.03": [31, true], "aps.15.04": [31, true], "aps.15.05": [31, true], "aps.15.06": [31, true], "aps.15.07": [31, true], "aps.15.08": [31, true], "aps.15.09": [31, true], "aps.15.10": [32, true], "aps.15.11": [32, true], "aps.15.12": [32, true], "aps.15.13": [32, true], "aps.15.14": [33, true], "aps.15.15": [33, true], "aps.15.16": [32, true], "aps.15.17": [32, true], "aps.15.18": [32, true], "aps.15.19": [32, true], "aps.15.20": [33, true], "aps.15.21": [34, true], "aps.15.22": [37, true], "aps.15.23": [37, true], "aps.15.24": [35, true], "aps.15.25": [36, true], "aps.15.26": [38, true], "aps.15.27": [36, true], "aps.15.28": [36, true], "aps.15.29": [36, true], "aps.15.30": [35, true]}}, "CHA": {"total": 3474, "solved": 40, "n": 45, "over": 0, "per": {"fun1.1": [9, true], "fun1.2": [13, true], "fun1.3": [17, true], "fun1.4": [27, true], "fun1.5": [42, true], "fun2.1": [11, true], "fun2.2": [27, true], "fun2.3": [32, true], "fun2.4": [45, true], "fun2.5": [50, true], "fun3.1": [88, true], "fun3.2": [93, true], "fun3.3": [113, true], "fun3.4": [124, true], "fun3.5": [153, true], "fun4.1": [89, true], "fun4.2": [93, true], "fun4.3": [112, true], "fun4.4": [124, true], "fun4.5": [152, true], "fun5.1": [88, true], "fun5.2": [88, true], "fun5.3": [90, true], "fun5.4": [94, true], "fun5.5": [96, true], "fun6.1": [88, true], "fun6.2": [88, true], "fun6.3": [90, true], "fun6.4": [94, true], "fun6.5": [96, true], "fun7.1": [51, false], "fun7.2": [48, false], "fun7.3": [53, false], "fun7.4": [11, false], "fun7.5": [13, false], "fun8.1": [12, true], "fun8.2": [13, true], "fun8.3": [16, true], "fun8.4": [18, true], "fun8.5": [20, true], "fun9.1": [10, true], "fun9.2": [12, true], "fun9.3": [16, true], "fun9.4": [16, true], "fun9.5": [15, true]}}}, {"label": "pure+dissim+slope.ratio.derived.credit", "spec": ["pure", "ratio", "derived", "credit", "x", "slope", "recent", "dissimilar"], "APS": {"total": 4769, "solved": 153, "n": 154, "over": 0, "per": {"aps.01.00": [13, true], "aps.02.00": [45, true], "aps.02.01": [14, true], "aps.02.02": [46, true], "aps.02.03": [42, true], "aps.02.04": [10, true], "aps.02.05": [38, true], "aps.02.06": [10, true], "aps.02.07": [36, true], "aps.02.08": [35, true], "aps.02.09": [33, true], "aps.03.00": [46, true], "aps.03.01": [49, true], "aps.03.02": [49, true], "aps.04.00": [46, true], "aps.04.01": [43, true], "aps.04.02": [45, true], "aps.04.03": [46, true], "aps.04.04": [46, true], "aps.04.05": [46, true], "aps.04.06": [46, true], "aps.04.07": [46, true], "aps.04.08": [46, true], "aps.04.09": [46, true], "aps.04.10": [46, true], "aps.04.11": [46, true], "aps.04.12": [46, true], "aps.04.13": [46, true], "aps.05.00": [44, true], "aps.06.00": [15, true], "aps.06.01": [26, true], "aps.06.02": [29, true], "aps.06.03": [35, true], "aps.06.04": [43, true], "aps.06.05": [43, true], "aps.06.06": [43, true], "aps.06.07": [43, true], "aps.06.08": [15, true], "aps.06.09": [15, true], "aps.07.00": [13, true], "aps.07.01": [13, true], "aps.07.02": [14, true], "aps.08.00": [3, true], "aps.08.01": [14, true], "aps.08.02": [13, true], "aps.08.03": [43, true], "aps.08.04": [41, true], "aps.09.00": [15, true], "aps.09.01": [26, true], "aps.09.02": [13, true], "aps.09.03": [14, true], "aps.09.04": [16, true], "aps.09.05": [20, true], "aps.09.06": [21, true], "aps.10.00": [41, true], "aps.10.01": [42, true], "aps.10.02": [38, true], "aps.10.03": [43, true], "aps.10.04": [43, true], "aps.11.00": [43, true], "aps.11.01": [14, true], "aps.11.02": [12, true], "aps.11.03": [21, true], "aps.12.00": [11, true], "aps.12.01": [12, true], "aps.12.02": [12, true], "aps.12.03": [12, true], "aps.12.04": [12, true], "aps.12.05": [12, true], "aps.12.06": [14, true], "aps.12.07": [50, true], "aps.12.08": [50, true], "aps.12.09": [50, true], "aps.12.10": [50, true], "aps.12.11": [50, true], "aps.12.12": [50, true], "aps.12.13": [49, true], "aps.12.14": [50, true], "aps.12.15": [50, true], "aps.12.16": [50, true], "aps.12.17": [50, true], "aps.12.18": [50, true], "aps.13.00": [9, false], "aps.14.00": [17, true], "aps.14.01": [17, true], "aps.14.02": [17, true], "aps.14.03": [17, true], "aps.14.04": [17, true], "aps.14.05": [17, true], "aps.14.06": [17, true], "aps.14.07": [17, true], "aps.14.08": [17, true], "aps.14.09": [17, true], "aps.14.10": [17, true], "aps.14.11": [17, true], "aps.14.12": [17, true], "aps.14.13": [17, true], "aps.14.14": [17, true], "aps.14.15": [17, true], "aps.14.16": [17, true], "aps.14.17": [17, true], "aps.14.18": [17, true], "aps.14.19": [17, true], "aps.14.20": [17, true], "aps.14.21": [17, true], "aps.14.22": [17, true], "aps.14.23": [17, true], "aps.14.24": [17, true], "aps.14.25": [17, true], "aps.14.26": [17, true], "aps.14.27": [17, true], "aps.14.28": [17, true], "aps.14.29": [17, true], "aps.14.30": [17, true], "aps.14.31": [17, true], "aps.14.32": [17, true], "aps.14.33": [17, true], "aps.14.34": [17, true], "aps.14.35": [17, true], "aps.14.36": [17, true], "aps.14.37": [17, true], "aps.14.38": [17, true], "aps.14.39": [17, true], "aps.15.00": [39, true], "aps.15.01": [38, true], "aps.15.02": [53, true], "aps.15.03": [50, true], "aps.15.04": [49, true], "aps.15.05": [31, true], "aps.15.06": [31, true], "aps.15.07": [31, true], "aps.15.08": [31, true], "aps.15.09": [31, true], "aps.15.10": [32, true], "aps.15.11": [32, true], "aps.15.12": [32, true], "aps.15.13": [32, true], "aps.15.14": [33, true], "aps.15.15": [33, true], "aps.15.16": [32, true], "aps.15.17": [32, true], "aps.15.18": [32, true], "aps.15.19": [32, true], "aps.15.20": [33, true], "aps.15.21": [53, true], "aps.15.22": [53, true], "aps.15.23": [38, true], "aps.15.24": [35, true], "aps.15.25": [36, true], "aps.15.26": [53, true], "aps.15.27": [43, true], "aps.15.28": [51, true], "aps.15.29": [36, true], "aps.15.30": [35, true]}}, "CHA": {"total": 3078, "solved": 40, "n": 45, "over": 0, "per": {"fun1.1": [38, true], "fun1.2": [47, true], "fun1.3": [48, true], "fun1.4": [58, true], "fun1.5": [78, true], "fun2.1": [43, true], "fun2.2": [57, true], "fun2.3": [63, true], "fun2.4": [77, true], "fun2.5": [83, true], "fun3.1": [46, true], "fun3.2": [48, true], "fun3.3": [58, true], "fun3.4": [64, true], "fun3.5": [78, true], "fun4.1": [46, true], "fun4.2": [48, true], "fun4.3": [58, true], "fun4.4": [64, true], "fun4.5": [78, true], "fun5.1": [46, true], "fun5.2": [46, true], "fun5.3": [47, true], "fun5.4": [49, true], "fun5.5": [50, true], "fun6.1": [46, true], "fun6.2": [46, true], "fun6.3": [47, true], "fun6.4": [49, true], "fun6.5": [50, true], "fun7.1": [9, false], "fun7.2": [46, false], "fun7.3": [7, false], "fun7.4": [11, false], "fun7.5": [13, false], "fun8.1": [44, true], "fun8.2": [45, true], "fun8.3": [45, true], "fun8.4": [48, true], "fun8.5": [50, true], "fun9.1": [37, true], "fun9.2": [34, true], "fun9.3": [47, true], "fun9.4": [48, true], "fun9.5": [24, true]}}}, {"label": "pure+dissim+slope.ratio.derived3.credit", "spec": ["pure", "ratio", "derived3", "credit", "x", "slope", "recent", "dissimilar"], "APS": {"total": 3880, "solved": 153, "n": 154, "over": 0, "per": {"aps.01.00": [43, true], "aps.02.00": [17, true], "aps.02.01": [13, true], "aps.02.02": [44, true], "aps.02.03": [45, true], "aps.02.04": [26, true], "aps.02.05": [20, true], "aps.02.06": [31, true], "aps.02.07": [12, true], "aps.02.08": [10, true], "aps.02.09": [10, true], "aps.03.00": [49, true], "aps.03.01": [47, true], "aps.03.02": [47, true], "aps.04.00": [46, true], "aps.04.01": [46, true], "aps.04.02": [46, true], "aps.04.03": [46, true], "aps.04.04": [46, true], "aps.04.05": [46, true], "aps.04.06": [46, true], "aps.04.07": [46, true], "aps.04.08": [46, true], "aps.04.09": [46, true], "aps.04.10": [46, true], "aps.04.11": [46, true], "aps.04.12": [46, true], "aps.04.13": [46, true], "aps.05.00": [13, true], "aps.06.00": [37, true], "aps.06.01": [25, true], "aps.06.02": [38, true], "aps.06.03": [10, true], "aps.06.04": [10, true], "aps.06.05": [43, true], "aps.06.06": [43, true], "aps.06.07": [43, true], "aps.06.08": [43, true], "aps.06.09": [43, true], "aps.07.00": [25, true], "aps.07.01": [32, true], "aps.07.02": [42, true], "aps.08.00": [3, true], "aps.08.01": [15, true], "aps.08.02": [43, true], "aps.08.03": [43, true], "aps.08.04": [43, true], "aps.09.00": [17, true], "aps.09.01": [17, true], "aps.09.02": [14, true], "aps.09.03": [13, true], "aps.09.04": [16, true], "aps.09.05": [19, true], "aps.09.06": [43, true], "aps.10.00": [41, true], "aps.10.01": [39, true], "aps.10.02": [43, true], "aps.10.03": [43, true], "aps.10.04": [41, true], "aps.11.00": [43, true], "aps.11.01": [27, true], "aps.11.02": [11, true], "aps.11.03": [21, true], "aps.12.00": [9, true], "aps.12.01": [10, true], "aps.12.02": [9, true], "aps.12.03": [10, true], "aps.12.04": [10, true], "aps.12.05": [10, true], "aps.12.06": [10, true], "aps.12.07": [10, true], "aps.12.08": [16, true], "aps.12.09": [16, true], "aps.12.10": [15, true], "aps.12.11": [30, true], "aps.12.12": [48, true], "aps.12.13": [35, true], "aps.12.14": [34, true], "aps.12.15": [34, true], "aps.12.16": [18, true], "aps.12.17": [21, true], "aps.12.18": [19, true], "aps.13.00": [9, false], "aps.14.00": [13, true], "aps.14.01": [13, true], "aps.14.02": [13, true], "aps.14.03": [13, true], "aps.14.04": [13, true], "aps.14.05": [13, true], "aps.14.06": [13, true], "aps.14.07": [13, true], "aps.14.08": [13, true], "aps.14.09": [13, true], "aps.14.10": [13, true], "aps.14.11": [13, true], "aps.14.12": [13, true], "aps.14.13": [13, true], "aps.14.14": [13, true], "aps.14.15": [13, true], "aps.14.16": [13, true], "aps.14.17": [13, true], "aps.14.18": [13, true], "aps.14.19": [13, true], "aps.14.20": [13, true], "aps.14.21": [13, true], "aps.14.22": [13, true], "aps.14.23": [13, true], "aps.14.24": [13, true], "aps.14.25": [13, true], "aps.14.26": [13, true], "aps.14.27": [13, true], "aps.14.28": [13, true], "aps.14.29": [13, true], "aps.14.30": [13, true], "aps.14.31": [13, true], "aps.14.32": [13, true], "aps.14.33": [13, true], "aps.14.34": [13, true], "aps.14.35": [13, true], "aps.14.36": [13, true], "aps.14.37": [13, true], "aps.14.38": [13, true], "aps.14.39": [13, true], "aps.15.00": [19, true], "aps.15.01": [19, true], "aps.15.02": [19, true], "aps.15.03": [19, true], "aps.15.04": [20, true], "aps.15.05": [20, true], "aps.15.06": [20, true], "aps.15.07": [20, true], "aps.15.08": [21, true], "aps.15.09": [24, true], "aps.15.10": [19, true], "aps.15.11": [21, true], "aps.15.12": [21, true], "aps.15.13": [22, true], "aps.15.14": [21, true], "aps.15.15": [21, true], "aps.15.16": [21, true], "aps.15.17": [22, true], "aps.15.18": [22, true], "aps.15.19": [21, true], "aps.15.20": [21, true], "aps.15.21": [23, true], "aps.15.22": [26, true], "aps.15.23": [26, true], "aps.15.24": [26, true], "aps.15.25": [25, true], "aps.15.26": [27, true], "aps.15.27": [28, true], "aps.15.28": [28, true], "aps.15.29": [27, true], "aps.15.30": [27, true]}}, "CHA": {"total": 3002, "solved": 40, "n": 45, "over": 0, "per": {"fun1.1": [19, true], "fun1.2": [45, true], "fun1.3": [50, true], "fun1.4": [58, true], "fun1.5": [76, true], "fun2.1": [11, true], "fun2.2": [57, true], "fun2.3": [63, true], "fun2.4": [77, true], "fun2.5": [83, true], "fun3.1": [46, true], "fun3.2": [48, true], "fun3.3": [58, true], "fun3.4": [64, true], "fun3.5": [74, true], "fun4.1": [46, true], "fun4.2": [48, true], "fun4.3": [58, true], "fun4.4": [64, true], "fun4.5": [61, true], "fun5.1": [46, true], "fun5.2": [46, true], "fun5.3": [47, true], "fun5.4": [49, true], "fun5.5": [50, true], "fun6.1": [46, true], "fun6.2": [46, true], "fun6.3": [47, true], "fun6.4": [49, true], "fun6.5": [50, true], "fun7.1": [9, false], "fun7.2": [10, false], "fun7.3": [7, false], "fun7.4": [11, false], "fun7.5": [13, false], "fun8.1": [44, true], "fun8.2": [45, true], "fun8.3": [43, true], "fun8.4": [48, true], "fun8.5": [41, true], "fun9.1": [43, true], "fun9.2": [45, true], "fun9.3": [47, true], "fun9.4": [48, true], "fun9.5": [16, true]}}}, {"label": "pure+dissim+slope.sqrt.derived.credit", "spec": ["pure", "sqrt", "derived", "credit", "x", "slope", "recent", "dissimilar"], "APS": {"total": 7711, "solved": 153, "n": 154, "over": 0, "per": {"aps.01.00": [44, true], "aps.02.00": [45, true], "aps.02.01": [46, true], "aps.02.02": [46, true], "aps.02.03": [47, true], "aps.02.04": [47, true], "aps.02.05": [47, true], "aps.02.06": [47, true], "aps.02.07": [47, true], "aps.02.08": [48, true], "aps.02.09": [48, true], "aps.03.00": [49, true], "aps.03.01": [49, true], "aps.03.02": [49, true], "aps.04.00": [46, true], "aps.04.01": [46, true], "aps.04.02": [46, true], "aps.04.03": [46, true], "aps.04.04": [46, true], "aps.04.05": [46, true], "aps.04.06": [46, true], "aps.04.07": [46, true], "aps.04.08": [46, true], "aps.04.09": [46, true], "aps.04.10": [46, true], "aps.04.11": [46, true], "aps.04.12": [46, true], "aps.04.13": [46, true], "aps.05.00": [44, true], "aps.06.00": [43, true], "aps.06.01": [43, true], "aps.06.02": [43, true], "aps.06.03": [43, true], "aps.06.04": [43, true], "aps.06.05": [43, true], "aps.06.06": [43, true], "aps.06.07": [43, true], "aps.06.08": [43, true], "aps.06.09": [43, true], "aps.07.00": [43, true], "aps.07.01": [43, true], "aps.07.02": [43, true], "aps.08.00": [43, true], "aps.08.01": [43, true], "aps.08.02": [43, true], "aps.08.03": [43, true], "aps.08.04": [43, true], "aps.09.00": [43, true], "aps.09.01": [43, true], "aps.09.02": [43, true], "aps.09.03": [43, true], "aps.09.04": [43, true], "aps.09.05": [43, true], "aps.09.06": [43, true], "aps.10.00": [43, true], "aps.10.01": [43, true], "aps.10.02": [43, true], "aps.10.03": [43, true], "aps.10.04": [43, true], "aps.11.00": [43, true], "aps.11.01": [43, true], "aps.11.02": [43, true], "aps.11.03": [43, true], "aps.12.00": [50, true], "aps.12.01": [50, true], "aps.12.02": [50, true], "aps.12.03": [50, true], "aps.12.04": [50, true], "aps.12.05": [50, true], "aps.12.06": [50, true], "aps.12.07": [50, true], "aps.12.08": [50, true], "aps.12.09": [50, true], "aps.12.10": [50, true], "aps.12.11": [50, true], "aps.12.12": [50, true], "aps.12.13": [50, true], "aps.12.14": [50, true], "aps.12.15": [50, true], "aps.12.16": [50, true], "aps.12.17": [50, true], "aps.12.18": [46, true], "aps.13.00": [9, false], "aps.14.00": [53, true], "aps.14.01": [53, true], "aps.14.02": [53, true], "aps.14.03": [53, true], "aps.14.04": [53, true], "aps.14.05": [53, true], "aps.14.06": [53, true], "aps.14.07": [53, true], "aps.14.08": [53, true], "aps.14.09": [53, true], "aps.14.10": [53, true], "aps.14.11": [53, true], "aps.14.12": [53, true], "aps.14.13": [53, true], "aps.14.14": [53, true], "aps.14.15": [53, true], "aps.14.16": [53, true], "aps.14.17": [53, true], "aps.14.18": [53, true], "aps.14.19": [53, true], "aps.14.20": [53, true], "aps.14.21": [53, true], "aps.14.22": [53, true], "aps.14.23": [53, true], "aps.14.24": [53, true], "aps.14.25": [53, true], "aps.14.26": [53, true], "aps.14.27": [53, true], "aps.14.28": [53, true], "aps.14.29": [53, true], "aps.14.30": [53, true], "aps.14.31": [53, true], "aps.14.32": [53, true], "aps.14.33": [53, true], "aps.14.34": [53, true], "aps.14.35": [53, true], "aps.14.36": [53, true], "aps.14.37": [53, true], "aps.14.38": [53, true], "aps.14.39": [53, true], "aps.15.00": [53, true], "aps.15.01": [53, true], "aps.15.02": [53, true], "aps.15.03": [53, true], "aps.15.04": [53, true], "aps.15.05": [53, true], "aps.15.06": [53, true], "aps.15.07": [53, true], "aps.15.08": [50, true], "aps.15.09": [53, true], "aps.15.10": [53, true], "aps.15.11": [53, true], "aps.15.12": [53, true], "aps.15.13": [53, true], "aps.15.14": [53, true], "aps.15.15": [53, true], "aps.15.16": [53, true], "aps.15.17": [51, true], "aps.15.18": [53, true], "aps.15.19": [51, true], "aps.15.20": [53, true], "aps.15.21": [53, true], "aps.15.22": [53, true], "aps.15.23": [53, true], "aps.15.24": [53, true], "aps.15.25": [53, true], "aps.15.26": [53, true], "aps.15.27": [53, true], "aps.15.28": [53, true], "aps.15.29": [53, true], "aps.15.30": [53, true]}}, "CHA": {"total": 3130, "solved": 40, "n": 45, "over": 0, "per": {"fun1.1": [43, true], "fun1.2": [47, true], "fun1.3": [50, true], "fun1.4": [58, true], "fun1.5": [78, true], "fun2.1": [43, true], "fun2.2": [57, true], "fun2.3": [63, true], "fun2.4": [77, true], "fun2.5": [83, true], "fun3.1": [46, true], "fun3.2": [48, true], "fun3.3": [58, true], "fun3.4": [64, true], "fun3.5": [78, true], "fun4.1": [46, true], "fun4.2": [48, true], "fun4.3": [58, true], "fun4.4": [64, true], "fun4.5": [78, true], "fun5.1": [46, true], "fun5.2": [46, true], "fun5.3": [47, true], "fun5.4": [49, true], "fun5.5": [50, true], "fun6.1": [46, true], "fun6.2": [46, true], "fun6.3": [47, true], "fun6.4": [49, true], "fun6.5": [50, true], "fun7.1": [9, false], "fun7.2": [9, false], "fun7.3": [8, false], "fun7.4": [9, false], "fun7.5": [12, false], "fun8.1": [44, true], "fun8.2": [45, true], "fun8.3": [47, true], "fun8.4": [48, true], "fun8.5": [50, true], "fun9.1": [43, true], "fun9.2": [45, true], "fun9.3": [47, true], "fun9.4": [48, true], "fun9.5": [50, true]}}}, {"label": "pure+dissim+slope.sqrt.derived3.credit", "spec": ["pure", "sqrt", "derived3", "credit", "x", "slope", "recent", "dissimilar"], "APS": {"total": 7704, "solved": 153, "n": 154, "over": 0, "per": {"aps.01.00": [44, true], "aps.02.00": [45, true], "aps.02.01": [46, true], "aps.02.02": [46, true], "aps.02.03": [47, true], "aps.02.04": [47, true], "aps.02.05": [47, true], "aps.02.06": [47, true], "aps.02.07": [47, true], "aps.02.08": [48, true], "aps.02.09": [48, true], "aps.03.00": [49, true], "aps.03.01": [49, true], "aps.03.02": [49, true], "aps.04.00": [46, true], "aps.04.01": [46, true], "aps.04.02": [46, true], "aps.04.03": [46, true], "aps.04.04": [46, true], "aps.04.05": [46, true], "aps.04.06": [46, true], "aps.04.07": [46, true], "aps.04.08": [46, true], "aps.04.09": [46, true], "aps.04.10": [46, true], "aps.04.11": [46, true], "aps.04.12": [46, true], "aps.04.13": [46, true], "aps.05.00": [44, true], "aps.06.00": [43, true], "aps.06.01": [43, true], "aps.06.02": [43, true], "aps.06.03": [43, true], "aps.06.04": [43, true], "aps.06.05": [43, true], "aps.06.06": [43, true], "aps.06.07": [43, true], "aps.06.08": [43, true], "aps.06.09": [43, true], "aps.07.00": [43, true], "aps.07.01": [43, true], "aps.07.02": [43, true], "aps.08.00": [43, true], "aps.08.01": [43, true], "aps.08.02": [43, true], "aps.08.03": [43, true], "aps.08.04": [43, true], "aps.09.00": [43, true], "aps.09.01": [43, true], "aps.09.02": [43, true], "aps.09.03": [43, true], "aps.09.04": [43, true], "aps.09.05": [43, true], "aps.09.06": [43, true], "aps.10.00": [43, true], "aps.10.01": [43, true], "aps.10.02": [43, true], "aps.10.03": [43, true], "aps.10.04": [43, true], "aps.11.00": [43, true], "aps.11.01": [43, true], "aps.11.02": [43, true], "aps.11.03": [43, true], "aps.12.00": [50, true], "aps.12.01": [50, true], "aps.12.02": [50, true], "aps.12.03": [50, true], "aps.12.04": [50, true], "aps.12.05": [50, true], "aps.12.06": [50, true], "aps.12.07": [50, true], "aps.12.08": [47, true], "aps.12.09": [50, true], "aps.12.10": [50, true], "aps.12.11": [50, true], "aps.12.12": [50, true], "aps.12.13": [50, true], "aps.12.14": [50, true], "aps.12.15": [50, true], "aps.12.16": [50, true], "aps.12.17": [50, true], "aps.12.18": [50, true], "aps.13.00": [9, false], "aps.14.00": [53, true], "aps.14.01": [53, true], "aps.14.02": [53, true], "aps.14.03": [53, true], "aps.14.04": [53, true], "aps.14.05": [53, true], "aps.14.06": [53, true], "aps.14.07": [53, true], "aps.14.08": [53, true], "aps.14.09": [53, true], "aps.14.10": [53, true], "aps.14.11": [53, true], "aps.14.12": [53, true], "aps.14.13": [53, true], "aps.14.14": [53, true], "aps.14.15": [53, true], "aps.14.16": [53, true], "aps.14.17": [53, true], "aps.14.18": [53, true], "aps.14.19": [53, true], "aps.14.20": [53, true], "aps.14.21": [53, true], "aps.14.22": [53, true], "aps.14.23": [53, true], "aps.14.24": [53, true], "aps.14.25": [53, true], "aps.14.26": [53, true], "aps.14.27": [53, true], "aps.14.28": [53, true], "aps.14.29": [53, true], "aps.14.30": [53, true], "aps.14.31": [53, true], "aps.14.32": [53, true], "aps.14.33": [53, true], "aps.14.34": [53, true], "aps.14.35": [53, true], "aps.14.36": [53, true], "aps.14.37": [53, true], "aps.14.38": [53, true], "aps.14.39": [53, true], "aps.15.00": [53, true], "aps.15.01": [53, true], "aps.15.02": [52, true], "aps.15.03": [53, true], "aps.15.04": [53, true], "aps.15.05": [45, true], "aps.15.06": [53, true], "aps.15.07": [53, true], "aps.15.08": [53, true], "aps.15.09": [53, true], "aps.15.10": [53, true], "aps.15.11": [53, true], "aps.15.12": [53, true], "aps.15.13": [53, true], "aps.15.14": [53, true], "aps.15.15": [53, true], "aps.15.16": [51, true], "aps.15.17": [53, true], "aps.15.18": [53, true], "aps.15.19": [53, true], "aps.15.20": [53, true], "aps.15.21": [53, true], "aps.15.22": [53, true], "aps.15.23": [53, true], "aps.15.24": [49, true], "aps.15.25": [53, true], "aps.15.26": [53, true], "aps.15.27": [53, true], "aps.15.28": [53, true], "aps.15.29": [53, true], "aps.15.30": [53, true]}}, "CHA": {"total": 3128, "solved": 40, "n": 45, "over": 0, "per": {"fun1.1": [43, true], "fun1.2": [47, true], "fun1.3": [50, true], "fun1.4": [58, true], "fun1.5": [78, true], "fun2.1": [43, true], "fun2.2": [57, true], "fun2.3": [63, true], "fun2.4": [77, true], "fun2.5": [83, true], "fun3.1": [46, true], "fun3.2": [48, true], "fun3.3": [58, true], "fun3.4": [64, true], "fun3.5": [78, true], "fun4.1": [46, true], "fun4.2": [48, true], "fun4.3": [58, true], "fun4.4": [64, true], "fun4.5": [78, true], "fun5.1": [45, true], "fun5.2": [46, true], "fun5.3": [47, true], "fun5.4": [49, true], "fun5.5": [50, true], "fun6.1": [46, true], "fun6.2": [45, true], "fun6.3": [47, true], "fun6.4": [49, true], "fun6.5": [50, true], "fun7.1": [9, false], "fun7.2": [46, false], "fun7.3": [8, false], "fun7.4": [11, false], "fun7.5": [11, false], "fun8.1": [44, true], "fun8.2": [45, true], "fun8.3": [47, true], "fun8.4": [48, true], "fun8.5": [50, true], "fun9.1": [43, true], "fun9.2": [45, true], "fun9.3": [47, true], "fun9.4": [48, true], "fun9.5": [50, true]}}}, {"label": "pure+dissim+slope.sqrt.derived.project", "spec": ["pure", "sqrt", "derived", "project", "x", "slope", "recent", "dissimilar"], "APS": {"total": 9688, "solved": 153, "n": 154, "over": 0, "per": {"aps.01.00": [60, true], "aps.02.00": [53, true], "aps.02.01": [62, true], "aps.02.02": [59, true], "aps.02.03": [61, true], "aps.02.04": [65, true], "aps.02.05": [65, true], "aps.02.06": [65, true], "aps.02.07": [65, true], "aps.02.08": [66, true], "aps.02.09": [66, true], "aps.03.00": [62, true], "aps.03.01": [61, true], "aps.03.02": [57, true], "aps.04.00": [58, true], "aps.04.01": [56, true], "aps.04.02": [53, true], "aps.04.03": [55, true], "aps.04.04": [59, true], "aps.04.05": [58, true], "aps.04.06": [57, true], "aps.04.07": [61, true], "aps.04.08": [56, true], "aps.04.09": [56, true], "aps.04.10": [63, true], "aps.04.11": [60, true], "aps.04.12": [62, true], "aps.04.13": [59, true], "aps.05.00": [57, true], "aps.06.00": [60, true], "aps.06.01": [59, true], "aps.06.02": [56, true], "aps.06.03": [58, true], "aps.06.04": [58, true], "aps.06.05": [54, true], "aps.06.06": [54, true], "aps.06.07": [55, true], "aps.06.08": [57, true], "aps.06.09": [54, true], "aps.07.00": [57, true], "aps.07.01": [56, true], "aps.07.02": [55, true], "aps.08.00": [60, true], "aps.08.01": [59, true], "aps.08.02": [52, true], "aps.08.03": [53, true], "aps.08.04": [54, true], "aps.09.00": [58, true], "aps.09.01": [58, true], "aps.09.02": [55, true], "aps.09.03": [57, true], "aps.09.04": [56, true], "aps.09.05": [54, true], "aps.09.06": [53, true], "aps.10.00": [60, true], "aps.10.01": [59, true], "aps.10.02": [55, true], "aps.10.03": [56, true], "aps.10.04": [53, true], "aps.11.00": [57, true], "aps.11.01": [58, true], "aps.11.02": [59, true], "aps.11.03": [52, true], "aps.12.00": [63, true], "aps.12.01": [60, true], "aps.12.02": [65, true], "aps.12.03": [63, true], "aps.12.04": [64, true], "aps.12.05": [67, true], "aps.12.06": [66, true], "aps.12.07": [65, true], "aps.12.08": [66, true], "aps.12.09": [66, true], "aps.12.10": [62, true], "aps.12.11": [65, true], "aps.12.12": [62, true], "aps.12.13": [65, true], "aps.12.14": [66, true], "aps.12.15": [66, true], "aps.12.16": [66, true], "aps.12.17": [61, true], "aps.12.18": [64, true], "aps.13.00": [16, false], "aps.14.00": [70, true], "aps.14.01": [70, true], "aps.14.02": [70, true], "aps.14.03": [70, true], "aps.14.04": [70, true], "aps.14.05": [70, true], "aps.14.06": [70, true], "aps.14.07": [70, true], "aps.14.08": [70, true], "aps.14.09": [70, true], "aps.14.10": [70, true], "aps.14.11": [70, true], "aps.14.12": [70, true], "aps.14.13": [70, true], "aps.14.14": [70, true], "aps.14.15": [70, true], "aps.14.16": [70, true], "aps.14.17": [70, true], "aps.14.18": [70, true], "aps.14.19": [70, true], "aps.14.20": [70, true], "aps.14.21": [70, true], "aps.14.22": [70, true], "aps.14.23": [70, true], "aps.14.24": [70, true], "aps.14.25": [70, true], "aps.14.26": [70, true], "aps.14.27": [70, true], "aps.14.28": [70, true], "aps.14.29": [70, true], "aps.14.30": [70, true], "aps.14.31": [70, true], "aps.14.32": [70, true], "aps.14.33": [70, true], "aps.14.34": [70, true], "aps.14.35": [70, true], "aps.14.36": [70, true], "aps.14.37": [70, true], "aps.14.38": [70, true], "aps.14.39": [70, true], "aps.15.00": [58, true], "aps.15.01": [60, true], "aps.15.02": [63, true], "aps.15.03": [64, true], "aps.15.04": [64, true], "aps.15.05": [64, true], "aps.15.06": [61, true], "aps.15.07": [58, true], "aps.15.08": [50, true], "aps.15.09": [60, true], "aps.15.10": [55, true], "aps.15.11": [55, true], "aps.15.12": [62, true], "aps.15.13": [62, true], "aps.15.14": [61, true], "aps.15.15": [61, true], "aps.15.16": [55, true], "aps.15.17": [51, true], "aps.15.18": [60, true], "aps.15.19": [51, true], "aps.15.20": [56, true], "aps.15.21": [62, true], "aps.15.22": [62, true], "aps.15.23": [62, true], "aps.15.24": [60, true], "aps.15.25": [60, true], "aps.15.26": [55, true], "aps.15.27": [54, true], "aps.15.28": [59, true], "aps.15.29": [55, true], "aps.15.30": [58, true]}}, "CHA": {"total": 3343, "solved": 40, "n": 45, "over": 0, "per": {"fun1.1": [53, true], "fun1.2": [61, true], "fun1.3": [65, true], "fun1.4": [66, true], "fun1.5": [83, true], "fun2.1": [58, true], "fun2.2": [70, true], "fun2.3": [81, true], "fun2.4": [94, true], "fun2.5": [100, true], "fun3.1": [31, true], "fun3.2": [34, true], "fun3.3": [40, true], "fun3.4": [46, true], "fun3.5": [54, true], "fun4.1": [39, true], "fun4.2": [39, true], "fun4.3": [55, true], "fun4.4": [61, true], "fun4.5": [66, true], "fun5.1": [45, true], "fun5.2": [48, true], "fun5.3": [43, true], "fun5.4": [44, true], "fun5.5": [46, true], "fun6.1": [50, true], "fun6.2": [55, true], "fun6.3": [70, true], "fun6.4": [72, true], "fun6.5": [73, true], "fun7.1": [16, false], "fun7.2": [13, false], "fun7.3": [8, false], "fun7.4": [19, false], "fun7.5": [19, false], "fun8.1": [60, true], "fun8.2": [61, true], "fun8.3": [64, true], "fun8.4": [61, true], "fun8.5": [66, true], "fun9.1": [58, true], "fun9.2": [58, true], "fun9.3": [60, true], "fun9.4": [50, true], "fun9.5": [63, true]}}}, {"label": "pure+dissim+slope.sqrt.derived3.project", "spec": ["pure", "sqrt", "derived3", "project", "x", "slope", "recent", "dissimilar"], "APS": {"total": 9569, "solved": 153, "n": 154, "over": 0, "per": {"aps.01.00": [60, true], "aps.02.00": [59, true], "aps.02.01": [60, true], "aps.02.02": [62, true], "aps.02.03": [61, true], "aps.02.04": [66, true], "aps.02.05": [60, true], "aps.02.06": [66, true], "aps.02.07": [66, true], "aps.02.08": [66, true], "aps.02.09": [65, true], "aps.03.00": [70, true], "aps.03.01": [63, true], "aps.03.02": [56, true], "aps.04.00": [60, true], "aps.04.01": [38, true], "aps.04.02": [60, true], "aps.04.03": [58, true], "aps.04.04": [62, true], "aps.04.05": [62, true], "aps.04.06": [62, true], "aps.04.07": [60, true], "aps.04.08": [62, true], "aps.04.09": [59, true], "aps.04.10": [62, true], "aps.04.11": [57, true], "aps.04.12": [64, true], "aps.04.13": [64, true], "aps.05.00": [59, true], "aps.06.00": [60, true], "aps.06.01": [60, true], "aps.06.02": [60, true], "aps.06.03": [60, true], "aps.06.04": [60, true], "aps.06.05": [61, true], "aps.06.06": [61, true], "aps.06.07": [61, true], "aps.06.08": [61, true], "aps.06.09": [61, true], "aps.07.00": [57, true], "aps.07.01": [56, true], "aps.07.02": [55, true], "aps.08.00": [60, true], "aps.08.01": [59, true], "aps.08.02": [54, true], "aps.08.03": [49, true], "aps.08.04": [56, true], "aps.09.00": [60, true], "aps.09.01": [56, true], "aps.09.02": [55, true], "aps.09.03": [57, true], "aps.09.04": [56, true], "aps.09.05": [54, true], "aps.09.06": [53, true], "aps.10.00": [60, true], "aps.10.01": [51, true], "aps.10.02": [55, true], "aps.10.03": [58, true], "aps.10.04": [60, true], "aps.11.00": [60, true], "aps.11.01": [57, true], "aps.11.02": [43, true], "aps.11.03": [57, true], "aps.12.00": [60, true], "aps.12.01": [68, true], "aps.12.02": [63, true], "aps.12.03": [57, true], "aps.12.04": [65, true], "aps.12.05": [69, true], "aps.12.06": [68, true], "aps.12.07": [68, true], "aps.12.08": [47, true], "aps.12.09": [65, true], "aps.12.10": [65, true], "aps.12.11": [61, true], "aps.12.12": [66, true], "aps.12.13": [67, true], "aps.12.14": [67, true], "aps.12.15": [67, true], "aps.12.16": [67, true], "aps.12.17": [64, true], "aps.12.18": [59, true], "aps.13.00": [7, false], "aps.14.00": [66, true], "aps.14.01": [66, true], "aps.14.02": [66, true], "aps.14.03": [66, true], "aps.14.04": [66, true], "aps.14.05": [66, true], "aps.14.06": [66, true], "aps.14.07": [66, true], "aps.14.08": [66, true], "aps.14.09": [66, true], "aps.14.10": [66, true], "aps.14.11": [66, true], "aps.14.12": [66, true], "aps.14.13": [66, true], "aps.14.14": [66, true], "aps.14.15": [66, true], "aps.14.16": [66, true], "aps.14.17": [66, true], "aps.14.18": [66, true], "aps.14.19": [66, true], "aps.14.20": [66, true], "aps.14.21": [66, true], "aps.14.22": [66, true], "aps.14.23": [66, true], "aps.14.24": [66, true], "aps.14.25": [66, true], "aps.14.26": [66, true], "aps.14.27": [66, true], "aps.14.28": [66, true], "aps.14.29": [66, true], "aps.14.30": [66, true], "aps.14.31": [66, true], "aps.14.32": [66, true], "aps.14.33": [66, true], "aps.14.34": [66, true], "aps.14.35": [66, true], "aps.14.36": [66, true], "aps.14.37": [66, true], "aps.14.38": [66, true], "aps.14.39": [66, true], "aps.15.00": [59, true], "aps.15.01": [57, true], "aps.15.02": [52, true], "aps.15.03": [59, true], "aps.15.04": [53, true], "aps.15.05": [45, true], "aps.15.06": [61, true], "aps.15.07": [61, true], "aps.15.08": [61, true], "aps.15.09": [61, true], "aps.15.10": [61, true], "aps.15.11": [61, true], "aps.15.12": [61, true], "aps.15.13": [59, true], "aps.15.14": [59, true], "aps.15.15": [56, true], "aps.15.16": [51, true], "aps.15.17": [57, true], "aps.15.18": [59, true], "aps.15.19": [59, true], "aps.15.20": [59, true], "aps.15.21": [58, true], "aps.15.22": [61, true], "aps.15.23": [62, true], "aps.15.24": [51, true], "aps.15.25": [61, true], "aps.15.26": [63, true], "aps.15.27": [61, true], "aps.15.28": [58, true], "aps.15.29": [58, true], "aps.15.30": [60, true]}}, "CHA": {"total": 3766, "solved": 40, "n": 45, "over": 0, "per": {"fun1.1": [52, true], "fun1.2": [58, true], "fun1.3": [64, true], "fun1.4": [77, true], "fun1.5": [97, true], "fun2.1": [53, true], "fun2.2": [64, true], "fun2.3": [83, true], "fun2.4": [96, true], "fun2.5": [104, true], "fun3.1": [47, true], "fun3.2": [48, true], "fun3.3": [65, true], "fun3.4": [73, true], "fun3.5": [89, true], "fun4.1": [58, true], "fun4.2": [60, true], "fun4.3": [71, true], "fun4.4": [76, true], "fun4.5": [104, true], "fun5.1": [62, true], "fun5.2": [60, true], "fun5.3": [60, true], "fun5.4": [64, true], "fun5.5": [66, true], "fun6.1": [53, true], "fun6.2": [84, true], "fun6.3": [84, true], "fun6.4": [86, true], "fun6.5": [87, true], "fun7.1": [7, false], "fun7.2": [12, false], "fun7.3": [8, false], "fun7.4": [11, false], "fun7.5": [15, false], "fun8.1": [60, true], "fun8.2": [60, true], "fun8.3": [66, true], "fun8.4": [66, true], "fun8.5": [68, true], "fun9.1": [60, true], "fun9.2": [54, true], "fun9.3": [63, true], "fun9.4": [61, true], "fun9.5": [63, true]}}}] \ No newline at end of file diff --git a/sweep_full.py b/sweep_full.py index 55d3af0..764d240 100644 --- a/sweep_full.py +++ b/sweep_full.py @@ -111,10 +111,13 @@ def make_method(spec): sim, scale, guard = spec[1], spec[2], spec[3] space = spec[4] if len(spec) > 4 else "x" prestep = spec[5] if len(spec) > 5 else "none" + points = spec[6] if len(spec) > 6 else "recent" + direction = spec[7] if len(spec) > 7 else "distance" def m(f, a, b, xtol, maxfev): return pure_root(f, a, b, xtol, maxfev, similarity=sim, - scale=scale, guard=guard, space=space, prestep=prestep) + scale=scale, guard=guard, space=space, prestep=prestep, + points=points, direction=direction) return m @@ -124,6 +127,10 @@ def label(spec): tag = "pure" if len(spec) > 4 and spec[4] != "x": tag = spec[4] + if len(spec) > 6 and spec[6] != "recent": + tag = f"{tag}+shape" + if len(spec) > 7 and spec[7] != "distance": + tag = f"{tag}+dissim" if len(spec) > 5 and spec[5] != "none": # name the gate by WHICH gate it is: "progress" is a measured negative and must # never be confused with "slope" in a results file @@ -191,6 +198,23 @@ def build_grid_log(smoke): for sim in sims for sc in ("derived", "derived3") for gu in guards] +def build_grid_points(smoke): + """Mode A (PREREG 2026-09-21): the triple chosen by shape, on top of the slope gate that + already reached the project target. Three-point scale only — a triple must exist.""" + sims = ["ratio", "sqrt"] if smoke else sorted(PURE_SIMS) + guards = ("credit", "project") if smoke else GUARD_MODES + return [("pure", sim, "derived3", gu, "x", "slope", "shape", "distance") + for sim in sims for gu in guards] + + +def build_grid_direction(smoke): + """Mode B (PREREG 2026-09-21): the far end read by dissimilarity, on top of the slope gate.""" + sims = ["ratio", "sqrt"] if smoke else sorted(PURE_SIMS) + guards = ("credit", "project") if smoke else GUARD_MODES + return [("pure", sim, sc, gu, "x", "slope", "recent", "dissimilar") + for sim in sims for sc in ("derived", "derived3") for gu in guards] + + def build_grid_slope(smoke): """The slope-stability gate grid (PREREG 2026-09-21). Only derived scales: there must be a slope to judge. Baselines are not recomputed — they are in sweep_full.json.""" @@ -231,7 +255,11 @@ def main(): logmode = "--log" in sys.argv # the u-space grid, written to its OWN file gatemode = "--gate" in sys.argv # the pre-step gate grid, likewise slopemode = "--slope" in sys.argv # the slope-stability gate grid - specs = (build_grid_slope(smoke) if slopemode else + pointsmode = "--points" in sys.argv # mode A: triple by shape + dirmode = "--direction" in sys.argv # mode B: far end by dissimilarity + specs = (build_grid_points(smoke) if pointsmode else + build_grid_direction(smoke) if dirmode else + build_grid_slope(smoke) if slopemode else build_grid_gate(smoke) if gatemode else build_grid_log(smoke) if logmode else build_grid(smoke)) t0 = time.time() @@ -249,6 +277,14 @@ 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 pointsmode or dirmode: + base = "sweep_points" if pointsmode else "sweep_direction" + out = f"{base}_smoke.json" if smoke else f"{base}.json" + with open(out, "w", encoding="utf8") as fh: + json.dump(results, fh) + print(f"wrote {out} ({time.time() - t0:.0f}s total)", flush=True) + report(results) + return if slopemode: out = "sweep_slope_smoke.json" if smoke else "sweep_slope.json" with open(out, "w", encoding="utf8") as fh: diff --git a/sweep_points_smoke.json b/sweep_points_smoke.json new file mode 100644 index 0000000..3d0693c --- /dev/null +++ b/sweep_points_smoke.json @@ -0,0 +1 @@ +[{"label": "pure+shape+slope.ratio.derived3.project", "spec": ["pure", "ratio", "derived3", "project", "x", "slope", "shape", "distance"], "APS": {"total": 2675, "solved": 153, "n": 154, "over": 0, "per": {"aps.01.00": [8, true], "aps.02.00": [14, true], "aps.02.01": [12, true], "aps.02.02": [48, true], "aps.02.03": [20, true], "aps.02.04": [16, true], "aps.02.05": [28, true], "aps.02.06": [11, true], "aps.02.07": [28, true], "aps.02.08": [20, true], "aps.02.09": [21, true], "aps.03.00": [17, true], "aps.03.01": [22, true], "aps.03.02": [20, true], "aps.04.00": [17, true], "aps.04.01": [30, true], "aps.04.02": [37, true], "aps.04.03": [22, true], "aps.04.04": [25, true], "aps.04.05": [14, true], "aps.04.06": [12, true], "aps.04.07": [13, true], "aps.04.08": [20, true], "aps.04.09": [14, true], "aps.04.10": [13, true], "aps.04.11": [13, true], "aps.04.12": [13, true], "aps.04.13": [14, true], "aps.05.00": [8, true], "aps.06.00": [7, true], "aps.06.01": [12, true], "aps.06.02": [9, true], "aps.06.03": [9, true], "aps.06.04": [9, true], "aps.06.05": [10, true], "aps.06.06": [10, true], "aps.06.07": [10, true], "aps.06.08": [13, true], "aps.06.09": [13, true], "aps.07.00": [10, true], "aps.07.01": [11, true], "aps.07.02": [11, true], "aps.08.00": [3, true], "aps.08.01": [10, true], "aps.08.02": [12, true], "aps.08.03": [15, true], "aps.08.04": [12, true], "aps.09.00": [10, true], "aps.09.01": [11, true], "aps.09.02": [11, true], "aps.09.03": [10, true], "aps.09.04": [10, true], "aps.09.05": [10, true], "aps.09.06": [11, true], "aps.10.00": [9, true], "aps.10.01": [12, true], "aps.10.02": [15, true], "aps.10.03": [12, true], "aps.10.04": [12, true], "aps.11.00": [5, true], "aps.11.01": [10, true], "aps.11.02": [5, true], "aps.11.03": [5, true], "aps.12.00": [9, true], "aps.12.01": [9, true], "aps.12.02": [10, true], "aps.12.03": [10, true], "aps.12.04": [10, true], "aps.12.05": [10, true], "aps.12.06": [10, true], "aps.12.07": [10, true], "aps.12.08": [10, true], "aps.12.09": [10, true], "aps.12.10": [10, true], "aps.12.11": [10, true], "aps.12.12": [10, true], "aps.12.13": [10, true], "aps.12.14": [9, true], "aps.12.15": [9, true], "aps.12.16": [9, true], "aps.12.17": [9, true], "aps.12.18": [9, true], "aps.13.00": [50, false], "aps.14.00": [16, true], "aps.14.01": [16, true], "aps.14.02": [16, true], "aps.14.03": [16, true], "aps.14.04": [16, true], "aps.14.05": [16, true], "aps.14.06": [16, true], "aps.14.07": [16, true], "aps.14.08": [16, true], "aps.14.09": [16, true], "aps.14.10": [16, true], "aps.14.11": [16, true], "aps.14.12": [16, true], "aps.14.13": [16, true], "aps.14.14": [16, true], "aps.14.15": [16, true], "aps.14.16": [16, true], "aps.14.17": [16, true], "aps.14.18": [16, true], "aps.14.19": [16, true], "aps.14.20": [16, true], "aps.14.21": [16, true], "aps.14.22": [16, true], "aps.14.23": [16, true], "aps.14.24": [16, true], "aps.14.25": [16, true], "aps.14.26": [16, true], "aps.14.27": [16, true], "aps.14.28": [16, true], "aps.14.29": [16, true], "aps.14.30": [16, true], "aps.14.31": [16, true], "aps.14.32": [16, true], "aps.14.33": [16, true], "aps.14.34": [16, true], "aps.14.35": [16, true], "aps.14.36": [16, true], "aps.14.37": [16, true], "aps.14.38": [16, true], "aps.14.39": [16, true], "aps.15.00": [22, true], "aps.15.01": [22, true], "aps.15.02": [22, true], "aps.15.03": [22, true], "aps.15.04": [22, true], "aps.15.05": [22, true], "aps.15.06": [22, true], "aps.15.07": [21, true], "aps.15.08": [22, true], "aps.15.09": [22, true], "aps.15.10": [22, true], "aps.15.11": [23, true], "aps.15.12": [24, true], "aps.15.13": [23, true], "aps.15.14": [23, true], "aps.15.15": [23, true], "aps.15.16": [23, true], "aps.15.17": [23, true], "aps.15.18": [23, true], "aps.15.19": [23, true], "aps.15.20": [25, true], "aps.15.21": [31, true], "aps.15.22": [28, true], "aps.15.23": [28, true], "aps.15.24": [28, true], "aps.15.25": [28, true], "aps.15.26": [28, true], "aps.15.27": [26, true], "aps.15.28": [28, true], "aps.15.29": [29, true], "aps.15.30": [30, true]}}, "CHA": {"total": 3498, "solved": 40, "n": 45, "over": 0, "per": {"fun1.1": [7, true], "fun1.2": [11, true], "fun1.3": [12, true], "fun1.4": [32, true], "fun1.5": [61, true], "fun2.1": [9, true], "fun2.2": [56, true], "fun2.3": [20, true], "fun2.4": [42, true], "fun2.5": [48, true], "fun3.1": [89, true], "fun3.2": [93, true], "fun3.3": [112, true], "fun3.4": [125, true], "fun3.5": [152, true], "fun4.1": [89, true], "fun4.2": [93, true], "fun4.3": [113, true], "fun4.4": [125, true], "fun4.5": [152, true], "fun5.1": [88, true], "fun5.2": [88, true], "fun5.3": [90, true], "fun5.4": [94, true], "fun5.5": [96, true], "fun6.1": [88, true], "fun6.2": [88, true], "fun6.3": [90, true], "fun6.4": [94, true], "fun6.5": [96, true], "fun7.1": [50, false], "fun7.2": [50, false], "fun7.3": [52, false], "fun7.4": [6, false], "fun7.5": [6, false], "fun8.1": [10, true], "fun8.2": [10, true], "fun8.3": [13, true], "fun8.4": [12, true], "fun8.5": [12, true], "fun9.1": [8, true], "fun9.2": [12, true], "fun9.3": [19, true], "fun9.4": [18, true], "fun9.5": [31, true]}}}, {"label": "pure+shape+slope.ratio.derived3.credit", "spec": ["pure", "ratio", "derived3", "credit", "x", "slope", "shape", "distance"], "APS": {"total": 3755, "solved": 153, "n": 154, "over": 0, "per": {"aps.01.00": [13, true], "aps.02.00": [14, true], "aps.02.01": [28, true], "aps.02.02": [44, true], "aps.02.03": [25, true], "aps.02.04": [25, true], "aps.02.05": [12, true], "aps.02.06": [17, true], "aps.02.07": [12, true], "aps.02.08": [10, true], "aps.02.09": [10, true], "aps.03.00": [49, true], "aps.03.01": [49, true], "aps.03.02": [49, true], "aps.04.00": [46, true], "aps.04.01": [46, true], "aps.04.02": [46, true], "aps.04.03": [46, true], "aps.04.04": [46, true], "aps.04.05": [46, true], "aps.04.06": [46, true], "aps.04.07": [46, true], "aps.04.08": [46, true], "aps.04.09": [46, true], "aps.04.10": [46, true], "aps.04.11": [46, true], "aps.04.12": [46, true], "aps.04.13": [46, true], "aps.05.00": [31, true], "aps.06.00": [10, true], "aps.06.01": [11, true], "aps.06.02": [30, true], "aps.06.03": [12, true], "aps.06.04": [43, true], "aps.06.05": [19, true], "aps.06.06": [33, true], "aps.06.07": [43, true], "aps.06.08": [34, true], "aps.06.09": [40, true], "aps.07.00": [13, true], "aps.07.01": [21, true], "aps.07.02": [35, true], "aps.08.00": [3, true], "aps.08.01": [20, true], "aps.08.02": [43, true], "aps.08.03": [43, true], "aps.08.04": [43, true], "aps.09.00": [42, true], "aps.09.01": [42, true], "aps.09.02": [21, true], "aps.09.03": [14, true], "aps.09.04": [18, true], "aps.09.05": [25, true], "aps.09.06": [39, true], "aps.10.00": [10, true], "aps.10.01": [17, true], "aps.10.02": [43, true], "aps.10.03": [43, true], "aps.10.04": [43, true], "aps.11.00": [33, true], "aps.11.01": [43, true], "aps.11.02": [43, true], "aps.11.03": [43, true], "aps.12.00": [9, true], "aps.12.01": [9, true], "aps.12.02": [10, true], "aps.12.03": [10, true], "aps.12.04": [10, true], "aps.12.05": [10, true], "aps.12.06": [10, true], "aps.12.07": [10, true], "aps.12.08": [10, true], "aps.12.09": [26, true], "aps.12.10": [17, true], "aps.12.11": [16, true], "aps.12.12": [50, true], "aps.12.13": [50, true], "aps.12.14": [50, true], "aps.12.15": [9, true], "aps.12.16": [11, true], "aps.12.17": [17, true], "aps.12.18": [16, true], "aps.13.00": [9, false], "aps.14.00": [14, true], "aps.14.01": [14, true], "aps.14.02": [14, true], "aps.14.03": [14, true], "aps.14.04": [14, true], "aps.14.05": [14, true], "aps.14.06": [14, true], "aps.14.07": [14, true], "aps.14.08": [14, true], "aps.14.09": [14, true], "aps.14.10": [14, true], "aps.14.11": [14, true], "aps.14.12": [14, true], "aps.14.13": [14, true], "aps.14.14": [14, true], "aps.14.15": [14, true], "aps.14.16": [14, true], "aps.14.17": [14, true], "aps.14.18": [14, true], "aps.14.19": [14, true], "aps.14.20": [14, true], "aps.14.21": [14, true], "aps.14.22": [14, true], "aps.14.23": [14, true], "aps.14.24": [14, true], "aps.14.25": [14, true], "aps.14.26": [14, true], "aps.14.27": [14, true], "aps.14.28": [14, true], "aps.14.29": [14, true], "aps.14.30": [14, true], "aps.14.31": [14, true], "aps.14.32": [14, true], "aps.14.33": [14, true], "aps.14.34": [14, true], "aps.14.35": [14, true], "aps.14.36": [14, true], "aps.14.37": [14, true], "aps.14.38": [14, true], "aps.14.39": [14, true], "aps.15.00": [16, true], "aps.15.01": [17, true], "aps.15.02": [17, true], "aps.15.03": [17, true], "aps.15.04": [17, true], "aps.15.05": [18, true], "aps.15.06": [18, true], "aps.15.07": [17, true], "aps.15.08": [16, true], "aps.15.09": [17, true], "aps.15.10": [17, true], "aps.15.11": [18, true], "aps.15.12": [18, true], "aps.15.13": [18, true], "aps.15.14": [18, true], "aps.15.15": [19, true], "aps.15.16": [19, true], "aps.15.17": [20, true], "aps.15.18": [20, true], "aps.15.19": [20, true], "aps.15.20": [20, true], "aps.15.21": [20, true], "aps.15.22": [23, true], "aps.15.23": [21, true], "aps.15.24": [22, true], "aps.15.25": [23, true], "aps.15.26": [22, true], "aps.15.27": [22, true], "aps.15.28": [22, true], "aps.15.29": [23, true], "aps.15.30": [23, true]}}, "CHA": {"total": 3021, "solved": 40, "n": 45, "over": 0, "per": {"fun1.1": [25, true], "fun1.2": [47, true], "fun1.3": [50, true], "fun1.4": [58, true], "fun1.5": [78, true], "fun2.1": [12, true], "fun2.2": [57, true], "fun2.3": [63, true], "fun2.4": [77, true], "fun2.5": [51, true], "fun3.1": [46, true], "fun3.2": [48, true], "fun3.3": [58, true], "fun3.4": [64, true], "fun3.5": [78, true], "fun4.1": [46, true], "fun4.2": [48, true], "fun4.3": [58, true], "fun4.4": [64, true], "fun4.5": [78, true], "fun5.1": [46, true], "fun5.2": [46, true], "fun5.3": [47, true], "fun5.4": [49, true], "fun5.5": [50, true], "fun6.1": [46, true], "fun6.2": [46, true], "fun6.3": [47, true], "fun6.4": [49, true], "fun6.5": [50, true], "fun7.1": [9, false], "fun7.2": [8, false], "fun7.3": [10, false], "fun7.4": [13, false], "fun7.5": [13, false], "fun8.1": [44, true], "fun8.2": [45, true], "fun8.3": [47, true], "fun8.4": [48, true], "fun8.5": [50, true], "fun9.1": [15, true], "fun9.2": [45, true], "fun9.3": [47, true], "fun9.4": [48, true], "fun9.5": [50, true]}}}, {"label": "pure+shape+slope.sqrt.derived3.credit", "spec": ["pure", "sqrt", "derived3", "credit", "x", "slope", "shape", "distance"], "APS": {"total": 7635, "solved": 153, "n": 154, "over": 0, "per": {"aps.01.00": [44, true], "aps.02.00": [45, true], "aps.02.01": [46, true], "aps.02.02": [46, true], "aps.02.03": [47, true], "aps.02.04": [47, true], "aps.02.05": [47, true], "aps.02.06": [47, true], "aps.02.07": [47, true], "aps.02.08": [48, true], "aps.02.09": [48, true], "aps.03.00": [49, true], "aps.03.01": [49, true], "aps.03.02": [49, true], "aps.04.00": [46, true], "aps.04.01": [46, true], "aps.04.02": [46, true], "aps.04.03": [46, true], "aps.04.04": [46, true], "aps.04.05": [46, true], "aps.04.06": [46, true], "aps.04.07": [46, true], "aps.04.08": [46, true], "aps.04.09": [46, true], "aps.04.10": [46, true], "aps.04.11": [46, true], "aps.04.12": [46, true], "aps.04.13": [46, true], "aps.05.00": [44, true], "aps.06.00": [43, true], "aps.06.01": [43, true], "aps.06.02": [43, true], "aps.06.03": [43, true], "aps.06.04": [43, true], "aps.06.05": [43, true], "aps.06.06": [43, true], "aps.06.07": [43, true], "aps.06.08": [43, true], "aps.06.09": [43, true], "aps.07.00": [43, true], "aps.07.01": [43, true], "aps.07.02": [43, true], "aps.08.00": [43, true], "aps.08.01": [43, true], "aps.08.02": [43, true], "aps.08.03": [43, true], "aps.08.04": [43, true], "aps.09.00": [43, true], "aps.09.01": [43, true], "aps.09.02": [43, true], "aps.09.03": [43, true], "aps.09.04": [43, true], "aps.09.05": [43, true], "aps.09.06": [43, true], "aps.10.00": [43, true], "aps.10.01": [43, true], "aps.10.02": [43, true], "aps.10.03": [43, true], "aps.10.04": [43, true], "aps.11.00": [43, true], "aps.11.01": [43, true], "aps.11.02": [43, true], "aps.11.03": [43, true], "aps.12.00": [50, true], "aps.12.01": [50, true], "aps.12.02": [50, true], "aps.12.03": [50, true], "aps.12.04": [50, true], "aps.12.05": [50, true], "aps.12.06": [50, true], "aps.12.07": [50, true], "aps.12.08": [50, true], "aps.12.09": [50, true], "aps.12.10": [50, true], "aps.12.11": [50, true], "aps.12.12": [50, true], "aps.12.13": [50, true], "aps.12.14": [50, true], "aps.12.15": [50, true], "aps.12.16": [50, true], "aps.12.17": [50, true], "aps.12.18": [42, true], "aps.13.00": [9, false], "aps.14.00": [53, true], "aps.14.01": [53, true], "aps.14.02": [53, true], "aps.14.03": [53, true], "aps.14.04": [53, true], "aps.14.05": [53, true], "aps.14.06": [53, true], "aps.14.07": [53, true], "aps.14.08": [53, true], "aps.14.09": [53, true], "aps.14.10": [53, true], "aps.14.11": [53, true], "aps.14.12": [53, true], "aps.14.13": [53, true], "aps.14.14": [53, true], "aps.14.15": [53, true], "aps.14.16": [53, true], "aps.14.17": [53, true], "aps.14.18": [53, true], "aps.14.19": [53, true], "aps.14.20": [53, true], "aps.14.21": [53, true], "aps.14.22": [53, true], "aps.14.23": [53, true], "aps.14.24": [53, true], "aps.14.25": [53, true], "aps.14.26": [53, true], "aps.14.27": [53, true], "aps.14.28": [53, true], "aps.14.29": [53, true], "aps.14.30": [53, true], "aps.14.31": [53, true], "aps.14.32": [53, true], "aps.14.33": [53, true], "aps.14.34": [53, true], "aps.14.35": [53, true], "aps.14.36": [53, true], "aps.14.37": [53, true], "aps.14.38": [53, true], "aps.14.39": [53, true], "aps.15.00": [51, true], "aps.15.01": [51, true], "aps.15.02": [52, true], "aps.15.03": [52, true], "aps.15.04": [52, true], "aps.15.05": [52, true], "aps.15.06": [52, true], "aps.15.07": [52, true], "aps.15.08": [52, true], "aps.15.09": [52, true], "aps.15.10": [52, true], "aps.15.11": [52, true], "aps.15.12": [52, true], "aps.15.13": [52, true], "aps.15.14": [52, true], "aps.15.15": [51, true], "aps.15.16": [51, true], "aps.15.17": [51, true], "aps.15.18": [51, true], "aps.15.19": [51, true], "aps.15.20": [50, true], "aps.15.21": [46, true], "aps.15.22": [50, true], "aps.15.23": [50, true], "aps.15.24": [49, true], "aps.15.25": [48, true], "aps.15.26": [50, true], "aps.15.27": [51, true], "aps.15.28": [50, true], "aps.15.29": [49, true], "aps.15.30": [38, true]}}, "CHA": {"total": 3130, "solved": 40, "n": 45, "over": 0, "per": {"fun1.1": [43, true], "fun1.2": [47, true], "fun1.3": [50, true], "fun1.4": [58, true], "fun1.5": [78, true], "fun2.1": [43, true], "fun2.2": [57, true], "fun2.3": [63, true], "fun2.4": [77, true], "fun2.5": [83, true], "fun3.1": [46, true], "fun3.2": [48, true], "fun3.3": [58, true], "fun3.4": [64, true], "fun3.5": [78, true], "fun4.1": [46, true], "fun4.2": [48, true], "fun4.3": [58, true], "fun4.4": [64, true], "fun4.5": [78, true], "fun5.1": [46, true], "fun5.2": [46, true], "fun5.3": [47, true], "fun5.4": [49, true], "fun5.5": [50, true], "fun6.1": [46, true], "fun6.2": [46, true], "fun6.3": [47, true], "fun6.4": [49, true], "fun6.5": [50, true], "fun7.1": [9, false], "fun7.2": [46, false], "fun7.3": [10, false], "fun7.4": [7, false], "fun7.5": [12, false], "fun8.1": [44, true], "fun8.2": [45, true], "fun8.3": [47, true], "fun8.4": [48, true], "fun8.5": [50, true], "fun9.1": [43, true], "fun9.2": [45, true], "fun9.3": [47, true], "fun9.4": [48, true], "fun9.5": [50, true]}}}, {"label": "pure+shape+slope.sqrt.derived3.project", "spec": ["pure", "sqrt", "derived3", "project", "x", "slope", "shape", "distance"], "APS": {"total": 9937, "solved": 153, "n": 154, "over": 0, "per": {"aps.01.00": [60, true], "aps.02.00": [87, true], "aps.02.01": [88, true], "aps.02.02": [89, true], "aps.02.03": [90, true], "aps.02.04": [67, true], "aps.02.05": [91, true], "aps.02.06": [91, true], "aps.02.07": [90, true], "aps.02.08": [92, true], "aps.02.09": [88, true], "aps.03.00": [94, true], "aps.03.01": [94, true], "aps.03.02": [94, true], "aps.04.00": [61, true], "aps.04.01": [59, true], "aps.04.02": [74, true], "aps.04.03": [88, true], "aps.04.04": [88, true], "aps.04.05": [62, true], "aps.04.06": [61, true], "aps.04.07": [69, true], "aps.04.08": [88, true], "aps.04.09": [74, true], "aps.04.10": [73, true], "aps.04.11": [89, true], "aps.04.12": [88, true], "aps.04.13": [88, true], "aps.05.00": [60, true], "aps.06.00": [60, true], "aps.06.01": [60, true], "aps.06.02": [60, true], "aps.06.03": [60, true], "aps.06.04": [60, true], "aps.06.05": [61, true], "aps.06.06": [61, true], "aps.06.07": [61, true], "aps.06.08": [61, true], "aps.06.09": [61, true], "aps.07.00": [60, true], "aps.07.01": [58, true], "aps.07.02": [57, true], "aps.08.00": [60, true], "aps.08.01": [59, true], "aps.08.02": [57, true], "aps.08.03": [56, true], "aps.08.04": [57, true], "aps.09.00": [60, true], "aps.09.01": [60, true], "aps.09.02": [57, true], "aps.09.03": [56, true], "aps.09.04": [52, true], "aps.09.05": [48, true], "aps.09.06": [46, true], "aps.10.00": [60, true], "aps.10.01": [57, true], "aps.10.02": [56, true], "aps.10.03": [56, true], "aps.10.04": [54, true], "aps.11.00": [57, true], "aps.11.01": [57, true], "aps.11.02": [55, true], "aps.11.03": [56, true], "aps.12.00": [67, true], "aps.12.01": [68, true], "aps.12.02": [68, true], "aps.12.03": [69, true], "aps.12.04": [69, true], "aps.12.05": [69, true], "aps.12.06": [69, true], "aps.12.07": [68, true], "aps.12.08": [64, true], "aps.12.09": [65, true], "aps.12.10": [66, true], "aps.12.11": [66, true], "aps.12.12": [67, true], "aps.12.13": [67, true], "aps.12.14": [67, true], "aps.12.15": [67, true], "aps.12.16": [68, true], "aps.12.17": [68, true], "aps.12.18": [68, true], "aps.13.00": [52, false], "aps.14.00": [65, true], "aps.14.01": [65, true], "aps.14.02": [65, true], "aps.14.03": [65, true], "aps.14.04": [65, true], "aps.14.05": [65, true], "aps.14.06": [65, true], "aps.14.07": [65, true], "aps.14.08": [65, true], "aps.14.09": [65, true], "aps.14.10": [65, true], "aps.14.11": [65, true], "aps.14.12": [65, true], "aps.14.13": [65, true], "aps.14.14": [65, true], "aps.14.15": [65, true], "aps.14.16": [65, true], "aps.14.17": [65, true], "aps.14.18": [65, true], "aps.14.19": [65, true], "aps.14.20": [65, true], "aps.14.21": [65, true], "aps.14.22": [65, true], "aps.14.23": [65, true], "aps.14.24": [65, true], "aps.14.25": [65, true], "aps.14.26": [65, true], "aps.14.27": [65, true], "aps.14.28": [65, true], "aps.14.29": [65, true], "aps.14.30": [65, true], "aps.14.31": [65, true], "aps.14.32": [65, true], "aps.14.33": [65, true], "aps.14.34": [65, true], "aps.14.35": [65, true], "aps.14.36": [65, true], "aps.14.37": [65, true], "aps.14.38": [65, true], "aps.14.39": [65, true], "aps.15.00": [51, true], "aps.15.01": [51, true], "aps.15.02": [52, true], "aps.15.03": [52, true], "aps.15.04": [52, true], "aps.15.05": [52, true], "aps.15.06": [52, true], "aps.15.07": [52, true], "aps.15.08": [52, true], "aps.15.09": [52, true], "aps.15.10": [52, true], "aps.15.11": [52, true], "aps.15.12": [52, true], "aps.15.13": [52, true], "aps.15.14": [52, true], "aps.15.15": [51, true], "aps.15.16": [51, true], "aps.15.17": [51, true], "aps.15.18": [51, true], "aps.15.19": [51, true], "aps.15.20": [50, true], "aps.15.21": [46, true], "aps.15.22": [50, true], "aps.15.23": [50, true], "aps.15.24": [49, true], "aps.15.25": [48, true], "aps.15.26": [50, true], "aps.15.27": [51, true], "aps.15.28": [50, true], "aps.15.29": [49, true], "aps.15.30": [38, true]}}, "CHA": {"total": 4401, "solved": 40, "n": 45, "over": 0, "per": {"fun1.1": [58, true], "fun1.2": [56, true], "fun1.3": [63, true], "fun1.4": [62, true], "fun1.5": [83, true], "fun2.1": [59, true], "fun2.2": [110, true], "fun2.3": [122, true], "fun2.4": [151, true], "fun2.5": [163, true], "fun3.1": [39, true], "fun3.2": [38, true], "fun3.3": [44, true], "fun3.4": [52, true], "fun3.5": [64, true], "fun4.1": [88, true], "fun4.2": [92, true], "fun4.3": [113, true], "fun4.4": [125, true], "fun4.5": [153, true], "fun5.1": [88, true], "fun5.2": [88, true], "fun5.3": [90, true], "fun5.4": [94, true], "fun5.5": [96, true], "fun6.1": [88, true], "fun6.2": [88, true], "fun6.3": [90, true], "fun6.4": [94, true], "fun6.5": [96, true], "fun7.1": [52, false], "fun7.2": [88, false], "fun7.3": [50, false], "fun7.4": [7, false], "fun7.5": [57, false], "fun8.1": [73, true], "fun8.2": [65, true], "fun8.3": [91, true], "fun8.4": [92, true], "fun8.5": [96, true], "fun9.1": [60, true], "fun9.2": [55, true], "fun9.3": [63, true], "fun9.4": [90, true], "fun9.5": [69, true]}}}] \ No newline at end of file diff --git a/tests/test_points_direction.py b/tests/test_points_direction.py new file mode 100644 index 0000000..bbdbb47 --- /dev/null +++ b/tests/test_points_direction.py @@ -0,0 +1,106 @@ +"""Gates P1-P5 for the two new places similarity is read (PREREG_points_and_direction_2026-09-21). + +mode A points="shape" — WHICH three points the model is built on, chosen by the shape + of the configuration (argmin |phi - xi|) instead of by recency +mode B direction="dissimilar" — WHICH end is "far", read as the end whose |f| is larger + (less similar to zero) instead of the geometrically distant one + +Inertness is a declared failure of the EXPERIMENT, not a pass: if a mode changes nothing, its +numbers are not evidence either way, so the counters are pinned here. +""" + +from __future__ import annotations + +import inspect +import math +import re + +import pytest + +from simroot import pure as P + +SMOOTH = [ + (lambda t: t ** 3 - 2.0 * t - 5.0, 2.0, 3.0), + (lambda t: math.exp(t) - 5.0, 0.0, 3.0), + (lambda t: t ** 2 - 2.0, 0.5, 2.0), + (lambda t: math.cos(t) - t, 0.0, 1.0), + (lambda t: t ** 3 - t + 0.2, -2.0, 2.0), +] + + +def test_P1_defaults_are_bit_identical_to_the_published_path(): + for f, a, b in SMOOTH: + for guard in ("credit", "project", "safe", "step"): + base = P.pure_root(f, a, b, 1e-12, 300, similarity="ratio", + scale="derived3", guard=guard) + same = P.pure_root(f, a, b, 1e-12, 300, similarity="ratio", scale="derived3", + guard=guard, points="recent", direction="distance") + assert base == same, (guard, base, same) + + +def test_P2_neither_rule_carries_a_constant(): + src = inspect.getsource(P._pick_triple) + inspect.getsource(P._shape_defect) + code = "\n".join(line.split("#", 1)[0] for line in src.splitlines()) + literals = set(re.findall(r"(?= 1, "mode A never changed the triple on any probe problem — inert" + + dchanged = 0 + for f, a, b in SMOOTH: + st = {} + _x, _n, ok = P.pure_root(f, a, b, 1e-12, 300, similarity="ratio", scale="derived3", + guard="credit", direction="dissimilar", stats=st) + assert ok and "dir_changed" in st + dchanged += st["dir_changed"] + assert dchanged >= 1, "mode B never changed the far end — inert" + + +def test_P4_degenerate_triples_are_dropped_not_divided_by(): + assert P._shape_defect(1.0, 1.0, 2.0, 5.0, 2.0, 7.0) is None # equal abscissae + assert P._shape_defect(1.0, 1.0, 2.0, 5.0, 3.0, 5.0) is None # equal values + d = P._shape_defect(1.0, 1.0, 0.0, 0.0, 2.0, 2.0) # exactly linear + assert d is not None and d == pytest.approx(0.0) + assert P._pick_triple(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0) is None + + +def test_P5_no_mode_adds_an_evaluation(): + for f, a, b in SMOOTH: + st = {} + _x, n, ok = P.pure_root(f, a, b, 1e-12, 300, similarity="ratio", scale="derived3", + guard="credit", points="shape", direction="dissimilar", + stats=st) + assert ok + assert st["triple_changed"] <= n - 2 and st["dir_changed"] <= n - 2, (st, n) + + +def test_modes_are_validated(): + with pytest.raises(ValueError): + P.pure_root(lambda t: t, -1.0, 1.0, 1e-10, 100, points="whatever") + with pytest.raises(ValueError): + P.pure_root(lambda t: t, -1.0, 1.0, 1e-10, 100, direction="whatever") + with pytest.raises(ValueError): # a triple needs the three-point scale + P.pure_root(lambda t: t, -1.0, 1.0, 1e-10, 100, scale="derived", points="shape") + + +def test_both_modes_still_solve(): + for f, a, b in SMOOTH: + for kw in ({"points": "shape"}, {"direction": "dissimilar"}, + {"points": "shape", "direction": "dissimilar"}): + x, _n, ok = P.pure_root(f, a, b, 1e-12, 300, similarity="ratio", + scale="derived3", guard="credit", **kw) + assert ok and abs(f(x)) < 1e-6, (kw, a, b, x)