2484 lines
129 KiB
Plaintext
Executable File
2484 lines
129 KiB
Plaintext
Executable File
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "4d2a8b6c",
|
|
"metadata": {},
|
|
"source": [
|
|
"#### Database"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 18,
|
|
"id": "7be9eeff",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"PROJECT_PATH = '/home/md/Work/ligalytics/leagues_stable/'\n",
|
|
"import os, sys\n",
|
|
"sys.path.insert(0, PROJECT_PATH)\n",
|
|
"os.environ.setdefault(\"DJANGO_SETTINGS_MODULE\", \"leagues.settings\")\n",
|
|
"\n",
|
|
"\n",
|
|
"# XPRESS ENVIRONMENT\n",
|
|
"os.environ['XPRESSDIR'] = \"/opt/xpressmp_8.4\"\n",
|
|
"os.environ['XPRESS'] = \"/opt/xpressmp_8.4/bin\"\n",
|
|
"os.environ['LD_LIBRARY_PATH'] = os.environ['XPRESSDIR']+\"/lib:\"+os.environ['LD_LIBRARY_PATH']\n",
|
|
"os.environ['DYLD_LIBRARY_PATH'] = os.environ['XPRESSDIR']+\"/lib:\"\n",
|
|
"os.environ['SHLIB_PATH'] = os.environ['XPRESSDIR']+\"/lib:\"\n",
|
|
"os.environ['LIBPATH'] = os.environ['XPRESSDIR']+\"/lib:\"\n",
|
|
"os.environ['PYTHONPATH'] =os.environ['XPRESSDIR']+\"/lib:\"+os.environ['PYTHONPATH']\n",
|
|
"os.environ['CLASSPATH'] =os.environ['XPRESSDIR']+\"/lib/xprs.jar:\"\n",
|
|
"os.environ['CLASSPATH'] =os.environ['XPRESSDIR']+\"/lib/xprb.jar:\"+os.environ['CLASSPATH']\n",
|
|
"os.environ['CLASSPATH'] =os.environ['XPRESSDIR']+\"/lib/xprm.jar:\"+os.environ['CLASSPATH']\n",
|
|
"os.environ['PATH'] =os.environ['XPRESSDIR']+\"/bin:\"+os.environ['PATH']\n",
|
|
"\n",
|
|
"\n",
|
|
"from leagues import settings\n",
|
|
"settings.DATABASES['default']['NAME'] = PROJECT_PATH+'/db.sqlite3'\n",
|
|
"\n",
|
|
"import django\n",
|
|
"django.setup()\n",
|
|
"\n",
|
|
"from scheduler.models import *\n",
|
|
"import operator\n",
|
|
"from scheduler.solver.functions import *\n",
|
|
"from common.functions import distanceInKmByGPS\n",
|
|
"import pandas as pd\n",
|
|
"import numpy as np\n",
|
|
"from django.db.models import Count, F, Value\n",
|
|
"from pulp import *\n",
|
|
"\n",
|
|
"\n",
|
|
"def makeIntVar(v):\n",
|
|
" if type(v) != int :\n",
|
|
" v.cat=pulp.LpInteger\n",
|
|
" # print (\"int var \", v)\n",
|
|
"\n",
|
|
"def setStart(v,vl):\n",
|
|
" if type(v) != int :\n",
|
|
" vl=float(vl)\n",
|
|
" v.start = vl\n",
|
|
"\n",
|
|
"def setLB(v,vl):\n",
|
|
" if type(v) != int :\n",
|
|
" vl=float(vl)\n",
|
|
" v.lowBound = vl\n",
|
|
" # print (\"set lb \", v , \" = \", vl)\n",
|
|
"\n",
|
|
"\n",
|
|
"def setUB(v,vl):\n",
|
|
" if type(v) != int :\n",
|
|
" vl=float(vl)\n",
|
|
" v.upBound = vl\n",
|
|
" # print (\"set ub \", v , \" = \", vl)\n",
|
|
"\n",
|
|
"def getVal(v):\n",
|
|
" if type(v) == int :\n",
|
|
" return v\n",
|
|
" else: \n",
|
|
" return v.value()\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"user_is_staff = True\n",
|
|
"runMode = 'New'\n",
|
|
"localsearch_time = 0\n",
|
|
"solver = '?'\n",
|
|
"\n",
|
|
"s2 = 2\n",
|
|
"thisScenario = Scenario.objects.get(id = s2)\n",
|
|
"thisSeason = thisScenario.season\n",
|
|
"thisLeague = thisSeason.league\n",
|
|
"\n",
|
|
"\n",
|
|
"mathModelName=thisLeague.name\n",
|
|
"if thisSeason.optimizationParameters!=\"\":\n",
|
|
" mathModelName=thisSeason.optimizationParameters"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 19,
|
|
"id": "ca4ac4b8",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Teams : [10, 3, 17, 14, 15, 13, 12, 6, 9, 5, 8, 18, 19, 20, 11, 7, 4, 16]\n",
|
|
"VIP Teams : []\n",
|
|
"TOP Teams : []\n",
|
|
"[]\n",
|
|
"objectivePrio: Breaks\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"\n",
|
|
"\n",
|
|
"otherScenGames=[]\n",
|
|
"if thisSeason.improvementObjective!=\"--\":\n",
|
|
" for otherScenario in Scenario.objects.filter(season=thisSeason):\n",
|
|
" impObjWeight = 5\n",
|
|
" if thisSeason.improvementObjective==\"stick to old solutions\":\n",
|
|
" impObjWeight = -5\n",
|
|
" if otherScenario.solutionlist() != [['']]:\n",
|
|
" for g in otherScenario.solutionlist(): \n",
|
|
" otherScenGames.append((int(g[1]),int(g[2]),int(g[3]), impObjWeight ))\n",
|
|
"\n",
|
|
"getGlobalCountry={ gc['uefa']: gc['id'] for gc in GlobalCountry.objects.values() }\n",
|
|
"\n",
|
|
"teamObjects = Team.objects.filter(season=thisSeason,active=True).order_by('position').values()\n",
|
|
"teams=[]\n",
|
|
"realteams=[]\n",
|
|
"faketeams=[]\n",
|
|
"importantteams=[]\n",
|
|
"shortteams=[]\n",
|
|
"t_pos={}\n",
|
|
"t_pot={}\n",
|
|
"t_color={}\n",
|
|
"t_country={}\n",
|
|
"t_globalCountry={}\n",
|
|
"t_stadium = {}\n",
|
|
"t_shortname = {}\n",
|
|
"t_usePhases = {}\n",
|
|
"t_lon = {}\n",
|
|
"t_lat = {}\n",
|
|
"t_attractivity ={}\n",
|
|
"getTeamById={}\n",
|
|
"getTeamIdByName={}\n",
|
|
"getTeamIdByShortName={}\n",
|
|
"getTeamByName={}\n",
|
|
"getStadiumById={}\n",
|
|
"teamByShort={}\n",
|
|
"top4 = []\n",
|
|
"for t in teamObjects:\n",
|
|
" # print (t['name'], t['id'])\n",
|
|
" teams.append(t['id'])\n",
|
|
" shortteams.append(t['shortname'])\n",
|
|
" teamByShort[t['shortname']]= t['name']\n",
|
|
" getTeamIdByShortName[t['shortname']]=t['id']\n",
|
|
" if t['name']!='-':\n",
|
|
" realteams.append(t['id'])\n",
|
|
" else:\n",
|
|
" faketeams.append(t['id'])\n",
|
|
" if t['very_important']:\n",
|
|
" importantteams.append(t['id'])\n",
|
|
" t_country[t['id']]= t['country']\n",
|
|
" t_globalCountry[t['id']]= t['globalCountry_id']\n",
|
|
" if not t_globalCountry[t['id']] and t_country[t['id']] in getGlobalCountry.keys() :\n",
|
|
" t_globalCountry[t['id']] = getGlobalCountry[t_country[t['id']]]\n",
|
|
" t_pos[t['name']]= t['position']\n",
|
|
" t_color[t['name']]=\"lightyellow\"\n",
|
|
" t_pot[t['id']]= t['pot']\n",
|
|
" t_stadium[t['id']]=t['stadium']\n",
|
|
" t_attractivity[t['id']]=t['attractivity']\n",
|
|
" t_lon[t['id']]=t['longitude']\n",
|
|
" t_lat[t['id']]=t['latitude']\n",
|
|
" t_shortname[t['id']]=t['shortname']\n",
|
|
" t_usePhases[t['id']]= thisScenario.usePhases\n",
|
|
" getTeamById[t['id']]=t['name']\n",
|
|
" getStadiumById[t['id']]=t['stadium']\n",
|
|
" getTeamIdByName[t['name']]=t['id']\n",
|
|
" getTeamByName[t['name']]=t\n",
|
|
" if t['attractivity'] >= thisSeason.topTeamMinCoefficient :\n",
|
|
" top4.append(t['id'])\n",
|
|
"\n",
|
|
"inactive_teams=[]\n",
|
|
"for t in Team.objects.filter(season=thisSeason,active=False).order_by('position').values():\n",
|
|
" inactive_teams.append(t['id'])\n",
|
|
" t_attractivity[t['id']]=t['attractivity']\n",
|
|
" t_lon[t['id']]=t['longitude']\n",
|
|
" t_lat[t['id']]=t['latitude']\n",
|
|
" t_country[t['id']]= t['country']\n",
|
|
" getTeamById[t['id']]=t['name']\n",
|
|
"\n",
|
|
"\n",
|
|
"lowerBoundFound = False\n",
|
|
"distance ={}\n",
|
|
"attractivity ={}\n",
|
|
"distanceById={}\n",
|
|
"distanceInDaysById={}\n",
|
|
"stadium_names = set([t['stadium'] for t in teamObjects if t['stadium']!=''])\n",
|
|
"stadium_id={}\n",
|
|
"stadium_name={}\n",
|
|
"sid=0\n",
|
|
"for stadium in stadium_names :\n",
|
|
" stadium_name[sid]=stadium\n",
|
|
" stadium_id[stadium]=sid\n",
|
|
" sid+=1\n",
|
|
"stadiums = list(stadium_name.keys())\n",
|
|
"teamsOfStadium ={ st:[] for st in stadiums }\n",
|
|
"\n",
|
|
"travelDict= thisSeason.travelDict()\n",
|
|
"for t1 in teamObjects:\n",
|
|
" if t1['stadium']!='':\n",
|
|
" teamsOfStadium[stadium_id[t1['stadium']]].append(t1['id'])\n",
|
|
" for t2 in teamObjects:\n",
|
|
" # distance[t1['name'],t2['name']] = distanceInKm(t1,t2)\n",
|
|
" # print (t1['name'],t2['name'],distance[t1['name'],t2['name']] ,\" -> \", travelDict[t1['id']][t2['id']]['distance'] )\n",
|
|
" distance[t1['name'],t2['name']] = travelDict[t1['id']][t2['id']]['distance'] \n",
|
|
" distanceById[t1['id'],t2['id']] = distance[t1['name'],t2['name']]\n",
|
|
" distanceInDaysById[t1['id'],t2['id']] = int(distance[t1['name'],t2['name']]/350 +0.99)\n",
|
|
" attractivity[t1['id'],t2['id']] = int(100*t1['attractivity']*t2['attractivity'])\n",
|
|
"\n",
|
|
"\n",
|
|
"dayObjects = Day.objects.filter(season=thisSeason).values()\n",
|
|
"days = [ d['id'] for d in dayObjects if d['round']>0 ]\n",
|
|
"\n",
|
|
"higherSeasons = thisSeason.higherSeasons()\n",
|
|
"higherGames = thisSeason.higherGames()\n",
|
|
"\n",
|
|
"this_season_team_names = list(getTeamByName.keys())\n",
|
|
"\n",
|
|
"higherTeamObjects = Team.objects.filter(season__in=higherSeasons,active=True).values()\n",
|
|
"higherDayObjects = Day.objects.filter(season__in=higherSeasons,maxGames__gte=1).values()\n",
|
|
"higherTeams = [ t['id'] for t in higherTeamObjects] \n",
|
|
"higherTeamsOf={ t: [] for t in teams}\n",
|
|
"for t in higherTeamObjects:\n",
|
|
" getTeamById[t['id']]=t['name']\n",
|
|
" t_country[t['id']]=t['country']\n",
|
|
" if t['name'] in this_season_team_names:\n",
|
|
" higherTeamsOf[getTeamIdByName[t['name']]].append(t['id'])\n",
|
|
"\n",
|
|
"print (\"Teams : \" , teams)\n",
|
|
"print (\"VIP Teams : \" , importantteams)\n",
|
|
"print (\"TOP Teams : \" , top4)\n",
|
|
"\n",
|
|
"allConferences = Conference.objects.filter(scenario=s2)\n",
|
|
"sharedStadiums = False\n",
|
|
"for ff in thisSeason.federationmember.all():\n",
|
|
" sharedStadiums= ff.federation.sharedStadiums\n",
|
|
"\n",
|
|
"# print (\"\\nGroups : \")\n",
|
|
"t_conference = {t : 0 for t in teams }\n",
|
|
"conf_teams={}\n",
|
|
"for c in Conference.objects.filter(scenario=s2,regional=False).order_by('name'):\n",
|
|
" # print (\"A\" , c)\n",
|
|
" cteams = c.teams.filter(active=True)\n",
|
|
" conf_teams[c.name]=[]\n",
|
|
" for t in cteams:\n",
|
|
" conf_teams[c.name].append(t.id)\n",
|
|
" # print (\"group for \", t)\n",
|
|
" # if t_conference[t.id]!=0:\n",
|
|
" # print (getTeamById[t.id] , \" in several groups\")\n",
|
|
" if t_conference[t.id]==0 or len(cteams)< len(t_conference[t.id].teams.filter(active=True)):\n",
|
|
" t_conference[t.id]=c\n",
|
|
" # print (\" is \" , c )\n",
|
|
"# for t in set([t for t in teams if t_conference[t]==0 ]):\n",
|
|
" # print (\" no group \" , getTeamById[ t])\n",
|
|
"# return ''\n",
|
|
"\n",
|
|
"prioVal ={'A': 25 , 'B': 5 , 'C': 1, 'Hard' : 1000}\n",
|
|
"\n",
|
|
"sw_prio = {}\n",
|
|
"sw_float1 = {}\n",
|
|
"sw_float2 = {}\n",
|
|
"sw_int1 = {}\n",
|
|
"sw_int2 = {}\n",
|
|
"sw_text = {}\n",
|
|
"for sw in SpecialWish.objects.filter(scenario=s2):\n",
|
|
" sw_prio[sw.name]=prioVal[sw.prio] if sw.active else 0\n",
|
|
" sw_float1[sw.name]=sw.float1\n",
|
|
" sw_float2[sw.name]=sw.float2\n",
|
|
" sw_int1[sw.name]=sw.int1\n",
|
|
" sw_int2[sw.name]=sw.int2\n",
|
|
" sw_text[sw.name]=sw.text\n",
|
|
"special_wishes=list(sw_prio.keys())\n",
|
|
"special_wishes_active = [ sw for sw in special_wishes if sw_prio[sw]>0 ]\n",
|
|
"\n",
|
|
"print (special_wishes_active)\n",
|
|
"\n",
|
|
"noBreakLimitTeams = []\n",
|
|
"if \"allowManyBreaksInRow\" in special_wishes_active :\n",
|
|
" noBreakLimitTeams = sw_text[\"allowManyBreaksInRow\"].split(\",\")\n",
|
|
" print (noBreakLimitTeams)\n",
|
|
" noBreakLimitTeams = [t for t in teams if getTeamById[t] in noBreakLimitTeams]\n",
|
|
" print (noBreakLimitTeams) \n",
|
|
"\n",
|
|
"pairings_tmp = Pairing.objects.filter(scenario=s2, active=True).values()\n",
|
|
"pairings_tmp2 = Pairing.objects.filter(scenario__is_published=True, team1__id__in=teams, team2__id__in=higherTeams, active=True).values()\n",
|
|
"pairings_tmp3 = Pairing.objects.filter(scenario__is_published=True, team2__id__in=teams, team1__id__in=higherTeams, active=True).values()\n",
|
|
"pairings = []\n",
|
|
"for p in [ p for p in pairings_tmp if p['team1_id'] in teams and p['team2_id'] in teams+higherTeams ] + [ p for p in pairings_tmp2 ] + [ p for p in pairings_tmp3]:\n",
|
|
" if p not in pairings:\n",
|
|
" pairings.append(p) \n",
|
|
"breaks = Break.objects.filter(season=thisSeason).values()\n",
|
|
"blockings_tmp = Blocking.objects.filter(scenario=s2,active=True).values()\n",
|
|
"blockings = [ bl for bl in blockings_tmp if bl['team_id'] in teams ]\n",
|
|
"\n",
|
|
"# times = ['Early', 'Late']\n",
|
|
"timeObjects = TimeSlot.objects.filter(season=thisSeason).values()\n",
|
|
"times = [ str(t['id']) for t in timeObjects]\n",
|
|
"getTimeById = {str(t['id']):t['name'] for t in timeObjects}\n",
|
|
"getIdByTime = {t['name']:str(t['id']) for t in timeObjects}\n",
|
|
"\n",
|
|
"blocked_arena = {(t,d, tm) : False for t in teams for d in days for tm in [\"----\"] + times }\n",
|
|
"hidden_arena = {(t,d, tm) : False for t in teams for d in days for tm in [\"----\"] + times }\n",
|
|
"nBlockingHome=0\n",
|
|
"nBlockingAway=0\n",
|
|
"\n",
|
|
"for bl in blockings:\n",
|
|
" if bl['type'] in [\"Hide\"]:\n",
|
|
" hidden_arena[(bl['team_id'],bl['day_id'], bl['time'] )]=True\n",
|
|
"\n",
|
|
" if bl['type'] in [\"Home\",\"Hide\"]:\n",
|
|
" nBlockingHome+=1\n",
|
|
" blocked_arena[(bl['team_id'],bl['day_id'], bl['time'] )]=True\n",
|
|
" else:\n",
|
|
" nBlockingAway+=1\n",
|
|
"\n",
|
|
"nTeams=len(teams)\n",
|
|
"nPhases =thisSeason.numPhases\n",
|
|
"groupView = thisSeason.groupBased\n",
|
|
"\n",
|
|
"gameCntr={(t1,t2) : 0 for t1 in teams for t2 in teams}\n",
|
|
"undirectedGameCntr={(t1,t2) : 0 for t1 in teams for t2 in teams}\n",
|
|
"\n",
|
|
"if thisSeason.useFeatureOpponentMatrix:\n",
|
|
" gameRequirements = GameRequirement.objects.filter(season=thisSeason, team1__active=True, team2__active=True) \n",
|
|
" # print (len(gameRequirements))\n",
|
|
" for gm in gameRequirements:\n",
|
|
" if thisSeason.undirectedGames:\n",
|
|
" undirectedGameCntr[(gm.team1.id,gm.team2.id)]+=gm.number\n",
|
|
" undirectedGameCntr[(gm.team2.id,gm.team1.id)]+=gm.number\n",
|
|
" # print ( \"found undirected game \" , (gm.team1.id,gm.team2.id) , gm.number )\n",
|
|
" else:\n",
|
|
" gameCntr[(gm.team1.id,gm.team2.id)]+=gm.number\n",
|
|
" # print ( \"found directed game \" , (gm.team1.id,gm.team2.id) , gm.number )\n",
|
|
"else:\n",
|
|
" for t1 in teams:\n",
|
|
" for t2 in teams:\n",
|
|
" if t1!=t2:\n",
|
|
" gameCntr[(t1,t2)]+=nPhases/2\n",
|
|
"\n",
|
|
" for c in Conference.objects.filter(scenario=s2):\n",
|
|
" cteams = c.teams.filter(active=True)\n",
|
|
" for t1 in cteams:\n",
|
|
" for t2 in cteams:\n",
|
|
" if t1!=t2:\n",
|
|
" gameCntr[(t1.id,t2.id)]+=c.deltaGames/2\n",
|
|
"\n",
|
|
" for (t1,t2) in gameCntr.keys():\n",
|
|
" if gameCntr[(t1,t2)]%1!=0 :\n",
|
|
" undirectedGameCntr[(t1,t2)]=1\n",
|
|
" gameCntr[(t1,t2)] = int(gameCntr[(t1,t2)])\n",
|
|
"\n",
|
|
"games = [ gm for gm in gameCntr.keys() if gameCntr[gm]+undirectedGameCntr[gm]>0]\n",
|
|
"\n",
|
|
"objectiveFunctionWeights = ObjectiveFunctionWeight.objects.filter(scenario=s2).values()\n",
|
|
"\n",
|
|
"gew={}\n",
|
|
"gew['Trips'] = 5\n",
|
|
"gew['Derbies'] = 5\n",
|
|
"gew['Pairings'] = 5\n",
|
|
"for ow in objectiveFunctionWeights:\n",
|
|
" gew[ow['name']]= ow['use'] * ow['prio']\n",
|
|
"\n",
|
|
"objectivePrio = 'Breaks'\n",
|
|
"if gew['Trips']>gew['Breaks'] :\n",
|
|
" objectivePrio = 'Trips'\n",
|
|
"\n",
|
|
"print(\"objectivePrio:\", objectivePrio)\n",
|
|
"\n",
|
|
"specialGameControl= mathModelName in [\"Florida State League\"]\n",
|
|
"\n",
|
|
"if len(games)==0:\n",
|
|
" games = [ (t1,t2) for t1 in teams for t2 in teams if t1!=t2 ]\n",
|
|
" specialGameControl=True\n",
|
|
" \n",
|
|
"realgames= [(t1,t2) for (t1,t2) in games if getTeamById[t1]!=\"-\" and getTeamById[t2]!=\"-\"]\n",
|
|
"\n",
|
|
"# nur wenn die solutionlist alle spiele enthält, wird dieser modus aktiviert\n",
|
|
"evalRun = ( runMode == \"Improve\" and localsearch_time==0 \n",
|
|
" and len(thisScenario.solutionlist())==sum([gameCntr[gm]+0.5*undirectedGameCntr[gm] for gm in realgames]) )\n",
|
|
"\n",
|
|
"opponents = { t: set([]) for t in realteams}\n",
|
|
"\n",
|
|
"for (t1,t2) in games:\n",
|
|
" if t1 in realteams and t2 in realteams:\n",
|
|
" opponents[t1].add(t2)\n",
|
|
" opponents[t2].add(t1)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 20,
|
|
"id": "1c51e80c",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"gmClusters range(1, 2)\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"\n",
|
|
"model7 = pulp.LpProblem(\"FindGameClusters_\"+str(thisScenario.id), pulp.LpMinimize)\n",
|
|
"gmClusters = range(1,nTeams+2)\n",
|
|
"\n",
|
|
"if nPhases>0 and not thisSeason.useFeatureOpponentMatrix and not specialGameControl:\n",
|
|
" gmClusters = range(1,2) \n",
|
|
"\n",
|
|
"print (\"gmClusters\", gmClusters)\n",
|
|
"x7 = {(t,c) : pulp.LpVariable('x7_'+str(t)+'_'+str(c), lowBound = 0, upBound = 1, cat = pulp.LpInteger) for t in teams for c in gmClusters}\n",
|
|
"\n",
|
|
"for t in realteams: \n",
|
|
" model7+= lpSum([ x7[(t,c)] for c in gmClusters]) ==1 \n",
|
|
"\n",
|
|
"for (t1,t2) in gameCntr.keys():\n",
|
|
" if gameCntr[(t1,t2)]+undirectedGameCntr[(t1,t2)]==0 and t1!=t2:\n",
|
|
" for c in gmClusters:\n",
|
|
" model7+= x7[(t1,c)]+ x7[(t2,c)] <=1\n",
|
|
"\n",
|
|
"model7+= lpSum([ c*x7[(t,c)] for (t,c) in x7.keys()]) \n",
|
|
"\n",
|
|
"if solver == \"CBC\":\n",
|
|
" model7.solve(PULP_CBC_CMD(threads = 8,msg=1))\n",
|
|
"elif solver == \"Gurobi\":\n",
|
|
" model7.solve(GUROBI(MIPGap=0.01,msg=1))\n",
|
|
"else:\n",
|
|
" model7.solve(XPRESS(msg=1, targetGap=0.01, maxSeconds = 100, keepFiles=True))\n",
|
|
"\n",
|
|
"\n",
|
|
"gameClusterTeams = { c : [ t for t in teams if x7[(t,c)].value()>0.01] for c in gmClusters }\n",
|
|
"gameClusters=[ c for c in gameClusterTeams.keys() if len(gameClusterTeams[c])>0]\n",
|
|
"biggestGroupSize = max([len(gameClusterTeams[c]) for c in gameClusters])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 21,
|
|
"id": "a446fffc",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"nRounds 34\n",
|
|
"nPhases 2\n",
|
|
"nRoundsPerPhase 17\n",
|
|
"defaultGameRepetions 1\n",
|
|
"tripStartHeuristicGroupsize 1\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"nPhases = min( [ gameCntr[(t1,t2)]+ gameCntr[(t2,t1)] + undirectedGameCntr[(t1,t2)] for (t1,t2) in realgames ])\n",
|
|
"tripStartHeuristicGroupsize = 1 if thisSeason.tripStartHeuristicGroupsize==\"None\" else int(thisSeason.tripStartHeuristicGroupsize)\n",
|
|
"defaultGameRepetions = 1 if not mathModelName in [\"NHL\", \"NBA\"] else 2\n",
|
|
"nPhases=max(1,int(nPhases/defaultGameRepetions))\n",
|
|
"phases = range(nPhases)\n",
|
|
"\n",
|
|
"useBasicGames = nPhases>0\n",
|
|
"\n",
|
|
"if not useBasicGames:\n",
|
|
" print ('no basic games but biggest group size ', biggestGroupSize, ' in nPhases ' , nPhases )\n",
|
|
"\n",
|
|
"nRounds = thisSeason.nRounds\n",
|
|
"rounds=range(1,nRounds+1)\n",
|
|
"\n",
|
|
"# nRoundsPerPhase= 1\n",
|
|
"# if nPhases>0:\n",
|
|
"nRoundsPerPhase= int(nRounds/nPhases)\n",
|
|
"\n",
|
|
"print ('nRounds ',nRounds)\n",
|
|
"print ('nPhases ',nPhases)\n",
|
|
"print ('nRoundsPerPhase ',nRoundsPerPhase)\n",
|
|
"print ('defaultGameRepetions ',defaultGameRepetions)\n",
|
|
"print ('tripStartHeuristicGroupsize ',tripStartHeuristicGroupsize)\n",
|
|
"\n",
|
|
"getPhaseOfRound = { r : min( nPhases-1 , int((r-1)/nRoundsPerPhase)) for r in rounds }\n",
|
|
"getDaysOfPhase = { p : [] for p in phases }\n",
|
|
"getDays = { r : [] for r in rounds}\n",
|
|
"roundGamesMax = { r : 0 for r in rounds}\n",
|
|
"roundGamesMin = { r : 0 for r in rounds}\n",
|
|
"getDayById = { d['id'] : d for d in dayObjects}\n",
|
|
"getDayByDateTime = { }\n",
|
|
"getNiceDayRaw = { d['id'] : d['day'] for d in dayObjects}\n",
|
|
"getNiceDay = { d['id'] : d['day'] for d in dayObjects}\n",
|
|
"getWeekDay = { d['id'] : '' for d in dayObjects}\n",
|
|
"getDateTimeDay = { d['id'] : '' for d in dayObjects}\n",
|
|
"getRoundByDay = { d['id'] : d['round'] for d in dayObjects if d['round']>0 }\n",
|
|
"getDayMinGames = { d['id'] : d['minGames'] for d in dayObjects if d['round']>0 }\n",
|
|
"getDayMaxGames = { d['id'] : d['maxGames'] for d in dayObjects if d['round']>0 }\n",
|
|
"getRoundsByDay = { d['id'] : [] for d in dayObjects }\n",
|
|
"nDerbies = { d['id'] : [d['nDerbies']] for d in dayObjects}\n",
|
|
"roundDays =[]\n",
|
|
"roundDaysMin ={ }\n",
|
|
"roundDaysMax ={ }\n",
|
|
"wds= {0:'Mon', 1:'Tue', 2:'Wed', 3:'Thu', 4:'Fri', 5:'Sat', 6:'Sun'}\n",
|
|
"for d in dayObjects:\n",
|
|
" if d['round']>0 :\n",
|
|
" getRoundsByDay[d['id']].append(d['round'])\n",
|
|
" getDays[d['round']].append(d['id'])\n",
|
|
" roundDays.append((d['round'],d['id']))\n",
|
|
" roundDaysMin[(d['round'],d['id'])]=d['minGames']\n",
|
|
" roundDaysMax[(d['round'],d['id'])]=d['maxGames']\n",
|
|
" roundGamesMax[d['round']]=min(nTeams/2, roundGamesMax[d['round']]+d['maxGames'] )\n",
|
|
" roundGamesMin[d['round']]+=d['minGames']\n",
|
|
" ph = getPhaseOfRound[d['round']]\n",
|
|
" getDaysOfPhase[ph].append(d['id'])\n",
|
|
" if d['round2']>0:\n",
|
|
" getRoundsByDay[d['id']].append(d['round2'])\n",
|
|
" getDays[d['round2']].append(d['id'])\n",
|
|
" roundDays.append((d['round2'],d['id']))\n",
|
|
" roundDaysMin[(d['round2'],d['id'])]=d['minGames2']\n",
|
|
" roundDaysMax[(d['round2'],d['id'])]=d['maxGames2']\n",
|
|
" roundGamesMax[d['round2']]=min(nTeams/2, roundGamesMax[d['round2']]+d['maxGames2'] )\n",
|
|
" roundGamesMin[d['round2']]+=d['minGames2']\n",
|
|
"\n",
|
|
" dt = parse(d['day'])\n",
|
|
" getDateTimeDay[d['id']] = dt\n",
|
|
" getDayByDateTime[dt] = d['id']\n",
|
|
" getNiceDay[d['id']] = str(dt.strftime('%a, %b %d, %Y'))\n",
|
|
" getWeekDay[d['id']] = str(wds[dt.weekday()])\n",
|
|
"\n",
|
|
"countries = list(set( [t_country[t] for t in teams ])) \n",
|
|
"\n",
|
|
"getWeekDaysPerRound = { r : [ getWeekDay[d] for d in getDays[r]] for r in rounds}\n",
|
|
"\n",
|
|
"wd = {\"Mondays\":0 , \"Tuesdays\":1 , \"Wednesdays\":2 , \"Thursdays\":3 , \"Fridays\":4 , \"Saturdays\":5 , \"Sundays\":6}\n",
|
|
"t_site_bestTimeSlots = { (t,d): [] for t in realteams for d in days }\n",
|
|
"prio_weight = { \"A\" : 0 , \"B\" : 50 , \"C\" : 100}\n",
|
|
"\n",
|
|
"\n",
|
|
"toTime=False\n",
|
|
"\n",
|
|
"\n",
|
|
"earliestDay={r: getDays[r][0] for r in rounds }\n",
|
|
"latestDay={r: getDays[r][0] for r in rounds }\n",
|
|
"for r in rounds :\n",
|
|
" for d in getDays[r]:\n",
|
|
" dt=getDateTimeDay[d]\n",
|
|
" if dt>getDateTimeDay[latestDay[r]]:\n",
|
|
" latestDay[r]=d\n",
|
|
" if dt<getDateTimeDay[earliestDay[r]]:\n",
|
|
" earliestDay[r]=d\n",
|
|
"\n",
|
|
"\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 22,
|
|
"id": "df5d6ff1",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"nPhases 2\n",
|
|
"nGameClusters 1\n",
|
|
"nBasicTeamsPerCluster 18\n",
|
|
"nBasicTeams 18\n",
|
|
"nBasicRounds 34\n",
|
|
"nRounds1 17\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"basicTeams = teams\n",
|
|
"basicGames = [ (t1,t2) for (t1,t2) in games if t1 in basicTeams and t2 in basicTeams ]\n",
|
|
"\n",
|
|
"nBasicTeams = len (basicTeams)\n",
|
|
"nBasicTeamsPerCluster = int(nBasicTeams/len(gameClusters)+0.9)\n",
|
|
"if nBasicTeamsPerCluster%2==1:\n",
|
|
" nBasicTeamsPerCluster+=1\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"nRounds1 = nBasicTeamsPerCluster-1\n",
|
|
"nBasicRounds= nPhases * (nBasicTeamsPerCluster-1)\n",
|
|
"\n",
|
|
"if nBasicTeamsPerCluster==1 or nBasicRounds==1:\n",
|
|
" nBasicRounds=nRounds\n",
|
|
" nRounds1=nRounds\n",
|
|
"\n",
|
|
"basicRounds = range (1,nBasicRounds+1)\n",
|
|
"\n",
|
|
"print (\"nPhases \", nPhases)\n",
|
|
"print (\"nGameClusters \", len(gameClusters))\n",
|
|
"print (\"nBasicTeamsPerCluster \", nBasicTeamsPerCluster)\n",
|
|
"print (\"nBasicTeams \", nBasicTeams)\n",
|
|
"print (\"nBasicRounds \", nBasicRounds)\n",
|
|
"print (\"nRounds1 \", nRounds1)\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"stretch = nRounds/nBasicRounds\n",
|
|
"# print (\"regionalPatternUse \" , regionalPatternUse)\n",
|
|
"rounds1=range(1,nRounds1+1)\n",
|
|
"nGames=nTeams*nRounds1\n",
|
|
"\n",
|
|
"\n",
|
|
"getBasicRound={ r : int ((r-1)/stretch)+1 for r in rounds}\n",
|
|
"getRealRounds = { br : [ r for r in rounds if getBasicRound[r]==br ] for br in basicRounds}\n",
|
|
"# print (\"stretch : \" , stretch)\n",
|
|
"\n",
|
|
"getBasicDays= {r : [] for r in basicRounds}\n",
|
|
"for r in rounds:\n",
|
|
" getBasicDays[getBasicRound[r]]+=(getDays[r])\n",
|
|
"\n",
|
|
"\n",
|
|
"getRoundDaysByDay = {d: [ rd for rd in roundDays if rd[1]==d ] for d in days}\n",
|
|
"getRoundDaysByRound = {r: [rd for rd in roundDays if rd[0]==r ] for r in rounds}\n",
|
|
"\n",
|
|
"daysSorted =[]\n",
|
|
"for dt in sorted([ getDateTimeDay[d] for d in days]):\n",
|
|
" daysSorted.append ( getDayByDateTime[dt] )\n",
|
|
"\n",
|
|
"minRest = { (t,s1,s2) : thisSeason.minDaysBetweenGames for t in teams for s1 in ['A','H'] for s2 in ['A','H']}\n",
|
|
"for t in teamObjects:\n",
|
|
" minRest[(t['id'],'H','H')] = max(minRest[(t['id'],'H','H')], t['minRest_HH'] )\n",
|
|
" minRest[(t['id'],'H','A')] = max(minRest[(t['id'],'H','A')], t['minRest_HA'] )\n",
|
|
" minRest[(t['id'],'A','H')] = max(minRest[(t['id'],'A','H')], t['minRest_AH'] )\n",
|
|
" minRest[(t['id'],'A','A')] = max(minRest[(t['id'],'A','A')], t['minRest_AA'] )\n",
|
|
" \n",
|
|
"maxMinRest = { t : max( [ minRest[(t,s1,s2)] for s1 in ['A','H'] for s2 in ['A','H'] ] ) for t in teams }\n",
|
|
"\n",
|
|
"excessGames = { rd: -roundDaysMax[rd] for rd in roundDays }\n",
|
|
"deficientGames = { rd: roundDaysMin[rd] for rd in roundDays }\n",
|
|
"\n",
|
|
"excessGames = { rd: max(0,excessGames[rd]) for rd in roundDays }\n",
|
|
"deficientGames = { rd: max(0,deficientGames[rd]) for rd in roundDays }"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 23,
|
|
"id": "0d1f6342",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"processing encounters\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"\n",
|
|
"\n",
|
|
"allowed_weekdays={'--' : [0,1,2,3,4,5,6], 'Mondays':[0], 'Tuesdays':[1], 'Wednesdays':[2], 'Thursdays':[3], 'Fridays':[4], 'Saturdays':[5],'Sundays':[6], 'Weekdays':[0,1,2,3,4], 'Weekends':[5,6], 'Mon.-Thu.':[0,1,2,3] , 'Fri.-Sun.':[4,5,6] } \n",
|
|
"\n",
|
|
"hawishes = HAWish.objects.filter(scenario=s2,active=True).order_by('reason').values()\n",
|
|
"hawTeams = {}\n",
|
|
"hawDays = {}\n",
|
|
"hawTimes = {}\n",
|
|
"hawRounds = {}\n",
|
|
"hawRoundsString = {}\n",
|
|
"for c in HAWish.objects.filter(scenario=s2):\n",
|
|
" # print ()\n",
|
|
" # print (c.reason )\n",
|
|
" hawDays[c.id] = []\n",
|
|
" hawTeams[c.id] = []\n",
|
|
" hawTimes[c.id]= [ str(dd.id) for dd in c.timeslots.all() ]\n",
|
|
" if c.selection_mode == 0:\n",
|
|
" for t in c.teams.filter(active=True):\n",
|
|
" hawTeams[c.id].append(t.id)\n",
|
|
" elif c.selection_mode == 1:\n",
|
|
" for t in c.groups.all():\n",
|
|
" for t2 in t.teams.filter(active=True):\n",
|
|
" hawTeams[c.id].append(t2.id)\n",
|
|
" elif c.selection_mode == 2:\n",
|
|
" cids = [ cn.id for cn in c.countries.all()]\n",
|
|
" for t in teams:\n",
|
|
" if t_globalCountry[t] in cids:\n",
|
|
" hawTeams[c.id].append(t)\n",
|
|
"\n",
|
|
" if c.multidate:\n",
|
|
" hawDays[c.id]= [ dd.id for dd in c.dates.all() ]\n",
|
|
" # print (\"multidate\")\n",
|
|
" else:\n",
|
|
" if c.day and not c.day2:\n",
|
|
" hawDays[c.id].append(c.day.id)\n",
|
|
" # print('+ ',getDayById[e['day_id']])\n",
|
|
"\n",
|
|
" if not c.day and c.day2:\n",
|
|
" hawDays[c.id].append(c.day2.id)\n",
|
|
" # print('+ ',getDayById[e['day2_id']])\n",
|
|
"\n",
|
|
" if not c.day and not c.day2:\n",
|
|
" for d in days:\n",
|
|
" dt = getDateTimeDay[d] \n",
|
|
" if dt.weekday() in allowed_weekdays[c.weekdays]:\n",
|
|
" # print (hawDays[e['id']])\n",
|
|
" hawDays[c.id].append(d)\n",
|
|
" # print('+ ',getDayById[d])\n",
|
|
"\n",
|
|
" if c.day and c.day2:\n",
|
|
" day1= getDateTimeDay[c.day.id] \n",
|
|
" day2= getDateTimeDay[c.day2.id] \n",
|
|
" for d in days:\n",
|
|
" dt = getDateTimeDay[d] \n",
|
|
" # print (day1, \"<=\" , dt , \"<=\", day2 , \" \" , day1<=dt and dt<=day2 )\n",
|
|
" if day1<=dt and dt<=day2 and dt.weekday() in allowed_weekdays[c.weekdays]:\n",
|
|
" # print (day1, \"<=\" , dt , \"<=\", day2 , \" \" , day1<=dt and dt<=day2 )\n",
|
|
" hawDays[c.id].append(d)\n",
|
|
" # print('+ ',getDayById[d])\n",
|
|
"\n",
|
|
"print (\"processing encounters\")\n",
|
|
"encwishes = EncWish.objects.filter(scenario=s2,active=True).values()\n",
|
|
"encTeams1 = {}\n",
|
|
"encTeams2 = {}\n",
|
|
"encGroups = {}\n",
|
|
"encGames = {}\n",
|
|
"encTeams1String = {}\n",
|
|
"encTeams2String = {}\n",
|
|
"encDays = { e['id'] : [] for e in encwishes}\n",
|
|
"encDaySets={}\n",
|
|
"encTimes = {}\n",
|
|
"encRounds = { e['id'] : [] for e in encwishes}\n",
|
|
"encRoundsString = { e['id'] : \"\" for e in encwishes}\n",
|
|
"for c in EncWish.objects.filter(scenario=s2,active=True):\n",
|
|
" encTimes[c.id]= [ str(dd.id) for dd in c.timeslots.all() ]\n",
|
|
" encTeams1[c.id] = []\n",
|
|
" encTeams2[c.id] = []\n",
|
|
" encGroups[c.id] = []\n",
|
|
" encTeams1String[c.id] = ''\n",
|
|
" encTeams2String[c.id] = ''\n",
|
|
" for t in c.encounterGroups.all():\n",
|
|
" encGroups[c.id].append(t)\n",
|
|
" if c.useGroups:\n",
|
|
" for gr in c.teams1_groups.all():\n",
|
|
" for t in gr.teams.filter(active=True):\n",
|
|
" encTeams1[c.id].append(t.id)\n",
|
|
" encTeams1String[c.id]+=gr.name +', '\n",
|
|
" for gr in c.teams2_groups.all():\n",
|
|
" for t in gr.teams.filter(active=True):\n",
|
|
" encTeams2[c.id].append(t.id)\n",
|
|
" encTeams2String[c.id]+=t.name +', '\n",
|
|
" else:\n",
|
|
" for t in c.teams1.filter(active=True):\n",
|
|
" encTeams1[c.id].append(t.id)\n",
|
|
" encTeams1String[c.id]+=t.name +', '\n",
|
|
" for t in c.teams2.filter(active=True):\n",
|
|
" encTeams2[c.id].append(t.id)\n",
|
|
" encTeams2String[c.id]+=t.name +', '\n",
|
|
" encTeams1String[c.id] = encTeams1String[c.id][:-2]\n",
|
|
" encTeams2String[c.id] = encTeams2String[c.id][:-2]\n",
|
|
"\n",
|
|
" if c.useEncounterGroups:\n",
|
|
" tmp_games = [(t1.id,t2.id) for eg in encGroups[c.id] for ec in eg.encounter_set.all() for t1 in ec.homeTeams.all() for t2 in ec.awayTeams.all() if t1!=t2 ]\n",
|
|
" tmp_games += [(t2.id,t1.id) for eg in encGroups[c.id] for ec in eg.encounter_set.all() for t1 in ec.homeTeams.all() for t2 in ec.awayTeams.all() if t1!=t2 and ec.symmetry]\n",
|
|
" encGames[c.id] = [tmp_games]\n",
|
|
" else:\n",
|
|
" elemHomeTeams= [encTeams1[c.id]]\n",
|
|
" if c.forEachTeam1:\n",
|
|
" elemHomeTeams= [ [t] for t in encTeams1[c.id]]\n",
|
|
" elemAwayTeams= [ encTeams2[c.id]]\n",
|
|
" if c.forEachTeam2:\n",
|
|
" elemAwayTeams= [ [t] for t in encTeams2[c.id]]\n",
|
|
" encGames[c.id]= []\n",
|
|
" # print (\"NEW ENC \", elemHomeTeams,elemAwayTeams)\n",
|
|
" for elh in elemHomeTeams:\n",
|
|
" for ela in elemAwayTeams:\n",
|
|
" # print (\" --- ENC \", elh,ela)\n",
|
|
" tmp_games= [(t1,t2) for t1 in elh for t2 in ela if t1!=t2 ] \n",
|
|
" if c.symmetry:\n",
|
|
" tmp_games += [(t1,t2) for t1 in ela for t2 in elh if t1!=t2 ] \n",
|
|
" encGames[c.id].append( tmp_games)\n",
|
|
"\n",
|
|
" if c.multidate:\n",
|
|
" encDays[c.id]= [ dd.id for dd in c.dates.all() ]\n",
|
|
" else:\n",
|
|
" if c.day:\n",
|
|
" day1= getDateTimeDay[c.day.id] \n",
|
|
"\n",
|
|
" if c.day and not c.day2:\n",
|
|
" encDays[c.id].append(c.day.id)\n",
|
|
"\n",
|
|
" if not c.day and c.day2:\n",
|
|
" encDays[c.id].append(c.day2.id)\n",
|
|
"\n",
|
|
" if not c.day and not c.day2:\n",
|
|
" for d in days:\n",
|
|
" dt= getDateTimeDay[d] \n",
|
|
" # dt = parse(getDayById[d]['day'])\n",
|
|
" if dt.weekday() in allowed_weekdays[c.weekdays]:\n",
|
|
" encDays[c.id].append(d)\n",
|
|
"\n",
|
|
" if c.day and c.day2:\n",
|
|
" # day1= parse(c.day.day)\n",
|
|
" # day2= parse(c.day2.day)\n",
|
|
" day1= getDateTimeDay[c.day.id] \n",
|
|
" day2= getDateTimeDay[c.day2.id] \n",
|
|
" for d in days:\n",
|
|
" dt= getDateTimeDay[d] \n",
|
|
" # dt = parse(getDayById[d]['day'])\n",
|
|
" if day1<=dt and dt<=day2 and dt.weekday() in allowed_weekdays[c.weekdays]:\n",
|
|
" encDays[c.id].append(d)\n",
|
|
"\n",
|
|
" encDaySets[c.id]=[]\n",
|
|
" elemDays= [ encDays[c.id]]\n",
|
|
" if c.forEachDay or c.forOneDay:\n",
|
|
" elemDays= [ [d] for d in encDays[c.id]]\n",
|
|
"\n",
|
|
" lastDaySet=[]\n",
|
|
" for d in elemDays :\n",
|
|
" tmpDays=d\n",
|
|
" if (c.forEachDay or c.forOneDay) and c.timeframe!=0:\n",
|
|
" tmpDays = []\n",
|
|
" # day1= parse(getDayById[d[0]]['day'])\n",
|
|
" day1= getDateTimeDay[d[0]] \n",
|
|
" if c.timeframe>0:\n",
|
|
" day2= day1 + datetime.timedelta(days=c.timeframe-1)\n",
|
|
" # print (e)\n",
|
|
" # print (day1, day2)\n",
|
|
" for d3 in days:\n",
|
|
" dt= getDateTimeDay[d3] \n",
|
|
" # dt = parse(getDayById[d3]['day'])\n",
|
|
" if day1<=dt and dt<=day2 :\n",
|
|
" tmpDays.append(d3) \n",
|
|
" else: \n",
|
|
" r1 = getDayById[d[0]]['round']\n",
|
|
" for d3 in days:\n",
|
|
" # dt = parse(getDayById[d3]['day'])\n",
|
|
" dt= getDateTimeDay[d3] \n",
|
|
" if day1<=dt and getRoundByDay[d3]< r1 + (-c.timeframe) :\n",
|
|
" tmpDays.append(d3)\n",
|
|
" # print (\" ROUNDWISH \", e, elemEncWishDays[cntr], e['timeframe'])\n",
|
|
" # for d4 in elemEncWishDays[cntr]:\n",
|
|
" # print (\" - \" ,getDayById[d4]['day'])\n",
|
|
"\n",
|
|
" if len([ d for d in tmpDays if d not in lastDaySet ])>0:\n",
|
|
" encDaySets[c.id].append(tmpDays)\n",
|
|
" lastDaySet = tmpDays\n",
|
|
" # print(\"-.--- NEW DAYS\", tmpDays)\n",
|
|
"\n",
|
|
" for ds in encDaySets[c.id]:\n",
|
|
" for d3 in ds:\n",
|
|
" encRounds[c.id]+= getRoundsByDay[d3]\n",
|
|
" encRounds[c.id]=sorted(list(set(encRounds[c.id])))\n",
|
|
" for r in encRounds[c.id]:\n",
|
|
" encRoundsString[c.id]+= str(r)+\"_\"\n",
|
|
" if encRoundsString[c.id]!=\"\":\n",
|
|
" encRoundsString[c.id]=encRoundsString[c.id][:-1]\n",
|
|
" # print (encRoundsString[c.id] , \" # \" ,c.affected_rounds , encRoundsString[c.id] != c.affected_rounds)\n",
|
|
"\n",
|
|
"\n",
|
|
"onlyEarlyDays= []\n",
|
|
"onlyLateDays= []\n",
|
|
"\n",
|
|
"\n",
|
|
"alwaysConsiderAllGames = not mathModelName in [\"Florida State League\" , \"UEFA NL\"]\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"elemEncWishes ={e['id'] : [] for e in encwishes}\n",
|
|
"elemEncWishGames={}\n",
|
|
"elemEncWishDays={}\n",
|
|
"\n",
|
|
"cntr=0\n",
|
|
"for e in encwishes:\n",
|
|
" for eg in encGames[e['id']] :\n",
|
|
" for ed in encDaySets[e['id']]:\n",
|
|
" if len(eg)>0 and len(ed)>0:\n",
|
|
" cntr+=1\n",
|
|
" elemEncWishes[e['id']].append(cntr)\n",
|
|
" elemEncWishGames[cntr] = eg\n",
|
|
" elemEncWishDays[cntr] = ed\n",
|
|
"\n",
|
|
"\n",
|
|
"# print (elemEncWishGames)\n",
|
|
"# print (elemEncWishDays)\n",
|
|
"\n",
|
|
"\n",
|
|
"encRelRoundsMin = { el :[] for enc in encwishes for el in elemEncWishes[enc['id']]}\n",
|
|
"encRelRoundsMax = { el :[] for enc in encwishes for el in elemEncWishes[enc['id']]}\n",
|
|
"\n",
|
|
"for enc in encwishes:\n",
|
|
" # print (e)\n",
|
|
" # print (\"ENC !! \" , enc['reason'] )\n",
|
|
" for el in elemEncWishes[enc['id']]:\n",
|
|
" relDaysSet = set(elemEncWishDays[el])\n",
|
|
" for r in basicRounds :\n",
|
|
" if len(relDaysSet.intersection(set(getBasicDays[r])))>0:\n",
|
|
" frac = len(relDaysSet.intersection(set(getBasicDays[r]))) / len (getBasicDays[r])\n",
|
|
" # print (len(relDaysSet.intersection(set(getBasicDays[r]))) , len (getBasicDays[r]) , frac)\n",
|
|
" if frac>0:\n",
|
|
" encRelRoundsMin[el].append(r)\n",
|
|
" if frac==1:\n",
|
|
" encRelRoundsMax[el].append(r)\n",
|
|
"\n",
|
|
"nElemEncWishes = sum ([len(elemEncWishes[enc['id']]) for enc in encwishes]) \n",
|
|
"\n",
|
|
"# print (encRelRoundsMin)\n",
|
|
"\n",
|
|
"elemHaWishes ={e['id'] : [] for e in hawishes}\n",
|
|
"elemHaWishTeams={}\n",
|
|
"elemHaWishDays ={}\n",
|
|
"elemHaWishFirstDay ={}\n",
|
|
"\n",
|
|
"cntr =1\n",
|
|
"for e in hawishes:\n",
|
|
" elemTeams= [ hawTeams[e['id']]]\n",
|
|
" if e['forEachTeam']:\n",
|
|
" elemTeams= [ [t] for t in hawTeams[e['id']]]\n",
|
|
"\n",
|
|
" elemDays= [ hawDays[e['id']]]\n",
|
|
" if e['forEachDay'] or e['forOneDay'] :\n",
|
|
" elemDays= [ [d] for d in hawDays[e['id']]]\n",
|
|
"\n",
|
|
" elemHaWishes[e['id']]=[]\n",
|
|
" allElemDays=[]\n",
|
|
" thisDaySet=[]\n",
|
|
" lastDaySet = []\n",
|
|
" for d in elemDays :\n",
|
|
" # print (e)\n",
|
|
" if (e['forEachDay'] or e['forOneDay']) and e['timeframe']!=1:\n",
|
|
" thisDaySet=[]\n",
|
|
" # day1= parse(getDayById[d[0]]['day'])\n",
|
|
" day1= getDateTimeDay[d[0]]\n",
|
|
" if e['timeframe']>1:\n",
|
|
" day2=day1 + datetime.timedelta(days=e['timeframe']-1)\n",
|
|
" for d3 in days:\n",
|
|
" # dt = parse(getDayById[d3]['day'])\n",
|
|
" dt= getDateTimeDay[d3]\n",
|
|
" if day1<=dt and dt<=day2 :\n",
|
|
" thisDaySet.append(d3)\n",
|
|
" else:\n",
|
|
" r1 = getDayById[d[0]]['round']\n",
|
|
" for d3 in days:\n",
|
|
" dt= getDateTimeDay[d3]\n",
|
|
" # dt = parse(getDayById[d3]['day'])\n",
|
|
" if day1<=dt and getRoundByDay[d3]< r1 + (-e['timeframe']) :\n",
|
|
" thisDaySet.append(d3)\n",
|
|
" print (\" ROUND HA WISH \", e, thisDaySet, e['timeframe'])\n",
|
|
" else:\n",
|
|
" thisDaySet=d\n",
|
|
"\n",
|
|
" # only create wish id new day set is superset\n",
|
|
" if len([d for d in thisDaySet if d not in lastDaySet])>0:\n",
|
|
" for t in elemTeams:\n",
|
|
" cntr+=1\n",
|
|
" elemHaWishes[e['id']].append(cntr)\n",
|
|
" elemHaWishTeams[cntr]=t\n",
|
|
" elemHaWishDays[cntr]=thisDaySet.copy()\n",
|
|
" elemHaWishFirstDay[cntr]=d[0]\n",
|
|
" lastDaySet = thisDaySet.copy()\n",
|
|
" allElemDays+= thisDaySet \n",
|
|
"\n",
|
|
" hawRounds[e['id']]=[]\n",
|
|
" for d3 in set(allElemDays):\n",
|
|
" hawRounds[e['id']]+=getRoundsByDay[d3]\n",
|
|
" hawRounds[e['id']]=sorted(list(set(hawRounds[e['id']])))\n",
|
|
" hawRoundsString[e['id']]= \"\"\n",
|
|
" for r in hawRounds[e['id']]:\n",
|
|
" hawRoundsString[e['id']]+= str(r)+\"_\"\n",
|
|
" if hawRoundsString[e['id']]!=\"\":\n",
|
|
" hawRoundsString[e['id']]=hawRoundsString[e['id']][:-1]\n",
|
|
" \n",
|
|
"nElemHaWishes = sum ([len(elemHaWishes[enc['id']]) for enc in hawishes]) \n",
|
|
"\n",
|
|
"gameAttractivity = { (t1,t2) : attractivity[t1,t2] for (t1,t2) in games if t1<t2 }\n",
|
|
"\n",
|
|
"\n",
|
|
"sorted_gameAttractivity = sorted(gameAttractivity.items(), key=operator.itemgetter(1))\n",
|
|
"\n",
|
|
"nGames= len(games)\n",
|
|
"topGames = [ sorted_gameAttractivity[i] for i in range(int(0.8*0.5*nGames), min( len(sorted_gameAttractivity) , int(0.5*nGames)) ) ]\n",
|
|
"goodGames = [ sorted_gameAttractivity[i] for i in range(int(0.6*0.5*nGames), min( len(sorted_gameAttractivity) , int(0.5*nGames))) ]\n",
|
|
"\n",
|
|
"broadcastingwishes = BroadcastingWish.objects.filter(scenario=s2)\n",
|
|
"\n",
|
|
"\n",
|
|
"nonBlocked = { (t,r) : len(getBasicDays[r]) for r in basicRounds for t in teams}\n",
|
|
"travelDays = { (t,r) : len(getBasicDays[r]) for r in basicRounds for t in teams}\n",
|
|
"hideDays = { (t,r) : len(getBasicDays[r]) for r in basicRounds for t in teams}\n",
|
|
"nonBlockedRounds = { (t,r) : len(getDays[r]) for r in rounds for t in teams}\n",
|
|
"travelRounds = { (t,r) : len(getDays[r]) for r in rounds for t in teams}\n",
|
|
"hideRounds = { (t,r) : len(getDays[r]) for r in rounds for t in teams}\n",
|
|
"\n",
|
|
"for bl in blockings:\n",
|
|
" bl_val =1.0 if bl['time']==\"----\" else 0.5\n",
|
|
" # if bl['time']!=\"----\":\n",
|
|
" # print (bl, bl_val , getDayById[bl['day_id']] ,getDayById[bl['day_id']]['round'] ,getDayById[bl['day_id']]['round'] !=0 )\n",
|
|
" if getDayById[bl['day_id']]['round'] !=0:\n",
|
|
" if bl['type'] in [\"Home\",\"Hide\"]:\n",
|
|
" nonBlocked[( bl['team_id'], getBasicRound[getDayById[bl['day_id']]['round']])]-=bl_val\n",
|
|
" nonBlockedRounds[( bl['team_id'], getDayById[bl['day_id']]['round'])]-=bl_val\n",
|
|
" # print ('FOUND HOME BLOCKING ', bl)\n",
|
|
" if bl['type'] in [\"Away\",\"Hide\"]:\n",
|
|
" travelDays[( bl['team_id'], getBasicRound[getDayById[bl['day_id']]['round']])]-=bl_val\n",
|
|
" travelRounds[( bl['team_id'], getDayById[bl['day_id']]['round'])]-=bl_val\n",
|
|
" # print ('FOUND AWAY BLOCKING ', bl)\n",
|
|
" if bl['type'] in [\"Hide\"]:\n",
|
|
" hideDays[( bl['team_id'], getBasicRound[getDayById[bl['day_id']]['round']])]-=bl_val\n",
|
|
" hideRounds[( bl['team_id'], getDayById[bl['day_id']]['round'])]-=bl_val\n",
|
|
" # print ('FOUND AWAY BLOCKING ', bl)\n",
|
|
"\n",
|
|
"noPlayRounds = { t: [ r for r in rounds if nonBlockedRounds[(t,r)] + travelRounds[(t,r)]==0 ] for t in teams }\n",
|
|
"noHomeRounds = { t: [ r for r in rounds if nonBlockedRounds[(t,r)] ==0 ] for t in teams }\n",
|
|
"# print(\"nonBlockedRounds\" ,nonBlockedRounds)\n",
|
|
"# print(\"noHomeRounds\" ,noHomeRounds)\n",
|
|
"# print(\"noPlayRounds\" ,noPlayRounds)\n",
|
|
"\n",
|
|
"playRounds = { t: sorted([ r for r in rounds if hideRounds[(t,r)]>0 ]) for t in teams }\n",
|
|
"\n",
|
|
"\n",
|
|
"# scale blocking of basic round to [0,1]\n",
|
|
"for t in teams: \n",
|
|
" for r in basicRounds:\n",
|
|
" if len(getBasicDays[r])>0:\n",
|
|
" nonBlocked[(t,r)]/=len(getBasicDays[r])\n",
|
|
" travelDays[(t,r)]/=len(getBasicDays[r])\n",
|
|
" if getTeamById[t]==\"AX Armani Exchange Milan\":\n",
|
|
" print (r , getRealRounds[r] , nonBlocked[(t,r)] , nonBlocked[(t,r)] )\n",
|
|
"\n",
|
|
"for t in teams:\n",
|
|
" if mathModelName==\"UEFA NL\" and noPlayRounds[t] in [ [3,4] ]:\n",
|
|
" t_usePhases[t]= False\n",
|
|
" print (\"No need for phases \" , getTeamById[t])\n",
|
|
" for t2 in opponents[t]:\n",
|
|
" t_usePhases[t2]= False\n",
|
|
" print (\" -- also no need for phases \" , getTeamById[t2])\n",
|
|
" if getTeamById[t]==\"AX Armani Exchange Milan\":\n",
|
|
" t_usePhases[t]= False\n",
|
|
" print (\"setting t_usePhases of \", getTeamById[t],t_usePhases[t] )\n",
|
|
"\n",
|
|
"runPatternAssignmentFirst=False\n",
|
|
"\n",
|
|
"\n",
|
|
"chosenGames = [ ]\n",
|
|
"\n",
|
|
"useFullModel1= False\n",
|
|
"\n",
|
|
"usePatterns= not mathModelName in [\"NHL\", \"LNR\"]\n",
|
|
"usePatterns= not mathModelName in [\"NHL\"]\n",
|
|
"\n",
|
|
"\n",
|
|
"balanceBreaks = mathModelName==\"LNR\" \n",
|
|
"haSymmetric = not mathModelName in [\"NHL\" , \"LNR\"]\n",
|
|
"haSymmetric = not mathModelName in [\"NHL\", \"Ligue 1\", \"Costa Rica Premier League\"]\n",
|
|
"haSymmetric = not mathModelName in [\"NHL\"]\n",
|
|
"# haSymmetric = not mathModelName in [\"NHL\" , \"LNR\"]\n",
|
|
"if thisSeason.symmetry:\n",
|
|
" haSymmetric=True\n",
|
|
"\n",
|
|
"use2BreakPatterns = False\n",
|
|
"\n",
|
|
"if thisSeason.initBreaks>=2 :\n",
|
|
" use2BreakPatterns = True\n",
|
|
"\n",
|
|
"half_symmetry_offset = 0 if thisSeason.symmetry or use2BreakPatterns or not thisSeason.startWithBreakAllowed or not thisSeason.endWithBreakAllowed else 1\n",
|
|
"\n",
|
|
"\n",
|
|
"prev_mirror_round= { r : 0 if r<=nRounds1 else r-nRounds1+half_symmetry_offset for r in basicRounds }\n",
|
|
"\n",
|
|
"\n",
|
|
"for r in basicRounds:\n",
|
|
" if r>nRounds1 and int((r-1)/nRounds1) == int((prev_mirror_round[r]-1)/nRounds1):\n",
|
|
" prev_mirror_round[r] = int((r-1)/nRounds1-1)*nRounds1 +half_symmetry_offset+1-prev_mirror_round[r]%nRounds1\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"getPhaseOfBasicRound={ br : getPhaseOfRound[getRealRounds[br][0]] for br in basicRounds}\n",
|
|
"getBasicRoundsOfPhase={ ph : [ br for br in basicRounds if getPhaseOfBasicRound[br]==ph ] for ph in phases }\n",
|
|
"\n",
|
|
"if use2BreakPatterns or nTeams >200 or not usePatterns or thisSeason.minRoundsBetweenGameOfSameTeams>0 :\n",
|
|
" useFullModel1=True\n",
|
|
"useFullModel1=True \n",
|
|
"\n",
|
|
"\n",
|
|
"preplan_phases = phases\n",
|
|
"preplan_phases= [0]\n",
|
|
"if not haSymmetric:\n",
|
|
" preplan_phases = phases\n",
|
|
"\n",
|
|
"fixedGamesRounds=[]\n",
|
|
"\n",
|
|
"starweight={t : 0.0 for t in teams}\n",
|
|
"for t1 in teams :\n",
|
|
" for t2 in teams :\n",
|
|
" starweight[t1]+=distance[getTeamById[t1],getTeamById[t2]]\n",
|
|
"\n",
|
|
"available_days={ (t,d) : 1 for t in teams for d in days}\n",
|
|
"\n",
|
|
"\n",
|
|
"for bl in blockings:\n",
|
|
" if bl['type'] in [\"Home\",\"Hide\"] and bl['time']=='----':\n",
|
|
" available_days[ bl['team_id'],bl['day_id']] =0\n",
|
|
"\n",
|
|
"t_blocked_at={ (t,r) : sum([available_days[t,d] for d in getDays[r]])==0 for t in teams for r in rounds}"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 24,
|
|
"id": "a11f1f0a",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
" .... got rid of 3006 + 0 vars\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"\n",
|
|
"model2 = pulp.LpProblem(\"League_Scheduling_Model_--_Schedule_Games_\"+str(thisScenario.id), pulp.LpMinimize)\n",
|
|
"\n",
|
|
"\n",
|
|
"nextDay = { d : -1 for d in days }\n",
|
|
"previousDay = { d : -1 for d in days}\n",
|
|
"\n",
|
|
"# cntr=0\n",
|
|
"lastDay=parse(\"01.01.1990\")\n",
|
|
"for thisDay in sorted(getDayByDateTime.keys()):\n",
|
|
" if thisDay-lastDay==datetime.timedelta(days=1):\n",
|
|
" # cntr+=1\n",
|
|
" d1 = getDayByDateTime[lastDay]\n",
|
|
" d2 = getDayByDateTime[thisDay]\n",
|
|
" nextDay[d1]=d2\n",
|
|
" previousDay[d2]=d1\n",
|
|
" # print (\"next day of \" , getNiceDay[d1] , ' ' , getNiceDay[d2])\n",
|
|
" lastDay=thisDay\n",
|
|
"\n",
|
|
"# print (cntr)\n",
|
|
"# cntr=0\n",
|
|
"# for d in days+higherLeagueDayIds :\n",
|
|
"# for d2 in days+higherLeagueDayIds:\n",
|
|
"# if getDateTimeDay[d2]-getDateTimeDay[d]==datetime.timedelta(days=1):\n",
|
|
"# cntr+=1\n",
|
|
"# nextDay[d]=d2\n",
|
|
"# previousDay[d2]=d\n",
|
|
"# print (\"next day of \" , getNiceDay[d] , ' ' , getNiceDay[d2])\n",
|
|
"# print (cntr)\n",
|
|
"\n",
|
|
"\n",
|
|
"cntr= 0\n",
|
|
"cntr2= 0\n",
|
|
"\n",
|
|
"# print (\"games\",games)\n",
|
|
"# print (roundDays)\n",
|
|
"\n",
|
|
"seedTV = []\n",
|
|
"dontPlay = []\n",
|
|
"dontPlayGames = []\n",
|
|
"\n",
|
|
"for bl in blockings:\n",
|
|
" if bl['type']==\"Hide\":\n",
|
|
" dontPlay += [(bl['team_id'],bl['day_id']) ]\n",
|
|
"\n",
|
|
"dontPlay += [(t,d) for d in days for t in teams if getDayMaxGames[d]==0 ] \n",
|
|
"\n",
|
|
"# for t1 in teams: \n",
|
|
"# for d in days:\n",
|
|
"# if blocked_arena[(t1,d, \"----\" )] :\n",
|
|
"# dontPlayGames += [(t1,t2,d) for t2 in teams]\n",
|
|
"\n",
|
|
"\n",
|
|
"# print()\n",
|
|
"# print(len(dontPlayGames) , \" \", len (days)*len(teams)*(len(teams)-1))\n",
|
|
"\n",
|
|
"\n",
|
|
"if mathModelName==\"NBA\":\n",
|
|
" for t1 in teams: \n",
|
|
" for d in days:\n",
|
|
" if blocked_arena[(t1,d, \"----\" )] :\n",
|
|
" dontPlayGames += [(t1,t2,d) for t2 in teams]\n",
|
|
" # print (len(dontPlayGames), \"BLOKING \" )\n",
|
|
"\n",
|
|
" for enc in encwishes:\n",
|
|
" # print (\"ENC \" ,enc , enc['reason'][:11],enc['reason'][:11]== 'TV Network:') \n",
|
|
" if enc['reason'][:11]== 'TV Network:': \n",
|
|
" print (\"ENC \" , encGames[enc['id']] ,encDays[enc['id']] )\n",
|
|
" seedTV += [ (t1,t2,d,enc['reason'][12:]) for (t1,t2) in encGames[enc['id']] for d in encDays[enc['id']]]\n",
|
|
" if enc['maxGames']== 0 and not enc['time'] in [getIdByTime[\"Early\"], getIdByTime[\"Late\"]]:\n",
|
|
" dontPlayGames += [ (t1,t2,d) for (t1,t2) in encGames[enc['id']] for d in encDays[enc['id']]]\n",
|
|
"\n",
|
|
" # print (len(dontPlayGames),encGames[enc['id']] , encDays[enc['id']] , enc['reason'] )\n",
|
|
" \n",
|
|
"\n",
|
|
" usingRDs={t: [] for t in teams}\n",
|
|
" for (t1,t2,d,channel) in seedTV:\n",
|
|
" # print (t1,t2,d , gameCntr[(t1,t2)], gameCntr[(t1,t2)]==1)\n",
|
|
" usingRDs[t1]+=getRoundDaysByDay[d]\n",
|
|
" usingRDs[t2]+=getRoundDaysByDay[d]\n",
|
|
" for d2 in [ previousDay[d], nextDay[d]]:\n",
|
|
" if channel==\"ABC\" and d2!=-1:\n",
|
|
" dontPlay+=[(t1,d2), (t2,d2)]\n",
|
|
"\n",
|
|
" TVteams = [t for t in teams if len (usingRDs[t])>=10 ]\n",
|
|
"\n",
|
|
"# for t in teams: \n",
|
|
"# print (t, getTeamById[t], [ r for (r,d) in usingRDs[t]], t_conference[t]) \n",
|
|
"\n",
|
|
"# print (TVteams)\n",
|
|
"# print (\"CHECKPOINT \", 5)\n",
|
|
"\n",
|
|
"# print (seedTV)\n",
|
|
"# print (dontPlay)\n",
|
|
"\n",
|
|
"x= {(t1,t2,rd) : 0 for t1 in teams for t2 in teams for rd in roundDays}\n",
|
|
"for (t1,t2) in games:\n",
|
|
" for rd in roundDays:\n",
|
|
" x[(t1,t2,rd)]=1\n",
|
|
"\n",
|
|
"for (t1,t2,rd) in x.keys():\n",
|
|
" if blocked_arena[(t1,rd[1],\"----\")] and runMode=='Improve' and not thisSeason.allowBlockingViosInImprove:\n",
|
|
" # cntr +=1\n",
|
|
" # print (\"FORBIDDING\")\n",
|
|
" \n",
|
|
" x[(t1,t2,rd)]=0\n",
|
|
"\n",
|
|
"for (t1,t2,d,channel) in seedTV:\n",
|
|
" if gameCntr[(t1,t2)]==1:\n",
|
|
" for (r,d2) in roundDays:\n",
|
|
" if d != d2 :\n",
|
|
" # cntr +=1\n",
|
|
" x[(t1,t2,(r,d2))]=0\n",
|
|
"\n",
|
|
" for t3 in teams: \n",
|
|
" if not t3 in [t1,t2]:\n",
|
|
" for rd in getRoundDaysByDay[d]:\n",
|
|
" x[(t1,t3,rd)]=0\n",
|
|
" x[(t2,t3,rd)]=0\n",
|
|
" x[(t3,t1,rd)]=0\n",
|
|
" x[(t3,t2,rd)]=0\n",
|
|
" # cntr +=4\n",
|
|
"\n",
|
|
"for (t,d) in dontPlay:\n",
|
|
" for t3 in teams:\n",
|
|
" if not t3 in [t1,t2]:\n",
|
|
" for rd in getRoundDaysByDay[d]:\n",
|
|
" x[(t,t3,rd)]=0\n",
|
|
" x[(t3,t,rd)]=0\n",
|
|
"\n",
|
|
"for (t1,t2,d) in dontPlayGames:\n",
|
|
" for rd in getRoundDaysByDay[d]:\n",
|
|
" x[(t1,t2,rd)]=0\n",
|
|
"\n",
|
|
"attendance = { (t1,t2,d) : 0 for (t1,t2) in games for d in days }\n",
|
|
"if thisSeason.useFeaturePrediction:\n",
|
|
" # learner = AttendanceLearner(thisSeason.id)\n",
|
|
" # attendance = learner.predict_games(attendance.keys())\n",
|
|
" oldestTrainingGame= parse(\"2015-01-01\")\n",
|
|
" oldestTrainingGame=oldestTrainingGame.date()\n",
|
|
" games_train = Game.objects.filter(season=thisSeason).exclude(historic_season=None)\n",
|
|
" print ( \" all games\",len(games_train), )\n",
|
|
" games_train = [g for g in games_train if g.date>oldestTrainingGame ]\n",
|
|
" print ( \" important games\",len(games_train), )\n",
|
|
"\n",
|
|
" games_predict = attendance.keys()\n",
|
|
"\n",
|
|
" X= []\n",
|
|
" y =[]\n",
|
|
" homeAttendances = {t: [] for t in teams+inactive_teams}\n",
|
|
" for game in games_train:\n",
|
|
" if game.attendance>0:\n",
|
|
" homeAttendances[game.homeTeam.id].append(game.attendance)\n",
|
|
" for t in teams+inactive_teams:\n",
|
|
" homeAttendances[t]=sorted(homeAttendances[t])\n",
|
|
" # print (getTeamById[t], homeAttendances[t])\n",
|
|
" if len(homeAttendances[t])==0:\n",
|
|
" homeAttendances[t]=[7500]\n",
|
|
" maxAttendance = {t: homeAttendances[t][-1] for t in teams+inactive_teams }\n",
|
|
" # maxAttendance = {t: homeAttendances[t][int(0.9*(len(homeAttendances[t])))] for t in teams+inactive_teams }\n",
|
|
" medianAttendance = {t: homeAttendances[t][int(0.5*(len(homeAttendances[t])))] for t in teams+inactive_teams }\n",
|
|
" loyalty = {t: medianAttendance[t]/maxAttendance[t] for t in teams+inactive_teams }\n",
|
|
"\n",
|
|
" for t in teams+inactive_teams: \n",
|
|
" print (getTeamById[t], loyalty[t] , medianAttendance[t] , maxAttendance[t] , )\n",
|
|
"\n",
|
|
"# x= {(t1,t2,rd) : 0 for t1 in teams for t2 in teams for rd in roundDays}\n",
|
|
"x_round= {(t1,t2,r) : 0 for t1 in teams for t2 in teams for r in rounds}\n",
|
|
"x_time= {(t1,t2,rd,tm) : 0 for t1 in teams for t2 in teams for rd in roundDays for tm in times}\n",
|
|
"\n",
|
|
"\n",
|
|
"for (t1,t2) in games:\n",
|
|
" for rd in roundDays:\n",
|
|
" # print (\"make var \" ,t1,t2,rd)\n",
|
|
" if x[(t1,t2,rd)]==1 :\n",
|
|
" # if not blocked_arena[(t1,rd[1],\"----\")] or runMode=='New':\n",
|
|
" if not evalRun:\n",
|
|
" x[(t1,t2,rd)] = pulp.LpVariable('x_'+str(t1)+'_'+str(t2)+'_'+str(rd[0])+'_'+str(rd[1]), lowBound = 0, upBound = 1, cat = pulp.LpContinuous) \n",
|
|
" cntr +=1\n",
|
|
" if thisSeason.useFeatureKickOffTime:\n",
|
|
" for tm in times:\n",
|
|
" x_time[(t1,t2,rd,tm)] = pulp.LpVariable('x_'+str(t1)+'_'+str(t2)+'_'+str(rd[0])+'_'+str(rd[1])+'_'+tm , lowBound = 0, upBound = 1, cat = pulp.LpContinuous) \n",
|
|
" else: \n",
|
|
" cntr+=len(roundDays)\n",
|
|
"\n",
|
|
" for r in rounds:\n",
|
|
" x_round[(t1,t2,r)]= pulp.LpVariable('x_round_'+str(t1)+'_'+str(t2)+'_'+str(r), lowBound = 0, upBound = 1, cat = pulp.LpContinuous)\n",
|
|
" model2+= x_round[(t1,t2,r)] == sum([x[(t1,t2,rd)] for rd in getRoundDaysByRound[r]])\n",
|
|
"\n",
|
|
"\n",
|
|
"t_prev_mirror_round ={(t,r) : 0 for t in teams for r in rounds}\n",
|
|
"\n",
|
|
"for t1 in teams: \n",
|
|
" phaseLength= int(len(playRounds[t1])/nPhases+0.5)\n",
|
|
" # print (\"phaseLength\", phaseLength)\n",
|
|
" for i in range(len(playRounds[t1])):\n",
|
|
" # print (i, phaseLength)\n",
|
|
" if i >=phaseLength:\n",
|
|
" # print (\"setting \" , playRounds[t1], playRounds[t1][i-phaseLength])\n",
|
|
" # print (\"setting \" , playRounds[t1][i], \"->\",playRounds[t1][i-phaseLength])\n",
|
|
" t_prev_mirror_round[(t1,playRounds[t1][i])]=playRounds[t1][i-phaseLength]\n",
|
|
" # t_prev_mirror_round[(t,playRounds[t1][i])]=5\n",
|
|
"\n",
|
|
"\n",
|
|
"# for tr in t_prev_mirror_round.keys():\n",
|
|
"# print( \"t_prev_mirror_round \" ,tr , t_prev_mirror_round[tr])\n",
|
|
"\n",
|
|
"# print (prev_mirror_round)\n",
|
|
"\n",
|
|
"\n",
|
|
"if not evalRun:\n",
|
|
" for (t1,t2) in games:\n",
|
|
" for r in rounds:\n",
|
|
" if r > nRounds1 and thisSeason.symmetry : \n",
|
|
" prev_round =prev_mirror_round[r] \n",
|
|
" if thisSeason.groupBased and len(noPlayRounds[t1])>0 and noPlayRounds[t1]==noPlayRounds[t2]:\n",
|
|
" prev_round=t_prev_mirror_round[t1,r]\n",
|
|
"\n",
|
|
" if prev_round>0:\n",
|
|
" model2+= x_round[(t1,t2,r)] == x_round[(t2,t1,prev_round)]\n",
|
|
" # print (\"x_round[(\",t1,\",\",t2,\",\",r,\")] == x_round[(\",t2,t1,prev_mirror_round[r],\")]\")\n",
|
|
" # print ( t1,t2,r , \" -> \",prev_mirror_round[r])\n",
|
|
"\n",
|
|
"\n",
|
|
" \n",
|
|
"\n",
|
|
"for (t1,t2,(r,d)) in x.keys():\n",
|
|
" if thisSeason.useFeatureKickOffTime:\n",
|
|
" for tm in times :\n",
|
|
" if blocked_arena[(t1,d,tm)] and runMode=='Improve':\n",
|
|
" x_time[(t1,t2,(r,d), tm)]=0\n",
|
|
" # print (\"forbidding tm \", t1,t2,r,d, tm)\n",
|
|
" cntr2+=1\n",
|
|
" # print (\"FORBIDDING\")\n",
|
|
" \n",
|
|
"\n",
|
|
"print (\" .... got rid of \" , len(x.keys())-cntr, \" + \" ,cntr2, \" vars\") \n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"for (t1,t2,d,channel) in seedTV:\n",
|
|
" print (t1,t2,d , gameCntr[(t1,t2)], gameCntr[(t1,t2)]==1)\n",
|
|
" model2+= sum([x[(t1,t2,rd)] for rd in getRoundDaysByDay[d] ])==1\n",
|
|
"\n",
|
|
"# model2+= lpSum( x[rr] for rr in x.keys() )\n",
|
|
"# model2.solve(XPRESS(msg=1,maxSeconds = 25, keepFiles=True))\n",
|
|
"# return \"\"\n",
|
|
"\n",
|
|
"homeInRound= {(t1,r) : pulp.LpVariable('homeInRound_'+str(t1)+'_'+str(r), lowBound = 0, upBound = 1, cat = pulp.LpContinuous) for t1 in teams for r in rounds}\n",
|
|
"awayInRound= {(t1,r) : pulp.LpVariable('awayInRound_'+str(t1)+'_'+str(r), lowBound = 0, upBound = 1, cat = pulp.LpContinuous) for t1 in teams for r in rounds}\n",
|
|
"gameInBasicRound= {(t1,t2,r) : pulp.LpVariable('gameInBasicRound_'+str(t1)+'_'+str(t2)+'_'+str(r), lowBound = 0, upBound = defaultGameRepetions, cat = pulp.LpContinuous) for (t1,t2) in games for r in basicRounds}\n",
|
|
"homeInBasicRound= {(t1,r) : pulp.LpVariable('homeInBasicRound_'+str(t1)+'_'+str(r), lowBound = 0, cat = pulp.LpContinuous) for t1 in teams for r in basicRounds}\n",
|
|
"awayInBasicRound= {(t1,r) : pulp.LpVariable('awayInBasicRound_'+str(t1)+'_'+str(r), lowBound = 0, cat = pulp.LpContinuous) for t1 in teams for r in basicRounds}\n",
|
|
"break3InRound= {(t1,r) : pulp.LpVariable('break3InRound_'+str(t1)+'_'+str(r), lowBound = 0, cat = pulp.LpContinuous) for t1 in teams for r in rounds}\n",
|
|
"# breakInRound= {(t1,r) : pulp.LpVariable('breakInRound_'+str(t1)+'_'+str(r), lowBound = 0, upBound = 1, cat = pulp.LpContinuous) for t1 in teams for r in rounds}\n",
|
|
"# breaksTotal = pulp.LpVariable('breaksTotal', lowBound = 0, cat = pulp.LpContinuous)\n",
|
|
"tooManyTop4InRow= {(t1,r) : pulp.LpVariable('tooManyTop4InRow_'+str(t1)+'_'+str(r), lowBound = 0, upBound = 1, cat = pulp.LpContinuous) for t1 in teams for r in rounds}\n",
|
|
"\n",
|
|
"\n",
|
|
"tooManyHomesInStadium= {(stadium,d) : pulp.LpVariable('tooManyHomesInStadium_'+str(stadium)+'_'+str(d), lowBound = 0, cat = pulp.LpContinuous) for stadium in stadiums for d in days}\n",
|
|
"pairingVio= {(pair['id'],d) : pulp.LpVariable('pairingVio_'+str(pair['id'])+'_'+str(d), lowBound = 0, cat = pulp.LpContinuous) for pair in pairings for d in days}\n",
|
|
"derbyMissing= {d : pulp.LpVariable('derbyMissing_'+str(d), lowBound = 0, cat = pulp.LpContinuous) for d in days}\n",
|
|
"\n",
|
|
"breakVio = { (br['id'],t) : pulp.LpVariable('breakVio_'+ str(br['id'])+'_'+str(t) , lowBound = 0, cat = pulp.LpContinuous) for br in breaks for t in teams}\n",
|
|
"blockingVio = { bl['id'] : pulp.LpVariable('blockingVio_'+ str(bl['id']) , lowBound = 0, cat = pulp.LpContinuous) for bl in blockings}\n",
|
|
"# blockingVioTotal = pulp.LpVariable('blockingVioTotal', lowBound = 0, cat = pulp.LpContinuous)\n",
|
|
"\n",
|
|
"hawVio = { haw['id'] : pulp.LpVariable('hawVio'+ str(haw['id']) , lowBound = 0, cat = pulp.LpContinuous) for haw in hawishes}\n",
|
|
"HawVioTooLess = { el : pulp.LpVariable('havviotooless_'+ str(el) , lowBound = 0, cat = pulp.LpContinuous) for haw in hawishes for el in elemHaWishes[haw['id']] }\n",
|
|
"HawVioTooMuch = { el : pulp.LpVariable('havviotoomuch_'+ str(el) , lowBound = 0, cat = pulp.LpContinuous) for haw in hawishes for el in elemHaWishes[haw['id']] }\n",
|
|
"# HawVioTotal = pulp.LpVariable('HawVioTotal', lowBound = 0, cat = pulp.LpContinuous)\n",
|
|
"encVio = { enc['id'] : pulp.LpVariable('encVio'+ str(enc['id']) , lowBound = 0, cat = pulp.LpContinuous) for enc in encwishes}\n",
|
|
"encVioTooLess = { el : pulp.LpVariable('encViotooless'+ str(enc['id'])+\"_\"+str(el) , lowBound = 0, cat = pulp.LpContinuous) for enc in encwishes for el in elemEncWishes[enc['id']]}\n",
|
|
"encVioTooMuch = { el : pulp.LpVariable('encViotoomuch'+ str(enc['id'])+\"_\"+str(el) , lowBound = 0, cat = pulp.LpContinuous) for enc in encwishes for el in elemEncWishes[enc['id']]}\n",
|
|
"# encVioTotal = pulp.LpVariable('encVioTotal', lowBound = 0, cat = pulp.LpContinuous)\n",
|
|
"# broadVio = { d : pulp.LpVariable('broadVio'+ str(d) , lowBound = 0, cat = pulp.LpContinuous) for d in days}\n",
|
|
"broadVioTm = { (b.id, r): pulp.LpVariable('broadVioTm_'+ str(b.id) +\"_\"+ str(r) , lowBound = 0, cat = pulp.LpContinuous) for b in broadcastingwishes for r in rounds}\n",
|
|
"gamesTooClose2 = { (t,r) : pulp.LpVariable('gamesTooClose2_'+ str(t) +'_'+ str(r) , lowBound = 0, cat = pulp.LpContinuous) for t in teams for r in rounds }\n",
|
|
"missingGamesVio = { (t1,t2) : pulp.LpVariable('missingGamesVio_'+ str(t1) +'_'+str(t2) , lowBound = 0, cat = pulp.LpContinuous) for (t1,t2) in games}\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 25,
|
|
"id": "7bc64f33",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"rounds range(1, 35) 34\n",
|
|
"realteams [10, 3, 17, 14, 15, 13, 12, 6, 9, 5, 8, 18, 19, 20, 11, 7, 4, 16]\n",
|
|
"taking care of right numbers of games ... \n",
|
|
"0 17 3 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17] [4, 13, 16] ratiopharm ulm\n",
|
|
"1 17 3 [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34] [19, 30, 34] ratiopharm ulm\n",
|
|
"0 17 6 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17] [1, 5, 9, 10, 12, 16] Basketball Löwen Braunschweig\n",
|
|
"1 17 9 [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34] [18, 19, 20, 22, 23, 26, 29, 30, 33] Basketball Löwen Braunschweig\n",
|
|
"0 17 2 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17] [7, 14] MHP RIESEN Ludwigsburg\n",
|
|
"1 17 6 [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34] [18, 21, 23, 25, 28, 29] MHP RIESEN Ludwigsburg\n",
|
|
"0 17 4 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17] [2, 9, 11, 12] BG Göttingen\n",
|
|
"1 17 5 [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34] [19, 21, 29, 31, 33] BG Göttingen\n",
|
|
"0 17 0 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17] [] SYNTAINICS MBC\n",
|
|
"1 17 4 [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34] [19, 21, 29, 31] SYNTAINICS MBC\n",
|
|
"0 17 6 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17] [1, 4, 9, 12, 13, 16] FRAPORT SKYLINERS\n",
|
|
"1 17 8 [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34] [19, 21, 23, 25, 27, 29, 31, 33] FRAPORT SKYLINERS\n",
|
|
"0 17 5 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17] [2, 4, 11, 13, 16] FC Bayern München\n",
|
|
"1 17 5 [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34] [20, 23, 27, 32, 34] FC Bayern München\n",
|
|
"0 17 2 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17] [4, 17] Brose Bamberg\n",
|
|
"1 17 1 [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34] [23] Brose Bamberg\n",
|
|
"0 17 3 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17] [1, 5, 6] ALBA BERLIN\n",
|
|
"1 17 5 [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34] [18, 19, 21, 31, 33] ALBA BERLIN\n",
|
|
"0 17 6 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17] [2, 3, 5, 10, 15, 17] Hamburg Towers\n",
|
|
"1 17 4 [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34] [19, 21, 24, 30] Hamburg Towers\n",
|
|
"0 17 6 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17] [5, 6, 11, 12, 16, 17] EWE Baskets Oldenburg\n",
|
|
"1 17 5 [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34] [19, 20, 22, 25, 28] EWE Baskets Oldenburg\n",
|
|
"0 17 6 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17] [2, 4, 9, 13, 15, 17] HAKRO Merlins Crailsheim\n",
|
|
"1 17 3 [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34] [23, 29, 31] HAKRO Merlins Crailsheim\n",
|
|
"0 17 7 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17] [2, 5, 6, 9, 10, 13, 15] medi bayreuth\n",
|
|
"1 17 2 [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34] [24, 27] medi bayreuth\n",
|
|
"0 17 4 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17] [6, 9, 15, 17] NINERS Chemnitz\n",
|
|
"1 17 7 [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34] [18, 19, 23, 24, 31, 33, 34] NINERS Chemnitz\n",
|
|
"0 17 0 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17] [] MLP Academics Heidelberg\n",
|
|
"1 17 2 [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34] [21, 29] MLP Academics Heidelberg\n",
|
|
"0 17 2 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17] [11, 12] JobStairs Gießen 46ers\n",
|
|
"1 17 4 [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34] [18, 21, 31, 33] JobStairs Gießen 46ers\n",
|
|
"0 17 4 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17] [1, 4, 7, 10] Telekom Baskets Bonn\n",
|
|
"1 17 4 [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34] [19, 20, 22, 25] Telekom Baskets Bonn\n",
|
|
"0 17 5 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17] [6, 14, 15, 16, 17] s.Oliver Würzburg\n",
|
|
"1 17 3 [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34] [23, 25, 34] s.Oliver Würzburg\n",
|
|
"check 1\n",
|
|
"check 2\n",
|
|
"- mindestens ein Heimspiel in den letzten zwei Wochen vor Weihnachten\n",
|
|
"ALBA hat nur Option\n",
|
|
"ALBA sollte nicht am Freitag Auswärts spielen\n",
|
|
"ALBA sollte nicht am Freitag Heim spielen\n",
|
|
"ALBA sollte nicht am Samstag Auswärts spielen\n",
|
|
"ALBA sollte nicht am Samstag Heim spielen\n",
|
|
"BBL 21 unbedingt Heimspiel am 14. 02.\n",
|
|
"BBL10 hätten wir gerne ein Heimspiel, da an BBL9, BBL11 + BBL12 die Arena leider nicht zur Verfügung steht.\n",
|
|
"Bitte Heimspiele aufgrund möglicher Verlegung durch Kollision mit EL-Spielen\n",
|
|
"Christmas Day on Dec 11, 2022 at 15:00\n",
|
|
"Da wir die reguläre Saison 21/22 mit drei Auswärtsspielen beenden, bitte ich um ein Heimspiel bei BBL 34 (BBL 33 ist nicht verfügbar).\n",
|
|
"Easter Special on April 08,2023 at 20: 30\n",
|
|
"Gerne Heimspiele an den Spieltagen 11, 12 und 13, da wir dort die Halle stehen lassen können.\n",
|
|
"In February 2023 (National Team Window) we need at least one home game, otherwise team is absent for interactions with fans for too long.\n",
|
|
"In November 2022 (National Team Window) we need at least one home game, otherwise team is absent for interactions with fans for too long.\n",
|
|
"gerne ein Heimspiel \"zwischen den Jahren\"\n",
|
|
"check 3\n",
|
|
"{'id': 12, 'useEncounterGroups': False, 'useGroups': False, 'forEachTeam1': True, 'forEachTeam2': False, 'day_id': 100, 'day2_id': 198, 'multidate': False, 'timeframe': -7, 'forEachDay': True, 'forOneDay': False, 'forOneDayNum': 1, 'symmetry': False, 'weekdays': '--', 'time': '----', 'minGames': -1, 'maxGames': 1, 'prio': 'B', 'reason': 'die Heimspiele gegen Bayern und Alba zeitlich gerne so weit wie möglich auseinander\\r\\nx', 'violation': 'Fri, Mar 10, 2023 <br>HAKRO Merlins Crailsheim<br> 1 too many<br><br>Fri, Mar 17, 2023 <br>HAKRO Merlins Crailsheim<br> 1 too many<br><br>Fri, Mar 24, 2023 <br>HAKRO Merlins Crailsheim<br> 1 too many<br><br>Fri, Mar 31, 2023 <br>HAKRO Merlins Crailsheim<br> 1 too many<br><br>Sat, Apr 08, 2023 <br>HAKRO Merlins Crailsheim<br> 1 too many<br><br>Fri, Apr 14, 2023 <br>HAKRO Merlins Crailsheim<br> 1 too many<br><br>', 'active': True, 'scenario_id': 2, 'affected_rounds': '1_2_3_4_5_6_7_8_9_10_11_12_13_14_15_16_17_18_19_20_21_22_23_24_25_26_27_28_29_30_31_32_33_34'}\n",
|
|
"{'id': 13, 'useEncounterGroups': False, 'useGroups': False, 'forEachTeam1': False, 'forEachTeam2': False, 'day_id': 100, 'day2_id': None, 'multidate': False, 'timeframe': 1, 'forEachDay': False, 'forOneDay': False, 'forOneDayNum': 1, 'symmetry': False, 'weekdays': '--', 'time': '----', 'minGames': 1, 'maxGames': -1, 'prio': 'B', 'reason': 'Seed Game', 'violation': '', 'active': True, 'scenario_id': 2, 'affected_rounds': '1'}\n",
|
|
"{'id': 14, 'useEncounterGroups': False, 'useGroups': False, 'forEachTeam1': False, 'forEachTeam2': False, 'day_id': 100, 'day2_id': 109, 'multidate': False, 'timeframe': 1, 'forEachDay': False, 'forOneDay': False, 'forOneDayNum': 1, 'symmetry': False, 'weekdays': '--', 'time': '----', 'minGames': 1, 'maxGames': -1, 'prio': 'B', 'reason': 'das Derby gegen Ludwigsburg als erstes Heimspiel', 'violation': ' 1 too few<br><br>', 'active': True, 'scenario_id': 2, 'affected_rounds': '1_2_3'}\n",
|
|
"{'id': 15, 'useEncounterGroups': False, 'useGroups': False, 'forEachTeam1': False, 'forEachTeam2': False, 'day_id': 123, 'day2_id': None, 'multidate': False, 'timeframe': 1, 'forEachDay': False, 'forOneDay': False, 'forOneDayNum': 1, 'symmetry': False, 'weekdays': '--', 'time': '----', 'minGames': 1, 'maxGames': -1, 'prio': 'B', 'reason': 'Seed Game', 'violation': '', 'active': True, 'scenario_id': 2, 'affected_rounds': '7'}\n",
|
|
"{'id': 16, 'useEncounterGroups': False, 'useGroups': False, 'forEachTeam1': False, 'forEachTeam2': False, 'day_id': 135, 'day2_id': None, 'multidate': False, 'timeframe': 1, 'forEachDay': False, 'forOneDay': False, 'forOneDayNum': 1, 'symmetry': False, 'weekdays': '--', 'time': '----', 'minGames': 1, 'maxGames': -1, 'prio': 'B', 'reason': 'Verlegung Spieltag 10 oder 11 auf den 23.12.2022! Prio 1 ist ein Weihnachtsspiel am 23.12.2022 :-). Bitte keine europäische Mannschaft zwecks Verschiebungen.', 'violation': '', 'active': True, 'scenario_id': 2, 'affected_rounds': '11'}\n",
|
|
"{'id': 17, 'useEncounterGroups': True, 'useGroups': False, 'forEachTeam1': False, 'forEachTeam2': False, 'day_id': 135, 'day2_id': 136, 'multidate': False, 'timeframe': 1, 'forEachDay': False, 'forOneDay': False, 'forOneDayNum': 1, 'symmetry': False, 'weekdays': '--', 'time': '----', 'minGames': 9, 'maxGames': -1, 'prio': 'B', 'reason': 'Derbyspieltag', 'violation': '', 'active': True, 'scenario_id': 2, 'affected_rounds': '11'}\n",
|
|
"{'id': 18, 'useEncounterGroups': False, 'useGroups': False, 'forEachTeam1': False, 'forEachTeam2': False, 'day_id': 137, 'day2_id': 138, 'multidate': True, 'timeframe': 1, 'forEachDay': False, 'forOneDay': False, 'forOneDayNum': 1, 'symmetry': False, 'weekdays': '--', 'time': '----', 'minGames': 4, 'maxGames': -1, 'prio': 'B', 'reason': 'Bitte Heimspiele aufgrund möglicher Verlegung durch Kollision mit EL-Spielen:BBL München 12 (29./30.12.)BBL 18 (31.01./01.02)BBL 29 (18./19.04.)BBL 31 (25./26.04.) Diese\\r\\nHeimspiele wenn möglich gegen nicht europäisch spielende Mannschaften, so dass eine Verlegung problemlos möglich ist.', 'violation': '', 'active': True, 'scenario_id': 2, 'affected_rounds': '12_18_29_31'}\n",
|
|
"{'id': 19, 'useEncounterGroups': False, 'useGroups': False, 'forEachTeam1': False, 'forEachTeam2': False, 'day_id': 154, 'day2_id': 157, 'multidate': False, 'timeframe': 1, 'forEachDay': False, 'forOneDay': False, 'forOneDayNum': 1, 'symmetry': True, 'weekdays': '--', 'time': '----', 'minGames': -1, 'maxGames': 0, 'prio': 'B', 'reason': 'Spieltag 18 nicht gegen München, Berlin und Giessen', 'violation': '', 'active': True, 'scenario_id': 2, 'affected_rounds': '18'}\n",
|
|
"{'id': 20, 'useEncounterGroups': False, 'useGroups': False, 'forEachTeam1': False, 'forEachTeam2': False, 'day_id': 166, 'day2_id': None, 'multidate': False, 'timeframe': 1, 'forEachDay': False, 'forOneDay': False, 'forOneDayNum': 1, 'symmetry': False, 'weekdays': '--', 'time': '----', 'minGames': 1, 'maxGames': -1, 'prio': 'B', 'reason': 'Seed Game', 'violation': '', 'active': True, 'scenario_id': 2, 'affected_rounds': '22'}\n",
|
|
"{'id': 21, 'useEncounterGroups': False, 'useGroups': False, 'forEachTeam1': False, 'forEachTeam2': False, 'day_id': 179, 'day2_id': None, 'multidate': False, 'timeframe': 1, 'forEachDay': False, 'forOneDay': False, 'forOneDayNum': 1, 'symmetry': False, 'weekdays': '--', 'time': '----', 'minGames': 1, 'maxGames': -1, 'prio': 'B', 'reason': 'Seed Game', 'violation': '', 'active': True, 'scenario_id': 2, 'affected_rounds': '27'}\n",
|
|
"{'id': 22, 'useEncounterGroups': False, 'useGroups': False, 'forEachTeam1': False, 'forEachTeam2': False, 'day_id': 184, 'day2_id': None, 'multidate': False, 'timeframe': 1, 'forEachDay': False, 'forOneDay': False, 'forOneDayNum': 1, 'symmetry': False, 'weekdays': '--', 'time': '----', 'minGames': 1, 'maxGames': -1, 'prio': 'B', 'reason': 'Seed Game', 'violation': '', 'active': True, 'scenario_id': 2, 'affected_rounds': '28'}\n",
|
|
"check 4\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"\n",
|
|
"home={}\n",
|
|
"away={}\n",
|
|
"home_time={}\n",
|
|
"away_time={}\n",
|
|
"away_in_cluster={}\n",
|
|
"away_in_cluster_day={}\n",
|
|
"\n",
|
|
"getRoundDaysByBasicRound={br : [rd for r in getRealRounds[br] for rd in getRoundDaysByRound[r]] for br in basicRounds}\n",
|
|
"getMaxGameOnRoundDaysByBasicRound={br : sum ( roundDaysMax[rd] for r in getRealRounds[br] for rd in getRoundDaysByRound[r]) for br in basicRounds}\n",
|
|
"\n",
|
|
"for t in realteams:\n",
|
|
" for d in days:\n",
|
|
" away[t,d] = lpSum([x[(t2,t,rd)] for t2 in opponents[t] for rd in getRoundDaysByDay[d]]) or pulp.LpVariable('away'+str(t)+'_'+str(d), lowBound = 0, upBound = 0, cat = pulp.LpContinuous)\n",
|
|
" home[t,d] = lpSum([x[(t,t2,rd)] for t2 in opponents[t] for rd in getRoundDaysByDay[d]]) or pulp.LpVariable('home'+str(t)+'_'+str(d), lowBound = 0, upBound = 0, cat = pulp.LpContinuous)\n",
|
|
" if thisSeason.useFeatureKickOffTime:\n",
|
|
" for t2 in opponents[t]:\n",
|
|
" # print (t,t2,getTeamById[t], getTeamById[t2], (t,t2) in games )\n",
|
|
" # if (t,t2) in games:\n",
|
|
" for rd in getRoundDaysByDay[d]:\n",
|
|
" # TODO: HOTFIX\n",
|
|
" if (x[(t2,t,rd)] != 0): \n",
|
|
" model2+= x[(t2,t,rd)] == lpSum([ x_time[(t2,t,rd,tm)] for tm in times])\n",
|
|
" for tm in times:\n",
|
|
" away_time[t,d,tm] = lpSum([x_time[(t2,t,rd,tm)] for t2 in opponents[t] for rd in getRoundDaysByDay[d] ])\n",
|
|
" home_time[t,d,tm] = lpSum([x_time[(t,t2,rd,tm)] for t2 in opponents[t] for rd in getRoundDaysByDay[d] ])\n",
|
|
"\n",
|
|
"for t in realteams:\n",
|
|
" for r in rounds:\n",
|
|
" # awayInRound[t,r] = lpSum([x[(t2,t,dr)] for t2 in teams for dr in getRoundDaysByRound[r]])\n",
|
|
" # homeInRound[t,r] = lpSum([x[(t,t2,dr)] for t2 in teams for dr in getRoundDaysByRound[r]])\n",
|
|
" \n",
|
|
" if thisSeason.gamesPerRound==\"one day\":\n",
|
|
" # model2 += homeInRound[(t,r)] == lpSum([home[(t,d)] for (r2,d) in getRoundDaysByRound[r]])\n",
|
|
" model2 += homeInRound[(t,r)] == lpSum([x[(t,t2,rd)] for t2 in opponents[t] for rd in getRoundDaysByRound[r]])\n",
|
|
" model2 += awayInRound[(t,r)] == lpSum([x[(t2,t,rd)] for t2 in opponents[t] for rd in getRoundDaysByRound[r]])\n",
|
|
" else:\n",
|
|
" model2 += homeInRound[(t,r)] == lpSum([x[(t,t2,getRoundDaysByRound[r][0])] for t2 in opponents[t] ])\n",
|
|
" model2 += awayInRound[(t,r)] == lpSum([x[(t2,t,getRoundDaysByRound[r][0])] for t2 in opponents[t] ])\n",
|
|
"\n",
|
|
" model2 += homeInRound[(t,r)] + awayInRound[(t,r)] <= 1\n",
|
|
" if r>=3:\n",
|
|
" model2 += break3InRound[(t,r)] +2>= homeInRound[(t,r-2)]+homeInRound[(t,r-1)]+homeInRound[(t,r)] \n",
|
|
" model2 += break3InRound[(t,r)] +2>= awayInRound[(t,r-2)]+awayInRound[(t,r-1)]+awayInRound[(t,r)] \n",
|
|
"\n",
|
|
" if r>1:\n",
|
|
" if thisSeason.gamesPerRound==\"one day\":\n",
|
|
" model2 += lpSum([x[(t,t4,d)]+x[(t4,t,d)] for t4 in top4 for d in (getRoundDaysByRound[r-1]+getRoundDaysByRound[r]) if t4 in opponents[t] ]) <= 1+tooManyTop4InRow[(t,r)]\n",
|
|
" else:\n",
|
|
" model2 += lpSum([x[(t,t4,d)]+x[(t4,t,d)] for t4 in top4 for d in [getRoundDaysByRound[r-1][0],getRoundDaysByRound[r][0]] if t4 in opponents[t] ]) <= 1+tooManyTop4InRow[(t,r)]\n",
|
|
"\n",
|
|
"\n",
|
|
"breakVioBalance = { t : pulp.LpVariable('breakVioBalance_'+str(t) , lowBound = 0, cat = pulp.LpContinuous) for t in realteams }\n",
|
|
"numBreaks = { t : lpSum([ breakVio[(bl['id'],t)] for bl in breaks ]) for t in realteams }\n",
|
|
"\n",
|
|
"\n",
|
|
"succBreaks = [ bl for bl in breaks if bl['round1']+1==bl['round2'] ]\n",
|
|
"\n",
|
|
"if thisSeason.forbidDoubleBreaks:\n",
|
|
" for bl1 in succBreaks:\n",
|
|
" for bl2 in succBreaks:\n",
|
|
" if bl1['round2']+1==bl2['round1']:\n",
|
|
" for t in realteams:\n",
|
|
" model2+= homeInRound[t,bl1['round1']] + homeInRound[t,bl1['round2']] + awayInRound[t,bl2['round1']] + awayInRound[t,bl2['round2']] <= 3 + 0.2* breakVio[(bl1['id'],t)] \n",
|
|
" model2+= awayInRound[t,bl1['round1']] + awayInRound[t,bl1['round2']] + homeInRound[t,bl2['round1']] + homeInRound[t,bl2['round2']] <= 3 + 0.2* breakVio[(bl1['id'],t)] \n",
|
|
"\n",
|
|
"for t in realteams:\n",
|
|
" for bl in breaks:\n",
|
|
" # print (getTeamById[t], realteams, getRoundDaysByRound[bl['round1']]+getRoundDaysByRound[bl['round2']] )\n",
|
|
" # model2+= breakVio[(bl['id'],t)] + 1 >= lpSum([x[(t,t2,rd)] for t2 in realteams for rd in getRoundDaysByRound[bl['round1']]+getRoundDaysByRound[bl['round2']] ])\n",
|
|
" # model2+= breakVio[(bl['id'],t)] + 1 >= lpSum([x[(t2,t,rd)] for t2 in realteams for rd in getRoundDaysByRound[bl['round1']]+getRoundDaysByRound[bl['round2']] ])\n",
|
|
" model2+= breakVio[(bl['id'],t)] + 1 >= homeInRound[t,bl['round1']] + homeInRound[t,bl['round2']]\n",
|
|
" model2+= breakVio[(bl['id'],t)] + 1 >= awayInRound[t,bl['round1']] + awayInRound[t,bl['round2']]\n",
|
|
" if bl['round2'] + 1 <= nRounds:\n",
|
|
" model2+= 0.2+breakVio[(bl['id'],t)] + 2 >= homeInRound[t,bl['round1']] + homeInRound[t,bl['round2']] + homeInRound[t,bl['round2']+1] \n",
|
|
" model2+= 0.2+breakVio[(bl['id'],t)] + 2 >= awayInRound[t,bl['round1']] + awayInRound[t,bl['round2']] + awayInRound[t,bl['round2']+1] \n",
|
|
"\n",
|
|
" if balanceBreaks:\n",
|
|
" model2+= numBreaks[t] <= lpSum([ numBreaks[t2] for t2 in realteams])/len(realteams) + breakVioBalance[t]\n",
|
|
" for t2 in teams: \n",
|
|
" if half_symmetry_offset==0:\n",
|
|
" model2+= numBreaks[t2] <= 4\n",
|
|
" model2+= numBreaks[t2] >= 3\n",
|
|
" else:\n",
|
|
" model2+= numBreaks[t2] <= 5\n",
|
|
" model2+= numBreaks[t2] >= 1\n",
|
|
" print (\"balancing Breaks \")\n",
|
|
"\n",
|
|
" for bl in breaks:\n",
|
|
" model2+= breakVio[(bl['id'],t)] <= 2 - homeInRound[t,bl['round1']] - awayInRound[t,bl['round2']] \n",
|
|
" model2+= breakVio[(bl['id'],t)] <= 2 - awayInRound[t,bl['round1']] - homeInRound[t,bl['round2']]\n",
|
|
"\n",
|
|
" \n",
|
|
"\n",
|
|
" if not evalRun:\n",
|
|
" if not thisSeason.minBreaks and len(breaks)>0 and not balanceBreaks:\n",
|
|
" for p in phases:\n",
|
|
" # print (\"Don't allow breaks for \",t, \" in phase \", p)\n",
|
|
" model2+= lpSum([breakVio[(bl['id'],t)] for bl in breaks if getPhaseOfRound[bl['round1']]==p and getPhaseOfRound[bl['round2']]==p]) <= thisSeason.initBreaks\n",
|
|
"\n",
|
|
" if mathModelName in [ \"Ligue 1\"]:\n",
|
|
" model2+= lpSum([breakVio[(bl['id'],t)] for bl in breaks ]) <= 4\n",
|
|
"\n",
|
|
" if not thisSeason.startWithBreakAllowed:\n",
|
|
" model2+= homeInRound[t,1] + homeInRound[t,2] <= 1\n",
|
|
" model2+= awayInRound[t,1] + awayInRound[t,2] <= 1\n",
|
|
" if not thisSeason.endWithBreakAllowed:\n",
|
|
" print (\"NO BREAK FOR \" , t , \" in rounds \" ,nRounds-1, nRounds)\n",
|
|
" model2+= homeInRound[t,nRounds-1] + homeInRound[t,nRounds] <= 1\n",
|
|
" model2+= awayInRound[t,nRounds-1] + awayInRound[t,nRounds] <= 1\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"getDays[0] =[]\n",
|
|
"\n",
|
|
"\n",
|
|
"if thisSeason.useFeaturePairings:\n",
|
|
" for pair in pairings:\n",
|
|
" # print (pair)\n",
|
|
" pDaysSets = []\n",
|
|
" for d in days:\n",
|
|
" pTeams = [pair['team1_id'], pair['team2_id']]\n",
|
|
" pDays = [d]\n",
|
|
" if pair['dist'] ==1 and nextDay[d]!=-1:\n",
|
|
" pDays.append(nextDay[d])\n",
|
|
" if pair['dist'] in [3,7]:\n",
|
|
" pDays=getDays[getRoundByDay[d]]\n",
|
|
" # print ( getNiceDay[d], getRoundByDay[d], getDays[getRoundByDay[d]] , \" +\" ,getHigherDaysByRound[getRoundByDay[d]])\n",
|
|
" factor = 1.0\n",
|
|
" if len(pDays)>0 and pDays not in pDaysSets:\n",
|
|
" pDaysSets.append(pDays.copy())\n",
|
|
" # print (\"+++ \")\n",
|
|
" # else: \n",
|
|
" # print (\"--- \")\n",
|
|
"\n",
|
|
" # if pair['prio'] =='A':\n",
|
|
" # factor = 0.1 \n",
|
|
" for pDays in pDaysSets:\n",
|
|
" d= pDays[0]\n",
|
|
" print (\"Treating day set starting with day \" , getNiceDay[d], \" \", pDays)\n",
|
|
" if pair['dist'] in [2,6] and thisSeason.useFeatureKickOffTime:\n",
|
|
" for tm in times:\n",
|
|
" if pair['type']== \"Home\":\n",
|
|
" if pair['dist']<=3:\n",
|
|
" model2 += lpSum([home_time[t,d,tm] for t in pTeams]) <= 1 + factor*pairingVio[(pair['id'],d)]\n",
|
|
" else:\n",
|
|
" model2 += home_time[pair['team1_id'],d,tm] - home_time[pair['team2_id'],d,tm] <= factor*pairingVio[(pair['id'],d)]\n",
|
|
" model2 += home_time[pair['team2_id'],d,tm] - home_time[pair['team1_id'],d,tm] <= factor*pairingVio[(pair['id'],d)]\n",
|
|
" else:\n",
|
|
" if pair['dist']<=3:\n",
|
|
" model2 += lpSum([home_time[t,d,tm] + away_time[t,d,tm] for t in pTeams]) <= 1 + pairingVio[(pair['id'],d)]\n",
|
|
" else:\n",
|
|
" model2 += home_time[pair['team1_id'],d,tm] + away_time[pair['team1_id'],d,tm] - home_time[pair['team2_id'],d,tm] - away_time[pair['team2_id'],d,tm] <= factor*pairingVio[(pair['id'],d)]\n",
|
|
" model2 += home_time[pair['team2_id'],d,tm] + away_time[pair['team2_id'],d,tm] - home_time[pair['team1_id'],d,tm] - away_time[pair['team1_id'],d,tm] <= factor*pairingVio[(pair['id'],d)]\n",
|
|
"\n",
|
|
" else:\n",
|
|
" if pair['type']== \"Home\":\n",
|
|
" if pair['dist']<=3:\n",
|
|
" model2 += lpSum([home[t,dd] for t in pTeams for dd in pDays]) <= 1 + factor*pairingVio[(pair['id'],d)]\n",
|
|
" else:\n",
|
|
" model2 += lpSum([home[pair['team1_id'],dd] - home[pair['team2_id'],dd] for dd in pDays]) <= factor*pairingVio[(pair['id'],d)]\n",
|
|
" model2 += lpSum([home[pair['team2_id'],dd] - home[pair['team1_id'],dd] for dd in pDays]) <= factor*pairingVio[(pair['id'],d)]\n",
|
|
" else:\n",
|
|
" if pair['dist']<=3:\n",
|
|
" model2 += lpSum([home[t,dd] + away[t,dd] for t in pTeams for dd in pDays]) <= 1 + pairingVio[(pair['id'],d)]\n",
|
|
" else:\n",
|
|
" model2 += lpSum([home[pair['team1_id'],dd] + away[pair['team1_id'],dd] - home[pair['team2_id'],dd] - away[pair['team2_id'],dd] for dd in pDays]) <= factor*pairingVio[(pair['id'],d)]\n",
|
|
" model2 += lpSum([home[pair['team2_id'],dd] + away[pair['team2_id'],dd] - home[pair['team1_id'],dd] - away[pair['team1_id'],dd] for dd in pDays]) <= factor*pairingVio[(pair['id'],d)]\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"use_currentSolution= False\n",
|
|
"\n",
|
|
"currentGameCntr = { (t1,t2) :0 for t1 in teams for t2 in teams }\n",
|
|
"\n",
|
|
"\n",
|
|
"# if use_currentSolution and len(currentSolution) !=len(fixedGames): \n",
|
|
"\n",
|
|
"teamGameCntr = { (t,r) :0 for t in teams for r in rounds }\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"# print (\"days \" , days)\n",
|
|
"for d in days: \n",
|
|
" model2 += lpSum([x[(t1,t2,rd)] for (t1,t2) in games for rd in getRoundDaysByDay[d] if distance[getTeamById[t1],getTeamById[t2]]<=thisSeason.maxDistanceDerby ]) >= nDerbies[d] - derbyMissing[d]\n",
|
|
" minG = sum([ roundDaysMin[rd] - deficientGames[rd] for rd in getRoundDaysByDay[d]]) \n",
|
|
" maxG = sum([ roundDaysMax[rd] + excessGames[rd] for rd in getRoundDaysByDay[d]]) \n",
|
|
" # print (getNiceDay[d] , maxG)\n",
|
|
" # if minG<3 :\n",
|
|
" if minG>0 :\n",
|
|
" model2 += lpSum([ home[(t,d)] for t in realteams]) >= minG\n",
|
|
" model2 += lpSum([ home[(t,d)] for t in realteams]) <= maxG\n",
|
|
"\n",
|
|
" if len(getRoundDaysByDay[d])>1:\n",
|
|
" for rd in getRoundDaysByDay[d]:\n",
|
|
" if roundDaysMin[rd]>0:\n",
|
|
" model2 += lpSum([x[(t1,t2,rd)] for (t1,t2) in games ] ) >= roundDaysMin[rd] - deficientGames[rd] \n",
|
|
" # model2 += lpSum([x[(t1,t2,rd)] for (t1,t2) in games ] ) >= roundDaysMin[rd] \n",
|
|
" print (\"At least \",roundDaysMin[rd] , \" on \" , rd)\n",
|
|
" model2 += lpSum([x[(t1,t2,rd)] for (t1,t2) in games ] ) <= roundDaysMax[rd] + excessGames[rd] \n",
|
|
"\n",
|
|
"print (\"rounds \" , rounds, nRounds)\n",
|
|
"for r in rounds:\n",
|
|
" # one game a round for everyone\n",
|
|
" for t1 in realteams:\n",
|
|
" if thisSeason.gamesPerRound==\"one day\":\n",
|
|
" cnstr = lpSum([x[(t1,t2,rd)] + x[(t2,t1,rd)] for t2 in opponents[t1] for rd in getRoundDaysByRound[r]] )\n",
|
|
" if len(cnstr) > 0:\n",
|
|
" model2 += cnstr <= 1\n",
|
|
" else:\n",
|
|
" print ( getRoundDaysByRound[r], opponents[t1])\n",
|
|
" if len(getRoundDaysByRound[r])>0:\n",
|
|
" for rd in getRoundDaysByRound[r]:\n",
|
|
" if rd==getRoundDaysByRound[r][0]:\n",
|
|
" model2 += lpSum([x[(t1,t2,rd)] + x[(t2,t1,rd)] for t2 in opponents[t1]] ) <= 1\n",
|
|
" else:\n",
|
|
" for t2 in opponents[t1]:\n",
|
|
" model2 += x[(t1,t2,rd)] == x[(t1,t2,getRoundDaysByRound[r][0])]\n",
|
|
"\n",
|
|
"# exit(0)\n",
|
|
"print (\"realteams \" , realteams)\n",
|
|
"\n",
|
|
"print (\"taking care of right numbers of games ... \" ) \n",
|
|
"cntr= 0\n",
|
|
"\n",
|
|
"if not specialGameControl:\n",
|
|
" for (t1,t2) in realgames: \n",
|
|
" if undirectedGameCntr[(t1,t2)]==0:\n",
|
|
" model2 += lpSum([x[(t1,t2,rd)] for rd in roundDays] ) == gameCntr[(t1,t2)] - missingGamesVio[(t1,t2)]\n",
|
|
" else:\n",
|
|
" # model2 += lpSum([x[(t1,t2,rd)] for rd in roundDays] ) == gameCntr[(t1,t2)]+undirectedGameCntr[(t1,t2)] - missingGamesVio[(t1,t2)]\n",
|
|
" model2 += missingGamesVio[(t1,t2)] >= gameCntr[(t1,t2)] - lpSum([x[(t1,t2,rd)] for rd in roundDays] ) \n",
|
|
" model2 += missingGamesVio[(t1,t2)] >= gameCntr[(t1,t2)]+gameCntr[(t2,t1)]+undirectedGameCntr[(t1,t2)] - lpSum([x[(t1,t2,rd)] + x[(t2,t1,rd)] for rd in roundDays] ) \n",
|
|
" model2 += lpSum([x[(t1,t2,rd)] + x[(t2,t1,rd)] for rd in roundDays] ) <= gameCntr[(t1,t2)]+gameCntr[(t2,t1)]+undirectedGameCntr[(t1,t2)] \n",
|
|
" \n",
|
|
" missingGamesVio[(t1,t2)].upBound= max(0,gameCntr[(t1,t2)]+undirectedGameCntr[(t1,t2)] - currentGameCntr[(t1,t2)])\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"if not evalRun:\n",
|
|
" for (t1,t2) in realgames:\n",
|
|
" # every pair plays each other in each phase once\n",
|
|
" for p in phases:\n",
|
|
" if p<len(phases)-1 or True: # phase violation in last phase possible if it contained more rounds than necessary\n",
|
|
" if t_usePhases[t1] or t_usePhases[t2]:\n",
|
|
" if thisSeason.groupBased and len(noPlayRounds[t1])>0 and noPlayRounds[t1]==noPlayRounds[t2]:\n",
|
|
" relDays = []\n",
|
|
" phaseLength= int(len(playRounds[t1])/nPhases+0.5)\n",
|
|
" for rr in playRounds[t1][p*phaseLength:(p+1)*phaseLength]:\n",
|
|
" relDays+=getDays[rr]\n",
|
|
" print (\"adding days of round \", rr , \" to phase \", p)\n",
|
|
" else:\n",
|
|
" relDays = getDaysOfPhase[p]\n",
|
|
" model2 += lpSum([x[(t1,t2,rd)] + x[(t2,t1,rd)] for d in relDays for rd in getRoundDaysByDay[d] ] ) <= 1\n",
|
|
" # print (len(relDays),\"reldays\") \n",
|
|
" # print (getTeamById[t1],getTeamById[t2], sum([x[(t1,t2,rd)] + x[(t2,t1,rd)] for d in relDays for rd in getRoundDaysByDay[d] ] ))\n",
|
|
"\n",
|
|
"if not evalRun :\n",
|
|
" for t in realteams:\n",
|
|
" if t_usePhases[t] and thisSeason.distributeHomeGamesEvenlyOverPhases:\n",
|
|
" for p in phases:\n",
|
|
" rds = [r for r in rounds if getPhaseOfRound[r]==p ]\n",
|
|
" nblocked =[ r for r in noHomeRounds[t] if r in rds]\n",
|
|
" print (p, len(rds), len(nblocked), rds,nblocked, getTeamById[t])\n",
|
|
" for p in phases:\n",
|
|
" phaseLength= int(len(playRounds[t])/nPhases+0.5)\n",
|
|
" model2 += lpSum([ home[(t,d)] for d in getDaysOfPhase[p] ] ) <= int(phaseLength/2+1)\n",
|
|
"\n",
|
|
" if thisSeason.minRoundsBetweenGameOfSameTeams>0:\n",
|
|
" for r in rounds:\n",
|
|
" if r +thisSeason.minRoundsBetweenGameOfSameTeams <=nRounds:\n",
|
|
" rds = [ ] \n",
|
|
" for r2 in range(r,r+thisSeason.minRoundsBetweenGameOfSameTeams+1):\n",
|
|
" rds+=getRoundDaysByRound[r2]\n",
|
|
" rds2 = [ ] \n",
|
|
" for r2 in range(r,r+int (0.5*thisSeason.minRoundsBetweenGameOfSameTeams)):\n",
|
|
" rds2+=getRoundDaysByRound[r2]\n",
|
|
" # print (\"ONLY ONE IN \" , rds)\n",
|
|
" # print (\"ONLY ONE IN \" , rds2)\n",
|
|
" for t1 in realteams:\n",
|
|
" for t2 in realteams:\n",
|
|
" if t1<t2 and (gameCntr[(t1,t2)]*gameCntr[(t2,t1)]>0 or x_round[(t1,t2,r)]!=0) :\n",
|
|
" # model2 += sum([ (x[(t1,t2, rd)]+x[(t2,t1,rd)]) for rd in rds ]) <= 1 + gamesTooClose2[t1,r]\n",
|
|
" model2 += sum([ (x[(t1,t2, rd)]+x[(t2,t1,rd)]) for rd in rds ]) <= 1 \n",
|
|
"\n",
|
|
" \n",
|
|
"if not evalRun:\n",
|
|
" # max length home stands /trips\n",
|
|
" for r in range (1,nRounds-thisSeason.maxTourLength+1):\n",
|
|
" # print (\" at least one home and away in rounds \")\n",
|
|
" # for r3 in range(r,r+thisSeason.maxTourLength+1):\n",
|
|
" # print (r3 )\n",
|
|
" for t in teams:\n",
|
|
" if t not in noBreakLimitTeams:\n",
|
|
" # model2 += lpSum([homeInRound[t,r2] for r2 in range(r,r+thisSeason.maxTourLength+1)]) >=1\n",
|
|
" model2 += lpSum([awayInRound[t,r2] for r2 in range(r,r+thisSeason.maxTourLength+1)]) <=thisSeason.maxTourLength\n",
|
|
" model2 += lpSum([homeInRound[t,r2] for r2 in range(r,r+thisSeason.maxTourLength+1)]) <=thisSeason.maxTourLength\n",
|
|
"\n",
|
|
"print (\"check 1\")\n",
|
|
"\n",
|
|
" # blockings\n",
|
|
"for bl in blockings:\n",
|
|
" if getDayById[bl['day_id']]['round'] !=0:\n",
|
|
" if thisSeason.useFeatureKickOffTime and bl['time']!='----':\n",
|
|
" if bl['type'] in [\"Home\", \"Hide\"]:\n",
|
|
" model2+= blockingVio[bl['id']]== home_time[bl['team_id'], bl['day_id'],bl['time']]\n",
|
|
" # print ('FOUND HOME BLOCKING ', bl)\n",
|
|
" else:\n",
|
|
" model2+= blockingVio[bl['id']]== away_time[bl['team_id'], bl['day_id'],bl['time']]\n",
|
|
" # print ('FOUND AWAY BLOCKING ', bl)\n",
|
|
" else:\n",
|
|
" if bl['type'] in [\"Home\", \"Hide\"]:\n",
|
|
" model2+= blockingVio[bl['id']]== home[bl['team_id'], bl['day_id']]\n",
|
|
" # print ('FOUND HOME BLOCKING ', bl)\n",
|
|
" else:\n",
|
|
" model2+= blockingVio[bl['id']]== away[bl['team_id'], bl['day_id']]\n",
|
|
" # print ('FOUND AWAY BLOCKING ', bl)\n",
|
|
"\n",
|
|
"\n",
|
|
"print (\"check 2\")\n",
|
|
"\n",
|
|
"hawOneVio={}\n",
|
|
"hawForOneNotViolated={}\n",
|
|
"\n",
|
|
"def getStringFromSet(ss):\n",
|
|
" s2 =\"\"\n",
|
|
" for s in ss: \n",
|
|
" s2+=str(s)+\"_\"\n",
|
|
" return s2[:-1]\n",
|
|
"\n",
|
|
" # hawishes\n",
|
|
"for haw in hawishes:\n",
|
|
" print (haw['reason'])\n",
|
|
" for el in elemHaWishes[haw['id']]:\n",
|
|
" if thisSeason.useFeatureKickOffTime and len(hawTimes[haw['id']])>0:\n",
|
|
" if haw['homeAway']=='Home':\n",
|
|
" relGames = lpSum([home_time[t,d,tm] for d in elemHaWishDays[el] for t in elemHaWishTeams[el] for tm in hawTimes[haw['id']]])\n",
|
|
" # print (haw['id'] ,\" haw : \", relGames, hawTimes[haw['id']])\n",
|
|
" elif haw['homeAway']=='Away':\n",
|
|
" relGames = lpSum([away_time[t,d,tm] for d in elemHaWishDays[el] for t in elemHaWishTeams[el] for tm in hawTimes[haw['id']]])\n",
|
|
" else :\n",
|
|
" # print(haw,el)\n",
|
|
" relGames = lpSum([home_time[t,d,tm] + away_time[t,d,tm] for d in elemHaWishDays[el] for t in elemHaWishTeams[el] for tm in hawTimes[haw['id']]]) \\\n",
|
|
" - lpSum([x_time[(t1,t2,rd,tm)] for d in elemHaWishDays[el] for rd in getRoundDaysByDay[d] for tm in hawTimes[haw['id']] for t1 in elemHaWishTeams[el] for t2 in elemHaWishTeams[el] if (t1,t2,rd,tm) in x_time.keys()]) \n",
|
|
"\n",
|
|
" else:\n",
|
|
" if haw['homeAway']=='Home':\n",
|
|
" relGames = lpSum([home[t,d] for d in elemHaWishDays[el] for t in elemHaWishTeams[el] ])\n",
|
|
" elif haw['homeAway']=='Away':\n",
|
|
" relGames = lpSum([away[t,d] for d in elemHaWishDays[el] for t in elemHaWishTeams[el] ])\n",
|
|
" else :\n",
|
|
" relGames = lpSum([home[t,d] + away[t,d] for d in elemHaWishDays[el] for t in elemHaWishTeams[el]]) - lpSum([x[t1,t2,rd] for d in elemHaWishDays[el] for rd in getRoundDaysByDay[d] for t1 in elemHaWishTeams[el] for t2 in elemHaWishTeams[el] if (t1,t2,rd) in x.keys() ]) \n",
|
|
" if haw['minGames'] >0 :\n",
|
|
" model2+= relGames >= haw['minGames'] - HawVioTooLess[el]\n",
|
|
" # print (\"adding min ha constraint\")\n",
|
|
" if haw['maxGames'] >=0 :\n",
|
|
" model2+= relGames <= haw['maxGames'] + HawVioTooMuch[el]\n",
|
|
" # print (\"adding max ha constraint\")\n",
|
|
"\n",
|
|
"\n",
|
|
" usedConstraintNames = [\"\"]\n",
|
|
" if haw['forOneDay']:\n",
|
|
" # print (haw['forOneDay'], hawDays[haw['id']])\n",
|
|
" # print ([el for el in elemHaWishes[haw['id']] ])\n",
|
|
" # for el in elemHaWishes[haw['id']] :\n",
|
|
" # print(\"- \" , elemHaWishDays[el] , elemHaWishTeams[el] )\n",
|
|
" # print ([ (el, elemHaWishFirstDay[el]) for el in elemHaWishes[haw['id']] ])\n",
|
|
" relTeamString = { el : getStringFromSet(elemHaWishTeams[el]) for el in elemHaWishes[haw['id']] }\n",
|
|
" relTeams = set([ relTeamString[el] for el in elemHaWishes[haw['id']]])\n",
|
|
" # print (relTeams)\n",
|
|
" for rt in relTeams:\n",
|
|
" rtname = rt \n",
|
|
" if len(rt)>50 :\n",
|
|
" scname=\"\"\n",
|
|
" while scname in usedConstraintNames:\n",
|
|
" ttt = bytes(rt+ ''.join(random.choice(string.ascii_lowercase) for i in range(10)), 'utf-8')\n",
|
|
" scname = hashlib.sha224(ttt).hexdigest()\n",
|
|
" rtname = scname[:10]\n",
|
|
" usedConstraintNames.append(rtname)\n",
|
|
" # print (\"use rtname to encode wishes \", rtname)\n",
|
|
"\n",
|
|
" hawOneVio[(haw['id'], rt)]= pulp.LpVariable('hawOneVio_'+str(haw['id'])+\"_\"+rtname, cat=pulp.LpContinuous)\n",
|
|
" for fd in hawDays[haw['id']]:\n",
|
|
" relWishes = [el for el in elemHaWishes[haw['id']] if elemHaWishFirstDay[el]== fd]\n",
|
|
" # relWishes = [el for el in elemHaWishes[haw['id']] ]\n",
|
|
" # print (\" -\" , relWishes , [elemHaWishDays[el] for el in relWishes])\n",
|
|
" hawForOneNotViolated[(haw['id'], rt, fd)]= 0\n",
|
|
" if len(relWishes)>0:\n",
|
|
" hawForOneNotViolated[(haw['id'], rt, fd)]= pulp.LpVariable('hawForOneViolated_'+str(haw['id'])+\"_\"+rtname+\"_\"+str(fd), cat=pulp.LpBinary)\n",
|
|
" model2 += lpSum( HawVioTooMuch[el]+HawVioTooLess[el] for el in relWishes if relTeamString[el]==rt) <= 1000 * (1-hawForOneNotViolated[(haw['id'],rt, fd)])\n",
|
|
" model2 += lpSum( hawForOneNotViolated[(haw['id'], rt, fd)] for fd in hawDays[haw['id']] ) >= haw['forOneDayNum']-hawOneVio[(haw['id'],rt)]\n",
|
|
" model2 += lpSum( hawOneVio[(haw['id'], rt)] for rt in relTeams ) == hawVio[haw['id']]\n",
|
|
" else:\n",
|
|
" # print (haw['forOneDay'], hawDays[haw['id']])\n",
|
|
" model2 += hawVio[haw['id']]== lpSum( HawVioTooMuch[el]+HawVioTooLess[el] for el in elemHaWishes[haw['id']]) \n",
|
|
"\n",
|
|
"\n",
|
|
" if haw['prio']==\"Hard\" and \"HardHAWishesNotBreakable\" in special_wishes_active:\n",
|
|
" model2+= hawVio[haw['id']] ==0\n",
|
|
" print (\"WISH HARD\" ,haw['reason'])\n",
|
|
"\n",
|
|
"\n",
|
|
"# HawVioTotal=lpSum([prioVal[haw['prio']] * (HawVioTooLess[el]+HawVioTooMuch[el]) for haw in hawishes for el in elemHaWishes[haw['id']]])\n",
|
|
"# print (hawDays)\n",
|
|
"# print (elemHaWishFirstDay) \n",
|
|
"\n",
|
|
"encOneVio={}\n",
|
|
"encForOneNotViolated={}\n",
|
|
"print (\"check 3\")\n",
|
|
"# encwishes\n",
|
|
"for enc in encwishes:\n",
|
|
" print (enc)\n",
|
|
" for el in elemEncWishes[enc['id']]: \n",
|
|
" # print (enc)\n",
|
|
" # model2+= encVio[enc['id']] == 1 - x[enc['team1_id'], enc['team2_id'], enc['day_id']]\n",
|
|
"\n",
|
|
" if thisSeason.useFeatureKickOffTime and len(encTimes[enc['id']])>0:\n",
|
|
" if enc['minGames'] >0 :\n",
|
|
" model2+= encVioTooLess[el] >= enc['minGames'] - sum([ x_time[(t1,t2,rd, tm )] for d in elemEncWishDays[el] for rd in getRoundDaysByDay[d] for (t1,t2) in elemEncWishGames[el] for tm in encTimes[enc['id']] if (t1,t2) in games ])\n",
|
|
" if enc['maxGames'] >=0 :\n",
|
|
" # if enc['maxGames']==0:\n",
|
|
" print (enc['reason'], ' ', elemEncWishDays[el], ' ',enc['time'], ' ', encTeams1[enc['id']] , ' ',encTeams2[enc['id']] )\n",
|
|
" # print (sum([x_time[(t1,t2,rd, enc['time'])] for d in elemEncWishDays[el] for rd in getRoundDaysByDay[d] for (t1,t2) in elemEncWishGames[el] if (t1,t2) in games ]))\n",
|
|
" model2+= encVioTooMuch[el] >= -enc['maxGames'] + sum([x_time[(t1,t2,rd, tm )] for d in elemEncWishDays[el] for rd in getRoundDaysByDay[d] for (t1,t2) in elemEncWishGames[el] for tm in encTimes[enc['id']] if (t1,t2) in games ])\n",
|
|
" else:\n",
|
|
" if enc['minGames'] >0 :\n",
|
|
" model2+= encVioTooLess[el] >= enc['minGames'] - sum([ x[t1,t2,rd] for d in elemEncWishDays[el] for rd in getRoundDaysByDay[d] for (t1,t2) in elemEncWishGames[el] if (t1,t2) in games ])\n",
|
|
" if enc['maxGames'] >=0 :\n",
|
|
" # if enc['maxGames']==0:\n",
|
|
" # print (enc['reason'], ' ', encDays[enc['id']], ' ', encTeams1[enc['id']] , ' ',encTeams2[enc['id']] )\n",
|
|
" model2+= encVioTooMuch[el] >= -enc['maxGames'] + sum([ x[t1,t2,rd] for d in elemEncWishDays[el] for rd in getRoundDaysByDay[d] for (t1,t2) in elemEncWishGames[el] if (t1,t2) in games ])\n",
|
|
"\n",
|
|
" if enc['forOneDay']:\n",
|
|
" for ed in encDaySets[enc['id']]:\n",
|
|
" if len(ed)>0:\n",
|
|
" relWishes = [ el for el in elemEncWishes[enc['id']] if elemEncWishDays[el] == ed ]\n",
|
|
" print (\"###\",ed, relWishes) \n",
|
|
" encForOneNotViolated[(enc['id'], ed[0])]= pulp.LpVariable('encForOneNotViolated_'+str(enc['id'])+\"_\"+str(ed[0]), cat=pulp.LpBinary)\n",
|
|
" model2 += sum( encVioTooMuch[el]+encVioTooLess[el] for el in relWishes) <= 1000 * (1-encForOneNotViolated[(enc['id'], ed[0])])\n",
|
|
" model2 += sum( encForOneNotViolated[(enc['id'], ed[0])] for ed in encDaySets[enc['id']] if len(ed)>0 ) >= enc['forOneDayNum']-encVio[enc['id']]\n",
|
|
" else:\n",
|
|
" model2 += encVio[enc['id']]== sum( encVioTooMuch[el]+encVioTooLess[el] for el in elemEncWishes[enc['id']]) \n",
|
|
"\n",
|
|
"\n",
|
|
" if enc['prio']==\"Hard\" and \"HardEncWishesNotBreakable\" in special_wishes_active:\n",
|
|
" model2+= encVio[enc['id']] ==0\n",
|
|
" print (\"WISH HARD\" ,enc['reason'])\n",
|
|
"\n",
|
|
"\n",
|
|
"print (\"check 4\")\n",
|
|
" \n",
|
|
"\n",
|
|
"# return \"\"\n",
|
|
"weekdayHomePref={}\n",
|
|
"dayHomePref={}\n",
|
|
"for t in teams:\n",
|
|
" tm = getTeamByName[getTeamById[t]]\n",
|
|
" weekdayHomePref[(t,'Mon')]=tm['home_pref_mo']\n",
|
|
" weekdayHomePref[(t,'Tue')]=tm['home_pref_tu']\n",
|
|
" weekdayHomePref[(t,'Wed')]=tm['home_pref_we']\n",
|
|
" weekdayHomePref[(t,'Thu')]=tm['home_pref_th']\n",
|
|
" weekdayHomePref[(t,'Fri')]=tm['home_pref_fr']\n",
|
|
" weekdayHomePref[(t,'Sat')]=tm['home_pref_sa']\n",
|
|
" weekdayHomePref[(t,'Sun')]=tm['home_pref_su']\n",
|
|
" for d in days :\n",
|
|
" dayHomePref[(t,d)]=weekdayHomePref[(t,getWeekDay[d])]\n",
|
|
"\n",
|
|
"\n",
|
|
"maxTravelDistance = max([ distanceById[t1,t2] for t1 in realteams for t2 in realteams ]) \n",
|
|
"maxTravelDistance = max(1,maxTravelDistance)\n",
|
|
"\n",
|
|
"singleTripWeight=50\n",
|
|
"breakImbalanceTotal= lpSum([ breakVioBalance[t] for t in realteams])\n",
|
|
"# HawVioTotal=lpSum([prioVal[haw['prio']] * (HawVioTooLess[el]+HawVioTooMuch[el]) for haw in hawishes for el in elemHaWishes[haw['id']]])\n",
|
|
"HawVioTotal=lpSum([prioVal[haw['prio']] * hawVio[haw['id']] for haw in hawishes])\n",
|
|
"encVioTotal=lpSum([prioVal[enc['prio']] * encVio[enc['id']] for enc in encwishes])\n",
|
|
"seedVioTotal=lpSum([100*prioVal[enc['prio']] * encVio[enc['id']] for enc in encwishes if enc['reason']==\"Seed Game\" ])\n",
|
|
"# broadVioTotal=lpSum([ 10 * broadVio[d] for d in days]) + lpSum([ 10 * broadVioTm[b.id] for b in broadcastingwishes])\n",
|
|
"broadVioTotal=lpSum([ 10 * broadVioTm[(b.id,r)] for b in broadcastingwishes for r in rounds])\n",
|
|
"breakVioTotal=lpSum([prioVal[bl['prio']]*breakVio[(bl['id'],t)] for bl in breaks for t in realteams]) + 2*lpSum([prioVal[bl['prio']]*breakVio[(bl['id'],t)] for bl in breaks for t in importantteams])\n",
|
|
"break3VioTotal=lpSum([2*break3InRound[t,r] for t in teams for r in rounds])\n",
|
|
"tooManyTop4InRowTotal=lpSum([ 10*tooManyTop4InRow[(t,r)] for t in teams for r in rounds])\n",
|
|
"pairingVioTotal=lpSum([ 5 *prioVal[pair['prio']] * pairingVio[(pair['id'],d)] for pair in pairings for d in days])\n",
|
|
"# blockingVioTotal=lpSum([ 100 * blockingVio[bl['id']] for bl in blockings if bl['type']==\"Home\"])\n",
|
|
"# print (blockings) \n",
|
|
"# for bl in blockings: \n",
|
|
" # if bl['type'] in [\"Home\"]:\n",
|
|
" # print (blocked_arena[(bl[\"team_id\"],bl[\"day_id\"],\"----\")], getTeamById[bl[\"team_id\"]], getNiceDay[bl[\"day_id\"]] , bl )\n",
|
|
"\n",
|
|
"fulfBlocks =set([(bl[\"team_id\"], getRoundByDay[bl[\"day_id\"]]) for bl in blockings if bl['type'] in [\"Home\"] and blocked_arena[(bl[\"team_id\"],bl[\"day_id\"],\"----\")]] )\n",
|
|
"\n",
|
|
"blockingVioTotal2=lpSum([ -30 * homeInRound[tr] for tr in fulfBlocks if thisSeason.allowBlockingViosInImprove and runMode=='Improve'] ) \n",
|
|
"blockingVioTotal=lpSum([ 100 * blockingVio[bl['id']] for bl in blockings if bl['type'] in [\"Home\", \"Hide\"]]) +blockingVioTotal2\n",
|
|
"\n",
|
|
"travelVioTotal=lpSum([ 100 * blockingVio[bl['id']] for bl in blockings if bl['type']==\"Away\"])\n",
|
|
"derbiesMissingTotal=lpSum([ 30 * derbyMissing[d] for d in days])\n",
|
|
"unpreferredTotal=lpSum([ home[t, d] for t in teams for d in days if dayHomePref[(t,d)]==0 ])\n",
|
|
"# competitionVioTotal=lpSum([ 100 * competitionVio[(c,d,t)] for (c,d,t) in competitions])\n",
|
|
"missingGamesVioTotal=lpSum([ 2000000 * missingGamesVio[(t1,t2)] for (t1,t2) in realgames])\n",
|
|
"# TODO - UNDO CHANGES: missingGamesVioTotal=lpSum([ 2000 * missingGamesVio[(t1,t2)] for (t1,t2) in games])\n",
|
|
"oldScenGamesTotal=lpSum([ wg * x[t1,t2,rd] for (t1,t2,r,wg) in otherScenGames for rd in getRoundDaysByRound[r]] )\n",
|
|
"totalAttendance=lpSum([ attendance[(t1,t2,d)] * x[t1,t2,(r,d)] for (t1,t2) in games for (r,d) in roundDays ] )\n",
|
|
"\n",
|
|
"specialObjectives = 0\n",
|
|
"specialWishItems ={ sw:[] for sw in special_wishes_active}\n",
|
|
"specialWishVio ={}\n",
|
|
"\n",
|
|
"\n",
|
|
"optCameraMovement = \"Standard\"\n",
|
|
"\n",
|
|
"# tvkitproblem = {}\n",
|
|
"move2 = {}\n",
|
|
"newtrip2 = {}\n",
|
|
"\n",
|
|
"\n",
|
|
"standardObjectives=1+gew['Home-/Away']*HawVioTotal\\\n",
|
|
" +gew['Home-/Away']*3*unpreferredTotal \\\n",
|
|
" +gew['Pairings']*pairingVioTotal \\\n",
|
|
" +gew['Blockings']*blockingVioTotal \\\n",
|
|
" +gew['Traveling']*travelVioTotal \\\n",
|
|
" +gew['Breaks']*breakVioTotal \\\n",
|
|
" +gew['Breaks']*2*break3VioTotal \\\n",
|
|
" +gew['Breaks']*1*breakImbalanceTotal \\\n",
|
|
" +5*gew['Encounters']*encVioTotal \\\n",
|
|
" +5*gew['Encounters']*seedVioTotal \\\n",
|
|
" +gew['Broadcasting']*broadVioTotal \\\n",
|
|
" +gew['Derbies']*derbiesMissingTotal \\\n",
|
|
" +1.0*tooManyTop4InRowTotal\\\n",
|
|
" +missingGamesVioTotal\\\n",
|
|
" +oldScenGamesTotal\\\n",
|
|
" -0.01*totalAttendance \n",
|
|
"\n",
|
|
"\n",
|
|
"model2+= standardObjectives "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 27,
|
|
"id": "952f1e44",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"script\n",
|
|
"HOMEAWAY;1-17\n",
|
|
"BASICGAME;1-17\n",
|
|
"HOMEAWAY;18-34\n",
|
|
"GAME;1-34\n",
|
|
"[['HOMEAWAY', '1-17'], ['BASICGAME', '1-17'], ['HOMEAWAY', '18-34'], ['GAME', '1-34']]\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"script =thisSeason.optimizationScript\n",
|
|
"if script == '' :\n",
|
|
" if useBasicGames:\n",
|
|
" script += \"HEURISTIC\\n\"\n",
|
|
" script += \"GAME;1-\"+str(nRounds)+\";0.1;200\\n\"\n",
|
|
" if thisSeason.groupBased:\n",
|
|
" for c in allConferences:\n",
|
|
" if not c.regional and c.teams.count() <= 12: \n",
|
|
" script += \"GROUP;1-\"+str(nRounds)+\";0.05;30;\"+c.name+\"\\n\"\n",
|
|
" for cr in range(nPhases):\n",
|
|
" minIntRound= min( (cr) * nRoundsPerPhase+1, nRounds)\n",
|
|
" maxIntRound= min( (cr+1)*nRoundsPerPhase, nRounds)\n",
|
|
"\n",
|
|
"\n",
|
|
"script=script.replace('\\r', '')\n",
|
|
"print (\"script\")\n",
|
|
"print (script)\n",
|
|
"optSteps = [ st.split(';') for st in script.split(\"\\n\")]\n",
|
|
"print (optSteps)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 29,
|
|
"id": "c4dc8d33",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Model built now solving .... \n",
|
|
"True True False\n",
|
|
" - ['HOMEAWAY', '1-17']\n",
|
|
"\n",
|
|
"[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]\n",
|
|
"########################\n",
|
|
"# SOLVING MODEL HOMEAWAY FOR ROUNDS 1-17 USING GAP 0.0 and MAXTIME 300 #\n",
|
|
"########################\n",
|
|
"[10, 3, 17, 14, 15, 13, 12, 6, 9, 5, 8, 18, 19, 20, 11, 7, 4, 16]\n",
|
|
"[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]\n",
|
|
"fixing home 5 : ratiopharm ulm 1.0\n",
|
|
"fixing home 6 : ratiopharm ulm 1.0\n",
|
|
"fixing home 8 : ratiopharm ulm 1.0\n",
|
|
"fixing home 9 : ratiopharm ulm 1.0\n",
|
|
"fixing home 11 : ratiopharm ulm 1.0\n",
|
|
"fixing home 12 : ratiopharm ulm 1.0\n",
|
|
"fixing home 15 : ratiopharm ulm 1.0\n",
|
|
"fixing home 17 : ratiopharm ulm 1.0\n",
|
|
"fixing home 2 : Basketball Löwen Braunschweig 1.0\n",
|
|
"fixing home 3 : Basketball Löwen Braunschweig 1.0\n",
|
|
"fixing home 4 : Basketball Löwen Braunschweig 1.0\n",
|
|
"fixing home 6 : Basketball Löwen Braunschweig 1.0\n",
|
|
"fixing home 8 : Basketball Löwen Braunschweig 1.0\n",
|
|
"fixing home 11 : Basketball Löwen Braunschweig 1.0\n",
|
|
"fixing home 13 : Basketball Löwen Braunschweig 1.0\n",
|
|
"fixing home 15 : Basketball Löwen Braunschweig 1.0\n",
|
|
"fixing home 17 : Basketball Löwen Braunschweig 1.0\n",
|
|
"fixing home 2 : MHP RIESEN Ludwigsburg 1.0\n",
|
|
"fixing home 4 : MHP RIESEN Ludwigsburg 1.0\n",
|
|
"fixing home 6 : MHP RIESEN Ludwigsburg 1.0\n",
|
|
"fixing home 10 : MHP RIESEN Ludwigsburg 1.0\n",
|
|
"fixing home 13 : MHP RIESEN Ludwigsburg 1.0\n",
|
|
"fixing home 17 : MHP RIESEN Ludwigsburg 1.0\n",
|
|
"fixing home 4 : BG Göttingen 1.0\n",
|
|
"fixing home 6 : BG Göttingen 1.0\n",
|
|
"fixing home 8 : BG Göttingen 1.0\n",
|
|
"fixing home 13 : BG Göttingen 1.0\n",
|
|
"fixing home 15 : BG Göttingen 1.0\n",
|
|
"fixing home 16 : BG Göttingen 1.0\n",
|
|
"fixing home 2 : SYNTAINICS MBC 1.0\n",
|
|
"fixing home 4 : SYNTAINICS MBC 1.0\n",
|
|
"fixing home 6 : SYNTAINICS MBC 1.0\n",
|
|
"fixing home 7 : SYNTAINICS MBC 1.0\n",
|
|
"fixing home 9 : SYNTAINICS MBC 1.0\n",
|
|
"fixing home 10 : SYNTAINICS MBC 1.0\n",
|
|
"fixing home 14 : SYNTAINICS MBC 1.0\n",
|
|
"fixing home 16 : SYNTAINICS MBC 1.0\n",
|
|
"fixing home 2 : FRAPORT SKYLINERS 1.0\n",
|
|
"fixing home 5 : FRAPORT SKYLINERS 1.0\n",
|
|
"fixing home 6 : FRAPORT SKYLINERS 1.0\n",
|
|
"fixing home 8 : FRAPORT SKYLINERS 1.0\n",
|
|
"fixing home 11 : FRAPORT SKYLINERS 1.0\n",
|
|
"fixing home 14 : FRAPORT SKYLINERS 1.0\n",
|
|
"fixing home 15 : FRAPORT SKYLINERS 1.0\n",
|
|
"fixing home 17 : FRAPORT SKYLINERS 1.0\n",
|
|
"fixing home 1 : FC Bayern München 1.0\n",
|
|
"fixing home 3 : FC Bayern München 1.0\n",
|
|
"fixing home 5 : FC Bayern München 1.0\n",
|
|
"fixing home 8 : FC Bayern München 1.0\n",
|
|
"fixing home 14 : FC Bayern München 1.0\n",
|
|
"fixing home 17 : FC Bayern München 1.0\n",
|
|
"fixing home 1 : Brose Bamberg 1.0\n",
|
|
"fixing home 5 : Brose Bamberg 1.0\n",
|
|
"fixing home 9 : Brose Bamberg 1.0\n",
|
|
"fixing home 12 : Brose Bamberg 1.0\n",
|
|
"fixing home 14 : Brose Bamberg 1.0\n",
|
|
"fixing home 16 : Brose Bamberg 1.0\n",
|
|
"fixing home 2 : ALBA BERLIN 1.0\n",
|
|
"fixing home 4 : ALBA BERLIN 1.0\n",
|
|
"fixing home 7 : ALBA BERLIN 1.0\n",
|
|
"fixing home 9 : ALBA BERLIN 1.0\n",
|
|
"fixing home 11 : ALBA BERLIN 1.0\n",
|
|
"fixing home 13 : ALBA BERLIN 1.0\n",
|
|
"fixing home 15 : ALBA BERLIN 1.0\n",
|
|
"fixing home 17 : ALBA BERLIN 1.0\n",
|
|
"fixing home 4 : Hamburg Towers 1.0\n",
|
|
"fixing home 7 : Hamburg Towers 1.0\n",
|
|
"fixing home 11 : Hamburg Towers 1.0\n",
|
|
"fixing home 12 : Hamburg Towers 1.0\n",
|
|
"fixing home 14 : Hamburg Towers 1.0\n",
|
|
"fixing home 16 : Hamburg Towers 1.0\n",
|
|
"fixing home 2 : EWE Baskets Oldenburg 1.0\n",
|
|
"fixing home 3 : EWE Baskets Oldenburg 1.0\n",
|
|
"fixing home 4 : EWE Baskets Oldenburg 1.0\n",
|
|
"fixing home 7 : EWE Baskets Oldenburg 1.0\n",
|
|
"fixing home 9 : EWE Baskets Oldenburg 1.0\n",
|
|
"fixing home 10 : EWE Baskets Oldenburg 1.0\n",
|
|
"fixing home 13 : EWE Baskets Oldenburg 1.0\n",
|
|
"fixing home 15 : EWE Baskets Oldenburg 1.0\n",
|
|
"fixing home 3 : HAKRO Merlins Crailsheim 1.0\n",
|
|
"fixing home 5 : HAKRO Merlins Crailsheim 1.0\n",
|
|
"fixing home 8 : HAKRO Merlins Crailsheim 1.0\n",
|
|
"fixing home 10 : HAKRO Merlins Crailsheim 1.0\n",
|
|
"fixing home 11 : HAKRO Merlins Crailsheim 1.0\n",
|
|
"fixing home 12 : HAKRO Merlins Crailsheim 1.0\n",
|
|
"fixing home 14 : HAKRO Merlins Crailsheim 1.0\n",
|
|
"fixing home 16 : HAKRO Merlins Crailsheim 1.0\n",
|
|
"fixing home 3 : medi bayreuth 1.0\n",
|
|
"fixing home 4 : medi bayreuth 1.0\n",
|
|
"fixing home 7 : medi bayreuth 1.0\n",
|
|
"fixing home 11 : medi bayreuth 1.0\n",
|
|
"fixing home 12 : medi bayreuth 1.0\n",
|
|
"fixing home 16 : medi bayreuth 1.0\n",
|
|
"fixing home 17 : medi bayreuth 1.0\n",
|
|
"fixing home 1 : NINERS Chemnitz 1.0\n",
|
|
"fixing home 2 : NINERS Chemnitz 1.0\n",
|
|
"fixing home 5 : NINERS Chemnitz 1.0\n",
|
|
"fixing home 7 : NINERS Chemnitz 1.0\n",
|
|
"fixing home 8 : NINERS Chemnitz 1.0\n",
|
|
"fixing home 14 : NINERS Chemnitz 1.0\n",
|
|
"fixing home 16 : NINERS Chemnitz 1.0\n",
|
|
"fixing home 1 : MLP Academics Heidelberg 1.0\n",
|
|
"fixing home 3 : MLP Academics Heidelberg 1.0\n",
|
|
"fixing home 7 : MLP Academics Heidelberg 1.0\n",
|
|
"fixing home 9 : MLP Academics Heidelberg 1.0\n",
|
|
"fixing home 11 : MLP Academics Heidelberg 1.0\n",
|
|
"fixing home 13 : MLP Academics Heidelberg 1.0\n",
|
|
"fixing home 15 : MLP Academics Heidelberg 1.0\n",
|
|
"fixing home 17 : MLP Academics Heidelberg 1.0\n",
|
|
"fixing home 1 : JobStairs Gießen 46ers 1.0\n",
|
|
"fixing home 3 : JobStairs Gießen 46ers 1.0\n",
|
|
"fixing home 5 : JobStairs Gießen 46ers 1.0\n",
|
|
"fixing home 8 : JobStairs Gießen 46ers 1.0\n",
|
|
"fixing home 10 : JobStairs Gießen 46ers 1.0\n",
|
|
"fixing home 15 : JobStairs Gießen 46ers 1.0\n",
|
|
"fixing home 17 : JobStairs Gießen 46ers 1.0\n",
|
|
"fixing home 3 : Telekom Baskets Bonn 1.0\n",
|
|
"fixing home 6 : Telekom Baskets Bonn 1.0\n",
|
|
"fixing home 9 : Telekom Baskets Bonn 1.0\n",
|
|
"fixing home 11 : Telekom Baskets Bonn 1.0\n",
|
|
"fixing home 12 : Telekom Baskets Bonn 1.0\n",
|
|
"fixing home 14 : Telekom Baskets Bonn 1.0\n",
|
|
"fixing home 16 : Telekom Baskets Bonn 1.0\n",
|
|
"fixing home 3 : s.Oliver Würzburg 1.0\n",
|
|
"fixing home 5 : s.Oliver Würzburg 1.0\n",
|
|
"fixing home 7 : s.Oliver Würzburg 1.0\n",
|
|
"fixing home 9 : s.Oliver Würzburg 1.0\n",
|
|
"fixing home 12 : s.Oliver Würzburg 1.0\n",
|
|
"fixing home 13 : s.Oliver Würzburg 1.0\n",
|
|
"fixing home 16 : s.Oliver Würzburg 1.0\n",
|
|
" - ['BASICGAME', '1-17']\n",
|
|
"\n",
|
|
"[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]\n",
|
|
"########################\n",
|
|
"# SOLVING MODEL BASICGAME FOR ROUNDS 1-17 USING GAP 0.0 and MAXTIME 300 #\n",
|
|
"########################\n"
|
|
]
|
|
},
|
|
{
|
|
"ename": "TypeError",
|
|
"evalue": "'>' not supported between instances of 'NoneType' and 'float'",
|
|
"output_type": "error",
|
|
"traceback": [
|
|
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
|
|
"\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
|
|
"\u001b[0;32m<ipython-input-29-44dbd5b21bed>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 132\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mt1\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mt2\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mgames\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 133\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mgetTeamById\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mt1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m!=\u001b[0m\u001b[0;34m\"-\"\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mgetTeamById\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mt2\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m!=\u001b[0m\u001b[0;34m\"-\"\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mt1\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mt2\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mr\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mgameInBasicRound\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mkeys\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mtype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mgameInBasicRound\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mt1\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mt2\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mr\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m!=\u001b[0m \u001b[0mint\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 134\u001b[0;31m \u001b[0;32mif\u001b[0m \u001b[0mgetVal\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mgameInBasicRound\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mt1\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mt2\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mr\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m>\u001b[0m\u001b[0;36m0.9\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 135\u001b[0m \u001b[0mgameInBasicRound\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mt1\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mt2\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mr\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlowBound\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 136\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
|
|
"\u001b[0;31mTypeError\u001b[0m: '>' not supported between instances of 'NoneType' and 'float'"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"\n",
|
|
"print(\"Model built now solving .... \")\n",
|
|
"\n",
|
|
"nRuns =1\n",
|
|
"maxSolveTime = 300\n",
|
|
"\n",
|
|
"if thisSeason.groupBased:\n",
|
|
" maxSolveTime = 40\n",
|
|
"\n",
|
|
"mipgap=0.01\n",
|
|
"\n",
|
|
"# print (\"######## Testing\")\n",
|
|
"# model2.solve(GUROBI(MIPGap=0.0, TimeLimit=120,msg=1))\n",
|
|
"\n",
|
|
"\n",
|
|
"use_LP_heuristic= False\n",
|
|
"print (runMode=='New' , useBasicGames , runPatternAssignmentFirst)\n",
|
|
"\n",
|
|
"nRuns=nPhases\n",
|
|
"# maxSolveTime = 120\n",
|
|
"mipgap=0.0\n",
|
|
"# mipgap=0.95\n",
|
|
"\n",
|
|
"# nRuns =1\n",
|
|
"onlyReopt= True\n",
|
|
"onlyReopt= False\n",
|
|
"onlyFewTrips= False\n",
|
|
"singleTripWeight =10 \n",
|
|
"\n",
|
|
"if onlyReopt:\n",
|
|
" nRuns=0\n",
|
|
"\n",
|
|
"maxIntRound=nRounds\n",
|
|
"\n",
|
|
"\n",
|
|
"missing_imp=[] \n",
|
|
"cntr =0\n",
|
|
"\n",
|
|
"for st in optSteps:\n",
|
|
" print (\" - \" ,st )\n",
|
|
" cntr +=1\n",
|
|
" if runMode=='New' and st[0] == \"HARDCONSTRAINTS\":\n",
|
|
" for bl in blockings:\n",
|
|
" blockingVio[bl['id']].upBound=0\n",
|
|
" print (\"blocking tightened : \" , getTeamById [bl['team_id']] , bl['day_id'] ) \n",
|
|
" for enc in encwishes:\n",
|
|
" if enc['reason']==\"Seed Game\":\n",
|
|
" encVio[enc['id']].upBound=0\n",
|
|
" \n",
|
|
" \n",
|
|
" if runMode=='New' and len(st)>=1 and st[0] in [\"PATTERNS\",\"HOMEAWAY\", \"BASICGAME\", \"GAME\",\"GAMES\", \"GROUP\", \"TRIPS\", \"LP-HEURISTIC\"]:\n",
|
|
" newRounds = []\n",
|
|
" print() \n",
|
|
" optTarget = st[0]\n",
|
|
" if len(st)>1 :\n",
|
|
" for rf in st[1].split(\",\"):\n",
|
|
" rr= rf.split(\"-\")\n",
|
|
" if len(rr)==1 :\n",
|
|
" newRounds.append(min(nRounds,int(rr[0])))\n",
|
|
" else:\n",
|
|
" for ii in range (int(rr[0]), min(nRounds, int(rr[1])+1)):\n",
|
|
" newRounds.append(ii) \n",
|
|
" newRoundsString = st[1]\n",
|
|
" else : \n",
|
|
" newRounds = rounds\n",
|
|
" newRoundsString = \"1-\"+str(nRounds) \n",
|
|
"\n",
|
|
" optsteptime = maxSolveTime\n",
|
|
" optstepgap = mipgap\n",
|
|
"\n",
|
|
" if len(st)>=3 and st[2]!=\"\":\n",
|
|
" optstepgap = float(st[2])\n",
|
|
" if len(st)>=4 and st[3]!=\"\":\n",
|
|
" optsteptime = float(st[3])\n",
|
|
" \n",
|
|
" print (newRounds)\n",
|
|
"\n",
|
|
" if st[0] == \"HOMEAWAY\":\n",
|
|
" for t in teams:\n",
|
|
" for r in newRounds:\n",
|
|
" homeInRound[(t,r)].cat = pulp.LpInteger\n",
|
|
"\n",
|
|
" if st[0] == \"BASICGAME\":\n",
|
|
" for (t1,t2) in games:\n",
|
|
" for r in newRounds:\n",
|
|
" gameInBasicRound[(t1,t2,r)].cat = pulp.LpInteger\n",
|
|
"\n",
|
|
" if st[0] in [\"GAME\",\"GAMES\"]:\n",
|
|
" for (t,t2) in games:\n",
|
|
" for r in newRounds:\n",
|
|
" for rd in getRoundDaysByRound[r]:\n",
|
|
" makeIntVar(x[(t,t2,rd)])\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
" print ('########################')\n",
|
|
" print ('# SOLVING MODEL '+optTarget+' FOR ROUNDS '+ newRoundsString+' USING GAP ' + str(optstepgap) + ' and MAXTIME ' + str(optsteptime) + ' #')\n",
|
|
" print ('########################')\n",
|
|
" \n",
|
|
" if solver == \"CBC\":\n",
|
|
" model2.solve(PULP_CBC_CMD(fracGap = optstepgap, maxSeconds = optsteptime, threads = 8,msg=1))\n",
|
|
" elif solver == \"Gurobi\":\n",
|
|
" model2.solve(GUROBI(MIPGap=optstepgap, TimeLimit=optsteptime,msg=1, Method=2,NodeMethod=2))\n",
|
|
" else:\n",
|
|
" # for debugging: \n",
|
|
" # with open (\"model2.txt\", \"w\") as f:\n",
|
|
" # f.write(model2.__repr__())\n",
|
|
" model2.solve(XPRESS(msg=1,targetGap=optstepgap, maxSeconds = optsteptime, options=[\"THREADS=12,DETERMINISTIC=0,CUTSTRATEGY=0\"], keepFiles=True))\n",
|
|
"\n",
|
|
" if model2.status<0:\n",
|
|
" print(\"Status: \" , model2.status)\n",
|
|
"\n",
|
|
" if not lowerBoundFound:\n",
|
|
" lowerBoundFound=value(model2.objective)\n",
|
|
"\n",
|
|
" cntr_rnd =0\n",
|
|
" \n",
|
|
"\n",
|
|
" if st[0] == \"HOMEAWAY\":\n",
|
|
" print (teams)\n",
|
|
" print (newRounds)\n",
|
|
" for t in teams:\n",
|
|
" for r in newRounds:\n",
|
|
" if homeInRound[(t,r)].value() >0.9 :\n",
|
|
" print ('fixing home '+ str(r) + ' : '+ getTeamById[t] +\" \" + str(homeInRound[(t,r)].value()))\n",
|
|
" homeInRound[(t,r)].lowBound = 1\n",
|
|
" else:\n",
|
|
" homeInRound[(t,r)].upBound = 0\n",
|
|
" \n",
|
|
"\n",
|
|
" if st[0] == \"BASICGAME\":\n",
|
|
" for r in newRounds:\n",
|
|
" for (t1,t2) in games:\n",
|
|
" if getTeamById[t1]!=\"-\" and getTeamById[t2]!=\"-\" and (t1,t2,r) in gameInBasicRound.keys() and type(gameInBasicRound[(t1,t2,r)])!= int:\n",
|
|
" if getVal(gameInBasicRound[(t1,t2,r)])>0.9:\n",
|
|
" gameInBasicRound[(t1,t2,r)].lowBound = 1\n",
|
|
" else:\n",
|
|
" gameInBasicRound[(t1,t2,r)].upBound = 0\n",
|
|
"\n",
|
|
" if st[0] in [\"GAME\",\"GAMES\"]:\n",
|
|
" feedback = \"Optimize games....\"\n",
|
|
" missing_imp=[]\n",
|
|
" \n",
|
|
" for (t1,t2) in realgames:\n",
|
|
" if missingGamesVio[(t1,t2)].value() >0.9:\n",
|
|
" feedback += 'Game missing : '+getTeamById[t1] + ' - ' + getTeamById[t2] + ' ' + str(missingGamesVio[(t1,t2)].value()) + '<br> \\n'\n",
|
|
" missing_imp += [(1,nRounds,[t1,t2], 50)] \n",
|
|
"\n",
|
|
" print (missing_imp)\n",
|
|
" print (feedback)\n",
|
|
" print (\"number of assigned games : \" , sum([getVal(x[ttrd]) for ttrd in x.keys()]))\n",
|
|
"\n",
|
|
" for (t1,t2) in games:\n",
|
|
" for r in newRounds:\n",
|
|
" for rd in getRoundDaysByRound[r]:\n",
|
|
" if getVal(x[(t1,t2,rd)])>0.9:\n",
|
|
" setLB(x[(t1,t2,rd)],1) \n",
|
|
" print (\"fixing \" ,t1,t2,rd, x[(t1,t2,rd)].lowBound )\n",
|
|
" else:\n",
|
|
" setUB(x[(t1,t2,rd)],0)\n",
|
|
"\n",
|
|
" for r in basicRounds:\n",
|
|
" for t1 in realteams:\n",
|
|
" homeInBasicRound[(t1,r)].lowBound = 0\n",
|
|
" homeInBasicRound[(t1,r)].upBound = 10\n",
|
|
" awayInBasicRound[(t1,r)].lowBound = 0\n",
|
|
" awayInBasicRound[(t1,r)].upBound = 10\n",
|
|
" for t2 in opponents[t1]:\n",
|
|
" if (t1,t2) in games:\n",
|
|
" gameInBasicRound[(t1,t2,r)].cat = pulp.LpContinuous\n",
|
|
" gameInBasicRound[(t1,t2,r)].lowBound = 0\n",
|
|
"\n",
|
|
"\n",
|
|
" for t in realteams:\n",
|
|
" for r in newRounds:\n",
|
|
" homeInRound[(t,r)].cat = pulp.LpContinuous\n",
|
|
" for t2 in opponents[t]:\n",
|
|
" for rd in getRoundDaysByRound[r]:\n",
|
|
" if (t,t2) in games and getVal(x[(t,t2,rd)]) >0.9 :\n",
|
|
" setLB(x[(t,t2,rd)], x[(t,t2,rd)].value())\n",
|
|
" currentSolution =[ (t1,t2,r,d) for (t1,t2) in realgames for (r,d) in roundDays if getVal(x[(t1,t2,(r,d))]) >0.9 ]\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"for r in rounds:\n",
|
|
" for t in teams:\n",
|
|
" homeInRound[(t,r)].lowBound = 0\n",
|
|
" homeInRound[(t,r)].upBound = 1\n",
|
|
"\n",
|
|
"for (t1,t2) in games:\n",
|
|
" for r in rounds:\n",
|
|
" for rd in getRoundDaysByRound[r]:\n",
|
|
" makeIntVar(x[(t1,t2,rd)])\n",
|
|
"\n",
|
|
"print ('Solved Again')\n",
|
|
"print ('NOW REOPT')\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "496f8609",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": []
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "Python 3.7.13 ('leagues')",
|
|
"language": "python",
|
|
"name": "python3"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.6.9"
|
|
},
|
|
"vscode": {
|
|
"interpreter": {
|
|
"hash": "a07b7f3079ca8c056705d3c757c4f3f92f9509f33eeab9ad5420dacec37bc01a"
|
|
}
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5
|
|
}
|