【问题标题】:Broadcast Schedule Selection广播时间表选择
【发布时间】:2019-10-08 09:24:54
【问题描述】:

我为 11 支球队制定了为期 11 周的比赛时间表(每周 5 场比赛)。我需要尝试从该列表中选择 11 场比赛(每周 1 场),为 11 支球队中的每支球队提供一场主场和一场客场比赛的转播。理想情况下,这将是我可以在未来几年重复使用的代码,并且如果需要,我可以扩展到更多的团队和几周。

我知道为给定的、已创建的时间表找到可行解决方案的可能性极低,而且在许多情况下不存在解决方案。因此,当不存在上述类型的解决方案时,我想获得一个接近的时间表。也就是说,所有球队都得到两次转播,但有些球队可能会得到两场主场比赛或两场客场比赛,而不是每场比赛一场。

我查看了几种不同的方法。我有许多 5x2(客队,主队)数组(每周对决),我试图在条件下运行排序/选择(如 a_1 =\= a_j j>1 和 a_i in {1..11} ) 上,但我不知道如何让双重限制选择起作用,而且当它没有更多可行的选择时,我不知道如何让它回到以前的选择。我尝试过暴力破解,但 4000 万种可能的组合超出了我的处理能力。

我正在使用 MATLab 来执行所有工作。我通常可以将 C 或 C++ 转换为 MATLab 可用代码。

【问题讨论】:

  • 不要使用枚举! :) 这是整数编程方法的完美设置。
  • 感谢拉里的建议。我已经考虑过 LP/IP 路由,但我找不到很好的问题约束。不是很有创造力的诅咒。我再看看能不能开发点东西。

标签: multipleselection operations-research


【解决方案1】:

这似乎是一个有趣的问题,所以我尝试将其制定为 IP。

JT 成为团队和周的集合。

G成为所有游戏的集合; G 的每个元素都是一个元组 (i,j,t),表示客队 (i)、主队 (j) 和周 (t)。

H成为所有主场比赛的集合; H 的每个元素都是一个元组 (j,t),表示主队 (j) 和周 (t)。

定义以下二元决策变量:

  • w[j,t] = 1 如果我们在t 周内通过j 广播主场比赛,则= 0 否则(为(j,t) in H 定义)
  • x[j] = 1 如果球队j 有客场转播,= 0 否则(在J 中为j 定义)
  • y[j] = 1 如果球队j 有主场比赛转播,= 0 否则(在J 中为j 定义)
  • z[j] = 1 如果球队 j 既有客场比赛也有主场比赛转播,= 0 否则(在J 中为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。最后一个约束说一切都必须是二进制的。

我使用 Python/PuLP 使用 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

您可以看到每支球队都有主客场转播。

【讨论】:

  • 很棒的拉里。按照您上面引用的论文的示例,我有一个 Excel 表,其中包含 605 个变量、5 个约束和 1210 个依赖项,我试图让求解器减少这些变量。它不喜欢它。 ;-) 这正是我正在寻找和需要的解决方案。我已经对其进行了调整,以解决我也遇到的一些较大的调度问题。
  • 太棒了。乐意效劳。你介意我问这是什么运动和/或联赛吗?
  • 这是在中西部举行的小型 NAIA(大学而非 NCAA)会议。我们正在与 ESPN3 合作转播足球和篮球比赛。会议有不同数量的足球队和篮球队,这就是我需要可扩展代码的原因。
  • 太棒了。我会继续关注。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多