Reputation: 155
I'm trying to solve a small problem in AMPL but I faced a difficulty which I couldn't translate it into a constraint. The problem is: Assume that I have 3 sets A,B, and C. I want to link elements from A to elements in B such that no more than 2 elements from A are linked to a single element in B if they exist in 1 subset of C (maximum of 2 out of 3 elements in any subset of C are linked to 1 elements in B). I already did this part
Assume I wrote this constraint:
subject to constr {(i,j,k) in C, b in B}: x[i,b] + x[j,b] + x[k,b] <= 2;
I want the objective of the code to maximize the case where {(i,j,k) in C, b in B}: x[i,b] + x[j,b] + x[k,b] <= 1;
or in other words, to minimize the case where:
{(i,j,k) in C, b in B}: x[i,b] + x[j,b] + x[k,b] = 2;
.
How can I write this objective? And in case I wanted to have the number of times where ( constraint is = 2 ) <= to a constant (for example MAX), how can I do that as well? Below is the code I wrote so far. I'm using a student edition of AMPL and a student edition of cplex. Your help is appreciated and thanks in advance.
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 "%s\t",i;for{c in B} {if x[i,c]=1 then printf "%s\n",c;}};
I tried this but it didn't work (neither did the numberof worked):
subject to constr2 {b in B}: count {(i,j,k) in C} ( (x[i,b] + x[j,b] + x[k,b]) = 2 ) <= MAX;
where MAX is declared as:
param MAX:= 5;
Upvotes: 2
Views: 684
Reputation: 21597
You can only optimize linear and (some) quadratic expressions. Since you are trying to minimize the number of times
x[i,b] + x[j,b] + x[k,b] == 2
, you need an additional indicator variable.
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
constr1 forces has_2 to be 1 if two of the x variables are 1. If 0 or 1 of the x variables are 1, then the objective will force has_2 to 0. If your x
variables are already binary, then you might be better off making has_2 continuous with an upper bound of 1, especially considering that there are more has_2 variables than x
variables.
Upvotes: 2