Reconstructing a point set from a Euclidean Distance Matrix
Recovering point locations from vectors.
Recovering point locations from Euclidean Distance Matrices has practical applications in ultrasound tomography and other fields that must determine the position of recording devices from acoustic signals. This post explains the solution to a concrete problem, drawing on the explanations in Linear Algebra and Learning from Data and a paper on Euclidean distance geometry.
I want to answer the question: How to reconstruct the locations of the original vectors given the Euclidean distance matrix,
We assume
Theory
This procedure, known as classical multidimensional scaling (MDS), comes from this paper. The approach extends to real-world problems like noisy data.
Consider a collection of
Expanding this norm yields:
The matrix equation for the distance matrix
The operator
Let the first point
It is now possible to construct the term
The Gram matrix
The final stage is to identify the point set using Eigenvalue Decomposition (EVD), for example:
Remember that
Example problem
This problem is Q5 from Problem Set
Let’s start with some useful imports:
import numpy as np
import matplotlib.pyplot as plt
from scipy.spatial import distance_matrix
from scipy.spatial.distance import cdist
And now let’s define the matrix
D = np.array([[0, 9, 25], [9, 0, 16], [25, 16, 0]])
Calculate the Gram matrix. Any point can serve as the origin; the code below uses the second, because it makes
G = -0.5 * (D - np.outer(np.ones(3), D[1, :]) - np.outer(D[:, 1], np.ones(3)))
G
array([[9., -0., -0.],
[-0., -0., -0.],
[-0., -0., 16.]])
Now use np.linalg.svd to solve
Q, Lambda, _ = np.linalg.svd(G)
print(Q)
print(Lambda)
[[0. 1. 0.]
[0. 0. 1.]
[1. 0. 0.]]
[16. 9. -0.]
Return the original point set using np.sqrt(Lambda) * Q.T scales the columns of
np.diag(np.sqrt(Lambda)) @ Q.T
array([[0., 0., 4.],
[3., 0., 0.],
[0., 0., 0.]])
The columns are the points. The third row is zero because the third eigenvalue is, so the three points lie in a plane: