2024-01-31 15:37:32 +01:00

308 lines
13 KiB
Python
Executable File

import pulp
from pulp import lpSum, XPRESS, GUROBI, PULP_CBC_CMD
"""
##########################################################################################################################
##########################################################################################################################
"""
teams = [{'id': 3696, 'country': 'FRA', 'pot': 4, 'shortname': 'Lens'},
{'id': 3697, 'country': 'GER', 'pot': 4, 'shortname': 'Unio'},
{'id': 3698, 'country': 'ENG', 'pot': 4, 'shortname': 'Newc'},
{'id': 3699, 'country': 'ESP', 'pot': 4, 'shortname': 'Soci'},
{'id': 3700, 'country': 'SUI', 'pot': 3, 'shortname': 'Youn'},
{'id': 3701, 'country': 'NED', 'pot': 3, 'shortname': 'Feye'},
{'id': 3702, 'country': 'ENG', 'pot': 1, 'shortname': 'ManU'},
{'id': 3730, 'country': 'SRB', 'pot': 3, 'shortname': 'Crve'},
{'id': 3732, 'country': 'ITA', 'pot': 1, 'shortname': 'Inte'},
{'id': 3734, 'country': 'ITA', 'pot': 2, 'shortname': 'Napo'},
{'id': 3756, 'country': 'ITA', 'pot': 3, 'shortname': 'Mila'},
{'id': 3757, 'country': 'SCO', 'pot': 4, 'shortname': 'Celt'},
{'id': 3758, 'country': 'DEN', 'pot': 3, 'shortname': 'Cope'},
{'id': 3760, 'country': 'NED', 'pot': 3, 'shortname': 'PSV'},
{'id': 3761, 'country': 'ENG', 'pot': 2, 'shortname': 'Arse'},
{'id': 3762, 'country': 'ESP', 'pot': 1, 'shortname': 'Sevi'},
{'id': 3764, 'country': 'ENG', 'pot': 1, 'shortname': 'Live'},
{'id': 3765, 'country': 'UKR', 'pot': 2, 'shortname': 'Shak'},
{'id': 3771, 'country': 'ITA', 'pot': 3, 'shortname': 'Atal'},
{'id': 3853, 'country': 'FRA', 'pot': 4, 'shortname': 'Mars'},
{'id': 3870, 'country': 'TUR', 'pot': 4, 'shortname': 'Gala'},
{'id': 3894, 'country': 'ESP', 'pot': 1, 'shortname': 'Barc'},
{'id': 3895, 'country': 'ITA', 'pot': 3, 'shortname': 'Lazi'},
{'id': 3898, 'country': 'ESP', 'pot': 2, 'shortname': 'Atle'},
{'id': 3904, 'country': 'AZE', 'pot': 4, 'shortname': 'Qara'},
{'id': 3925, 'country': 'BEL', 'pot': 4, 'shortname': 'Antw'},
{'id': 3926, 'country': 'GER', 'pot': 2, 'shortname': 'Leip'},
{'id': 3928, 'country': 'POR', 'pot': 3, 'shortname': 'Brag'},
{'id': 3930, 'country': 'POR', 'pot': 2, 'shortname': 'Benf'},
{'id': 3932, 'country': 'GER', 'pot': 1, 'shortname': 'Baye'},
{'id': 3933, 'country': 'ESP', 'pot': 1, 'shortname': 'Real'},
{'id': 3935, 'country': 'FRA', 'pot': 1, 'shortname': 'PSG'},
{'id': 3936, 'country': 'GER', 'pot': 2, 'shortname': 'Dort'},
{'id': 3937, 'country': 'POR', 'pot': 2, 'shortname': 'Port'},
{'id': 3938, 'country': 'AUT', 'pot': 2, 'shortname': 'Salz'},
{'id': 3940, 'country': 'ENG', 'pot': 1, 'shortname': 'Manc'}]
getTeamById = {3702: '(ENG) Manchester United FC',
3764: '(ENG) Liverpool FC',
3940: '(ENG) Manchester City FC',
3762: '(ESP) Sevilla FC',
3894: '(ESP) FC Barcelona',
3933: '(ESP) Real Madrid CF',
3935: '(FRA) Paris Saint-Germain',
3932: '(GER) FC Bayern München',
3732: '(ITA) FC Internazionale Milano',
3938: '(AUT) FC Salzburg',
3761: '(ENG) Arsenal FC',
3898: '(ESP) Club Atlético de Madrid',
3926: '(GER) RB Leipzig',
3936: '(GER) Borussia Dortmund',
3734: '(ITA) SSC Napoli',
3930: '(POR) SL Benfica',
3937: '(POR) FC Porto',
3765: '(UKR) FC Shakhtar Donetsk',
3758: '(DEN) F.C. Copenhagen',
3756: '(ITA) AC Milan',
3771: '(ITA) Atalanta BC',
3895: '(ITA) S.S. Lazio',
3701: '(NED) Feyenoord',
3760: '(NED) PSV Eindhoven',
3928: '(POR) SC Braga',
3730: '(SRB) FK Crvena zvezda',
3700: '(SUI) BSC Young Boys',
3904: '(AZE) Qarabağ FK',
3925: '(BEL) R. Antwerp FC',
3698: '(ENG) Newcastle United FC',
3699: '(ESP) Real Sociedad de Fútbol',
3696: '(FRA) RC Lens',
3853: '(FRA) Olympique de Marseille',
3697: '(GER) 1. FC Union Berlin',
3757: '(SCO) Celtic FC',
3870: '(TUR) Galatasaray A.Ş.'}
pot = {1: [{'id': 3702, 'country': 'ENG', 'pot': 1, 'shortname': 'ManU'},
{'id': 3764, 'country': 'ENG', 'pot': 1, 'shortname': 'Liver'},
{'id': 3940, 'country': 'ENG', 'pot': 1, 'shortname': 'Manch'},
{'id': 3762, 'country': 'ESP', 'pot': 1, 'shortname': 'Sevil'},
{'id': 3894, 'country': 'ESP', 'pot': 1, 'shortname': 'Barce'},
{'id': 3933, 'country': 'ESP', 'pot': 1, 'shortname': 'Real '},
{'id': 3935, 'country': 'FRA', 'pot': 1, 'shortname': 'PSG'},
{'id': 3932, 'country': 'GER', 'pot': 1, 'shortname': 'Bayer'},
{'id': 3732, 'country': 'ITA', 'pot': 1, 'shortname': 'Inter'}],
2: [{'id': 3938, 'country': 'AUT', 'pot': 2, 'shortname': 'Salzb'},
{'id': 3761, 'country': 'ENG', 'pot': 2, 'shortname': 'Arsen'},
{'id': 3898, 'country': 'ESP', 'pot': 2, 'shortname': 'Atlét'},
{'id': 3926, 'country': 'GER', 'pot': 2, 'shortname': 'Leipz'},
{'id': 3936, 'country': 'GER', 'pot': 2, 'shortname': 'Dortm'},
{'id': 3734, 'country': 'ITA', 'pot': 2, 'shortname': 'Napol'},
{'id': 3930, 'country': 'POR', 'pot': 2, 'shortname': 'Benfi'},
{'id': 3937, 'country': 'POR', 'pot': 2, 'shortname': 'Porto'},
{'id': 3765, 'country': 'UKR', 'pot': 2, 'shortname': 'Shakh'}],
3: [{'id': 3758, 'country': 'DEN', 'pot': 3, 'shortname': 'Copen'},
{'id': 3756, 'country': 'ITA', 'pot': 3, 'shortname': 'Milan'},
{'id': 3771, 'country': 'ITA', 'pot': 3, 'shortname': 'Atala'},
{'id': 3895, 'country': 'ITA', 'pot': 3, 'shortname': 'Lazio'},
{'id': 3701, 'country': 'NED', 'pot': 3, 'shortname': 'Feyen'},
{'id': 3760, 'country': 'NED', 'pot': 3, 'shortname': 'PSV'},
{'id': 3928, 'country': 'POR', 'pot': 3, 'shortname': 'Braga'},
{'id': 3730, 'country': 'SRB', 'pot': 3, 'shortname': 'Crven'},
{'id': 3700, 'country': 'SUI', 'pot': 3, 'shortname': 'Young'}],
4: [{'id': 3904, 'country': 'AZE', 'pot': 4, 'shortname': 'Qarab'},
{'id': 3925, 'country': 'BEL', 'pot': 4, 'shortname': 'Antwe'},
{'id': 3698, 'country': 'ENG', 'pot': 4, 'shortname': 'Newca'},
{'id': 3699, 'country': 'ESP', 'pot': 4, 'shortname': 'Socied'},
{'id': 3696, 'country': 'FRA', 'pot': 4, 'shortname': 'Lens'},
{'id': 3853, 'country': 'FRA', 'pot': 4, 'shortname': 'Marse'},
{'id': 3697, 'country': 'GER', 'pot': 4, 'shortname': 'Union'},
{'id': 3757, 'country': 'SCO', 'pot': 4, 'shortname': 'Celti'},
{'id': 3870, 'country': 'TUR', 'pot': 4, 'shortname': 'Galat'}]}
teams_from_country = {'NED': [{'id': 3701, 'country': 'NED', 'pot': 3, 'shortname': 'Feye'},
{'id': 3760, 'country': 'NED', 'pot': 3, 'shortname': 'PSV'}],
'UKR': [{'id': 3765, 'country': 'UKR', 'pot': 2, 'shortname': 'Shak'}],
'ENG': [{'id': 3702, 'country': 'ENG', 'pot': 1, 'shortname': 'ManU'},
{'id': 3764, 'country': 'ENG', 'pot': 1, 'shortname': 'Live'},
{'id': 3940, 'country': 'ENG', 'pot': 1, 'shortname': 'Manc'},
{'id': 3761, 'country': 'ENG', 'pot': 2, 'shortname': 'Arse'},
{'id': 3698, 'country': 'ENG', 'pot': 4, 'shortname': 'Newc'}],
'POR': [{'id': 3930, 'country': 'POR', 'pot': 2, 'shortname': 'Benf'},
{'id': 3937, 'country': 'POR', 'pot': 2, 'shortname': 'Port'},
{'id': 3928, 'country': 'POR', 'pot': 3, 'shortname': 'Brag'}],
'GER': [{'id': 3932, 'country': 'GER', 'pot': 1, 'shortname': 'Baye'},
{'id': 3926, 'country': 'GER', 'pot': 2, 'shortname': 'Leip'},
{'id': 3936, 'country': 'GER', 'pot': 2, 'shortname': 'Dort'},
{'id': 3697, 'country': 'GER', 'pot': 4, 'shortname': 'Unio'}],
'DEN': [{'id': 3758, 'country': 'DEN', 'pot': 3, 'shortname': 'Cope'}],
'FRA': [{'id': 3935, 'country': 'FRA', 'pot': 1, 'shortname': 'PSG'},
{'id': 3696, 'country': 'FRA', 'pot': 4, 'shortname': 'Lens'},
{'id': 3853, 'country': 'FRA', 'pot': 4, 'shortname': 'Mars'}],
'AZE': [{'id': 3904, 'country': 'AZE', 'pot': 4, 'shortname': 'Qara'}],
'TUR': [{'id': 3870, 'country': 'TUR', 'pot': 4, 'shortname': 'Gala'}],
'ITA': [{'id': 3732, 'country': 'ITA', 'pot': 1, 'shortname': 'Inte'},
{'id': 3734, 'country': 'ITA', 'pot': 2, 'shortname': 'Napo'},
{'id': 3756, 'country': 'ITA', 'pot': 3, 'shortname': 'Mila'},
{'id': 3771, 'country': 'ITA', 'pot': 3, 'shortname': 'Atal'},
{'id': 3895, 'country': 'ITA', 'pot': 3, 'shortname': 'Lazi'}],
'BEL': [{'id': 3925, 'country': 'BEL', 'pot': 4, 'shortname': 'Antw'}],
'SRB': [{'id': 3730, 'country': 'SRB', 'pot': 3, 'shortname': 'Crve'}],
'SUI': [{'id': 3700, 'country': 'SUI', 'pot': 3, 'shortname': 'Youn'}],
'SCO': [{'id': 3757, 'country': 'SCO', 'pot': 4, 'shortname': 'Celt'}],
'ESP': [{'id': 3762, 'country': 'ESP', 'pot': 1, 'shortname': 'Sevi'},
{'id': 3894, 'country': 'ESP', 'pot': 1, 'shortname': 'Barc'},
{'id': 3933, 'country': 'ESP', 'pot': 1, 'shortname': 'Real'},
{'id': 3898, 'country': 'ESP', 'pot': 2, 'shortname': 'Atle'},
{'id': 3699, 'country': 'ESP', 'pot': 4, 'shortname': 'Soci'}],
'AUT': [{'id': 3938, 'country': 'AUT', 'pot': 2, 'shortname': 'Salz'}]}
countries = ['NED',
'UKR',
'ENG',
'POR',
'GER',
'DEN',
'FRA',
'AZE',
'TUR',
'ITA',
'BEL',
'SRB',
'SUI',
'SCO',
'ESP',
'AUT']
fixed_games = [(3940, 3894), (3933, 3940), (3940, 3937), (3765, 3940), (3940, 3895), (3700, 3940), (3940, 3696),
(3925, 3940), (3702, 3935), (3894, 3702), (3702, 3926), (3937, 3702), (3702, 3700), (3758, 3702),
(3702, 3699), (3757, 3702), (3932, 3762), (3732, 3932), (3932, 3938), (3761, 3932), (3932, 3730),
(3701, 3932), (3932, 3870), (3853, 3932), (3764, 3933), (3935, 3764), (3764, 3936), (3898, 3764),
(3764, 3756), (3928, 3764), (3764, 3925), (3904, 3764), (3762, 3732), (3762, 3761), (3930, 3762),
(3762, 3701), (3760, 3762), (3762, 3697), (3698, 3762), (3732, 3765), (3926, 3732), (3732, 3928),
(3730, 3732), (3732, 3698), (3870, 3732), (3894, 3930), (3938, 3894), (3894, 3758)]
"""
##########################################################################################################################
##########################################################################################################################
"""
model = pulp.LpProblem(f"Draws", pulp.LpMinimize)
x = {}
for t1 in teams:
for t2 in teams:
if t1['country'] != t2['country']:
x[t1['id'], t2['id']] = pulp.LpVariable('x_'+str(t1['id'])+'_'+str(t2['id']),lowBound=0, upBound=1, cat=pulp.LpInteger)
# REQUIREMENTS
for t in teams:
for r in range(1,5):
model += lpSum(x[t['id'],t2['id']] for t2 in pot[r] if (t['id'],t2['id']) in x.keys()) == 1
model += lpSum(x[t2['id'],t['id']] for t2 in pot[r] if (t2['id'],t['id']) in x.keys()) == 1
for c in countries:
if c != t['country']:
model += lpSum(x[t['id'],t2['id']]+x[t2['id'],t['id']] for t2 in teams_from_country[c]) <= 2
for (t1,t2) in x.keys():
model += x[t1,t2] + x[t2,t1] <= 1
# FIXATIONS
for (t1,t2) in fixed_games:
model += x[t1,t2] == 1
model.solve(XPRESS(msg=1))
if model.status in [-1,-2]:
print("INFEASIBLE")
else:
print("SUCCESS")
"""
##########################################################################################################################
##########################################################################################################################
"""
# if feasible:
# # GET GAMES
# games = []
# for key in sol.keys():
# if sol[key].value() != 0:
# games.append(key)
# # CHECK AGAIN
# check_feasible(games)
# # WRITE SOL '.html'
# teams = sorted(teams, key=lambda k: k['pot'])
# sol = '<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">'
# sol += " \
# <style> \
# table, th, td { \
# border: 1px solid black; \
# border-collapse: collapse; \
# text-align: center; \
# min-width:40px; \
# padding:3px; \
# margin: 3px; \
# font-family : Arial;\
# } \
# h1 {\
# font-family : Arial;\
# }\
# \
# #etable td:nth-child(10),#etable th:nth-child(10) { border-right: 5px solid black; }\
# #etable td:nth-child(19),#etable th:nth-child(19) { border-right: 5px solid black; }\
# #etable td:nth-child(28),#etable th:nth-child(28) { border-right: 5px solid black; }\
# tr:nth-child(9) { border-bottom: 5px solid black; }\
# tr:nth-child(18) { border-bottom: 5px solid black; }\
# tr:nth-child(27) { border-bottom: 5px solid black; }\
# </style> \
# "
# sol += "<table id='etable' style='border:5px solid black'>\n"
# sol += "<thead>\n"
# sol += "<tr>"
# sol += "<th></th>"
# sol += "<th colspan=9 style='border-right: 5px solid black;'>Pot A</th>"
# sol += "<th colspan=9 style='border-right: 5px solid black;'>Pot B</th>"
# sol += "<th colspan=9 style='border-right: 5px solid black;'>Pot C</th>"
# sol += "<th colspan=9>Pot D</th>"
# sol += "</tr>"
# sol += "<tr>\n"
# sol += f"<th></th>\n"
# for t in teams:
# sol += f"<th>{getTeamById[t['id']]}</th>\n"
# sol += "</tr>\n"
# sol += "</thead>\n"
# sol += "<tbody>\n"
# for t1 in teams:
# sol += "<tr>\n"
# sol += f"<td>{getTeamById[t1['id']]}</td>"
# for t2 in teams:
# if (t1['id'],t2['id']) in games:
# sol += f"<td>{t2['country']}</td>"
# elif (t2['id'],t1['id']) in games:
# sol += f"<td>@{t2['country']}</td>"
# else:
# sol += f"<td></td>"
# sol += "</tr>\n"
# sol += "</tbody>\n"
# sol += "</table>\n"
# with open(f'debug_draws.html', 'w') as f:
# f.write(sol)