research/uefa/feb24_checkandschedule/uefa_tester_24_gurobi.py
2024-03-13 09:35:38 +01:00

335 lines
11 KiB
Python

import csv
import operator
import os
import random
import sys
import time
import timeit
import datetime
# import networkx as nx
from datetime import datetime
from dateutil.parser import parse
from math import sqrt, pow, sin, cos, atan2, pi
try:
import simplejson as json
except:
import json
from gurobipy import *
# import config
getTeamsOfPot = { p: [ p+str(i) for i in range(1,10) ] for p in ["A","B","C","D"] }
allTeams = getTeamsOfPot['A']+getTeamsOfPot['B']+getTeamsOfPot['C']+getTeamsOfPot['D']
activeTeams= allTeams
pots = getTeamsOfPot.keys()
# print (pots)
gamesAgainst = { (p1,p2) : 2 for p1 in pots for p2 in pots}
# for p in pots:
# gamesAgainst[(p,p)]=2
# for (p1,p2) in [('A','D'), ('D','A'), ('B','C'), ('C','B') ]:
# gamesAgainst[(p1,p2)]=2
nMatchDays=8
# for p1 in pots:
# for p2 in pots:
# print (p1,p2,gamesAgainst[(p1,p2)])
# print()
# print (allTeams)
cntr=0
mbus = Model("Draw")
possAssigns= [ (t1,t2) for t1 in allTeams for t2 in allTeams if t1!=t2]
# print (possAssigns)
plays = mbus.addVars(possAssigns, vtype=GRB.BINARY)
for (t1,t2) in possAssigns:
if t1<t2:
mbus.addConstr( plays[(t1,t2)] ==plays[(t2,t1)] )
for p in pots:
for t in getTeamsOfPot[p]:
for p2 in pots:
mbus.addConstr( quicksum(plays[(t,t2)] for t2 in getTeamsOfPot[p2] if t!=t2 ) == gamesAgainst[(p,p2)])
# for (t1,t2) in [("A1","A2"), ("A2","A3"), ("A3","A1"),
# ("B1","B2"), ("B2","B3"), ("B3","B1"),
# ("C1","C2"), ("C2","C3"), ("C3","C1"),
# # ("D1","D2"), ("D2","D3"), ("D3","D1"),
# ] :
# mbus.addConstr( plays[(t1,t2)] == 1)
# for (p1,p2) in [ ("A","B"), ("B","C"), ("C","D"), ("D","A") ]:
# for (n1,n2) in [ (1,1),(1,2),(3,2),(3,3),(2,3) ,(2,1)]:
# mbus.addConstr( plays[( p1+str(n1) , p2+str(n2))] == 1)
# potpairs = [ (p1,p2) for p1 in pots for p2 in pots if p1!=p2]
# clusters = [[1,2,3], [4,5,6], [7,8,9]]
# for cl in clusters:
# for (p1,p2) in potpairs:
# if len(cl)==2:
# mbus.addConstr( quicksum(plays[( p1+str(n1),p2+str(n2))] for n1 in cl for n2 in cl ) == 4)
# print ( [( p1+str(n1),p2+str(n2)) for n1 in cl for n2 in cl ])
# for (p1,p2) in [ ("A","B"), ("B","C"), ("C","D"), ("D","A") ]:
# for (n1,n2) in [ (1,1),(1,2),(3,2),(3,3),(2,3) ,(2,1)]:
# mbus.addConstr( plays[( p1+str(n1) , p2+str(n2))] == 1)
badExample=False
if badExample:
for p in pots:
for i in [2,3]:
mbus.addConstr( plays[( p+str(i-1),p+str(i))]==1)
# print ( p+str(i-1),p+str(i))
mbus.addConstr( plays[( p+"3",p+"1")]==1)
for p1 in pots:
for i in [1,2,3]:
for p2 in pots:
if p1!=p2:
mbus.addConstr( quicksum(plays[( p1+str(i),p2+str(j))] for j in [4,5,6] ) ==2)
mbus.Params.OutputFlag = 0
debug=False
now = datetime.now()
nSims=1
if len(sys.argv)>1:
nSims=int(sys.argv[1])
mbus_time = 0
cal_time0 = 0
cal_time1 = 0
cal_time2 = 0
cal_time3 = 0
report_time = 0
solutions =[]
solution_strings =[]
for i in range(nSims):
ttt = time.time()
if i%100==0:
print(i)
print("mbus_time:", mbus_time)
print("cal_time0:", cal_time0)
print("cal_time1:", cal_time1)
print("cal_time2:", cal_time2)
print("cal_time3:", cal_time3)
print("report_time:", report_time)
cntr+=1
mbus.setObjective(quicksum([ int(100*random.random()) * plays[pa] for pa in possAssigns ]))
# mbus.setObjective(quicksum([ max(0,int(pa[0][1]) - int(pa[1][1] )) * plays[pa] for pa in possAssigns ]))
# print ("DRAWING !!!!")
mbus.optimize()
mbus_time += time.time()-ttt
ttt = time.time()
sol= [ pa for pa in possAssigns if plays[pa].x>0.9]
sol2 = [('A1', 'A7'), ('A1', 'A9'), ('A1', 'B2'), ('A1', 'B3'), ('A1', 'C1'), ('A1', 'C2'), ('A1', 'D1'), ('A1', 'D2'), ('A2', 'A3'), ('A2', 'A4'), ('A2', 'B1'), ('A2', 'B4'), ('A2', 'C2'), ('A2', 'C3'), ('A2', 'D1'), ('A2', 'D4'), ('A3', 'A4'), ('A3', 'B3'), ('A3', 'B4'), ('A3', 'C3'), ('A3', 'C4'), ('A3', 'D2'), ('A3', 'D3'), ('A4', 'B1'), ('A4', 'B2'), ('A4', 'C1'), ('A4', 'C4'), ('A4', 'D3'), ('A4', 'D4'), ('A5', 'A8'), ('A5', 'A9'), ('A5', 'B5'), ('A5', 'B9'), ('A5', 'C8'), ('A5', 'C9'), ('A5', 'D6'), ('A5', 'D9'), ('A6', 'A7'), ('A6', 'A8'), ('A6', 'B6'), ('A6', 'B8'), ('A6', 'C5'), ('A6', 'C6'), ('A6', 'D5'), ('A6', 'D6'), ('A7', 'B5'), ('A7', 'B6'), ('A7', 'C5'), ('A7', 'C7'), ('A7', 'D7'), ('A7', 'D8'), ('A8', 'B7'), ('A8', 'B9'), ('A8', 'C8'), ('A8', 'C9'), ('A8', 'D5'), ('A8', 'D7'), ('A9', 'B7'), ('A9', 'B8'), ('A9', 'C6'), ('A9', 'C7'), ('A9', 'D8'), ('A9', 'D9'), ('B1', 'B2'), ('B1', 'B4'), ('B1', 'C2'), ('B1', 'C3'), ('B1', 'D3'), ('B1', 'D4'), ('B2', 'B3'), ('B2', 'C3'), ('B2', 'C4'), ('B2', 'D1'), ('B2', 'D3'), ('B3', 'B4'), ('B3', 'C1'), ('B3', 'C2'), ('B3', 'D2'), ('B3', 'D4'), ('B4', 'C1'), ('B4', 'C4'), ('B4', 'D1'), ('B4', 'D2'), ('B5', 'B8'), ('B5', 'B9'), ('B5', 'C6'), ('B5', 'C7'), ('B5', 'D7'), ('B5', 'D9'), ('B6', 'B7'), ('B6', 'B9'), ('B6', 'C5'), ('B6', 'C8'), ('B6', 'D5'), ('B6', 'D9'), ('B7', 'B8'), ('B7', 'C6'), ('B7', 'C8'), ('B7', 'D6'), ('B7', 'D7'), ('B8', 'C5'), ('B8', 'C9'), ('B8', 'D6'), ('B8', 'D8'), ('B9', 'C7'), ('B9', 'C9'), ('B9', 'D5'), ('B9', 'D8'), ('C1', 'C2'), ('C1', 'C4'), ('C1', 'D3'), ('C1', 'D4'), ('C2', 'C3'), ('C2', 'D1'), ('C2', 'D2'), ('C3', 'C4'), ('C3', 'D1'), ('C3', 'D3'), ('C4', 'D2'), ('C4', 'D4'), ('C5', 'C6'), ('C5', 'C8'), ('C5', 'D5'), ('C5', 'D6'), ('C6', 'C9'), ('C6', 'D7'), ('C6', 'D8'), ('C7', 'C8'), ('C7', 'C9'), ('C7', 'D7'), ('C7', 'D8'), ('C8', 'D6'), ('C8', 'D9'), ('C9', 'D5'), ('C9', 'D9'), ('D1', 'D2'), ('D1', 'D3'), ('D2', 'D4'), ('D3', 'D4'), ('D5', 'D6'), ('D5', 'D8'), ('D6', 'D9'), ('D7', 'D8'), ('D7', 'D9')]
sol = []
for (g1,g2) in sol:
sol.append((g1,g2))
sol.append((g2,g1))
solutions.append(sol.copy())
report_time += time.time()-ttt
ttt = time.time()
if debug:
print ("Solution")
# exit(0)
print ("INPOT")
for p in pots:
print ("")
print ("POT",p)
for (t1,t2) in [(t1,t2) for (t1,t2) in sol if t1<t2 and t1[0]==p and t2[0]==p]:
print ( t1 , "-" , t2)
print ("OUTPOT")
for p in pots:
print ("")
print ("POT",p)
for (t1,t2) in [(t1,t2) for (t1,t2) in sol if t1[0]==p and t2[0]!=p]:
print ( t1 , "-" , t2)
solstring =""
for pa in possAssigns:
solstring+= str(int(plays[pa].x +0.1) )
if nSims < 1000:
solution_strings.append(solstring)
report_time += time.time()-ttt
ttt = time.time()
mds =range(1,nMatchDays+1)
pas2= [ (t1,t2,md) for md in mds for (t1,t2) in sol]
# print ("pas2", pas2)
cal = Model("Calendar")
x = cal.addVars(pas2, vtype=GRB.BINARY)
computeCalendarsHA = True
computeCalendarsHA = False
cal_time0 += time.time()-ttt
ttt = time.time()
if computeCalendarsHA:
pos_patterns = [
[1,0,1,1,0,0,1,0 ],
[1,0,1,0,1,0,1,0 ],
[1,0,1,0,1,0,0,1 ],
[1,0,1,0,0,1,1,0 ],
[1,0,1,0,0,1,0,1 ],
[1,0,0,1,1,0,1,0 ],
[1,0,0,1,1,0,0,1 ],
[1,0,0,1,0,1,1,0 ],
[1,0,0,1,0,1,0,1 ],
]
# add reverse patterns (all those starting with 0,1 )
pos_patterns+=[ [ 1-p[i] for i in range(8)] for p in pos_patterns ]
# print ("pos_patterns",pos_patterns)
positions = range (len(pos_patterns))
pos = cal.addVars( [(t,p) for t in allTeams for p in positions], vtype=GRB.CONTINUOUS)
for t in allTeams:
cal.addConstr( quicksum( [ pos[t,p] for p in positions ]) ==1)
for md in mds:
cal.addConstr( quicksum(x[(t1,t2,md)] for (t1,t2) in sol if t ==t1 ) == quicksum( [ pos[t,p] for p in positions if pos_patterns[p][md-1]==1 ]) )
for (t1,t2) in sol :
if t1<t2:
cal.addConstr( quicksum(x[(t1,t2,md)] + x[(t2,t1,md)] for md in mds) <=1 )
for t in allTeams:
# every team 4 home games
cal.addConstr( quicksum(x[(t1,t2,md)] for (t1,t2) in sol if t ==t1 for md in mds ) == 4)
# every team one game a day
for md in mds:
cal.addConstr( quicksum(x[(t1,t2,md)] for (t1,t2) in sol if t in [t1,t2] ) == 1)
for p in pots:
for t in getTeamsOfPot[p]:
for p2 in pots:
cal.addConstr( quicksum(x[(t1,t2,md)] for (t1,t2) in sol if t ==t1 and t2 in getTeamsOfPot[p2] for md in mds ) >= int(0.5*gamesAgainst[(p,p2)]) )
else:
for (t1,t2) in sol :
if t1<t2:
cal.addConstr( quicksum(x[(t1,t2,md)] for md in mds) ==1 )
for md in mds:
cal.addConstr( x[(t1,t2,md)] == x[(t2,t1,md)] )
for t in activeTeams:
for md in mds:
cal.addConstr( quicksum(x[(t1,t2,md)] for (t1,t2) in sol if t==t1 ) == 1)
cal.setObjective(quicksum( -x[pa] for pa in x.keys() ))
cal.Params.OutputFlag = 1
# print ("SCHEDULING !!!!")
cal_time1 += time.time()-ttt
ttt = time.time()
cal.optimize()
cal_time2 += time.time()-ttt
ttt = time.time()
# cal_sol= [pa for pa in x.keys() if x[pa].x>0.9 ]
# print( cal_sol)
# for pa in cal_sol :
# print (pa)
# # print (cal.status)
# print(cal.objVal)
if cal.status!=2 or cal.objVal>-288:
sol= [ (t1,t2) for (t1,t2) in sol if t1<t2]
# sol= [ (t1,t2) for (t1,t2) in sol if t1[0]=="A" and t2[0]=="D" ]
print ("No calendar for ", sol)
print ("Tested " , str(i+1) , " calendars" )
exit(0)
# pas2_sol= [ pas for pas in pas2 if x[pas].x>0.9]
# # print (pas2_sol)
# showSolution= False
# showSolution= True
# if showSolution and debug:
# for md in mds:
# print (md,":")
# for (t1,t2,md2) in pas2_sol:
# # if md2==md and t1<t2 and "C" in [t1[0],t2[0]] :
# if md2==md :
# print (" " ,t1, " -" ,t2)
for t in activeTeams:
for md in mds:
if not computeCalendarsHA and sum(x[(t1,t2,md)].x for (t1,t2) in sol if t==t1 ) < 1:
print ("ALERT ",t,md)
exit()
# print (solutions)
# oldGm = [ gg for gg in solutions[1] if gg not in solutions[0]]
# if len(solutions)>1 and showSolution:
# newGm = [ gg for gg in solutions[-1] if gg not in solutions[-2]]
cal_time3 += time.time()-ttt
ttt = time.time()
# print (oldGm)
# print (newGm)
# print (solution_strings)
print (len(set(solution_strings)) )
f = open("draw_feasibility/log_"+datetime.now().strftime("%Y%m%d_%H%M%S")+"_"+str(nSims)+".txt", "a")
for s in solutions:
for s2 in s:
f.write(s2[0]+s2[1])
f.write("\n")
f.close()
print ("done" , datetime.now()-now )
print("mbus_time:", mbus_time)
print("cal_time0:", cal_time0)
print("cal_time1:", cal_time1)
print("cal_time2:", cal_time2)
print("cal_time3:", cal_time3)
print("report_time:", report_time)