我正在学习AMPL,以便稍后在我的课程中使用它。我有一个小问题,我想解决。正如标题所述,我试图使用一些迭代操作来最小化约束数量。所以问题如下: 假设我有2组 A 和 B 并假设我有代码:
set A:= (1, 2, 3) (4, 5, 6);
set B:= a b c;
var x{A,B} binary;
**some_objective** ;
subject to constraint { (i,j,k) in A, b in B }: x[i,b] + x[j,b] + x[k,b] <= 1;
现在,如果我们扩展先前的约束,将形成以下约束:
x[1,a] + x[2,a] + x[3,a] <=1;
x[1,b] + x[2,b] + x[3,b] <=1;
x[1,c] + x[2,c] + x[3,c] <=1;
x[4,a] + x[5,a] + x[6,a] <=1;
x[4,b] + x[5,b] + x[6,b] <=1;
x[4,c] + x[5,c] + x[6,c] <=1;
这意味着,对于 A 中的 y 子元素和 B 中的 z 元素,我们将获得总计 y * z 约束(在我们的例子中是2 x 3 = 6个约束)。
现在,如果我们将约束更改为:
subject to constraint { (i,j,k) in A }: prod { b in B } (x[i,b] + x[j,b] + x[k,b]) <= 1;
将导致:
{(x[1,a] + x[2,a] + x[3,a]) * (x[1,b] + x[2,b] + x[3,b]) * (x[1,c] + x[2,c] + x[3,c])} <= 1;
{(x[4,a] + x[5,a] + x[6,a]) * (x[4,b] + x[5,b] + x[6,b]) * (x[4,c] + x[5,c] + x[6,c])} <= 1;
它应该与之前的形式具有相同的结果,但我们减少了从 y * z 到 y 的约束数量,这是一个很好的改进!! 另一个改进是逻辑和约束:
subject to constraint { (i,j,k) in A }: forall { b in B } ( (x[i,b] + x[j,b] + x[k,b]) <= 1 );
将导致:
{(x[1,a] + x[2,a] + x[3,a]) <= 1} && {(x[1,b] + x[2,b] + x[3,b]) <= 1} && {(x[1,c] + x[2,c] + x[3,c]) <= 1};
{(x[4,a] + x[5,a] + x[6,a]) <= 1} && {(x[4,b] + x[5,b] + x[6,b]) <= 1} && {(x[4,c] + x[5,c] + x[6,c]) <= 1};
问题是,当我们这样做时,我们正在将问题从线性或二次方程式转换为非二次方程式, cplex 不再能够解决它:/
是否有任何工作或任何技巧可以让我在不将问题转换为非二次问题的情况下执行此操作(至少使用 cplex 解决)?
也可以说x[1,a] + x[1,b] + x[1,c] = 1
对于 A 中的任何其他元素都是如此。感谢您的帮助,并提前致谢。
答案 0 :(得分:1)
首先,我想指出使用产品的约束不等于原始约束。例如,其余x[1,a] = 1, x[2,a] = 1, x[3,a] = 1
等于零的解x
满足prod
制定的约束,因为(x[1,a] + x[2,a] + x[3,a]) * (x[1,b] + x[2,b] + x[3,b]) * (x[1,c] + x[2,c] + x[3,c]) = 3 * 0 * 0 = 0 <= 1
,但不满足原始约束{ {1}}。
您可以将逻辑x[1,a] + x[2,a] + x[3,a] = 3 <= 1
或&&
与IBM/ILOG CPLEX CP Optimizer(ilogcp)一起使用,这对所有AMPL / CPLEX用户都可用,但我怀疑这对于单独的约束会更好。您可以在“Logic” and Constraint Programming Extensions页面上找到有关forall
的更多信息,其中还包含有关如何获取它的信息(如果您拥有CPLEX许可证,您也应该能够获得ilogcp)。此解算器将接受以下形式的约束:
ilogcp