Я использую инструменты ИЛИ для решения 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)
- Я следил за ИЛИ-инструменты решают коммивояжер (TSP) без возврата к домашнему узлу, чтобы установить расстояние от всех узлов до 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
Чтобы проверить вышеприведенный вывод, я отметил точки на карте Google. Порядок нумерации такой же, как и в матрице расстояний.
Депо (начальная точка) находится в Ваттхане, который можно увидеть возле маркера B.
Очевидно, что из Ваттханы самый дешевый путь должен быть 2-1-3 за одну поездку. Но Google OR возвращает его как две поездки (как показано на маршрутах для транспортных средств 0 и 3). Это также можно проверить, добавив расстояния вручную.
Расстояние от дома до 2 до 1 до 3 = 2613 + 5392 + 15013 = 23018 м
Расстояние от машин 0 и 3 = 20079 + 8005 = 28084 м.
Что я делаю неправильно? Как я могу заставить Google не отделять точку 1? Также обратите внимание, что в идеале точки E, F, D также могли быть сгруппированы, но это не так.
Заранее спасибо!