サンゴ礁最適化(CRO)
内容
はじめに
近年、自然界のプロセスやシステムに着想を得たバイオインスパイアードアルゴリズムは、開発者の間で大きな関心を集めています。その中でも、2014年にS. Salcedo-Sanzらによって提案されたサンゴ礁最適化(CRO, Coral Reef Optimization)アルゴリズムは、特に注目されている手法の一つです。
CROアルゴリズムは、自然界におけるサンゴ礁の形成および発展過程をモデル化したものです。これには、サンゴのさまざまな繁殖メカニズム(放卵放精、体内発生、無性生殖)、限られた礁空間を巡る競争、さらには弱い個体の死滅などが含まれます。自然界において進化が強靭で適応性の高いサンゴ礁を形成するように、CROアルゴリズムも探索空間を効果的に探索し、さまざまな問題に対して最適解または準最適解を導き出すことが可能です。
本記事では、最良解近傍における新たな解生成に逆べき乗則分布を利用した改良版CROmアルゴリズムを提案します。本手法は、探索能力および探索空間における大域探索と局所探索の自然なバランスといった、従来のCROが有する利点を維持しつつ、有望な探索領域をより高い精度で特定し、最適解への収束を高速化する効率的なメカニズムを導入しています。
さらに、本記事では提案アルゴリズムを古典的な最適化ベンチマーク関数に対して広範に評価し、従来のCROアルゴリズムおよび他の現代的メタヒューリスティクスと比較した際の性能向上を示します。実験結果から、提案手法は特に多峰性目的関数や複雑な探索空間構造を有する問題に対して高い有効性を示すことが確認されました。
本稿の構成は以下の通りです。まず、標準CROアルゴリズムの基本概念および動作原理について概説します。次に、提案する改良手法とその理論的背景について詳細に説明します。その後、アルゴリズムの実験と結果分析をおこないます。最後に、本研究で得られた成果、提案手法の限界、および今後の研究課題について議論します。
アルゴリズムの実装
CROアルゴリズムの基本的な考え方は、サンゴ群体が礁内で成長し、限られた空間を巡って競争しながら、最終的に最適な構造を形成する過程を模倣することにあります。礁内の各サンゴは、対象となる最適化問題に対する潜在的な解を表します。
礁は、N×Mの二次元グリッドとしてモデル化されます。各グリッドセルは、サンゴによって占有されているか、あるいは空の状態のいずれかです。サンゴは最適化問題に対する符号化された解であり、各サンゴには適応度関数が割り当てられます。この適応度は、最適化問題における目的関数に対応します。
パラメータρ₀ ∈ (0,1)は、初期状態においてサンゴによって占有される礁の割合を表します。すなわち、アルゴリズム開始時点における占有セル数と総セル数との比率です。礁の初期化は以下の手順でおこなわれます。
- 礁サイズN×Mと初期充填率ρ₀を設定します。
- ⌊ρ₀ × N × M⌋個のセルをランダムに選択し、初期サンゴを配置します。
- 探索領域内でランダムに生成した初期サンゴを、選択されたセルへ配置します。
礁の初期化後、礁の形成および発展を模倣する反復プロセスが開始されます。このプロセスは、以下の複数の段階から構成されます。
放卵放精:この繁殖方式では、既存サンゴのうち一定割合Fₑが選択されます。選択されたサンゴはペアを形成し、交叉演算子を用いて子個体を生成します。本研究では、通常の平均化による交叉を採用しています。
体内発生:残りの(1-Fₑ)のサンゴは体内発生をおこない、突然変異によって子個体を生成します。体内発生対象として選択された各サンゴに対し、突然変異演算子を用いて幼生が生成されます。通常、この幼生は元の解に対する小規模なランダム変動を表します。幼生定着:幼生が生成された後、それぞれの幼生は礁内への定着を試みます。定着は以下の規則に従って実行されます。
- 幼生はサンゴ礁内のセル(i, j)をランダムに選択します。
- 選択されたセルが空いている場合、幼生はそのセルを占有します。
- セルが既に占有されている場合、幼生の適応度が既存サンゴより高い場合に限り、既存サンゴを置き換えます。すなわち、f(larva) > f(Ξᵢⱼ)を満たす必要があります。
- 置換が発生しなかった場合、幼生は別のセルへの定着を再試行できます(最大k回まで)。
- k回試行しても定着できなかった場合、幼生は死滅します。
無性生殖(断片化):礁内で最も適応度の高いサンゴ群(割合Fₐ)は、無性生殖によって自身の複製(クローン)を生成できます。具体的には、以下の手順で実行されます。
- サンゴを適応度関数に基づいてソートします。
- 上位Fₐ × 100%のサンゴを無性生殖対象として選択します。
- 各サンゴは自身のクローンを生成し、そのクローンは幼生定着と同様の規則に従って礁への定着を試みます。
捕食:各反復の終了時には、礁内で適応度の低いサンゴが、確率Pdに基づいて死滅する場合があります。これにより、次世代の新しいサンゴが定着するための空間が確保されます。
以上の礁形成プロセスは、最大反復回数への到達など、あらかじめ設定された停止条件を満たすまで繰り返されます。アルゴリズム終了後、礁内で最も適応度の高いサンゴが、最適化問題に対する最終的な解として採用されます。

図1:CROアルゴリズムの動作概要
上図は、アルゴリズムの主要な6つの段階を示しています。
- 初期化(ρ₀ = 0.6):二次元グリッド(礁)が生成され、異なる解を表す多色のサンゴが部分的に配置されます。
- 放卵放精(Fb = 0.9):サンゴがペアを形成し、交叉操作を通じて幼生を生成する様子を示します。
- 体内発生(1-Fb = 0.1):各サンゴが突然変異によって個別に幼生を生成する過程を表します。
- 幼生定着(k = 3回の試行):幼生が礁内で定着可能な場所を探索する様子を示し、成功例と失敗例の両方が含まれます。
- 無性生殖(Fa = 0.1):高適応度のサンゴ(星印で示される)が自身のクローンを生成する様子を表します。
- 捕食(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テスト関数のCROm

Forestテスト関数のCROm

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%まで拡大することで、アルゴリズムは解空間のより広い領域を探索できるようになります。
さらに、最良解のみを基盤として新しい解を生成することにより、最適領域への収束速度が向上し、解の品質も改善されます。一方で、放卵放精、体内発生、幼生定着、無性生殖といったサンゴ進化の主要要素を模倣する多様な演算子は、他の集団ベース最適化手法の開発にも応用可能です。

図2:対応するテストに応じたアルゴリズムのカラーグラデーション

図3:アルゴリズムテスト結果のヒストグラム(0から100のスケール、高いほど良い)100は理論上の最大値であり、アーカイブには評価表を計算するためのスクリプトがあります。
CROmのメリットとデメリット:
長所
- 興味深いアイディア
- 将来的な発展性が期待できる
- 安定した結果
短所
- 離散関数での結果が悪い
- 多数の外部パラメータ
この記事には、最新版のアルゴリズムコードを含むアーカイブが添付されています。記事の著者は、正規アルゴリズムの説明の絶対的な正確さについて責任を負いません。検索機能を向上させるために、それらの多くに変更が加えられています。記事に示された結論と判断は、実験結果に基づいています。
記事で使用されているプログラム
| # | 名前 | 種類 | 詳細 |
|---|---|---|---|
| 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
警告: これらの資料についてのすべての権利はMetaQuotes Ltd.が保有しています。これらの資料の全部または一部の複製や再プリントは禁じられています。
この記事はサイトのユーザーによって執筆されたものであり、著者の個人的な見解を反映しています。MetaQuotes Ltdは、提示された情報の正確性や、記載されているソリューション、戦略、または推奨事項の使用によって生じたいかなる結果についても責任を負いません。
ペアトレード:Zスコアの差に基づく自動最適化機能を備えたアルゴリズム取引
市場シミュレーション(第17回):ソケット(XI)
トレンドの基準:結論
市場シミュレーション(第16回):ソケット(X)
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索