Search code examples
round-robintournament

Tournament pairing algorithm, groups of 4 as round robin, then swiss?


I'm looking for a combination of Swiss and round robin paring. We have a (volleyball) tournament that spans 4 weeks. Some 64 teams are divided into 16 groups of 4 teams, the first round is based on geography. In each group, every team plays against all other teams. After the first round of 3 matches per team, I'd like to apply some Swiss paring to make new groups of teams of equal strength, geography is less important. Similarly, after the second and third round, new groups should be created using Swiss. After the fourth round a winner is announced per group.

Is there an algorithm for this, especially for the Swiss pairing part?

TIA


Solution

  • For your scenario of 4 rounds, with 16 groups of 4, we can precompute the matchups based on the results of each round according to the following algorithm.

    • Here we define Swiss as no two teams being assigned to the same group in subsequent rounds, but for each round the teams are matched up according to skill/ability such that the top ranked teams only play other top ranked teams.

    Round 2:

    R2 Group 1

    • #1 from Group 1
    • #1 from Group 2
    • #1 from Group 3
    • #1 from Group 4

    R2 Group 2

    • #1 from Group 5
    • #1 from Group 6
    • #1 from Group 7
    • #1 from Group 8

    R2 Group 3

    • #1 from Group 9
    • #1 from Group 10
    • #1 from Group 11
    • #1 from Group 12

    R2 Group 4

    • #1 from Group 13
    • #1 from Group 14
    • #1 from Group 15
    • #1 from Group 16

    R2 Group 5

    • #2 from Group 1
    • #2 from Group 2
    • #2 from Group 3
    • #2 from Group 4

    ...

    R2 Group 16

    • #4 from Group 13
    • #4 from Group 14
    • #4 from Group 15
    • #4 from Group 16

    This hardcoded schedule should be the same that you would get from applying the swiss procedure, but after round 2, the top teams have still not seen each other, so instead of dynamically allocating we can use the fixed outcomes from Round 1 and are guaranteed that the teams have not played each other:

    R3 Group 1

    • #1 from R2 Group 1 (Only played #1 R1G1-4)
    • #1 from R2 Group 2 (Only played #1 R1G5-8)
    • #1 from R2 Group 3 (Only played #1 R1G9-12)
    • #1 from R2 Group 4 (Only played #1 R1G13-16)

    R3 Group 2

    • #1 from R2 Group 5 (Only played #2 R1G1-4)
    • #1 from R2 Group 6 (Only played #2 R1G5-8)
    • #1 from R2 Group 7 (Only played #2 R1G9-12)
    • #1 from R2 Group 8 (Only played #2 R1G13-16)

    R3 Group 2

    • #1 from R2 Group 9 (Only played #3 R1G1-4)
    • #1 from R2 Group 10 (Only played #3 R1G5-8)
    • #1 from R2 Group 11 (Only played #3 R1G9-12)
    • #1 from R2 Group 12 (Only played #3 R1G13-16)

    ...

    R3 Group 16

    • #4 from R2 Group 13 (Only played #4 R1G1-4)
    • #4 from R2 Group 14 (Only played #4 R1G5-8)
    • #4 from R2 Group 15 (Only played #4 R1G9-12)
    • #4 from R2 Group 16 (Only played #4 R1G13-16)

    We can again apply the same logic to the 4th Round, but round 4 is the last time that this can guarantee unique pairings:

    Round 4

    R4 Group 1

    • #1 from R3 Group 1 (Only played #1 R1, #1 R2G1-4)
    • #1 from R3 Group 2 (Only played #2 R1, #1 R2G5-8)
    • #1 from R3 Group 3 (Only played #3 R1, #1 R2G9-12)
    • #1 from R3 Group 4 (Only played #4 R1, #1 R2G13-16)

    R4 Group 2

    • #1 from R3 Group 5 (Only played #2 R1G1-4)
    • #1 from R3 Group 6 (Only played #2 R1G5-8)
    • #1 from R3 Group 7 (Only played #2 R1G9-12)
    • #1 from R3 Group 8 (Only played #2 R1G13-16)

    ...

    R4 Group 16

    • #4 from R3 Group 13 (Only played #4 R1G1-4)
    • #4 from R3 Group 14 (Only played #4 R1G5-8)
    • #4 from R3 Group 15 (Only played #4 R1G9-12)
    • #4 from R3 Group 16 (Only played #4 R1G13-16)

    After 4 swiss rounds, if we were to apply this logic again then some teams WILL play each other again. Ideally if you want an overall winner you might choose to cull the list based on overall ranking and start again fresh (so ignore the previous matches for the purpose/rules of swissing) or use a round-robin approach from there.

    If you wanted to continue swissing past the 4th round for this dataset and maintain that no team plays each other twice you can rank all the teams into a list. Then apply the swissing logic, but instead of checking against 1 opponent, check against the next 3.

    Treat this as a sorting algorithm, following these steps:

    1. Take the top 4
    2. #1 team stays at the top
    3. If #2 team has played #1, #3, #4 (any of the top 4), move them to the next group (placeholder for now)
    4. Take the next team from the original list (#5) ...

    Cycle through the teams until you have the first group. Then take the teams from the placeholder group (maintaining the ranked order) with the remainder of the original list and begin the process again.

    UPDATE:

    I've put together a fiddle that demonstrates 1 application of the above matrix vs a brute force or dynamically allocated Swiss style draw: https://dotnetfiddle.net/XF0gkl

    In this proof, the Team number indicates their relative skill rank. To make the outcome predictable, the higher rank will always win. The teams are randomly distributed at the start, but you can see (in the final table at the end) for both the pre-computed matrix and the dynamic draw that the higher skilled teams come to the relative top over the 4 rounds.

    • In both outcomes 15 of the top 16 skilled teams end up in the top 16 overall ranked teams.
    • In the Matrix there are 6 of the top 8 skilled in the top 8 ranked
    • In the Dynamic there are 7 of the top 8 skilled in the top 8 ranked
    • The top 16 is adequate to now run a knockout or round robin tournament to find an overall winner.
    • Top 8 in the matrix misses team #4, who would want to appeal if they missed out on the finals, #6 would probably also protest in the dynamic

    Overall, even though the group stage does a good job (via either method) to identify the best teams, 4 rounds in groups of 4 is not conclusive enough to produce outright winners alone, but for only playing 12 teams out of the 64, it's not bad.

    Key: Team (score) G[group]

    RANK Round 4 Matrix Round 4 Dynamic
    #1 1 (34) G[ 3] 1 (33) G[ 1]
    #2 3 (33) G[ 2] 10 (31) G[ 4]
    #3 2 (33) G[ 1] 2 (31) G[ 1]
    #4 5 (32) G[ 5] 3 (30) G[ 1]
    #5 9 (31) G[ 7] 7 (29) G[ 2]
    #6 6 (31) G[ 1] 4 (29) G[ 2]
    #7 7 (31) G[ 6] 5 (29) G[ 2]
    #8 11 (31) G[10] 8 (29) G[ 2]
    #9 8 (31) G[ 1] 16 (29) G[ 5]
    #10 12 (30) G[ 4] 9 (28) G[ 3]
    #11 13 (30) G[13] 12 (28) G[ 3]
    #12 14 (30) G[ 9] 6 (28) G[ 1]
    #13 4 (30) G[ 5] 13 (28) G[ 3]
    #14 10 (30) G[ 2] 24 (28) G[ 7]
    #15 18 (29) G[11] 11 (28) G[ 3]
    #16 16 (29) G[ 6] 14 (28) G[ 5]
    #17 17 (28) G[ 9] 19 (28) G[ 8]
    #18 21 (28) G[14] 15 (28) G[ 4]
    #19 22 (28) G[ 3] 17 (26) G[ 6]
    #20 19 (28) G[ 8] 21 (26) G[10]
    #21 20 (27) G[13] 18 (26) G[ 6]
    #22 35 (27) G[ 4] 20 (26) G[ 6]
    #23 27 (26) G[14] 29 (26) G[ 7]
    #24 15 (26) G[ 2] 32 (25) G[ 8]
    #25 32 (25) G[12] 27 (25) G[ 9]
    #26 30 (25) G[10] 31 (25) G[ 9]
    #27 36 (25) G[ 8] 28 (25) G[ 9]
    #28 24 (25) G[15] 26 (25) G[ 4]
    #29 28 (25) G[ 3] 23 (25) G[ 4]
    #30 34 (24) G[ 7] 30 (24) G[10]
    #31 29 (24) G[ 9] 22 (24) G[ 5]
    #32 33 (24) G[ 6] 33 (24) G[13]
    #33 31 (24) G[ 7] 40 (24) G[11]
    #34 26 (24) G[ 5] 25 (24) G[ 5]
    #35 23 (24) G[ 1] 38 (24) G[11]
    #36 40 (23) G[16] 37 (24) G[ 8]
    #37 25 (23) G[ 5] 39 (23) G[12]
    #38 39 (22) G[11] 41 (23) G[12]
    #39 42 (22) G[15] 36 (23) G[ 7]
    #40 43 (22) G[16] 34 (23) G[ 7]
    #41 44 (21) G[ 2] 35 (23) G[ 6]
    #42 46 (21) G[12] 44 (22) G[13]
    #43 48 (21) G[14] 51 (22) G[14]
    #44 45 (21) G[10] 42 (21) G[ 8]
    #45 54 (21) G[ 4] 46 (21) G[ 9]
    #46 47 (20) G[ 6] 53 (21) G[14]
    #47 37 (20) G[13] 43 (21) G[10]
    #48 51 (20) G[10] 54 (21) G[15]
    #49 38 (20) G[ 9] 52 (21) G[14]
    #50 49 (19) G[11] 45 (21) G[10]
    #51 41 (19) G[13] 49 (20) G[12]
    #52 55 (19) G[ 8] 50 (20) G[13]
    #53 53 (19) G[11] 48 (20) G[11]
    #54 52 (19) G[ 7] 47 (20) G[11]
    #55 50 (18) G[15] 57 (20) G[15]
    #56 56 (18) G[ 3] 56 (20) G[14]
    #57 58 (17) G[ 4] 59 (19) G[15]
    #58 60 (17) G[12] 55 (18) G[12]
    #59 57 (17) G[14] 58 (18) G[13]
    #60 59 (16) G[12] 60 (18) G[16]
    #61 64 (16) G[16] 64 (17) G[16]
    #62 62 (15) G[ 8] 62 (17) G[16]
    #63 61 (15) G[16] 61 (17) G[16]
    #64 63 (13) G[15] 63 (16) G[15]