diff options
| -rw-r--r-- | augment.py | 12 |
1 files changed, 11 insertions, 1 deletions
| @@ -8,6 +8,7 @@ tabelle = [] | |||
| 8 | with open('data.json') as f: | 8 | with open('data.json') as f: |
| 9 | data = json.load(f) | 9 | data = json.load(f) |
| 10 | 10 | ||
| 11 | # Augment example orte with Raucher flag | ||
| 11 | ident = 0 | 12 | ident = 0 |
| 12 | for o in data["orte"]: | 13 | for o in data["orte"]: |
| 13 | o["id"] = ident | 14 | o["id"] = ident |
| @@ -15,6 +16,7 @@ for o in data["orte"]: | |||
| 15 | o["teams"] = [] | 16 | o["teams"] = [] |
| 16 | ident += 1 | 17 | ident += 1 |
| 17 | 18 | ||
| 19 | # Augment example teams with weekday, league and Raucher flag | ||
| 18 | ident = 0 | 20 | ident = 0 |
| 19 | for t in data["teams"]: | 21 | for t in data["teams"]: |
| 20 | 22 | ||
| @@ -59,7 +61,7 @@ for league in range(league_count): | |||
| 59 | 61 | ||
| 60 | print( "Max Spieltage: ", max_spieltage) | 62 | print( "Max Spieltage: ", max_spieltage) |
| 61 | 63 | ||
| 62 | # Fill Tabelle with our demo data | 64 | # Generate all pairings with our demo data, making up wildcards as we go |
| 63 | ident = 0 | 65 | ident = 0 |
| 64 | for league in range(league_count): | 66 | for league in range(league_count): |
| 65 | league_teams = [t for t in data["teams"] if t["liga"] == league] | 67 | league_teams = [t for t in data["teams"] if t["liga"] == league] |
| @@ -80,6 +82,7 @@ for league in range(league_count): | |||
| 80 | ident += 1 | 82 | ident += 1 |
| 81 | game_count += 1 | 83 | game_count += 1 |
| 82 | 84 | ||
| 85 | # For leagues with fewer Spieltage, fill up the remainder with wildcard games | ||
| 83 | while game_count < max_spieltage / 2: | 86 | while game_count < max_spieltage / 2: |
| 84 | tabelle.append({"team_a": team_a["id"], "team_b": -1, "liga": league, "ort": -1, "tag": -1, "id": ident}) | 87 | tabelle.append({"team_a": team_a["id"], "team_b": -1, "liga": league, "ort": -1, "tag": -1, "id": ident}) |
| 85 | ident += 1 | 88 | ident += 1 |
| @@ -87,11 +90,13 @@ for league in range(league_count): | |||
| 87 | ident += 1 | 90 | ident += 1 |
| 88 | game_count += 1 | 91 | game_count += 1 |
| 89 | 92 | ||
| 93 | # To ensure that Rueckspiele only happen in Rueckrunde, this is the threshold | ||
| 90 | rueckrundenstart = max_spieltage // 2 | 94 | rueckrundenstart = max_spieltage // 2 |
| 91 | 95 | ||
| 92 | from ortools.sat.python import cp_model | 96 | from ortools.sat.python import cp_model |
| 93 | model = cp_model.CpModel() | 97 | model = cp_model.CpModel() |
| 94 | 98 | ||
| 99 | # Create variables in our solver's model to hold all the possible Spieltage | ||
| 95 | variables = {game["id"]: model.new_int_var(0, max_spieltage - 1, f"game{game['id']}") for game in tabelle} | 100 | variables = {game["id"]: model.new_int_var(0, max_spieltage - 1, f"game{game['id']}") for game in tabelle} |
| 96 | 101 | ||
| 97 | # Make sure each team only plays once each spieltag | 102 | # Make sure each team only plays once each spieltag |
| @@ -158,6 +163,8 @@ for team in data["teams"]: | |||
| 158 | 163 | ||
| 159 | violations.append(is_consecutive) | 164 | violations.append(is_consecutive) |
| 160 | 165 | ||
| 166 | # Most probably this constraint can't be fully satisfied, so just | ||
| 167 | # ask the solver to minimize clusters of Heimspiele for a team | ||
| 161 | model.minimize(sum(violations)) | 168 | model.minimize(sum(violations)) |
| 162 | 169 | ||
| 163 | print ("All set, solving") | 170 | print ("All set, solving") |
| @@ -172,12 +179,15 @@ from sys import exit | |||
| 172 | if status == cp_model.INFEASIBLE: | 179 | if status == cp_model.INFEASIBLE: |
| 173 | exit(-1) | 180 | exit(-1) |
| 174 | 181 | ||
| 182 | # Distribute Spieltage back to the games so we can sort them | ||
| 175 | for game in tabelle: | 183 | for game in tabelle: |
| 176 | game["spieltag"] = solver.value(variables[game["id"]]) | 184 | game["spieltag"] = solver.value(variables[game["id"]]) |
| 177 | 185 | ||
| 178 | # tabelle.sort(key=lambda game: game["spieltag"]) | 186 | # tabelle.sort(key=lambda game: game["spieltag"]) |
| 179 | 187 | ||
| 180 | # PRINT OUT RESULTS AS TABLE | 188 | # PRINT OUT RESULTS AS TABLE |
| 189 | |||
| 190 | # helper table for quicker lookup of teams and orte by their id | ||
| 181 | all_teams = {team["id"]: team for team in data["teams"]} | 191 | all_teams = {team["id"]: team for team in data["teams"]} |
| 182 | all_teams[-1] = {"name": "*"} | 192 | all_teams[-1] = {"name": "*"} |
| 183 | all_orte = {ort["id"]: ort for ort in data["orte"]} | 193 | all_orte = {ort["id"]: ort for ort in data["orte"]} |
