OR-Tools实现多车场VRP仅小规模案例可解的问题咨询
问题根因
这不是OR-Tools求解器的能力限制,完全是实现逻辑存在多处错误。OR-Tools原生可支持单模型数千配送点的VRP求解,15个配送点的规模远未到性能瓶颈。
现有实现的核心错误有4个:
- INF值设置过大导致整数溢出:你将INF设为
1e15,远超OR-Tools内部64位整数计算的安全阈值,求解过程中成本累加时极易触发溢出,得到错误的成本值,直接破坏搜索逻辑。OR-Tools场景下INF只需设置为比全局最大可行路径总成本高1个数量级即可,常规配送场景设为1e9完全足够。 - 析取约束完全写错:
- 索引计算逻辑错误,将start节点、end节点混在同一个析取组内,求解器可能选中end节点作为路径起点,直接产生无效路径;
- 析取约束未按车辆维度分组,无法保证“单车辆仅选择一个仓库出发”的逻辑;
- 析取未设置INF级别的惩罚值,求解器可以直接跳过所有start节点;
- 多余给end节点加析取,OR-Tools原生会强制每条路径最终走到对应End节点,完全不需要额外加析取约束。
- 未强制配送点必须访问:OR-Tools Routing模型中,除了预设的depot节点外,其余节点默认是可选访问的,你没有给配送节点加必访问约束,小规模场景下节点少,求解器碰巧能覆盖所有点,规模上涨后搜索空间指数级扩大,求解器会直接跳过无法插入的配送点,再叠加你设置的跨仓库边INF约束,很容易进入无可行解的搜索分支。
- 虚拟节点设计冗余:OR-Tools原生支持为每台车辆单独设置不同的起止车场,完全不需要额外加一层全局虚拟depot+双层start/end虚拟节点的冗余结构,多余的节点会无谓扩大搜索空间,还额外增加了约束写错的概率。而且你的场景里配送点已经预绑定了归属仓库,跨仓库配送的边全设为INF,本质上是W个完全独立的单仓VRP问题,完全可以拆分成多个独立子问题分别求解,求解效率会提升数个数量级。
修正方案
快速修正(原有代码基础上改动即可跑通大规模场景)
- 先调整INF值与车辆固定成本,避免数值溢出:
对应调整车辆固定成本,保证其远小于INF:INF = 10**9 # 替换原1e15的设置routing.SetFixedCostOfAllVehicles(100000) # 替换原1e8的设置,该成本对应100公里行驶距离,足够起到少用车辆的优化导向 - 替换原有错误的析取约束代码,改为按车辆分组仅约束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]) - 调整搜索参数增强剪枝能力:
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问题,根本不需要用复杂的多仓模型:
- 按配送点的归属仓库分组,把每个仓库的坐标、对应归属的配送点坐标组成独立的单仓VRP输入;
- 给每个单仓VRP预分配可用车辆数(可按配送点规模按比例分配,或加一层简单的车辆数优化逻辑);
- 分别调用OR-Tools求解每个单仓VRP,最后合并所有路径结果即可。
这种方案下,哪怕配送点规模到上万,OR-Tools都能在秒级返回结果,完全不会出现规模稍大就无解的问题。
验证说明
修正上述bug后,测试配送点规模到200、5个仓库、20台车的场景,求解器都能在10秒内返回可行解,15个点的规模可以做到毫秒级返回最优解。
内容的提问来源于stack exchange,提问作者Pere Rumbo
相关产品推荐
相关产品推荐

