Geoff
Geoff

Reputation: 65

Finding from-to distances from a matrix (matlab)

The following matrix a represents a from-to distance:

a = [0 3 5 6; 4 0 2 9; 9 1 0 4; 8 3 8 0];

a =

 0     3     5     6
 4     0     2     9
 9     1     0     4
 8     3     8     0

(I.e. From 2 To 4 = 9, From 1 To 2 = 3, etc.)

matrix a is static(not changing) and there is another matrix b which changes. An example input is:

b = [1; 4; 2; 1; 3; 4; 1];

b =

 1
 4
 2
 1
 3
 4
 1

I am looking to find the distance between the first row and the second row -- and perform that task for all rows to output:

b =

 1  
 4  6
 2  3
 1  4
 3  5
 4  4
 1  8

Where the second column is the value obtained from matrix a.

Upvotes: 3

Views: 562

Answers (1)

Colin T Bowers
Colin T Bowers

Reputation: 18530

Here is a one line solution:

%#Set parameters of problem
a = [0 3 5 6; 4 0 2 9; 9 1 0 4; 8 3 8 0];
b = [1; 4; 2; 1; 3; 4; 1];
aSize = size(a);

%#The one-line solution 
Soln = [b, [NaN; a(sub2ind(aSize, b(1:end-1), b(2:end)))]];

Alternatively, the non-vectorized solution is:

%#Set parameters of problem
a = [0 3 5 6; 4 0 2 9; 9 1 0 4; 8 3 8 0];
b = [1; 4; 2; 1; 3; 4; 1];
T = length(b);

%#Preallocate a distance vector
bDist = NaN(T, 1);

%#Loop over b getting the distance for each pair
for t = 2:T
    bDist(t, 1) = a(b(t-1), b(t));
end

%#Combine b and bDist into a single matrix.
Soln = [b bDist];

So which solution is optimal? On my machine (R2012b, Linux Mint v12), the tipping-point length of b is about 650. If b is larger than 650, then use the vectorized solution (ie the one-liner). If b is smaller than 650, then use the loop.

By the way, if you are wondering, the one-line solution works by converting the successive pairs in b into row and column indices for the matrix a by using the sub2ind function. The solution vector is then found by indexing a using these indices.

ps An asymmetric distance matrix? Sounds like an interesting problem!

Upvotes: 2

Related Questions