From bb32c5ab70a969e9e911ceaadb19b22c5fab5585 Mon Sep 17 00:00:00 2001 From: martin Date: Wed, 31 Jan 2024 15:37:32 +0100 Subject: [PATCH] UEFA Cycle 24 --- .gitignore | 8 +- .../cycle24/simulations/debugging/conflict.py | 316 ++++++++ uefa/cycle24/simulations/debugging/debug.py | 744 ++++++++++++++++++ uefa/cycle24/simulations/debugging/debug_2.py | 495 ++++++++++++ .../simulations/debugging/debug_draws.py | 307 ++++++++ .../simulations/debugging/debug_xpress.py | 18 + .../drawsimulation_october_gurobi_double.py | 492 ++++++++++++ .../double_draws/probabilities_october.py | 315 ++++++++ .../simulations/drawsimulation_october.py | 497 ++++++++++++ .../drawsimulation_october_gurobi.py | 477 +++++++++++ .../drawsimulation_october_gurobi_all.py | 596 ++++++++++++++ .../drawsimulation_october_gurobi_double.py | 506 ++++++++++++ .../drawsimulation_october_gurobi_all.py | 582 ++++++++++++++ .../mixed_draws/probabilities_october.py | 316 ++++++++ .../simulations/probabilities_october.py | 559 +++++++++++++ .../single_draws/probabilities_october.py | 316 ++++++++ uefa/nations_league/analytics.py | 2 + 17 files changed, 6545 insertions(+), 1 deletion(-) create mode 100755 uefa/cycle24/simulations/debugging/conflict.py create mode 100755 uefa/cycle24/simulations/debugging/debug.py create mode 100755 uefa/cycle24/simulations/debugging/debug_2.py create mode 100755 uefa/cycle24/simulations/debugging/debug_draws.py create mode 100755 uefa/cycle24/simulations/debugging/debug_xpress.py create mode 100755 uefa/cycle24/simulations/double_draws/drawsimulation_october_gurobi_double.py create mode 100755 uefa/cycle24/simulations/double_draws/probabilities_october.py create mode 100755 uefa/cycle24/simulations/drawsimulation_october.py create mode 100755 uefa/cycle24/simulations/drawsimulation_october_gurobi.py create mode 100755 uefa/cycle24/simulations/drawsimulation_october_gurobi_all.py create mode 100755 uefa/cycle24/simulations/drawsimulation_october_gurobi_double.py create mode 100755 uefa/cycle24/simulations/mixed_draws/drawsimulation_october_gurobi_all.py create mode 100755 uefa/cycle24/simulations/mixed_draws/probabilities_october.py create mode 100755 uefa/cycle24/simulations/probabilities_october.py create mode 100755 uefa/cycle24/simulations/single_draws/probabilities_october.py diff --git a/.gitignore b/.gitignore index 285c420..c8e3fd4 100644 --- a/.gitignore +++ b/.gitignore @@ -160,4 +160,10 @@ cython_debug/ # option (not recommended) you can uncomment the following to ignore the entire idea folder. #.idea/ -solver/data/save_point/* \ No newline at end of file +solver/data/save_point/* +*.json +*.csv +*.html +*.lp +*.mps +*.pptx diff --git a/uefa/cycle24/simulations/debugging/conflict.py b/uefa/cycle24/simulations/debugging/conflict.py new file mode 100755 index 0000000..01e272e --- /dev/null +++ b/uefa/cycle24/simulations/debugging/conflict.py @@ -0,0 +1,316 @@ +import pulp +from pulp import lpSum, XPRESS, GUROBI, PULP_CBC_CMD, XPRESS_PY + +""" +########################################################################################################################## +########################################################################################################################## +""" + + +teams = [{'id': 3696, 'country': 'FRA', 'pot': 4, 'shortname': 'Lens'}, + {'id': 3697, 'country': 'GER', 'pot': 4, 'shortname': 'Unio'}, + {'id': 3698, 'country': 'ENG', 'pot': 4, 'shortname': 'Newc'}, + {'id': 3699, 'country': 'ESP', 'pot': 4, 'shortname': 'Soci'}, + {'id': 3700, 'country': 'SUI', 'pot': 3, 'shortname': 'Youn'}, + {'id': 3701, 'country': 'NED', 'pot': 3, 'shortname': 'Feye'}, + {'id': 3702, 'country': 'ENG', 'pot': 1, 'shortname': 'ManU'}, + {'id': 3730, 'country': 'SRB', 'pot': 3, 'shortname': 'Crve'}, + {'id': 3732, 'country': 'ITA', 'pot': 1, 'shortname': 'Inte'}, + {'id': 3734, 'country': 'ITA', 'pot': 2, 'shortname': 'Napo'}, + {'id': 3756, 'country': 'ITA', 'pot': 3, 'shortname': 'Mila'}, + {'id': 3757, 'country': 'SCO', 'pot': 4, 'shortname': 'Celt'}, + {'id': 3758, 'country': 'DEN', 'pot': 3, 'shortname': 'Cope'}, + {'id': 3760, 'country': 'NED', 'pot': 3, 'shortname': 'PSV'}, + {'id': 3761, 'country': 'ENG', 'pot': 2, 'shortname': 'Arse'}, + {'id': 3762, 'country': 'ESP', 'pot': 1, 'shortname': 'Sevi'}, + {'id': 3764, 'country': 'ENG', 'pot': 1, 'shortname': 'Live'}, + {'id': 3765, 'country': 'UKR', 'pot': 2, 'shortname': 'Shak'}, + {'id': 3771, 'country': 'ITA', 'pot': 3, 'shortname': 'Atal'}, + {'id': 3853, 'country': 'FRA', 'pot': 4, 'shortname': 'Mars'}, + {'id': 3870, 'country': 'TUR', 'pot': 4, 'shortname': 'Gala'}, + {'id': 3894, 'country': 'ESP', 'pot': 1, 'shortname': 'Barc'}, + {'id': 3895, 'country': 'ITA', 'pot': 3, 'shortname': 'Lazi'}, + {'id': 3898, 'country': 'ESP', 'pot': 2, 'shortname': 'Atle'}, + {'id': 3904, 'country': 'AZE', 'pot': 4, 'shortname': 'Qara'}, + {'id': 3925, 'country': 'BEL', 'pot': 4, 'shortname': 'Antw'}, + {'id': 3926, 'country': 'GER', 'pot': 2, 'shortname': 'Leip'}, + {'id': 3928, 'country': 'POR', 'pot': 3, 'shortname': 'Brag'}, + {'id': 3930, 'country': 'POR', 'pot': 2, 'shortname': 'Benf'}, + {'id': 3932, 'country': 'GER', 'pot': 1, 'shortname': 'Baye'}, + {'id': 3933, 'country': 'ESP', 'pot': 1, 'shortname': 'Real'}, + {'id': 3935, 'country': 'FRA', 'pot': 1, 'shortname': 'PSG'}, + {'id': 3936, 'country': 'GER', 'pot': 2, 'shortname': 'Dort'}, + {'id': 3937, 'country': 'POR', 'pot': 2, 'shortname': 'Port'}, + {'id': 3938, 'country': 'AUT', 'pot': 2, 'shortname': 'Salz'}, + {'id': 3940, 'country': 'ENG', 'pot': 1, 'shortname': 'Manc'}] + +getTeamById = {3702: '(ENG) Manchester United FC', + 3764: '(ENG) Liverpool FC', + 3940: '(ENG) Manchester City FC', + 3762: '(ESP) Sevilla FC', + 3894: '(ESP) FC Barcelona', + 3933: '(ESP) Real Madrid CF', + 3935: '(FRA) Paris Saint-Germain', + 3932: '(GER) FC Bayern München', + 3732: '(ITA) FC Internazionale Milano', + 3938: '(AUT) FC Salzburg', + 3761: '(ENG) Arsenal FC', + 3898: '(ESP) Club Atlético de Madrid', + 3926: '(GER) RB Leipzig', + 3936: '(GER) Borussia Dortmund', + 3734: '(ITA) SSC Napoli', + 3930: '(POR) SL Benfica', + 3937: '(POR) FC Porto', + 3765: '(UKR) FC Shakhtar Donetsk', + 3758: '(DEN) F.C. Copenhagen', + 3756: '(ITA) AC Milan', + 3771: '(ITA) Atalanta BC', + 3895: '(ITA) S.S. Lazio', + 3701: '(NED) Feyenoord', + 3760: '(NED) PSV Eindhoven', + 3928: '(POR) SC Braga', + 3730: '(SRB) FK Crvena zvezda', + 3700: '(SUI) BSC Young Boys', + 3904: '(AZE) Qarabağ FK', + 3925: '(BEL) R. Antwerp FC', + 3698: '(ENG) Newcastle United FC', + 3699: '(ESP) Real Sociedad de Fútbol', + 3696: '(FRA) RC Lens', + 3853: '(FRA) Olympique de Marseille', + 3697: '(GER) 1. FC Union Berlin', + 3757: '(SCO) Celtic FC', + 3870: '(TUR) Galatasaray A.Ş.'} + +pot = {1: [{'id': 3702, 'country': 'ENG', 'pot': 1, 'shortname': 'ManU'}, + {'id': 3764, 'country': 'ENG', 'pot': 1, 'shortname': 'Liver'}, + {'id': 3940, 'country': 'ENG', 'pot': 1, 'shortname': 'Manch'}, + {'id': 3762, 'country': 'ESP', 'pot': 1, 'shortname': 'Sevil'}, + {'id': 3894, 'country': 'ESP', 'pot': 1, 'shortname': 'Barce'}, + {'id': 3933, 'country': 'ESP', 'pot': 1, 'shortname': 'Real '}, + {'id': 3935, 'country': 'FRA', 'pot': 1, 'shortname': 'PSG'}, + {'id': 3932, 'country': 'GER', 'pot': 1, 'shortname': 'Bayer'}, + {'id': 3732, 'country': 'ITA', 'pot': 1, 'shortname': 'Inter'}], + 2: [{'id': 3938, 'country': 'AUT', 'pot': 2, 'shortname': 'Salzb'}, + {'id': 3761, 'country': 'ENG', 'pot': 2, 'shortname': 'Arsen'}, + {'id': 3898, 'country': 'ESP', 'pot': 2, 'shortname': 'Atlét'}, + {'id': 3926, 'country': 'GER', 'pot': 2, 'shortname': 'Leipz'}, + {'id': 3936, 'country': 'GER', 'pot': 2, 'shortname': 'Dortm'}, + {'id': 3734, 'country': 'ITA', 'pot': 2, 'shortname': 'Napol'}, + {'id': 3930, 'country': 'POR', 'pot': 2, 'shortname': 'Benfi'}, + {'id': 3937, 'country': 'POR', 'pot': 2, 'shortname': 'Porto'}, + {'id': 3765, 'country': 'UKR', 'pot': 2, 'shortname': 'Shakh'}], + 3: [{'id': 3758, 'country': 'DEN', 'pot': 3, 'shortname': 'Copen'}, + {'id': 3756, 'country': 'ITA', 'pot': 3, 'shortname': 'Milan'}, + {'id': 3771, 'country': 'ITA', 'pot': 3, 'shortname': 'Atala'}, + {'id': 3895, 'country': 'ITA', 'pot': 3, 'shortname': 'Lazio'}, + {'id': 3701, 'country': 'NED', 'pot': 3, 'shortname': 'Feyen'}, + {'id': 3760, 'country': 'NED', 'pot': 3, 'shortname': 'PSV'}, + {'id': 3928, 'country': 'POR', 'pot': 3, 'shortname': 'Braga'}, + {'id': 3730, 'country': 'SRB', 'pot': 3, 'shortname': 'Crven'}, + {'id': 3700, 'country': 'SUI', 'pot': 3, 'shortname': 'Young'}], + 4: [{'id': 3904, 'country': 'AZE', 'pot': 4, 'shortname': 'Qarab'}, + {'id': 3925, 'country': 'BEL', 'pot': 4, 'shortname': 'Antwe'}, + {'id': 3698, 'country': 'ENG', 'pot': 4, 'shortname': 'Newca'}, + {'id': 3699, 'country': 'ESP', 'pot': 4, 'shortname': 'Socied'}, + {'id': 3696, 'country': 'FRA', 'pot': 4, 'shortname': 'Lens'}, + {'id': 3853, 'country': 'FRA', 'pot': 4, 'shortname': 'Marse'}, + {'id': 3697, 'country': 'GER', 'pot': 4, 'shortname': 'Union'}, + {'id': 3757, 'country': 'SCO', 'pot': 4, 'shortname': 'Celti'}, + {'id': 3870, 'country': 'TUR', 'pot': 4, 'shortname': 'Galat'}]} + + +teams_from_country = {'NED': [{'id': 3701, 'country': 'NED', 'pot': 3, 'shortname': 'Feye'}, + {'id': 3760, 'country': 'NED', 'pot': 3, 'shortname': 'PSV'}], + 'UKR': [{'id': 3765, 'country': 'UKR', 'pot': 2, 'shortname': 'Shak'}], + 'ENG': [{'id': 3702, 'country': 'ENG', 'pot': 1, 'shortname': 'ManU'}, + {'id': 3764, 'country': 'ENG', 'pot': 1, 'shortname': 'Live'}, + {'id': 3940, 'country': 'ENG', 'pot': 1, 'shortname': 'Manc'}, + {'id': 3761, 'country': 'ENG', 'pot': 2, 'shortname': 'Arse'}, + {'id': 3698, 'country': 'ENG', 'pot': 4, 'shortname': 'Newc'}], + 'POR': [{'id': 3930, 'country': 'POR', 'pot': 2, 'shortname': 'Benf'}, + {'id': 3937, 'country': 'POR', 'pot': 2, 'shortname': 'Port'}, + {'id': 3928, 'country': 'POR', 'pot': 3, 'shortname': 'Brag'}], + 'GER': [{'id': 3932, 'country': 'GER', 'pot': 1, 'shortname': 'Baye'}, + {'id': 3926, 'country': 'GER', 'pot': 2, 'shortname': 'Leip'}, + {'id': 3936, 'country': 'GER', 'pot': 2, 'shortname': 'Dort'}, + {'id': 3697, 'country': 'GER', 'pot': 4, 'shortname': 'Unio'}], + 'DEN': [{'id': 3758, 'country': 'DEN', 'pot': 3, 'shortname': 'Cope'}], + 'FRA': [{'id': 3935, 'country': 'FRA', 'pot': 1, 'shortname': 'PSG'}, + {'id': 3696, 'country': 'FRA', 'pot': 4, 'shortname': 'Lens'}, + {'id': 3853, 'country': 'FRA', 'pot': 4, 'shortname': 'Mars'}], + 'AZE': [{'id': 3904, 'country': 'AZE', 'pot': 4, 'shortname': 'Qara'}], + 'TUR': [{'id': 3870, 'country': 'TUR', 'pot': 4, 'shortname': 'Gala'}], + 'ITA': [{'id': 3732, 'country': 'ITA', 'pot': 1, 'shortname': 'Inte'}, + {'id': 3734, 'country': 'ITA', 'pot': 2, 'shortname': 'Napo'}, + {'id': 3756, 'country': 'ITA', 'pot': 3, 'shortname': 'Mila'}, + {'id': 3771, 'country': 'ITA', 'pot': 3, 'shortname': 'Atal'}, + {'id': 3895, 'country': 'ITA', 'pot': 3, 'shortname': 'Lazi'}], + 'BEL': [{'id': 3925, 'country': 'BEL', 'pot': 4, 'shortname': 'Antw'}], + 'SRB': [{'id': 3730, 'country': 'SRB', 'pot': 3, 'shortname': 'Crve'}], + 'SUI': [{'id': 3700, 'country': 'SUI', 'pot': 3, 'shortname': 'Youn'}], + 'SCO': [{'id': 3757, 'country': 'SCO', 'pot': 4, 'shortname': 'Celt'}], + 'ESP': [{'id': 3762, 'country': 'ESP', 'pot': 1, 'shortname': 'Sevi'}, + {'id': 3894, 'country': 'ESP', 'pot': 1, 'shortname': 'Barc'}, + {'id': 3933, 'country': 'ESP', 'pot': 1, 'shortname': 'Real'}, + {'id': 3898, 'country': 'ESP', 'pot': 2, 'shortname': 'Atle'}, + {'id': 3699, 'country': 'ESP', 'pot': 4, 'shortname': 'Soci'}], + 'AUT': [{'id': 3938, 'country': 'AUT', 'pot': 2, 'shortname': 'Salz'}]} + +countries = ['NED', + 'UKR', + 'ENG', + 'POR', + 'GER', + 'DEN', + 'FRA', + 'AZE', + 'TUR', + 'ITA', + 'BEL', + 'SRB', + 'SUI', + 'SCO', + 'ESP', + 'AUT'] + + +""" +########################################################################################################################## +########################################################################################################################## +""" + + + +def check_feasible(fixed_games): + model = pulp.LpProblem(f"Draws", pulp.LpMinimize) + 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) + + # REQUIREMENTS + for t in teams: + for r in range(1,5): + 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']: + model += lpSum(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 += x[t1,t2] + x[t2,t1] <= 1 + + # FIXATIONS + for (t1,t2) in fixed_games: + model += x[t1,t2] == 1 + + # OBJECTIVE + model += lpSum(x[t1,t2] for (t1,t2) in x.keys()) + solver = XPRESS_PY(msg=1) + model.solve(solver) + print(XPRESS_PY.getAttribute(None,model,'bestbound')) + + if model.status in [0,-1,-2]: + print("INFEASIBLE") + return False,x + else: + print("SUCCESS") + return True,x + + + +""" +########################################################################################################################## +########################################################################################################################## +""" + + + + +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)] + + + + +feasible, sol = check_feasible(fixed_games) + + +# if feasible: +# # GET GAMES +# games = [] +# for key in sol.keys(): +# if sol[key].value() != 0: +# games.append(key) + + +# # CHECK AGAIN +# check_feasible(games) + + +# # WRITE SOL '.html' +# teams = sorted(teams, key=lambda k: k['pot']) +# sol = '' +# sol += " \ +# \ +# " +# sol += "\n" +# sol += "\n" +# sol += "" +# sol += "" +# sol += "" +# sol += "" +# sol += "" +# sol += "" +# sol += "" +# sol += "\n" +# sol += f"\n" +# for t in teams: +# sol += f"\n" +# sol += "\n" +# sol += "\n" +# sol += "\n" +# for t1 in teams: +# sol += "\n" +# sol += f"" +# for t2 in teams: +# 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.html', 'w') as f: +# f.write(sol) + diff --git a/uefa/cycle24/simulations/debugging/debug.py b/uefa/cycle24/simulations/debugging/debug.py new file mode 100755 index 0000000..ade0118 --- /dev/null +++ b/uefa/cycle24/simulations/debugging/debug.py @@ -0,0 +1,744 @@ +# %% +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) + + + + + + + + + + + + +# %% + + diff --git a/uefa/cycle24/simulations/debugging/debug_2.py b/uefa/cycle24/simulations/debugging/debug_2.py new file mode 100755 index 0000000..b2ce4ff --- /dev/null +++ b/uefa/cycle24/simulations/debugging/debug_2.py @@ -0,0 +1,495 @@ +# %% +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_8.4" +# os.environ["XPRESS"] = "/opt/xpressmp_8.4/bin" +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 codecs +# 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','shortname') + +for t in teams: + t['shortname'] = t['shortname'][:4] + if t['shortname'][:-1] == 'Atl': + t['shortname'] = 'Atle' + +getTeamById = {} +for t in teamObjects: + getTeamById[t.id] = f"({t.country}) {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)] + + + +# %% + + + + + +model = pulp.LpProblem(f"Draws", pulp.LpMinimize) +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) + +# REQUIREMENTS +for t in teams: + for r in range(1,5): + 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']: + 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: + model += x[t1,t2] == 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()) +with open ("model.txt", "w") as f: + f.write(model.__repr__()) +model.writeLP('pulp.lp') +model.writeMPS('pulp.mps') +model.solve(XPRESS(msg=1)) + +if model.status in [-1,-2]: + print("ERROR") +else: + print("SUCCESS") + + +exit() + +print("\n\n\n\n") + +model = pulp.LpProblem(f"Draws", pulp.LpMinimize) +x = {} +for t1 in teams: + for t2 in teams: + if t1['country'] != t2['country']: + x[t1['id'], t2['id']] = pulp.LpVariable('x_'+str(t1['shortname'])+'_'+str(t2['shortname']),lowBound=0, upBound=1, cat=pulp.LpInteger) + +# REQUIREMENTS +for t in teams: + for r in range(1,5): + model += lpSum(x[t['id'],t2['id']] for t2 in pot[r] if (t['id'],t2['id']) in x.keys()) == 1, f"pot_{getTeamById[t['id']]}_{r}_H" + model += lpSum(x[t2['id'],t['id']] for t2 in pot[r] if (t2['id'],t['id']) in x.keys()) == 1, f"pot_{getTeamById[t['id']]}_{r}_A" + + + for c in countries: + if c != t['country']: + model += lpSum(x[t['id'],t2['id']]+x[t2['id'],t['id']] for t2 in teams_from_country[c]) <= 2, f"country_{getTeamById[t['id']]}_{c}" + + +# FIXATIONS +for (t1,t2) in fixed_games: + model += x[t1,t2] == 1, f"fix_{t1}_{t2}" + + + +for (t1,t2) in x.keys(): + model += x[t1,t2] + x[t2,t1] <= 1, f"symmetry_{t1}_{t2}" + +model.solve(XPRESS(msg=1)) + + + +# games = [] +# for key in x.keys(): +# x[key].lowBound = x[key].value() +# if x[key].value() != 0: +# games.append(key) + +# with open ("model2.txt", "w") as f: +# f.write(model.__repr__()) +# model.solve(XPRESS(msg=1)) + + + +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) + + + + + + + + + + + + +# %% + + diff --git a/uefa/cycle24/simulations/debugging/debug_draws.py b/uefa/cycle24/simulations/debugging/debug_draws.py new file mode 100755 index 0000000..d37eb50 --- /dev/null +++ b/uefa/cycle24/simulations/debugging/debug_draws.py @@ -0,0 +1,307 @@ +import pulp +from pulp import lpSum, XPRESS, GUROBI, PULP_CBC_CMD + +""" +########################################################################################################################## +########################################################################################################################## +""" + + +teams = [{'id': 3696, 'country': 'FRA', 'pot': 4, 'shortname': 'Lens'}, + {'id': 3697, 'country': 'GER', 'pot': 4, 'shortname': 'Unio'}, + {'id': 3698, 'country': 'ENG', 'pot': 4, 'shortname': 'Newc'}, + {'id': 3699, 'country': 'ESP', 'pot': 4, 'shortname': 'Soci'}, + {'id': 3700, 'country': 'SUI', 'pot': 3, 'shortname': 'Youn'}, + {'id': 3701, 'country': 'NED', 'pot': 3, 'shortname': 'Feye'}, + {'id': 3702, 'country': 'ENG', 'pot': 1, 'shortname': 'ManU'}, + {'id': 3730, 'country': 'SRB', 'pot': 3, 'shortname': 'Crve'}, + {'id': 3732, 'country': 'ITA', 'pot': 1, 'shortname': 'Inte'}, + {'id': 3734, 'country': 'ITA', 'pot': 2, 'shortname': 'Napo'}, + {'id': 3756, 'country': 'ITA', 'pot': 3, 'shortname': 'Mila'}, + {'id': 3757, 'country': 'SCO', 'pot': 4, 'shortname': 'Celt'}, + {'id': 3758, 'country': 'DEN', 'pot': 3, 'shortname': 'Cope'}, + {'id': 3760, 'country': 'NED', 'pot': 3, 'shortname': 'PSV'}, + {'id': 3761, 'country': 'ENG', 'pot': 2, 'shortname': 'Arse'}, + {'id': 3762, 'country': 'ESP', 'pot': 1, 'shortname': 'Sevi'}, + {'id': 3764, 'country': 'ENG', 'pot': 1, 'shortname': 'Live'}, + {'id': 3765, 'country': 'UKR', 'pot': 2, 'shortname': 'Shak'}, + {'id': 3771, 'country': 'ITA', 'pot': 3, 'shortname': 'Atal'}, + {'id': 3853, 'country': 'FRA', 'pot': 4, 'shortname': 'Mars'}, + {'id': 3870, 'country': 'TUR', 'pot': 4, 'shortname': 'Gala'}, + {'id': 3894, 'country': 'ESP', 'pot': 1, 'shortname': 'Barc'}, + {'id': 3895, 'country': 'ITA', 'pot': 3, 'shortname': 'Lazi'}, + {'id': 3898, 'country': 'ESP', 'pot': 2, 'shortname': 'Atle'}, + {'id': 3904, 'country': 'AZE', 'pot': 4, 'shortname': 'Qara'}, + {'id': 3925, 'country': 'BEL', 'pot': 4, 'shortname': 'Antw'}, + {'id': 3926, 'country': 'GER', 'pot': 2, 'shortname': 'Leip'}, + {'id': 3928, 'country': 'POR', 'pot': 3, 'shortname': 'Brag'}, + {'id': 3930, 'country': 'POR', 'pot': 2, 'shortname': 'Benf'}, + {'id': 3932, 'country': 'GER', 'pot': 1, 'shortname': 'Baye'}, + {'id': 3933, 'country': 'ESP', 'pot': 1, 'shortname': 'Real'}, + {'id': 3935, 'country': 'FRA', 'pot': 1, 'shortname': 'PSG'}, + {'id': 3936, 'country': 'GER', 'pot': 2, 'shortname': 'Dort'}, + {'id': 3937, 'country': 'POR', 'pot': 2, 'shortname': 'Port'}, + {'id': 3938, 'country': 'AUT', 'pot': 2, 'shortname': 'Salz'}, + {'id': 3940, 'country': 'ENG', 'pot': 1, 'shortname': 'Manc'}] + +getTeamById = {3702: '(ENG) Manchester United FC', + 3764: '(ENG) Liverpool FC', + 3940: '(ENG) Manchester City FC', + 3762: '(ESP) Sevilla FC', + 3894: '(ESP) FC Barcelona', + 3933: '(ESP) Real Madrid CF', + 3935: '(FRA) Paris Saint-Germain', + 3932: '(GER) FC Bayern München', + 3732: '(ITA) FC Internazionale Milano', + 3938: '(AUT) FC Salzburg', + 3761: '(ENG) Arsenal FC', + 3898: '(ESP) Club Atlético de Madrid', + 3926: '(GER) RB Leipzig', + 3936: '(GER) Borussia Dortmund', + 3734: '(ITA) SSC Napoli', + 3930: '(POR) SL Benfica', + 3937: '(POR) FC Porto', + 3765: '(UKR) FC Shakhtar Donetsk', + 3758: '(DEN) F.C. Copenhagen', + 3756: '(ITA) AC Milan', + 3771: '(ITA) Atalanta BC', + 3895: '(ITA) S.S. Lazio', + 3701: '(NED) Feyenoord', + 3760: '(NED) PSV Eindhoven', + 3928: '(POR) SC Braga', + 3730: '(SRB) FK Crvena zvezda', + 3700: '(SUI) BSC Young Boys', + 3904: '(AZE) Qarabağ FK', + 3925: '(BEL) R. Antwerp FC', + 3698: '(ENG) Newcastle United FC', + 3699: '(ESP) Real Sociedad de Fútbol', + 3696: '(FRA) RC Lens', + 3853: '(FRA) Olympique de Marseille', + 3697: '(GER) 1. FC Union Berlin', + 3757: '(SCO) Celtic FC', + 3870: '(TUR) Galatasaray A.Ş.'} + +pot = {1: [{'id': 3702, 'country': 'ENG', 'pot': 1, 'shortname': 'ManU'}, + {'id': 3764, 'country': 'ENG', 'pot': 1, 'shortname': 'Liver'}, + {'id': 3940, 'country': 'ENG', 'pot': 1, 'shortname': 'Manch'}, + {'id': 3762, 'country': 'ESP', 'pot': 1, 'shortname': 'Sevil'}, + {'id': 3894, 'country': 'ESP', 'pot': 1, 'shortname': 'Barce'}, + {'id': 3933, 'country': 'ESP', 'pot': 1, 'shortname': 'Real '}, + {'id': 3935, 'country': 'FRA', 'pot': 1, 'shortname': 'PSG'}, + {'id': 3932, 'country': 'GER', 'pot': 1, 'shortname': 'Bayer'}, + {'id': 3732, 'country': 'ITA', 'pot': 1, 'shortname': 'Inter'}], + 2: [{'id': 3938, 'country': 'AUT', 'pot': 2, 'shortname': 'Salzb'}, + {'id': 3761, 'country': 'ENG', 'pot': 2, 'shortname': 'Arsen'}, + {'id': 3898, 'country': 'ESP', 'pot': 2, 'shortname': 'Atlét'}, + {'id': 3926, 'country': 'GER', 'pot': 2, 'shortname': 'Leipz'}, + {'id': 3936, 'country': 'GER', 'pot': 2, 'shortname': 'Dortm'}, + {'id': 3734, 'country': 'ITA', 'pot': 2, 'shortname': 'Napol'}, + {'id': 3930, 'country': 'POR', 'pot': 2, 'shortname': 'Benfi'}, + {'id': 3937, 'country': 'POR', 'pot': 2, 'shortname': 'Porto'}, + {'id': 3765, 'country': 'UKR', 'pot': 2, 'shortname': 'Shakh'}], + 3: [{'id': 3758, 'country': 'DEN', 'pot': 3, 'shortname': 'Copen'}, + {'id': 3756, 'country': 'ITA', 'pot': 3, 'shortname': 'Milan'}, + {'id': 3771, 'country': 'ITA', 'pot': 3, 'shortname': 'Atala'}, + {'id': 3895, 'country': 'ITA', 'pot': 3, 'shortname': 'Lazio'}, + {'id': 3701, 'country': 'NED', 'pot': 3, 'shortname': 'Feyen'}, + {'id': 3760, 'country': 'NED', 'pot': 3, 'shortname': 'PSV'}, + {'id': 3928, 'country': 'POR', 'pot': 3, 'shortname': 'Braga'}, + {'id': 3730, 'country': 'SRB', 'pot': 3, 'shortname': 'Crven'}, + {'id': 3700, 'country': 'SUI', 'pot': 3, 'shortname': 'Young'}], + 4: [{'id': 3904, 'country': 'AZE', 'pot': 4, 'shortname': 'Qarab'}, + {'id': 3925, 'country': 'BEL', 'pot': 4, 'shortname': 'Antwe'}, + {'id': 3698, 'country': 'ENG', 'pot': 4, 'shortname': 'Newca'}, + {'id': 3699, 'country': 'ESP', 'pot': 4, 'shortname': 'Socied'}, + {'id': 3696, 'country': 'FRA', 'pot': 4, 'shortname': 'Lens'}, + {'id': 3853, 'country': 'FRA', 'pot': 4, 'shortname': 'Marse'}, + {'id': 3697, 'country': 'GER', 'pot': 4, 'shortname': 'Union'}, + {'id': 3757, 'country': 'SCO', 'pot': 4, 'shortname': 'Celti'}, + {'id': 3870, 'country': 'TUR', 'pot': 4, 'shortname': 'Galat'}]} + + +teams_from_country = {'NED': [{'id': 3701, 'country': 'NED', 'pot': 3, 'shortname': 'Feye'}, + {'id': 3760, 'country': 'NED', 'pot': 3, 'shortname': 'PSV'}], + 'UKR': [{'id': 3765, 'country': 'UKR', 'pot': 2, 'shortname': 'Shak'}], + 'ENG': [{'id': 3702, 'country': 'ENG', 'pot': 1, 'shortname': 'ManU'}, + {'id': 3764, 'country': 'ENG', 'pot': 1, 'shortname': 'Live'}, + {'id': 3940, 'country': 'ENG', 'pot': 1, 'shortname': 'Manc'}, + {'id': 3761, 'country': 'ENG', 'pot': 2, 'shortname': 'Arse'}, + {'id': 3698, 'country': 'ENG', 'pot': 4, 'shortname': 'Newc'}], + 'POR': [{'id': 3930, 'country': 'POR', 'pot': 2, 'shortname': 'Benf'}, + {'id': 3937, 'country': 'POR', 'pot': 2, 'shortname': 'Port'}, + {'id': 3928, 'country': 'POR', 'pot': 3, 'shortname': 'Brag'}], + 'GER': [{'id': 3932, 'country': 'GER', 'pot': 1, 'shortname': 'Baye'}, + {'id': 3926, 'country': 'GER', 'pot': 2, 'shortname': 'Leip'}, + {'id': 3936, 'country': 'GER', 'pot': 2, 'shortname': 'Dort'}, + {'id': 3697, 'country': 'GER', 'pot': 4, 'shortname': 'Unio'}], + 'DEN': [{'id': 3758, 'country': 'DEN', 'pot': 3, 'shortname': 'Cope'}], + 'FRA': [{'id': 3935, 'country': 'FRA', 'pot': 1, 'shortname': 'PSG'}, + {'id': 3696, 'country': 'FRA', 'pot': 4, 'shortname': 'Lens'}, + {'id': 3853, 'country': 'FRA', 'pot': 4, 'shortname': 'Mars'}], + 'AZE': [{'id': 3904, 'country': 'AZE', 'pot': 4, 'shortname': 'Qara'}], + 'TUR': [{'id': 3870, 'country': 'TUR', 'pot': 4, 'shortname': 'Gala'}], + 'ITA': [{'id': 3732, 'country': 'ITA', 'pot': 1, 'shortname': 'Inte'}, + {'id': 3734, 'country': 'ITA', 'pot': 2, 'shortname': 'Napo'}, + {'id': 3756, 'country': 'ITA', 'pot': 3, 'shortname': 'Mila'}, + {'id': 3771, 'country': 'ITA', 'pot': 3, 'shortname': 'Atal'}, + {'id': 3895, 'country': 'ITA', 'pot': 3, 'shortname': 'Lazi'}], + 'BEL': [{'id': 3925, 'country': 'BEL', 'pot': 4, 'shortname': 'Antw'}], + 'SRB': [{'id': 3730, 'country': 'SRB', 'pot': 3, 'shortname': 'Crve'}], + 'SUI': [{'id': 3700, 'country': 'SUI', 'pot': 3, 'shortname': 'Youn'}], + 'SCO': [{'id': 3757, 'country': 'SCO', 'pot': 4, 'shortname': 'Celt'}], + 'ESP': [{'id': 3762, 'country': 'ESP', 'pot': 1, 'shortname': 'Sevi'}, + {'id': 3894, 'country': 'ESP', 'pot': 1, 'shortname': 'Barc'}, + {'id': 3933, 'country': 'ESP', 'pot': 1, 'shortname': 'Real'}, + {'id': 3898, 'country': 'ESP', 'pot': 2, 'shortname': 'Atle'}, + {'id': 3699, 'country': 'ESP', 'pot': 4, 'shortname': 'Soci'}], + 'AUT': [{'id': 3938, 'country': 'AUT', 'pot': 2, 'shortname': 'Salz'}]} + +countries = ['NED', + 'UKR', + 'ENG', + 'POR', + 'GER', + 'DEN', + 'FRA', + 'AZE', + 'TUR', + 'ITA', + 'BEL', + 'SRB', + 'SUI', + 'SCO', + 'ESP', + 'AUT'] + + + + +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)] + + + +""" +########################################################################################################################## +########################################################################################################################## +""" + +model = pulp.LpProblem(f"Draws", pulp.LpMinimize) +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) + +# REQUIREMENTS +for t in teams: + for r in range(1,5): + 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']: + model += lpSum(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 += x[t1,t2] + x[t2,t1] <= 1 + +# FIXATIONS +for (t1,t2) in fixed_games: + model += x[t1,t2] == 1 + +model.solve(XPRESS(msg=1)) + +if model.status in [-1,-2]: + print("INFEASIBLE") +else: + print("SUCCESS") + + + + +""" +########################################################################################################################## +########################################################################################################################## +""" + + + + + +# if feasible: +# # GET GAMES +# games = [] +# for key in sol.keys(): +# if sol[key].value() != 0: +# games.append(key) + + +# # CHECK AGAIN +# check_feasible(games) + + +# # WRITE SOL '.html' +# teams = sorted(teams, key=lambda k: k['pot']) +# sol = '' +# sol += " \ +# \ +# " +# sol += "\n" +# sol += "\n" +# sol += "" +# sol += "" +# sol += "" +# sol += "" +# sol += "" +# sol += "" +# sol += "" +# sol += "\n" +# sol += f"\n" +# for t in teams: +# sol += f"\n" +# sol += "\n" +# sol += "\n" +# sol += "\n" +# for t1 in teams: +# sol += "\n" +# sol += f"" +# for t2 in teams: +# 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_draws.html', 'w') as f: +# f.write(sol) + diff --git a/uefa/cycle24/simulations/debugging/debug_xpress.py b/uefa/cycle24/simulations/debugging/debug_xpress.py new file mode 100755 index 0000000..11261d2 --- /dev/null +++ b/uefa/cycle24/simulations/debugging/debug_xpress.py @@ -0,0 +1,18 @@ +import xpress as xp + +m = xp.problem() +m.read("debug.mps") + +print("Set presolve to 1") +m.setControl('presolve',1) +m.optimize() +print("solution status code: ", m.getProbStatus(), " -->", + m.getProbStatusString()) + + +print("\n\n") +print("Set presolve to 0") +m.setControl('presolve',0) +m.optimize() +print("solution status code: ", m.getProbStatus(), " -->", + m.getProbStatusString()) diff --git a/uefa/cycle24/simulations/double_draws/drawsimulation_october_gurobi_double.py b/uefa/cycle24/simulations/double_draws/drawsimulation_october_gurobi_double.py new file mode 100755 index 0000000..b78f4d5 --- /dev/null +++ b/uefa/cycle24/simulations/double_draws/drawsimulation_october_gurobi_double.py @@ -0,0 +1,492 @@ +# %% +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_8.4" +os.environ["XPRESS"] = "/opt/xpressmp_8.4/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 gurobipy as gp +from gurobipy import GRB +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') +teams = teamObjects.values('id','country','pot','name') + +getTeamById = {} +for t in teamObjects: + getTeamById[t.id] = f"({t.pot}) {t.name}" + +getCountryById = {} +for t in teamObjects: + getCountryById[t.id] = t.country + + +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)] + + + +def check_feasible_pulp(fixed_games): + + model = pulp.LpProblem(f"Draws", pulp.LpMinimize) + + 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) + + + # 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) + 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']: + # model.addConstraint(xp.Sum(x[t['id'],t2['id']]+x[t2['id'],t['id']] for t2 in teams_from_country[c]) <= 3) + model += lpSum(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) + model += x[t1,t2] == 1 + + for (t1,t2) in x.keys(): + model += x[t1,t2] + x[t2,t1] <= 1, f'directed_{t1}_{t2}' + # model.addConstraint(x[t1,t2] + x[t2,t1] <= 1) + + model += lpSum(random.uniform(0,1)*x[key] for key in x.keys()) + tt =time.time() + model.solve(XPRESS(msg=0,timeLimit=120,keepFiles=0)) + comp_time = time.time()-tt + + if model.status in [-1,-2]: + return False, comp_time + else: + return True, comp_time + + + + +model = gp.Model('Draws') +model.Params.OutputFlag = 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) + x[t1['id'], t2['id']] = model.addVar(vtype=GRB.BINARY) + +# REQUIREMENTS +for t in teams: + for r in range(1,5): + model.addConstr(gp.quicksum(x[t['id'],t2['id']] for t2 in pot[r] if (t['id'],t2['id']) in x.keys()) == 1) + model.addConstr(gp.quicksum(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.addConstr(gp.quicksum(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.addConstr(x[t1,t2] + x[t2,t1] <= 1) + + + + +def check_feasible_gurobi(fixed_games): + + # FIXATIONS + for key in x.keys(): + if key in fixed_games: + x[key].lb = 1 + else: + x[key].lb = 0 + + model.update() + + # tt =time.time() + # model.solve() + model.optimize() + # comp_time = time.time()-tt + + + if model.Status == GRB.OPTIMAL: + return True, 0 + else: + # print("INFEASIBLE FOUND") + return False, 0 + + +def check_feasible(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 + + + + +# 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()) == 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 + + + + + +import itertools +from itertools import permutations , product + +def simulate_draws(filename,n): + + print("RUNNING ASYNC",filename) + fixed_games=None + 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) + } + + sol_countries = { + (t['id'],c):0 + for t in teams for c in countries if c != t['country'] + } + + 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(2*(p-1),8,2): + if sol_opps[new_team,current_pos] != None and sol_opps[new_team,current_pos+1] != None: + continue + + possible_opps[current_pos][new_team] = [t for t in possible_opps[current_pos][new_team] if sol_countries[new_team,getCountryById[t]] < 2 and + sol_countries[t,getCountryById[new_team]] < 2 and sol_opps[t,(2*p-1)] == None] + possible_opps[current_pos+1][new_team] = [t for t in possible_opps[current_pos+1][new_team] if sol_countries[new_team,getCountryById[t]] < 2 and + sol_countries[t,getCountryById[new_team]] < 2 and sol_opps[t,(2*p-1)-1] == None] + + list_1 = [None] + list_2 = [None] + if sol_opps[new_team,current_pos] == None: + list_1 = possible_opps[current_pos][new_team] + if sol_opps[new_team,current_pos+1] == None: + list_2 = possible_opps[current_pos+1][new_team] + + # unique_combinations = [] + # for i in range(len(list_1)): + # for j in range(len(list_2)): + # unique_combinations.append((list_1[i], list_2[j])) + unique_combinations = list(itertools.product(list_1, list_2)) + random.shuffle(unique_combinations) + + + no_solution_found = True + while (no_solution_found): + new_games = [] + # if sol_opps[new_team,current_pos] == None: + # new_opponent1 = random.choice(possible_opps[current_pos][new_team]) + # new_games.append((new_team,new_opponent1)) + + # if sol_opps[new_team,current_pos+1] == None: + # new_opponent2 = random.choice(possible_opps[current_pos+1][new_team]) + # new_games.append((new_opponent2,new_team)) + + new_opponent1,new_opponent2 = unique_combinations.pop() + + if new_opponent1: + new_games.append((new_team,new_opponent1)) + + if new_opponent2: + new_games.append((new_opponent2,new_team)) + + # n_computations += 1 + # tt = time.time() + check, comp_time = check_feasible_gurobi(fixed_games+new_games) + # check_time += time.time()-tt + # total_comp_time += comp_time + if check: + no_solution_found = False + if sol_opps[new_team,current_pos] == None: + sol_opps[new_team,current_pos] = new_opponent1 + sol_countries[new_team,getCountryById[new_opponent1]] += 1 + sol_opps[new_opponent1,(2*p-1)] = new_team + sol_countries[new_opponent1,getCountryById[new_team]] += 1 + if new_team in possible_opps[(2*p-1)-1][new_opponent1]: + possible_opps[(2*p-1)-1][new_opponent1].remove(new_team) + if sol_opps[new_team,current_pos+1] == None: + sol_opps[new_team,current_pos+1] = new_opponent2 + sol_countries[new_team,getCountryById[new_opponent2]] += 1 + sol_opps[new_opponent2,(2*p-1)-(1)] = new_team + sol_countries[new_opponent2,getCountryById[new_team]] += 1 + if new_team in possible_opps[(2*p-1)][new_opponent2]: + possible_opps[(2*p-1)][new_opponent2].remove(new_team) + fixed_games += new_games + + + + # 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") + + + + + + # WRITE SOL '.html' + sol = '' + sol += " \ + \ + " + sol += "\n" + sol += "\n" + sol += "" + sol += "" + sol += "" + sol += "" + sol += "" + sol += "" + sol += "" + sol += "\n" + sol += f"\n" + for t in teams: + sol += f"\n" + sol += "\n" + sol += "\n" + sol += "\n" + for t1 in teams: + sol += "\n" + sol += f"" + for t2 in teams: + 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
{getTeamById[t['id']]}
{getTeamById[t1['id']]}{t2['country']}@{t2['country']}
\n" + + with open(f'debug.html', 'w') as f: + f.write(sol) + + +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 = 2 +# simulate_draws('test', n) + + + + + + + + + + diff --git a/uefa/cycle24/simulations/double_draws/probabilities_october.py b/uefa/cycle24/simulations/double_draws/probabilities_october.py new file mode 100755 index 0000000..bfbda48 --- /dev/null +++ b/uefa/cycle24/simulations/double_draws/probabilities_october.py @@ -0,0 +1,315 @@ +# %% +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 + + + + +scenario = Scenario.objects.get(id=34) + +# %% + +order = {} + +order['FC Bayern München'] = 1 +order['Manchester City FC'] = 2 +order['Liverpool FC'] = 3 +order['Real Madrid CF'] = 4 +order['Chelsea FC'] = 5 +order['FC Barcelona'] = 6 +order['Paris Saint-Germain'] = 7 +order['Juventus'] = 8 +order['Club Atlético de Madrid'] = 9 +order['Sevilla FC'] = 10 +order['RB Leipzig'] = 11 +order['Tottenham Hotspur'] = 12 +order['AFC Ajax'] = 13 +order['FC Porto'] = 14 +order['Arsenal FC'] = 15 +order['Borussia Dortmund'] = 16 +order['FC Salzburg'] = 17 +order['FC Shakhtar Donetsk'] = 18 +order['FC Internazionale Milano'] = 19 +order['SSC Napoli'] = 20 +order['Eintracht Frankfurt'] = 21 +order['SL Benfica'] = 22 +order['Sporting Clube de Portugal'] = 23 +order['Bayer 04 Leverkusen'] = 24 +order['Rangers FC'] = 25 +order['GNK Dinamo'] = 26 +order['FK Crvena zvezda'] = 27 +order['Olympique de Marseille'] = 28 +order['F.C. Copenhagen'] = 29 +order['Club Brugge'] = 30 +order['AC Milan'] = 31 +order['PSV Eindhoven'] = 32 +order['Celtic FC'] = 33 +order['FC Viktoria Plzeň'] = 34 +order['AS Monaco'] = 35 +order['Maccabi Haifa FC'] = 36 + + + + + + + +# %% + + +teams = Team.objects.filter(season=scenario.season,active=True).order_by('pot','country') + + +countries = list(set(list(teams.values_list('country', flat=True)))) + + +# print(countries) + + +# %% + + +getTeamByID = { + t.id:t for t in teams +} + +getPotByID = { + t.id:t.pot for t in teams +} + +getTeamByName = { + t.name:t for t in teams +} + +getCountryByTeamID = { + t.id:t.country for t in teams +} + + + + +played_countries = { + (t1, c):0 for c in countries for t1 in teams +} +random_played_countries = { + (t1, c):0 for c in countries for t1 in teams +} +stats = { + (t1,t2):0 for t1 in teams for t2 in teams +} +random_stats = { + (t1,t2):0 for t1 in teams for t2 in teams +} + + +pots = { + t1:{ + p:0 for p in range(1,5) + } + for t1 in teams +} +simulations_undirected = 0 +simulations_directed = 0 +maxVal = 1 +minVal = 99999999 +maxCVal = 1 +minCVal = 9999999 +maxRVal = 1 +minRVal = 9999999 +maxCRVal = 1 +minCRVal = 9999999 + +old_c = "START" +for i in range(16): + with open(f'thread_{i}_pot_by_pot.csv', newline='') as csvfile: + # with open('verteilung_random.csv', newline='') as csvfile: + reader = csv.reader(csvfile) + next(reader, None) + for row in reader: + if int(row[0]) != old_c: + old_c = int(row[0]) + simulations_undirected +=1 + + team = getTeamByID[int(row[1])] + Aopps = [getTeamByID[int(t)] for t in row[2].split(";")][:2] + for o in Aopps: + stats[team,o] += 1 + pots[team][getPotByID[o.id]] += 1 + played_countries[team,o.country] += 1 + Bopps = [getTeamByID[int(t)] for t in row[2].split(";")][2:4] + for o in Bopps: + stats[team,o] += 1 + pots[team][getPotByID[o.id]] += 1 + played_countries[team,o.country] += 1 + Copps = [getTeamByID[int(t)] for t in row[2].split(";")][4:6] + for o in Copps: + stats[team,o] += 1 + pots[team][getPotByID[o.id]] += 1 + played_countries[team,o.country] += 1 + Dopps = [getTeamByID[int(t)] for t in row[2].split(";")][6:] + for o in Dopps: + stats[team,o] += 1 + pots[team][getPotByID[o.id]] += 1 + played_countries[team,o.country] += 1 + + if stats[team,o] > maxVal: + maxVal = stats[team,o] + + if played_countries[team,o.country] > maxCVal: + maxCVal = played_countries[team,o.country] + +diff = {} +mindval = 999999 +maxdval = 0 +# simulations_undirected = 1 +simulations_directed = 1 + +for key in random_stats.keys(): + diff[key] = stats[key]/simulations_undirected - 2*random_stats[key]/simulations_directed + if diff[key] > maxdval: + maxdval = diff[key] + if diff[key] > 0 and diff[key] < mindval: + mindval = diff[key] + + + +for key, val in stats.items(): + if val > 0 and val < minVal: + minVal = val + + +for key, val in random_stats.items(): + if val > 0 and val < minRVal: + minRVal = val + + +for key, val in played_countries.items(): + if val > 0 and val < minCVal: + minCVal = val + + +for key, val in random_played_countries.items(): + if val > 0 and val < minCRVal: + minCRVal = val + + + +# for t in pots: +# print(t,pots[t]) + + +def heatmap_color_for(value): + if value <= 0.5: + g = 256 + r = 2 * max(0,value) * 256 + if value > 0.5: + g = 2*(1-min(1,value))*256 + r = 256 + return f"rgb({r},{g},{0})" + + + +sol = '' +sol += " \ + \ +" +sol += "" +sol += "

Probabilities of games - drawn pot by pot

" +sol += "\n" +sol += "\n" +sol += "" +sol += f"" +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] + color = heatmap_color_for((stats[t1,t2]-minVal)/((maxVal-minVal) or 1)) + if stats[t1,t2] == 0: + color = 'grey' + val = f"{round((stats[t1,t2]/simulations_undirected)*100)}%" + # val = stats[t1,t2] + sol += f"" + sol += "\n" + +sol += "\n" +sol += "
{simulations_undirected}Pot APot BPot CPot D
({t.country}) {t.shortname}
({t1.country}) {t1.shortname}{val}
\n" + + +with open(f'probabilities_pot_by_pot.html', 'w') as f: + f.write(sol) + + + + + + + +# %% diff --git a/uefa/cycle24/simulations/drawsimulation_october.py b/uefa/cycle24/simulations/drawsimulation_october.py new file mode 100755 index 0000000..cce0e0c --- /dev/null +++ b/uefa/cycle24/simulations/drawsimulation_october.py @@ -0,0 +1,497 @@ +# %% +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_9.0.2" +os.environ["XPRESS"] = "/opt/xpressmp_9.0.2/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 * +from draws.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=4) + +# %% + +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) + +clashes = Clash.objects.filter(draw__season=scenario.season) + + +# 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)] + +# %% + +def check_feasible_pulp(fixed_games): + + model = pulp.LpProblem(f"Draws", pulp.LpMinimize) + + 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) + + # 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) + 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']: + # model.addConstraint(xp.Sum(x[t['id'],t2['id']]+x[t2['id'],t['id']] for t2 in teams_from_country[c]) <= 3) + model += lpSum(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) + model += x[t1,t2] == 1 + + for (t1,t2) in x.keys(): + model += x[t1,t2] + x[t2,t1] <= 1, f'directed_{t1}_{t2}' + # model.addConstraint(x[t1,t2] + x[t2,t1] <= 1) + + model += lpSum(random.uniform(0,1)*x[key] for key in x.keys()) + tt =time.time() + model.solve(XPRESS(msg=0,timeLimit=120,keepFiles=0)) + comp_time = time.time()-tt + + if model.status in [-1,-2]: + return False, comp_time + else: + return True, comp_time + + + +def check_feasible(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]) <= 3) + + + for clash in clashes: + for c1 in clash.countries.all(): + for c2 in clash.countries.all(): + if c1 != c2 and teams_from_country.get(c1.shortname) and teams_from_country.get(c2.shortname): + model.addConstraint(xp.Sum(x[t['id'],t2['id']]+x[t2['id'],t['id']] for t in teams_from_country[c1.shortname] for t2 in teams_from_country[c2.shortname]) <= 0) + + + + + + # 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 + + + + +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()) == 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 clash in clashes: + for c1 in clash.countries.all(): + for c2 in clash.countries.all(): + if c1 != c2 and teams_from_country.get(c1.shortname) and teams_from_country.get(c2.shortname): + model.addConstraint(xp.Sum(x[t['id'],t2['id']]+x[t2['id'],t['id']] for t in teams_from_country[c1.shortname] for t2 in teams_from_country[c2.shortname]) <= 0) + + +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 + + +# 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_pulp(fixed_games+[new_game]) + # check, comp_time = check_feasible_fix(fixed_games+[new_game]) + check, comp_time = check_feasible(fixed_games+[new_game]) + check_time += time.time()-tt + total_comp_time += comp_time + if check: + # 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 +n = 2 +simulate_draws('test', n) + + + + + + + + + + + + +# %% + + diff --git a/uefa/cycle24/simulations/drawsimulation_october_gurobi.py b/uefa/cycle24/simulations/drawsimulation_october_gurobi.py new file mode 100755 index 0000000..d29aa2b --- /dev/null +++ b/uefa/cycle24/simulations/drawsimulation_october_gurobi.py @@ -0,0 +1,477 @@ +# %% +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_8.4" +os.environ["XPRESS"] = "/opt/xpressmp_8.4/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 gurobipy as gp +from gurobipy import GRB +import xpress as xp +# xp.controls.outputlog = 0 + + + +scenario = Scenario.objects.get(id=34) + +# %% + +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)] + + + +def check_feasible_pulp(fixed_games): + + model = pulp.LpProblem(f"Draws", pulp.LpMinimize) + + 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) + + + # 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) + 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']: + # model.addConstraint(xp.Sum(x[t['id'],t2['id']]+x[t2['id'],t['id']] for t2 in teams_from_country[c]) <= 3) + model += lpSum(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) + model += x[t1,t2] == 1 + + for (t1,t2) in x.keys(): + model += x[t1,t2] + x[t2,t1] <= 1, f'directed_{t1}_{t2}' + # model.addConstraint(x[t1,t2] + x[t2,t1] <= 1) + + model += lpSum(random.uniform(0,1)*x[key] for key in x.keys()) + tt =time.time() + model.solve(XPRESS(msg=0,timeLimit=120,keepFiles=0)) + comp_time = time.time()-tt + + if model.status in [-1,-2]: + return False, comp_time + else: + return True, comp_time + + + + +model = gp.Model('Draws') +model.Params.OutputFlag = 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) + x[t1['id'], t2['id']] = model.addVar(vtype=GRB.BINARY) + +# REQUIREMENTS +for t in teams: + for r in range(1,5): + model.addConstr(gp.quicksum(x[t['id'],t2['id']] for t2 in pot[r] if (t['id'],t2['id']) in x.keys()) == 1) + model.addConstr(gp.quicksum(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.addConstr(gp.quicksum(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) + model.addConstr(x[t1,t2] + x[t2,t1] <= 1) + + + + +def check_feasible_gurobi(fixed_games): + + # FIXATIONS + for key in x.keys(): + if key in fixed_games: + x[key].lb = 1 + else: + x[key].lb = 0 + + model.update() + + tt =time.time() + # model.solve() + model.optimize() + comp_time = time.time()-tt + + + if model.Status == GRB.OPTIMAL: + return True, comp_time + else: + # print("INFEASIBLE FOUND") + return False, comp_time + + +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()) == 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 + + + + +# 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()) == 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 + + + + + + + +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_pulp(fixed_games+[new_game]) + check, comp_time = check_feasible_gurobi(fixed_games+[new_game]) + # check_time += time.time()-tt + # total_comp_time += comp_time + if check: + # 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 = 2 +# simulate_draws('test', n) + + + + + + + + + + + + +# %% + + diff --git a/uefa/cycle24/simulations/drawsimulation_october_gurobi_all.py b/uefa/cycle24/simulations/drawsimulation_october_gurobi_all.py new file mode 100755 index 0000000..f58f738 --- /dev/null +++ b/uefa/cycle24/simulations/drawsimulation_october_gurobi_all.py @@ -0,0 +1,596 @@ +# %% +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_8.4" +os.environ["XPRESS"] = "/opt/xpressmp_8.4/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 * +from draws.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 gurobipy as gp +from gurobipy import GRB +import xpress as xp +# xp.controls.outputlog = 0 + + + +scenario = Scenario.objects.get(id=4) + +# %% + +teamObjects = Team.objects.filter(season=scenario.season,active=True).order_by('pot') +teams = teamObjects.values('id','country','pot','name') + +getTeamById = {} +for t in teamObjects: + getTeamById[t.id] = f"({t.pot}) {t.name}" + +getCountryById = {} +for t in teamObjects: + getCountryById[t.id] = t.country + +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)] + + + +def check_feasible_pulp(fixed_games): + + model = pulp.LpProblem(f"Draws", pulp.LpMinimize) + + 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) + + + # 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) + 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']: + # model.addConstraint(xp.Sum(x[t['id'],t2['id']]+x[t2['id'],t['id']] for t2 in teams_from_country[c]) <= 3) + model += lpSum(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) + model += x[t1,t2] == 1 + + for (t1,t2) in x.keys(): + model += x[t1,t2] + x[t2,t1] <= 1, f'directed_{t1}_{t2}' + # model.addConstraint(x[t1,t2] + x[t2,t1] <= 1) + + model += lpSum(random.uniform(0,1)*x[key] for key in x.keys()) + tt =time.time() + model.solve(XPRESS(msg=0,timeLimit=120,keepFiles=0)) + comp_time = time.time()-tt + + if model.status in [-1,-2]: + return False, comp_time + else: + return True, comp_time + + + + +model = gp.Model('Draws') +model.Params.OutputFlag = 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) + x[t1['id'], t2['id']] = model.addVar(vtype=GRB.BINARY) + +# REQUIREMENTS +for t in teams: + for r in range(1,5): + model.addConstr(gp.quicksum(x[t['id'],t2['id']] for t2 in pot[r] if (t['id'],t2['id']) in x.keys()) == 1) + model.addConstr(gp.quicksum(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.addConstr(gp.quicksum(x[t['id'],t2['id']]+x[t2['id'],t['id']] for t2 in teams_from_country[c]) <= 2) + + +for clash in Clash.objects.filter(draw__season=scenario.season): + for c1 in clash.countries.all(): + for c2 in clash.countries.all(): + if c1 != c2 and teams_from_country.get(c1.shortname) and teams_from_country.get(c2.shortname): + model.addConstr(gp.quicksum(x[t['id'],t2['id']]+x[t2['id'],t['id']] for t in teams_from_country[c1.shortname] for t2 in teams_from_country[c2.shortname]) <= 0) + print("CLASH",c1,c2) + + + + +for (t1,t2) in x.keys(): + model.addConstr(x[t1,t2] + x[t2,t1] <= 1) + + + + +def check_feasible_gurobi(fixed_games): + + # FIXATIONS + for key in x.keys(): + if key in fixed_games: + x[key].lb = 1 + else: + x[key].lb = 0 + + model.update() + + # tt =time.time() + # model.solve() + model.optimize() + # comp_time = time.time()-tt + + + if model.Status == GRB.OPTIMAL: + return True, 0 + else: + # print("INFEASIBLE FOUND") + return False, 0 + + +def check_feasible(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 + + + + +# 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()) == 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 + + + + + +import itertools +from itertools import permutations , product + +def simulate_draws(filename,n): + + print("RUNNING ASYNC",filename) + fixed_games=None + for i_sim in range(1, n): + if i_sim % 100 == 0: + print("RUNNING ASYNC",filename,i_sim) + # 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) + } + + sol_countries = { + (t['id'],c):0 + for t in teams for c in countries if c != t['country'] + } + + fixed_games = [] + feasible = True + + for p in range(1,2): + 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(0,8,2): + if sol_opps[new_team,current_pos] != None and sol_opps[new_team,current_pos+1] != None: + continue + + + possible_opps[current_pos][new_team] = [t for t in possible_opps[current_pos][new_team] if sol_countries[new_team,getCountryById[t]] < 2 and sol_countries[t,getCountryById[new_team]] < 2] + possible_opps[current_pos+1][new_team] = [t for t in possible_opps[current_pos+1][new_team] if sol_countries[new_team,getCountryById[t]] < 2 and sol_countries[t,getCountryById[new_team]] < 2] + + list_1 = [None] + list_2 = [None] + if sol_opps[new_team,current_pos] == None: + list_1 = possible_opps[current_pos][new_team] + if sol_opps[new_team,current_pos+1] == None: + list_2 = possible_opps[current_pos+1][new_team] + + # unique_combinations = [] + # for i in range(len(list_1)): + # for j in range(len(list_2)): + # unique_combinations.append((list_1[i], list_2[j])) + unique_combinations = list(itertools.product(list_1, list_2)) + random.shuffle(unique_combinations) + + + no_solution_found = True + while (no_solution_found): + new_games = [] + # if sol_opps[new_team,current_pos] == None: + # new_opponent1 = random.choice(possible_opps[current_pos][new_team]) + # new_games.append((new_team,new_opponent1)) + + # if sol_opps[new_team,current_pos+1] == None: + # new_opponent2 = random.choice(possible_opps[current_pos+1][new_team]) + # new_games.append((new_opponent2,new_team)) + + new_opponent1,new_opponent2 = unique_combinations.pop() + + if new_opponent1: + new_games.append((new_team,new_opponent1)) + + if new_opponent2: + new_games.append((new_opponent2,new_team)) + + # n_computations += 1 + # tt = time.time() + check, comp_time = check_feasible_gurobi(fixed_games+new_games) + # check_time += time.time()-tt + # total_comp_time += comp_time + if check: + no_solution_found = False + if sol_opps[new_team,current_pos] == None: + sol_opps[new_team,current_pos] = new_opponent1 + sol_countries[new_team,getCountryById[new_opponent1]] += 1 + sol_opps[new_opponent1,(2*p-1)] = new_team + sol_countries[new_opponent1,getCountryById[new_team]] += 1 + + if new_team in possible_opps[(2*p-1)-1][new_opponent1]: + possible_opps[(2*p-1)-1][new_opponent1].remove(new_team) + if sol_opps[new_team,current_pos+1] == None: + sol_opps[new_team,current_pos+1] = new_opponent2 + sol_countries[new_team,getCountryById[new_opponent2]] += 1 + sol_opps[new_opponent2,(2*p-1)-(1)] = new_team + sol_countries[new_opponent2,getCountryById[new_team]] += 1 + if new_team in possible_opps[(2*p-1)][new_opponent2]: + possible_opps[(2*p-1)][new_opponent2].remove(new_team) + fixed_games += new_games + + + for p in range(2,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)) + + + unique_combinations = {} + for current_pos in range(2*(p-1),8,2): + + possible_opps[current_pos][new_team] = [t for t in possible_opps[current_pos][new_team] if sol_countries[new_team,getCountryById[t]] < 2 and + sol_countries[t,getCountryById[new_team]] < 2 and sol_opps[t,(2*p-1)] == None] + possible_opps[current_pos+1][new_team] = [t for t in possible_opps[current_pos+1][new_team] if sol_countries[new_team,getCountryById[t]] < 2 and + sol_countries[t,getCountryById[new_team]] < 2 and sol_opps[t,(2*p-1)-1] == None] + + list_1 = [0] + list_2 = [0] + if sol_opps[new_team,current_pos] == None: + list_1 = possible_opps[current_pos][new_team] + if sol_opps[new_team,current_pos+1] == None: + list_2 = possible_opps[current_pos+1][new_team] + + unique_combinations[current_pos] = [] + for i in list_1: + for j in list_2: + if i != j or (i == 0 and j == 0): + unique_combinations[current_pos].append((i, j)) + + combi_list = list(itertools.product(*unique_combinations.values())) + random.shuffle(combi_list) + + + + + # print("STOP") + # for current_pos in range(2*(p-1),8,2): + # print(current_pos,possible_opps[current_pos][new_team]) + # print(current_pos+1,possible_opps[current_pos+1][new_team]) + # list_1 = [0] + # list_2 = [0] + # if sol_opps[new_team,current_pos] == None: + # list_1 = possible_opps[current_pos][new_team] + # if sol_opps[new_team,current_pos+1] == None: + # list_2 = possible_opps[current_pos+1][new_team] + + # unique_combinations[current_pos] = [] + # for i in list_1: + # for j in list_2: + # if i != j or (i == 0 and j == 0): + # unique_combinations[current_pos].append((i, j)) + # print(unique_combinations) + # exit() + + + no_solution_found = True + while (no_solution_found): + # print("\tPOP",len(combi_list)) + new_games = [] + new_opponents = combi_list.pop() + for o1,o2 in new_opponents: + if o1: + new_games.append((new_team,o1)) + if o2: + new_games.append((o2,new_team)) + + + # n_computations += 1 + # tt = time.time() + check, comp_time = check_feasible_gurobi(fixed_games+new_games) + # check_time += time.time()-tt + # total_comp_time += comp_time + if check: + no_solution_found = False + fixed_games += new_games + for i,(new_opponent1,new_opponent2) in enumerate(new_opponents): + current_pos = 2*(p-1)+2*i + if sol_opps[new_team,current_pos] == None: + sol_opps[new_team,current_pos] = new_opponent1 + sol_countries[new_team,getCountryById[new_opponent1]] += 1 + sol_opps[new_opponent1 ,(2*p-1)] = new_team + sol_countries[new_opponent1,getCountryById[new_team]] += 1 + if new_team in possible_opps[(2*p-1)-1][new_opponent1]: + possible_opps[(2*p-1)-1][new_opponent1].remove(new_team) + if sol_opps[new_team,current_pos+1] == None: + sol_opps[new_team,current_pos+1] = new_opponent2 + sol_countries[new_team,getCountryById[new_opponent2]] += 1 + sol_opps[new_opponent2,(2*p-1)-(1)] = new_team + sol_countries[new_opponent2,getCountryById[new_team]] += 1 + if new_team in possible_opps[(2*p-1)][new_opponent2]: + possible_opps[(2*p-1)][new_opponent2].remove(new_team) + + # 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_sim},{t['id']},{';'.join([str(sol_opps[t['id'],p]) for p in range(8)])}\n") + + + + + + # # WRITE SOL '.html' + # sol = '' + # sol += " \ + # \ + # " + # sol += "\n" + # sol += "\n" + # sol += "" + # sol += "" + # sol += "" + # sol += "" + # sol += "" + # sol += "" + # sol += "" + # sol += "\n" + # sol += f"\n" + # for t in teams: + # sol += f"\n" + # sol += "\n" + # sol += "\n" + # sol += "\n" + # for t1 in teams: + # sol += "\n" + # sol += f"" + # for t2 in teams: + # 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
{getTeamById[t['id']]}
{getTeamById[t1['id']]}{t2['country']}@{t2['country']}
\n" + + # with open(f'debug.html', 'w') as f: + # f.write(sol) + + +# 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 = 2 +simulate_draws('test', n) + + + + + + + + + + + +# %% diff --git a/uefa/cycle24/simulations/drawsimulation_october_gurobi_double.py b/uefa/cycle24/simulations/drawsimulation_october_gurobi_double.py new file mode 100755 index 0000000..7627390 --- /dev/null +++ b/uefa/cycle24/simulations/drawsimulation_october_gurobi_double.py @@ -0,0 +1,506 @@ +# %% +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_8.4" +os.environ["XPRESS"] = "/opt/xpressmp_8.4/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 * +from draws.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 gurobipy as gp +from gurobipy import GRB +import xpress as xp +# xp.controls.outputlog = 0 + + + +scenario = Scenario.objects.get(id=4) + +# %% + +teamObjects = Team.objects.filter(season=scenario.season,active=True).order_by('pot') +teams = teamObjects.values('id','country','pot','name') + +getTeamById = {} +for t in teamObjects: + getTeamById[t.id] = f"({t.pot}) {t.name}" + +getCountryById = {} +for t in teamObjects: + getCountryById[t.id] = t.country + + +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)] + + + +def check_feasible_pulp(fixed_games): + + model = pulp.LpProblem(f"Draws", pulp.LpMinimize) + + 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) + + + # 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) + 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']: + # model.addConstraint(xp.Sum(x[t['id'],t2['id']]+x[t2['id'],t['id']] for t2 in teams_from_country[c]) <= 3) + model += lpSum(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) + model += x[t1,t2] == 1 + + for (t1,t2) in x.keys(): + model += x[t1,t2] + x[t2,t1] <= 1, f'directed_{t1}_{t2}' + # model.addConstraint(x[t1,t2] + x[t2,t1] <= 1) + + model += lpSum(random.uniform(0,1)*x[key] for key in x.keys()) + tt =time.time() + model.solve(XPRESS(msg=0,timeLimit=120,keepFiles=0)) + comp_time = time.time()-tt + + if model.status in [-1,-2]: + return False, comp_time + else: + return True, comp_time + + + + +model = gp.Model('Draws') +model.Params.OutputFlag = 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) + x[t1['id'], t2['id']] = model.addVar(vtype=GRB.BINARY) + +# REQUIREMENTS +for t in teams: + for r in range(1,5): + model.addConstr(gp.quicksum(x[t['id'],t2['id']] for t2 in pot[r] if (t['id'],t2['id']) in x.keys()) == 1) + model.addConstr(gp.quicksum(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.addConstr(gp.quicksum(x[t['id'],t2['id']]+x[t2['id'],t['id']] for t2 in teams_from_country[c]) <= 2) + + + +for clash in Clash.objects.filter(draw__season=scenario.season): + for c1 in clash.countries.all(): + for c2 in clash.countries.all(): + if c1 != c2 and teams_from_country.get(c1.shortname) and teams_from_country.get(c2.shortname): + model.addConstr(gp.quicksum(x[t['id'],t2['id']]+x[t2['id'],t['id']] for t in teams_from_country[c1.shortname] for t2 in teams_from_country[c2.shortname]) <= 0) + print("CLASH",c1,c2) + + +for (t1,t2) in x.keys(): + model.addConstr(x[t1,t2] + x[t2,t1] <= 1) + + + + +def check_feasible_gurobi(fixed_games): + + # FIXATIONS + for key in x.keys(): + if key in fixed_games: + x[key].lb = 1 + else: + x[key].lb = 0 + + model.update() + + # tt =time.time() + # model.solve() + model.optimize() + # comp_time = time.time()-tt + + + if model.Status == GRB.OPTIMAL: + return True, 0 + else: + # print("INFEASIBLE FOUND") + return False, 0 + + +def check_feasible(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]) <= 5) + + # 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 + + + + +# 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()) == 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 + + + + + +import itertools +from itertools import permutations , product + +def simulate_draws(filename,n): + + print("RUNNING ASYNC",filename) + fixed_games=None + 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) + } + + sol_countries = { + (t['id'],c):0 + for t in teams for c in countries if c != t['country'] + } + + 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(2*(p-1),8,2): + if sol_opps[new_team,current_pos] != None and sol_opps[new_team,current_pos+1] != None: + continue + + possible_opps[current_pos][new_team] = [t for t in possible_opps[current_pos][new_team] if sol_countries[new_team,getCountryById[t]] < 2 and + sol_countries[t,getCountryById[new_team]] < 2 and sol_opps[t,(2*p-1)] == None] + possible_opps[current_pos+1][new_team] = [t for t in possible_opps[current_pos+1][new_team] if sol_countries[new_team,getCountryById[t]] < 2 and + sol_countries[t,getCountryById[new_team]] < 2 and sol_opps[t,(2*p-1)-1] == None] + + list_1 = [None] + list_2 = [None] + if sol_opps[new_team,current_pos] == None: + list_1 = possible_opps[current_pos][new_team] + if sol_opps[new_team,current_pos+1] == None: + list_2 = possible_opps[current_pos+1][new_team] + + # unique_combinations = [] + # for i in range(len(list_1)): + # for j in range(len(list_2)): + # unique_combinations.append((list_1[i], list_2[j])) + unique_combinations = list(itertools.product(list_1, list_2)) + random.shuffle(unique_combinations) + + + no_solution_found = True + while (no_solution_found): + new_games = [] + # if sol_opps[new_team,current_pos] == None: + # new_opponent1 = random.choice(possible_opps[current_pos][new_team]) + # new_games.append((new_team,new_opponent1)) + + # if sol_opps[new_team,current_pos+1] == None: + # new_opponent2 = random.choice(possible_opps[current_pos+1][new_team]) + # new_games.append((new_opponent2,new_team)) + + new_opponent1,new_opponent2 = unique_combinations.pop() + print(new_opponent1,new_opponent2) + + if new_opponent1: + new_games.append((new_team,new_opponent1)) + + if new_opponent2: + new_games.append((new_opponent2,new_team)) + + # n_computations += 1 + # tt = time.time() + check, comp_time = check_feasible_gurobi(fixed_games+new_games) + # check_time += time.time()-tt + # total_comp_time += comp_time + if check: + no_solution_found = False + if sol_opps[new_team,current_pos] == None: + sol_opps[new_team,current_pos] = new_opponent1 + sol_countries[new_team,getCountryById[new_opponent1]] += 1 + sol_opps[new_opponent1,(2*p-1)] = new_team + sol_countries[new_opponent1,getCountryById[new_team]] += 1 + if new_team in possible_opps[(2*p-1)-1][new_opponent1]: + possible_opps[(2*p-1)-1][new_opponent1].remove(new_team) + if sol_opps[new_team,current_pos+1] == None: + sol_opps[new_team,current_pos+1] = new_opponent2 + sol_countries[new_team,getCountryById[new_opponent2]] += 1 + sol_opps[new_opponent2,(2*p-1)-(1)] = new_team + sol_countries[new_opponent2,getCountryById[new_team]] += 1 + if new_team in possible_opps[(2*p-1)][new_opponent2]: + possible_opps[(2*p-1)][new_opponent2].remove(new_team) + fixed_games += new_games + + + + # 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") + + + + + + # WRITE SOL '.html' + sol = '' + sol += " \ + \ + " + sol += "\n" + sol += "\n" + sol += "" + sol += "" + sol += "" + sol += "" + sol += "" + sol += "" + sol += "" + sol += "\n" + sol += f"\n" + for t in teams: + sol += f"\n" + sol += "\n" + sol += "\n" + sol += "\n" + for t1 in teams: + sol += "\n" + sol += f"" + for t2 in teams: + 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
{getTeamById[t['id']]}
{getTeamById[t1['id']]}{t2['country']}@{t2['country']}
\n" + + with open(f'debug.html', 'w') as f: + f.write(sol) + + +# 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 = 2 +simulate_draws('test', n) + + + + + + + + + + + +# %% diff --git a/uefa/cycle24/simulations/mixed_draws/drawsimulation_october_gurobi_all.py b/uefa/cycle24/simulations/mixed_draws/drawsimulation_october_gurobi_all.py new file mode 100755 index 0000000..226e315 --- /dev/null +++ b/uefa/cycle24/simulations/mixed_draws/drawsimulation_october_gurobi_all.py @@ -0,0 +1,582 @@ +# %% +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_8.4" +os.environ["XPRESS"] = "/opt/xpressmp_8.4/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 gurobipy as gp +from gurobipy import GRB +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') +teams = teamObjects.values('id','country','pot','name') + +getTeamById = {} +for t in teamObjects: + getTeamById[t.id] = f"({t.pot}) {t.name}" + +getCountryById = {} +for t in teamObjects: + getCountryById[t.id] = t.country + +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)] + + + +def check_feasible_pulp(fixed_games): + + model = pulp.LpProblem(f"Draws", pulp.LpMinimize) + + 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) + + + # 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) + 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']: + # model.addConstraint(xp.Sum(x[t['id'],t2['id']]+x[t2['id'],t['id']] for t2 in teams_from_country[c]) <= 3) + model += lpSum(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) + model += x[t1,t2] == 1 + + for (t1,t2) in x.keys(): + model += x[t1,t2] + x[t2,t1] <= 1, f'directed_{t1}_{t2}' + # model.addConstraint(x[t1,t2] + x[t2,t1] <= 1) + + model += lpSum(random.uniform(0,1)*x[key] for key in x.keys()) + tt =time.time() + model.solve(XPRESS(msg=0,timeLimit=120,keepFiles=0)) + comp_time = time.time()-tt + + if model.status in [-1,-2]: + return False, comp_time + else: + return True, comp_time + + + + +model = gp.Model('Draws') +model.Params.OutputFlag = 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) + x[t1['id'], t2['id']] = model.addVar(vtype=GRB.BINARY) + +# REQUIREMENTS +for t in teams: + for r in range(1,5): + model.addConstr(gp.quicksum(x[t['id'],t2['id']] for t2 in pot[r] if (t['id'],t2['id']) in x.keys()) == 1) + model.addConstr(gp.quicksum(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.addConstr(gp.quicksum(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.addConstr(x[t1,t2] + x[t2,t1] <= 1) + + + + +def check_feasible_gurobi(fixed_games): + + # FIXATIONS + for key in x.keys(): + if key in fixed_games: + x[key].lb = 1 + else: + x[key].lb = 0 + + model.update() + + # tt =time.time() + # model.solve() + model.optimize() + # comp_time = time.time()-tt + + + if model.Status == GRB.OPTIMAL: + return True, 0 + else: + # print("INFEASIBLE FOUND") + return False, 0 + + +def check_feasible(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 + + + + +# 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()) == 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 + + + + + +import itertools +from itertools import permutations , product + +def simulate_draws(filename,n): + + print("RUNNING ASYNC",filename) + fixed_games=None + for i_sim in range(1, n): + if i_sim % 100 == 0: + print("RUNNING ASYNC",filename,i_sim) + # 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) + } + + sol_countries = { + (t['id'],c):0 + for t in teams for c in countries if c != t['country'] + } + + fixed_games = [] + feasible = True + + for p in range(1,2): + 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(0,8,2): + if sol_opps[new_team,current_pos] != None and sol_opps[new_team,current_pos+1] != None: + continue + + + possible_opps[current_pos][new_team] = [t for t in possible_opps[current_pos][new_team] if sol_countries[new_team,getCountryById[t]] < 2 and sol_countries[t,getCountryById[new_team]] < 2] + possible_opps[current_pos+1][new_team] = [t for t in possible_opps[current_pos+1][new_team] if sol_countries[new_team,getCountryById[t]] < 2 and sol_countries[t,getCountryById[new_team]] < 2] + + list_1 = [None] + list_2 = [None] + if sol_opps[new_team,current_pos] == None: + list_1 = possible_opps[current_pos][new_team] + if sol_opps[new_team,current_pos+1] == None: + list_2 = possible_opps[current_pos+1][new_team] + + # unique_combinations = [] + # for i in range(len(list_1)): + # for j in range(len(list_2)): + # unique_combinations.append((list_1[i], list_2[j])) + unique_combinations = list(itertools.product(list_1, list_2)) + random.shuffle(unique_combinations) + + + no_solution_found = True + while (no_solution_found): + new_games = [] + # if sol_opps[new_team,current_pos] == None: + # new_opponent1 = random.choice(possible_opps[current_pos][new_team]) + # new_games.append((new_team,new_opponent1)) + + # if sol_opps[new_team,current_pos+1] == None: + # new_opponent2 = random.choice(possible_opps[current_pos+1][new_team]) + # new_games.append((new_opponent2,new_team)) + + new_opponent1,new_opponent2 = unique_combinations.pop() + + if new_opponent1: + new_games.append((new_team,new_opponent1)) + + if new_opponent2: + new_games.append((new_opponent2,new_team)) + + # n_computations += 1 + # tt = time.time() + check, comp_time = check_feasible_gurobi(fixed_games+new_games) + # check_time += time.time()-tt + # total_comp_time += comp_time + if check: + no_solution_found = False + if sol_opps[new_team,current_pos] == None: + sol_opps[new_team,current_pos] = new_opponent1 + sol_countries[new_team,getCountryById[new_opponent1]] += 1 + sol_opps[new_opponent1,(2*p-1)] = new_team + sol_countries[new_opponent1,getCountryById[new_team]] += 1 + + if new_team in possible_opps[(2*p-1)-1][new_opponent1]: + possible_opps[(2*p-1)-1][new_opponent1].remove(new_team) + if sol_opps[new_team,current_pos+1] == None: + sol_opps[new_team,current_pos+1] = new_opponent2 + sol_countries[new_team,getCountryById[new_opponent2]] += 1 + sol_opps[new_opponent2,(2*p-1)-(1)] = new_team + sol_countries[new_opponent2,getCountryById[new_team]] += 1 + if new_team in possible_opps[(2*p-1)][new_opponent2]: + possible_opps[(2*p-1)][new_opponent2].remove(new_team) + fixed_games += new_games + + + for p in range(2,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)) + + + unique_combinations = {} + for current_pos in range(2*(p-1),8,2): + + possible_opps[current_pos][new_team] = [t for t in possible_opps[current_pos][new_team] if sol_countries[new_team,getCountryById[t]] < 2 and + sol_countries[t,getCountryById[new_team]] < 2 and sol_opps[t,(2*p-1)] == None] + possible_opps[current_pos+1][new_team] = [t for t in possible_opps[current_pos+1][new_team] if sol_countries[new_team,getCountryById[t]] < 2 and + sol_countries[t,getCountryById[new_team]] < 2 and sol_opps[t,(2*p-1)-1] == None] + + list_1 = [0] + list_2 = [0] + if sol_opps[new_team,current_pos] == None: + list_1 = possible_opps[current_pos][new_team] + if sol_opps[new_team,current_pos+1] == None: + list_2 = possible_opps[current_pos+1][new_team] + + unique_combinations[current_pos] = [] + for i in list_1: + for j in list_2: + if i != j or (i == 0 and j == 0): + unique_combinations[current_pos].append((i, j)) + + combi_list = list(itertools.product(*unique_combinations.values())) + random.shuffle(combi_list) + + + + + # print("STOP") + # for current_pos in range(2*(p-1),8,2): + # print(current_pos,possible_opps[current_pos][new_team]) + # print(current_pos+1,possible_opps[current_pos+1][new_team]) + # list_1 = [0] + # list_2 = [0] + # if sol_opps[new_team,current_pos] == None: + # list_1 = possible_opps[current_pos][new_team] + # if sol_opps[new_team,current_pos+1] == None: + # list_2 = possible_opps[current_pos+1][new_team] + + # unique_combinations[current_pos] = [] + # for i in list_1: + # for j in list_2: + # if i != j or (i == 0 and j == 0): + # unique_combinations[current_pos].append((i, j)) + # print(unique_combinations) + # exit() + + + no_solution_found = True + while (no_solution_found): + # print("\tPOP",len(combi_list)) + new_games = [] + new_opponents = combi_list.pop() + for o1,o2 in new_opponents: + if o1: + new_games.append((new_team,o1)) + if o2: + new_games.append((o2,new_team)) + + + # n_computations += 1 + # tt = time.time() + check, comp_time = check_feasible_gurobi(fixed_games+new_games) + # check_time += time.time()-tt + # total_comp_time += comp_time + if check: + no_solution_found = False + fixed_games += new_games + for i,(new_opponent1,new_opponent2) in enumerate(new_opponents): + current_pos = 2*(p-1)+2*i + if sol_opps[new_team,current_pos] == None: + sol_opps[new_team,current_pos] = new_opponent1 + sol_countries[new_team,getCountryById[new_opponent1]] += 1 + sol_opps[new_opponent1 ,(2*p-1)] = new_team + sol_countries[new_opponent1,getCountryById[new_team]] += 1 + if new_team in possible_opps[(2*p-1)-1][new_opponent1]: + possible_opps[(2*p-1)-1][new_opponent1].remove(new_team) + if sol_opps[new_team,current_pos+1] == None: + sol_opps[new_team,current_pos+1] = new_opponent2 + sol_countries[new_team,getCountryById[new_opponent2]] += 1 + sol_opps[new_opponent2,(2*p-1)-(1)] = new_team + sol_countries[new_opponent2,getCountryById[new_team]] += 1 + if new_team in possible_opps[(2*p-1)][new_opponent2]: + possible_opps[(2*p-1)][new_opponent2].remove(new_team) + + # 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_sim},{t['id']},{';'.join([str(sol_opps[t['id'],p]) for p in range(8)])}\n") + + + + + + # # WRITE SOL '.html' + # sol = '' + # sol += " \ + # \ + # " + # sol += "\n" + # sol += "\n" + # sol += "" + # sol += "" + # sol += "" + # sol += "" + # sol += "" + # sol += "" + # sol += "" + # sol += "\n" + # sol += f"\n" + # for t in teams: + # sol += f"\n" + # sol += "\n" + # sol += "\n" + # sol += "\n" + # for t1 in teams: + # sol += "\n" + # sol += f"" + # for t2 in teams: + # 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
{getTeamById[t['id']]}
{getTeamById[t1['id']]}{t2['country']}@{t2['country']}
\n" + + # with open(f'debug.html', 'w') as f: + # f.write(sol) + + +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 = 2 +# simulate_draws('test', n) + + + + + + + + + + diff --git a/uefa/cycle24/simulations/mixed_draws/probabilities_october.py b/uefa/cycle24/simulations/mixed_draws/probabilities_october.py new file mode 100755 index 0000000..6ebc0ae --- /dev/null +++ b/uefa/cycle24/simulations/mixed_draws/probabilities_october.py @@ -0,0 +1,316 @@ +# %% +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 + + + + +scenario = Scenario.objects.get(id=34) + +# %% + +order = {} + +order['FC Bayern München'] = 1 +order['Manchester City FC'] = 2 +order['Liverpool FC'] = 3 +order['Real Madrid CF'] = 4 +order['Chelsea FC'] = 5 +order['FC Barcelona'] = 6 +order['Paris Saint-Germain'] = 7 +order['Juventus'] = 8 +order['Club Atlético de Madrid'] = 9 +order['Sevilla FC'] = 10 +order['RB Leipzig'] = 11 +order['Tottenham Hotspur'] = 12 +order['AFC Ajax'] = 13 +order['FC Porto'] = 14 +order['Arsenal FC'] = 15 +order['Borussia Dortmund'] = 16 +order['FC Salzburg'] = 17 +order['FC Shakhtar Donetsk'] = 18 +order['FC Internazionale Milano'] = 19 +order['SSC Napoli'] = 20 +order['Eintracht Frankfurt'] = 21 +order['SL Benfica'] = 22 +order['Sporting Clube de Portugal'] = 23 +order['Bayer 04 Leverkusen'] = 24 +order['Rangers FC'] = 25 +order['GNK Dinamo'] = 26 +order['FK Crvena zvezda'] = 27 +order['Olympique de Marseille'] = 28 +order['F.C. Copenhagen'] = 29 +order['Club Brugge'] = 30 +order['AC Milan'] = 31 +order['PSV Eindhoven'] = 32 +order['Celtic FC'] = 33 +order['FC Viktoria Plzeň'] = 34 +order['AS Monaco'] = 35 +order['Maccabi Haifa FC'] = 36 + + + + + + + +# %% + + +teams = Team.objects.filter(season=scenario.season,active=True).order_by('pot','country') + + +countries = list(set(list(teams.values_list('country', flat=True)))) + + +# print(countries) + + +# %% + + +getTeamByID = { + t.id:t for t in teams +} + +getPotByID = { + t.id:t.pot for t in teams +} + +getTeamByName = { + t.name:t for t in teams +} + +getCountryByTeamID = { + t.id:t.country for t in teams +} + + + + +played_countries = { + (t1, c):0 for c in countries for t1 in teams +} +random_played_countries = { + (t1, c):0 for c in countries for t1 in teams +} +stats = { + (t1,t2):0 for t1 in teams for t2 in teams +} +random_stats = { + (t1,t2):0 for t1 in teams for t2 in teams +} + + +pots = { + t1:{ + p:0 for p in range(1,5) + } + for t1 in teams +} +simulations_undirected = 0 +simulations_directed = 0 +maxVal = 1 +minVal = 99999999 +maxCVal = 1 +minCVal = 9999999 +maxRVal = 1 +minRVal = 9999999 +maxCRVal = 1 +minCRVal = 9999999 + +old_c = "START" +for i in range(16): + with open(f'thread_{i}_pot_by_pot.csv', newline='') as csvfile: + # with open('verteilung_random.csv', newline='') as csvfile: + reader = csv.reader(csvfile) + next(reader, None) + for row in reader: + if int(row[0]) != old_c: + old_c = int(row[0]) + simulations_undirected +=1 + + team = getTeamByID[int(row[1])] + Aopps = [getTeamByID[int(t)] for t in row[2].split(";")][:2] + for o in Aopps: + stats[team,o] += 1 + pots[team][getPotByID[o.id]] += 1 + played_countries[team,o.country] += 1 + Bopps = [getTeamByID[int(t)] for t in row[2].split(";")][2:4] + for o in Bopps: + stats[team,o] += 1 + pots[team][getPotByID[o.id]] += 1 + played_countries[team,o.country] += 1 + Copps = [getTeamByID[int(t)] for t in row[2].split(";")][4:6] + for o in Copps: + stats[team,o] += 1 + pots[team][getPotByID[o.id]] += 1 + played_countries[team,o.country] += 1 + Dopps = [getTeamByID[int(t)] for t in row[2].split(";")][6:] + for o in Dopps: + stats[team,o] += 1 + pots[team][getPotByID[o.id]] += 1 + played_countries[team,o.country] += 1 + + if stats[team,o] > maxVal: + maxVal = stats[team,o] + + if played_countries[team,o.country] > maxCVal: + maxCVal = played_countries[team,o.country] + + +diff = {} +mindval = 999999 +maxdval = 0 +# simulations_undirected = 1 +simulations_directed = 1 + +for key in random_stats.keys(): + diff[key] = stats[key]/simulations_undirected - 2*random_stats[key]/simulations_directed + if diff[key] > maxdval: + maxdval = diff[key] + if diff[key] > 0 and diff[key] < mindval: + mindval = diff[key] + + + +for key, val in stats.items(): + if val > 0 and val < minVal: + minVal = val + + +for key, val in random_stats.items(): + if val > 0 and val < minRVal: + minRVal = val + + +for key, val in played_countries.items(): + if val > 0 and val < minCVal: + minCVal = val + + +for key, val in random_played_countries.items(): + if val > 0 and val < minCRVal: + minCRVal = val + + + +# for t in pots: +# print(t,pots[t]) + + +def heatmap_color_for(value): + if value <= 0.5: + g = 256 + r = 2 * max(0,value) * 256 + if value > 0.5: + g = 2*(1-min(1,value))*256 + r = 256 + return f"rgb({r},{g},{0})" + + + +sol = '' +sol += " \ + \ +" +sol += "" +sol += "

Probabilities of games - drawn simultaneously

" +sol += "\n" +sol += "\n" +sol += "" +sol += f"" +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] + color = heatmap_color_for((stats[t1,t2]-minVal)/((maxVal-minVal) or 1)) + if stats[t1,t2] == 0: + color = 'grey' + val = f"{round((stats[t1,t2]/simulations_undirected)*100)}%" + # val = stats[t1,t2] + sol += f"" + sol += "\n" + +sol += "\n" +sol += "
{simulations_undirected}Pot APot BPot CPot D
({t.country}) {t.shortname}
({t1.country}) {t1.shortname}{val}
\n" + + +with open(f'probabilities_simultaneously.html', 'w') as f: + f.write(sol) + + + + + + + +# %% diff --git a/uefa/cycle24/simulations/probabilities_october.py b/uefa/cycle24/simulations/probabilities_october.py new file mode 100755 index 0000000..659bd83 --- /dev/null +++ b/uefa/cycle24/simulations/probabilities_october.py @@ -0,0 +1,559 @@ +# %% +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 + + + + +scenario = Scenario.objects.get(id=34) + +# %% + +order = {} + +order['FC Bayern München'] = 1 +order['Manchester City FC'] = 2 +order['Liverpool FC'] = 3 +order['Real Madrid CF'] = 4 +order['Chelsea FC'] = 5 +order['FC Barcelona'] = 6 +order['Paris Saint-Germain'] = 7 +order['Juventus'] = 8 +order['Club Atlético de Madrid'] = 9 +order['Sevilla FC'] = 10 +order['RB Leipzig'] = 11 +order['Tottenham Hotspur'] = 12 +order['AFC Ajax'] = 13 +order['FC Porto'] = 14 +order['Arsenal FC'] = 15 +order['Borussia Dortmund'] = 16 +order['FC Salzburg'] = 17 +order['FC Shakhtar Donetsk'] = 18 +order['FC Internazionale Milano'] = 19 +order['SSC Napoli'] = 20 +order['Eintracht Frankfurt'] = 21 +order['SL Benfica'] = 22 +order['Sporting Clube de Portugal'] = 23 +order['Bayer 04 Leverkusen'] = 24 +order['Rangers FC'] = 25 +order['GNK Dinamo'] = 26 +order['FK Crvena zvezda'] = 27 +order['Olympique de Marseille'] = 28 +order['F.C. Copenhagen'] = 29 +order['Club Brugge'] = 30 +order['AC Milan'] = 31 +order['PSV Eindhoven'] = 32 +order['Celtic FC'] = 33 +order['FC Viktoria Plzeň'] = 34 +order['AS Monaco'] = 35 +order['Maccabi Haifa FC'] = 36 + + + + + + + +# %% + + +teams = Team.objects.filter(season=scenario.season,active=True).order_by('pot','country') + + +countries = list(set(list(teams.values_list('country', flat=True)))) + + +# print(countries) + + +# %% + + +getTeamByID = { + t.id:t for t in teams +} + +getPotByID = { + t.id:t.pot for t in teams +} + +getTeamByName = { + t.name:t for t in teams +} + +getCountryByTeamID = { + t.id:t.country for t in teams +} + + + + +played_countries = { + (t1, c):0 for c in countries for t1 in teams +} +random_played_countries = { + (t1, c):0 for c in countries for t1 in teams +} +stats = { + (t1,t2):0 for t1 in teams for t2 in teams +} +random_stats = { + (t1,t2):0 for t1 in teams for t2 in teams +} + + +pots = { + t1:{ + p:0 for p in range(1,5) + } + for t1 in teams +} +simulations_undirected = 0 +simulations_directed = 0 +maxVal = 1 +minVal = 99999999 +maxCVal = 1 +minCVal = 9999999 +maxRVal = 1 +minRVal = 9999999 +maxCRVal = 1 +minCRVal = 9999999 + +old_c = "START" +for i in range(16): + with open(f'thread_{i}_pot_by_pot.csv', newline='') as csvfile: + # with open('verteilung_random.csv', newline='') as csvfile: + reader = csv.reader(csvfile) + next(reader, None) + for row in reader: + if int(row[0]) != old_c: + old_c = int(row[0]) + simulations_undirected +=1 + + team = getTeamByID[int(row[1])] + Aopps = [getTeamByID[int(t)] for t in row[2].split(";")][:2] + for o in Aopps: + stats[team,o] += 1 + pots[team][getPotByID[o.id]] += 1 + played_countries[team,o.country] += 1 + Bopps = [getTeamByID[int(t)] for t in row[2].split(";")][2:4] + for o in Bopps: + stats[team,o] += 1 + pots[team][getPotByID[o.id]] += 1 + played_countries[team,o.country] += 1 + Copps = [getTeamByID[int(t)] for t in row[2].split(";")][4:6] + for o in Copps: + stats[team,o] += 1 + pots[team][getPotByID[o.id]] += 1 + played_countries[team,o.country] += 1 + Dopps = [getTeamByID[int(t)] for t in row[2].split(";")][6:] + for o in Dopps: + stats[team,o] += 1 + pots[team][getPotByID[o.id]] += 1 + played_countries[team,o.country] += 1 + + if stats[team,o] > maxVal: + maxVal = stats[team,o] + + if played_countries[team,o.country] > maxCVal: + maxCVal = played_countries[team,o.country] + +# with open(f'test.csv', newline='') as csvfile: +# # with open('verteilung_random.csv', newline='') as csvfile: +# reader = csv.reader(csvfile) +# next(reader, None) +# for row in reader: +# if int(row[0]) != old_c: +# old_c = int(row[0]) +# simulations_undirected +=1 + +# team = getTeamByID[int(row[1])] +# Aopps = [getTeamByID[int(t)] for t in row[2].split(";")][:2] +# for o in Aopps: +# stats[team,o] += 1 +# pots[team][getPotByID[o.id]] += 1 +# played_countries[team,o.country] += 1 +# Bopps = [getTeamByID[int(t)] for t in row[2].split(";")][2:4] +# for o in Bopps: +# stats[team,o] += 1 +# pots[team][getPotByID[o.id]] += 1 +# played_countries[team,o.country] += 1 +# Copps = [getTeamByID[int(t)] for t in row[2].split(";")][4:6] +# for o in Copps: +# stats[team,o] += 1 +# pots[team][getPotByID[o.id]] += 1 +# played_countries[team,o.country] += 1 +# Dopps = [getTeamByID[int(t)] for t in row[2].split(";")][6:] +# for o in Dopps: +# stats[team,o] += 1 +# pots[team][getPotByID[o.id]] += 1 +# played_countries[team,o.country] += 1 + +# if stats[team,o] > maxVal: +# maxVal = stats[team,o] + +# if played_countries[team,o.country] > maxCVal: +# maxCVal = played_countries[team,o.country] + +# %% + + + + +# old_c = "START" + +# # with open('verteilung_draw.csv', newline='') as csvfile: +# with open('draw_options_HA_2country.csv', newline='') as csvfile: +# reader = csv.reader(csvfile) +# next(reader, None) +# for row in reader: +# if int(row[0]) != old_c: +# old_c = int(row[0]) +# simulations_directed +=1 + + +# team = getTeamByID[int(row[1])] +# Aopps = [getTeamByID[int(t)] for t in row[2].split(";")][:1] +# for o in Aopps: +# random_stats[team,o] += 1 +# # pots[team][getPotByID[o.id]] += 1 +# random_played_countries[team,o.country] += 1 +# Bopps = [getTeamByID[int(t)] for t in row[2].split(";")][2:3] +# for o in Bopps: +# random_stats[team,o] += 1 +# # pots[team][getPotByID[o.id]] += 1 +# random_played_countries[team,o.country] += 1 +# Copps = [getTeamByID[int(t)] for t in row[2].split(";")][4:5] +# for o in Copps: +# random_stats[team,o] += 1 +# # pots[team][getPotByID[o.id]] += 1 +# random_played_countries[team,o.country] += 1 +# Dopps = [getTeamByID[int(t)] for t in row[2].split(";")][6:7] +# for o in Dopps: +# random_stats[team,o] += 1 +# # pots[team][getPotByID[o.id]] += 1 +# random_played_countries[team,o.country] += 1 + +# if random_stats[team,o] > maxRVal: +# maxRVal = random_stats[team,o] + + +# if random_played_countries[team,o.country] > maxCRVal: +# maxCRVal = random_played_countries[team,o.country] + + +diff = {} +mindval = 999999 +maxdval = 0 +# simulations_undirected = 1 +simulations_directed = 1 + +for key in random_stats.keys(): + diff[key] = stats[key]/simulations_undirected - 2*random_stats[key]/simulations_directed + if diff[key] > maxdval: + maxdval = diff[key] + if diff[key] > 0 and diff[key] < mindval: + mindval = diff[key] + + + +for key, val in stats.items(): + if val > 0 and val < minVal: + minVal = val + + +for key, val in random_stats.items(): + if val > 0 and val < minRVal: + minRVal = val + + +for key, val in played_countries.items(): + if val > 0 and val < minCVal: + minCVal = val + + +for key, val in random_played_countries.items(): + if val > 0 and val < minCRVal: + minCRVal = val + + + +# for t in pots: +# print(t,pots[t]) + + +def heatmap_color_for(value): + if value <= 0.5: + g = 256 + r = 2 * max(0,value) * 256 + if value > 0.5: + g = 2*(1-min(1,value))*256 + r = 256 + return f"rgb({r},{g},{0})" + + + +sol = '' +sol += " \ + \ +" +sol += "" +sol += "

Probabilities of games - undirected vs directed

" +sol += "" +sol += "Each options data is based on approximately 5000 random draws. Both options are restricted to at most 2 opponents from the same country." +sol += "
" +sol += "

Table 1: Probabilities of games - undirected

" +sol += "Home/Away games are assigned in the calendar phase, therefore this table is symmetric." +sol += "\n" +sol += "\n" +sol += "" +sol += f"" +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] + color = heatmap_color_for((stats[t1,t2]-minVal)/((maxVal-minVal) or 1)) + if stats[t1,t2] == 0: + color = 'grey' + val = f"{round(round(stats[t1,t2]/simulations_undirected,2)*100)}%" + # val = stats[t1,t2] + sol += f"" + sol += "\n" + +sol += "\n" +sol += "
{simulations_undirected}Pot APot BPot CPot D
({t.country}) {t.shortname}
({t1.country}) {t1.shortname}{val}
\n" + +sol += "
" +sol += "
" +sol += "
" +sol += "
" + +sol += "

Table 2: Probabilities of games - directed

" +sol += "Home/Away games are assigned during the draw, therefore this table is asymmetric." +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] + color = heatmap_color_for((random_stats[t1,t2]-minRVal)/((maxRVal-minRVal) or 1)) + if random_stats[t1,t2] == 0: + color = 'grey' + val = f"{round(round(random_stats[t1,t2]/simulations_directed,2)*100)}%" + # val = stats[t1,t2] + sol += f"" + sol += "\n" + +sol += "\n" +sol += "
Pot APot BPot CPot D
({t.country}) {t.shortname}
({t1.country}) {t1.shortname}{val}
\n" + + +sol += "
" +sol += "
" +sol += "
" +sol += "
" + +sol += "

Table 3: Difference of probabilities (moving from undirected to directed)

" +sol += "\n" +sol += "\n" +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] + color = heatmap_color_for((abs(diff[t1,t2])-mindval)/((maxdval-mindval) or 1)) + if stats[t1,t2] == 0: + color = 'grey' + val = f"{diff[t1,t2]}%" + # val = stats[t1,t2] + sol += f"" + sol += "\n" + +sol += "\n" +sol += "
({t.country}) {t.shortname}
({t1.country}) {t1.shortname}{round(round(diff[t1,t2],2)*100)}%
\n" + +# sol += "
" +# sol += "
" +# sol += "
" +# sol += "
" + +# sol += "

Average number of games against other countries - undirected

" +# sol += "\n" +# sol += "\n" +# sol += "" +# sol += "\n" +# sol += f"\n" +# for c in countries: +# 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 c in countries: +# # color = heatmap_color_for((played_countries[t1,c]-minCVal)/(maxCVal-minCVal)) +# color = 'lightsteelblue' +# if played_countries[t1,c] == 0: +# color = 'grey' +# # val = f"{round(round(played_played_countries[t1][c]/simulations,2)*100)}%" +# val = f"{round(played_countries[t1,c]/(simulations_undirected),2)}" +# # val = stats[t1,t2] +# sol += f"" +# sol += "\n" + +# sol += "\n" +# sol += "
{c}
{t1.shortname}{val}
\n" + + +# sol += "
" +# sol += "
" +# sol += "
" +# sol += "
" + +# sol += "

Average number of games against other countries - directed

" +# sol += "\n" +# sol += "\n" +# sol += "" +# sol += "\n" +# sol += f"\n" +# for c in countries: +# 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 c in countries: +# # color = heatmap_color_for((played_countries[t1,c]-minCVal)/(maxCVal-minCVal)) +# color = 'lightsteelblue' +# if random_played_countries[t1,c] == 0: +# color = 'grey' +# # val = f"{round(round(played_played_countries[t1][c]/simulations,2)*100)}%" +# val = f"{round(random_played_countries[t1,c]/(simulations_directed),2)}" +# # val = stats[t1,t2] +# sol += f"" +# sol += "\n" + +sol += "\n" +sol += "
{c}
{t1.shortname}{val}
\n" + + + +with open(f'probabilities.html', 'w') as f: + f.write(sol) + + + + + + + +# %% diff --git a/uefa/cycle24/simulations/single_draws/probabilities_october.py b/uefa/cycle24/simulations/single_draws/probabilities_october.py new file mode 100755 index 0000000..56df730 --- /dev/null +++ b/uefa/cycle24/simulations/single_draws/probabilities_october.py @@ -0,0 +1,316 @@ +# %% +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 + + + + +scenario = Scenario.objects.get(id=34) + +# %% + +order = {} + +order['FC Bayern München'] = 1 +order['Manchester City FC'] = 2 +order['Liverpool FC'] = 3 +order['Real Madrid CF'] = 4 +order['Chelsea FC'] = 5 +order['FC Barcelona'] = 6 +order['Paris Saint-Germain'] = 7 +order['Juventus'] = 8 +order['Club Atlético de Madrid'] = 9 +order['Sevilla FC'] = 10 +order['RB Leipzig'] = 11 +order['Tottenham Hotspur'] = 12 +order['AFC Ajax'] = 13 +order['FC Porto'] = 14 +order['Arsenal FC'] = 15 +order['Borussia Dortmund'] = 16 +order['FC Salzburg'] = 17 +order['FC Shakhtar Donetsk'] = 18 +order['FC Internazionale Milano'] = 19 +order['SSC Napoli'] = 20 +order['Eintracht Frankfurt'] = 21 +order['SL Benfica'] = 22 +order['Sporting Clube de Portugal'] = 23 +order['Bayer 04 Leverkusen'] = 24 +order['Rangers FC'] = 25 +order['GNK Dinamo'] = 26 +order['FK Crvena zvezda'] = 27 +order['Olympique de Marseille'] = 28 +order['F.C. Copenhagen'] = 29 +order['Club Brugge'] = 30 +order['AC Milan'] = 31 +order['PSV Eindhoven'] = 32 +order['Celtic FC'] = 33 +order['FC Viktoria Plzeň'] = 34 +order['AS Monaco'] = 35 +order['Maccabi Haifa FC'] = 36 + + + + + + + +# %% + + +teams = Team.objects.filter(season=scenario.season,active=True).order_by('pot','country') + + +countries = list(set(list(teams.values_list('country', flat=True)))) + + +# print(countries) + + +# %% + + +getTeamByID = { + t.id:t for t in teams +} + +getPotByID = { + t.id:t.pot for t in teams +} + +getTeamByName = { + t.name:t for t in teams +} + +getCountryByTeamID = { + t.id:t.country for t in teams +} + + + + +played_countries = { + (t1, c):0 for c in countries for t1 in teams +} +random_played_countries = { + (t1, c):0 for c in countries for t1 in teams +} +stats = { + (t1,t2):0 for t1 in teams for t2 in teams +} +random_stats = { + (t1,t2):0 for t1 in teams for t2 in teams +} + + +pots = { + t1:{ + p:0 for p in range(1,5) + } + for t1 in teams +} +simulations_undirected = 0 +simulations_directed = 0 +maxVal = 1 +minVal = 99999999 +maxCVal = 1 +minCVal = 9999999 +maxRVal = 1 +minRVal = 9999999 +maxCRVal = 1 +minCRVal = 9999999 + +old_c = "START" +for i in range(16): + with open(f'thread_{i}_pot_by_pot.csv', newline='') as csvfile: + # with open('verteilung_random.csv', newline='') as csvfile: + reader = csv.reader(csvfile) + next(reader, None) + for row in reader: + if int(row[0]) != old_c: + old_c = int(row[0]) + simulations_undirected +=1 + + team = getTeamByID[int(row[1])] + Aopps = [getTeamByID[int(t)] for t in row[2].split(";")][:2] + for o in Aopps: + stats[team,o] += 1 + pots[team][getPotByID[o.id]] += 1 + played_countries[team,o.country] += 1 + Bopps = [getTeamByID[int(t)] for t in row[2].split(";")][2:4] + for o in Bopps: + stats[team,o] += 1 + pots[team][getPotByID[o.id]] += 1 + played_countries[team,o.country] += 1 + Copps = [getTeamByID[int(t)] for t in row[2].split(";")][4:6] + for o in Copps: + stats[team,o] += 1 + pots[team][getPotByID[o.id]] += 1 + played_countries[team,o.country] += 1 + Dopps = [getTeamByID[int(t)] for t in row[2].split(";")][6:] + for o in Dopps: + stats[team,o] += 1 + pots[team][getPotByID[o.id]] += 1 + played_countries[team,o.country] += 1 + + if stats[team,o] > maxVal: + maxVal = stats[team,o] + + if played_countries[team,o.country] > maxCVal: + maxCVal = played_countries[team,o.country] + + +diff = {} +mindval = 999999 +maxdval = 0 +# simulations_undirected = 1 +simulations_directed = 1 + +for key in random_stats.keys(): + diff[key] = stats[key]/simulations_undirected - 2*random_stats[key]/simulations_directed + if diff[key] > maxdval: + maxdval = diff[key] + if diff[key] > 0 and diff[key] < mindval: + mindval = diff[key] + + + +for key, val in stats.items(): + if val > 0 and val < minVal: + minVal = val + + +for key, val in random_stats.items(): + if val > 0 and val < minRVal: + minRVal = val + + +for key, val in played_countries.items(): + if val > 0 and val < minCVal: + minCVal = val + + +for key, val in random_played_countries.items(): + if val > 0 and val < minCRVal: + minCRVal = val + + + +# for t in pots: +# print(t,pots[t]) + + +def heatmap_color_for(value): + if value <= 0.5: + g = 256 + r = 2 * max(0,value) * 256 + if value > 0.5: + g = 2*(1-min(1,value))*256 + r = 256 + return f"rgb({r},{g},{0})" + + + +sol = '' +sol += " \ + \ +" +sol += "" +sol += "

Probabilities of games - drawn team by team

" +sol += "\n" +sol += "\n" +sol += "" +sol += f"" +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] + color = heatmap_color_for((stats[t1,t2]-minVal)/((maxVal-minVal) or 1)) + if stats[t1,t2] == 0: + color = 'grey' + val = f"{round((stats[t1,t2]/simulations_undirected)*100)}%" + # val = stats[t1,t2] + sol += f"" + sol += "\n" + +sol += "\n" +sol += "
{simulations_undirected}Pot APot BPot CPot D
({t.country}) {t.shortname}
({t1.country}) {t1.shortname}{val}
\n" + + +with open(f'probabilities_team_by_team.html', 'w') as f: + f.write(sol) + + + + + + + +# %% diff --git a/uefa/nations_league/analytics.py b/uefa/nations_league/analytics.py index cf325fa..791487d 100644 --- a/uefa/nations_league/analytics.py +++ b/uefa/nations_league/analytics.py @@ -96,6 +96,8 @@ for scenario in season.scenarios.all(): violated_blockings[b.team]['comments'][f"{b.type} - {b.day}"] += 1 +violated_blockings = dict(sorted(violated_blockings.items(), key=lambda x: x[1]['violations'], reverse=True)) + violated_wishes = dict(sorted(violated_wishes.items(), key=lambda x: x[1]['violations'], reverse=True)) for key,val in violated_wishes.items():