我正在做一个优化项目,我遇到了一个小问题。对于我的项目,我使用 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”约束)。你能指导我如何解决这个问题吗?提前致谢。