--A sporting tournament will be held in ** 8 countries **. Suppose you play 4 games for 7 days. ――It is assumed that you know the popularity ranking of the previous reputation. ――As much as possible, try to make the match of the popular pair in the second half, and create a schedule that will make you feel uncomfortable until the end.
Let's solve this problem with Combinatorial Optimization.
Let the variables be 0-1 variables that represent "choose and choose" the combination for country 1, country 2, and day.
Also, the "weight of the match on a day (k) with two countries (i, j)" corresponding to the variable is as follows. By maximizing the sum of these weights, "matches between countries with lower rankings" will be prioritized.
Maximize td> | $ \ sum_i {weight _i x_i} $ td> | sum of weights td> tr> |
Variables td> | $ x_i \ in \ {0, 1 \} ~ ~ \ forall i \ in Candidate $ td> | Whether to select that candidate td> td> tr> |
Constraints td> | $ \ sum_ {i \ in j, k pairs ~~~~~} {x_i} = 1 ~ ~ \ forall j, k \ in \ mbox {country} $ td> | One same pair td> tr> |
$ \ sum_ {i \ in day k including country j ~~~~~~~~~~~~~} {x_i} = 1 ~ ~ \ forall j \ in \ mbox {country }, \ forall k \ in \ mbox {day} $ td> | Same day, one td> tr> |
First, create a table of combinations.
python3
import pandas as pd
from itertools import combinations, product
from pulp import *
ss = 'Italy Netherlands Japan South Korea Thailand Dominican Republic Peru Kazakhstan'.split()
rnk = {s:(i+1) for i, s in enumerate(ss)} #Country name → ranking
a = pd.DataFrame([(i, j, k, 2**k/rnk[i]/rnk[j]) for i, j in combinations(ss, 2)
for k in range(7)], columns='Country 1 Country 2 days Weight'.split())
a[:3]
>>>
Country 1 Country 2 days Weight
0 Italy Netherlands 0 0.5
1 Italy Netherlands 1 1.0
2 Italy Netherlands 2 2.0
Let's formulate and solve it.
python3
m = LpProblem(sense=LpMaximize) #Mathematical model
a['Var'] = [LpVariable('v%d'%i, cat=LpBinary) for i in a.index] #variable
m += lpDot(a.weight, a.Var) #Objective function
for _, b in a.groupby(['Country 1', 'Country 2']):
m += lpSum(b.Var) == 1 #One in the same group
for s, i in product(ss, range(7)):
#The same country, one on the same day
m += lpSum(a.query('(Country 1=="{0}" |Country 2=="{0}") &Day=={1}'.format(s, i)).Var) == 1
m.solve() #Solution
a['Val'] = a.Var.apply(value) #result
#display
for i, b in a.groupby('Day'):
print(i+1, 'Day')
for _, r in b[b.Val > 0].iterrows():
print(' %*s - %s'%(8-len(r.Country 1), r.Country 1, r.Country 2))
>>>
First day
Italy-Kazakhstan
Netherlands-Peru
Japan-Dominican Republic
Korea-Thailand
the 2nd day
Italy-Peru
Netherlands-Kazakhstan
Japan-Thailand
Korea-Dominican Republic
Third day
Italy-Dominican Republic
Netherlands-Thailand
Japan-Kazakhstan
Korea-Peru
Day 4
Italy-Thailand
Netherlands-Dominican Republic
Japan-Peru
Korea-Kazakhstan
Day 5
Italy-Korea
Netherlands-Japan
Thailand-Kazakhstan
Dominican Republic-Peru
Day 6
Italy-Japan
Netherlands-Korea
Thailand-Peru
Dominican Republic-Kazakhstan
Day 7
Italy-Netherlands
Japan-Korea
Thailand-Dominican Republic
Peru-Kazakhstan
The schedule for each day was output.
As another method, there may be a combination with a difference in strength in the first half and a combination with a difference in strength in the second half.
Temporarily, I'm making my most recent Python-related post run on Arukas.
that's all