Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/scipy/linalg/_procrustes.py: 24%
17 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-12 06:31 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-12 06:31 +0000
1"""
2Solve the orthogonal Procrustes problem.
4"""
5import numpy as np
6from ._decomp_svd import svd
9__all__ = ['orthogonal_procrustes']
12def orthogonal_procrustes(A, B, check_finite=True):
13 """
14 Compute the matrix solution of the orthogonal Procrustes problem.
16 Given matrices A and B of equal shape, find an orthogonal matrix R
17 that most closely maps A to B using the algorithm given in [1]_.
19 Parameters
20 ----------
21 A : (M, N) array_like
22 Matrix to be mapped.
23 B : (M, N) array_like
24 Target matrix.
25 check_finite : bool, optional
26 Whether to check that the input matrices contain only finite numbers.
27 Disabling may give a performance gain, but may result in problems
28 (crashes, non-termination) if the inputs do contain infinities or NaNs.
30 Returns
31 -------
32 R : (N, N) ndarray
33 The matrix solution of the orthogonal Procrustes problem.
34 Minimizes the Frobenius norm of ``(A @ R) - B``, subject to
35 ``R.T @ R = I``.
36 scale : float
37 Sum of the singular values of ``A.T @ B``.
39 Raises
40 ------
41 ValueError
42 If the input array shapes don't match or if check_finite is True and
43 the arrays contain Inf or NaN.
45 Notes
46 -----
47 Note that unlike higher level Procrustes analyses of spatial data, this
48 function only uses orthogonal transformations like rotations and
49 reflections, and it does not use scaling or translation.
51 .. versionadded:: 0.15.0
53 References
54 ----------
55 .. [1] Peter H. Schonemann, "A generalized solution of the orthogonal
56 Procrustes problem", Psychometrica -- Vol. 31, No. 1, March, 1996.
58 Examples
59 --------
60 >>> import numpy as np
61 >>> from scipy.linalg import orthogonal_procrustes
62 >>> A = np.array([[ 2, 0, 1], [-2, 0, 0]])
64 Flip the order of columns and check for the anti-diagonal mapping
66 >>> R, sca = orthogonal_procrustes(A, np.fliplr(A))
67 >>> R
68 array([[-5.34384992e-17, 0.00000000e+00, 1.00000000e+00],
69 [ 0.00000000e+00, 1.00000000e+00, 0.00000000e+00],
70 [ 1.00000000e+00, 0.00000000e+00, -7.85941422e-17]])
71 >>> sca
72 9.0
74 """
75 if check_finite:
76 A = np.asarray_chkfinite(A)
77 B = np.asarray_chkfinite(B)
78 else:
79 A = np.asanyarray(A)
80 B = np.asanyarray(B)
81 if A.ndim != 2:
82 raise ValueError('expected ndim to be 2, but observed %s' % A.ndim)
83 if A.shape != B.shape:
84 raise ValueError('the shapes of A and B differ (%s vs %s)' % (
85 A.shape, B.shape))
86 # Be clever with transposes, with the intention to save memory.
87 u, w, vt = svd(B.T.dot(A).T)
88 R = u.dot(vt)
89 scale = w.sum()
90 return R, scale