Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 566 lines (436 sloc) 18.851 kB
8bdf044 updated sparse docstrings
wnbell authored
1 """Compressed Block Sparse Row matrix format"""
5f4c579 @pv MAINT: add relevant from __future__ import to all files
pv authored
2 from __future__ import division, print_function, absolute_import
3
7838d22 add bsr_matrix format
wnbell authored
4
4e0da1a updated sparse docstrings
wnbell authored
5 __docformat__ = "restructuredtext en"
6
7838d22 add bsr_matrix format
wnbell authored
7 __all__ = ['bsr_matrix', 'isspmatrix_bsr']
8
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
9 from warnings import warn
10
bd2650c cleaned up bsr_matrix imports
wnbell authored
11 import numpy as np
12
e680e5f @larsmans ENH: sparse: min and max methods on matrices with .data, except dia
larsmans authored
13 from .data import _data_matrix, _minmax_mixin
3add620 @pv MAINT: Automated 2to3 conversion of the code base
pv authored
14 from .compressed import _cs_matrix
15 from .base import isspmatrix, _formats
16 from .sputils import isshape, getdtype, to_native, upcast
17 from . import sparsetools
18 from .sparsetools import bsr_matvec, bsr_matvecs, csr_matmat_pass1, \
8bf603b Removed unused imports.
Alan McIntyre authored
19 bsr_matmat_pass2, bsr_transpose, bsr_sort_indices
7838d22 add bsr_matrix format
wnbell authored
20
5d565c0 @timleslie PEP8: Fix E302 expected 2 blank lines, found 1
timleslie authored
21
e680e5f @larsmans ENH: sparse: min and max methods on matrices with .data, except dia
larsmans authored
22 class bsr_matrix(_cs_matrix, _minmax_mixin):
36d6938 added bsr_matrix docstring
wnbell authored
23 """Block Sparse Row matrix
24
25 This can be instantiated in several ways:
4e0da1a updated sparse docstrings
wnbell authored
26 bsr_matrix(D, [blocksize=(R,C)])
27 with a dense matrix or rank-2 ndarray D
36d6938 added bsr_matrix docstring
wnbell authored
28
4e0da1a updated sparse docstrings
wnbell authored
29 bsr_matrix(S, [blocksize=(R,C)])
30 with another sparse matrix S (equivalent to S.tobsr())
36d6938 added bsr_matrix docstring
wnbell authored
31
4e0da1a updated sparse docstrings
wnbell authored
32 bsr_matrix((M, N), [blocksize=(R,C), dtype])
33 to construct an empty matrix with shape (M, N)
34 dtype is optional, defaulting to dtype='d'.
36d6938 added bsr_matrix docstring
wnbell authored
35
4e0da1a updated sparse docstrings
wnbell authored
36 bsr_matrix((data, ij), [blocksize=(R,C), shape=(M, N)])
37 where ``data`` and ``ij`` satisfy ``a[ij[0, k], ij[1, k]] = data[k]``
36d6938 added bsr_matrix docstring
wnbell authored
38
4e0da1a updated sparse docstrings
wnbell authored
39 bsr_matrix((data, indices, indptr), [shape=(M, N)])
e835bd3 @jarrodmillman ran reindent
jarrodmillman authored
40 is the standard BSR representation where the block column
1d6ddd3 @WarrenWeckesser DOC: sparse: fix csr_matrix and bsr_matrix docstrings.
WarrenWeckesser authored
41 indices for row i are stored in ``indices[indptr[i]:indptr[i+1]]``
e835bd3 @jarrodmillman ran reindent
jarrodmillman authored
42 and their corresponding block values are stored in
4e0da1a updated sparse docstrings
wnbell authored
43 ``data[ indptr[i]: indptr[i+1] ]``. If the shape parameter is not
44 supplied, the matrix dimensions are inferred from the index arrays.
36d6938 added bsr_matrix docstring
wnbell authored
45
d19c963 @pv DOC: sparse: document attributes of the sparse matrices, and mention …
pv authored
46 Attributes
47 ----------
48 dtype : dtype
49 Data type of the matrix
50 shape : 2-tuple
51 Shape of the matrix
52 ndim : int
53 Number of dimensions (this is always 2)
54 nnz
55 Number of nonzero elements
56 data
57 Data array of the matrix
58 indices
59 BSR format index array
60 indptr
61 BSR format index pointer array
62 blocksize
63 Block size of the matrix
64 has_sorted_indices
65 Whether indices are sorted
66
8bdf044 updated sparse docstrings
wnbell authored
67 Notes
4e0da1a updated sparse docstrings
wnbell authored
68 -----
d19c963 @pv DOC: sparse: document attributes of the sparse matrices, and mention …
pv authored
69 Sparse matrices can be used in arithmetic operations: they support
70 addition, subtraction, multiplication, division, and matrix power.
71
a36f106 @rgommers MAINT: fix more Sphinx issues.
rgommers authored
72 **Summary of BSR format**
d19c963 @pv DOC: sparse: document attributes of the sparse matrices, and mention …
pv authored
73
a36f106 @rgommers MAINT: fix more Sphinx issues.
rgommers authored
74 The Block Compressed Row (BSR) format is very similar to the Compressed
75 Sparse Row (CSR) format. BSR is appropriate for sparse matrices with dense
76 sub matrices like the last example below. Block matrices often arise in
77 vector-valued finite element discretizations. In such cases, BSR is
78 considerably more efficient than CSR and CSC for many sparse arithmetic
79 operations.
4e0da1a updated sparse docstrings
wnbell authored
80
a36f106 @rgommers MAINT: fix more Sphinx issues.
rgommers authored
81 **Blocksize**
e835bd3 @jarrodmillman ran reindent
jarrodmillman authored
82
a36f106 @rgommers MAINT: fix more Sphinx issues.
rgommers authored
83 The blocksize (R,C) must evenly divide the shape of the matrix (M,N).
84 That is, R and C must satisfy the relationship ``M % R = 0`` and
85 ``N % C = 0``.
36d6938 added bsr_matrix docstring
wnbell authored
86
a36f106 @rgommers MAINT: fix more Sphinx issues.
rgommers authored
87 If no blocksize is specified, a simple heuristic is applied to determine
88 an appropriate blocksize.
36d6938 added bsr_matrix docstring
wnbell authored
89
8bdf044 updated sparse docstrings
wnbell authored
90 Examples
4e0da1a updated sparse docstrings
wnbell authored
91 --------
a36f106 @rgommers MAINT: fix more Sphinx issues.
rgommers authored
92 >>> from scipy.sparse import bsr_matrix
93 >>> bsr_matrix((3,4), dtype=np.int8).todense()
36d6938 added bsr_matrix docstring
wnbell authored
94 matrix([[0, 0, 0, 0],
95 [0, 0, 0, 0],
93f47f7 make doctests work the same on 32/64-bit platforms
wnbell authored
96 [0, 0, 0, 0]], dtype=int8)
36d6938 added bsr_matrix docstring
wnbell authored
97
a36f106 @rgommers MAINT: fix more Sphinx issues.
rgommers authored
98 >>> row = np.array([0,0,1,2,2,2])
99 >>> col = np.array([0,2,2,0,1,2])
100 >>> data = np.array([1,2,3,4,5,6])
101 >>> bsr_matrix((data, (row,col)), shape=(3,3)).todense()
36d6938 added bsr_matrix docstring
wnbell authored
102 matrix([[1, 0, 2],
103 [0, 0, 3],
104 [4, 5, 6]])
e835bd3 @jarrodmillman ran reindent
jarrodmillman authored
105
a36f106 @rgommers MAINT: fix more Sphinx issues.
rgommers authored
106 >>> indptr = np.array([0,2,3,6])
107 >>> indices = np.array([0,2,2,0,1,2])
108 >>> data = np.array([1,2,3,4,5,6]).repeat(4).reshape(6,2,2)
109 >>> bsr_matrix((data,indices,indptr), shape=(6,6)).todense()
36d6938 added bsr_matrix docstring
wnbell authored
110 matrix([[1, 1, 0, 0, 2, 2],
111 [1, 1, 0, 0, 2, 2],
112 [0, 0, 0, 0, 3, 3],
113 [0, 0, 0, 0, 3, 3],
114 [4, 4, 5, 5, 6, 6],
115 [4, 4, 5, 5, 6, 6]])
e835bd3 @jarrodmillman ran reindent
jarrodmillman authored
116
36d6938 added bsr_matrix docstring
wnbell authored
117 """
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
118 def __init__(self, arg1, shape=None, dtype=None, copy=False, blocksize=None):
119 _data_matrix.__init__(self)
120
121 if isspmatrix(arg1):
bd2650c cleaned up bsr_matrix imports
wnbell authored
122 if isspmatrix_bsr(arg1) and copy:
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
123 arg1 = arg1.copy()
124 else:
bd2650c cleaned up bsr_matrix imports
wnbell authored
125 arg1 = arg1.tobsr(blocksize=blocksize)
6e4ecd9 @timleslie PEP8: Fix E202 whitespace before ')'
timleslie authored
126 self._set_self(arg1)
e835bd3 @jarrodmillman ran reindent
jarrodmillman authored
127
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
128 elif isinstance(arg1,tuple):
129 if isshape(arg1):
6f9f01d @timleslie PEP8: Fix E261 at least two spaces before inline comment
timleslie authored
130 # it's a tuple of matrix dimensions (M,N)
bfda3d8 @timleslie PEP8: Fix E221 multiple spaces before operator
timleslie authored
131 self.shape = arg1
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
132 M,N = self.shape
6f9f01d @timleslie PEP8: Fix E261 at least two spaces before inline comment
timleslie authored
133 # process blocksize
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
134 if blocksize is None:
135 blocksize = (1,1)
136 else:
137 if not isshape(blocksize):
bd2650c cleaned up bsr_matrix imports
wnbell authored
138 raise ValueError('invalid blocksize=%s' % blocksize)
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
139 blocksize = tuple(blocksize)
bfda3d8 @timleslie PEP8: Fix E221 multiple spaces before operator
timleslie authored
140 self.data = np.zeros((0,) + blocksize, getdtype(dtype, default=float))
6e4ecd9 @timleslie PEP8: Fix E202 whitespace before ')'
timleslie authored
141 self.indices = np.zeros(0, dtype=np.intc)
e835bd3 @jarrodmillman ran reindent
jarrodmillman authored
142
059ab8a use recursive template for BSR matrix vector product
wnbell authored
143 R,C = blocksize
144 if (M % R) != 0 or (N % C) != 0:
1559800 ENH: sparse: update 'raise' statements
warren.weckesser authored
145 raise ValueError('shape must be multiple of blocksize')
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
146
bfda3d8 @timleslie PEP8: Fix E221 multiple spaces before operator
timleslie authored
147 self.indptr = np.zeros(M//R + 1, dtype=np.intc)
e835bd3 @jarrodmillman ran reindent
jarrodmillman authored
148
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
149 elif len(arg1) == 2:
150 # (data,(row,col)) format
3add620 @pv MAINT: Automated 2to3 conversion of the code base
pv authored
151 from .coo import coo_matrix
6e4ecd9 @timleslie PEP8: Fix E202 whitespace before ')'
timleslie authored
152 self._set_self(coo_matrix(arg1, dtype=dtype).tobsr(blocksize=blocksize))
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
153
154 elif len(arg1) == 3:
155 # (data,indices,indptr) format
156 (data, indices, indptr) = arg1
bd2650c cleaned up bsr_matrix imports
wnbell authored
157 self.indices = np.array(indices, copy=copy)
daf2d37 @timleslie PEP8: Fix E241 multiple spaces after ','
timleslie authored
158 self.indptr = np.array(indptr, copy=copy)
159 self.data = np.array(data, copy=copy, dtype=getdtype(dtype, data))
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
160 else:
bd2650c cleaned up bsr_matrix imports
wnbell authored
161 raise ValueError('unrecognized bsr_matrix constructor usage')
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
162 else:
6f9f01d @timleslie PEP8: Fix E261 at least two spaces before inline comment
timleslie authored
163 # must be dense
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
164 try:
bd2650c cleaned up bsr_matrix imports
wnbell authored
165 arg1 = np.asarray(arg1)
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
166 except:
b5ccb04 @timleslie PEP8: Fix E502 the backslash is redundant between brackets
timleslie authored
167 raise ValueError("unrecognized form for"
bd2650c cleaned up bsr_matrix imports
wnbell authored
168 " %s_matrix constructor" % self.format)
3add620 @pv MAINT: Automated 2to3 conversion of the code base
pv authored
169 from .coo import coo_matrix
40e1c9a added scipy.sparse.find()
wnbell authored
170 arg1 = coo_matrix(arg1, dtype=dtype).tobsr(blocksize=blocksize)
6e4ecd9 @timleslie PEP8: Fix E202 whitespace before ')'
timleslie authored
171 self._set_self(arg1)
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
172
173 if shape is not None:
174 self.shape = shape # spmatrix will check for errors
175 else:
176 if self.shape is None:
177 # shape not already set, try to infer dimensions
178 try:
179 M = len(self.indptr) - 1
180 N = self.indices.max() + 1
181 except:
f4146a7 fixed handling of dtype= constructor argument in sparse case
wnbell authored
182 raise ValueError('unable to infer matrix dimensions')
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
183 else:
184 R,C = self.blocksize
185 self.shape = (M*R,N*C)
186
187 if self.shape is None:
188 if shape is None:
6f9f01d @timleslie PEP8: Fix E261 at least two spaces before inline comment
timleslie authored
189 # TODO infer shape here
f4146a7 fixed handling of dtype= constructor argument in sparse case
wnbell authored
190 raise ValueError('need to infer shape')
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
191 else:
192 self.shape = shape
a01c277 @jarrodmillman ran reindent
jarrodmillman authored
193
f4146a7 fixed handling of dtype= constructor argument in sparse case
wnbell authored
194 if dtype is not None:
195 self.data = self.data.astype(dtype)
36d6938 added bsr_matrix docstring
wnbell authored
196
27d8a32 minor change to SA
wnbell authored
197 self.check_format(full_check=False)
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
198
199 def check_format(self, full_check=True):
200 """check whether the matrix format is valid
201
202 *Parameters*:
203 full_check:
204 True - rigorous check, O(N) operations : default
205 False - basic check, O(1) operations
7838d22 add bsr_matrix format
wnbell authored
206
207 """
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
208 M,N = self.shape
209 R,C = self.blocksize
210
211 # index arrays should have integer data types
212 if self.indptr.dtype.kind != 'i':
b5ccb04 @timleslie PEP8: Fix E502 the backslash is redundant between brackets
timleslie authored
213 warn("indptr array has non-integer dtype (%s)"
6e4ecd9 @timleslie PEP8: Fix E202 whitespace before ')'
timleslie authored
214 % self.indptr.dtype.name)
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
215 if self.indices.dtype.kind != 'i':
b5ccb04 @timleslie PEP8: Fix E502 the backslash is redundant between brackets
timleslie authored
216 warn("indices array has non-integer dtype (%s)"
6e4ecd9 @timleslie PEP8: Fix E202 whitespace before ')'
timleslie authored
217 % self.indices.dtype.name)
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
218
219 # only support 32-bit ints for now
bfda3d8 @timleslie PEP8: Fix E221 multiple spaces before operator
timleslie authored
220 self.indptr = np.asarray(self.indptr, np.intc)
bd2650c cleaned up bsr_matrix imports
wnbell authored
221 self.indices = np.asarray(self.indices, np.intc)
bfda3d8 @timleslie PEP8: Fix E221 multiple spaces before operator
timleslie authored
222 self.data = to_native(self.data)
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
223
224 # check array shapes
bd2650c cleaned up bsr_matrix imports
wnbell authored
225 if np.rank(self.indices) != 1 or np.rank(self.indptr) != 1:
1559800 ENH: sparse: update 'raise' statements
warren.weckesser authored
226 raise ValueError("indices, and indptr should be rank 1")
bd2650c cleaned up bsr_matrix imports
wnbell authored
227 if np.rank(self.data) != 3:
1559800 ENH: sparse: update 'raise' statements
warren.weckesser authored
228 raise ValueError("data should be rank 3")
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
229
230 # check index pointer
6e4ecd9 @timleslie PEP8: Fix E202 whitespace before ')'
timleslie authored
231 if (len(self.indptr) != M//R + 1):
1559800 ENH: sparse: update 'raise' statements
warren.weckesser authored
232 raise ValueError("index pointer size (%d) should be (%d)" %
233 (len(self.indptr), M//R + 1))
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
234 if (self.indptr[0] != 0):
1559800 ENH: sparse: update 'raise' statements
warren.weckesser authored
235 raise ValueError("index pointer should start with 0")
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
236
237 # check index and data arrays
238 if (len(self.indices) != len(self.data)):
1559800 ENH: sparse: update 'raise' statements
warren.weckesser authored
239 raise ValueError("indices and data should have the same size")
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
240 if (self.indptr[-1] > len(self.indices)):
1559800 ENH: sparse: update 'raise' statements
warren.weckesser authored
241 raise ValueError("Last value of index pointer should be less than "
242 "the size of index and data arrays")
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
243
244 self.prune()
245
246 if full_check:
6f9f01d @timleslie PEP8: Fix E261 at least two spaces before inline comment
timleslie authored
247 # check format validity (more expensive)
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
248 if self.nnz > 0:
032e647 @pv 3K: sparse: fix several integer divisions
pv authored
249 if self.indices.max() >= N//C:
dbe3310 @pv PY23: sparse: __bool__/__nonzero__ + remove unnecessary list()'s + it…
pv authored
250 raise ValueError("column index values must be < %d (now max %d)" % (N//C, self.indices.max()))
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
251 if self.indices.min() < 0:
1559800 ENH: sparse: update 'raise' statements
warren.weckesser authored
252 raise ValueError("column index values must be >= 0")
720e000 BUG: sparse: fix a few undefined names found by pyflakes (but there a…
warren.weckesser authored
253 if np.diff(self.indptr).min() < 0:
1559800 ENH: sparse: update 'raise' statements
warren.weckesser authored
254 raise ValueError("index pointer values must form a "
255 "non-decreasing sequence")
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
256
6f9f01d @timleslie PEP8: Fix E261 at least two spaces before inline comment
timleslie authored
257 # if not self.has_sorted_indices():
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
258 # warn('Indices were not in sorted order. Sorting indices.')
259 # self.sort_indices(check_first=False)
260
261 def _get_blocksize(self):
262 return self.data.shape[1:]
263 blocksize = property(fget=_get_blocksize)
e835bd3 @jarrodmillman ran reindent
jarrodmillman authored
264
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
265 def getnnz(self):
266 R,C = self.blocksize
42420f1 @cowlicks BUG: Homogenezie nnz type to be int for all sparse matrix types.
cowlicks authored
267 return int(self.indptr[-1] * R * C)
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
268 nnz = property(fget=getnnz)
e835bd3 @jarrodmillman ran reindent
jarrodmillman authored
269
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
270 def __repr__(self):
271 nnz = self.getnnz()
272 format = self.getformat()
273 return "<%dx%d sparse matrix of type '%s'\n" \
274 "\twith %d stored elements (blocksize = %dx%d) in %s format>" % \
2180a74 @timleslie PEP8: Fix E201 whitespace after '('
timleslie authored
275 (self.shape + (self.dtype.type, nnz) + self.blocksize +
6e4ecd9 @timleslie PEP8: Fix E202 whitespace before ')'
timleslie authored
276 (_formats[format][1],))
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
277
1e02779 added .diagonal() function to sparse matrices
wnbell authored
278 def diagonal(self):
279 """Returns the main diagonal of the matrix
280 """
281 M,N = self.shape
282 R,C = self.blocksize
bd2650c cleaned up bsr_matrix imports
wnbell authored
283 y = np.empty(min(M,N), dtype=upcast(self.dtype))
b5ccb04 @timleslie PEP8: Fix E502 the backslash is redundant between brackets
timleslie authored
284 sparsetools.bsr_diagonal(M//R, N//C, R, C,
bd2650c cleaned up bsr_matrix imports
wnbell authored
285 self.indptr, self.indices, np.ravel(self.data), y)
1e02779 added .diagonal() function to sparse matrices
wnbell authored
286 return y
287
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
288 ##########################
289 # NotImplemented methods #
290 ##########################
291
292 def getdata(self,ind):
293 raise NotImplementedError
294
295 def __getitem__(self,key):
296 raise NotImplementedError
e835bd3 @jarrodmillman ran reindent
jarrodmillman authored
297
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
298 def __setitem__(self,key,val):
299 raise NotImplementedError
300
301 ######################
302 # Arithmetic methods #
303 ######################
7838d22 add bsr_matrix format
wnbell authored
304
d2a18de refactored sparse matrix multiplication handlers
wnbell authored
305 def matvec(self, other):
306 return self * other
7838d22 add bsr_matrix format
wnbell authored
307
d2a18de refactored sparse matrix multiplication handlers
wnbell authored
308 def matmat(self, other):
309 return self * other
7838d22 add bsr_matrix format
wnbell authored
310
d2a18de refactored sparse matrix multiplication handlers
wnbell authored
311 def _mul_vector(self, other):
312 M,N = self.shape
313 R,C = self.blocksize
e835bd3 @jarrodmillman ran reindent
jarrodmillman authored
314
bd2650c cleaned up bsr_matrix imports
wnbell authored
315 result = np.zeros(self.shape[0], dtype=upcast(self.dtype, other.dtype))
e835bd3 @jarrodmillman ran reindent
jarrodmillman authored
316
b5ccb04 @timleslie PEP8: Fix E502 the backslash is redundant between brackets
timleslie authored
317 bsr_matvec(M//R, N//C, R, C,
79a6019 @jarrodmillman ran reindent
jarrodmillman authored
318 self.indptr, self.indices, self.data.ravel(),
f27946d added several block matrix vector products
wnbell authored
319 other, result)
320
321 return result
79a6019 @jarrodmillman ran reindent
jarrodmillman authored
322
da9cb74 cleaned up dok_matrix imports
wnbell authored
323 def _mul_multivector(self,other):
f27946d added several block matrix vector products
wnbell authored
324 R,C = self.blocksize
325 M,N = self.shape
6f9f01d @timleslie PEP8: Fix E261 at least two spaces before inline comment
timleslie authored
326 n_vecs = other.shape[1] # number of column vectors
f27946d added several block matrix vector products
wnbell authored
327
bd2650c cleaned up bsr_matrix imports
wnbell authored
328 result = np.zeros((M,n_vecs), dtype=upcast(self.dtype,other.dtype))
f27946d added several block matrix vector products
wnbell authored
329
b5ccb04 @timleslie PEP8: Fix E502 the backslash is redundant between brackets
timleslie authored
330 bsr_matvecs(M//R, N//C, n_vecs, R, C,
331 self.indptr, self.indices, self.data.ravel(),
f27946d added several block matrix vector products
wnbell authored
332 other.ravel(), result.ravel())
e835bd3 @jarrodmillman ran reindent
jarrodmillman authored
333
d2a18de refactored sparse matrix multiplication handlers
wnbell authored
334 return result
7838d22 add bsr_matrix format
wnbell authored
335
d2a18de refactored sparse matrix multiplication handlers
wnbell authored
336 def _mul_sparse_matrix(self, other):
337 M, K1 = self.shape
338 K2, N = other.shape
7838d22 add bsr_matrix format
wnbell authored
339
6e4ecd9 @timleslie PEP8: Fix E202 whitespace before ')'
timleslie authored
340 indptr = np.empty_like(self.indptr)
7838d22 add bsr_matrix format
wnbell authored
341
d2a18de refactored sparse matrix multiplication handlers
wnbell authored
342 R,n = self.blocksize
7838d22 add bsr_matrix format
wnbell authored
343
6f9f01d @timleslie PEP8: Fix E261 at least two spaces before inline comment
timleslie authored
344 # convert to this format
d2a18de refactored sparse matrix multiplication handlers
wnbell authored
345 if isspmatrix_bsr(other):
346 C = other.blocksize[1]
7838d22 add bsr_matrix format
wnbell authored
347 else:
d2a18de refactored sparse matrix multiplication handlers
wnbell authored
348 C = 1
7838d22 add bsr_matrix format
wnbell authored
349
3add620 @pv MAINT: Automated 2to3 conversion of the code base
pv authored
350 from .csr import isspmatrix_csr
7838d22 add bsr_matrix format
wnbell authored
351
d2a18de refactored sparse matrix multiplication handlers
wnbell authored
352 if isspmatrix_csr(other) and n == 1:
6f9f01d @timleslie PEP8: Fix E261 at least two spaces before inline comment
timleslie authored
353 other = other.tobsr(blocksize=(n,C), copy=False) # lightweight conversion
d2a18de refactored sparse matrix multiplication handlers
wnbell authored
354 else:
355 other = other.tobsr(blocksize=(n,C))
bded5f8 use CSR matmat for 1x1 BSR
wnbell authored
356
2180a74 @timleslie PEP8: Fix E201 whitespace after '('
timleslie authored
357 csr_matmat_pass1(M//R, N//C,
daf2d37 @timleslie PEP8: Fix E241 multiple spaces after ','
timleslie authored
358 self.indptr, self.indices,
b5ccb04 @timleslie PEP8: Fix E502 the backslash is redundant between brackets
timleslie authored
359 other.indptr, other.indices,
d2a18de refactored sparse matrix multiplication handlers
wnbell authored
360 indptr)
aaa736c implemented block CSR multiplication
wnbell authored
361
d2a18de refactored sparse matrix multiplication handlers
wnbell authored
362 bnnz = indptr[-1]
bd2650c cleaned up bsr_matrix imports
wnbell authored
363 indices = np.empty(bnnz, dtype=np.intc)
bfda3d8 @timleslie PEP8: Fix E221 multiple spaces before operator
timleslie authored
364 data = np.empty(R*C*bnnz, dtype=upcast(self.dtype,other.dtype))
aaa736c implemented block CSR multiplication
wnbell authored
365
2180a74 @timleslie PEP8: Fix E201 whitespace after '('
timleslie authored
366 bsr_matmat_pass2(M//R, N//C, R, C, n,
daf2d37 @timleslie PEP8: Fix E241 multiple spaces after ','
timleslie authored
367 self.indptr, self.indices, np.ravel(self.data),
b5ccb04 @timleslie PEP8: Fix E502 the backslash is redundant between brackets
timleslie authored
368 other.indptr, other.indices, np.ravel(other.data),
daf2d37 @timleslie PEP8: Fix E241 multiple spaces after ','
timleslie authored
369 indptr, indices, data)
aaa736c implemented block CSR multiplication
wnbell authored
370
d2a18de refactored sparse matrix multiplication handlers
wnbell authored
371 data = data.reshape(-1,R,C)
bd2650c cleaned up bsr_matrix imports
wnbell authored
372
6f9f01d @timleslie PEP8: Fix E261 at least two spaces before inline comment
timleslie authored
373 # TODO eliminate zeros
e835bd3 @jarrodmillman ran reindent
jarrodmillman authored
374
d2a18de refactored sparse matrix multiplication handlers
wnbell authored
375 return bsr_matrix((data,indices,indptr),shape=(M,N),blocksize=(R,C))
aaa736c implemented block CSR multiplication
wnbell authored
376
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
377 ######################
378 # Conversion methods #
379 ######################
e835bd3 @jarrodmillman ran reindent
jarrodmillman authored
380
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
381 def tobsr(self,blocksize=None,copy=False):
382 if blocksize not in [None, self.blocksize]:
5c1966f make CSR the default for ->BSR conversions
wnbell authored
383 return self.tocsr().tobsr(blocksize=blocksize)
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
384 if copy:
385 return self.copy()
386 else:
387 return self
388
389 def tocsr(self):
390 return self.tocoo(copy=False).tocsr()
6f9f01d @timleslie PEP8: Fix E261 at least two spaces before inline comment
timleslie authored
391 # TODO make this more efficient
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
392
393 def tocsc(self):
394 return self.tocoo(copy=False).tocsc()
395
7838d22 add bsr_matrix format
wnbell authored
396 def tocoo(self,copy=True):
397 """Convert this matrix to COOrdinate format.
398
399 When copy=False the data array will be shared between
400 this matrix and the resultant coo_matrix.
401 """
e835bd3 @jarrodmillman ran reindent
jarrodmillman authored
402
7838d22 add bsr_matrix format
wnbell authored
403 M,N = self.shape
059ab8a use recursive template for BSR matrix vector product
wnbell authored
404 R,C = self.blocksize
7838d22 add bsr_matrix format
wnbell authored
405
bfda3d8 @timleslie PEP8: Fix E221 multiple spaces before operator
timleslie authored
406 row = (R * np.arange(M//R)).repeat(np.diff(self.indptr))
407 row = row.repeat(R*C).reshape(-1,R,C)
bd2650c cleaned up bsr_matrix imports
wnbell authored
408 row += np.tile(np.arange(R).reshape(-1,1), (1,C))
bfda3d8 @timleslie PEP8: Fix E221 multiple spaces before operator
timleslie authored
409 row = row.reshape(-1)
7838d22 add bsr_matrix format
wnbell authored
410
bfda3d8 @timleslie PEP8: Fix E221 multiple spaces before operator
timleslie authored
411 col = (C * self.indices).repeat(R*C).reshape(-1,R,C)
bd2650c cleaned up bsr_matrix imports
wnbell authored
412 col += np.tile(np.arange(C), (R,1))
bfda3d8 @timleslie PEP8: Fix E221 multiple spaces before operator
timleslie authored
413 col = col.reshape(-1)
7838d22 add bsr_matrix format
wnbell authored
414
415 data = self.data.reshape(-1)
416
417 if copy:
418 data = data.copy()
419
3add620 @pv MAINT: Automated 2to3 conversion of the code base
pv authored
420 from .coo import coo_matrix
bd2650c cleaned up bsr_matrix imports
wnbell authored
421 return coo_matrix((data,(row,col)), shape=self.shape)
7838d22 add bsr_matrix format
wnbell authored
422
9adfbb8 enabled bsr_matrix
wnbell authored
423 def transpose(self):
e835bd3 @jarrodmillman ran reindent
jarrodmillman authored
424
059ab8a use recursive template for BSR matrix vector product
wnbell authored
425 R,C = self.blocksize
7838d22 add bsr_matrix format
wnbell authored
426 M,N = self.shape
032e647 @pv 3K: sparse: fix several integer divisions
pv authored
427 NBLK = self.nnz//(R*C)
e835bd3 @jarrodmillman ran reindent
jarrodmillman authored
428
aaa736c implemented block CSR multiplication
wnbell authored
429 if self.nnz == 0:
bd2650c cleaned up bsr_matrix imports
wnbell authored
430 return bsr_matrix((N,M), blocksize=(C,R))
7838d22 add bsr_matrix format
wnbell authored
431
daf2d37 @timleslie PEP8: Fix E241 multiple spaces after ','
timleslie authored
432 indptr = np.empty(N//C + 1, dtype=self.indptr.dtype)
433 indices = np.empty(NBLK, dtype=self.indices.dtype)
bfda3d8 @timleslie PEP8: Fix E221 multiple spaces before operator
timleslie authored
434 data = np.empty((NBLK,C,R), dtype=self.data.dtype)
0b734ec added two BSR methods to sparsetools
wnbell authored
435
b5ccb04 @timleslie PEP8: Fix E502 the backslash is redundant between brackets
timleslie authored
436 bsr_transpose(M//R, N//C, R, C,
437 self.indptr, self.indices, self.data.ravel(),
daf2d37 @timleslie PEP8: Fix E241 multiple spaces after ','
timleslie authored
438 indptr, indices, data.ravel())
7838d22 add bsr_matrix format
wnbell authored
439
bd2650c cleaned up bsr_matrix imports
wnbell authored
440 return bsr_matrix((data,indices,indptr), shape=(N,M))
e835bd3 @jarrodmillman ran reindent
jarrodmillman authored
441
442 ##############################################################
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
443 # methods that examine or modify the internal data structure #
444 ##############################################################
e835bd3 @jarrodmillman ran reindent
jarrodmillman authored
445
8529b5b added eliminate_zeros() to compressed formats
wnbell authored
446 def eliminate_zeros(self):
447 R,C = self.blocksize
448 M,N = self.shape
449
6f9f01d @timleslie PEP8: Fix E261 at least two spaces before inline comment
timleslie authored
450 mask = (self.data != 0).reshape(-1,R*C).sum(axis=1) # nonzero blocks
e835bd3 @jarrodmillman ran reindent
jarrodmillman authored
451
8529b5b added eliminate_zeros() to compressed formats
wnbell authored
452 nonzero_blocks = mask.nonzero()[0]
453
454 if len(nonzero_blocks) == 0:
6f9f01d @timleslie PEP8: Fix E261 at least two spaces before inline comment
timleslie authored
455 return # nothing to do
8529b5b added eliminate_zeros() to compressed formats
wnbell authored
456
457 self.data[:len(nonzero_blocks)] = self.data[nonzero_blocks]
458
3add620 @pv MAINT: Automated 2to3 conversion of the code base
pv authored
459 from .csr import csr_matrix
8529b5b added eliminate_zeros() to compressed formats
wnbell authored
460
461 # modifies self.indptr and self.indices *in place*
032e647 @pv 3K: sparse: fix several integer divisions
pv authored
462 proxy = csr_matrix((mask,self.indices,self.indptr),shape=(M//R,N//C))
8529b5b added eliminate_zeros() to compressed formats
wnbell authored
463 proxy.eliminate_zeros()
e835bd3 @jarrodmillman ran reindent
jarrodmillman authored
464
8529b5b added eliminate_zeros() to compressed formats
wnbell authored
465 self.prune()
466
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
467 def sum_duplicates(self):
468 raise NotImplementedError
7838d22 add bsr_matrix format
wnbell authored
469
a558af6 set _has_sorted_indices after CSR<->CSC
wnbell authored
470 def sort_indices(self):
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
471 """Sort the indices of this matrix *in place*
472 """
dbb4ae9 made has_sorted_indices a property
wnbell authored
473 if self.has_sorted_indices:
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
474 return
475
476 R,C = self.blocksize
477 M,N = self.shape
478
032e647 @pv 3K: sparse: fix several integer divisions
pv authored
479 bsr_sort_indices(M//R, N//C, R, C, self.indptr, self.indices, self.data.ravel())
0b734ec added two BSR methods to sparsetools
wnbell authored
480
dbb4ae9 made has_sorted_indices a property
wnbell authored
481 self.has_sorted_indices = True
a558af6 set _has_sorted_indices after CSR<->CSC
wnbell authored
482
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
483 def prune(self):
484 """ Remove empty space after all non-zero elements.
485 """
486
487 R,C = self.blocksize
488 M,N = self.shape
489
032e647 @pv 3K: sparse: fix several integer divisions
pv authored
490 if len(self.indptr) != M//R + 1:
1559800 ENH: sparse: update 'raise' statements
warren.weckesser authored
491 raise ValueError("index pointer has invalid length")
e835bd3 @jarrodmillman ran reindent
jarrodmillman authored
492
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
493 bnnz = self.indptr[-1]
494
e835bd3 @jarrodmillman ran reindent
jarrodmillman authored
495 if len(self.indices) < bnnz:
1559800 ENH: sparse: update 'raise' statements
warren.weckesser authored
496 raise ValueError("indices array has too few elements")
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
497 if len(self.data) < bnnz:
1559800 ENH: sparse: update 'raise' statements
warren.weckesser authored
498 raise ValueError("data array has too few elements")
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
499
bfda3d8 @timleslie PEP8: Fix E221 multiple spaces before operator
timleslie authored
500 self.data = self.data[:bnnz]
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
501 self.indices = self.indices[:bnnz]
e835bd3 @jarrodmillman ran reindent
jarrodmillman authored
502
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
503 # utility functions
504 def _binopt(self, other, op, in_shape=None, out_shape=None):
2d075b4 @cowlicks ENH: Altered _binop and boolean comparisons to use the boolean data o…
cowlicks authored
505 """Apply the binary operation fn to two sparse matrices."""
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
506
2d075b4 @cowlicks ENH: Altered _binop and boolean comparisons to use the boolean data o…
cowlicks authored
507 # Ideally we'd take the GCDs of the blocksize dimensions
508 # and explode self and other to match.
d787abe added path for BSR (op) BSR where the BSR format is not canonical
wnbell authored
509 other = self.__class__(other, blocksize=self.blocksize)
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
510
511 # e.g. bsr_plus_bsr, etc.
512 fn = getattr(sparsetools, self.format + op + self.format)
e835bd3 @jarrodmillman ran reindent
jarrodmillman authored
513
514 R,C = self.blocksize
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
515
516 max_bnnz = len(self.data) + len(other.data)
bfda3d8 @timleslie PEP8: Fix E221 multiple spaces before operator
timleslie authored
517 indptr = np.empty_like(self.indptr)
bd2650c cleaned up bsr_matrix imports
wnbell authored
518 indices = np.empty(max_bnnz, dtype=np.intc)
2d075b4 @cowlicks ENH: Altered _binop and boolean comparisons to use the boolean data o…
cowlicks authored
519
75768bc @cowlicks ENH: Add inequalities to compressed.py, bsr.py.
cowlicks authored
520 bool_ops = ['_ne_', '_lt_', '_gt_', '_le_', '_ge_']
521 if op in bool_ops:
2d075b4 @cowlicks ENH: Altered _binop and boolean comparisons to use the boolean data o…
cowlicks authored
522 data = np.empty(R*C*max_bnnz, dtype=np.bool_)
523 else:
524 data = np.empty(R*C*max_bnnz, dtype=upcast(self.dtype,other.dtype))
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
525
032e647 @pv 3K: sparse: fix several integer divisions
pv authored
526 fn(self.shape[0]//R, self.shape[1]//C, R, C,
daf2d37 @timleslie PEP8: Fix E241 multiple spaces after ','
timleslie authored
527 self.indptr, self.indices, np.ravel(self.data),
bd2650c cleaned up bsr_matrix imports
wnbell authored
528 other.indptr, other.indices, np.ravel(other.data),
daf2d37 @timleslie PEP8: Fix E241 multiple spaces after ','
timleslie authored
529 indptr, indices, data)
e835bd3 @jarrodmillman ran reindent
jarrodmillman authored
530
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
531 actual_bnnz = indptr[-1]
532 indices = indices[:actual_bnnz]
bfda3d8 @timleslie PEP8: Fix E221 multiple spaces before operator
timleslie authored
533 data = data[:R*C*actual_bnnz]
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
534
535 if actual_bnnz < max_bnnz/2:
536 indices = indices.copy()
bfda3d8 @timleslie PEP8: Fix E221 multiple spaces before operator
timleslie authored
537 data = data.copy()
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
538
539 data = data.reshape(-1,R,C)
540
d787abe added path for BSR (op) BSR where the BSR format is not canonical
wnbell authored
541 return self.__class__((data, indices, indptr), shape=self.shape)
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
542
543 # needed by _data_matrix
544 def _with_data(self,data,copy=True):
545 """Returns a matrix with the same sparsity structure as self,
546 but with different data. By default the structure arrays
547 (i.e. .indptr and .indices) are copied.
548 """
7838d22 add bsr_matrix format
wnbell authored
549 if copy:
b5ccb04 @timleslie PEP8: Fix E502 the backslash is redundant between brackets
timleslie authored
550 return self.__class__((data,self.indices.copy(),self.indptr.copy()),
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
551 shape=self.shape,dtype=data.dtype)
7838d22 add bsr_matrix format
wnbell authored
552 else:
b5ccb04 @timleslie PEP8: Fix E502 the backslash is redundant between brackets
timleslie authored
553 return self.__class__((data,self.indices,self.indptr),
e1e0f37 consolidated bsr with _cs_matrix class
wnbell authored
554 shape=self.shape,dtype=data.dtype)
555
556 # # these functions are used by the parent class
557 # # to remove redudancy between bsc_matrix and bsr_matrix
558 # def _swap(self,x):
559 # """swap the members of x if this is a column-oriented matrix
560 # """
561 # return (x[0],x[1])
7838d22 add bsr_matrix format
wnbell authored
562
5d565c0 @timleslie PEP8: Fix E302 expected 2 blank lines, found 1
timleslie authored
563
7838d22 add bsr_matrix format
wnbell authored
564 def isspmatrix_bsr(x):
06cd6e5 @pv ENH: sparse: reduce overheads in sparse matrix multiplication
pv authored
565 return isinstance(x, bsr_matrix)
Something went wrong with that request. Please try again.