0

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

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

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

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

4

1 回答 1

1

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

JT成为一组团队和周。

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

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

定义以下二元决策变量:

  • w[j,t] = 1j如果我们在一周内广播主场比赛t= 0否则(定义为(j,t) in H
  • x[j] = 1如果球队j有客场比赛转播,= 0否则(定义为jin J
  • y[j] = 1如果球队j有主场比赛转播,= 0否则(定义为jin J
  • z[j] = 1如果球队j既有客场比赛也有主场比赛转播,= 0否则(定义为jin 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

您可以看到每支球队都获得了主场和客场广播。

于 2019-05-22T13:51:30.420 回答