
Алгоритм конкурентного обучения — Competitive Learning Algorithm (CLA)
Содержание
Введение
За последние десятилетия было предложено множество биоинспирированных алгоритмов: от муравьиных колоний и роев частиц до серых волков и китов. Однако человеческое общество, с его сложными социальными взаимодействиями, также может служить богатым источником идей для создания эффективных оптимизационных методов. Именно эта идея легла в основу алгоритма конкурентного обучения (Competitive Learning Algorithm, CLA).
CLA использует метафору образовательного процесса, где популяция решений представлена в образе студентов, организованных в классы. Алгоритм элегантно моделирует три типа обучения: у лучшего в классе (учителя), из личного опыта и через межклассовое взаимодействие. Такой подход обеспечивает баланс между исследованием пространства поиска и использованием найденных хороших решений, что критически важно для эффективной оптимизации.
В данной статье мы детально рассмотрим принципы работы CLA, его математическую основу, особенности реализации, и сравним его эффективность с другими популярными метаэвристиками на наших стандартных тестовых функциях.
Реализация алгоритма
Алгоритм Конкурентного Обучения (Competitive Learning Algorithm) основан на метафоре образовательного процесса в школе. В этой метафоре студенты представляют собой возможные решения задачи оптимизации, классы — это группы студентов, учителя — лучшие студенты в каждом классе, знания соответствуют координатам в пространстве поиска, а оценка определяется значением фитнес-функции.
Работа алгоритма начинается с инициализации, которую можно сравнить с началом учебного года. Создается популяция, к примеру, из 198 студентов, которые делятся на 9 классов по 22 студента в каждом. Каждому студенту случайным образом присваиваются начальные "знания" —координаты в пространстве поиска.
Процесс обучения происходит итеративно, и на каждой итерации студенты обучаются тремя различными способами. Первый способ — это обучение у учителя, где каждый студент учится у лучшего в своем классе и, чем хуже показатели класса, тем активнее идет процесс обучения, но со временем интенсивность обучения снижается для всех. Второй способ — персональное обучение, которое начинается только после четвертой итерации. В этом режиме студент вспоминает свои лучшие результаты за последние четыре "урока" и пытается вернуться к своему личному рекорду. Третий способ — обучение у других классов, также начинающееся после четвертой итерации. С вероятностью 50% студент может учиться у "среднего учителя" всех классов, что помогает избежать застревания в локальных оптимумах.
После каждого цикла обучения происходит оценка успеваемости. Определяется лучший студент в каждом классе, который становится учителем, подсчитывается общий рейтинг класса с учетом показателей всех студентов, и обновляется глобально лучшее найденное решение.
Алгоритм использует пять ключевых параметров:
- popSize — определяет общее количество студентов,
- numClasses — задает количество классов,
- beta — регулирует влияние всех студентов класса на его общий рейтинг,
- gamma — устанавливает вероятность обучения у других классов,
- deltaIter — указывает, после какой итерации начинается расширенное обучение с использованием персонального опыта и межклассового взаимодействия.
В алгоритме реализовано несколько умных механизмов. Адаптивные факторы обучения обеспечивают более интенсивное обучение для слабых классов и постепенное замедление обучения со временем, как это происходит в реальном образовательном процессе. Баланс между исследованием и использованием достигается через активное исследование на начальных этапах с последующей фокусировкой на лучших найденных решениях. Механизм памяти позволяет алгоритму помнить историю каждого студента и, при необходимости, возвращаться к хорошим решениям из прошлого.
Математически обновление знаний студента можно представить как сумму текущих знаний: урока от учителя класса, личного опыта из истории, знаний, полученных от среднего учителя всех классов. Эта формула обеспечивает баланс между следованием за лидером, использованием личного опыта и исследованием новых областей.
В итоге, эффективность алгоритма обусловлена несколькими факторами. Разнообразие достигается за счет множества классов, исследующих разные направления в пространстве поиска. Конкуренция между студентами за место учителя стимулирует улучшение решений. Кооперация через обмен знаниями между классами старается предотвращать преждевременную сходимость. Адаптивность обеспечивает дополнительную помощь слабым классам, а механизм памяти сохраняет информацию о хороших решениях.
Рисунок 1. Схема работы алгоритма
Иллюстрация работы алгоритма описывает три основных шага: инициализацию, фазу обучения и оценку с обновлением. Теперь приступим к написанию псевдокода алгоритма CLA_L.
ЧТО НАМ НУЖНО ЗАРАНЕЕ:
- 198 студентов (наши решения)
- 9 классов (группы для студентов)
- Параметр β = 0.9 (насколько важны все студенты в классе)
- Параметр γ = 0.5 (шанс учиться у других классов)
- После 4-й итерации включаем дополнительные виды обучения
- Функция для оценки качества решения
НАЧИНАЕМ:
1. СОЗДАЁМ ШКОЛУ:
- Распределяем 198 студентов по 9 классам (по 22 в каждом)
- Даём каждому студенту случайную начальную позицию в пространстве
- В каждом классе выбираем лучшего студента - он становится учителем
- Создаём журнал для записи истории каждого студента
2. УЧЕБНЫЙ ПРОЦЕСС (итерационный процесс) :
Шаг 1: Определяем интенсивность обучения
- Для каждого класса считаем, насколько активно нужно учиться
- Слабые классы (с плохим рангом) учатся интенсивнее
- Со временем все учатся менее интенсивно (как в реальной жизни)
Шаг 2: Находим "среднего учителя"
- Берём позиции всех учителей
- Считаем их среднее значение
- Это будет общешкольный эталон знаний
Шаг 3: Каждый студент учится:
Для каждого студента делаем:
а) ВСЕГДА учимся у своего учителя:
- Смотрим, где находится учитель нашего класса
- Двигаемся в его сторону
- Скорость движения зависит от фактора обучения класса
б) После 4-й итерации - вспоминаем свой опыт:
- Смотрим в журнал: где я был лучше всего за последние 4 урока?
- С некоторой случайной силой возвращаемся к той позиции
- Это помогает не забыть хорошие решения
в) После 4-й итерации — учимся у других классов:
- Бросаем монетку (с вероятностью 50%)
- Если выпала решка — смотрим на "среднего учителя"
- Немного двигаемся в его сторону
- Это помогает обмениваться опытом между классами
Шаг 4: Оцениваем всех студентов
- Каждый студент получает оценку (fitness)
- Чем лучше позиция, тем выше оценка
Шаг 5: Обновляем школьную иерархию
Для каждого класса:
- Находим нового лучшего студента — он становится учителем
- Считаем общий уровень класса:
* Берём оценку учителя
* Добавляем средний балл всех студентов (умноженный на β)
- Определяем ранг класса:
* Лучшие классы получают низкий ранг (1, 2, 3...)
* Худшие классы получают высокий ранг
Шаг 6: Запоминаем лучшее решение
- Если какой-то учитель лучше нашего рекорда
- Сохраняем его как новый рекорд
Шаг 7: Записываем в историю
- Сохраняем текущие позиции всех студентов
- Это понадобится для персонального обучения
3. ЗАКАНЧИВАЕМ:
- Возвращаем лучшее найденное решение
- И его оценку
Теперь приступим к написанию кода алгоритма. Класс "C_AO_CLA_l" является наследником класса "C_AO" (родительского класса) и реализует алгоритм, основанный на концепции конкурентного обучения. Класс содержит ряд параметров, настраиваемых пользователем:
- popSize — размер популяции (количество "агентов" или "учеников");
- numClasses — количество классов, на которые разделены агенты;
- beta — параметр, вероятно влияющий на скорость обучения или адаптации;
- gamma — еще один параметр, скорее всего, связанный с обучением;
- deltaIter — частота выполнения определенных шагов алгоритма (в итерациях).
Конструктор инициализирует основные параметры, устанавливает название и описание алгоритма, задает значения по умолчанию для переменных, и выполняет размер массива "params", который предназначен для хранения информации о параметрах алгоритма.
Методы:
- SetParams () — обновляет значения внутренних переменных класса (параметров алгоритма), используя значения из массива "params". Это позволяет изменять параметры, заданные вовне.
- Init () — инициализирует алгоритм. Принимает параметры, для определения границ и шага изменения параметров.
- Moving () — основной метод для "движения" агентов (выполнения итераций и шагов алгоритма).
- Revision () — метод связан с коррекцией или улучшением решений.
- Injection () — метод для "внедрения" (inserting) нового знания или данных в агента.
- numClasses, beta, gamma, deltaIter — параметры алгоритма.
- currentIter, studentsPerClass, totalIters — внутренние переменные для управления ходом алгоритма.
- teachers [] — массив структур "S_AO_Agent", представляющих "учителей" в каждом классе (опорные точки).
- classRanks [] — ранги классов, отражающие их производительность.
- classTotalCosts [] — общие затраты или "стоимость" каждого класса.
- CL [] — временный массив для вычисления среднего знания учителей.
- UpdateTeachersAndCosts () — внутренний метод для обновления информации об учителях и их стоимости.
- UpdateClassRanks () — внутренний метод для обновления рангов классов.
- UpdateStudentsKnowledge () — внутренний метод для обновления знаний или параметров "учеников".
//———————————————————————————————————————————————————————————————————— class C_AO_CLA_l : public C_AO { public: //---------------------------------------------------------- ~C_AO_CLA_l () { } C_AO_CLA_l () { ao_name = "CLA_L"; ao_desc = "Competitive Learning Algorithm"; ao_link = "https://www.mql5.com/ru/articles/18857"; popSize = 198; numClasses = 3; beta = 0.3; gamma = 0.8; deltaIter = 2; ArrayResize (params, 5); params [0].name = "popSize"; params [0].val = popSize; params [1].name = "numClasses"; params [1].val = numClasses; params [2].name = "beta"; params [2].val = beta; params [3].name = "gamma"; params [3].val = gamma; params [4].name = "deltaIter"; params [4].val = deltaIter; } void SetParams () { popSize = (int)params [0].val; numClasses = (int)params [1].val; beta = params [2].val; gamma = params [3].val; deltaIter = (int)params [4].val; } bool Init (const double &rangeMinP [], const double &rangeMaxP [], const double &rangeStepP [], const int epochsP = 0); void Moving (); void Revision (); void Injection (const int popPos, const int coordPos, const double value) { } //------------------------------------------------------------------ int numClasses; double beta; double gamma; int deltaIter; private: //--------------------------------------------------------- int currentIter; int studentsPerClass; int totalIters; // Структуры для классов S_AO_Agent teachers []; double classRanks []; double classTotalCosts []; // Временные массивы double CL []; // Среднее знание учителей // Вспомогательные методы void UpdateTeachersAndCosts (); void UpdateClassRanks (); void UpdateStudentsKnowledge (); }; //————————————————————————————————————————————————————————————————————
Метод "Init ()" класса "C_AO_CLA_l" выполняет инициализацию алгоритма перед началом работы. Логика работы разбита на несколько этапов. Standard Initialization: вызывается метод "StandardInit ()" и выполняет стандартную инициализацию для алгоритма оптимизации. Ему передаются границы параметров "rangeMinP", "rangeMaxP", и шаг "rangeStepP". Если стандартная инициализация не удалась, метод "Init ()" возвращает "false".
Initialization of Algorithm Parameters: сбрасывает счетчик текущей итерации в "0", устанавливает общее количество итераций, которое алгоритм должен выполнить, используя значение, переданное в аргументе "epochsP", вычисляет количество "студентов" (агентов) в каждом классе, деля размер популяции на количество классов. Далее метод проверяет, что в каждом классе есть хотя бы один студент. Далее цикл "for" инициализирует каждого агента в популяции. Для каждого агента в массиве "a" вызывается метод "Init ()". Метод предполагает инициализацию количества координат для каждого человека.
Цикл "for" инициализирует "учителя" для каждого класса, устанавливает ранг каждого класса равным "1.0", а также устанавливает начальную "стоимость" каждого класса в отрицательное максимальное значение, чтобы гарантировать, что впоследствии будет найдено лучшее решение. Если все этапы инициализации прошли успешно, метод возвращает "true".
//———————————————————————————————————————————————————————————————————— bool C_AO_CLA_l::Init (const double &rangeMinP [], const double &rangeMaxP [], const double &rangeStepP [], const int epochsP = 0) { if (!StandardInit (rangeMinP, rangeMaxP, rangeStepP)) return false; //------------------------------------------------------------------ currentIter = 0; totalIters = epochsP; studentsPerClass = popSize / numClasses; if (studentsPerClass < 1) { Print ("Ошибка: слишком мало студентов на класс"); return false; } // Корректировка размера популяции //spopSize = studentsPerClass * numClasses; ArrayResize (a, popSize); for (int i = 0; i < popSize; i++) a [i].Init (coords); // Инициализация структур классов ArrayResize (teachers, numClasses); ArrayResize (classRanks, numClasses); ArrayResize (classTotalCosts, numClasses); for (int i = 0; i < numClasses; i++) { teachers [i].Init (coords); classRanks [i] = 1.0; classTotalCosts [i] = -DBL_MAX; } // Временные массивы ArrayResize (CL, coords); return true; } //————————————————————————————————————————————————————————————————————
Метод "Moving ()" класса "C_AO_CLA_l" реализует одну итерацию основного алгоритма оптимизации, проверяет, является ли она первой итерацией и, если это первая итерация (то есть, "revision" имеет значение "false"), метод инициализирует положения всех агентов в популяции случайными значениями в заданном диапазоне. Перебирает всех агентов в популяции и для каждого агента перебирает все его координаты.
Для каждой координаты метод генерирует случайное значение "val" в диапазоне от "rangeMin [c]" до "rangeMax [c]" с использованием метода "u.RNDfromCI ()", предоставляющего функцию для генерации случайных чисел. Присваивает координате "a [i].c [c]" агента "i" значение "val", предварительно "обрезав" его, чтобы он находился в допустимом диапазоне и соответствовал заданному шагу "rangeStep [c]". Используется метод "u.SeInDiSp ()", который выполняет проверку и корректировку значения.
После инициализации популяции, устанавливает флаг, чтобы указать, что инициализация была выполнена. Если это не первая итерация, увеличивает счетчик текущей итерации. Вызывает метод "UpdateStudentsKnowledge ()", который реализует основной механизм обучения или адаптации агентов в соответствии с принципами конкурентного обучения, используемого в алгоритме "CLA_L". Логика этого метода определяет, как агенты взаимодействуют, обмениваются информацией и улучшают свои позиции в пространстве поиска решений.
//———————————————————————————————————————————————————————————————————— void C_AO_CLA_l::Moving () { // Начальная инициализация популяции if (!revision) { for (int i = 0; i < popSize; i++) { for (int c = 0; c < coords; c++) { double val = u.RNDfromCI (rangeMin [c], rangeMax [c]); a [i].c [c] = u.SeInDiSp (val, rangeMin [c], rangeMax [c], rangeStep [c]); } } revision = true; return; } currentIter++; // Обновление знаний студентов UpdateStudentsKnowledge (); } //————————————————————————————————————————————————————————————————————
Метод "UpdateStudentsKnowledge ()" отвечает за обновление позиции каждого ученика (агента) в процессе оптимизации. Вычисляется текущий прогресс оптимизации. Рассчитываются два ключевых фактора обучения:
- TF (Teaching Factor) — показывает, насколько ученик учится у учителя.
- CF (Confirmatory Factor) — показывает, насколько ученик учитывает средние знания учителей. Эти факторы зависят от прогресса и ранга класса ученика.
Далее вычисляется среднее значение координат всех "активных" учителей (учителей, чьи результаты валидны). Это среднее знание хранится во временном массиве. Для каждого ученика (агента) определяется класс, к которому принадлежит ученик, а для каждой координаты ученика вычисляется новая позиция ученика, суммируя текущую координату с "источниками знаний". Ученик учится у своего учителя, корректируя свою позицию на величину, пропорциональную разнице между координатой учителя и своей собственной, умноженную на TF. Если прошло достаточно итераций (currentIter > deltaIter) и у ученика есть "лучшее решение", то ученик учится на своем предыдущем успешном опыте, корректируя свою позицию в направлении лучшей координаты, умножая на случайный фактор.
Если прошло достаточно итераций, и количество учителей валидно, ученик учится у среднего знания всех учителей, корректируя свою позицию в направлении средней координаты, умноженную на "CF", с определенной вероятностью (1-gamma). Применяются границы (ограничения) для каждой координаты ученика, чтобы убедиться, что значение находится в допустимом диапазоне. Значение корректируется, чтобы соответствовать допустимым значениям, учитывающим шаг дискретизации поиска.
//———————————————————————————————————————————————————————————————————— void C_AO_CLA_l::UpdateStudentsKnowledge () { // Расчет факторов обучения для текущей итерации double progress = (double)currentIter / (double)MathMax (totalIters, 100); // Вычисление среднего знания всех учителей (CL) ArrayInitialize (CL, 0.0); int validTeachers = 0; for (int k = 0; k < numClasses; k++) { // Проверяем, что учитель инициализирован if (teachers [k].f > -DBL_MAX) { for (int c = 0; c < coords; c++) { CL [c] += teachers [k].c [c]; } validTeachers++; } } if (validTeachers > 0) { for (int c = 0; c < coords; c++) { CL [c] /= validTeachers; } } // Обновление каждого студента for (int i = 0; i < popSize; i++) { int classIdx = i / studentsPerClass; // Teaching Factor - уменьшается с прогрессом double TF = MathExp (-0.6 * progress * classRanks [classIdx]); TF = MathMax (0.1, MathMin (1.0, TF)); // Confirmatory Factor double CF = MathExp (-0.5 * progress * classRanks [classIdx]); CF = MathMax (0.1, MathMin (1.0, CF)); // Обновление позиции студента for (int c = 0; c < coords; c++) { double newPos = a [i].c [c]; // a) Teacher Learning - учимся у учителя класса if (teachers [classIdx].f > -DBL_MAX) { newPos += TF * (teachers [classIdx].c [c] - a [i].c [c]); } // b) Personal Learning - учимся у своего лучшего решения if (currentIter > deltaIter && a [i].fB > -DBL_MAX) { double PF = u.RNDprobab (); newPos += PF * (a [i].cB [c] - a [i].c [c]); } // c) Confirmatory Learning - учимся у среднего всех учителей if (currentIter > deltaIter && validTeachers > 0) { double rnd = u.RNDprobab (); if (rnd >= gamma) // Участвует с вероятностью (1-gamma) { newPos += CF * (CL [c] - a [i].c [c]); } } // Применение границ a [i].c [c] = u.SeInDiSp (newPos, rangeMin [c], rangeMax [c], rangeStep [c]); } } } //————————————————————————————————————————————————————————————————————
Метод "Revision ()" в классе "C_AO_CLA_l" служит для обновления информации о лучших решениях каждого агента, а также для обновления глобального лучшего решения и соответствующих параметров.
Для каждого агента проверяется, улучшилась ли его текущая функция цели (a [i].f) по сравнению с его запомненным лучшим значением (a [i].fB). Если да, то лучшее значение сохраняется, и копируются соответствующие координаты. После проверки всех агентов, если у какого-либо из них получилось лучшее значение функции, чем текущий глобальный максимум (fB), обновляются глобальные параметры: fB — глобальное лучшее значение функции и cB — координаты этого лучшего решения.
Далее вызывается метод "UpdateTeachersAndCosts ()", который обновляет информацию о лучших учителях. В конце вызывается "UpdateClassRanks ()", чтобы пересчитать ранги классов, что влияет на приоритетность выбора определенных решений в последующих итерациях.
//———————————————————————————————————————————————————————————————————— void C_AO_CLA_l::Revision () { for (int i = 0; i < popSize; i++) { // Обновление персональных лучших позиций if (a [i].f > a [i].fB) { a [i].fB = a [i].f; ArrayCopy (a [i].cB, a [i].c); } // Обновление глобального лучшего if (a [i].f > fB) { fB = a [i].f; ArrayCopy (cB, a [i].c); } } // Обновление учителей UpdateTeachersAndCosts (); // Обновление рангов классов UpdateClassRanks (); } //————————————————————————————————————————————————————————————————————
Метод "UpdateTeachersAndCosts ()" предназначен для обновления информации об учителях в каждом классе и расчета общей "стоимости" класса. Метод проходит в цикле по всем классам, определённым в системе. Для каждого класса определяются начальный и конечный индексы студентов (агентов), входящих в этот класс.
Для поиска лучшего студента в классе инициализируются переменные для хранения лучшего значения функции, индекса лучшего студента, суммы значений функции всех студентов в классе и количества валидных студентов. Цикл проходит по всем студентам в текущем классе. Для каждого студента проверяется, является ли его решение валидным, и если решение валидно, то: значение функции этого студента добавляется к "sumFitness", увеличивается счётчик валидных студентов, и если значение функции текущего студента лучше, чем текущее лучшее значение "bestFitness", тогда оно обновляется и "bestIdx".
После нахождения лучшего студента в классе, проверяется, что в классе был хотя бы один валидный студент (validStudents > 0). Если условие выполнено, то координаты лучшего студента копируются в координаты учителя соответствующего класса, и значение функции лучшего студента присваивается значению функции учителя.
Вычисляется среднее значение функции всех студентов в классе "avgFitness". Рассчитывается общая "стоимость" класса, как сумма значения функции лучшего студента и произведения коэффициента "beta" на среднее значение функции всех студентов. Это комбинация эффективности учителя и среднего благосостояния класса.
//———————————————————————————————————————————————————————————————————— void C_AO_CLA::UpdateTeachersAndCosts () { for (int k = 0; k < numClasses; k++) { int startIdx = k * studentsPerClass; int endIdx = startIdx + studentsPerClass; double bestFitness = -DBL_MAX; int bestIdx = startIdx; double sumFitness = 0.0; int validStudents = 0; // Находим лучшего студента (учителя) в классе for (int i = startIdx; i < endIdx; i++) { if (a[i].f > -DBL_MAX) // Проверка валидности { sumFitness += a[i].f; validStudents++; if (a[i].f > bestFitness) { bestFitness = a[i].f; bestIdx = i; } } } // Обновляем учителя if (validStudents > 0) { ArrayCopy (teachers[k].c, a[bestIdx].c); teachers[k].f = bestFitness; // Расчет total cost класса double avgFitness = sumFitness / validStudents; classTotalCosts[k] = bestFitness + beta * avgFitness; } } } //————————————————————————————————————————————————————————————————————
Метод "UpdateClassRanks ()" служит для определения рангов классов на основе их общей "стоимости", которая характеризует насколько эффективный класс. Процесс метода начинается с поиска минимальной и максимальной стоимости среди всех валидных классов. Если все классы имеют одинаковую стоимость, или валидных классов нет, то для всех устанавливается одинаковый ранг равный 1.
Если же есть различия в стоимости, то производится нормализация этих значений — каждая стоимость приводится к диапазону от 0 до 1. После этого осуществляется инверсия: классы с более высокой стоимостью получают более низкий ранг, приближенный к 1, а с более низкой стоимостью — к максимальному рангу, равному числу классов.
Затем каждое значение ранга ограничивается минимальным и максимальным значением, чтобы избежать выходов за пределы допустимых границ. В итоге, по результатам этого метода, классы получают ранги, основанные на их эффективности.
//———————————————————————————————————————————————————————————————————— void C_AO_CLA_l::UpdateClassRanks () { // Находим min и max costs среди валидных классов double minCost = DBL_MAX; double maxCost = -DBL_MAX; int validClasses = 0; for (int k = 0; k < numClasses; k++) { if (classTotalCosts [k] > -DBL_MAX) { if (classTotalCosts [k] < minCost) minCost = classTotalCosts [k]; if (classTotalCosts [k] > maxCost) maxCost = classTotalCosts [k]; validClasses++; } } if (validClasses == 0 || maxCost - minCost < 1e-10) { // Все классы одинаковые или нет валидных for (int k = 0; k < numClasses; k++) classRanks [k] = 1.0; } else { // Ранжирование: лучшие классы (высокий cost) получают низкий ранг for (int k = 0; k < numClasses; k++) { if (classTotalCosts [k] > -DBL_MAX) { // Нормализация от 0 до 1 double normalized = (classTotalCosts [k] - minCost) / (maxCost - minCost); // Инверсия: лучшие получают ранг близкий к 1 classRanks [k] = 1.0 + (1.0 - normalized) * (numClasses - 1.0); // Ограничение classRanks [k] = MathMax (1.0, MathMin ((double)numClasses, classRanks [k])); } else { classRanks [k] = numClasses; // Худший ранг для неинициализированных } } } } //————————————————————————————————————————————————————————————————————
Результаты тестов
По результатам тестирования, алгоритм CLA_L набирает неплохие результаты.CLA_L|Competitive Learning Algorithm|198.0|3.0|0.3|0.8|2.0|
=============================
5 Hilly's; Func runs: 10000; result: 0.6482993681242128
25 Hilly's; Func runs: 10000; result: 0.5535249826770444
500 Hilly's; Func runs: 10000; result: 0.2584959913710746
=============================
5 Forest's; Func runs: 10000; result: 0.8027208362980616
25 Forest's; Func runs: 10000; result: 0.49540442971179494
500 Forest's; Func runs: 10000; result: 0.20048686632188017
=============================
5 Megacity's; Func runs: 10000; result: 0.6353846153846153
25 Megacity's; Func runs: 10000; result: 0.2716923076923076
500 Megacity's; Func runs: 10000; result: 0.10086153846153936
=============================
All score: 3.96687 (44.08%)
На визуализации заметно, что алгоритм в начале работы обладает хорошими поисковыми способностями, которые ухудшаются из-за попадания в локальные ловушки, от чего происходит стагнация во второй половине работы алгоритма.
CLA_L на тестовой функции Hilly
CLA_L на тестовой функции Forest
CLA_L на тестовой функции Megacity
По итогам работы алгоритма в турнирной таблице CLA_L представлен ознакомительно.
№ | 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 | 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 |
2 | 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 |
3 | 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 |
4 | (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 |
5 | 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 |
6 | 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 |
7 | 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 |
8 | 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 |
9 | 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 |
10 | 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 |
11 | 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 |
12 | 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 |
13 | 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 |
14 | 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 |
15 | 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 |
16 | 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 |
17 | 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 |
18 | 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 |
19 | 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 |
20 | 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 |
21 | 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 |
22 | 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 |
23 | 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 |
24 | 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 |
25 | 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 |
26 | 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 |
27 | 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 |
28 | 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 |
29 | 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 |
30 | 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 |
31 | 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 |
32 | (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 |
33 | 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 |
34 | 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 |
35 | 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 |
36 | 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 |
37 | 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 |
38 | 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 |
39 | 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 |
40 | 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 |
41 | 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 |
42 | BFO-GA | bacterial foraging optimization - ga | 0,89150 | 0,55111 | 0,31529 | 1,75790 | 0,96982 | 0,39612 | 0,06305 | 1,42899 | 0,72667 | 0,27500 | 0,03525 | 1,03692 | 4,224 | 46,93 |
43 | SOA | simple optimization algorithm | 0,91520 | 0,46976 | 0,27089 | 1,65585 | 0,89675 | 0,37401 | 0,16984 | 1,44060 | 0,69538 | 0,28031 | 0,10852 | 1,08422 | 4,181 | 46,45 |
44 | ABHA | artificial bee hive algorithm | 0,84131 | 0,54227 | 0,26304 | 1,64663 | 0,87858 | 0,47779 | 0,17181 | 1,52818 | 0,50923 | 0,33877 | 0,10397 | 0,95197 | 4,127 | 45,85 |
45 | ACMO | atmospheric cloud model optimization | 0,90321 | 0,48546 | 0,30403 | 1,69270 | 0,80268 | 0,37857 | 0,19178 | 1,37303 | 0,62308 | 0,24400 | 0,10795 | 0,97503 | 4,041 | 44,90 |
CLA_L | competitivelearningalgorithm | 0,64829 | 0,55352 | 0,25849 | 1,46030 | 0,80272 | 0,49540 | 0,20048 | 1,49860 | 0,63538 | 0,27169 | 0,10086 | 1,00793 | 3,967 | 44,08 | |
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 |
Выводы
Алгоритм конкурентного обучения (CLA_L) демонстрирует средние показатели эффективности при решении стандартных задач оптимизации. Анализ работы алгоритма выявил характерную двухфазную динамику: активную фазу исследования в начальных итерациях и фазу преждевременной стагнации во второй половине оптимизационного процесса.
Разделение популяции на классы обеспечивает хорошее покрытие пространства поиска на ранних этапах. Каждый класс исследует свою область, что способствует глобальному поиску. Образовательная модель делает алгоритм понятным и легко интерпретируемым. Концепции учителей, студентов и различных типов обучения естественны для понимания. Факторы обучения, зависящие от ранга класса, теоретически должны обеспечивать баланс между исследованием и использованием. Комбинация трех типов обучения (у учителя, персональное, подтверждающее) создает потенциал для избежания локальных оптимумов. Несмотря на механизмы диверсификации, алгоритм склонен к застреванию в локальных оптимумах.
Алгоритм CLA представляет интересную концепцию применения образовательной метафоры к задачам оптимизации. Несмотря на инновационный подход и хорошие начальные показатели, алгоритм требует существенных модификаций для конкурентоспособности с современными метаэвристиками. Основным вызовом остается обеспечение баланса между исследованием и использованием на протяжении всего оптимизационного процесса.
Рисунок 2. Цветовая градация алгоритмов по соответствующим тестам
Рисунок 3. Гистограмма результатов тестирования алгоритмов (по шкале от 0 до 100, чем больше, тем лучше, где 100 — максимально возможный теоретический результат, в архиве скрипт для расчета рейтинговой таблицы)
Плюсы и минусы алгоритма CLA_L:
Плюсы:
- Быстрый.
Минусы:
- Большое количество внешних параметров.
- Склонность к застреванию на задачах.
К статье прикреплён архив с актуальными версиями кодов алгоритмов. Автор статьи не несёт ответственности за абсолютную точность в описании канонических алгоритмов, во многие из них были внесены изменения для улучшения поисковых возможностей. Выводы и суждения, представленные в статьях, основываются на результатах проведённых экспериментов.
Программы, используемые в статье
# | Имя | Тип | Описание |
---|---|---|---|
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_CLA_L.mq5 | Скрипт | Испытательный стенд для CLA_L |





- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования