Download
"""
PyCSP3 Model (see pycsp.org)
Examples:
python SportsScheduling.py
python SportsScheduling.py -data=10
python SportsScheduling.py -data=10 -variant=dummy
"""
from pycsp3 import *
nTeams = data or 8
nWeeks, nPeriods, nMatches = nTeams - 1, nTeams // 2, (nTeams - 1) * nTeams // 2
def match_number(t1, t2):
return nMatches - ((nTeams - t1) * (nTeams - t1 - 1)) // 2 + (t2 - t1 - 1)
table = {(t1, t2, match_number(t1, t2)) for t1, t2 in combinations(range(nTeams), 2)}
# m[w][p] is the number of the match at week w and period p
m = VarArray(size=[nWeeks, nPeriods], dom=range(nMatches))
# x[w][p] is the first team for the match at week w and period p
x = VarArray(size=[nWeeks, nPeriods], dom=range(nTeams))
# y[w][p] is the second team for the match at week w and period p
y = VarArray(size=[nWeeks, nPeriods], dom=range(nTeams))
satisfy(
# all matches are different (no team can play twice against another team)
AllDifferent(m),
# linking variables through ternary table constraints
[(x[w][p], y[w][p], m[w][p]) in table for w in range(nWeeks) for p in range(nPeriods)],
# each week, all teams are different (each team plays each week)
[AllDifferent(x[w] + y[w]) for w in range(nWeeks)],
# each team plays at most two times in each period
[Cardinality(x[:, p] + y[:, p], occurrences={t: range(1, 3) for t in range(nTeams)}) for p in range(nPeriods)],
# tag(symmetry-breaking)
[
# the match '0 versus t' (with t strictly greater than 0) appears at week t-1
[Count(m[w], value=match_number(0, w + 1)) == 1 for w in range(nWeeks)],
# the first week is set : 0 vs 1, 2 vs 3, 4 vs 5, etc.
[m[0][p] == match_number(2 * p, 2 * p + 1) for p in range(nPeriods)]
]
)
if variant("dummy"):
# xd[p] is the first team for the dummy match of period p tag(dummy-week)
xd = VarArray(size=nPeriods, dom=range(nTeams))
# yd[p] is the second team for the dummy match of period p tag(dummy-week)
yd = VarArray(size=nPeriods, dom=range(nTeams))
satisfy(
# handling dummy week (variables and constraints) tag(dummy-week)
[
# all teams are different in the dummy week
AllDifferent(xd + yd),
# each team plays two times in each period
[Cardinality(x[:, p] + y[:, p] + [xd[p], yd[p]], occurrences={t: 2 for t in range(nTeams)}) for p in range(nPeriods)],
# tag(symmetry-breaking)
[xd[p] < yd[p] for p in range(nPeriods)]
]
)