Compute Mahalanobis distance between vectors x and y using covariance matrix cov if provided; otherwise estimate covariance from the two-sample dataset formed by x and y. NOTE: check if cov matrix is positive definite.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
real(kind=wp), | intent(in) | :: | x(:) |
input vector 1 (features) |
||
real(kind=wp), | intent(in) | :: | y(:) |
input vector 2 (features) |
||
real(kind=wp), | intent(in), | optional | :: | cov(:,:) |
covariance matrix (m,m) |
Mahalanobis distance
pure function f_lin_mahalanobis_core(x, y, cov) result(dist) ! ==== Description !! Compute Mahalanobis distance between vectors x and y !! using covariance matrix cov if provided; otherwise !! estimate covariance from the two-sample dataset formed by x and y. !! NOTE: check if cov matrix is positive definite. ! ==== Declarations real(wp), intent(in) :: x(:) !! input vector 1 (features) real(wp), intent(in) :: y(:) !! input vector 2 (features) real(wp), intent(in), optional :: cov(:,:) !! covariance matrix (m,m) real(wp) :: dist !! Mahalanobis distance real(wp), allocatable :: cov_w(:,:) !! covariance matrix real(wp), allocatable :: diff(:) !! difference vector real(wp), allocatable :: z(:) !! solution vector real(wp), allocatable :: xy(:,:) !! 2-sample data matrix integer(i4) :: m !! number of features integer(i4) :: i, j ! ==== Instructions ! ---- prepare data ! get dims and allocate m = size(x) allocate(diff(m)) allocate(z(m)) allocate(xy(2,m)) ! create 2-sample dataset with x and y as rows xy(1,:) = x xy(2,:) = y ! compute difference vector diff = x - y ! ---- use cholesky-based solver and calculate distance ! get final cov matrix and use solver if (present(cov)) then ! use passed covariance matrix directly (m x m) z = s_utl_cholesky_solve(cov, diff, m) else ! estimate covariance matrix (m x m) from xy rows (samples) allocate(cov_w(m,m)) do i = 1, m do j = 1, m cov_w(i,j) = f_sts_cov_core(xy(:,i), xy(:,j), ddf=1.0_wp) enddo enddo z = s_utl_cholesky_solve(cov_w, diff, m) endif ! get distance dist = sqrt( max(0.0_wp, dot_product(diff, z)) ) ! ---- finish ! deallocate where needed deallocate(diff) deallocate(z) deallocate(xy) if (.not. present(cov)) deallocate(cov_w) end function f_lin_mahalanobis_core