1

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

4

1 回答 1

0

约束moveApart是非线性的(非二次的),因为它包含对 的调用abs。但是,由于您的问题是纯整数,您可以使用CPLEX CP Optimizer (ilogcp)来解决它。

于 2015-04-11T01:08:59.273 回答