我正在进行优化项目,我遇到了一个小问题。对于我的项目,我使用AMPL和CPLEX作为解算器。在我的代码中,我有一些由e1,e2,...,en表示的元素。我还有一个包含这些元素中的元组的集合。我必须在1到' n'之间分配一个数字。每个元素使我最大化moveTuples集中1个元组中每2个元素之间的距离(我需要对它们进行排序,但尝试在同一元组中保持元素之间的距离)。
每个元素必须只有1个指定的编号,每个编号只能给1个元素。为此,我编写了以下代码:
set Elements;
set moveTuples dimen 2;
set Numbers;
var assign {Elements,Numbers} binary;
var maximizer{moveTuples} integer >= 0;
maximize obj: sum {(A,B) in moveTuples} maximizer[A,B];
subject to assign1NumberPerElement {i in Element}: sum {c in Numbers} assign[i,c] = 1;
subject to assign1ElementPerNumber {c in Numbers}: sum {i in Element} assign[i,c] = 1;
subject to moveApart {(A,B) in moveTuples}: abs(sum{i in Numbers}(assign[A,i]*i) - (sum{j in Numbers}x[B,j]*j)) - maximizer[A,B] = 0 ;
data;
set Elements:= e1 e2 e3;
set Numbers:= 1 2 3;
set moveTuples: e1 e2 e3:=
(e1, e2);
solve;
display assign;
现在问题很明显,对于前面的例子,输出必须是:
e1 - > 1
e2 - > 3
e3 - > 2
或
e1 - > 3
e2 - > 1
e3 - > 2
因为只需要使用元组(e1,e2)从e2移动e1。运行前面的代码时,我得到错误:...包含非二次非线性约束(绝对是" moveApart"约束)。你能指导我如何解决这个问题吗?提前谢谢。
答案 0 :(得分:0)
约束moveApart
是非线性的(非二次),因为它包含对abs
的调用。但是,由于您的问题纯粹是整数,因此可以使用CPLEX CP Optimizer (ilogcp)解决问题。