OR-Tools VRP 使用距离维度设置每辆车的最大路线

问题描述

我在计算每辆车的路线距离时遇到问题

示例 车辆数量:9
总地址:70

只返回6条路线,其中一辆车应用了36条路线

目前,我正在使用距离维度,我也已经尝试过“计数器”维度,根据我们设置的最大路线,结果是正确的,但点之间的距离是随机的(示例结果:路线 1 : 1KM,路线2:7KM,路线3:2KM)

我想设置每辆车的限制,但使用“距离”维度

我的代码

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 distance constraint.
    dimension_name = 'distance'
    routing.AddDimension(
        transit_callback_index,# no slack
        100000,# vehicle maximum travel distance
        True,# start cumul to zero
        dimension_name)
    distance_dimension = routing.GetDimensionorDie(dimension_name)
    distance_dimension.SetGlobalSpanCostCoefficient(100)

    # Setting first solution heuristic.
    search_parameters = pywrapcp.DefaultRoutingSearchParameters()
    search_parameters.first_solution_strategy = (
        routing_enums_pb2.FirstSolutionStrategy.PATH_CHEApest_ARC)

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

解决方法

  1. 创建维度时
routing.AddDimension(
        transit_callback_index,# no slack
        100_000,# vehicle maximum travel distance
        True,# start cumul to zero
        dimension_name)

这里的 100_000 是硬上限。

  1. 要对每辆车设置特定限制,您可以使用过载方法 AddDimensionWithVehicleCapacity() 使用列表而不是容量值,即最大行驶距离。 参考:https://github.com/google/or-tools/blob/b77bd3ac69b7f3bb02f55b7bab6cbb4bab3917f2/ortools/constraint_solver/routing.h#L448-L451

  2. 对于计数器的东西,如果你想“平等地”分发节点,你可以使用:

  # Distribution
    routing.AddConstantDimension(
            1,manager.GetNumberOfNodes(),True,# start cumul to zero
            "Counter")
    counter_dimension = routing.GetDimensionOrDie("Counter")
    nb_visit = (manager.GetNumberOfNodes()) // manager.GetNumberOfVehicles()
    print(f'visit_mean: {nb_visit}')
    penalty = 10_000 # must be adapted to your problem
    for vehicle_id in range(data["num_vehicles"]):
      index = routing.End(vehicle_id)
      counter_dimension.SetCumulVarSoftLowerBound(index,nb_visit,penalty)
      counter_dimension.SetCumulVarSoftUpperBound(index,nb_visit + 1,penalty)