Feathersky 2007
流程图
初始化一群随机粒子(随机解)
//粒子的类
class CParticle
{
public:
int nDimension; //维度
double coordinate[MaxDimension]; //每个维度的坐标
//粒子i位置:xi=(xi1,xi2,…xid),将xi代入适应函数f(xi)求适应值;
double coordinateLimit[MaxDimension][2]; // 每个维度的坐标上下限
double velocity[MaxDimension]; //每个维度的速度
double velocityLimit[MaxDimension][2]; //每个维度的速度上下限
在每一维,粒子都有一个最大限制速度Vmax,如果
某一维的速度超过设定的Vmax ,那么这一维的速度
就被限定为Vmax 。( Vmax >0)
//个体的最优记录
double pBest;
double pBestCoordinate[MaxDimension]; //每个维度的坐标
//更新速度所用参数
double w;
double c1;
double c2;
}
每次迭代中,粒子通过跟踪两个极值更新自己:
-粒子本身找到的历史最后解(个体极值点pbest)
-整个种群目前找到的最好解(全局极值点gbest)
double Fitness(FitnessFunc pFunc,int N,double fChange=0)
{
double fitness=pFunc(coordinate,N,fChange);
//记录个体最优
if(fitness<pBest)
{
pBest=fitness;
memcpy(pBestCoordinate,coordinate,nDimension*sizeof(double));
}
return fitness;
}
需要计算粒子的适应值,以判断粒子位置距最优点的距离。
每次迭代中,根据适应度值更新pbest和gbest。
粒子i的第n维速度和位置更新公式:
vin=w*vin+c1*r1*(pbestin-xin)+c2*r2*(gbestn-xin)
xin=xin+vin
c1,c2—学习因子,经验值取c1=c2=2,调节学习最大步长
r1,r2—两个随机数,取值范围(0,1),以增加搜索随机性
w —惯性因子,非负数,调节对解空间的搜索范围
//更新速度 standard
void UpdateVelocity1(double gBestCoordinate[])
{
for(int i=0; i<nDimension; i++)
{
velocity[i]=w*velocity[i]+c1*MyRand(0,1)*(pBestCoordinate[i]-coordinate[i]) + c2*MyRand(0,1)*(gBestCoordinate[i]-coordinate[i]);
}
//检测是否溢出
CheckOverflow(velocity,velocityLimit);
}
迭代中止条件:设置最大迭代次数或全局最优位置满足预定最小适应阈值。
//粒子群的类
class CParticleGroup
{
public:
int nPopulation; //粒子数量
CParticle * pParticles; //保存粒子的数组
//信息记录
int maxIteration; //
int iteration; //第几代
int gBestIndex; //当前最优的particle对应的索引
double gBest; //当前最优的particle对应的函数值
double gBestCoordinate[MaxDimension]; //当前最优的particle对应的坐标值
double gAverageFitness; //平均适应度
double environmentChangeThreshold;
}
初始化各粒子初始位置,在有效范围内随机选数
void Initial(int population,int dimension, double w, double c1,double c2, double coordinateLimit[][2],double velocityLimit[][2])
{
nPopulation=population;
if(pParticles) free(pParticles);
pParticles=(CParticle *)malloc(nPopulation*sizeof(CParticle));
for(int i=0; i<nPopulation; i++) pParticles[i].Initial(dimension,w,c1,c2,coordinateLimit,velocityLimit);
iteration=0;
gBest=0;
environmentChangeThreshold=1.0;
}
double Run(FitnessFunc pFunc,int N,double fChange=0)
{
iteration++;
double lastgBest=gBest; //记录上一次全局最优
double lastAverageFitness=gAverageFitness; //记录上一次平均适应度
gBest=MAXNUM;
double totalFitness=0;
for(int i=0; i<nPopulation; i++)
{
pParticles[i].Run();
double fit=pParticles[i].Fitness(pFunc,N,fChange); 计算各粒子的适应度值
totalFitness+=fit;
if(gBest>fit) 记录各粒子的个体极值点位置 记录最佳适应度值 找出全局极值和相应的序号
{
gBestIndex=i;
gBest=fit;
memcpy(gBestCoordinate,pParticles[i].coordinate,MaxDimension*sizeof(double));
}
}
gAverageFitness=totalFitness/nPopulation;
更新各粒子速度
for( i=0; i<nPopulation; i++)
{
pParticles[i].UpdateVelocity3(gBestCoordinate,iteration,maxIteration);
}
//检测环境是否发生变化
double gBestchange=abs(lastgBest-gBest)/(abs(lastgBest)+0.0001);
double gAveragechange=abs(lastAverageFitness-gAverageFitness)/(abs(lastAverageFitness)+0.0001);
//若变化,更新粒子参数,使粒子群在上次子群附近加一个随机变化后重新开始迭代
if(lastgBest<gBest && gBestchange>environmentChangeThreshold && gAveragechange>environmentChangeThreshold)
{
for( i=0; i<nPopulation; i++)
{
pParticles[i].w=0.9;
pParticles[i].pBest=MAXNUM;
for(int k=0; k<pParticles[0].nDimension; k++)
{
double low=pParticles[0].coordinateLimit[k][0];
double up=pParticles[0].coordinateLimit[k][1];
pParticles[i].coordinate[k]+=MyRand(0,(up-low)/10.0);
pParticles[i].coordinate[k]-=MyRand(0,(up-low)/10.0);
}
}
}
return gBest;
}
对于第一方面,本程序采用如下检测
//检测环境是否发生变化
double gBestchange=abs(lastgBest-gBest)/(abs(lastgBest)+0.0001); 最优值的变换
double gAveragechange=abs(lastAverageFitness-gAverageFitness)/(abs(lastAverageFitness)+0.0001); 评价值的变化
if(lastgBest<gBest && gBestchange>environmentChangeThreshold && gAveragechange>environmentChangeThreshold)
对于第2方面改进,本程序采用
更新粒子参数,使粒子群在上次子群附近加一个随机变化后重新开始迭代
for( i=0; i<nPopulation; i++)
{
pParticles[i].w=0.9;
pParticles[i].pBest=MAXNUM;
for(int k=0; k<pParticles[0].nDimension; k++)
{
double low=pParticles[0].coordinateLimit[k][0];
double up=pParticles[0].coordinateLimit[k][1];
pParticles[i].coordinate[k]+=MyRand(0,(up-low)/10.0);
pParticles[i].coordinate[k]-=MyRand(0,(up-low)/10.0);
}
}