前言
本文整理自卓金武《MATLAB在数学建模中的应用》
粒子群算法
用以寻找最优值
1. PSO 算法
PSO(particle swarm optimization,粒子群算法)
1. 基本理论
PSO 算法是基于群鸟觅食提出来的。
群鸟觅食的过程中,和人类决策过程相似,人类在决策过程中会综合两种重要的信息:
- 一种是根据自己的尝试和经历,已经积累了一定的经验,知道怎样的状态会比较好;
- 另一种是根据他人的行为获取信息,从中知道哪些选择是正面的,哪些选择是消极的。
同样的道理,群鸟在觅食的过程中,每只鸟的初始状态处于随机位置,且飞翔的方向也是随机的。每只鸟都不知道食物在哪,但是随着时间的推移,这些初始处于随机位置的鸟类通过群内互相学习、信息共享和个体不断积累自身寻觅食物的经验,自组织积聚成一个群落,并逐渐朝唯一的目标——食物——前进。
每只鸟能够通过一定经验和信息估计目前的所处位置对于能寻找到食物有多大的价值,即多大的适应值;每只鸟能够记住自己所找到的最好位置,称之为局部最优。此外,还能记住群鸟中所有个体所能找到的最好位置,称为全局最优,通过鸟群觅食的位置不断移动,即不断迭代,可以使鸟群朝食物步步逼近
在群鸟觅食模型中,每个个体可以被看成一个粒子,则鸟群可以被看成一个粒子群。
假设在一个 维的目标搜索空间中,有 个粒子组成一个群体,其中第 个粒子( ) 位置表示为 = ( ),即第 个粒子在 维搜索空间中的位置是 。
换言之,每个粒子的位置就是一个潜在解,将 代入目标函数就可以计算出其适应值,根据适应值的大小衡量其优劣。
粒子个体经历过的最好位置记为 = ( ),整个群体所有粒子经历过的最好位置记为 = ( )。粒子 的速度记为 = ( )。
则粒子群算法对粒子所在位置不断更新的公式是:
其中, , 是非负数,称为惯性因子,加速常数 和 是非负常数, 和 是 [0,1] 范围内变换的随机数; 称为约束因子,目的是控制速度的权重
此外, ,即粒子 的飞翔速度 被一个最大速度 所限制。如果当前时刻粒子在某维的速度 更新后超过该维的最大飞翔速度 ,则当前时刻该维的速度被限制在 。 为常数,可以根据不同的优化问题设定
迭代终止条件根据具体问题设定,一般达到预订最大迭代次数或粒子群目前为止搜索到的最优位置满足目标函数的最小容许误差
2. 约束优化
约束优化工作主要分为两类:
- 罚函数法,将约束优化问题转化为无约束优化问题
- 将粒子群的搜索范围限制在条件约束簇内
2. 程序设计
1. 程序设计流程
初始化粒子群(速度和位置)、惯性因子、加速常数、最大迭代次数和算法终止的最小允许误差
评价每个粒子的初始适应值
将初始适应值作为当前每个粒子的局部最优解,并将各适应值对应的位置作为每个粒子的局部最优解所在的位置
将最佳初始适应值作为全局最优解,并将最佳适应值对应的位置作为全局最优值所在的位置
根据公式更新每个粒子当前的飞翔速度
对每个粒子的飞翔速度进行限幅处理,使之不能超过设定的最大飞翔速度
根据公式更新每个粒子当前所在的位置
比较当前每个粒子的适应度是否比历史局部最优值好,如果好,则将当前粒子适应度作为粒子的局部最优解,其对应的位置作为每个粒子的局部最优解所在的位置
在当前群中找出全局最优解,并将当前全局最优解对应的位置作为粒子群的全局最优解所在的位置
重复步骤 5~9,直到满足设定的最小误差或者达到最大迭代次数
输出粒子群全局最优解和其对应的位置以及每个粒子的局部最优值和其对应的位置
流程图如下:
2. 参数选取
在基本粒子群算法中,粒子数 、惯性因子 、最大飞翔速度 和加速常数 和 等几个参数对算法寻优性能的影响非常显著
粒子数
粒子数量越多,搜索范围越大,越容易找到全局最优解,算法运行的时间也越长。一般取值 20~40
惯性因子
对算法的收敛性起到很大作用,值越大,粒子的飞翔幅度越大,容易错失局部寻优能力,而全局搜索能力越强;反之。
如果 是变量,通常在迭代开始将 设置得较大,然后在迭代过程中逐步减小;也可以取 [0,1] 区间的随机数;如果 是定值,建议取 0.6~0.75 区间的合理值
最大飞翔速度
参数 有利于防止搜索范围毫无意义地发散,防止粒子群由于飞翔速度过大而直接俯冲掠过最优目标值,如果 的选择是固定不变的,通常设定 为每维变化范围的 10%~20%
加速常数 和
加速常数是调整自身经验和社会经验在其运动中所起作用的权重,一般情况下取 = = 2.0
3. 例子
1. PSO 解法
clc;clear all;close all;
tic; %程序运行计时
E0=0.001; %允许误差
MaxNum=100; %粒子最大迭代次数
narvs=1; %目标函数的自变量个数
particlesize=30; %粒子群规模
c1=2; %每个粒子的个体学习因子,也称为加速常数
c2=2; %每个粒子的社会学习因子,也称为加速常数
w=0.6; %惯性因子
vmax=0.8; %粒子的最大飞翔速度
x=-5+10*rand(particlesize,narvs); %粒子所在的位置
v=2*rand(particlesize,narvs); %粒子的飞翔速度
%用inline定义适应度函数以便将子函数文件与主程序文件放在一起,
%目标函数是:y=1+(2.1*(1-x+2*x.^2).*exp(-x.^2/2))
%inline命令定义适应度函数如下:
fitness=inline('1/(1+(2.1*(1-x+2*x.^2).*exp(-x.^2/2)))','x');
%inline定义的适应度函数会使程序运行速度大大降低
for i=1:particlesize
for j=1:narvs
f(i)=fitness(x(i,j));
end
end
personalbest_x=x;
personalbest_faval=f;
[globalbest_faval i]=min(personalbest_faval);
globalbest_x=personalbest_x(i,:);
k=1;
while k<=MaxNum
for i=1:particlesize
for j=1:narvs
f(i)=fitness(x(i,j));
end
if f(i)<personalbest_faval(i) %判断当前位置是否是历史上最佳位置
personalbest_faval(i)=f(i);
personalbest_x(i,:)=x(i,:);
end
end
[globalbest_faval i]=min(personalbest_faval);
globalbest_x=personalbest_x(i,:);
for i=1:particlesize %更新粒子群里每个个体的最新位置
v(i,:)=w*v(i,:)+c1*rand*(personalbest_x(i,:)-x(i,:))...
+c2*rand*(globalbest_x-x(i,:));
for j=1:narvs %判断粒子的飞翔速度是否超过了最大飞翔速度
if v(i,j)>vmax;
v(i,j)=vmax;
elseif v(i,j)<-vmax;
v(i,j)=-vmax;
end
end
x(i,:)=x(i,:)+v(i,:);
end
if abs(globalbest_faval)<E0,break,end
k=k+1;
end
Value1=1/globalbest_faval-1; Value1=num2str(Value1);
% strcat指令可以实现字符的组合输出
disp(strcat('the maximum value','=',Value1));
%输出最大值所在的横坐标位置
Value2=globalbest_x; Value2=num2str(Value2);
disp(strcat('the corresponding coordinate','=',Value2));
x=-5:0.01:5;
y=2.1*(1-x+2*x.^2).*exp(-x.^2/2);
plot(x,y,'m-','linewidth',3);
hold on;
plot(globalbest_x,1/globalbest_faval-1,'kp','linewidth',4);
legend('目标函数','搜索到的最大值');xlabel('x');ylabel('y');grid on;toc;
2. 遗传算法解法
前面不是才学了遗传算法,试试用 ga 工具箱来求解
%主程序:本程序采用遗传算法接力进化,
%将上次进化结束后得到的最终种群作为下次输入的初始种群
clc;
close all;
clear all;
%进化的代数
T=100;
optionsOrigin=gaoptimset('Generations',T/2);
[x,fval,reason,output,finnal_pop]=ga(@ch14_2f,1,optionsOrigin);
%进行第二次接力进化
options1=gaoptimset('Generations',T/2,'InitialPopulation',finnal_pop,...
'PlotFcns',@gaplotbestf);
[x,fval,reason,output,finnal_pop]=ga(@ch14_2f,1,options1);
%进行第三次接力进化
options1=gaoptimset('Generations',T/2,'InitialPopulation',finnal_pop,...
'PlotFcns',@gaplotbestf);
[x,fval,reason,output,finnal_pop]=ga(@ch14_2f,1,options1);
%进行第四次接力进化
options1=gaoptimset('Generations',T/2,'InitialPopulation',finnal_pop,...
'PlotFcns',@gaplotbestf);
[x,fval,reason,output,finnal_pop]=ga(@ch14_2f,1,options1);
%进行第五次接力进化
options1=gaoptimset('Generations',T/2,'InitialPopulation',finnal_pop,...
'PlotFcns',@gaplotbestf);
[x,fval,reason,output,finnal_pop]=ga(@ch14_2f,1,options1);
%进行第六次接力进化
options1=gaoptimset('Generations',T/2,'InitialPopulation',finnal_pop,...
'PlotFcns',@gaplotbestf);
[x,fval,reason,output,finnal_pop]=ga(@ch14_2f,1,options1);
Bestx=x
BestFval=fval
%子函数:适应度函数同时也是目标函数,函数存储名称为ch14_2f.m
function f=ch14_2f(x)
if(x<-5|x>5)
f=inf;
else
f=-2.1*(1-x+2*x.^2).*exp(-x.^2/2); % 这是求最大值,所以适应度函数取反,最后得到的答案再取个反
end
答案刚好对上欸