1import numpy as np 2from numpy.linalg import LinAlgError 3from .blas import get_blas_funcs 4from .lapack import get_lapack_funcs 5 6__all__ = ['LinAlgError', 'LinAlgWarning', 'norm'] 7 8 9class LinAlgWarning(RuntimeWarning): 10 """ 11 The warning emitted when a linear algebra related operation is close 12 to fail conditions of the algorithm or loss of accuracy is expected. 13 """ 14 pass 15 16 17def norm(a, ord=None, axis=None, keepdims=False, check_finite=True): 18 """ 19 Matrix or vector norm. 20 21 This function is able to return one of eight different matrix norms, 22 or one of an infinite number of vector norms (described below), depending 23 on the value of the ``ord`` parameter. For tensors with rank different from 24 1 or 2, only `ord=None` is supported. 25 26 Parameters 27 ---------- 28 a : array_like 29 Input array. If `axis` is None, `a` must be 1-D or 2-D, unless `ord` 30 is None. If both `axis` and `ord` are None, the 2-norm of 31 ``a.ravel`` will be returned. 32 ord : {int, inf, -inf, 'fro', 'nuc', None}, optional 33 Order of the norm (see table under ``Notes``). inf means NumPy's 34 `inf` object. 35 axis : {int, 2-tuple of ints, None}, optional 36 If `axis` is an integer, it specifies the axis of `a` along which to 37 compute the vector norms. If `axis` is a 2-tuple, it specifies the 38 axes that hold 2-D matrices, and the matrix norms of these matrices 39 are computed. If `axis` is None then either a vector norm (when `a` 40 is 1-D) or a matrix norm (when `a` is 2-D) is returned. 41 keepdims : bool, optional 42 If this is set to True, the axes which are normed over are left in the 43 result as dimensions with size one. With this option the result will 44 broadcast correctly against the original `a`. 45 check_finite : bool, optional 46 Whether to check that the input matrix contains only finite numbers. 47 Disabling may give a performance gain, but may result in problems 48 (crashes, non-termination) if the inputs do contain infinities or NaNs. 49 50 Returns 51 ------- 52 n : float or ndarray 53 Norm of the matrix or vector(s). 54 55 Notes 56 ----- 57 For values of ``ord <= 0``, the result is, strictly speaking, not a 58 mathematical 'norm', but it may still be useful for various numerical 59 purposes. 60 61 The following norms can be calculated: 62 63 ===== ============================ ========================== 64 ord norm for matrices norm for vectors 65 ===== ============================ ========================== 66 None Frobenius norm 2-norm 67 'fro' Frobenius norm -- 68 'nuc' nuclear norm -- 69 inf max(sum(abs(a), axis=1)) max(abs(a)) 70 -inf min(sum(abs(a), axis=1)) min(abs(a)) 71 0 -- sum(a != 0) 72 1 max(sum(abs(a), axis=0)) as below 73 -1 min(sum(abs(a), axis=0)) as below 74 2 2-norm (largest sing. value) as below 75 -2 smallest singular value as below 76 other -- sum(abs(a)**ord)**(1./ord) 77 ===== ============================ ========================== 78 79 The Frobenius norm is given by [1]_: 80 81 :math:`||A||_F = [\\sum_{i,j} abs(a_{i,j})^2]^{1/2}` 82 83 The nuclear norm is the sum of the singular values. 84 85 Both the Frobenius and nuclear norm orders are only defined for 86 matrices. 87 88 References 89 ---------- 90 .. [1] G. H. Golub and C. F. Van Loan, *Matrix Computations*, 91 Baltimore, MD, Johns Hopkins University Press, 1985, pg. 15 92 93 Examples 94 -------- 95 >>> from scipy.linalg import norm 96 >>> a = np.arange(9) - 4.0 97 >>> a 98 array([-4., -3., -2., -1., 0., 1., 2., 3., 4.]) 99 >>> b = a.reshape((3, 3)) 100 >>> b 101 array([[-4., -3., -2.], 102 [-1., 0., 1.], 103 [ 2., 3., 4.]]) 104 105 >>> norm(a) 106 7.745966692414834 107 >>> norm(b) 108 7.745966692414834 109 >>> norm(b, 'fro') 110 7.745966692414834 111 >>> norm(a, np.inf) 112 4 113 >>> norm(b, np.inf) 114 9 115 >>> norm(a, -np.inf) 116 0 117 >>> norm(b, -np.inf) 118 2 119 120 >>> norm(a, 1) 121 20 122 >>> norm(b, 1) 123 7 124 >>> norm(a, -1) 125 -4.6566128774142013e-010 126 >>> norm(b, -1) 127 6 128 >>> norm(a, 2) 129 7.745966692414834 130 >>> norm(b, 2) 131 7.3484692283495345 132 133 >>> norm(a, -2) 134 0 135 >>> norm(b, -2) 136 1.8570331885190563e-016 137 >>> norm(a, 3) 138 5.8480354764257312 139 >>> norm(a, -3) 140 0 141 142 """ 143 # Differs from numpy only in non-finite handling and the use of blas. 144 if check_finite: 145 a = np.asarray_chkfinite(a) 146 else: 147 a = np.asarray(a) 148 149 if a.size and a.dtype.char in 'fdFD' and axis is None and not keepdims: 150 151 if ord in (None, 2) and (a.ndim == 1): 152 # use blas for fast and stable euclidean norm 153 nrm2 = get_blas_funcs('nrm2', dtype=a.dtype, ilp64='preferred') 154 return nrm2(a) 155 156 if a.ndim == 2: 157 # Use lapack for a couple fast matrix norms. 158 # For some reason the *lange frobenius norm is slow. 159 lange_args = None 160 # Make sure this works if the user uses the axis keywords 161 # to apply the norm to the transpose. 162 if ord == 1: 163 if np.isfortran(a): 164 lange_args = '1', a 165 elif np.isfortran(a.T): 166 lange_args = 'i', a.T 167 elif ord == np.inf: 168 if np.isfortran(a): 169 lange_args = 'i', a 170 elif np.isfortran(a.T): 171 lange_args = '1', a.T 172 if lange_args: 173 lange = get_lapack_funcs('lange', dtype=a.dtype, ilp64='preferred') 174 return lange(*lange_args) 175 176 # fall back to numpy in every other case 177 return np.linalg.norm(a, ord=ord, axis=axis, keepdims=keepdims) 178 179 180def _datacopied(arr, original): 181 """ 182 Strict check for `arr` not sharing any data with `original`, 183 under the assumption that arr = asarray(original) 184 185 """ 186 if arr is original: 187 return False 188 if not isinstance(original, np.ndarray) and hasattr(original, '__array__'): 189 return False 190 return arr.base is None 191