Español Português
preview
Алгоритм успешного ресторатора —  Successful Restaurateur Algorithm (SRA)

Алгоритм успешного ресторатора — Successful Restaurateur Algorithm (SRA)

MetaTrader 5Тестер |
473 0
Andrey Dik
Andrey Dik

Содержание

  1. Введение
  2. Реализация алгоритма
  3. Результаты тестов


Введение

Меня всегда увлекали параллели между задачами оптимизации и реальными жизненными сценариями. Исследуя новые подходы к метаэвристическим алгоритмам, я обнаружил сходство между популяционной оптимизацией и эволюцией ресторанного бизнеса, и эта идея стала источником вдохновения для того, что я называю "Алгоритмом успешного ресторатора" (SRA).

Представьте владельца ресторана, который постоянно стремится улучшить свое меню для улучшения популярности своего ресторана и привлечения новых клиентов. Вместо того, чтобы полностью отказываться от непопулярных блюд, он использует более тонкий подход: определяет наименее популярную позицию, а затем аккуратно смешивает ее с элементами из самых успешных блюд. Иногда вносятся консервативные изменения, а иногда добавляются смелые новые ингредиенты. Цель всегда одна — превратить самое слабое предложение в нечто, что может стать новым фаворитом в меню для клиентов ресторана.

Эта кулинарная метафора формирует основу SRA. В отличие от традиционных эволюционных алгоритмов, которые часто полностью отбрасывают неудачные решения, SRA фокусируется на реабилитации наихудших исполнителей, сочетая их с успешными элементами. Такой подход сохраняет разнообразие в пространстве решений, одновременно неуклонно повышая общее качество популяции.

В этой статье рассмотрим основные механизмы SRA, проанализируем его реализацию и то, как параметры вроде "температуры" и "интенсивности кулинарных экспериментов" управляют балансом между эксплуатацией и исследованием, а также я поделюсь результатами тестирования, сравнивая SRA с другими известными алгоритмами в рейтинговой таблице на различных тестовых функциях.

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


Реализация алгоритма

Давайте разберем работу алгоритма через простые аналогии. Представьте, что я являюсь владельцем ресторана. У меня есть меню с разными блюдами и замечаю, что некоторые из них очень популярны, а некоторые блюда гости почти не заказывают. Что я делаю? Я не выбрасываю сразу непопулярные блюда из меню (тем самым уменьшая список доступных блюд), а вместо этого — беру самое непопулярное блюдо и пытаюсь его улучшить. Как? Я смотрю на хитовые позиции ресторана и заимствую оттуда какие-то идеи или ингредиенты. Например, у меня плохо продаётся рыбное блюдо, а салат — очень популярен. Я беру элементы из успешного салата (может, особую заправку или способ подачи) и применяю к рыбному блюду. Получается что-то новое.

Иногда я делаю небольшие изменения, а иногда — решаюсь на смелые эксперименты. В начале, когда я только открыл ресторан, я больше экспериментировал, а когда уже нашел несколько действительно удачных блюд, делаю более тонкую настройку состава ингредиентов и их количества. Со временем, даже самые слабые блюда в моем меню становятся всё лучше и лучше. А иногда бывает, что бывший аутсайдер после доработки становится новым успешным блюдом! Таким образом, общая популярность ресторана растет за счет того, что все позиции меню пользуются успехом.

Вот так работает и мой алгоритм, — мы не выбрасываем плохие решения, а постоянно улучшаем их, используя идеи из лучших решений. И чем дальше, тем меньше мы экспериментируем, больше уточняя уже найденное. На рисунке 1 представлена схема работы алгоритма.

sra-algorithm-flow

Рисунок 1. Схема работы алгоритма SRA

Схема начинается с блока "Инициализация", где создаётся начальное меню. Затем следует основной цикл алгоритма, в центре которого находится текущее меню ресторана, отсортированное по качеству блюд. Это меню изображено как цветовой градиент от зелёного (лучшие блюда) к красному (худшие блюда). Ниже идут четыре последовательных шага: первый — выбор блюд для улучшения, где берётся худшее блюдо и лучший донор с увеличенной вероятностью ко квадратичному закону; второй — создание новых вариантов путём комбинирования рецептов и мутации ингредиентов (причём, чем выше температура, тем смелее эксперименты); третий — оценка новых блюд через расчёт фитнес-функции; четвёртый — снижение температуры для уменьшения радикальности экспериментов. Слева пунктирная стрелка показывает, что процесс повторяется до достижения сходимости или выполнения критерия останова. Справа даны обозначения: A (зелёный круг) — лучшие блюда, B (красный круг) — худшие блюда. Вся схема визуализирует процесс, напоминающий работу ресторатора, который систематически улучшает слабые позиции своего меню, используя элементы успешных блюд.

Переходим к написанию псевдокода алгоритма SRA.

// Инициализация
Создать популяцию из popSize агентов (блюд в меню)
Для каждого агента:
    Случайно инициализировать все координаты в допустимых пределах
Установить начальную температуру = 1.0
Установить коэффициент охлаждения = 0.98
Установить интенсивность кулинарных экспериментов = 0.3

// Основной цикл алгоритма
ПОКА не выполнено условие остановки:
    // Шаг 1: Оценка всех агентов
    Для каждого агента:
        Вычислить значение фитнес-функции
    
    // Объединить текущую и предыдущую популяции
    Сформировать общее меню из текущих агентов и предыдущих агентов
    Отсортировать общее меню по значению фитнес-функции от лучшего к худшему
    
    // Шаг 2: Создание новых вариантов
    Для каждого агента в новой популяции:
        // Берем худший элемент из первой половины отсортированной популяции
        Скопировать координаты из агента с индексом (popSize-1)
        
        // Выбор между улучшением и экспериментом
        Если (случайное число < (1.0 - menuInnovationRate * температура)):
            // Выбираем "донора" методом квадратичной рулетки
            r = случайное число от 0 до 1
            r = r²
            donorIndex = масштабировать r от 0 до (popSize-1)
            
            // Для каждой координаты
            Для каждой координаты c:
                // С вероятностью 0.8 берем координату из донора
                Если (случайное число < 0.8):
                    текущий_агент.c = донор.c
                
                // Адаптивная мутация
                mutationRate = 0.1 + 0.4 * температура * (индекс_агента / popSize)
                Если (случайное число < mutationRate):
                    // Выбираем тип мутации
                    Если (случайное число < 0.5):
                        текущий_агент.c = гауссовское распределение(текущий_агент.c)
                    Иначе:
                        текущий_агент.c = случайное значение в диапазоне
                    
                    // Убедиться, что значение в допустимых пределах
                    текущий_агент.c = округлить до ближайшего допустимого значения
        Иначе:
            // Создание нового "блюда"
            Для каждой координаты c:
                Если (случайное число < 0.7):
                    текущий_агент.c = случайное значение в диапазоне
                Иначе:
                    текущий_агент.c = гауссовское распределение(лучшее_решение.c)
                
                // Убедиться, что значение в допустимых пределах
                текущий_агент.c = округлить до ближайшего допустимого значения
        
        // Элитизм — иногда простое добавление элементов из лучшего решения
        Если (случайное число < 0.1):
            numEliteCoords = случайное число от 1 до (coords * 0.3)
            Для i от 1 до numEliteCoords:
                c = случайный индекс координаты
                текущий_агент.c = лучшее_решение.c
    
    // Шаг 3: Обновление лучшего решения
    Для каждого агента:
        Если агент.фитнес > лучшее_решение.фитнес:
            лучшее_решение = агент
    
    // Шаг 4: Снижение температуры
    температура = температура * коэффициент_охлаждения
    Если температура < 0.1:
        температура = 0.1

Вернуть лучшее_решение

Теперь можно приступить к написанию кода алгоритма. Напишем класс "C_AO_SRA", который наследуется от главного класса "C_AO" и реализует алгоритм SRA. Давайте разберем его подробнее.

Конструктор и деструктор: popSize, temperature, coolingRate, menuInnovationRate — эти параметры определяют основные характеристики алгоритма, такие как количество агентов и параметры управления поиском.

Метод SetParams: обновляет параметры класса на основании значений, хранящихся в массиве "params", параметры ранее инициализировались в конструкторе.

Метод Init: предназначен для инициализации алгоритма. Он принимает минимальные и максимальные значения, шаг изменения параметров и количество эпох и подготавливает алгоритм к выполнению задачи поиска.

Методы Moving и Revision: предназначены для выполнения основных этапов работы алгоритма, связанных с движением (или обновлением) состояния агентов и "Revision", который отвечает за пересмотр и адаптацию параметров.

Члены класса:

  • temperature — текущая температура, связанная с управлением исследованием и температурным графиком алгоритма.
  • coolingRate — скорость охлаждения, которая используется для управления тем, как быстро температура будет понижаться.
  • menuInnovationRate — интенсивность кулинарных экспериментов, насколько агенты поощряются к поиску новых решений.
Приватные члены класса:
  • S_AO_Agent menu [] — массив агентов, который представляет "меню" в контексте алгоритма SRA.
  • S_AO_Agent menuT [] — массив агентов, используемый для временного хранения вариантов блюд.
//——————————————————————————————————————————————————————————————————————————————
class C_AO_SRA : public C_AO
{
  public: //--------------------------------------------------------------------
  ~C_AO_SRA () { }
  C_AO_SRA ()
  {
    ao_name = "SRA";
    ao_desc = "Successful Restaurateur Algorithm (joo)";
    ao_link = "https://www.mql5.com/ru/articles/17380";

    popSize            = 50;   // число агентов (размер "меню")
    temperature        = 1.0;  // начальная "температура" для управления исследованием
    coolingRate        = 0.98; // скорость охлаждения
    menuInnovationRate = 0.3;  // интенсивность кулинарных экспериментов

    ArrayResize (params, 4);

    params [0].name = "popSize";            params [0].val = popSize;
    params [1].name = "temperature";        params [1].val = temperature;
    params [2].name = "coolingRate";        params [2].val = coolingRate;
    params [3].name = "menuInnovationRate"; params [3].val = menuInnovationRate;
  }

  void SetParams ()
  {
    popSize            = (int)params [0].val;
    temperature        = params      [1].val;
    coolingRate        = params      [2].val;
    menuInnovationRate = params      [3].val;
  }

  bool Init (const double &rangeMinP  [],  // минимальные значения
             const double &rangeMaxP  [],  // максимальные значения
             const double &rangeStepP [],  // шаг изменения
             const int     epochsP = 0);   // количество эпох

  void Moving   ();
  void Revision ();

  //----------------------------------------------------------------------------
  double temperature;        // текущая "температура"
  double coolingRate;        // скорость охлаждения
  double menuInnovationRate; // интенсивность кулинарных экспериментов

  private: //-------------------------------------------------------------------
  S_AO_Agent menu  [];
  S_AO_Agent menuT [];
};
//——————————————————————————————————————————————————————————————————————————————

Метод "Init" класса "C_AO_SRA" выполняет инициализацию алгоритма:

Проверка начальной инициализации: метод вызывает "StandardInit" с минимальными и максимальными значениями диапазонов и шагов, если неудачно, возвращается "false".

Инициализация массивов:

  • Распределяет размеры массивов "menu" и "menuT" в соответствии с количеством агентов.
  • Инициализирует каждого агента в массиве "menu".

Сброс температуры: устанавливает начальное значение "temperature" равным "1.0".

Успешное завершение: возвращается "true", если инициализация прошла успешно.

//——————————————————————————————————————————————————————————————————————————————
//--- Инициализация
bool C_AO_SRA::Init (const double &rangeMinP  [],
                     const double &rangeMaxP  [],
                     const double &rangeStepP [],
                     const int epochsP = 0)
{
  if (!StandardInit (rangeMinP, rangeMaxP, rangeStepP)) return false;

  //----------------------------------------------------------------------------
  ArrayResize (menu,  popSize * 2);
  ArrayResize (menuT, popSize * 2);

  for (int p = 0; p < popSize * 2; p++) menu [p].Init (coords);

  temperature = 1.0; // сброс температуры при инициализации

  return true;
}
//——————————————————————————————————————————————————————————————————————————————

Метод "Moving" класса "C_AO_SRA" реализует основной шаг алгоритма. Он имеет две основные части: инициализацию агентов и их адаптацию через мутацию и создание новых решений.

Первоначальная инициализация (если "revision" равно "false"):
  • Каждый агент инициализируется случайными значениями в пределах заданных диапазонов (rangeMin, rangeMax) с применением шагов (rangeStep). Значения сохраняются в "c" и "cB" для каждого агента.
  • Устанавливается "revision" в "true" и метод завершает выполнение.

Снижение температуры: температура умножается на коэффициент охлаждения (coolingRate), что влияет на вероятности дальнейших изменений.

Основной цикл по агентам: для каждого агента выбирается худший элемент из первой половины отсортированной популяции (из массива menu).

Классификация действий: с определенной вероятностью, которая зависит от температуры, агент либо:

  • модифицирует текущее решение (с использованием "рецепта-донор" из лучшего блюда), применяя мутацию с изменяющейся вероятностью.
  • создает новое решение (случайные значения).

Элитизм: с некоторой вероятностью к новому решению могут быть добавлены элементы от лучшего найденного решения.

//——————————————————————————————————————————————————————————————————————————————
//--- Основной шаг алгоритма
void C_AO_SRA::Moving ()
{
  //----------------------------------------------------------------------------
  // Начальная инициализация
  if (!revision)
  {
    for (int p = 0; p < popSize; p++)
    {
      for (int c = 0; c < coords; c++)
      {
        a [p].c  [c] = u.RNDfromCI (rangeMin [c], rangeMax [c]);
        a [p].c  [c] = u.SeInDiSp (a [p].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);
        a [p].cB [c] = a [p].c [c];
      }
    }

    revision = true;
    return;
  }

  //----------------------------------------------------------------------------
  // Снижаем температуру
  temperature *= coolingRate;

  // Основной цикл по агентам популяции
  for (int p = 0; p < popSize; p++)
  {
    // Берем худший элемент из первой половины отсортированной популяции (с индексом popSize-1)
    // Помним, что в menu элементы отсортированы от лучшего к худшему
    ArrayCopy (a [p].c, menu [popSize - 1].c, 0, 0, WHOLE_ARRAY);

    // Решаем, создавать ли гибрид или экспериментировать с новым "блюдом"
    // Вероятность эксперимента зависит от температуры - в начале больше экспериментов
    if (u.RNDprobab () < (1.0 - menuInnovationRate * temperature))
    {
      // Выбираем "рецепт-донор" с вероятностью пропорциональной успешности блюда
      double r = u.RNDprobab ();
      r = pow (r, 2);                                         // Усиление предпочтения к лучшим блюдам
      int menuIND = (int)u.Scale (r, 0, 1.0, 0, popSize - 1); // Лучшие в начале массива

      // Для каждой координаты
      for (int c = 0; c < coords; c++)
      {
        // С вероятностью, зависящей от температуры, берем параметр из успешного блюда
        if (u.RNDprobab () < 0.8)
        {
          a [p].c [c] = menu [menuIND].c [c];
        }

        // Мутация с адаптивной вероятностью - чем дальше от лучшего решения и выше температура, тем больше мутаций
        double mutationRate = 0.1 + 0.4 * temperature * (double)(p) / popSize;
        if (u.RNDprobab () < mutationRate)
        {
          // Комбинация различных типов мутаций
          if (u.RNDprobab () < 0.5) a [p].c [c] = u.GaussDistribution (a [p].c [c], rangeMin [c], rangeMax [c], 2);
          else                      a [p].c [c] = u.RNDfromCI (rangeMin [c], rangeMax [c]); // Иногда полностью новое значение

          // Убедимся, что значение в допустимых пределах
          a [p].c [c] = u.SeInDiSp (a [p].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);
        }
      }
    }
    else // Создаем абсолютно новое "блюдо"
    {
      for (int c = 0; c < coords; c++)
      {
        // Вариация 1: полностью случайное значение
        if (u.RNDprobab () < 0.7)
        {
          a [p].c [c] = u.RNDfromCI (rangeMin [c], rangeMax [c]);
        }
        // Вариация 2: основано на лучшем найденном решении с большим отклонением
        else
        {
          a [p].c [c] = u.GaussDistribution (cB [c], rangeMin [c], rangeMax [c], 1);
        }

        a [p].c [c] = u.SeInDiSp (a [p].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);
      }
    }

    // Иногда добавляем элементы из лучшего решения напрямую (элитизм)
    if (u.RNDprobab () < 0.1)
    {
      int numEliteCoords = u.RNDintInRange (1, coords / 3); // Берем от 1 до 30% координат
      for (int i = 0; i < numEliteCoords; i++)
      {
        int c = u.RNDminusOne (coords);
        a [p].c [c] = cB [c]; // Берем значение из лучшего решения
      }
    }
  }
}
//——————————————————————————————————————————————————————————————————————————————

Метод "Revision" класса "C_AO_SRA" отвечает за обновление лучшего найденного решения и за управление общим "меню" решений в процессе работы алгоритма:

Поиск лучшего агента: проходит по всем агентам в текущей популяции и находит агента с наилучшей фитнес-функцией (f). Если найден новый лучший агент, обновляет значение "fB" и индекс "bestIND".

Обновление лучшего решения: если найден лучший агент (т.е. bestIND не равен -1), копирует его параметры решения (c) в переменную cB, представляющую текущее лучшее решение.

Обновление общего "меню": добавляет текущие параметры всех агентов в общее "меню", что позволяет сохранять выполненные эксперименты.

Сортировка меню: сортирует массив "menu" по фитнес-функции от лучших к худшим решениям, обеспечивая, что лучшие решения находятся в первой половине. Это будет использоваться в следующей итерации алгоритма.

Контроль температуры: устанавливает нижний порог для температуры, чтобы она не опускалась ниже "0.1", что предотвращает слишком быструю конвергенцию.
//——————————————————————————————————————————————————————————————————————————————
//--- Обновление лучшего решения с учетом жадного выбора и вероятности принятия худших решений
void C_AO_SRA::Revision ()
{
  int bestIND = -1;

  // Находим лучшего агента в текущей популяции
  for (int p = 0; p < popSize; p++)
  {
    if (a [p].f > fB)
    {
      fB = a [p].f;
      bestIND = p;
    }
  }

  // Если нашли лучшее решение, обновляем cB
  if (bestIND != -1) ArrayCopy (cB, a [bestIND].c, 0, 0, WHOLE_ARRAY);

  // Добавляем текущий набор блюд в общее "меню"
  for (int p = 0; p < popSize; p++)
  {
    menu [popSize + p] = a [p];
  }

  // Сортируем всё "меню" от лучших к худшим решениям
  // После сортировки, первая половина menu будет содержать лучшие решения,
  // которые будут использоваться на следующей итерации
  u.Sorting (menu, menuT, popSize * 2);

  // Не позволяем температуре упасть ниже определенного порога
  if (temperature < 0.1) temperature = 0.1;
}
//——————————————————————————————————————————————————————————————————————————————


Результаты тестов

Теперь можем посмотреть, как работает алгоритм SRA. Ниже представлена распечатка результатов тестирования:

SRA|Successful Restaurateur Algorithm|50.0|1.0|0.98|0.3|
=============================
5 Hilly's; Func runs: 10000; result: 0.9688326305968623
25 Hilly's; Func runs: 10000; result: 0.6345483084017249
500 Hilly's; Func runs: 10000; result: 0.292167027537253
=============================
5 Forest's; Func runs: 10000; result: 0.946368863880973
25 Forest's; Func runs: 10000; result: 0.5550607959254661
500 Forest's; Func runs: 10000; result: 0.19124225531141872
=============================
5 Megacity's; Func runs: 10000; result: 0.7492307692307693
25 Megacity's; Func runs: 10000; result: 0.4403076923076923
500 Megacity's; Func runs: 10000; result: 0.12526153846153956
=============================
All score: 4.90302 (54.48%)

Визуализация работы алгоритма SRA на тестовом стенде позволяет сделать выводы о характерных чертах стратегии поиска. В данном случае наблюдается широкое исследование пространства поиска: агенты равномерно распределены по всему пространству, изучая даже самые удаленные его уголки. При этом, не наблюдается заметных признаков группирования в локальных экстремумах, движения агентов выглядят хаотично.

Однако, несмотря на хорошую способность к исследованию, алгоритм демонстрирует некоторые недостатки в уточнении решений, что проявляется в относительно низкой точности сходимости. Следует отметить также небольшой разброс результатов тестирования.

Hilly

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

Forest

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

Megacity

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

По результатам проведенных тестов, алгоритм занимает 20 место в рейтинге самых сильных популяционных алгоритмов оптимизации. На данный момент в таблице представлены девять авторских алгоритмов оптимизации (joo), в число которых входит и новый алгоритм SRA.

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 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
13 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
14 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
15 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
16 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
17 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
18 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
19 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
20 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
21 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
22 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
23 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
24 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
25 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
26 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
27 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
28 (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
29 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
30 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
31 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
32 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
33 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
34 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
35 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
36 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
37 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
38 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
39 ADAMm adaptive moment estimation M 0,88635 0,44766 0,26613 1,60014 0,84497 0,38493 0,16889 1,39880 0,66154 0,27046 0,10594 1,03794 4,037 44,85
40 CGO chaos game optimization 0,57256 0,37158 0,32018 1,26432 0,61176 0,61931 0,62161 1,85267 0,37538 0,21923 0,19028 0,78490 3,902 43,35
41 ATAm artificial tribe algorithm M 0,71771 0,55304 0,25235 1,52310 0,82491 0,55904 0,20473 1,58867 0,44000 0,18615 0,09411 0,72026 3,832 42,58
42 ASHA artificial showering algorithm 0,89686 0,40433 0,25617 1,55737 0,80360 0,35526 0,19160 1,35046 0,47692 0,18123 0,09774 0,75589 3,664 40,71
43 ASBO adaptive social behavior optimization 0,76331 0,49253 0,32619 1,58202 0,79546 0,40035 0,26097 1,45677 0,26462 0,17169 0,18200 0,61831 3,657 40,63
44 MEC mind evolutionary computation 0,69533 0,53376 0,32661 1,55569 0,72464 0,33036 0,07198 1,12698 0,52500 0,22000 0,04198 0,78698 3,470 38,55
45 CSA circle search algorithm 0,66560 0,45317 0,29126 1,41003 0,68797 0,41397 0,20525 1,30719 0,37538 0,23631 0,10646 0,71815 3,435 38,17
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


Выводы

Разработав и протестировав алгоритм успешного ресторатора (SRA), я могу с уверенностью сказать, что он показал себя достойно. На данный момент алгоритм занимает 20-е место в рейтинговой таблице, что для новой концепции весьма неплохо. Анализируя результаты, я заметил некоторые особенности в его поведении. На задачах малой размерности наблюдается разброс результатов. Особенно это заметно на дискретной функции "Megacity", где алгоритм имеет особенно большой разброс значений. Эта функция очень сложная для алгоритмов и застревание в локальных экстремумах является больше правилом, чем исключением.

На задачах большой размерности SRA показывает результаты немного слабее, чем хотелось бы. Вероятно, это связано с тем, что в многомерных пространствах стратегия улучшения наихудших решений требует более тонкой настройки параметров температуры и скорости охлаждения.

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

Создавая алгоритм успешного ресторатора, я стремился не столько к достижению превосходства над существующими методами оптимизации, сколько к раскрытию новых концептуальных горизонтов через оригинальную жизненную метафору. Результаты исследования убедительно демонстрируют, что этот подход заслуживает своего места в экосистеме метаэвристических алгоритмов.

Неожиданно продуктивной оказалась идея фокусирования на худшем решении в популяции, используя его как базу для экспериментов — концепция, которая на первый взгляд может показаться бредовой. Однако, именно этот принцип "реабилитации аутсайдеров" раскрывает удивительный потенциал для оптимизации. Подобно искусному ресторатору, преображающему непопулярное блюдо в будущий хит, алгоритм трансформирует слабые решения в более совершенные, используя ингредиентный материал лидеров.

Этот опыт подтверждает ценное правило в научном поиске: даже самые неортодоксальные идеи при правильной реализации могут принести практическую пользу. Нестандартные подходы часто открывают те грани проблемы, которые остаются незамеченными при использовании традиционных методологий.

Tab

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

Chart

Рисунок 3. Гистограмма результатов тестирования алгоритмов (по шкале от 0 до 100, чем больше, тем лучше, где 100 — максимально возможный теоретический результат, в архиве скрипт для расчета рейтинговой таблицы)

Плюсы и минусы алгоритма SRA:

Плюсы:

  1. Простая реализация.
  2. Хорошие результаты.

Минусы:

  1. Без серьезных минусов.

К статье прикреплён архив с актуальными версиями кодов алгоритмов. Автор статьи не несёт ответственности за абсолютную точность в описании канонических алгоритмов, во многие из них были внесены изменения для улучшения поисковых возможностей. Выводы и суждения, представленные в статьях, основываются на результатах проведённых экспериментов.


Программы, используемые в статье

# Имя Тип Описание
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_SRA.mq5
Скрипт Испытательный стенд для SRA
Прикрепленные файлы |
SRA.ZIP (172.76 KB)
Удаленный профессиональный риск-менеджер Forex на Python Удаленный профессиональный риск-менеджер Forex на Python
Делаем удаленный профессиональный риск-менеджер Для Forex на Python, разворачиваем его на сервере по шагам. В процессе статьи поймем, как программно управлять рисками на Форекс, и как больше не слить депозит на Форекс.
Нейросети в трейдинге: Двойная кластеризация временных рядов (DUET) Нейросети в трейдинге: Двойная кластеризация временных рядов (DUET)
Фреймворк DUET предлагает инновационный подход к анализу временных рядов, сочетая временную и канальную кластеризацию для выявления скрытых закономерностей в анализируемых данных. Это позволяет адаптировать модели к изменениям во времени и повысить качество прогнозирования за счет устранения шума.
Создание самооптимизирующихся советников на языках MQL5 и Python Создание самооптимизирующихся советников на языках MQL5 и Python
В этой статье обсудим, как можно создать советник, способный самостоятельно выбирать и менять торговые стратегии в зависимости от преобладающих на рынке условий. Познакомимся с цепями Маркова и с их возможностями с точки зрения пользы для нас, алготрейдеров.
Возможности Мастера MQL5, которые вам нужно знать (Часть 34): Эмбеддинг цены с нетрадиционной RBM Возможности Мастера MQL5, которые вам нужно знать (Часть 34): Эмбеддинг цены с нетрадиционной RBM
Ограниченные машины Больцмана (Restricted Boltzmann Machines, RBM) — форма нейронной сети, разработанная в середине 1980-х годов, когда вычислительные ресурсы были непомерно дорогими. Вначале она опиралась на выборку Гиббса (Gibbs Sampling) и контрастивную дивергенцию (Contrastive Divergence) с целью уменьшения размерности или выявления скрытых вероятностей/свойств во входных обучающих наборах данных. Мы рассмотрим, как обратное распространение ошибки (backpropagation) может работать аналогичным образом, когда RBM "встраивает" (embeds) цены в прогнозирующий многослойный перцептрон.