1 简介
有时间窗的车辆路径问题(Vehicle Routing Problem with Time Windows,VRPTW)因为其有重要的现实意义而备受关注.其时间窗即为客户接受服务的时间范围,该问题是运筹学和组合优化领域中的著名NP问题,是解决物流配送效率的关键,传统寻优方法效率低,耗时长,找不到满意解,往往导致物流成本过高.为了提高寻优效率,降低物流运送成本,基本遗传算法求解VRPTW问题.首先建立数学模型,然后基于大规模邻域搜索算法(LNS)生成遗传算法初始解,最后利用遗传算法在初始种群中找到最优解.计算结果表明,遗传算法可以更好求解车辆路径问题,有效降低物流成本.
2 部分代码
% % clear clc close all tic %% 用importdata这个函数来读取文件 % filename='.\evrptw_instances\c101_21.txt'; c101=importdata('data.txt'); cap=200; %车辆最大装载量 %% 提取数据信息 E=c101(1,5); %配送中心时间窗开始时间 L=c101(1,6); %配送中心时间窗结束时间 vertexs=c101(:,2:3); %所有点的坐标x和y customer=vertexs(2:end,:); %顾客坐标 cusnum=size(customer,1); %顾客数 v_num=6; %车辆最多使用数目 demands=c101(2:end,4); %需求量 a=c101(2:end,5); %顾客时间窗开始时间[a[i],b[i]] b=c101(2:end,6); %顾客时间窗结束时间[a[i],b[i]] s=c101(2:end,7); clc %清空命令行窗口 clear %从当前工作区中删除所有变量,并将它们从系统内存中释放 close all %删除其句柄未隐藏的所有图窗 tic % 保存当前时间 %% GA-PSO算法求解VRPTW %输入: %City 需求点经纬度 %Distance 距离矩阵 %Demand 各点需求量 %Travelcon 行程约束 %Capacity 车容量约束 %TimeWindow 各需求点时间窗 %NIND 种群个数 %MAXGEN 遗传到第MAXGEN代时程序停止 %输出: %Gbest 最短路径 %GbestDistance最短路径长度 %% 加载数据 load('./test_data/City.mat') %需求点经纬度,用于画实际路径的XY坐标 load('./test_data/Distance.mat') %距离矩阵 load('./test_data/TravelTime.mat') %行驶时间矩阵 load('./test_data/Demand.mat') %需求量 load('./test_data/TimeWindow.mat') %时间窗 load('./test_data/Travelcon.mat') %行程约束 load('./test_data/Capacity.mat') %车容量约束 %% 初始化问题参数 CityNum=size(City,1)-1; %需求点个数 %% 初始化算法参数 NIND=60; %粒子数量 MAXGEN=100; %最大迭代次数 %% 为预分配内存而初始化的0矩阵 Population = zeros(NIND,CityNum*2+1); %预分配内存,用于存储种群数据 PopDistance = zeros(NIND,1); %预分配矩阵内存 GbestDisByGen = zeros(MAXGEN,1); %预分配矩阵内存 for i = 1:NIND %% 初始化各粒子 Population(i,:)=InitPop(CityNum,Distance,TravelTime,Demand,TimeWindow,Travelcon,Capacity); %随机生成TSP路径 %% 计算路径长度 PopDistance(i) = CalcDis(Population(i,:),Distance,TravelTime,Demand,TimeWindow,Travelcon,Capacity); % 计算路径长度 end %% 存储Pbest数据 Pbest = Population; % 初始化Pbest为当前粒子集合 PbestDistance = PopDistance; % 初始化Pbest的目标函数值为当前粒子集合的目标函数值 %% 存储Gbest数据 [mindis,index] = min(PbestDistance); %获得Pbest中 Gbest = Pbest(index,:); % 初始Gbest粒子 GbestDistance = mindis; % 初始Gbest粒子的目标函数值 %% 开始迭代 gen=gen+1; end %删去路径中多余1 for i=1:length(Gbest)-1 if Gbest(i)==Gbest(i+1) Gbest(i)=0; %相邻位都为1时前一个置零 end end Gbest(Gbest==0)=[]; %删去多余零元素 Gbest=Gbest-1; % 编码各减1,与文中的编码一致 %% 计算结果数据输出到命令行 disp('-------------------------------------------------------------') toc %显示运行时间 fprintf('Total Distance = %s km \n',num2str(GbestDistance)) TextOutput(Gbest,Distance,TravelTime,Demand,TimeWindow,Capacity) %显示最优路径 disp('-------------------------------------------------------------') %% 迭代图 figure plot(GbestDisByGen,'LineWidth',2) %展示目标函数值历史变化 xlim([1 gen-1]) %设置 x 坐标轴范围 set(gca, 'LineWidth',1) xlabel('Iterations') ylabel('Min Distance(km)') title('HPSO Process') img =gcf; %获取当前画图的句柄 print(img, '-dpng', '-r600', './img.png') %即可得到对应格式和期望dpi的图像 %% 绘制实际路线 figure DrawPath(Gbest,City) img =gcf; %获取当前画图的句柄 print(img, '-dpng', '-r600', './img1.png') %即可得到对应格式和期望dpi的图像 %客户点的服务时间 h=pdist(vertexs); dist=squareform(h); %距离矩阵,满足三角关系,暂用距离表示花费c[i][j]=dist[i][j] %% 遗传算法参数设置 alpha=10; %违反的容量约束的惩罚函数系数 belta=100; %违反时间窗约束的惩罚函数系数 NIND=100; %种群大小 MAXGEN=100; %迭代次数 Pc=0.9; %交叉概率 Pm=0.05; %变异概率 GGAP=0.9; %代沟(Generation gap) N=cusnum+v_num-1; %染色体长度=顾客数目+车辆最多使用数目-1 %% 初始化种群 init_vc=init(cusnum,a,demands,cap); %构造初始解 Chrom=InitPopCW(NIND,N,cusnum,init_vc); %% 输出随机解的路线和总距离 disp('初始种群中的一个随机值:') [VC,NV,TD,violate_num,violate_cus]=decode(Chrom(1,:),cusnum,cap,demands,a,b,L,s,dist); % disp(['总距离:',num2str(TD)]); disp(['车辆使用数目:',num2str(NV),',车辆行驶总距离:',num2str(TD),',违反约束路径数目:',num2str(violate_num),',违反约束顾客数目:',num2str(violate_cus)]); disp('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~') %% 优化 gen=1; gcf=figure(1); hold on;box on xlim([0,MAXGEN]) title('优化过程') xlabel('代数') ylabel('最优值') img =gcf; %获取当前画图的句柄 print(img, '-dpng', '-r600', './img.png') %即可得到对应格式和期望dpi的图像 ObjV=calObj(Chrom,cusnum,cap,demands,a,b,L,s,dist,alpha,belta); %计算种群目标函数值 preObjV=min(ObjV); while gen<=MAXGEN ObjV=calObj(Chrom,cusnum,cap,demands,a,b,L,s,dist,alpha,belta); %计算种群目标函数值 [minObjV,minInd]=min(ObjV); disp(['第',num2str(gen),'代最优解:']) [bestVC,bestNV,bestTD,best_vionum,best_viocus]=decode(Chrom(minInd(1),:),cusnum,cap,demands,a,b,L,s,dist); disp(['车辆使用数目:',num2str(bestNV),',车辆行驶总距离:',num2str(bestTD),',违反约束路径数目:',num2str(best_vionum),',违反约束顾客数目:',num2str(best_viocus)]); fprintf('\n') %% 更新迭代次数 gen=gen+1 ; end %% 画出最优解的路线图 ObjV=calObj(Chrom,cusnum,cap,demands,a,b,L,s,dist,alpha,belta); %计算种群目标函数值 [minObjV,minInd]=min(ObjV); %% 输出最优解的路线和总距离 disp('最优解:') bestChrom=Chrom(minInd(1),:); [bestVC,bestNV,bestTD,best_vionum,best_viocus]=decode(bestChrom,cusnum,cap,demands,a,b,L,s,dist); disp(['车辆使用数目:',num2str(bestNV),',车辆行驶总距离:',num2str(bestTD),',违反约束路径数目:',num2str(best_vionum),',违反约束顾客数目:',num2str(best_viocus)]); disp('-------------------------------------------------------------') %% 判断最优解是否满足时间窗约束和载重量约束,0表示违反约束,1表示满足全部约束 flag=Judge(bestVC,cap,demands,a,b,L,s,dist); %% 检查最优解中是否存在元素丢失的情况,丢失元素,如果没有则为空 DEL=Judge_Del(bestVC); %% 画出最终路线图 draw_Best(bestVC,vertexs); img =gcf; %获取当前画图的句柄 print(img, '-dpng', '-r600', './img2.png') %即可得到对应格式和期望dpi的图像 save c101.mat toc
3 仿真结果
4 参考文献
[1]张露. (2020). 基于改进遗传算法求解带时间窗车辆路径规划问题. 中国物流与采购(14).