干货 | 列生成VRPTW子问题ESPPRC( Elementary shortest path problem with resource constraints)介绍附C++代码...

本文介绍了Elementary shortest path problem with resource constraints(ESPPRC),即资源约束下的最短路径问题,常用于解决如车辆路径问题的子问题。ESPPRC与SPPRC的区别在于不允许节点被重复访问。文章讨论了ESPPRC在column generation框架中的应用,解释了如何根据Master Problem的对偶变量更新边的成本以求解reduced cost最小的路径,并概述了动态规划、拉格朗日松弛、约束编程和启发式算法等常见求解方法。此外,文章重点介绍了Pulse算法,这是一种精确的ESPPRC算法,结合了bound算法和脉冲搜索过程来寻找满足资源约束的最短路径。
摘要由CSDN通过智能技术生成

00 前言

各位小伙伴大家好,相信大家已经看过前面column generation求解vehicle routing problems的过程详解。该问题中,子问题主要是找到一条reduced cost最小的合法路径,然后加入到Master Problem中。其实,子问题也是一个著名的NP-Hard问题,今天我们就来介绍一下。

01 ESPPRC

考虑图1.1中描述的网络。 除了每条边的成本c_ij之外,还存在经过边(i,j)的所消耗的资源t_ij,比如时间。 我们的目标是找到从开始节点到结束节点的最短路径,每个节点只能访问一次,同时使得资源消耗满足可用的资源约束,比如全程不能超过多少时间。[1]

1240

当然上面描述问题只是ESPPRC中的一个例子,实际的资源约束可能有很多种,比如在VRPTW的子问题中:[2]

1240

起始节点和结束节点一样,每个节点有固定的时间窗和固定的需求。车辆不能超过容量约束的要求等等。

ESPPRC

以下是用Python实现标签算法求解VRPTW问题代码,其中采用深度优先搜索的方式: ```python import numpy as np # 车辆容量 CAPACITY = 100 # 客户点信息(坐标、需求量、时间窗口) CUSTOMER_POINTS = np.array([ [40, 50, 0, 0, 8], [45, 68, 10, 12, 10], [60, 70, 20, 25, 12], [70, 40, 20, 30, 15], [66, 20, 30, 40, 20], [30, 30, 35, 50, 5], [35, 20, 40, 45, 3], [20, 25, 45, 50, 5], [50, 25, 50, 55, 8], [55, 45, 60, 70, 10] ]) # 标签结构定义:(到达时间, 已服务客户, 车辆位置) LABEL_TUPLE = (int, list, int) def label_extend(current_state, current_label): """ 标签扩展函数,根据当前状态和标签信息,生成所有可能的下一状态,并计算其对应的标签信息 :param current_state: 当前状态,即当前已服务的客户点 :param current_label: 当前标签信息,即当前状态对应的标签信息 :return: 下一状态和对应的标签信息 """ current_time, served_customers, current_position = current_label next_states = [] for i in range(len(CUSTOMER_POINTS)): if i not in served_customers and CAPACITY >= CUSTOMER_POINTS[i][3]: # 计算到达下一客户点的时间 distance = np.sqrt((CUSTOMER_POINTS[i][0] - CUSTOMER_POINTS[current_state][0]) ** 2 + (CUSTOMER_POINTS[i][1] - CUSTOMER_POINTS[current_state][1]) ** 2) arrival_time = current_time + distance if arrival_time <= CUSTOMER_POINTS[i][4]: # 状态扩展 next_state = i next_served_customers = served_customers.copy() next_served_customers.append(i) next_position = i next_label = (arrival_time, next_served_customers, next_position) next_states.append((next_state, next_label)) return next_states def heuristic_function(state, label): """ 启发函数,评估当前状态的优劣程度 :param state: 当前状态 :param label: 当前标签信息 :return: 启发函数值 """ return label[0] def dfs_search(): """ 标签算法主函数,按照深度优先的方式搜索状态空间,直到找到满足所有约束条件的解 :return: 找到的解 """ # 初始化搜索树 root_state = 0 root_label = (0, [0], 0) search_tree = {root_state: [root_label]} # 深度优先搜索 best_label = None stack = [(root_state, root_label)] while stack: current_state, current_label = stack.pop() if len(current_label[1]) == len(CUSTOMER_POINTS): # 找到解 if best_label is None or heuristic_function(current_state, current_label) < heuristic_function(best_label[0], best_label[1]): best_label = (current_state, current_label) else: # 扩展状态,并加入搜索树 next_states = label_extend(current_state, current_label) for next_state, next_label in next_states: if next_state not in search_tree: search_tree[next_state] = [next_label] stack.append((next_state, next_label)) else: if heuristic_function(next_state, next_label) < heuristic_function(next_state, search_tree[next_state][-1]): search_tree[next_state].append(next_label) stack.append((next_state, next_label)) return best_label if __name__ == '__main__': best_label = dfs_search() print('找到的最优解:', best_label) ``` 这个代码实现了深度优先搜索,可以根据需要进行修改以实现广度优先搜索或其他搜索算法。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值