库“ortools”使 jupyter 笔记本上的内核崩溃

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

我一直试图理解为什么我的这段使用库

ortools
的代码会导致jupyter笔记本内核崩溃。由于我不熟悉该库,因此我无法提供更多详细信息,而是提供我运行的代码。感谢您提前提出建议。

from ortools.linear_solver import pywraplp
from ortools.constraint_solver import routing_enums_pb2
from ortools.constraint_solver import pywrapcp


# Define the geographical coordinates and names of locations
locations = {
    "Kabul": (34.52933, 69.12532),
    "Tirana": (41.32755, 19.8187),
    "Algiers": (36.75377, 3.05876),
    "Andorra la Vella": (42.50729, 1.5218),
    "Luanda": (-8.81155, 13.242),
    "Buenos Aires": (-34.60372, -58.38159),
    "Yerevan": (40.18111, 44.51361),
}

# Time spent per location
SOLVER_TIME_LIMIT=30

# Time spent per location
VEHICLE_LOCATION_TIME_LIMIT=100

# maximum time per each location
MAX_ROUTING_TIME_LIMIT=100000

# don't force start cumul to zero
IS_CUMUL_ZERO=False

# no slack
SLACK_AMOUNT=0

# Create a distance matrix based on the Haversine distance (spherical distance)
def haversine(coord1, coord2):
    import math

    lat1, lon1 = coord1
    lat2, lon2 = coord2

    radius = 6371  # Radius of the Earth in kilometers

    dlat = math.radians(lat2 - lat1)
    dlon = math.radians(lon2 - lon1)

    a = (
        math.sin(dlat / 2) * math.sin(dlat / 2) +
        math.cos(math.radians(lat1)) * math.cos(math.radians(lat2)) *
        math.sin(dlon / 2) * math.sin(dlon / 2)
    )

    c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
    distance = radius * c

    return distance

num_locations = len(locations)
distance_matrix = [[0] * num_locations for _ in range(num_locations)]

for i in range(num_locations):
    for j in range(num_locations):
        if i != j:
            points_keys=list(locations.keys())
            
            P_i=locations[points_keys[i]]
            P_j=locations[points_keys[j]]
            
            distance_matrix[i][j] = haversine(P_i, P_j)

# Create a routing model
def create_routing_model(distance_matrix, depot, num_vehicles):
    tsp_size = len(distance_matrix)

    manager = pywrapcp.RoutingIndexManager(tsp_size, num_vehicles, depot)
    routing = pywrapcp.RoutingModel(manager)

    # Set the cost function (distance matrix)
    def distance_callback(from_index, to_index):
        from_node = manager.IndexToNode(from_index)
        to_node = manager.IndexToNode(to_index)
        
        return distance_matrix[from_node][to_node]

    transit_callback_index = routing.RegisterTransitCallback(distance_callback)
    routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)

    # Set 10 seconds as the maximum time allowed per each visit
    dimension_name="Time"
    
    routing.AddDimension(
        transit_callback_index,
        SLACK_AMOUNT,             
        MAX_ROUTING_TIME_LIMIT,
        IS_CUMUL_ZERO,
        dimension_name
    )
    
    # Set a time limit per each location
    time_dimension = routing.GetDimensionOrDie(dimension_name)
    time_dimension.SetSpanUpperBoundForVehicle(LOCATION_TIME_LIMIT)

    return routing, manager

# Solve the problem
def solve_routing_problem():
    # Number of vehicles (1 for a basic TSP)
    num_vehicles = 1
    
    # The depot is the first location in the list
    depot = 0
    
    routing, search_parameters = create_routing_model(distance_matrix, num_vehicles, depot)
    
    # Set a time limit for the solver
    search_parameters.time_limit.seconds = SOLVER_TIME_LIMIT
    
    solution = routing.SolveWithParameters(search_parameters)
    
    if solution:
        print_solution(routing, solution)

# Print the solution
def print_solution(routing, solution):
    print("Objective: {} km".format(solution.ObjectiveValue()))
    
    index = routing.Start(0)
    plan_output = "Route:\n"
    route_distance = 0
    
    while not routing.IsEnd(index):
        node=routing.IndexToNode(index)
        route=list(locations.keys())[node]
        value=solution.Value(routing.NextVar(index))
        
        plan_output += " -> {} ({} km)\n".format(route, value)
        previous_index = index
        
        index = solution.Value(routing.NextVar(index))
        route_distance += routing.GetArcCostForVehicle(previous_index, index, 0)
    
    print(plan_output)
    print("Total Distance: {} km".format(route_distance))

if __name__ == "__main__":
    solve_routing_problem()
or-tools
1个回答
0
投票

是的,内核崩溃是因为

solver
被破坏(超出范围),而您仍然保留对其变量的引用或尝试调用其方法。在 Python 中,您必须将 solverrouting model 保留在范围内,直到您真正完成它。返回(或存储)求解器对象,或仅返回原始解决方案数据,可以避免崩溃。

在 Jupyter 笔记本(或任何环境)中使用 OR-Tools 时,如果您构建代码以使求解器成为函数中的局部变量,并且您仍然想在之后检查变量,那么这是一个常见的陷阱。最简单的解决方法是:

  • 保持解算器对象处于活动状态(例如作为全局对象或从函数中返回它)。
  • 或者完全求解并提取函数内的所有解决方案信息,仅返回纯 Python 数据(浮点数、列表、字典),以便不保留对被破坏的求解器的引用。 这应该可以防止“库或工具在 jupyter 笔记本上崩溃内核”问题,并帮助其他人避免同样的困惑。
© www.soinside.com 2019 - 2024. All rights reserved.