用Matlab搞定物流配送难题:手把手教你写VRPTW遗传算法(附完整代码)

发布时间:2026/5/30 18:01:33

用Matlab搞定物流配送难题:手把手教你写VRPTW遗传算法(附完整代码) 用Matlab实现VRPTW遗传算法从理论到实战的完整指南物流配送优化一直是企业降本增效的关键环节。想象一下你负责一家电商公司的配送调度每天需要安排数十辆货车为数百个客户送货每个客户都有特定的时间窗口要求车辆载重也各不相同。如何科学安排路线既满足客户需求又最小化成本这就是VRPTW带时间窗的车辆路径问题要解决的核心问题。遗传算法作为一种模拟自然进化过程的优化方法特别适合解决这类复杂约束的组合优化问题。本文将带你用Matlab一步步实现VRPTW遗传算法从数据结构设计到最终可视化提供可直接应用于实际项目的完整解决方案。1. 环境准备与问题建模1.1 Matlab基础配置在开始编码前确保你的Matlab环境已准备好以下工具包Optimization Toolbox用于基础数学运算和优化函数Statistics and Machine Learning Toolbox包含概率分布和统计函数Mapping Toolbox可选如需高级地理可视化功能验证安装ver(optim) % 检查优化工具箱 ver(stats) % 检查统计工具箱1.2 VRPTW问题数学表达标准的VRPTW问题可表述为目标函数minimize Σ(α·dij) Σ(D·|tij - ej|)其中α单位距离运输成本dij车辆行驶距离D时间惩罚系数tij实际到达时间ej期望到达时间关键约束车辆载重不超过最大容量每个客户仅由一辆车服务到达时间在客户接受窗口内使用车辆数不超过车队规模1.3 数据结构设计采用元胞数组存储种群信息结构设计如下列索引数据类型示例说明1标量4使用车辆数2数组[2,3,7,6]车辆编号3数组[5,6,2,3]各车辆服务客户数4数组[1,3,15,...]客户服务顺序初始化函数框架function population InitializePopulation(popSize, truckNum, customerNum) population cell(popSize, 4); for i 1:popSize % 随机生成个体 usedTrucks randsample(truckNum, randi(truckNum)); population{i,1} length(usedTrucks); population{i,2} usedTrucks; % ...其他字段初始化 end end2. 遗传算法核心组件实现2.1 适应度函数设计适应度函数需同时考虑运输成本和时间惩罚function fitness CalculateFitness(individual, distMatrix, alpha, D, timeWindows) totalCost 0; % 计算路径距离成本 for k 1:individual{1} route GetVehicleRoute(individual, k); distCost alpha * CalculateRouteDistance(route, distMatrix); timePenalty CalculateTimePenalty(route, timeWindows, D); totalCost totalCost distCost timePenalty; end fitness 1 / (1 totalCost); % 将成本转换为适应度 end提示实际编码时应预处理距离矩阵避免重复计算2.2 选择操作实现采用轮盘赌选择法保留优质个体function newPop Selection(population, fitness) popSize size(population, 1); cumProb cumsum(fitness)/sum(fitness); newPop cell(size(population)); for i 1:popSize r rand(); idx find(cumProb r, 1); newPop(i,:) population(idx,:); end end2.3 交叉与变异策略顺序交叉(OX)实现function [child1, child2] OXcrossover(parent1, parent2) route1 parent1{4}; route2 parent2{4}; n length(route1); % 选择交叉点 points sort(randperm(n,2)); % 中间段直接继承 child1 zeros(1,n); child1(points(1):points(2)) route1(points(1):points(2)); % 填充剩余位置 ptr 1; for i 1:n if ptr points(1) ptr points(2)1; end if ~ismember(route2(i), child1) child1(ptr) route2(i); ptr ptr 1; end end % 同理生成child2... end变异操作采用交换突变function mutant SwapMutation(individual, prob) if rand() prob return; end route individual{4}; n length(route); swapPos randperm(n, 2); route(swapPos) route(swapPos([2 1])); individual{4} route; mutant individual; end3. 约束处理与可行性维护3.1 载重约束处理在初始化、交叉和变异后都需要检查载重约束function isValid CheckCapacity(individual, demands, capacities) truckRoutes SplitRoutes(individual); for k 1:individual{1} truckId individual{2}(k); if sum(demands(truckRoutes{k})) capacities(truckId) isValid false; return; end end isValid true; end3.2 时间窗约束处理计算到达时间并验证function [isValid, arrivalTimes] CheckTimeWindows(route, distMatrix, speed, timeWindows) currentTime 0; % 从仓库出发时间 arrivalTimes zeros(1, length(route)); for i 1:length(route) % 计算到达下一个节点时间 travelTime distMatrix(route(i-1), route(i)) / speed; currentTime currentTime travelTime; % 检查时间窗 if currentTime timeWindows(route(i), 2) || ... currentTime timeWindows(route(i), 1) isValid false; return; end arrivalTimes(i) currentTime; currentTime currentTime serviceTime; % 加入服务时间 end isValid true; end4. 结果可视化与性能优化4.1 路径可视化展示绘制最优路径方案function PlotSolution(solution, coordinates) figure; plot(coordinates(1,1), coordinates(1,2), rp, MarkerSize, 15); % 仓库 hold on; colors lines(solution{1}); for k 1:solution{1} route GetVehicleRoute(solution, k); plot(coordinates(route,1), coordinates(route,2), ... Color, colors(k,:), LineWidth, 2); plot(coordinates(route,1), coordinates(route,2), ... o, Color, colors(k,:)); end title(sprintf(最优路径方案 (总成本: %.2f), CalculateTotalCost(solution))); end4.2 算法参数调优建议通过实验得到的参数推荐范围参数推荐值影响分析种群规模50-200过小易早熟过大会增加计算时间交叉概率0.7-0.9主导搜索方向变异概率0.01-0.1维持种群多样性最大迭代200-500权衡收敛速度与解质量4.3 常见问题排查收敛过快增加变异概率尝试锦标赛选择代替轮盘赌检查适应度函数是否过于激进无法找到可行解放松初始种群生成条件实现修复算子处理不可行解验证约束条件是否过于严格实际项目中我们曾遇到变异概率设置过高导致算法无法收敛的情况。通过记录每代最优解的变化曲线最终将变异概率调整到0.05左右获得了最佳平衡。

相关新闻