preview
Оптимизация атмосферными облаками — Atmosphere Clouds Model Optimization (ACMO): Практика

Оптимизация атмосферными облаками — Atmosphere Clouds Model Optimization (ACMO): Практика

MetaTrader 5Тестер | 25 сентября 2024, 13:20
148 0
Andrey Dik
Andrey Dik

Содержание

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


Введение

В мире науки, где технологии и природа пересекаются, возникла уникальная идея метаэвристического алгоритма ACMO (Atmospheric Cloud Model Optimization) для оптимизации сложных задач. В предыдущей статье мы технически разобрали реализацию алгоритма, которая моделирует процесс формирования и движения облаков в атмосфере на основе различных метеорологических параметров. Что было проделано в первой части:  мы создали класс для управления моделированием облаков, содержащий методы для инициализации, движения облаков, обновления свойств регионов и других процессов.

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

Что еще осталось сделать? Реализовать функции для случайного размещения капель и их распределения между облаками. Завершить процесс дождя и обновление глобального решения. Провести тестирование модели на наших тестовых функциях с различными параметрами для оценки ее производительности и точности. Внесем изменения в процесс дождя и формирования капель для реализации более полноценного обмена информацией в популяции о перспективных регионах.


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

Опишем весь метеорологический процесс в виде псевдокода, что позволит нам на его основе собрать окончательную версию алгоритма:

1. На первой эпохе случайное размещение облаков:
   EnCk = EnM0;
   HeCk = HeM0;
//------------------------------------------------------------------------------
1.1 Движение облаков в сторону регионов с меньшим давлением:
   β = deltaP / normP
   d = Tck.x - Cck.c
   VC = β * d;
   Ck = Ck + VC

   изменение количества капель после движения:
   nk = nk × (1 - γ)

   изменение энтропии и гиперэнтропии:
   α = ΔP / ΔPmax;
   EnCk = EnCk * (1 + α)
   HeCk = HeCk * (1 - α)
//------------------------------------------------------------------------------
2. Процесс дождя, выпадение капель:
   распределение капель между облаками пропорционально влажности региона
   увеличение количества капель к существующим в облаках
//------------------------------------------------------------------------------
3. Расчет фитнес-функции для капель
//------------------------------------------------------------------------------
4. Обновление глобального решения и минимального давления в регионах, где выпадали капли
//------------------------------------------------------------------------------
5. Проверка на распад облаков и создание новых в регионах взамен распавшихся больше порога:
   правило распада в следствии расширения больше допустимого значения (разрыв облака):
   En > 5 * EnM0_t
   правило распада при содержании влаги ниже критического значения (высушивание облака):
   dCk < dMin

   пороговое значение, выше которого регионы могут образовать облака:
   HT = H_min + λ * (H_max - H_min);
//------------------------------------------------------------------------------
6. Энтропия и гиперэнтропия для новых облаков рассчитать:
   En = EnM0 / (1 + 2.72 ^ (-(8 - 16 * (t / maxT))))
   He = HeM0 / (1 + 2.72 ^ ((8 - 16 * (t / maxT))))

Итак, продолжим. Разберем метод "Moving" класса "C_AO_ACMO". Метод выполняет две операции: "MoveClouds (revision)" — отвечает за перемещение облаков, "RainProcess (revision)" — обрабатывает процесс дождя, который зависит от состояния облаков, а также от параметра "revision". Метод "Moving" выполняет два основных действия, связанных с динамикой облаков и процессом дождя. Он инкапсулирует логику перемещения облаков и их взаимодействия с процессом дождя. Таким образом, метод "Moving" служит для обновления состояния облаков и дождя в рамках симуляции погоды.

//——————————————————————————————————————————————————————————————————————————————
void C_AO_ACMO::Moving ()
{
  MoveClouds       (revision);
  RainProcess      (revision);
}
//——————————————————————————————————————————————————————————————————————————————

Подробно разберем следующий метод "MoveClouds" класса "C_AO_ACMO":

1. Первый блок (если "rev" равно "false"), метод создает облака со случайными центрами. Для каждого облака и каждой координаты:

  • Генерируется случайное значение центра облака в заданных диапазонах (функция "RNDfromCI").
  • Центр корректируется с помощью "SeInDiSp" для нормализации значений.
  • Определяется индекс региона, в котором находится облако, с помощью "GetRegionIndex".
  • Устанавливаются значения энтропии и начальной энтропии для облака.
  • Устанавливается начальное значение гиперэнтропии "hyperEntropy".
Метод завершает выполнение.

2. Второй блок (если "rev" равно "true"):

  • Если "rev" равно "true", метод начинает искать регионы с наименьшим давлением.
  • Создаются массивы для хранения индексов регионов с наименьшей влажностью "lHind" и для нормализации давления "normP".

3. Цикл для поиска региона с наименьшим давлением:

  • Для каждой координаты "c" определяется минимальное и максимальное давление среди всех регионов.
  • Индекс региона с наименьшим давлением сохраняется в массиве "lHind".
  • Нормализованное давление для каждой координаты сохраняется в "normP".

5. Перемещение облаков для каждого из них и каждой координаты:

  • Если облако уже находится в регионе с наименьшим давлением, пропускается итерация.
  • Выбирается случайный целевой регион с меньшим давлением.
  • Вычисляется разница давления между текущим и целевым регионом.
  • Нормализуется значение давления и вычисляется скорость перемещения облака "VC".
  • Центр облака обновляется с учетом скорости перемещения.
  • Индекс региона обновляется.
  • Энтропия облака обновляется с учетом изменения давления.
  • Уменьшается количество влаги в облаке и обновляется гиперэнтропия, ограничивая ее значение максимальным значением 8.

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

//——————————————————————————————————————————————————————————————————————————————
void C_AO_ACMO::MoveClouds (bool &rev)
{
  //----------------------------------------------------------------------------
  if (!rev)
  {
    //creating clouds with random centers---------------------------------------
    for (int i = 0; i < cloudsNumber; i++)
    {
      for (int c = 0; c < coords; c++)
      {
        clouds [i].center [c] = u.RNDfromCI (rangeMin [c], rangeMax [c]);
        clouds [i].center [c] = u.SeInDiSp  (clouds [i].center [c], rangeMin [c], rangeMax [c], rangeStep [c]);

        clouds [i].regionIndex [c] = GetRegionIndex (clouds [i].center [c], c);

        clouds [i].entropy      [c] = entropy [c] * EnM0;
        clouds [i].entropyStart [c] = clouds [i].entropy [c];
      }

      clouds [i].hyperEntropy = HeM0;
    }

    return;
  }

  //search for the region with the lowest pressure------------------------------
  int targetRegion = 0;

  int lHind []; //lowest humidity index
  ArrayResize     (lHind, coords);
  ArrayInitialize (lHind, 0);

  double normP [];
  ArrayResize (normP, coords);
  double minP;
  double maxP;

  for (int c = 0; c < coords; c++)
  {
    minP =  DBL_MAX;
    maxP = -DBL_MAX;

    for (int r = 0; r < regionsNumber; r++)
    {
      if (areas [c].regions [r].pressure < areas [c].regions [lHind [c]].pressure)
      {
        lHind [c] = r;
      }

      if (areas [c].regions [r].pressure < minP) minP = areas [c].regions [r].pressure;
      if (areas [c].regions [r].pressure > maxP) maxP = areas [c].regions [r].pressure;
    }

    normP [c] = maxP - minP;
  }

  //moving the cloud to a region with less pressure-----------------------------
  int    clRegIND = 0;
  double deltaP   = 0.0;
  double α        = 0.0; // Entropy factor
  double β        = 0.0; // Atmospheric pressure factor
  double VC       = 0.0; // Cloud velocity
  double d        = 0.0; // Cloud direction

  for (int i = 0; i < cloudsNumber; i++)
  {
    for (int c = 0; c < coords; c++)
    {
      //find a region with lower pressure---------------------------------------
      if (clouds [i].regionIndex [c] == lHind [c]) continue;

      clRegIND = clouds [i].regionIndex [c];

      do targetRegion = u.RNDminusOne (regionsNumber);
      while (areas [c].regions [clRegIND].pressure < areas [c].regions [targetRegion].pressure);

      //------------------------------------------------------------------------
      deltaP = areas [c].regions [clRegIND].pressure - areas [c].regions [targetRegion].pressure;

      β = deltaP / normP [c];
      d = areas [c].regions [targetRegion].x - areas [c].regions [clRegIND].centre;

      VC = β * d;

      clouds [i].center      [c] += VC;
      clouds [i].center      [c] = u.SeInDiSp (clouds [i].center [c], rangeMin [c], rangeMax [c], rangeStep [c]);
      clouds [i].regionIndex [c] = GetRegionIndex (clouds [i].center [c], c);

      α = β;
      clouds [i].entropy [c] *=(1 + α);
    }

    clouds [i].droplets     *=(1 - γ);
    clouds [i].hyperEntropy *=(1 + α);
    if (clouds [i].hyperEntropy > 8) clouds [i].hyperEntropy = 8;
  }
}
//——————————————————————————————————————————————————————————————————————————————

Далее разберем метод "GetRegionIndex" класса "C_AO_ACMO". Описание метода:

1. Вычисление позиции региона. Происходит вычисление индекса региона "regPos", в котором находится заданная точка "point" и с помощью функции "floor" округляется вниз до ближайшего целого числа.
2. Проверка границ. Этот блок проверяет, не выходит ли вычисленный индекс "regPos" за пределы допустимых значений (то есть ему нельзя превышать допустимое количество регионов).
3. Метод возвращает индекс региона, в котором находится точка.

Метод "GetRegionIndex" предназначен для определения индекса региона, в котором располагается заданная точка в пределах определенного диапазона. Он учитывает количество регионов и корректно обрабатывает случаи, когда точка находится на границе диапазона. 

//——————————————————————————————————————————————————————————————————————————————
int C_AO_ACMO::GetRegionIndex (double point, int ind)
{
  int regPos = (int)floor ((point - rangeMin [ind]) / ((rangeMax [ind] - rangeMin [ind]) / regionsNumber));

  if (regPos >= regionsNumber) regPos = regionsNumber - 1;

  return regPos;
}
//——————————————————————————————————————————————————————————————————————————————

Опишем следующий метод "RainProcess" класса "C_AO_ACMO":

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

  • Создаются два массива: "cloud" для хранения значений облаков и "drops" для хранения количества капель дождя для каждого облака.
  • Оба массива изменяются по размеру в зависимости от количества облаков "cloudsNumber".

3. Инициализация массива "cloud":

  • Если "rev" равно "false", все элементы массива "cloud" инициализируются значением "1.0".
  • Если иначе, массив "cloud" инициализируется значением "0.0" и дальше происходит вычисление влажности для каждого облака.

4. Вычисление влажности:

  • Для каждого облака и каждой координаты происходит вычисление влажности в зависимости от регионов.
  • Если влажность не равна "-DBL_MAX", она добавляется к соответствующему элементу массива "cloud". В противном случае добавляется минимальное значение капли "minGp".

5. Распределение капель:

  • Вызов метода "DropletsDistribution" для распределения капель на основе значений в массиве "cloud".

6. Основной цикл обработки капель, для каждого облака и каждой капли:

  • Вычисляются значения "dist", "centre", "xMin", "xMax".
  • Генерируется значение "x" с использованием нормального (гауссовского) распределения.
  • Если "x" выходит за пределы диапазона, оно корректируется с помощью метода "RNDfromCI".
  • Значение "x" нормализуется с помощью метода "SeInDiSp" и сохраняется в массиве "a".

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

//——————————————————————————————————————————————————————————————————————————————
void C_AO_ACMO::RainProcess (bool &rev)
{
  //to shed drops from every cloud----------------------------------------------
  double cloud [];
  int    drops [];
  ArrayResize (cloud, cloudsNumber);
  ArrayResize (drops, cloudsNumber);

  if (!rev)
  {
    ArrayInitialize (cloud, 1.0);
  }
  else
  {
    ArrayInitialize (cloud, 0.0);

    double humidity;

    for (int i = 0; i < cloudsNumber; i++)
    {
      for (int c = 0; c < coords; c++)
      {
        for (int r = 0; r < regionsNumber; r++)
        {
          humidity = areas [c].regions [clouds [i].regionIndex [r]].humidity;
          if (humidity != -DBL_MAX) cloud [i] += humidity;
          else                      cloud [i] += minGp;
        }
      }
    }
  }

  DropletsDistribution (cloud, drops);

  double dist   = 0.0;
  double centre = 0.0;
  double xMin   = 0.0;
  double xMax   = 0.0;
  double x      = 0.0;
  int    dCNT   = 0;

  for (int i = 0; i < cloudsNumber; i++)
  {
    for (int dr = 0; dr < drops [i]; dr++)
    {
      for (int c = 0; c < coords; c++)
      {
        dist   = clouds [i].entropy [c];
        centre = clouds [i].center  [c];
        xMin   = centre - dist;
        xMax   = centre + dist;

        x = u.GaussDistribution (centre, xMin, xMax, clouds [i].hyperEntropy);

        if (x < rangeMin [c]) x = u.RNDfromCI (rangeMin [c], centre);
        if (x > rangeMax [c]) x = u.RNDfromCI (centre, rangeMax [c]);

        x = u.SeInDiSp (x, rangeMin [c], rangeMax [c], rangeStep [c]);

        a [dCNT].c [c] = x;
      }

      dCNT++;
    }

    clouds [i].droplets += drops [i];
  }
}
//——————————————————————————————————————————————————————————————————————————————

Следующий метод "DropletsDistribution" класса "C_AO_ACMO" предназначен для распределения капель дождя между облаками на основе их влажности. Давайте разберем его по шагам.

2. Инициализация переменных:

  • minHumidity- инициализируется максимальным значением, чтобы можно было найти минимальную влажность.
  • indMinHumidity- хранит индекс облака с минимальной влажностью.
  • totalHumidity - используется для хранения суммы влажности всех облаков.

3. Суммирование влажности: в этом цикле происходит суммирование влажности всех облаков и определение облака с минимальной влажностью.

4. Пропорциональное распределение капель: для каждого облака рассчитывается количество капель, пропорциональное его влажности по отношению к общей влажности. Это значение сохраняется в массив "droplets".

5. Распределение оставшихся капель:

  • Сначала вычисляется общее количество распределенных капель "totalDrops".
  • Затем вычисляется количество оставшихся капель "remainingDrops".
  • Если есть оставшиеся капли, они добавляются к облаку с минимальной влажностью.

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

//——————————————————————————————————————————————————————————————————————————————
void C_AO_ACMO::DropletsDistribution (double &cloud [], int &droplets [])
{
  double minHumidity    = DBL_MAX;
  int    indMinHumidity = -1;
  double totalHumidity  = 0; //total amount of humidity in all clouds

  for (int i = 0; i < ArraySize (cloud); i++)
  {
    totalHumidity += cloud [i];

    if (cloud [i] < minHumidity)
    {
      minHumidity = cloud [i];
      indMinHumidity = i;
    }
  }

  // Filling the droplets array in proportion to the value in clouds
  for (int i = 0; i < ArraySize (clouds); i++)
  {
    droplets [i] = int((cloud [i] / totalHumidity)*popSize); //proportional distribution of droplets
  }

  // Distribute the remaining drops, if any
  int totalDrops = 0;

  for (int i = 0; i < ArraySize (droplets); i++)
  {
    totalDrops += droplets [i];
  }

  // If not all drops are distributed, add the remaining drops to the element with the lowest humidity
  int remainingDrops = popSize - totalDrops;

  if (remainingDrops > 0)
  {
    droplets [indMinHumidity] += remainingDrops; //add the remaining drops to the lightest cloud
  }
}
//——————————————————————————————————————————————————————————————————————————————

Метод "Revision" класса "C_AO_ACMO" выполняет обновление состояния системы, подробнее разберем метод:

1. Цикл по элементам массива "a" (популяция агентов оптимизации). В этом цикле происходит итерация по всем элементам массива "a" размером "popSize":

  • Если значение приспособленности "f" текущего элемента больше, чем текущее максимальное значение приспособленности "fB", то обновляется "fB", и индекс "ind" устанавливается в текущий индекс.
  • Также происходит поиск минимального значения приспособленности "f" среди всех элементов массива, и если текущее значение меньше, чем "minGp", то "minGp" обновляется.

2. Копирование данных: если был найден элемент с максимальным значением приспособленности "f" (то есть "ind" не равен -1), то происходит копирование данных из массива "c" элемента "a [ind]" в массив "cB".

3. Обновление свойств региона: вызывается метод "UpdateRegionProperties", который обновляет параметры влажности и давления в различных регионах.

4. Генерация облаков: вызывается метод "GenerateClouds", который отвечает за исчезновение старых облаков и создание новых.

5. Обновление состояния:

  • Устанавливается флаг "revision" в "true", что указывает на то, что первоначальное состояние системы пройдено.
  • Увеличивается счетчик "epochNow" для отслеживания количества эпох.

Метод "Revision" отвечает за обновление состояния системы, связанной с облаками. Он находит максимальное значение приспособленности "f", обновляет соответствующие параметры, инициализирует новые облака и обновляет свойства регионов. Этот метод является ключевым для поддержания актуальности данных в модели, что позволяет системе адаптироваться к изменениям.

//——————————————————————————————————————————————————————————————————————————————
void C_AO_ACMO::Revision ()
{
  //----------------------------------------------------------------------------
  int ind = -1;

  for (int i = 0; i < popSize; i++)
  {
    if (a [i].f > fB)
    {
      fB = a [i].f;
      ind = i;
    }

    if (a [i].f < minGp) minGp = a [i].f;
  }

  if (ind != -1) ArrayCopy (cB, a [ind].c, 0, 0, WHOLE_ARRAY);

  //----------------------------------------------------------------------------
  UpdateRegionProperties (); //updating humidity and pressure in the regions
  GenerateClouds         (); //disappearance of clouds and the creation of new ones

  revision = true;
  epochNow++;
}
//——————————————————————————————————————————————————————————————————————————————

Метод "GenerateClouds" класса "C_AO_ACMO" отвечает за создание облаков и управление их состоянием в зависимости от различных факторов, таких как влажность и энтропия. Описание метода:

1. Расчет порога влажности: вызывается функция "CalculateHumidityThreshold", которая возвращает значение порога влажности, необходимое для формирования облаков.

2. Структура для хранения индексов регионов:

  • Определяется структура "S_Areas", которая содержит массив индексов регионов, способных к образованию облаков. 
  • Массив "ar" инициализируется с размером, равным количеству координат "coords".

3. Сбор информации о регионах: в этом двойном цикле происходит проверка каждого региона на соответствие порогу влажности. Если влажность региона больше порога, индекс этого региона добавляется в массив "regsIND" соответствующей структуры "S_Areas".

4. Проверка условий распада облаков:

  • Для каждого облака проверяется, не превышает ли его энтропия определенный предел (в 5 раз больше начальной энтропии). Если это так, облако считается распавшимся.
  • Затем проверяется, если количество влаги в облаке меньше минимального значения "dMin", что также может привести к распаду облака.

5. Создание нового облака в самых влажных регионах:

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

Метод "GenerateClouds" управляет процессом создания и распада облаков на основе влажности и энтропии. Он собирает информацию о регионах, способных к образованию облаков, проверяет существующие облака на предмет распада и создает новые облака в подходящих регионах. Этот метод является ключевым для динамического управления состоянием облаков в модели.                                                                                                                                                    

//——————————————————————————————————————————————————————————————————————————————
void C_AO_ACMO::GenerateClouds ()
{
  //Collecting statistics of regions capable of creating clouds-----------------
  double Ht = CalculateHumidityThreshold ();

  struct S_Areas
  {
      int regsIND []; //index of the potential region
  };

  S_Areas ar [];
  ArrayResize (ar, coords);

  int sizePr = 0;

  for (int i = 0; i < coords; i++)
  {
    for (int r = 0; r < regionsNumber; r++)
    {
      if (areas [i].regions [r].humidity > Ht)
      {
        sizePr = ArraySize (ar [i].regsIND);
        sizePr++;
        ArrayResize (ar [i].regsIND, sizePr, coords);
        ar [i].regsIND [sizePr - 1] = r;
      }
    }
  }

  //Check the conditions for cloud decay----------------------------------------
  bool   cloudDecay = false;

  for (int i = 0; i < cloudsNumber; i++)
  {
    cloudDecay = false;

    //checking the cloud for too much entropy-----------------------------------
    for (int c = 0; c < coords; c++)
    {
      if (clouds [i].entropy [c] > 5.0 * clouds [i].entropyStart [c])
      {
        //Print ("Распад облака №", i, " - порвалось на эпохе ", epochNow);
        cloudDecay = true;
        break;
      }
    }

    //checking the cloud for decay----------------------------------------------
    if (!cloudDecay)
    {
      if (clouds [i].droplets < dMin)
      {
        //Print ("Распад облака №", i, " - высохло на эпохе ", epochNow);
        cloudDecay = true;
      }
    }

    //if the cloud has decayed--------------------------------------------------
    int regIND = 0;

    if (cloudDecay)
    {
      //creating a cloud in a very humid region---------------------------------
      for (int c = 0; c < coords; c++)
      {
        regIND = u.RNDminusOne (ArraySize (ar [c].regsIND));
        regIND = ar [c].regsIND [regIND];

        clouds [i].center      [c] = areas [c].regions [regIND].x;
        clouds [i].regionIndex [c] = regIND;
      }

      CalculateNewEntropy (clouds [i], epochNow);
    }
  }
}
//——————————————————————————————————————————————————————————————————————————————

Метод "CalculateHumidityThreshold" класса "C_AO_ACMO" отвечает за вычисление порога влажности, необходимого для формирования облаков, далее подробно по шагам:

1. Двойной цикл для поиска минимальной влажности. Внешний цикл проходит по всем координатам "coords", а внутренний цикл — по всем регионам "regionsNumber" в каждой координате. Если влажность региона не равна "-DBL_MAX", происходит проверка: если текущая влажность меньше текущего "H_min", то обновляется "H_min".

2. Метод возвращает значение, которое представляет собой "H_min", увеличенное на произведение "λ" и разности между "H_max" и "H_min", что представляет собой порог влажности, необходимый для формирования облаков.

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

//——————————————————————————————————————————————————————————————————————————————
double C_AO_ACMO::CalculateHumidityThreshold ()
{
  double H_max = fB;
  double H_min = DBL_MAX;

  for (int c = 0; c < coords; c++)
  {
    for (int r = 0; r < regionsNumber; r++)
    {
      if (areas [c].regions [r].humidity != -DBL_MAX)
      {
        if (areas [c].regions [r].humidity < H_min)
        {
          H_min = areas [c].regions [r].humidity;
        }
      }
    }
  }

  return H_min + λ * (H_max - H_min);
}
//——————————————————————————————————————————————————————————————————————————————

Метод "CalculateNewEntropy" класса "C_AO_ACMO" отвечает за вычисление новой энтропии и гиперэнтропии для облаков, представленных структурой "S_ACMO_Cloud". Разберем его:

1. Вычисление энтропии:

  • Цикл проходит по всем координатам "coords".
  • Для каждой координаты вычисляется новое значение энтропии "cl.entropy [c]", используя формулу: En = (entropy [c] * EnM0) / (1 + e ^ (-(8 - 16 * (t / epochs)))).
  • cl.entropyStart [c] и cl.entropy [c] инициализируются значением "entropy [c]", что служит для сохранения начального значения энтропии.

2. Вычисление гиперэнтропии: He = 1 / (1 + e ^ (8 - 16 * (t / epochs))).

3. Гиперэнтропия масштабируется с помощью метода "Scale" объекта "u", что позволяет масштабировать значение гиперэнтропии в заданный диапазон (от 0 до 8) с использованием параметров "HeM0" и 8.0.

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

//——————————————————————————————————————————————————————————————————————————————
void C_AO_ACMO::CalculateNewEntropy (S_ACMO_Cloud &cl, int t)
{
  //----------------------------------------------------------------------------
  //En: 1/(1+2.72^(-(8-16*(t/maxT))))
  for (int c = 0; c < coords; c++)
  {
    cl.entropy      [c] = entropy [c] * EnM0 / (1.0 + pow (M_E, (-(8.0 - 16.0 * (t / epochs)))));
    cl.entropyStart [c] = cl.entropy [c] = entropy [c];
  }

  //----------------------------------------------------------------------------
  //He: 1/(1+2.72^((8-16*(t/maxT))))
  cl.hyperEntropy = 1.0 / (1.0 + pow (M_E, ((8.0 - 16.0 * (t / epochs)))));

  cl.hyperEntropy = u.Scale (cl.hyperEntropy, 0.0, 8.0, HeM0, 8.0);
}
//——————————————————————————————————————————————————————————————————————————————

En and He 2

Рисунок 1. Варианты формул для вычисления коэффициента ζ в зависимости от текущей эпохи. Выбрать формулу и попробовать работу алгоритма можно с каждой из них (в коде строки закомментированы).


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

Переходим к тестированию алгоритма. Метеорологическая модель формирования облаков по замыслу авторов работает следующим образом:

//original version
ACMO|Atmospheric Cloud Model Optimization|50.0|5.0|10.0|0.2|5.0|5.0|0.9|0.2|
=============================
5 Hilly's; Func runs: 10000; result: 0.6017884495404766
25 Hilly's; Func runs: 10000; result: 0.3426222382089618
500 Hilly's; Func runs: 10000; result: 0.2526410178225118
=============================
5 Forest's; Func runs: 10000; result: 0.4780554376190664
25 Forest's; Func runs: 10000; result: 0.261057831391174
500 Forest's; Func runs: 10000; result: 0.17318135866144563
=============================
5 Megacity's; Func runs: 10000; result: 0.3507692307692307
25 Megacity's; Func runs: 10000; result: 0.16153846153846158
500 Megacity's; Func runs: 10000; result: 0.09632307692307775
=============================
All score: 2.71798 (30.20%)

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

ACMOm|Atmospheric Cloud Model Optimization|50.0|4.0|10.0|0.2|0.2|2.0|0.9|0.9|
=============================
5 Hilly's; Func runs: 10000; result: 0.9032099148349984
25 Hilly's; Func runs: 10000; result: 0.48545807643133143
500 Hilly's; Func runs: 10000; result: 0.30403284557071203
=============================
5 Forest's; Func runs: 10000; result: 0.8026793420899985
25 Forest's; Func runs: 10000; result: 0.3785708322859447
500 Forest's; Func runs: 10000; result: 0.1917777390119122
=============================
5 Megacity's; Func runs: 10000; result: 0.6230769230769231
25 Megacity's; Func runs: 10000; result: 0.244
500 Megacity's; Func runs: 10000; result: 0.10795384615384714
=============================
All score: 4.04076 (44.90%)

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

В конце для каждого облака обновляется общее количество капель (для облака — это показатель влажности), сброшенных из него, добавляя соответствующее значение из массива "drops". Метод "RainProcess" реализует механизм, который моделирует процесс дождя, учитывая влажность, распределение капель и взаимодействие с популяцией. Зеленым цветом выделено место внесения изменений в код.

Для каждого сгенерированного значения "x" происходит выбор случайного индекса "p" из популяции. В зависимости от вероятности (95%), происходит обновление значений в массиве "a", который представляет собой популяцию или набор решений. В конце для каждого облака обновляется общее количество капель, сброшенных из него, добавляя соответствующее значение из массива "drops".

//——————————————————————————————————————————————————————————————————————————————
void C_AO_ACMO::RainProcess (bool &rev)
{
  //to shed drops from every cloud----------------------------------------------
  double cloud [];
  int    drops [];
  ArrayResize (cloud, cloudsNumber);
  ArrayResize (drops, cloudsNumber);

  if (!rev)
  {
    ArrayInitialize (cloud, 1.0);
  }
  else
  {
    ArrayInitialize (cloud, 0.0);

    double humidity;

    for (int i = 0; i < cloudsNumber; i++)
    {
      for (int c = 0; c < coords; c++)
      {
        humidity = areas [c].regions [clouds [i].regionIndex [c]].humidity;
       
        if (humidity != -DBL_MAX) cloud [i] += humidity;

        else                      cloud [i] += minGp;
      }
    }
  }

  DropletsDistribution (cloud, drops);
  //ArrayPrint (drops);

  double dist   = 0.0;
  double centre = 0.0;
  double xMin   = 0.0;
  double xMax   = 0.0;
  double x      = 0.0;

  int    dCNT   = 0;


  for (int i = 0; i < cloudsNumber; i++)
  {
    for (int dr = 0; dr < drops [i]; dr++)
    {
      for (int c = 0; c < coords; c++)
      {
        dist   = clouds [i].entropy [c];
        centre = clouds [i].center  [c];
        xMin   = centre - dist;
        xMax   = centre + dist;

        x = u.GaussDistribution (centre, xMin, xMax, clouds [i].hyperEntropy);

        if (x < rangeMin [c]) x = u.RNDfromCI (rangeMin [c], centre);
        
        if (x > rangeMax [c]) x = u.RNDfromCI (centre, rangeMax [c]);

        x = u.SeInDiSp (x, rangeMin [c], rangeMax [c], rangeStep [c]);

        int p = u.RNDminusOne (popSize);

        if (a [p].f > a [dCNT].f)
        {
          if (u.RNDprobab () < 0.95) a [dCNT].c [c] = a [p].c [c];
        }

        else
        {
          a [dCNT].c [c] = x;
        }
      }
      dCNT++;
    }

    clouds [i].droplets += drops [i];
  }
}
//——————————————————————————————————————————————————————————————————————————————

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

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

Hilly

AСMO на тестовой функции Hilly

Forest

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

Megacity

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

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

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)
1ANSacross neighbourhood search0,949480,847760,438572,235811,000000,923340,399882,323230,709230,634770,230911,574916,13468,15
2CLAcode lock algorithm0,953450,871070,375902,200420,989420,917090,316422,222940,796920,693850,193031,683806,10767,86
3AMOmanimal migration ptimization M0,903580,843170,462842,209590,990010,924360,465982,380340,567690,591320,237731,396755,98766,52
4(P+O)ES(P+O) evolution strategies0,922560,881010,400212,203790,977500,874900,319452,171850,673850,629850,186341,490035,86665,17
5CTAcomet tail algorithm0,953460,863190,277702,094350,997940,857400,339492,194840,887690,564310,105121,557125,84664,96
6SDSmstochastic diffusion search M0,930660,854450,394762,179880,999830,892440,196192,088460,723330,611000,106701,441035,70963,44
7AAmarchery algorithm M0,917440,708760,421602,047800,925270,758020,353282,036570,673850,552000,237381,463235,54861,64
8ESGevolution of social groups0,999060,796540,350562,146161,000000,828630,131021,959650,823330,553000,047251,423585,52961,44
9SIAsimulated isotropic annealing0,957840,842640,414652,215130,982390,795860,205071,983320,686670,493000,090531,270205,46960,76
10ACSartificial cooperative search0,755470,747440,304071,806981,000000,888610,224132,112740,690770,481850,133221,305835,22658,06
11ASOanarchy society optimization0,848720,746460,314651,909830,961480,791500,238031,991010,570770,540620,166141,277525,17857,54
12TSEAturtle shell evolution algorithm0,967980,644800,296721,909490,994490,619810,227081,841390,690770,426460,135981,253225,00455,60
13DEdifferential evolution0,950440,616740,303081,870260,953170,788960,166521,908650,786670,360330,029531,176534,95555,06
14CROchemical reaction optimisation0,946290,661120,298531,905930,879060,584220,211461,674730,758460,426460,126861,311784,89254,36
15BSAbird swarm algorithm0,893060,649000,262501,804550,924200,711210,249391,884790,693850,326150,100121,120124,80953,44
16HSharmony search0,865090,687820,325271,878180,999990,680020,095901,775920,620000,422670,054581,097254,75152,79
17SSGsaplings sowing and growing0,778390,649250,395431,823080,859730,624670,174291,658690,646670,441330,105981,193984,67651,95
18BCOmbacterial chemotaxis optimization M0,759530,622680,314831,697040,893780,613390,225421,732590,653850,420920,144351,219124,64951,65
19(PO)ES(PO) evolution strategies0,790250,626470,429351,846060,876160,609430,195911,681510,590000,379330,113221,082554,61051,22
20TSmtabu search M0,877950,614310,291041,783300,928850,518440,190541,637830,610770,382150,121571,114494,53650,40
21BSObrain storm optimization0,937360,576160,296881,810410,931310,558660,235371,725340,552310,290770,119140,962224,49849,98
22WOAmwale optimization algorithm M0,845210,562980,262631,670810,931000,522780,163651,617430,663080,411380,113571,188034,47649,74
23AEFAartificial electric field algorithm0,877000,617530,252351,746880,927290,726980,180641,834900,666150,116310,095080,877544,45949,55
24ACOmant colony optimization M0,881900,661270,303771,846930,858730,586800,150511,596040,596670,373330,024720,994724,43849,31
25BFO-GAbacterial foraging optimization - ga0,891500,551110,315291,757900,969820,396120,063051,428990,726670,275000,035251,036924,22446,93
26ABHAartificial bee hive algorithm0,841310,542270,263041,646630,878580,477790,171811,528180,509230,338770,103970,951974,12745,85
27ACMOatmospheric cloud model optimization0,903210,485460,304031,692700,802680,378570,191781,373030,623080,244000,107950,975034,04144,90
28ASBOadaptive social behavior optimization0,763310,492530,326191,582020,795460,400350,260971,456770,264620,171690,182000,618313,65740,63
29MECmind evolutionary computation0,695330,533760,326611,555690,724640,330360,071981,126980,525000,220000,041980,786983,47038,55
30IWOinvasive weed optimization0,726790,522560,331231,580580,707560,339550,074841,121960,423330,230670,046170,700173,40337,81
31Micro-AISmicro artificial immune system0,795470,519220,308611,623300,729560,368790,093981,192330,376670,158670,028020,563353,37937,54
32COAmcuckoo optimization algorithm M0,758200,486520,313691,558410,740540,280510,055991,077040,505000,174670,033800,713473,34937,21
33SDOmspiral dynamics optimization M0,746010,446230,296871,489120,702040,346780,109441,158260,428330,167670,036630,632633,28036,44
34NMmNelder-Mead method M0,738070,505980,313421,557470,636740,283020,082211,001970,446670,186670,040280,673623,23335,92
35FAmfirefly algorithm M0,586340,472280,322761,381380,684670,374390,109081,168140,286670,164670,047220,498553,04833,87
36GSAgravitational search algorithm0,647570,491970,300621,440160,539620,363530,099451,002600,326670,122000,019170,467832,91132,34
37BFObacterial foraging optimization0,611710,432700,313181,357590,544100,215110,056760,815970,421670,138000,031950,591622,76530,72
38ABCartificial bee colony0,633770,424020,308921,366710,551030,218740,056230,826000,340000,142000,031020,513022,70630,06
39BAbat algorithm0,597610,459110,352421,409150,403210,193130,071750,668100,210000,101000,035170,346172,42326,93
40AAAalgae adaptive algorithm0,500070,320400,255251,075720,370210,222840,167850,760890,278460,148000,097550,524022,36126,23
41SAsimulated annealing0,557870,421770,315491,295130,349980,152590,050230,552800,311670,100330,028830,440832,28925,43
42IWDmintelligent water drops M0,545010,378970,301241,225220,461040,147040,043690,651770,258330,097000,023080,378422,25525,06
43PSOparticle swarm optimisation0,597260,369230,299281,265770,372370,163240,070100,605720,256670,080000,021570,358232,23024,77
44Boidsboids algorithm0,433400,305810,254250,993460,357180,201600,157080,715860,278460,142770,098340,519572,22924,77
45MAmonkey algorithm0,591070,426810,318161,336040,311380,140690,066120,518190,228330,085670,027900,341902,19624,40


Выводы

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

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

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

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

Tab

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

chart

Рисунок 3. Цветовая градация алгоритмов по соответствующим тестам. Белым цветом подсвечены результаты больше или равные 0.99

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

Плюсы:

  1. Встроенные механизмы против застревания.
  2. Неплохая сходимость.
  3. Неплохая масштабируемость.

Минусы:

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

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

Прикрепленные файлы |
ACMO.ZIP (38.88 KB)
Возможности Мастера MQL5, которые вам нужно знать (Часть 19): Байесовский вывод Возможности Мастера MQL5, которые вам нужно знать (Часть 19): Байесовский вывод
Байесовский вывод — это применение теоремы Байеса для обновления вероятностной гипотезы по мере поступления новой информации. Это намекает на необходимость адаптации в анализе временных рядов, и поэтому мы рассмотрим, как мы могли бы использовать его при создании пользовательских классов не только применительно к сигналам, но и для управления капиталом и трейлинг-стопами.
Нейросети в трейдинге: Безмасочный подход к прогнозированию ценового движения Нейросети в трейдинге: Безмасочный подход к прогнозированию ценового движения
В данной статье предлагаем познакомиться с методом Mask-Attention-Free Transformer (MAFT) и его применение в области трейдинга. В отличие от традиционных Transformer, требующих маскирования данных при обработке последовательностей, MAFT оптимизирует процесс внимания, устраняя необходимость в маскировании, что значительно повышает вычислительную эффективность.
DoEasy. Сервисные функции (Часть 3): Паттерн "Внешний бар" DoEasy. Сервисные функции (Часть 3): Паттерн "Внешний бар"
В статье разработаем паттерн Price Action "Внешний Бар" в библиотеке DoEasy и оптимизируем методы доступа к управлению ценовыми паттернами. Кроме того, проведём работу по исправлению ошибок и недоработок, выявленных при тестировании библиотеки.
Оптимизация атмосферными облаками — Atmosphere Clouds Model Optimization (ACMO): Теория Оптимизация атмосферными облаками — Atmosphere Clouds Model Optimization (ACMO): Теория
Статья посвящена метаэвристическому алгоритму Atmosphere Clouds Model Optimization (ACMO), который моделирует поведение облаков для решения задач оптимизации. Алгоритм использует принципы генерации, движения и распространения облаков, адаптируясь к "погодным условиям" в пространстве решений. Статья раскрывает, как метеорологическая симуляция алгоритма находит оптимальные решения в сложном пространстве возможностей и подробно описывает этапы работы ACMO, включая подготовку "неба", рождение облаков, их перемещение и концентрацию дождя.