Oktav: vektörlerin iki matrisi arasındaki mesafeyi hesapla


12

Diyelim ki sırasıyla N, M 2d vektörlerini temsil eden iki Nx2, Mx2 matrisine sahibim. Her vektör çifti (n, m) arasındaki mesafeleri hesaplamanın basit ve iyi bir yolu var mı?

Kolay ama verimsiz yol elbette:

d = zeros(N, M);
for i = 1:N,
  for j = 1:M,
    d(i,j) = norm(n(i,:) - m(j,:));
  endfor;
endfor;

Bulduğum en yakın cevap şu şekilde bsxfunkullanılıyor:

bsxfun(inline("x-y"),[1,2,3,4],[3;4;5;6])

ans =
  -2 -1  0  1
  -3 -2 -1  0
  -4 -3 -2 -1
  -5 -4 -3 -2

Buna bir göz attım ve hesaplamayı vektör yapmaktan daha iyisini yapamadım. Bu hesaplamanın harici bir C / Fortran işlevi yazmak için oldukça iyi bir aday olduğunu düşünüyorum.
Aron Ahmadia

1
Bahse girerim, bir dış ürünle doldurduğunuz 2xNxM matrisi yapabilir, daha sonra girişlerin her birini kare ve sıfırıncı eksen ve kare kök boyunca toplayabilirsiniz. Python'da bu şöyle görünecektir: distance_matrix = (n [:,:, nexaxis] * m [:, newaxis ,:]); distance_matrix = distance_matrix ** 2; distance_matrix = sqrt (distance_matrix.sum (eksen = 1)); Sadece en yakın n-vektörleri bilmeniz gerekiyorsa, bunu yapmanın çok daha iyi yolları vardır!
meawoppl

3
@meawoppl (Octave'den New'e) Octave'de lineer-cebir paketinin nasıl kullanıldığını öğrendim cartprod, bu da şimdi yazabiliyorum: (1) x = cartprod(n(:,1), m(:,1)); (2) y = cartprod(n(:,2), m(:,2)); (3) d = sqrt((x(:,1)-x(:,2)).^2+(y(:,1)-y(:,2)).^2) .. ki bu çok daha hızlı çalışır!
Kelley van Evert

Yanıtlar:


6

Bu gibi bir stratejiyi kullanarak bu durumlarda vektörleştirme basittir:

eN = ones(N,1);
eM = ones(M,1);
d  = sqrt(eM*n.^2' - 2*m*n' + m.^2*eN');

M = 1000 ve N = 2000 için for döngüsünü 15x hız ile vektörleştiren bir örnek.

n = rand(N,2);
m = rand(M,2);
eN = ones(N,2);
eM = ones(2,M);

tic;
d_vect  = sqrt(eN*m.^2' - 2*n*m' + n.^2*eM);
vect_time = toc;

tic;
for i=1:N
  for j=1:M
     d_for(i,j) = norm(n(i,:)-m(j,:));
  end
end
for_time = toc; 

assert(norm(d_vect-d_for) < 1e-10*norm(d_for)) 

David, seni scicomp'da görmek güzel! Utanmadan kod parçanızı düzenledim ve biraz genişlettim, lütfen düzenlemelerim ne istediğini açıklığa kavuşturmaktan yanlış yöne giderse geri dönün.
Aron Ahmadia

2

Octave 3.4.3 ve sonraki sürümlerden itibaren operatör - otomatik yayın yapar (dahili olarak bsxfun kullanır). Böylece bu şekilde ilerleyebilirsiniz.

Dx = N(:,1) - M(:,1)';
Dy = N(:,2) - M(:,2)';
D = sqrt (Dx.^2 + Dy.^2);

Aynı şeyi bir 3d matris kullanarak da yapabilirsiniz ama sanırım bu daha net. D, bir NxM mesafe matrisidir, N'deki her vektör, M'deki her vektöre karşı.

Bu yardımcı olur umarım

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.