This commit is contained in:
JQSakaJoo
2026-07-02 21:56:31 +04:00
parent dea4bde628
commit 91e79ee3b0
4 changed files with 403 additions and 0 deletions
Binary file not shown.
@@ -0,0 +1,401 @@
//+——————————————————————————————————————————————————————————————————+
//| C_AO_BEA |
//| Copyright 2007-2026, Andrey Dik |
//| https://www.mql5.com/ru/users/joo |
//———————————————————————————————————————————————————————————————————+
#include "#C_AO.mqh"
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
struct S_BEA_Ind
{
double c []; // координаты (валидные, уже прогнаны через SeInDiSp)
double f; // фитнес
void Init(int coords)
{
ArrayResize(c, coords);
f = -DBL_MAX;
}
};
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class C_AO_BEA : public C_AO
{
public:
~C_AO_BEA() {}
C_AO_BEA()
{
ao_name = "BEA";
ao_desc = "Bacterial Evolutionary Algorithm";
ao_link = "https://www.mql5.com/ru/articles/23232";
popSize = 10; // число бактерий
Nc = 2; // свежих мутантов сегмента на бактерию (>=1)
Nseg = 10; // число сегментов хромосомы
nTrans = 2; // эпох переноса генов на поколение
transFrac = 0.2; // длина переносимого блока как доля coords (0..1]
ArrayResize(params, 5);
params [0].name = "popSize"; params [0].val = popSize;
params [1].name = "Nc"; params [1].val = Nc;
params [2].name = "Nseg"; params [2].val = Nseg;
params [3].name = "nTrans"; params [3].val = nTrans;
params [4].name = "transFrac"; params [4].val = transFrac;
}
void SetParams()
{
popSize = (int)params [0].val;
Nc = (int)params [1].val;
Nseg = (int)params [2].val;
nTrans = (int)params [3].val;
transFrac = params [4].val;
//--- предохранители
if(popSize < 1)
popSize = 1;
if(Nc < 1)
Nc = 1; // число свежих мутантов на сегмент
if(Nseg < 1)
Nseg = 1;
if(nTrans < 0)
nTrans = 0;
if(transFrac <= 0.0)
transFrac = 0.01;
if(transFrac > 1.0)
transFrac = 1.0;
}
bool Init(const double &rangeMinP [],
const double &rangeMaxP [],
const double &rangeStepP [],
const int epochsP = 0);
void Moving();
void Revision();
//--- видимые параметры
int Nc; // клонов
int Nseg; // сегментов
int nTrans; // эпох переноса генов
double transFrac; // доля coords для блока переноса
private:
//--- фазы конечного автомата
enum E_Phase { PH_MUT = 0, PH_TRANS = 1 };
E_Phase phase;
int segIdx; // текущий сегмент в мутации
int cloneIdx; // текущий клон (срез оценки) в мутации
int transIdx; // текущая эпоха переноса
//--- данные (массивы структур)
S_BEA_Ind bact []; // [popSize] — закреплённые бактерии
S_BEA_Ind clone []; // [popSize * Nc] — рабочие клоны
int ord []; // [popSize] — индексы для сортировки
int transLen; // длина блока переноса (из transFrac)
//--- вспомогательные
void SegBounds(int s, int &lo, int &hi);
void BuildClonesForSeg(int s);
void DoGeneTransfer();
};
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Init |
//+------------------------------------------------------------------+
bool C_AO_BEA::Init(const double &rangeMinP [],
const double &rangeMaxP [],
const double &rangeStepP [],
const int epochsP = 0)
{
if(!StandardInit(rangeMinP, rangeMaxP, rangeStepP))
return false;
//--- сегментов не больше, чем координат
if(Nseg > coords)
Nseg = coords;
//--- длина блока переноса
transLen = (int)MathRound(transFrac * coords);
if(transLen < 1)
transLen = 1;
if(transLen > coords)
transLen = coords;
//--- буферы (массивы структур)
ArrayResize(bact, popSize);
ArrayResize(clone, popSize * Nc);
ArrayResize(ord, popSize);
for(int i = 0; i < popSize; i++)
bact [i].Init(coords);
for(int i = 0; i < popSize * Nc; i++)
clone [i].Init(coords);
//--- стартовая случайная популяция бактерий
for(int i = 0; i < popSize; i++)
{
for(int c = 0; c < coords; c++)
bact [i].c [c] = u.SeInDiSp(u.RNDfromCI(rangeMin [c], rangeMax [c]),
rangeMin [c], rangeMax [c], rangeStep [c]);
bact [i].f = -DBL_MAX;
}
//--- стартовое состояние автомата
phase = PH_MUT;
segIdx = 0;
cloneIdx = 0;
transIdx = 0;
return true;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| SegBounds — границы сегмента s в [lo, hi) с равномерным |
//| распределением остатка координат по сегментам |
//+------------------------------------------------------------------+
void C_AO_BEA::SegBounds(int s, int &lo, int &hi)
{
lo = (int)((long)s * coords / Nseg);
hi = (int)((long)(s + 1) * coords / Nseg);
if(lo < 0)
lo = 0;
if(hi > coords)
hi = coords;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| BuildClonesForSeg — снять с каждой бактерии Nc клонов и во |
//| ВСЕХ клонах случайно регенерировать координаты сегмента s. |
//| Инкумбент не хранится отдельным клоном: его фитнес помнится в |
//| bact.f и сравнивается при закреплении (см. Revision). |
//+------------------------------------------------------------------+
void C_AO_BEA::BuildClonesForSeg(int s)
{
int lo, hi;
SegBounds(s, lo, hi);
for(int b = 0; b < popSize; b++)
{
for(int j = 0; j < Nc; j++)
{
int idx = b * Nc + j;
//--- копия бактерии вне сегмента
for(int c = 0; c < coords; c++)
clone [idx].c [c] = bact [b].c [c];
//--- регенерация сегмента во ВСЕХ клонах. Инкумбент хранится
// отдельно (bact.f) и сравнивается на этапе закрепления —
// переоценивать его клоном не нужно, экономим вызовы FF.
for(int c = lo; c < hi; c++)
clone [idx].c [c] = u.SeInDiSp(u.RNDfromCI(rangeMin [c], rangeMax [c]),
rangeMin [c], rangeMax [c], rangeStep [c]);
clone [idx].f = -DBL_MAX;
}
}
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| DoGeneTransfer — сортировка популяции и инфицирование «слабой» |
//| половины блоками из «сильной». Модифицирует bact[] на месте. |
//+------------------------------------------------------------------+
void C_AO_BEA::DoGeneTransfer()
{
if(popSize < 2)
return;
//--- сортировка индексов по фитнесу бактерий (по убыванию)
for(int i = 0; i < popSize; i++)
ord [i] = i;
for(int i = 0; i < popSize - 1; i++)
{
int bi = i;
for(int j = i + 1; j < popSize; j++)
if(bact [ord [j]].f > bact [ord [bi]].f)
bi = j;
int t = ord [i];
ord [i] = ord [bi];
ord [bi] = t;
}
int half = popSize / 2;
if(half < 1)
half = 1;
int span = coords - transLen + 1;
if(span < 1)
span = 1;
//--- каждый приёмник «слабой» половины принимает блок от случайного
// источника «сильной» половины
for(int k = half; k < popSize; k++)
{
int dst = ord [k];
int src = ord [u.RNDminusOne(half)];
int start = u.RNDminusOne(span);
for(int t = 0; t < transLen; t++)
{
int c = start + t;
if(c < coords)
bact [dst].c [c] = bact [src].c [c];
}
}
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Moving |
//| Заполняет слоты a[i].c кандидатами для оценки этой эпохи. |
//+------------------------------------------------------------------+
void C_AO_BEA::Moving()
{
//--- первый прогон: бактерии -> слоты для первичной оценки FF
if(!revision)
{
for(int i = 0; i < popSize; i++)
for(int c = 0; c < coords; c++)
a [i].c [c] = u.SeInDiSp(bact [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);
return;
}
if(phase == PH_MUT)
{
//--- на старте сегмента строим клоны
if(cloneIdx == 0)
BuildClonesForSeg(segIdx);
//--- грузим текущий клон каждой бактерии в слоты
for(int b = 0; b < popSize; b++)
{
int idx = b * Nc + cloneIdx;
for(int c = 0; c < coords; c++)
a [b].c [c] = clone [idx].c [c];
}
}
else // PH_TRANS
{
//--- инфицируем «слабую» половину и грузим бактерии в слоты
DoGeneTransfer();
for(int b = 0; b < popSize; b++)
for(int c = 0; c < coords; c++)
a [b].c [c] = bact [b].c [c];
}
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Revision |
//| Считывает a[i].f, обновляет cB/fB и продвигает автомат. |
//+------------------------------------------------------------------+
void C_AO_BEA::Revision()
{
//--- глобальный лучший (элитизм: лучшее не теряется при переносе)
for(int i = 0; i < popSize; i++)
{
if(a [i].f > fB)
{
fB = a [i].f;
ArrayCopy(cB, a [i].c, 0, 0, coords);
}
}
//--- первичная фиксация фитнеса бактерий
if(!revision)
{
for(int i = 0; i < popSize; i++)
bact [i].f = a [i].f;
revision = true;
phase = PH_MUT;
segIdx = 0;
cloneIdx = 0;
transIdx = 0;
return;
}
if(phase == PH_MUT)
{
//--- сохраняем фитнес оценённого среза клонов
for(int b = 0; b < popSize; b++)
clone [b * Nc + cloneIdx].f = a [b].f;
cloneIdx++;
//--- сегмент полностью оценён -> закрепляем лучший клон
if(cloneIdx >= Nc)
{
for(int b = 0; b < popSize; b++)
{
int best = 0;
double bf = clone [b * Nc + 0].f;
for(int j = 1; j < Nc; j++)
{
double cf = clone [b * Nc + j].f;
if(cf > bf)
{
bf = cf;
best = j;
}
}
//--- закрепляем лучший мутант ТОЛЬКО если он превзошёл
// инкумбента; иначе бактерия остаётся прежней (монотонность
// мутации сохраняется без переоценки инкумбента клоном)
if(bf > bact [b].f)
{
int bi = b * Nc + best;
for(int c = 0; c < coords; c++)
bact [b].c [c] = clone [bi].c [c];
bact [b].f = bf;
}
}
cloneIdx = 0;
segIdx++;
//--- все сегменты пройдены -> перенос генов (или новое поколение)
if(segIdx >= Nseg)
{
segIdx = 0;
if(nTrans > 0)
{
phase = PH_TRANS;
transIdx = 0;
}
else
phase = PH_MUT;
}
}
}
else // PH_TRANS
{
//--- принимаем инфицированные генотипы (не-greedy)
for(int b = 0; b < popSize; b++)
bact [b].f = a [b].f;
transIdx++;
if(transIdx >= nTrans)
{
phase = PH_MUT;
segIdx = 0;
cloneIdx = 0;
}
}
}
//+------------------------------------------------------------------+
@@ -82,6 +82,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>BEA</td><td><a href="https://www.mql5.com/ru/articles/23232" target="_blank">bacterial evolutionary 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>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>
+1
View File
@@ -35,6 +35,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)
BEA (bacterial evolutionary algorithm)
BWOm (beluga whale optimization M) BWOm (beluga whale optimization M)
DEA (dolphin echolocation algorithm) DEA (dolphin echolocation algorithm)
HS (harmony search) HS (harmony search)