我一直试图理解为什么我的这段使用库
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()
是的,内核崩溃是因为
solver
被破坏(超出范围),而您仍然保留对其变量的引用或尝试调用其方法。在 Python 中,您必须将 solver 或 routing model 保留在范围内,直到您真正完成它。返回(或存储)求解器对象,或仅返回原始解决方案数据,可以避免崩溃。
在 Jupyter 笔记本(或任何环境)中使用 OR-Tools 时,如果您构建代码以使求解器成为函数中的局部变量,并且您仍然想在之后检查变量,那么这是一个常见的陷阱。最简单的解决方法是: