粒子群算法是计算算法的一种,1995年由Eberhart 博士和kennedy 博士提出,源于对鸟群捕食的行为研究 。
该算法利用群体中的个体对信息的共享使整个群体的运动在问题求解空间中产生从无序到有序的演化过程,从而获得最优解。
试想一下,如果一群鸟在一片区域中寻找食物,所有的鸟都不知道食物在什么地方,但是每一只鸟都知道自己距离食物有多远,也知道这一群鸟中离食物最近的鸟在什么位置,这样每一只鸟都可以改变当前自己的移动方向,逐渐向离食物最近的鸟所在位置靠近,这样通过不断的搜寻,就能找到食物。
这一思想可以运用到数学的优化问题中,比如,要求解 的最大值,我们可以假设有100只鸟,初始时这100只鸟分布在不同的位置,每只鸟的位置可以抽象成自变量x和y,有了随机的x和y的值就可以计算出每只鸟f(x)的值,f(x)的值越大表示鸟离食物越近,同时计算出这100只鸟中离食物最近的位置作为此时的全局最优解,之后,根据每一只鸟当前的位置与全局最优解的位置更新当前的速度与位置,向最优解的位置靠近,这样通过数次迭代,就能得到食物的位置。
更新每只鸟的速度与位置的数学公式为:
其中, 表示粒子i的速度, 为惯性权重,用于记录当前自身的速度,通常为非负数,调节解空间的搜索范围,为0时则失去自身速度的记忆, 表示学习参数,调节学习的最大步长,pbest是当前粒子的最优值,gbest为集群中搜索到的最优值,present[i]为当前粒子的位置。
下面用Java代码编写用PSO算法求解 的最大值:
public class EX {
int n; //粒子数量
ParticleState[] p; //粒子数组
ParticleState[] v; //速度数组
ParticleState[] pbest; //粒子最优解
ParticleState gbest; //全局最优解
double vmax; //最大速度
int c1,c2; //学习参数
public static void main(String[] args) {
EX e = new EX();
e.init();
e.PSO(200);
}
//适应函数
public void fitnessFunction() {
for(int i = 0; i<n; i++) {
p[i].f = p[i].x*p[i].x*p[i].x + 3*p[i].x*p[i].y*p[i].y - 15*p[i].x -12*p[i].y;
}
}
//初始化
public void init() {
n = 1000;
p = new ParticleState[n];
v = new ParticleState[n];
pbest = new ParticleState[n];
gbest = new ParticleState(0.0, 0.0);
c1=c2=3;
vmax = 0.1;
for(int i=0;i<n;i++) {
p[i]=new ParticleState(Math.random(),Math.random());
v[i]=new ParticleState(Math.random()*vmax,Math.random()*vmax);
}
fitnessFunction();
//初始化粒子与集群的最优值
gbest.f = Integer.MIN_VALUE;
for(int i=0;i<n;i++) {
pbest[i]=p[i];
if(p[i].f > gbest.f) {
gbest = p[i];
}
}
System.out.println("初始最优值:" +gbest.x+" "+gbest.y+" "+" "+gbest.f);
}
//粒子群算法 max-迭代次数
public void PSO(int max) {
for(int i=0;i<max;i++) {
double w = 0.3;//惯性权重
for(int j=0;j<n;j++) {
//更新粒子速度
double vx=w*v[j].x+c1*Math.random()*(pbest[j].x-p[j].x)+c2*Math.random()*(gbest.x-p[j].x);
double vy=w*v[j].y+c1*Math.random()*(pbest[j].y-p[j].y)+c2*Math.random()*(gbest.y-p[j].y);
if (vx>vmax) vx=vmax;
if (vy>vmax) vy=vmax;
v[j] = new ParticleState(vx,vy);
//更新粒子的位置
p[j].x += v[j].x;
p[j].y += v[j].y;
}
fitnessFunction();
//更新个体极值和群体极值
for(int j=0;j<n;j++) {
if(p[i].f > pbest[i].f) {
pbest[i] = p[i];
}
if(p[i].f > gbest.f) {
gbest = p[i];
}
}
System.out.println("==="+i+"==="+gbest.x+" "+gbest.y+" "+" "+gbest.f);
}
}
}
//粒子的状态类
class ParticleState{
public double x;
public double y;
public double f;//适应度,即求解函数值
ParticleState(double x, double y) {
this.x = x;
this.y = y;
}
}