本系列主要分享关于利用蚁群算法进行有约束的路径规划的代码过程
后续更新连接
最新功能增加、使用便利性改善的汇总放置文章
https://blog.csdn.net/qq_33980829/article/details/115108756
本文未解决以下问题
更新2021年3月23日
从数据到论文全系列连接
第一部分 基础版代码
- 无时间窗口的基础版
- 改进的蚁群算法
- 带软时间窗口的
- 最新版https://blog.csdn.net/qq_33980829/article/details/112005978
代码过程
说明 : 本代码参考了网上一些基础代码,根据实际需求进行了修改。本文章只展示代码实现过程,对具体原理将在后续过程更新。所示代码仅供参考。
如果要定制服务私聊
主函数
%% 完成时间 2020年5月5日21:12:00
% 基础版本 尚帝
% 0.1版
% 基本的体积约束和质量约束
% 三种模式 利用直角坐标计算 自定义路径矩阵 利用经纬度进行计算
banbenhao=0.01;
%% 输入数据
S2= xlsread('煤矿分布表1.xlsx','Sheet3');
Un = xlsread('煤矿分布表1.xlsx','Sheet2');
microsoftexcel = xlsread('煤矿分布表1.xlsx','陕西省煤矿分布表','E4:F20');
qidian_where=[126.63 45.75]; %起始的城市坐标
S3=[microsoftexcel;qidian_where];
%% 数据整理
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
D=zeros(n,n);
panduan_1=input('请输入要计算的矩阵---1路径矩阵,-2空间距离矩阵==其他情况为用坐标直接计算==');
if panduan_1==1
load('juli_3.mat'); %路径距离相对矩阵
elseif panduan_1==2
load('juli_7.mat'); %空间距离相对矩
elseif panduan_1==3
%% 导入数据
raw = xlsread('煤矿分布表1.xlsx','陕西省煤矿分布表','E4:F20');
mi=[raw;qidian_where];
cc=zeros(size(mi,1));
for j=1:size(mi,1)
for i=j:size(mi,1)
cc(j,i)=abs(6371004*acos((sin(deg2rad(mi(j,2)))*sin(deg2rad(mi(i,2)))+cos(deg2rad(mi(j,2)))*cos(deg2rad(mi(i,2)))*cos(deg2rad(mi(i,1)-mi(j,1))))));
if i==j || cc(j,i)==0
cc(j,i)=eps;
end
cc(i,j)=cc(j,i);
end
end
un_1_1=cc;
D=un_1_1;
end
v=16.7; %16.7 m/min 60km/h 速度约束矩阵
time_1=20;% 20分钟
time_2=20;% 20分钟
Alpha=1;
Beta=5; %
Rho=0.75; %
iter_max=100; %迭代次数
Q=10; %
Cap=S2; %车辆承载能力限制矩阵
m=size(D,1); %起始放置数目
qidian=m; % qidian起点坐标
if qidian<size(S3,1)
errordlg('输入的起点位置出现问题请重新输入')
qidian=input("起点坐标的(编号)=");
end
[R_best,L_best,L_ave,Shortest_Route,Shortest_Length]=ANT_VRP(D,Demand,Cap,iter_max,m,Alpha,Beta,Rho,Q,qidian,v,time_1,time_2); %蚁群算法求解VRP问题有约束函数
Shortest_Route_1=Shortest_Route; %提取最优路线
cc=find(Shortest_Route_1==qidian);
xx_1=[];
best_route_2=[];
for i=1:length(cc)/2+2
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)); %路线
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_2(i,1)= best_route_1; %每条路径的长度
end
Shortest_Length; %提取最短路径长度
%% ==============作图==============
figure(1)%作迭代收敛曲线图
x=linspace(0,iter_max,iter_max);
y=L_best(:,1);
plot(x,y);
xlabel('迭代次数'); ylabel('最优路径变化');
saveas(gcf,'迭代过程.jpg')
figure(2) %作最短路径图
plot(C(Shortest_Route,1),C(Shortest_Route,2),'*-');
grid on
for i =1:size(C,1)
text(C(i,1),C(i,2),[' ' num2str(i)]);
end
xlabel('客户所在横坐标'); ylabel('客户所在纵坐标');
saveas(gcf,'路径结果.jpg')
xlswrite('相关参数与结果.xlsx',[xx_1,best_route_2],'路径结果','A2')
clc
disp(strcat('运行的版本为:',num2str( banbenhao)))
disp(strcat('运行的模式为:',num2str( panduan_1)))
disp(strcat('默认的起点为:',num2str(qidian)))
disp(strcat('迭代次数:',num2str(iter_max)))
disp(strcat('最短路径长度为:',num2str(Shortest_Length)))
disp('结果已经成功保存')
寻优函数
function [R_best,L_best,L_ave,Shortest_Route,Shortest_Length]=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);
T=zeros(m,2*n); %装载距离
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,2); %最大体积承受能力
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 %待访问城市
if Cap_1-Demand(J(1,k),1)>=0 && Cap_2-Demand(J(1,k),2)>=0 %如果车辆装载量大于待访问城市需求量
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,2); %最大体积承受能力
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-Demand(o_visit,1); %车辆装载质量剩余量
Cap_2=Cap_2-Demand(o_visit,2); %车辆装载体检剩余量
L(i)=L(i)+T(i,Select(1)); %路径长度
end
end
L(i)=L(i)+D(Tabu(i,n),1); %%路径长度
end
L_best(nC)=min(L); %最优路径为距离最短的路径
pos=find(L==min(L)); %找出最优路径对应的位置:即为哪只蚂蚁
R_best(nC,:)=Route(pos(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==min(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;
nC=nC+1;
end
Shortest_Route=zeros(1,2*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=min(L_best); %提取最短路径长度
L_ave=mean(L_best);
结果展示
结果会生成一个表格,在表格里展示数据结果,也可以通过看注释进行理解。
表格数据展示
链接:https://pan.baidu.com/s/1-QvztHBiXbkkIb2Xp6oPxQ
提取码:hot6
更新时间:2020年11月18日