Matlab Vectorization : How to avoid this “for” loo

2019-06-03 10:26发布

问题:

I have following matrices :

X=1 2 3  
Y=4 5 6  

A=1 2 3  
  4 5 6  
  7 8 9  

I Want to do

for each (i,j) in A  
  v = A(i,j)*X - Y
  B(i,j) = v * v'

i.e. each element of A is multiplied by vector X, then resultant vector subtracts Y from itself and finally we take inner product of that vector to bring a single number.
Can it be done without for loop ?

回答1:

One thing often forgotten in Matlab: The operator ' takes the conjugate transposed (.' is the ordinary transposed). In other words, A' == conj(trans(A)), whereas A.' == trans(A), which makes a difference if A is a complex matrix.

Ok, let's apply some mathematics to your equations. We have

v = A(i,j)*X - Y
B(i,j) = v * v'
       = (A(i,j)*X - Y) * (A(i,j)*X - Y)'
       = A(i,j)*X * conj(A(i,j))*X' - Y * conj(A(i,j))*X' 
         - A(i,j)*X * Y' + Y * Y'
       = A(i,j)*conj(A(i,j)) * X*X' - conj(A(i,j)) * Y*X' - A(i,j) * X*Y' + Y*Y'

So a first result would be

B = A.*conj(A) * (X*X') - conj(A) * (Y*X') - A * (X*Y') + Y*Y'

In the case of real matrices/vectors, one has the identities

X*Y' == Y*X'
A == conj(A)

which means, you can reduce the expression to

B = A.*A * (X*X') - 2*A * (X*Y') + Y*Y'
  = A.^2 * (X*X') - 2*A * (X*Y') + Y*Y'


回答2:

An alternative method:

X = [1 2 3]
Y = [4 5 6]
A = [1 2 3; 4 5 6; 7 8 9]

V = bsxfun(@minus, A(:)*X, [4 5 6])
b = sum((V.^2)')
B = reshape(b , 3, 3)

I get the result:

B = 27     5    11
    45   107   197
   315   461   635