Это нейроэволюционный симулятор муравьиной колонии. Каждый муравей управляется нейросетью и обучается не градиентным спуском, а естественным отбором между поколениями.
Целевая метрика (Fitness) — сколько единиц еды муравей смог доставить в гнездо за поколение. Чем выше Fitness, тем больше вклад в следующее поколение.
Мир дискретный: сетка W×H (по умолчанию 200×140). Визуально каждая клетка рисуется с масштабом SCALE (по умолчанию 5), поэтому рабочий canvas 1000×700.
В каждой клетке хранятся: целочисленное количество порций еды, наличие стены, концентрации трёх каналов феромона. Стены блокируют проход и подавляют феромон в клетке; еда под стеной не хранится (при постановке стены удаляется, при рисовании еды клетки-стены пропускаются).
Гнездо фиксировано в центре карты. Доставка еды засчитывается, когда муравей с едой попадает в радиус гнезда.
Базовая еда при обычном запуске страницы генерируется заново: используются 6 фиксированных центров кластеров, но распределение порций внутри них случайное (поэтому после reload карта еды немного другая). Кнопка «Сброс» новую карту не генерирует: она переинициализирует популяцию, но оставляет текущую базовую карту еды/стен и просто восстанавливает еду до baseline.
У каждого муравья есть позиция (x,y), угол, флаг hasFood, индивидуальная нейросеть, счётчик доставленной еды и возраст. Также хранятся простые метки событий (тик последнего подбора/доставки/коллизии).
Рекуррентной памяти в сети нет: контекст формируется через эти внешние таймеры и через конфигурацию мира (следы феромонов), а не через скрытое состояние RNN/GRU/LSTM.
Сеть имеет промежуточный слой: 25-10-6 (входы-hidden-выходы). Активации: быстрая аппроксимация tanh, x/(1+|x|), в скрытом слое и на выходах.
Это полноценный MLP: сначала линейная комбинация входов и смещений, затем нелинейность в hidden-слое, затем второй линейный слой и нелинейность на выходах (диапазон -1..1).
Весовые коэффициенты и смещения мутируют при эволюции. Диапазон значений ограничивается, чтобы сеть не «взрывалась» численно.
1) Муравей проверяет текущую клетку: если там есть хотя бы 1 порция еды и он не несёт еду, происходит подбор 1 порции. Если он с едой и рядом с гнездом, еда засчитывается и флаг сбрасывается.
2) Муравей считывает сенсоры, пропускает входы через сеть и получает действия.
3) Применяется поворот и шаг движения; при столкновении со стеной или краем агент физически блокируется и получает только небольшой случайный доворот, чтобы не залипать детерминированно.
4) В текущую клетку добавляются феромоны (по трём каналам) с ограничением максимальной концентрации.
5) После обновления всех муравьёв выполняется общая динамика феромонов: диффузия к соседям + испарение.
25 входов состоят из: 9 значений феромонов (3 канала × 3 луча: лево/центр/право), флага «несёт еду», флага «на базе» (по тому же радиусу, что используется для сдачи еды), угла до гнезда в виде sin/cos (только если включён параметр «Направление на базу»), трёх бинарных входов стен (лево/центр/право), трёх бинарных входов видимости базы по лучам (лево/центр/право, с учётом перекрытия стенами; передаются всегда), трёх бинарных входов короткого сенсора еды по лучам (лево/центр/право), и трёх нормированных таймеров: тики с последнего подбора еды, тики с последней доставки, тики с последней коллизии.
Стены теперь учитываются явно: отдельные входы `wL/wC/wR` позволяют отличать «пусто» от «стена» даже при нулевых феромонах.
Еду издалека муравей не видит. Есть только короткий локальный сенсор по лучам (L/C/R) на малой дистанции, плюс автоматический подбор при контакте (одна порция за раз).
Дальность короткого сенсора еды фиксирована константой FOOD_RAY_SENSOR_DIST = 3 клетки (и дополнительно ограничена текущим sensorDist, если он меньше).
6 выходов: поворот, скорость, выброс феромона R, выброс феромона G, выброс феромона B, и небольшой шумовой wiggle для разведки.
Сырые значения выхода после активации всегда в диапазоне -1..1 (используется аппроксимация tanh: x/(1+|x|)). Преобразование в действия: turn = out0 * (π/2), speed = 0.5 + ((out1 + 1) * 0.5), emitR/G/B = ((out2..4 + 1) * 0.5) * pherEmitMax, wiggle = out5 * 0.3. Итоговый поворот за тик: angle += turn + wiggle.
Пример: out=[0.40, -0.20, 0.10, -0.60, 0.90, 0.25], pherEmitMax=0.15 → turn≈36.0°, speed=0.9, emitR/G/B=0.0825/0.03/0.1425, wiggle≈4.3°, итоговый поворот за тик≈40.3°.
Поворот симметричный вокруг нуля, а выброс феромонов ограничен сверху параметром pherEmitMax, что стабилизирует динамику следов.
Подбор еды сейчас автоматический при контакте, а сброс происходит в зоне гнезда.
Автоподбор упрощает пространство действий: сеть концентрируется на навигации и маркировке феромонами, а не на переключении carry-состояния.
Да. Для локальной навигации и троп этого набора достаточно, и колония обычно учится рабочей стратегии. Но это частично наблюдаемая среда, поэтому плато по Fitness нормально: сеть видит локально и не знает глобально, где «лучшая» цель.
Плато обычно означает, что найдена устойчивая локальная стратегия. Для выхода на новый уровень часто нужно либо больше разнообразия через мутации, либо более информативные сенсоры.
Можно добавить аналогичные угловые/силовые входы для стен и соседей, чтобы сеть предсказывала пробки и обходы заранее.
Добавить выход «поднять/бросить» тоже можно (как минимум +1 выход). Тогда нужно переопределять правила награды и штрафовать бесполезные переключения, иначе агент начинает «дёргать» состояние carry.
Практичный вариант: оставить базовый режим как сейчас и сделать advanced-режим с расширенными входами/выходами для сравнения.
Диффузия управляет растеканием следа по соседним клеткам, испарение — скоростью затухания. Высокая диффузия делает следы «шире», но хуже по направленности.
Каналы теперь имеют разную физику по умолчанию: R быстрый (evap 0.95, diff 0.05), B средний (evap 0.990, diff 0.40), G медленный (evap 0.996, diff 0.15).
Лимит концентрации нужен для стабильности: без него клетки насыщаются, и полезный контраст троп исчезает.
В конце поколения муравьи сортируются лексикографически: сначала по доставленной еде, затем (если у обоих были доставки) по среднему возрасту переноски до сдачи (меньше лучше), затем по подобранной еде, затем по разбеганию от базы в фазе поиска (учитывается только пока муравей не несёт еду), и последним критерием — по числу ударов о стены/края (меньше лучше, если включено).
Параметр «Эпизодов на геном» позволяет оценивать один и тот же набор геномов несколько раз подряд перед селекцией (батч-оценка), чтобы снизить влияние случайности.
Вероятность мутации интерполируется между mutationMin и текущим mutationMax. После разгонной фазы верхняя граница mutationMax дополнительно мягко сжимается по сглаженному качеству популяции (avgFitness относительно предела среднего) с учётом разброса внутри популяции (IQR), чтобы меньше ломать почти оптимальные стратегии и не зажимать мутации слишком рано при «рваном» поколении.
Если включена «Адаптивная мутация», первые поколения идут с усиленным поиском (повышенные mutationMax и mutationStrength), затем значения плавно возвращаются к базовым, и дальше работает мягкое сжатие по качеству.
Fitness считается как среднее число доставленной еды за эпизод; без штрафов и бонусов. Скорость возврата теперь учитывается лексикографически через средний возраст переноски до сдачи.
Столкновения со стенами/краями можно учитывать как последний тай-брейкер (параметр «Удары о стену (тай-брейк)»).
Каждое поколение стартует с одинаковой базовой карты еды и чистых феромонов, чтобы сравнение поколений было честным.
Если параметр «Прогресивная схема» включён, используется checkpoint-защита от сползания: хранится checkpoint (лучшее подтверждённое поколение по доле доставки), а нижняя граница задаётся параметром «Нижняя граница» как floor = checkpoint × floorFactor.
Кандидат-поколение принимается только если не ниже floor (с epsilon-защитой от float-шума). Если ниже — накапливается счётчик провалов; rollback к checkpoint срабатывает после достижения порога «Провалов до rollback».
Поверх normal-режима включаются две фазы поиска: Near Search (усиленная мутация, floor активен) и Far Search (более сильная мутация, floor отключён внутри фазы). Старт Near/Far всегда якорится к checkpoint (поиск от лучшей подтверждённой точки, а не от хвоста предыдущей линии).
Текущие константы: N=20 по умолчанию (длительность normal до старта Near, настраивается), L=12 по умолчанию (длительность Near, настраивается), K=2 (неудачных Near до Far), B=16 (длина Far), nearMult=1.20, farMult=1.45, farScoutTail=10% неэлитных потомков, farScoutMult=1.50, floorFactor(по умолчанию)=0.70, rollbackGrace(по умолчанию)=5, epsilon=1e-9.
Цикл без успеха: N normal -> L near -> N normal -> L near -> 16 far. Если far не улучшил checkpoint, выполняется rollback к checkpoint и цикл запускается заново по тем же условиям.
Near/Far не изменяют сам критерий принятия checkpoint: новый checkpoint фиксируется только при реальном улучшении доли доставки.
Открыть отдельную схему состояний progressive-режима
antCount и generationTicks задают «объём отбора»: больше агентов и больше тиков дают статистически устойчивее отбор, но требуют больше CPU.
survivorPct и selectionPressure задают селекционное давление: кто и как часто становится родителем внутри пула выживших. elitePct задаёт долю элиты (переход без мутаций).
mutationMin/mutationMax/mutationStrength управляют балансом исследования и сохранения. Слишком мало мутаций = раннее плато, слишком много = разрушение хороших решений.
sensorDist и sensorAngleDeg меняют геометрию восприятия. Обычно это самые чувствительные параметры для качества навигации.
Лучше делать гибрид: режим «один муравей» для отладки и «агрегаты колонии» для общей картины.
Для одного муравья: показывать 25 входов (бар-чарт), 10 hidden-активаций, 6 выходов, текущий fitness, hasFood и лучи сенсоров прямо на карте.
Для колонии: показывать распределения выходов, средние/дисперсии hidden-нейронов, энтропию действий, долю carrying, и heatmap плотности муравьёв по карте.
Если нужно выбрать только одно: сначала агрегаты колонии (полезнее для эволюции), затем переключаемый инспектор лучшего муравья поколения.
Верхняя панель позволяет рисовать еду и стены, стирать их, управлять скоростью, открывать параметры/описание/сохранения и панель аудио. Видимость феромонов и муравьёв вынесена в блок «Карта» на правой панели. В модалке параметров у каждого слайдера есть подробный тултип.
Звук строится по вращающемуся лучу из центра карты. На каждом аудио-тике луч поворачивается, вдоль него считывается плотность феромонов, и эти значения превращаются в частоты/громкости осцилляторов.
У луча есть «немая» зона вокруг гнезда: участок внутри радиуса базы не озвучивается. Если канал феромона скрыт на карте (R/G/B выключен), он полностью исключается из синтеза.
Луч делится на полосы (параметр «Полосы луча»). Для каждой полосы берётся несколько точек выборки, усредняется концентрация R/G/B в этой полосе, и получается спектральный «срез» текущего направления.
В режиме Σ используется суммарная плотность видимых каналов. В режиме RGB каждый канал звучит отдельно своим тембром и диапазоном частот.
Положение полосы по лучу переводится в частоту логарифмически (нижние и верхние границы задаются слайдерами диапазона). Затем, при включении квантования, частоты притягиваются к выбранной музыкальной гамме (мажор/минор, пентатоники, блюзовые, модальные и др., включая хроматику).
Громкость полосы зависит от силы феромона напрямую: есть только небольшой порог тишины для микрошумов, нормализации «к максимуму карты» нет. Поэтому пустая карта звучит тихо, а плотные следы звучат заметно громче.
Для феромонов доступен и перкуссионный слой: он настраивается отдельно для R/G/B. Набор пресетов единый с муравьями; удары берут частоту из активной полосы (то есть тоже частотно модулируются по спектру).
Муравьи озвучиваются отдельно от феромонов. В скане Радар считается сектор 15° вокруг луча: считаются муравьи без еды и с едой вне зоны гнезда.
В скане Поле используется кластеризация: муравьи группируются на сетке, берутся крупнейшие кластеры, а их вклад раскладывается по тем же радиальным полосам, что и звук поля. Параметр «Плотность ударов» (antRate) масштабирует частоту срабатываний, а «Громкость муравьёв» — амплитуду удара.
Каждый тип муравья имеет свой выбранный пресет (перкуссия/эмбиент и т.д.). Если пресет установлен в «нет», соответствующий тип не звучит. Озвучка муравьёв работает только когда муравьи видимы на карте.
Параметр «Обновление (Гц)» влияет и на феромоны, и на муравьёв: это частота вызова аудио-тика, где считается луч, синтез и события муравьёв.
Параметр «Полосы луча/поля» задаёт количество частотных полос для феромонного слоя; в режиме Поле к этим же полосам привязаны и частоты муравьиных кластеров.
Для слабых CPU уменьшай «Полосы луча» и «Обновление», а также сложность тембров. Для более ровного ритма муравьёв повышай «Обновление». Если важна читаемость, оставляй умеренный antRate и разные тембры для «ищет/несёт».