编程语言
首页 > 编程语言> > (Python)利用OR-Tools求解CVRP问题

(Python)利用OR-Tools求解CVRP问题

作者:互联网

目录

代码:

from __future__ import print_function
from ortools.constraint_solver import routing_enums_pb2
from ortools.constraint_solver import pywrapcp


def create_data_model():
    data = dict()
    # Distance matrix: 17 by 17
    data['distance_matrix'] = [
        [0, 548, 776, 696, 582, 274, 502, 194, 308, 194, 536, 502, 388, 354, 468, 776, 662],
        [548, 0, 684, 308, 194, 502, 730, 354, 696, 742, 1084, 594, 480, 674, 1016, 868, 1210],
        [776, 684, 0, 992, 878, 502, 274, 810, 468, 742, 400, 1278, 1164, 1130, 788, 1552, 754],
        [696, 308, 992, 0, 114, 650, 878, 502, 844, 890, 1232, 514, 628, 822, 1164, 560, 1358],
        [582, 194, 878, 114, 0, 536, 764, 388, 730, 776, 1118, 400, 514, 708, 1050, 674, 1244],
        [274, 502, 502, 650, 536, 0, 228, 308, 194, 240, 582, 776, 662, 628, 514, 1050, 708],
        [502, 730, 274, 878, 764, 228, 0, 536, 194, 468, 354, 1004, 890, 856, 514, 1278, 480],
        [194, 354, 810, 502, 388, 308, 536, 0, 342, 388, 730, 468, 354, 320, 662, 742, 856],
        [308, 696, 468, 844, 730, 194, 194, 342, 0, 274, 388, 810, 696, 662, 320, 1084, 514],
        [194, 742, 742, 890, 776, 240, 468, 388, 274, 0, 342, 536, 422, 388, 274, 810, 468],
        [536, 1084, 400, 1232, 1118, 582, 354, 730, 388, 342, 0, 878, 764, 730, 388, 1152, 354],
        [502, 594, 1278, 514, 400, 776, 1004, 468, 810, 536, 878, 0, 114, 308, 650, 274, 844],
        [388, 480, 1164, 628, 514, 662, 890, 354, 696, 422, 764, 114, 0, 194, 536, 388, 730],
        [354, 674, 1130, 822, 708, 628, 856, 320, 662, 388, 730, 308, 194, 0, 342, 422, 536],
        [468, 1016, 788, 1164, 1050, 514, 514, 662, 320, 274, 388, 650, 536, 342, 0, 764, 194],
        [776, 868, 1552, 560, 674, 1050, 1278, 742, 1084, 810, 1152, 274, 388, 422, 764, 0, 798],
        [662, 1210, 754, 1358, 1244, 708, 480, 856, 514, 468, 354, 844, 730, 536, 194, 798, 0],
    ]
    # list with 17 elements
    # the first element represents the depot, which has no demand
    data['demands'] = [0, 1, 1, 2, 4, 2, 4, 8, 8, 1, 2, 1, 2, 4, 4, 8, 8]
    # four vehicles
    data['vehicle_capacities'] = [15, 15, 15, 15]
    data['num_vehicles'] = 4
    data['depot'] = 0
    return data


def print_solution(data, manager, routing, assignment):
    # 打印每辆车的路线(访问的位置),以及路线的距离。
    # 请注意,这些距离包括从仓库到路线中第一个位置的距离以及从最后一个位置返回到仓库的距离。
    # IndexToNode, NextVar 函数和前面的tsp问题是相同的意思
    total_distance = 0
    total_load = 0
    for vehicle_id in range(data['num_vehicles']):
        index = routing.Start(vehicle_id)
        plan_output = 'The vehicle {}:\n'.format(vehicle_id + 1)
        route_distance = 0
        route_load = 0
        while not routing.IsEnd(index):
            node_index = manager.IndexToNode(index)
            route_load += data['demands'][node_index]
            plan_output += ' {0} Cumulative load({1}) -> '.format(node_index, route_load)
            previous_index = index
            index = assignment.Value(routing.NextVar(index))
            route_distance += routing.GetArcCostForVehicle(
                previous_index, index, vehicle_id)
        plan_output += ' {0} Cumulative load({1})\n'.format(manager.IndexToNode(index),
                                                 route_load)
        plan_output += 'Total travel distance: {}m\n'.format(route_distance)
        plan_output += 'Total load: {}\n'.format(route_load)
        print(plan_output)
        total_distance += route_distance
        total_load += route_load
    print('The total travel distance of all vehicles: {}m'.format(total_distance))
    print('The total load of all vehicles: {}'.format(total_load))


def main():
    # 生成测试数据
    data = create_data_model()
    # 创建模型
    manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']),
                                           data['num_vehicles'], data['depot'])
    routing = pywrapcp.RoutingModel(manager)

    # 回调函数,用于计算两个节点间的距离
    def distance_callback(from_index, to_index):
        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)
    # 定义网络中各条边的成本
    routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)

    # 添加容量约束,返回每个节点的需求量
    def demand_callback(from_index):
        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'],  # 车辆最大装载量
        True,  # 从累积到零,意思应该和“装了这么多剩余空间还能装多少”差不多
        'Capacity')
    # 必须指定启发式方法来找到第一个可行解
    search_parameters = pywrapcp.DefaultRoutingSearchParameters()
    search_parameters.first_solution_strategy = (
        routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)
    # 求解并打印结果
    assignment = routing.SolveWithParameters(search_parameters)
    if assignment:
        print_solution(data, manager, routing, assignment)


if __name__ == '__main__':
    main()


求解结果:

The vehicle 1:
 0 Cumulative load(0) ->  1 Cumulative load(1) ->  4 Cumulative load(5) ->  3 Cumulative load(7) ->  15 Cumulative load(15) ->  0 Cumulative load(15)
Total travel distance: 2192m
Total load: 15

The vehicle 2:
 0 Cumulative load(0) ->  14 Cumulative load(4) ->  16 Cumulative load(12) ->  10 Cumulative load(14) ->  2 Cumulative load(15) ->  0 Cumulative load(15)
Total travel distance: 2192m
Total load: 15

The vehicle 3:
 0 Cumulative load(0) ->  7 Cumulative load(8) ->  13 Cumulative load(12) ->  12 Cumulative load(14) ->  11 Cumulative load(15) ->  0 Cumulative load(15)
Total travel distance: 1324m
Total load: 15

The vehicle 4:
 0 Cumulative load(0) ->  9 Cumulative load(1) ->  8 Cumulative load(9) ->  6 Cumulative load(13) ->  5 Cumulative load(15) ->  0 Cumulative load(15)
Total travel distance: 1164m
Total load: 15

The total travel distance of all vehicles: 6872m
The total load of all vehicles: 60

Process finished with exit code 0

标签:load,index,15,distance,Python,data,Cumulative,CVRP,Tools
来源: https://blog.csdn.net/MarcoLee1997/article/details/113861811