distmat

PURPOSE ^

DISTMAT Distance matrix for a set of points

SYNOPSIS ^

function [dmat,opt] = distmat(xy,varargin)

DESCRIPTION ^

 DISTMAT Distance matrix for a set of points
   Returns the point-to-point distance between all pairs of points in XY
       (similar to PDIST in the Statistics Toolbox)

   DMAT = DISTMAT(XY) Calculates the distance matrix using an automatic option
   DMAT = DISTMAT(XY,OPT) Uses the specified option to compute the distance matrix
   [DMAT,OPT] = DISTMAT(XY) Also returns the automatic option used by the function

   Inputs:
       XY is an NxP matrix of coordinates for N points in P dimensions
       OPT (optional) is an integer between 1 and 4 representing the chosen
           method for computing the distance matrix (see note below)

   Outputs:
       DMAT is an NxN matrix, where the value of DMAT(i,j) corresponds to
           the distance from XY(i,:) to XY(j,:)
       OPT (optional) is an integer between 1 and 4 representing the method
           used to compute the distance matrix (see note below)

   Note:
       DISTMAT contains 4 methods for computing the distance matrix
         OPT=1 Usually fastest for small inputs. Takes advantage of the symmetric
               property of distance matrices to perform half as many calculations
         OPT=2 Usually fastest for medium inputs. Uses a fully vectorized method
         OPT=3 Usually fastest for large inputs. Uses a partially vectorized
               method with relatively small memory requirement
         OPT=4 Another compact calculation, but usually slower than the others

   Example:
       % Test computation times for the options
       n = [10 100 1000];
       dmat = distmat(10*rand(10,3),1); % First call is always really slow
       for k=1:3
           for opt=1:4
               tic; [dmat,opt] = distmat(10*rand(n(k),3),opt); t=toc;
               disp(sprintf('n=%d, opt=%d, t=%0.6f', n(k), opt, t))
           end
       end

   Example:
       xy = 10*rand(25,2);  % 25 points in 2D
       dmat = distmat(xy);
       figure; plot(xy(:,1),xy(:,2),'.');
       for k=1:25, text(xy(k,1),xy(k,2),[' ' num2str(k)]); end
       figure; imagesc(dmat); set(gca,'XTick',1:25,'YTick',1:25); colorbar

   Example:
       xyz = 10*rand(20,3);  % 20 points in 3D
       dmat = distmat(xyz);
       figure; plot3(xyz(:,1),xyz(:,2),xyz(:,3),'.');
       for k=1:20, text(xyz(k,1),xyz(k,2),xyz(k,3),[' ' num2str(k)]); end
       figure; imagesc(dmat); set(gca,'XTick',1:20,'YTick',1:20); colorbar

 Author: Joseph Kirk
 Email: jdkirk630 at gmail dot com
 Release: 1.0
 Release Date: 5/29/07

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 function [dmat,opt] = distmat(xy,varargin)
0002 % DISTMAT Distance matrix for a set of points
0003 %   Returns the point-to-point distance between all pairs of points in XY
0004 %       (similar to PDIST in the Statistics Toolbox)
0005 %
0006 %   DMAT = DISTMAT(XY) Calculates the distance matrix using an automatic option
0007 %   DMAT = DISTMAT(XY,OPT) Uses the specified option to compute the distance matrix
0008 %   [DMAT,OPT] = DISTMAT(XY) Also returns the automatic option used by the function
0009 %
0010 %   Inputs:
0011 %       XY is an NxP matrix of coordinates for N points in P dimensions
0012 %       OPT (optional) is an integer between 1 and 4 representing the chosen
0013 %           method for computing the distance matrix (see note below)
0014 %
0015 %   Outputs:
0016 %       DMAT is an NxN matrix, where the value of DMAT(i,j) corresponds to
0017 %           the distance from XY(i,:) to XY(j,:)
0018 %       OPT (optional) is an integer between 1 and 4 representing the method
0019 %           used to compute the distance matrix (see note below)
0020 %
0021 %   Note:
0022 %       DISTMAT contains 4 methods for computing the distance matrix
0023 %         OPT=1 Usually fastest for small inputs. Takes advantage of the symmetric
0024 %               property of distance matrices to perform half as many calculations
0025 %         OPT=2 Usually fastest for medium inputs. Uses a fully vectorized method
0026 %         OPT=3 Usually fastest for large inputs. Uses a partially vectorized
0027 %               method with relatively small memory requirement
0028 %         OPT=4 Another compact calculation, but usually slower than the others
0029 %
0030 %   Example:
0031 %       % Test computation times for the options
0032 %       n = [10 100 1000];
0033 %       dmat = distmat(10*rand(10,3),1); % First call is always really slow
0034 %       for k=1:3
0035 %           for opt=1:4
0036 %               tic; [dmat,opt] = distmat(10*rand(n(k),3),opt); t=toc;
0037 %               disp(sprintf('n=%d, opt=%d, t=%0.6f', n(k), opt, t))
0038 %           end
0039 %       end
0040 %
0041 %   Example:
0042 %       xy = 10*rand(25,2);  % 25 points in 2D
0043 %       dmat = distmat(xy);
0044 %       figure; plot(xy(:,1),xy(:,2),'.');
0045 %       for k=1:25, text(xy(k,1),xy(k,2),[' ' num2str(k)]); end
0046 %       figure; imagesc(dmat); set(gca,'XTick',1:25,'YTick',1:25); colorbar
0047 %
0048 %   Example:
0049 %       xyz = 10*rand(20,3);  % 20 points in 3D
0050 %       dmat = distmat(xyz);
0051 %       figure; plot3(xyz(:,1),xyz(:,2),xyz(:,3),'.');
0052 %       for k=1:20, text(xyz(k,1),xyz(k,2),xyz(k,3),[' ' num2str(k)]); end
0053 %       figure; imagesc(dmat); set(gca,'XTick',1:20,'YTick',1:20); colorbar
0054 %
0055 % Author: Joseph Kirk
0056 % Email: jdkirk630 at gmail dot com
0057 % Release: 1.0
0058 % Release Date: 5/29/07
0059 
0060 % We need this because pdist and pdist2 are in the stats toolbox in matlab
0061 
0062 % process inputs
0063 if nargin<1 || nargin>2;
0064    error('Call distmat with 1 or 2 args');
0065 end
0066 if ischar(xy) && strcmp(xy,'UNIT_TEST'); do_unit_test; return; end
0067 
0068 
0069 [n,dims] = size(xy);
0070 numels = n*n*dims;
0071 opt = 2; if numels > 5e4, opt = 3; elseif n < 20, opt = 1; end
0072 for var = varargin
0073     if length(var{1}) == 1
0074         opt = max(1, min(4, round(abs(var{1}))));
0075     else
0076         error('Invalid input argument.');
0077     end
0078 end
0079 
0080 % distance matrix calculation options
0081 switch opt
0082     case 1 % half as many computations (symmetric upper triangular property)
0083         [k,kk] = find(triu(ones(n),1));
0084         dmat = zeros(n);
0085         dmat(k+n*(kk-1)) = sqrt(sum((xy(k,:) - xy(kk,:)).^2,2));
0086         dmat(kk+n*(k-1)) = dmat(k+n*(kk-1));
0087     case 2 % fully vectorized calculation (very fast for medium inputs)
0088         a = reshape(xy,1,n,dims);
0089         b = reshape(xy,n,1,dims);
0090         dmat = sqrt(sum((a(ones(n,1),:,:) - b(:,ones(n,1),:)).^2,3));
0091     case 3 % partially vectorized (smaller memory requirement for large inputs)
0092         dmat = zeros(n,n);
0093         for k = 1:n
0094             dmat(k,:) = sqrt(sum((xy(k*ones(n,1),:) - xy).^2,2));
0095         end
0096     case 4 % another compact method, generally slower than the others
0097         a = (1:n);
0098         b = a(ones(n,1),:);
0099         dmat = reshape(sqrt(sum((xy(b,:) - xy(b',:)).^2,2)),n,n);
0100 end
0101 
0102 function do_unit_test
0103    a = 1:3; b=4:6;
0104    xy= [a;b];
0105    out = norm(a-b)*(1-eye(2));
0106    unit_test_cmp('distmat 0', distmat(xy), out, 1e-14); 
0107    unit_test_cmp('distmat 1', distmat(xy,1), out, 1e-14); 
0108    unit_test_cmp('distmat 2', distmat(xy,2), out, 1e-14); 
0109    unit_test_cmp('distmat 3', distmat(xy,3), out, 1e-14); 
0110    unit_test_cmp('distmat 4', distmat(xy,4), out, 1e-14); 
0111

Generated on Fri 30-Dec-2022 19:44:54 by m2html © 2005