p6biii
if(uniRand()<0.4)
ifrand()<0.4
p6c
if(uniRand()<0.5)
ifrand()<0.5
k
(0.5*max_iteration-n_iteration)/20
(0.5*max_iteration-n_iteration)/20
Max_iteration
constintmax_iteration=2000;
max_iteration=2000;
μ
normal_distributionn(0,1)
normrnd(0,1,1,n_d)
σ
BSO的维度修改
在进行不同维度测试时,请注意不仅要修改bsocore.cpp里的维度值,如下阴影部分:
constintnd=10;//Numberofdimension
而且要同步手动修改function.cpp里面的纬度值,如下阴影部分:
for(inti=0;i<10;i++)
三、测试结果
测试组别
BenchmarkFunctions
测试版本
dimension
mean
best
worst
variance
times
第1组
Rastrigin
C++
10
6.116364
1.98992
12.9345
6.586904071
4h7min
第2组
20
20.9735298
7.99479
41.9196
54.44474071
7h14min
第3组
30
45.723414
24.6508
111.986
294.5966334
9h42min
第4组
MATLAB
10
4.01963449
0.994959057
5.969754343
1.503129856
8min
第5组
20
18.30723405
8.954631514
30.84370054
23.60017541
10min
第6组
30
33.31119546
15.91934491
48.75290806
53.90180219
12min
第7组
Sphere
C++
10
5.23E-10
9.94E-45
2.05E-08
8.73199E-18
4h21min
第8组
20
2.26E-04
3.07826E-14
0.00498379
8.37836E-07
8h30min
第9组
30
3.26E-03
2.37E-05
7.33E-02
0.000114121
11h46min
第10组
MATLAB
10
3.97518E-44
1.4457E-44
6.55026E-44
1.56692E-88
12.5min
第11组
20
3.21718E-43
1.37202E-43
5.99555E-43
8.50032E-87
12min
第12组
30
1.12363E-42
4.90549E-43
1.59672E-42
5.34992E-86
11.5min
C++版本完成评估测试使用时间:
45h40min(20位没有优化)
MATLAB版本完成评估测试使用时间:
66min(16位平台优化)
Rastrigin评估BSO算法
在维度相同、代码语言版本不同时的最优解分布图。
下面是三幅分别维度为10、20、30的两款代码的最优解分布图,其中x轴为遍数,范围是0~50,y轴是最优解的大小。
现象:
dimension=10时,MATLAB的BSO的最优解更优。
dimension=20、30时,两版本的最优解相差不大。
我们估计这个区别来源于MATLAB的随机数与C++的不太一样,需要进一步验证。
在代码版本相同、维度不同时的最优解分布图。
现象:
两版本在迭代最优解时,最优解随维度变化而变化,维度越低最优解越好,维度越高最优解越差。
因为局部最优的数量指数递增。
Sphere评估BSO算法
由于C++版本的BSO精度位数与MATLAB不同,导致随机数实际分布状态也不一致,单峰测试比上面的多峰测试收敛速度快出去许多,所以同一维度的最优解相差甚大,不同维度的最优解也是相差甚大,无法绘制出一张可供分析的最优解分布图。
所以本节改为最优解的指数分布情况,以及MATLAB的不同维度最优解分布情况。
C++版本的不同维度最优解的指数量级分布图
现象:
最优解的精度与随机数的精度不匹配,相比较优化完美的Matlab在10维20维30维的平均值3.97518E-44、3.21718E-43、1.12363E-42,C++在小数部分精度还存在匹配问题,需要手动优化,但是不影响不需要超精细的优化的运用。
MATLAB版本的不同维度最优解分布图
现象:
与Rastrigin评估结果相同
MATLAB在迭代最优解时,最优解随维度变化而变化,维度越低最优解越好,维度越高最优解越差。
四、对角线变种算法
可以看到随机数的多寡,精度以及实际分布都会影响到算法的探索与收敛能力,为了进一步验证这个现象,下面我们对原始BSO做了一个歪打正着的变种,也就是让不同维度的随机数强制为同一个随机数,相当于探索只在对角线上跑,运行结果会差一点,但凑合能用!
在CPP版本的BSO代码中,新解生成的步骤采用了对角线算法,截图如上:
stepSize里的每一个值与高斯分布(一个)相乘。
而MATLAB版本的新解生成则是:
stepSize里的每一个值与高斯分布(n_d个)相乘。
截图如下。
将对角线算法应用到MATLAB版本中运行。
(使用Rastrigin函数,每个维度运行50次,取10,20,30这三个维度进行测试)结果如下:
Dimension
mean
best
worst
variance
C++
10
6.116364
1.98992
12.9345
6.586904
MATLAB
12.05889
2.984877
24.87393
25.80335
C++
20
20.97353
7.99479
41.9196
54.44474
MATLAB
25.33163
11.9395
42.78316
68.03684
C++
30
45.72341
24.6508
111.986
294.5966
MATLAB
45.45065
18.90488
73.62722
184.5416
附录A:
C++版本的BSO代码
function.h
#pragmaonce
#include
#include
#include
#include
#include
#include
#include
#include"kmeans.h"
usingnamespacestd;
classFunction
{
public:
Function();
doublefun(Pointpoint);
};
kmeans.h
#pragmaonce
#include
#include
#include
#include
#include
#include
#include
#include
usingnamespacestd;
/**
Created:
2018-11-17,Updated:
2018-11-17
Author:
SiqingMa
Version:
V0.1T
**/
classPoint
{
private:
intid_point,id_cluster;
vectorvalues;
intnd;
public:
Point(intid_point,vector&values);
intgetID();
voidsetID(intid);
voidsetCluster(intid_cluster);
intgetCluster();
doublegetValue(intindex);
intgetDimension();
voidsetValue(intindex,doublevalue);
};
classCluster
{
private:
intid_cluster;
vectorcentral_values;
mappoints;
public:
Cluster(intid_cluster,Pointpoint);
voidaddPoint(Pointpoint);
voidremovePoint(intid_point);
doublegetCentralValue(intindex);
voidsetCentralValue(intindex,doublevalue);
mapgetPoints();
intgetID();
intgetSize();
};
classKMeans
{
private:
intnc,nd,np,max_iterations;
vectorinit_centres;
vectorclusters;
vectordependency;
//returnIDofnearestcenter
intgetNearestCentreId(Pointpoint);
public:
KMeans(intnc,intnp,intnd,intmax_iterations,vectorcenters);
ClustergetCluster(intindex);
vectorgetDependency();
voidrun(vector&points);
};
function.cpp
//Authors:
SiqingMa
//Date:
2018-11-15created,2018-12-1updated
//BSOFUNCTION
#include
#include
#include
#include
#include
#include
#include"kmeans.h"
#include"function.h"
usingnamespacestd;
Function:
:
Function(){}
doubleFunction:
:
fun(Pointpoint)
{
doublez=0;
for(inti=0;i<10;i++)
{
//functionrastrigin
z=z+pow(point.getValue(i),2)+10-10*cos(2*3.141592654*point.getValue(i));
//functionsphere
//z=z+pow(point.getValue(i),2)
}
returnz;
}
kmeans.cpp
//Authors:
SiqingMa
//Date:
2018-11-15created,2018-12-1updated
//Kmeansalgorithm
//Distancemode:
"cityblock"
//EmptyActionmode:
"singleton"
#include
#include
#include
#include
#include
#include
#include
#include"kmeans.h"
usingnamespacestd;
Point:
:
Point(intid_point,vector&values)
{
this->id_point=id_point;
nd=values.size();
for(inti=0;ivalues.push_back(values[i]);
id_cluster=-1;
}
intPoint:
:
getID()
{
returnid_point;
}
voidPoint:
:
setID(intid)
{
this->id_point=id;
}
voidPoint:
:
setCluster(intid_cluster)
{
this->id_cluster=id_cluster;
}
intPoint:
:
getCluster()
{
returnid_cluster;
}
doublePoint:
:
getValue(intindex)
{
returnvalues[index];
}
intPoint:
:
getDimension()
{
returnnd;
}
voidPoint:
:
setValue(intindex,doublevalue)
{
values[index]=value;
}
Cluster:
:
Cluster(intid_cluster,Pointpoint)
{
this->id_cluster=id_cluster;
intdimension=point.getDimension();
for(inti=0;icentral_values.push_back(point.getValue(i));
//points.insert(pair(point.getID(),point));
}
voidCluster:
:
addPoint(Pointpoint)
{
points.insert(pair(point.getID(),point));
}
voidCluster:
:
removePoint(intid_point)
{
points.erase(id_point);
}
doubleCluster:
:
getCentralValue(intindex)
{
returncentral_values[index];
}
voidCluster:
:
setCentralValue(intindex,doublevalue)
{
central_values[index]=value;
}
intCluster:
:
getSize()
{
returnpoints.size();
}
intCluster:
:
getID()
{
returnid_cluster;
}
mapCluster:
:
getPoints()
{
returnpoints;
}
KMeans:
:
KMeans(intnc,intnp,intnd,intmax_iterations,vectorcenters)
{
this->nc=nc;
this->np=np;
this->nd=nd;
this->max_iterations=max_iterations;
this->init_centres=centers;
}
intKMeans:
:
getNearestCentreId(Pointpoint)
{
doublesum=0.0,min_dist;
intnearest_centre_id=0;
//Initial
//Usescityblockdistance
for(inti=0;i{
sum+=abs(clusters[0].getCentralValue(i)-
point.getValue(i));
}
min_dist=sum;
for(inti=1;i{
doubledist;
sum=0.0;
//Usescityblockdistance
for(intj=0;j{
sum+=abs(clusters[i].getCentralValue(j)-
point.getValue(j));
}
dist=sum;
if(dist{
min_dist=dist;
nearest_centre_id=i;
}
}
returnnearest_centre_id;
}
ClusterKMeans:
:
getCluster(intindex)
{
returnclusters[index];
}
vectorKMeans:
:
getDependency()
{
returndependency;
}
voidKMeans:
:
run(vector&po)
{
if(nc>np)
return;
vectornow_indexes;
//Initialtheclustercentrebyusingtheprovidedcentre_2018-11-19
for(inti=0;i{
init_centres[i].setID(-1);
Clustercentre(i,init_centres[i]);
clusters.push_back(centre);
}
for(inti=0;i{
po[i].setCluster(-1);
}
intiter=1;
while(true)
{
booldone=true;
//associateseachpointtothenearestcenter
for(inti=0;i{
intid_old_cluster=po[i].getCluster();
intid_nearest_center=getNearestCentreId(po[i]);
if(id_old_cluster!
=id_nearest_center)
{
if(id_old_cluster!
=-1)
clusters[id_old_cluster].removePoint(po[i].getID());
po[i].setCluster(id_nearest_center);