# %% 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" import random import time # XPRESS ENVIRONMENT os.environ['XPRESSDIR'] = "/opt/xpressmp_8.4" os.environ['XPRESS'] = "/opt/xpressmp_8.4/bin" os.environ['LD_LIBRARY_PATH'] = os.environ['XPRESSDIR']+"/lib:"+os.environ['LD_LIBRARY_PATH'] 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['PYTHONPATH'] 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.environ['CLASSPATH'] os.environ['CLASSPATH'] =os.environ['XPRESSDIR']+"/lib/xprm.jar:"+os.environ['CLASSPATH'] os.environ['PATH'] =os.environ['XPRESSDIR']+"/bin:"+os.environ['PATH'] from leagues import settings settings.DATABASES['default']['NAME'] = PROJECT_PATH+'/db.sqlite3' import django django.setup() from scheduler.models import * from pulp import * import csv import xpress as xp # xp.controls.outputlog = 0 scenario = Scenario.objects.get(id=59) # %% teamObjects = Team.objects.filter(season=scenario.season,active=True) teams = teamObjects.values('id','country','pot') 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) def check_feasible(fixed_games): model = xp.problem(name='Draws', sense=xp.minimize) model.setControl ('outputlog', 0) 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()) == 2) for c in countries: if c != t['country']: model.addConstraint(xp.Sum(x[t['id'],t2['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) # SYMMETRY for (t1,t2) in x.keys(): model.addConstraint(x[t1,t2] == x[t2,t1]) # for (t1,t2) in x.keys(): # model.addConstraint(x[t1,t2] + x[t2,t1] <= 1) start_time = time() model.solve() comp_time = time()-start_time if model.getProbStatus() != 6: # print("INFEASIBLE FOUND") return False else: return True # %% for i in range(1,9999999999): print("SIMULATION",i) possible_opps = {} for p in range(1,5): teams_from_pot = list(teamObjects.filter(pot=p).values('id','country')) possible_opps[p] = { t['id']: [t2['id'] for t2 in teams_from_pot if t2['country'] != t['country']] for t in teams } sol_opps = { (t['id'],p):[] for t in teams for p in range(1,5) } fixed_games = [] feasible = True num_combinatorial_clashes = { (t['id'],p):0 for t in teams for p in range(8) } num_possible_opps = { (t['id'],p):None for t in teams for p in range(8) } draw_index = 1 draw_index_dict = { t['id']:None for t in teams } for p in range(1,5): 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): newpot = pos//2+1 # Skip if already drawn if len(sol_opps[new_team,newpot]) >= 2: continue # Update possible opponents opponent_pool = [] for new_opponent in possible_opps[newpot][new_team]: # print("Try opponent",new_opponent,getTeamById[new_opponent]) if len(sol_opps[new_opponent,p]) >= 2: continue # print(f"---> ALREADY DRAWN {pos}: {getTeamById[new_opponent]}") else: new_game = (new_team,new_opponent) if check_feasible(fixed_games+[new_game]): 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) # print(opponent_pool) # print("New team",new_opponent,getTeamById[new_opponent]) # exit() # 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,newpot].append(new_opponent) sol_opps[new_opponent,p].append(new_team) # if pos % 2 == 0: possible_opps[newpot][new_team].remove(new_opponent) fixed_games.append(new_game) with open('draw_options_noHA_2country.csv', "a") as f: for t in teams: opponents = "" for p in range(1,5): for o in sol_opps[t['id'],p]: opponents += str(o)+';' opponents = opponents[:-1] f.write(f"{i},{t['id']},{draw_index_dict[t['id']]},{opponents},{';'.join([str(num_possible_opps[t['id'],p]) for p in range(8)])},{';'.join([str(num_combinatorial_clashes[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]]) # %%