[英]Vehicle routing problem with time windows at different start and end depot
I am trying to write a trip planner for which I am using Google's ORtools.我正在尝试编写一个旅行计划,我正在使用 Google 的 ORtools。 The problem that I am trying to solve is that each vehicle has a different start and end depot and all the services have a different start and end time.
我试图解决的问题是每辆车都有不同的起点和终点站,所有的服务都有不同的起点和终点时间。 Even the depots have a different start and end time, which need to be added as a constraint.
即使是 depot 也有不同的开始和结束时间,需要将其添加为约束。 I have been following there two examples from google's documentation:
我一直在关注谷歌文档中的两个例子:
I have scoured through all of documentations that are available for ortools, but have not been able to find a reason as to why this error is occurring.我已经浏览了所有可用于 ortools 的文档,但无法找到发生此错误的原因。 According to the documentation, what I am trying to do is possible and the code that I have written should give a correct result.
根据文档,我正在尝试做的事情是可能的,并且我编写的代码应该给出正确的结果。
Here is a sample code of what I am doing:这是我正在做的示例代码:
"""Simple Vehicles Routing Problem."""
from __future__ import print_function
from ortools.constraint_solver import routing_enums_pb2
from ortools.constraint_solver import pywrapcp
def create_data_model():
"""Stores the data for the problem."""
data = {}
data['time_matrix'] = [
[0, 6, 7, 9, 7, 3, 6, 2, 3, 2, 6, 6, 4, 4, 5, 9, 7, 0],
[6, 0, 8, 3, 2, 6, 8, 4, 8, 8, 13, 7, 5, 8, 12, 12, 14, 6],
[7, 8, 0, 11, 10, 6, 3, 9, 5, 8, 4, 15, 14, 13, 9, 18, 9, 15],
[9, 3, 11, 0, 3, 7, 10, 6, 10, 10, 14, 6, 7, 9, 14, 6, 16, 14],
[7, 2, 10, 3, 0, 6, 9, 4, 8, 9, 13, 4, 6, 8, 12, 8, 14, 9],
[3, 6, 6, 7, 6, 0, 2, 8, 2, 2, 7, 9, 7, 7, 6, 12, 8, 3],
[6, 8, 3, 10, 9, 2, 0, 6, 2, 5, 4, 12, 10, 10, 6, 11, 5, 10],
[2, 4, 9, 6, 4, 8, 6, 0, 4, 4, 8, 5, 4, 13, 7, 8, 10, 12],
[3, 8, 5, 10, 8, 2, 2, 4, 0, 3, 4, 9, 8, 7, 3, 13, 6, 5],
[2, 8, 8, 10, 9, 2, 5, 4, 3, 0, 4, 6, 5, 4, 3, 9, 5, 8],
[6, 13, 4, 14, 13, 7, 4, 8, 4, 4, 0, 10, 9, 8, 4, 13, 4, 9],
[6, 7, 15, 6, 4, 9, 12, 5, 9, 6, 10, 0, 1, 3, 7, 13, 10, 11],
[4, 5, 14, 7, 6, 7, 10, 4, 8, 5, 9, 1, 0, 2, 16, 4, 8, 1],
[4, 8, 13, 9, 8, 7, 10, 13, 7, 4, 8, 3, 2, 0, 4, 5, 6, 2],
[5, 12, 9, 14, 12, 6, 6, 7, 3, 3, 4, 7, 16, 4, 0, 9, 12, 4],
[9, 12, 18, 6, 8, 12, 11, 8, 13, 9, 13, 13, 4, 5, 9, 0, 9, 10],
[7, 14, 9, 16, 14, 8, 5, 10, 6, 5, 4, 10, 8, 6, 12, 9, 0, 13],
[0, 6, 15, 14, 9, 3, 10, 12, 5, 8, 9, 11, 1, 2, 4, 10, 13, 0]
]
data['time_windows'] = [
(0, 22), # depot
(7, 12), # 1
(10, 15), # 2
(6, 8), # 3
(10, 13), # 4
(0, 5), # 5
(5, 10), # 6
(0, 4), # 7
(5, 7), # 8
(0, 3), # 9
(10, 16), # 10
(10, 15), # 11
(0, 9), # 12
(5, 10), # 13
(7, 10), # 14
(10, 15), # 15
(11, 15), # 16
(18, 25) # 17
]
data['num_days'] = 3
data['start'] = [0,0,0]#, 0, 0, 0] # ,17,0,17]
data['end'] = [17,17,17]#, 17, 17, 17]
return data
def print_solution(data, manager, routing, assignment):
# prints the final routing solution on the console
time_dimension = routing.GetDimensionOrDie('Time')
total_time = 0
for vehicle_id in range(data['num_days']):
index = routing.Start(vehicle_id)
plan_output = 'Route for vehicle {}:\n'.format(vehicle_id)
while not routing.IsEnd(index):
time_var = time_dimension.CumulVar(index)
plan_output += '{0} Time({1},{2}) -> '.format(
manager.IndexToNode(index), assignment.Min(time_var),
assignment.Max(time_var))
index = assignment.Value(routing.NextVar(index))
time_var = time_dimension.CumulVar(index)
plan_output += '{0} Time({1},{2})\n'.format(
manager.IndexToNode(index), assignment.Min(time_var),
assignment.Max(time_var))
plan_output += 'Time of the route: {}min\n'.format(
assignment.Min(time_var))
print(plan_output)
total_time += assignment.Min(time_var)
print('Total time of all routes: {}min'.format(total_time))
def main():
"""Entry point of the program."""
# Instantiate the data problem.
data = create_data_model()
# Create the routing index manager.
manager = pywrapcp.RoutingIndexManager(len(data['time_matrix']), data['num_days'], data['start'], data['end'])
# Create Routing Model.
routing = pywrapcp.RoutingModel(manager)
# Create and register a transit callback.
def time_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['time_matrix'][from_node][to_node]
transit_callback_index = routing.RegisterTransitCallback(time_callback)
# Define cost of each arc.
routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)
# Add time constraint.
dimension_name = 'time'
routing.AddDimension(
transit_callback_index,
30, # no slack
1000000000, # vehicle maximum travel distance
False, # start cumul to zero
dimension_name)
time_dimension = routing.GetDimensionOrDie(dimension_name)
# add time window constraints
for location_idx, time_window in enumerate(data['time_windows']):
if location_idx == 17 or location_idx == 0:
continue
index = manager.NodeToIndex(location_idx)
time_dimension.CumulVar(index).SetRange(time_window[0], time_window[1])
# Add time window constraints for each vehicle start node.
for vehicle_id in range(data['num_days']):
index = routing.Start(vehicle_id)
end_index = routing.End(vehicle_id)
print(end_index)
time_dimension.CumulVar(index).SetRange(data['time_windows'][0][0],
data['time_windows'][0][1])
time_dimension.CumulVar(end_index).SetRange(data['time_windows'][17][0],
data['time_windows'][17][1])
for i in range(data['num_days']):
routing.AddVariableMinimizedByFinalizer(time_dimension.CumulVar(routing.Start(i)))
routing.AddVariableMinimizedByFinalizer(time_dimension.CumulVar(routing.End(i)))
time_dimension.SetSpanCostCoefficientForAllVehicles(200)
# 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)
# Print solution on console.
if solution:
print_solution(data, manager, routing, solution)
if __name__ == '__main__':
main()
Every time I run the code for more than 2 vehicles this is the error that I am getting:每次我为超过 2 辆车运行代码时,这就是我得到的错误:
RuntimeError: SWIG std::function invocation failed.
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/travelapp/PycharmProjects/TravelApp/venv/lib/python3.7/site-packages/ortools/constraint_solver/pywrapcp.py", line 2136, in <lambda>
__setattr__ = lambda self, name, value: _swig_setattr(self, Assignment, name, value)
File "/Users/travelapp/PycharmProjects/TravelApp/venv/lib/python3.7/site-packages/ortools/constraint_solver/pywrapcp.py", line 71, in _swig_setattr
return _swig_setattr_nondynamic(self, class_type, name, value, 0)
File "/Users/travelapp/PycharmProjects/TravelApp/venv/lib/python3.7/site-packages/ortools/constraint_solver/pywrapcp.py", line 55, in _swig_setattr_nondynamic
if type(value).__name__ == 'SwigPyObject':
SystemError: <class 'type'> returned a result with an error set
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/travelapp/Library/Preferences/PyCharmCE2019.1/scratches/scratch.py", line 150, in <module>
main()
File "/Users/travelapp/Library/Preferences/PyCharmCE2019.1/scratches/scratch.py", line 142, in main
solution = routing.SolveWithParameters(search_parameters)
File "/Users/travelapp/PycharmProjects/TravelApp/venv/lib/python3.7/site-packages/ortools/constraint_solver/pywrapcp.py", line 3464, in SolveWithParameters
return _pywrapcp.RoutingModel_SolveWithParameters(self, search_parameters, solutions)
SystemError: <built-in function RoutingModel_SolveWithParameters> returned a result with an error set
For 1 or 2 vehicles I am getting None
as the solution.对于 1 或 2 辆车,我得到
None
作为解决方案。 This may be due to infeasibility of a trip for 2 vehicles.这可能是由于 2 辆车的行程不可行。
For each vehicle create one dummy node for the start, and one for the end, then restrict the vehicle var of these nodes to the vehicle.对于每辆车,为开始创建一个虚拟节点,为结束创建一个虚拟节点,然后将这些节点的车辆变量限制为车辆。 make these nodes optional.
使这些节点可选。
Now tweak the distance matrix such that there are no arcs between the depot and any nodes.现在调整距离矩阵,使得仓库和任何节点之间没有弧线。 There are only arcs from the depot to the dummy start nodes, and from the dummy end nodes to the depot.
只有从仓库到虚拟起始节点,以及从虚拟结束节点到仓库的弧。
Now, it should be easy to add time constraints on these dummy nodes.现在,应该很容易在这些虚拟节点上添加时间限制。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.