算法描述
PSO中,每个优化问题的解都是搜索空间中一个“粒子”。所有的粒子都有一个由被优化的函数决定的适应值(fitness value),每个粒子还有一个速度决定他们移动的方向和距离。然后粒子们就追随当前的最优粒子在解空间中搜索。PSO 初始化为一群随机粒子(随机解)。然后通过迭代找到最优解。在每一次迭代中,粒子通过跟踪两个"极值"来更新自己。第一个就是粒子本身所找到的最优解,这个解叫做个体极值pBest。另一个极值是整个种群目前找到的最优解,这个极值是全局极值gBest。另外也可以不用整个种群而只是用其中一部分作为粒子的邻居,那么在所有邻居中的极值就是局部极值。
算法参数解释
速度和位置公式
粒子只有两个重要属性:位置和速度,速度和物理中的速度含义有所区别,这里可以理解为位置的变化量的多少快慢。粒子通过跟踪两个“极值”(pbest,gbest)来更新自己。在找到这两个最优值后,粒子通过下面的公式来更新自己的速度和位置:
对于公式(1),第一部分称为 记忆项 ,表示上一次速度大小和方向的影响。第二部分称为 自身认知项 ,是粒子自己找到的最优解的影响。第三部分称为 群体认知项 ,是粒子群找到的最优解的影响。公式(2)就是通过公式(1)调整粒子的位置。
系数解释
叫做惯性因子,值为非负。其值较大,全局寻优能力强,局部寻优能力弱。可采用线性递减权值的方法设置动态,其公式为:。其中:初始惯性权值,:迭代至最大迭代次数时的惯性权值,最大迭代次数,当前迭代次数。典型的权值设置为:
为介于0到1之间的随机数。
为学习因子,通常取
算法流程
- 初始化一群微粒(群体规模为N),包括随机位置和速度;
- 评价每个微粒的适应度;
- 对每个微粒,将其适应值与其经过的最好位置pbest作比较,如果较好,则将其作为当前的最好位置pbest;
- 对每个微粒,将其适应值与其经过的最好位置gbest作比较,如果较好,则将其作为当前的最好位置gbest;
- 根据公式调整微粒速度和位置;
- 未达到结束条件则转第2步。
迭代终止条件根据具体问题一般选为最大迭代次数Gk或微粒群迄今为止搜索到的最优位置满足预定最小适应阈值
求解函数的最大值的JAVA版本代码如下:
public class App {
int n=4; //设定粒子数
double x[]; //横坐标矩阵,粒子的位置
double y[]; //目标函数值,可以说是适应度
double v[]; //粒子移动速度
double c1=2;
double c2=2;
double omega=0.4;
double pbest_x[];
double pbest_y[];
double gbest_x;
double gbest_y;
double vmax=0.1; //设定最大速度,也就是最多只移动0.1个单位
//计算目标函数值
public double targetFunction(double arg){
return -arg*(arg-2);
}
//计算粒子适应度函数
public void fitnessFunction(){
for(int i=0;i<n;i++){
y[i]=-x[i]*(x[i]-2);
}
}
//初始化
public void init(){
x=new double[n];
y=new double[n];
v=new double[n];
pbest_x=new double[n];
pbest_y=new double[n];
//初始化粒子位置和速度
for(int i=0;i<n;i++){
//取大一点可以感受收敛的广度
x[i]=(Math.random()-0.5)*5;
//取大一点可以感受收敛的速度
v[i]=Math.random()*0.1;
}
//初始化初始迭代个体最优和群体最优
for(int i=0;i<n;i++){
pbest_x[i]=x[i];
pbest_y[i]=targetFunction(x[i]);
if(targetFunction(x[i])>gbest_y){
gbest_x=x[i];
gbest_y=targetFunction(gbest_x);
}
}
System.out.println("PSO start:"+gbest_y);
System.out.println("\n");
}
//用于判断大小
public double getMAX(double a,double b){
return a>b?a:b;
}
//粒子群算法
public void PSO(int max){
//对于每一次迭代
for(int i=0;i<max;i++){
//对于每一个粒子
for(int j=0;j<n;j++){
v[j]=omega*v[j]+c1*Math.random()*(pbest_x[j]-x[j])+c2*Math.random()*(gbest_x-x[j]);
//速度越界处理
if(v[j]>vmax){
v[j]=vmax;
}
//位置移动
x[j]+=v[j];
//位置越界处理
if(x[j]<0) x[j]=0;
if(x[j]>2) x[j]=2;
}
fitnessFunction();
//更新个体最优和群体最优
for(int j=0;j<n;j++){
pbest_y[j]=getMAX(targetFunction(x[j]), pbest_y[j]);
if(pbest_y[j]>gbest_y){
gbest_y=pbest_y[j];
gbest_x=x[j];
}
System.out.println("particle"+j+": ("+x[j]+","+targetFunction(x[j])+")"+" v = "+v[j]);
}
System.out.println("this is "+(i+1)+" epoch, gbset is ("+gbest_x+","+gbest_y+")");
System.out.println("\n");
}
}
public static void main(String[] args) throws Exception {
App test=new App();
test.init();
test.PSO(20);
}
}
「真诚赞赏,手留余香」