【发布时间】:2021-04-06 05:32:33
【问题描述】:
我正在使用 OR 工具来解决 VRP 问题,没有任何限制。以下是源代码:
def create_data_model():
"""Stores the data for the problem."""
data = {}
data['distance_matrix'] = [
[0, 20079, 2613, 8005, 19277, 12468, 13701],
[0, 0, 21285, 16012, 32574, 35394, 28806],
[0, 18233, 0, 5392, 19965, 19650, 13064],
[0, 15013, 5639, 0, 22883, 22570, 15982],
[0, 32991, 19256, 21815, 0, 18414, 9112],
[0, 34348, 16976, 23122, 15678, 0, 14647],
[0, 27652, 13917, 16476, 8043, 14820, 0]
]
data['time_matrix'] = [
[0, 1955, 508, 1331, 1474, 1427, 1292],
[0, 0, 1795, 1608, 2057, 2410, 2036],
[0, 1485, 0, 823, 1370, 1541, 1100],
[0, 1402, 924, 0, 1533, 1637, 1263],
[0, 2308, 1663, 1853, 0, 1766, 1104],
[0, 2231, 1373, 1660, 1441, 0, 1554],
[0, 1998, 1353, 1543, 764, 1550, 0]
]
data['num_vehicles'] = 6
data['depot'] = 0
return data
def print_solution(data, manager, routing, solution):
"""Prints solution on console."""
max_route_distance = 0
for vehicle_id in range(data['num_vehicles']):
index = routing.Start(vehicle_id)
plan_output = 'Route for vehicle {}:\n'.format(vehicle_id)
route_distance = 0
while not routing.IsEnd(index):
plan_output += ' {} -> '.format(manager.IndexToNode(index))
previous_index = index
index = solution.Value(routing.NextVar(index))
route_distance += routing.GetArcCostForVehicle(
previous_index, index, vehicle_id)
plan_output += '{}\n'.format(manager.IndexToNode(index))
plan_output += 'Distance of the route: {}m\n'.format(route_distance)
print(plan_output)
max_route_distance = max(route_distance, max_route_distance)
print('Maximum of the route distances: {}m'.format(max_route_distance))
def test(request):
# Instantiate the data problem.
data = create_data_model()
# Create the routing index manager.
manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']),
data['num_vehicles'], data['depot'])
# Create Routing Model.
routing = pywrapcp.RoutingModel(manager)
def distance_callback(from_index, to_index):
"""Returns the distance between the two nodes."""
# Convert from routing variable Index to distance matrix NodeIndex.
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)
dimension_name = 'Distance'
routing.AddDimension(
transit_callback_index,
0, # no slack
1000000000, # vehicle maximum travel distance
True, # start cumul to zero
dimension_name)
distance_dimension = routing.GetDimensionOrDie(dimension_name)
distance_dimension.SetGlobalSpanCostCoefficient(35394)
# Setting first solution heuristic.
search_parameters = pywrapcp.DefaultRoutingSearchParameters()
search_parameters.first_solution_strategy = (
routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)
# Solve the problem.
solution = routing.SolveWithParameters(search_parameters)
# Print solution on console.
if solution:
print_solution(data, manager, routing, solution)
return HttpResponse('')
以上所有内容都是从 google 的示例中复制粘贴的,但以下内容除外:
- 我自己的距离矩阵和车辆数量
- AddDimension 函数中非常大的车辆最大行驶距离
- SetGlobalSpanCostCoefficient(35394)
- 我按照 OR-Tools solve traveling salesman (TSP) without returning to the home node 将所有节点到 0 的距离(仓库)设置为 0。
上述代码的结果如下所示:
Route for vehicle 0:
0 -> 1 -> 0
Distance of the route: 20079m
Route for vehicle 1:
0 -> 5 -> 0
Distance of the route: 12468m
Route for vehicle 2:
0 -> 4 -> 0
Distance of the route: 19277m
Route for vehicle 3:
0 -> 2 -> 3 -> 0
Distance of the route: 8005m
Route for vehicle 4:
0 -> 6 -> 0
Distance of the route: 13701m
Route for vehicle 5:
0 -> 0
Distance of the route: 0m
Maximum of the route distances: 20079m
为了验证上述输出,我在谷歌地图中标记了点。编号顺序与距离矩阵的顺序相同。
仓库(起点)在 Watthana,可以在标记 B 附近看到。
显然,从 Watthana 出发,单程最便宜的路线应该是 2-1-3。但 Google OR 将其作为两次行程返回(如车辆 0 和 3 的路线所示)。这也可以通过手动添加距离来验证。
从家到2到1到3的距离=2613+5392+15013=23018m
车辆 0 和 3 的距离 = 20079+8005 = 28084m
我做错了什么?我怎样才能让谷歌不把第 1 点分开?另请注意,理想情况下,E、F、D 点也可以被分组,但它们没有。
提前致谢!
【问题讨论】:
标签: python-3.x or-tools vehicle-routing