-->

Modeling tennis matchups with Choco (CSP)

2019-09-12 17:13发布

问题:

I am trying to model a problem with Choco to get the combinations of possible matchups in a tennis event (or any sport).

The way I am trying to do it I have the following:

// Set of timeslots when the event is held (i.e. 10am-10pm)
int nTimeslots = 12;

// Courts available: court #1, #2 and #3
int nCourts = 3;

String[] players = { "Novak", "Andy", "Roger", "Stan", "Rafel", "Kei", "Tomas", "David" };
int nPlayers = players.length;

// Timeslots when each player cannot play for whatever reason
int[][] unavailability = {
    { 0, 1, 5 },
    { 8, 10, 11 },
    { 1, 2, 11 },
    { 0, 1 },
    { 2, 3, 4, 5, 6 },
    { 3, 4, 9, 10, 11 },
    { 4, 5 },
    { 2, 3 }
};

// Number of timeslots each match will occupy
int matchDuration = 2;

// This will hold the final combinations
// rows -> players, columns -> timeslots, matches[i][j] -> court where the player plays at that timeslot (0 means the player does not play at that time)
IntVar[][] matches;

My main problem is that with this setup I cannot think of a way of defining my problem. I have been spending days on this to no success. I have seem slighly similar problems but the amount of different elements that ought to be combined are less, normally 1 or 2, but in my problem there are 3: players, timeslots and courts.

After expending a lot of time on this, I couldn't get further than this:

for (int player = 0; player < nPlayers; player++) {
    for (int timeslot = 0; timeslot < nTimeslots; timeslot++) {
        for (int playerUnavailbleTimeslot : unavailability[player]) {
            if (playerUnavailbleTimeslot != timeslot) {
                solver.post(IntConstraintFactory.arithm(matches[player][playerUnavailbleTimeslot], ">=", 0));
            } else {
                for (int i = 0; i < matchDuration; i++)
                    if (playerUnavailbleTimeslot - i >= 0)
                        solver.post(IntConstraintFactory.arithm(matches[player][playerUnavailbleTimeslot - i], "=", 0));
            }
        }
    }
}

IntVar matchesSum = VariableFactory.enumerated("Matches sum", 1 * matchDuration, nCourts * matchDuration, solver);
for (int player = 0; player < nPlayers; player++) {
    solver.post(IntConstraintFactory.sum(matches[player], matchesSum));
    //solver.post(IntConstraintFactory.nvalues(matches[player], VariableFactory.fixed(2, solver)));
}

The first double loop just forces to 0 those timeslots where the player is unavailable (plus the range based on the value of the match duration), and greater or equal to if he is available. That way the final matrix starts looking like this:

0 0 ? ? ? 0 ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? 0 0 0 0 ?
.........................

Then I just ensure than the sum of the values in each player's timeslots is between the court with the lowest number multiplied by the match duration and the court with the highest number multiplied by the match duration. This is one of the constraints I thought of so each row looks like this, for example, player 0 plays in court 2 at the timeslots 3 and 4:

0 0 0 2 2 0 0 0 0 0 0 0 

I tried defining the constraint nvalues that is supposed to enforced that no more than n different values conform the array, but if I use it like you can see above the problem just renders one solution (what?!).

However I need to define more constraints I don't even know how to start:

  • For each row the court where the player plays must have consecutive numbers if indeed that court is assigned
  • For each row I can only have 0s and the court number [1 - nCourts]
  • Columns should pair up to create the matches between a pair of players.
  • The same court cannot be paired up more than once for the same timeslot range (meaning not more than one match can take place in the court at the same time)

This is all I can think of in terms of constraints but I am sure there are more.

I would love any suggestion to help me continue doing this because right now I feel absolutely clueless and there is virtually zero information about Choco online to help me clear this up.

回答1:

I would start with writing down in math what you want.

Not sure if this is helpful, but here is my implementation, solving it as a mathematical programming problem. It is not using Constraint Programming but things can look similar to what you would do in Choco:

I try to maximize the minimum number of games of a player, so we don't have someone playing zero games. One could think of many variations, such as not playing against the same person all the time etc.

The results look like:

The numbers in the table are the court numbers (-1 means not allowed). In this schedule everyone plays three times.