English Русский 中文 Español Deutsch Português
preview
サンゴ礁最適化(CRO)

サンゴ礁最適化(CRO)

MetaTrader 5トレーディング |
27 0
Andrey Dik
Andrey Dik


内容

  1. はじめに
  2. アルゴリズムの実装
  3. テスト結果


はじめに

近年、自然界のプロセスやシステムに着想を得たバイオインスパイアードアルゴリズムは、開発者の間で大きな関心を集めています。その中でも、2014年にS. Salcedo-Sanzらによって提案されたサンゴ礁最適化(CRO, Coral Reef Optimization)アルゴリズムは、特に注目されている手法の一つです。

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(larva) > f(Ξᵢⱼ)を満たす必要があります。
  4. 置換が発生しなかった場合、幼生は別のセルへの定着を再試行できます(最大k回まで)。
  5. k回試行しても定着できなかった場合、幼生は死滅します。

無性生殖(断片化):礁内で最も適応度の高いサンゴ群(割合Fₐ)は、無性生殖によって自身の複製(クローン)を生成できます。具体的には、以下の手順で実行されます。

  1. サンゴを適応度関数に基づいてソートします。
  2. 上位Fₐ × 100%のサンゴを無性生殖対象として選択します。
  3. 各サンゴは自身のクローンを生成し、そのクローンは幼生定着と同様の規則に従って礁への定着を試みます。

捕食:各反復の終了時には、礁内で適応度の低いサンゴが、確率Pdに基づいて死滅する場合があります。これにより、次世代の新しいサンゴが定着するための空間が確保されます。

以上の礁形成プロセスは、最大反復回数への到達など、あらかじめ設定された停止条件を満たすまで繰り返されます。アルゴリズム終了後、礁内で最も適応度の高いサンゴが、最適化問題に対する最終的な解として採用されます。

CROアルゴリズム

図1:CROアルゴリズムの動作概要

上図は、アルゴリズムの主要な6つの段階を示しています。

  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アルゴリズムを実装します。CROアルゴリズムを実装するクラスとしてC_AO_CROを定義し、基底クラスであるC_AOを継承して構築します。 

CROパラメータ

このクラスでは、アルゴリズムの挙動を制御する以下のパラメータを定義します。

  • popSize:サンゴの集団サイズ
  • reefRows:礁の行数(グリッドの高さ)
  • reefCols:礁の列数(グリッドの幅)
  • rho0:初期礁占有率(アルゴリズム開始時にサンゴが占めるセルの割合)
  • Fb:放卵放精に参加するサンゴの割合
  • Fa:無性生殖に参加するサンゴの割合
  • Fd:低適応度により除去対象となるサンゴの割合
  • Pd:サンゴが破壊される確率
  • attemptsNum:幼生が礁への定着を試みる最大試行回数

クラスメソッド

  • SetParams():パラメータ配列paramsに格納された値に基づいて、アルゴリズムの各種パラメータを設定します。 この配列を用いることで、実行中に動的にパラメータを変更することが可能です。
  • Init (rangeMinP, rangeMaxP, rangeStepP, epochsP):探索変数の範囲(最小値、最大値、刻み幅)およびエポック数を受け取り、初期集団の生成および礁構造の初期化など、アルゴリズム実行に必要な準備をおこないます。
  • Moving ():礁内におけるサンゴの移動に関する基本的な動作ロジックを実装します。 
  • Revision ():礁上のサンゴの配置を再評価し、必要に応じて更新と調整をおこないます。
  • InitReef():礁構造を初期化し、サンゴを配置できる状態にします。
  • LarvaSettling (larva):サンゴ幼生の定着位置を決定し、新規コロニーの形成プロセスをシミュレートします。
  • BroadcastSpawning():サンゴが水中に幼生を放出する処理をおこないます。
  • Brooding ():サンゴ内部で幼生が生成されるプロセスを実行します。
  • AsexualReproduction ():サンゴが無性生殖し、遺伝的に同一なクローンを生成する処理を実行します。
  • Depredation ():低適応度のサンゴを確率的に除去します。
  • GetReefCoordIndex():礁の2次元座標(行・列)を1次元配列のインデックスに変換します。
  • SortAgentsByFitness ():サンゴを適応度に基づいてソートします。

private変数

  • 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/ja/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を計算し(reefRows×reefCols)、初期サンゴ数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;
}
//——————————————————————————————————————————————————————————————————————————————

InitReefメソッドはC_AO_CROクラスにおいて、礁上の初期サンゴ個体群を初期化します。まず、与えられた礁の密度(rho0)に基づいて初期化するサンゴ数を計算します。この数はpopSizeによって上限が設定されます。次に、各サンゴについて礁上のランダムかつ未使用の位置を割り当てます。空いているセルが見つかった場合、そのセルをoccupiedとしてマークし、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を取得します。取得された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メソッドを用いて、生成された幼生が礁上のどの位置に定着するかを決定します。 AsexualReproductionが実行され、その後に捕食が実行されます。要するに、このメソッドは解の更新、有性生殖によるサンゴ生成、幼生の配置、および捕食の影響をシミュレーションします。

//——————————————————————————————————————————————————————————————————————————————
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)が該当するa[]配列のセルにコピーされます。

その後、その礁位置が占有されたことが更新され、定着に成功したposインデックスを返します。一方、選択された位置が既に占有されている場合、幼生とその位置に存在するサンゴの適応度を比較します。幼生の方が優れている場合、既存サンゴを置き換え、そのパラメータをa[配列内の対応セルへコピーし、置換が発生した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 (Fraction for Depredation)に基づいて削除対象となるサンゴの数を決定し、この値は最も近い整数に丸められます。決定された数の最も適応度の低いサンゴが削除されます。その後、礁のクリーニング処理をおこないます。削除対象となった各位置について、対応する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と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メソッドは、indices配列(要素数count)を適応度の降順でソートします。本処理では、reefIndices配列を介して参照されるa配列内の適応度値を基準として、バブルソートアルゴリズムを使用します。この結果、メソッド実行後の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
=============================
All score:1.82096 (20.23%)

CROアルゴリズムについて最初に確認された点は、破壊メソッドの改善の必要性です。このメソッドは探索性能を向上させるために修正されるべきであり、礁上の最も悪いサンゴを削除する代わりに、最良のサンゴ(解)の近傍で生成された新しいサンゴで置き換える方式に変更します。これにより、探索がより有望な領域へと誘導されます。まず、最良解の数(eliteCount)および削除対象となる最悪解の数 (removeCount)を決定します。 

最悪解の置き換え: 次に、最悪解(prey)を1つずつ処理し、それぞれに対して最良のサンゴ(elite)を選択し、その近傍に新しいサンゴを生成します。 改良された破壊メカニズムでは、最良解からの変位生成に逆べき乗則分布(指数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
=============================
All score:3.89459 (43.27%)

アルゴリズムの可視化自体は特に目立った特徴は見られません。また、Megacityテスト関数における離散的なタスクに対しては、アルゴリズムはやや対応が難しい傾向が見られます。

Hilly

Hillyテスト関数のCROm

Forest

Forestテスト関数のCROm

Megacity

Megacityテスト関数のCROm

テスト結果に基づくと、CROmアルゴリズムは集団ベース最適化アルゴリズムのランキング表において42位に位置しています。

# AO 詳細 Hilly Hilly
ファイナル
Forest Forest
ファイナル
Megacity(離散) Megacity
ファイナル
ファイナル
結果

MAX
10p(5F) 50p(25F) 1000p(500F) 10p(5F) 50p(25F) 1000p(500F) 10p(5F) 50p(25F) 1000p(500F)
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 コードロックアルゴリズム(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 サンゴ礁最適化M 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 適応型社会行動最適化(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 ニューロボイド最適化アルゴリズム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%まで拡大することで、アルゴリズムは解空間のより広い領域を探索できるようになります。

さらに、最良解のみを基盤として新しい解を生成することにより、最適領域への収束速度が向上し、解の品質も改善されます。一方で、放卵放精、体内発生、幼生定着、無性生殖といったサンゴ進化の主要要素を模倣する多様な演算子は、他の集団ベース最適化手法の開発にも応用可能です。

Tab

図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スコアを用いて2つの通貨ペア間の差異を計算する方法についても学びます。
市場シミュレーション(第17回):ソケット(XI) 市場シミュレーション(第17回):ソケット(XI)
MetaTrader 5上で実行されるコードの実装自体は、それほど難しいものではありません。しかし、いくつか考慮すべき重要な点があります。これはシステムを正しく動作させるために必要です。ここで重要な点を1つ覚えておいてください。実際には1つのプログラムだけが動作するわけではありません。現実には、3つのプログラムを同時に実行する必要があります。それぞれのプログラムが相互に連携し、通信できるように設計して構造化することが重要です。また、それぞれが他のプログラムの処理内容を認識できる必要があります。
トレンドの基準:結論 トレンドの基準:結論
本記事では、実務におけるいくつかのトレンド判定基準の適用について検討します。また、それらの基準を基にしていくつかの新しい判定基準の開発も試みます。特に、市場データ解析および取引への適用効率に焦点を当てます。
市場シミュレーション(第16回):ソケット(X) 市場シミュレーション(第16回):ソケット(X)
このチャレンジも終盤に差し掛かっていますが、その前に、今回の内容と前回の記事の2つの記事をしっかり理解しておく必要があります。そうすることで、次の記事をより深く理解できるようになります。次の記事では、MQL5プログラミングに関連する部分のみを扱う予定です。また、できるだけ分かりやすく説明するように努めます。しかし、これら2つの記事の内容を理解していない場合、次の記事を理解することは難しくなるでしょう。内容が段階的に積み重なっていく構造になっているからです。達成すべき目標に近づくほど、必要となる理解や実装すべき要素は増えていきます。