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

1"""Sparse matrix norms. 

2 

3""" 

4import numpy as np 

5from scipy.sparse import issparse 

6from scipy.sparse.linalg import svds 

7import scipy.sparse as sp 

8 

9from numpy import Inf, sqrt, abs 

10 

11__all__ = ['norm'] 

12 

13 

14def _sparse_frobenius_norm(x): 

15 data = sp._sputils._todata(x) 

16 return np.linalg.norm(data) 

17 

18 

19def norm(x, ord=None, axis=None): 

20 """ 

21 Norm of a sparse matrix 

22 

23 This function is able to return one of seven different matrix norms, 

24 depending on the value of the ``ord`` parameter. 

25 

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. 

39 

40 Returns 

41 ------- 

42 n : float or ndarray 

43 

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. 

48 

49 This docstring is modified based on numpy.linalg.norm. 

50 https://github.com/numpy/numpy/blob/main/numpy/linalg/linalg.py 

51 

52 The following norms can be calculated: 

53 

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 ===== ============================ 

68 

69 The Frobenius norm is given by [1]_: 

70 

71 :math:`||A||_F = [\\sum_{i,j} abs(a_{i,j})^2]^{1/2}` 

72 

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 

77 

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]]) 

91 

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 

105 

106 The matrix 2-norm or the spectral norm is the largest singular 

107 value, computed approximately and with limitations. 

108 

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") 

115 

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) 

119 

120 # Some norms require functions that are not implemented for all types. 

121 x = x.tocsr() 

122 

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,) 

134 

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.")