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 |
//—————————————————————————————————————————————————————————————————————————————+
//Article: https://www.mql5.com/ru/articles/14491
#include "#C_AO.mqh"
//——————————————————————————————————————————————————————————————————————————————
@@ -29,6 +31,7 @@ class C_AO_BSA : public C_AO
{
ao_name = "BSA";
ao_desc = "Bird Swarm Algorithm";
ao_link = "https://www.mql5.com/ru/articles/14491";
popSize = 20; //population size
@@ -14,18 +14,20 @@ struct S_BSO_Agent
double c []; //coordinates
double f; //fitness
int label; //cluster membership label
double minDist; //minimum distance to the nearest centroid
void Init (int coords)
{
ArrayResize (c, coords);
f = -DBL_MAX;
label = -1;
minDist = DBL_MAX;
}
};
//——————————————————————————————————————————————————————————————————————————————
/*
//——————————————————————————————————————————————————————————————————————————————
struct S_Clusters
struct S_Cluster
{
double centroid []; //cluster centroid
double f; //centroid fitness
@@ -42,11 +44,11 @@ struct S_Clusters
//——————————————————————————————————————————————————————————————————————————————
//——————————————————————————————————————————————————————————————————————————————
class S_BSO_KMeans
class C_BSO_KMeans
{
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++)
{
@@ -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 distance = 0.0;
@@ -65,7 +111,7 @@ class S_BSO_KMeans
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;
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
@@ -219,8 +442,8 @@ class C_AO_BSO : public C_AO
S_BSO_Agent agent [];
S_BSO_Agent parents [];
S_Clusters clusters [];
S_BSO_KMeans km;
S_Cluster clusters [];
C_BSO_KMeans km;
private: //-------------------------------------------------------------------
S_BSO_Agent parentsTemp [];
@@ -275,16 +498,16 @@ bool C_AO_BSO::Init (const double &rangeMinP [], //minimum search range
выбирается индивид из одного кластера.
Если Pone_center
выбирается центр кластера для мутации,
выбирается центр кластера
иначе
случайный индивид из этого кластера.
случайный индивид из этого кластера
Иначе
выбираются индивиды из двух кластеров.
выбираются индивиды из двух кластеров
Если Ptwo_center,
то два центра кластера объединяются и мутируют
то два центра кластера объединяются
иначе
случайно выбираются два индивида из каждого выбранного кластера, которые затем объединяются и мутируют.
случайно выбираются два индивида из каждого выбранного кластера, которые затем объединяются
Мутация:
Полученный индивид подвергается мутации с помощью гауссовой мутации
@@ -455,7 +678,7 @@ void C_AO_BSO::Moving ()
{
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 min = a [i].c [c] - dist; if (min < rangeMin [c]) min = rangeMin [c];
@@ -506,12 +729,15 @@ void C_AO_BSO::Revision ()
//выполнить кластеризацию-----------------------------------------------------
if (!revision)
{
km.KMeansInit (parents, parentPopSize, clusters);
km.KMeansInit (parents, parentPopSize, clusters);
//km.KMeansPlusPlusInit (parents, parentPopSize, clusters);
revision = true;
}
km.KMeansInit (parents, parentPopSize, clusters);
km.KMeans (parents, parentPopSize, clusters);
km.KMeansInit (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++)
Binary file not shown.
View File
Binary file not shown.