English Русский Español Português
preview
珊瑚礁优化算法(CRO)

珊瑚礁优化算法(CRO)

MetaTrader 5交易 |
64 0
Andrey Dik
Andrey Dik


内容

  1. 引言
  2. 算法实现
  3. 测试结果


引言

近期,基于自然过程和系统的仿生算法引发了开发人员的广泛关注。由S. Salcedo-Sanz等人于2014年首次提出的珊瑚礁优化(CRO)算法,或许是最引人注意的算法之一。

CRO算法基于对自然界中珊瑚礁形成与发育过程的建模。这些过程涵盖了珊瑚繁殖的多种机制(包括群体产卵、体内受精以及无性繁殖)、礁石有限空间的竞争,以及弱势个体的死亡。正如进化在自然界中创造出具有韧性和适应性的珊瑚礁一样,CRO算法能够探索搜索空间,并为各类问题找到最优或近似最优的解决方案。

在本文中,我们提出了一种改进版的CRO算法(CROm),通过引入基于逆幂律分布的淘汰机制,在最优解的邻域内生成新解。这样不仅保留了传统CRO算法的探索能力,以及全局探索与局部开发之间的自然平衡,还增加了一种更高效的机制,能够更精准地锁定有前景的搜索区域,从而更快地收敛到最优解。

我们将在一系列经典优化基准函数上对所提出的算法进行广泛测试,以证明其相较于原始CRO算法和其他现代元启发式算法的性能提升。实验结果表明,该方法对于具有多模态目标函数和复杂搜索空间结构的问题尤为有效。

本文结构如下:首先,我们回顾标准CRO算法的基本概念和运行原理;然后,详细描述所提出的改进及其理论依据。接下来,对算法进行实验评估并对结果进行分析。最后,我们讨论所得结果、该方法的局限性以及未来研究的可能方向。


算法实现

CRO的基本思想是模拟珊瑚群落在礁石上生长并竞争空间,最终形成最优结构的过程。礁石上的每一株珊瑚都代表所考虑优化问题的一个潜在解。

珊瑚礁石被建模为一个二维的N×M网格。每个网格单元要么被珊瑚占据,要么为空。珊瑚是优化问题的一个编码解。对于每一株珊瑚,都会确定一个适应度(健康度)函数,该函数对应于优化问题的目标函数。

参数ρ₀ ∈ (0,1)用于确定算法开始时珊瑚占据礁石的比例,即占据单元与总单元数的初始比值。礁石的初始化过程如下:

  1. 指定礁石大小为N×M以及初始填充比例ρ₀。
  2. 随机选择⌊ρ₀ × N × M⌋个礁石单元来安置初始珊瑚。
  3. 在搜索区域内随机生成初始珊瑚,并将其放置在所选单元中。

礁石初始化完成后,开始由多个阶段组成的礁石形成和发育的一个迭代过程:

群体产卵繁殖。对于这种繁殖方式,会从现有珊瑚中选择一定比例Fₑ的珊瑚。所选珊瑚两两配对,并使用交叉算子产生后代。每对珊瑚通过交叉算子(普通平均法)产生一个幼虫。

体内受精繁殖。 剩余的珊瑚(1-Fₑ比例)进行体内受精繁殖,每株珊瑚通过变异产生后代。对于每一株被选中进行体内受精繁殖的珊瑚,都使用变异算子产生一个幼虫。幼虫通常代表编码解的一个微小随机变异。幼虫附着。幼虫形成后,在繁殖阶段,每只幼虫都试图在礁石上找到自己的位置。附着过程遵循以下规则:

  1. 幼虫在珊瑚礁石上随机选择一个单元(i, j)。
  2. 如果该单元为空,则幼虫占据该单元。
  3. 如果该单元已被占据,则只有当幼虫的适应度更高时,即f(幼虫) > f(Ξᵢⱼ),幼虫才能取代现有的珊瑚。
  4. 如果未发生取代,则幼虫可能会尝试在其他地方附着(最多尝试k次)。
  5. 如果经过k次尝试后,幼虫仍未找到附着位置,则幼虫死亡。

无性繁殖(出芽生殖)。礁石中表现最优的珊瑚(占比Fₐ)可通过无性繁殖生成与自身完全相同的个体(克隆体)。具体如下:

  1. 根据适应度函数对珊瑚进行排序。
  2. 选取最优的Fₐ × 100%的珊瑚进行无性繁殖。
  3. 每株被选中的珊瑚生成一个克隆体,该克隆体尝试按照幼虫附着的规则在礁石上定居繁殖。

捕食(淘汰)。每次迭代结束时,珊瑚礁石中表现最差的珊瑚可能以Pd概率死亡,从而为后续迭代中的新珊瑚腾出空间。

礁石的形成过程将持续迭代,直至满足预设的停止条件(如达到最大迭代次数)。停止后,珊瑚礁石中表现最优的珊瑚即为所求优化问题的解。

CRO算法

图例1. CRO算法的工作流程如下:

上图展示了算法的六个主要阶段:

  1. 初始化(ρ₀ = 0.6) :展示了一个二维网格(珊瑚礁石),其中部分单元格被彩色珊瑚占据,代表不同的解。
  2. 群体产卵繁殖(Fb = 0.9) :珊瑚两两配对,通过交叉操作生成幼虫。
  3. 体内受精繁殖(1-Fb = 0.1) :个体珊瑚通过变异操作产生幼虫。
  4. 幼虫附着(k = 3次尝试) :幼虫在珊瑚礁石上寻找定居位置,包括成功和失败的尝试。
  5. 无性繁殖(Fa = 0.1):表现最优的珊瑚(标记为星号)产生与自身完全相同的克隆体。
  6. 捕食(Fd = 0.1, Pd = 0.05):表现最差的珊瑚从礁石中被移除。
接下来,我们将编写该算法的伪代码。

输入:礁石参数(N, M, ρ₀, Fₑ, Fₐ, Fd, Pd, k)
输出:找到的最优解

1. 初始化:
   - 创建N×M的礁石
   - 在⌊ρ₀ × N × M⌋个单元格中随机放置珊瑚
   - 计算每株珊瑚的适应度

2. 直到满足停止准则:
   3. 群体产卵繁殖:
      - 选择占比Fₑ的珊瑚参与繁殖
      - 珊瑚两两配对,通过交叉操作生成幼虫
   
   4. 体内受精繁殖:
      - 剩余珊瑚(1-Fₑ)通过变异操作生成幼虫
   
   5. 幼虫附着:
      - 对于每只幼虫:
        - 尝试占据一个随机的礁石单元格
        - 如果单元格已被占据,且幼虫适应度更高,则取代原有珊瑚
        - 如果附着失败,则重新尝试(最多k次)
   
   6. 无性繁殖:
      - 根据适应度对珊瑚进行排序
      - 最优的Fₐ珊瑚生成克隆体
      - 克隆体尝试在礁石上定居
   
   7. 捕食:
      - 以概率Pd实行淘汰操作
      - 移除表现最差珊瑚中的Fd占比

8. 返回礁石中最优的珊瑚

接下来,我们来实现CRO算法代码。让我们创建一个名为C_AO_CRO的类,该类实现CRO算法并继承自C_AO基类。 

CRO参数:

该类声明了控制算法行为的参数:

  • popSize — 珊瑚种群大小。
  • reefRows — 礁石高度(网格的行数)。
  • reefCols — 礁石宽度(网格的列数)。
  • rho0 — 初始珊瑚礁石的占用率。即算法开始时礁石单元格中被珊瑚占据的百分比。
  • Fb — 参与群体产卵繁殖的珊瑚比例。
  • Fa — 参与无性繁殖(分裂)的珊瑚比例。
  • Fd — 因适应度低而被移除的珊瑚比例。
  • Pd — 珊瑚被淘汰的概率。
  • attemptsNum — 幼虫尝试在礁石上定居的次数。

类方法:

  • SetParams() — 根据“params”数组中存储的值设置算法参数。该数组允许我们在执行过程中动态更改算法参数。
  • Init() — 初始化方法,接受优化变量的搜索范围(rangeMinP, rangeMaxP, rangeStepP)和迭代次数(epochsP)。Init方法执行启动算法所需的准备工作,如初始化种群和礁石。
  • Moving() — 珊瑚在礁石上移动的基本逻辑。 
  • Revision() — 调整珊瑚在礁石上的位置。
  • InitReef() — 初始化礁石结构,为珊瑚的定居做准备。
  • LarvaSettling() — 确定珊瑚幼虫将在礁石的哪个位置定居,模拟新珊瑚对礁石的殖民过程。“larva”参数代表珊瑚幼虫。
  • BroadcastSpawning() — 珊瑚向水中释放幼虫。
  • Brooding() — 幼虫在珊瑚体内发育。
  • AsexualReproduction() — 珊瑚分裂形成新的群体。
  • Depredation() — 珊瑚被淘汰。
  • GetReefCoordIndex() — 将礁石坐标(行和列)转换为一维数组的索引。
  • SortAgentsByFitness() — 根据适应度对珊瑚进行排序。

私有变量:

  • totalReefSize — 礁石的总大小(reefRows和reefCols的乘积)。
  • occupied[] — 布尔值数组,指示每个礁石单元格是否被珊瑚占据。
  • reefIndices[] — 包含占据礁石单元格的珊瑚索引的数组(来自C_AO基类的a[]数组)。
//——————————————————————————————————————————————————————————————————————————————
class C_AO_CRO : public C_AO
{
  public: //--------------------------------------------------------------------
  ~C_AO_CRO () { }
  C_AO_CRO ()
  {
    ao_name = "CRO";
    ao_desc = "Coral Reef Optimization";
    ao_link = "https://www.mql5.com/en/articles/17760";
    
    popSize     = 50;      // population size
    reefRows    = 20;      // reef height
    reefCols    = 20;      // reef width
    rho0        = 0.2;     // initial reef occupancy
    Fb          = 0.99;    // fraction of corals for broadcast spawning
    Fa          = 0.01;    // fraction of corals for asexual reproduction
    Fd          = 0.8;     // fraction of corals to remove
    Pd          = 0.9;     // probability of destruction
    attemptsNum = 20;      // number of attempts for larvae to settle

    ArrayResize (params, 9);

    params [0].name = "popSize";     params [0].val = popSize;
    params [1].name = "reefRows";    params [1].val = reefRows;
    params [2].name = "reefCols";    params [2].val = reefCols;
    params [3].name = "rho0";        params [3].val = rho0;
    params [4].name = "Fb";          params [4].val = Fb;
    params [5].name = "Fa";          params [5].val = Fa;
    params [6].name = "Fd";          params [6].val = Fd;
    params [7].name = "Pd";          params [7].val = Pd;
    params [8].name = "attemptsNum"; params [8].val = attemptsNum;
  }

  void SetParams ()
  {
    popSize     = (int)params [0].val;
    reefRows    = (int)params [1].val;
    reefCols    = (int)params [2].val;
    rho0        = params      [3].val;
    Fb          = params      [4].val;
    Fa          = params      [5].val;
    Fd          = params      [6].val;
    Pd          = params      [7].val;
    attemptsNum = (int)params [8].val;
  }

  bool Init (const double &rangeMinP  [],  // minimum search range
             const double &rangeMaxP  [],  // maximum search range
             const double &rangeStepP [],  // search step
             const int     epochsP = 0);   // number of epochs

  void Moving        ();
  void Revision      ();

  //----------------------------------------------------------------------------
  int                reefRows;      // reef height
  int                reefCols;      // reef width
  double             rho0;          // initial reef occupancy
  double             Fb;            // fraction of corals for broadcast spawning
  double             Fa;            // fraction of corals for asexual reproduction
  double             Fd;            // fraction of corals to remove
  double             Pd;            // probability of destruction
  int                attemptsNum;   // number of attempts for larvae to settle

  private: //-------------------------------------------------------------------
  int                totalReefSize; // total reef size
  bool   occupied    [];   // flags of reef cell occupancy
  int                reefIndices []; // agent indices in a[] corresponding to occupied cells

  // Auxiliary methods
  void   InitReef            ();
  int    LarvaSettling       (S_AO_Agent &larva);
  void   BroadcastSpawning   (S_AO_Agent &larvae [], int &larvaCount);
  void   Brooding            (S_AO_Agent &larvae [], int &larvaCount);
  void   AsexualReproduction ();
  void   Depredation         ();
  int    GetReefCoordIndex   (int row, int col);
  void   SortAgentsByFitness (int &indices [], int &count);
};
//——————————————————————————————————————————————————————————————————————————————

Init方法用于初始化CRO算法:首先调用基类的StandardInit方法,接下来计算总礁石规模(totalReefSize),确定初始珊瑚数量(initialPopSize),初始化"occupied"数组和"reefIndices"数组,调用InitReef()方法将珊瑚放置在礁石上,最后在成功时返回"true"。

//——————————————————————————————————————————————————————————————————————————————
bool C_AO_CRO::Init (const double &rangeMinP  [],  // minimum search range
                     const double &rangeMaxP  [],  // maximum search range
                     const double &rangeStepP [],  // search step
                     const int     epochsP = 0)    // number of epochs
{
  // Standard initialization of the parent class
  if (!StandardInit (rangeMinP, rangeMaxP, rangeStepP)) return false;

  //----------------------------------------------------------------------------
  // Calculate the reef total size
  totalReefSize = reefRows * reefCols;

  // The number of starting corals should not exceed popSize
  int initialPopSize = (int)MathRound (rho0 * totalReefSize);
  if (initialPopSize > popSize) initialPopSize = popSize;

  // Initialize the occupancy array and indices
  ArrayResize (occupied, totalReefSize);
  ArrayResize (reefIndices, totalReefSize);

  // Fill the arrays with initial values
  for (int i = 0; i < totalReefSize; i++)
  {
    occupied    [i] = false;
    reefIndices [i] = -1;
  }

  // Reef initialization
  InitReef ();

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

C_AO_CRO类的InitReef()方法用于在礁石上初始化珊瑚的初始种群。首先,我们根据礁石给定的初始密度(rho0)计算需要初始化的珊瑚数量。该数量受种群规模(popSize)限制。接下来,针对每只珊瑚,在珊瑚礁石上分配一个随机且未被占用的位置。一旦找到这样的位置,就将其标记为已占用,并在reefIndices数组中将该珊瑚与这个位置关联起来。之后,为每只珊瑚生成坐标。每个坐标均在给定的边界范围(rangeMin,rangeMax)内随机选取,并使用u.SeInDiSp函数进行离散化处理,该函数会考虑离散化步长(rangeStep)。这样确保初始解(珊瑚)在搜索空间内均匀且可控地分布。

//——————————————————————————————————————————————————————————————————————————————
void C_AO_CRO::InitReef ()
{
  // Number of starting corals in the reef (based on rho0)
  int initialCorals = (int)MathRound (rho0 * totalReefSize);

  // The number of starting corals should not exceed the population size
  if (initialCorals > popSize) initialCorals = popSize;

  // Initialize initialCorals random positions in the reef
  for (int i = 0; i < initialCorals; i++)
  {
    int pos;
    // Look for a free position
    do
    {
      pos = (int)MathFloor (u.RNDfromCI (0, totalReefSize));
      // Protection against exceeding the array size
      if (pos < 0) pos = 0;
      if (pos >= totalReefSize) pos = totalReefSize - 1;
    }
    while (occupied [pos]);

    // Create a new coral at the found position
    occupied [pos] = true;
    reefIndices [pos] = i;

    // Generate random coordinates for a new coral
    for (int c = 0; c < coords; c++)
    {
      double coordinate = u.RNDfromCI (rangeMin [c], rangeMax [c]);
      a [i].c [c] = u.SeInDiSp (coordinate, rangeMin [c], rangeMax [c], rangeStep [c]);
    }
  }
}
//——————————————————————————————————————————————————————————————————————————————

Moving()方法用于对珊瑚种群进行初始评估。如果"revision"为false,那么该方法会遍历礁石上的所有位置。对于每个已被占用的位置(通过“occupied”数组元素的值确定),该方法会从reefIndices数组中获取位于该位置的珊瑚索引。如果得到的索引idx有效,则会计算该珊瑚的适应度。

需要注意的是,Moving()方法本身并不直接计算适应度,而只是提供计算适应度所需的信息。在遍历完礁石上的所有位置后,该方法会将"revision"的值设置为"true",以防止在同一优化迭代中再次运行珊瑚评估循环。本质上讲,Moving()方法充当计算珊瑚适应度的触发器,确保该过程在每次优化迭代中仅执行一次。

//——————————————————————————————————————————————————————————————————————————————
void C_AO_CRO::Moving ()
{
  if (!revision)
  {
    // Initial assessment of all corals in the reef
    for (int i = 0; i < totalReefSize; i++)
    {
      if (occupied [i])
      {
        int idx = reefIndices [i];
        if (idx >= 0 && idx < popSize)
        {
          // Calculating fitness does not require using GetFitness()
          // since it will be evaluated in external code (in FuncTests)
        }
      }
    }

    revision = true;
  }
}
//——————————————————————————————————————————————————————————————————————————————

Revision()方法用于更新全局最优解。该方法会在礁石上搜索适应度优于当前全局最优解的珊瑚,并将其替换为新的全局最优解。同时,它会创建一个数组,为通过繁殖产生的幼体预留位置。随后,该方法启动有性繁殖过程,调用BroadcastSpawning和Brooding方法以培育幼体。下一步涉及幼体定居繁殖,调用LarvaSettling方法确定礁石上新幼体的位置。接着启动无性繁殖过程,随后进行淘汰。简言之,该方法负责更新最优解、繁殖珊瑚、安置幼体,并模拟捕食对种群的影响。

//——————————————————————————————————————————————————————————————————————————————
void C_AO_CRO::Revision ()
{

  // Update the global best solution
  for (int i = 0; i < totalReefSize; i++)
  {
    if (occupied [i] && a [reefIndices [i]].f > fB)
    {
      fB = a [reefIndices [i]].f;
      ArrayCopy (cB, a [reefIndices [i]].c, 0, 0, WHOLE_ARRAY);
    }
  }

  // Form an array to store larvae
  S_AO_Agent larvae [];
  ArrayResize (larvae, totalReefSize * 2); // Allocate with reserve
  int larvaCount = 0;

  // Stage 1: Broadcast Spawning
  BroadcastSpawning (larvae, larvaCount);

  // Stage 2: Brooding
  Brooding (larvae, larvaCount);

  // Calculate the fitness function for each larva
  // (will be executed in external code in FuncTests)

  // Stage 3: Larval settlement
  for (int i = 0; i < larvaCount; i++)
  {
    LarvaSettling (larvae [i]);
  }

  // Stage 4: Asexual reproduction
  AsexualReproduction ();

  // Stage 5: Depredation
  Depredation ();
}
//——————————————————————————————————————————————————————————————————————————————

LarvaSettling方法模拟幼体在珊瑚礁石上的定居繁殖过程。该方法会尝试为幼体寻找一个合适的位置,要么将其安置在空位上,要么替换掉一个现有但适应度较低的珊瑚。在尝试定居繁殖时,幼体会进行attemptsNum次尝试。对于每次尝试,会在礁石上随机选择一个位置。如果所选位置为空(未被珊瑚占据),该方法会在a[]智能体数组中搜索一个空闲索引;如果找到空闲索引,幼体会将其解(c[]坐标和f适应度)复制到智能体数组的相应单元格中。

此时,会更新礁石位置已被占用的信息,且该方法会返回成功占据的pos位置的索引。如果所选位置已被占据,该方法会比较幼体的适应度与该位置上当前珊瑚的适应度。如果幼体的适应度更高,它会将现有珊瑚替换掉,即将其参数复制到智能体数组中的对应单元格,并返回发生替换的pos位置索引。如果幼体在所有尝试后均未能成功定居繁殖(既未能在空位上安置,也未能替换掉现有珊瑚),则该方法返回-1。

//——————————————————————————————————————————————————————————————————————————————
int C_AO_CRO::LarvaSettling (S_AO_Agent &larva)
{
  // Try to settle the larva attemptsNum times
  for (int attempt = 0; attempt < attemptsNum; attempt++)
  {
    // Select a random position in the reef
    int pos = (int)MathFloor (u.RNDfromCI (0, totalReefSize));

    // Check that the position is within the array
    if (pos < 0 || pos >= totalReefSize) continue;

    // If the position is free, populate the larva
    if (!occupied [pos])
    {
      // Search for a free index in the agents array
      int newIndex = -1;
      for (int i = 0; i < popSize; i++)
      {
        bool used = false;
        for (int j = 0; j < totalReefSize; j++)
        {
          if (reefIndices [j] == i)
          {
            used = true;
            break;
          }
        }

        if (!used)
        {
          newIndex = i;
          break;
        }
      }

      if (newIndex != -1)
      {
        // Copy the larva's solution
        ArrayCopy (a [newIndex].c, larva.c, 0, 0, WHOLE_ARRAY);
        a [newIndex].f = larva.f;

        // Update information about the reef
        occupied [pos] = true;
        reefIndices [pos] = newIndex;

        return pos;
      }
    }
    // If the position is occupied, check if the larva is better than the current coral
    else
      if (occupied [pos] && reefIndices [pos] >= 0 && reefIndices [pos] < popSize && larva.f > a [reefIndices [pos]].f)
      {
        // The larva displaces the existing coral
        ArrayCopy (a [reefIndices [pos]].c, larva.c, 0, 0, WHOLE_ARRAY);
        a [reefIndices [pos]].f = larva.f;

        return pos;
      }
  }

  // If the larva failed to settle, return -1
  return -1;
}
//——————————————————————————————————————————————————————————————————————————————

BroadcastSpawning方法模拟了珊瑚的广播产卵行为。该方法执行以下基本步骤:首先,找出礁石上所有被珊瑚占据的位置的索引;接着,根据Fb(孵育比例)参数确定参与产卵的珊瑚数量 —— 即参与广播产卵的珊瑚所占比例;然后,打乱被占据珊瑚的索引顺序,并从中选取配对进行产卵。通过交叉操作生成幼体:对于每一对珊瑚,创建一个新幼体,其坐标计算为父母珊瑚坐标的平均值,并添加少量随机变异。交叉操作的目的是融合父母双方的优良特性,所生成的幼体会被添加到"larvae"数组中。

要点:

  • 这里的参数Fb表示参与广播产卵的珊瑚比例,而在孵育过程中,则表示参与孵育孕育的珊瑚比例。
  • 交叉操作与变异操作能够增加种群的遗传多样性。
  • 该方法的目的是通过结合亲代珊瑚的基因来培育新的幼体,以便进一步实现珊瑚礁石的集群。该方法采用成对交叉的方式进行操作。
//——————————————————————————————————————————————————————————————————————————————
void C_AO_CRO::BroadcastSpawning (S_AO_Agent &larvae [], int &larvaCount)
{
  // Find all occupied positions
  int occupiedIndices [];
  int occupiedCount = 0;

  for (int i = 0; i < totalReefSize; i++)
  {
    if (occupied [i])
    {
      ArrayResize (occupiedIndices, occupiedCount + 1);
      occupiedIndices [occupiedCount] = i;
      occupiedCount++;
    }
  }

  // Check if there are no occupied positions
  if (occupiedCount == 0) return;

  // Select the Fb share for broadcast spawning
  int broadcastCount = (int)MathRound (Fb * occupiedCount);
  if (broadcastCount <= 0) broadcastCount = 1; // At least one coral
  if (broadcastCount > occupiedCount) broadcastCount = occupiedCount;

  // Shuffle the indices
  for (int i = 0; i < occupiedCount; i++)
  {
    // Register the array out-of-bounds problem
    int j = (int)MathFloor (u.RNDfromCI (0, occupiedCount));

    // Ensure that j is within the array bounds
    if (j >= 0 && j < occupiedCount && i < occupiedCount)
    {
      int temp = occupiedIndices [i];
      occupiedIndices [i] = occupiedIndices [j];
      occupiedIndices [j] = temp;
    }
  }

  // Form pairs and create offspring
  for (int i = 0; i < broadcastCount - 1; i += 2)
  {
    if (i + 1 < broadcastCount) // Make sure there is a second parent 
    {
      int idx1 = reefIndices [occupiedIndices [i]];
      int idx2 = reefIndices [occupiedIndices [i + 1]];

      if (idx1 >= 0 && idx1 < popSize && idx2 >= 0 && idx2 < popSize)
      {
        // Initialize the larva
        larvae [larvaCount].Init (coords);

        // Create a new larva as a result of crossover
        for (int c = 0; c < coords; c++)
        {
          // Simple crossover method: average of parents' coordinates with a small mutation
          double value = (a [idx1].c [c] + a [idx2].c [c]) / 2.0 + u.RNDfromCI (-0.1, 0.1) * (rangeMax [c] - rangeMin [c]);
          larvae [larvaCount].c [c] = u.SeInDiSp (value, rangeMin [c], rangeMax [c], rangeStep [c]);
        }

        // Increase the larvae counter
        larvaCount++;
      }
    }
  }
}
//——————————————————————————————————————————————————————————————————————————————

Brooding方法模拟了CRO中珊瑚幼体的内部孕育过程,具体步骤如下:

  • 确定礁石上被珊瑚占据的位置,并存储这些位置的索引。 
  • 根据Fb(孕育比例参数)计算参与孕育的珊瑚数量。随机打乱被占据位置的索引,以随机选择参与繁殖的珊瑚个体。 
  • 创建并变异幼体:针对每个选中的珊瑚,创建一个幼体。幼体的初始化与变异:幼体的坐标在父代珊瑚坐标的基础上进行小幅随机偏移(模拟基因突变)。将变异后的幼体添加到"larvae"数组中。

要点:

  • Fb定义了参与广播产卵(即参与内部孕育)的珊瑚所占比例。
  • 变异为幼体种群提供了基因多样性。
  • 目标是培育具有潜在优势的新个体,使其在礁石空间竞争中占据优势。
//——————————————————————————————————————————————————————————————————————————————
void C_AO_CRO::Brooding (S_AO_Agent &larvae [], int &larvaCount)
{
  // Find all occupied positions
  int occupiedIndices [];
  int occupiedCount = 0;

  for (int i = 0; i < totalReefSize; i++)
  {
    if (occupied [i])
    {
      ArrayResize (occupiedIndices, occupiedCount + 1);
      occupiedIndices [occupiedCount] = i;
      occupiedCount++;
    }
  }

  // Check if there are no occupied positions
  if (occupiedCount == 0) return;

  // Number of corals for internal reproduction
  int broodingCount = (int)MathRound ((1.0 - Fb) * occupiedCount);
  if (broodingCount <= 0) broodingCount = 1; // At least one coral
  if (broodingCount > occupiedCount) broodingCount = occupiedCount;

  // Shuffle the indices
  for (int i = 0; i < occupiedCount; i++)
  {
    // Register the array out-of-bounds problem
    int j = (int)MathFloor (u.RNDfromCI (0, occupiedCount));

    // Ensure that j is within the array bounds
    if (j >= 0 && j < occupiedCount && i < occupiedCount)
    {
      int temp = occupiedIndices [i];
      occupiedIndices [i] = occupiedIndices [j];
      occupiedIndices [j] = temp;
    }
  }

  // For each selected coral, create a mutated copy
  for (int i = 0; i < broodingCount; i++)
  {
    if (i < occupiedCount) // Check for out-of-bounds
    {
      int idx = reefIndices [occupiedIndices [i]];

      if (idx >= 0 && idx < popSize)
      {
        // Initialize the larva
        larvae [larvaCount].Init (coords);

        // Create a new larva as a mutation of the original coral
        for (int c = 0; c < coords; c++)
        {
          // Mutation: add a small random deviation
          double value = a [idx].c [c] + u.RNDfromCI (-0.2, 0.2) * (rangeMax [c] - rangeMin [c]);
          larvae [larvaCount].c [c] = u.SeInDiSp (value, rangeMin [c], rangeMax [c], rangeStep [c]);
        }

        // Increase the larvae counter
        larvaCount++;
      }
    }
  }
}
//——————————————————————————————————————————————————————————————————————————————

AsexualReproduction方法通过出芽方式模拟珊瑚的无性繁殖过程。该方法的具体步骤如下:获取所有被珊瑚占据的位置索引,根据珊瑚的适应度对位置索引进行排序,适应度最高的珊瑚排在首位。基于参数 "Fa"(无性繁殖比例),计算需克隆的优质珊瑚数量。创建克隆幼体:对每个选中的珊瑚,创建其精确副本(克隆幼体),包括完全相同的坐标和适应度值。调用 LarvaSettling方法,尝试让克隆幼体在珊瑚礁上定居。

要点:

  • 无性繁殖使适应性最强的珊瑚能够快速扩散其基因。
  • Fa参数控制无性繁殖的强度。
  • 通过LarvaSettling方法让克隆幼体定居,意味着克隆体需与有性繁殖产生的幼体以相同方式竞争礁石空间。 
  • 在该克隆方法中,子代是父代的精确副本,不发生变异。变异仅在有性繁殖过程中发生。
//——————————————————————————————————————————————————————————————————————————————
void C_AO_CRO::AsexualReproduction ()
{
  // Find all occupied positions and their indices
  int occupiedIndices [];
  int occupiedCount = 0;

  for (int i = 0; i < totalReefSize; i++)
  {
    if (occupied [i])
    {
      ArrayResize (occupiedIndices, occupiedCount + 1);
      occupiedIndices [occupiedCount] = i;
      occupiedCount++;
    }
  }

  // If there are no occupied positions, exit
  if (occupiedCount == 0) return;

  // Sort indices by fitness
  SortAgentsByFitness (occupiedIndices, occupiedCount);

  // Select the best Fa% of corals for asexual reproduction
  int budCount = (int)MathRound (Fa * occupiedCount);
  if (budCount <= 0) budCount = 1; // At least one coral
  if (budCount > occupiedCount) budCount = occupiedCount;

  // For each selected coral, create a clone and try to populate it 
  for (int i = 0; i < budCount; i++)
  {
    if (i < occupiedCount) // Check for out-of-bounds
    {
      int idx = reefIndices [occupiedIndices [i]];

      if (idx >= 0 && idx < popSize)
      {
        // Create a new larva as an exact copy of the original coral
        S_AO_Agent clone;
        clone.Init (coords);
        ArrayCopy (clone.c, a [idx].c, 0, 0, WHOLE_ARRAY);
        clone.f = a [idx].f;

        // Try to populate the clone
        LarvaSettling (clone);
      }
    }
  }
}
//——————————————————————————————————————————————————————————————————————————————

Depredation方法模拟因捕食或其他负面因素(如污染)导致的珊瑚灭绝过程。在此情况下,按概率Pd触发淘汰事件。如果随机数小于Pd,则执行珊瑚淘汰操作。获取所有被珊瑚占据的位置索引。根据珊瑚的适应度对位置索引进行排序。

将数组反转,使最不适应的珊瑚索引位于数组开头。基于参数Fd(灭绝比例),确定需移除的珊瑚数量,将结果四舍五入为整数。从排序后的数组开头移除对应数量的珊瑚个体。珊瑚礁石清理: 对于每个计划移除的对应位置:将"occupied"数组中的相应单元格设置为“false”,标记为空位。将reefIndices数组中对应位置的值设置为-1,表示该位置无珊瑚存在。

//——————————————————————————————————————————————————————————————————————————————
oid C_AO_CRO::Depredation()
{
  // Apply destruction with Pd probability
  if (u.RNDfromCI(0, 1) < Pd)
  {
    // Find all occupied positions and their indices
    int occupiedIndices[];
    int occupiedCount = 0;

    for (int i = 0; i < totalReefSize; i++)
    {
      if (occupied[i])
      {
        ArrayResize(occupiedIndices, occupiedCount + 1);
        occupiedIndices[occupiedCount] = i;
        occupiedCount++;
      }
    }

    // If there are no occupied positions, exit
    if (occupiedCount == 0) return;

    // Sort indices by fitness
    SortAgentsByFitness(occupiedIndices, occupiedCount);

    // Reverse the array so the worst ones are first
    for (int i = 0; i < occupiedCount / 2; i++)
    {
      if(i < occupiedCount && (occupiedCount - 1 - i) < occupiedCount) // Check for out-of-bounds
      {
        int temp = occupiedIndices[i];
        occupiedIndices[i] = occupiedIndices[occupiedCount - 1 - i];
        occupiedIndices[occupiedCount - 1 - i] = temp;
      }
    }

    // Remove the worst Fd% corals
    int removeCount = (int)MathRound(Fd * occupiedCount);
    if (removeCount <= 0) removeCount = 1; // At least one coral
    if (removeCount > occupiedCount) removeCount = occupiedCount; // Overflow protection

    for (int i = 0; i < removeCount; i++)
    {
      if(i < occupiedCount) // Check for out-of-bounds
      {
        int pos = occupiedIndices[i];
        if(pos >= 0 && pos < totalReefSize) // Additional check
        {
          occupied[pos] = false;
          reefIndices[pos] = -1;
        }
      }
    }
  }
}
//——————————————————————————————————————————————————————————————————————————————

GetReefCoordIndex方法用于将礁石的二维坐标(行和列)转换为一维数组索引,以"row"和"col"作为输入,返回代表珊瑚礁的数组中的相应索引。首先,该方法检查传入的坐标是否在珊瑚礁边界之外。否则,其使用公式(row * reefCols + col,其中"reefCols"是珊瑚礁的列数)计算索引。该方法用于访问存储珊瑚礁状态的数组。

//——————————————————————————————————————————————————————————————————————————————
int C_AO_CRO::GetReefCoordIndex (int row, int col)
{
  // Check for out-of-bounds
  if (row < 0 || row >= reefRows || col < 0 || col >= reefCols) return -1;

  // Convert a two-dimensional position to a one-dimensional index
  return row * reefCols + col;
}
//——————————————————————————————————————————————————————————————————————————————

SortAgentsByFitness方法通过冒泡排序算法,根据通过reefIndices数组间接访问的存储在"a"数组中的适应度值,将"count"个元素的"indices"数组按适应度降序排列。因此,运行"indices"方法后,包含从最适应到最不适应排序的珊瑚索引。增加额外的检查以防止超出数组边界。

//——————————————————————————————————————————————————————————————————————————————
void C_AO_CRO::SortAgentsByFitness (int &indices [], int &count)
{
  // Check for an empty array
  if (count <= 0) return;

  // Bubble sort by decreasing fitness
  for (int i = 0; i < count - 1; i++)
  {
    for (int j = 0; j < count - i - 1; j++)
    {
      if (j + 1 < count) // Check that j+1 is not out of bounds
      {
        int idx1 = reefIndices [indices [j]];
        int idx2 = reefIndices [indices [j + 1]];

        if (idx1 >= 0 && idx1 < popSize && idx2 >= 0 && idx2 < popSize) // Check indices
        {
          if (a [idx1].f < a [idx2].f)
          {
            int temp = indices [j];
            indices [j] = indices [j + 1];
            indices [j + 1] = temp;
          }
        }
      }
    }
  }
}
//——————————————————————————————————————————————————————————————————————————————

我们已完成算法的完整构建,并对所有方法进行了详细说明。现在可直接进入测试阶段。


测试结果

经多轮测试验证,当前实现的CRO性能表现欠佳,需对原始方法中的部分设计进行系统性重构。

CRO|Coral Reef Optimization|50.0|5.0|5.0|0.4|0.9|0.1|0.1|0.01|3.0|
=============================
5 Hilly's; Func runs: 10000; result: 0.365266682511984
25 Hilly's; Func runs: 10000; result: 0.270828009448956
500 Hilly's; Func runs: 10000; result: 0.2504192846772352
=============================
5 Forest's; Func runs: 10000; result: 0.23618879234608753
25 Forest's; Func runs: 10000; result: 0.19453106526100442
500 Forest's; Func runs: 10000; result: 0.1679109693993047
=============================
5 Megacity's; Func runs: 10000; result: 0.13076923076923075
25 Megacity's; Func runs: 10000; result: 0.11138461538461542
500 Megacity's; Func runs: 10000; result: 0.09366153846153921
=============================
总分:1.82096 (20.23%)

我首先注意到原CRO算法的淘汰机制存在明显缺陷。需要对其进行修改以提升搜索能力。我们将用最优珊瑚(精英解)附近生成的新珊瑚替换珊瑚礁上最差的珊瑚,从而将搜索推向更有前景的区域。我们将确定最优(eliteCount)和最差(removeCount)珊瑚的数量。 

替换最差解: 针对每个“猎物”个体,算法会选择一个“精英”珊瑚作为基准,并在该精英珊瑚的邻域内生成新解。在改进的淘汰机制的过程中,采用指数为10的逆幂律分布(幂参数power = 0.1)生成相对于最优解的偏离量,以增强搜索的多样性。该分布的特征在于,绝大多数新解在最优解的邻域内生成,但存在小概率产生显著偏离,从而在局部搜索(开发)与全局解空间的探索之间实现平衡。新坐标受允许范围的限制。接下来,珊瑚礁上空出的位置由新珊瑚占据。

//——————————————————————————————————————————————————————————————————————————————
void C_AO_CRO::Depredation ()
{
  // Apply destruction with Pd probability
  if (u.RNDfromCI (0, 1) < Pd)
  {
    // Find all occupied positions and their indices
    int occupiedIndices [];
    int occupiedCount = 0;

    for (int i = 0; i < totalReefSize; i++)
    {
      if (occupied [i])
      {
        ArrayResize (occupiedIndices, occupiedCount + 1);
        occupiedIndices [occupiedCount] = i;
        occupiedCount++;
      }
    }

    // If there are no occupied positions, exit
    if (occupiedCount == 0) return;

    // Sort the indices by fitness (from best to worst)
    SortAgentsByFitness (occupiedIndices, occupiedCount);

    // Determine the number of best solutions used to generate new ones
    int eliteCount = (int)MathRound (0.1 * occupiedCount); // Use top 10%
    if (eliteCount <= 0) eliteCount = 1; // At least one elite solution
    if (eliteCount > occupiedCount) eliteCount = occupiedCount;

    // Determine the number of worst solutions to be replaced
    int removeCount = (int)MathRound (Fd * occupiedCount);
    if (removeCount <= 0) removeCount = 1; // At least one solution is replaced
    if (removeCount > occupiedCount - eliteCount) removeCount = occupiedCount - eliteCount; // Do not remove elite solutions

    // Remove the worst solutions and replace them with new ones in the vicinity of the best ones
    for (int i = 0; i < removeCount; i++)
    {
      // Index of the solution to be removed (from the end of the sorted array)
      int removeIndex = occupiedCount - 1 - i;
      if (removeIndex < 0 || removeIndex >= occupiedCount) continue;

      int posToRemove = occupiedIndices [removeIndex];
      if (posToRemove < 0 || posToRemove >= totalReefSize) continue;

      // Choose one of the elite solutions
      double power = 0.1; // Power distribution parameter
      double r = u.RNDfromCI (0, 1);
      int eliteIdx = (int)(eliteCount);
      if (eliteIdx >= eliteCount) eliteIdx = eliteCount - 1;

      int posBest = occupiedIndices [eliteIdx];
      if (posBest < 0 || posBest >= totalReefSize) continue;

      int bestAgentIdx = reefIndices [posBest];
      if (bestAgentIdx < 0 || bestAgentIdx >= popSize) continue;

      // Free up space for a new solution
      occupied [posToRemove] = false;

      // Generate a new solution in the neighborhood of the selected elite solution
      int newAgentIdx = reefIndices [posToRemove]; // Use the same agent index

      if (newAgentIdx >= 0 && newAgentIdx < popSize)
      {
        // Generation via power-law distribution around the best solution
        for (int c = 0; c < coords; c++)
        {
          // Determine the search radius (can be adapted depending on progress)
          double radius = 0.7 * (rangeMax [c] - rangeMin [c]); // 10% of the range

          // Generate a value using a power law
          double sign = u.RNDfromCI (0, 1) < 0.5 ? -1.0 : 1.0; // Random sign
          double deviation = sign * radius * MathPow (u.RNDfromCI (0, 1), 1.0 / power);

          // New value in the neighborhood of the best one
          double newValue = a [bestAgentIdx].c [c] + deviation;

          // Limit the value to an acceptable range
          a [newAgentIdx].c [c] = u.SeInDiSp (newValue, rangeMin [c], rangeMax [c], rangeStep [c]);
        }

        // Populate the new solution into the reef
        occupied [posToRemove] = true;
        reefIndices [posToRemove] = newAgentIdx;
      }
    }
  }
}

//——————————————————————————————————————————————————————————————————————————————

在完成上述优化后,我们对改进版CROm算法进行系统性测试。以下是关键结论:由以下结果可见,算法的性能得到了显著地提升。

CROm|Coral Reef Optimization M|50.0|20.0|20.0|0.2|0.99|0.01|0.8|0.9|20.0|
=============================
5 Hilly's; Func runs: 10000; result: 0.7851210159578113
25 Hilly's; Func runs: 10000; result: 0.4603296933002806
500 Hilly's; Func runs: 10000; result: 0.25958379129490083
=============================
5 Forest's; Func runs: 10000; result: 0.8668751980437325
25 Forest's; Func runs: 10000; result: 0.3529695710837671
500 Forest's; Func runs: 10000; result: 0.16267582083006701
=============================
5 Megacity's; Func runs: 10000; result: 0.6323076923076923
25 Megacity's; Func runs: 10000; result: 0.2673846153846154
500 Megacity's; Func runs: 10000; result: 0.10733846153846247
=============================
总分: 3.89459 (43.27%)

该算法的可视化效果一般。在处理Megacity测试函数的离散任务时略显困难。

Hilly值

CROm在Hilly测试函数上

Forest值

CROm在Forest测试函数上

Megacity值

CROm在Megacity测试函数上

根据测试结果,CROm算法在基于种群的优化算法排名表中位列第42。

# AO 描述 Hilly值 Hilly
最终
Forest值 Forest
最终
Megacity (离散) Megacity
最终
Final
结果
% 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 跨邻域搜索 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 密码锁算法(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 动物迁徙优化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) 进化策略 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 彗星尾算法(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 时间演化旅行算法(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 随机扩散搜索 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 台球优化算法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 射箭算法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 社会群体的进化(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 模拟各向同性退火(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 人工协同搜索 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 辩证算法 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 黑洞算法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 无序社会优化 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 皇家同花顺优化(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 原子轨道搜索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 龟壳演化算法(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 差分进化 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 成功餐饮经营者算法 (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 化学反应优化 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 血液遗传优化算法(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 鸟群算法 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 和声搜索 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 树苗播种和生长 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 细菌趋化性优化算法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 非洲水牛优化 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) 进化策略 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 禁忌搜索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 头脑风暴优化 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 鲸鱼优化算法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 人工电场算法 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 基于人工生态系统的优化算法 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 蚁群优化 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 细菌觅食优化 - 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 简单优化算法 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 人工蜂巢算法 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 大气云模型优化 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 群体自适应矩估计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 混沌博弈优化 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 人工部落算法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 CROm 珊瑚礁优化算法 0.78512 0.46032 0.25958 1.50502 0.86688 0.35297 0.16267 1.38252 0.63231 0.26738 0.10734 1.00703 3.895 43.27
43 CFO 中央力优化 0.60961 0.54958 0.27831 1.43750 0.63418 0.46833 0.22541 1.32792 0.57231 0.23477 0.09586 0.90294 3.668 40.76
44 ASHA 人工淋浴算法 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
45 ASBO 适应性社会行为优化 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
RW 神经Boid优化算法2(joo) 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


总结

活体珊瑚礁是高度精密的生态系统,它们通过持续调节稳定性与变异性的平衡,在保留已被验证的生存策略的同时,不断试验新的适应性机制。这种改进的捕食机制通过在最优解附近生成新解,模拟了珊瑚礁生态演化的自然过程。

在自然界中,当部分珊瑚群体消亡后,空出的珊瑚礁区并不会被随机物种占据,而是由那些最成功适应本地环境条件的物种所替代。此外,新群落在现有成功群落周围区域的存活率更高,通过围绕精英解生成新解直接在算法中得到体现。这样确保了对搜索空间有前景区域的持续探索,并维持恒定的种群规模。

采用逆幂律分布(指数为10,即幂参数power = 0.1)可生成相对于最优解的偏离量。该分布将大多数新解集中在最优解附近,同时允许罕见的显著偏差,在局部利用与全局探索之间提供最佳平衡。

将搜索半径增加到可行范围的70%,使算法能够探索更广区域的解空间。

仅以最优解(精英解)为基准生成新解,可加速算法收敛至最优区域并提升最终解质量。此外,该算法中模拟珊瑚进化关键过程的多种算子(如广播产卵、孵化育幼、幼体定居及无性繁殖),也可为其他群体优化算法的开发提供借鉴。

标签

图例2. 算法在相应测试中的颜色渐变表示

图表

图例3. 算法测试结果的直方图(评分范围为0到100,越高越好,其中100为理论上的最高可能得分,档案中附有计算排名表的脚本)

CROm算法优缺点:

优点:

  1. 这是个有趣的理念。
  2. 有发展前景。
  3. 结果稳定。

缺点:

  1. 在离散函数上表现较弱。
  2. 外部参数过多。

文章附有一个包含当前版本算法代码的归档文件。本文作者对标准算法描述的绝对准确性不承担责任。为提升搜索能力,已经对其中的许多算法进行了修改。文章中表述的结论和论断都是基于实验的结果。


文中所用的程序

# 名称 类型 描述
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_CROm.mq5
脚本 CROm测试平台

本文由MetaQuotes Ltd译自俄文
原文地址: https://www.mql5.com/ru/articles/17760

附加的文件 |
CROm.zip (195.48 KB)
交易策略 交易策略
各种交易策略的分类都是任意的,下面这种分类强调从交易的基本概念上分类。
配对交易:基于Z值差异的自动优化算法交易 配对交易:基于Z值差异的自动优化算法交易
本文将深入探究配对交易的核心逻辑,以及相关性交易的运作机制。我们还将编写一套自动化配对交易EA,并为其加入基于历史数据的算法自动优化功能。此外,在整个项目中,我们还会学习如何通过 Z 值(Z-Score)计算两个交易品种之间的价差偏离度。
新手在交易中的10个基本错误 新手在交易中的10个基本错误
新手在交易中会犯的10个基本错误: 在市场刚开始时交易, 获利时不适当地仓促, 在损失的时候追加投资, 从最好的仓位开始平仓, 翻本心理, 最优越的仓位, 用永远买进的规则进行交易, 在第一天就平掉获利的仓位,当发出建一个相反的仓位警示时平仓, 犹豫。
风险管理(第五部分):将风险管理系统集成到 EA 中 风险管理(第五部分):将风险管理系统集成到 EA 中
在本文中,我们将实现在先前文章中开发的风险管理系统,并添加在其他文章中描述的订单区块指标。此外,我们将进行一次回测,以便比较启用风险管理系统前后的结果,并评估动态风险的影响。