1 from . import (best_similarity_transform, contract, np, assert_allclose,
2 project_vectors_onto_sphere, eigh)
3 from contracts import check_multiple
4 import itertools
5
6
7 @contract(S='array[KxN]', returns='array[NxN](>=0)')
9 ''' Computes the euclidean distance matrix for the given points. '''
10 K, N = S.shape
11 D = np.zeros((N, N))
12 for i in range(N):
13 p = S[:, i]
14 pp = np.tile(p, (N, 1)).T
15 assert pp.shape == (K, N)
16 d2 = ((S - pp) * (S - pp)).sum(axis=0)
17 d2 = np.maximum(d2, 0)
18 D[i, :] = np.sqrt(d2)
19 return D
20
23 n = P.shape[0]
24
25 grand_mean = P.mean()
26 row_mean = np.zeros(n)
27 col_mean = np.zeros(n)
28 for i in range(n):
29 row_mean[i] = P[i, :].mean()
30 col_mean[i] = P[:, i].mean()
31
32 R = row_mean.reshape(n, 1).repeat(n, axis=1)
33 assert R.shape == (n, n)
34 C = col_mean.reshape(1, n).repeat(n, axis=0)
35 assert C.shape == (n, n)
36
37 B2 = -0.5 * (P - R - C + grand_mean)
38
39 if False:
40 B = np.zeros(P.shape)
41 for i, j in itertools.product(range(n), range(n)):
42 B[i, j] = -0.5 * (P[i, j] - col_mean[j] - row_mean[i] + grand_mean)
43 assert_allclose(B2, B)
44
45 return B2
46
50 U, S, V = np.linalg.svd(C, full_matrices=0)
51 check_multiple([('array[NxN]', U),
52 ('array[N]', S),
53 ('array[NxN]', V)])
54 coords = V[:ndim, :]
55 for i in range(ndim):
56 coords[i, :] = coords[i, :] * np.sqrt(S[i])
57 return coords
58
62 n = C.shape[0]
63 eigvals = (n - ndim, n - 1)
64 S, V = eigh(C, eigvals=eigvals)
65
66 assert S[0] <= S[1]
67
68 check_multiple([('K', ndim),
69 ('array[NxK]', V),
70 ('array[K]', S)])
71 coords = V.T
72 for i in range(ndim):
73 coords[i, :] = coords[i, :] * np.sqrt(S[i])
74 return coords
75
78 ''' Truncated SVD based on randomized projections. '''
79 p = k + 5
80 Y = np.dot(M, np.random.normal(size=(M.shape[1], p)))
81 Q, r = np.linalg.qr(Y)
82 B = np.dot(Q.T, M)
83 Uhat, s, v = np.linalg.svd(B, full_matrices=False)
84 U = np.dot(Q, Uhat)
85 return U.T[:k].T, s[:k], v[:k]
86
90 '''
91 Best embedding of inner product matrix based on
92 randomized projections.
93 '''
94 U, S, V = truncated_svd_randomized(C, ndim)
95 check_multiple([('K', ndim),
96 ('array[KxN]', V),
97 ('array[K]', S)])
98 coords = V
99 for i in range(ndim):
100 coords[i, :] = coords[i, :] * np.sqrt(S[i])
101 return coords
102
106 diag = D.diagonal()
107 assert_allclose(diag, 0)
108
109 P = D * D
110 B = double_center(P)
111 return embed(B, ndim)
112
113
114 @contract(D='array[MxM](>=0)', ndim='K,int,>=1', returns='array[KxM]')
115 -def mds_randomized(D, ndim):
118
126
127
128
129 best_embedding_on_sphere = spherical_mds
130
131
132 @contract(references='array[KxN]', distances='array[N](>=0)')
133 -def place(references, distances):
134
135 K, N = references.shape
136
137
138 D = np.zeros((N + 1, N + 1))
139 D[:N, :N] = euclidean_distances(references)
140 D[N, N] = 0
141 D[N, :N] = distances
142 D[:N, N] = distances
143 Sm = mds(D, K)
144
145
146
147
148
149 R, t = best_similarity_transform(Sm[:, :N], references)
150
151 Sm_aligned = np.dot(R, Sm) + t
152 result = Sm_aligned[:, N]
153
154 return result
155