本系列主要分享关于利用蚁群算法进行有约束的路径规划的代码过程
本文未解决以下问题
- 带时间约束的
- 多车辆同时除非问题
- 上传数据表格太麻烦了
- [确定 ] 代码都是能完整运行的
- [代码免费分享] 如果定制是收费的 价格为30 到100 不等
第一部分 基础版代码
- 改进的蚁群算法
- 带软时间窗口的
- 例子为港口航线的优化
- 时间窗口是指随着时间的变化不同地区的需求的变化的。每次进行规划时需要考虑当前运行时间和货物需求点的情况
- 主要约束包括路径长度,不同港口费用,装卸
- 里面包含改进的蚁群算法过程
代码过程
说明 : 本代码参考了网上一些基础代码,根据实际需求进行了修改。本文章只展示代码实现过程,对具体原理将在后续过程更新。所示代码仅供参考。
如果要定制服务私聊。本代码为原创,采用留个爪印。。。。
主函数
港口不需要全部都经过,选取收益最大的线路做为运行线路
clc
clear
close all
% 主程序
for i=2:9
[x2,D,Cap,C,d_u,t1,v_2,cost_2]=fist_1(5);
D=D(1:i,1:i);
Demand=zeros(size(D,1),2);
Alpha=1;Beta=5; %
Rho=0.75; %
iter_max=100; %迭代次数
Q=10; %
m=size(D,1); %起始放置数目
qidian=1; % qidian起点坐标
[R_best,L_best,L_ave,Shortest_Route,Shortest_Length,j_1_j]=ANT_VRP_1(D,Demand,Cap,iter_max,m,Alpha,Beta,Rho,Q,qidian,d_u,t1,v_2,cost_2,x2);
Shortest_Route_1=Shortest_Route; %提取最优路线
cc=find(Shortest_Route_1==qidian);
xx_1=[];
if length(cc)==2
for i=1: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)); %路线
end
else
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)); %路线
end
end
Shortest_Length; %提取最短路径长度
%% ==============作图==============
% figure(1) %作迭代收敛曲线图
% x=linspace(0,iter_max,iter_max);
% y=L_best(:,1);
% plot(x,y);
% xlabel('迭代次数'); ylabel('最短路径长度');
figure(2) %作最短路径图
plot(C(Shortest_Route,1),C(Shortest_Route,2),'o-');
grid on
for i =1:size(C,1)
if i==qidian
text(C(i,1),C(i,2),' 起始港口 ');
else
text(C(i,1),C(i,2),[' ' num2str(i)]);
end
end
xlabel('客户所在横坐标'); ylabel('客户所在纵坐标');
hold on
best_all(i)=1/Shortest_Length;
for i=1:length(Shortest_Route)-1
tim_1(i)=t1(Shortest_Route(i),Shortest_Route(i+1));
end
time_all=sum(tim_1);
end
hold off
disp("最后收益为:")
disp(strcat(num2str(max(best_all)),'元'))
disp("最后需要经历的港口数目:")
disp(num2str(find(best_all==max(best_all))))
disp("运行的时间:")
disp(strcat(num2str(time_all),'天'))
disp("运行的顺序:")
disp(Shortest_Route)
初始成本核算
导入要计算的数据,计算初始的成本,后续成本与时间成关联
function [x2,d,ronlian_1,x6,d1,t1,v_2,cost_2] =fist_1(cc)
%%
% 输入初始数据 cc起始的星期
% 输出 窗口系数矩阵 初始成本,船型约束 第一次运行后需要的计算的成本
%%
% 导入需求矩阵
x1 = xlsread('H:\项目文件\交通规划项目结果图\蚁群算法规划\工作簿1.xlsx','平均需求','B2:J10');
% 导入时间系数矩阵
x2 = xlsread('H:\项目文件\交通规划项目结果图\蚁群算法规划\工作簿1.xlsx','时间窗口','B2:H10');
% 导入距离矩阵
x3 = xlsread('H:\项目文件\交通规划项目结果图\蚁群算法规划\工作簿1.xlsx','距离','B2:J10');
% 导入运价矩阵
x4 = xlsread('H:\项目文件\交通规划项目结果图\蚁群算法规划\工作簿1.xlsx','运价','B2:J10');
% 导入其他数据
x5 = xlsread('H:\项目文件\交通规划项目结果图\蚁群算法规划\工作簿1.xlsx','其他数据','B2:B7');
% 导入坐标数据
x6=xlsread('H:\项目文件\交通规划项目结果图\蚁群算法规划\工作簿1.xlsx','位置坐标','B2:C10');
%判断是否进行时间窗口约束
if nargin==1
d_1=x1;
if cc>7
cc=ceil(mod(cc,7));
if cc==0
cc=1;
end
end
t=ones(size(d_1,1),size(d_1,2));
for i=1:size(t,2)
t(:,i)=x2(:,cc);
end
else
d_1=x1;
t=ones(size(d_1,1),size(d_1,2));
end
% 油价 维修费用 运行速度
v1 = x5(1); %速度 21节/小时
lio_1 = x5(2); %轻油
lio_2 = x5(3); %重油
ronlian_1 = [x5(4),inf]; %船型
zhujing_1 = x5(5); %船舶租金
used_1 = x5(6); %港口租金
t3 = 0; %初始运行
t1=x3/(24*v1); %航行时间
v_2=x1.*x4.*t; %运行收入
t2=0.5;
n=0;%运行到第n个港口
other_cost=0; %初始其他消费
cost_1=t1.*(lio_1+lio_2)/2+0.5*n*used_1+(t1+t2*12).* zhujing_1+other_cost*n; %初始成本
n=1;
cost_2=t1.*(lio_1+lio_2)/2+0.5*n*used_1+(t1+t2*12).* zhujing_1+other_cost*n; %初始成本
d=v_2-cost_1; %初始收益
d1=v_2-cost_2; %初始收益
if min(max(d))<=0
disp('设计的数据不合理,请重新设计')
end
if min(max(d1))<=0
disp('设计的数据不合理,请重新设计')
end
% 成本取倒数
d(d<=0)=eps;
d=1./d;
d1(d1<=0)=eps;
d1=1./d1;
进行成本约束
function [R_best,L_best,L_ave,Shortest_Route,Shortest_Length,j_1_j]=ANT_VRP_1(D,Demand,Cap,iter_max,m,Alpha,Beta,Rho,Q,qidian,d1,t1,v_2,cost_2,x2)
%% 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);
D_XX=D; %第一出发
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; %循环时的起始车辆
mod_way=2; %计算的模式 2时间窗口 1改进算法 3 不带窗口
r=0.5;
while nC<=iter_max %停止条件
disp(strcat('已经迭代次数',num2str(nC)))
clc
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 %如果车辆装载量大于待访问城市需求量
hij(i,k)=abs((Cap_1+Demand(J(1,k),1))/Cap(cap_num,1)); %计算满载率
j_1_j(i,k)=1/hij(i,k);
if Route(i,j_r)==1 %如果每只蚂蚁在起点城市
D=D_XX;
T(i,k)=D(1,J(1,k));
P(k)=(Tau(1,J(1,k))^Alpha)*((1/T(i,k))^Beta); %概率计算公式中的分子
if mod_way==1
%考虑满载率
P(k)=(Tau(1,J(1,k))^Alpha)*((1/T(i,k))^Beta)*((1/hij(i,k))^r); %概率计算公式中的分子
end
else %如果每只蚂蚁在不在起点城市
D=d1;
if mod_way==2
cc=t1(Tabu(i,j),J(1,k));
cc=ceil(mod(cc,7));
if cc==0
cc=1;
end
d=Update_weights(D,x2,cc,cost_2,v_2);
D=d;
end
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); %概率计算公式中的分子
if mod_way==1
%考虑满载率
P(k)=(Tau(Tabu(i,visited(end)),J(1,k))^Alpha)*((1/T(i,k))^Beta)*((1/hij(i,k))^r);
end
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);
if mod_way==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
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);
随时间进行权重更新
function d=Update_weights(D,x2,n,cost_1,v_2)
%% d 收益矩阵
% n 航线到第n个港口的费用
% x2 时间窗口矩阵
d=D;
if nargin<=6
t=ones(size(d,1),size(d,2));
else
t=ones(size(d,1),size(d,2));
for i=1:size(t,2)
t(:,i)=x2(:,n);
end
end
d=v_2.*t-cost_1; %运行到n第次的收益
if min(max(d))<=0
disp('设计的数据不合理,请重新设计')
end
% 成本取倒数
d(d<=0)=eps;
d=1./d;
结果说明
结果展示运行的最大收益,经过的港口数目,运行的周期。
本代码设计的主要是单一航线,如果多航线有返回的,只需要把需求和载重更改。
数据文件链接
链接:https://pan.baidu.com/s/1upG7Qvfa-LyWxHW4MSjQLA
提取码:frqq