Оптимизатор Бонобо — Bonobo Optimizer (BO)
Содержание
Введение
Разберем еще один интересный и многообещающий метод оптимизации, который получил название Bonobo Optimizer. Алгоритм BO был опубликован в 2021 году, а его авторами являются Amit Kumar Das и Dilip Kumar Pratihar. Метод основан на социальном поведении приматов бонобо, которые живут сложной общественной жизнью с несколькими уникальными особенностями. Представьте популяцию, где каждый бонобо —это одно возможное решение для задачи оптимизации.
Реализация алгоритма
Главная идея алгоритма BO — это динамическая социальная структура "fission-fusion", которая означает, что особи не всегда действуют всей группой сразу, они формируют временные подгруппы для разных активностей. Самый лучший бонобо в популяции называется альфа-бонобо — это текущее лучшее найденное решение, к которому стремятся все остальные.
Алгоритм BO реализует три разные стратегии спаривания, которые имитируют реальное поведение бонобо. Первая стратегия — это рандомизированный выбор, где бонобо создает потомка, двигаясь одновременно к альфа-бонобо (лучшему решению) и к случайному партнеру из подгруппы. Например, если текущий бонобо находится в точке X=5, альфа в точке X=10, а случайный партнер в точке X=7, то потомок может оказаться примерно в точке X=7.5, сделав шаг и к лучшему решению и добавив немного разнообразия от партнера. Коэффициенты scab=1.25 и scsb=1.3 контролируют насколько большие эти шаги, причем они могут быть больше единицы, что позволяет иногда перепрыгивать через лучшее решение для исследования области за ним.
Вторая стратегия — это внегрупповое спаривание "extra-group mating", оно происходит с небольшой вероятностью и имитирует ситуацию когда бонобо ищет партнера из другой группы. В этом случае потомок создается, используя информацию о границах популяции, где находятся самые крайние бонобо по каждой координате. Алгоритм смотрит на позицию альфа-бонобо относительно текущей особи и решает двигаться к верхней границе диапазона или к нижней, используя экспоненциальные коэффициенты "beta", которые создают нелинейные прыжки в пространстве решений. Например, если альфа справа от текущего бонобо, то потомок делает прыжок вправо к максимальной границе, если альфа слева, то прыжок влево к минимальной границе. Это помогает исследовать крайние области пространства поиска.
Третья стратегия — это временное спаривание "consorship mating", где два бонобо формируют временную пару и потомок создается как комбинация их позиций с использованием направленного движения. Здесь важную роль играет флаг "direction", который определяется сравнением фитнеса текущего бонобо и его партнера. Если текущий бонобо лучше партнера, то direction=1 и движение идет от партнера, если хуже, то direction=-1 и движение идет к партнеру. Например, если два бонобо в точках X=5 и X=8, и первый лучше, то потомок создается примерно в точке X=4 или X=6, двигаясь от худшего партнера, а если первый хуже, то потомок будет ближе к X=8, двигаясь к лучшему из двух решений. Коэффициент "exp(-random)" создает затухающие шаги, уменьшающиеся со временем.
Критически важный механизм в алгоритме, это "acceptance criteria" или критерий принятия нового решения. Бонобо не всегда принимает созданного потомка — новое решение принимается только если оно лучше, чем текущее, или с небольшой вероятностью принимается случайно, даже если хуже. Это предотвращает деградацию популяции и гарантирует, что плохие решения не вытесняют хорошие. Например, если у бонобо фитнес 0.8, а потомок имеет фитнес 0.7, то в 97 процентах случаев потомок отвергается, и бонобо остается на своей текущей позиции, и только в 3 процентах случаев принимается для разнообразия популяции. Если потомок лучше (фитнес 0.9), он всегда принимается.
Алгоритм использует адаптивную систему положительных и отрицательных фаз, которая автоматически настраивает параметры в зависимости от прогресса оптимизации. Когда находится новое лучшее решение, начинается положительная фаза "positive phase", где счетчик "ppc" увеличивается, вероятность рандомизированного спаривания растет, становясь более агрессивным (может достичь 1.0), размер подгрупп увеличивается для более широкого поиска, а вероятность внегруппового спаривания возвращается к минимуму — 3 процента. Это период интенсивной эксплуатации найденной перспективной области.
Когда несколько итераций проходит без улучшения, начинается отрицательная фаза "negative phase", где счетчик "npc" растет, вероятность рандомизированного выбора партнера падает (может упасть до 0), размер подгрупп уменьшается для более осторожного поиска, а вероятность внегруппового спаривания увеличивается до 50 процентов. Это период усиленной разведки "exploration", когда алгоритм пытается найти новые перспективные области пространства поиска. Скорость этих изменений контролируется параметром "rcpp", обычно около 0.0035, что означает, что параметры меняются постепенно, а не скачками.
Например, представьте поиск максимума функции на плоскости, где оптимум находится на вершине холма. В начале 30 бонобо разбросаны случайно по всей плоскости. На каждой итерации каждый бонобо формирует подгруппу из 3-5 соседей, выбирает лучшего партнера из подгруппы, создает потомка, используя одну из трех стратегий спаривания, и, если потомок лучше, переходит на его позицию.
Альфа-бонобо постоянно обновляется, когда кто-то находит лучшую точку. Допустим, один бонобо случайно оказался близко к вершине холма, и его фитнес улучшился — он становится альфа, начинается положительная фаза, все остальные бонобо начинают активно двигаться к нему, создавая потомков в направлении альфы, подгруппы становятся больше, охватывая больше популяции, вероятность рандомизированного спаривания растет до 70-80 процентов, и популяция быстро сходится к области вокруг вершины.
Если после 50 итераций улучшений не наблюдается, то начинается отрицательная фаза, рандомизированный поиск партнера падает до 30-40 процентов, а внегрупповое спаривание возрастает до 20-30 процентов, и бонобо начинают делать более дальние прыжки, исследуя другие части ландшафта на случай, если есть другая более высокая вершина и "acceptance criteria" гарантирует, что даже в период активных прыжков бонобо не покидают хорошие найденные позиции без веской причины — они пробуют новые точки, но возвращаются, если новая точка хуже.
Важной деталью является использование нормализованных весов, которые в сумме дают единицу, это создает выпуклую комбинацию позиций и гарантирует, чтобы потомок не улетел слишком далеко от родителей, плюс граничные условия "clipping" жестко обрезают координаты, если они выходят за допустимые пределы. Экспоненциальные коэффициенты "beta" вычисляются по формуле: exp(r^2 + r - 2/r), где "r" — случайное число. Формула специально подобрана, чтобы создавать коэффициенты в диапазоне от 0.1 до 3 с тяжелыми хвостами распределения, позволяющие иногда делать очень большие прыжки для выхода из локальных оптимумов. Очень напоминает поведение цены, когда происходит резкий скачок, и движение выносит нас на новый уровень. Параметр "direction" умноженный на "exp(-random)" создает направленное движение с экспоненциально убывающей силой, что имитирует затухание активности со временем, наблюдаемое у реальных бонобо.

Рисунок 1. Схема работы алгоритма BO
Диаграмма включает: Initialization - начальная популяция и параметры, Fission-Fusion — динамические подгруппы, Three Mating Strategies — все 3 типа спаривания с формулами, Direction Flag Logic — логика флага направления, Acceptance Criteria — критический механизм отбора (красным) и Positive/Negative Phases — адаптивные режимы. Переходим к написанию псевдокода алгоритма BO.
ИНИЦИАЛИЗАЦИЯ
Создаем популяцию из тридцати бонобо со случайными позициями в допустимых
границах и вычисляем их фитнес. Лучший становится альфа-бонобо.
Устанавливаем начальные параметры: вероятность случайного спаривания -
половина, внегруппового - три процента, счетчики фаз - в ноль, фактор размера
подгрупп - на средний уровень.
ГЛАВНЫЙ ЦИКЛ
Вычисляем максимальный размер подгруппы как минимум два, но не больше
размера популяции × текущий фактор.
ДЛЯ КАЖДОГО БОНОБО:
Формируем список остальных бонобо. Выбираем случайное количество от двух
до максимума во временную подгруппу. Из подгруппы выбираем лучшего по
фитнесу как партнера.
Определяем флаг направления: если текущий лучше партнера, то партнер
переназначается на случайного из подгруппы и флаг = +1, иначе флаг = -1.
СОЗДАНИЕ ПОТОМКА:
Генерируем случайное число и сравниваем с вероятностью фазы.
ЕСЛИ меньше вероятности фазы - СЛУЧАЙНОЕ СПАРИВАНИЕ:
Для каждой координаты:
новая позиция = текущая + 1.25 × случайный вес × (альфа - текущая) +
флаг × 1.3 × (1 - случайный вес) × (текущая - партнер)
ИНАЧЕ для каждой координаты генерируем случайное число:
ЕСЛИ меньше вероятности внегруппового - ВНЕГРУППОВОЕ СПАРИВАНИЕ:
Вычисляем экспоненциальные коэффициенты бета по формулам
с квадратами и обратными величинами случайного числа.
Проверяем позицию альфы относительно текущей. В зависимости от этого
и направленной вероятности, либо прыгаем к верхней границе -
новая позиция = текущая + бета × (максимум - текущая),
либо к нижней - новая позиция = текущая - бета × (текущая - минимум).
Четыре возможные стратегии создают нелинейные прыжки к краям популяции.
ИНАЧЕ - КОНСОРТНОЕ СПАРИВАНИЕ:
Если флаг = +1 или случайное меньше направленной вероятности, то
новая позиция = текущая + флаг × exp(-случайное число) × (текущая - партнер),
иначе копируем позицию партнера.
Ограничиваем координаты потомка границами. Вычисляем его фитнес.
КРИТЕРИЙ ПРИНЯТИЯ:
Если фитнес потомка лучше текущего, ИЛИ случайное число меньше
вероятности внегруппового, то заменяем текущего потомком и, если
потомок лучше глобального лучшего, обновляем альфу. Иначе текущий
бонобо остается без изменений.
АДАПТАЦИЯ ПАРАМЕТРОВ:
ЕСЛИ глобальное лучшее улучшилось - ПОЗИТИВНАЯ ФАЗА:
Обнуляем счетчик негативной фазы, увеличиваем позитивной. Вероятность
внегруппового возвращается к трем процентам. Вероятность
случайного растет к единице. Фактор размера подгрупп
увеличивается. Режим агрессивной эксплуатации найденной области.
ИНАЧЕ - НЕГАТИВНАЯ ФАЗА:
Увеличиваем счетчик негативной фазы, обнуляем позитивной. Вероятность
внегруппового растет к половине. Вероятность случайного падает
к нулю. Фактор размера подгрупп уменьшается. Режим интенсивной
разведки новых областей.
РЕЗУЛЬТАТ
Возвращаем лучшее найденное значение, позицию альфа бонобо и историю
сходимости.
Переходим к написанию кода алгоритма. Класс, "C_AO_BO" является специфической реализацией алгоритма оптимизации, основанного на поведении бонобо. Он наследуется от базового класса "C_AO", это предполагает наличие общих механизмов управления оптимизационным процессом.
При создании объекта "C_AO_BO" автоматически устанавливаются некоторые начальные настройки, инициализируются основные параметры, такие как размер популяции (popSize), начальная вероятность внегруппового спаривания (xgmProbInit), коэффициенты разделения (scab, scsb), вероятность смены фазы (rcpp) и максимальный коэффициент размера подгруппы (subgroupFactorMax). Эти параметры также сохраняются в структурированном виде внутри объекта для удобства управления.
SetParams() — метод позволяет обновить внутренние параметры объекта "C_AO_BO" на основе значений, хранящихся в его параметрической структуре. Это удобно для настройки алгоритма перед запуском.
Публичные методы (Init, Moving, Revision), объявленные в базовом классе, "Init" отвечает за инициализацию алгоритма, "Moving" — за основную фазу поиска и перемещения особей в пространстве решений, а "Revision" — за форму пересмотра и корректировки текущего решения.
Публичные данные-члены (параметры):
- xgmProbInit — начальное значение вероятности, с которой выбирается партнер для спаривания из другой группы (внегруппового спаривания);
- scab — коэффициент, влияющий на расстояние, на которое перемещается "альфа-бонобо" (лучшая особь);
- scsb — коэффициент, влияющий на расстояние, на которое перемещается "выбранная особь" (другая особь в популяции);
- rcpp — вероятность, с которой особь может сменить свою "фазу" поведения;
- subgroupFactorMax — максимальный коэффициент, ограничивающий размер подгрупп, которые могут формироваться внутри общей популяции.
- negPhaseCount, posPhaseCount — счетчики, отслеживающие количество "отрицательных" и "положительных" фаз;
- xgmProb — текущая вероятность внегруппового спаривания, которая может изменяться в ходе работы алгоритма;
- subgroupFactorInit и subgroupFactor — переменные, связанные с расчетом и управлением размером подгруппы;
- phaseProb — вероятность перехода между фазами поведения;
- directProb — вероятность прямого направления движения, влияющая на шаг поиска;
- prevBestFitness — значение лучшей приспособленности (fitness) с предыдущего шага, используемое для сравнения и принятия решений;
- prevState — массив, хранящий предыдущие состояния (позиции) особей, он используется для оценки стабильности и принятия решений на основе предыдущих результатов.
Таким образом, "C_AO_BO" представляет собой сложный алгоритм оптимизации, имитирующий социальное поведение бонобо, где решения принимаются на основе вероятностей, коэффициентов и фазовых переходов, а также учитывается предыдущий опыт (предыдущие состояния и приспособленность).
//———————————————————————————————————————————————————————————————————— class C_AO_BO : public C_AO { public: //---------------------------------------------------------- ~C_AO_BO () { } C_AO_BO () { ao_name = "BO"; ao_desc = "Bonobo Optimizer"; ao_link = "https://www.mql5.com/ru/articles/20245"; popSize = 50; xgmProbInit = 0.03; scab = 1.25; scsb = 1.3; rcpp = 0.0035; subgroupFactorMax = 0.05; ArrayResize (params, 6); params [0].name = "popSize"; params [0].val = popSize; params [1].name = "xgmProbInit"; params [1].val = xgmProbInit; params [2].name = "scab"; params [2].val = scab; params [3].name = "scsb"; params [3].val = scsb; params [4].name = "rcpp"; params [4].val = rcpp; params [5].name = "subgroupFactorMax"; params [5].val = subgroupFactorMax; } void SetParams () { popSize = (int)params [0].val; xgmProbInit = params [1].val; scab = params [2].val; scsb = params [3].val; rcpp = params [4].val; subgroupFactorMax = params [5].val; } bool Init (const double &rangeMinP [], const double &rangeMaxP [], const double &rangeStepP [], const int epochsP); void Moving (); void Revision (); //------------------------------------------------------------------ double xgmProbInit; // Начальная вероятность внегруппового спаривания double scab; // Коэффициент разделения для альфа-бонобо double scsb; // Коэффициент разделения для выбранного бонобо double rcpp; // Вероятность изменения фазы double subgroupFactorMax; // Максимальное значение временного коэффициента размера подгруппы private: //--------------------------------------------------------- int negPhaseCount; // npc - Отрицательное количество фаз int posPhaseCount; // ppc - Положительное количество фаз double xgmProb; // p_xgm - Вероятность внегруппового спаривания double subgroupFactorInit;// tsgs_factor_initial double subgroupFactor; // tsgs_factor double phaseProb; // p_p - Фазовая вероятность double directProb; // p_d - Вероятность направления double prevBestFitness; // pbestcost S_AO_Agent prevState []; // Старые позиции для критериев приемлемости }; //————————————————————————————————————————————————————————————————————
Метод "Init" отвечает за начальную инициализацию алгоритма оптимизации "C_AO_BO". Он является частью процесса подготовки к выполнению основного цикла оптимизации.
Базовая инициализация. Первым шагом вызывается метод "StandardInit", который является частью базового класса "C_AO". Этот вызов выполняет общие для всех алгоритмов "C_AO" процедуры инициализации, такие как установка диапазонов поиска (rangeMinP, rangeMaxP) и шагов (rangeStepP), а также количества эпох (epochsP). Если эта базовая инициализация завершается неудачно (возвращает "false"), то метод "Init" также прерывает свою работу и возвращает "false", сигнализируя о невозможности продолжения.
Сброс внутренних счетчиков и переменных: далее, метод сбрасывает внутренние переменные, связанные с фазами поведения и вероятностями, к их начальным значениям.
Инициализация состояний агентов. Метод выделяет память для хранения предыдущих состояний агентов (prevState). Размер этого массива определяется "popSize" (размером популяции). Затем для каждого агента в популяции вызывается его собственный метод "Init", передавая ему информацию о координатах (coords). Это означает, что для каждого "агента" (предполагается, что это отдельная особь или решение в популяции) устанавливается его первоначальное состояние.
Если все предыдущие шаги прошли успешно, метод возвращает "true", алгоритм "C_AO_BO" успешно проинициализирован и готов к работе. В целом, метод "Init" выполняет все необходимые подготовительные действия, устанавливая начальные условия и структуру данных, которые будут использоваться на последующих этапах работы алгоритма оптимизации.
//———————————————————————————————————————————————————————————————————— bool C_AO_BO::Init (const double &rangeMinP [], const double &rangeMaxP [], const double &rangeStepP [], const int epochsP) { if (!StandardInit (rangeMinP, rangeMaxP, rangeStepP)) return false; //------------------------------------------------------------------ negPhaseCount = 0; posPhaseCount = 0; xgmProb = xgmProbInit; subgroupFactorInit = 0.5 * subgroupFactorMax; subgroupFactor = subgroupFactorInit; phaseProb = 0.5; directProb = 0.5; prevBestFitness = -DBL_MAX; ArrayResize (prevState, popSize); for (int i = 0; i < popSize; i++) prevState [i].Init (coords); return true; } //————————————————————————————————————————————————————————————————————
Метод "Moving" является основной активной фазой алгоритма "C_AO_BO", ответственной за генерацию новых решений (потомков) и обновление текущих позиций особей в пространстве поиска. Если флаг "revision" установлен в "false" (что означает, что это первый вызов "Moving" или алгоритм находится в начальной фазе), вся популяция генерируется случайным образом. Для каждого агента (popSize) и каждой координаты (coords) новое значение генерируется в пределах заданных диапазонов (rangeMin, rangeMax) и с учетом шага (rangeStep). После генерации случайных значений, флаг "revision" устанавливается в "true", и метод завершает свою работу. Это гарантирует, что случайная инициализация выполняется только один раз.
Основной цикл перемещения (при revision равном true). Вычисляется максимальный размер подгруппы (maxSubgroupSize), который зависит от общего размера популяции (popSize) и текущего коэффициента размера подгруппы (subgroupFactor). Минимальный установлен в 2. Метод проходит по каждому агенту (с индексом i) в популяции.
Сохранение предыдущего состояния: текущая позиция (a[i].c) и значение приспособленности (a[i].f) агента сохраняются в "prevState" для последующего использования.
Формирование списка доступных индексов: создается временный массив "availableIndices", содержащий индексы всех агентов, кроме текущего агента "i".
Выбор случайной подгруппы: определяется фактический размер подгруппы (actualSubgroupSize), который выбирается случайно (от 2 до maxSubgroupSize). Среди доступных индексов случайным образом выбирается (actualSubgroupSize) уникальных индексов, формирующих (subgroupIndices). Элементы из "availableIndices" удаляются по мере выбора, чтобы избежать повторений.
Выбор партнера из подгруппы: из выбранной подгруппы "subgroupIndices" ищется агент с наилучшей приспособленностью (наибольшее значение "f").
Определение направления:если текущий агент "i" имеет худшую приспособленность, чем лучший партнер из подгруппы, то выбирается новый случайный партнер из этой же подгруппы, и направление (direction) устанавливается в 1 (для движения к лучшему). В противном случае (a[i].f лучше, чем у партнера), направление (direction) устанавливается в -1.
Создание нового решения (offspring):проверяется фазовая вероятность (phaseProb). Если фазовая вероятность срабатывает, то новое решение "offspring" генерируется на основе линейной комбинации текущей позиции агента (a[i].c), лучшей особи в популяции (cB), партнера из подгруппы (a[partnerIdx].c) и случайных весов. Используются коэффициенты (scab и scsb). Если фазовая вероятность не срабатывает, алгоритм может перейти к одному из двух подтипов:
EXTRA-GROUP MATING: если случайная вероятность "u.RNDprobab()" меньше или равна вероятности внегруппового спаривания (xgmProb), применяется специальный механизм генерации. Он включает в себя экспоненциальные функции "MathExp" и зависит от направления "cB[c]" по сравнению с (a[i].c[c]) и вероятности прямого направления (directProb). Рассчитываются коэффициенты "betaCoef1" и "betaCoef2" для смещения решения.
CONSORSHIP MATING: в противном случае (если не EXTRA-GROUP MATING), применяется "CONSORSHIP MATING". Новый вариант решения генерируется на основе текущей позиции, партнера из подгруппы и вероятности прямого направления (directProb). Также используется экспоненциальная функция.
Сгенерированное решение "offspring" проверяется на соответствие диапазонам поиска (rangeMin, rangeMax). Значения, выходящие за пределы, ограничиваются. Затем, с учетом шага (rangeStep), оно "привязывается" к допустимым значениям. Скорректированное решение "offspring" присваивается текущему агенту "a[i].c". В целом, метод "Moving" моделирует сложный процесс взаимодействия особей в популяции, где каждое решение генерируется на основе комбинации случайности, информации о лучших особях, партнерах в подгруппах и фазовых состояниях, что позволяет эффективно исследовать пространство поиска.
//———————————————————————————————————————————————————————————————————— void C_AO_BO::Moving () { if (!revision) { for (int i = 0; i < popSize; i++) { for (int c = 0; c < coords; c++) { a [i].c [c] = u.RNDfromCI (rangeMin [c], rangeMax [c]); a [i].c [c] = u.SeInDiSp (a [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]); } } revision = true; return; } //------------------------------------------------------------------ int maxSubgroupSize = (int)MathMax (2.0, MathCeil (popSize * subgroupFactor)); //------------------------------------------------------------------ for (int i = 0; i < popSize; i++) { // Сохраняем старое состояние ArrayCopy (prevState [i].c, a [i].c, 0, 0, coords); prevState [i].f = a [i].f; // Создаем список индексов без текущего агента int availableIndices []; ArrayResize (availableIndices, popSize - 1); int idx = 0; for (int k = 0; k < popSize; k++) { if (k != i) availableIndices [idx++] = k; } //---------------------------------------------------------------- // Определяем фактический размер подгруппы int actualSubgroupSize = 2 + u.RNDminusOne (maxSubgroupSize - 1); // Выбираем случайную подгруппу int subgroupIndices []; ArrayResize (subgroupIndices, actualSubgroupSize); for (int k = 0; k < actualSubgroupSize; k++) { int rndIdx = u.RNDminusOne (popSize - 1 - k); subgroupIndices [k] = availableIndices [rndIdx]; // Удаляем выбранный элемент for (int m = rndIdx; m < popSize - 2 - k; m++) { availableIndices [m] = availableIndices [m + 1]; } } //---------------------------------------------------------------- // Выбираем лучшего партнера из подгруппы int partnerIdx = subgroupIndices [0]; for (int k = 1; k < actualSubgroupSize; k++) { if (a [subgroupIndices [k]].f > a [partnerIdx].f) { partnerIdx = subgroupIndices [k]; } } // Определяем направление (флаг) int direction; if (a [i].f > a [partnerIdx].f) { partnerIdx = subgroupIndices [u.RNDminusOne (actualSubgroupSize)]; direction = 1; } else { direction = -1; } //---------------------------------------------------------------- // Создание нового решения double offspring []; ArrayResize (offspring, coords); if (u.RNDprobab () <= phaseProb) { //-------------------------------------------------------------- // PROMISCUOUS или RESTRICTIVE MATING //-------------------------------------------------------------- for (int c = 0; c < coords; c++) { double rndWeight = u.RNDprobab (); offspring [c] = a [i].c [c] + scab * rndWeight * (cB [c] - a [i].c [c]) + direction * scsb * (1.0 - rndWeight) * (a [i].c [c] - a [partnerIdx].c [c]); } } else { //-------------------------------------------------------------- // CONSORSHIP или EXTRA-GROUP MATING //-------------------------------------------------------------- for (int c = 0; c < coords; c++) { if (u.RNDprobab () <= xgmProb) { //---------------------------------------------------------- // EXTRA-GROUP MATING //---------------------------------------------------------- double rndValue = u.RNDprobab (); if (rndValue < 0.01) rndValue = 0.01; if (cB [c] >= a [i].c [c]) { if (u.RNDprobab () <= directProb) { double betaCoef1 = MathExp (rndValue * rndValue + rndValue - 2.0 / rndValue); offspring [c] = a [i].c [c] + betaCoef1 * (rangeMax [c] - a [i].c [c]); } else { double betaCoef2 = MathExp (-rndValue * rndValue + 2.0 * rndValue - 2.0 / rndValue); offspring [c] = a [i].c [c] - betaCoef2 * (a [i].c [c] - rangeMin [c]); } } else { if (u.RNDprobab () <= directProb) { double betaCoef1 = MathExp (rndValue * rndValue + rndValue - 2.0 / rndValue); offspring [c] = a [i].c [c] - betaCoef1 * (a [i].c [c] - rangeMin [c]); } else { double betaCoef2 = MathExp (-rndValue * rndValue + 2.0 * rndValue - 2.0 / rndValue); offspring [c] = a [i].c [c] + betaCoef2 * (rangeMax [c] - a [i].c [c]); } } } else { //---------------------------------------------------------- // CONSORSHIP MATING //---------------------------------------------------------- if (direction == 1 || u.RNDprobab () <= directProb) { offspring [c] = a [i].c [c] + direction * MathExp (-u.RNDprobab ()) * (a [i].c [c] - a [partnerIdx].c [c]); } else { offspring [c] = a [partnerIdx].c [c]; } } } } //---------------------------------------------------------------- // Ограничение границами for (int c = 0; c < coords; c++) { if (offspring [c] > rangeMax [c]) offspring [c] = rangeMax [c]; if (offspring [c] < rangeMin [c]) offspring [c] = rangeMin [c]; offspring [c] = u.SeInDiSp (offspring [c], rangeMin [c], rangeMax [c], rangeStep [c]); a [i].c [c] = offspring [c]; } } } //————————————————————————————————————————————————————————————————————
Метод "Revision" выполняет несколько ключевых функций после того, как генерируется новое поколение решений (потомков) в результате работы метода "Moving". Он отвечает за оценку и принятие новых решений, обновление глобального наилучшего результата и адаптивное изменение параметров алгоритма.
Критерий принятия решений (Acceptance Criteria):для каждого агента в популяции принимается решение, будет ли он заменен своим новым (сгенерированным) состоянием, или сохранено его предыдущее состояние. Новое состояние принимается в двух случаях:
- Если новое значение приспособленности (a[i].f) лучше, чем предыдущее (prevState[i].f), или если сработает случайное условие, основанное на вероятности "xgmProb". Это позволяет сохранить некоторую подвижность даже при ухудшении приспособленности.
- Если "acceptNew" оказывается "false" (то-есть, новое решение хуже и случайное условие не сработало), агент возвращается к своему предыдущему состоянию, копируя как его координаты (a[i].c = prevState[i].c), так и значение приспособленности (a[i].f = prevState[i].f).
Обновление глобального лучшего:после того, как определены окончательные состояния агентов на текущем шаге (после применения критерия принятия), происходит обновление глобального наилучшего решения. Перебираются все особи, и если приспособленность текущего агента (a[i].f) лучше, чем текущее глобальное лучшее значение (fB), то глобальное лучшее значение (fB) обновляется. Координаты глобального лучшего решения (cB) копируются из координат текущего агента (a[i].c).
Обновление параметров (Адаптация):этот раздел метода отвечает за адаптацию параметров алгоритма в зависимости от того, улучшается ли найденное лучшее решение.
Позитивная фаза: если текущее лучшее значение (fB) лучше, чем предыдущее лучшее значение (prevBestFitness), это считается "позитивной фазой". Счетчик отрицательных фаз сбрасывается в ноль, а счетчик положительных фаз увеличивается. Адаптивные параметры настраиваются следующим образом:
- prevBestFitness обновляется до текущего "fB",
- xgmProb (вероятность внегруппового спаривания) устанавливается обратно на начальное значение "xgmProbInit",
- phaseProb (фазовая вероятность) увеличивается, приближаясь к 1.0 (что означает большую вероятность выбора одних стратегий размножения),
- directProb (вероятность прямого направления) устанавливается равной "phaseProb",
- subgroupFactor (коэффициент размера подгруппы) увеличивается, разрешая выбор больших подгрупп.
Негативная фаза: если текущее лучшее значение (fB) не лучше, чем предыдущее лучшее значение, это считается "негативной фазой". Счетчик отрицательных фаз "negPhaseCount" увеличивается. Счетчик положительных фаз "posPhaseCount" сбрасывается в ноль. Адаптивные параметры настраиваются следующим образом:
- xgmProb увеличивается, приближаясь к 0.5 (что увеличивает шанс принятия худших решений),
- subgroupFactor уменьшается, уменьшая размер подгрупп,
- phaseProb уменьшается, приближаясь к 0.0 (что означает меньшую вероятность выбора определенных стратегий размножения),
- directProb устанавливается обратно на 0.5.
Таким образом, метод "Revision" динамически корректирует поведение алгоритма, стремясь найти баланс между исследованием новых областей поиска (exploration) и эксплуатацией уже найденных хороших решений (exploitation), основываясь на прогрессе в оптимизации.
//———————————————————————————————————————————————————————————————————— void C_AO_BO::Revision () { //------------------------------------------------------------------ // ACCEPTANCE CRITERIA //------------------------------------------------------------------ for (int i = 0; i < popSize; i++) { bool acceptNew = (a [i].f > prevState [i].f) || (u.RNDprobab () <= xgmProb); if (!acceptNew) { // Откатываем к предыдущему состоянию ArrayCopy (a [i].c, prevState [i].c, 0, 0, coords); a [i].f = prevState [i].f; } } //------------------------------------------------------------------ // Обновляем глобальное лучшее for (int i = 0; i < popSize; i++) { if (a [i].f > fB) { fB = a [i].f; ArrayCopy (cB, a [i].c, 0, 0, coords); } } //------------------------------------------------------------------ // Обновление параметров //------------------------------------------------------------------ if (fB > prevBestFitness) { // POSITIVE PHASE negPhaseCount = 0; posPhaseCount = posPhaseCount + 1; double changeParam = MathMin (0.5, posPhaseCount * rcpp); prevBestFitness = fB; xgmProb = xgmProbInit; phaseProb = 0.5 + changeParam; directProb = phaseProb; subgroupFactor = MathMin (subgroupFactorMax, subgroupFactorInit + posPhaseCount * rcpp * rcpp); } else { // NEGATIVE PHASE negPhaseCount = negPhaseCount + 1; posPhaseCount = 0; double changeParam = -MathMin (0.5, negPhaseCount * rcpp); xgmProb = MathMin (0.5, xgmProbInit + negPhaseCount * rcpp * rcpp); subgroupFactor = MathMax (0.0, subgroupFactorInit - negPhaseCount * rcpp * rcpp); phaseProb = 0.5 + changeParam; directProb = 0.5; } } //————————————————————————————————————————————————————————————————————
Результаты тестов
Результаты тестирования порадовали, хороший и сильный алгоритм.=============================
5 Hilly's; Func runs: 10000; result: 0.7756590260834754
25 Hilly's; Func runs: 10000; result: 0.638053360829739
500 Hilly's; Func runs: 10000; result: 0.3290817311313
=============================
5 Forest's; Func runs: 10000; result: 0.8808853768283266
25 Forest's; Func runs: 10000; result: 0.7634448901275042
500 Forest's; Func runs: 10000; result: 0.25572940087496915
=============================
5 Megacity's; Func runs: 10000; result: 0.6107692307692308
25 Megacity's; Func runs: 10000; result: 0.49846153846153846
500 Megacity's; Func runs: 10000; result: 0.14246153846153967
=============================
All score: 4.89455 (54.38%)
На визуализации заметен большой разброс результатов на задачах малой размерности, высокие показатели для задач средней размерности, тоже присутствует разброс, хорошо происходит поиск на функциях с максимальным количеством координат, недостаточно только итераций, чтобы показать высокую сходимость.

BO на тестовой функции Hilly

BO на тестовой функции Forest

BO на тестовой функции Megacity
Посмотрим, как алгоритм ведет себя на стандартных тестовых функциях. Тоже достаточно хорошо, однако тип задач имеет значение для алгоритма BO, на функции Shaffer заметны некоторые трудности с большой размерностью.

BO на стандартной тестовой функции Ackley

BO на стандартной тестовой функции Shaffer
По результатам тестирования алгоритм BO занимает 25 место в рейтинговой таблице лучших популяционных методов оптимизации.
| № | AO | Description | Hilly | Hilly Final | Forest | Forest Final | Megacity (discrete) | Megacity Final | Final Result | % of MAX | ||||||
| 10 p (5 F) | 50 p (25 F) | 1000 p (500 F) | 10 p (5 F) | 50 p (25 F) | 1000 p (500 F) | 10 p (5 F) | 50 p (25 F) | 1000 p (500 F) | ||||||||
| 1 | DOAdingom | dingo_optimization_algorithm_M | 0,47968 | 0,45367 | 0,46369 | 1,39704 | 0,94145 | 0,87909 | 0,91454 | 2,73508 | 0,78615 | 0,86061 | 0,84805 | 2,49481 | 6,627 | 73,63 |
| 2 | ANS | across neighbourhood search | 0,94948 | 0,84776 | 0,43857 | 2,23581 | 1,00000 | 0,92334 | 0,39988 | 2,32323 | 0,70923 | 0,63477 | 0,23091 | 1,57491 | 6,134 | 68,15 |
| 3 | CLA | code lock algorithm (joo) | 0,95345 | 0,87107 | 0,37590 | 2,20042 | 0,98942 | 0,91709 | 0,31642 | 2,22294 | 0,79692 | 0,69385 | 0,19303 | 1,68380 | 6,107 | 67,86 |
| 4 | AMOm | animal migration ptimization M | 0,90358 | 0,84317 | 0,46284 | 2,20959 | 0,99001 | 0,92436 | 0,46598 | 2,38034 | 0,56769 | 0,59132 | 0,23773 | 1,39675 | 5,987 | 66,52 |
| 5 | (P+O)ES | (P+O) evolution strategies | 0,92256 | 0,88101 | 0,40021 | 2,20379 | 0,97750 | 0,87490 | 0,31945 | 2,17185 | 0,67385 | 0,62985 | 0,18634 | 1,49003 | 5,866 | 65,17 |
| 6 | CTA | comet tail algorithm (joo) | 0,95346 | 0,86319 | 0,27770 | 2,09435 | 0,99794 | 0,85740 | 0,33949 | 2,19484 | 0,88769 | 0,56431 | 0,10512 | 1,55712 | 5,846 | 64,96 |
| 7 | TETA | time evolution travel algorithm (joo) | 0,91362 | 0,82349 | 0,31990 | 2,05701 | 0,97096 | 0,89532 | 0,29324 | 2,15952 | 0,73462 | 0,68569 | 0,16021 | 1,58052 | 5,797 | 64,41 |
| 8 | SDSm | stochastic diffusion search M | 0,93066 | 0,85445 | 0,39476 | 2,17988 | 0,99983 | 0,89244 | 0,19619 | 2,08846 | 0,72333 | 0,61100 | 0,10670 | 1,44103 | 5,709 | 63,44 |
| 9 | BOAm | billiards optimization algorithm M | 0,95757 | 0,82599 | 0,25235 | 2,03590 | 1,00000 | 0,90036 | 0,30502 | 2,20538 | 0,73538 | 0,52523 | 0,09563 | 1,35625 | 5,598 | 62,19 |
| 10 | AAm | archery algorithm M | 0,91744 | 0,70876 | 0,42160 | 2,04780 | 0,92527 | 0,75802 | 0,35328 | 2,03657 | 0,67385 | 0,55200 | 0,23738 | 1,46323 | 5,548 | 61,64 |
| 11 | ESG | evolution of social groups (joo) | 0,99906 | 0,79654 | 0,35056 | 2,14616 | 1,00000 | 0,82863 | 0,13102 | 1,95965 | 0,82333 | 0,55300 | 0,04725 | 1,42358 | 5,529 | 61,44 |
| 12 | SIA | simulated isotropic annealing (joo) | 0,95784 | 0,84264 | 0,41465 | 2,21513 | 0,98239 | 0,79586 | 0,20507 | 1,98332 | 0,68667 | 0,49300 | 0,09053 | 1,27020 | 5,469 | 60,76 |
| 13 | EOm | extremal_optimization_M | 0,76166 | 0,77242 | 0,31747 | 1,85155 | 0,99999 | 0,76751 | 0,23527 | 2,00277 | 0,74769 | 0,53969 | 0,14249 | 1,42987 | 5,284 | 58,71 |
| 14 | BBO | biogeography based optimization | 0,94912 | 0,69456 | 0,35031 | 1,99399 | 0,93820 | 0,67365 | 0,25682 | 1,86867 | 0,74615 | 0,48277 | 0,17369 | 1,40261 | 5,265 | 58,50 |
| 15 | ACS | artificial cooperative search | 0,75547 | 0,74744 | 0,30407 | 1,80698 | 1,00000 | 0,88861 | 0,22413 | 2,11274 | 0,69077 | 0,48185 | 0,13322 | 1,30583 | 5,226 | 58,06 |
| 16 | DA | dialectical algorithm | 0,86183 | 0,70033 | 0,33724 | 1,89940 | 0,98163 | 0,72772 | 0,28718 | 1,99653 | 0,70308 | 0,45292 | 0,16367 | 1,31967 | 5,216 | 57,95 |
| 17 | BHAm | black hole algorithm M | 0,75236 | 0,76675 | 0,34583 | 1,86493 | 0,93593 | 0,80152 | 0,27177 | 2,00923 | 0,65077 | 0,51646 | 0,15472 | 1,32195 | 5,196 | 57,73 |
| 18 | ASO | anarchy society optimization | 0,84872 | 0,74646 | 0,31465 | 1,90983 | 0,96148 | 0,79150 | 0,23803 | 1,99101 | 0,57077 | 0,54062 | 0,16614 | 1,27752 | 5,178 | 57,54 |
| 19 | RFO | royal flush optimization (joo) | 0,83361 | 0,73742 | 0,34629 | 1,91733 | 0,89424 | 0,73824 | 0,24098 | 1,87346 | 0,63154 | 0,50292 | 0,16421 | 1,29867 | 5,089 | 56,55 |
| 20 | AOSm | atomic orbital search M | 0,80232 | 0,70449 | 0,31021 | 1,81702 | 0,85660 | 0,69451 | 0,21996 | 1,77107 | 0,74615 | 0,52862 | 0,14358 | 1,41835 | 5,006 | 55,63 |
| 21 | TSEA | turtle shell evolution algorithm (joo) | 0,96798 | 0,64480 | 0,29672 | 1,90949 | 0,99449 | 0,61981 | 0,22708 | 1,84139 | 0,69077 | 0,42646 | 0,13598 | 1,25322 | 5,004 | 55,60 |
| 22 | BSA | backtracking_search_algorithm | 0,97309 | 0,54534 | 0,29098 | 1,80941 | 0,99999 | 0,58543 | 0,21747 | 1,80289 | 0,84769 | 0,36953 | 0,12978 | 1,34700 | 4,959 | 55,10 |
| 23 | DE | differential evolution | 0,95044 | 0,61674 | 0,30308 | 1,87026 | 0,95317 | 0,78896 | 0,16652 | 1,90865 | 0,78667 | 0,36033 | 0,02953 | 1,17653 | 4,955 | 55,06 |
| 24 | SRA | successful restaurateur algorithm (joo) | 0,96883 | 0,63455 | 0,29217 | 1,89555 | 0,94637 | 0,55506 | 0,19124 | 1,69267 | 0,74923 | 0,44031 | 0,12526 | 1,31480 | 4,903 | 54,48 |
| 25 | BO | bonobo_optimizer | 0,77565 | 0,63805 | 0,32908 | 1,74278 | 0,88088 | 0,76344 | 0,25573 | 1,90005 | 0,61077 | 0,49846 | 0,14246 | 1,25169 | 4,895 | 54,38 |
| 26 | CRO | chemical reaction optimisation | 0,94629 | 0,66112 | 0,29853 | 1,90593 | 0,87906 | 0,58422 | 0,21146 | 1,67473 | 0,75846 | 0,42646 | 0,12686 | 1,31178 | 4,892 | 54,36 |
| 27 | BIO | blood inheritance optimization (joo) | 0,81568 | 0,65336 | 0,30877 | 1,77781 | 0,89937 | 0,65319 | 0,21760 | 1,77016 | 0,67846 | 0,47631 | 0,13902 | 1,29378 | 4,842 | 53,80 |
| 28 | DOA | dream_optimization_algorithm | 0,85556 | 0,70085 | 0,37280 | 1,92921 | 0,73421 | 0,48905 | 0,24147 | 1,46473 | 0,77231 | 0,47354 | 0,18561 | 1,43146 | 4,825 | 53,62 |
| 29 | BSA | bird swarm algorithm | 0,89306 | 0,64900 | 0,26250 | 1,80455 | 0,92420 | 0,71121 | 0,24939 | 1,88479 | 0,69385 | 0,32615 | 0,10012 | 1,12012 | 4,809 | 53,44 |
| 30 | DEA | dolphin_echolocation_algorithm | 0,75995 | 0,67572 | 0,34171 | 1,77738 | 0,89582 | 0,64223 | 0,23941 | 1,77746 | 0,61538 | 0,44031 | 0,15115 | 1,20684 | 4,762 | 52,91 |
| 31 | HS | harmony search | 0,86509 | 0,68782 | 0,32527 | 1,87818 | 0,99999 | 0,68002 | 0,09590 | 1,77592 | 0,62000 | 0,42267 | 0,05458 | 1,09725 | 4,751 | 52,79 |
| 32 | SSG | saplings sowing and growing | 0,77839 | 0,64925 | 0,39543 | 1,82308 | 0,85973 | 0,62467 | 0,17429 | 1,65869 | 0,64667 | 0,44133 | 0,10598 | 1,19398 | 4,676 | 51,95 |
| 33 | BCOm | bacterial chemotaxis optimization M | 0,75953 | 0,62268 | 0,31483 | 1,69704 | 0,89378 | 0,61339 | 0,22542 | 1,73259 | 0,65385 | 0,42092 | 0,14435 | 1,21912 | 4,649 | 51,65 |
| 34 | ABO | african buffalo optimization | 0,83337 | 0,62247 | 0,29964 | 1,75548 | 0,92170 | 0,58618 | 0,19723 | 1,70511 | 0,61000 | 0,43154 | 0,13225 | 1,17378 | 4,634 | 51,49 |
| 35 | (PO)ES | (PO) evolution strategies | 0,79025 | 0,62647 | 0,42935 | 1,84606 | 0,87616 | 0,60943 | 0,19591 | 1,68151 | 0,59000 | 0,37933 | 0,11322 | 1,08255 | 4,610 | 51,22 |
| 36 | FBA | fractal-based Algorithm | 0,79000 | 0,65134 | 0,28965 | 1,73099 | 0,87158 | 0,56823 | 0,18877 | 1,62858 | 0,61077 | 0,46062 | 0,12398 | 1,19537 | 4,555 | 50,61 |
| 37 | TSm | tabu search M | 0,87795 | 0,61431 | 0,29104 | 1,78330 | 0,92885 | 0,51844 | 0,19054 | 1,63783 | 0,61077 | 0,38215 | 0,12157 | 1,11449 | 4,536 | 50,40 |
| 38 | BSO | brain storm optimization | 0,93736 | 0,57616 | 0,29688 | 1,81041 | 0,93131 | 0,55866 | 0,23537 | 1,72534 | 0,55231 | 0,29077 | 0,11914 | 0,96222 | 4,498 | 49,98 |
| 39 | WOAm | wale optimization algorithm M | 0,84521 | 0,56298 | 0,26263 | 1,67081 | 0,93100 | 0,52278 | 0,16365 | 1,61743 | 0,66308 | 0,41138 | 0,11357 | 1,18803 | 4,476 | 49,74 |
| 40 | AEFA | artificial electric field algorithm | 0,87700 | 0,61753 | 0,25235 | 1,74688 | 0,92729 | 0,72698 | 0,18064 | 1,83490 | 0,66615 | 0,11631 | 0,09508 | 0,87754 | 4,459 | 49,55 |
| 41 | AEO | artificial ecosystem-based optimization algorithm | 0,91380 | 0,46713 | 0,26470 | 1,64563 | 0,90223 | 0,43705 | 0,21400 | 1,55327 | 0,66154 | 0,30800 | 0,28563 | 1,25517 | 4,454 | 49,49 |
| 42 | CAm | camel algorithm M | 0,78684 | 0,56042 | 0,35133 | 1,69859 | 0,82772 | 0,56041 | 0,24336 | 1,63149 | 0,64846 | 0,33092 | 0,13418 | 1,11356 | 4,444 | 49,37 |
| 43 | ACOm | ant colony optimization M | 0,88190 | 0,66127 | 0,30377 | 1,84693 | 0,85873 | 0,58680 | 0,15051 | 1,59604 | 0,59667 | 0,37333 | 0,02472 | 0,99472 | 4,438 | 49,31 |
| 44 | CMAES | covariance_matrix_adaptation_evolution_strategy | 0,76258 | 0,72089 | 0,00000 | 1,48347 | 0,82056 | 0,79616 | 0,00000 | 1,61672 | 0,75846 | 0,49077 | 0,00000 | 1,24923 | 4,349 | 48,33 |
| 45 | DA_duelist | duelist_algorithm | 0,92782 | 0,53778 | 0,27792 | 1,74352 | 0,86957 | 0,47536 | 0,18193 | 1,52686 | 0,62153 | 0,33569 | 0,11715 | 1,07437 | 4,345 | 48,28 |
| RW | random walk | 0,48754 | 0,32159 | 0,25781 | 1,06694 | 0,37554 | 0,21944 | 0,15877 | 0,75375 | 0,27969 | 0,14917 | 0,09847 | 0,52734 | 2,348 | 26,09 | |
Выводы
Bonobo Optimizer демонстрирует стабильно хорошую производительность, набирая 54% по результатам тестирования и занимая 25 место из 45 лучших популяционных алгоритмов, что характеризует его как надежный универсальный метод оптимизации.
Алгоритм показывает свои лучшие результаты на задачах средней размерности, где проявляется эффективность его основных механизмов, таких как fission-fusion. Социальная структура создает временные подгруппы размером от 2 до максимального значения, определяемого адаптивно, три стратегии спаривания обеспечивают баланс между эксплуатацией найденных решений посредством движения к альфа-бонобо и разведкой новых областей через внегрупповое спаривание с прыжками к границам популяции.
Критически важный механизм acceptance criteria принимает новые решения только если они лучше предыдущих или случайно, с малой вероятностью, что предотвращает деградацию популяции и является абсолютно необходимым условием работоспособности алгоритма.
Адаптивная система положительных и отрицательных фаз автоматически переключает алгоритм между режимами exploitation когда найдено улучшение, увеличивая вероятность рандомизированного спаривания до единицы и размер подгрупп, и exploration, когда происходит застой, уменьшая рандомизированное спаривание до нуля и увеличивая внегрупповое до 50 процентов, что создает саморегулирующуюся систему не требующую ручной настройки баланса исследования и эксплуатации.
На малых размерностях наблюдается повышенный разброс результатов, что объясняется избыточностью механизмов алгоритма для простых задач, где популяция из 30 агентов с тремя различными стратегиями спаривания создает слишком много вариативности и случайности, приводя к нестабильной сходимости, в то время как на средних размерностях эта же сложность становится преимуществом, позволяя эффективно исследовать многомерное пространство поиска через комбинацию локального поиска в подгруппах и глобальных прыжков через внегрупповое спаривание.
Выбор лучшего партнера из временной подгруппы по фитнесу вместо случайного выбора направляет поиск к перспективным областям, использование коэффициентов scab равного 1.25 и scsb равного 1.3 превышающих единицу позволяет агентам перепрыгивать через текущие лучшие решения исследуя области за ними, что полезно для выхода из локальных оптимумов, а направленный флаг, определяемый сравнением фитнесов текущего агента и партнера создает адаптивное поведение, где сильные агенты исследуют, отдаляясь от слабых партнеров, а слабые эксплуатируют, приближаясь к сильным.
Алгоритм хорошо подходит для задач оптимизации средней сложности, где требуется баланс между надежностью и производительностью без необходимости тонкой настройки параметров, благодаря встроенной адаптации, однако для очень простых задач малой размерности или критичных по производительности применений, где важна максимальная стабильность результатов могут быть предпочтительнее более специализированные алгоритмы с меньшей внутренней вариативностью.

Рисунок 2. Цветовая градация алгоритмов по соответствующим тестам

Рисунок 3. Гистограмма результатов тестирования алгоритмов (по шкале от 0 до 100, чем больше, тем лучше, где 100 — максимально возможный теоретический результат, в архиве скрипт для расчета рейтинговой таблицы)
Плюсы и минусы алгоритма BO:
Плюсы:
- Эффективен на задачах средней и высокой размерности.
Минусы:
- Много внешних параметров.
- Застревает на функциях малой размерности.
К статье прикреплён архив с актуальными версиями кодов алгоритмов. Автор статьи не несёт ответственности за абсолютную точность в описании канонических алгоритмов, во многие из них были внесены изменения для улучшения поисковых возможностей. Выводы и суждения, представленные в статьях, основываются на результатах проведённых экспериментов.
Программы, используемые в статье
| # | Имя | Тип | Описание |
|---|---|---|---|
| 1 | #C_AO.mqh | Включаемый файл | Родительский класс популяционных алгоритмов оптимизации |
| 2 | #C_AO_enum.mqh | Включаемый файл | Перечисление популяционных алгоритмов оптимизации |
| 3 | TestFunctions.mqh | Включаемый файл | Библиотека тестовых функций |
| 4 | TestStandFunctions.mqh | Включаемый файл | Библиотека функций тестового стенда |
| 5 | Utilities.mqh | Включаемый файл | Библиотека вспомогательных функций |
| 6 | CalculationTestResults.mqh | Включаемый файл | Скрипт для расчета результатов в сравнительную таблицу |
| 7 | Testing AOs.mq5 | Скрипт | Единый испытательный стенд для всех популяционных алгоритмов оптимизации |
| 8 | Simple use of population optimization algorithms.mq5 | Скрипт | Простой пример использования популяционных алгоритмов оптимизации без визуализации |
| 9 | Test_AO_BO.mq5 | Скрипт | Испытательный стенд для BO |
Предупреждение: все права на данные материалы принадлежат MetaQuotes Ltd. Полная или частичная перепечатка запрещена.
Данная статья написана пользователем сайта и отражает его личную точку зрения. Компания MetaQuotes Ltd не несет ответственности за достоверность представленной информации, а также за возможные последствия использования описанных решений, стратегий или рекомендаций.
Моделирование рынка (Часть 09): Сокеты (III)
Индикатор тепловой карты рынка на основе плотности простых чисел
Нейросети в трейдинге: Спайковая архитектура пространственно-временного анализа рынка (Энкодер)
Моделирование рынка (Часть 08): Сокеты (II)
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования