ortools系列:VRP中的一些常见问题
1. 搜索限制
对于节点很多的车辆路径问题需要很长时间才能解决。对于此类问题,最好设置搜索限制,即在指定的时间长度或返回的结果数量之后终止搜索。当解决程序达到极限时,可以将最新的解决方案保存到文件中。如果以后您想找到更好的解决方案,可以使用保存的结果作为初始点重新启动搜索。
要设置搜索的时间限制,请在调用解决程序之前添加以下搜索参数:
search_parameters.time_limit_ms = 30000
这将在30000毫秒(或30秒)后停止搜索。有关有时间限制的完整示例,请参见
要设置返回的解决方案数量的限制,请添加以下内容:
search_parameters.solution_limit = 100
2. 将结果存储在数组中
有时可能会发现将VRP的结果存储在数组中非常方便。例如,可能希望使用不同的参数执行多个搜索,然后比较保存的结果。
def get_routes_array(assignment, num_vehicles, routing):
# Get the routes for an assignent and return as a list of lists.
routes = []
for route_nbr in range(num_vehicles):
node = routing.Start(route_nbr)
route = []
while not routing.IsEnd(node):
index = routing.NodeToIndex(node)
route.append(index)
node = assignment.Value(routing.NextVar(node))
routes.append(route)
return routes
当然,你也可以将此函数添加到VRP的Python程序中,并按如下方式调用它:
assignment = routing.SolveWithParameters(search_parameters)
routes = get_routes_array(assignment, num_routes, routing)
将搜索结果存储在数组中的另一个原因是,可以将数组保存到文件中,然后从保存的文件中恢复。
3. 设置搜索的初始路径
要创建初始路由,请执行以下步骤:建立路由模型并声明求解器。
定义包含初始路由的数组。(在下面的例子中,数组是在程序中显式定义的,但是如果之前已将解决方案保存到文件中,则可以从文件中创建数组。)
下面是示例代码
initial_routes = [[8, 16, 14, 13, 12, 11], [3, 4, 9, 10], [15, 1], [7, 5, 2, 6]]
routing = pywrapcp.RoutingModel(num_locations, num_vehicles, depot)
dist_callback = create_dist_callback(dist_matrix)
add_distance_dimension(routing, dist_callback)
routing.SetArcCostEvaluatorOfAllVehicles(dist_callback)
initial_assignment = routing.ReadAssignmentFromRoutes(initial_routes, True)
4. 设置路由的开始和结束位置
到目前为止,我们假设所有的车辆都在一个地点开始和结束,即仓库。其实还可以为问题中的每个车辆设置可能不同的开始和结束位置。为此,将包含起始位置和结束位置索引的两个向量作为输入传递给主函数中的RoutingModel方法。下面是一些示例代码,用于解决四种车辆的问题:
start_locations = [8, 3, 15, 7]
end_locations = [11, 10, 1, 6]
routing = pywrapcp.RoutingModel(num_locations,
num_vehicles,
start_locations,
end_locations)
5. 允许任意开始和结束位置
在其他版本的车辆路径问题中,车辆可以在任意位置开始和结束。以这种方式设置问题,只需修改距离回调,使从仓库到任何其他位置的距离为0。这就把车场变成了一个虚拟的位置,它的位置对最优路线没有影响。
locations = \
[(4, 4), # depot
(2, 0), (8, 0), # row 0
(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)]
num_locations = len(locations)
dist_matrix = {}
for from_node in range(num_locations):
dist_matrix[from_node] = {}
for to_node in range(num_locations):
if from_node == depot or to_node == depot:
# Define the distance from the depot to any node to be 0.
# 这里将到距离设置为0
self.matrix[from_node][to_node] = 0
else:
dist_matrix[from_node][to_node] = (
manhattan_distance(locations[from_node], locations[to_node]))
6. 关于VRPLite
安利一个软件:VRPLite:为交通运输规划服务的车辆路径问题解决方案,有时间研究一下其原理,道理都是差不多的。
7. 参考
大家看完记得关注点赞.
master苏.