基于 MATLAB 通过遗传算法实现车辆路径优化问题(CVRP)求解(附代码链接)

基于 MATLAB 通过遗传算法实现车辆路径优化问题(CVRP)求解

2024 年 5 月我的实验课作业要求使用遗传算法解决任意的交通领域实践问题。我用 MATLAB 自己写了一个遗传算法求解器,对 CVRP 问题进行了求解,这里把代码分享给大家。

CVRP 问题,即包含容量限制的车辆路径优化问题(Capacity Vehicle Routing Problem),是物流和运输领域中的一个经典优化问题。其目标是确定一组车辆从一个配送中心出发,访问一系列客户节点并返回配送中心的 最优路径方案。该问题的目的是在满足所有客户需求和车辆运载能力限制的同时,最小化总行驶距离或总成本。该问题可以被认为是 TSP 问题的一种变体,即增加了车辆容量限制的 TSP 问题。TSP 问题也可以被理解为无容量限制的 VRP 问题,即一辆车走完全局最短路即可满足所有节点的需求。

我在写这个求解器的时候我尽量去做了很多的适配,比如让这个求解器能够适配尽可能多的 CVRP 问题,以及让代码注释尽可能详细,以便大家能够在我写的代码基础上自行开展学习等等。原本就想着等我把这个作业写完之后就把内容发到博客里面来的,但写完之后发现代码文件太多太长了,没有办法直接插入到博客里面来。博客园没有云存储,CSDN 又要充米恰金豆,所以只好上传到 Gitee 平台上了。

项目地址是这个 User1396529 / GA CVRP Optimize - 基于 MATLAB 通过遗传算法实现车辆路径优化问题求解,点击链接进行访问。

如果您还不知道如何从 Gitee 上面下载代码,请查看这篇文章:没有 Git,如何下载 Gitee 代码?


2024 年 5 月 24 日更新: 发现了代码中轮盘赌部分的一个小问题,进行了改进。现在的效率比原来更高,取得最小化函数值 732.00


示例代码及算例

算例生成

算例来自于 MATLAB 官网文章 Capacitated Vehicle Routing Problem,坐标点及各个顾客的需求量根据原文中的方法随机生成。算例可视化如下图所示,详情请参照原文。

Capacitated vehicle routing is a combination of a knapsack problem and a traveling salesperson problem. The problem is for a vehicle (or set of vehicles) to visit a group of customers that are geographically distributed. The vehicle has a capacity constraint, where the capacity refers to a quantity that the vehicle delivers to each customer. The problem has a central depot, and the vehicle must return to the depot after each visit to a set of customers, or route. The problem is to visit the customers at minimal cost, where the cost is the total length of the route for visiting a group of customers.

The following figure shows four routes originating from a single point, the depot. These routes do not represent a minimal solution, because nodes 2 and 3 (at least) should be visited in the opposite order. The route containing nodes 2 and 3 has a self-intersection, which does not occur in an optimal tour.

下面的代码可以生成算例:

% Capacitated Vehicle Routing Problem
rng(1) % For reproducibility
numCustomers = 24; % Depot at [0 0] makes 25 locations
depot = [0 0]; % Depot at the origin
loc = [depot; randi([-50, 50],numCustomers,2)]; 
% Integers from -50 to 50, 24-by-2
demands = 100*randi([1, 25],numCustomers,1);
capacity = 6000;

算例可视化

同样是官网提供的代码,用下面的代码可以对算例进行可视化:

% Plot the locations with demands overlaid
% figure;
scatter(loc(:,1),loc(:,2),'filled','SizeData',25);
text(loc(:,1),loc(:,2),["Depot"; num2str((1:numCustomers)')]);
title("Customer Locations and Demands");
hold off;

如下图所示:

image

算法使用顾客与仓库之间的 OD 矩阵,而不是真实坐标进行运算,保障了算法的兼容性和可拓展性。

取得 OD 矩阵,可以使用如下的代码:

% 生成 OD 矩阵
% OD_mat = squareform(pdist(loc));

% 鉴于一些人的电脑里可能没有统计与机器学习工具箱,pdist 函数有可能无法使用
% 下面的代码也可以获取原问题的 OD 矩阵
OD_mat = zeros(numCustomers, numCustomers);
for i = 1:numCustomers+1
    for j = 1:numCustomers+1
        OD_mat(i, j) = sqrt(sum((loc(i, :) - loc(j, :)).^2));
    end
end

算法设计简述

基因编码设计: 基因编码设计参考了博客 用遗传算法解决VRP问题,其基本逻辑为:首先随机生成所有顾客节点编号的随机排列,再在其中插入数量相当于运载工具数量减去 1 数量的 0,即,设此时共有 K K K 辆车,则插入的 0 元素数量为 K − 1 K - 1 K1。每一段用 0 分割的节点序列即代表一辆车的访问节点次序。

如:设此时存在基因编码方案 2 3 9 0 7 6 4 0 1 8 5,代表第一辆车访问节点的顺序是 2、3、9,第二辆车访问的节点是 7、6、4,第三辆车访问的节点是 1、8、5。详情参见原文所述。

约束处理: 算法强调并实现了如下的模型约束:

  • 每个客户节点必须被访问一次。
  • 每辆车从配送中心出发并返回配送中心。
  • 每辆车的总负载不能超过其最大载重量。

适应度函数取值: 取总路程倒数为适应度函数值。对于超出模型约束(车辆数量约束和总载重量限制约束)的个体,强制令其适应度函数值为 0。

交叉和变异方法: 使用单点交叉和单点变异的方法。对于交叉、变异后产生不符合模型约束的非法个体的情形,不予交叉变异。 该策略通过在交叉、变异前提前对交叉编译产生的个体进行检验并根据检验结果进行判断来实现。

精英策略: 算法保存历次迭代中取得的最优适应度个体,并在未来次数迭代中使用该个体替换种群中适应度最低的个体,避免种群劣化。

对于代码里的详细的信息内容,请自行下载代码查看。

算法迭代过程

设置迭代次数为 1000 次,种群大小为 50000。由于交叉变异过程受到模型约束的限制,为了保障实际的交叉变异发生率,应当适当增加交叉变异概率。这里取得交叉变异概率分别为 P c = 0.9 , P m = 0.09 P_c = 0.9, P_m = 0.09 Pc=0.9,Pm=0.09

求解器的使用是很容易的。使用 help GA_CVRP_optimize 命令可以查看求解器的使用方法。这些代码注释我已经写得非常详细了。(真的很详细!)

>> help GA_CVRP_optimize
  GA_CVRP_optimize 针对 CVRP 问题的遗传算法求解器
     此 MATLAB 函数利用遗传算法优化解决 CVRP 问题,支持动态图实时显示迭代过程的全
     局最优解搜索下降进度,会在命令行窗口输出提示信息。
  
     [bestIndividual, minCost] = GA_CVRP_optimize( ...
              OD_mat, numVehicles, demands, capacity, ...
              popSize, maxIter, pc, pm)
  
     [bestIndividual, minCost, iterPop, fitnessValues] ...
         = GA_CVRP_optimize( ...
              OD_mat, numVehicles, demands, capacity, ...
              popSize, maxIter, pc, pm, ...
              dynamic_plot ...
      )
 
     注意事项
         1. 为了简化问题的建模,采用整型数据编码的形式。
         2. 算法采用了精英策略,保存、记录和返回历代中的最精英个体及其适应度。
         3. 交叉、变异过程采用了带约束的交叉编译过程,如果交叉变异产生的新的个体
            无法满足模型约束的要求,交叉、变异将不会发生。
         4. 无法确保找到全局最优解。
  
     输入参数
         OD_mat - 所有节点之间的 OD 矩阵。此处要求 OD 矩阵中的第一个节点是 CVRP 
             问题的配送中心节点,即 Depot 节点。
         numVehicles - CVRP 问题中运载工具的数量
         demands - CVRP 问题中各个顾客节点的需求量的一维向量
         capacity - CVRP 问题中运载工具的容量限制
         popSize - 遗传算法的种群大小
         maxIter - 最大迭代次数限制
         pc - 交叉概率
         pm - 变异概率
         dynamic_plot - 一个 Bool 值,表示是否弹窗并动态绘制模型求解的下降过程
  
     输出参数
         bestIndividual - 遗传算法迭代产生的最优精英个体
         minCost - 遗传算法优化的结果,即 CVRP 问题中汽车最终行驶的总里程数
         iterPop - 最终次迭代的种群

求解器支持在算法迭代过程中实时动态绘制下降过程,绘制效果如下图所示。

image

输出结果

算法的输出结果如下图所示,图中使用不同的颜色标记了不同车辆的访问路径。取得极小化路径长度为 732.00。

image

总结

代码是根据自己的理解写的,可能有诸多不成熟、不严谨的地方。如果您对于代码有任何的改进建议,欢迎您提交 Pull Request 和 Issue。您的建议对我来说很重要。

  • 26
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Python遗传算法可以用来解决车辆路径问题(CVRP问题)。 首先,我们需要定义遗传算法的基本元素:个体(染色体)、适应度函数、选择操作、交叉操作和突变操作。 在CVRP问题中,每个个体可以表示为一组路径,每个路径表示一个车辆的路线。路径中包含从起点到终点的一系列节点(顾客),节点之间的顺序决定了车辆的路线。 适应度函数根据个体的路径评估其性能。在CVRP问题中,适应度函数可以使用总路程或总成本作为评估指标,目标是使这些指标最小化。 选择操作使用适应度函数来选择优秀的个体作为父代,以便将它们的基因传递给下一代。 交叉操作从两个父代个体中选择每个路径的子集,并将它们组合成一个子代个体。这样可以保留父代个体中优良的路径。 突变操作通过随机地改变染色体的一小部分来引入种群的多样性。在CVRP问题中,可以通过随机重排或插入节点来进行染色体的突变。 使用上述操作,我们可以编写Python代码实现遗传算法求解CVRP问题。通过初始化种群,迭代选择、交叉和突变操作,直到找到满足停止准则的解。 总的来说,Python遗传算法是一种有效的求解CVRP问题的方法,可以通过定义合适的个体表示和适应度函数来解决这个问题。通过调整遗传算法的参数,我们可以获得更好的解,并且可以应用于更大规模的实例。 ### 回答2: Python遗传算法是一种基于生物进化原理的优化算法。对于cvrp(车辆路径规划)问题,可以通过遗传算法求解。 cvrp问题是指在一辆或多辆车辆的情况下,如何优化配送路线以使成本最小化或效率最大化。遗传算法的基本思想是通过模拟自然进化过程中的选择、交叉和变异来生成和改进可行解。 首先,需要定义适应度函数来评估每个个体(路线规划解)的质量。适应度函数可以根据成本、距离、时间等指标来度量每个个体的优劣性。然后,生成初始种群,每个个体代表一个可能的解决方案,其中包含车辆路径和顺序。 接下来,采用选择运算,根据适应度函数的值对个体进行评估和排序,选取一部分优秀的个体作为下一代的父代。 然后,进行交叉运算,通过将两个父代个体的染色体进行交叉、重组,生成新的子代个体。交叉运算的目的是充分利用父代个体的优点,生成更好的后代。 最后,进行变异运算,以一定的概率对子代个体进行基因的变异,引入多样性,使得解空间更丰富。变异可以通过交换节点、删除或添加节点等操作进行。 通过多次迭代,逐渐优化种群中个体的适应度,最终得到一个或多个较优的解决方案。 在Python中,可以通过使用遗传算法相关的库来实现cvrp问题求解,如DEAP、Pyevolve等。 总而言之,Python遗传算法能够应用于cvrp问题求解,通过适应度函数、选择、交叉和变异等运算,逐步改进种群中的个体,找到优化路径规划解决方案。 ### 回答3: Python遗传算法可以用来解决车辆路径问题(CVRP),这是一种组合优化问题。CVRP是指在给定一组配送点和一组车辆的情况下,如何将这些配送点分配给车辆并确定车辆的行驶路线,以便最小化总行驶距离或总配送成本。 遗传算法(Genetic Algorithm)是一种模拟生物进化过程的算法,通过模拟进化的过程,不断优化问题的解。在解决CVRP问题时,可以将每个车辆路径表示为染色体。染色体上的基因代表配送点的顺序。遗传算法通过交叉、变异等操作,在不断迭代的过程中,逐渐优化车辆路径。 具体来说,可以使用以下步骤来解决CVRP问题: 1. 初始化种群:随机生成一组初始染色体,每个染色体表示一辆车的路径。 2. 评估适应度:计算每个染色体的适应度,即该路径的总行驶距离或总配送成本。 3. 选择操作:根据染色体的适应度,选择部分染色体作为父代。 4. 交叉操作:从父代中选择两个染色体,进行交叉操作生成新的子代。 5. 变异操作:对子代进行变异操作,引入新的基因。 6. 替换操作:用新的子代替换掉部分父代染色体。 7. 迭代操作:重复进行2-6步骤,直到达到迭代次数或满足终止条件。 8. 输出结果:返回最优的染色体作为求解的最优解,即最优的车辆路径。 通过不断迭代,遗传算法能够逐渐优化车辆路径,寻找到更优的解决方案。Python遗传算法库(如DEAP)提供了丰富的工具和函数,方便实现和调试遗传算法求解CVRP问题

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值