# %% 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 csv from multiprocessing import Pool, cpu_count import random import time import pulp from pulp import lpSum, value, XPRESS, GUROBI, PULP_CBC_CMD import xpress as xp # xp.controls.outputlog = 0 scenario = Scenario.objects.get(id=34) # %% # teamObjects = Team.objects.filter(season=scenario.season,active=True).order_by('pot','country') teamObjects = Team.objects.filter(season=scenario.season,active=True) teams = teamObjects.values('id','country','pot','name') getTeamById = {} for t in teamObjects: getTeamById[t.id] = f"({t.pot}) {t.name}" countries = list(set(teamObjects.values_list('country', flat=True))) teams_from_country = { c:[t for t in teams if t['country']==c] for c in countries } pot = {} for i in teamObjects.values_list('pot',flat=True).distinct(): pot[i] = list(teams.filter(pot=i)) teams = list(teams) fixed_games = [(3940, 3894), (3933, 3940), (3940, 3937), (3765, 3940), (3940, 3895), (3700, 3940), (3940, 3696), (3925, 3940), (3702, 3935), (3894, 3702), (3702, 3926), (3937, 3702), (3702, 3700), (3758, 3702), (3702, 3699), (3757, 3702), (3932, 3762), (3732, 3932), (3932, 3938), (3761, 3932), (3932, 3730), (3701, 3932), (3932, 3870), (3853, 3932), (3764, 3933), (3935, 3764), (3764, 3936), (3898, 3764), (3764, 3756), (3928, 3764), (3764, 3925), (3904, 3764), (3762, 3732), (3762, 3761), (3930, 3762), (3762, 3701), (3760, 3762), (3762, 3697), (3698, 3762), (3732, 3765), (3926, 3732), (3732, 3928), (3730, 3732), (3732, 3698), (3870, 3732), (3894, 3930), (3938, 3894), (3894, 3758)] # fixed_games = [(3702, 3935), (3702, 3926), (3702, 3700), (3702, 3699), (3764, 3933), (3764, 3936), (3764, 3756), (3764, 3925), (3940, 3894), (3940, 3937), (3940, 3895), (3940, 3696), (3762, 3732), (3762, 3761), (3762, 3701), (3762, 3697), (3894, 3702), (3894, 3930), (3894, 3758), (3894, 3904), (3933, 3940), (3933, 3734), (3933, 3771), (3933, 3853), (3935, 3764), (3935, 3898), (3935, 3760), (3935, 3757), (3932, 3762), (3932, 3938), (3932, 3730), (3932, 3870), (3732, 3932), (3732, 3765), (3732, 3928), (3732, 3698), (3938, 3894), (3938, 3930), (3938, 3730), (3938, 3697), (3761, 3932), (3761, 3938), (3761, 3895), (3761, 3904), (3898, 3764), (3898, 3761), (3898, 3700), (3898, 3696), (3926, 3732), (3926, 3734), (3926, 3701), (3926, 3699), (3936, 3933), (3936, 3765), (3936, 3758), (3936, 3698), (3734, 3935), (3734, 3936), (3734, 3928), (3734, 3925), (3930, 3762), (3930, 3926), (3930, 3756), (3930, 3853), (3937, 3702), (3937, 3898), (3937, 3771), (3937, 3757), (3765, 3940), (3765, 3937), (3765, 3760), (3765, 3870), (3758, 3702), (3758, 3926), (3758, 3756), (3758, 3925), (3756, 3894), (3756, 3936), (3756, 3701), (3756, 3698), (3771, 3935), (3771, 3898), (3771, 3700), (3771, 3697), (3895, 3933), (3895, 3930), (3895, 3758), (3895, 3699), (3701, 3932), (3701, 3761), (3701, 3771), (3701, 3870), (3760, 3762), (3760, 3734), (3760, 3895), (3760, 3757), (3928, 3764), (3928, 3938), (3928, 3760), (3928, 3904), (3730, 3732), (3730, 3937), (3730, 3928), (3730, 3696), (3700, 3940), (3700, 3765), (3700, 3730), (3700, 3853), (3904, 3764), (3904, 3898), (3904, 3771), (3904, 3696), (3925, 3940), (3925, 3930), (3925, 3701), (3925, 3697), (3698, 3762), (3698, 3938), (3698, 3758), (3698, 3699), (3699, 3935), (3699, 3937), (3699, 3760), (3699, 3853), (3696, 3894), (3696, 3765), (3696, 3895), (3696, 3925), (3853, 3932), (3853, 3936), (3853, 3928), (3853, 3757), (3697, 3933), (3697, 3761), (3697, 3756), (3697, 3904), (3757, 3702), (3757, 3734), (3757, 3730), (3757, 3870), (3870, 3732), (3870, 3926), (3870, 3700), (3870, 3698)] # sol = '' # sol += " \ # \ # " # sol += "" # sol += "\n" # sol += "\n" # sol += "" # sol += "" # sol += "" # sol += "" # sol += "" # sol += "" # sol += "" # sol += "\n" # sol += f"\n" # # for o in order: # for t in teams: # # t = getTeamByName[o] # sol += f"\n" # sol += "\n" # sol += "\n" # sol += "\n" # # for o1 in order: # for t1 in teams: # # t1 = getTeamByName[o1] # sol += "\n" # sol += f"" # # for o2 in order: # for t2 in teams: # # t2 = getTeamByName[o2] # # val = stats[t1,t2] # if (t1['id'],t2['id']) in fixed_games: # sol += f"" # elif (t2['id'],t1['id']) in fixed_games: # sol += f"" # else: # sol += f"" # sol += "\n" # sol += "\n" # sol += "
Pot APot BPot CPot D
{t['name']}({t['country']})
{t1['name']}({t1['country']}){t2['country']}@{t2['country']}
\n" # with open(f'debug.html', 'w') as f: # f.write(sol) # %% def check_feasible(fixed_games): model = pulp.LpProblem(f"Draws", pulp.LpMinimize) xp_model = xp.problem(name='Draws', sense=xp.minimize) xp_model.setControl('outputlog', 1) xp_model.setControl('presolve',0) x = {} xp_x = {} for t1 in teams: for t2 in teams: if t1['country'] != t2['country']: x[t1['id'], t2['id']] = pulp.LpVariable('x_'+str(t1['id'])+'_'+str(t2['id']),lowBound=0, upBound=1, cat=pulp.LpInteger) xp_x[t1['id'], t2['id']] = xp.var(ub=1, vartype=xp.integer) xp_model.addVariable(xp_x) # REQUIREMENTS for t in teams: for r in range(1,5): xp_model.addConstraint(xp.Sum(xp_x[t['id'],t2['id']] for t2 in pot[r] if (t['id'],t2['id']) in xp_x.keys()) == 1) xp_model.addConstraint(xp.Sum(xp_x[t2['id'],t['id']] for t2 in pot[r] if (t2['id'],t['id']) in xp_x.keys()) == 1) model += lpSum(x[t['id'],t2['id']] for t2 in pot[r] if (t['id'],t2['id']) in x.keys()) == 1 model += lpSum(x[t2['id'],t['id']] for t2 in pot[r] if (t2['id'],t['id']) in x.keys()) == 1 for c in countries: if c != t['country']: xp_model.addConstraint(xp.Sum(xp_x[t['id'],t2['id']]+xp_x[t2['id'],t['id']] for t2 in teams_from_country[c]) <= 2) model += lpSum(x[t['id'],t2['id']]+x[t2['id'],t['id']] for t2 in teams_from_country[c]) <= 2 # FIXATIONS for (t1,t2) in fixed_games: xp_model.addConstraint(xp_x[t1,t2] == 1) model += x[t1,t2] == 1 for (t1,t2) in xp_x.keys(): xp_model.addConstraint(xp_x[t1,t2] + xp_x[t2,t1] <= 1) for (t1,t2) in x.keys(): model += x[t1,t2] + x[t2,t1] <= 1 # model += lpSum(random.uniform(0,1)*x[key] for key in x.keys()) model.writeMPS('pulp.mps',rename=True) model.solve(XPRESS(msg=1)) # xp_model.solve() # print(model.status) # if model.status in [-1,-2]: # print("ERROR") # else: # print("SUCCESS") # games = [] # for key in x.keys(): # if x[key].value() != 0: # # print(key,xp_model.getSolution(xp_x[key])) # games.append(key) # sol = '' # sol += " \ # \ # " # sol += "\n" # sol += "\n" # sol += "" # sol += "" # sol += "" # sol += "" # sol += "" # sol += "" # sol += "" # sol += "\n" # sol += f"\n" # # for o in order: # for t in teams: # # t = getTeamByName[o] # sol += f"\n" # sol += "\n" # sol += "\n" # sol += "\n" # # for o1 in order: # for t1 in teams: # # t1 = getTeamByName[o1] # sol += "\n" # sol += f"" # # for o2 in order: # for t2 in teams: # # t2 = getTeamByName[o2] # # val = stats[t1,t2] # if (t1['id'],t2['id']) in games: # sol += f"" # elif (t2['id'],t1['id']) in games: # sol += f"" # else: # sol += f"" # sol += "\n" # sol += "\n" # sol += "
Pot APot BPot CPot D
{getTeamById[t['id']]}
{getTeamById[t1['id']]}{t2['country']}@{t2['country']}
\n" # with open(f'debug_pulp.html', 'w') as f: # f.write(sol) # print("\n\n\n\n") # # model.writeMPS('pulp.mps',rename=True) # # xp_model.write('xpress.lp','lps') # xp_model.solve() # if xp_model.getProbStatus() != 6: # print("ERROR") # # print("INFEASIBLE FOUND") # else: # print("SUCCESS") # games = [] # for key in xp_x.keys(): # if xp_model.getSolution(xp_x[key]) != 0: # # print(key,xp_model.getSolution(xp_x[key])) # games.append(key) # print(len(games)) # sol = '' # sol += " \ # \ # " # sol += "\n" # sol += "\n" # sol += "" # sol += "" # sol += "" # sol += "" # sol += "" # sol += "" # sol += "" # sol += "\n" # sol += f"\n" # # for o in order: # for t in teams: # # t = getTeamByName[o] # sol += f"\n" # sol += "\n" # sol += "\n" # sol += "\n" # # for o1 in order: # for t1 in teams: # # t1 = getTeamByName[o1] # sol += "\n" # sol += f"" # # for o2 in order: # for t2 in teams: # # t2 = getTeamByName[o2] # # val = stats[t1,t2] # if (t1['id'],t2['id']) in games: # sol += f"" # elif (t2['id'],t1['id']) in games: # sol += f"" # else: # sol += f"" # sol += "\n" # sol += "\n" # sol += "
Pot APot BPot CPot D
{getTeamById[t['id']]}
{getTeamById[t1['id']]}{t2['country']}@{t2['country']}
\n" # with open(f'debug_xpress.html', 'w') as f: # f.write(sol) # def check_feasible_2(fixed_games): # model = xp.problem(name='Draws', sense=xp.minimize) # model.setControl ('outputlog', 1) # x = {} # for t1 in teams: # for t2 in teams: # if t1['country'] != t2['country']: # x[t1['id'], t2['id']] = xp.var(ub=1, vartype=xp.integer) # model.addVariable(x) # # REQUIREMENTS # for t in teams: # for r in range(1,5): # model.addConstraint(xp.Sum(x[t['id'],t2['id']] for t2 in pot[r] if (t['id'],t2['id']) in x.keys()) == 1) # model.addConstraint(xp.Sum(x[t2['id'],t['id']] for t2 in pot[r] if (t2['id'],t['id']) in x.keys()) == 1) # for c in countries: # if c != t['country']: # model.addConstraint(xp.Sum(x[t['id'],t2['id']]+x[t2['id'],t['id']] for t2 in teams_from_country[c]) <= 2) # # FIXATIONS # for (t1,t2) in fixed_games: # # print("FIXING",t1,t2) # model.addConstraint(x[t1,t2] == 1) # for (t1,t2) in x.keys(): # model.addConstraint(x[t1,t2] + x[t2,t1] <= 1) # tt =time.time() # model.solve() # comp_time = time.time()-tt # if model.getProbStatus() != 6: # # print("INFEASIBLE FOUND") # return False, comp_time # else: # return True, comp_time check_feasible(fixed_games) exit() # %% model = xp.problem(name='Draws', sense=xp.minimize) model.setControl ('outputlog', 1) x = {} for t1 in teams: for t2 in teams: if t1['country'] != t2['country']: x[t1['id'], t2['id']] = xp.var(ub=1, vartype=xp.integer) model.addVariable(x) # REQUIREMENTS for t in teams: for r in range(1,5): model.addConstraint(xp.Sum(x[t['id'],t2['id']] for t2 in pot[r] if (t['id'],t2['id']) in x.keys()) == 1) model.addConstraint(xp.Sum(x[t2['id'],t['id']] for t2 in pot[r] if (t2['id'],t['id']) in x.keys()) == 1) for c in countries: if c != t['country']: model.addConstraint(xp.Sum(x[t['id'],t2['id']]+x[t2['id'],t['id']] for t2 in teams_from_country[c]) <= 2) for (t1,t2) in x.keys(): model.addConstraint(x[t1,t2] + x[t2,t1] <= 1) def check_feasible_fix(fixed_games): # FIXATIONS # for key in x.keys(): # if key in fixed_games: # # x[key].lb = 1 # model.chgbounds([x[key]],['L'],[1]) # else: # # x[key].lb = 0 # model.chgbounds([x[key]],['L'],[0]) reset_bounds = [key for key in x.keys() if key not in fixed_games] model.chgbounds([x[key] for key in fixed_games],['L' for _ in range(len(fixed_games))],[1 for _ in range(len(fixed_games))]) model.chgbounds([x[key] for key in reset_bounds],['L' for _ in range(len(reset_bounds))],[0 for _ in range(len(reset_bounds))]) # tt =time.time() model.solve() # comp_time = time.time()-tt if model.getProbStatus() != 6: # print("INFEASIBLE FOUND") # return False, comp_time return False else: # return True, comp_time return True check_feasible_fix(fixed_games) exit() # def ucl24_random_games(team_to_check, pots_to_check, oldgames): # teamObjects = Team.objects.filter(season=scenario.season,active=True) # teams = [t.id for t in teamObjects] # t_country = {t.id : t.country for t in teamObjects} # t_name = {t.id : t.name for t in teamObjects} # t_pot = {t.id : t.pot for t in teamObjects} # countries = sorted(list(set(t_country.values()))) # pots = sorted(list(set(t_pot.values()))) # max_opponents_from_same_country=2 # givenHome = { (t,p) : False for t in teams for p in pots } # givenAway = { (t,p) : False for t in teams for p in pots } # gamesAgainstCountry = { (t,c) : 0 for t in teams for c in countries } # for (t1,t2) in oldgames: # givenHome[t1,t_pot[t2]]=t2 # givenAway[t2,t_pot[t1]]=t1 # gamesAgainstCountry[(t1,t_country[t2])]+=1 # gamesAgainstCountry[(t2,t_country[t1])]+=1 # no_solution_found = True # possHomeOpponents={} # possAwayOpponents={} # for p in pots_to_check: # print( "POT " , p) # possOpponents1 = [ t for t in teams if t_country[t]!=t_country[team_to_check] and t_pot[t]==p and t!=givenAway[team_to_check,p] ] # possOpponents = [ t for t in possOpponents1 if gamesAgainstCountry[(team_to_check,t_country[t])]<2 and gamesAgainstCountry[(t,t_country[team_to_check])]<2] # if givenHome[team_to_check,p]: # possHomeOpponents[p]= [givenHome[team_to_check,p]] # else: # possHomeOpponents[p] = [ t for t in possOpponents if not givenAway[t,t_pot[team_to_check]] ] # if givenAway[team_to_check,p]: # possAwayOpponents[p]= [givenAway[team_to_check,p]] # else: # possAwayOpponents[p] = [ t for t in possOpponents if not givenHome[t,t_pot[team_to_check]]] # while no_solution_found: # newgames = [] # for p in pots_to_check: # random_home= random.choice(possHomeOpponents[p]) # random_away= random.choice(possAwayOpponents[p]) # print (p,"-> " , random_home==random_away, t_name[random_home], "\t ", t_name[random_away] ) # newgames+=[(team_to_check,random_home), (random_away,team_to_check) ] # if random_home!=random_away and check_feasible(oldgames+newgames): # no_solution_found = False # newgames = [gm for gm in newgames if gm not in oldgames] # return newgames # %% def simulate_draws(filename,n): print("RUNNING ASYNC",filename) for i in range(1, n): if i % 100 == 0: print("RUNNING ASYNC",filename,i) # start_time = time.time() # n_computations = 0 # check_time = 0 # total_comp_time = 0 possible_opps = {} for pos in range(8): p = pos//2+1 teams_from_pot = list(teamObjects.filter(pot=p).values('id','country')) possible_opps[pos] = { t['id']: [t2['id'] for t2 in teams_from_pot if t2['country'] != t['country']] for t in teams } sol_opps = { (t['id'],p):None for t in teams for p in range(8) } fixed_games = [] feasible = True for p in range(1,5): currentPot = list(teamObjects.filter(pot=p).values_list('id', flat=True)) while(feasible and currentPot): new_team = currentPot.pop(random.randint(0,len(currentPot)-1)) for current_pos in range(8): while (feasible and sol_opps[new_team,current_pos] == None): try: new_opponent = random.choice(possible_opps[current_pos][new_team]) except: feasible = False print("INFEASIBLE") print(sol_opps) print(fixed_games) print(possible_opps) print(new_team,current_pos) print(possible_opps[current_pos][new_team]) exit() if sol_opps[new_opponent,(2*p-1)-(current_pos % 2)] == None: new_game = (new_team,new_opponent) if current_pos % 2 == 0 else (new_opponent,new_team) # n_computations += 1 # tt = time.time() # check, comp_time = check_feasible_fix(fixed_games+[new_game]) # check_time += time.time()-tt # total_comp_time += comp_time if check_feasible_fix(fixed_games+[new_game]): sol_opps[new_team,current_pos] = new_opponent sol_opps[new_opponent,(2*p-1)-(current_pos % 2)] = new_team fixed_games.append(new_game) if new_opponent in possible_opps[(2*p-1)-(current_pos % 2)][new_team]: possible_opps[(2*p-1)-(current_pos % 2)][new_team].remove(new_opponent) possible_opps[current_pos][new_team].remove(new_opponent) else: possible_opps[current_pos][new_team].remove(new_opponent) # for p in [1,2,3,4]: # # for p in [4,3,2,1]: # currentPot = list(teamObjects.filter(pot=p).values_list('id', flat=True)) # while(feasible and currentPot): # # Draw Team # new_team = currentPot.pop(random.randint(0,len(currentPot)-1)) # draw_index_dict[new_team] = draw_index # draw_index += 1 # # print("New team",new_team,getTeamById[new_team]) # for pos in range(8): # # Skip if already drawn # if sol_opps[new_team,pos]: # continue # # Update possible opponents # opponent_pool = [] # for new_opponent in possible_opps[pos][new_team]: # if sol_opps[new_opponent,(2*p-1)-(pos % 2)] != None: # continue # # print(f"---> ALREADY DRAWN {pos}: {getTeamById[new_opponent]}") # else: # new_game = (new_team,new_opponent) if pos % 2 == 0 else (new_opponent,new_team) # n_computations += 1 # tt = time.time() # feasible = check_feasible(fixed_games+[new_game]) # comp_time += time.time()-tt # if feasible: # opponent_pool.append(new_opponent) # else: # # print(f"---> CANNOT DRAW {pos}: {[getTeamById[ttt] for ttt in new_game]}") # num_combinatorial_clashes[new_team,pos] += 1 # num_possible_opps[new_team,pos] = len(opponent_pool) # # Draw random opponent # new_opponent = random.choice(opponent_pool) # new_game = (new_team,new_opponent) if pos % 2 == 0 else (new_opponent,new_team) # # if not check_feasible(fixed_games+[new_game]): # # print("INFEASIBLE") # # print("POSSOPS AFTER",[getTeamById[tt] for tt in possible_opps[pos][new_team]]) # # print(f"{p} - {pos} - {getTeamById[sol_opps[new_opponent,(2*p-1)-(pos % 2)]]}") # # feasible = False # # break # sol_opps[new_team,pos] = new_opponent # sol_opps[new_opponent,(2*p-1)-(pos % 2)] = new_team # if pos % 2 == 0: # possible_opps[pos+1][new_team].remove(new_opponent) # fixed_games.append(new_game) # print("COMPUTATIONS",n_computations) # print("TIME\t",time.time()-start_time) # print("CHECK\t",check_time) # print("COMP\t",total_comp_time) with open(filename+'.csv', "a") as f: for t in teams: f.write(f"{i},{t['id']},{';'.join([str(sol_opps[t['id'],p]) for p in range(8)])}\n") # for game in fixed_games: # if game[0] == new_team or game[1] == new_team: # print("\t"," vs ".join([getTeamById[tt] for tt in game])) # print(f"--- > {draw_index_dict[new_team]}") # for pos in range(8): # print(f"--- > {pos} - {num_possible_opps[new_team,pos]}") # iterate over h/a-encounters # for current_pos in range(8): # while (sol_opps[new_team,current_pos] == None): # # print(possible_opps[current_pos][new_team]) # # draw opponent # new_opponent = random.choice(possible_opps[current_pos][new_team]) # print("\tNEW OPP",new_opponent,getTeamById[new_opponent]) # new_game = (new_team,new_opponent) if current_pos % 2 == 0 else (new_opponent,new_team) # if check_feasible(fixed_games+[new_game]): # # print("FEASIBLE",new_game,[getTeamById[tt] for tt in new_game]) # sol_opps[new_team,current_pos] = new_opponent # sol_opps[new_opponent,(2*p-1)-(current_pos % 2)] = new_team # fixed_games.append(new_game) # possible_opps[current_pos][new_team].remove(new_opponent) # else: # possible_opps[current_pos][new_team].remove(new_opponent) # %% # # SOLUTION # for g in fixed_games: # print(getTeamById[g[0]],getTeamById[g[1]]) # n = sys.maxsize # pool = Pool() # result = {} # answer = {} # n_threads = cpu_count() # # n_threads = 1 # for cpu in range(n_threads): # result[cpu] = pool.apply_async(simulate_draws, args=(f'thread_{cpu}_pot_by_pot', n,)) # for cpu in range(n_threads): # answer[cpu] = result[cpu].get() # %% n = sys.maxsize simulate_draws('test', n) # %%