1. 问题模型

VRP问题是车辆路径问题的缩写。问题是:有N辆车,都从原点出发,每辆车访问一些点后回到原点,要求所有的点都要被访问到,求最短的车辆行驶距离或最少需要的车辆数或最小化最长行驶距离。
常见的限制要求包括:车辆容量限制、时间窗限制、点访问顺序要求等。

2. RoutingModel的一些说明

对于VRP问题,我们可以使用ortools的RoutingModel模型。首先为车添加用于进行优化的dimension:

方法 输入 说明
AddDimension evaluator, slack_max, capacity, fix_start_cumul_to_zero, name Creates a dimension where the transit variable is constrained to be equal to evaluator(i, next(i)); ‘slack_max’ is the upper bound of the slack variable and ‘capacity’ is the upper bound of the cumul variables. ‘name’ is the name used to reference the dimension; this name is used to get cumul and transit variables from the routing model. Returns false if a dimension with the same name has already been created (and doesn’t create the new dimension). Takes ownership of the callback ‘evaluator’.

然后使用GetDimensionOrDie方法获取dimension,并设置优化目标。注意在VRP问题中,路径上给点赋的index和点实际的index不一样,需要使用IndexToNode方法进行转换才能得到实际的index。

3. 例子

先看一个简单的例子:距离用曼哈顿距离,目标函数是最小化各车辆行驶距离的差别。可以对dimension使用SetGlobalSpanCostCoefficient方法可以获得目标函数。global_span_cost = coefficient * (Max(dimension end value) - Min(dimension start value)).

代码如下:

from __future__ import print_function
from ortools.constraint_solver import pywrapcp
from ortools.constraint_solver import routing_enums_pb2###########################
# Problem Data Definition #
###########################
def create_data_model():"""Stores the data for the problem"""data = {}# Locations in block units_locations = \[(4, 4), # depot(2, 0), (8, 0), # locations to visit(0, 1), (1, 1),(5, 2), (7, 2),(3, 3), (6, 3),(5, 5), (8, 5),(1, 6), (2, 6),(3, 7), (6, 7),(0, 8), (7, 8)]# Multiply coordinates in block units by the dimensions of an average city block, 114m x 80m,# to get location coordinates.data["locations"] = [(l[0] * 114, l[1] * 80) for l in _locations]data["num_locations"] = len(data["locations"])data["num_vehicles"] = 4data["depot"] = 0return data
#######################
# Problem Constraints #
#######################
def manhattan_distance(position_1, position_2):"""Computes the Manhattan distance between two points"""return (abs(position_1[0] - position_2[0]) + abs(position_1[1] - position_2[1]))
def create_distance_callback(data):"""Creates callback to return distance between points."""_distances = {}for from_node in range(data["num_locations"]):_distances[from_node] = {}for to_node in range(data["num_locations"]):if from_node == to_node:_distances[from_node][to_node] = 0else:_distances[from_node][to_node] = (manhattan_distance(data["locations"][from_node],data["locations"][to_node]))def distance_callback(from_node, to_node):"""Returns the manhattan distance between the two nodes"""return _distances[from_node][to_node]return distance_callback
def add_distance_dimension(routing, distance_callback):"""Add Global Span constraint"""distance = 'Distance'maximum_distance = 3000  # Maximum distance per vehicle.routing.AddDimension(distance_callback,0,  # null slackmaximum_distance,True,  # start cumul to zerodistance)distance_dimension = routing.GetDimensionOrDie(distance)# Try to minimize the max distance among vehicles.distance_dimension.SetGlobalSpanCostCoefficient(100)
###########
# Printer #
###########
def print_solution(data, routing, assignment):"""Print routes on console."""total_distance = 0for vehicle_id in range(data["num_vehicles"]):index = routing.Start(vehicle_id)plan_output = 'Route for vehicle {}:\n'.format(vehicle_id)distance = 0while not routing.IsEnd(index):plan_output += ' {} ->'.format(routing.IndexToNode(index))previous_index = indexindex = assignment.Value(routing.NextVar(index))distance += routing.GetArcCostForVehicle(previous_index, index, vehicle_id)plan_output += ' {}\n'.format(routing.IndexToNode(index))plan_output += 'Distance of route: {}m\n'.format(distance)print(plan_output)total_distance += distanceprint('Total distance of all routes: {}m'.format(total_distance))
########
# Main #
########
def main():"""Entry point of the program"""# Instantiate the data problem.data = create_data_model()# Create Routing Modelrouting = pywrapcp.RoutingModel(data["num_locations"],data["num_vehicles"],data["depot"])# Define weight of each edgedistance_callback = create_distance_callback(data)routing.SetArcCostEvaluatorOfAllVehicles(distance_callback)add_distance_dimension(routing, distance_callback)# Setting first solution heuristic (cheapest addition).search_parameters = pywrapcp.RoutingModel.DefaultSearchParameters()search_parameters.first_solution_strategy = (routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC) # pylint: disable=no-member# Solve the problem.assignment = routing.SolveWithParameters(search_parameters)if assignment:print_solution(data, routing, assignment)
if __name__ == '__main__':main()

输出为:

结果如下图:

运筹系列16:routing模型之VRP问题相关推荐

  1. 机器学习系列16:机器学习系统设计

    https://www.toutiao.com/a6700782123118232068/ 机器学习系列16:机器学习系统设计 偏斜分类的误差评估 举个例子,我们想训练一个模型去诊断患者是否患有癌症. ...

  2. Caffe学习系列(17):模型各层特征和过滤器可视化

    转载自: Caffe学习系列(17):模型各层特征和过滤器可视化 - denny402 - 博客园 http://www.cnblogs.com/denny402/p/5105911.html cif ...

  3. Caffe学习系列(16):各层权值参数可视化

    原文有更新: Caffe学习系列(16):各层权值参数可视化 - denny402 - 博客园 http://www.cnblogs.com/denny402/p/5103425.html 通过前面的 ...

  4. Deep Learning(深度学习)学习笔记整理系列之常用模型

    Deep Learning(深度学习)学习笔记整理系列之常用模型(四.五.六.七) 九.Deep Learning的常用模型或者方法 9.1.AutoEncoder自动编码器 Deep Learnin ...

  5. df满足条件的值修改_文科生学 Python 系列 16:泰坦尼克数据 2(缺失值处理)

    第八课:案例分析 - 泰坦尼克数据 本节课将重点分析泰坦尼克号沉船事故,我们将探索是什么因素决定了最后是否生还. 我们将将前面课程所学过的知识点融会贯通,举一反三 新增知识点: 缺失值处理:panda ...

  6. SAP PM 初级系列16 - 设备相关的Asset号

    SAP PM 初级系列16 - 设备相关的Asset号 业务上,由于很多维修部门的设备价值不菲,所以自然也是企业里的重要资产.在SAP系统里,为某个设备创建固定资产号,也是很正常的. IE03用于显示 ...

  7. SAP PM 入门系列16 - KO88对维护工单做结算

    SAP PM 入门系列16 - KO88对维护工单做结算 1, 如下的维护工单100316384, 该工单settlement rule信息, Settle type, FUL & PER , ...

  8. 4Python全栈之路系列之Django模型

    Python全栈之路系列之Django模型 MTV开发模式 把数据存取逻辑.业务逻辑和表现逻辑组合在一起的概念有时被称为软件架构的Model-View-Controller(MVC)模式.在这个模式中 ...

  9. 企业管理系统前后端分离架构设计 系列一 权限模型篇

    ACL(Access Control List)(访问控制列表) DAC(Discretionary Access Control)(自主访问控制) MAC(Mandatory Access Cont ...

最新文章

  1. 主动模式FTP与被动模式FTP该如何选择
  2. 增加数组下标_数组以及ArrayList源码解析
  3. python 实例 cadu_【示例详解】AutoCAD处理控件Aspose.CAD 8月新更!支持加载大型DWG文件...
  4. error parsing xml:unbound prefix
  5. AngularJS学习之旅—AngularJS 事件(十四)
  6. a+ open python_python编程之文件操作
  7. Mysql-DML操作
  8. if函数判断单元格颜色_IF条件函数10大用法完整版,全会是高手,配合SUMIF,VLOOKUP更逆天...
  9. 贝叶斯和EM算法简介
  10. 上课作业(5)——#576. 饥饿的牛(hunger)
  11. angular 自定义组件的双向数据绑定
  12. 树莓派3B安装linux(ubuntu mate 16.04.2)+ 远程桌面
  13. eNSP:实现不同网段不同vlan主机之间的互访(配置单臂路由)
  14. 菜鸟的springboot项目图片上传及图片路径分析
  15. C++使用AES+Base64算法对文本进行加密
  16. linux中负载值为多少正常_linux查看系统负载常用指标与命令
  17. CSS-3D酷炫柱状图
  18. 最新最全的非常有趣的逻辑推理题目大全
  19. 51单片机定时器工作方式1、2原理详解
  20. 马东:经营《奇葩说》,我对内容经济本质的3个判断

热门文章

  1. Exchange Server 2013 DAG高可用部署(一)-前期准备
  2. 网页视频下载方法汇总
  3. 区块链下的保护个人信息安全武器
  4. 湖广填四川与安岳姓氏源流
  5. 【实训项目】教师工作量管理系统
  6. 如何使用GitHub Desktop管理Gitlab库
  7. 鼠标滚轮上下失灵的解决办法(机械编码器)
  8. 泛微OA调用SAP接口
  9. Windebug的一个缺点
  10. Programming Exercise 7: K-means Clustering and Principal Component Analysis【Maching Learning】