一个简单的机位分配的demo
from ortools.sat.python import cp_model
import heapq
INF = 10**12
def get_taxi_time_by_dp(plane, stand, airport_map):
"""
动态规划 / 最短路函数:计算某架飞机到某个机位的最短滑行时长。
输入:
plane:
{
"id": "P1",
"start": (0, 0)
}
stand:
{
"id": "G1",
"pos": (4, 5)
}
airport_map:
二维网格地图。
airport_map[r][c] = 0 表示不可通行;
airport_map[r][c] > 0 表示可通行,并表示进入该格子的滑行耗时。
返回:
taxi_time: 最短滑行时长,整数
path: 最短滑行路径
"""
start = plane["start"]
target = stand["pos"]
rows = len(airport_map)
cols = len(airport_map[0])
if airport_map[start[0]][start[1]] == 0:
return INF, []
if airport_map[target[0]][target[1]] == 0:
return INF, []
# dp[r][c] 表示从飞机起点滑行到位置 (r, c) 的最短时长
dp = [[INF for _ in range(cols)] for _ in range(rows)]
parent = [[None for _ in range(cols)] for _ in range(rows)]
dp[start[0]][start[1]] = 0
# 这里用优先队列求最短滑行时长。
# 如果你的机场滑行道是 DAG,也可以替换成严格的拓扑 DP。
heap = [(0, start)]
directions = [
(-1, 0), # 上
(1, 0), # 下
(0, -1), # 左
(0, 1), # 右
]
while heap:
current_time, current = heapq.heappop(heap)
r, c = current
if current_time > dp[r][c]:
continue
if current == target:
break
for dr, dc in directions:
nr = r + dr
nc = c + dc
if nr < 0 or nr >= rows or nc < 0 or nc >= cols:
continue
if airport_map[nr][nc] == 0:
continue
next_time = current_time + airport_map[nr][nc]
if next_time < dp[nr][nc]:
dp[nr][nc] = next_time
parent[nr][nc] = (r, c)
heapq.heappush(heap, (next_time, (nr, nc)))
taxi_time = dp[target[0]][target[1]]
if taxi_time >= INF:
return INF, []
path = []
cur = target
while cur is not None:
path.append(cur)
cur = parent[cur[0]][cur[1]]
path.reverse()
return int(taxi_time), path
def assign_planes_to_stands_by_min_taxi_time(planes, stands, airport_map):
"""
使用 OR-Tools 求解飞机-机位分配问题,使总滑行时长最短。
决策变量:
x[i, j] = 1 表示第 i 架飞机分配到第 j 个机位
目标:
min sum(taxi_time[i, j] * x[i, j])
"""
m = len(planes)
n = len(stands)
if m > n:
raise ValueError(
"飞机数量 m 不能大于机位数量 n,否则无法保证每架飞机都有机位。"
)
model = cp_model.CpModel()
x = {}
taxi_time = {}
taxi_paths = {}
for i in range(m):
for j in range(n):
time_value, path = get_taxi_time_by_dp(planes[i], stands[j], airport_map)
taxi_time[i, j] = time_value
taxi_paths[i, j] = path
x[i, j] = model.NewBoolVar(f"x_{i}_{j}")
# 如果飞机到该机位不可达,则禁止该分配
if time_value >= INF:
model.Add(x[i, j] == 0)
# 每架飞机必须分配到一个机位
for i in range(m):
model.Add(sum(x[i, j] for j in range(n)) == 1)
# 每个机位最多分配一架飞机
for j in range(n):
model.Add(sum(x[i, j] for i in range(m)) <= 1)
# 目标函数:总滑行时长最短
model.Minimize(sum(taxi_time[i, j] * x[i, j] for i in range(m) for j in range(n)))
solver = cp_model.CpSolver()
status = solver.Solve(model)
if status not in (cp_model.OPTIMAL, cp_model.FEASIBLE):
return None
assignments = []
total_taxi_time = 0
for i in range(m):
for j in range(n):
if solver.Value(x[i, j]) == 1:
selected_time = taxi_time[i, j]
total_taxi_time += selected_time
assignments.append(
{
"plane_id": planes[i]["id"],
"stand_id": stands[j]["id"],
"taxi_time": selected_time,
"path": taxi_paths[i, j],
}
)
return {
"total_taxi_time": total_taxi_time,
"assignments": assignments,
}
if __name__ == "__main__":
# m 个飞机
planes = [
{"id": "P1", "start": (0, 0)},
{"id": "P2", "start": (1, 0)},
{"id": "P3", "start": (2, 0)},
]
# n 个机位
stands = [
{"id": "G1", "pos": (3, 3)},
{"id": "G2", "pos": (4, 4)},
{"id": "G3", "pos": (2, 5)},
{"id": "G4", "pos": (5, 5)},
]
# 机场滑行地图
# 0 表示不能通行
# 正数表示进入该位置需要的滑行时长
airport_map = [
[1, 1, 1, 2, 2, 2],
[1, 0, 1, 0, 3, 2],
[1, 1, 1, 1, 2, 1],
[2, 0, 2, 1, 1, 1],
[2, 2, 2, 0, 1, 1],
[3, 3, 2, 1, 1, 1],
]
solution = assign_planes_to_stands_by_min_taxi_time(planes, stands, airport_map)
if solution is None:
print("无可行分配方案")
else:
print("最短总滑行时长:", solution["total_taxi_time"])
print("分配结果:")
for item in solution["assignments"]:
print(
f"飞机 {item['plane_id']} -> 机位 {item['stand_id']}, "
f"滑行时长 = {item['taxi_time']}, "
f"路径 = {item['path']}"
)
漫思
浙公网安备 33010602011771号