MVRPTW

一、问题简介

MTVRPTW问题,该问题的图论描述如下: G ( N , A ) G(N,A) G(N,A)表示一个无向图, N = { 0 , 1 , ⋅ ⋅ ⋅ , n } N=\{0,1,\cdot\cdot\cdot,n\} N={0,1,,n}表示无向图的节点集合,节点0表示中心货物配送中心,是车辆出发和返回地点,要求所有的车辆从配送中心出发,最后回到配送中心,每辆车可以跑多个车程;节点 1 , ⋅ ⋅ ⋅ , n 1,···,n 1,,n表示客户节点,每个客户 i ∈ N i\in N iN有货品配送需求量 q i q_i qi,每两个节点之间有两条弧线相连, A = { ( i , j ) ∣ i , j ∈ N ; i ≠ j } A=\{(i,j)|i,j\in N;i\neq j\} A={(i,j)i,jN;i=j}表示所有弧的集合, c i j { i , j ∈ N ; i ≠ j } c_{ij}\{i,j\in N;i\neq j\} cij{i,jN;i=j}表示节点之间的配送成本,通常用两点之间的欧式距离表示,且 c i j = c j i c_{ij}=c_{ji} cij=cji,假设配送中心有 m m m辆同类型的配送车辆,每辆车的核定载重为 Q Q Q

配送中心和客户均有时间窗限制,配送中心的时间窗为 [ e 0 , l 0 ] [e_0,l_0] [e0,l0],即车辆只能在 e 0 e_0 e0之后(包含 e 0 e_0 e0)离开,且只能在 l 0 l_0 l0之前(包含 l 0 l_0 l0)返回。对于编号为 i i i的客户也有预先设定的时间窗 [ e i , l i ] [e_i,l_i] [ei,li],车辆为客户 i i i提供的时间必须在此区间内。此外客户 i i i有需求准备时间 p r e p a r e T i m e i prepareTime_i prepareTimei,即当配送中心接到客户 i i i的订单后,准备完成时间为 p r e p a r e T i m e i prepareTime_i prepareTimei,这意味着若车辆要配送客户 i i i的订单,那么只能在 p r e p a r e T i m e i prepareTime_i prepareTimei之后才能开始配送。

MTVRPTW问题是传统VRP问题的拓展,在VRP问题的基础上考虑了节点的时间窗、车辆容量以及车辆能够行驶多车程的问题,如下图所示:

image-20201011174328407

该问题的目标通常包含配送里程最小(即所有车程的里程之和最小),最小化车辆的使用数(每多使用一辆车就需要多增加一辆车的固定资产投入),最大化客户满意度(尽量满足客户的需求且在客户的时间窗范围提供服务)。

二、模型假设

(1) 仅考虑一个派单网点(即一个配送中心);

(2) 服务不可拆分,每个客户点只能由一辆车在一条回路中提供服务;

(3) 每条回路从配送中心开始,到配送中心结束;

(4) 车辆需要在客户的时间窗内提供服务;

(5) 每条回路覆盖的客户需求量不能超过车辆的运载能力;

(6) 所有客户订单信息已知,暂不考虑实时单;

(7)不考虑客户点的服务时间;

(8)车辆匀速行驶;

三、符号设定

image-20201019154942325

决策变量

image-20201011144349697

四、数学模型

目标函数:最小化总配送里程

image-20201023202208145
  • 约束(1)如果配送中心在回路 r r r上为客户 j j j提供服务,那么客户 j j j之前最多一个前置节点;
  • 约束(2)每一个客户节点仅被服务一次;
  • 约束(3)每一条回路都是单向的;
  • 约束(4)流守恒,有进必有出,进出必相等;
  • 约束(5)每一条回路上覆盖的总需求不能超过车辆的运载能力;
  • 约束(6)消除子回路;
  • 约束(7)每一条回路的车辆的出发时间必须晚于这条回路覆盖的所有客户的需求准备完成时间;
  • 约束(8)(9)时间窗约束;
  • 约束(10)(11)每一条回路必须从配送中心出发到配送中心结束;
  • 约束(12-14)回路分配约束;
  • 约束(15-18)0-1变量约束;

五、算法设计

5.1 编码设计

节点编码设计:

采用自然数编码,0表示配送中心,【1,2,······,n】表示客户点。

解的编码设计:

解是A*B的二维矩阵,其中A是车辆数 A = ∣ K ∣ A=|K| A=K

B B B=仅有一辆车时采用启发式算生成初始解时的路径点数

5.2 初始解的生成

Step1: 初始化未访问节点集 remainNode = 【1,2,······,n】;

Step2: 从未访问节点集remainNode中选择车辆在当前回路的剩余装载能力能够覆盖的节点,作为候选节点集candidateNode。若candidateNode不为空则执行Step3,否则执行Step5;

Step3: 计算当前节点的离开时刻和下一个访问节点,并将下一访问节点加入到回路中,从remainNode中删除该节点,更新当前节点、和当前车辆所在回路的承载量。

Step4: 若remainNode不为空则执行Step2,否则执行Step6;

Step5: 当前回路结束,将0点加入到当前回路中(即回到配送中心),初始化下一回路车辆承载能力,返回Step2;

Step6: 最后一条回路结束,将0点加入到回路中;

Step7: 将所有回路按照顺序循环分配给所有车辆形成初始解。

算法流程图

image-20201019165325024

c a n d i d a t e D T j = m a x ( R T j , E T j − t i j ) i = c u r r e n t N o d e , ∀ j ∈ c a n d i d a t e N o d e candidateDT_{j} = max(RT_j,ET_j-t_{ij}) \qquad i = currentNode,\forall j \in candidateNode candidateDTj=max(RTj,ETjtij)i=currentNode,jcandidateNode

**注:**当前节点的离开时刻 = min(max(候选节点需求的准备完成时刻,前一节点到达当前节点的时刻,候选节点的最早服务时间-从当前节点到候选节点的旅行时间))

c u r r e n t D T i = m a x ( A T i , m i n ( { c a n d i d a t e D T j ∣ ∀ j ∈ c a n d i d a t e N o d e } ) ) currentDT_{i} =max (AT_i, min(\{candidateDT_j|\forall j \in candidateNode\})) currentDTi=max(ATi,min({candidateDTjjcandidateNode}))

n e x t N o d e = arg ⁡ min ⁡ j c a n d i d a t e D T j , ∀ j ∈ c a n d i d a t e N o d e nextNode = \mathop{\arg\min}_{j} \quad candidateDT_{j},\quad \forall j \in candidateNode nextNode=argminjcandidateDTj,jcandidateNode

  • R T j RT_j RTj:订单 j j j的需求准备完成时间

  • A T i AT_{i} ATi:当前节点 i i i的到达时间

  • t i j t_{ij} tij:当前节点 i i i到候选节点 j j j的旅行距离

  • nextNode:下一个访问节点

**例 1:**当前有3辆车负责7个客户点的配送,经过Step1-Step5之后的所有回路为【0-1-0-2-0-3-4-0-5-0-6-0-7-0】

则循环分配给3辆车后形成的初始解为:
[ 0 1 0 5 0 0 0 0 0 0 0 0 0 0 0 2 0 6 0 0 0 0 0 0 0 0 0 0 0 3 4 0 7 0 0 0 0 0 0 0 0 0 ] \left[ \begin{matrix} 0&1&0&5&0&0&0&0&0&0&0&0&0&0\\ 0&2&0&6&0&0&0&0&0&0&0&0&0&0\\ 0&3&4&0&7&0&0&0&0&0&0&0&0&0 \end{matrix} \right] 000123004560007000000000000000000000000000
**含义:**第一辆车行驶顺序为从配送中心到客户点1再回到配送中心到客户点2最后再回到配送中心。

5.3 邻域设计

destroy函数设计

Step1: 将车辆的行驶路径按其配送成本降序排列;

Step2: 从前往后选取车辆覆盖客户点作为候选破坏点集,直到候选点个数大于等于破坏点数( d e s t r o y N u m ≥ 1 destroyNum \ge 1 destroyNum1);

Step3: 从候选点集中随机选择destroyNum个候选点作为破坏点,输出破坏后的不完整解及其破坏点集合。

同例1:

当前解为:
[ 0 1 0 5 0 0 0 0 0 0 0 0 0 0 0 2 0 6 0 0 0 0 0 0 0 0 0 0 0 3 4 0 7 0 0 0 0 0 0 0 0 0 ] \left[ \begin{matrix} 0&1&0&5&0&0&0&0&0&0&0&0&0&0\\ 0&2&0&6&0&0&0&0&0&0&0&0&0&0\\ 0&3&4&0&7&0&0&0&0&0&0&0&0&0 \end{matrix} \right] 000123004560007000000000000000000000000000
假设破坏点的个数为1,车辆的行驶路径按其配送成本降序排列后的解为
[ 0 3 4 0 7 0 0 0 0 0 0 0 0 0 0 2 0 6 0 0 0 0 0 0 0 0 0 0 0 1 0 5 0 0 0 0 0 0 0 0 0 0 ] \left[ \begin{matrix} 0&3&4&0&7&0&0&0&0&0&0&0&0&0\\ 0&2&0&6&0&0&0&0&0&0&0&0&0&0\\ 0&1&0&5&0&0&0&0&0&0&0&0&0&0 \end{matrix} \right] 000321400065700000000000000000000000000000
则候选破坏点集为【3、4、7】,从中随机选择一个点作为候选点。

假设选中的破坏点为7,则破坏后的不完整解为
[ 0 3 4 0 0 0 0 0 0 0 0 0 0 0 0 2 0 6 0 0 0 0 0 0 0 0 0 0 0 1 0 5 0 0 0 0 0 0 0 0 0 0 ] \left[ \begin{matrix} 0&3&4&0&0&0&0&0&0&0&0&0&0&0\\ 0&2&0&6&0&0&0&0&0&0&0&0&0&0\\ 0&1&0&5&0&0&0&0&0&0&0&0&0&0 \end{matrix} \right] 000321400065000000000000000000000000000000

repair函数设计

将破坏的点插入到经destroy函数处理后的不完整解中。有多种插入方法,选取其中neighborhoodSize个插入方法构成邻域。从邻域中选择总配送成本最小的解作为新解。

同上例1:将破坏点7插入到破坏后的不完整解中有多种插入方式,如下【】表示的是其有效插入位置,则破坏点716种插入方式,每一种插入方式作为邻域中的一个解。每一行其余的0位和该行最后一个【】效果等价,因此我们去除掉重复情况。
[ 0 【 】 【 】 【 】 【 】 0 0 0 0 0 0 0 0 0 0 【 】 【 】 【 】 【 】 【 】 【 】 0 0 0 0 0 0 0 0 【 】 【 】 【 】 【 】 【 】 【 】 0 0 0 0 0 0 0 ] \left[ \begin{matrix} 0&【】&【】&【】&【】&0&0&0&0&0&0&0&0&0\\ 0&【】&【】&【】&【】&【】&【】&0&0&0&0&0&0&0\\ 0&【】&【】&【】&【】&【】&【】&0&0&0&0&0&0&0 \end{matrix} \right] 00000000000000000000000000

5.4 算法总框架
image-20201018214411716

六、算例测试

参数输入:

节点数: N = 30 N = 30 N=30

车辆数量: v e h i c l e N r = 3 vehicleNr = 3 vehicleNr=3

车辆容量: Q = 12 e 6 c m 3 Q = 12e6cm^3 Q=12e6cm3

车辆行驶速度: s p e e d = 1 k m / m i n speed = 1 km/min speed=1km/min

邻域空间大小: n e i g h b o r h o o d S i z e = 50 neighborhoodSize = 50 neighborhoodSize=50

破坏率: d e s t r o y r a t i o n = 0.15 destroyration = 0.15 destroyration=0.15

初始温度: T = 100 T=100 T=100

最低温度: T f l o o r = 1 Tfloor=1 Tfloor=1

降温系数: α = 0.8 \alpha=0.8 α=0.8

每一温度下的迭代次数: i t e r C o u n t = 100 iterCount = 100 iterCount=100

==注:==配送成本 = α \alpha α总配送里程+ β \beta β总超时+ γ \gamma γ总超载量,在此次实验中选取 α = 1 \alpha=1 α=1 β = 10 \beta=10 β=10 γ = 20 \gamma=20 γ=20

算例求解结果

image-20201019201036900

结果解释

运行时间耗费41.92秒,配送成本为131;

第一辆车的运行路线:【0-6-9-2-22-18-20-19-1-15-5-4-28–13-23-17-11-8-29-12-0】;

第二辆车的运行路线:【0-10-21-16-3–25-26-24-27-14-7-0】;

第三辆车没有被使用。

image-20201019202851704
迭代过程图

七、参考文献


[1]吴球军. 带硬时间窗的外卖配送车辆路径问题研究[D].集美大学,2020.

[2]袁晓建,张岐山,吴伶,江义火.带时间窗和同时送取货的车辆路径问题模型及算法[J/OL].福州大学学报(自然科学版):1-7[2020-10-19].

[3]Binbin Pan, Zhenzhen Zhang, Andrew Lim,Multi-trip time-dependent vehicle routing problem with time windows,European Journal of Operational Research,2020,ISSN 0377-2217.

[4]Philippe Grangier, Michel Gendreau, Fabien Lehuédé, Louis-Martin Rousseau,An adaptive large neighborhood search for the two-echelon multiple-trip vehicle routing problem with satellite synchronization,European Journal of Operational Research,Volume 254, Issue 1,2016,Pages 80-91,ISSN 0377-2217.

Fabien Lehuédé, Louis-Martin Rousseau,An adaptive large neighborhood search for the two-echelon multiple-trip vehicle routing problem with satellite synchronization,European Journal of Operational Research,Volume 254, Issue 1,2016,Pages 80-91,ISSN 0377-2217.

  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值