%CHECKTR Check whether Square Distance Matrix Obeys the Triangle Inequality % % [P,C] = CHECKTR(D,N) % % INPUT % D NxN symmetric distance matrix or dataset % % OUTPUT % P Total fraction of inequalities disobeying the triangle inequality % C Constant determined such that when added to all off-diagonal % values of D, makes D metric % % DESCRIPTION % Checks whether a symmetric distance matrix D obeys the triangle inequality. % If D is asymmetric, it is made symmetric by averaging. M is the total number % of disobeyed inequalities. Hence, for M = 0, the triangle inequality holds % for the distance matrix D. Additionally, a constant C is sought, which when % added to the off-diagonal elements of D will make D obey the triangle inequality: % C = max_{i,j,k} {abs(D_{ij} + D_{ik} - D_{jk})} % If C is zero, then D fulfills the condition. % % If N is given, a random NxN subset is taken to speed up and P is an % estimate. % Copyright: Elzbieta Pekalska, ela.pekalska@googlemail.com % Faculty EWI, Delft University of Technology and % School of Computer Science, University of Manchester function [no,c] = checktr(d,nmax) d = +d; [n,m] = size(d); if nargin < 2 nmax = n; % check all end prec = 1e-12; if ~issym(d,prec) prwarning(1,'Distance matrix should be symmetric. It is made so by averaging.') end d = 0.5*(d+d'); d(1:n+1:end) = 0; c = 0; ismetric = 1; no = 0; % Number of disobeyed triangle inequalities if n > nmax % take subset to speed up. R = randperm(n); R = R(1:nmax); d = d(R,R); n = nmax; end prwaitbar(n,'check triangle inequalities'); N = 0; for j=1:n-1 prwaitbar(n,j); r1 = d(:,j); r2 = d(j,j+1:n); % M checks the triangle ineqaulities; all elements of M are % positive or zero if this holds. M = repmat(r1,1,n-j) + d(:,j+1:n) - repmat(r2,n,1); % The elemnets of M should ideally be compared to 0. However, % due to numerical inaccuracies, a small negative number should % be used. Experiments indicate that -1e-13 works well. % Otherwise, one gets wrong results. tol = 1e-13; mm = sum(M(:) < -tol); N = N + (n-j)*n; no = no + mm; ismetric = ismetric & (mm == 0); if ~ismetric, cc = max(max(M)); if cc > c, c = cc; end end end no = no/N; prwaitbar(0); return;