如何在 Choco (CSP) 中定义产品
How to define a product in Choco (CSP)
我正在尝试对网球调度问题建模,正如我在此 中所解释的那样。我很幸运地得到了描述问题的方程式的答案,这让我可以在 Choco 中实现它,看起来它运行得很好。
所以我要说明的是前面post的回答的执行结果。
基本上我最终会得到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
的约束,您可以在其中确保一组值的总和等于一个值,是否可以定义 product这组值?如果没有,我该怎么做?
基本上我实现的是:
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]
根据您的代码注释,x 是一组二进制变量(值为 0 或 1),因此您应该使用 BoolVar(扩展 IntVar)声明它。
如果所有二进制变量都设置为 1,则乘以二进制变量得到 1,否则得到 0。换句话说,您可以使用 "LogicalConstraintFactory.and" 或 "IntConstraintFactory.minimum" 约束来获得该乘法。查看 IntConstraintFactory,您还具有可能有用的隐含约束。
有帮助吗?
让-纪尧姆,
https://www.cosling.com/
我正在尝试对网球调度问题建模,正如我在此
所以我要说明的是前面post的回答的执行结果。
基本上我最终会得到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
的约束,您可以在其中确保一组值的总和等于一个值,是否可以定义 product这组值?如果没有,我该怎么做?
基本上我实现的是:
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]
根据您的代码注释,x 是一组二进制变量(值为 0 或 1),因此您应该使用 BoolVar(扩展 IntVar)声明它。
如果所有二进制变量都设置为 1,则乘以二进制变量得到 1,否则得到 0。换句话说,您可以使用 "LogicalConstraintFactory.and" 或 "IntConstraintFactory.minimum" 约束来获得该乘法。查看 IntConstraintFactory,您还具有可能有用的隐含约束。
有帮助吗?
让-纪尧姆, https://www.cosling.com/