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

1""" 

2Solve the orthogonal Procrustes problem. 

3 

4""" 

5import numpy as np 

6from ._decomp_svd import svd 

7 

8 

9__all__ = ['orthogonal_procrustes'] 

10 

11 

12def orthogonal_procrustes(A, B, check_finite=True): 

13 """ 

14 Compute the matrix solution of the orthogonal Procrustes problem. 

15 

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]_. 

18 

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. 

29 

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``. 

38 

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. 

44 

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. 

50 

51 .. versionadded:: 0.15.0 

52 

53 References 

54 ---------- 

55 .. [1] Peter H. Schonemann, "A generalized solution of the orthogonal 

56 Procrustes problem", Psychometrica -- Vol. 31, No. 1, March, 1996. 

57 

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]]) 

63 

64 Flip the order of columns and check for the anti-diagonal mapping 

65 

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 

73 

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