def pinv2(a, cond=None, rcond=None): """ Compute the (Moore-Penrose) pseudo-inverse of a matrix. Calculate a generalized inverse of a matrix using its singular-value decomposition and including all 'large' singular values. Parameters ---------- a : array, shape (M, N) Matrix to be pseudo-inverted. cond, rcond : float or None Cutoff for 'small' singular values. Singular values smaller than ``rcond*largest_singular_value`` are considered zero. If None or -1, suitable machine precision is used. Returns ------- B : array, shape (N, M) The pseudo-inverse of matrix `a`. Raises ------ LinAlgError If SVD computation does not converge. Examples -------- >>> a = np.random.randn(9, 6) >>> B = linalg.pinv2(a) >>> np.allclose(a, dot(a, dot(B, a))) True >>> np.allclose(B, dot(B, dot(a, B))) True """ a = np.asarray_chkfinite(a) u, s, vh = decomp_svd.svd(a) t = u.dtype.char if rcond is not None: cond = rcond if cond in [None,-1]: eps = np.finfo(np.float).eps feps = np.finfo(np.single).eps _array_precision = {'f': 0, 'd': 1, 'F': 0, 'D': 1} cond = {0: feps*1e3, 1: eps*1e6}[_array_precision[t]] m, n = a.shape cutoff = cond*np.maximum.reduce(s) psigma = np.zeros((m, n), t) for i in range(len(s)): if s[i] > cutoff: psigma[i,i] = 1.0/np.conjugate(s[i]) #XXX: use lapack/blas routines for dot return np.transpose(np.conjugate(np.dot(np.dot(u,psigma),vh)))
def pinv2(a, cond=None, rcond=None): """ Compute the (Moore-Penrose) pseudo-inverse of a matrix. Calculate a generalized inverse of a matrix using its singular-value decomposition and including all 'large' singular values. Parameters ---------- a : array, shape (M, N) Matrix to be pseudo-inverted. cond, rcond : float or None Cutoff for 'small' singular values. Singular values smaller than ``rcond*largest_singular_value`` are considered zero. If None or -1, suitable machine precision is used. Returns ------- B : array, shape (N, M) The pseudo-inverse of matrix `a`. Raises ------ LinAlgError If SVD computation does not converge. Examples -------- >>> a = np.random.randn(9, 6) >>> B = linalg.pinv2(a) >>> np.allclose(a, dot(a, dot(B, a))) True >>> np.allclose(B, dot(B, dot(a, B))) True """ a = np.asarray_chkfinite(a) u, s, vh = decomp_svd.svd(a) t = u.dtype.char if rcond is not None: cond = rcond if cond in [None, -1]: eps = np.finfo(np.float).eps feps = np.finfo(np.single).eps _array_precision = {'f': 0, 'd': 1, 'F': 0, 'D': 1} cond = {0: feps * 1e3, 1: eps * 1e6}[_array_precision[t]] m, n = a.shape cutoff = cond * np.maximum.reduce(s) psigma = np.zeros((m, n), t) for i in range(len(s)): if s[i] > cutoff: psigma[i, i] = 1.0 / np.conjugate(s[i]) #XXX: use lapack/blas routines for dot return np.transpose(np.conjugate(np.dot(np.dot(u, psigma), vh)))
def pinv2(a, cond=None, rcond=None, return_rank=False, check_finite=True): """ Compute the (Moore-Penrose) pseudo-inverse of a matrix. Calculate a generalized inverse of a matrix using its singular-value decomposition and including all 'large' singular values. Parameters ---------- a : array, shape (M, N) Matrix to be pseudo-inverted. cond, rcond : float or None Cutoff for 'small' singular values. Singular values smaller than ``rcond*largest_singular_value`` are considered zero. If None or -1, suitable machine precision is used. return_rank : bool, optional if True, return the effective rank of the matrix check_finite : boolean, optional Whether to check the input matrixes contain only finite numbers. Disabling may give a performance gain, but may result to problems (crashes, non-termination) if the inputs do contain infinities or NaNs. Returns ------- B : array, shape (N, M) The pseudo-inverse of matrix `a`. rank : int The effective rank of the matrix. Returned if return_rank == True Raises ------ LinAlgError If SVD computation does not converge. Examples -------- >>> a = np.random.randn(9, 6) >>> B = linalg.pinv2(a) >>> np.allclose(a, dot(a, dot(B, a))) True >>> np.allclose(B, dot(B, dot(a, B))) True """ if check_finite: a = np.asarray_chkfinite(a) else: a = np.asarray(a) u, s, vh = decomp_svd.svd(a, full_matrices=False) if rcond is not None: cond = rcond if cond in [None,-1]: t = u.dtype.char.lower() factor = {'f': 1E3, 'd': 1E6} cond = factor[t] * np.finfo(t).eps rank = np.sum(s > cond * np.max(s)) psigma_diag = 1.0 / s[: rank] B = np.transpose(np.conjugate(np.dot(u[:, : rank] * psigma_diag, vh[: rank]))) if return_rank: return B, rank else: return B
def pinv2(a, cond=None, rcond=None, return_rank=False, check_finite=True): """ Compute the (Moore-Penrose) pseudo-inverse of a matrix. Calculate a generalized inverse of a matrix using its singular-value decomposition and including all 'large' singular values. Parameters ---------- a : array, shape (M, N) Matrix to be pseudo-inverted. cond, rcond : float or None Cutoff for 'small' singular values. Singular values smaller than ``rcond*largest_singular_value`` are considered zero. If None or -1, suitable machine precision is used. return_rank : bool, optional if True, return the effective rank of the matrix check_finite : boolean, optional Whether to check the input matrixes contain only finite numbers. Disabling may give a performance gain, but may result to problems (crashes, non-termination) if the inputs do contain infinities or NaNs. Returns ------- B : array, shape (N, M) The pseudo-inverse of matrix `a`. rank : int The effective rank of the matrix. Returned if return_rank == True Raises ------ LinAlgError If SVD computation does not converge. Examples -------- >>> a = np.random.randn(9, 6) >>> B = linalg.pinv2(a) >>> np.allclose(a, dot(a, dot(B, a))) True >>> np.allclose(B, dot(B, dot(a, B))) True """ if check_finite: a = np.asarray_chkfinite(a) else: a = np.asarray(a) u, s, vh = decomp_svd.svd(a, full_matrices=False) if rcond is not None: cond = rcond if cond in [None, -1]: t = u.dtype.char.lower() factor = {'f': 1E3, 'd': 1E6} cond = factor[t] * np.finfo(t).eps above_cutoff = (s > cond * np.max(s)) psigma_diag = np.zeros_like(s) psigma_diag[above_cutoff] = 1.0 / s[above_cutoff] B = np.transpose(np.conjugate(np.dot(u * psigma_diag, vh))) if return_rank: return B, np.sum(above_cutoff) else: return B
def signm(a, disp=True): """Matrix sign function. Extension of the scalar sign(x) to matrices. Parameters ---------- A : array, shape(M,M) Matrix at which to evaluate the sign function disp : boolean Print warning if error in the result is estimated large instead of returning estimated error. (Default: True) Returns ------- sgnA : array, shape(M,M) Value of the sign function at A (if disp == False) errest : float 1-norm of the estimated error, ||err||_1 / ||A||_1 Examples -------- >>> from scipy.linalg import signm, eigvals >>> a = [[1,2,3], [1,2,1], [1,1,1]] >>> eigvals(a) array([ 4.12488542+0.j, -0.76155718+0.j, 0.63667176+0.j]) >>> eigvals(signm(a)) array([-1.+0.j, 1.+0.j, 1.+0.j]) """ def rounded_sign(x): rx = real(x) if rx.dtype.char=='f': c = 1e3*feps*amax(x) else: c = 1e3*eps*amax(x) return sign( (absolute(rx) > c) * rx ) result,errest = funm(a, rounded_sign, disp=0) errtol = {0:1e3*feps, 1:1e3*eps}[_array_precision[result.dtype.char]] if errest < errtol: return result # Handle signm of defective matrices: # See "E.D.Denman and J.Leyva-Ramos, Appl.Math.Comp., # 8:237-250,1981" for how to improve the following (currently a # rather naive) iteration process: a = asarray(a) #a = result # sometimes iteration converges faster but where?? # Shifting to avoid zero eigenvalues. How to ensure that shifting does # not change the spectrum too much? vals = svd(a,compute_uv=0) max_sv = np.amax(vals) #min_nonzero_sv = vals[(vals>max_sv*errtol).tolist().count(1)-1] #c = 0.5/min_nonzero_sv c = 0.5/max_sv S0 = a + c*np.identity(a.shape[0]) prev_errest = errest for i in range(100): iS0 = inv(S0) S0 = 0.5*(S0 + iS0) Pp=0.5*(dot(S0,S0)+S0) errest = norm(dot(Pp,Pp)-Pp,1) if errest < errtol or prev_errest==errest: break prev_errest = errest if disp: if not isfinite(errest) or errest >= errtol: print "Result may be inaccurate, approximate err =", errest return S0 else: return S0, errest
def pinv2(a, cond=None, rcond=None, return_rank=False): """ Compute the (Moore-Penrose) pseudo-inverse of a matrix. Calculate a generalized inverse of a matrix using its singular-value decomposition and including all 'large' singular values. Parameters ---------- a : array, shape (M, N) Matrix to be pseudo-inverted. cond, rcond : float or None Cutoff for 'small' singular values. Singular values smaller than ``rcond*largest_singular_value`` are considered zero. If None or -1, suitable machine precision is used. return_rank : bool, optional if True, return the effective rank of the matrix Returns ------- B : array, shape (N, M) The pseudo-inverse of matrix `a`. rank : int The effective rank of the matrix. Returned if return_rank == True Raises ------ LinAlgError If SVD computation does not converge. Examples -------- >>> a = np.random.randn(9, 6) >>> B = linalg.pinv2(a) >>> np.allclose(a, dot(a, dot(B, a))) True >>> np.allclose(B, dot(B, dot(a, B))) True """ a = np.asarray_chkfinite(a) u, s, vh = decomp_svd.svd(a, full_matrices=False) if rcond is not None: cond = rcond if cond in [None,-1]: t = u.dtype.char.lower() factor = {'f': 1E3, 'd': 1E6} cond = factor[t] * np.finfo(t).eps above_cutoff = (s > cond * np.max(s)) psigma_diag = np.zeros_like(s) psigma_diag[above_cutoff] = 1.0 / s[above_cutoff] B = np.transpose(np.conjugate(np.dot(u * psigma_diag, vh))) if return_rank: return B, np.sum(above_cutoff) else: return B