0

正如我在这篇文章中解释的那样,我正在尝试对网球调度问题进行建模。我很幸运地得到了描述问题的方程式的答案,这使我能够在 Choco 中实现它,而且看起来它工作得很好。

所以我要解释的是关于上一篇回答的实现的产物。

基本上我最终会得到 2 个三维矩阵和 1 个二维矩阵,如下所述:

// 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;

使用这种方法,将调度矩阵映射到游戏开始矩阵的约束如下所示:

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));
    }
}

这使用times约束技巧来映射x[p][c][t]x[p][c][t + 1]进入g[p][c][t].

但是,该定义认为每个匹配具有 2 个时隙的固定持续时间。我想改变它,使持续时间是可变的。

但是,如果我想要一个可变的匹配持续时间,我将不得不映射两个以上x的值来定义g. 例如,如果比赛持续时间是 3 个插槽,map g[p][c][t]我需要这样做,x[p][c][t] * x[p][c][t + 1] * x[p][c][t + 2]但我不能这样做,times或者以类似的方式,它现在正在完成。

所以我的问题是,由于 Choco 中有一个约束称为sum,您可以确保一组值的总和等于一个值,是否有一个定义这组值的乘积?如果没有,我该怎么做?

基本上我要做的是:

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]
4

1 回答 1

1

从您的代码注释来看,x 是一组二进制变量(值是 0 或 1),因此您应该使用 BoolVar(扩展 IntVar)声明它。

如果所有二进制文件都设置为 1,则乘以二进制变量会得到 1,否则会得到 0。换句话说,您可以使用“LogicalConstraintFactory.and”或“IntConstraintFactory.minimum”约束来获得该乘法。看看 IntConstraintFactory,你也有可能有用的隐含约束。

它有帮助吗?

让-纪尧姆, https://www.cosling.com/

于 2016-03-04T19:20:39.367 回答