这似乎是一个有趣的问题,所以我尝试将其制定为 IP。
让J
并T
成为一组团队和周。
让我们G
成为所有游戏的集合;的每个元素G
都是一个元组(i,j,t)
,表示客队 ( i
)、主队 ( j
) 和周 ( t
)。
让H
成为所有主场比赛的集合;的每个元素H
都是一个元组(j,t)
,表示主队 ( j
) 和周 ( t
)。
定义以下二元决策变量:
w[j,t] = 1
j
如果我们在一周内广播主场比赛t
,= 0
否则(定义为(j,t) in H
)
x[j] = 1
如果球队j
有客场比赛转播,= 0
否则(定义为j
in J
)
y[j] = 1
如果球队j
有主场比赛转播,= 0
否则(定义为j
in J
)
z[j] = 1
如果球队j
既有客场比赛也有主场比赛转播,= 0
否则(定义为j
in J
)
那么模型是:
maximize sum {j in J} z[j]
subject to sum {j in J} w[j,t] = 1 for all t
x[j] <= sum {(i,t) in H: (j,i,t) in G} w[i,t] for all j
y[j] <= sum {t in T} w[j,t] for all j
z[j] <= (1/2) * (x[j] + y[j]) for all j
w[j,t], x[j], y[j], z[j] in {0,1}
目标函数计算同时获得主客场转播的球队总数。第一个限制条件是我们每周只需要一个广播。第二个约束条件是x[j]
不能等于 1,除非有一周j
的客场比赛播出。第三个约束y[j]
对家庭广播也一样。第四个约束说z[j]
不能等于 1,除非两者都x[j]
等于y[j]
1。最后一个约束说一切都必须是二进制的。
PuLP
我使用 Python/使用 11 场比赛的时间表编写了这个模型。(显然你会插入你自己的时间表。)
from pulp import *
import numpy as np
# Number of teams, weeks, and games per week.
num_teams = 11
num_weeks = 11
num_games_per_week = 5
# Lists of teams and weeks.
teams = range(1, num_teams+1)
weeks = range(1, num_weeks+1)
# List of game tuples: (i, j, t) means team i plays at team j in week t.
games = [(1, 10, 1), (2, 9, 1), (3, 8, 1), (4, 7, 1), (5, 6, 1),
(6, 4, 2), (7, 3, 2), (8, 2, 2), (9, 1, 2), (10, 11, 2),
(2, 11, 3), (3, 10, 3), (4, 9, 3), (5, 8, 3), (6, 7, 3),
(7, 5, 4), (8, 4, 4), (9, 3, 4), (10, 2, 4), (11, 1, 4),
(3, 1, 5), (4, 11, 5), (5, 10, 5), (6, 9, 5), (7, 8, 5),
(8, 6, 6), (9, 5, 6), (10, 4, 6), (11, 3, 6), (1, 2, 6),
(4, 2, 7), (5, 1, 7), (6, 11, 7), (7, 10, 7), (8, 9, 7),
(9, 7, 8), (10, 6, 8), (11, 5, 8), (1, 4, 8), (2, 3, 8),
(5, 3, 9), (6, 2, 9), (7, 1, 9), (8, 11, 9), (9, 10, 9),
(10, 8, 10), (11, 7, 10), (1, 6, 10), (2, 5, 10), (3, 4, 10),
(11, 9, 11), (1, 8, 11), (2, 7, 11), (3, 6, 11), (4, 5, 11)]
# List of home games: (j, t) means there is a home game at j in week t.
home_games = [(j, t) for (i, j, t) in games]
# Initialize problem.
prob = LpProblem('Broadcast', LpMaximize)
# Generate decision variables.
w = LpVariable.dicts('w', home_games, 0, 1, LpInteger)
x = LpVariable.dicts('x', teams, 0, 1, LpInteger)
y = LpVariable.dicts('y', teams, 0, 1, LpInteger)
z = LpVariable.dicts('z', teams, 0, 1, LpInteger)
# Objective function.
prob += lpSum([z[j] for j in teams])
# Constraint: 1 broadcast per week.
for t in weeks:
prob += lpSum([w[j, t] for j in teams if (j, t) in home_games]) == 1
# Constraint: x[j] can only = 1 if we broadcast a game in which j is away team.
for j in teams:
prob += x[j] <= lpSum([w[i, t] for (i, t) in home_games if (j, i, t) in games])
# Constraint: y[j] can only = 1 if we broadcast a game in which j is home team.
for j in teams:
prob += y[j] <= lpSum(([w[j, t] for t in weeks if (j, t) in home_games]))
# Constraint: z[j] can only = 1 if x[j] and y[j] both = 1.
for j in teams:
prob += z[j] <= 0.5 * (x[j] + y[j])
# Solve problem.
prob.solve()
# Print status.
print("Status:", LpStatus[prob.status])
# Print optimal values of decision variables.
for v in prob.variables():
if v.varValue is not None and v.varValue > 0:
print(v.name, "=", v.varValue)
# Prettier print.
print("\nNumber of teams with both home and away broadcasts: {:.0f}".format(np.sum([z[j].value() for j in teams])))
for (i, j, t) in games:
if w[j, t].value() == 1:
print("Week {:2d}: broadcast team {:2d} at team {:2d}".format(t, i, j))
结果是:
Number of teams with both home and away broadcasts: 11
Week 1: broadcast team 1 at team 10
Week 2: broadcast team 10 at team 11
Week 3: broadcast team 5 at team 8
Week 4: broadcast team 8 at team 4
Week 5: broadcast team 6 at team 9
Week 6: broadcast team 11 at team 3
Week 7: broadcast team 4 at team 2
Week 8: broadcast team 9 at team 7
Week 9: broadcast team 7 at team 1
Week 10: broadcast team 2 at team 5
Week 11: broadcast team 3 at team 6
您可以看到每支球队都获得了主场和客场广播。