我正试图解决AMPL中的一个小问题,但我遇到了一个困难,我无法将其转化为约束。问题是:假设我有3套的, B ,和 C 。我想将A中的元素链接到B中的元素,这样,如果A中的元素存在于C的一个子集中,则不超过2个来自A的元素链接到B中的单个元素(C的任何子集中的3个元素中最多有2个链接到B中的1个元素)。我已经做了这部分
假设我写了这个约束:
subject to constr {(i,j,k) in C, b in B}: x[i,b] + x[j,b] + x[k,b] <= 2;
我希望代码的目标是最大化{(i,j,k) in C, b in B}: x[i,b] + x[j,b] + x[k,b] <= 1;
或者换句话说,尽量减少以下情况:
{(i,j,k) in C, b in B}: x[i,b] + x[j,b] + x[k,b] = 2;
。
我该如何写这个目标?如果我想有次数(约束是= 2) <=一个常数(例如MAX),我怎么能做到这一点?下面是我到目前为止写的代码。我用的是学生版的AMPL和学生版的complex。非常感谢您的帮助。
set A;
set B;
set C within A cross A cross A;
param constant:= 5;
var x{A,B} binary;
subject to constr1 {(i,j,k) in C, b in B}: x[i,b] + x[j,b] + x[k,b] <= 2;
subject to onlyOneLinkForEachElementInA {a in A}: sum{b in B} x[a,b] = 1;
data;
set A:= 0 a b c d e f; #note that 0 is used only to pad the subsets and force them to have dimension of 3
set B:= 1 2 3;
set C: 0 a b c d e f:=
(a,b,c) (a,c,0) (c,d,0) (e,f,b) (a,b,0) (f,b,0);
solve;
for {i in A :i!=0} { printf "%st",i;for{c in B} {if x[i,c]=1 then printf "%sn",c;}};
我试过这个,但它没有工作(也没有工作的数字):
subject to constr2 {b in B}: count {(i,j,k) in C} ( (x[i,b] + x[j,b] + x[k,b]) = 2 ) <= MAX;
,其中MAX声明为:
param MAX:= 5;
您只能优化线性和(某些)二次表达式。因为你想尽量减少次数x[i,b] + x[j,b] + x[k,b] == 2
,你需要一个额外的指示变量。
var has_2{C} binary;
minimize has_2 sum((i,j,k) in C) not_2[i,j,k]
subject to constr1 {(i,j,k) in C, b in B}: x[i,b] + x[j,b] + x[k,b] - has_2[i,j,k] <= 1
如果两个x变量为1,constr1强制has_2为1。如果x变量中的0或1为1,则目标将迫使has_2为0。如果您的x
变量已经是二进制的,那么您最好将has_2设置为连续的,上限为1,特别是考虑到has_2变量比x
变量更多。