# %% import os, sys from dotenv import load_dotenv load_dotenv() # %% if os.environ.get("SERVER", None): PROJECT_PATH = "/home/django/leagues/" else: PROJECT_PATH = "/home/md/Work/ligalytics/leagues_stable/" 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' if os.environ.get("SERVER", None): 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" else: 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"] = {} 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.5.0" os.environ["XPRESS"] = "/opt/xpressmp_9.5.0/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_teams=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, use_chess=False, suffix="", opt_param="", scenario_id=None ): self.chess = use_chess self.blue_groups = [] self.red_groups = [] self.suffix = suffix self.opt_param = opt_param self.scenario_id = scenario_id if self.chess: # basepots {'D': [ # {'id': 47715, 'pot': 'D', 'name': 'Rouen Dragons', 'country': 'France', 'coeff': 2.0, 'lat': 49.443232, 'lon': 1.099971}, # {'id': 47747, 'pot': 'D', 'name': 'Fehérvár AV19', 'country': 'Austria', 'coeff': 3.0, 'lat': 47.1860262, 'lon': 18.4221358}, # {'id': 52169, 'pot': 'D', 'name': 'Sheffield Steelers', 'country': 'United Kingdom', 'coeff': 3.0, 'lat': 53.38112899999999, 'lon': -1.470085}, # {'id': 52170, 'pot': 'D', 'name': 'SønderjyskE Vojens', 'country': 'Denmark', 'coeff': 1.0, 'lat': 55.249489, 'lon': 9.3019649}, # {'id': 52171, 'pot': 'D', 'name': 'Unia Oświęcim', 'country': 'Poland', 'coeff': 1.0, 'lat': 50.0343982, 'lon': 19.2097782}, # {'id': 47741, 'pot': 'D', 'name': 'Storhamar Hamar', 'country': 'Norway', 'coeff': 1.0, 'lat': 60.794442, 'lon': 11.0442983}], 'C': [ # {'id': 52167, 'pot': 'C', 'name': 'KAC Klagenfurt', 'country': 'Austria', 'coeff': 3.0, 'lat': 46.625704, 'lon': 14.3137371}, # {'id': 47742, 'pot': 'C', 'name': 'Växjö Lakers', 'country': 'Sweden', 'coeff': 4.0, 'lat': 56.8790044, 'lon': 14.8058522}, # {'id': 47743, 'pot': 'C', 'name': 'Straubing Tigers', 'country': 'Germany', 'coeff': 4.0, 'lat': 48.8777333, 'lon': 12.5801538}, # {'id': 47755, 'pot': 'C', 'name': 'Sparta Prague', 'country': 'Czechia', 'coeff': 4.0, 'lat': 50.0755381, 'lon': 14.4378005}, # {'id': 52168, 'pot': 'C', 'name': 'Lausanne HC', 'country': 'Switzerland', 'coeff': 3.0, 'lat': 46.5196535, 'lon': 6.6322734}, # {'id': 47737, 'pot': 'C', 'name': 'Lahti Pelicans', 'country': 'Finland', 'coeff': 2.0, 'lat': 60.9826749, 'lon': 25.6612096}], 'B': [ # {'id': 52166, 'pot': 'B', 'name': 'Pinguins Bremerhaven', 'country': 'Germany', 'coeff': 4.0, 'lat': 53.5395845, 'lon': 8.5809424}, # {'id': 47761, 'pot': 'B', 'name': 'Red Bull Salzburg', 'country': 'Austria', 'coeff': 3.0, 'lat': 47.80949, 'lon': 13.05501}, # {'id': 47724, 'pot': 'B', 'name': 'Ilves Tampere', 'country': 'Finland', 'coeff': 4.0, 'lat': 61.4977524, 'lon': 23.7609535}, # {'id': 47735, 'pot': 'B', 'name': 'Dynamo Pardubice', 'country': 'Czechia', 'coeff': 4.0, 'lat': 50.0343092, 'lon': 15.7811994}, # {'id': 47740, 'pot': 'B', 'name': 'Färjestad Karlstad', 'country': 'Sweden', 'coeff': 4.0, 'lat': 59.4002601, 'lon': 13.5009352}, # {'id': 47717, 'pot': 'B', 'name': 'Fribourg-Gottéron', 'country': 'Switzerland', 'coeff': 4.0, 'lat': 46.8064773, 'lon': 7.1619719}], 'A': [ # {'id': 47721, 'pot': 'A', 'name': 'Eisbären Berlin', 'country': 'Germany', 'coeff': 4.0, 'lat': 52.5200066, 'lon': 13.404954}, # {'id': 47719, 'pot': 'A', 'name': 'ZSC Lions Zurich', 'country': 'Switzerland', 'coeff': 4.0, 'lat': 47.4124497, 'lon': 8.5578995}, # {'id': 47756, 'pot': 'A', 'name': 'Oceláři Třinec', 'country': 'Czechia', 'coeff': 4.0, 'lat': 49.677631, 'lon': 18.6707901}, # {'id': 47757, 'pot': 'A', 'name': 'Skellefteå AIK', 'country': 'Sweden', 'coeff': 4.0, 'lat': 64.750244, 'lon': 20.950917}, # {'id': 47725, 'pot': 'A', 'name': 'Tappara Tampere', 'country': 'Finland', 'coeff': 4.0, 'lat': 61.4977524, 'lon': 23.7609535}, # {'id': 47733, 'pot': 'A', 'name': 'Genève-Servette', 'country': 'Switzerland', 'coeff': 4.0, 'lat': 46.2043907, 'lon': 6.1431577}]} # self.blue_teams = ['Sheffield Steelers', 'Fribourg-Gottéron', 'ZSC Lions Zurich'] # self.red_teams = ['Sparta Prague'] self.blue_teams = [ 'Genève-Servette','Eisbären Berlin','Sheffield Steelers','ZSC Lions Zurich','Fribourg-Gottéron', ] self.red_teams = [ 'Ilves Tampere','Sparta Prague','Tappara Tampere', ] else: self.blue_teams = [] self.red_teams = [] self.pots = ["D", "C", "B", "A"] if use_db: scenario = Scenario.objects.get(id=self.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]: try: ranking = df_rank[df_rank["TEAM"] == team["name"]].iloc[0] team["coeff"] = ranking["RANK"] except: team["coeff"] = 0 self.blue_teams = [t.id for t in Team.objects.filter(season=scenario.season,name__in=self.blue_teams)] self.red_teams = [t.id for t in Team.objects.filter(season=scenario.season,name__in=self.red_teams)] 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_chess(self): return self.groups_1_24() def groups_1_24(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 ) # no more than 2 teams from same country in one group # for c in self.countries: # for g in self.groups: # model_xp.addConstraint( # xp.Sum( # [x_xp[t["id"], g] for t in self.teams if t["country"] == c] # ) # <= 2 # ) if self.chess: # print("BLUE",self.blue_groups) model_xp.addConstraint( xp.Sum(x_xp[t, g] for t in self.red_teams for g in self.blue_groups) <= 0 ) # print("RED",self.red_groups) model_xp.addConstraint( xp.Sum(x_xp[t, g] for t in self.blue_teams for g in self.red_groups) <= 0 ) # do not play other countries more than 2 times if self.opt_param == "max_2": for t1 in self.teams: for c in self.countries: for (g1, p1), opponents in self.opponents.items(): if p1 == t1['pot']: model_xp.addConstraint( xp.Sum([x_xp[t2['id'], g2] for (g2, p2) in opponents for t2 in self.teams if p2 == t2['pot'] and t2['country'] == c]) <= 2) # print(t1['name'],t1['country'],t1['pot'],[t2['name'] for (g2, p2) in awayGames for t2 in self.teams if p2 == t2['pot'] and t2['country'] == c]) # for (g2, p2) in awayGames: # if p2 == t2['pot']: # model_xp.addConstraint( # x_xp[t1['id'], g1] + x_xp[t2['id'], g2] <= 1) # # model_xp.addConstraint( # xp.Sum([x_xp[t['id'], g] for t in self.teams if t['country'] == c]) <= 2) # for t in self.teams: # for c in ['Finland']: # for t2 in self.teams_by_country[c]: # for (g1, p1), awayGames in self.awayGames.items(): # if p1 == t1['pot']: # for (g2, p2) in awayGames: # if p2 == t2['pot']: # print(t['name'],t['country'], t2['name'], t2['country']) # model_xp.addConstraint( # xp.Sum([x_xp[t2['id'], g] for (g2, p2) in awayGames]) <= 3) # 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) # print(f"\tFixed {fixed_groups[g][p]['name']}, {fixed_groups[g][p]['country']} in group {g}") 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 # print("STATUS",model_xp.getProbStatus(),model_xp.getProbStatusString()) 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): tt = time.time() if nTimes < 1: return None tmp_stats = defaultdict(lambda: {}) for n in range(nTimes): print( f"{self.opponent_func.__name__} - {self.opt_param} - Simulation {n} - in {time.time()-tt}" ) 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 self.blue_groups = [] self.red_groups = [] 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: # print(f"Trying to add {r['name']} to group {g}") sol_dict[g][p] = r feasible, comptime, modeltime, _ = self.check_feasibility( sol_dict, nSim=n ) # print("\tFeasible:", feasible) total_computations += 1 total_time += comptime total_model_time += modeltime if feasible: feasible = True if self.chess and not self.blue_groups: if r["id"] in self.blue_teams: self.blue_groups = ( [1, 3, 5] if g % 2 == 1 else [2, 4, 6] ) self.red_groups = ( [2, 4, 6] if g % 2 == 1 else [1, 3, 5] ) elif r["id"] in self.red_teams: self.blue_groups = ( [2, 4, 6] if g % 2 == 1 else [1, 3, 5] ) self.red_groups = ( [1, 3, 5] if g % 2 == 1 else [2, 4, 6] ) 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({})) visited_finland = defaultdict(lambda: 0) travel_finland = defaultdict(lambda: 0) 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"]] if t2["country"] == "Switzerland": travel_finland[t1["id"]] += 1 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"]) if t2["country"] == "Switzerland": visited_finland[t1["id"]] += 1 else: print("INFEASIBLE") exit() blockings, breaks = self.create_schedule(sol_dict, n) # blockings = defaultdict(lambda:0) # breaks = defaultdict(lambda:0) 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, "visited_finland": visited_finland, "travel_finland": travel_finland, } 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 ), } visited_finland = { t["id"]: { "sum": np.sum( [ 1 for s in tmp_stats.values() if s["visited_finland"][t["id"]] >= 3 ] ), } for t in self.teams } visited_finland["total"] = { "sum": np.sum([visited_finland[t["id"]]["sum"] for t in self.teams]), } travel_finland = { t["id"]: { "sum": np.sum( [1 for s in tmp_stats.values() if s["travel_finland"][t["id"]] >= 3] ), } for t in self.teams } travel_finland["total"] = { "sum": np.sum([travel_finland[t["id"]]["sum"] for t in self.teams]), } 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, "visited_finland": visited_finland, "travel_finland": travel_finland, "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 = 13020 base_scenario = Scenario.objects.get(id=base_scenario_id) scenario = copy_scenario( base_scenario, f" - {self.opponent_func.__name__} - {self.opt_param} - {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: if g in self.blue_groups: color = "blue" elif g in self.red_groups: color = "red" else: color = "white" 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" if sol_dict[g][p]["id"] in self.blue_teams: text_color = "blue" elif sol_dict[g][p]["id"] in self.red_teams: text_color = "red" else: text_color = "black" 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 += "
" if nFixed == 24: with open( f"html/{self.algorithm}_{self.opponent_func.__name__}_{self.opt_param}_{nSim}_{nFixed}_{self.suffix}_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_1_24, "free"), (Draw_Simulator.groups_1_24_chess, "free"), # (Draw_Simulator.groups_1_24, "max_2"), # (Draw_Simulator.groups_1_24_chess, "max_2"), # Draw_Simulator.groups_2_12_martin, # Draw_Simulator.groups_2_12_stephan, # Draw_Simulator.groups_1_24_stephan, # Draw_Simulator.groups_3_8_stephan, ] scenario_id = 13020 scenario = Scenario.objects.get(id=scenario_id) # Scenario.objects.filter(base_scenario=scenario).delete() Scenario.objects.filter(season=scenario.season).exclude(id=scenario_id).delete() filename = "worst_case" stats = {} for (func,opt_param) in funcs: if func == Draw_Simulator.groups_1_24_chess: simulator = Draw_Simulator( algorithm="XP", opponent_func=func, html_output=True, use_db=True, use_chess=True, suffix=filename, opt_param=opt_param, scenario_id=scenario_id, ) else: simulator = Draw_Simulator( algorithm="XP", opponent_func=func, html_output=True, use_db=True, suffix=filename, opt_param=opt_param, scenario_id=scenario_id, ) nSim = 100 stats[(func.__name__,opt_param)] = 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 += "" sol += "" sol += "" for t in simulator.teams: sol += "" sol += "" 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,opt_param) in funcs: sol += "" sol += f"" for p in simulator.pots: sol += f"" sol += f"" ttmean = stats[(func.__name__,opt_param)]["travel_stats"]["total"]["mean"] ttstd = stats[(func.__name__,opt_param)]["travel_stats"]["total"]["std"] ctmean = stats[(func.__name__,opt_param)]["coefficient_stats"]["total"]["mean"] ctstd = stats[(func.__name__,opt_param)]["coefficient_stats"]["total"]["std"] sol += f"" sol += f"" sol += f"" sol += f"" sol += f"" sol += f"" sol += f"" sol += f"" sol += f"" for t in simulator.teams: tmean = stats[(func.__name__,opt_param)]["travel_stats"][t["id"]]["mean"] tstd = stats[(func.__name__,opt_param)]["travel_stats"][t["id"]]["std"] cmean = stats[(func.__name__,opt_param)]["coefficient_stats"][t["id"]]["mean"] cstd = stats[(func.__name__,opt_param)]["coefficient_stats"][t["id"]]["std"] blmean = stats[(func.__name__,opt_param)]["blockings"][t["id"]]["mean"] brmean = stats[(func.__name__,opt_param)]["breaks"][t["id"]]["mean"] visited = stats[(func.__name__,opt_param)]["visited_countries"][t["id"]]["mean"] visited_finland = stats[(func.__name__,opt_param)]["visited_finland"][t["id"]]["sum"] travel_finland = stats[(func.__name__,opt_param)]["travel_finland"][t["id"]]["sum"] 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 += f"" sol += f"" sol += "" sol += "\n" sol += "
n={nSim}ConflictsTotalTeams
{p}{t['name']} ({t['country']})
Cfl.Trav.Coe.BlockNo TravelCountr.Play Switzerland 3xTravel Switzerland 3xTrav.Coe.BlockNo TravelCountr.Play Switzerland 3xTravel Switzerland 3x
MSMSMSMS
{func.__name__} - {opt_param} {stats[(func.__name__,opt_param)]['conflicts_dict'][p]}{stats[(func.__name__,opt_param)]['conflicts_dict']['total']}{stats[(func.__name__,opt_param)]['travel_stats']['total']['mean']}{stats[(func.__name__,opt_param)]['travel_stats']['total']['std']}{stats[(func.__name__,opt_param)]['coefficient_stats']['total']['mean']}{stats[(func.__name__,opt_param)]['coefficient_stats']['total']['std']}{stats[(func.__name__,opt_param)]['blockings']['total']['sum']}{stats[(func.__name__,opt_param)]['breaks']['total']['sum']}{stats[(func.__name__,opt_param)]['visited_countries']['total']['mean']}{stats[(func.__name__,opt_param)]['visited_finland']['total']['sum']}{stats[(func.__name__,opt_param)]['travel_finland']['total']['sum']}{tmean}{tstd}{cmean}{cstd}{blmean}{brmean}{visited}{visited_finland}{travel_finland}
\n" with open(f"stats_{filename}.html", "w") as f: f.write(sol) # %% # %% with open(f"color_{filename}.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) # %%