一、简介
基本介绍
粒子群优化算法(Particle swarm optimization, PSO)是一种基于群体搜索的处理连续或者离散空间内优化问题的算法。
粒子群算法使用在解空间中不断移动的粒子作为寻优的群体,每个粒子具有位置和速度两个属性(位置和速度的维数和解空间的维数相同),粒子的位置代表了某个可行解,速度代表了与下一个寻找到的可行解的差值。
每个粒子根据自己已经寻找过的最优解和群体当前寻找到的最优解来调整自己的速度(按某种特定规则),以搜索到更优的解。
粒子群算法的基本过程
初始化常数和各记录矩阵:
代价函数计算函数CostFunction; 代价函数参数数目nVar; 代价函数各参数上下界(即粒子位置的边界)[VarMin,VarMax]
最大迭代次数iter_max
粒子群体的数量nPop
粒子速度边界[VelMin,VelMax]
单粒子最优加速常数C1
全局最优加速常数C2(一般取C 1 = C 2 ∈ [ 0 , 4 ] C1=C2\in[0,4]C1=C2∈[0,4])
惯性因子W
粒子位置记录矩阵PopPosition(nPop行nVar列,每一行是一个粒子的位置坐标)
粒子速度记录矩阵PopVelocity(nPop行nVar列,每一行是一个粒子的速度各分量)
单粒子历史最优位置记录矩阵Pbest(nPop行nVar列,每一行是一个粒子历史最优位置坐标)
全局历史最优位置记录矩阵Gbest(一行nVar列,只记录最最优解)
历史最优值记录矩阵(iter_max行一列,每一代的最优解值)
初始化粒子位置和速度:
在粒子的解空间中随机初始化各粒子的位置;在粒子各个速度分量的范围内随机初始化各粒子的初速度。
计算代价函数
计算各粒子当前位置对应的代价函数值,并与该粒子历史最优解比较,更新Pbest矩阵;同时与Gbest比较,更新Gbest值;并更新历史最优值记录矩阵
更新速度和位置
在更新Pbest矩阵和Gbest矩阵后,按下公式更新粒子的速度:
V i + 1 = W V i + C 1 R 1 ( P i − X i ) + C 2 R 2 ( G − X i ) V_{i+1} = WV_i + C_1R_1(P_i-X_i) + C_2R_2(G-X_i)Vi+1=WVi+C1R1(Pi−Xi)+C2R2(G−Xi)
其中,W为惯性因子,表征粒子维持原速不变的能力;C1为单粒子加速常数,表征粒子向他自己历史最优解出加速的能力;C2位全局最优加速常数,表征粒子向当前全局最优解处加速的能力;R1、R2为两个0到1之间的随机数。
计算完速度之后注意要限制速度边界,一旦速度大于边界值,令其等于边界值。
更新速度之后,应该计算粒子下一次的位置,并保存为当前粒子位置:
X i + 1 = X i + V i + 1 X_{i+1} = X_i + V_{i+1}Xi+1=Xi+Vi+1
同理,计算完位置后也要限制边界。
循环迭代和输出
循环迭代计算代价函数和更新速度和位置,达到最大代数之后输出结果即可。
在使用面向对象的语言实现该算法的时候,可以定义粒子这一对象,其应具有属性:当前位置、当前速度、当前代价值、历史最优位置、历史最优代价值,应具有方法:速度更新方法、位置更新方法、代价值更新方法。
二、源代码
%
tic
clear
clc
%% 用importdata这个函数来读取文件
r101=importdata('r101.txt');
cap=200; %车辆最大装载量
%% 提取数据信息
E=r101(1,5); %配送中心时间窗开始时间
L=r101(1,6); %配送中心时间窗结束时间
vertexs=r101(:,2:3); %所有点的坐标x和y
customer=vertexs(2:end,:); %顾客坐标
cusnum=size(customer,1); %顾客数
v_num=25; %车辆最多使用数目
demands=r101(2:end,4); %需求量
a=r101(2:end,5); %顾客时间窗开始时间[a[i],b[i]]
b=r101(2:end,6); %顾客时间窗结束时间[a[i],b[i]]
s=r101(2:end,7); %客户点的服务时间
h=pdist(vertexs);
dist=squareform(h); %距离矩阵
%% 粒子群算法参数
alpha=10; %违反的容量约束的惩罚函数系数
belta=100; %违反时间窗约束的惩罚函数系数
NIND=50; %粒子数目
MAXGEN=100; %迭代次数
w=1; %惯性因子
wdamp=0.99; %惯性因子衰减率
c1=1.5; %个体学习因子
c2=2.0; %全局学习因子
XvMin=1; %Xv下限
XvMax=v_num; %Xv上限
XrMin=1; %Xr下限
XrMax=cusnum; %Xr上限
VvMin=-(v_num-1); %Vv下限
VvMax=v_num-1; %Vv上限
VrMin=-(cusnum-1); %Vr下限
VrMax=cusnum-1; %Vr上限
%% 初始化粒子群位置
init_vc=init(cusnum,a,demands,cap); %构造初始解
population=initpopCW(init_vc,NIND,cusnum,XvMin,XvMax,XrMin,XrMax,VvMin,VvMax,VrMin,VrMax);
ObjV=calObj(population,v_num,cap,demands,a,b,L,s,dist,alpha,belta); %计算各个粒子的目标函数值
gbest_pos=population{1,1}(1:2,:); %假设第一个粒子位置为全局最优位置
gbest_obj=ObjV(1,1); %第一个粒子位置的目标函数值
pbest_pos=cell(NIND,1); %初始化各个粒子的个体最优位置
pbest_obj=ObjV; %初始化各个粒子的个体最优的目标函数值
for i=1:NIND
particle=population{i,1}; %第i个粒子
position=particle(1:2,:); %第i个粒子的位置
pbest_pos{i,1}=position; %初始化这个粒子的个体最优
if pbest_obj(i,1)<gbest_obj
%更新初始种群中的全局最优粒子
gbest_obj=pbest_obj(i,1);
gbest_pos=position;
end
end
globalVC=decode(gbest_pos,v_num); %初始全局最优配送方案
%统计一个配送方案的总成本、车辆使用数目、行驶总距离、违反约束路径数目、违反约束顾客数目
[cost,NV,TD,vio_NV,vio_cus]=statistic(globalVC,a,b,s,L,dist,demands,cap,alpha,belta);
disp(['初始全局最优解总成本为:',num2str(cost),',车辆使用数目为:',num2str(NV),...
',行驶总距离为:',num2str(TD),',违反约束路径数目为:',num2str(vio_NV),',违反约束顾客数目为:',num2str(vio_cus)]);
BestCost=zeros(MAXGEN,1); %记录每次迭代的全局最优目标函数值
%% 主循环
gen=1; %计数器
while gen<=MAXGEN
%% 更新各个粒子的位置和速度
for i=1:NIND
particle=population{i,1}; %第i个粒子
position=particle(1:2,:); %第i个粒子的位置
Xv=position(1,:);
Xr=position(2,:);
velocity=particle(3:4,:); %第i个粒子的速度
Vv=velocity(1,:);
Vr=velocity(2,:);
%% 更新速度
velocity=w*velocity+ +c1*rand([2,cusnum]).*(pbest_pos{i,1}-position)...
+c2*rand([2,cusnum]).*(gbest_pos-position);
%% 速度越界处理
velocity(1,:)=max(velocity(1,:),VvMin);
velocity(1,:)=min(velocity(1,:),VvMax);
velocity(2,:)=max(velocity(2,:),VrMin);
velocity(2,:)=min(velocity(2,:),VrMax);
%% 更新位置
position=position+velocity;
position(1,:)=ceil(position(1,:)); %对Xv向上取整
%% 速度镜像影响
IsOutside=(position(1,:)<XvMin | position(1,:)>XvMax | position(2,:)<XrMin | position(2,:)>XrMax);
velocity(IsOutside)=-velocity(IsOutside);
%% 位置越界处理
position(1,:)=max(position(1,:),XvMin);
position(1,:)=min(position(1,:),XvMax);
position(2,:)=max(position(2,:),XrMin);
position(2,:)=min(position(2,:),XrMax);
%% 对第i个粒子解码出的配送方案进行relocate操作
VC=decode(position,v_num);
RVC=relocate(VC,cap,demands,a,b,L,s,dist,alpha,belta);
position=change(RVC,cusnum);
%% 计算第i个粒子目标函数值
cost=costFuction(RVC,a,b,s,L,dist,demands,cap,alpha,belta);
%% 更新个体最优
if cost<pbest_obj(i,1)
pbest_pos{i,1}=position;
pbest_obj(i,1)=cost;
%% 更新全局最优
if pbest_obj(i,1)<gbest_obj
gbest_pos=pbest_pos{i,1};
gbest_obj=pbest_obj(i,1);
end
end
%% 更新第i个粒子的速度和位置
particle=[position;velocity];
population{i,1}=particle;
end
%% 记录各代全局最优解,打印各代全局最优解
BestCost(gen)=gbest_obj;
globalVC=decode(gbest_pos,v_num); %初始全局最优配送方案
%统计一个配送方案的总成本、车辆使用数目、行驶总距离、违反约束路径数目、违反约束顾客数目
[cost,NV,TD,vio_NV,vio_cus]=statistic(globalVC,a,b,s,L,dist,demands,cap,alpha,belta);
disp(['第',num2str(gen),'代全局最优解总成本为:',num2str(cost),',车辆使用数目为:',num2str(NV),...
',行驶总距离为:',num2str(TD),',违反约束路径数目为:',num2str(vio_NV),',违反约束顾客数目为:',num2str(vio_cus)]);
w=w*wdamp;
%% 更新计数器
gen=gen+1;
end
%% 将全局最优粒子解码为全局最优配送方案
globalVC=decode(gbest_pos,v_num);
%% 对全局最优配送方案进行局部搜索
globalVC=relocate_gbest(globalVC,cap,demands,a,b,L,s,dist,alpha,belta);
%% 统计全局最优配送方案的总成本、车辆使用数目、行驶总距离、违反约束路径数目、违反约束顾客数目
[cost,NV,TD,vio_NV,vio_cus]=statistic(globalVC,a,b,s,L,dist,demands,cap,alpha,belta);
disp(['最终全局最优解总成本为:',num2str(cost),',车辆使用数目为:',num2str(NV),...
',行驶总距离为:',num2str(TD),',违反约束路径数目为:',num2str(vio_NV),',违反约束顾客数目为:',num2str(vio_cus)]);
%% 画出全局最优配送方案路线图
draw_Best(globalVC,vertexs);
%% Results
figure;
%plot(BestCost,'LineWidth',2);
semilogy(BestCost,'LineWidth',2);
xlabel('迭代次数');
ylabel('全局最优目标函数值');
grid on;
toc
三、运行结果
四、备注
版本:2014a