对计数标准差的约束始终为零

时间:2016-08-08 22:14:47

标签: cplex constraint-programming ilog opl

我目前正在尝试解决运动队的日程安排问题。我的决策变量声明为:

dvar int plays[Games][0..1] in Teams;

Games的范围是0..19Teams的范围,在此特定情况下是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而崩溃。

最终,我的问题是:

  1. 我是否违反了某些OPL规则并以某种方式使用陈述?
  2. 如果上述情况属实,是否有合法,有效的方式来表达我正在寻找的约束?
  3. 如果不是,那么为什么OPL无法计算约束中的标准偏差?

0 个答案:

没有答案