ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

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

2021-02-19 13:33:07  阅读:654  来源: 互联网

标签:load index 15 distance Python data Cumulative CVRP Tools


目录

代码:

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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有