从Python包中调用时,Python OR-tools函数不起作用

问题描述 投票:1回答:1

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

我在用:

  • Python 3.6.5
  • ortools 7.0.6546
  • jupyter 4.4.0

看来我错过了在我的python包中提供OR工具的东西。我查了一个类似的错误并遇到了更新distance_callback函数的建议。但我正在使用的功能是建议的版本。

Working Code in Jupyter notebook

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)

Function contained in python module

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)

Calling function from Jupyter

from package_name.router import packaged_function
output = packaged_function(data)

当我以这种方式执行调用时,我最终会遇到一些错误,即:

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
python package runtime-error swig or-tools
1个回答
2
投票

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

EG

package_function.朋友:

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()我可以重现你的错误

© www.soinside.com 2019 - 2024. All rights reserved.