多目标蚁群算法路径规划(2.5)------番外篇
系列前言(一定要看)
- 本系列为总结本人近一年多关于启发式算法解决路径规划的相关内容。主要从以下几个主题内容进行系列写作1.常见的数据获取方式与处理过程、,2、算法的基础流程,3.常见算法改进,4.多目标排序、5.基于应用场景的改进、6.其他相关问题、7、批量运行测试数据本系列全程免费提供相关代码。
- 本系列代码来源主要参考网上相关博客与文献、根据不同实际需求重构的代码。
- 本文所有提供的代码与文字说明仅供参考,不作为商业目的。
- 对内容有疑问或是错误部分可以留言或私信。
- 有偿定制特定功能,qq1602480875 。价格范围60—500。(建议优先看完系列内容,尝试系列中的代码,这些都是免费且能解决大部分问题。),具体代码后续会以完整形式上传百度云。
更新时间:2021年5月30日
1.1 本章内容说明-完整代码已经更新(2021年7月7日)
相关代码可以在我的 github下载
https://github.com/huang-xin-lei/parper/blob/main/多目标蚁群算法路径规划(2.5)------番外篇.md
- 包含时间、成本、载货需求变动的路径规划
- 算法设计的流程
- 路径规划主函数
- 路径规划的结果图
1.2 本章主要分享内容简介(摘要)
本章是对路径规划-从数据设计到毕业论文系列系列文章第二章
的一个补充说明,目的为分享程序的具体设计过程。补充算法
的流程图,完善了结果的展示过程。对算例使用的数据进行呈现
,并描述使用的数据特点。
- 本章代码会于6.20号后补充完整
- 详细讲解会在后续更新过程不断完善。
1.3 算法思路详细流程图
1.4 主函数
%% 输入数据
%% 版本0.1
clc
clear
close all
S2= xlsread('编队数据.xlsx','Sheet3');
Un = xlsread('编队数据.xlsx','补给时间与价值','A1:C10'); % 可提供的服务时间 消耗时间 消耗的物质的量
microsoftexcel = xlsread('编队数据.xlsx','舰船坐标','A1:B9');
qidian_where=[0 0]; %补给船起始坐标
S3=[microsoftexcel;qidian_where];
%% 清除临时变量
clearvars raw;
%% 数据整理
xdata=S3;
x_label=xdata(1:end,1);
y_label=xdata(1:end,2);
Demand=Un; %补给时间与价值矩阵
C=[x_label y_label]; %坐标矩阵
n=size(C,1); %n表示节点(作战舰船)个数
% ==============计算距离矩阵==============
D=zeros(n,n); %D表示完全图的赋权邻接矩阵,即距离矩阵D初始化
for i=1:n
for j=1:n
if i~=j
D(i,j)=((C(i,1)-C(j,1))^2+(C(i,2)-C(j,2))^2)^0.5; %计算两舰船之间的距离
if D(i,j)==0
D(i,j)=eps; %对不可直接到达的地方一个赋予一个极小值
end
else
D(i,j)=eps; %i=j, 则距离为0;赋予一个极小值
end
D(j,i)=D(i,j); %距离矩阵为对称矩阵
end
end
v=37; % 30km/h 速度约束矩阵
Alpha=1;%
Beta=5; %
Rho=0.75; % 信息挥发程度
iter_max=100; %迭代次数
Q=10; %
Cap=S2; %最大补给时间限制矩阵
m=size(D,1); %起始放置数目
qidian=m; % qidian起点坐标
[R_best,L_best,L_ave,Shortest_Route,~,L_ave_long]=ANT_VRP(D,Demand,Cap,iter_max,m,Alpha,Beta,Rho,Q,qidian,v); %蚁群算法求解VRP问题有约束函数
Shortest_Route_1=Shortest_Route; %提取最优路线
cc=find(Shortest_Route_1==qidian);
xx_1=[];
best_route_2=[];
for i=1:length(cc)-1
if i~=length(cc);
cs_1=length(Shortest_Route_1(cc(i):cc(i+1)));
xx_1(i,1:cs_1)=Shortest_Route_1(cc(i):cc(i+1)); %路线
else
end
best_route_1=0;
for j=1:length(xx_1(i,1:cs_1))-1 %计算每条路径的距离/成本
best_route_1=D(xx_1(i,j),xx_1(i,j+1))+best_route_1;
end
best_route_vaule=0;
for j=1:length(xx_1(i,1:cs_1))-1 %计算每条路径的距离/成本
best_route_vaule=Demand(xx_1(i,j),2)+best_route_vaule;
end
best_route_2(i,1)= best_route_1; %每条路径的长度
best_route_2(i,2)= best_route_vaule; %每条路径的长度
end
[~,n]=max(best_route_2(:,2));
Shortest_Length=best_route_2(n,2); %提取最短路径长度
%% ==============作图==============
figure(1)%作迭代收敛曲线图
x=linspace(0,iter_max,iter_max);
y=L_best(:,1);
plot(x,y);
xlabel('迭代次数'); ylabel('最大补给价值');
title('最大补给价值迭代图')
figure(2) %作最短路径图
[~,m]=max(best_route_2(:,2));
Shortest_Route=xx_1(m,:);
plot(C(:,1),C(:,2),'*');
hold on
plot(C(Shortest_Route,1),C(Shortest_Route,2),'*-');
axis ( [-60 60 -20 100] ); %坐标绘制范围
grid on
%% 设置导入选项并导入数据
S1={'航空母舰','驱逐舰1','驱逐舰2','护卫舰1','护卫舰2','护卫舰3','护卫舰4','驱逐舰3','驱逐舰4','补给船'};
for i =1:size(C,1)
% text(C(i,1),C(i,2),[' ' num2str(i)]);
text(C(i,1),C(i,2),[' ' S1(i)]);
end
xlabel('编队舰船横坐标'); ylabel('编队舰船纵坐标');
title('最大价值路径图')
figure(3)%作迭代收敛曲线图
axis ( [-60,60,-20,100] );
x=linspace(0,iter_max,iter_max);
y=L_ave_long;
plot(x,y);
xlabel('迭代次数'); ylabel('每代最优路径');
title('补给路程迭代图')
xlswrite('相关参数与结果.xlsx',[xx_1,best_route_2],'路径结果','A2')
clc
beak_length=D(Shortest_Route(end-1),Shortest_Route(end));
all_time=sum(Demand(Shortest_Route))+best_route_2(n,1)/v+beak_length/v;
disp(strcat('迭代次数:',num2str(iter_max)))
disp(strcat('最大补给价值为:',num2str(Shortest_Length)))
disp(strcat('最大补给价值路径长度为:',num2str(best_route_2(n,1))))
disp(strcat('返程路径长度:',num2str(beak_length)))
disp(strcat('返程路径消耗时间:',num2str(beak_length/v),'小时'))
disp(strcat('约束时间:',num2str(S2(1)),'小时'))
disp(strcat('剩余时间:',num2str(S2(1)-all_time),'小时'))
disp(strcat('剩余时间可服务距离:',num2str(v*(S2(1,1)-all_time)),'km'))
disp(strcat('总共消耗时间:',num2str(all_time),'小时'))
disp(strcat('运输货物量:',num2str(sum(Demand(Shortest_Route,3))),'单位'))
disp(strcat('运输货物剩余量:',num2str(S2(1,3)-sum(Demand(Shortest_Route,3))),'单位'))
- 蚁群规划核心部分
%因为cnsd平台一直提示存在营销行为不能正常展示,具体内容见github链接
function [R_best,L_best,L_ave,Shortest_Route,Shortest_Length,L_ave_long]=ANT_VRP(D,Demand,Cap,iter_max,m,Alpha,Beta,Rho,Q,qidian,v,time_1,time_2)
%% v车辆运行速度
%% time_1 装货时间
%% time_2 卸货时间
%% qidian 起点(仓库)的位置
%% R_best 各代最佳路线
%% L_best 各代最佳路线的长度
%% L_ave 各代平均距离
%% Shortest_Route 最短路径
%% Shortest_Length 最短路径长度
%% D 城市间之间的距离矩阵,为对称矩阵
%% Demand 客户需求量
%% Cap 车辆最大载重
%% iter_max 最大迭代次数
%% m 蚂蚁个数
%% Alpha 表征信息素重要程度的参数
%% Beta 表征启发式因子重要程度的参数
%% Rho 信息素蒸发系数
%% Q 信息素增加强度系数
cap_num=1; % 补给船初始化
n=size(D,1);
Eta=ones(m,2*n); %启发因子
Tau=ones(n,n); %信息素
Tabu=zeros(m,n); %禁忌表
Route=zeros(m,2*n); %路径
L=zeros(m,1); %总路程
L_best=zeros(iter_max,1); %各代最佳路线长度
R_best=zeros(iter_max,2*n); %各代最佳路线
nC=1;
k_1=1; %循环时的起始车辆
while nC<=iter_max %停止条件
disp(strcat('已经迭代次数',num2str(nC)))
Eta=zeros(m,2*n);
T=zeros(m,2*n);
Tabu=zeros(m,n);
Route=zeros(m,2*n);
L=zeros(m,1);
%% %%%%%%==============初始化起点城市(禁忌表)====================
for i=1:m
Cap_1=Cap(cap_num,1); %最大装载量
Cap_2=Cap(cap_num,3); %最大装载量
j=1;
j_r=1;
while Tabu(i,n)==0
T=zeros(m,2*n); %装载量加载矩阵
Tabu(i,1)=qidian; %禁忌表起点位置为1
Route(i,1)=qidian; %路径起点位置为1
visited=find(Tabu(i,:)>0); %已访问城市
num_v=length(visited); %已访问城市个数
J=zeros(1,(n-num_v)); %待访问城市加载表
P=J; %待访问城市选择概率分布
Jc=1; %待访问城市选择指针
for k=1:n %城市
if isempty(find(Tabu(i,:)==k, 1)) %如果k不是已访问城市代号,就将k加入矩阵J中
J(Jc)=k;
Jc=Jc+1;
end
end
%% %%%%%%%=============每只蚂蚁按照选择概率遍历所有城市==================
for k=1:n-num_v %待访问城市
Cap_1=Cap_1-D(1,Tabu(i,visited(end)))/v;%减去路上消耗时间
if (Cap_1-Demand(J(1,k),1))>=0 && (Cap_2-Demand(J(1,k),3))>=0
if (Cap_2-Demand(J(1,k),3))<=0
disp('chuwu')
end
if Route(i,j_r)==1 %如果每只蚂蚁在起点城市
T(i,k)=D(1,J(1,k));
P(k)=(Tau(1,J(1,k))^Alpha)*((1/T(i,k))^Beta); %概率计算公式中的分子
else %如果每只蚂蚁在不在起点城市
T(i,k)=D(Tabu(i,j),J(1,k));
P(k)=(Tau(Tabu(i,visited(end)),J(1,k))^Alpha)*((1/T(i,k))^Beta); %概率计算公式中的分子
end
else %如果车辆装载量小于待访问城市需求量
T(i,k)=0;
P(k)=0;
end
end
if isempty(find(T(i,:)>0, 1)) %%%当车辆装载量小于待访问城市时,选择起点返回
if cap_num>size(Cap,1) %当超过一定时间后重新出发车辆
cap_num=1;
end
Cap_1=Cap(cap_num,1); %最大装载量
Cap_2=Cap(cap_num,3); %最大装载量
Cap_1=Cap_1-D(1,Tabu(i,visited(end)))/v;%减去路上消耗时间
j_r=j_r+1;
Route(i,j_r)=qidian; %每次定义每次从起点出发
L(i)=L(i)+D(1,Tabu(i,visited(end))); %距离长度
else
P=P/(sum(P)); %按照概率原则选取下一个城市
Pcum=cumsum(P); %求累积概率和:cumsum([1 2 3])=1 3 6,目的在于使得Pcum的值总有大于rand的数
Select=find(Pcum>rand); %按概率选取下一个城市:当累积概率和大于给定的随机数,则选择求和被加上的最后一个城市作为即将访问的城市
o_visit=J(1,Select(1)); %待访问城市
j=j+1;
j_r=j_r+1;
Tabu(i,j)=o_visit; %待访问城市
Route(i,j_r)=o_visit;
Cap_1=Cap_1-D(1,Tabu(i,visited(end)))/v;
Cap_1=Cap_1-Demand(o_visit,1); %车辆装载质量剩余量
Cap_2=Cap_2-Demand(o_visit,3); %车辆装载质量剩余量
L(i)=L(i)+T(i,Select(1)); %路径长度
end
end
L(i)=L(i)+D(Tabu(i,n),1); %%路径长度
end
%% 寻找价值最大路径
for i_j=1:size(Route,1)
Shortest_Route_1=Route(i_j,:);
cc=find(Route(i_j,:)==qidian);
cc_pp=find(Route(i_j,:)==0,1); %最后一个路径的的结尾
xx_1=[];
best_route_2=[];
if length(cc)<=1
cc_xulie=length(cc);
else
cc_xulie=length(cc);
end
for i=1:cc_xulie
if i==1 && cc_xulie~=1
cs_1=length(Shortest_Route_1(cc(i):cc(i+1)));
xx_1(i,1:cs_1)=Shortest_Route_1(cc(i):cc(i+1)); %路线
elseif i==length(cc)
cs_1=length(Shortest_Route_1(cc(i):cc_pp));
xx_1(i,1:cs_1)=Shortest_Route_1(cc(i):cc_pp); %路线
else
cs_1=length(Shortest_Route_1(cc(i):cc(i+1)));
xx_1(i,1:cs_1)=Shortest_Route_1(cc(i):cc(i+1)); %路线
end
best_route_1=0;
xx_1(xx_1==0)=qidian;
%计算每条路的长度
for j=1:length(xx_1(i,1:cs_1))-1 %计算每条路径的距离/价值
best_route_1=D(xx_1(i,j),xx_1(i,j+1))+best_route_1;
end
best_route_vaule=0;
for j=1:length(xx_1(i,1:cs_1))-1 %计算每条路径的距离/价值
best_route_vaule=Demand(xx_1(i,j),2)+best_route_vaule;
end
best_route_2(i,1)= best_route_1; %每条路径的长度
best_route_2(i,2)= best_route_vaule; %每条路径的长度
end
[~,kk_num]=max(best_route_2(:,2));
L_vaule(i_j,:)=best_route_2(kk_num,2);
L_long(i_j,:)=best_route_2(kk_num,1);
end
%% 以价值最大的作为选择指标
L=L_vaule;
L_best(nC)=max(L); %最优路径为距离最短的路径
pos=find(L==max(L)); %找出最优路径对应的位置:即为哪只蚂蚁\
[~,kk_1]=min(L_long(pos)); %最大价值最短路径
L_ave_long(nC)=mean(L_long)';
R_best(nC,:)=Route(pos(kk_1),:); %确定最优路径对应的城市顺序
L_ave(nC)=mean(L)'; %求第k次迭代的平均距离
Delta_Tau=zeros(n,n); %Delta_Tau(i,j)表示所有蚂蚁留在第i个城市到第j个城市路径上的信息素增量
L_zan=L_best(1:nC,1);
post=find(L_zan==max(L_zan));
Cities=find(R_best(nC,:)>0);
num_R=length(Cities);
for k=1:num_R-1 %建立了完整路径后在释放信息素
Delta_Tau(R_best(nC,k),R_best(nC,k+1))=Delta_Tau(R_best(nC,k),R_best(nC,k+1))+Q/L_best(nC);
end
Delta_Tau(R_best(nC,num_R),1)=Delta_Tau(R_best(nC,num_R),1)+Q/L_best(nC);
Tau=Rho*Tau+Delta_Tau;
mod=1;
if mod==1
% %% 基于迭代次数控制挥发程度
% switch nC
% case nC<iter_max/3
% Rho=0.2;
% case nC<2*iter_max/3 && nC>iter_max/3
% Rho=0.3;
% otherwise
% Rho=0.5;
% end
end
nC=nC+1;
end
Shortest_Route=zeros(1,2*n); %提取最短路径
[~,n]=max(L_best);
% Shortest_Route(1,:)=R_best(n,:);%保留最优
Shortest_Route(1,:)=R_best(iter_max,:);%保留最后
Shortest_Route=Shortest_Route(Shortest_Route>0);
Shortest_Route=[Shortest_Route Shortest_Route(1,1)];
Shortest_Length=max(L_best); %提取最短路径长度
L_ave=mean(L_best);
1.4 运算的示例数据
- 路径数据数据
- 车辆约束数据
- 路径坐标信息
- 运算结果
- 变动数据的运行结果