盲目搜索:按照预定的策略实行搜索,在搜索过程中获取的中间信息不用来改进策略,如枚举法、蒙特卡罗算法
启发式搜索:一个基于直观或经验构造的算法,在可接受的花费(比如计算的空间和时间)下给出待解决优化问题的一个可行解,相比于盲目搜索,启发式搜索利用了中间息来改进搜索策略
粒子群算法,其全称为粒子群优化算法(Particle Swarm Optimization, PSO)
这是通过模拟鸟群觅食行为而发展起来的一种基于群体协作的搜索算法,其核心思想是利用群体中的个体对信息的共享使整个群体的运动在问题求解空间中产生从无序到有序的演化过程,从而获得问题的可行解
假设有一群鸟在搜索食物,且满足如下条件:
所有的鸟都不知道食物在哪
它们知道自己的当前位置距离食物有多远
每只鸟都会记住自己距离食物最近时的位置
它们知道当前距离食物最近的鸟的位置
那么在这个过程中,每只鸟运动状态的变化会被三个因素影响:
因素1:由于自身惯性,受到前一个时刻速度的影响,称为自身惯性
因素2:自己距离食物最近时的位置,称为自我认知部分
因素3:当前距离食物最近鸟的位置,称为社会认知部分
对于一只鸟在第d时刻的速度 v d v_{d} vd可以以如下公式表示:
v d = w v d − 1 + c 1 r 1 ( p b e s t d − x d ) + c 2 r 2 ( g b e s t d − x d ) v_{d}=wv_{d-1}+c_{1}r_{1}(pbest_{d}-x_{d})+c_{2}r_{2}(gbest_{d}-x_{d}) vd=wvd−1+c1r1(pbestd−xd)+c2r2(gbestd−xd)
其中各种符号的说明为:
符号 | 含义 |
---|---|
w w w | 惯性权重,也称为惯性系数 |
c 1 c_{1} c1 | 粒子的个体学习因子,也称为个体加速因子 |
p b e s t d pbest_{d} pbestd | 截止到 d 时刻,这只鸟的最佳位置 |
c 2 c_{2} c2 | 粒子的社会学习因子,也称为社会加速因子 |
g b e s t d gbest_{d} gbestd | 在 d 时刻时,距离食物最近的鸟的位置 |
r 1 r_{1} r1和 r 2 r_{2} r2 | [ 0 , 1 ] [0,1] [0,1]上的随机数 |
因此,此公式的含义为:
这只鸟d时刻的速度 = 上一步自身的速度惯性 + 自我认知部分 + 社会认知部分
粒子:优化问题的候选解
位置:候选解所在的位置
速度:候选解移动的速度
适应度:评价粒子优劣的值,一般设置为目标函数值
个体最佳位置:单个粒子迄今为止找到的最佳位置
群体最佳位置:所有粒子迄今为止找到的最佳位置
在之前单只鸟运动状态的公式理解部分的基础上,我们得到粒子群算法的核心公式为(假设每个时间间隔为t=1):
v i d = w v i d − 1 + c 1 r 1 ( p b e s t i d − x i d ) + c 2 r 2 ( g b e s t d − x i d ) v_{i}^d = wv_{i}^{d-1} + c_{1}r_{1}(pbest_{i}^d-x_{i}^d)+c_{2}r_{2}(gbest^d-x_{i}^d) vid=wvid−1+c1r1(pbestid−xid)+c2r2(gbestd−xid)
x i d + 1 = x i d + v i d x_{i}^{d+1}=x_{i}^d+v_{i}^d xid+1=xid+vid
其中各种符号的说明为:
符号 | 含义 |
---|---|
n n n | 粒子个数 |
v i d v_{i}^d vid | 第d次迭代时,第i个粒子的速度 |
w w w | 惯性权重,一般取为0.9 |
c 1 c_{1} c1 | 粒子的个体学习因子,也称为个体加速因子,一般取为2 |
c 2 c_{2} c2 | 粒子的社会学习因子,也称为社会加速因子,一般取为2 |
x i d x_{i}^d xid | 第d次迭代时,第i个粒子所在的位置 |
f ( x ) f(x) f(x) | 在位置x时的适应度值,一般取目标函数值 |
p b e s t i d pbest_{i}^d pbestid | 到第di次迭代为止,第i个粒子经过的最好的位置 |
g b e s t d gbest^d gbestd | 到第d次迭代为止,所有粒子经过的最好的位置 |
r 1 r_{1} r1和 r 2 r_{2} r2 | [ 0 , 1 ] [0,1] [0,1]上的随机数 |
求函数 y = 11 s i n x + 7 c o s ( 5 x ) y=11sinx+7cos(5x) y=11sinx+7cos(5x)在 [ − 3 , 3 ] [-3,3] [−3,3]内的最大值
用MATLAB画出函数图像:
%% 画出函数图像
%% 绘制函数的图形
x = -3:0.01:3;
y = 11*sin(x) + 7*cos(5*x);
figure(1);
plot(x,y,'b-')
title('y = 11*sin(x) + 7*cos(5*x)')
set(gca, 'LooseInset', [0, 0, 0, 0]); % 消除图片白边
hold on % 不关闭图形,继续在上面画图
函数图像:
%% 设置粒子群算法的参数
n = 10; % 粒子数量
narvs = 1; % 自变量个数
c1 = 2; % 个体学习因子
c2 = 2; % 社会学习因子
w = 0.9; % 惯性权重
num = 50; % 迭代的次数
vmax = 1; % 粒子的最大速度
x_lb = -3; % 自变量的取值下界
x_ub = 3; % 自变量的取值上界
接下来初始化粒子的位置和速度,并计算初始适应度:
%% 初始化粒子的位置和速度,并计算适应度
x = zeros(n,narvs);
for i = 1:narvs
% 在定义域内随机初始化粒子所在的位置
x(:,i) = x_lb(i)+(x_ub(i)-x_lb(i))*rand(n,1);
end
v = -vmax+2*vmax.*rand(n,narvs); % 随机初始化粒子的速度
fitness = zeros(n,1); % 初始化适应度
for i = 1:n % 遍历每一个粒子
fitness(i) = Cal_func(x(i,:)); % 调用Cal_func函数计算适应度,即目标函数值
end
pbest = x; % 初始化每个粒子目前找到的最佳位置
ind = find(fitness==max(fitness),1); % 找到适应度最大的粒子的下标
gbest = x(ind,:); % 初始化粒子总体目前所找到的最佳位置
function y = Cal_func(x) % 计算适应度的函数
y = 11*sin(x)+7*cos(5*x);
end
之后循环更新粒子的速度和位置,并重新计算适应度并找到最优的粒子,将结果表示为图像:
%% 更新粒子的速度和位置
%% 重新计算适应度并找到最优的粒子,并将结果表示为图像
for d = 1:K % 开始迭代,共K次
for i = 1:n % 以此更新第i个粒子的速度和位置
% 更新第i个粒子的速度
v(i,:) = w*v(i,:)+c1*rand()*(pbest(i,:)-x(i,:))+c2*rand()*(gbest-x(i,:));
% 如果粒子速度超过限制,就进行调整
for j = 1:narvs
if v(i,j)<-vmax(j)
v(i,j) = -vmax(j);
elseif v(i,j) > vmax(j)
v(i,j) = vmax(j);
end
end
x(i,:) = x(i,:)+v(i,:); % 更新第i个粒子的位置
% 如果粒子的位置超出了定义域,就对其进行调整
for j = 1:narvs
if x(i,j)<x_lb(j)
x(i,j) = x_lb(j);
elseif x(i,j) > x_ub(j)
x(i,j) = x_ub(j);
end
end
fit(i) = Obj_fun1(x(i,:)); % 重新计算第i个粒子的适应度
% 如果第i个粒子适应度大于自身迄今为止找到的最佳适应度
if fit(i) > Obj_fun1(pbest(i,:))
pbest(i,:) = x(i,:); % 更新该粒子的最佳位置
end
% 如果第i个粒子的适应度大于所有粒子迄今为止的最佳适应度
if Obj_fun1(pbest(i,:))>Obj_fun1(gbest)
gbest = pbest(i,:); % 更新所有粒子找到的的最佳位置
end
end
fitnessbest(d) = Obj_fun1(gbest); % 更新第d次迭代得到的最佳的适应度
pause(0.1); % 暂停0.1s
h.XData = x;
% 更新散点图句柄的x轴的数据(此时粒子的位置在图上发生了变化)
h.YData = fit;
% 更新散点图句柄的y轴的数据(此时粒子的位置在图上发生了变化)
end
figure(2)
plot(fitnessbest) % 绘制出每次迭代最佳适应度的变化图
set(gca, 'LooseInset', [0, 0, 0, 0]); % 消除图片白边
xlabel('迭代次数');
disp('最佳的位置是:'); disp(gbest)
disp('此时最优值是:'); disp(Obj_fun1(gbest))
%% 自定义函数写在代码末尾
function y = Obj_fun1(x)
y = 11*sin(x) + 7*cos(5*x);
end
最终运行的结果为:
对于粒子群算法的核心公式:
v i d = w v i d − 1 + c 1 r 1 ( p b e s t i d − x i d ) + c 2 r 2 ( g b e s t d − x i d ) v_{i}^d = wv_{i}^{d-1} + c_{1}r_{1}(pbest_{i}^d-x_{i}^d)+c_{2}r_{2}(gbest^d-x_{i}^d) vid=wvid−1+c1r1(pbestid−xid)+c2r2(gbestd−xid)
其中 惯性权重w 体现的是粒子继承先前速度的能力,一个较大的惯性权值有利于全局搜索,而一个较小的权值则更有利于局部搜索,为了更好的平衡算法的全局搜索以及局部搜索能力,我们可以采用递减惯性权重。
本文介绍 1 种线性递减惯性权重表达式为:
w d = w s t a r t − ( w s t a r t − w e n d ) d K w^{d}=w_{start}-(w_{start}-w_{end})\frac{d}{K} wd=wstart−(wstart−wend)Kd
其中 d 是当前迭代的次数,K 是迭代总次数
w s t a r t w_{start} wstart 一般取 0.9, w e n d w_{end} wend一般取 0.4,与之前的固定数值相比,当前惯性权重与迭代次数有关。
本文介绍 2 种非线性递减惯性权重表达式,分别为:
w d = w s t a r t − ( w s t a r t − w e n d ) ( d K ) 2 w^{d}=w_{start}-(w_{start}-w_{end})(\frac{d}{K})^2 wd=wstart−(wstart−wend)(Kd)2
w d = w s t a r t − ( w s t a r t − w e n d ) [ 2 d K − ( d K ) 2 ] w^{d}=w_{start}-(w_{start}-w_{end})[\frac{2d}{K}-(\frac{d}{K})^2] wd=wstart−(wstart−wend)[K2d−(Kd)2]
将 3 种递减惯性权重在图中对比:
代码:
clear;clc;
%% 三种递减惯性权重的图形
% 参数及公式说明
w_start = 0.9; % 初始惯性权重
w_end = 0.4; % 最终惯性权重
K = 30; % 迭代总次数
d = 1:K; % 迭代次数
w1 = w_start-(w_start-w_end)*d/K;
w2 = w_start-(w_start-w_end)*(d/K).^2;
w3 = w_start-(w_start-w_end)*(2*d/K-(d/K).^2);
% 设置颜色,rgb值
C1 = [21/255, 151/255, 165/255];
C2 = [1, 194/255, 75/255];
C3 = [246/255, 111/255, 105/255];
% 设置线条,调整线型、标记符号、线宽和颜色
Line1 = line(d,w1);
Line2 = line(d,w2);
Line3 = line(d,w3);
set(Line1, 'LineStyle', '--', 'Marker', 'd', 'LineWidth', 1.5, 'Color', C1);
set(Line2, 'LineStyle', '--', 'Marker', 'o', 'LineWidth', 1.5, 'Color', C2);
set(Line3, 'LineStyle', '--', 'Marker', 'v', 'LineWidth', 1.5, 'Color', C3);
% 坐标区调整
set(gca, 'Box', 'off', ... % 去掉图中右侧和上方的边框
'XGrid', 'off', 'YGrid', 'on', ... % 设置是否开启网格线
'TickDir', 'out', 'TickLength', [0.01 0.01], ... % 设置坐标轴刻度的指向和长短
'XMinorTick', 'off', 'YMinorTick', 'on', ... % 设置坐标轴刻度的精度
'XColor', [.1, .1, .1], 'YColor', [.1, .1, .1], ... % 设置坐标轴的颜色
'XTick', 0:1:100, 'YTick', 0:0.1:1, ... % 设置坐标轴刻度的最大显示范围
'Xlim', [0, K], 'Ylim', [0, 1.1], ... % 设置坐标轴刻度的显示范围
'Xticklabel', {[0:1:K]}, ... % 设置x坐标轴刻度值
'Yticklabel', {[0:0.1:1]}) % 设置y坐标轴刻度值
% 坐标轴标签、legend、刻度标签、背景颜色
hXLabel = xlabel('d');
hYLabel = ylabel('w');
hLegend = legend([Line1, Line2, Line3], ...
'w1', 'w2', 'w3', ...
'Location', 'northeast');
% 设置坐标轴标签的字体格式
set(gca, 'FontName', 'Times', 'FontSize', 12);
% 设置图例字体格式
set([hXLabel, hYLabel, hLegend], 'FontName', 'Helvetica');
set([hXLabel, hYLabel, hLegend], 'FontSize', 10);
set(gca, 'LooseInset', [0, 0, 0, 0]); % 消除白边
图示:
除了递减惯性权重,本文引入自适应惯性权重和随机惯性权重:
若问题要求最小值问题,则有:
w i d = { w m i n + ( w m a x − w m i n ) f ( x i d ) − f m i n d f a v e r a g e d − f m i n d , f ( x i d ) ≤ f a v e r a g e d w m a x , f ( x i d ) < f a v e r a g e d w_{i}^d=\begin{cases} w_{min}+(w_{max}-w_{min})\frac{f(x_{i}^d)-f_{min}^d}{f_{average}^d-f_{min}^d} & ,f(x_{i}^d)\leq f_{average}^d\\ w_{max} & ,f(x_{i}^d)< f_{average}^d \end{cases} wid={wmin+(wmax−wmin)faveraged−fmindf(xid)−fmindwmax,f(xid)≤faveraged,f(xid)<faveraged
若问题要求最大值问题,则有:
w i d = { w m i n + ( w m a x − w m i n ) f m a x d − f ( x i d ) f m a x d − f a v e r a g e d , f ( x i d ) ≥ a v e r a g e d w m a x , f ( x i d ) < f a v e r a g e d w_{i}^d=\begin{cases} w_{min}+(w_{max}-w_{min})\frac{f_{max}^d-f(x_{i}^d)}{f_{max}^d-f_{average}^d} & ,f(x_{i}^d)\geq_{average}^d\\ w_{max} & ,f(x_{i}^d)< f_{average}^d \end{cases} wid={wmin+(wmax−wmin)fmaxd−faveragedfmaxd−f(xid)wmax,f(xid)≥averaged,f(xid)<faveraged
其中:
w m i n w_{min} wmin和 w m a x w_{max} wmax为预先给定的最小和最大惯性系数,一般取0.4和0.9
f a v e r a g e f_{average} faverage为第 d 次迭代时所有粒子的平均适应度
f m i n d f_{min}^d fmind为第 d 次迭代时所有粒子的最小适应度
f m a x d f_{max}^d fmaxd为第 d 次迭代时所有粒子的最大适应度
与原来相比,自适应惯性权重与迭代次数和每个粒子的适应度相关。
w = w= w=
与原来相比,随机惯性权重可以避免在迭代前期局部搜索能力不足,也避免了迭代后期全局搜索能力不足。
对于粒子群算法的核心公式:
v i d = w v i d − 1 + c 1 r 1 ( p b e s t i d − x i d ) + c 2 r 2 ( g b e s t d − x i d ) v_{i}^d = wv_{i}^{d-1} + c_{1}r_{1}(pbest_{i}^d-x_{i}^d)+c_{2}r_{2}(gbest^d-x_{i}^d) vid=wvid−1+c1r1(pbestid−xid)+c2r2(gbestd−xid)
其中 个体学习因子c1和社会学习因子c2 决定了粒子本身经验信息和其他粒子的经验信息对粒子运行轨迹的影响,其反映了粒子群之间的信息交流。设置 c1 较大的值,会使粒子过多地在自身的局部范围内搜索,而较大的 c2 值,会促使粒子过早地收敛到局部最优值。
为了有效地控制粒子的飞行速度,使算法达到全局搜索和局部搜索两者间的有效平衡,引入 压缩因子,通过选取合适参数,确保PSO算法的收敛性,并可取消对速度的边界限制。
引入压缩因子后公式变为:
v i d = Φ [ w v i d − 1 + c 1 r 1 ( p b e s t i d − x i d ) + c 2 r 2 ( g b e s t d − x i d ) ] v_{i}^d = \Phi[wv_{i}^{d-1} + c_{1}r_{1}(pbest_{i}^d-x_{i}^d)+c_{2}r_{2}(gbest^d-x_{i}^d)] vid=Φ[wvid−1+c1r1(pbestid−xid)+c2r2(gbestd−xid)]
Φ = 2 ∣ 2 − C − C 2 − 4 C ∣ \Phi=\frac{2}{|2-C-\sqrt{C^2-4C}|} Φ=∣2−C−C2−4C∣2 为压缩因子
令 c 1 = c 2 = 2.05 , C = c 1 + c 2 = 4.1 , w = 0.9 c1=c2=2.05, C=c1+c2=4.1, w=0.9 c1=c2=2.05,C=c1+c2=4.1,w=0.9
在搜索初期应采用较大的 c1 值和较小的 c2 值,使粒子尽量发散到搜索空间,即强调“个体独立意识”,而较少受到种群内其他粒子,即“社会意识部分”的影响,以增加群内粒子的多样性。随着迭代次数增加,使 c1 线性递减,c2 线性递增,从而加强粒子向全局最优点的收敛能力。
引入非对称学习因子:
c 1 d = c 1 i n i + ( c 1 f i n − c 1 i n i ) d K c 2 d = c 2 i n i + ( c 2 f i n − c 2 i n i ) d K c_{1}^d=c_{1}^{ini}+(c_{1}^{fin}-c_{1}^{ini})\frac{d}{K}\\ c_{2}^d=c_{2}^{ini}+(c_{2}^{fin}-c_{2}^{ini})\frac{d}{K} c1d=c1ini+(c1fin−c1ini)Kdc2d=c2ini+(c2fin−c2ini)Kd
其中:
c 1 i n i = 2.5 c_{1}^{ini}=2.5 c1ini=2.5 是个体学习因子的初始值
c 1 f i n = 0.5 c_{1}^{fin}=0.5 c1fin=0.5 是个体学习因子的最终值
c 2 i n i = 1 c_{2}^{ini}=1 c2ini=1 是社会学习因子的初始值
c 2 f i n = 2.25 c_{2}^{fin}=2.25 c2fin=2.25 是社会学习因子的最终值
d 和 K 分别为当前迭代次数和总迭代次数