Skip to content

fix(zeta): вычисляемая эталонная колонка GUE; исправлены wignerCDF и normalCDFApprox - #724

Closed
gHashTag wants to merge 4 commits into
mainfrom
fix/gue-reference-column-2026-08-13
Closed

gHashTag wants to merge 4 commits into
mainfrom
fix/gue-reference-column-2026-08-13

Conversation

@gHashTag

Copy link
Copy Markdown
Owner

Три дефекта одной формы — эталонное значение, которое никто не может пересчитать, и код с верным именем, считающий не ту функцию.

Код

  1. src/sacred/zeta_spacing.zig — wignerCDF возвращала 1 − e^{−x}(1+x), x = 4s²/π. Производная этого выражения — (32/π²)·s³·e^{−4s²/π}, то есть s³-плотность, а не surmise Вигнера для GUE. Замена на точную замкнутую форму F(s) = erf(2s/√π) − (4s/π)e^{−4s²/π} (коэффициент при erf выходит ровно 1, второй член ровно 4s/π — квадратура не нужна). Добавлены два теста: производная воспроизводит pdf; GUE, а не GOE — проверка в s = 0.3, потому что при s ≈ 1 кривые пересекаются (0.5331 против 0.5441) и guard в этой точке пропустил бы подмену функции.

  2. ksPValue снят. Surmise — приближение к точному закону зазоров GUE (детерминант Фредгольма / Пенлеве V), его систематическая ошибка фиксирована, а D_crit ≈ 1.36/√n падает: при n = 10⁵ отвержение гарантировано устройством теста, а не свойством данных. Теперь возвращается D против D_crit(95%) как размер эффекта. Обновлены все вызовы в zeta_spacing.zig, zeta_cf.zig, zeta_commands.zig.

  3. src/tools/uart_echo_test.zig — normalCDFApprox потеряла множитель exp(−a²) из A&S 7.1.26 и перепутала вложенность полинома. F(0) = 0.3362 вместо 0.5, максимальная ошибка 0.164, область значений зажата в [0.0858, 0.9142]. Критическое значение KS здесь 1.36/√n, то есть ошибка эталона одна превышает его при n ≳ 250: тесты Normal и Log-Normal в отчётах о джиттере UART печатали «does not fit» при любой реалистичной выборке, независимо от данных. Исправлено, добавлен тест.

Документы

data/zeta/zeta_gue_analysis_results.md и zeta_bin_analysis_update.md печатали эталон 0.91 / 2.15 / 2.75 (median / p95 / p99) без вывода. Ни одно из трёх чисел не воспроизводится: surmise GUE даёт 0.9639 / 1.7518 / 2.1107, surmise GOE — 0.9394 / 1.9530 / 2.4215, s³-баг выше — 1.1481 / 1.9302 / 2.2834. Верной была только строка std (0.42–0.43 против точного √(3π/8 − 1) = 0.4220).

Пересчёт по 100 000 нулей Одлыжко из этого же репозитория, развёртка s = Δγ·ln(γ/2π)/2π:

метрика наблюдение GUE (вычислено) отклонение
mean 1.0000 1.0 −0.00%
p50 0.9655 0.9639 +0.17%
p95 1.7189 1.7518 −1.88%
p99 2.0680 2.1107 −2.02%
std 0.4009 0.4220 −5.00%

Расхождение p95 — 1.9%, а не 19.8%. Отозваны: вывод «Montgomery–Odlyzko — лишь приближение, хвосты существенно легче», ссылка «Odlyzko (1989) ✅ Confirmed» и «Forrester–Mays (2015) ✅ Confirmed» — настоящие ссылки были приклеены к артефакту неверной колонки. По равным корзинам p95 = 1.7186 ± 0.0045, тренда по высоте нет, поэтому таблица χ²/dof помечена UNVERIFIED. Остаётся один настоящий дефицит: std −5.0%.

Дефицит константы Хинчина (2.6201 ± 0.0293 против 2.685) помечен OPEN, а не находкой: контроль Монте-Карло показывает, что оценка «среднее по-разложенческих геометрических средних» смещена вверх (2.755 при m = 20), а пулированная — вниз (2.668 ± 0.029, то есть 1.6σ от наблюдения). Документ не фиксирует ни оценку, ни число неполных частных, так что претензия не регенерируема в любую сторону.

Эталоны теперь вычисляемые

  • scripts/gue_surmise_reference.py — 7 self-test'ов, печатает верный эталон рядом с двумя неверными
  • scripts/recompute_zeta_percentiles.py — 3 self-test'а, включая пуассоновский контроль, который пайплайн обязан отвергнуть
  • scripts/khinchin_finite_sample.py — 2 self-test'а (восстанавливает K на генерических числах, возвращает 1 на золотом сечении)

Ограничение

Не скомпилировано: в окружении правки не было Zig-тулчейна. Изменения в .zig проверены глазами, вся численность продублирована в Python. Перед мержем нужен zig build test.

Trinity Audit Loop added 4 commits August 12, 2026 18:44
…lCDFApprox

Three defects of the same shape: a reference value that no one could
regenerate, and code behind a correct name computing the wrong function.

1. src/sacred/zeta_spacing.zig: wignerCDF returned 1 - e^{-x}(1+x),
   x = 4s^2/pi. Its derivative is (32/pi^2) s^3 e^{-4s^2/pi} -- an s^3
   density, not the GUE surmise. Replaced with the exact closed form
   F(s) = erf(2s/sqrt(pi)) - (4s/pi) e^{-4s^2/pi}, plus two tests
   (derivative reproduces the pdf; GUE not GOE, checked at s = 0.3
   because the two curves cross near s = 1).

2. ksPValue (p ~ 2 e^{-2nD^2}) removed. The surmise approximates the exact
   GUE gap law, so its systematic error is fixed while D_crit ~ 1.36/sqrt(n)
   shrinks: at n = 1e5 rejection is guaranteed by construction. Now reports
   D against D_crit(95%) as an effect size. Callers updated in zeta_cf.zig
   and zeta_commands.zig.

3. src/tools/uart_echo_test.zig: normalCDFApprox dropped the exp(-a^2)
   factor of A&S 7.1.26 and mis-nested the polynomial. F(0) = 0.3362 instead
   of 0.5, |error| <= 0.164, range clamped to [0.086, 0.914]. Since the KS
   critical value is 1.36/sqrt(n), the reference error alone exceeded it for
   n > ~250 -- the Normal and Log-Normal latency fits reported 'does not fit'
   for every realistic sample, independently of the data. Fixed and tested.

Documents: data/zeta/zeta_gue_analysis_results.md and
zeta_bin_analysis_update.md carried a GUE reference column of 0.91 / 2.15 /
2.75 for median / p95 / p99 with no derivation. None of the three is
reproducible from the Wigner surmise (0.9639 / 1.7518 / 2.1107), the GOE
surmise, or the s^3 variant above. Recomputed from the 100K Odlyzko zeros in
this repo: p95 deviation is -1.9%, not -19.8%; the 'persistent light tails'
conclusion and the Odlyzko-1989 / Forrester-Mays-2015 confirmations attached
to it are withdrawn. Surviving deviation: std 0.4009 vs 0.4220 (-5.0%).

Reference columns are now computable, not cited:
  scripts/gue_surmise_reference.py       (7 self-tests)
  scripts/recompute_zeta_percentiles.py  (3 self-tests, incl. a Poisson control)

Not compiled: no Zig toolchain in this environment. Zig changes are reviewed
by hand and their numerics verified in Python; run 'zig build test' before merge.
zeta_bin_analysis_update.md read K = 2.6201 +/- 0.0293 vs 2.685 as possible
arithmetic structure in zeta spacings. Monte-Carlo control over uniform random
reals (Khinchin-generic almost surely), same 500 expansions per bin:

  mean of per-expansion geometric means: biased ABOVE K (2.755 at m=20)
  pooled geometric mean over all terms:  biased BELOW K (2.668 at m=20)

The observed value is 1.6 sigma from one control and 4 sigma from the other.
The document records neither the estimator nor the number of partial quotients
per expansion, so the claim is not regenerable either way. Marked OPEN.

scripts/khinchin_finite_sample.py (2 self-tests: recovers K on generic reals,
returns 1 for the golden ratio).
…cts it

A `test` declaration nested inside a struct is not collected by
`zig test` unless that struct is referenced, so the previous in-struct
placement compiled to zero tests: "All 0 tests passed". Verified with
zig 0.15.1 — 1/1 test now runs and passes.
… finite height OPEN

- scripts/gue_exact_gap.py: E2(s) = det(I - K_s) by Nystrom on Gauss-Legendre
  nodes (|dE2| = 4e-16 between n=60 and n=140); the Wigner surmise itself is
  off by 0.3-0.5%, so it cannot serve as the reference for 2% effects.
- scripts/unfolding_test.py: exact Riemann-von Mangoldt unfolding vs the
  leading-order one agree to 1e-5 -- the deficit is not an unfolding artifact.
- scripts/height_extrapolation.py: 1/L extrapolation brings std, p90 and p99
  within 1.5% of exact GUE but leaves p95 at -2.3%; lever arm is too short,
  status OPEN, needs zeros near 10^12.
- scripts/test_reachability.py: only 5492 of 39814 declared tests (<=13.8%)
  are reachable from build.zig roots through the import graph.
@gHashTag

Copy link
Copy Markdown
Owner Author

Второй тик: ограничение снято, эталон заменён на точный закон

Zig собран в окружении правки (0.15.1 и 0.16.0), тесты прогнаны:
zeta_spacing.zig — 2/2 OK, zeta_cf.zig и zeta_commands.zig компилируются и проходят refAllDecls, тест normalCDFApprox — 1/1 OK. Полная проверка uart_echo_test.zig на Linux падает на предсуществующем termio.cflag.CRTS_IFLOW (флаг BSD/macOS, в std.os.linux его нет), то есть файл целиком собирается только на macOS. zig build test целиком не гонялся: зависимости тянут emsdk и raylib.

Мой собственный дефект, поймал self-check: тест normalCDFApprox в первой ревизии лежал внутри struct, а такое объявление zig test не собирает, если struct не отреферен — прогон печатал All 0 tests passed. Перенесён на уровень файла. По всему корпусу вложенных тестов больше нет: 0 из 39 885.

Эталон теперь точный закон, а не surmise. scripts/gue_exact_gap.py считает E₂(s) = det(I − K_s) с синус-ядром методом Нюстрёма (сходимость спектральная, |ΔE₂| = 4e−16 между n = 60 и n = 140): std 0.424258, p50 0.962807, p90 1.570136, p95 1.757099, p99 2.120406. Сам surmise отклоняется от точного закона на 0.3–0.5% — то есть для разговора о 2% он не годится как эталон.

Развёртка как причина отвергнута. scripts/unfolding_test.py сравнивает развёртку по точной считающей функции Римана–фон Мангольдта, s = (θ(γ_{i+1}) − θ(γ_i))/π, с ведущим членом ln(γ/2π)/2π: совпадение до 1e−5. Против точного эталона дефицит даже чуть больше: std −5.50%, p90 −2.11%, p95 −2.17%, p99 −2.47%, p50 +0.29%.

Конечная высота — OPEN. scripts/height_extrapolation.py: при γ ~ 7.5·10⁴ имеем 1/L ≈ 0.107, поправка порядка 1/L ожидаема по величине. Экстраполяция по корзинам к 1/L → 0 даёт std +1.09%, p90 +0.09%, p99 +1.52% — но p95 −2.29%, потому что тренда по высоте у p95 нет вообще. Рычаг короткий (1/L = 0.153..0.107), поэтому статус OPEN, а не «объяснено». Закрывается нулями около 10¹² / 10²¹, которых в репозитории нет.

Побочная находка, отдельная от этого PR. Раз «тест, который не запускается» — реальный класс, я его измерил: scripts/test_reachability.py обходит граф @import от всех 155 root_source_file из build.zig (включая 35 модулей, разрешённых по именам) — достижимо 5 492 объявления test из 39 814, то есть ≤ 13.8%; файлов с недостижимыми тестами 1 547 из 2 821. Один сгенерированный файл src/tri27/emu/test_t27_programs.zig даёт 21 771 объявление и недостижим; без него доля 30.4%. Плюс 12 из 25 файлов с наибольшим числом тестов не компилируются автономно ни на 0.15.1, ни на 0.16.0, причём падают внутри тел тестов (например src/brain/federation.zig:2166 — expectEqual(@as(u8, i), ...) при i: usize). Оговорка: граф строится регулярными выражениями, а не компилятором, и я взял все корни, включая исполняемые цели, поэтому 13.8% — оценка сверху для того, что видит именно zig build test.

@gHashTag

Copy link
Copy Markdown
Owner Author

Закрываю без мержа: подмножество #738, который смержен. Ретракция статистики (0.2%→64.2%, 2.9%→99.8%, снятие «~10σ», 75→70 фитов, Šidák 5.06σ) вошла в main в более полном виде.

@gHashTag gHashTag closed this Aug 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant