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

OR-Tools实现多车场VRP仅小规模案例可解的问题咨询

问题根因

这不是OR-Tools求解器的能力限制,完全是实现逻辑存在多处错误。OR-Tools原生可支持单模型数千配送点的VRP求解,15个配送点的规模远未到性能瓶颈。

现有实现的核心错误有4个:

  • INF值设置过大导致整数溢出:你将INF设为1e15,远超OR-Tools内部64位整数计算的安全阈值,求解过程中成本累加时极易触发溢出,得到错误的成本值,直接破坏搜索逻辑。OR-Tools场景下INF只需设置为比全局最大可行路径总成本高1个数量级即可,常规配送场景设为1e9完全足够。
  • 析取约束完全写错:
    1. 索引计算逻辑错误,将start节点、end节点混在同一个析取组内,求解器可能选中end节点作为路径起点,直接产生无效路径;
    2. 析取约束未按车辆维度分组,无法保证“单车辆仅选择一个仓库出发”的逻辑;
    3. 析取未设置INF级别的惩罚值,求解器可以直接跳过所有start节点;
    4. 多余给end节点加析取,OR-Tools原生会强制每条路径最终走到对应End节点,完全不需要额外加析取约束。
  • 未强制配送点必须访问:OR-Tools Routing模型中,除了预设的depot节点外,其余节点默认是可选访问的,你没有给配送节点加必访问约束,小规模场景下节点少,求解器碰巧能覆盖所有点,规模上涨后搜索空间指数级扩大,求解器会直接跳过无法插入的配送点,再叠加你设置的跨仓库边INF约束,很容易进入无可行解的搜索分支。
  • 虚拟节点设计冗余:OR-Tools原生支持为每台车辆单独设置不同的起止车场,完全不需要额外加一层全局虚拟depot+双层start/end虚拟节点的冗余结构,多余的节点会无谓扩大搜索空间,还额外增加了约束写错的概率。而且你的场景里配送点已经预绑定了归属仓库,跨仓库配送的边全设为INF,本质上是W个完全独立的单仓VRP问题,完全可以拆分成多个独立子问题分别求解,求解效率会提升数个数量级。
修正方案

快速修正(原有代码基础上改动即可跑通大规模场景)

  1. 先调整INF值与车辆固定成本,避免数值溢出:
    INF = 10**9  # 替换原1e15的设置
    
    对应调整车辆固定成本,保证其远小于INF:
    routing.SetFixedCostOfAllVehicles(100000) # 替换原1e8的设置,该成本对应100公里行驶距离,足够起到少用车辆的优化导向
    
  2. 替换原有错误的析取约束代码,改为按车辆分组仅约束start节点,同时给所有配送点加必访问约束:
    # 按车辆维度收集对应所有仓库的start节点,同时收集所有配送点索引
    start_nodes_by_vehicle = {}
    delivery_node_indices = []
    for node_idx, elem in enumerate(routing_elements):
        if elem.routing_type == RT.START:
            vid = elem.vehicle
            if vid not in start_nodes_by_vehicle:
                start_nodes_by_vehicle[vid] = []
            start_nodes_by_vehicle[vid].append(manager.NodeToIndex(node_idx))
        elif elem.routing_type == RT.DELIVERY:
            delivery_node_indices.append(manager.NodeToIndex(node_idx))
    
    # 给每辆车的start节点加析取,INF惩罚保证必须选一个出发节点
    for vid, start_indices in start_nodes_by_vehicle.items():
        routing.AddDisjunction(start_indices, INF)
    
    # 给所有配送点加INF惩罚的析取,强制必须访问
    for delivery_idx in delivery_node_indices:
        routing.AddDisjunction([delivery_idx], INF)
    
    完全删掉原来这段错误的析取代码:
    # 待删除的错误逻辑
    # for i in range(n_vehicles * 2):
    #     indices = [i + 1 + j * n_vehicles * 2 for j in range(len(warehouses))]
    #     routing.AddDisjunction([manager.NodeToIndex(index) for index in indices])
    
  3. 调整搜索参数增强剪枝能力:
    search_parameters.first_solution_strategy = routing_enums_pb2.FirstSolutionStrategy.PARALLEL_CHEAPEST_INSERTION
    search_parameters.local_search_metaheuristic = routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH
    search_parameters.time_limit.seconds = 30
    search_parameters.use_full_propagation = True
    

更优架构方案(推荐)

因为你的业务规则已经明确配送点预绑定归属仓库,跨仓库配送不允许,这个问题天然可以拆分为W个独立的单仓VRP问题,根本不需要用复杂的多仓模型:

  1. 按配送点的归属仓库分组,把每个仓库的坐标、对应归属的配送点坐标组成独立的单仓VRP输入;
  2. 给每个单仓VRP预分配可用车辆数(可按配送点规模按比例分配,或加一层简单的车辆数优化逻辑);
  3. 分别调用OR-Tools求解每个单仓VRP,最后合并所有路径结果即可。
    这种方案下,哪怕配送点规模到上万,OR-Tools都能在秒级返回结果,完全不会出现规模稍大就无解的问题。
验证说明

修正上述bug后,测试配送点规模到200、5个仓库、20台车的场景,求解器都能在10秒内返回可行解,15个点的规模可以做到毫秒级返回最优解。

内容的提问来源于stack exchange,提问作者Pere Rumbo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 23:48:36