我是Google OR工具的新手,当从Jupyter Notebook调用时,我设法使其中一个示例可以工作。但是,当我使用此工作代码并将其打包到python模块中的函数中时,我开始遇到RunTimeError

我在用:

  • Python 3.6.5
  • ortools 7.0.6546
  • jupyter 4.4.0

  • 似乎我缺少使python工具包中提供OR工具的功能。我查找了类似的错误,并遇到了更新distance_callback函数的建议。但是我使用的功能还是建议的版本。

    Jupyter笔记本中的工作代码
    from ortools.constraint_solver import routing_enums_pb2
    from ortools.constraint_solver import pywrapcp
    
    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]
    
    def get_solution(manager, routing, assignment):
        index = routing.Start(0)
        output = [manager.IndexToNode(index)]
        while not routing.IsEnd(index):
            previous_index = index
            index = assignment.Value(routing.NextVar(index))
            output.append(manager.IndexToNode(index))
    
        return np.array(output)
    
    # Create the routing index manager.
    manager = pywrapcp.RoutingIndexManager(
        len(data['distance_matrix']), data['num_vehicles'], data['depot']
    )
    
    # Create Routing Model.
    routing = pywrapcp.RoutingModel(manager)
    
    transit_callback_index = routing.RegisterTransitCallback(distance_callback)
    
    # Define cost of each arc.
    routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)
    
    # Setting first solution heuristic.
    search_parameters = pywrapcp.DefaultRoutingSearchParameters()
    
    search_parameters.first_solution_strategy = (
        routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC
    )
    
    search_parameters.time_limit.seconds = 30
    
    # Solve the problem.
    assignment = routing.SolveWithParameters(search_parameters)
    
    x = get_solution(manager, routing, assignment)
    

    python模块中包含的功能
    def packaged_function(data):
        # Create the routing index manager.
        manager = pywrapcp.RoutingIndexManager(
            len(data['distance_matrix']), data['num_vehicles'], data['depot']
        )
    
        # Create Routing Model.
        routing = pywrapcp.RoutingModel(manager)
    
        transit_callback_index = routing.RegisterTransitCallback(distance_callback)
    
        # Define cost of each arc.
        routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)
    
        # Setting first solution heuristic.
        search_parameters = pywrapcp.DefaultRoutingSearchParameters()
    
        search_parameters.first_solution_strategy = (
            routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC
        )
    
        search_parameters.time_limit.seconds = 30
    
        # Solve the problem.
        assignment = routing.SolveWithParameters(search_parameters)
    
        return (manager, routing, assignment)
    

    从Jupyter调用函数
    from package_name.router import packaged_function
    output = packaged_function(data)
    

    当我以这种方式执行 call 时,我会遇到一些错误,即:
    RuntimeError                              Traceback (most recent call last)
    RuntimeError: SWIG std::function invocation failed.
    
    The above exception was the direct cause of the following exception:
    
    SystemError                               Traceback (most recent call last)
    /usr/local/lib/python3.6/site-packages/ortools/constraint_solver/pywrapcp.py in <lambda>(self, name, value)
       2135         __swig_setmethods__.update(getattr(_s, '__swig_setmethods__', {}))
    -> 2136     __setattr__ = lambda self, name, value: _swig_setattr(self, Assignment, name, value)
       2137     __swig_getmethods__ = {}
    
    /usr/local/lib/python3.6/site-packages/ortools/constraint_solver/pywrapcp.py in _swig_setattr(self, class_type, name, value)
         70 def _swig_setattr(self, class_type, name, value):
    ---> 71     return _swig_setattr_nondynamic(self, class_type, name, value, 0)
         72
    
    /usr/local/lib/python3.6/site-packages/ortools/constraint_solver/pywrapcp.py in _swig_setattr_nondynamic(self, class_type, name, value, static)
         54     if (name == "this"):
    ---> 55         if type(value).__name__ == 'SwigPyObject':
         56             self.__dict__[name] = value
    
    SystemError: <class 'type'> returned a result with an error set
    
    The above exception was the direct cause of the following exception:
    
    SystemError                               Traceback (most recent call last)
        233
        234     # Solve the problem.
    --> 235     assignment = routing.SolveWithParameters(search_parameters)
        236
        237     return (manager, routing, assignment)
    
    /usr/local/lib/python3.6/site-packages/ortools/constraint_solver/pywrapcp.py in SolveWithParameters(self, search_parameters, solutions)
       3423
       3424     def SolveWithParameters(self, search_parameters: 'operations_research::RoutingSearchParameters const &', solutions: 'std::vector< operations_research::Assignment const * > *'=None) -> "operations_research::Assignment const *":
    -> 3425         return _pywrapcp.RoutingModel_SolveWithParameters(self, search_parameters, solutions)
       3426
       3427     def SolveFromAssignmentWithParameters(self, assignment: 'Assignment', search_parameters: 'operations_research::RoutingSearchParameters const &', solutions: 'std::vector< operations_research::Assignment const * > *'=None) -> "operations_research::Assignment const *":
    
    SystemError: <built-in function RoutingModel_SolveWithParameters> returned a result with an error set
    

    最佳答案

    您必须在packaged_function()中移动distance_callback定义

    例如

    package_function.py:

    from ortools.constraint_solver import routing_enums_pb2
    from ortools.constraint_solver import pywrapcp
    
    def packaged_function(data):
        # Create the routing index manager.
        manager = pywrapcp.RoutingIndexManager(
            len(data['distance_matrix']), data['num_vehicles'], data['depot']
        )
    
        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]
    
        # Create Routing Model.
        routing = pywrapcp.RoutingModel(manager)
    
        transit_callback_index = routing.RegisterTransitCallback(distance_callback)
    
        # Define cost of each arc.
        routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)
    
        # Setting first solution heuristic.
        search_parameters = pywrapcp.DefaultRoutingSearchParameters()
    
        search_parameters.first_solution_strategy = (
            routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC
        )
    
        search_parameters.time_limit.seconds = 30
    
        # Solve the problem.
        assignment = routing.SolveWithParameters(search_parameters)
    
        return (manager, routing, assignment)
    

    和test.py:

    from packaged_function import packaged_function as pf
    
    def print_solution(manager, routing, assignment):
        """Prints assignment on console."""
        print('Objective: {} miles'.format(assignment.ObjectiveValue()))
        index = routing.Start(0)
        plan_output = 'Route for vehicle 0:\n'
        route_distance = 0
        while not routing.IsEnd(index):
            plan_output += ' {} ->'.format(manager.IndexToNode(index))
            previous_index = index
            index = assignment.Value(routing.NextVar(index))
            route_distance += routing.GetArcCostForVehicle(previous_index, index, 0)
        plan_output += ' {}\n'.format(manager.IndexToNode(index))
        print(plan_output)
        plan_output += 'Route distance: {}miles\n'.format(route_distance)
    
    def main():
        data = {}
        data['distance_matrix'] = [
                [0, 2451, 713, 1018, 1631, 1374, 2408, 213, 2571, 875, 1420, 2145, 1972],
                [2451, 0, 1745, 1524, 831, 1240, 959, 2596, 403, 1589, 1374, 357, 579],
                [713, 1745, 0, 355, 920, 803, 1737, 851, 1858, 262, 940, 1453, 1260],
                [1018, 1524, 355, 0, 700, 862, 1395, 1123, 1584, 466, 1056, 1280, 987],
                [1631, 831, 920, 700, 0, 663, 1021, 1769, 949, 796, 879, 586, 371],
                [1374, 1240, 803, 862, 663, 0, 1681, 1551, 1765, 547, 225, 887, 999],
                [2408, 959, 1737, 1395, 1021, 1681, 0, 2493, 678, 1724, 1891, 1114, 701],
                [213, 2596, 851, 1123, 1769, 1551, 2493, 0, 2699, 1038, 1605, 2300, 2099],
                [2571, 403, 1858, 1584, 949, 1765, 678, 2699, 0, 1744, 1645, 653, 600],
                [875, 1589, 262, 466, 796, 547, 1724, 1038, 1744, 0, 679, 1272, 1162],
                [1420, 1374, 940, 1056, 879, 225, 1891, 1605, 1645, 679, 0, 1017, 1200],
                [2145, 357, 1453, 1280, 586, 887, 1114, 2300, 653, 1272, 1017, 0, 504],
                [1972, 579, 1260, 987, 371, 999, 701, 2099, 600, 1162, 1200, 504, 0],
            ] # yapf: disable
        data['num_vehicles'] = 1
        data['depot'] = 0
    
        (manager, routing, assignment) = pf(data)
        print_solution(manager, routing, assignment)
    
    if __name__ == '__main__':
        main()
    

    输出

    python test.py
    Objective: 7293 miles
    Route for vehicle 0:
     0 -> 7 -> 2 -> 3 -> 4 -> 12 -> 6 -> 8 -> 1 -> 11 -> 10 -> 5 -> 9 -> 0
    

    注意:如果我将distance_callback移到def packaged_function()之前,我可以重现您的错误

    关于python - 从Python包中调用Python OR-tools函数不起作用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55862927/

    10-11 03:29
    查看更多