Tonify Research · август 2026 · economist → engineer · реализация: sim2/tonify_graph_sim.py, seed=42
Задача: проверить GTM-гипотезу Tonify «посев трека в хабы (каналы) эффективнее случайного посева» на графе, воспроизводящем два свойства Telegram: степенной хвост контактов (хабы-каналы) и плотные пересекающиеся групповые чаты (широкие мосты Centola). Спека самодостаточна: engineer реализует её, не задавая вопросов. Правило матрицы {signed × independent} из HANDOFF к sim2 неприменимо: кассового слоя в модели нет, распространение от контракта не зависит — фиксируем явно, чтобы красная команда не искала пропажу.
Причина пересмотра: реализация v1.0 вернула штатный стоп §4.1 — p* не существует. Реализация инженера верифицирована и НЕ виновата: лемма 2.4 подтверждена наивной референс-реализацией гиперрёбер байт-в-байт на полном N=50k; T1/T2/T2b PASS (γ̂ = 2,913; медиана клик 12,0; покрытие 0,502); классика k=1 на месте (p_c = 0,10 при mean-field 0,025; охват до 100 % при p ≥ 0,95).
Обвинение. Равномерно независимая посадка клик v1.0 не создаёт широких мостов МЕЖДУ чатами: пересечение чата с каким-либо другим ≥ 2 общими узлами ≈ 1,2 % на чат. Complex contagion заперт в чате посева: медианный R_eff = 0,000 на ВСЕЙ сетке p, включая p = 1,0 (стохастики розжига нет — p_seed = 1); медианный охват 0,02–0,03 % N; у 54 % чатов-посевов G₁ = 0 — ни один внешний узел не имеет двух посеянных соседей (nucleation-барьер). Утверждение v1.0 §9.6 «независимая посадка консервативна» — неверно: это не консервативность, а полная блокада механики, которую sim2 обязан мерить.
Вердикт. Конструкция v1.0 фальсифицирована собственной валидацией — стоп сработал как задуман. Вторичный дефект: правило p* на медианном R_eff слепо при экстремальной бимодальности — при p = 1,0 макрокаскад зажигали 37,1 % чатов-посевов (255/688, верх IQR 87–100 % N при p ≥ 0,60), а медиана всё равно 0: медиана меряет вероятность розжига, не критичность распространения. Форс-тест инженера (p* := 0,7) дал медианный охват 0,03 % N — мишень T3(в) v1.0 провалилась бы и при формальном существовании p*.
Действие (v1.1).
Механика заражения (§3.1–3.3), лемма о редукции (§2.4), протокол эксперимента A, фальсификатор GTM (§6), палитра и рантайм-бюджет — БЕЗ изменений: дифф реализации — функция посадки, C, правило p*, агрегаты и мишень T2c.
Причина пересмотра: T3(б) FAIL при живой конструкции — всё остальное v1.1 сработало (T1/T2/T2b/T2c PASS: мосты у 100 % чатов, d̄(B_chat) = 4,62, слой связен — 1 компонента; complex ожил, p* = 0,15 существует; аналитика p_c^chat = 0,526 попала в измеренную).
Обвинение (самому economist’у). v1.1 перевела метрику T3 на mean (правильно), но порог (б) «G_BA complex < 5 % N» остался от медианной интуиции v1.0 — категориальная ошибка метрика/порог, зеркальная CRITIC §1 sim1. Факты инженера (p_C = 0,7, 40 прогонов): mean охват G_BA complex = 12,54 % (FAIL порога 5 %), медиана 0,024 % — старый порог прошла бы. Механизм: розжиг в 6/40 = 15 % прогонов через rich-club-ядро BA (степени центров розжига [11, 11, 17, 21, 32, 257] — не хабовый артефакт), зажёгшийся каскад доходит до 81,9–84,5 % N; mean = 0,15 × 83,6 % ≈ 12,5 %. Посылка §1.20 v1.1 «второй источник на G_BA почти не встречается при любом p» опиралась на МЕДИАНУ форс-теста v1.0 — в mean-выражении она неверна.
Вердикт. Контраст Centola жив и велик (G complex 93,7 % vs G_BA complex 12,54 % mean — 7,5×; P(розжиг) 1,00 vs 0,15; G_BA simple 98,6 % PASS), но T3(б) в mean-формулировке ловила не тот инвариант: тезис Centola — про НАДЁЖНОСТЬ распространения complex, а mean смешивает редкость розжига с величиной условного охвата (зажёгшийся каскад макроскопичен на обоих графах).
Действие (v1.2).
Конструкция, правило p*, T2c, протоколы A/B, фальсификатор GTM — без изменений; дифф реализации — одно место в валидации (T3) и справочные числа.
Причина пересмотра: внешний аудит красной команды по прогону v1.2. Вердикт аудита: «принять при выполнении требования 1»; отзываемых чисел НЕТ — вердикт фальсификатора («гипотеза хабов подтверждена на B ∈ [2; 500]») выдержал перепроверку на трёх осях (union-хабы, чистые BA-хабы, вариация p). v1.3 — не пересмотр конструкции, а достройка контроля интерпретации и требований к отчётности.
Обвинение. (1) Загрязнение union-хабов кликовыми рёбрами (§9.10 признавала качественно) количественно хуже признанного: у топ-500 по union-степени 81,6 % степени — кликовые рёбра; 384/500 узлов — не BA-хабы (deg_BA < 15); пересечение с топ-500 по deg_BA — 84/500; членства: медиана 8, max 42. «Хабы» v1.2 — в большинстве чат-хопперы, не «каналы». (2) На B ≤ 20 выигрыш хабов смешан с эффектом плотности посева вообще (cliques тоже бьют random: 712–1111); чистый хаб-эффект +14–19 % изолируется на B ≥ 50 (cliques сходятся к random: 222,8 vs 222,0). (3) p* = 0,15 на грани шага сетки: mean охват при p = 0,10 на независимых батчах сидов 3,86–4,40 % N против порога 5,00 (репо-факт 4,90) — граница батч-чувствительна. (4) Окно gif «25–40 кадров» §7 недостижимо при N_gif = 4 000 и p* = 0,15: max каскад 14 раундов на всех 40 сидах ⟹ max 20 кадров — дефект пережил две ревизии. (5) Прикидки §2.2 разошлись с фактом (max членств «~70» vs 42; «~565k рёбер, ⟨k⟩ ≈ 22,6» vs 586 182 / 23,45). (6) Процессное: пороги T3 v1.2 фиксировались ПОСЛЕ диагностических прогонов (пост-хок признан в CHANGELOG v1.2).
Вердикт. Вердикт фальсификатора устойчив и аудитом УСИЛЕН: контрольный прогон критика — посев топ-B по степени ЧИСТОГО G_BA (p = 0,15, 30 прогонов) — бьёт random на ВСЕХ B (B=5: reach-per-seed 4 213,6±206,9 vs 0,0; B=100: 254,8 vs 222,0; B=500: 59,2 vs 46,4), а на B ≥ 20 бьёт и top-union: union-определение хабов ЗАНИЖАЛО канальное преимущество, а не создавало его. От выбора p вердикт не зависит (проверено при p = 0,25/0,30). Подгонки порогов T3 не выявлено: PASS воспроизводится на независимых батчах сидов 43/44/45 — P_macro(G_BA complex) = 0,150/0,075/0,125, всюду под 0,25. Но контроль интерпретации и правило о порядке фиксации порогов обязаны жить в спеке.
Действие (v1.3). Трасса требование → правка:
Конструкция §2, правило p*, T2c, критерий §6, пороги T3 — без изменений; дифф реализации — одна стратегия посева, печать декомпозиции и метаданные фигур.
Каждый параметр — либо источник, либо флаг допущение с одной строкой обоснования. Немотивированных чисел нет.
| # | Параметр | Значение | Источник / флаг |
|---|---|---|---|
| 1 | N узлов | 50 000 | ТЗ (HANDOFF) |
| 2 | BA: параметр присоединения m | 3 | ТЗ; механизм — Barabási & Albert 1999 |
| 3 | Глобальный seed | 42 | ТЗ, конвенция sim1 |
| 4 | Размер клики: лог-нормаль | μ = ln 12 ≈ 2,4849; σ = 0,6; округление до целого; клиппинг [5, 40] | Границы [5, 40] и лог-нормальность — ТЗ. μ, σ — допущение: медиана 12 = типичный малый групповой чат; публичной статистики размеров приватных Telegram-групп нет; σ = 0,6 держит массу на границах клипа малой (~9,7 % в 5 и ~2,4 % в 40) |
| 5 | Число клик C | 3 460 | Калибровка на покрытие q = 0,50 (строка 6): наивная формула C = ln(1/(1−q))·N/(E[s]−n_par·o) = 3 398 занижает ~2 % (поправки наследования); C = 3 460 — эмпирическая интерполяция посадки seed=42 (покрытие 0,493 при C = 3 400; 0,506 при C = 3 500) |
| 6 | Доля узлов в ≥1 чате (покрытие) q | 0,50 | Допущение: групповые чаты — ядро Telegram-UX, но доля пользователей в ≥1 приватной группе не публикуется; 0,50 — консервативная середина. Проверка — T2b |
| 7 | Перекрытие чатов: n_par родителей, o общих узлов с каждым | n_par = 2; o = 2 | Допущение (обоснование реализмом и минимальностью): o = 2 — минимальная ширина широкого моста (Centola 2010: complex проводят перекрывающиеся кластеры); n_par = 2 — минимум, дающий мостовому слою среднюю степень ~4,7 > 2, т.е. ветвление > 1 достижимо при p < 1 и существование сверхкритики не висит на хвостах BA. Эмпирика перекрывающихся сообществ в реальных соцсетях — Palla, Derényi, Farkas & Vicsek, Nature 2005. Признание: посадка выбрана ТАК, ЧТОБЫ мосты существовали, — §9.6 |
| 8 | Порог принятия complex k | 2 разных соседа-источника | ТЗ; Centola & Macy 2007, Centola 2010 |
| 9 | Порог simple k | 1 | ТЗ (режим сравнения); контраст со слабыми связями — Granovetter 1973 |
| 10 | Share rate p | ось эксперимента; сетка {0,05; 0,10; …; 1,00}, шаг 0,05 (20 точек) | ТЗ («p — ось фазовой диаграммы»); границы — полный носитель вероятности |
| 11 | Рабочая точка p* (для A, gif) | min{p из сетки: mean охват(k=2, посев-чат §4.2) ≥ 5 % N} | Правило-конструкция: привязка к измеренной фазовой (эксперимент B). Mean = P(розжиг) × условный охват — единственный из агрегатов монотонен по p при бимодальности (урок v1.0, CHANGELOG). Порог 5 % N = 2 500 узлов — допущение: макрокаскад, на порядок больше любого посева (≤500) и первого кольца (~55) |
| 12 | Вероятность трансляции посева p_seed | 1 | Допущение (GTM-реализм): посев = оплаченное/гарантированное размещение; органика транслирует с p |
| 13 | Память касаний | бессрочная в рамках каскада, без затухания | Centola & Macy 2007: exposures перманентны внутри каскада; отсутствие забывания — ограничение §9.1 |
| 14 | Бюджеты посева B | {1, 2, 5, 10, 20, 50, 100, 200, 500} | Конструкция: лог-сетка от 1 узла до 1 % N; «равный бюджет» = равное число посеянных УЗЛОВ (ТЗ) |
| 15 | Прогонов на точку | A: 30; B: 40; C: 40 | Допущение: бюджет рантайма ≤ 10 мин (§8); разрыв, не видимый поверх SEM на 30–40 прогонах, не является GTM-аргументом |
| 16 | Лимит раундов T_max | 100 | Техника: защитный предел; выход по T_max логируется |
| 17 | Посев экспериментов B и C | один случайный чат размера 10–14 (факт: 970 кандидатов = 28 % C) | Centola 2010: посев соседства (локально плотный); окно 10–14 убирает дисперсию размера посева. Аналитика окна — с continuity-поправкой округления: s ∈ {10..14} ⟺ x ∈ [9,5; 14,5) ⟹ 27,5 % C = 953 (фикс v1.2: без поправки выходило 764 — CHANGELOG) |
| 18 | Посев C на графе без клик | случайный узел степени ≥ 11 + 11 его случайных соседей (итого 12) | Конструкция: локальный посев того же размера, что медианный чат — симметрия протокола |
| 19 | R_eff | пулированное отношение поколений (§3.4) по прогонам с G₁ ≥ 1; отдельно P_macro = P(охват ≥ 5 % N) | Конструкция: кейс-репродукция ранних поколений; условие G₁ ≥ 1 и P_macro — декомпозиция бимодальности (розжиг × распространение), урок v1.0 |
| 20 | Точка эксперимента C и T3: p_C | max(p*, 0,7) | Конструкция: глубоко в сверхкритике ОБЕИХ механик (аналитика: p_c^MF simple ≈ 0,03, p_c^chat complex ≈ 0,52 — запас ≥ 35 %); контраст C структурный, не параметрический, потолок его не маскирует. Уточнение v1.2: complex на G_BA при p = 0,7 МЕДИАННО мёртв (0,024 % N), но изредка зажигается через rich-club-ядро (≈ 15 % посевов — §9.12); именно это T3 ловит через P_macro |
| 21 | Хабы («каналы») | топ-B узлов по степени итогового графа (BA + клики) | ТЗ; степень союзного графа = суммарная досягаемость узла (личные + со-чатники); оговорка §9.10 |
| 22 | GIF: N_gif, C_gif | 4 000; 277 = round(3 460·4 000/50 000) | ТЗ (разрешено 3–5k); пропорция клик сохранена, подпись «иллюстративный масштаб» |
| 23 | Палитра | фон #0D0A1A; #6B2FFF / #00D4F5 / #FF4D8D / #FFD426 | ТЗ, sim1 |
G_BA = networkx.barabasi_albert_graph(n=50_000, m=3, seed=42).
Рёбер (N−m)·m ≈ 149 991, средняя степень ≈ 6. Интерпретация ребра BA — личная связь
(контакт, личка). Хвост степеней P(k) ~ k^−3 — мишень T1, меряется на чистом G_BA
ДО посадки клик.
Число клик C = 3 460 (калибровка — §1.5). Посадка последовательная, c = 0…C−1:
Интерпретация наследования: новые чаты отпочковываются от существующих — людей приводят знакомые; реальные сообщества перекрываются (Palla et al. 2005), и именно перекрытия кластеров проводят complex contagion (Centola 2010). Побочный реализм: вероятность быть унаследованным ∝ числу текущих членств → хвост «чат-хопперов» (rich-get-richer по членствам) — §9.9.
Свойства посадки (аналитика + эмпирика seed=42, проверено скриптом):
RNG посадки: default_rng(SeedSequence(42, spawn_key=(0,0,0))).
Хабы — топ-узлы по степени итогового графа G (BA + клики), тай-брейк — меньший id. Интерпретация: узлы максимальной суммарной досягаемости (Telegram-каналы и суперактивные участники чатов — не различаются, оговорка §9.10). Ненаправленность хаба — ограничение §9.3.
Семантика ТЗ: «внутри клики одно сообщение = касание всем участникам одновременно». Формально: чат c — гиперребро h_c ⊆ V; трансляция узла u ∈ h_c порождает касание ⟨источник u → узел v⟩ для каждого v ∈ h_c \ {u} за один раунд. Личный канал: трансляция u порождает касание ⟨u → v⟩ для каждого BA-соседа v.
Лемма о редукции (подтверждена в v1.0 наивной референс-реализацией байт-в-байт).
Если (1) касание идентифицируется ИСТОЧНИКОМ, а не сообщением, (2) каждый узел
транслирует не более одного раза за каскад (§3.3), (3) граф простой, — то множество
источников, коснувшихся v за историю каскада, равно множеству транслировавших соседей v
в союзном графе G, и счётчик различных источников v равен сумме по раундам числа
транслировавших соседей v. Следствие: динамика — один sparse-matvec на раунд
(touches += A @ sharers_t), без явного перебора гиперрёбер; двойное касание
«лично + через общий чат» от одного u схлопывается в один источник автоматически.
Гиперрёберная семантика сохранена полностью.
Касание — событие ⟨источник u → узел v⟩ по любому из двух каналов (§2.4): личному (BA-ребро) или чатовому (общее гиперребро). Касания от одного источника по разным каналам/чатам считаются ОДНИМ источником (дедуп по u — лемма 2.4). Принятие: S-узел v принимает в конце раунда t, если touches[v] ≥ k. Complex: k = 2 (два разных соседа — Centola). Simple: k = 1. Оба канала активируются одной трансляцией: узел, решивший шарить, постит во все свои чаты И шлёт всем личным (BA) соседям — одна монетка p на узел, не на канал (упрощение — §9.5).
t=0: посев Σ₀ принимает (A), will_share=да для всех сеяных (p_seed=1)
раунд t≥1:
sharers_t = {узлы, принявшие в t−1 с will_share=да}
touches += A_csr @ indicator(sharers_t) # лемма 2.4
new = {v ∈ S: touches[v] ≥ k}
new → A; will_share[new] = (U(0,1) < p) # монетка один раз, навсегда
терминация: sharers_t пусто (некому слать) ИЛИ t = T_max=100 (логируется)
sharers_t пусто ⟹ новых касаний не будет ⟹ каскад мёртв — критерий точный, не эвристика. Охват прогона = |A| в терминации (включая посев).
G₀ = посев; G_t = узлы, принявшие в раунде t. Эффективный branching factor прогона:
| R_eff = ( | G₂ | + | G₃ | + | G₄ | ) / ( | G₁ | + | G₂ | + | G₃ | ), при нулевом знаменателе R_eff := 0. |
Пулированное отношение соседних ранних поколений (до насыщения; ratio-метод обходит атрибуцию complex-принятия двум родителям). Агрегация по прогонам (изменение v1.1): R_eff агрегируется средним ПО ПРОГОНАМ С G₁ ≥ 1 (условный на розжиг первого поколения); отдельно печатается P_macro(p) = доля прогонов с охватом ≥ 5 % N — вероятность макрокаскада (порог согласован с §1.11). Разложение mean охвата = P_macro × условный охват — рабочий язык бимодальности (урок v1.0). Суб-/крит-/сверхкритика: R_eff < 1 / ≈ 1 / > 1; аналитическая референс-линия R_eff = 1.
Замечание к розжигу (следствие §2.2): при посеве-чате общие узлы посева с соседними чатами сеяны и шарят гарантированно (p_seed = 1) ⟹ мостовые соседи посева зажигаются детерминированно, G₁ ≈ 55 узлов > 0 всегда. Nucleation-барьер v1.0 снят конструкцией; фазовый переход управляется РАСПРОСТРАНЕНИЕМ (мост проводит с вероятностью p² — оба общих узла шарят), а не розжигом.
Режим: complex k = 2, p = p*. «Равный бюджет» = равное число посеянных узлов B ∈ {1, 2, 5, 10, 20, 50, 100, 200, 500}. Стратегии:
30 прогонов на точку; RNG: spawn_key=(1, strategy_id·100+B_index, run); strategy_id приколочен: 0 = random, 1 = top-hubs, 2 = random-cliques, 3 = top-BA (нумерация 0–2 совпадает с v1.2 — воспроизводимость опубликованных чисел не трогается). Метрики: охват = |A| в терминации; reach-per-seed = (охват − B)/B. Агрегат — СРЕДНЕЕ по прогонам ± 1 SEM (критерий фальсификатора §6 определён на средних; mean честен при бимодальности — §3.4).
Декомпозиция хабов (v1.3) — печатается в stdout и в README рядом с таблицей A. Обозначим H₅₀₀ — топ-500 узлов по union-степени deg_G (тай-брейк — меньший id, §2.3); H₅₀₀^BA — топ-500 по степени чистого G_BA deg_BA (тот же тай-брейк). Три числа, считаемые В КОДЕ:
| Пересечение | H₅₀₀ ∩ H₅₀₀^BA | (из 500). |
Правило p* (изменение v1.1): эксперимент B гонится ПЕРВЫМ; p* = min{p из сетки: mean охват(k = 2, посев-чат §4.2) ≥ 5 % N}. По конструкции v1.1 p* существует (при p = 1 мосты проводят с вероятностью 1, мостовой слой связен ⟹ охват ≥ покрытие ≈ 50 % N); страховочная ветка сохраняется: если p* не существует — печатается «p* не существует; эксперимент A и фальсификатор GTM не интерпретируемы; конструкция пересматривается», T3 проваливается штатно. Никаких тихих fallback-ов.
Оба режима: k = 1 и k = 2. Сетка p — 20 точек (§1.10), 40 прогонов на точку и режим. Посев прогона: один случайный чат размера 10–14 (весь состав; 970 кандидатов — факт §1.17; локально плотный посев — Centola 2010). RNG: spawn_key=(2, k·100+p_index, run). Измеряется: финальный охват (доля N, с посевом), R_eff и P_macro (§3.4).
Агрегаты (изменение v1.1): охват — МЕДИАНА + IQR и mean (медиана показывает типичный исход, mean — GTM-ожидание; расхождение кривых = визуальная подпись бимодальности); R_eff — среднее по прогонам с G₁ ≥ 1; P_macro — доля прогонов.
Выходы: p_c(k) = min{p: mean охват ≥ 5 % N} для k = 1, 2 (печатаются; p_c(2) = p*). Аналитические референс-вертикали: (а) simple — mean-field порог бондовой перколяции p_c^MF = ⟨k⟩/(⟨k²⟩−⟨k⟩) по фактическим степеням G (Newman 2002), подпись «аналитика (mean-field)»; (б) complex (новое в v1.1) — mean-field мостового слоя: p_c^chat = 1/√(d̄_bridge − 1), где d̄_bridge — фактическая средняя степень B_chat (ветвление чатового каскада b = (d̄−1)·p², мост проводит при p² — оба общих узла шарят); при d̄ ≈ 4,7 оценка ≈ 0,52. Подпись: «аналитика: mean-field мостового слоя, оценка СВЕРХУ (хвост степеней B_chat и личные BA-рёбра понижают порог)».
Один чёткий протокол: контраст 2×2 «граф × механика» при одинаковом p и локальном посеве одинакового размера.
Читается так: simple (k=1) проводится длинными слабыми связями BA-хабов и живёт на обоих графах — «теория рукопожатий» Granovetter работает для информации. Complex (k=2) требует широких мостов: на G_BA розжиг ненадёжен — второй источник лишь изредка (≈ 15 % посевов) собирается в плотном rich-club-ядре BA (§9.12), хотя зажёгшийся каскад макроскопичен; перекрытия чатов G (§2.2) дают второй голос достоверно. Печатается матрица 2×2: P_macro и mean-охват. Численные пороги — мишень T3 (§5).
Engineer печатает блок VALIDATION (мишень → получено → допуск → PASS/FAIL) в stdout и в sim2/README.md ДО любых выводов. Любой FAIL ⟹ выводы не публикуются, процесс завершается с ненулевым кодом и текстом «МИШЕНЬ ПРОВАЛЕНА». Все мишени — assert-совместимые неравенства.
| Мишень | Что меряем | Допуск | Основание |
|---|---|---|---|
| T1 | Показатель хвоста степеней чистого G_BA (до клик): дискретный MLE Ньюмана γ̂ = 1 + n·[Σ_{k_i≥k_min} ln(k_i/(k_min−0,5))]^{−1}, k_min = 15 | γ̂ ∈ [2,6; 3,4] | BA 1999: γ = 3; конечный N и k_min-обрезка дают ±0,4 (Newman 2005). v1.0-факт: 2,913 PASS |
| T2 | Фактически посаженные размеры клик (C = 3 460 значений) | медиана ∈ [11; 13]; среднее ∈ [13,3; 15,0]; P(s=5) ≤ 0,12; P(s=40) ≤ 0,04 | Аналитика клипнутой лог-нормали §2.2; посадка v1.1 распределение размеров не меняет |
| T2b | Доля узлов, состоящих в ≥ 1 чате | ∈ [0,45; 0,55] | Калибровка C на q = 0,50 (§1.5–1.6); эмпирика посадки: 0,493–0,506 на C = 3 400–3 500 |
| T2c (новая) | Мостовой слой B_chat (§2.2): (а) доля чатов c ≥ 1, имеющих ≥ 1 широкий мост (пересечение ≥ 2 узла с другим чатом); (б) средняя степень d̄(B_chat) | (а) ≥ 0,99; (б) ∈ [4,0; 5,5] | По построению (а) = 1,0 строго (o = 2 без повторов внутри родителя); (б): конструкционный минимум 2·n_par = 4 + случайные пересечения; эмпирика seed=42: d̄ ≈ 4,72. Связность B_chat — по построению, печатается справочно |
| T3 | Канонический контраст Centola при p_C = max(p*, 0,7), 40 прогонов на ячейку; единая метрика — P_macro = P(охват ≥ 5 % N) (§3.4), mean-матрица 2×2 печатается справочно: (а) G_BA simple: P_macro ≥ 0,75; (б) G_BA complex: P_macro ≤ 0,25; (в) G complex: P_macro ≥ 0,75 | все три неравенства | Тезис Centola 2010 — про НАДЁЖНОСТЬ распространения complex на кластеризованной против random-топологии, поэтому мишень — на вероятности макрокаскада, не на величине условного охвата (зажёгшийся complex-каскад макроскопичен на обоих графах — §9.12). Пороги — симметричная квартильная пара: «достоверен» = чаще 3 из 4 посевов, «ненадёжен» = реже 1 из 4; обоснование внешнее — семантика пары плюс статразделимость (SE доли при 40 прогонах ≤ 0,08 ⟹ пороги разнесены на > 6 SE, контраст не спутать с шумом), не значения ре-рана. Урок v1.2: mean-порог «< 5 %» был категориальной ошибкой метрика/порог — CHANGELOG |
T3 автоматически проваливается, если p* не существует (§4.1) — штатный стоп конструкции. Провал T3(в) при выполненных (а)–(б) читается отдельно: контраст Centola на месте, но мостовой слой слишком редок для макрокаскада — печатается именно это.
Дословно из ТЗ: «если при complex contagion посев в хабы НЕ бьёт случайный при равном бюджете — гипотеза хабов Tonify неверна, так и написать».
Численный критерий (по эксперименту A, complex k = 2, p = p*, средние по 30 прогонам):
Оговорка контроля (v1.3): top-BA в критерий НЕ входит. Критерий определён на top-hubs (union-степень, §2.3) vs random и после трёх ревизий не меняется; top-BA (§4.1) — контрольная стратегия интерпретации «каналы vs чат-хопперы», её числа печатаются рядом с вердиктом без участия в нём.
Оговорка вырожденности (v1.2): B = 1 исключается из критерия. При k = 2 двух РАЗНЫХ источников от одного сеяного узла не существует структурно — все стратегии тождественно дают нулевую органику, точка не различает стратегии. Она остаётся на fig8 (и сама по себе GTM-факт: complex-трек не сеется одним постом), но сравнение стратегий и вердикт фальсификатора определены на B ≥ 2.
Критерий на средних, без статкритериев — намеренно: разрыв, который не виден поверх SEM на 30 прогонах, не является GTM-аргументом.
Общее: фон #0D0A1A, сетка/оси приглушённые, каждая кривая подписана «симуляция» или «аналитика» (референс-линии — #FFD426, пунктир) — конвенция sim1. Файлы в /figures (нумерация продолжает sim1: fig1–7 заняты).
fig8_reach_per_seed.png — эксперимент A. Оси: X — бюджет посева B (лог-шкала, 1…500); Y — reach-per-seed = (охват−B)/B. Кривые (симуляция, среднее ± лента 1 SEM, 30 прогонов): top-hubs #6B2FFF, random #00D4F5, random-cliques #FF4D8D, top-BA #00E08F (контроль, §4.1; выбор v1.3: зелёный — единственная свободная от занятых серий и референсов ось палитры, отличим от всех на фоне #0D0A1A). Референс: горизонталь y = 0 «нет органики» (#FFD426, пунктир, «аналитика: посев без размножения»). В подписи: режим complex k=2, значение p*.
fig9_phase_diagram.png — эксперимент B. Две панели, общая ось X = p (0,05…1,00). Верх: финальный охват (% N) — медиана + IQR-лента И mean тонкой линией того же цвета (расхождение mean/медианы = визуальная подпись бимодальности); complex k=2 #6B2FFF, simple k=1 #00D4F5 (симуляция). Референс-вертикали #FFD426 пунктир: p_c^MF simple («аналитика: mean-field ⟨k⟩/(⟨k²⟩−⟨k⟩)») и p_c^chat complex («аналитика: mean-field мостового слоя 1/√(d̄−1), оценка сверху»); измеренные p_c(1), p_c(2)=p* — засечки «симуляция». Низ: условный R_eff vs p (левая ось, те же цвета; горизонталь R_eff = 1 #FFD426 «аналитика: порог критичности»; заливка зон суб-/сверхкритики complex) и P_macro vs p (маркеры-точки без линии на общей левой оси — dual-axis запрещён; те же цвета с прозрачностью; подпись «P_macro = P(охват ≥ 5 % N)»). Подпись панели: «посев: один случайный чат (10–14 узлов); 40 прогонов/точку».
fig10_cascade.gif — один complex-каскад (k=2, p = p*), N_gif = 4 000, C_gif = 277, та же конструкция графа (§2, тот же μ/σ/клиппинг, та же посадка с перекрытием, seed=42), посев — случайный чат 10–14. Кадр = раунд (плюс 5 финальных статичных кадров); число кадров = фактическая длина каскада + 5 финальных, ориентир 15–40 (фикс v1.3: старое окно «25–40» недостижимо при N_gif = 4 000 и p* = 0,15 — max каскад 14 раундов на всех 40 сидах, CHANGELOG); ~4 fps, spring-layout (networkx, seed=42). Цвета узлов: непринявшие с 0 касаний — тусклый производный от фона (#2A2342); на пороге (1 касание из 2) — #00D4F5; принявшие — #FF4D8D; транслирующие в текущем раунде — вспышка #FFD426; посев — #6B2FFF. Размер узла ~ степень. Обязательная подпись в кадре: «иллюстративный масштаб N = 4 000; конструкция графа идентична основной (N = 50 000)».
default_rng(SeedSequence(42, spawn_key=(exp, point, run))); exp: 0 = посадка клик,
1 = A, 2 = B, 3 = C, 4 = gif. Результат не зависит от порядка исполнения точек
и прогонов. networkx-генерация и layout — seed=42.figures/fig8_reach_per_seed.png, figures/fig9_phase_diagram.png,
figures/fig10_cascade.gif; sim2/README.md — параметры → источники (таблица §1),
блок VALIDATION (§5) ПЕРЕД результатами, числа A/B/C (таблица A — с контрольной
строкой top-BA), вердикт фальсификатора (§6), честные ограничения (§9),
CHANGELOG-факт v1.0 → v1.1 одной строкой со ссылкой на SPEC. Обязательные блоки v1.3
в stdout И README:
(а) «декомпозиция хабов» — три числа по определениям §4.1;
(б) строка механики малых B (числа — из собственного прогона A): «на B ≤ 20
выигрыш — плотность посева вообще, cliques тоже бьют random; чистый хаб-эффект
(ориентир аудита +14–19 %) изолируется на B ≥ 50»;
(в) оговорка p*: «0,15 с точностью до шага сетки; граница батч-чувствительна
(mean охват при p = 0,10 на независимых батчах 3,86–4,90 % N против порога 5,00);
вердикт фальсификатора §6 от неё не зависит (проверено при p = 0,25/0,30)».
Запуск: python3 sim2/tonify_graph_sim.py; интеграция в run_all.py. MIT.Модель сознательно НЕ моделирует:
Ни один вывод sim2 не заявляется сильнее своего фальсификатора (§6) и валидационных мишеней (§5).