This commit is contained in:
JQSakaJoo
2026-05-24 17:40:27 +04:00
parent e70141e538
commit b5dbcdc3e3
6 changed files with 352 additions and 1 deletions
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,349 @@
//+——————————————————————————————————————————————————————————————————+
//| C_AO_BWOm |
//| Copyright 2007-2026, Andrey Dik |
//| https://www.mql5.com/ru/users/joo |
//———————————————————————————————————————————————————————————————————+
#include "#C_AO.mqh"
//+------------------------------------------------------------------+
//| Beluga Whale Optimization — МОДИФИЦИРОВАННАЯ версия. |
//| |
//| Общий принцип модификации: в оригинальной BWO каждая из трёх фаз |
//| использует случайные множители, разыгранные ОДИН раз на агента |
//| (r1..r7 — скаляры), домножающие целые векторы. Любой такой |
//| скаляр-на-вектор запирает кандидата в низкоразмерное подпрост- |
//| ранство. На бенче из N копий одной функции оптимум осесимметри- |
//| чен, и это подпространство совпадает с главной диагональю, на |
//| которой оптимум и лежит — алгоритм «считывает диагональ» даром, |
//| причём эффект УСИЛИВАЕТСЯ с размерностью: покоординатный шум |
//| Леви усредняется при greedy-приёмке по среднему фитнесу. |
//| |
//| BWOm заменяет скаляры-на-агента на ПОКООРДИНАТНУЮ случайность во |
//| всех трёх фазах: |
//| - разведка: r1, r2 на каждую пару; тяга к одноимённой паре |
//| соседа (без общего скаляра-опоры и кросс-перестановки); |
//| - эксплуатация: тяга к глобальному лучшему — покоординатная |
//| интерполяция (r3 на каждую координату); масштаб-скаляр |
//| r3*cB убран — именно он порождал луч origin->cB; |
//| - падение кита: r5, r6 покоординатные. |
//| Трёхфазная структура, балансовый фактор, вероятность падения |
//| кита, полёт Леви и временное затухание C1/C2 сохранены. |
//+------------------------------------------------------------------+
class C_AO_BWOm : public C_AO
{
public:
~C_AO_BWOm() {}
C_AO_BWOm()
{
ao_name = "BWOm";
ao_desc = "Beluga Whale Optimization (modified)";
ao_link = "https://www.mql5.com/ru/articles/22686";
popSize = 20;
KD = 1.5;
ArrayResize(params, 2);
params [0].name = "popSize"; params [0].val = popSize;
params [1].name = "KD"; params [1].val = KD;
}
void SetParams()
{
popSize = (int)params [0].val;
KD = params [1].val;
//--- предохранители
if(popSize < 1)
popSize = 1;
if(KD < 0.0)
KD = 0.0;
}
bool Init(const double &rangeMinP [],
const double &rangeMaxP [],
const double &rangeStepP [],
const int epochsP = 0);
void Moving();
void Revision();
//--- видимые параметры
double KD; // интенсивность полёта Леви (оригинал: 0.05)
private:
//--- snapshot для greedy acceptance
double snap_c []; // [popSize * coords] — плоский буфер
double snap_f []; // [popSize]
//--- счётчик итераций (для отношения T/Max_it)
int epochs; // всего эпох (из Init)
int epochsDen; // знаменатель для T/Max_it
int epochNow; // номер текущей «боевой» итерации
//--- константа масштаба для полёта Леви (Mantegna, beta = 1.5)
double levySigma;
//--- стандартное нормальное число (Box–Muller)
double Gauss();
//--- один отсчёт полёта Леви по координате
double LevyStep();
};
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Init |
//+------------------------------------------------------------------+
bool C_AO_BWOm::Init(const double &rangeMinP [],
const double &rangeMaxP [],
const double &rangeStepP [],
const int epochsP = 0)
{
if(!StandardInit(rangeMinP, rangeMaxP, rangeStepP))
return false;
//--- начальная случайная популяция в cP[] (попадёт в c[] на первом Moving)
for(int i = 0; i < popSize; i++)
for(int c = 0; c < coords; c++)
a [i].cP [c] = u.RNDfromCI(rangeMin [c], rangeMax [c]);
//--- внутренние буферы
ArrayResize(snap_c, popSize * coords);
ArrayResize(snap_f, popSize);
//--- счётчик итераций
epochs = epochsP;
epochsDen = (epochs > 1) ? epochs - 1 : 1;
epochNow = 0;
//--- sigma для полёта Леви (Mantegna), beta = 1.5
// значения гамма-функции посчитаны заранее, чтобы не зависеть
// от наличия MathGamma:
// Г(1 + beta) = Г(2.5) = 1.3293403881791
// Г((1+beta)/2) = Г(1.25) = 0.9064024770554
double beta = 1.5;
double g1 = 1.3293403881791;
double g2 = 0.9064024770554;
levySigma = MathPow((g1 * MathSin(M_PI * beta / 2.0)) /
(g2 * beta * MathPow(2.0, (beta - 1.0) / 2.0)),
1.0 / beta); // ≈ 0.69655
return true;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Gauss — стандартное нормальное (Box–Muller) |
//+------------------------------------------------------------------+
double C_AO_BWOm::Gauss()
{
double u1 = u.RNDfromCI(0.0, 1.0);
double u2 = u.RNDfromCI(0.0, 1.0);
if(u1 < 1e-15)
u1 = 1e-15;
return MathSqrt(-2.0 * MathLog(u1)) * MathCos(2.0 * M_PI * u2);
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| LevyStep — один отсчёт полёта Леви (Mantegna) |
//+------------------------------------------------------------------+
double C_AO_BWOm::LevyStep()
{
double uu = Gauss() * levySigma;
double vv = Gauss();
double av = MathAbs(vv);
if(av < 1e-300)
av = 1e-300;
return KD * (uu / MathPow(av, 1.0 / 1.5));
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Moving |
//| |
//| Структура итерации: |
//| 1. snapshot текущей популяции; |
//| 2. для каждого агента — балансовый фактор Bf и сосед RJ; |
//| 3. выбор ветви: |
//| Bf <= WF -> падение кита; |
//| Bf > 0.5 -> разведка (честное парное плавание); |
//| иначе -> эксплуатация (покоординатная тяга к cB); |
//| 4. новый кандидат пишется в a[i].c. |
//| Во всех ветвях случайность ПОКООРДИНАТНАЯ — нет скаляра на |
//| агента, домножающего целый вектор. |
//+------------------------------------------------------------------+
void C_AO_BWOm::Moving()
{
//--- первый прогон: cP -> c, чтобы внешний цикл оценил FF
if(!revision)
{
for(int i = 0; i < popSize; i++)
for(int c = 0; c < coords; c++)
a [i].c [c] = u.SeInDiSp(a [i].cP [c], rangeMin [c], rangeMax [c], rangeStep [c]);
return;
}
//--- номер текущей итерации и отношение T/Max_it
epochNow++;
double tRatio = (double)epochNow / (double)epochsDen;
if(tRatio > 1.0)
tRatio = 1.0;
//--- snapshot текущей популяции
for(int i = 0; i < popSize; i++)
{
for(int c = 0; c < coords; c++)
snap_c [i * coords + c] = a [i].c [c];
snap_f [i] = a [i].f;
}
//--- вероятность падения кита
double WF = 0.1 - 0.05 * tRatio;
//--- движение
for(int i = 0; i < popSize; i++)
{
//--- балансовый фактор Bf = B0 * (1 - T/2Tmax)
double Bf = (1.0 - 0.5 * tRatio) * u.RNDprobab();
//--- случайный сосед RJ != i
int RJ = i;
if(popSize > 1)
while(RJ == i)
RJ = u.RNDminusOne(popSize);
//================================================================
if(Bf <= WF)
{
//--- ФАЗА 3: ПАДЕНИЕ КИТА (whale fall) — модификация
// Оригинал: v = r5*xi - r6*xr + step, r5/r6 — скаляры на
// агента -> скелет заперт в плоскости (xi, xr), на стянутой
// диагонали — в линию. BWOm: r5, r6 покоординатные.
// r7 (магнитуда шага) оставлен на агента — равномерный
// масштаб шага не запирает кандидата.
double r7 = u.RNDprobab();
double C2 = 2.0 * (double)popSize * WF;
double decay = MathExp(-C2 * tRatio);
for(int c = 0; c < coords; c++)
{
double r5c = u.RNDprobab();
double r6c = u.RNDprobab();
double step = r7 * (rangeMax [c] - rangeMin [c]) * decay;
double v = r5c * snap_c [i * coords + c] -
r6c * snap_c [RJ * coords + c] + step;
a [i].c [c] = u.SeInDiSp(v, rangeMin [c], rangeMax [c], rangeStep [c]);
}
}
//================================================================
else
if(Bf > 0.5)
{
//--- ФАЗА 1: РАЗВЕДКА — честное парное плавание (модификация)
// каждая пара координат (dA, dB) тянется к своей одноимённой
// паре соседа RJ; r1, r2 разыгрываются на КАЖДУЮ пару.
// Ни общего скаляра-опоры, ни кросс-перестановки измерений.
//--- незатронутые координаты остаются прежними
for(int c = 0; c < coords; c++)
a [i].c [c] = snap_c [i * coords + c];
int pairs = coords / 2;
for(int j = 0; j < pairs; j++)
{
int dA = 2 * j; // x-координата пары
int dB = 2 * j + 1; // y-координата пары
double r1 = u.RNDprobab();
double r2 = u.RNDprobab();
double ang = 2.0 * M_PI * r2;
double sinA = MathSin(ang);
double cosA = MathCos(ang);
double xA = snap_c [i * coords + dA];
double xB = snap_c [i * coords + dB];
double refA = snap_c [RJ * coords + dA];
double refB = snap_c [RJ * coords + dB];
double vA = xA + (refA - xA) * (r1 + 1.0) * sinA;
double vB = xB + (refB - xB) * (r1 + 1.0) * cosA;
a [i].c [dA] = u.SeInDiSp(vA, rangeMin [dA], rangeMax [dA], rangeStep [dA]);
a [i].c [dB] = u.SeInDiSp(vB, rangeMin [dB], rangeMax [dB], rangeStep [dB]);
}
}
//================================================================
else
{
//--- ФАЗА 2: ЭКСПЛУАТАЦИЯ (охота, полёт Леви) — модификация
// Оригинал: v = r3*cB - r4*xi + C1*LF*(xr-xi), r3 — скаляр
// на агента. Слагаемое r3*cB — масштабированный осесиммет-
// ричный глобальный лучший: кандидат скользит по лучу
// origin->cB (главная диагональ на бенче из копий функции).
// На больших размерностях покоординатный шум Леви усред-
// няется при greedy-приёмке по среднему фитнесу, и отбор
// оптимизирует фактически одномерное сканирование диагонали.
// BWOm: тяга к лучшему — покоординатная интерполяция (r3 на
// КАЖДУЮ координату), скаляр-масштаб r3*cB убран.
// C1 (затухание Леви) оставлен на агента: равномерный
// масштаб покоординатно-случайного вектора Леви не запирает
// кандидата в подпространство.
double r4 = u.RNDprobab();
double C1 = 2.0 * r4 * (1.0 - tRatio);
for(int c = 0; c < coords; c++)
{
double r3c = u.RNDprobab();
double xi = snap_c [i * coords + c];
double xr = snap_c [RJ * coords + c];
double Lv = LevyStep();
double v = xi + r3c * (cB [c] - xi) + C1 * Lv * (xr - xi);
a [i].c [c] = u.SeInDiSp(v, rangeMin [c], rangeMax [c], rangeStep [c]);
}
}
}
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Revision |
//| |
//| Стандартное обновление fB/cB + greedy acceptance: если новый |
//| фитнес хуже снапшота — откат координат и фитнеса агента. |
//+------------------------------------------------------------------+
void C_AO_BWOm::Revision()
{
//--- обновление личных и глобального лучших
for(int i = 0; i < popSize; i++)
{
if(a [i].f > a [i].fB)
{
a [i].fB = a [i].f;
ArrayCopy(a [i].cB, a [i].c, 0, 0, coords);
}
if(a [i].f > fB)
{
fB = a [i].f;
ArrayCopy(cB, a [i].c, 0, 0, coords);
}
}
if(!revision)
{
revision = true;
return;
}
//--- greedy acceptance: rollback если стало хуже
for(int i = 0; i < popSize; i++)
{
if(a [i].f < snap_f [i])
{
for(int c = 0; c < coords; c++)
a [i].c [c] = snap_c [i * coords + c];
a [i].f = snap_f [i];
}
}
}
//+------------------------------------------------------------------+
@@ -81,6 +81,7 @@
<tr><td>BIO</td><td><a href="https://www.mql5.com/ru/articles/17246" target="_blank">blood inheritance optimization (joo)</a></td></tr> <tr><td>BIO</td><td><a href="https://www.mql5.com/ru/articles/17246" target="_blank">blood inheritance optimization (joo)</a></td></tr>
<tr><td>DOA</td><td><a href="https://www.mql5.com/ru/articles/19177" target="_blank">dream optimization algorithm</a></td></tr> <tr><td>DOA</td><td><a href="https://www.mql5.com/ru/articles/19177" target="_blank">dream optimization algorithm</a></td></tr>
<tr><td>BSA</td><td><a href="https://www.mql5.com/ru/articles/14491" target="_blank">bird swarm algorithm</a></td></tr> <tr><td>BSA</td><td><a href="https://www.mql5.com/ru/articles/14491" target="_blank">bird swarm algorithm</a></td></tr>
<tr><td>BWOm</td><td><a href="https://www.mql5.com/ru/articles/22686" target="_blank">beluga whale optimization M</a></td></tr>
<tr><td>DEA</td><td><a href="https://www.mql5.com/ru/articles/18495" target="_blank">dolphin echolocation algorithm</a></td></tr> <tr><td>DEA</td><td><a href="https://www.mql5.com/ru/articles/18495" target="_blank">dolphin echolocation algorithm</a></td></tr>
<tr><td>HS</td><td><a href="https://www.mql5.com/ru/articles/12163" target="_blank">harmony search</a></td></tr> <tr><td>HS</td><td><a href="https://www.mql5.com/ru/articles/12163" target="_blank">harmony search</a></td></tr>
<tr><td>SSG</td><td><a href="https://www.mql5.com/ru/articles/12268" target="_blank">saplings sowing and growing</a></td></tr> <tr><td>SSG</td><td><a href="https://www.mql5.com/ru/articles/12268" target="_blank">saplings sowing and growing</a></td></tr>
@@ -108,7 +109,7 @@
<tr><td>ACMO</td><td><a href="https://www.mql5.com/ru/articles/15921" target="_blank">atmospheric cloud model optimization</a></td></tr> <tr><td>ACMO</td><td><a href="https://www.mql5.com/ru/articles/15921" target="_blank">atmospheric cloud model optimization</a></td></tr>
<tr><td>ADAMm</td><td><a href="https://www.mql5.com/ru/articles/16443" target="_blank">adaptive moment estimation M</a></td></tr> <tr><td>ADAMm</td><td><a href="https://www.mql5.com/ru/articles/16443" target="_blank">adaptive moment estimation M</a></td></tr>
<tr><td>CryStAlm</td><td><a href="https://www.mql5.com/ru/articles/19899" target="_blank">crystal structure algorithm M</a></td></tr> <tr><td>CryStAlm</td><td><a href="https://www.mql5.com/ru/articles/19899" target="_blank">crystal structure algorithm M</a></td></tr>
<tr><td>BOA</td><td><a href="https://www.mql5.com/ru/articles/21209" target="_blank">butterfly optimization algorithm</a></td></tr> <tr><td>BOA</td><td><a href="https://www.mql5.com/ru/articles/21209" target="_blank">butterfly optimization algorithm</a></td></tr>
<tr><td>CoSO</td><td><a href="https://www.mql5.com/ru/articles/18886" target="_blank">community of scientist optimization</a></td></tr> <tr><td>CoSO</td><td><a href="https://www.mql5.com/ru/articles/18886" target="_blank">community of scientist optimization</a></td></tr>
<tr><td>CGO</td><td><a href="https://www.mql5.com/ru/articles/17047" target="_blank">chaos game optimization</a></td></tr> <tr><td>CGO</td><td><a href="https://www.mql5.com/ru/articles/17047" target="_blank">chaos game optimization</a></td></tr>
<tr><td>BSO(Beetle)</td><td><a href="https://www.mql5.com/ru/articles/21292" target="_blank">beetle swarm optimization</a></td></tr> <tr><td>BSO(Beetle)</td><td><a href="https://www.mql5.com/ru/articles/21292" target="_blank">beetle swarm optimization</a></td></tr>
+1
View File
@@ -34,6 +34,7 @@ CSO (competitive swarm optimizer)
BIO (blood inheritance optimization, joo) BIO (blood inheritance optimization, joo)
DOA_Dream (dream optimization algorithm) DOA_Dream (dream optimization algorithm)
BSA (bird swarm algorithm) BSA (bird swarm algorithm)
BWOm (beluga whale optimization M)
DEA (dolphin echolocation algorithm) DEA (dolphin echolocation algorithm)
HS (harmony search) HS (harmony search)
BCOm (bacterial chemotaxis optimization M) BCOm (bacterial chemotaxis optimization M)