# %% PROJECT_PATH = '/home/md/Work/ligalytics/leagues_stable/' import os, sys sys.path.insert(0, PROJECT_PATH) os.environ.setdefault("DJANGO_SETTINGS_MODULE", "leagues.settings") os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = "true" from leagues import settings # settings.DATABASES['default']['NAME'] = PROJECT_PATH+'/db.sqlite3' settings.DATABASES['default']['ENGINE'] = 'django.db.backends.postgresql_psycopg2' settings.DATABASES['default']['HOST'] = '0.0.0.0' settings.DATABASES['default']['PORT'] = '5432' settings.DATABASES['default']['USER'] = 'postgres' settings.DATABASES['default']['PASSWORD'] = 'secret123' settings.DATABASES['default']['NAME'] = 'mypgsqldb' settings.DATABASES['default']['ATOMIC_REQUESTS'] = False settings.DATABASES['default']['AUTOCOMMIT'] = True settings.DATABASES['default']['CONN_MAX_AGE'] = 0 settings.DATABASES['default']['CONN_HEALTH_CHECKS'] = False settings.DATABASES['default']['OPTIONS'] = {} os.environ["XPRESSDIR"] = "/opt/xpressmp" os.environ["XPRESS"] = "/opt/xpressmp/bin" os.environ["LD_LIBRARY_PATH"] = os.environ["XPRESSDIR"] + "/lib" os.environ["DYLD_LIBRARY_PATH"] = os.environ["XPRESSDIR"] + "/lib" os.environ["SHLIB_PATH"] = os.environ["XPRESSDIR"] + "/lib" os.environ["LIBPATH"] = os.environ["XPRESSDIR"] + "/lib" os.environ["PYTHONPATH"] = os.environ["XPRESSDIR"] + "/lib" os.environ["CLASSPATH"] = os.environ["XPRESSDIR"] + "/lib/xprs.jar" os.environ["CLASSPATH"] = os.environ["XPRESSDIR"] + "/lib/xprb.jar" + os.pathsep + os.environ["CLASSPATH"] os.environ["CLASSPATH"] = os.environ["XPRESSDIR"] + "/lib/xprm.jar" + os.pathsep + os.environ["CLASSPATH"] os.environ["PATH"] = os.environ["XPRESSDIR"] + "/bin" + os.pathsep + os.environ["PATH"] import django django.setup() from scheduler.models import * import pulp from pulp import lpSum, value, XPRESS, GUROBI, PULP_CBC_CMD from django.db.models import Q from django.template.loader import render_to_string from qualifiers.models import * from common.models import GlobalTeam, GlobalCountry from scheduler.models import Season, Scenario, Team, DayObj, CountryClash, Country from qualifiers.draws import groupTeams, optimize_inversions4 from scheduler.solver.tasks.optimize import optimize from draws.solver.optimize_draws import ucl24_ha_matrix, ucl24_opponent_matrix import random import time import json import csv import networkx as nx import matplotlib.pyplot as plt from datetime import timedelta from django.contrib.sessions.models import Session def getVal(v): if type(v) == int : return v else: return v.value() scenario = Scenario.objects.get(id=9607) hawishes = HAWish.objects.filter(scenario=scenario,prio__in=['Hard','A']) encwishes = EncWish.objects.filter(scenario=scenario,prio__in=['Hard','A']) # %% all_rounds = [] getDateByIso = {} season = scenario.season teams = Team.objects.filter(season=scenario.season,active=True) higherHomeGames = defaultdict(lambda: []) higherAwayGames = defaultdict(lambda: []) higherDates = scenario.season.higherDates() for game in scenario.season.higherGames(): higherHomeGames[game[1]].append(game) higherAwayGames[game[2]].append(game) higherRound = f"{higherDates[game[0]].isocalendar().year}-{higherDates[game[0]].isocalendar().week}" all_rounds.append(higherRound) getDateByIso[higherRound] = higherDates[game[0]] higherTeams = set(list(higherHomeGames.keys()) + list(higherAwayGames.keys())) gameRequirements = GameRequirement.objects.filter(scenario=scenario) stadium_clashes = Pairing.objects.filter(scenario=scenario,type="Home",prio="Hard",active=True,team2__in=teams) pairings = Pairing.objects.filter(scenario=scenario,active=True,team2__in=teams).exclude(id__in=stadium_clashes.values_list('id')) encwishes = EncWish.objects.filter(scenario=scenario,prio__in=['Hard','A']) hawishes = HAWish.objects.filter(scenario=scenario,prio__in=['Hard','A']) pairings_dependencies = Pairing.objects.filter(scenario=scenario,active=True,team2__in=higherTeams) days = Day.objects.filter(season=scenario.season, maxGames__gt=0) blockings = Blocking.objects.filter(scenario=scenario) uclpatterns = SpecialWish.objects.filter(scenario=scenario,name='UCL24Patterns',active=True).exists() alternatestart = SpecialWish.objects.filter(scenario=scenario,name='AlternateStart',active=True).exists() maxTourLength = season.maxTourLength groups = Conference.objects.filter(scenario=scenario).filter(name__in=["UEL","UECL"]) uel_teams = list(groups.filter(name="UEL").first().teams.order_by('pot','country').values_list('id',flat=True)) uecl_teams = list(groups.filter(name="UECL").first().teams.order_by('pot','country').values_list('id',flat=True)) prioVal ={'A': 25 , 'B': 5 , 'C': 1, 'Hard' : 1000} pairings_prio = { p.id:prioVal[p.prio] for p in pairings } dependency_prio = { p.id:prioVal[p.prio] for p in pairings_dependencies } daysPerRound = defaultdict(lambda:[]) # getRoundByDay = {} # for d in days: # daysPerRound[d.round].append(d) # getRoundByDay[d.id] = d.round getRoundByIso = {} getIsoByRound = {} getDateByDay = {} for d in days: getDateByDay[d] = datetime.datetime.strptime(d.day,"%Y-%m-%d") iso = datetime.datetime.strptime(d.day,"%Y-%m-%d").isocalendar() getRoundByIso[f"{iso.year}-{iso.week}"] = d.round getIsoByRound[d.round] = f"{iso.year}-{iso.week}" all_rounds.append(f"{iso.year}-{iso.week}") getDateByIso[f"{iso.year}-{iso.week}"] = getDateByDay[d] daysPerRound[f"{iso.year}-{iso.week}"].append(d) all_rounds = sorted(list(set(all_rounds))) single_day_rounds = [r for r in daysPerRound if len(daysPerRound[r]) == 1] two_day_rounds = [r for r in daysPerRound if len(daysPerRound[r]) == 2 ] multi_day_rounds = [r for r in daysPerRound if len(daysPerRound[r]) >= 3 ] team_ids = list(teams.values_list('id',flat=True)) getTeamByID = { t.id:t for t in teams } # list all rounds where each day is blocked for a team blockedRounds = {(t.id,r):True for r in all_rounds for t in teams} for t in teams: tblocks = blockings.filter(team=t) for r in all_rounds: for d in daysPerRound[r]: if not tblocks.filter(day=d).exists(): blockedRounds[(t.id,r)] = False break gamereqs = [] opponents_from_pot = defaultdict(lambda:defaultdict(lambda:[])) for req in gameRequirements: gamereqs.append((req.team1.id,req.team2.id)) opponents_from_pot[req.team1.id][req.team2.pot].append(req.team2.id) opponents_from_pot[req.team2.id][req.team1.pot].append(req.team1.id) pot = {} teams_in_pot = {} for i in teams.values_list('pot',flat=True).distinct(): pot[i] = teams.filter(pot=i) teams_in_pot[i] = list(teams.filter(pot=i).values_list('id',flat=True)) topTeams = teams.filter(attractivity__gte=4) topGames = [(t1.id,t2.id) for t1 in topTeams for t2 in topTeams if (t1.id,t2.id) in gamereqs] topTeam_clashes = {t.id:[] for t in topTeams} for t in topTeams: for pair in stadium_clashes.filter(team1=t): topTeam_clashes[t.id].append(pair.team2.id) for pair in stadium_clashes.filter(team2=t): topTeam_clashes[t.id].append(pair.team1.id) rounds = all_rounds ucl_rounds = [r for i,r in enumerate(rounds) if i in [0,2,3,4,5,6,8,9]] uel_rounds = [r for i,r in enumerate(rounds) if i in [1,2,3,4,5,6,8,9]] uecl_rounds = [r for i,r in enumerate(rounds) if i in [2,3,4,5,6,7]] model = pulp.LpProblem(f"test", pulp.LpMinimize) dummy = pulp.LpVariable("Dummy", lowBound=1, cat=pulp.LpContinuous) x = { (r,t1,t2) : pulp.LpVariable('x_'+str(r)+'_'+str(t1)+'_'+str(t2) , lowBound = 0, upBound = 1, cat = pulp.LpContinuous) for r in rounds for t1 in team_ids for t2 in team_ids if (t1,t2) in gamereqs or (t2,t1) in gamereqs} home = {(r,t) : pulp.LpVariable('home_'+str(r)+'_'+str(t) , lowBound = 0, upBound = 1, cat = pulp.LpContinuous) for r in rounds for t in team_ids} away = {(r,t) : pulp.LpVariable('away_'+str(r)+'_'+str(t) , lowBound = 0, upBound = 1, cat = pulp.LpContinuous) for r in rounds for t in team_ids} y = {(r,t) : pulp.LpVariable('y_'+str(r)+'_'+str(t) , lowBound = 0, upBound = 1, cat = pulp.LpInteger) for r in rounds for t in team_ids} team_viol = {t : pulp.LpVariable('team_viol_'+str(t) , lowBound = 0, cat = pulp.LpContinuous) for t in team_ids} dependencyViolation = {(r,t,t2) : pulp.LpVariable('dependencyViol_'+str(r)+"_"+str(t)+"_"+str(t2) , lowBound = 0, cat = pulp.LpContinuous) for r in rounds for t in team_ids for t2 in team_ids+list(higherHomeGames.keys())} blockingViolation = { (r,t) : pulp.LpVariable('blockingViolation_'+ str(r) +'_'+str(t) , lowBound = 0, cat = pulp.LpContinuous) for t in team_ids for r in rounds} # %% # model += home['2024-51',42286] == 1 # model += x[('2024-50', 42279, 42278)] == 0 # for key in x.keys(): # # if key[0] >= '2024-45': # x[key].cat = pulp.LpInteger # each game has to be played for (t1,t2) in gamereqs: model += lpSum([x[r,t1,t2] for r in rounds]) == 1 for r in uel_rounds: model += lpSum(home[r,t] for t in uel_teams) == lpSum(away[r,t] for t in uel_teams) for r in uecl_rounds: model += lpSum(home[r,t] for t in uecl_teams) == lpSum(away[r,t] for t in uecl_teams) for t in team_ids: for r in rounds: model += y[r,t] >= home[r,t] - 0.8 model += y[r,t] >= away[r,t] - 0.8 if t in uecl_teams: model += lpSum(home[r,t] for r in rounds) == lpSum(away[r,t] for r in rounds) for r in [i for i in rounds if i not in uecl_rounds]: model += home[r,t] + away[r,t] <= 0 for r in uecl_rounds: # each team plays once in each round model += lpSum([x[r,t,t2]+x[r,t2,t] for t2 in team_ids if (r,t,t2) in x.keys()]) == 1 model += home[r,t] + away[r,t] == 1 # blockings are hard restrictions if blockedRounds[(t,r)]: model += home[r,t] == blockingViolation[r,t] for r in rounds: # couple homes # model += home[r,t] == lpSum([x[r,t,t2] for t2 in team_ids if (r,t,t2) in x.keys()]) # model += away[r,t] == lpSum([x[r,t2,t] for t2 in team_ids if (r,t2,t) in x.keys()]) for t2 in team_ids: if (r,t,t2) in x.keys(): model += home[r,t] >= x[r,t,t2] model += away[r,t] >= x[r,t2,t] # always play alternating end of season model += lpSum([home[r2,t] for r2 in list(uecl_rounds)[-2:]]) <= 1 model += lpSum([away[r2,t] for r2 in list(uecl_rounds)[-2:]]) <= 1 # alternating start of season model += lpSum([home[r2,t] for r2 in uecl_rounds[:2]]) <= 1 model += lpSum([away[r2,t] for r2 in uecl_rounds[:2]]) <= 1 # no more than 2 consecutive homegames/awaygames for r in range(1,len(uecl_rounds)-1): model += lpSum([away[r2,t] for r2 in uecl_rounds[r:r+3]]) <= 2 model += lpSum([home[r2,t] for r2 in uecl_rounds[r:r+3]]) <= 2 elif t in uel_teams: model += lpSum(home[r,t] for r in rounds) == lpSum(away[r,t] for r in rounds) for r in [i for i in rounds if i not in uel_rounds]: model += home[r,t] + away[r,t] <= 0 for r in uel_rounds: # each team plays once in each round model += lpSum([x[r,t,t2]+x[r,t2,t] for t2 in team_ids if (r,t,t2) in x.keys()]) == 1 model += home[r,t] + away[r,t] == 1 # blockings are hard restrictions if blockedRounds[(t,r)]: model += home[r,t] == blockingViolation[r,t] for r in rounds: # couple homes # model += home[r,t] == lpSum([x[r,t,t2] for t2 in team_ids if (r,t,t2) in x.keys()]) # model += away[r,t] == lpSum([x[r,t2,t] for t2 in team_ids if (r,t2,t) in x.keys()]) for t2 in team_ids: if (r,t,t2) in x.keys(): model += home[r,t] >= x[r,t,t2] model += away[r,t] >= x[r,t2,t] # always play alternating end of season model += lpSum([home[r2,t] for r2 in list(uel_rounds)[-2:]]) <= 1 model += lpSum([away[r2,t] for r2 in list(uel_rounds)[-2:]]) <= 1 # alternating start of season model += lpSum([home[r2,t] for r2 in uel_rounds[:2]]) <= 1 model += lpSum([away[r2,t] for r2 in uel_rounds[:2]]) <= 1 # no more than 2 consecutive homegames/awaygames for r in range(1,len(uel_rounds)-1): model += lpSum([home[r2,t] for r2 in uel_rounds[r:r+3]]) <= 2 model += lpSum([away[r2,t] for r2 in uel_rounds[r:r+3]]) <= 2 team_pairing = defaultdict(lambda:[]) # PAIRINGDIST = ((0, _('do not play both on same day')), (1, _('do not play both within two successive days')), (8, _('do not play both within three successive days')), # (2, _('do not play both at the same time')), (3, _('do not play both in the same round')),(10, _('do not play both on same weekend (Fr.-Mo.)')), # (4, _('play both on same day')), (5, _('play both within two successive days')), (9, _('play both within three successive days')), # (6, _('play both at the same time')), (7, _('play both in the same round')), (11, _('play both on same weekend (Fr.-Mo.)')), # stadium/city clashes + pairings for r in single_day_rounds: for pair in stadium_clashes.filter(dist__in=[0,1,3,8]): team_pairing[pair.team1.id].append(pair.team2.shortname) team_pairing[pair.team2.id].append(pair.team1.shortname) fullseason = True iso1 = all_rounds[0] iso2 = all_rounds[-1] if pair.first_day: iso1 = pair.first_day.getDate().isocalendar() iso1 = f"{iso.year}-{iso.week}" fullseason = False if pair.last_day: iso2 = pair.last_day.getDate().isocalendar() iso2 = f"{iso.year}-{iso.week}" fullseason = False if fullseason or (iso1 <= r and r <= iso2): if pair.team1.id in uel_teams and (r not in uel_rounds): continue if pair.team1.id in uecl_teams and (r not in uecl_rounds): continue if pair.team2.id in uel_teams and (r not in uel_rounds): continue if pair.team2.id in uecl_teams and (r not in uecl_rounds): continue print(r, f"ADDED STADIUM single {pair}") model += lpSum(home[r,pair.team1.id]+home[r,pair.team2.id]) <= 1 + dependencyViolation[r,pair.team1.id,pair.team2.id] model += home[r,pair.team1.id] <= away[r,pair.team2.id] + dependencyViolation[r,pair.team1.id,pair.team2.id] for pair in pairings.filter(dist__in=[0,1,3,8]): team_pairing[pair.team1.id].append(pair.team2.shortname) team_pairing[pair.team2.id].append(pair.team1.shortname) # print(f"ADDED PAIRING single {pair}") fullseason = True iso1 = all_rounds[0] iso2 = all_rounds[-1] if pair.first_day: iso1 = pair.first_day.getDate().isocalendar() iso1 = f"{iso.year}-{iso.week}" fullseason = False if pair.last_day: iso2 = pair.last_day.getDate().isocalendar() iso2 = f"{iso.year}-{iso.week}" fullseason = False if fullseason or (iso1 <= r and r <= iso2): if pair.team1.id in uel_teams and (r not in uel_rounds): continue if pair.team1.id in uecl_teams and (r not in uecl_rounds): continue if pair.team2.id in uel_teams and (r not in uel_rounds): continue if pair.team2.id in uecl_teams and (r not in uecl_rounds): continue print(r, f"ADDED PAIRING single {pair}") model += lpSum(home[r,pair.team1.id]+home[r,pair.team2.id]) <= 1 + dependencyViolation[r,pair.team1.id,pair.team2.id] model += home[r,pair.team1.id] <= away[r,pair.team2.id] + dependencyViolation[r,pair.team1.id,pair.team2.id] if pair.type == 'Home and Away': model += lpSum(home[r,pair.team1.id]+home[r,pair.team2.id]) >= 1 - dependencyViolation[r,pair.team1.id,pair.team2.id] for r in two_day_rounds: for pair in stadium_clashes.filter(dist__in=[1,3,8]): team_pairing[pair.team1.id].append(pair.team2.shortname) team_pairing[pair.team2.id].append(pair.team1.shortname) fullseason = True iso1 = all_rounds[0] iso2 = all_rounds[-1] if pair.first_day: iso1 = pair.first_day.getDate().isocalendar() iso1 = f"{iso.year}-{iso.week}" fullseason = False if pair.last_day: iso2 = pair.last_day.getDate().isocalendar() iso2 = f"{iso.year}-{iso.week}" fullseason = False if fullseason or (iso1 <= r and r <= iso2): if pair.team1.id in uel_teams and (r not in uel_rounds): continue if pair.team1.id in uecl_teams and (r not in uecl_rounds): continue if pair.team2.id in uel_teams and (r not in uel_rounds): continue if pair.team2.id in uecl_teams and (r not in uecl_rounds): continue print(r, f"ADDED STADIUM twoday {pair}") model += lpSum(home[r,pair.team1.id]+home[r,pair.team2.id]) <= 1 + dependencyViolation[r,pair.team1.id,pair.team2.id] model += home[r,pair.team1.id] <= away[r,pair.team2.id] + dependencyViolation[r,pair.team1.id,pair.team2.id] for pair in pairings.filter(dist__in=[1,3,8]): team_pairing[pair.team1.id].append(pair.team2.shortname) team_pairing[pair.team2.id].append(pair.team1.shortname) fullseason = True iso1 = all_rounds[0] iso2 = all_rounds[-1] if pair.first_day: iso1 = pair.first_day.getDate().isocalendar() iso1 = f"{iso.year}-{iso.week}" fullseason = False if pair.last_day: iso2 = pair.last_day.getDate().isocalendar() iso2 = f"{iso.year}-{iso.week}" fullseason = False if fullseason or (iso1 <= r and r <= iso2): if pair.team1.id in uel_teams and (r not in uel_rounds): continue if pair.team1.id in uecl_teams and (r not in uecl_rounds): continue if pair.team2.id in uel_teams and (r not in uel_rounds): continue if pair.team2.id in uecl_teams and (r not in uecl_rounds): continue print(r, f"ADDED PAIRING multi {pair}") model += lpSum(home[r,pair.team1.id]+home[r,pair.team2.id]) <= 1 + dependencyViolation[r,pair.team1.id,pair.team2.id] model += home[r,pair.team1.id] <= away[r,pair.team2.id] + dependencyViolation[r,pair.team1.id,pair.team2.id] if pair.type == 'Home and Away': model += lpSum(home[r,pair.team1.id]+home[r,pair.team2.id]) >= 1 - dependencyViolation[r,pair.team1.id,pair.team2.id] for r in multi_day_rounds: for pair in stadium_clashes.filter(dist__in=[3,8]): team_pairing[pair.team1.id].append(pair.team2.shortname) team_pairing[pair.team2.id].append(pair.team1.shortname) fullseason = True iso1 = all_rounds[0] iso2 = all_rounds[-1] if pair.first_day: iso1 = pair.first_day.getDate().isocalendar() iso1 = f"{iso.year}-{iso.week}" fullseason = False if pair.last_day: iso2 = pair.last_day.getDate().isocalendar() iso2 = f"{iso.year}-{iso.week}" fullseason = False if fullseason or (iso1 <= r and r <= iso2): if pair.team1.id in uel_teams and (r not in uel_rounds): continue if pair.team1.id in uecl_teams and (r not in uecl_rounds): continue if pair.team2.id in uel_teams and (r not in uel_rounds): continue if pair.team2.id in uecl_teams and (r not in uecl_rounds): continue print(r, f"ADDED STADIUM multi {pair}") model += lpSum(home[r,pair.team1.id]+home[r,pair.team2.id]) <= 1 + dependencyViolation[r,pair.team1.id,pair.team2.id] model += home[r,pair.team1.id] <= away[r,pair.team2.id] + dependencyViolation[r,pair.team1.id,pair.team2.id] for pair in pairings.filter(dist__in=[3,8]): team_pairing[pair.team1.id].append(pair.team2.shortname) team_pairing[pair.team2.id].append(pair.team1.shortname) fullseason = True iso1 = all_rounds[0] iso2 = all_rounds[-1] if pair.first_day: iso1 = pair.first_day.getDate().isocalendar() iso1 = f"{iso.year}-{iso.week}" fullseason = False if pair.last_day: iso2 = pair.last_day.getDate().isocalendar() iso2 = f"{iso.year}-{iso.week}" fullseason = False if fullseason or (iso1 <= r and r <= iso2): if pair.team1.id in uel_teams and (r not in uel_rounds): continue if pair.team1.id in uecl_teams and (r not in uecl_rounds): continue if pair.team2.id in uel_teams and (r not in uel_rounds): continue if pair.team2.id in uecl_teams and (r not in uecl_rounds): continue print(r, f"ADDED PAIRING multi {pair}") model += lpSum(home[r,pair.team1.id]+home[r,pair.team2.id]) <= 1 + dependencyViolation[r,pair.team1.id,pair.team2.id] model += home[r,pair.team1.id] <= away[r,pair.team2.id] + dependencyViolation[r,pair.team1.id,pair.team2.id] if pair.type == 'Home and Away': model += lpSum(home[r,pair.team1.id]+home[r,pair.team2.id]) >= 1 - dependencyViolation[r,pair.team1.id,pair.team2.id] ucl_home = defaultdict(lambda:[]) ucl_away = defaultdict(lambda:[]) # Season Dependencies for p in pairings_dependencies.filter(dist__in=[3,8]): # do not play same round team_pairing[p.team1.id].append(p.team2.shortname) team_pairing[p.team2.id].append(p.team1.shortname) for game in higherHomeGames[p.team2.id]: higherRound = f"{higherDates[game[0]].isocalendar().year}-{higherDates[game[0]].isocalendar().week}" ucl_home[p.team2].append(higherRound) if higherRound in single_day_rounds: if p.team1.id in uel_teams and higherRound in uel_rounds: model += away[higherRound,p.team1.id] >= 1 - dependencyViolation[higherRound,p.team1.id,p.team2.id] elif p.team1.id in uecl_teams and higherRound in uecl_rounds: model += away[higherRound,p.team1.id] >= 1 - dependencyViolation[higherRound,p.team1.id,p.team2.id] for game in higherAwayGames[p.team2.id]: higherRound = f"{higherDates[game[0]].isocalendar().year}-{higherDates[game[0]].isocalendar().week}" ucl_away[p.team2].append(higherRound) for p in pairings_dependencies.filter(dist__in=[0,1]): # do not play same day/two days team_pairing[p.team1.id].append(p.team2.shortname) team_pairing[p.team2.id].append(p.team1.shortname) for game in higherHomeGames[p.team2.id]: higherRound = f"{higherDates[game[0]].isocalendar().year}-{higherDates[game[0]].isocalendar().week}" ucl_home[p.team2].append(higherRound) if p.dist == 0: forbidden_days = [higherDates[game[0]].date()] elif p.dist == 1: forbidden_days = [higherDates[game[0]].date() - timedelta(days=1),higherDates[game[0]].date(),higherDates[game[0]].date() + timedelta(days=1)] available_days = [d for d in daysPerRound[higherRound] if getDateByDay[d].date() not in forbidden_days] if not available_days: if p.team1.id in uel_teams and higherRound in uel_rounds: model += away[higherRound,p.team1.id] >= 1 - dependencyViolation[higherRound,p.team1.id,p.team2.id] elif p.team1.id in uecl_teams and higherRound in uecl_rounds: model += away[higherRound,p.team1.id] >= 1 - dependencyViolation[higherRound,p.team1.id,p.team2.id] for game in higherAwayGames[p.team2.id]: higherRound = f"{higherDates[game[0]].isocalendar().year}-{higherDates[game[0]].isocalendar().week}" ucl_away[p.team2].append(higherRound) # model += home['2024-40',42339] == 1 # model += home['2024-43',42339] == 0 # model += home['2024-45',42339] == 1 # model += home['2024-48',42339] == 0 # model += home['2024-50',42339] == 1 # model += home['2024-51',42339] == 0 # model += home['2024-40',42278] == 0 # model += x[('2024-43',42278,42339)] == 1 # model += x[('2024-40',42339,42340)] == 1 # model += home['2024-51',42339] == 0 # model += home["2024-51",42286] <= 0 # minimize pairing violation objective_function = dummy +\ lpSum(10*y[key] for key in y.keys()) +\ lpSum(home[key] for key in home.keys()) +\ lpSum(away[key] for key in away.keys()) +\ 10000*lpSum(dependencyViolation[key] for key in dependencyViolation.keys()) +\ 10000*lpSum(blockingViolation[key] for key in blockingViolation.keys()) model += objective_function #+ 0.001*random_seed with open ("basicmodel.txt", "w") as f: f.write(model.__repr__()) model.solve(XPRESS(msg=1,timeLimit=300, gapRel=0)) # FOR DEBUGGING nDays = len(rounds) home_dict = {} away_dict = {} viol_dict = {} for key in home.keys(): if getVal(home[key]) and getVal(home[key]) > 0.95: home_dict[key[0],key[1]] = "H" for key in away.keys(): if getVal(away[key]) and getVal(away[key]) > 0.95: away_dict[key[0],key[1]] = "A" for key in dependencyViolation.keys(): if getVal(dependencyViolation[key]) and getVal(dependencyViolation[key]) > 0: print("VIOLATED DEPENDENCY",key,getVal(dependencyViolation[key])) viol_dict[key[0],key[1]] = Team.objects.get(id=key[2]) for key in blockingViolation.keys(): if getVal(blockingViolation[key]) and getVal(blockingViolation[key]) > 0: print("VIOLATED BLOCKING",key,getVal(blockingViolation[key])) viol_dict[key[0],key[1]] = key[0] for key in x.keys(): if getVal(x[key]) and getVal(x[key]) > 0.95: print(key,getVal(x[key])) print(r[0],teams.get(id=key[1]),teams.get(id=key[2])) home_dict[key[0],key[1]] = f"{teams.get(id=key[2])}" away_dict[key[0],key[2]] = f"@{teams.get(id=key[1])}" for k,v in team_pairing.items(): team_pairing[k] = ",".join(set(v)) sol = " \ \ " sol += "
| " for d in all_rounds: sol += f" | {d} - {getDateByIso[d].date()} | " sol += "|||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| UCL | {t.id} | Pot {t.pot} | {t.country} | {t.name} | {t.shortname} | {team_pairing[t.id]} | " for d in all_rounds: if d in ucl_rounds: if d in ucl_home[t]: fontcolor = 'black' bgcolor = 'lightsteelblue' sol += f"H | " elif d in ucl_away[t]: fontcolor = 'black' bgcolor = 'lightyellow' sol += f"A | " else: sol += "" else: sol += " | " sol += " | ||||||
| UEL | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | ||||||||
| UEL | {t} | Pot {tpot} | {tcountry} | {tname} | {tshortname} | {team_pairing[t]} | " for d in all_rounds: if d in uel_rounds: if (d,t) in home_dict.keys(): fontcolor = 'black' bgcolor = 'lightsteelblue' if (d,t) in viol_dict.keys(): fontcolor = 'white' bgcolor = 'darkred' sol += f"{home_dict[(d,t)]} | " elif (d,t) in away_dict.keys(): fontcolor = 'black' bgcolor = 'lightyellow' if (d,t) in viol_dict.keys(): fontcolor = 'white' bgcolor = 'darkred' sol += f"{away_dict[(d,t)]} | " elif (d,t) in viol_dict.keys(): fontcolor = 'white' bgcolor = 'darkred' sol += f"{viol_dict[(d,t)]} | " else: sol += "" else: sol += " | " sol += " | |||||
| UECL | 1 | 2 | 3 | 4 | 5 | 6 | ||||||||||
| UECL | {t} | Pot {tpot} | {tcountry} | {tname} | {tshortname} | {team_pairing[t]} | " for d in all_rounds: if d in uecl_rounds: # if (d,t) in viol_dict.keys(): # fontcolor = 'white' # bgcolor = 'darkred' # sol += f"{viol_dict[(d,t)]} | " if (d,t) in home_dict.keys(): fontcolor = 'black' bgcolor = 'lightsteelblue' if (d,t) in viol_dict.keys(): fontcolor = 'white' bgcolor = 'darkred' sol += f"{home_dict[(d,t)]} | " elif (d,t) in away_dict.keys(): fontcolor = 'black' bgcolor = 'lightyellow' if (d,t) in viol_dict.keys(): fontcolor = 'white' bgcolor = 'darkred' sol += f"{away_dict[(d,t)]} | " elif (d,t) in viol_dict.keys(): fontcolor = 'white' bgcolor = 'darkred' sol += f"{viol_dict[(d,t)]} | " else: sol += "" else: sol += " | " sol += " | ||||