MATLAB实现遗传算法优化VRP问题
MATLAB实现遗传算法优化VRP问题
一、问题描述
车辆路径问题(Vehicle Routing Problem, VRP)是物流配送领域的经典组合优化问题。其基本描述为:一个配送中心(仓库)拥有若干辆容量有限的车辆,需要为多个地理位置分散的客户配送货物,每个客户有特定的需求量。目标是规划出一组总行驶距离最短的车辆配送路线,同时满足以下约束条件:
- 每条路线从仓库出发,最终返回仓库
- 每个客户有且仅有一辆车为其服务
- 每条路线上的客户总需求量不超过车辆的最大载重容量
二、数学模型
2.1 参数定义
| 符号 | 含义 |
|---|---|
| V={0,1,2,...,N}V = \{0, 1, 2, ..., N\}V={0,1,2,...,N} | 节点集合,0为仓库,1~N为客户 |
| KKK | 车辆集合 |
| QQQ | 车辆最大载重容量 |
| did_idi | 客户 iii 的需求量 |
| cijc_{ij}cij | 节点 iii 到 jjj 的距离 |
| xijkx_{ijk}xijk | 0-1变量,车辆 kkk 是否从 iii 行驶到 jjj |
2.2 目标函数
min∑k∈K∑i∈V∑j∈Vcij⋅xijk\min \sum_{k \in K} \sum_{i \in V} \sum_{j \in V} c_{ij} \cdot x_{ijk}mink∈K∑i∈V∑j∈V∑cij⋅xijk
2.3 约束条件
每个客户被服务一次:
∑k∈K∑j∈Vxijk=1∀i∈V∖{0}\sum_{k \in K} \sum_{j \in V} x_{ijk} = 1 \quad \forall i \in V \setminus \{0\}k∈K∑j∈V∑xijk=1∀i∈V∖{0}
流量守恒:
∑i∈Vxijk=∑i∈Vxjik∀j∈V,∀k∈K\sum_{i \in V} x_{ijk} = \sum_{i \in V} x_{jik} \quad \forall j \in V, \forall k \in Ki∈V∑xijk=i∈V∑xjik∀j∈V,∀k∈K
容量约束:
∑i∈V∖{0}di⋅∑j∈Vxijk≤Q∀k∈K\sum_{i \in V \setminus \{0\}} d_i \cdot \sum_{j \in V} x_{ijk} \leq Q \quad \forall k \in Ki∈V∖{0}∑di⋅j∈V∑xijk≤Q∀k∈K
车辆从仓库出发:
∑j∈V∖{0}x0jk=1∀k∈K\sum_{j \in V \setminus \{0\}} x_{0jk} = 1 \quad \forall k \in Kj∈V∖{0}∑x0jk=1∀k∈K
车辆返回仓库:
∑i∈V∖{0}xi0k=1∀k∈K\sum_{i \in V \setminus \{0\}} x_{i0k} = 1 \quad \forall k \in Ki∈V∖{0}∑xi0k=1∀k∈K
三、遗传算法设计
3.1 算法流程
- 编码:采用客户排列编码,染色体为客户访问顺序的排列
- 初始化:随机生成若干个客户排列作为初始种群
- 适应度评估:按容量约束分割路线,计算总路径长度
- 选择:锦标赛选择
- 交叉:顺序交叉(Order Crossover, OX)
- 变异:交换变异
- 迭代:重复3-6直到满足终止条件
3.2 编码与解码
编码方式: 染色体长度为客户总数,每个基因位表示一个客户的编号,染色体顺序代表客户被服务的先后顺序。
解码方式: 按车辆容量约束,将客户排列依次分配给各车辆,形成多条路线。
3.3 交叉算子
采用顺序交叉(OX)算子,随机选择两个交叉点,保留父代1的中间段,其余位置按父代2的顺序填充。
3.4 变异算子
采用交换变异算子,随机选择两个位置交换其基因值。
四、MATLAB实现
4.1 主程序
%% GA-VRP: 遗传算法求解车辆路径问题
clc; clear; close all;
%% 问题参数
rng(42);
numCustomers = 20; % 客户数量
vehicleCapacity = 100; % 车辆容量
popSize = 100; % 种群大小
maxGen = 200; % 最大迭代次数
crossoverRate = 0.8; % 交叉概率
mutationRate = 0.1; % 变异概率
%% 生成测试数据
depot = [50, 50]; % 仓库坐标
customers = 100 * rand(numCustomers, 2); % 客户坐标
points = [depot; customers]; % 所有点
demands = randi([1, 15], numCustomers, 1); % 客户需求
% 距离矩阵
n = numCustomers + 1;
dist = zeros(n, n);
for i = 1:n
for j = i+1:n
d = sqrt(sum((points(i,:) - points(j,:)).^2));
dist(i,j) = d; dist(j,i) = d;
end
end
%% 初始化种群
pop = zeros(popSize, numCustomers);
for i = 1:popSize
pop(i,:) = randperm(numCustomers);
end
%% 主循环
bestFitness = inf;
bestRoute = [];
bestHistory = zeros(1, maxGen);
for gen = 1:maxGen
% 计算适应度
fitness = zeros(popSize, 1);
for i = 1:popSize
fitness(i) = evaluateVRP(pop(i,:), demands, dist, vehicleCapacity);
end
% 记录最优
[minFit, idx] = min(fitness);
if minFit < bestFitness
bestFitness = minFit;
bestRoute = pop(idx,:);
end
bestHistory(gen) = bestFitness;
% 锦标赛选择
newPop = zeros(popSize, numCustomers);
for i = 1:popSize
candidates = randi(popSize, 1, 3);
[~, bestIdx] = min(fitness(candidates));
newPop(i,:) = pop(candidates(bestIdx),:);
end
% 顺序交叉
for i = 1:2:popSize-1
if rand < crossoverRate
child1 = crossoverOX(newPop(i,:), newPop(i+1,:));
child2 = crossoverOX(newPop(i+1,:), newPop(i,:));
newPop(i,:) = child1;
newPop(i+1,:) = child2;
end
end
% 交换变异
for i = 1:popSize
if rand < mutationRate
idx1 = randi(numCustomers);
idx2 = randi(numCustomers);
newPop(i, [idx1, idx2]) = newPop(i, [idx2, idx1]);
end
end
pop = newPop;
if mod(gen, 20) == 0
fprintf('迭代 %d/%d: 最优路径长度 = %.2f\n', gen, maxGen, bestFitness);
end
end
fprintf('\n===== 最终结果 =====\n');
fprintf('最优总路径长度: %.2f\n', bestFitness);
4.2 适应度评估函数
function [totalDist] = evaluateVRP(route, demands, dist, capacity)
% 评估染色体适应度(按容量约束分割路线)
[~, segmentsDist] = decodeVRP(route, demands, dist, capacity);
totalDist = sum(segmentsDist);
end
4.3 解码函数
function [routeDistList, routeDists] = decodeVRP(route, demands, dist, capacity)
% 按容量约束将染色体解码为车辆路线
segments = {};
distList = [];
currentRoute = [];
currentLoad = 0;
for i = 1:length(route)
customerIdx = route(i);
demand = demands(customerIdx);
if currentLoad + demand <= capacity
currentRoute = [currentRoute, customerIdx];
currentLoad = currentLoad + demand;
else
% 保存当前路线
d = calcRouteDist(currentRoute, dist);
segments{end+1} = currentRoute;
distList = [distList, d];
% 开始新路线
currentRoute = [customerIdx];
currentLoad = demand;
end
end
% 最后一条路线
if ~isempty(currentRoute)
d = calcRouteDist(currentRoute, dist);
segments{end+1} = currentRoute;
distList = [distList, d];
end
routeDistList = segments;
routeDists = distList;
end
function d = calcRouteDist(route, dist)
% 计算一条路线的总距离
if isempty(route)
d = 0; return;
end
d = dist(1, route(1)+1); % 仓库到第一个客户
for j = 1:length(route)-1
d = d + dist(route(j)+1, route(j+1)+1);
end
d = d + dist(route(end)+1, 1); % 最后一个客户回仓库
end
4.4 顺序交叉函数
function child = crossoverOX(parent1, parent2)
% 顺序交叉(Order Crossover)
n = length(parent1);
cut1 = randi(n-1);
cut2 = randi([cut1+1, n]);
child = zeros(1, n);
child(cut1:cut2) = parent1(cut1:cut2);
rest = setdiff(parent2, parent1(cut1:cut2), 'stable');
pos = 1;
for j = 1:n
if j < cut1 || j > cut2
child(j) = rest(pos);
pos = pos + 1;
end
end
end
五、运行结果
5.1 控制台输出
迭代 20/200: 最优路径长度 = 528.92
迭代 40/200: 最优路径长度 = 449.07
迭代 60/200: 最优路径长度 = 435.45
迭代 80/200: 最优路径长度 = 435.45
...
迭代 200/200: 最优路径长度 = 435.45
===== 最终结果 =====
最优总路径长度: 435.45
使用的车辆数: 2
车辆1: 路线 [0 -> 19 -> 6 -> 16 -> 14 -> 15 -> 11 -> 5 -> 7 -> 17 -> 20 -> 1 -> 9 -> 0] 长度=253.38
车辆2: 路线 [0 -> 4 -> 3 -> 18 -> 10 -> 13 -> 2 -> 12 -> 8 -> 0] 长度=182.07
5.2 迭代收敛曲线

图1:GA-VRP迭代收敛曲线
5.3 最优路径图

图2:GA-VRP最优路径示意图(20客户示例,2辆车)
六、结果分析
从运行结果可以看出:
- 收敛性:算法在前40代快速收敛,从528.92下降至449.07,之后逐步收敛至435.45
- 车辆使用:20个客户共使用2辆车,总需求154,两辆车分别承担需求74和80
- 路径效率:两辆车行驶距离分别为253.38和182.07,里程平衡性较好
七、参数设置建议
| 参数 | 建议范围 | 说明 |
|---|---|---|
| 种群大小 | 50~200 | 太小易早熟,太大计算慢 |
| 最大迭代次数 | 200~500 | 根据问题规模调整 |
| 交叉概率 | 0.6~0.9 | 控制搜索与开发的平衡 |
| 变异概率 | 0.05~0.2 | 维持种群多样性 |
| 锦标赛规模 | 2~5 | 控制选择压力 |
八、算法特点与改进方向
优点
- 全局搜索能力强:能有效避免陷入局部最优
- 并行性:种群搜索天然适合并行化
- 适应性强:可处理各种约束条件
缺点
- 局部搜索能力弱:需要结合局部搜索算子
- 参数敏感:性能依赖参数调优
- 编码复杂性:约束条件增加了编码难度
改进方向
- 混合遗传算法:结合2-opt局部搜索
- 自适应参数:动态调整交叉和变异概率
- 精英保留策略:保留历代最优解
九、总结
本文详细介绍了使用遗传算法求解车辆路径问题(VRP)的MATLAB实现。通过合理的编码设计、选择、交叉和变异算子,算法能够高效地找到高质量的配送路线方案。该算法可广泛应用于物流配送、快递调度、校车路线等实际问题。
参考资料
- Dantzig G, Ramser J. The Truck Dispatching Problem. Management Science, 1959.
- 《MATLAB智能算法30个案例分析》
本文完整代码可直接运行,如有问题欢迎交流!
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)