This commit is contained in:
JQSakaJoo
2026-06-07 00:18:38 +04:00
parent b5dbcdc3e3
commit 1ffbc1bc5c
4 changed files with 329 additions and 1 deletions
Binary file not shown.
@@ -0,0 +1,326 @@
//+——————————————————————————————————————————————————————————————————+
//| C_AO_CVO |
//| Copyright 2007-2026, Andrey Dik |
//| https://www.mql5.com/ru/users/joo |
//———————————————————————————————————————————————————————————————————+
#include "#C_AO.mqh"
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
struct S_CVO_Patient
{
double c [];
double f;
};
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class C_AO_CVO : public C_AO
{
public:
~C_AO_CVO() {}
C_AO_CVO()
{
ao_name = "CVO";
ao_desc = "Corona Virus Optimization";
ao_link = "https://www.mql5.com/ru/articles/22887";
popSize = 50; // бюджет FE на эпоху (= кандидатов за проход)
nPop = 200; // потолок инфекционной популяции
basePop = 5; // стартовая инфекционная популяция
R0 = 5; // потомков-восприимчивых на одного носителя
rho = 0.1; // контактность: общий множитель масштаба λ
ArrayResize(params, 5);
params [0].name = "popSize"; params [0].val = popSize;
params [1].name = "nPop"; params [1].val = nPop;
params [2].name = "basePop"; params [2].val = basePop;
params [3].name = "R0"; params [3].val = R0;
params [4].name = "rho"; params [4].val = rho;
}
void SetParams()
{
popSize = (int)params [0].val;
nPop = (int)params [1].val;
basePop = (int)params [2].val;
R0 = (int)params [3].val;
rho = params [4].val;
//--- предохранители
if(popSize < 1) popSize = 1;
if(nPop < 1) nPop = 1;
if(R0 < 1) R0 = 1;
if(rho < 0.0) rho = 0.0;
if(basePop < 1) basePop = 1;
if(basePop > popSize) basePop = popSize; // пул засевается из 1-го батча
if(basePop > nPop) basePop = nPop;
}
bool Init(const double &rangeMinP [],
const double &rangeMaxP [],
const double &rangeStepP [],
const int epochsP = 0);
void Moving();
void Revision();
//--- видимые параметры
int nPop; // потолок инфекционной популяции
int basePop; // стартовая инфекционная популяция
int R0; // потомков на носителя
double rho; // множитель масштаба λ
private:
//--- инфекционный пул (массив структур: координаты + фитнес вместе)
S_CVO_Patient inf []; // [nPop]
int infCount; // текущий размер пула (<= nPop)
//--- привязка слота-кандидата к носителю
int parentOf []; // [popSize]
//--- временный пул пересборки
S_CVO_Patient tmp []; // [nPop + popSize]
//--- стандартное нормальное (Box-Muller), Eq.3
double Gauss();
//--- индексная сортировка по убыванию f
void ArgSortDesc(const double &f [], int &idx [], const int count);
};
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Init |
//+------------------------------------------------------------------+
bool C_AO_CVO::Init(const double &rangeMinP [],
const double &rangeMaxP [],
const double &rangeStepP [],
const int epochsP = 0)
{
if(!StandardInit(rangeMinP, rangeMaxP, rangeStepP))
return false;
//--- стартовый случайный батч в cP[] (оценится на первом проходе)
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(inf, nPop);
for(int i = 0; i < nPop; i++)
ArrayResize(inf [i].c, coords);
ArrayResize(tmp, nPop + popSize);
for(int i = 0; i < nPop + popSize; i++)
ArrayResize(tmp [i].c, coords);
ArrayResize(parentOf, popSize);
infCount = 0;
return true;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Moving |
//| |
//| Первый проход: случайный батч cP -> c (стенд его оценит, далее |
//| Revision засеет инфекционный пул лучшими basePop особями). |
//| Боевой проход: каждый слот-кандидат = восприимчивый, рождённый |
//| носителем p = (k/R0) % infCount возмущением λ (покоординатно). |
//+------------------------------------------------------------------+
void C_AO_CVO::Moving()
{
//--- первый прогон: cP -> c
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;
}
//--- генерация кандидатов-восприимчивых
for(int k = 0; k < popSize; k++)
{
int denom = infCount > 0 ? infCount : 1; // защита от %0
int p = (k / R0) % denom; // носитель данного слота
parentOf [k] = p;
for(int c = 0; c < coords; c++)
{
double phi = Gauss(); // Eq.3, [D1] свой на координату
double frac = (double)(infCount + k) / (double)nPop; // I/N, Eq.1*Eq.2, [D3]
if(frac > 1.0)
frac = 1.0;
double lam = rho * phi * frac; // абсолютный шаг, ТОЧНО по статье (Eq.1*2*3)
double v = inf [p].c [c] + lam * (rangeMax [c] - rangeMin [c]);
a [k].c [c] = u.SeInDiSp(v, rangeMin [c], rangeMax [c], rangeStep [c]);
}
}
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Revision |
//| |
//| 1. обновление личных и глобального лучших по кандидатам; |
//| 2. первый проход: посев пула лучшими basePop особями; |
//| 3. LocalBest эпохи; решение замена/рост пула; |
//| 4. приёмка восприимчивых (иммунитет >= носителя); |
//| 5. отсечение пула до nPop по убыванию f (выздоровление). |
//+------------------------------------------------------------------+
void C_AO_CVO::Revision()
{
//--- сохранить прежний глобальный лучший ДО обновления (для решения замена/рост)
double fB_prev = fB;
//--- 1) обновление лучших
for(int i = 0; i < popSize; i++)
{
if(!MathIsValidNumber(a [i].f)) // нечисло не должно отравлять лучших/пул
continue;
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);
}
}
//--- 2) первый проход: посев инфекционного пула лучшими basePop
if(!revision)
{
int idx [];
double af [];
ArrayResize(idx, popSize);
ArrayResize(af, popSize);
for(int i = 0; i < popSize; i++) af [i] = a [i].f;
ArgSortDesc(af, idx, popSize);
infCount = basePop; // basePop <= popSize (зажато в SetParams)
for(int n = 0; n < infCount; n++)
{
int s = idx [n];
ArrayCopy(inf [n].c, a [s].c, 0, 0, coords);
inf [n].f = a [s].f;
}
revision = true;
return;
}
//--- 3) лучший кандидат эпохи и решение замена/рост
double localBest = -DBL_MAX;
for(int i = 0; i < popSize; i++)
if(MathIsValidNumber(a [i].f) && a [i].f > localBest)
localBest = a [i].f;
bool improved = (localBest > fB_prev);
//--- 4) сборка обновлённого пула во временный пул (предвыделен в Init)
int cnt = 0;
if(!improved)
{
//--- рост: сначала весь прежний пул
for(int n = 0; n < infCount; n++)
{
ArrayCopy(tmp [cnt].c, inf [n].c, 0, 0, coords);
tmp [cnt].f = inf [n].f;
cnt++;
}
}
//--- принятые восприимчивые: иммунитет не лучше носителя -> заразился
// (читаем inf[p].f ДО перезаписи пула — наложения нет)
for(int k = 0; k < popSize; k++)
{
int p = parentOf [k];
if(MathIsValidNumber(a [k].f) && a [k].f >= inf [p].f)
{
ArrayCopy(tmp [cnt].c, a [k].c, 0, 0, coords);
tmp [cnt].f = a [k].f;
cnt++;
}
}
//--- защита: при замене с пустым набором сохраняем прежний пул
if(cnt == 0)
return;
//--- 5) отсечение до nPop (выздоровление/смерть слабейших)
if(cnt > nPop)
{
int idx [];
double tf [];
ArrayResize(idx, cnt);
ArrayResize(tf, cnt);
for(int n = 0; n < cnt; n++)
tf [n] = tmp [n].f;
ArgSortDesc(tf, idx, cnt);
for(int n = 0; n < nPop; n++)
{
int s = idx [n];
ArrayCopy(inf [n].c, tmp [s].c, 0, 0, coords);
inf [n].f = tmp [s].f;
}
infCount = nPop;
}
else
{
for(int n = 0; n < cnt; n++)
{
ArrayCopy(inf [n].c, tmp [n].c, 0, 0, coords);
inf [n].f = tmp [n].f;
}
infCount = cnt;
}
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Gauss — стандартное нормальное (Box-Muller) |
//+------------------------------------------------------------------+
double C_AO_CVO::Gauss()
{
double u1 = u.RNDfromCI(0.0, 1.0);
double u2 = u.RNDfromCI(0.0, 1.0);
if(u1 < 1e-15)
u1 = 1e-15; // защита от ln(0)
return MathSqrt(-2.0 * MathLog(u1)) * MathCos(2.0 * M_PI * u2);
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| ArgSortDesc — порядок индексов по убыванию f |
//+------------------------------------------------------------------+
void C_AO_CVO::ArgSortDesc(const double &f [], int &idx [], const int count)
{
for(int i = 0; i < count; i++)
idx [i] = i;
for(int i = 0; i < count - 1; i++)
{
int b = i;
for(int j = i + 1; j < count; j++)
if(f [idx [j]] > f [idx [b]])
b = j;
if(b != i)
{
int t = idx [i];
idx [i] = idx [b];
idx [b] = t;
}
}
}
//+------------------------------------------------------------------+
@@ -109,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>
@@ -151,6 +151,7 @@
<tr><td>ASSA</td><td><a href="https://www.mql5.com/ru/articles/21671" target="_blank">artificial searching swarm algorithm</a></td></tr> <tr><td>ASSA</td><td><a href="https://www.mql5.com/ru/articles/21671" target="_blank">artificial searching swarm algorithm</a></td></tr>
<tr><td>CHA</td><td><a href="https://www.mql5.com/ru/articles/18132" target="_blank">color harmony algorithm</a></td></tr> <tr><td>CHA</td><td><a href="https://www.mql5.com/ru/articles/18132" target="_blank">color harmony algorithm</a></td></tr>
<tr><td>GSA</td><td><a href="https://www.mql5.com/ru/articles/12072" target="_blank">gravitational search algorithm</a></td></tr> <tr><td>GSA</td><td><a href="https://www.mql5.com/ru/articles/12072" target="_blank">gravitational search algorithm</a></td></tr>
<tr><td>CVO</td><td><a href="https://www.mql5.com/ru/articles/22887" target="_blank">corona virus optimization</a></td></tr>
<tr><td>ACCS</td><td><a href="https://www.mql5.com/ru/articles/19861" target="_blank">artificial coronary circulation system</a></td></tr> <tr><td>ACCS</td><td><a href="https://www.mql5.com/ru/articles/19861" target="_blank">artificial coronary circulation system</a></td></tr>
<tr><td>BFO</td><td><a href="https://www.mql5.com/ru/articles/12031" target="_blank">bacterial foraging optimization</a></td></tr> <tr><td>BFO</td><td><a href="https://www.mql5.com/ru/articles/12031" target="_blank">bacterial foraging optimization</a></td></tr>
<tr><td>ABC</td><td><a href="https://www.mql5.com/ru/articles/11736" target="_blank">artificial bee colony</a></td></tr> <tr><td>ABC</td><td><a href="https://www.mql5.com/ru/articles/11736" target="_blank">artificial bee colony</a></td></tr>
+1
View File
@@ -93,6 +93,7 @@ CPA (cyclic parthenogenesis algorithm)
CA_Cricket (cricket algorithm) CA_Cricket (cricket algorithm)
ASSA (artificial searching swarm algorithm) ASSA (artificial searching swarm algorithm)
CHA (color harmony algorithm) CHA (color harmony algorithm)
CVO (corona virus optimization)
ACCS (Artificial Coronary Circulation System) ACCS (Artificial Coronary Circulation System)
AAA (artificial algae algorithm) AAA (artificial algae algorithm)
Boids (boids algorithm) Boids (boids algorithm)