Mutations
4.2 Операторы мутации¶
| Оператор | Тип | Описание | Математика |
|---|---|---|---|
split |
Структурная | Вставка скрытой вершины | Ребро \(u \to w\) disable; создаются \(u \to n \to w\); \(\mathbf{s}(n) = \lfloor(\mathbf{s}(u)+\mathbf{s}(w))/2\rfloor\) |
without_split |
Структурная | Добавление параллельного ребра | Новое \((u,w)\) при сохранении DAG + constraints |
mutate_weights |
Весовая | Гауссов шум на \(\sigma\) | \(\sigma \leftarrow \text{clip}(\sigma + \varepsilon, [\sigma_\min, \sigma_\max])\), \(\varepsilon \sim \mathcal{N}(0, \tau^2)\), \(\tau = 0.5\); rate=0.8; с prob 0.1 — полный resample |
aggressive_mutate_weights |
Весовая | Агрессивная мутация \(\sigma\) | rate=1.0, scale=1.5 |
remove_edge |
Структурная | Удаление/disable одного ребра | Связность input→output; кандидат из list_removable_edges |
remove_edges |
Структурная | Удаление до REMOVE_EDGES_COUNT=3 non-bridge рёбер |
Пересчёт removable после каждого удаления; кандидаты — не-мосты |
remove_node |
Структурная | Удаление скрытого узла | Удаляются все инцидентные рёбра; rebuild |
dissolve_node |
Структурная | Контракция скрытого узла | dissolve_hidden_node: узел стягивается, предшественники перекоммутируются на потомков (связность сохраняется); кандидаты из list_dissolvable_hidden_nodes |
crossover |
Рекомбинация | Скрещивание двух родителей | Union включённых рёбер (см. §4.3) |
mutate_activation |
Структурная (opt-in) | Смена σ ровно у одной не-входной вершины | Кандидаты (node_id, new_act) из пула; веса / рёбра / каналы не трогать. Нет в DEFAULT_MUTATION_TYPES — только при evolve_node_activations=True |
Выбор оператора — из легального множества (кандидаты), не слепой retry.
Clamp весов: \(\sigma \in [\text{WEIGHT\_CLAMP\_MIN}, \text{WEIGHT\_CLAMP\_MAX}] = [-8, 8]\).
Полная мутация \(\sigma\):
Для каждого elite-родителя порождаются потомки всеми типами мутаций из MUTATION_TYPES, плюс агрессивный клон (without_split × 5).
Script 06 vs 07
Скрипт 06 (OVA) на старте убирает remove_edge / remove_edges из набора,
скрипт 07 их сохраняет (config.py, комментарий у MUTATION_TYPES).

4.2.1 Батч-предложение и параллельные мутации¶
Для крупных популяций перечисление кандидатов и применение операторов выносится из горячего цикла:
propose_batch(mutations.py) — один раз перечислить легальные множества для всех родителей, затем последовательно применить операторы (без повторного скана кандидатов на каждого потомка).mutation_mp.propose_parents_mp(cnn_neat/mutation_mp.py) — ProcessPool по родителям (обход GIL). В production используется topology-only payload (~КиБ на потомка): воркеры мутируют «безвесовых» родителей, аevolver.pyзатем переприкрепляет conv-веса родителя к вернувшимся детям. Число процессов —runtime_cpu.resolve_cpu_workers(mutation_propose_parallel)(0= все CPU). ПриBrokenProcessPool— откат на последовательный путь.
Управление: ExperimentConfig.mutation_propose_parallel (0 = авто),
mutation_propose_max_children. Cone-размножение (breeding_cone_mp) использует
тот же пул и сериализацию генома (genome_to_payload / genome_from_payload).