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

?

+3


source to share


3 answers


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:

+3


source


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.

+4


source


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 .

+1


source







All Articles