蚁群算法求解需求可拆分车辆路径问题(SDVRP)
**作者简介:**本人擅长运筹优化建模及算法设计,包括各类车辆路径问题、生产车间调度、二三维装箱问题,熟悉CPLEX和gurobi求解器
**微信公众号:**运筹优化与学习
前言
今天给大家介绍SDVRP(split delivery vehicle routing problem,需求可拆分的车辆路径问题),同时介绍蚁群优化算法求解SDVRP。
话不多说,我们直接开始。
问题简介
传统的VRP通常假设车辆载重大于客户需求。如果车辆载重小于顾客的实际需求,就需要多辆车来服务一个顾客,由此衍生出了SDVRP。
SDVRP,即需求可拆分的车辆路径问题,是车辆路径问题的变体,它在VRP的基础之上增加了一个条件:每个顾客的需求可以拆分并分配给不同的车辆配送,而不是必须由一个车辆在一条路径中满足。
定义SDVRP在一个无向完全网络 G = ( V , E ) G=(V,E) G=(V,E),其中 V = { 0 , 1 , ⋯ , n } V=\left\{0,1,\cdots, n\right\} V={0,1,⋯,n}为所有的顶点集, E = { ( i , j ) : i , j ∈ V , i ≠ j } E=\left\{(i,j):i,j\in V, i\ne j\right\} E={(i,j):i,j∈V,i=j}为边集。节点 0 0 0表示配送中心,每个客户 i ∈ { 1 , 2 , ⋯ , n } i\in \left\{1,2,\cdots, n\right\} i∈{1,2,⋯,n}需求为 q i q_i qi,车辆最大载重为 Q Q Q。
求解思路
蚁群算法原理
(1)状态转移函数
初始状态下,每条路径上的信息素数量是相同的。同时,初始状态下,每只蚂蚁会通过随机寻找路径的方式前行,信息素释放的数量与搜索路径的目标函数值成反比。随后,搜索过程中,每只蚂蚁根据路径上残留的信息素,计算蚂蚁前往每一个节点的概率,并基于概率选择下一个访问的节点。其中,第 t t t次迭代蚂蚁 k k k从节点 i i i前往节点 j j j的概率 P i j k ( t ) P_{ij}^k(t) Pijk(t)的计算表达式如下:
表达式中, τ i j ( t ) \tau_{ij}(t) τij(t)表示第 t t t次迭代从节点 i i i前往节点 j j j残留的信息素数量, η i j ( t ) \eta_{ij}(t) ηij(t)表示节点 i i i前往节点 j j j的距离长度的倒数, J k J_k Jk表示蚂蚁 k k k还没有访问过的节点的集合。同时, a a a表示信息素因子, b b b表示启发函数因子,这两个参数为蚁群优化算法的关键参数。
(2)更新信息素
在初始状态下,每条路径的信息素数量均设置为0。在搜索过程中,部分信息素会随着时间流逝而挥发,信息素挥发快慢通过参数信息素挥发因子 c c c进行控制。信息素的更新计算表达式如下:
表达式中, Δ τ i j k \Delta \tau_{ij}^k Δτijk蚂蚁 k k k遍历过的路径总长度的倒数, τ i j ( t ) \tau_{ij}(t) τij(t)表示第 t t t次迭代从节点 i i i前往节点 j j j残留的信息素数量。
求解步骤
- 蚂蚁从配送中心(节点0)出发;
- 根据状态转移函数,选择前往的下一个节点,判断当前车辆载重是否超出;若当前节点需求量超出车辆最大载重,则进行需求拆分,同时车辆返回配送中心;
- 局部更新车辆走过路径的信息素;
- 判断车辆是否已完成所有客户配送,否则返回步骤2;
- 当车辆对所有客户配送完毕之后,计算所有车辆行驶的路径长度之和,对信息素进行整体更新
- 如果迭代次数达到最大次数要求,则算法结束,输出最短路径的总长度和最优配送路线;否则返回步骤1,继续迭代。
部分代码展示
## 主函数
def main():
bestSolution = None
vertices, edges, capacityLimit, demand, feromones, optimalValue = generateGraph() # 读取数据
for i in range(iterations):
solutions = list()
for _ in range(ants):
solution = solutionOfOneAnt(vertices.copy(), edges, capacityLimit, demand.copy(), feromones)
solutions.append((solution, rateSolution(solution, edges)))
bestSolution = updateFeromone(feromones, solutions, bestSolution)
print(str(i) + "/" + str(iterations) + ": " + str(bestSolution[1]), end='\r', flush=True)
return bestSolution
小规模算例结果展示
参考文献
[1]姜婷.求解需求可拆分车辆路径问题的人工蜂群算法[J].四川理工学院学报(自然科学版),2017,30(03):6-9.