# %% PROJECT_PATH = '/home/md/Work/ligalytics/leagues_stable/' # PROJECT_PATH = '/home/django/leagues/' import os, sys import json from numpyencoder import NumpyEncoder 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' 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'] = {} # settings.DATABASES['default']['ENGINE'] = 'django.db.backends.postgresql' # settings.DATABASES['default']['HOST'] = '0.0.0.0' # settings.DATABASES['default']['PORT'] = '5433' # settings.DATABASES['default']['USER'] = 'leagues_user' # settings.DATABASES['default']['PASSWORD'] = 'ligalytics' # settings.DATABASES['default']['NAME'] = 'prod_16' 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 * from scheduler.helpers import * # from scheduler.solver.optimizer import optimize_2phases from scheduler.solver.tasks.optimize import optimize # %% import copy from collections import defaultdict from unittest import TextTestResult from ortools.sat.python import cp_model from pulp import * import random import os import time import pandas as pd from math import sqrt, sin, cos, atan2, pi import numpy as np # XPRESS ENVIRONMENT os.environ['XPRESSDIR'] = "/opt/xpressmp_9.2.5" os.environ['XPRESS'] = "/opt/xpressmp_9.2.5/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'] import xpress as xp xp.controls.outputlog = 0 import datetime from dateutil.parser import parse def Availabilities(scenario_id,showSolution = "0"): tt = time.time() sc = Scenario.objects.get(id=scenario_id) teams = Team.objects.filter(season=sc.season,active=True).order_by('name').exclude(name='-') realteams= [ t.id for t in teams] getTeamById= { t.id : t for t in teams} t_short= { t.id : t.shortname for t in teams} blockings = Blocking.objects.filter(scenario=sc,team__active=True).exclude(day__round=0).order_by('day', 'team').annotate( dayID=F('day__id'), teamID=F('team__id'), ) days = Day.objects.filter(season=sc.season).order_by('day','round') getDay = { d.id : d for d in days} getDateTimeDay = { d.id : '' for d in days} for d in days: if d.day[0]!='R' : getDateTimeDay[d.id] = parse(d.day) getDayByDateTime = { getDateTimeDay[d.id] : d for d in days} daysSorted =[] for dt in sorted([ getDateTimeDay[d.id] for d in days]): daysSorted.append ( getDayByDateTime[dt] ) usedDays =getDateTimeDay.values() for d in daysSorted: d.firstDayInSequence = (getDateTimeDay[d.id] - datetime.timedelta(days=1)) not in usedDays nRounds = sc.season.nRounds rounds=range(1,nRounds+1) breaks = Break.objects.filter(season=sc.season).values() # SLOWING VIEW DOWN # for bl in blockings: # if bl.day.round==0 or not bl.team.active: # bl.delete() # print ("blocking not assigned to round: deleting " , bl) blockings.filter(day__round=0).exclude(team__active=False).delete() blockRefreshNecessary = False blockDict = defaultdict(dict) for bl in blockings: if not blockDict[(bl.dayID,bl.teamID)]: blockDict[(bl.dayID,bl.teamID)]=bl else: if (blockDict[(bl.dayID,bl.teamID)].type=="Home" and bl.type=="Away") or (blockDict[(bl.dayID,bl.teamID)].type=="Away" and bl.type=="Home"): blockDict[(bl.dayID,bl.teamID)].type="Game" blockDict[(bl.dayID,bl.teamID)].tag=None blockDict[(bl.dayID,bl.teamID)].save() bl.delete() blockRefreshNecessary = True if blockRefreshNecessary: blockings = Blocking.objects.filter(scenario=sc, team__active=True).exclude(day__round=0).order_by('day', 'team').annotate( dayID=F('day__id'), teamID=F('team__id'), ) isBlocked = { (d.id,t.id,ha) : False for t in teams for d in days for ha in ['H','A'] } isBlockedTags = { (d.id,t.id,ha) : [] for t in teams for d in days for ha in ['H','A'] } blockComment = defaultdict(dict) for bl in blockings: if bl.tag: if bl.tag.blocking_weight <0.0: continue isBlockedTags[ (bl.day.id, bl.team.id, "H")].append(bl.tag.name) if bl.comment not in ["","-"]: blockComment[int(bl.day.id)][int(bl.team.id)] = bl.comment if bl.type!="Home": isBlocked[ (int(bl.day.id), int(bl.team.id), "A")]=True if bl.type!="Away": isBlocked[ (bl.day.id, bl.team.id, "H")]=True # print ("isBlocked",isBlocked) for b in blockings.exclude(comment__in=["","-"]): blockComment[int(b.day.id)][int(b.team.id)] = b.comment stadiums = Stadium.objects.filter(season=sc.season) stadiumblockings = StadiumBlocking.objects.filter(scenario=sc, stadium__in=stadiums) # print ("stadiumblockings",stadiumblockings) groups = Conference.objects.filter(scenario=sc,display_group=True).order_by('name') # firstTeams = [ g.teams.all().order_by('name').first().id for g in groups] firstTeams = [] for g in groups: tms = [(t.name, t.id ) for t in g.teams.all()] tms.sort() firstTeams.append(tms[0][1]) wd = {"Mondays":0 , "Tuesdays":1 , "Wednesdays":2 , "Thursdays":3 , "Fridays":4 , "Saturdays":5 , "Sundays":6} t_possible_weekdays={ t.id : [] for t in teams} t_available_slot_per_weekday={ (t.id,w) : 0 for t in teams for w in wd.keys() } t_stadiums = { t.id : [] for t in teams} t_site_available = { (t.id,d.id):0 for t in teams for d in days } for t in teams: # print ("checking stadium availabilities for " , t.name) t_stadiums[t.id] = [sts.stadium for sts in t.stadiumpreferences.all()] for stsp in t.stadiumTimeSlotPreferences.all(): t_possible_weekdays[t.id].append(wd[stsp.stadiumTimeSlot.weekday]) blockedDays = [ sb.day for sb in stsp.stadiumTimeSlot.stadiumtimeslotblockings.all().exclude(homeTeam_id__in=teams)] for d in days: if getDateTimeDay[d.id].weekday() == wd[stsp.stadiumTimeSlot.weekday] and d.day not in blockedDays: t_site_available[(t.id,d.id)]+=1 stadiumBlocks = [ (tid,did) for (tid,did) in t_site_available.keys() if t_site_available[(tid,did)]==0 and t_possible_weekdays[tid]!=[]] # for t,d in stadiumBlocks: # print (getDateTimeDay[d], [ t2.name for t2 in teams if t2.id==t]) competitions = InternationalGame.objects.filter(season=sc.season, active=True) playDays = [day.id for day in days if day.maxGames>0 and day.round>0] compDays = {} competitionBlocks = [] for c in competitions: c.blocking_weight = 0.5 compDays[c.id] = [] dayBefore=datetime.timedelta(days=c.nDaysNotPlayBefore) dayAfter=datetime.timedelta(days=c.nDaysNotPlayAfter) for d in c.days.all(): firstDay = getDateTimeDay[d.id]-dayBefore lastDay = getDateTimeDay[d.id]+dayAfter compDays[c.id] += [ d2 for d2 in playDays if firstDay<= getDateTimeDay[d2] <= lastDay ] compDays[c.id] = list(set(compDays[c.id])) for t in c.teams.all(): for d in compDays[c.id]: competitionBlocks.append((t.id,d)) for tp in ["H", "A"]: isBlocked[ (d, t.id, tp)]=True isBlockedTags[ (d, t.id, tp)].append(c.name) if sc.season.useFeatureKickOffTime: currentSolution= [ (int(sl[1]),int(sl[2]),int(sl[3]),int(sl[0]),sl[4]) for sl in sc.solutionlist() if len(sl)>4] else: currentSolution= [ (int(sl[1]),int(sl[2]),int(sl[3]),int(sl[0])) for sl in sc.solutionlist() if len(sl)>3] currentSolutionOfDay = { d.id: [] for d in days } currentSolutionInRound = { (t,r): "" for t in realteams for r in rounds } currentSolutionAtDay = { (t,d.id): "" for t in realteams for d in days } currentSolutionTimeAtDay = { (t,d.id): "" for t in realteams for d in days } currentSolutionTimeAtDayCode = { (t,d.id): "" for t in realteams for d in days } currentSolutionDayOfTeamRound = { (t,r) : 0 for t in realteams for r in rounds } games={} shortGames = defaultdict(dict) violations =[] fullHaName = {"H":"Home", "A":"Away"} for cs in currentSolution: (t1,t2,r,d)=(cs[0],cs[1],cs[2],cs[3]) if d in currentSolutionOfDay.keys(): currentSolutionInRound[(t1,r)]="H" currentSolutionInRound[(t2,r)]="A" currentSolutionAtDay[(t1,d)]="H" currentSolutionAtDay[(t2,d)]="A" currentSolutionOfDay[d].append((t1,t2,r)) currentSolutionDayOfTeamRound[(t1,r)]= d currentSolutionDayOfTeamRound[(t2,r)]= d if sc.season.useFeatureKickOffTime : currentSolutionTimeAtDay[(t1,d)]=cs[4] currentSolutionTimeAtDay[(t2,d)]=cs[4] ts = TimeSlot.objects.filter(season=sc.season,name=cs[4]).first() if ts: currentSolutionTimeAtDayCode[(t1,d)]=ts.code currentSolutionTimeAtDayCode[(t2,d)]=ts.code for t3 in [t1,t2]: color = "red" if isBlocked[ (d, t3, currentSolutionAtDay[(t3,d)])] else "" games[ str(d)+"_"+str(t3)]= (currentSolutionAtDay[(t3,d)]+currentSolutionTimeAtDayCode[(t3,d)] , color) shortGames[d][t3] = t_short[t1] +"-"+ t_short[t2] if color=="red": violations.append( ( getTeamById[t3], getDay[d] , fullHaName[currentSolutionAtDay[(t3,d)]] , currentSolutionTimeAtDay[(t3,d)] , ", ".join(isBlockedTags[(d,t3,currentSolutionAtDay[(t3,d)])]) )) for bl in blockings: if bl.tag and bl.tag.blocking_weight <0.0 and currentSolutionAtDay[(bl.team.id,bl.day.id)]!="H": violations.append( ( getTeamById[bl.team.id], getDay[bl.day.id] , "Home" , "" , bl.tag.name )) redStripes = [] missingBreaks = [] for bl in breaks : for t in realteams: if currentSolutionInRound[(t,bl['round1'])]== currentSolutionInRound[(t,bl['round2'])] and currentSolutionInRound[(t,bl['round1'])] in ["H","A"]: redStripes.append(str(currentSolutionDayOfTeamRound[(t,bl['round1'])])+'_'+str(t) +'__'+str(currentSolutionDayOfTeamRound[(t,bl['round2'])])+'_'+str(t)) else: missingBreaks.append(t) if showSolution=="0": games=[] redStripes=[] violations=[] shortGames={} context = { # 'blockings1' : blockings1, # 'games' : games, # 'shortGames' : shortGames, 'violations' : violations, # 'firstTeams' : firstTeams, # 'blockings' : blockings, # 'stadiumBlocks' : stadiumBlocks, # 'competitionBlocks' : competitionBlocks, # 'groups' : groups, # 'days' : daysSorted, # 'teams' : teams, # 'comments': blockComment, # 'redStripes': redStripes, # 'tags': Tag.objects.filter(season=sc.season).exclude(blocking_weight=0), # 'stadiums' : stadiums, # 'stadiumblockings' : stadiumblockings, # 'showStadiums' : showSolution=="0", 'missingBreaks': missingBreaks, } return context class Draw_Simulator: def __init__(self,algorithm, opponent_func, html_output, use_db=False): self.pots = ['D','C','B','A'] if use_db: scenario_id = 9529 scenario = Scenario.objects.get(id=scenario_id) self.basepots = { pot : [ { 'id': team.id, 'pot': pot, 'name': team.name, 'country': team.countryObj.name, 'coeff': team.attractivity, 'lat': team.latitude, 'lon': team.longitude, } for team in Team.objects.filter(season=scenario.season,pot=pot_n+1,active=True) ] for pot_n,pot in enumerate(self.pots) } df_rank = pd.read_csv('rankings_2.0.csv') for pot in self.basepots: for team in self.basepots[pot]: ranking = df_rank[df_rank['TEAM'] == team['name']].iloc[0] team['coeff'] = ranking['RANK'] else: self.basepots = { 'A': [ {'id': 0, 'pot': 'A', 'name': 'Rögle Ängelholm', 'country': 'Sweden'}, {'id': 1, 'pot': 'A', 'name': 'Färjestad Karlstad', 'country': 'Sweden'}, {'id': 2, 'pot': 'A', 'name': 'EV Zug', 'country': 'Switzerland'}, {'id': 3, 'pot': 'A', 'name': 'Eisbären Berlin', 'country': 'Germany'}, {'id': 4, 'pot': 'A', 'name': 'Tappara Tampere', 'country': 'Finland'}, {'id': 5, 'pot': 'A', 'name': 'Oceláři Třinec', 'country': 'Czech Republic'}, ], 'B': [ {'id': 6, 'pot': 'B', 'name': 'Red Bull Salzburg', 'country': 'Austria'}, {'id': 7, 'pot': 'B', 'name': 'Lulea Hockey', 'country': 'Sweden'}, {'id': 8, 'pot': 'B', 'name': 'Fribourg-Gottéron', 'country': 'Switzerland'}, {'id': 9, 'pot': 'B', 'name': 'Red Bull Munich', 'country': 'Germany'}, {'id': 10, 'pot': 'B', 'name': 'Jukurit Mikkeli', 'country': 'Finland'}, {'id': 11, 'pot': 'B', 'name': 'Mountfield HK', 'country': 'Czech Republic'}, ], 'C': [ {'id': 12, 'pot': 'C', 'name': 'VS Villach', 'country': 'Austria'}, {'id': 13, 'pot': 'C', 'name': 'ZSC Lions Zürich', 'country': 'Switzerland'}, {'id': 14, 'pot': 'C', 'name': 'Grizzlys Wolfsburg', 'country': 'Germany'}, {'id': 15, 'pot': 'C', 'name': 'Ilves Tampere', 'country': 'Finland'}, {'id': 16, 'pot': 'C', 'name': 'Sparta Prague', 'country': 'Czech Republic'}, {'id': 17, 'pot': 'C', 'name': 'Fehérvár AV19', 'country': 'Austria'}, ], 'D': [ {'id': 18, 'pot': 'D', 'name': 'Belfast Giants', 'country': 'United Kingdom'}, {'id': 19, 'pot': 'D', 'name': 'Grenoble', 'country': 'France'}, {'id': 20, 'pot': 'D', 'name': 'GKS Katowice', 'country': 'Poland'}, {'id': 21, 'pot': 'D', 'name': 'Aalborg Pirates', 'country': 'Denmark'}, {'id': 22, 'pot': 'D', 'name': 'Stavanger Oilers', 'country': 'Norway'}, {'id': 23, 'pot': 'D', 'name': 'Slovan Bratislava', 'country': 'Slovakia'}, ] } df_rank = pd.read_csv('rankings.csv') df_geo = pd.read_csv('geocoord.csv') for pot in self.basepots: for team in self.basepots[pot]: ranking = df_rank[df_rank['TEAM'] == team['name']].iloc[0] team['coeff'] = ranking['RANK'] geo = df_geo[df_geo['TEAM'] == team['name']].iloc[0] team['lat'] = geo['LAT'] team['lon'] = geo['LON'] self.groups = range(1, len(self.basepots[self.pots[0]])+1) self.empty_groups = { g: {b: None for b in self.pots} for g in self.groups } teams = [] id = 0 for _, plist in self.basepots.items(): for team in plist: teams.append(team) id += 1 self.teams = teams self.countries = set([t['country'] for t in teams]) self.teams_by_country = { c: [v for v in teams if v['country'] == c] for c in self.countries } self.distance_matrix = { (t1['id'],t2['id']): Draw_Simulator.distanceInKmByGPS(t1['lat'],t1['lon'],t2['lat'],t2['lon']) for t1 in self.teams for t2 in self.teams } self.opponent_func = opponent_func self.opponents, self.homeGames, self.awayGames = opponent_func(self) self.algorithm = algorithm self.html_output = html_output @staticmethod def distanceInKmByGPS(lat1, lon1, lat2, lon2): def degreesToRadians(degrees): return degrees * pi / 180 earthRadiusKm = 6371 dLat = degreesToRadians(lat2-lat1) dLon = degreesToRadians(lon2-lon1) lat1 = degreesToRadians(lat1) lat2 = degreesToRadians(lat2) a = sin(dLat/2) * sin(dLat/2) + sin(dLon/2) * \ sin(dLon/2) * cos(lat1) * cos(lat2) c = 2 * atan2(sqrt(a), sqrt(1-a)) return int(earthRadiusKm * c) @staticmethod def heatmap_color_for(value): r = 255 g = 255 if not value: return "rgb(255,255,255)" if value == 0: return "rgb(255,255,255)" 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})" def groups_6_4(self): """ 6 groups of 4 teams """ opponents = defaultdict(lambda: []) homeGames = defaultdict(lambda:[]) awayGames = defaultdict(lambda:[]) for i, g in enumerate(self.groups): for p in self.pots: other_pots = [k for k in self.pots if k != p] for l in other_pots: opponents[g, p].append((g, l)) homeGames[g, p].append((g, l)) awayGames[g, l].append((g, p)) return opponents, homeGames, awayGames def groups_3_8(self): """ 3 groups of 8 teams """ opponents = defaultdict(lambda: []) homeGames = defaultdict(lambda:[]) awayGames = defaultdict(lambda:[]) for i, g in enumerate(self.groups): if g % 2 == 0: other_group = self.groups[i-1] else: other_group = self.groups[i+1] for p in self.pots: other_pots = [k for k in self.pots if k != p] for l in other_pots: opponents[g, p].append((g, l)) opponents[g, p].append((other_group, l)) if p == 'A' and l in ['B','C','D']: awayGames[g, p].append((g, l)) homeGames[g, l].append((g, p)) homeGames[g, p].append((other_group, l)) awayGames[other_group, l].append((g, p)) if p == 'B' and l in ['C','D']: awayGames[g, p].append((g, l)) homeGames[g, l].append((g, p)) homeGames[g, p].append((other_group, l)) awayGames[other_group, l].append((g, p)) if p == 'C' and l in ['D']: awayGames[g, p].append((g, l)) homeGames[g, l].append((g, p)) homeGames[g, p].append((other_group, l)) awayGames[other_group, l].append((g, p)) return opponents, homeGames, awayGames def groups_3_8_stephan(self): """ 3 groups of 8 teams - stephan """ opponents = defaultdict(lambda: []) homeGames = defaultdict(lambda:[]) awayGames = defaultdict(lambda:[]) for i,g in enumerate(self.groups): if g % 2 == 0: other_group = self.groups[i-1] else: other_group = self.groups[i+1] for i2,p in enumerate(self.pots): other_pots = [k for k in self.pots] for j2,l in enumerate(other_pots): if p == l: opponents[g, p].append((other_group, l)) elif i2+j2 == 3: opponents[g, p].append((g, l)) else: opponents[g, p].append((g, l)) opponents[g, p].append((other_group, l)) if g % 2 == 0: awayGames[g, 'A'] += [(g, 'D'),(g, 'B'),(g, 'C')] homeGames[g, 'A'] += [(other_group, 'A'),(other_group, 'B'),(other_group, 'C')] awayGames[g, 'B'] += [(other_group, 'A'),(g, 'C'),(g, 'D')] homeGames[g, 'B'] += [(g, 'A'),(other_group, 'B'),(other_group, 'D')] awayGames[g, 'C'] += [(other_group, 'A'),(other_group, 'C'),(g, 'D')] homeGames[g, 'C'] += [(g, 'B'),(other_group, 'D'),(g, 'A')] awayGames[g, 'D'] += [(other_group, 'D'),(other_group, 'C'),(other_group, 'B')] homeGames[g, 'D'] += [(g, 'A'),(g, 'B'),(g, 'C')] else: awayGames[g, 'A'] += [(other_group, 'A'),(g, 'B'),(g, 'C')] homeGames[g, 'A'] += [(g, 'D'),(other_group, 'B'),(other_group, 'C')] awayGames[g, 'B'] += [(other_group, 'B'),(other_group, 'A'),(g, 'D')] homeGames[g, 'B'] += [(g, 'A'),(g, 'C'),(other_group, 'D')] awayGames[g, 'C'] += [(g, 'B'),(other_group, 'A'),(g, 'D')] homeGames[g, 'C'] += [(g, 'A'),(other_group, 'C'),(other_group, 'D')] awayGames[g, 'D'] += [(g, 'A'),(other_group, 'C'),(other_group, 'B')] homeGames[g, 'D'] += [(g, 'B'),(g, 'C'),(other_group, 'D')] # if p == 'A': # if l == 'A': # awayGames[g, p].append((g, l)) # if l in ['B','C']: # awayGames[g, p].append((g, l)) # homeGames[g, l].append((g, p)) # homeGames[g, p].append((other_group, l)) # awayGames[other_group, l].append((g, p)) # if p == 'B' and l in ['C','D']: # awayGames[g, p].append((g, l)) # homeGames[g, l].append((g, p)) # homeGames[g, p].append((other_group, l)) # awayGames[other_group, l].append((g, p)) # if p == 'C' and l in ['D']: # awayGames[g, p].append((g, l)) # homeGames[g, l].append((g, p)) # homeGames[g, p].append((other_group, l)) # awayGames[other_group, l].append((g, p)) return opponents, homeGames, awayGames def groups_2_12_martin(self): """ 2 groups of 12 teams """ opponents = defaultdict(lambda: []) homeGames = defaultdict(lambda:[]) awayGames = defaultdict(lambda:[]) for i, g in enumerate(self.groups): half = len(self.groups)//2 if g <= half: left_group = self.groups[:half][i-1] right_group = self.groups[:half][(i+1) % half] else: left_group = self.groups[half:][(i-half-1)] right_group = self.groups[half:][(i-half+1) % half] for p in self.pots: other_pots = [k for k in self.pots if k != p] for l in other_pots: opponents[g, p].append((right_group, l)) awayGames[g, p].append((right_group, l)) opponents[g, p].append((left_group, l)) homeGames[g, p].append((left_group, l)) return opponents, homeGames, awayGames def groups_2_12_stephan(self): """ 2 groups of 12 teams """ opponents = defaultdict(lambda: []) homeGames = defaultdict(lambda:[]) awayGames = defaultdict(lambda:[]) for i, g in enumerate(self.groups): half = len(self.groups)//2 if g <= half: left_group = self.groups[:half][i-1] right_group = self.groups[:half][(i+1) % half] else: left_group = self.groups[half:][(i-half-1)] right_group = self.groups[half:][(i-half+1) % half] for p in self.pots: other_pots = [k for k in self.pots if k != p] for l in other_pots: opponents[g, p].append((g, l)) if p == "A" and l in ['B', 'C']: opponents[g, p].append((right_group, l)) awayGames[g, p].append((g, l)) homeGames[g, p].append((right_group, l)) elif p == "A" and l in ['D']: opponents[g, p].append((left_group, l)) homeGames[g, p].append((g, l)) awayGames[g, p].append((left_group, l)) elif p == "B" and l in ['C', 'D']: opponents[g, p].append((right_group, l)) awayGames[g, p].append((g, l)) homeGames[g, p].append((right_group, l)) elif p == "B" and l in ['A']: opponents[g, p].append((left_group, l)) awayGames[g, p].append((left_group, l)) homeGames[g, p].append((g, l)) elif p == "C" and l in ['D']: opponents[g, p].append((right_group, l)) awayGames[g, p].append((g, l)) homeGames[g, p].append((right_group, l)) elif p == "C" and l in ['A', 'B']: opponents[g, p].append((left_group, l)) awayGames[g, p].append((left_group, l)) homeGames[g, p].append((g, l)) elif p == "D" and l in ['A']: opponents[g, p].append((right_group, l)) homeGames[g, p].append((right_group, l)) awayGames[g, p].append((g, l)) elif p == "D" and l in ['B', 'C']: opponents[g, p].append((left_group, l)) awayGames[g, p].append((left_group, l)) homeGames[g, p].append((g, l)) return opponents, homeGames, awayGames def groups_1_24_martin(self): """ 1 groups of 24 teams """ opponents = defaultdict(lambda: []) homeGames = defaultdict(lambda:[]) awayGames = defaultdict(lambda:[]) for i, g in enumerate(self.groups): left_group = self.groups[i-1] right_group = self.groups[(i+1) % len(self.groups)] for p in self.pots: other_pots = [k for k in self.pots if k != p] for l in other_pots: opponents[g, p].append((right_group, l)) awayGames[g, p].append((right_group, l)) opponents[g, p].append((left_group, l)) homeGames[g, p].append((left_group, l)) return opponents, homeGames, awayGames def groups_1_24_stephan(self): """ 1 groups of 24 teams """ opponents = defaultdict(lambda: []) homeGames = defaultdict(lambda:[]) awayGames = defaultdict(lambda:[]) for i, g in enumerate(self.groups): left_group = self.groups[i-1] right_group = self.groups[(i+1) % len(self.groups)] for p in self.pots: other_pots = [k for k in self.pots if k != p] for l in other_pots: opponents[g, p].append((g, l)) if p == "A" and l in ['B', 'C']: opponents[g, p].append((right_group, l)) awayGames[g, p].append((g, l)) homeGames[g, p].append((right_group, l)) elif p == "A" and l in ['D']: opponents[g, p].append((left_group, l)) homeGames[g, p].append((g, l)) awayGames[g, p].append((left_group, l)) elif p == "B" and l in ['C', 'D']: opponents[g, p].append((right_group, l)) awayGames[g, p].append((g, l)) homeGames[g, p].append((right_group, l)) elif p == "B" and l in ['A']: opponents[g, p].append((left_group, l)) awayGames[g, p].append((left_group, l)) homeGames[g, p].append((g, l)) elif p == "C" and l in ['D']: opponents[g, p].append((right_group, l)) awayGames[g, p].append((g, l)) homeGames[g, p].append((right_group, l)) elif p == "C" and l in ['A', 'B']: opponents[g, p].append((left_group, l)) awayGames[g, p].append((left_group, l)) homeGames[g, p].append((g, l)) elif p == "D" and l in ['A']: opponents[g, p].append((right_group, l)) homeGames[g, p].append((right_group, l)) awayGames[g, p].append((g, l)) elif p == "D" and l in ['B', 'C']: opponents[g, p].append((left_group, l)) awayGames[g, p].append((left_group, l)) homeGames[g, p].append((g, l)) return opponents, homeGames, awayGames def check_feasibility(self, fixed_groups, nSim): model_time = time.time() sol_dict = { g: {b: None for b in self.pots} for g in self.groups } if self.algorithm == 'SAT': model_sat = cp_model.CpModel() x_sat = {} for g in self.groups: for t in self.teams: t_id = t['id'] x_sat[t_id, g] = model_sat.NewBoolVar(f'var_{t_id}_{g}') # one group for each team for t in self.teams: model_sat.AddExactlyOne(x_sat[t['id'], g] for g in self.groups) # one team from each pot for g in self.groups: for p in self.pots: model_sat.AddExactlyOne(x_sat[t['id'], g] for t in self.teams if t['pot'] == p) # no country conflicts for c in self.countries: # print(c) for i, t1 in enumerate(self.teams_by_country[c]): for t2 in self.teams_by_country[c][i+1:]: for (g1, p1), other_games in self.opponents.items(): if p1 == t1['pot']: for (g2, p2) in other_games: if p2 == t2['pot']: model_sat.AddAtMostOne( x_sat[t1['id'], g1], x_sat[t2['id'], g2]) # add fixations nFixed = 0 for g in self.groups: for p in self.pots: if fixed_groups[g][p]: nFixed += 1 model_sat.Add(x_sat[fixed_groups[g][p]['id'], g] >= 1) if self.algorithm == 'MIP': model_mip = LpProblem( "Xpress", LpMinimize) x_mip = {} for g in self.groups: for t in self.teams: t_id = t['id'] x_mip[t_id, g] = LpVariable(f'var_{t_id}_{g}', lowBound=0, upBound=1, cat=LpContinuous) # one group for each team for t in self.teams: model_mip += lpSum([x_mip[t['id'], g] for g in self.groups]) == 1 # one team from each pot for g in self.groups: for p in self.pots: model_mip += lpSum([x_mip[t['id'], g] for t in self.teams if t['pot'] == p]) == 1 # no country conflicts for c in self.countries: # print(c) for i, t1 in enumerate(self.teams_by_country[c]): for t2 in self.teams_by_country[c][i+1:]: for (g1, p1), other_games in self.opponents.items(): if p1 == t1['pot']: for (g2, p2) in other_games: if p2 == t2['pot']: model_mip += x_mip[t1['id'], g1] + x_mip[t2['id'], g2] <= 1 # add fixations nFixed = 0 for g in self.groups: for p in self.pots: if fixed_groups[g][p]: nFixed += 1 model_mip += x_mip[fixed_groups[g][p]['id'], g] >= 1 model_mip += lpSum([x_mip[key] for key in x_mip.keys()]) if self.algorithm == 'XP': model_xp = xp.problem(name='Xpress', sense=xp.minimize) x_xp = {} for g in self.groups: for t in self.teams: t_id = t['id'] x_xp[t_id, g] = xp.var(ub=10, vartype=xp.integer) model_xp.addVariable(x_xp) # one group for each team for t in self.teams: model_xp.addConstraint(xp.Sum([x_xp[t['id'], g] for g in self.groups]) == 1) # one team from each pot for g in self.groups: for p in self.pots: model_xp.addConstraint( xp.Sum([x_xp[t['id'], g] for t in self.teams if t['pot'] == p]) == 1) # no country conflicts for c in self.countries: for i, t1 in enumerate(self.teams_by_country[c]): for t2 in self.teams_by_country[c][i+1:]: for (g1, p1), other_games in self.opponents.items(): if p1 == t1['pot']: for (g2, p2) in other_games: if p2 == t2['pot']: model_xp.addConstraint( x_xp[t1['id'], g1] + x_xp[t2['id'], g2] <= 1) # add fixations nFixed = 0 for g in self.groups: for p in self.pots: if fixed_groups[g][p]: nFixed += 1 model_xp.addConstraint(x_xp[fixed_groups[g][p]['id'], g] >= 1) model_xp.setObjective(xp.Sum([x_xp[key] for key in x_xp.keys()]), sense=xp.minimize) if self.algorithm == 'SAT': solver = cp_model.CpSolver() start_time = time.time() status = solver.Solve(model_sat) comp_time = time.time()-start_time model_time = time.time()-model_time-comp_time # solver.parameters.enumerate_all_solutions = True # solver.parameters.log_search_progress = True if status == cp_model.OPTIMAL or status == cp_model.FEASIBLE: if self.html_output: for g in self.groups: for p in self.pots: for t in self.basepots[p]: if solver.BooleanValue(x_sat[t['id'], g]): sol_dict[g][p] = t self.html_solution(nSim, sol_dict, fixed_groups) return True, comp_time, model_time, sol_dict else: return False, comp_time, model_time, {} elif self.algorithm == "MIP": # with open ("model2_xpress.txt", "w") as f: # f.write(model_mip.__repr__()) start_time = time.time() model_mip.solve(PULP_CBC_CMD(msg=0)) comp_time = time.time()-start_time model_time = time.time()-model_time-comp_time if model_mip.status == 1: if self.html_output: for g in self.groups: for p in self.pots: for t in self.basepots[p]: if x_mip[t['id'], g].value() > 0: sol_dict[g][p] = t self.html_solution(nSim, sol_dict, fixed_groups) return True, comp_time, model_time, sol_dict else: return False, comp_time, model_time, {} elif self.algorithm == "XP": # with open ("model2_xpress.txt", "w") as f: # f.write(model_mip.__repr__()) start_time = time.time() model_xp.solve() comp_time = time.time()-start_time model_time = time.time()-model_time-comp_time if model_xp.getProbStatus() == 6: if self.html_output: for g in self.groups: for p in self.pots: for t in self.basepots[p]: if model_xp.getSolution(x_xp[t['id'], g]) > 0: sol_dict[g][p] = t self.html_solution(nSim, sol_dict, fixed_groups) return True, comp_time, model_time, sol_dict else: return False, comp_time, model_time, {} def team_travel(self,team,sol): return 0 def team_coefficients(self,team,sol): return 0 def simulate(self, nTimes): if nTimes < 1: return None tmp_stats = defaultdict(lambda: {}) for n in range(nTimes): print(f"{self.opponent_func.__name__} - Simulation {n}") ttt =time.time() sol_dict = { g: {b: None for b in self.pots} for g in self.groups } pots = copy.deepcopy(self.basepots) infeasible = False conflicts = defaultdict(lambda: 0) total_time = 0 total_model_time = 0 total_computations = 0 feasible = False for p in self.pots: pot = pots[p] random.shuffle(pot) while (pot): r = random.choice(pot) for g in self.groups: if sol_dict[g][p]: continue else: sol_dict[g][p] = r feasible, comptime, modeltime, _ = self.check_feasibility( sol_dict, nSim=n) total_computations += 1 total_time += comptime total_model_time += modeltime if feasible: feasible = True break else: # print("\tCONFLICT: skipping group {} for team {}".format(g,r)) conflicts[p] += 1 sol_dict[g][p] = None if not feasible: infeasible = True break pot.remove(r) travel = defaultdict(lambda:0) coefficients = defaultdict(lambda:0) visited_countries = defaultdict(lambda:set({})) if not infeasible: for g in self.groups: for p in self.pots: t1 = sol_dict[g][p] for ag in self.awayGames[g, p]: t2 = sol_dict[ag[0]][ag[1]] travel[t1['id']] += self.distance_matrix[t1['id'],t2['id']] for op in self.opponents[g,p]: t2 = sol_dict[op[0]][op[1]] if self.opponent_func.__name__ == 'groups_6_4': coefficients[t1['id']] += 2*(abs(t1['coeff']-t2['coeff'])) else: coefficients[t1['id']] += abs(t1['coeff']-t2['coeff']) visited_countries[t1['id']].add(t2['country']) blockings, breaks = self.create_schedule(sol_dict, n) tmp_stats[n] = { 'conflicts': conflicts, 'infeasible': infeasible, 'comptime': total_time, 'modeltime': total_model_time, 'total_computations': total_computations, 'travel':travel, 'coefficients':coefficients, 'visited_countries':{t['id']:len(visited_countries[t['id']]) for t in self.teams}, 'blockings':blockings, 'breaks':breaks, } with open(f'json/{self.opponent_func.__name__}_{n}.json', 'w') as f: json.dump(tmp_stats, f, cls=NumpyEncoder) nInfeasible = sum(s['infeasible'] for s in tmp_stats.values()) > 0 nComputation = sum(s['total_computations'] for s in tmp_stats.values()) tComputation = sum(s['comptime'] for s in tmp_stats.values()) conflicts_dict = { p: round(sum(s['conflicts'][p] for s in tmp_stats.values())/nTimes,2) for p in self.pots } conflicts_dict['total'] = round(sum(conflicts_dict[p] for p in self.pots),2) travel_stats = { t['id']: { 'mean': round(np.mean([s['travel'][t['id']] for s in tmp_stats.values()]),2), 'std': round(np.std([s['travel'][t['id']] for s in tmp_stats.values()]),2), 'var': round(np.var([s['travel'][t['id']] for s in tmp_stats.values()]),2), } for t in self.teams } travel_stats['total'] = { 'mean': round(np.mean([travel_stats[t['id']]['mean'] for t in self.teams]),2), 'std': round(np.mean([travel_stats[t['id']]['std'] for t in self.teams]),2), 'var': round(np.mean([travel_stats[t['id']]['var'] for t in self.teams]),2), } coefficient_stats = { t['id']: { 'mean': round(np.mean([s['coefficients'][t['id']] for s in tmp_stats.values()]),2), 'std': round(np.std([s['coefficients'][t['id']] for s in tmp_stats.values()]),2), 'var': round(np.var([s['coefficients'][t['id']] for s in tmp_stats.values()]),2), } for t in self.teams } coefficient_stats['total'] = { 'mean': round(np.mean([coefficient_stats[t['id']]['mean'] for t in self.teams]),2), 'std': round(np.mean([coefficient_stats[t['id']]['std'] for t in self.teams]),2), 'var': round(np.mean([coefficient_stats[t['id']]['var'] for t in self.teams]),2), } visited_countries = { t['id']: { 'mean': round(np.mean([s['visited_countries'][t['id']] for s in tmp_stats.values()]),2), } for t in self.teams } visited_countries['total'] = { 'mean': round(np.mean([visited_countries[t['id']]['mean'] for t in self.teams]),2), } blockings = { t['id']: { 'mean': round(np.mean([s['blockings'][t['id']] for s in tmp_stats.values()]),3), } for t in self.teams } blockings['total'] = { 'sum': round(np.sum([blockings[t['id']]['mean'] for t in self.teams]),3), } breaks = { t['id']: { 'mean': round(np.mean([s['breaks'][t['id']] for s in tmp_stats.values()])*0.5,3), } for t in self.teams } breaks['total'] = { 'sum': round(np.sum([breaks[t['id']]['mean'] for t in self.teams]),3), } stats = { 'nInfeasible':nInfeasible, 'nComputation':nComputation, 'tComputation':tComputation, 'conflicts_dict':conflicts_dict, 'conflicts_dict':conflicts_dict, 'travel_stats':travel_stats, 'coefficient_stats':coefficient_stats, 'visited_countries':visited_countries, 'blockings':blockings, 'breaks':breaks, } return stats def create_schedule(self, sol_dict, nSim): # for g in self.groups: # for p in self.pots: # print(g,p,sol_dict[g][p]['name'],sol_dict[g][p]['country']) # for game in self.homeGames[g, p]: # print("\t",game[0],game[1],sol_dict[game[0]][game[1]]) # for game in self.awayGames[g, p]: # print("\t",game[0],game[1],sol_dict[game[0]][game[1]]) base_scenario_id = 9529 base_scenario = Scenario.objects.get(id=base_scenario_id) scenario = copy_scenario(base_scenario,f" - {self.opponent_func.__name__} - {nSim}") scenario.base_scenario = base_scenario scenario.save() GameRequirement.objects.filter(scenario=scenario).delete() games = [] for g in self.groups: for p in self.pots: # print(g,p,sol_dict[g][p]['name'],sol_dict[g][p]['country']) for game in self.homeGames[g, p]: # print("\t",game[0],game[1],sol_dict[game[0]][game[1]]) games.append(GameRequirement(number=1, scenario=scenario, team1=Team.objects.get(id=sol_dict[g][p]['id']), team2=Team.objects.get(id=sol_dict[game[0]][game[1]]['id']))) # for game in self.awayGames[g, p]: # print("\t",game[0],game[1],sol_dict[game[0]][game[1]]) # games.append(GameRequirement(number=1, scenario=scenario, team1=Team.objects.get(id=sol_dict[game[0]][game[1]]['id']), team2=Team.objects.get(id=sol_dict[g][p]['id']))) GameRequirement.objects.bulk_create(games) s2 = scenario.id user_name = 'md' user_is_staff = True runMode = 'New' localsearch_time = 0 RUN_ENV = 'celery' SOLVER = 'xpress' sol = optimize(task=None, s2=s2, user_name=user_name, user_is_staff=user_is_staff, runMode=runMode, localsearch_time=localsearch_time, RUN_ENV=RUN_ENV, solver=SOLVER) kpis = Availabilities(scenario.id,showSolution=1) blockings = defaultdict(lambda:0) breaks = defaultdict(lambda:0) for v in kpis['violations']: blockings[v[0].id] += 1 for b in kpis['missingBreaks']: breaks[b] += 1 return blockings, breaks def html_solution(self, nSim, sol_dict, fixed_groups): sol = " \ \ " sol += "\n" sol += "\n" sol += "" for g in self.groups: sol += f"" sol += "" sol += "\n" sol += "\n" nFixed = 0 for p in self.pots: sol += f"" for g in self.groups: if fixed_groups[g][p]: color = 'lightgreen' nFixed += 1 else: color = 'lightyellow' tpot = sol_dict[g][p]['pot'] tname = sol_dict[g][p]['name'] tcountry = sol_dict[g][p]['country'] sol += f"" sol += "" sol += "\n" sol += "
{g}
{p}({tpot}){tname}({tcountry})
\n" sol += "


\n" for (g1, p1), other_games in self.opponents.items(): for (g2, p2) in other_games: tpot = sol_dict[g1][p1]['pot'] tname = sol_dict[g1][p1]['name'] tcountry = sol_dict[g1][p1]['country'] sol += f'({tpot}){tname}({tcountry})' sol += " vs " tpot = sol_dict[g2][p2]['pot'] tname = sol_dict[g2][p2]['name'] tcountry = sol_dict[g2][p2]['country'] sol += f'({tpot}){tname}({tcountry})' sol += "
" sol += "
" sol += "
" with open(f'html/{self.algorithm}_{self.opponent_func.__name__}_{nSim}_{nFixed}_sol.html', 'w') as f: f.write(sol) # %% # simulator = Draw_Simulator(algorithm='XP', opponent_func = Draw_Simulator.groups_2_12_stephan, html_output=False) # nSim = 10 # %% funcs = [ # Draw_Simulator.groups_6_4, # Draw_Simulator.groups_3_8, # Draw_Simulator.groups_2_12_martin, # Draw_Simulator.groups_2_12_stephan, Draw_Simulator.groups_1_24_martin, # Draw_Simulator.groups_1_24_stephan, # Draw_Simulator.groups_3_8_stephan, ] scenario_id = 9529 scenario = Scenario.objects.get(id=scenario_id) Scenario.objects.filter(base_scenario=scenario).delete() stats = {} for func in funcs: simulator = Draw_Simulator(algorithm='XP', opponent_func = func, html_output=True,use_db=True) nSim = 4 stats[func.__name__] = simulator.simulate(nSim) # %% sol = " \ \ " sol += "\n" sol += "\n" sol += f"" sol += f"" sol += f"" sol += f"" sol += "" sol += "" for p in simulator.pots: sol += f"" for t in simulator.teams: sol+= f"" sol += "" sol += "" sol += "" sol += "" sol += "" sol += "" sol += "" sol += "" for t in simulator.teams: sol += "" sol += "" sol += "" sol += "" sol += "" sol += "" sol += "" sol += "" sol += "" sol += "" sol += "" for t in simulator.teams: sol += "" sol += "" sol += "" sol += "" sol += "" sol += "\n" sol += "\n" for func in funcs: sol += "" sol += f"" for p in simulator.pots: sol += f"" sol += f"" ttmean = stats[func.__name__]['travel_stats']['total']['mean'] ttstd = stats[func.__name__]['travel_stats']['total']['std'] ctmean = stats[func.__name__]['coefficient_stats']['total']['mean'] ctstd = stats[func.__name__]['coefficient_stats']['total']['std'] sol += f"" sol += f"" sol += f"" sol += f"" sol += f"" sol += f"" sol += f"" for t in simulator.teams: tmean = stats[func.__name__]['travel_stats'][t['id']]['mean'] tstd = stats[func.__name__]['travel_stats'][t['id']]['std'] cmean = stats[func.__name__]['coefficient_stats'][t['id']]['mean'] cstd = stats[func.__name__]['coefficient_stats'][t['id']]['std'] blmean = stats[func.__name__]['blockings'][t['id']]['mean'] brmean = stats[func.__name__]['breaks'][t['id']]['mean'] visited = stats[func.__name__]['visited_countries'][t['id']]['mean'] color = Draw_Simulator.heatmap_color_for(abs(tmean-ttmean)/ttmean) sol += f"" color = Draw_Simulator.heatmap_color_for(abs(tstd-ttstd)/ttstd) sol += f"" color = Draw_Simulator.heatmap_color_for(abs(cmean-ctmean)/ctmean) sol += f"" color = Draw_Simulator.heatmap_color_for(abs(cstd-ctstd)/ctstd) sol += f"" sol += f"" sol += f"" sol += f"" sol += "" sol += "\n" sol += "
n={nSim}ConflictsTotalTeams
{p}{t['name']}
Cfl.Trav.Coe.BlockNo TravelCountr.Trav.Coe.BlockNo TravelCountr.
MSMSMSMS
{func.__name__}{stats[func.__name__]['conflicts_dict'][p]}{stats[func.__name__]['conflicts_dict']['total']}{stats[func.__name__]['travel_stats']['total']['mean']}{stats[func.__name__]['travel_stats']['total']['std']}{stats[func.__name__]['coefficient_stats']['total']['mean']}{stats[func.__name__]['coefficient_stats']['total']['std']}{stats[func.__name__]['blockings']['total']['sum']}{stats[func.__name__]['breaks']['total']['sum']}{stats[func.__name__]['visited_countries']['total']['mean']}{tmean}{tstd}{cmean}{cstd}{blmean}{brmean}{visited}
\n" with open(f'stats.html', 'w') as f: f.write(sol) # %% # %% with open(f'color.html', 'w') as f: table = f"" for i in range(1,11): color = Draw_Simulator.heatmap_color_for(i/10) table += f"" table += f"
{color}
" f.write(table) # %%