Files
Population-optimization-alg…/MQL5/Include/Math/AOs/PopulationAO/AO_DE_DifferentialEvolution.mqh
T
JQSakaJoo ca5827242c add DE
2024-05-01 12:02:50 +05:00

188 lines
12 KiB
Plaintext

//+————————————————————————————————————————————————————————————————————————————+
//| C_AO_DE |
//| Copyright 2007-2024, Andrey Dik |
//| https://www.mql5.com/ru/users/joo |
//—————————————————————————————————————————————————————————————————————————————+
//Article: https://www.mql5.com/ru/articles/13781
#include "#C_AO.mqh"
//——————————————————————————————————————————————————————————————————————————————
struct S_DE_Agent
{
double cPrev []; //previous coordinates
double fPrev; //previous fitness
void Init (int coords)
{
ArrayResize (cPrev, coords);
fPrev = -DBL_MAX;
}
};
//——————————————————————————————————————————————————————————————————————————————
//——————————————————————————————————————————————————————————————————————————————
class C_AO_DE : public C_AO
{
public: //--------------------------------------------------------------------
~C_AO_DE () { }
C_AO_DE ()
{
ao_name = "DE";
ao_desc = "Differential Evolution";
ao_link = "https://www.mql5.com/ru/articles/13781";
popSize = 50; //population size
diffWeight = 0.2; //differential weight
crossProbab = 0.8; //crossover robability
ArrayResize (params, 3);
params [0].name = "popSize"; params [0].val = popSize;
params [1].name = "diffWeight"; params [1].val = diffWeight;
params [2].name = "crossProbab"; params [2].val = crossProbab;
}
void SetParams ()
{
popSize = (int)params [0].val;
diffWeight = params [1].val;
crossProbab = params [2].val;
}
bool Init (const double &rangeMinP [], //minimum search range
const double &rangeMaxP [], //maximum search range
const double &rangeStepP [], //step search
const int epochsP = 0); //number of epochs
void Moving ();
void Revision ();
void Injection (const int popPos, const int coordPos, const double value);
//----------------------------------------------------------------------------
double diffWeight; //differential weight
double crossProbab; //crossover robability
S_DE_Agent agent [];
};
//——————————————————————————————————————————————————————————————————————————————
//——————————————————————————————————————————————————————————————————————————————
bool C_AO_DE::Init (const double &rangeMinP [], //minimum search range
const double &rangeMaxP [], //maximum search range
const double &rangeStepP [], //step search
const int epochsP = 0) //number of epochs
{
if (!StandardInit (rangeMinP, rangeMaxP, rangeStepP)) return false;
//----------------------------------------------------------------------------
ArrayResize (agent, popSize);
for (int i = 0; i < popSize; i++) agent [i].Init (coords);
return true;
}
//——————————————————————————————————————————————————————————————————————————————
//——————————————————————————————————————————————————————————————————————————————
void C_AO_DE::Moving ()
{
//----------------------------------------------------------------------------
if (!revision)
{
for (int i = 0; i < popSize; i++)
{
for (int c = 0; c < coords; c++)
{
a [i].c [c] = u.RNDfromCI (rangeMin [c], rangeMax [c]);
a [i].c [c] = u.SeInDiSp (a [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);
}
}
revision = true;
return;
}
//----------------------------------------------------------------------------
int r1 = 0;
int r2 = 0;
int r3 = 0;
for (int i = 0; i < popSize; i++)
{
do r1 = u.RNDminusOne (popSize);
while (r1 == i);
do r2 = u.RNDminusOne (popSize);
while (r2 == i || r2 == r1);
do r3 = u.RNDminusOne (popSize);
while (r3 == i || r3 == r1 || r3 == r2);
for (int c = 0; c < coords; c++)
{
if (u.RNDprobab () < crossProbab)
{
a [i].c [c] = agent [r1].cPrev [c] + diffWeight * (agent [r2].cPrev [c] - agent [r3].cPrev [c]);
a [i].c [c] = u.SeInDiSp (a [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);
}
else
{
a [i].c [c] = agent [i].cPrev [c];
}
}
}
}
//——————————————————————————————————————————————————————————————————————————————
//——————————————————————————————————————————————————————————————————————————————
void C_AO_DE::Revision ()
{
//----------------------------------------------------------------------------
int ind = -1;
for (int i = 0; i < popSize; i++)
{
if (a [i].f > fB)
{
fB = a [i].f;
ind = i;
}
}
if (ind != -1) ArrayCopy (cB, a [ind].c, 0, 0, WHOLE_ARRAY);
//----------------------------------------------------------------------------
for (int i = 0; i < popSize; i++)
{
if (a [i].f > agent [i].fPrev)
{
agent [i].fPrev = a [i].f;
ArrayCopy (agent [i].cPrev, a [i].c, 0, 0, WHOLE_ARRAY);
}
}
}
//——————————————————————————————————————————————————————————————————————————————
//——————————————————————————————————————————————————————————————————————————————
void C_AO_DE::Injection (const int popPos, const int coordPos, const double value)
{
if (popPos < 0 || popPos >= popSize) return;
if (coordPos < 0 || coordPos >= coords) return;
if (value < rangeMin [coordPos])
{
a [popPos].c [coordPos] = rangeMin [coordPos];
}
if (value > rangeMax [coordPos])
{
a [popPos].c [coordPos] = rangeMax [coordPos];
}
a [popPos].c [coordPos] = u.SeInDiSp (value, rangeMin [coordPos], rangeMax [coordPos], rangeStep [coordPos]);
}
//——————————————————————————————————————————————————————————————————————————————