我目前正在尝试解决运动队的日程安排问题。我的决策变量声明为:
dvar int plays[Games][0..1] in Teams;
Games
的范围是0..19
和Teams
的范围,在此特定情况下是0..9
的范围。这形成了一个20乘2的矩阵,表示哪些球队正在参加每场比赛。
[
[3, 7],
[2, 4],
[9, 1]
]
是一个3游戏矩阵的示例,显示第3组在第一场比赛中扮演第7队,然后是第2队与第4队,第9队与第1队结束。
在我的约束中,我试图表达每支球队应该接近相同数量的比赛。我表达这种约束的尝试如下:
subject to {
gameBalance:
standardDeviation(all(t in Teams) count(all(g in Games, s in 0..1) plays[g][s], t)) < 1;
}
我相信这个表述是合理的 - 但是,我觉得我遇到了某种未定义的行为,因为即使CPLEX说它返回了一个&#34;最佳&#34,但约束并不令人满意。 ; {9}团队案件[18, 18, 0, 0, 0, 0, 0, 0, 0]
的解决方案。
手动计算,我得到7.59
的标准偏差,显然不小于1。为了验证这一点,我将以下内容放在模型的结果数据部分中:
int playcounts[Teams] = all(t in Teams) count(all(g in Games, s in 0..1) plays[g][s], t);
float std = standardDeviation(all(t in Teams) count(all(g in Games, s in 0..1) plays[g][s], t));
execute {
writeln("counts: " + playcounts);
writeln("std: " + std);
}
其中给出了以下输出:
// solution with objective 0
counts: [18 18 0 0 0 0 0 0 0]
std: 7.48331477
这进一步证实了我写的约束不正确。为了进一步调试这种情况,我使用了以下约束:
standardDeviation(foo) < 1;
其中foo
被声明为[1, 100, 10000, 1000000, 100000000]
的整数数组 - 它肯定没有小于1的标准偏差。正如所料,这个模型被证明是不可行的,这表明标准偏差按预期工作,因此问题必须是我构建计数数组的方式。然后我尝试了以下约束:
standardDeviation(all(t in Teams) count(all(g in Games, s in 0..1) plays[g][s], t)) + 2.999999999 < 3;
我的理论是,如果标准偏差被处理为非零,那么这应该使模型不可行。令我惊讶的是,该模型通过了上面相同的琐碎[18, 18, 0, ...]
解决方案。通过将2.999...
更改为3,该模型是不可行的。因此,我得出结论,我计算的标准偏差在约束中评估为0,但在搜索结束后,它在结果数据部分中正确计算。
此时我确信问题源于我计算计数数组的方式(all(t in Teams) count(all(g in Games, s in 0..1) plays[g][s], t)
),但我不理解的部分是为什么它在结果数据中起作用而在约束中不起作用(如上面playcounts
打印出来的那样)。
此外,以下约束完全正常:
// The total number of games played must be exactly 36
sum(t in Teams) count(all(g in Games, s in 0..1) plays[g][s], t) == 36;
这让我相信问题在于约束的all(t in Teams)...
部分。为了测试这个理论,我使用了以下约束:
// The number of games the first team plays must be exactly 18
(all(t in Teams) count(all(g in Games, s in 0..1) plays[g][s], t))[0] == 18;
理论上,这应该是一个冗余约束,因为返回的普通解决方案以[18, 18, 0, ...]
开头。令我惊讶的是,这创造了一个不可行的模型。即使使用== 0
代替== 18
,该模型仍然不可行。因此,我想弄清楚这个数字正在评估什么。为此,我添加了以下决策变量:
dvar int a;
并将目标函数更改为:
maximize a;
使用以下约束:
(all(t in Teams) count(all(g in Games, s in 0..1) plays[g][s], t))[0] == a;
这导致了一个具有最佳解决方案的模型。该解决方案已将a
设置为-9007199254740991
。如果我尝试minimize
这个模型,会发生同样的结果。
如果我尝试将a
限制为非负数,则CPLEX会因### UNEXPECTED ERROR
而崩溃。