Matrix assignment element without loop
I am trying to build a constraint matrix that I will use with linprog
and I am struggling to build this efficiently without using for loops. Here's an example of what I am trying to achieve:
A = zeros(3, 3); % Constraint matrix
i = [1 3]; % row indexes
j = [1 2 ; 1 3]; % column indexes
x = [1 2 ; 3 4]; % values to assign
Expected result after assignment:
A = [1 2 0 ; 0 0 0 ; 3 0 4]
I want to perform the following operations:
A(i(1), j(1,:)) = x(1,:) A(i(2), j(2,:)) = x(2,:)
I am currently using a for loop:
for k=1:length(i)
A(i(k), j(k,:)) = x(k,:);
end
Is there a better way to do this for any i
u j
? I could use a for loop everywhere, but the number of constraints depends on the number of variables, so my code is filled with for-loops. What is the standard way to define a constraint matrix for use with linprog
?
source to share
One vectorized
with bsxfun
-
A(bsxfun(@plus,ii(:),(jj-1)*size(A,1))) = x
You need expansion
c bsxfun
as the number of row indices is not the same as the number of column indices.
Also note that I replaced the variable names i
with ii
and j
with jj
as i
well j
as with complex numbers, as this might cause some conflict otherwise.
Example run -
>> ii(:) %// Row indices
ans =
1
3
>> jj %// Column indices
jj =
1 2 4
1 3 5
>> x %// Values to assign
x =
1 2 6
3 4 8
>> A %// Output
A =
1 2 0 6 0
0 0 0 0 0
3 0 4 0 8
It has two advantages:
-
Avoid calling
sub2ind
with its original version, formore efficient with runtime
. -
An extension that is executed internally without using any kind of loop or
repmat
saves a loop or other function call, respectively.
source to share
What you are looking for is the sub2ind function . Here's how you would improve your matrix creation:
>> indx = sub2ind(size(A),[1 3 1 3]',j(:))
indx =
1
3
4
9
>> A(indx)=x(:)
A =
1 2 0
0 0 0
3 0 4
Note that you will have to tweak your definition of i a little so that i and j have the same number of elements.
source to share
Here's another way using sparse
:
A = full(sparse(repmat(ii,size(jj,1),1).', jj ,x));
I use ii
both jj
as variable names instead of i
and j
as in Divakar's answer .
source to share