前言
之前提到过, 无论遗传算法、蚁群算法以及今天要学习的粒子群算法,本质上都是对穷搜算法的精进版本,即通过参照一些自然界的规律来提高搜索的效率。 粒子群算法则是参考了鸟群寻找栖息地的自然现象,它的中心思想是每只鸟既根据自己的历史经验寻找栖息地的同时,也会参考同伴们的经验进行搜索。
粒子群算法步骤
- 初始化 N N N 个粒子作为一个群落, 分别对应优化问题的 N N N个随机可行解 x i , i = 1 , ⋯ , N x_i, i=1,\cdots, N xi,i=1,⋯,N。同时初始化每个粒子的速度 v i v_i vi,代表下一步的搜索方向,也可以说是更新方向。
- 计算每个粒子的适应度值, 也即函数值 f ( x i ) f(x_i) f(xi),并更新每个粒子的历史最佳结果 p i p_i pi及群落的历史最佳结果 g g g。
- 根据
p
i
p_i
pi与
g
g
g, 按下式更新
v
i
v_i
vi:
v i = v i + c 1 r 1 ( p i − x i ) + c 2 r 2 ( g i − x i ) (1) v_i = v_i + c_1r_1(p_i - x_i) + c_2r_2(g_i-x_i) \tag{1} vi=vi+c1r1(pi−xi)+c2r2(gi−xi)(1)
这个式子右边的第一项代表运动的惯性, 即只是在上一次搜索的方向是进行一些改进。 c 1 , c 2 c_1, c_2 c1,c2代表学习因子,是一个给定常数。 r 1 , r 2 r_1,r_2 r1,r2代表随机数,为搜索加入了随机因素。 p i − x i p_i-x_i pi−xi则代表了粒子基于自身历史经验对方向进行的修正,即朝着历史最好的结果进行搜索。 g i − x i g_i - x_i gi−xi则代表了粒子也会考虑整个群落的经验进行修正。 - 更新粒子 x i = x i + v i x_i = x_i + v_i xi=xi+vi
- 判断算法迭代是否终止,否则跳转回步骤2.
从算法流程可以看出来,粒子群算法和蚁群算法等本质上还是很一致的,就是并行地从 N N N个随机可行解开始搜索,基于一些启发式的思想优化搜索效率。比如粒子群算法里区别于穷搜算法的点就在于会不断参考粒子自身经验和整个种群的经验。
一些增强
- 标准粒子群算法:将(1)改为:
v i = w v i + c 1 r 1 ( p i − x i ) + c 2 r 2 ( g i − x i ) (2) v_i = wv_i + c_1r_1(p_i - x_i) + c_2r_2(g_i-x_i) \tag{2} vi=wvi+c1r1(pi−xi)+c2r2(gi−xi)(2)
也即对惯性引入一个权重,这个权重是所有粒子共享的。 显然, w w w越大,搜索越趋向于随机。 w w w越小,越趋向于纯粹利用经验。 - 压缩粒子群算法: (2)中的
w
w
w由下式给出:
λ = 2 ∣ 2 − φ − ( φ 2 − 4 φ ) ∣ , φ = c 1 + c 2 \lambda=\frac{2}{\left|2-\varphi-\sqrt{\left(\varphi^2-4 \varphi\right)}\right|},\varphi=c_1+c_2 λ=∣∣∣2−φ−(φ2−4φ)∣∣∣2,φ=c1+c2
实验结果表明可显著提升收敛速度。 - 离散粒子群算法: 用于求解离散问题。 比如,如果变量的取值为0或1, 而粒子群飞行时到达的可行解势必是连续结果。 此时,只需将该结果投影到离其最近的可行解上即可 (也可引入一些随机因素),而速度及飞行的更新式不变。
Matlab代码
仿真实例: 用粒子群算法求解 f ( x , y ) = 3 cos ( x y ) + x + y 2 f(x,y)=3\cos(xy) +x + y^2 f(x,y)=3cos(xy)+x+y2, x,y取值范围为 [ − 4 , 4 ] [-4,4] [−4,4]:
%%%%%%%%%%%%%%%%%粒子群算法求函数极值%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%初始化%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear all; %清除所有变量
close all; %清图
clc; %清屏
N=100; %群体粒子个数
D=2; %粒子维数
T=200; %最大迭代次数
c1=1.5; %学习因子1
c2=1.5; %学习因子2
Wmax=0.8; %惯性权重最大值
Wmin=0.4; %惯性权重最小值
Xmax=4; %位置最大值
Xmin=-4; %位置最小值
Vmax=1; %速度最大值
Vmin=-1; %速度最小值
%%%%%%%%%%%%%%%%初始化种群个体(限定位置和速度)%%%%%%%%%%%%%%%%
x=rand(N,D) * (Xmax-Xmin)+Xmin;
v=rand(N,D) * (Vmax-Vmin)+Vmin;
%%%%%%%%%%%%%%%%%%初始化个体最优位置和最优值%%%%%%%%%%%%%%%%%%%
p=x;
pbest=ones(N,1);
for i=1:N
pbest(i)=func2(x(i,:));
end
%%%%%%%%%%%%%%%%%%%初始化全局最优位置和最优值%%%%%%%%%%%%%%%%%%
g=ones(1,D);
gbest=inf;
for i=1:N
if(pbest(i)<gbest)
g=p(i,:);
gbest=pbest(i);
end
end
gb=ones(1,T);
%%%%%%%%%%%按照公式依次迭代直到满足精度或者迭代次数%%%%%%%%%%%%%
for i=1:T
for j=1:N
%%%%%%%%%%%%%%更新个体最优位置和最优值%%%%%%%%%%%%%%%%%
if (func2(x(j,:))<pbest(j))
p(j,:)=x(j,:);
pbest(j)=func2(x(j,:));
end
%%%%%%%%%%%%%%%%更新全局最优位置和最优值%%%%%%%%%%%%%%%
if(pbest(j)<gbest)
g=p(j,:);
gbest=pbest(j);
end
%%%%%%%%%%%%%%%%计算动态惯性权重值%%%%%%%%%%%%%%%%%%%%
w=Wmax-(Wmax-Wmin)*i/T;
%%%%%%%%%%%%%%%%%跟新位置和速度值%%%%%%%%%%%%%%%%%%%%%
v(j,:)=w*v(j,:)+c1*rand*(p(j,:)-x(j,:))...
+c2*rand*(g-x(j,:));
x(j,:)=x(j,:)+v(j,:);
%%%%%%%%%%%%%%%%%%%%边界条件处理%%%%%%%%%%%%%%%%%%%%%%
for ii=1:D
if (v(j,ii)>Vmax) | (v(j,ii)< Vmin)
v(j,ii)=rand * (Vmax-Vmin)+Vmin;
end
if (x(j,ii)>Xmax) | (x(j,ii)< Xmin)
x(j,ii)=rand * (Xmax-Xmin)+Xmin;
end
end
end
%%%%%%%%%%%%%%%%%%%%记录历代全局最优值%%%%%%%%%%%%%%%%%%%%%
gb(i)=gbest;
end
g; %最优个体
gb(end); %最优值
figure
plot(gb)
xlabel('迭代次数');
ylabel('适应度值');
title('适应度进化曲线')