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

关于Google OR-Tools CVRP求解器的两大疑问:目标与depot设置

Google OR-Tools CVRP求解器疑问解答

1. 当前代码的优化目标确认

当前代码已经实现了所有路径总距离的优化,具体说明:

  • OR-Tools的RoutingModel默认优化目标是所有弧段(节点间路径)的成本总和,也就是所有车辆路径的总距离之和。
  • SetGlobalSpanCostCoefficient()是专门用于切换优化目标为「最长单车辆路径距离」(最小化所有车辆路径中的最大长度)的方法,你的代码未调用该方法,因此默认目标就是总距离。
  • 后续扩展多车辆时,只要保持SetArcCostEvaluatorOfAllVehicles使用距离回调,求解器依然会自动优化所有车辆路径的总距离之和,无需额外调整。

2. data["depot"] = 0的含义

这个参数的作用是指定求解器使用「节点索引为0的节点」作为所有车辆的起点和终点,与该节点的坐标是否为(0,0)完全无关:

  • 你的distance_matrix是基于生成的客户位置(包含非零坐标的depot)计算的,其中索引0对应的就是你定义的depot节点的距离数据(比如distance_matrix[0][i]是depot到第i个节点的距离)。
  • 求解器会让所有车辆从这个索引对应的节点出发,完成配送后必须返回该节点,不需要修改坐标把depot设为(0,0),只要保证distance_matrix的索引和节点顺序对应即可。

附当前代码

def create_data_model():
    data = {}
    data["distance_matrix"] = createDistanceMatrix(customers).tolist()
    data["demands"] = customers['Demand'].astype(int).tolist()
    data["vehicle_capacities"] = [1000]
    data["num_vehicles"] = 1
    data["depot"] = 0
    return data

def print_solution(data, manager, routing, solution):
    """Prints solution on console."""
    print(f"Objective: {solution.ObjectiveValue()}")
    total_distance = 0
    total_load = 0
    for vehicle_id in range(data["num_vehicles"]):
        index = routing.Start(vehicle_id)
        plan_output = f"Route for vehicle {vehicle_id}:\n"
        route_distance = 0
        route_load = 0
        while not routing.IsEnd(index):
            node_index = manager.IndexToNode(index)
            route_load += data["demands"][node_index]
            plan_output += f" {node_index} Load({route_load}) -> "
            previous_index = index
            index = solution.Value(routing.NextVar(index))
            route_distance += routing.GetArcCostForVehicle(
                previous_index, index, vehicle_id
            )
        plan_output += f" {manager.IndexToNode(index)} Load({route_load})\n"
        plan_output += f"Distance of the route: {route_distance}m\n"
        plan_output += f"Load of the route: {route_load}\n"
        print(plan_output)
        total_distance += route_distance
        total_load += route_load
    print(f"Total distance of all routes: {total_distance}m")
    print(f"Total load of all routes: {total_load}")

def main():
    """Solve the CVRP problem."""
    # Instantiate the data problem.
    data = create_data_model()

    # Create the routing index manager.
    manager = pywrapcp.RoutingIndexManager(
        len(data["distance_matrix"]), data["num_vehicles"], data["depot"]
    )

    # Create Routing Model.
    routing = pywrapcp.RoutingModel(manager)

    # Create and register a transit callback.
    def distance_callback(from_index, to_index):
        """Returns the distance between the two nodes."""
        # Convert from routing variable Index to distance matrix NodeIndex.
        from_node = manager.IndexToNode(from_index)
        to_node = manager.IndexToNode(to_index)
        return data["distance_matrix"][from_node][to_node]

    transit_callback_index = routing.RegisterTransitCallback(distance_callback)

    # Define cost of each arc.
    routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)

    # Add Capacity constraint.
    def demand_callback(from_index):
        """Returns the demand of the node."""
        # Convert from routing variable Index to demands NodeIndex.
        from_node = manager.IndexToNode(from_index)
        return data["demands"][from_node]

    demand_callback_index = routing.RegisterUnaryTransitCallback(demand_callback)
    routing.AddDimensionWithVehicleCapacity(
        demand_callback_index,
        0,  # null capacity slack
        data["vehicle_capacities"],  # vehicle maximum capacities
        True,  # start cumul to zero
        "Capacity",
    )

    # Setting first solution heuristic.
    search_parameters = pywrapcp.DefaultRoutingSearchParameters()
    search_parameters.first_solution_strategy = (
        routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC
    )
    search_parameters.local_search_metaheuristic = (
        routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH
    )
    search_parameters.time_limit.FromSeconds(5)

    # Solve the problem.
    solution = routing.SolveWithParameters(search_parameters)

    # Print solution on console.
    if solution:
        print_solution(data, manager, routing, solution)

内容的提问来源于stack exchange,提问作者Levi Rohring

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 23:48:12