Download
language ESSENCE' 1.0
given nbTeams : int(1..)
letting nbRounds = nbTeams-1
letting nbStates = 7
letting Teams be domain int(1..nbTeams)
letting Rounds be domain int(1..nbRounds)
letting Travels be domain int(1..nbRounds+1)
letting maxObj be sum([nbTeams/2 | i : Teams, j : Travels])
$ predefined venue: pv[i][j] = 1 iff i is playing at home against j
given pv : matrix indexed by [Teams, Teams] of int(1..2)
find opponent : matrix indexed by [Teams, Rounds] of Teams
$ auxiliary variables: venue[i,k] = 1 iff team i plays at home in round k
find venue : matrix indexed by [Teams, Rounds] of int(1..2)
find travel : matrix indexed by [Teams, Travels] of int(0..(nbTeams/2))
find distance : matrix indexed by [Teams, Teams] of int(0..nbTeams)
find objective : int(0..maxObj)
branching on [[opponent[i,j] | i : Teams, j : Rounds],
[venue[i,j] | i : Teams, j : Rounds],
[travel[i,j] | i : Teams, j : Travels]]
minimising objective
such that
objective = sum(flatten(travel)),
forAll i : Teams .
forAll j : Teams .
(i >= j -> (
(i-j < j-i+nbTeams -> distance[i,j] = i-j)
/\
(i-j >= j-i+nbTeams -> distance[i,j] = j-i+nbTeams)
))
/\
(i < j -> (
(j-i < i-j+nbTeams -> distance[i,j] = j-i)
/\
(j-i >= i-j+nbTeams -> distance[i,j] = i-j+nbTeams)
)),
$ predetermined venues match venue allocation
forAll i : Teams .
forAll k : Rounds .
venue[i,k] = pv[i,opponent[i,k]],
$ cannot play against oneself
forAll i : Teams .
forAll k : Rounds .
opponent[i,k] != i,
$ if I play you, you play me
forAll i : Teams .
forAll k : Rounds .
opponent[opponent[i,k],k] = i,
$ each team i, all the opponents are different
forAll i : Teams .
allDiff(opponent[i, ..]),
$ each round, all opponents are different (implied)
forAll k : Rounds.
allDiff(opponent[..,k]),
$ for each team i, there can be at most 3 consecutive home games and at most 3 consecutive away games
forAll i : Teams .
forAll j : int(1..2) .
forAll k : int(1..nbRounds-3) .
(venue[i,k] = j /\ venue[i,k+1] = j /\ venue[i,k+2] = j) -> venue[i,k+3] != j,
$ break symmetry
opponent[1,1] < opponent[1,nbRounds],
$ define travel variables wrt venues of current- and next-round games
forAll i : Teams .
(venue[i,1]=1 -> travel[i,1] = 0) /\
(venue[i,1]=2 -> travel[i,1] = distance[i,opponent[i,1]]),
forAll i : Teams .
forAll k : int(1..nbRounds-1) .
((venue[i,k]=1 /\ venue[i,k+1]=1) -> travel[i,k+1] = 0) /\
((venue[i,k]=2 /\ venue[i,k+1]=1) -> travel[i,k+1] = distance[opponent[i,k],i]) /\
((venue[i,k]=1 /\ venue[i,k+1]=2) -> travel[i,k+1] = distance[i,opponent[i,k+1]]) /\
((venue[i,k]=2 /\ venue[i,k+1]=2) -> travel[i,k+1] = distance[opponent[i,k],opponent[i,k+1]]),
forAll i : Teams .
(venue[i,nbRounds]=1 -> travel[i,nbRounds+1] = 0) /\
(venue[i,nbRounds]=2 -> travel[i,nbRounds+1] = distance[opponent[i,nbRounds],i])