week16车辆路径规划问题2

1,965 阅读6分钟

VRP规划的方案流程

VRP(Vehicle Routing Problem):

车辆路径问题,可以看成旅行商问题的推广

有N辆车,都从原点出发,每辆车访问一些点后回到原点,要求所有的点都要被访问到,求最短的车辆行驶距离或最少需要的车辆数

Thinking:有哪些应用领域,适用于VRP问题

快递公司,给司机分配送货线路

拼车软件,为司机分配接送乘客的路线

常见的限制要求:

车辆具有可携带的最大重量或数量

司机需要在指定时间窗口内访问某位置

使用RoutingModel进行路径规划管理

1)设置城市个数,车辆数,起点下标

2)设置距离回调函数 distance_callback

3)设置初始可行解算法

PATH_CHEAPEST_ARC,从start节点开始,找到CHEAPEST的路径

4)在初始可行解的基础上进行优化(使用local search)

search_parameters.local_search_metaheuristic = (

routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)

#搜索时间限制

search_parameters.time_limit.seconds = 120

车辆路径规划 步骤:

Step1, 创建参数字典data

Step2,创建路线索引管理器

Step3,创建路线模型

Step4,注册各种限制和约束条件

Step5,设置解决方案策略

Step6,计算解决方案

Step7,输出结果

Project B:指定城市的旅行商 TSP

Step1,数据预处理

1)所有城市的位置(经度、维度)

2)城市之间的距离矩阵

Step2,根据指定的城市,计算TSP,得到路径route

Step3,可视化交互

1)选择指定的城市

2)画出车辆行驶路径(基于百度地图API)

数据源:

1)cities.xlsx,需要指定地点的经度、纬度

2)distance.xlsx,通过compute_distance计算得到

调用高德API计算距离

{"status":"1","info":"OK","infocode":"10000","count":"1","results":[{"origin_id":"1","dest_id":"1","distance":"135381","duration":"6780"}]}

Step1,数据预处理

1)所有城市的位置(经度、维度)

2)城市之间的距离矩阵

针对常用的功能,可以封装为自己的工具包

from cylearn import common_tools

# 读取,写入指定的pickle

result = common_tools.load_pickle('result.pkl')

common_tools.save_pickle(result, 'result.pkl')

# 计算两点之间的距离

dist = common_tools.compute_distance(longitude1, latitude1, longitude2, latitude2)

Step2,根据指定的城市,计算TSP,得到路径route

创建tsp类

1)def __init__(self, city_names=None):

类初始化 __init__,定义常用的变量

2)def create_data_model(self):

初始化data,得到data字典,记录distance_matrix,num_vehicles,depot等数据

3)def get_solution(self, routing, solution):

返回路径(这里为index list,比如[0, 1, 2]) 以及 总距离

4)def work(self):

# 定义路由,比如10个节点,1辆车

manager = RoutingIndexManager(10, 1, starts_ends)

# 创建 Routing Model.

routing = pywrapcp.RoutingModel(manager)

# 计算两点之间的距离

def distance_callback(from_index, to_index):

# 将路由变量Index转化为 距离矩阵ditance_matrix的节点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)

# 定义每条边arc的代价

routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)

# 设置启发式搜索

search_parameters = pywrapcp.DefaultRoutingSearchParameters()

search_parameters.first_solution_strategy = (

routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)

# 求解路径规划

solution = routing.SolveWithParameters(search_parameters)

TSP类编写完后,可以进行测试

测试1:使用全量的城市,不对city_names进行筛选

测试2:city_names = ['北京', '天津', '南京']

Step3,可视化交互

1)选择指定的城市

// 表单提交

// checkbox使用

2)画出车辆行驶路径(基于百度地图API)

基于 map_line1.html 进行改写

多辆车的路径规划 VRP

条件:经过中国33个城市,一共4辆车,每辆车最大行驶10000公里

目标:1) 每辆车的行驶里程数更接近 2)总里程数更少

数据预处理:

1)设置 num_vehicles,代表一共多少量车

2)设置 depot,代表所有车的起始出发点一样,都是从节点depot开始

3)添加距离约束,即每辆车的最大行驶距离

需要注意:

1)在VRP问题中,路径上给点赋的index和点实际的index不一样,需要使用IndexToNode方法进行转换才能得到实际的index

# 添加距离约束

dimension_name = 'Distance'

routing.AddDimension(

transit_callback_index,

0, # no slack

10000, # 车辆最大行驶距离

True, # start cumul to zero

dimension_name)

distance_dimension = routing.GetDimensionOrDie(dimension_name)

# 尽量减少车辆之间的最大距离

distance_dimension.SetGlobalSpanCostCoefficient(100)

说明:车辆之间最大距离,最小化

global_span_cost = coefficient * (Max(dimension end value) - Min(dimension start value))

带有容量约束的VRP

现在有4辆车,均从原点出发,他们需要收16个客户点的货,如何安排使得总距离最短

1)从起始仓库出发,回到起始仓库

2)每辆车都有容量限制,每个客户点也有货物容量

distance_matrix,两点之间的距离

demands,每个客户点需要配送的货物量

num_vehicles,一共多少量车

vehicle_capacities,每辆车的容量

depot,起始原点的下标 

带有时间窗口约束的VRP

现在有4辆车,均从原点出发,他们需要去16个配送点送货,如何安排使得总时间最短

1)起始出发仓库,最多只能同时装载/卸载 两辆车

2)每个配送点需要在指定时间窗口内完成

比如 点8 [5, 10],需要在第5-10分钟内完成配送

time_matrix,两点之间的行驶时间

time_windows,每个配送点的时间窗口

num_vehicles,一共多少量车

vehicle_load_time,车的装载所需时间

vehicle_unload_time,车的卸载所需时间

depot_capacity,起始仓库容量,同时装载/卸载的车数

depot,起始原点的下标

时间窗口约束限制 (根据距离换算出的时间矩阵)

routing.RegisterTransitCallback(time_callback)

routing.SetArcCostEvaluatorOfAllVehicles(time_callback_index)

添加时间变量 每天允许的时间

time_dimension = routing.GetDimensionOrDie(time)

添加时间变量的累积限制 时间窗限制

time_dimension.CumulVar(index).SetRange(time_window[0], time_window[1])

routing.AddVariableMinimizedByFinalizer(

time_dimension.CumulVar(routing.Start(i)))

routing.AddVariableMinimizedByFinalizer(

time_dimension.CumulVar(routing.End(i)))

Project F:带有指定拿起放下约束的VRP

现在有4辆车,均从原点出发,他们需要完成指定的任务,即帮指定的商家,送给指定的客户

1)一共8项任务,每项任务都有指定的(商家、客户)比如[1, 6],即为 商家1给客户6进行配送

2)所有车辆的总距离最小

distance_matrix,两点之间的行驶距离

num_vehicles,一共多少量车

pickups_deliveries,需要配送的商家、客户

depot,起始原点的下标

添加车载容量限制

demand_callback_index = routing.RegisterUnaryTransitCallback(

demand_callback)

routing.AddDimensionWithVehicleCapacity(

demand_callback_index,

0, # null capacity slack

data['vehicle_capacities'], # 车辆最大容量

True, # start cumul to zero

'Capacity')

VRP问题的求解

NP Hard问题,即使只有几百个客户节点,也很难在有限时间内找到最优解

研究工作分为两个流派

1)通过运筹学(Operations)

将VRP定义为数学优化问题,通过启发式算法达求近似最优解

2)通过深度学习

比如GCN,计算节点特征,边特征

OR-Tools工具:

• Google的运筹学工具,启发式求解器

• 在可接受的时间内可以求解较大规模的VRP问题

• 支持的应用场景:

1)VRP(一辆车或多辆车)

2)带有容量约束的VRP

3)带有时间窗口约束的VRP

4)指定拿起放下地点的VRP(pickups and deliveries)