Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/scipy/sparse/linalg/_norm.py: 11%
74 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
1"""Sparse matrix norms.
3"""
4import numpy as np
5from scipy.sparse import issparse
6from scipy.sparse.linalg import svds
7import scipy.sparse as sp
9from numpy import Inf, sqrt, abs
11__all__ = ['norm']
14def _sparse_frobenius_norm(x):
15 data = sp._sputils._todata(x)
16 return np.linalg.norm(data)
19def norm(x, ord=None, axis=None):
20 """
21 Norm of a sparse matrix
23 This function is able to return one of seven different matrix norms,
24 depending on the value of the ``ord`` parameter.
26 Parameters
27 ----------
28 x : a sparse matrix
29 Input sparse matrix.
30 ord : {non-zero int, inf, -inf, 'fro'}, optional
31 Order of the norm (see table under ``Notes``). inf means numpy's
32 `inf` object.
33 axis : {int, 2-tuple of ints, None}, optional
34 If `axis` is an integer, it specifies the axis of `x` along which to
35 compute the vector norms. If `axis` is a 2-tuple, it specifies the
36 axes that hold 2-D matrices, and the matrix norms of these matrices
37 are computed. If `axis` is None then either a vector norm (when `x`
38 is 1-D) or a matrix norm (when `x` is 2-D) is returned.
40 Returns
41 -------
42 n : float or ndarray
44 Notes
45 -----
46 Some of the ord are not implemented because some associated functions like,
47 _multi_svd_norm, are not yet available for sparse matrix.
49 This docstring is modified based on numpy.linalg.norm.
50 https://github.com/numpy/numpy/blob/main/numpy/linalg/linalg.py
52 The following norms can be calculated:
54 ===== ============================
55 ord norm for sparse matrices
56 ===== ============================
57 None Frobenius norm
58 'fro' Frobenius norm
59 inf max(sum(abs(x), axis=1))
60 -inf min(sum(abs(x), axis=1))
61 0 abs(x).sum(axis=axis)
62 1 max(sum(abs(x), axis=0))
63 -1 min(sum(abs(x), axis=0))
64 2 Spectral norm (the largest singular value)
65 -2 Not implemented
66 other Not implemented
67 ===== ============================
69 The Frobenius norm is given by [1]_:
71 :math:`||A||_F = [\\sum_{i,j} abs(a_{i,j})^2]^{1/2}`
73 References
74 ----------
75 .. [1] G. H. Golub and C. F. Van Loan, *Matrix Computations*,
76 Baltimore, MD, Johns Hopkins University Press, 1985, pg. 15
78 Examples
79 --------
80 >>> from scipy.sparse import *
81 >>> import numpy as np
82 >>> from scipy.sparse.linalg import norm
83 >>> a = np.arange(9) - 4
84 >>> a
85 array([-4, -3, -2, -1, 0, 1, 2, 3, 4])
86 >>> b = a.reshape((3, 3))
87 >>> b
88 array([[-4, -3, -2],
89 [-1, 0, 1],
90 [ 2, 3, 4]])
92 >>> b = csr_matrix(b)
93 >>> norm(b)
94 7.745966692414834
95 >>> norm(b, 'fro')
96 7.745966692414834
97 >>> norm(b, np.inf)
98 9
99 >>> norm(b, -np.inf)
100 2
101 >>> norm(b, 1)
102 7
103 >>> norm(b, -1)
104 6
106 The matrix 2-norm or the spectral norm is the largest singular
107 value, computed approximately and with limitations.
109 >>> b = diags([-1, 1], [0, 1], shape=(9, 10))
110 >>> norm(b, 2)
111 1.9753...
112 """
113 if not issparse(x):
114 raise TypeError("input is not sparse. use numpy.linalg.norm")
116 # Check the default case first and handle it immediately.
117 if axis is None and ord in (None, 'fro', 'f'):
118 return _sparse_frobenius_norm(x)
120 # Some norms require functions that are not implemented for all types.
121 x = x.tocsr()
123 if axis is None:
124 axis = (0, 1)
125 elif not isinstance(axis, tuple):
126 msg = "'axis' must be None, an integer or a tuple of integers"
127 try:
128 int_axis = int(axis)
129 except TypeError as e:
130 raise TypeError(msg) from e
131 if axis != int_axis:
132 raise TypeError(msg)
133 axis = (int_axis,)
135 nd = 2
136 if len(axis) == 2:
137 row_axis, col_axis = axis
138 if not (-nd <= row_axis < nd and -nd <= col_axis < nd):
139 raise ValueError('Invalid axis %r for an array with shape %r' %
140 (axis, x.shape))
141 if row_axis % nd == col_axis % nd:
142 raise ValueError('Duplicate axes given.')
143 if ord == 2:
144 # Only solver="lobpcg" supports all numpy dtypes
145 _, s, _ = svds(x, k=1, solver="lobpcg")
146 return s[0]
147 elif ord == -2:
148 raise NotImplementedError
149 #return _multi_svd_norm(x, row_axis, col_axis, amin)
150 elif ord == 1:
151 return abs(x).sum(axis=row_axis).max(axis=col_axis)[0,0]
152 elif ord == Inf:
153 return abs(x).sum(axis=col_axis).max(axis=row_axis)[0,0]
154 elif ord == -1:
155 return abs(x).sum(axis=row_axis).min(axis=col_axis)[0,0]
156 elif ord == -Inf:
157 return abs(x).sum(axis=col_axis).min(axis=row_axis)[0,0]
158 elif ord in (None, 'f', 'fro'):
159 # The axis order does not matter for this norm.
160 return _sparse_frobenius_norm(x)
161 else:
162 raise ValueError("Invalid norm order for matrices.")
163 elif len(axis) == 1:
164 a, = axis
165 if not (-nd <= a < nd):
166 raise ValueError('Invalid axis %r for an array with shape %r' %
167 (axis, x.shape))
168 if ord == Inf:
169 M = abs(x).max(axis=a)
170 elif ord == -Inf:
171 M = abs(x).min(axis=a)
172 elif ord == 0:
173 # Zero norm
174 M = (x != 0).sum(axis=a)
175 elif ord == 1:
176 # special case for speedup
177 M = abs(x).sum(axis=a)
178 elif ord in (2, None):
179 M = sqrt(abs(x).power(2).sum(axis=a))
180 else:
181 try:
182 ord + 1
183 except TypeError as e:
184 raise ValueError('Invalid norm order for vectors.') from e
185 M = np.power(abs(x).power(ord).sum(axis=a), 1 / ord)
186 if hasattr(M, 'toarray'):
187 return M.toarray().ravel()
188 elif hasattr(M, 'A'):
189 return M.A.ravel()
190 else:
191 return M.ravel()
192 else:
193 raise ValueError("Improper number of dimensions to norm.")