我正在学习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中的任何其他元素都是正确的。感谢您的帮助,并在此先感谢您。
首先,我想指出的是,使用乘积的约束不等于原始约束。例如,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
,但不满足原始约束x[1,a] + x[2,a] + x[3,a] = 3 <= 1
。
您可以使用逻辑&&
或forall
与IBM / ILOG CPLEX CP优化器(ilogcp),它适用于所有幅度/ CPLEX用户,但我怀疑这会好于具有独立的限制。您可以ilogcp
在“逻辑”和“约束编程扩展”页面上找到更多信息,该页面还包括有关如何获取它的信息(如果您拥有CPLEX许可证,那么您也应该可以获得ilogcp)。该求解器将接受以下形式的约束:
subject to c{(i,j,k) in A}: forall {b in B} (x[i,b] + x[j,b] + x[k,b] <= 1);
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句