Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/scipy/linalg/_decomp_polar.py: 27%
15 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
1import numpy as np
2from scipy.linalg import svd
5__all__ = ['polar']
8def polar(a, side="right"):
9 """
10 Compute the polar decomposition.
12 Returns the factors of the polar decomposition [1]_ `u` and `p` such
13 that ``a = up`` (if `side` is "right") or ``a = pu`` (if `side` is
14 "left"), where `p` is positive semidefinite. Depending on the shape
15 of `a`, either the rows or columns of `u` are orthonormal. When `a`
16 is a square array, `u` is a square unitary array. When `a` is not
17 square, the "canonical polar decomposition" [2]_ is computed.
19 Parameters
20 ----------
21 a : (m, n) array_like
22 The array to be factored.
23 side : {'left', 'right'}, optional
24 Determines whether a right or left polar decomposition is computed.
25 If `side` is "right", then ``a = up``. If `side` is "left", then
26 ``a = pu``. The default is "right".
28 Returns
29 -------
30 u : (m, n) ndarray
31 If `a` is square, then `u` is unitary. If m > n, then the columns
32 of `a` are orthonormal, and if m < n, then the rows of `u` are
33 orthonormal.
34 p : ndarray
35 `p` is Hermitian positive semidefinite. If `a` is nonsingular, `p`
36 is positive definite. The shape of `p` is (n, n) or (m, m), depending
37 on whether `side` is "right" or "left", respectively.
39 References
40 ----------
41 .. [1] R. A. Horn and C. R. Johnson, "Matrix Analysis", Cambridge
42 University Press, 1985.
43 .. [2] N. J. Higham, "Functions of Matrices: Theory and Computation",
44 SIAM, 2008.
46 Examples
47 --------
48 >>> import numpy as np
49 >>> from scipy.linalg import polar
50 >>> a = np.array([[1, -1], [2, 4]])
51 >>> u, p = polar(a)
52 >>> u
53 array([[ 0.85749293, -0.51449576],
54 [ 0.51449576, 0.85749293]])
55 >>> p
56 array([[ 1.88648444, 1.2004901 ],
57 [ 1.2004901 , 3.94446746]])
59 A non-square example, with m < n:
61 >>> b = np.array([[0.5, 1, 2], [1.5, 3, 4]])
62 >>> u, p = polar(b)
63 >>> u
64 array([[-0.21196618, -0.42393237, 0.88054056],
65 [ 0.39378971, 0.78757942, 0.4739708 ]])
66 >>> p
67 array([[ 0.48470147, 0.96940295, 1.15122648],
68 [ 0.96940295, 1.9388059 , 2.30245295],
69 [ 1.15122648, 2.30245295, 3.65696431]])
70 >>> u.dot(p) # Verify the decomposition.
71 array([[ 0.5, 1. , 2. ],
72 [ 1.5, 3. , 4. ]])
73 >>> u.dot(u.T) # The rows of u are orthonormal.
74 array([[ 1.00000000e+00, -2.07353665e-17],
75 [ -2.07353665e-17, 1.00000000e+00]])
77 Another non-square example, with m > n:
79 >>> c = b.T
80 >>> u, p = polar(c)
81 >>> u
82 array([[-0.21196618, 0.39378971],
83 [-0.42393237, 0.78757942],
84 [ 0.88054056, 0.4739708 ]])
85 >>> p
86 array([[ 1.23116567, 1.93241587],
87 [ 1.93241587, 4.84930602]])
88 >>> u.dot(p) # Verify the decomposition.
89 array([[ 0.5, 1.5],
90 [ 1. , 3. ],
91 [ 2. , 4. ]])
92 >>> u.T.dot(u) # The columns of u are orthonormal.
93 array([[ 1.00000000e+00, -1.26363763e-16],
94 [ -1.26363763e-16, 1.00000000e+00]])
96 """
97 if side not in ['right', 'left']:
98 raise ValueError("`side` must be either 'right' or 'left'")
99 a = np.asarray(a)
100 if a.ndim != 2:
101 raise ValueError("`a` must be a 2-D array.")
103 w, s, vh = svd(a, full_matrices=False)
104 u = w.dot(vh)
105 if side == 'right':
106 # a = up
107 p = (vh.T.conj() * s).dot(vh)
108 else:
109 # a = pu
110 p = (w * s).dot(w.T.conj())
111 return u, p