Hello,大家好,今天为大家讲解使用模拟退火(SA)算法求解容量受限的车辆路径(CVRP)问题,其实算法的设计思路与模拟退火(SA)算法求解旅行商(TSP)问题这篇推文的设计思路差不多。
一 | 容量受限的车辆路径(CVRP)问题
01 | 问题描述
现有若干个有需求的顾客,每个顾客的坐标、需求量以及配送中心的坐标已知,现在需要设计配送路线在满足所有顾客需求的前提下,使总成本最小。
02 | 数学模型
目标函数(1)表示最小化车辆行驶总距离;
表示顾客集合,约束(2)限制每个顾客只能被分配到一条路径;
约束(3)~(5)表示车辆k在路径上的流量限制;
约束(6)表示载重量约束。
二 | 算法设计
01 | 编码
编码采用遗传算法(GA)求解VRPTW问题(附MATLAB代码)这篇推文中的编码方式。
比如说有5个顾客,最多使用3辆车,那么一个可行解可表达为1263475,那么这个1263475究竟代表什么意思呢?
其中1263475中的6和7代表配送中心,6和7将顾客12345划分为3段,即划分为3条路径。
(0代表配送中心)
第1条路径为0-1-2-0
第2条路径为0-3-4-0
第3条路径为0-5-0
如果染色体表达为1236745,那么这个染色体表示2条配送路径。
(0代表配送中心)
第1条路径为0-1-2-3-0
第2条路径为0-4-5-0
可以看出当顾客数目为N且最大车辆使用数目为K时,染色体长度为N+K-1,染色体表达形式为(1,2,3,……,N,N+1,N+2,……,N+K-1)
02 | 邻域结构
邻域结构采用模拟退火(SA)算法求解旅行商(TSP)问题这篇推文的三种邻域结构。
(1)交换结构
比如当前解为123456,我们随机选择两个位置,然后将这两个位置上的元素进行交换。
比如说,交换2和5两个位置上的元素,则交换后的解为153426。
(2)逆转结构
比如当前解为123456,我们随机选择两个位置,然后将这两个位置之间的元素进行逆序排列。
比如说,逆转2和5之间的所有元素,则逆转后的解为154326。
(3)插入结构
比如当前解为123456,我们随机选择两个位置,然后将这第一个位置上的元素插入到第二个元素后面。
比如说,第一个选择2这个位置,第二个选择5这个位置,则插入后的解为134526。
在搜索过程中,我们将以上三种邻域结构赋予不同的权重,然后采用轮盘赌的方式选择究竟使用哪个邻域结构。
03 | 接受准则
模拟退火算法的核心思想就是以一定概率接受比当前解更差的解,那么这个概率究竟如何计算呢?
比如说当前解用Scurr表示,当前解Scurr的某个邻域产生的一个新解用Snew表示。用f(Scurr)表示当前解的总行驶距离,f(Snew)表示新解的总行驶距离。我用下面这个伪代码表示接受准则。这里需要注意的是T表示当前温度,因为在外层循环中每迭代一次后,温度T都会降低,即温度T需要乘一个小于1的冷却因子来降低温度,这就体现了“退火”的思想。
if f(Snew)<=f(Scurr)
Scurr=Snew;
else
delta=(f(Snew)-f(Scurr))/f(Scurr);
p=exp(-T/delta);
if rand<=p
Scurr=Snew;
end
end
代码会在下期进行更新。
知乎 | bilibili:随心390
长按识别二维码关注我们