Оптимизатор на основе экологического цикла — Ecological Cycle Optimizer (ECO)
Содержание
Введение
Природа на протяжении миллиардов лет оттачивала механизмы выживания, адаптации и самоорганизации живых систем. Эти механизмы неизменно привлекают внимание исследователей в области вычислительного интеллекта, стремящихся перенести эффективные природные стратегии в алгоритмы оптимизации. Генетические алгоритмы черпают вдохновение из эволюции, роевые методы — из коллективного поведения насекомых и птиц, а алгоритмы иммунных систем моделируют защитные механизмы организма.
Однако до недавнего времени практически без внимания оставался один из фундаментальных процессов биосферы — экологический цикл, представляющий собой непрерывный круговорот энергии и вещества между различными трофическими уровнями экосистемы. В любой устойчивой экосистеме присутствует сложная сеть взаимодействий: продуценты (растения) преобразуют солнечную энергию в органическое вещество, травоядные потребляют продуцентов, хищники охотятся на травоядных, всеядные занимают промежуточные ниши, а редуценты замыкают цикл, разлагая органику и возвращая питательные вещества в среду.
Эта элегантная система баланса и взаимозависимости легла в основу алгоритма Ecological Cycle Optimizer (ECO), представленного в 2025 году группой китайских исследователей под руководством Boyu Ma и Jiaxiao Shi. Авторы предложили рассматривать популяцию поисковых агентов как экосистему, где каждая группа особей выполняет свою роль в общем цикле оптимизации.
Продуценты в алгоритме ECO — это элитные решения, накапливающие «энергию» в виде высокого значения целевой функции. Травоядные стремятся к продуцентам, перенимая их успешные характеристики. Плотоядные, в свою очередь, ориентируются на травоядных, а всеядные способны извлекать информацию из всех трофических уровней. Завершает цикл стадия декомпозиции, на которой все решения подвергаются трансформации — подобно тому, как редуценты перерабатывают органическое вещество, создавая основу для нового роста.
Ключевой особенностью ECO является адаптивный коэффициент хищничества, который регулирует интенсивность взаимодействия между группами. На ранних этапах оптимизации этот коэффициент высок, что способствует активному обмену информацией и глобальному исследованию пространства поиска. По мере приближения к оптимуму, коэффициент снижается, переводя алгоритм в режим локальной эксплуатации найденных перспективных областей.
Три режима декомпозиции — оптимальный, локальный случайный и глобальный случайный — обеспечивают разнообразие поисковых стратегий и помогают избегать преждевременной сходимости. Жадный отбор на этапе ревизии гарантирует, что качество решений не ухудшается от итерации к итерации.
В данной статье мы подробно рассмотрим математическую модель алгоритма ECO, проанализируем роль каждого компонента экологического цикла в процессе оптимизации и представим результаты тестирования на стандартном наборе функций, которые позволят оценить эффективность алгоритма и его место среди других метаэвристических методов.
Реализация алгоритма
Алгоритм ECO моделирует круговорот энергии в природной экосистеме. Представьте луг, на котором растут травы (продуценты), пасутся зайцы (травоядные), охотятся лисы (плотоядные), кормятся медведи (всеядные), а бактерии и грибы (редуценты) перерабатывают органику. Каждая группа выполняет свою роль, и вместе они образуют устойчивую систему.
В алгоритме ECO популяция поисковых агентов разделена на аналогичные группы. Каждый агент — это потенциальное решение задачи оптимизации, а его «приспособленность» (фитнес) — значение целевой функции.
Популяция делится на четыре группы в следующих пропорциях:
| Группа | Доля | Роль в алгоритме |
|---|---|---|
| Продуценты (Producers) | 20% | Лучшие решения, источник информации |
| Травоядные (Herbivores) | 30% | Следуют за продуцентами |
| Плотоядные (Carnivores) | 30% | Следуют за травоядными |
| Всеядные (Omnivores) | 20% | Используют информацию от всех групп |
Пример: при размере популяции 50 агентов получаем: 10 продуцентов, 15 травоядных, 15 плотоядных и 10 всеядных.
Ключевой параметр алгоритма — коэффициент хищничества G, который управляет интенсивностью перемещения агентов: G = 1 + 2 × rand × exp(-9 × (t/T)³) × sign, где: t - текущая итерация; T - максимальное число итераций; rand - случайное число от 0 до 1; sign - случайно выбранный знак (+1 или -1).
В начале оптимизации (t ≈ 0) экспонента близка к 1, и коэффициент G может достигать значений от -1 до 3. Агенты совершают большие прыжки, исследуя пространство поиска. К концу оптимизации (t → T) экспонента стремится к 0, G - приближается к 1, и движения становятся более осторожными - алгоритм переходит к локальному уточнению.
Пример: итерация 10 из 1000: G ≈ 1 + 2 × 0.7 × 0.99 × (+1) = 2.39 — агент может «перепрыгнуть» через цель; итерация 900 из 1000: G ≈ 1 + 2 × 0.7 × 0.001 × (+1) = 1.001 — агент движется почти точно к цели.
Стратегия продуцентов. Продуценты — это элита популяции. После каждой итерации вся популяция сортируется по значению фитнеса, и лучшие 20% автоматически становятся продуцентами.
Например, если у нас 50 агентов с фитнесами от 10 до 100, то 10 агентов с наивысшими значениями (скажем, от 85 до 100) станут продуцентами. Они не перемещаются активно — их задача служить «маяками» для остальных групп.
Стратегия травоядных. Травоядные движутся в направлении продуцентов, пытаясь «поедать» хорошие решения. Для каждого травоядного методом рулеточного отбора выбираются 3 продуцента (лучшие имеют больше шансов быть выбранными). Вычисляется новая позиция: новая позиция = текущая + G × (r₁×(prod₁ - текущая) + r₂×(prod₂ - текущая) + r₃×(prod₃ - текущая)), где r₁, r₂, r₃ - случайные числа от 0 до 1.
Пример для одномерного пространства: травоядный находится в позиции x = 20. Выбраны продуценты в позициях: 80, 90, 75. Случайные числа: r₁ = 0.6, r₂ = 0.3, r₃ = 0.4. Коэффициент G = 1.5. Вычисляем: движение = 0.6×(80-20) + 0.3×(90-20) + 0.4×(75-20) = 36 + 21 + 22 = 79, тогда новая позиция будет = 20 + 1.5 × 79 = 138.5. Травоядный переместился в направлении продуцентов, причём благодаря G > 1 он «перепрыгнул» дальше среднего положения целей.
Стратегия плотоядных. Плотоядные охотятся на травоядных по аналогичной схеме: выбираются 3 травоядных методом рулетки, плотоядный движется в их направлении с учётом коэффициента G. Травоядные уже сместились к хорошим областям, следуя за продуцентами. Плотоядные «охотятся» в этих же перспективных зонах, но с некоторым смещением, что помогает исследовать окрестности найденных решений.
Стратегия всеядных. Всеядные — универсальные исследователи. Они получают информацию от всех групп: выбирается 1 продуцент, 1 травоядный и 2 плотоядных. Всеядный движется к комбинации этих целей: новая позиция = текущая + G × (r₁×(prod - текущая) + r₂×(herb - текущая) + r₃×(carn₁ - текущая) + r₄×(carn₂ - текущая)). Всеядные могут обнаружить связи между разными областями поиска, которые другие группы могли пропустить.
Рулеточный отбор. При выборе целей для движения используется рулеточный отбор — агенты с лучшим фитнесом имеют больше шансов быть выбранными. Например, три продуцента с фитнесами 100, 80, 60. Вероятности выбора (после нормализации): продуцент 1: 100/240 = 41.7%; продуцент 2: 80/240 = 33.3%; продуцент 3: 60/240 = 25.0%. Это не означает, что худший никогда не будет выбран — он просто выбирается реже. Такой механизм сохраняет разнообразие поиска.
Стратегия декомпозиции. После движения всех групп наступает ключевая фаза — декомпозиция. Подобно тому, как редуценты перерабатывают органику в природе, алгоритм трансформирует все решения одним из трёх способов:
Режим 1: оптимальная декомпозиция (вероятность 50%). Агент смещается к окрестности лучшего решения: окрестность = лучший × rand_vector; новая позиция = окрестность + coef × (окрестность - текущая), где coef ∈ [-0 .2, 0.2] - это небольшое случайное смещение.
Пример, лучшая позиция: [100, 50]; текущая позиция: [70, 40]; rand_vector = [0.9, 0.8]; coef = 0.1; окрестность = [100×0.9, 50×0.8] = [90, 40]; новая позиция тогда рассчитается [90 + 0.1×(90-70), 40 + 0.1×(40-40)] = [92, 40]. Агент переместился ближе к лучшему решению с небольшой вариацией.
Режим 2: локальная случайная декомпозиция (вероятность 25%), агент делает случайный шаг в произвольном направлении, но размер шага пропорционален расстоянию до лучшего решения: расстояние = ||лучший - текущий||, случайное направление = нормализованный случайный вектор, тогда новая позиция = текущая + rand × расстояние × случайное направление. Смысл действий, если агент далеко от лучшего — он делает большой случайный шаг. Если близко — маленький. Это позволяет исследовать пропорционально «неизведанности» области.
Режим 3: глобальная случайная декомпозиция (вероятность 25%). Агент может переместиться в совершенно новую область пространства: H = (1 - t/(1.5T))^(5t/T) × cos(π × rand); новая позиция = weight × текущая + (1 - weight) × случайное блуждание. Коэффициент "H" уменьшается со временем, поэтому в начале оптимизации возможны большие прыжки, а к концу — только локальные корректировки. Почему сделано три режима: комбинация обеспечивает баланс между эксплуатацией (режим 1), локальным исследованием (режим 2) и глобальным исследованием (режим 3).
Ревизия (жадный отбор). После декомпозиции вычисляется фитнес новых позиций и применяется жадный отбор: если новый фитнес > старый, тогда фитнес → принять новую позицию; иначе → вернуться к старой позиции.
Например: агент был в позиции x = 50 с фитнесом 80, после декомпозиции переместился в x = 65 с фитнесом 75. Новый фитнес (75) хуже старого (80) → агент возвращается в x = 50. Этот механизм гарантирует, что качество лучшего найденного решения никогда не ухудшается. Алгоритм может экспериментировать с рискованными перемещениями, зная, что неудачные попытки будут отменены.
Обработка границ. Если агент выходит за пределы допустимой области поиска, его позиция заменяется случайным значением внутри границ: если позиция < минимум или позиция > максимум: позиция = случайное значение(минимум, максимум). Такой подход (в отличие от простого «отражения» от границы) помогает сохранить разнообразие популяции.
Подведём итог. Каждая итерация алгоритма ECO состоит из следующих шагов:
- Обновить коэффициент G — он уменьшается со временем
- Отсортировать популяцию по фитнесу
- Определить продуцентов — лучшие 20% после сортировки
- Переместить травоядных к продуцентам
- Переместить плотоядных к травоядным
- Переместить всеядных ко всем группам
- Сохранить текущие позиции для возможного отката
- Выполнить декомпозицию всех агентов (один из трёх режимов)
- Вычислить фитнес новых позиций
- Провести ревизию — откатить неудачные перемещения

Рисунок 1. Схема работы методов внутри алгоритма.
Диаграмма показывает группы организмов:
Producers (зелёный) — лучшие решения после сортировки, к ним стремятся травоядные
Herbivores (светло-зелёный) — следуют за продуцентами, являются целью для плотоядных
Carnivores (красный) — следуют за травоядными
Omnivores (оранжевый) — получают информацию от всех групп
Decomposers (коричневый) — трансформируют все решения тремя способами
Центральный элемент Sorting (синий) — сортировка по фитнесу, лучшие становятся продуцентами
Потоки взаимодействия:
Сплошные стрелки — направление притяжения (attract)
Пунктирные стрелки — все решения проходят через декомпозицию
Синие стрелки — цикл через ревизию и сортировку
Информационные блоки:
Формула коэффициента хищничества G
Пропорции групп в популяции (20/30/30/20%)
Три режима декомпозиции с вероятностями
ИНИЦИАЛИЗАЦИЯ
Определить размеры групп на основе заданных пропорций:
Продуценты (producers): 20% популяции
Травоядные (herbivores): 30% популяции
Плотоядные (carnivores): 30% популяции
Всеядные (omnivores): 20% популяции
Случайно инициализировать позиции всех агентов в пространстве поиска
Сохранить начальные позиции каждого агента как "предыдущие" для последующего сравнения
Вычислить фитнес всех агентов
ОСНОВНОЙ ЦИКЛ ОПТИМИЗАЦИИ
Для каждой итерации t от 1 до MaxIterations:
Шаг 1: Обновление коэффициента хищничества G
Для каждой координаты вычислить коэффициент хищничества:
G[c] = 1 + 2 × rand × exp(-9 × (t/T)³) × случайный_знак(±1), где T — максимальное число итераций.
Коэффициент G уменьшается со временем, что обеспечивает переход от глобального исследования к локальной эксплуатации.
Шаг 2: Стратегия продуцентов (отбор лучших)
Отсортировать всю популяцию по убыванию фитнеса
Лучшие агенты автоматически становятся продуцентами (занимают первые позиции в отсортированном массиве)
Обновить глобально лучшее решение если найдено улучшение
Шаг 3: Стратегия травоядных (движение к продуцентам)
Для каждого травоядного агента i:
Выбрать 3 продуцента методом рулеточного отбора (вероятность пропорциональна фитнесу)
Сгенерировать 3 случайных коэффициента r₁, r₂, r₃ ∈ [0, 1]
Вычислить новую позицию:
новая_позиция = текущая_позиция + G × (r₁×(продуцент₁ - текущая) + r₂×(продуцент₂ - текущая) + r₃×(продуцент₃ - текущая))
Шаг 4: Стратегия плотоядных (движение к травоядным)
Для каждого плотоядного агента i:
Выбрать 3 травоядных методом рулеточного отбора
Сгенерировать 3 случайных коэффициента r₁, r₂, r₃ ∈ [0, 1]
Вычислить новую позицию:
новая_позиция = текущая_позиция + G × (r₁×(травоядный₁ - текущая) + r₂×(травоядный₂ - текущая) + r₃×(травоядный₃ - текущая))
Шаг 5: Стратегия всеядных (движение ко всем группам)
Для каждого всеядного агента i:
Выбрать по рулетке: 1 продуцента, 1 травоядного, 2 плотоядных
Сгенерировать 4 случайных коэффициента r₁, r₂, r₃, r₄ ∈ [0, 1]
Вычислить новую позицию:
новая_позиция = текущая_позиция + G × (r₁×(продуцент - текущая) + r₂×(травоядный - текущая) + r₃×(плотоядный₁ - текущая) + r₄×(плотоядный₂ - текущая))
Шаг 6: Сохранение позиций перед декомпозицией
Для всех агентов сохранить текущие позиции и фитнес как "предыдущие" для последующего сравнения в стадии ревизии.
Шаг 7: Стратегия декомпозиторов (три режима)
Для каждого агента i в популяции выбрать случайно один из трёх режимов:
Режим A: Оптимальная декомпозиция (вероятность 50%)
Сгенерировать коэффициент: coef = 0.4 × rand - 0.2 (диапазон [-0.2, 0.2])
Для каждой координаты:
окрестность_лучшего = позиция_лучшего[c] × rand[c]
новая_позиция[c] = окрестность_лучшего + coef × (окрестность_лучшего - текущая[c])
Режим B: Локальная случайная декомпозиция (вероятность 25%)
Вычислить расстояние до лучшего агента: dist = ||лучший - текущий||
Сгенерировать случайный единичный вектор направления
Вычислить новую позицию:
новая_позиция = текущая_позиция + rand × dist × единичный_вектор
Режим C: Глобальная случайная декомпозиция (вероятность 25%)
Вычислить затухающий коэффициент: H = (1 - t/(1.5×T))^(5t/T) × cos(π × rand)
Найти минимальную ширину диапазона поиска
Вычислить случайное блуждание: rand_walk = (2/3) × H × rand × min(rangeMin - rangeMax)
Вычислить новую позицию:
weight = rand
новая_позиция = weight × текущая_позиция + (1 - weight) × rand_walk
Шаг 8: Проверка границ
Для каждого агента и каждой координаты:
Если позиция вышла за границы — присвоить случайное значение в допустимом диапазоне
Применить дискретизацию согласно шагу поиска
Шаг 9: Вычисление фитнеса
Вычислить значение целевой функции для всех агентов.
Шаг 10: Ревизия (жадный отбор)
Для каждого агента i:
Сравнить новый фитнес с предыдущим
Если новый фитнес хуже или равен — откатить позицию и фитнес к предыдущим значениям
Обновить глобально лучшее решение если найдено улучшение
ЗАВЕРШЕНИЕ
Вернуть глобально лучшее найденное решение и его фитнес.
Класс наследуется от базового класса "C_AO". Конфигурационные параметры:
- Размер популяции (popSize) — определяет общее количество агентов в моделируемой экосистеме.
- Соотношение потребителей, доля организмов:
- ratioProd (продуценты) производящих пищу (например, растения).
- ratioHerb (травоядные) питающихся продуцентами.
- ratioCarn (хищники) питающихся другими животными.
- ratioOmni (всеядные) питающихся как растениями, так и животными.
Состояние и внутренние переменные:
- maxIter и currIter отслеживают максимальное количество итераций (шагов симуляции) и текущую итерацию.
- numProd, numHerb, numCarn, numOmni: хранят фактическое количество агентов каждого типа (продуцентов, травоядных, хищников, всеядных) на основе popSize и соотношений.
- prodEnd, herbEnd, carnEnd: указывают на индексы в неком общем массиве агентов, разделяя их по экологическим группам.
- huntCoef: массив коэффициентов, предполагающий модель "хищничества" или взаимодействия между хищниками и их жертвами.
- aT: временный массив, используемый для сортировки или временного хранения агентов.
Методы:
- SetParams — позволяет обновить внутренние переменные "popSize", "ratioProd", "ratioHerb", "ratioCarn", "ratioOmni" на основе значений, установленных в структуре "params".
- Init — инициализация, принимает диапазоны и шаги для параметров, а также количество эпох. Вероятно, настраивает начальное состояние экосистемы.
- Moving — моделирует перемещение или поведение агентов в течение одной итерации.
- Revision — выполняет "пересмотр" или обновление состояния экосистемы после одного шага.
- SelectFromGroup (приватный) — вспомогательный метод для выбора определенного количества агентов из указанной группы (диапазона индексов).
- VectorNorm (приватный) — вспомогательный метод для вычисления некоторой нормы или расстояния между двумя агентами.
Класс C_AO_ECOc представляет собой инструментарий для симуляции динамики экосистемы. Он позволяет моделировать различные типы организмов (продуценты, потребители разных уровней) и их взаимоотношения, включая потребление пищи и хищничество. Параметры позволяют гибко настраивать состав популяции и поведение агентов, а методы Moving и Revision реализуют логику симуляции.
//———————————————————————————————————————————————————————————————————— class C_AO_ECOc : public C_AO { public: ~C_AO_ECOc () { }2 C_AO_ECOc () { ao_name = "ECOc"; ao_desc = "Ecological Cycle Optimizer"; ao_link = "https://www.mql5.com/ru/articles/20611"; popSize = 50; ratioProd = 0.2; ratioHerb = 0.3; ratioCarn = 0.3; ratioOmni = 0.2; ArrayResize (params, 5); params [0].name = "popSize"; params [0].val = popSize; params [1].name = "ratioProd"; params [1].val = ratioProd; params [2].name = "ratioHerb"; params [2].val = ratioHerb; params [3].name = "ratioCarn"; params [3].val = ratioCarn; params [4].name = "ratioOmni"; params [4].val = ratioOmni; } void SetParams () { popSize = (int)params [0].val; ratioProd = params [1].val; ratioHerb = params [2].val; ratioCarn = params [3].val; ratioOmni = params [4].val; } bool Init (const double &rangeMinP [], const double &rangeMaxP [], const double &rangeStepP [], const int epochsP); void Moving (); void Revision (); //------------------------------------------------------------------ double ratioProd; double ratioHerb; double ratioCarn; double ratioOmni; private: //————————————————————————————————————————————————————————— int maxIter; int currIter; int numProd; int numHerb; int numCarn; int numOmni; // Индексы групп в общем массиве a[] int prodEnd; int herbEnd; int carnEnd; // Коэффициент хищничества double huntCoef []; // Временный массив для сортировки S_AO_Agent aT []; // Вспомогательные методы void SelectFromGroup (int startIdx, int endIdx, int selCount, int &indices []); double VectorNorm (int idx1, int idx2); }; //————————————————————————————————————————————————————————————————————
Метод "Init" выполняет инициализацию объекта класса C_AO_ECOc для начала работы оптимизатора. Первым делом вызывается метод "StandardInit", которому передаются параметры "rangeMinP", "rangeMaxP" и "rangeStepP". Этот метод устанавливает границы и шаги для координат в пространстве поиска. Если стандартная инициализация не удалась, метод возвращает "false".
Метод подготавливает оптимизатор к работе, настраивая начальные параметры, распределяя агентов по экологическим группам и выделяя необходимую память. Он служит точкой входа для запуска алгоритма оптимизации.
//———————————————————————————————————————————————————————————————————— bool C_AO_ECOc::Init (const double &rangeMinP [], const double &rangeMaxP [], const double &rangeStepP [], const int epochsP) { if (!StandardInit (rangeMinP, rangeMaxP, rangeStepP)) return false; //------------------------------------------------------------------ maxIter = epochsP; currIter = 0; // Вычисление размеров групп numProd = (int)MathRound (popSize * ratioProd); numHerb = (int)MathRound (popSize * ratioHerb); numCarn = (int)MathRound (popSize * ratioCarn); numOmni = popSize - numProd - numHerb - numCarn; if (numProd < 1) numProd = 1; if (numHerb < 1) numHerb = 1; if (numCarn < 1) numCarn = 1; if (numOmni < 1) numOmni = 1; // Корректировка numOmni если сумма не равна popSize numOmni = popSize - numProd - numHerb - numCarn; // Индексы групп (начало группы = конец предыдущей) prodEnd = numProd; herbEnd = prodEnd + numHerb; carnEnd = herbEnd + numCarn; // Выделяем память ArrayResize (huntCoef, coords); ArrayResize (aT, popSize); ArrayResize (u.roulette, popSize); for (int i = 0; i < popSize; i++) aT [i].Init (coords); return true; } //————————————————————————————————————————————————————————————————————
Метод "Moving" моделирует эволюцию и поведение агентов в экосистеме на протяжении одной итерации алгоритма. Он разделен на несколько логических блоков, каждый из которых отражает определенную "стратегию".
Если алгоритм находится на первой итерации, то происходит случайная инициализация позиций всех агентов в пределах заданных диапазонов и с учетом дискретизации.
Увеличивается счетчик текущих итераций. Вычисляются относительные значения текущей и максимальной итераций. Для каждой координаты вычисляется новый коэффициент хищничества. Этот коэффициент динамически меняется в зависимости от стадии оптимизации и случайного фактора. Он может быть как положительным, так и отрицательным.
Стратегия продуцентов. Весь массив агентов "a" сортируется по значению фитнеса "f" в порядке убывания. Это делается с помощью вспомогательного метода "u.Sorting", который использует временный массив "aT". Если лучший агент после сортировки имеет лучший фитнес, чем текущий глобальный максимум "fB", то "fB" и лучшая позиция "cB" обновляются.
Стратегия травоядных (движение к продуцентам). Выбираются три случайных продуцента из группы продуцентов. Каждый травоядный агент (a[i] из группы "prodEnd" до "herbEnd") перемещается. Его новое положение вычисляется как комбинация его текущего положения и взвешенной суммы позиций выбранных продуцентов. Весовые коэффициенты "r1", "r2", "r3" случайны, а общий вектор движения умножается на "huntCoef[c]". Это имитирует поиск и потребление "пищи" (продуцентов).
Стратегия плотоядных (движение к травоядным). Аналогично травоядным, выбираются три случайных травоядных агента "selHerb". Каждый хищник (a[i] из группы "herbEnd" до "carnEnd") перемещается, стремясь к позициям выбранных травоядных. Формула движения похожа на стратегию травоядных, но направлена на другую группу.
Стратегия всеядных (движение ко всем группам). Всеядные агенты (a[i] с "carnEnd" до "popSize") также перемещаются. Их движение является комбинацией стремления к продуценту, одному травоядному и двум хищникам. Это отражает их способность питаться разнообразными источниками.
Стратегия декомпозиторов (поиск решения). Перед применением стратегии декомпозиторов, текущие позиции и фитнес всех агентов сохраняются в "cP" и "fP" соответственно.
- Оптимальная декомпозиция (rnd < 0.5) — агент смещается от своего предыдущего положения к позиции, определяемой комбинацией случайного коэффициента и положения лучшего агента.
- Локальная случайная декомпозиция (0.5 <= rnd < 0.75) — агент перемещается в направлении, заданном случайным единичным вектором, на расстояние, которое зависит от предыдущего положения агента, а также расстояния до лучшего агента и случайного множителя.
- Глобальная случайная декомпозиция (rnd >= 0.75) — агент перемещается на основе взвешенной комбинации его предыдущего положения и некоторого случайного "блуждания", величина которого зависит от стадии оптимизации (t/T) и случайных множителей. Этот тип движения становится менее активным по мере приближения к концу оптимизации.
После применения любой из стратегий перемещения (травоядные, хищники, всеядные, декомпозиторы), для каждого агента проверяется, не вышли ли его новые координаты за пределы допустимых диапазонов. Если это произошло, его позиция случайно генерируется заново в пределах диапазона и затем дискретизируется с помощью "u.SeInDiSp" в соответствии с заданным шагом.
В целом, метод Moving выполняет следующую логику:
Первый шаг: случайная инициализация всей популяции.
Последующие шаги:
- динамически изменяет "силу" хищничества,
- сортирует агентов по качеству решения, обновляя лучший найденный результат,
- имитирует поиск пищи и хищничество, где каждая группа (травоядные, хищники, всеядные) "стремится" к агентам из нижележащих или смежных групп,
- применяет различные стратегии "декомпозиции" (по сути, методы поиска и улучшения решения), которые могут быть как более направленными (к лучшему агенту), так и более случайными, с разной степенью глобальности и активности в зависимости от стадии оптимизации,
- принудительно удерживает всех агентов в заданных границах поиска.
Данный метод моделирует экосистему, где различные "виды" (группы агентов) взаимодействуют, а также применяется механизм оптимизации (стратегии декомпозиторов) для поиска наилучшего решения.
//———————————————————————————————————————————————————————————————————— void C_AO_ECOc::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]); // Сохраняем в cP для сравнения в Revision a [i].cP [c] = a [i].c [c]; } a [i].f = -DBL_MAX; a [i].fP = -DBL_MAX; } revision = true; return; } //------------------------------------------------------------------ currIter++; double t = (double)currIter; double T = (double)maxIter; // Обновление коэффициента хищничества G for (int c = 0; c < coords; c++) { int sign = (u.RNDprobab () < 0.5) ? -1 : 1; huntCoef [c] = 1.0 + 2.0 * u.RNDfromCI (0.0, 1.0) * MathExp (-9.0 * MathPow (t / T, 3)) * sign; } //================================================================== // (1) Стратегия продуцентов - сортировка популяции по фитнесу //================================================================== // Используем готовую сортировку из утилит u.Sorting (a, aT, popSize); // Обновляем лучшее решение if (a [0].f > fB) { fB = a [0].f; ArrayCopy (cB, a [0].c, 0, 0, coords); } //================================================================== // (2) Стратегия травоядных - движение к продуцентам //================================================================== int selProd []; SelectFromGroup (0, prodEnd, 3, selProd); for (int i = prodEnd; i < herbEnd; i++) { double r1 = u.RNDfromCI (0.0, 1.0); double r2 = u.RNDfromCI (0.0, 1.0); double r3 = u.RNDfromCI (0.0, 1.0); for (int c = 0; c < coords; c++) { double move = r1 * (a [selProd [0]].c [c] - a [i].c [c]) + r2 * (a [selProd [1]].c [c] - a [i].c [c]) + r3 * (a [selProd [2]].c [c] - a [i].c [c]); a [i].c [c] = a [i].c [c] + huntCoef [c] * move; } } //================================================================== // (3) Стратегия плотоядных - движение к травоядным //================================================================== int selHerb []; SelectFromGroup (prodEnd, herbEnd, 3, selHerb); for (int i = herbEnd; i < carnEnd; i++) { double r1 = u.RNDfromCI (0.0, 1.0); double r2 = u.RNDfromCI (0.0, 1.0); double r3 = u.RNDfromCI (0.0, 1.0); for (int c = 0; c < coords; c++) { double move = r1 * (a [selHerb [0]].c [c] - a [i].c [c]) + r2 * (a [selHerb [1]].c [c] - a [i].c [c]) + r3 * (a [selHerb [2]].c [c] - a [i].c [c]); a [i].c [c] = a [i].c [c] + huntCoef [c] * move; } } //================================================================== // (4) Стратегия всеядных - движение ко всем группам //================================================================== int selProd1 []; int selHerb1 []; int selCarn2 []; SelectFromGroup (0, prodEnd, 1, selProd1); SelectFromGroup (prodEnd, herbEnd, 1, selHerb1); SelectFromGroup (herbEnd, carnEnd, 2, selCarn2); for (int i = carnEnd; i < popSize; i++) { double r1 = u.RNDfromCI (0.0, 1.0); double r2 = u.RNDfromCI (0.0, 1.0); double r3 = u.RNDfromCI (0.0, 1.0); double r4 = u.RNDfromCI (0.0, 1.0); for (int c = 0; c < coords; c++) { double move = r1 * (a [selProd1 [0]].c [c] - a [i].c [c]) + r2 * (a [selHerb1 [0]].c [c] - a [i].c [c]) + r3 * (a [selCarn2 [0]].c [c] - a [i].c [c]) + r4 * (a [selCarn2 [1]].c [c] - a [i].c [c]); a [i].c [c] = a [i].c [c] + huntCoef [c] * move; } } //================================================================== // (5) Стратегия декомпозиторов //================================================================== // Сохраняем текущие позиции в cP перед декомпозицией for (int i = 0; i < popSize; i++) { for (int c = 0; c < coords; c++) { a [i].cP [c] = a [i].c [c]; } a [i].fP = a [i].f; } // Лучший агент - индекс 0 после сортировки int bestIdx = 0; // Декомпозиция for (int i = 0; i < popSize; i++) { double rnd = u.RNDfromCI (0.0, 1.0); if (rnd < 0.5) { //--- Оптимальная декомпозиция --- double coef = 0.4 * u.RNDfromCI (0.0, 1.0) - 0.2; for (int c = 0; c < coords; c++) { double randC = u.RNDfromCI (0.0, 1.0); double bestNeighbor = a [bestIdx].cP [c] * randC; a [i].c [c] = bestNeighbor + coef * (bestNeighbor - a [i].cP [c]); } } else if (rnd < 0.75) { //--- Локальная случайная декомпозиция --- double dist = VectorNorm (bestIdx, i); // Генерация случайного единичного вектора double randDir []; ArrayResize (randDir, coords); double norm = 0.0; for (int c = 0; c < coords; c++) { randDir [c] = 2.0 * u.RNDfromCI (0.0, 1.0) - 1.0; norm += randDir [c] * randDir [c]; } norm = MathSqrt (norm) + 1e-10; double randMult = u.RNDfromCI (0.0, 1.0); for (int c = 0; c < coords; c++) { randDir [c] /= norm; a [i].c [c] = a [i].cP [c] + randMult * dist * randDir [c]; } } else { //--- Глобальная случайная декомпозиция --- double tRatio = t / (1.5 * T); if (tRatio > 1.0) tRatio = 1.0; double H = MathPow (1.0 - tRatio, 5.0 * t / T) * MathCos (M_PI * u.RNDfromCI (0.0, 1.0)); // min(Low - Up) double minRange = rangeMin [0] - rangeMax [0]; for (int c = 1; c < coords; c++) { double diff = rangeMin [c] - rangeMax [c]; if (diff < minRange) minRange = diff; } double randWalk = (2.0 / 3.0) * H * u.RNDfromCI (0.0, 1.0) * minRange; double weight = u.RNDfromCI (0.0, 1.0); for (int c = 0; c < coords; c++) { a [i].c [c] = weight * a [i].cP [c] + (1.0 - weight) * randWalk; } } // Проверка границ и дискретизация for (int c = 0; c < coords; c++) { if (a [i].c [c] < rangeMin [c] || a [i].c [c] > rangeMax [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" служит для "самокоррекции" популяции. Он гарантирует, что ни один агент не останется с состоянием хуже, чем было до его последнего действия (путем отката). Параллельно он отслеживает и сохраняет лучшее найденное решение во всей популяции за время работы алгоритма. Это классический аспект многих эволюционных алгоритмов, где важно сохранять наилучшие достижения и не принимать ухудшающие шаги.
//———————————————————————————————————————————————————————————————————— void C_AO_ECOc::Revision () { for (int i = 0; i < popSize; i++) { // Если новая позиция хуже - откат к предыдущей if (a [i].f <= a [i].fP) { a [i].f = a [i].fP; ArrayCopy (a [i].c, a [i].cP, 0, 0, coords); } // Обновление лучшего глобального решения if (a [i].f > fB) { fB = a [i].f; ArrayCopy (cB, a [i].c, 0, 0, coords); } } } //————————————————————————————————————————————————————————————————————
Метод "SelectFromGroup" реализует рулеточную селекцию для выбора "selCount" индексов из группы агентов (startIdx до endIdx).
- Подготовка: инициализирует выходной массив "indices", определяет размер группы. Обрабатывает случаи, когда группа пуста или слишком мала.
- Расчет весов: находит минимальный фитнес в группе и использует его для преобразования фитнесов агентов в положительные веса.
- Построение рулетки: создает "рулетку" (массивы интервалов), где каждый интервал соответствует агенту, а его размер пропорционален его весу (с учетом минимального фитнеса).
- Выбор: "selCount" раз генерирует случайное число на рулетке и выбирает агента, чей интервал попадает в это число. Результат сохраняется в "indices".
//———————————————————————————————————————————————————————————————————— void C_AO_ECOc::SelectFromGroup (int startIdx, int endIdx, int selCount, int &indices []) { ArrayResize (indices, selCount); int groupSize = endIdx - startIdx; if (groupSize <= 0) { for (int s = 0; s < selCount; s++) indices [s] = startIdx; return; } if (groupSize < selCount) { for (int s = 0; s < selCount; s++) indices [s] = startIdx + (s % groupSize); return; } // Подготовка рулетки для группы double minFit = a [startIdx].f; for (int i = startIdx + 1; i < endIdx; i++) { if (a [i].f < minFit) minFit = a [i].f; } // Заполняем структуру рулетки double cumSum = 0.0; for (int i = 0; i < groupSize; i++) { u.roulette [i].start = cumSum; double prob = a [startIdx + i].f - minFit + 1e-10; cumSum += prob; u.roulette [i].end = cumSum; } // Выбор for (int s = 0; s < selCount; s++) { double r = u.RNDfromCI (0.0, cumSum); indices [s] = startIdx; for (int i = 0; i < groupSize; i++) { if (r >= u.roulette [i].start && r < u.roulette [i].end) { indices [s] = startIdx + i; break; } } } } //————————————————————————————————————————————————————————————————————
Метод "VectorNorm" вычисляет Евклидово расстояние между двумя точками (координатами агентов "idx1" и "idx2") в "coords"-мерном пространстве.
- Суммирование квадратов разностей: проходит по всем "coords" измерениям, вычисляет разницу между соответствующими координатами двух агентов, возводит эту разницу в квадрат и накапливает сумму.
- Извлечение корня: возвращает квадратный корень из полученной суммы, что является длиной вектора (Евклидовым расстоянием).
//———————————————————————————————————————————————————————————————————— double C_AO_ECOc::VectorNorm (int idx1, int idx2) { double sum = 0.0; for (int c = 0; c < coords; c++) { double diff = a [idx1].cP [c] - a [idx2].cP [c]; sum += diff * diff; } return MathSqrt (sum); } //————————————————————————————————————————————————————————————————————
Результаты тестов
ECO|Ecological Cycle Optimizer|50.0|0.2|0.3|0.3|
=============================
5 Hilly's; Func runs: 10000; result: 0.7030067722054903
25 Hilly's; Func runs: 10000; result: 0.3712282206716303
500 Hilly's; Func runs: 10000; result: 0.3380465748120792
=============================
5 Forest's; Func runs: 10000; result: 0.4856459718015104
25 Forest's; Func runs: 10000; result: 0.2948314767505128
500 Forest's; Func runs: 10000; result: 0.1987204244277699
=============================
5 Megacity's; Func runs: 10000; result: 0.5892307692307692
25 Megacity's; Func runs: 10000; result: 0.3683076923076923
500 Megacity's; Func runs: 10000; result: 0.35736923076923105
=============================
All score: 3.70639 (41.18%)
Визуализация работы алгоритма на различных тестовых функциях.

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

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

ECOc на тестовой функции Megacity

ECOc на стандартной тестовой функции Shaffer

ECOc на стандартной тестовой функции Peaks
| № | 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 |
| ECOc | ecological_cycle_optimizer | 0,70300 | 0,37122 | 0,33804 | 1,41226 | 0,48564 | 0,29483 | 0,19872 | 0,97919 | 0,58923 | 0,36830 | 0,35736 | 1,31489 | 3,706 | 41,18 | |
| 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 | |
Выводы
Алгоритм ECO можно рекомендовать для задач, где важна стабильность сходимости и допустимы умеренные вычислительные затраты. Для задач, требующих максимальной эффективности, следует рассмотреть алгоритмы из верхней части нашего рейтинга. Оригинальная и интуитивно понятная концепция, основанная на экологических взаимодействиях. Адаптивный коэффициент хищничества G, обеспечивающий плавный переход от глобального исследования к локальной эксплуатации. Механизм жадного отбора (ревизии), гарантирующий монотонное улучшение лучшего решения. Три режима декомпозиции, вносящие разнообразие в поисковые стратегии. Высокая вычислительная сложность из-за множества операций копирования и сортировки на каждой итерации.

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

Рисунок 3. Гистограмма результатов тестирования алгоритмов (по шкале от 0 до 100, чем больше, тем лучше, где 100 — максимально возможный теоретический результат, в архиве скрипт для расчета рейтинговой таблицы)
Плюсы и минусы алгоритма ECOc:
Плюсы:
- Хорошо справляется с некоторым типом задач.
Минусы:
- Труднее справляется с дискретными функциями.
К статье прикреплён архив с актуальными версиями кодов алгоритмов. Автор статьи не несёт ответственности за абсолютную точность в описании канонических алгоритмов, во многие из них были внесены изменения для улучшения поисковых возможностей. Выводы и суждения, представленные в статьях, основываются на результатах проведённых экспериментов.
Программы, используемые в статье
| # | Имя | Тип | Описание |
|---|---|---|---|
| 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_ECOc.mq5 | Скрипт | Испытательный стенд для ECO |
Предупреждение: все права на данные материалы принадлежат MetaQuotes Ltd. Полная или частичная перепечатка запрещена.
Данная статья написана пользователем сайта и отражает его личную точку зрения. Компания MetaQuotes Ltd не несет ответственности за достоверность представленной информации, а также за возможные последствия использования описанных решений, стратегий или рекомендаций.
Объединяем 3D-бары, квантовые вычисления и машинное обучение в единую торговую систему
Знакомство с языком MQL5 (Часть 21): Автоматическое обнаружение паттернов Гартли
Нейросети в трейдинге: Сеточная аппроксимация событийного потока как инструмент анализа ценовых паттернов (Окончание)
Нейросети в трейдинге: Сеточная аппроксимация событийного потока как инструмент анализа ценовых паттернов (CDC-модуль)
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования