184 lines
10 KiB
Plaintext
184 lines
10 KiB
Plaintext
//+——————————————————————————————————————————————————————————————————+
|
|
//| C_AO_HS |
|
|
//| Copyright 2007-2025, Andrey Dik |
|
|
//| https://www.mql5.com/ru/users/joo |
|
|
//+——————————————————————————————————————————————————————————————————+
|
|
|
|
#include "#C_AO.mqh"
|
|
|
|
//————————————————————————————————————————————————————————————————————
|
|
class C_AO_HS : public C_AO
|
|
{
|
|
public: //------------------------------------------------------------
|
|
~C_AO_HS() { }
|
|
C_AO_HS()
|
|
{
|
|
ao_name = "HS";
|
|
ao_desc = "Harmony Search";
|
|
ao_link = "https://www.mql5.com/ru/articles/11230";
|
|
|
|
popSize = 50;
|
|
|
|
Eh = 0.9;
|
|
Ep = 0.1;
|
|
rangeKo = 0.1;
|
|
|
|
ArrayResize(params, 4);
|
|
|
|
params [0].name = "popSize";
|
|
params [0].val = popSize;
|
|
params [1].name = "Eh";
|
|
params [1].val = Eh;
|
|
params [2].name = "Ep";
|
|
params [2].val = Ep;
|
|
params [3].name = "rangeKo";
|
|
params [3].val = rangeKo;
|
|
}
|
|
|
|
void SetParams()
|
|
{
|
|
popSize = (int)params [0].val;
|
|
Eh = params [1].val;
|
|
Ep = params [2].val;
|
|
rangeKo = params [3].val;
|
|
}
|
|
|
|
bool Init(const double &rangeMinP [],
|
|
const double &rangeMaxP [],
|
|
const double &rangeStepP [],
|
|
const int epochsP = 0);
|
|
|
|
void Moving();
|
|
void Revision();
|
|
|
|
//------------------------------------------------------------------
|
|
double Eh; // частота случайного выбора аккорда из гармонии
|
|
double Ep; // частота пошаговой настройки
|
|
double rangeKo; // диапазон случайного отклонения
|
|
|
|
private: //-----------------------------------------------------------
|
|
int epochs;
|
|
int epochNow;
|
|
double freq []; // ширина диапазона по каждой координате
|
|
};
|
|
//————————————————————————————————————————————————————————————————————
|
|
|
|
//————————————————————————————————————————————————————————————————————
|
|
bool C_AO_HS::Init(const double &rangeMinP [],
|
|
const double &rangeMaxP [],
|
|
const double &rangeStepP [],
|
|
const int epochsP = 0)
|
|
{
|
|
if(!StandardInit(rangeMinP, rangeMaxP, rangeStepP))
|
|
return false;
|
|
|
|
//--------------------------------------------------------------------
|
|
epochs = epochsP;
|
|
epochNow = 0;
|
|
|
|
ArrayResize(freq, coords);
|
|
|
|
for(int c = 0; c < coords; c++)
|
|
{
|
|
freq [c] = rangeMax [c] - rangeMin [c];
|
|
}
|
|
|
|
return true;
|
|
}
|
|
//————————————————————————————————————————————————————————————————————
|
|
|
|
//————————————————————————————————————————————————————————————————————
|
|
void C_AO_HS::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;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
epochNow++;
|
|
|
|
double r = 0.0;
|
|
int addr = 0;
|
|
double minB = 0.0;
|
|
double maxB = 0.3;
|
|
double B = 0.0;
|
|
|
|
if(epochs > 0)
|
|
B = ((epochs - epochNow) / (double)epochs) * (maxB - minB) + minB;
|
|
else
|
|
B = maxB;
|
|
|
|
for(int i = 0; i < popSize; i++)
|
|
{
|
|
for(int c = 0; c < coords; c++)
|
|
{
|
|
r = u.RNDfromCI(0.0, 1.0);
|
|
|
|
if(r <= Eh)
|
|
{
|
|
// выбрать аккорд из случайной гармонии
|
|
r = u.RNDfromCI(0.0, popSize - 1);
|
|
addr = (int)MathRound(r);
|
|
if(addr < 0)
|
|
addr = 0;
|
|
if(addr > popSize - 1)
|
|
addr = popSize - 1;
|
|
|
|
a [i].c [c] = a [addr].cB [c];
|
|
|
|
// пошаговая настройка с вероятностью Ep
|
|
r = u.RNDfromCI(0.0, 1.0);
|
|
|
|
if(r < Ep)
|
|
{
|
|
r = u.RNDfromCI(-1.0, 1.0);
|
|
a [i].c [c] = a [i].c [c] + r * B * freq [c];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// случайное отклонение от личного лучшего
|
|
r = u.RNDfromCI(-1.0, 1.0);
|
|
a [i].c [c] = a [i].cB [c] + r * rangeKo * freq [c];
|
|
}
|
|
|
|
a [i].c [c] = u.SeInDiSp(a [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);
|
|
}
|
|
}
|
|
}
|
|
//————————————————————————————————————————————————————————————————————
|
|
|
|
//————————————————————————————————————————————————————————————————————
|
|
void C_AO_HS::Revision()
|
|
{
|
|
for(int i = 0; i < popSize; i++)
|
|
{
|
|
// обновление глобального лучшего
|
|
if(a [i].f > fB)
|
|
{
|
|
fB = a [i].f;
|
|
ArrayCopy(cB, a [i].c, 0, 0, WHOLE_ARRAY);
|
|
}
|
|
|
|
// обновление личного лучшего
|
|
if(a [i].f > a [i].fB)
|
|
{
|
|
a [i].fB = a [i].f;
|
|
ArrayCopy(a [i].cB, a [i].c, 0, 0, WHOLE_ARRAY);
|
|
}
|
|
}
|
|
}
|
|
//————————————————————————————————————————————————————————————————————
|