如何在OR-Tools的VRPTW中为行程时间添加上下限约束?
在OR-Tools中为VRPTW添加路径节点时间差约束
要实现路径中每个节点i与其后续节点j的时间差满足 lb ≤ Time(j) - Time(i) ≤ ub 的约束,核心是利用OR-Tools中**边激活变量(ActiveVar)**关联时间变量(CumulVar),具体步骤如下:
1. 获取核心变量
首先从已初始化的VRPTW模型中获取时间维度的累计变量(即每个节点的到达时间),以及每条边的激活状态变量:
# 假设已完成manager和routing的初始化,并添加了Time维度 time_dimension = routing.GetDimensionOrDie('Time') time_var = time_dimension.CumulVar # time_var[i] 表示到达节点i的时间
2. 遍历所有边添加约束
遍历所有可能的节点对(i,j),仅当边i->j被激活(即j是i的后续节点)时,强制执行时间差的上下限约束:
# 示例:全局时间差上下限,可根据实际需求替换为边-specific的lb_ij/ub_ij lb = 5 ub = 20 for i in range(manager.GetNumberOfNodes()): for j in range(manager.GetNumberOfNodes()): if i == j: continue # 跳过节点自身 # 获取边i->j的激活变量(布尔值,1表示该边被使用) active_edge = routing.ActiveVar(i, j) if active_edge is None: continue # 跳过被禁用的边 # 添加时间差上限约束:Time(j) - Time(i) ≤ ub model.Add(time_var[j] - time_var[i] <= ub).OnlyEnforceIf(active_edge) # 添加时间差下限约束:Time(j) - Time(i) ≥ lb model.Add(time_var[j] - time_var[i] >= lb).OnlyEnforceIf(active_edge)
关键说明
- 为什么不用NextVar?:NextVar(i)是整数变量,存储i的下一个节点索引,若直接用它需要针对每个j做
NextVar(i) == j的条件判断,而ActiveVar(i,j)是直接对应边激活状态的布尔变量,使用起来更直观简洁,也更适合这类边级别的约束。 - 边-specific的上下限:如果不同的i->j边需要不同的lb和ub,只需将代码中的
lb和ub替换为对应的lb_ij和ub_ij(例如从预定义的时间差矩阵中取值)即可。 - 与VRPTW时间窗的兼容性:该约束和VRPTW原生的节点时间窗约束(
Time(i) ∈ [start_time[i], end_time[i]])是互补关系,只要参数设置合理,不会产生冲突。
内容的提问来源于stack exchange,提问作者htam_ujn
相关产品推荐
相关产品推荐

