【问题标题】:Generating natural schedule for a sports league为体育联盟生成自然时间表
【发布时间】:2011-05-06 15:30:35
【问题描述】:

我正在寻找一种算法来为一组 团队。例如,想象一个赛季,每支球队都参加比赛 彼此,一次作为主队,另一次作为客队 另一个团队字段。

生成一个赛季中所有比赛的集合很容易,如果球队是 以下将执行的团队列表:

set((x, y) for x in teams for y in teams if x != y)

但我也想按时间顺序排列游戏 它满足有效比赛时间表的约束的方式,并且还 看起来“自然随机”。

限制是游戏列表应该可以分组为一个数字 每轮由 n / 2 场比赛组成的轮次(其中 n 是 团队数量),其中每个团队与另一个团队配对。

为了让赛程看起来更自然,两支球队不应该各自面对 其他两次在连续回合中。也就是说,如果(a,b)在一个 回合,比赛(b,a)不应该在下一场比赛中进行。

此外,每支球队都应该尽可能地每隔一轮比赛 客队和其他回合作为主队。我不认为 有可能总是满足这个约束,所以更好 有事。例如,一支球队不应该打 8 场主场比赛并且 然后是 8 场客场比赛。

下面是我现在得到的。该算法的主要问题是 它经常卡在while循环中。尤其是当 团队数量为 16 或更多。它也非常低效,因为它 建立在使用随机样本函数的基础上,并希望得到正确的结果:

from random import sample
def season_schedule_order(teams, pairs):
    n_games_per_round = len(teams) // 2
    last_pairs = set()
    while pairs:
        r_pairs = set(sample(pairs, n_games_per_round))
        # Check that each team is present once in the round.
        r_teams = set(x for (x, y) in r_pairs) | set(y for (x, y) in r_pairs)
        if r_teams != teams:
            continue
        # Check that two teams doesn't face each other again.
        rev_pairs = set((y, x) for (x, y) in r_pairs)
        if rev_pairs & last_pairs:
            continue
        pairs -= r_pairs
        for p in r_pairs:
            yield p
        last_pairs = r_pairs

teams = set(['aik', 'djurgarden', 'elfsborg', 'gais',
             'gefle', 'hacken', 'halmstad', 'helsingborg'])
pairs = set((x, y) for x in teams for y in teams if x != y)
for (ht, at) in season_schedule_order(teams, pairs):
    print '%-20s %-20s' % (ht, at)

【问题讨论】:

    标签: python algorithm sorting combinatorics sports-league-scheduling-problem


    【解决方案1】:

    我找到了一个方法here,我稍微适应了这个:

    def round_robin(units, sets = None):
        """ Generates a schedule of "fair" pairings from a list of units """
        count = len(units)
        sets = sets or (count - 1)
        half = count / 2
        for turn in range(sets):
            left = units[:half]
            right = units[count - half - 1 + 1:][::-1]
            pairings = zip(left, right)
            if turn % 2 == 1:
                pairings = [(y, x) for (x, y) in pairings]
            units.insert(1, units.pop())
            yield pairings
    
    teams = ['a', 'b', 'c', 'd']
    print list(round_robin(teams, sets = len(teams) * 2 - 2))
    

    现在我只需要把它变成 plpgsql。 :)

    【讨论】:

    • 产生 [[('1', '5'), ('2', '4')], [('4', '1'), ('3', '5 ')], [('1', '3'), ('4', '2')], [('2', '1'), ('5', '3')]] 例如5 支球队,套数 = 无。这是不正确的。 '2' 队与 '4' 对战两次,而不是与 '3'、'5' 对战。这不是正确的答案。
    【解决方案2】:
    REQUIREMENTS for the BALANCED ROUND ROBIN algorithm
    The requirements of the algorithm can be defined by these four rules:
     1) All versus all
     Each team must meet exactly once, and once only, the other teams in the division league. 
     If the division is composed of n teams, the championship takes place in the n-1 rounds.
    2) Alternations HOME / AWAY rule
    The sequence of alternations HOME / AWAY matches for every teams in the division league, should be retained if possible. 
    For any team in the division league at most once in the sequence of consecutive matches HAHA, occurs the BREAK of the rhythm, i.e. HH or AA match in the two consecutive rounds.
    3) The rule of the last slot number
    The team with the highest slot number must always be positioned in the last row of the grid. 
    For each subsequent iteration the highest slot number of grid alternates left and right position; left column (home) and right (away).
    The system used to compose the league schedule is "counter-clockwise circuit." 
    In the construction of matches in one round of the championship, a division with an even number of teams. 
    If in a division is present odd number of teams, it will be inserted a BYE/Dummy team in the highest slot number of grid/ring.
    4) HH and AA are non-terminal and not initial
     Cadence HH or AA must never happen at the beginning or at the end of the of matches for any team in the division.
     Corrective inversion RULE performs only once, in the bottom line in the RING, LeftRight redundant inversion flip-flop RULE, so we will never obtain in the last two rounds CC or FF.
    Round Robin ALGORITHM
    The algorithm that satisfies rule (1) is obtained with a simple algorithm Round Robin:
    where every successive round is obtained applying to the slot numbers ring a   "counterclockwise" rotation.
    To satisfy the rule (2) we must "improve", the simple round robin algorithm by performing balancing of Home and Away sequence. 
    It is performed by applying several "counterclockwise" rotations in the slot numbers ring in order to obtain acceptable combinations of slot positions for the next round.
    
    The number of rotations required in the ring is (n / 2 -1).
    So we will get that in the two successive rounds, almost all the teams playing at home in the previous round, will play away from home in the next round.
    DATA STRUCTURE
    n_teams: (4,6,8,..,20)
    n_rounds:  n_teams -1;
    

    环 - 电路 环就是这样的数据结构,即一种特定类型的序列,可以执行并在算法上正式定义:环元素之间的(逆时针)旋转操作和INSERT_LAST_TEAM操作, 戒指内容定义了比赛时间表中每个特定回合的所有比赛 Ring.Length 是等于 n_teams 的偶数 Left_ring 子序列:元素从 1 到 n/2 的 Ring 子序列。 Right_ring 子序列:元素从 n/2+1 到 n 的环子序列。 匹配 [i] = Ring_element [ i ] : Ring_element [ n – i + 1 ];其中 i = 1 到 n/2 MATCH 是由两个 TEAMS (Home_team : Away_team) 组成的有序对。 第一轮 家 : 离开 01:07 02:06 03:05 04:08

    Next_Iteration is obtained by applying these rules:
    a)   perform (n/2 – 1) times * ANTI CLOCKWISE ROTATIONs  
    b)   all right column elements, below the last team, will be shifted upwards 
    c)   INSERT_LAST_TEAM 
    (Insert_Last_Element_into_ Ring_onLeft (n) or 
     Insert_Last_Element_into_Ring_onRight(n), alternatively)
    d.1) Last Line LeftRight redundant swap RULE 
    eventually have to swap elements in the last row once again
    d.1) last team left/right - flip/flop
    
    
    
    In the following example it will be explained how the Ring elements of 8 teams 
    are gradually transformed in five steps, 
    from from the SECOND ROUND into the THIRD ROUND.
    If we start from from the SECOND ROUND:
    05 :04
    06 :03
    07 :02
    08 :01
    a. After we perform THREE Anti-clockwise rotations, (n =8, 3 = 8/2 -1)
    we will get the situation like this:
    02 :01
    03 :08
    04 :07
    05 :06
    b. When we apply the LAST SLOT RULE: 
    the right column elements (06,07) below last team (08) will be shifted upwards
    02 :01
    03
    04 :07
    05 :06
    c. And now we will apply the LAST SLOT RULE-bottom right, 
    we will get the situation which describes the THIRD ROUND: 
    (08 must be moved to the bottom right position)
    02 :01
    03 :07
    04 :06
    05 :08
    d.1 Now it will be checked if for this iteration number (i.e. round) 
    depending on CODE SIX or ZERO Cadence, we eventually have to 
    swap elements in the last row redundantly,
    Left/Right swaping
    d.2 And at the end we will apply the LAST TEAM SLOT ROULE
    swap left & right elements, 
    if in the previous iteration last team was positioned on the right, 
    in this iteration it should be positioned on the left bottom position, 
    so the last line elements will be swapped, else do nothing.
    THIRD ROUND:
    02 :01
    03 :07
    04 :06
    05 :08
    

    read more

    Here is the snippet of the code in Perl.

    【讨论】:

    • 很难理解你的答案——请更有选择性地复制和粘贴来解释你链接到的页面与原始问题的相关性,并可能提供代码(或伪代码)概述 Björn 如何利用这些算法。
    • 这里是 Perl 中代码的 sn-p .. constellationsystems.net/constellation/…
    猜你喜欢
    • 2010-11-05
    • 1970-01-01
    • 1970-01-01
    • 2013-08-24
    • 1970-01-01
    • 1970-01-01
    • 2013-08-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多