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 += "Pot A | "
+# sol += "Pot B | "
+# sol += "Pot C | "
+# sol += "Pot D | "
+# sol += "
"
+# sol += "\n"
+# sol += f" | \n"
+# for t in teams:
+# sol += f"{getTeamById[t['id']]} | \n"
+# sol += "
\n"
+# sol += "\n"
+# sol += "\n"
+# for t1 in teams:
+# sol += "\n"
+# sol += f"| {getTeamById[t1['id']]} | "
+# for t2 in teams:
+# if (t1['id'],t2['id']) in games:
+# sol += f"{t2['country']} | "
+# elif (t2['id'],t1['id']) in games:
+# sol += f"@{t2['country']} | "
+# else:
+# sol += f" | "
+# sol += "
\n"
+# sol += "\n"
+# sol += "
\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 += "Pot A | "
+# sol += "Pot B | "
+# sol += "Pot C | "
+# sol += "Pot D | "
+# sol += "
"
+# sol += "\n"
+# sol += f" | \n"
+# # for o in order:
+# for t in teams:
+# # t = getTeamByName[o]
+# sol += f"{t['name']}({t['country']}) | \n"
+# sol += "
\n"
+# sol += "\n"
+# sol += "\n"
+# # for o1 in order:
+# for t1 in teams:
+# # t1 = getTeamByName[o1]
+# sol += "\n"
+# sol += f"| {t1['name']}({t1['country']}) | "
+# # 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"{t2['country']} | "
+# elif (t2['id'],t1['id']) in fixed_games:
+# sol += f"@{t2['country']} | "
+# else:
+# sol += f" | "
+# sol += "
\n"
+
+# sol += "\n"
+# sol += "
\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 += "Pot A | "
+ # sol += "Pot B | "
+ # sol += "Pot C | "
+ # sol += "Pot D | "
+ # sol += "
"
+ # sol += "\n"
+ # sol += f" | \n"
+ # # for o in order:
+ # for t in teams:
+ # # t = getTeamByName[o]
+ # sol += f"{getTeamById[t['id']]} | \n"
+ # sol += "
\n"
+ # sol += "\n"
+ # sol += "\n"
+ # # for o1 in order:
+ # for t1 in teams:
+ # # t1 = getTeamByName[o1]
+ # sol += "\n"
+ # sol += f"| {getTeamById[t1['id']]} | "
+ # # for o2 in order:
+ # for t2 in teams:
+ # # t2 = getTeamByName[o2]
+ # # val = stats[t1,t2]
+ # if (t1['id'],t2['id']) in games:
+ # sol += f"{t2['country']} | "
+ # elif (t2['id'],t1['id']) in games:
+ # sol += f"@{t2['country']} | "
+ # else:
+ # sol += f" | "
+ # sol += "
\n"
+
+ # sol += "\n"
+ # sol += "
\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 += "Pot A | "
+ # sol += "Pot B | "
+ # sol += "Pot C | "
+ # sol += "Pot D | "
+ # sol += "
"
+ # sol += "\n"
+ # sol += f" | \n"
+ # # for o in order:
+ # for t in teams:
+ # # t = getTeamByName[o]
+ # sol += f"{getTeamById[t['id']]} | \n"
+ # sol += "
\n"
+ # sol += "\n"
+ # sol += "\n"
+ # # for o1 in order:
+ # for t1 in teams:
+ # # t1 = getTeamByName[o1]
+ # sol += "\n"
+ # sol += f"| {getTeamById[t1['id']]} | "
+ # # for o2 in order:
+ # for t2 in teams:
+ # # t2 = getTeamByName[o2]
+ # # val = stats[t1,t2]
+ # if (t1['id'],t2['id']) in games:
+ # sol += f"{t2['country']} | "
+ # elif (t2['id'],t1['id']) in games:
+ # sol += f"@{t2['country']} | "
+ # else:
+ # sol += f" | "
+ # sol += "
\n"
+
+ # sol += "\n"
+ # sol += "
\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 += "Pot A | "
+# sol += "Pot B | "
+# sol += "Pot C | "
+# sol += "Pot D | "
+# sol += "
"
+# sol += "\n"
+# sol += f" | \n"
+# for t in teams:
+# sol += f"{getTeamById[t['id']]} | \n"
+# sol += "
\n"
+# sol += "\n"
+# sol += "\n"
+# for t1 in teams:
+# sol += "\n"
+# sol += f"| {getTeamById[t1['id']]} | "
+# for t2 in teams:
+# if (t1['id'],t2['id']) in games:
+# sol += f"{t2['country']} | "
+# elif (t2['id'],t1['id']) in games:
+# sol += f"@{t2['country']} | "
+# else:
+# sol += f" | "
+# sol += "
\n"
+# sol += "\n"
+# sol += "
\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 += "Pot A | "
+ sol += "Pot B | "
+ sol += "Pot C | "
+ sol += "Pot D | "
+ sol += "
"
+ sol += "\n"
+ sol += f" | \n"
+ for t in teams:
+ sol += f"{getTeamById[t['id']]} | \n"
+ sol += "
\n"
+ sol += "\n"
+ sol += "\n"
+ for t1 in teams:
+ sol += "\n"
+ sol += f"| {getTeamById[t1['id']]} | "
+ for t2 in teams:
+ if (t1['id'],t2['id']) in fixed_games:
+ sol += f"{t2['country']} | "
+ elif (t2['id'],t1['id']) in fixed_games:
+ sol += f"@{t2['country']} | "
+ else:
+ sol += f" | "
+ sol += "
\n"
+ sol += "\n"
+ sol += "
\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"| {simulations_undirected} | "
+sol += "Pot A | "
+sol += "Pot B | "
+sol += "Pot C | "
+sol += "Pot D | "
+sol += "
"
+sol += "\n"
+sol += f" | \n"
+# for o in order:
+for t in teams:
+ # t = getTeamByName[o]
+ sol += f"({t.country}) {t.shortname} | \n"
+sol += "
\n"
+sol += "\n"
+sol += "\n"
+# for o1 in order:
+for t1 in teams:
+ # t1 = getTeamByName[o1]
+ sol += "\n"
+ sol += f"| ({t1.country}) {t1.shortname} | "
+ # 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"{val} | "
+ sol += "
\n"
+
+sol += "\n"
+sol += "
\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 += "Pot A | "
+ # sol += "Pot B | "
+ # sol += "Pot C | "
+ # sol += "Pot D | "
+ # sol += "
"
+ # sol += "\n"
+ # sol += f" | \n"
+ # for t in teams:
+ # sol += f"{getTeamById[t['id']]} | \n"
+ # sol += "
\n"
+ # sol += "\n"
+ # sol += "\n"
+ # for t1 in teams:
+ # sol += "\n"
+ # sol += f"| {getTeamById[t1['id']]} | "
+ # for t2 in teams:
+ # if (t1['id'],t2['id']) in fixed_games:
+ # sol += f"{t2['country']} | "
+ # elif (t2['id'],t1['id']) in fixed_games:
+ # sol += f"@{t2['country']} | "
+ # else:
+ # sol += f" | "
+ # sol += "
\n"
+ # sol += "\n"
+ # sol += "
\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 += "Pot A | "
+ sol += "Pot B | "
+ sol += "Pot C | "
+ sol += "Pot D | "
+ sol += "
"
+ sol += "\n"
+ sol += f" | \n"
+ for t in teams:
+ sol += f"{getTeamById[t['id']]} | \n"
+ sol += "
\n"
+ sol += "\n"
+ sol += "\n"
+ for t1 in teams:
+ sol += "\n"
+ sol += f"| {getTeamById[t1['id']]} | "
+ for t2 in teams:
+ if (t1['id'],t2['id']) in fixed_games:
+ sol += f"{t2['country']} | "
+ elif (t2['id'],t1['id']) in fixed_games:
+ sol += f"@{t2['country']} | "
+ else:
+ sol += f" | "
+ sol += "
\n"
+ sol += "\n"
+ sol += "
\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 += "Pot A | "
+ # sol += "Pot B | "
+ # sol += "Pot C | "
+ # sol += "Pot D | "
+ # sol += "
"
+ # sol += "\n"
+ # sol += f" | \n"
+ # for t in teams:
+ # sol += f"{getTeamById[t['id']]} | \n"
+ # sol += "
\n"
+ # sol += "\n"
+ # sol += "\n"
+ # for t1 in teams:
+ # sol += "\n"
+ # sol += f"| {getTeamById[t1['id']]} | "
+ # for t2 in teams:
+ # if (t1['id'],t2['id']) in fixed_games:
+ # sol += f"{t2['country']} | "
+ # elif (t2['id'],t1['id']) in fixed_games:
+ # sol += f"@{t2['country']} | "
+ # else:
+ # sol += f" | "
+ # sol += "
\n"
+ # sol += "\n"
+ # sol += "
\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"| {simulations_undirected} | "
+sol += "Pot A | "
+sol += "Pot B | "
+sol += "Pot C | "
+sol += "Pot D | "
+sol += "
"
+sol += "\n"
+sol += f" | \n"
+# for o in order:
+for t in teams:
+ # t = getTeamByName[o]
+ sol += f"({t.country}) {t.shortname} | \n"
+sol += "
\n"
+sol += "\n"
+sol += "\n"
+# for o1 in order:
+for t1 in teams:
+ # t1 = getTeamByName[o1]
+ sol += "\n"
+ sol += f"| ({t1.country}) {t1.shortname} | "
+ # 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"{val} | "
+ sol += "
\n"
+
+sol += "\n"
+sol += "
\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 += "- Table 1: Probability of two teams to be drawn against each other (symmetric)
"
+sol += "- Table 2: Probability of a home or away encounter (asymmetric)
"
+sol += "- Table 3: Difference of the two options from above. Moving from undirected to directed
"
+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"| {simulations_undirected} | "
+sol += "Pot A | "
+sol += "Pot B | "
+sol += "Pot C | "
+sol += "Pot D | "
+sol += "
"
+sol += "\n"
+sol += f" | \n"
+# for o in order:
+for t in teams:
+ # t = getTeamByName[o]
+ sol += f"({t.country}) {t.shortname} | \n"
+sol += "
\n"
+sol += "\n"
+sol += "\n"
+# for o1 in order:
+for t1 in teams:
+ # t1 = getTeamByName[o1]
+ sol += "\n"
+ sol += f"| ({t1.country}) {t1.shortname} | "
+ # 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"{val} | "
+ sol += "
\n"
+
+sol += "\n"
+sol += "
\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 += "Pot A | "
+sol += "Pot B | "
+sol += "Pot C | "
+sol += "Pot D | "
+sol += "
"
+sol += "\n"
+sol += f" | \n"
+# for o in order:
+for t in teams:
+ # t = getTeamByName[o]
+ sol += f"({t.country}) {t.shortname} | \n"
+sol += "
\n"
+sol += "\n"
+sol += "\n"
+# for o1 in order:
+for t1 in teams:
+ # t1 = getTeamByName[o1]
+ sol += "\n"
+ sol += f"| ({t1.country}) {t1.shortname} | "
+ # 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"{val} | "
+ sol += "
\n"
+
+sol += "\n"
+sol += "
\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"({t.country}) {t.shortname} | \n"
+sol += "
\n"
+sol += "\n"
+sol += "\n"
+# for o1 in order:
+for t1 in teams:
+ # t1 = getTeamByName[o1]
+ sol += "\n"
+ sol += f"| ({t1.country}) {t1.shortname} | "
+ # 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"{round(round(diff[t1,t2],2)*100)}% | "
+ sol += "
\n"
+
+sol += "\n"
+sol += "
\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"{c} | \n"
+# sol += "
\n"
+# sol += "\n"
+# sol += "\n"
+# # for o1 in order:
+# for t1 in teams:
+# # t1 = getTeamByName[o1]
+# sol += "\n"
+# sol += f"| {t1.shortname} | "
+# 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"{val} | "
+# sol += "
\n"
+
+# sol += "\n"
+# sol += "
\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"{c} | \n"
+# sol += "
\n"
+# sol += "\n"
+# sol += "\n"
+# # for o1 in order:
+# for t1 in teams:
+# # t1 = getTeamByName[o1]
+# sol += "\n"
+# sol += f"| {t1.shortname} | "
+# 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"{val} | "
+# sol += "
\n"
+
+sol += "\n"
+sol += "
\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"| {simulations_undirected} | "
+sol += "Pot A | "
+sol += "Pot B | "
+sol += "Pot C | "
+sol += "Pot D | "
+sol += "
"
+sol += "\n"
+sol += f" | \n"
+# for o in order:
+for t in teams:
+ # t = getTeamByName[o]
+ sol += f"({t.country}) {t.shortname} | \n"
+sol += "
\n"
+sol += "\n"
+sol += "\n"
+# for o1 in order:
+for t1 in teams:
+ # t1 = getTeamByName[o1]
+ sol += "\n"
+ sol += f"| ({t1.country}) {t1.shortname} | "
+ # 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"{val} | "
+ sol += "
\n"
+
+sol += "\n"
+sol += "
\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():