function [dist, flow] = emd(X, Y, X_weights, Y_weights, distance, D) %Computes the Earth Mover's Distance between two weighted samples % emd(X, Y[, X_weights, Y_weights, distance, D]) % X : First sample % Y : Second sample % X_weights : weights of elements in X (must sum to 1); % default: 1/|X| is used as the weight of each element % Y_weights : weights of elements in Y (must sum to 1); % default: 1/|Y| is used as the weight of each element % distance : valid distance type used by pdist2, % or "precomputed" if the pairwise distances D is supplied; % default: euclidean % D : precomputed distance matrix; ignored unless distance="precomputed"; % must be array of size |X|-by-|Y| if nargin < 2 error('Must at least provide two samples.'); end if nargin < 3 X_weights = []; end if nargin < 4 Y_weights = []; end if nargin < 5 distance = 'euclidean'; end if nargin < 6 D = []; end if ~strcmp(distance, 'precomputed') n = length(X); m = length(Y); D = pdist2(X, Y, distance); if isempty(X_weights) X_weights = ones(1, n)/n; elseif n ~= length(X_weights) error('Size mismatch of X and X_weights'); else X_weights = reshape(X_weights, 1, []); end if isempty(Y_weights) Y_weights = ones(1, m)/m; elseif m ~= length(Y_weights) error('Size mismatch of Y and Y_weights'); else Y_weights = reshape(Y_weights, 1, []); end else if isempty(D) error('D must be supplied when distance=''precomputed'''); end [n, m] = size(D); if isempty(X_weights) X_weights = ones(1, n)/n; elseif n ~= length(X_weights) error('Size mismatch of D and X_weights'); else X_weights = reshape(X_weights, 1, []); end if isempty(Y_weights) Y_weights = ones(1, m)/m; elseif m ~= length(Y_weights) error('Size mismatch of D and Y_weights'); else Y_weights = reshape(Y_weights, 1, []); end end if nargout > 1 [dist, flow] = c_emd(X_weights, Y_weights, D); else dist = c_emd(X_weights, Y_weights, D); end end