0

I am trying to model a tennis scheduling problem, as I explain in this post. I was lucky to get an answer with the equations describing the problem which allowed me to implement it in Choco, and it looks like it's working good enough.

So what I am about to explain is about the product of the implementation of the previous post's answer.

Basically I will end up having 2 three-dimensional matrices and 1 two-dimensional one, described as follows:

// Matches schedule
// i -> players, j-> courts, k -> timeslots
// x[i][j][k] holds a value 0..1 where 0 means the player doesn't play in court_j in the timeslot_k, and 1 the opposite
IntVar[][][] x;

// Beginning of all matches
// i -> players, j-> courts, k -> timeslots
// g[i][j][k] holds a value 0..1 where 0 means the player doesn't play in court_j in the timeslot_k, and 1 the opposite
// Basically the same matrix as the previous one but it only holds the first timeslot of a match
IntVar[][][] g;

// Occupied courts
// i-> courts, j-> timeslots
// crt[i][j] holds a value 0..1 where 0 means the court_i is occupied in the timeslot_j, and 1 means the opposite
IntVar[][] crt;

With this approach the constraint that maps the schedule matrix to the game-starts matrix looks like this:

for (int p = 0; p < nPlayers; p++) {
    for (int c = 0; c < nCourts; c++) {
        for (int t = 0; t < nTimeslots - nTimeslotsPerMatch; t++) {
            if (nTimeslotsPerMatch == 1)
                solver.post(IntConstraintFactory.arithm(g[p][c][t], "=", x[p][c][t]));
            else
                solver.post(IntConstraintFactory.times(x[p][c][t], x[p][c][t + 1], g[p][c][t]));
        }               

        if (nTimeslotsPerMatch == 1)
            solver.post(IntConstraintFactory.arithm(g[p][c][nTimeslots - 1], "=", x[p][c][nTimeslots - 1]));
        else
            for (int i = 0; i < nTimeslotsPerMatch - 1; i++)
                solver.post(IntConstraintFactory.arithm(g[p][c][nTimeslots - i - 1], "=", 0));
    }
}

This uses the times constraint trick to map x[p][c][t] and x[p][c][t + 1] into g[p][c][t].

However, that definition considers each match has a fixed duration of 2 timeslots. I want to change it so that duration is variable.

But if I want to have a variable match duration I would have to map more than two values in x to define the value in g. For example, if the match duration is 3 slots, to map g[p][c][t] I need to do x[p][c][t] * x[p][c][t + 1] * x[p][c][t + 2] but I can't do that with times or in a similar fashion it's being done right now.

So my questions is, as there is a constraint in Choco called sum where you can ensure the summation of a set of values is equal to a value, is there one to define the product of this set of values? If not, how can I do this?

Basically what I achieve to do is:

g[i][j][k] = x[i][j][k] + x[i][j][k + 1] * x[i][j][k + 2] * x[i][j][k + 3] * ... * x[i][j][nTimeslotsPerMatch - 1]
Community
  • 1
  • 1
dabadaba
  • 9,064
  • 21
  • 85
  • 155

1 Answers1

1

From your code comments, x is a set of binary variables (value is either 0 or 1), so you should declare it using BoolVar (which extends IntVar).

Multiplying binary variables gives 1 if all binaries are set to 1 or 0 otherwise. In other terms, you can use "LogicalConstraintFactory.and" or "IntConstraintFactory.minimum" constraints to get that multiplication. Look at IntConstraintFactory, you also have implication constraints that may be usefull.

Does it help?

Jean-Guillaume, https://www.cosling.com/

  • Can you tell me in a small sample code how to do what I am trying with using `and` and `minimum`? I just don't see how. Besides, the problem with BoolVars is that in another part of the problem I need these matrices to be IntVars because I need to calculate the number of courts in which each player plays and add a constraint to match that to the required number of matches each player must play. So how can I do both things? Anyway, I'd still like to know how to do a product. – dabadaba Mar 04 '16 at 21:02
  • To get a BoolVar bx equal to b1*b2*b3 : solver.post(minimum(bx,new BoolVar[]{b1,b2,b3})); – Jean-Guillaume Fages Mar 06 '16 at 15:12
  • if the domain is 0/1, it will be BoolVar objects whether you store them into an BoolVar matrix or an IntVar matrix, so I recommend the type of the matrix to be BoolVar[][]. As any BoolVar is an IntVar, you should not have problems. If so, please precise which instruction does not work. – Jean-Guillaume Fages Mar 06 '16 at 15:37
  • Yes I totally understand it now. The way I see it multiplying boolean vars is the same than applying the AND opperation on them, so the same than using the `minimum` constraint. Now I need to apply an OR opperation over a set of vars, I guess using `maximum` would work in a similar fashion? Can you explain how using `LogicalConstraintFactory.and` and `or` would help my problem? As far as I can see the force to ensure that the constraint is applied over a set of variables, but I can't bond the "result" on a var the same way it's done with constraints like `sum`, `times`, `minimum` or `maximum`. – dabadaba Mar 06 '16 at 16:28
  • Even though this totally helped my particular problem that doesn't answer the main question: how do I define a product in Choco? Imagine I have a set of `IntVars` and I want to define a constraint over them that ensures that `x1 * x2 * x3 * ... * xn OP y`. Basically to achieve the same that `IntConstraintFactory.sum` does except that it should be a product instead of a sum. – dabadaba Mar 06 '16 at 16:31
  • About AND (and OR): BoolVar result = LCF.and(b1,b2,...,bn).reif() will do the job. Reification consists of associating a constraint with a BoolVar that states whether the constraint is satisfied or not,i.e. result=1 <=> and(b1,b2,...bn) – Jean-Guillaume Fages Mar 06 '16 at 18:20
  • About the n-ary product over IntVar, there is currently no implementation for that but you can use a chain of "times" constraints by introducing intermediary variables: z = x1 * x2 * x3 can be reformulated as: z = x1*x23 and x23 = x2*x3 etc. It is a bit boring but you can implement this reformulation into a static method once and for all. We may eventually add it to the library. – Jean-Guillaume Fages Mar 06 '16 at 18:26