This commit is contained in:
JQSakaJoo
2024-04-11 11:51:56 +05:00
parent 1afbcb0236
commit 85c1360fab
11 changed files with 245 additions and 16 deletions
Binary file not shown.
@@ -4,6 +4,8 @@
//| https://www.mql5.com/ru/users/joo | //| https://www.mql5.com/ru/users/joo |
//—————————————————————————————————————————————————————————————————————————————+ //—————————————————————————————————————————————————————————————————————————————+
//Article: https://www.mql5.com/ru/articles/14491
#include "#C_AO.mqh" #include "#C_AO.mqh"
//—————————————————————————————————————————————————————————————————————————————— //——————————————————————————————————————————————————————————————————————————————
@@ -29,6 +31,7 @@ class C_AO_BSA : public C_AO
{ {
ao_name = "BSA"; ao_name = "BSA";
ao_desc = "Bird Swarm Algorithm"; ao_desc = "Bird Swarm Algorithm";
ao_link = "https://www.mql5.com/ru/articles/14491";
popSize = 20; //population size popSize = 20; //population size
@@ -14,18 +14,20 @@ struct S_BSO_Agent
double c []; //coordinates double c []; //coordinates
double f; //fitness double f; //fitness
int label; //cluster membership label int label; //cluster membership label
double minDist; //minimum distance to the nearest centroid
void Init (int coords) void Init (int coords)
{ {
ArrayResize (c, coords); ArrayResize (c, coords);
f = -DBL_MAX; f = -DBL_MAX;
label = -1; label = -1;
minDist = DBL_MAX;
} }
}; };
//—————————————————————————————————————————————————————————————————————————————— //——————————————————————————————————————————————————————————————————————————————
/*
//—————————————————————————————————————————————————————————————————————————————— //——————————————————————————————————————————————————————————————————————————————
struct S_Clusters struct S_Cluster
{ {
double centroid []; //cluster centroid double centroid []; //cluster centroid
double f; //centroid fitness double f; //centroid fitness
@@ -42,11 +44,11 @@ struct S_Clusters
//—————————————————————————————————————————————————————————————————————————————— //——————————————————————————————————————————————————————————————————————————————
//—————————————————————————————————————————————————————————————————————————————— //——————————————————————————————————————————————————————————————————————————————
class S_BSO_KMeans class C_BSO_KMeans
{ {
public: //-------------------------------------------------------------------- public: //--------------------------------------------------------------------
void KMeansInit (S_BSO_Agent &data [], int dataSizeClust, S_Clusters &clust []) void KMeansInit (S_BSO_Agent &data [], int dataSizeClust, S_Cluster &clust [])
{ {
for (int i = 0; i < ArraySize (clust); i++) for (int i = 0; i < ArraySize (clust); i++)
{ {
@@ -55,6 +57,50 @@ class S_BSO_KMeans
} }
} }
void KMeansPlusPlusInit (S_BSO_Agent &data [], int dataSizeClust, S_Cluster &clust [])
{
// Choose the first centroid randomly
int ind = MathRand () % dataSizeClust;
ArrayCopy (clust [0].centroid, data [ind].c, 0, 0, WHOLE_ARRAY);
for (int i = 1; i < ArraySize (clust); i++)
{
double sum = 0;
// Compute the distance from each data point to the nearest centroid
for (int j = 0; j < dataSizeClust; j++)
{
double minDist = DBL_MAX;
for (int k = 0; k < i; k++)
{
double dist = VectorDistance (data [j].c, clust [k].centroid);
if (dist < minDist)
{
minDist = dist;
}
}
data [j].minDist = minDist;
sum += minDist;
}
// Choose the next centroid with a probability proportional to the distance
double r = MathRand () * sum;
for (int j = 0; j < dataSizeClust; j++)
{
if (r <= data [j].minDist)
{
ArrayCopy (clust [i].centroid, data [j].c, 0, 0, WHOLE_ARRAY);
break;
}
r -= data [j].minDist;
}
}
}
double VectorDistance (double &v1 [], double &v2 []) double VectorDistance (double &v1 [], double &v2 [])
{ {
double distance = 0.0; double distance = 0.0;
@@ -65,7 +111,7 @@ class S_BSO_KMeans
return MathSqrt (distance); return MathSqrt (distance);
} }
void KMeans (S_BSO_Agent &data [], int dataSizeClust, S_Clusters &clust []) void KMeans (S_BSO_Agent &data [], int dataSizeClust, S_Cluster &clust [])
{ {
bool changed = true; bool changed = true;
int nClusters = ArraySize (clust); int nClusters = ArraySize (clust);
@@ -146,6 +192,183 @@ class S_BSO_KMeans
} }
}; };
//—————————————————————————————————————————————————————————————————————————————— //——————————————————————————————————————————————————————————————————————————————
*/
struct S_Cluster
{
double centroid []; //cluster centroid
double f; //centroid fitness
int count; //number of points in the cluster
int ideasList []; //list of ideas
void Init (int coords)
{
ArrayResize (centroid, coords);
f = -DBL_MAX;
ArrayResize (ideasList, 0, 100);
}
};
class C_BSO_KMeans
{
public:
double FitnessDistance (S_BSO_Agent &data, S_Cluster &clust, double alpha)
{
double distance = VectorDistance (data.c, clust.centroid);
double fitness_diff = fabs (data.f - clust.f);
return alpha * distance + (1 - alpha) * fitness_diff;
}
void KMeansInit (S_BSO_Agent &data [], int dataSizeClust, S_Cluster &clust [])
{
for (int i = 0; i < ArraySize (clust); i++)
{
int ind = MathRand () % dataSizeClust;
ArrayCopy (clust [i].centroid, data [ind].c, 0, 0, WHOLE_ARRAY);
clust [i].f = data [ind].f;
}
}
void KMeansPlusPlusInit (S_BSO_Agent &data [], int dataSizeClust, S_Cluster &clust [])
{
// Choose the first centroid randomly
int ind = MathRand () % dataSizeClust;
ArrayCopy (clust [0].centroid, data [ind].c, 0, 0, WHOLE_ARRAY);
for (int i = 1; i < ArraySize (clust); i++)
{
double sum = 0;
// Compute the distance from each data point to the nearest centroid
for (int j = 0; j < dataSizeClust; j++)
{
double minDist = DBL_MAX;
for (int k = 0; k < i; k++)
{
double dist = VectorDistance (data [j].c, clust [k].centroid);
if (dist < minDist)
{
minDist = dist;
}
}
data [j].minDist = minDist;
sum += minDist;
}
// Choose the next centroid with a probability proportional to the distance
double r = MathRand () * sum;
for (int j = 0; j < dataSizeClust; j++)
{
if (r <= data [j].minDist)
{
ArrayCopy (clust [i].centroid, data [j].c, 0, 0, WHOLE_ARRAY);
clust [i].f = data [ind].f;
break;
}
r -= data [j].minDist;
}
}
}
double VectorDistance (double &v1 [], double &v2 [])
{
double distance = 0.0;
for (int i = 0; i < ArraySize (v1); i++)
{
distance += (v1 [i] - v2 [i]) * (v1 [i] - v2 [i]);
}
return MathSqrt (distance);
}
void KMeans (S_BSO_Agent &data [], int dataSizeClust, S_Cluster &clust [], double alpha)
{
bool changed = true;
int nClusters = ArraySize (clust);
int cnt = 0;
while (changed && cnt < 100)
{
cnt++;
changed = false;
// Назначение точек данных к ближайшему центроиду
for (int d = 0; d < dataSizeClust; d++)
{
int closest_centroid = -1;
double closest_distance = DBL_MAX;
if (data [d].f != -DBL_MAX)
{
for (int cl = 0; cl < nClusters; cl++)
{
double distance = FitnessDistance (data [d], clust [cl], alpha);
if (distance < closest_distance)
{
closest_distance = distance;
closest_centroid = cl;
}
}
if (data [d].label != closest_centroid)
{
data [d].label = closest_centroid;
changed = true;
}
}
else
{
data [d].label = -1;
}
}
// Обновление центроидов
double sum_c [];
ArrayResize (sum_c, ArraySize (data [0].c));
double sum_f = 0.0;
for (int cl = 0; cl < nClusters; cl++)
{
ArrayInitialize (sum_c, 0.0);
clust [cl].count = 0;
ArrayResize (clust [cl].ideasList, 0);
sum_f = -DBL_MAX;
for (int d = 0; d < dataSizeClust; d++)
{
if (data [d].label == cl)
{
for (int k = 0; k < ArraySize (data [d].c); k++)
{
sum_c [k] += data [d].c [k];
}
if (data [d].f > sum_f) sum_f = data [d].f;
clust [cl].count++;
ArrayResize (clust [cl].ideasList, clust [cl].count);
clust [cl].ideasList [clust [cl].count - 1] = d;
}
}
if (clust [cl].count > 0)
{
for (int k = 0; k < ArraySize (sum_c); k++)
{
clust [cl].centroid [k] = sum_c [k] / clust [cl].count;
}
}
}
}
}
};
//—————————————————————————————————————————————————————————————————————————————— //——————————————————————————————————————————————————————————————————————————————
class C_AO_BSO : public C_AO class C_AO_BSO : public C_AO
@@ -219,8 +442,8 @@ class C_AO_BSO : public C_AO
S_BSO_Agent agent []; S_BSO_Agent agent [];
S_BSO_Agent parents []; S_BSO_Agent parents [];
S_Clusters clusters []; S_Cluster clusters [];
S_BSO_KMeans km; C_BSO_KMeans km;
private: //------------------------------------------------------------------- private: //-------------------------------------------------------------------
S_BSO_Agent parentsTemp []; S_BSO_Agent parentsTemp [];
@@ -275,16 +498,16 @@ bool C_AO_BSO::Init (const double &rangeMinP [], //minimum search range
выбирается индивид из одного кластера. выбирается индивид из одного кластера.
Если Pone_center Если Pone_center
выбирается центр кластера для мутации, выбирается центр кластера
иначе иначе
случайный индивид из этого кластера. случайный индивид из этого кластера
Иначе Иначе
выбираются индивиды из двух кластеров. выбираются индивиды из двух кластеров
Если Ptwo_center, Если Ptwo_center,
то два центра кластера объединяются и мутируют то два центра кластера объединяются
иначе иначе
случайно выбираются два индивида из каждого выбранного кластера, которые затем объединяются и мутируют. случайно выбираются два индивида из каждого выбранного кластера, которые затем объединяются
Мутация: Мутация:
Полученный индивид подвергается мутации с помощью гауссовой мутации Полученный индивид подвергается мутации с помощью гауссовой мутации
@@ -455,7 +678,7 @@ void C_AO_BSO::Moving ()
{ {
int x = (int)u.Scale (epochsNow, 1, epochs, 1, 200); int x = (int)u.Scale (epochsNow, 1, epochs, 1, 200);
double ξ = (1.0 / (1.0 + exp (-((100 - x) / k_Mutation))));// * u.RNDprobab (); double ξ = (1.0 / (1.0 + exp (-((100 - x) / k_Mutation)))); // * u.RNDprobab ();
double dist = (rangeMax [c] - rangeMin [c]) * distribCoeff * ξ; double dist = (rangeMax [c] - rangeMin [c]) * distribCoeff * ξ;
double min = a [i].c [c] - dist; if (min < rangeMin [c]) min = rangeMin [c]; double min = a [i].c [c] - dist; if (min < rangeMin [c]) min = rangeMin [c];
@@ -506,12 +729,15 @@ void C_AO_BSO::Revision ()
//выполнить кластеризацию----------------------------------------------------- //выполнить кластеризацию-----------------------------------------------------
if (!revision) if (!revision)
{ {
km.KMeansInit (parents, parentPopSize, clusters); km.KMeansInit (parents, parentPopSize, clusters);
//km.KMeansPlusPlusInit (parents, parentPopSize, clusters);
revision = true; revision = true;
} }
km.KMeansInit (parents, parentPopSize, clusters); km.KMeansInit (parents, parentPopSize, clusters);
km.KMeans (parents, parentPopSize, clusters); //km.KMeansPlusPlusInit (parents, parentPopSize, clusters);
km.KMeans (parents, parentPopSize, clusters, 0.8);
//km.KMeans (parents, parentPopSize, clusters);
//Назначить лучшее решение кластера центром кластера-------------------------- //Назначить лучшее решение кластера центром кластера--------------------------
for (int cl = 0; cl < clustersNumb; cl++) for (int cl = 0; cl < clustersNumb; cl++)
Binary file not shown.
View File
Binary file not shown.