def lstsq(a, b, cond=None, overwrite_a=0, overwrite_b=0): """ lstsq(a, b, cond=None, overwrite_a=0, overwrite_b=0) -> x,resids,rank,s Return least-squares solution of a * x = b. Inputs: a -- An M x N matrix. b -- An M x nrhs matrix or M vector. cond -- Used to determine effective rank of a. Outputs: x -- The solution (N x nrhs matrix) to the minimization problem: 2-norm(| b - a * x |) -> min resids -- The residual sum-of-squares for the solution matrix x (only if M>N and rank==N). rank -- The effective rank of a. s -- Singular values of a in decreasing order. The condition number of a is abs(s[0]/s[-1]). """ a1, b1 = map(asarray_chkfinite,(a,b)) if len(a1.shape) != 2: raise ValueError, 'expected matrix' m,n = a1.shape if len(b1.shape)==2: nrhs = b1.shape[1] else: nrhs = 1 if m != b1.shape[0]: raise ValueError, 'incompatible dimensions' gelss, = get_lapack_funcs(('gelss',),(a1,b1)) if n>m: # need to extend b matrix as it will be filled with # a larger solution matrix b2 = zeros((n,nrhs), dtype=gelss.dtype) if len(b1.shape)==2: b2[:m,:] = b1 else: b2[:m,0] = b1 b1 = b2 overwrite_a = overwrite_a or (a1 is not a and not hasattr(a,'__array__')) overwrite_b = overwrite_b or (b1 is not b and not hasattr(b,'__array__')) if gelss.module_name[:7] == 'flapack': lwork = calc_lwork.gelss(gelss.prefix,m,n,nrhs)[1] v,x,s,rank,info = gelss(a1,b1,cond = cond, lwork = lwork, overwrite_a = overwrite_a, overwrite_b = overwrite_b) else: raise NotImplementedError,'calling gelss from %s' % (gelss.module_name) if info>0: raise LinAlgError, "SVD did not converge in Linear Least Squares" if info<0: raise ValueError,\ 'illegal value in %-th argument of internal gelss'%(-info) resids = asarray([], dtype=x.dtype) if n<m: x1 = x[:n] if rank==n: resids = sum(x[n:]**2,axis=0) x = x1 return x,resids,rank,s
def lstsq(a, b, cond=None, overwrite_a=0, overwrite_b=0): """Compute least-squares solution to equation :m:`a x = b` Compute a vector x such that the 2-norm :m:`|b - a x|` is minimised. Parameters ---------- a : array, shape (M, N) b : array, shape (M,) or (M, K) cond : float Cutoff for 'small' singular values; used to determine effective rank of a. Singular values smaller than rcond*largest_singular_value are considered zero. overwrite_a : boolean Discard data in a (may enhance performance) overwrite_b : boolean Discard data in b (may enhance performance) Returns ------- x : array, shape (N,) or (N, K) depending on shape of b Least-squares solution residues : array, shape () or (1,) or (K,) Sums of residues, squared 2-norm for each column in :m:`b - a x` If rank of matrix a is < N or > M this is an empty array. If b was 1-d, this is an (1,) shape array, otherwise the shape is (K,) rank : integer Effective rank of matrix a s : array, shape (min(M,N),) Singular values of a. The condition number of a is abs(s[0]/s[-1]). Raises LinAlgError if computation does not converge """ a1, b1 = lmap(asarray_chkfinite, (a, b)) if a1.ndim != 2: raise ValueError('expected matrix') m, n = a1.shape if b1.ndim == 2: nrhs = b1.shape[1] else: nrhs = 1 if m != b1.shape[0]: raise ValueError('incompatible dimensions') gelss, = get_lapack_funcs(('gelss',), (a1, b1)) if n > m: # need to extend b matrix as it will be filled with # a larger solution matrix b2 = zeros((n, nrhs), dtype=gelss.dtype) if b1.ndim == 2: b2[:m, :] = b1 else: b2[:m, 0] = b1 b1 = b2 overwrite_a = overwrite_a or (a1 is not a and not hasattr(a, '__array__')) overwrite_b = overwrite_b or (b1 is not b and not hasattr(b, '__array__')) if gelss.module_name[:7] == 'flapack': lwork = calc_lwork.gelss(gelss.prefix, m, n, nrhs)[1] v, x, s, rank, info = gelss(a1, b1, cond=cond, lwork=lwork, overwrite_a=overwrite_a, overwrite_b=overwrite_b) else: raise NotImplementedError('calling gelss from %s' % gelss.module_name) if info > 0: raise LinAlgError("SVD did not converge in Linear Least Squares") if info < 0: raise ValueError('illegal value in %-th argument of ' 'internal gelss' % -info) resids = asarray([], dtype=x.dtype) if n < m: x1 = x[:n] if rank == n: resids = sum(x[n:]**2, axis=0) x = x1 return x, resids, rank, s
def lstsq(a, b, cond=None, overwrite_a=False, overwrite_b=False): """ Compute least-squares solution to equation Ax = b. Compute a vector x such that the 2-norm ``|b - A x|`` is minimized. Parameters ---------- a : array, shape (M, N) Left hand side matrix (2-D array). b : array, shape (M,) or (M, K) Right hand side matrix or vector (1-D or 2-D array). cond : float, optional Cutoff for 'small' singular values; used to determine effective rank of a. Singular values smaller than ``rcond * largest_singular_value`` are considered zero. overwrite_a : bool, optional Discard data in `a` (may enhance performance). Default is False. overwrite_b : bool, optional Discard data in `b` (may enhance performance). Default is False. Returns ------- x : array, shape (N,) or (N, K) depending on shape of b Least-squares solution. residues : ndarray, shape () or (1,) or (K,) Sums of residues, squared 2-norm for each column in ``b - a x``. If rank of matrix a is < N or > M this is an empty array. If b was 1-D, this is an (1,) shape array, otherwise the shape is (K,). rank : int Effective rank of matrix `a`. s : array, shape (min(M,N),) Singular values of `a`. The condition number of a is ``abs(s[0]/s[-1])``. Raises ------ LinAlgError : If computation does not converge. See Also -------- optimize.nnls : linear least squares with non-negativity constraint """ a1, b1 = map(asarray_chkfinite, (a, b)) if len(a1.shape) != 2: raise ValueError('expected matrix') m, n = a1.shape if len(b1.shape) == 2: nrhs = b1.shape[1] else: nrhs = 1 if m != b1.shape[0]: raise ValueError('incompatible dimensions') gelss, = get_lapack_funcs(('gelss', ), (a1, b1)) gelss_info = get_func_info(gelss) if n > m: # need to extend b matrix as it will be filled with # a larger solution matrix b2 = zeros((n, nrhs), dtype=gelss_info.dtype) if len(b1.shape) == 2: b2[:m, :] = b1 else: b2[:m, 0] = b1 b1 = b2 overwrite_a = overwrite_a or _datacopied(a1, a) overwrite_b = overwrite_b or _datacopied(b1, b) if gelss_info.module_name[:7] == 'flapack': lwork = calc_lwork.gelss(gelss_info.prefix, m, n, nrhs)[1] v, x, s, rank, info = gelss(a1, b1, cond=cond, lwork=lwork, overwrite_a=overwrite_a, overwrite_b=overwrite_b) else: raise NotImplementedError('calling gelss from %s' % get_func_info(gelss).module_name) if info > 0: raise LinAlgError("SVD did not converge in Linear Least Squares") if info < 0: raise ValueError('illegal value in %d-th argument of internal gelss' % -info) resids = asarray([], dtype=x.dtype) if n < m: x1 = x[:n] if rank == n: resids = sum(abs(x[n:])**2, axis=0) x = x1 return x, resids, rank, s
def lstsq(a, b, cond=None, overwrite_a=False, overwrite_b=False): """ Compute least-squares solution to equation Ax = b. Compute a vector x such that the 2-norm ``|b - A x|`` is minimized. Parameters ---------- a : array, shape (M, N) Left hand side matrix (2-D array). b : array, shape (M,) or (M, K) Right hand side matrix or vector (1-D or 2-D array). cond : float, optional Cutoff for 'small' singular values; used to determine effective rank of a. Singular values smaller than ``rcond * largest_singular_value`` are considered zero. overwrite_a : bool, optional Discard data in `a` (may enhance performance). Default is False. overwrite_b : bool, optional Discard data in `b` (may enhance performance). Default is False. Returns ------- x : array, shape (N,) or (N, K) depending on shape of b Least-squares solution. residues : ndarray, shape () or (1,) or (K,) Sums of residues, squared 2-norm for each column in ``b - a x``. If rank of matrix a is < N or > M this is an empty array. If b was 1-D, this is an (1,) shape array, otherwise the shape is (K,). rank : int Effective rank of matrix `a`. s : array, shape (min(M,N),) Singular values of `a`. The condition number of a is ``abs(s[0]/s[-1])``. Raises ------ LinAlgError : If computation does not converge. See Also -------- optimize.nnls : linear least squares with non-negativity constraint """ a1, b1 = map(asarray_chkfinite, (a, b)) if len(a1.shape) != 2: raise ValueError('expected matrix') m, n = a1.shape if len(b1.shape) == 2: nrhs = b1.shape[1] else: nrhs = 1 if m != b1.shape[0]: raise ValueError('incompatible dimensions') gelss, = get_lapack_funcs(('gelss',), (a1, b1)) if n > m: # need to extend b matrix as it will be filled with # a larger solution matrix b2 = zeros((n, nrhs), dtype=gelss.dtype) if len(b1.shape) == 2: b2[:m,:] = b1 else: b2[:m,0] = b1 b1 = b2 overwrite_a = overwrite_a or (a1 is not a and not hasattr(a,'__array__')) overwrite_b = overwrite_b or (b1 is not b and not hasattr(b,'__array__')) if gelss.module_name[:7] == 'flapack': lwork = calc_lwork.gelss(gelss.prefix, m, n, nrhs)[1] v, x, s, rank, info = gelss(a1, b1, cond=cond, lwork=lwork, overwrite_a=overwrite_a, overwrite_b=overwrite_b) else: raise NotImplementedError('calling gelss from %s' % gelss.module_name) if info > 0: raise LinAlgError("SVD did not converge in Linear Least Squares") if info < 0: raise ValueError('illegal value in %d-th argument of internal gelss' % -info) resids = asarray([], dtype=x.dtype) if n < m: x1 = x[:n] if rank == n: resids = sum(abs(x[n:])**2, axis=0) x = x1 return x, resids, rank, s
def lstsq(a, b, cond=None, overwrite_a=0, overwrite_b=0): """Compute least-squares solution to equation :m:`a x = b` Compute a vector x such that the 2-norm :m:`|b - a x|` is minimised. Parameters ---------- a : array, shape (M, N) b : array, shape (M,) or (M, K) cond : float Cutoff for 'small' singular values; used to determine effective rank of a. Singular values smaller than rcond*largest_singular_value are considered zero. overwrite_a : boolean Discard data in a (may enhance performance) overwrite_b : boolean Discard data in b (may enhance performance) Returns ------- x : array, shape (N,) or (N, K) depending on shape of b Least-squares solution residues : array, shape () or (1,) or (K,) Sums of residues, squared 2-norm for each column in :m:`b - a x` If rank of matrix a is < N or > M this is an empty array. If b was 1-d, this is an (1,) shape array, otherwise the shape is (K,) rank : integer Effective rank of matrix a s : array, shape (min(M,N),) Singular values of a. The condition number of a is abs(s[0]/s[-1]). Raises LinAlgError if computation does not converge """ a1, b1 = map(asarray_chkfinite, (a, b)) if len(a1.shape) != 2: raise ValueError, 'expected matrix' m, n = a1.shape if len(b1.shape) == 2: nrhs = b1.shape[1] else: nrhs = 1 if m != b1.shape[0]: raise ValueError, 'incompatible dimensions' gelss, = get_lapack_funcs(('gelss', ), (a1, b1)) if n > m: # need to extend b matrix as it will be filled with # a larger solution matrix b2 = zeros((n, nrhs), dtype=gelss.dtype) if len(b1.shape) == 2: b2[:m, :] = b1 else: b2[:m, 0] = b1 b1 = b2 overwrite_a = overwrite_a or (a1 is not a and not hasattr(a, '__array__')) overwrite_b = overwrite_b or (b1 is not b and not hasattr(b, '__array__')) if gelss.module_name[:7] == 'flapack': lwork = calc_lwork.gelss(gelss.prefix, m, n, nrhs)[1] v, x, s, rank, info = gelss(a1, b1, cond=cond, lwork=lwork, overwrite_a=overwrite_a, overwrite_b=overwrite_b) else: raise NotImplementedError, 'calling gelss from %s' % ( gelss.module_name) if info > 0: raise LinAlgError, "SVD did not converge in Linear Least Squares" if info < 0: raise ValueError,\ 'illegal value in %-th argument of internal gelss'%(-info) resids = asarray([], dtype=x.dtype) if n < m: x1 = x[:n] if rank == n: resids = sum(x[n:]**2, axis=0) x = x1 return x, resids, rank, s
def pinv_array(a, cond=None): """Calculate the Moore-Penrose pseudo inverse of each block of the three dimensional array a. Parameters ---------- a : {dense array} Is of size (n, m, m) cond : {float} Used by *gelss to filter numerically zeros singular values. If None, a suitable value is chosen for you. Returns ------- Nothing, a is modified in place so that a[k] holds the pseudoinverse of that block. Notes ----- By using lapack wrappers, this can be much faster for large n, than directly calling pinv2 Examples -------- >>> import numpy as np >>> from pyamg.util.linalg import pinv_array >>> a = np.array([[[1.,2.],[1.,1.]], [[1.,1.],[3.,3.]]]) >>> ac = a.copy() >>> # each block of a is inverted in-place >>> pinv_array(a) """ n = a.shape[0] m = a.shape[1] if m == 1: # Pseudo-inverse of 1 x 1 matrices is trivial zero_entries = (a == 0.0).nonzero()[0] a[zero_entries] = 1.0 a[:] = 1.0/a a[zero_entries] = 0.0 del zero_entries else: # The block size is greater than 1 # Create necessary arrays and function pointers for calculating pinv gelss, = get_lapack_funcs(('gelss',), (np.ones((1,), dtype=a.dtype))) RHS = np.eye(m, dtype=a.dtype) lwork = calc_lwork.gelss(gelss.prefix, m, m, m)[1] # Choose tolerance for which singular values are zero in *gelss below if cond is None: t = a.dtype.char eps = np.finfo(np.float).eps feps = np.finfo(np.single).eps geps = np.finfo(np.longfloat).eps _array_precision = {'f': 0, 'd': 1, 'g': 2, 'F': 0, 'D': 1, 'G': 2} cond = {0: feps*1e3, 1: eps*1e6, 2: geps*1e6}[_array_precision[t]] # Invert each block of a for kk in range(n): gelssoutput = gelss(a[kk], RHS, cond=cond, lwork=lwork, overwrite_a=True, overwrite_b=False) a[kk] = gelssoutput[1]
def pinv_array(a, cond=None): """Calculate the Moore-Penrose pseudo inverse of each block of the three dimensional array a. Parameters ---------- a : {dense array} Is of size (n, m, m) cond : {float} Used by *gelss to filter numerically zeros singular values. If None, a suitable value is chosen for you. Returns ------- Nothing, a is modified in place so that a[k] holds the pseudoinverse of that block. Notes ----- By using lapack wrappers, this can be much faster for large n, than directly calling pinv2 Examples -------- >>> import numpy as np >>> from pyamg.util.linalg import pinv_array >>> a = np.array([[[1.,2.],[1.,1.]], [[1.,1.],[3.,3.]]]) >>> ac = a.copy() >>> # each block of a is inverted in-place >>> pinv_array(a) """ n = a.shape[0] m = a.shape[1] if m == 1: # Pseudo-inverse of 1 x 1 matrices is trivial zero_entries = (a == 0.0).nonzero()[0] a[zero_entries] = 1.0 a[:] = 1.0 / a a[zero_entries] = 0.0 del zero_entries else: # The block size is greater than 1 # Create necessary arrays and function pointers for calculating pinv gelss, = get_lapack_funcs(('gelss', ), (np.ones((1, ), dtype=a.dtype))) RHS = np.eye(m, dtype=a.dtype) lwork = calc_lwork.gelss(gelss.prefix, m, m, m)[1] # Choose tolerance for which singular values are zero in *gelss below if cond is None: t = a.dtype.char eps = np.finfo(np.float).eps feps = np.finfo(np.single).eps geps = np.finfo(np.longfloat).eps _array_precision = {'f': 0, 'd': 1, 'g': 2, 'F': 0, 'D': 1, 'G': 2} cond = { 0: feps * 1e3, 1: eps * 1e6, 2: geps * 1e6 }[_array_precision[t]] # Invert each block of a for kk in range(n): gelssoutput = gelss(a[kk], RHS, cond=cond, lwork=lwork, overwrite_a=True, overwrite_b=False) a[kk] = gelssoutput[1]