首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >不同起止点有时间窗的车辆路径问题

不同起止点有时间窗的车辆路径问题
EN

Stack Overflow用户
提问于 2019-07-21 22:52:25
回答 1查看 1.1K关注 0票数 1

我正在尝试写一个旅行计划,我正在使用谷歌的ORtools。我试图解决的问题是,每辆车都有不同的起点和终点,所有的服务都有不同的起点和终点时间。即使仓库也有不同的开始和结束时间,这需要作为约束添加。我一直在关注google文档中的两个示例:

我已经搜索了所有可用于ortools的文档,但还没有找到为什么会发生这个错误的原因。根据文档,我试图做的事情是可能的,我写的代码应该会给出正确的结果。

下面是我正在做的事情的示例代码:

代码语言:javascript
复制
"""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()

每次我运行超过2辆车的代码时,这就是我得到的错误:

代码语言:javascript
复制
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

对于1辆或2辆车,我使用None作为解决方案。这可能是因为两辆车的行程不可行。

EN

回答 1

Stack Overflow用户

发布于 2019-07-22 00:29:17

对于每个车辆,分别为开始和结束创建一个虚拟节点,然后将这些节点的车辆变量限制为车辆。将这些节点设为可选。

现在调整距离矩阵,使仓库和任何节点之间没有圆弧。只有从仓库到虚拟开始节点的圆弧,以及从虚拟结束节点到仓库的圆弧。

现在,在这些虚拟节点上添加时间约束应该很容易。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57134292

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档