4 views (last 30 days)

The situation is, you have a vector A, a vector i, and a vector x. The vector A is your base vector you want to add some values to. The vector x is the values you want to add to A, and the vector i is the indices of where you want the values in x to be added in A. So A is 1-by-n, and x and i are both 1-by-m.

You can execute this in two ways as far as I can tell, by either using a for loop to iterate through x (and i) and adding the values where appropriate, or you can use vectorized indexing to do the entire operation in one line. However, the vectorized indexing only works if the index vector contains only unique values. If the vector i contains multiple values that are the same, the two different ways of doing the operation give different results. It seems that what happens is Matlab just adds to A(i) whatever value in x corresponds to the last instance of that value of i in the vector, rather than adding them all cumulatively.

My question is, can anyone suggest a solution to this problem that is more efficient than just using a for loop? Is there an efficient function that can give me a unique version of the vector i with a corresponding new vector x' where all of the values that correspond to the same index (same value in i) have been added together, such that I can use a vectorized operation and get the same result as when using a for loop?

Here is some code that demonstrates the issue as simply as possible:

clear all; close all; clc;

% first, an example of it working when the index vector has no repeated

% values

A = rand(1,5);

A_vector = A;

A_forloop = A;

indices = [1 2 3];

x = rand(size(indices));

A_vector(indices) = A_vector(indices) + x;

for i = 1:length(indices)

A_forloop(indices(i)) = A_forloop(indices(i)) + x(i);

end

all(A_vector==A_forloop) % check that all values are the same

% second, an example of it not working when the index vector has repeated

% values

A = rand(1,5);

A_vector = A;

A_forloop = A;

indices = [1 1 1 2 3];

x = rand(size(indices));

A_vector(indices) = A_vector(indices) + x;

for i = 1:length(indices)

A_forloop(indices(i)) = A_forloop(indices(i)) + x(i);

end

all(A_vector==A_forloop) % check that all values are the same

The first check gives a true value, the second check gives a false value, because the vectorization of the procedure does not give the same result as the for loop when the vector i has repeated values.

David Goodmanson
on 9 Jan 2020

Edited: David Goodmanson
on 9 Jan 2020

Hi Nathan,

sparse matrices automatically do what you want. You have full matrices, and sparse operations are on the slow side when operating on full matrices, but unless the dimensions are quite large, this should not be a problem. For example,

A = 1:12;

x = 1:10;

ind = [1 2 4 4 5 9 9 2 2 2];

sA = size(A);

B = full(sparse(ones(size(ind)),ind,x,sA(1),sA(2)))

A = A + B

See the help on sparse for the input scheme.

Sign in to answer this question.

Opportunities for recent engineering grads.

Apply Today
## 0 Comments

Sign in to comment.