You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在OR-Tools VRP中实现乘客最大乘车时间软约束?

解决OR-Tools VRP中统一目的地的乘客乘车时长软约束问题

针对你提出的统一目的地VRP场景(如校车接送),以及乘车时长≤MaxRideTime的软约束需求,结合OR-Tools的特性,给出以下解决方案:

问题解答

  1. 相关建模经验
    该场景属于统一目的地VRP(UD-VRP),是VRP的常见变体,核心约束是控制乘客从接载到抵达终点的时长。这类需求通常通过累积时间维度+自定义约束/惩罚项来实现,在通勤接送、物流配送(统一配送中心)等场景广泛应用。

  2. 能否直接为(终点值-接载值)添加软惩罚
    OR-Tools Routing API本身不支持直接对两个累积变量的差值设置软约束,但可以通过底层CP-SAT约束+目标函数惩罚项间接实现:直接引用Duration维度的累积变量(接载时间和终点到达时间),构建差值约束,将违规部分转化为惩罚加入目标函数。

  3. 是否需要big-M约束
    不需要。因为可以直接通过RoutingModel获取每个节点的累积时间变量(CumulVar),这些变量本身是线性的,差值约束可以直接用CP-SAT的线性不等式表达,无需引入big-M辅助变量。

  4. 更优方法推荐
    推荐两种高效实现方式,优先选择方案一:

    • 方案一:基于现有Duration维度添加软约束惩罚
      利用已有的Duration维度,为每个乘客节点添加软约束:车辆到达终点的时间 - 乘客接载时间 ≤ MaxRideTime,违规则按单位时长施加惩罚。这种方式无需新增维度,代码改动最小。
    • 方案二:自定义追踪乘车时长的维度
      创建一个自定义维度,在乘客节点处记录当前时间,在终点处计算与该时间的差值,设置软上限。这种方式更直观,但需要额外的维度配置。

代码修改示例(方案一)

在现有代码中,添加软约束的部分(建议放在添加完Duration维度之后):

# 定义乘车时长上限和惩罚系数
MAX_RIDE_TIME = 60 * 60  # 60分钟,单位秒
RIDE_TIME_PENALTY = 100  # 每超1秒的惩罚值

# 获取Duration维度
duration_dim = routing.GetDimensionOrDie('Duration')

# 遍历所有乘客节点(假设data['pickup_nodes']是乘客节点列表,需根据你的数据模型调整)
for pickup_node in data['pickup_nodes']:
    pickup_index = manager.NodeToIndex(pickup_node)
    # 遍历所有车辆,为每个车辆的终点添加约束(因为每个车辆对应一个终点)
    for vehicle_idx in range(data['num_vehicles']):
        end_node = data['ends'][vehicle_idx]
        end_index = manager.NodeToIndex(end_node)
        
        # 获取接载时间和终点到达时间的累积变量
        pickup_time_var = duration_dim.CumulVar(pickup_index)
        end_time_var = duration_dim.CumulVar(end_index)
        
        # 构建约束:end_time_var - pickup_time_var <= MAX_RIDE_TIME + slack_var
        # 其中slack_var >=0,惩罚项为RIDE_TIME_PENALTY * slack_var
        slack_var = routing.solver().IntVar(0, routing.solver().infinity(), f"slack_{pickup_node}_{vehicle_idx}")
        routing.solver().Add(end_time_var - pickup_time_var <= MAX_RIDE_TIME + slack_var)
        
        # 将惩罚项加入目标函数
        routing.AddCost(RIDE_TIME_PENALTY * slack_var)

注意事项

  • 需确保data['pickup_nodes']正确包含所有乘客节点的ID,根据你的_create_data_model逻辑调整。
  • 惩罚系数RIDE_TIME_PENALTY需要根据实际业务调整:如果希望优先满足乘车时长约束,设置较大的惩罚值(比如远大于路径成本的单位权重);如果允许少量违规,设置较小值。
  • 若车辆的终点是同一个节点(比如所有车都送同一个学校),可以简化为只针对该终点节点处理,无需遍历所有车辆。

额外优化建议

  • 如果乘客节点数量较多,为避免约束过多影响求解速度,可以将惩罚项调整为分段惩罚:比如超过MaxRideTime的前10分钟惩罚系数低,超过部分惩罚系数高,平衡求解效率和约束优先级。
  • 可以结合routing.AddDisjunction为乘客节点设置可选性(如果允许部分乘客不被接载),但需配合相应的惩罚。

内容的提问来源于stack exchange,提问作者Harshaadhithya Kalaikumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 10:54:53