0-1 optimization with absolute value (equiv., with two inequalities) - matlab

The bintprog command from the Optimization Toolbox solves 0-1 programming problems with an inequality constraint and an optional equality constraint: Ax <= b where A is a matrix and b a column vector.
I have a problem of the form |Ax| <= b, or equivalently, -b <= Ax <= b. Is there a way to solve this sort of problem with Matlab?

With size(A) = [n,m], your constraints are of the form
for each {i in 1..m}
-b <= sum {j in 1..n} a_{ij} * x_{ij} <= b
this is the same as two sets of constraints
for each {i in 1..m}
sum {j in 1..n} a_{ij} * x_{ij} <= b
sum {j in 1..n} a_{ij} * x_{ij} >= -b
Since you have to write it in the form Ax <= b, it would look like
for each {i in 1..m}
sum {j in 1..n} a_{ij} * x_{ij} <= b
sum {j in 1..n} -a_{ij} * x_{ij} <= b
In MATLAB, given your original A and b, you can make these "doubled" constraint matrices with
A = [A; -A];
b = [b; b];
and solve your integer program with these new (A,b).

This is very easy:
You have |Ax| <= b. This is equivalent to (as you yourself noted) to -b <= Ax <= b.
So, you have additional inequality constraints: Ax <= b and -Ax <= b.
Thus you have over all AA = [ A ; -A ] and bb = [b;b] defining your abs-value constraints:
x = bintprog( f, AA, bb );

Related

Need to write a set of linear equations for following condition:

I have three variables : A, B, C.
I want to write a set of linear equations such that
X = 1 if atleast 2 of A,B,C are ones.
X= 0 if only one of A,B,C is one.
X = 0 if all of them are zero.
A,B and C are binary (0,1).
Kindly suggest a linear equation for this.
Thank you.
To implement
A+B+C ≥ 2 => X=1
A+B+C ≤ 1 => X=0
we can write simply:
2X ≤ A+B+C ≤ 2X+1
A,B,C,X ∈ {0,1}
In practice, you may have to formulate the sandwich equation as two inequalities.
X >= A + B - 1
X >= B + C - 1
X >= A + C - 1
X <= A + B
X <= B + C
X <= A + C
as mentioned in comment, you didn't define outcome for A=B=C=0, but in that case X -> 0 by inspection.

Matlab equivalent code of the following equation

I have an equation for which I am trying to write a code in Matlab, but I am not sure if my code is right. The equation is as follows:
Where I think the iteration is over the superscript i.e. k, k+1 etc and the dimensions are marked by subscripts m, n, n'. The notations are not well defined in the literature so I think this is how it should be.
My code segment for this equation is as follows:
c_n = [1,2,3,4]'; % c^(0)_n (nx1) vector
K = 50;
d = [0.5,0.9]';
for k = 1:1:K
c_n = c_n.*((sum(A_mn'*d/(sum(A_mn*c_n,2)),2))./sum(A_mn',2)) ;
end
Is this code correct for the above equation?. The summations in the equation are confusing me.
If A is a matrix with m rows and n columns, then the sum is just the sum of the nth row in AT. This is the same as the corresponding sum of the nth column in A: . The matrix multiplication it represents works out nicer with the transpose because matrix multiplications are just sums of weighted rows.
Similarly, is the mth row of A, weighted element-wise by by c.
We can assume that c and d are column vectors of size n and m, respectively. (d' will be represented by just plain d in the code). In that case, most of the operations can be reduced to matrix operations:
is just the matrix product A * c, which yields a column vector of size m.
then becomes the element-wise ratio d ./ (A * c), also of size m.
The ratio is used to scale the elements of the sum of AT in the numerator, making it the matrix product A.' * (d ./ (A * c)) of size n.
Each element of that is scaled by , which can be represented by either A.' * ones(m, 1) or sum(A, 1).', so the final matrix product is just c .* (A.' * (d ./ (A * c)) ./ sum(A, 1).').
You can pre-calculate sum(A, 1).', call it e to get the following:
c = [1; 2; 3; 4];
d = [0.5; 0.9];
A = ... some 2x4 matrix;
e = sum(A, 1).';
k = 50;
for i = 1 : k
c = c .* (A.' * (d ./ (A * c)) ./ e);
end
If you want to retain the intermediate values of c for each k, you can allocate a matrix of size n, k + 1 and fill that in with each column representing a new iteration of c:
c = zeros(4, 51);
c(:, 1) = [1; 2; 3; 4];
for i = 1 : k
c(:, k + 1) = c(:, k) .* (A.' * (d ./ (A * c(:, k))) ./ e);
end

How to define a negative constraint only in Aeq * X <= Beq

I am using quadprog link to find a portfolio of optimal weights.
So far, I have managed to implement a long only constraint (i.e. weights cannot be smaller than zero w >= 0 and w1 + w2 + ... wN = 1) as follows:
FirstDegree = zeros(NumAssets,1);
SecondDegree = Covariance;
Aeq = ones(1,NumAssets);
beq = 1;
A = -eye(NumAssets);
b = zeros(NumAssets,1);
x0 = 1/NumAssets*ones(NumAssets,1);
MinVol_Weights = quadprog(SecondDegree,FirstDegree,A,b,Aeq,beq,[],[],x0, options);
I am now tring to setup a short-only constraints, i.e. all the weights need to add up to -1 and they should be all strict smaller or equal to zero. How can this be rewritten?
Note that you can rewrite any “greater than” inequality a ≥ b into a “less than” inequality -a ≤ -b by flipping signs. In your example, choose
Aeq = ones(1,NumAssets);
beq = -1;
A = eye(NumAssets);
b = zeros(NumAssets,1);
That means Aeq*w == w(1) + w(2) + … + w(NumAssets) == -1, and A*w <= 0 which is the same as saying w(i) <= 0 for all i.

How to use index in MATLAB to find function constraints

I want to return the indices of elements which satisfy some conditions and the condition that their index should be between some constants A and B. There is a naive form of implementing this with:
inds=find(conditions)
real_inds=find(A<=inds<=B)
but it is inefficient and actually I want to limit my search to elements with index between those constants, not all elements.
how about restricting yourself to the range A, B?
Suppose you have my_vector and you wish to find the elements larger than 0.3 and smaller than 0.5 (the "conditions"). Limiting yourself to the range A, B is simply:
masked_ind = find(my_vector(A:B) > 0.3 & my_vector(A:B) < 0.5);
real_ids = masked_ind + A - 1; %// correct the offset induced by `A`.
By applying the conditions on my_vector(A:B) you actually don't care how big is my_vector and you are only processing elements in the range A:B.
BTW, have you considered using logical indexing, as suggested by Andras Deak, instead of using find and the actual linear indices?
%// create a mask to keep indices from A to B only
real_inds_logical = false(size(your_vector));
real_inds_logical(A:B) = (my_vector(A:B)>0.3 & my_vector(A:B)<0.5);
You can do something like this:
Suppose that you have vector x, conditions: x == 7 or ( x > 3 and x < 5) and you want the search between A and B.
Now define vector g as an auxiliar vector of indices:
g = 1:length(x);
And then get your indices like this:
indices = g( (g >= A) & (g <= B) & (conditions) );
That in this case is translated to:
indices = g( (g >= A) & (g <= B) & (x == 7 | (x > 3 & x < 5)) );
This will return the elements of g that satisfice the conditions between the extern parenthesis.
An example code:
Initial values:
x = [0.0975 0.2785 0.5469 0.9575 0.9649 0.1576 0.9706 0.9572 0.4854 0.8003];
A = 4;
B = 9;
Conditions: x >= 0.1 and x <= 0.7
Code:
g = 1:length(x);
indices = g((g >= A) & (g <= B) & (x <= 0.7) & (x >= 0.1));
Result:
indices =
6 9

replace elements of vector by condition

I have got a vector a and a vecor b. And a have bound vectors lb and ub. I want to replace: a[i] = b[i] if lb[i]<b[i]<ub[i]. How should I do it without loops?
M = lb < b & b < ub;
a(M) = b(M);