Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/scipy/sparse/_base.py: 29%

534 statements  

« prev     ^ index     » next       coverage.py v7.3.1, created at 2023-09-23 06:43 +0000

1"""Base class for sparse matrices""" 

2from warnings import warn 

3 

4import numpy as np 

5from scipy._lib._util import VisibleDeprecationWarning 

6 

7from ._sputils import (asmatrix, check_reshape_kwargs, check_shape, 

8 get_sum_dtype, isdense, isscalarlike, 

9 matrix, validateaxis,) 

10 

11from ._matrix import spmatrix 

12 

13__all__ = ['isspmatrix', 'issparse', 'sparray', 

14 'SparseWarning', 'SparseEfficiencyWarning'] 

15 

16 

17class SparseWarning(Warning): 

18 pass 

19 

20 

21class SparseFormatWarning(SparseWarning): 

22 pass 

23 

24 

25class SparseEfficiencyWarning(SparseWarning): 

26 pass 

27 

28 

29# The formats that we might potentially understand. 

30_formats = {'csc': [0, "Compressed Sparse Column"], 

31 'csr': [1, "Compressed Sparse Row"], 

32 'dok': [2, "Dictionary Of Keys"], 

33 'lil': [3, "List of Lists"], 

34 'dod': [4, "Dictionary of Dictionaries"], 

35 'sss': [5, "Symmetric Sparse Skyline"], 

36 'coo': [6, "COOrdinate"], 

37 'lba': [7, "Linpack BAnded"], 

38 'egd': [8, "Ellpack-itpack Generalized Diagonal"], 

39 'dia': [9, "DIAgonal"], 

40 'bsr': [10, "Block Sparse Row"], 

41 'msr': [11, "Modified compressed Sparse Row"], 

42 'bsc': [12, "Block Sparse Column"], 

43 'msc': [13, "Modified compressed Sparse Column"], 

44 'ssk': [14, "Symmetric SKyline"], 

45 'nsk': [15, "Nonsymmetric SKyline"], 

46 'jad': [16, "JAgged Diagonal"], 

47 'uss': [17, "Unsymmetric Sparse Skyline"], 

48 'vbr': [18, "Variable Block Row"], 

49 'und': [19, "Undefined"] 

50 } 

51 

52 

53# These univariate ufuncs preserve zeros. 

54_ufuncs_with_fixed_point_at_zero = frozenset([ 

55 np.sin, np.tan, np.arcsin, np.arctan, np.sinh, np.tanh, np.arcsinh, 

56 np.arctanh, np.rint, np.sign, np.expm1, np.log1p, np.deg2rad, 

57 np.rad2deg, np.floor, np.ceil, np.trunc, np.sqrt]) 

58 

59 

60MAXPRINT = 50 

61 

62 

63class _spbase: 

64 """ This class provides a base class for all sparse arrays. It 

65 cannot be instantiated. Most of the work is provided by subclasses. 

66 """ 

67 

68 __array_priority__ = 10.1 

69 _format = 'und' # undefined 

70 ndim = 2 

71 

72 @property 

73 def _bsr_container(self): 

74 from ._bsr import bsr_array 

75 return bsr_array 

76 

77 @property 

78 def _coo_container(self): 

79 from ._coo import coo_array 

80 return coo_array 

81 

82 @property 

83 def _csc_container(self): 

84 from ._csc import csc_array 

85 return csc_array 

86 

87 @property 

88 def _csr_container(self): 

89 from ._csr import csr_array 

90 return csr_array 

91 

92 @property 

93 def _dia_container(self): 

94 from ._dia import dia_array 

95 return dia_array 

96 

97 @property 

98 def _dok_container(self): 

99 from ._dok import dok_array 

100 return dok_array 

101 

102 @property 

103 def _lil_container(self): 

104 from ._lil import lil_array 

105 return lil_array 

106 

107 def __init__(self, maxprint=MAXPRINT): 

108 self._shape = None 

109 if self.__class__.__name__ == '_spbase': 

110 raise ValueError("This class is not intended" 

111 " to be instantiated directly.") 

112 self.maxprint = maxprint 

113 

114 # Use this in 1.13.0 and later: 

115 # 

116 # @property 

117 # def shape(self): 

118 # return self._shape 

119 

120 def reshape(self, *args, **kwargs): 

121 """reshape(self, shape, order='C', copy=False) 

122 

123 Gives a new shape to a sparse array/matrix without changing its data. 

124 

125 Parameters 

126 ---------- 

127 shape : length-2 tuple of ints 

128 The new shape should be compatible with the original shape. 

129 order : {'C', 'F'}, optional 

130 Read the elements using this index order. 'C' means to read and 

131 write the elements using C-like index order; e.g., read entire first 

132 row, then second row, etc. 'F' means to read and write the elements 

133 using Fortran-like index order; e.g., read entire first column, then 

134 second column, etc. 

135 copy : bool, optional 

136 Indicates whether or not attributes of self should be copied 

137 whenever possible. The degree to which attributes are copied varies 

138 depending on the type of sparse array being used. 

139 

140 Returns 

141 ------- 

142 reshaped : sparse array/matrix 

143 A sparse array/matrix with the given `shape`, not necessarily of the same 

144 format as the current object. 

145 

146 See Also 

147 -------- 

148 numpy.reshape : NumPy's implementation of 'reshape' for ndarrays 

149 """ 

150 # If the shape already matches, don't bother doing an actual reshape 

151 # Otherwise, the default is to convert to COO and use its reshape 

152 shape = check_shape(args, self.shape) 

153 order, copy = check_reshape_kwargs(kwargs) 

154 if shape == self.shape: 

155 if copy: 

156 return self.copy() 

157 else: 

158 return self 

159 

160 return self.tocoo(copy=copy).reshape(shape, order=order, copy=False) 

161 

162 def resize(self, shape): 

163 """Resize the array/matrix in-place to dimensions given by ``shape`` 

164 

165 Any elements that lie within the new shape will remain at the same 

166 indices, while non-zero elements lying outside the new shape are 

167 removed. 

168 

169 Parameters 

170 ---------- 

171 shape : (int, int) 

172 number of rows and columns in the new array/matrix 

173 

174 Notes 

175 ----- 

176 The semantics are not identical to `numpy.ndarray.resize` or 

177 `numpy.resize`. Here, the same data will be maintained at each index 

178 before and after reshape, if that index is within the new bounds. In 

179 numpy, resizing maintains contiguity of the array, moving elements 

180 around in the logical array but not within a flattened representation. 

181 

182 We give no guarantees about whether the underlying data attributes 

183 (arrays, etc.) will be modified in place or replaced with new objects. 

184 """ 

185 # As an inplace operation, this requires implementation in each format. 

186 raise NotImplementedError( 

187 f'{type(self).__name__}.resize is not implemented') 

188 

189 def astype(self, dtype, casting='unsafe', copy=True): 

190 """Cast the array/matrix elements to a specified type. 

191 

192 Parameters 

193 ---------- 

194 dtype : string or numpy dtype 

195 Typecode or data-type to which to cast the data. 

196 casting : {'no', 'equiv', 'safe', 'same_kind', 'unsafe'}, optional 

197 Controls what kind of data casting may occur. 

198 Defaults to 'unsafe' for backwards compatibility. 

199 'no' means the data types should not be cast at all. 

200 'equiv' means only byte-order changes are allowed. 

201 'safe' means only casts which can preserve values are allowed. 

202 'same_kind' means only safe casts or casts within a kind, 

203 like float64 to float32, are allowed. 

204 'unsafe' means any data conversions may be done. 

205 copy : bool, optional 

206 If `copy` is `False`, the result might share some memory with this 

207 array/matrix. If `copy` is `True`, it is guaranteed that the result and 

208 this array/matrix do not share any memory. 

209 """ 

210 

211 dtype = np.dtype(dtype) 

212 if self.dtype != dtype: 

213 return self.tocsr().astype( 

214 dtype, casting=casting, copy=copy).asformat(self.format) 

215 elif copy: 

216 return self.copy() 

217 else: 

218 return self 

219 

220 @classmethod 

221 def _ascontainer(cls, X, **kwargs): 

222 if issubclass(cls, sparray): 

223 return np.asarray(X, **kwargs) 

224 else: 

225 return asmatrix(X, **kwargs) 

226 

227 @classmethod 

228 def _container(cls, X, **kwargs): 

229 if issubclass(cls, sparray): 

230 return np.array(X, **kwargs) 

231 else: 

232 return matrix(X, **kwargs) 

233 

234 def _asfptype(self): 

235 """Upcast array to a floating point format (if necessary)""" 

236 

237 fp_types = ['f', 'd', 'F', 'D'] 

238 

239 if self.dtype.char in fp_types: 

240 return self 

241 else: 

242 for fp_type in fp_types: 

243 if self.dtype <= np.dtype(fp_type): 

244 return self.astype(fp_type) 

245 

246 raise TypeError('cannot upcast [%s] to a floating ' 

247 'point format' % self.dtype.name) 

248 

249 def __iter__(self): 

250 for r in range(self.shape[0]): 

251 yield self[r, :] 

252 

253 def _getmaxprint(self): 

254 """Maximum number of elements to display when printed.""" 

255 return self.maxprint 

256 

257 def count_nonzero(self): 

258 """Number of non-zero entries, equivalent to 

259 

260 np.count_nonzero(a.toarray()) 

261 

262 Unlike the nnz property, which return the number of stored 

263 entries (the length of the data attribute), this method counts the 

264 actual number of non-zero entries in data. 

265 """ 

266 raise NotImplementedError("count_nonzero not implemented for %s." % 

267 self.__class__.__name__) 

268 

269 def _getnnz(self, axis=None): 

270 """Number of stored values, including explicit zeros. 

271 

272 Parameters 

273 ---------- 

274 axis : None, 0, or 1 

275 Select between the number of values across the whole array, in 

276 each column, or in each row. 

277 

278 See also 

279 -------- 

280 count_nonzero : Number of non-zero entries 

281 """ 

282 raise NotImplementedError("getnnz not implemented for %s." % 

283 self.__class__.__name__) 

284 

285 @property 

286 def nnz(self) -> int: 

287 """Number of stored values, including explicit zeros. 

288 

289 See also 

290 -------- 

291 count_nonzero : Number of non-zero entries 

292 """ 

293 return self._getnnz() 

294 

295 @property 

296 def size(self) -> int: 

297 """Number of stored values. 

298 

299 See also 

300 -------- 

301 count_nonzero : Number of non-zero values. 

302 """ 

303 return self._getnnz() 

304 

305 @property 

306 def format(self) -> str: 

307 """Format string for matrix.""" 

308 return self._format 

309 

310 @property 

311 def A(self) -> np.ndarray: 

312 """DEPRECATED: Return a dense array. 

313 

314 .. deprecated:: 1.11.0 

315 

316 `.A` is deprecated and will be removed in v1.13.0. 

317 Use `.toarray()` instead. 

318 """ 

319 if isinstance(self, sparray): 

320 warn(VisibleDeprecationWarning( 

321 "`.A` is deprecated and will be removed in v1.13.0. " 

322 "Use `.toarray()` instead." 

323 )) 

324 return self.toarray() 

325 

326 @property 

327 def T(self): 

328 """Transpose.""" 

329 return self.transpose() 

330 

331 @property 

332 def H(self): 

333 """DEPRECATED: Returns the (complex) conjugate transpose. 

334 

335 .. deprecated:: 1.11.0 

336 

337 `.H` is deprecated and will be removed in v1.13.0. 

338 Please use `.T.conjugate()` instead. 

339 """ 

340 if isinstance(self, sparray): 

341 warn(VisibleDeprecationWarning( 

342 "`.H` is deprecated and will be removed in v1.13.0. " 

343 "Please use `.T.conjugate()` instead." 

344 )) 

345 return self.T.conjugate() 

346 

347 @property 

348 def real(self): 

349 return self._real() 

350 

351 @property 

352 def imag(self): 

353 return self._imag() 

354 

355 def __repr__(self): 

356 _, format_name = _formats[self.format] 

357 sparse_cls = 'array' if isinstance(self, sparray) else 'matrix' 

358 return f"<%dx%d sparse {sparse_cls} of type '%s'\n" \ 

359 "\twith %d stored elements in %s format>" % \ 

360 (self.shape + (self.dtype.type, self.nnz, format_name)) 

361 

362 def __str__(self): 

363 maxprint = self._getmaxprint() 

364 

365 A = self.tocoo() 

366 

367 # helper function, outputs "(i,j) v" 

368 def tostr(row, col, data): 

369 triples = zip(list(zip(row, col)), data) 

370 return '\n'.join([(' %s\t%s' % t) for t in triples]) 

371 

372 if self.nnz > maxprint: 

373 half = maxprint // 2 

374 out = tostr(A.row[:half], A.col[:half], A.data[:half]) 

375 out += "\n :\t:\n" 

376 half = maxprint - maxprint//2 

377 out += tostr(A.row[-half:], A.col[-half:], A.data[-half:]) 

378 else: 

379 out = tostr(A.row, A.col, A.data) 

380 

381 return out 

382 

383 def __bool__(self): # Simple -- other ideas? 

384 if self.shape == (1, 1): 

385 return self.nnz != 0 

386 else: 

387 raise ValueError("The truth value of an array with more than one " 

388 "element is ambiguous. Use a.any() or a.all().") 

389 __nonzero__ = __bool__ 

390 

391 # What should len(sparse) return? For consistency with dense matrices, 

392 # perhaps it should be the number of rows? But for some uses the number of 

393 # non-zeros is more important. For now, raise an exception! 

394 def __len__(self): 

395 raise TypeError("sparse array length is ambiguous; use getnnz()" 

396 " or shape[0]") 

397 

398 def asformat(self, format, copy=False): 

399 """Return this array/matrix in the passed format. 

400 

401 Parameters 

402 ---------- 

403 format : {str, None} 

404 The desired sparse format ("csr", "csc", "lil", "dok", "array", ...) 

405 or None for no conversion. 

406 copy : bool, optional 

407 If True, the result is guaranteed to not share data with self. 

408 

409 Returns 

410 ------- 

411 A : This array/matrix in the passed format. 

412 """ 

413 if format is None or format == self.format: 

414 if copy: 

415 return self.copy() 

416 else: 

417 return self 

418 else: 

419 try: 

420 convert_method = getattr(self, 'to' + format) 

421 except AttributeError as e: 

422 raise ValueError(f'Format {format} is unknown.') from e 

423 

424 # Forward the copy kwarg, if it's accepted. 

425 try: 

426 return convert_method(copy=copy) 

427 except TypeError: 

428 return convert_method() 

429 

430 ################################################################### 

431 # NOTE: All arithmetic operations use csr_matrix by default. 

432 # Therefore a new sparse array format just needs to define a 

433 # .tocsr() method to provide arithmetic support. Any of these 

434 # methods can be overridden for efficiency. 

435 #################################################################### 

436 

437 def multiply(self, other): 

438 """Point-wise multiplication by another array/matrix.""" 

439 return self.tocsr().multiply(other) 

440 

441 def maximum(self, other): 

442 """Element-wise maximum between this and another array/matrix.""" 

443 return self.tocsr().maximum(other) 

444 

445 def minimum(self, other): 

446 """Element-wise minimum between this and another array/matrix.""" 

447 return self.tocsr().minimum(other) 

448 

449 def dot(self, other): 

450 """Ordinary dot product 

451 

452 Examples 

453 -------- 

454 >>> import numpy as np 

455 >>> from scipy.sparse import csr_array 

456 >>> A = csr_array([[1, 2, 0], [0, 0, 3], [4, 0, 5]]) 

457 >>> v = np.array([1, 0, -1]) 

458 >>> A.dot(v) 

459 array([ 1, -3, -1], dtype=int64) 

460 

461 """ 

462 if np.isscalar(other): 

463 return self * other 

464 else: 

465 return self @ other 

466 

467 def power(self, n, dtype=None): 

468 """Element-wise power.""" 

469 return self.tocsr().power(n, dtype=dtype) 

470 

471 def __eq__(self, other): 

472 return self.tocsr().__eq__(other) 

473 

474 def __ne__(self, other): 

475 return self.tocsr().__ne__(other) 

476 

477 def __lt__(self, other): 

478 return self.tocsr().__lt__(other) 

479 

480 def __gt__(self, other): 

481 return self.tocsr().__gt__(other) 

482 

483 def __le__(self, other): 

484 return self.tocsr().__le__(other) 

485 

486 def __ge__(self, other): 

487 return self.tocsr().__ge__(other) 

488 

489 def __abs__(self): 

490 return abs(self.tocsr()) 

491 

492 def __round__(self, ndigits=0): 

493 return round(self.tocsr(), ndigits=ndigits) 

494 

495 def _add_sparse(self, other): 

496 return self.tocsr()._add_sparse(other) 

497 

498 def _add_dense(self, other): 

499 return self.tocoo()._add_dense(other) 

500 

501 def _sub_sparse(self, other): 

502 return self.tocsr()._sub_sparse(other) 

503 

504 def _sub_dense(self, other): 

505 return self.todense() - other 

506 

507 def _rsub_dense(self, other): 

508 # note: this can't be replaced by other + (-self) for unsigned types 

509 return other - self.todense() 

510 

511 def __add__(self, other): # self + other 

512 if isscalarlike(other): 

513 if other == 0: 

514 return self.copy() 

515 # Now we would add this scalar to every element. 

516 raise NotImplementedError('adding a nonzero scalar to a ' 

517 'sparse array is not supported') 

518 elif issparse(other): 

519 if other.shape != self.shape: 

520 raise ValueError("inconsistent shapes") 

521 return self._add_sparse(other) 

522 elif isdense(other): 

523 other = np.broadcast_to(other, self.shape) 

524 return self._add_dense(other) 

525 else: 

526 return NotImplemented 

527 

528 def __radd__(self,other): # other + self 

529 return self.__add__(other) 

530 

531 def __sub__(self, other): # self - other 

532 if isscalarlike(other): 

533 if other == 0: 

534 return self.copy() 

535 raise NotImplementedError('subtracting a nonzero scalar from a ' 

536 'sparse array is not supported') 

537 elif issparse(other): 

538 if other.shape != self.shape: 

539 raise ValueError("inconsistent shapes") 

540 return self._sub_sparse(other) 

541 elif isdense(other): 

542 other = np.broadcast_to(other, self.shape) 

543 return self._sub_dense(other) 

544 else: 

545 return NotImplemented 

546 

547 def __rsub__(self,other): # other - self 

548 if isscalarlike(other): 

549 if other == 0: 

550 return -self.copy() 

551 raise NotImplementedError('subtracting a sparse array from a ' 

552 'nonzero scalar is not supported') 

553 elif isdense(other): 

554 other = np.broadcast_to(other, self.shape) 

555 return self._rsub_dense(other) 

556 else: 

557 return NotImplemented 

558 

559 def _mul_dispatch(self, other): 

560 """`np.matrix`-compatible mul, i.e. `dot` or `NotImplemented` 

561 

562 interpret other and call one of the following 

563 self._mul_scalar() 

564 self._mul_vector() 

565 self._mul_multivector() 

566 self._mul_sparse_matrix() 

567 """ 

568 # This method has to be different from `__matmul__` because it is also 

569 # called by sparse matrix classes. 

570 

571 M, N = self.shape 

572 

573 if other.__class__ is np.ndarray: 

574 # Fast path for the most common case 

575 if other.shape == (N,): 

576 return self._mul_vector(other) 

577 elif other.shape == (N, 1): 

578 return self._mul_vector(other.ravel()).reshape(M, 1) 

579 elif other.ndim == 2 and other.shape[0] == N: 

580 return self._mul_multivector(other) 

581 

582 if isscalarlike(other): 

583 # scalar value 

584 return self._mul_scalar(other) 

585 

586 if issparse(other): 

587 if self.shape[1] != other.shape[0]: 

588 raise ValueError('dimension mismatch') 

589 return self._mul_sparse_matrix(other) 

590 

591 # If it's a list or whatever, treat it like an array 

592 other_a = np.asanyarray(other) 

593 

594 if other_a.ndim == 0 and other_a.dtype == np.object_: 

595 # Not interpretable as an array; return NotImplemented so that 

596 # other's __rmul__ can kick in if that's implemented. 

597 return NotImplemented 

598 

599 try: 

600 other.shape 

601 except AttributeError: 

602 other = other_a 

603 

604 if other.ndim == 1 or other.ndim == 2 and other.shape[1] == 1: 

605 # dense row or column vector 

606 if other.shape != (N,) and other.shape != (N, 1): 

607 raise ValueError('dimension mismatch') 

608 

609 result = self._mul_vector(np.ravel(other)) 

610 

611 if isinstance(other, np.matrix): 

612 result = self._ascontainer(result) 

613 

614 if other.ndim == 2 and other.shape[1] == 1: 

615 # If 'other' was an (nx1) column vector, reshape the result 

616 result = result.reshape(-1, 1) 

617 

618 return result 

619 

620 elif other.ndim == 2: 

621 ## 

622 # dense 2D array or matrix ("multivector") 

623 

624 if other.shape[0] != self.shape[1]: 

625 raise ValueError('dimension mismatch') 

626 

627 result = self._mul_multivector(np.asarray(other)) 

628 

629 if isinstance(other, np.matrix): 

630 result = self._ascontainer(result) 

631 

632 return result 

633 

634 else: 

635 raise ValueError('could not interpret dimensions') 

636 

637 def __mul__(self, *args, **kwargs): 

638 return self.multiply(*args, **kwargs) 

639 

640 # by default, use CSR for __mul__ handlers 

641 def _mul_scalar(self, other): 

642 return self.tocsr()._mul_scalar(other) 

643 

644 def _mul_vector(self, other): 

645 return self.tocsr()._mul_vector(other) 

646 

647 def _mul_multivector(self, other): 

648 return self.tocsr()._mul_multivector(other) 

649 

650 def _mul_sparse_matrix(self, other): 

651 return self.tocsr()._mul_sparse_matrix(other) 

652 

653 def _rmul_dispatch(self, other): 

654 if isscalarlike(other): 

655 return self._mul_scalar(other) 

656 else: 

657 # Don't use asarray unless we have to 

658 try: 

659 tr = other.transpose() 

660 except AttributeError: 

661 tr = np.asarray(other).transpose() 

662 ret = self.transpose()._mul_dispatch(tr) 

663 if ret is NotImplemented: 

664 return NotImplemented 

665 return ret.transpose() 

666 

667 def __rmul__(self, *args, **kwargs): # other * self 

668 return self.multiply(*args, **kwargs) 

669 

670 ####################### 

671 # matmul (@) operator # 

672 ####################### 

673 

674 def __matmul__(self, other): 

675 if isscalarlike(other): 

676 raise ValueError("Scalar operands are not allowed, " 

677 "use '*' instead") 

678 return self._mul_dispatch(other) 

679 

680 def __rmatmul__(self, other): 

681 if isscalarlike(other): 

682 raise ValueError("Scalar operands are not allowed, " 

683 "use '*' instead") 

684 return self._rmul_dispatch(other) 

685 

686 #################### 

687 # Other Arithmetic # 

688 #################### 

689 

690 def _divide(self, other, true_divide=False, rdivide=False): 

691 if isscalarlike(other): 

692 if rdivide: 

693 if true_divide: 

694 return np.true_divide(other, self.todense()) 

695 else: 

696 return np.divide(other, self.todense()) 

697 

698 if true_divide and np.can_cast(self.dtype, np.float64): 

699 return self.astype(np.float64)._mul_scalar(1./other) 

700 else: 

701 r = self._mul_scalar(1./other) 

702 

703 scalar_dtype = np.asarray(other).dtype 

704 if (np.issubdtype(self.dtype, np.integer) and 

705 np.issubdtype(scalar_dtype, np.integer)): 

706 return r.astype(self.dtype) 

707 else: 

708 return r 

709 

710 elif isdense(other): 

711 if not rdivide: 

712 if true_divide: 

713 recip = np.true_divide(1., other) 

714 else: 

715 recip = np.divide(1., other) 

716 return self.multiply(recip) 

717 else: 

718 if true_divide: 

719 return np.true_divide(other, self.todense()) 

720 else: 

721 return np.divide(other, self.todense()) 

722 elif issparse(other): 

723 if rdivide: 

724 return other._divide(self, true_divide, rdivide=False) 

725 

726 self_csr = self.tocsr() 

727 if true_divide and np.can_cast(self.dtype, np.float64): 

728 return self_csr.astype(np.float64)._divide_sparse(other) 

729 else: 

730 return self_csr._divide_sparse(other) 

731 else: 

732 return NotImplemented 

733 

734 def __truediv__(self, other): 

735 return self._divide(other, true_divide=True) 

736 

737 def __div__(self, other): 

738 # Always do true division 

739 return self._divide(other, true_divide=True) 

740 

741 def __rtruediv__(self, other): 

742 # Implementing this as the inverse would be too magical -- bail out 

743 return NotImplemented 

744 

745 def __rdiv__(self, other): 

746 # Implementing this as the inverse would be too magical -- bail out 

747 return NotImplemented 

748 

749 def __neg__(self): 

750 return -self.tocsr() 

751 

752 def __iadd__(self, other): 

753 return NotImplemented 

754 

755 def __isub__(self, other): 

756 return NotImplemented 

757 

758 def __imul__(self, other): 

759 return NotImplemented 

760 

761 def __idiv__(self, other): 

762 return self.__itruediv__(other) 

763 

764 def __itruediv__(self, other): 

765 return NotImplemented 

766 

767 def __pow__(self, *args, **kwargs): 

768 return self.power(*args, **kwargs) 

769 

770 def transpose(self, axes=None, copy=False): 

771 """ 

772 Reverses the dimensions of the sparse array/matrix. 

773 

774 Parameters 

775 ---------- 

776 axes : None, optional 

777 This argument is in the signature *solely* for NumPy 

778 compatibility reasons. Do not pass in anything except 

779 for the default value. 

780 copy : bool, optional 

781 Indicates whether or not attributes of `self` should be 

782 copied whenever possible. The degree to which attributes 

783 are copied varies depending on the type of sparse array/matrix 

784 being used. 

785 

786 Returns 

787 ------- 

788 p : `self` with the dimensions reversed. 

789 

790 See Also 

791 -------- 

792 numpy.transpose : NumPy's implementation of 'transpose' for ndarrays 

793 """ 

794 return self.tocsr(copy=copy).transpose(axes=axes, copy=False) 

795 

796 def conjugate(self, copy=True): 

797 """Element-wise complex conjugation. 

798 

799 If the array/matrix is of non-complex data type and `copy` is False, 

800 this method does nothing and the data is not copied. 

801 

802 Parameters 

803 ---------- 

804 copy : bool, optional 

805 If True, the result is guaranteed to not share data with self. 

806 

807 Returns 

808 ------- 

809 A : The element-wise complex conjugate. 

810 

811 """ 

812 if np.issubdtype(self.dtype, np.complexfloating): 

813 return self.tocsr(copy=copy).conjugate(copy=False) 

814 elif copy: 

815 return self.copy() 

816 else: 

817 return self 

818 

819 def conj(self, copy=True): 

820 return self.conjugate(copy=copy) 

821 

822 conj.__doc__ = conjugate.__doc__ 

823 

824 def _real(self): 

825 return self.tocsr()._real() 

826 

827 def _imag(self): 

828 return self.tocsr()._imag() 

829 

830 def nonzero(self): 

831 """Nonzero indices of the array/matrix. 

832 

833 Returns a tuple of arrays (row,col) containing the indices 

834 of the non-zero elements of the array. 

835 

836 Examples 

837 -------- 

838 >>> from scipy.sparse import csr_array 

839 >>> A = csr_array([[1,2,0],[0,0,3],[4,0,5]]) 

840 >>> A.nonzero() 

841 (array([0, 0, 1, 2, 2]), array([0, 1, 2, 0, 2])) 

842 

843 """ 

844 

845 # convert to COOrdinate format 

846 A = self.tocoo() 

847 nz_mask = A.data != 0 

848 return (A.row[nz_mask], A.col[nz_mask]) 

849 

850 def _getcol(self, j): 

851 """Returns a copy of column j of the array, as an (m x 1) sparse 

852 array (column vector). 

853 """ 

854 # Subclasses should override this method for efficiency. 

855 # Post-multiply by a (n x 1) column vector 'a' containing all zeros 

856 # except for a_j = 1 

857 n = self.shape[1] 

858 if j < 0: 

859 j += n 

860 if j < 0 or j >= n: 

861 raise IndexError("index out of bounds") 

862 col_selector = self._csc_container(([1], [[j], [0]]), 

863 shape=(n, 1), dtype=self.dtype) 

864 return self @ col_selector 

865 

866 def _getrow(self, i): 

867 """Returns a copy of row i of the array, as a (1 x n) sparse 

868 array (row vector). 

869 """ 

870 # Subclasses should override this method for efficiency. 

871 # Pre-multiply by a (1 x m) row vector 'a' containing all zeros 

872 # except for a_i = 1 

873 m = self.shape[0] 

874 if i < 0: 

875 i += m 

876 if i < 0 or i >= m: 

877 raise IndexError("index out of bounds") 

878 row_selector = self._csr_container(([1], [[0], [i]]), 

879 shape=(1, m), dtype=self.dtype) 

880 return row_selector @ self 

881 

882 # The following dunder methods cannot be implemented. 

883 # 

884 # def __array__(self): 

885 # # Sparse matrices rely on NumPy wrapping them in object arrays under 

886 # # the hood to make unary ufuncs work on them. So we cannot raise 

887 # # TypeError here - which would be handy to not give users object 

888 # # arrays they probably don't want (they're looking for `.toarray()`). 

889 # # 

890 # # Conversion with `toarray()` would also break things because of the 

891 # # behavior discussed above, plus we want to avoid densification by 

892 # # accident because that can too easily blow up memory. 

893 # 

894 # def __array_ufunc__(self): 

895 # # We cannot implement __array_ufunc__ due to mismatching semantics. 

896 # # See gh-7707 and gh-7349 for details. 

897 # 

898 # def __array_function__(self): 

899 # # We cannot implement __array_function__ due to mismatching semantics. 

900 # # See gh-10362 for details. 

901 

902 def todense(self, order=None, out=None): 

903 """ 

904 Return a dense representation of this sparse array/matrix. 

905 

906 Parameters 

907 ---------- 

908 order : {'C', 'F'}, optional 

909 Whether to store multi-dimensional data in C (row-major) 

910 or Fortran (column-major) order in memory. The default 

911 is 'None', which provides no ordering guarantees. 

912 Cannot be specified in conjunction with the `out` 

913 argument. 

914 

915 out : ndarray, 2-D, optional 

916 If specified, uses this array (or `numpy.matrix`) as the 

917 output buffer instead of allocating a new array to 

918 return. The provided array must have the same shape and 

919 dtype as the sparse array/matrix on which you are calling the 

920 method. 

921 

922 Returns 

923 ------- 

924 arr : numpy.matrix, 2-D 

925 A NumPy matrix object with the same shape and containing 

926 the same data represented by the sparse array/matrix, with the 

927 requested memory order. If `out` was passed and was an 

928 array (rather than a `numpy.matrix`), it will be filled 

929 with the appropriate values and returned wrapped in a 

930 `numpy.matrix` object that shares the same memory. 

931 """ 

932 return self._ascontainer(self.toarray(order=order, out=out)) 

933 

934 def toarray(self, order=None, out=None): 

935 """ 

936 Return a dense ndarray representation of this sparse array/matrix. 

937 

938 Parameters 

939 ---------- 

940 order : {'C', 'F'}, optional 

941 Whether to store multidimensional data in C (row-major) 

942 or Fortran (column-major) order in memory. The default 

943 is 'None', which provides no ordering guarantees. 

944 Cannot be specified in conjunction with the `out` 

945 argument. 

946 

947 out : ndarray, 2-D, optional 

948 If specified, uses this array as the output buffer 

949 instead of allocating a new array to return. The provided 

950 array must have the same shape and dtype as the sparse 

951 array/matrix on which you are calling the method. For most 

952 sparse types, `out` is required to be memory contiguous 

953 (either C or Fortran ordered). 

954 

955 Returns 

956 ------- 

957 arr : ndarray, 2-D 

958 An array with the same shape and containing the same 

959 data represented by the sparse array/matrix, with the requested 

960 memory order. If `out` was passed, the same object is 

961 returned after being modified in-place to contain the 

962 appropriate values. 

963 """ 

964 return self.tocoo(copy=False).toarray(order=order, out=out) 

965 

966 # Any sparse array format deriving from _spbase must define one of 

967 # tocsr or tocoo. The other conversion methods may be implemented for 

968 # efficiency, but are not required. 

969 def tocsr(self, copy=False): 

970 """Convert this array/matrix to Compressed Sparse Row format. 

971 

972 With copy=False, the data/indices may be shared between this array/matrix and 

973 the resultant csr_array/matrix. 

974 """ 

975 return self.tocoo(copy=copy).tocsr(copy=False) 

976 

977 def todok(self, copy=False): 

978 """Convert this array/matrix to Dictionary Of Keys format. 

979 

980 With copy=False, the data/indices may be shared between this array/matrix and 

981 the resultant dok_array/matrix. 

982 """ 

983 return self.tocoo(copy=copy).todok(copy=False) 

984 

985 def tocoo(self, copy=False): 

986 """Convert this array/matrix to COOrdinate format. 

987 

988 With copy=False, the data/indices may be shared between this array/matrix and 

989 the resultant coo_array/matrix. 

990 """ 

991 return self.tocsr(copy=False).tocoo(copy=copy) 

992 

993 def tolil(self, copy=False): 

994 """Convert this array/matrix to List of Lists format. 

995 

996 With copy=False, the data/indices may be shared between this array/matrix and 

997 the resultant lil_array/matrix. 

998 """ 

999 return self.tocsr(copy=False).tolil(copy=copy) 

1000 

1001 def todia(self, copy=False): 

1002 """Convert this array/matrix to sparse DIAgonal format. 

1003 

1004 With copy=False, the data/indices may be shared between this array/matrix and 

1005 the resultant dia_array/matrix. 

1006 """ 

1007 return self.tocoo(copy=copy).todia(copy=False) 

1008 

1009 def tobsr(self, blocksize=None, copy=False): 

1010 """Convert this array/matrix to Block Sparse Row format. 

1011 

1012 With copy=False, the data/indices may be shared between this array/matrix and 

1013 the resultant bsr_array/matrix. 

1014 

1015 When blocksize=(R, C) is provided, it will be used for construction of 

1016 the bsr_array/matrix. 

1017 """ 

1018 return self.tocsr(copy=False).tobsr(blocksize=blocksize, copy=copy) 

1019 

1020 def tocsc(self, copy=False): 

1021 """Convert this array/matrix to Compressed Sparse Column format. 

1022 

1023 With copy=False, the data/indices may be shared between this array/matrix and 

1024 the resultant csc_array/matrix. 

1025 """ 

1026 return self.tocsr(copy=copy).tocsc(copy=False) 

1027 

1028 def copy(self): 

1029 """Returns a copy of this array/matrix. 

1030 

1031 No data/indices will be shared between the returned value and current 

1032 array/matrix. 

1033 """ 

1034 return self.__class__(self, copy=True) 

1035 

1036 def sum(self, axis=None, dtype=None, out=None): 

1037 """ 

1038 Sum the array/matrix elements over a given axis. 

1039 

1040 Parameters 

1041 ---------- 

1042 axis : {-2, -1, 0, 1, None} optional 

1043 Axis along which the sum is computed. The default is to 

1044 compute the sum of all the array/matrix elements, returning a scalar 

1045 (i.e., `axis` = `None`). 

1046 dtype : dtype, optional 

1047 The type of the returned array/matrix and of the accumulator in which 

1048 the elements are summed. The dtype of `a` is used by default 

1049 unless `a` has an integer dtype of less precision than the default 

1050 platform integer. In that case, if `a` is signed then the platform 

1051 integer is used while if `a` is unsigned then an unsigned integer 

1052 of the same precision as the platform integer is used. 

1053 

1054 .. versionadded:: 0.18.0 

1055 

1056 out : np.matrix, optional 

1057 Alternative output matrix in which to place the result. It must 

1058 have the same shape as the expected output, but the type of the 

1059 output values will be cast if necessary. 

1060 

1061 .. versionadded:: 0.18.0 

1062 

1063 Returns 

1064 ------- 

1065 sum_along_axis : np.matrix 

1066 A matrix with the same shape as `self`, with the specified 

1067 axis removed. 

1068 

1069 See Also 

1070 -------- 

1071 numpy.matrix.sum : NumPy's implementation of 'sum' for matrices 

1072 

1073 """ 

1074 validateaxis(axis) 

1075 

1076 # We use multiplication by a matrix of ones to achieve this. 

1077 # For some sparse array formats more efficient methods are 

1078 # possible -- these should override this function. 

1079 m, n = self.shape 

1080 

1081 # Mimic numpy's casting. 

1082 res_dtype = get_sum_dtype(self.dtype) 

1083 

1084 if axis is None: 

1085 # sum over rows and columns 

1086 return ( 

1087 self @ self._ascontainer(np.ones((n, 1), dtype=res_dtype)) 

1088 ).sum(dtype=dtype, out=out) 

1089 

1090 if axis < 0: 

1091 axis += 2 

1092 

1093 # axis = 0 or 1 now 

1094 if axis == 0: 

1095 # sum over columns 

1096 ret = self._ascontainer( 

1097 np.ones((1, m), dtype=res_dtype) 

1098 ) @ self 

1099 else: 

1100 # sum over rows 

1101 ret = self @ self._ascontainer( 

1102 np.ones((n, 1), dtype=res_dtype) 

1103 ) 

1104 

1105 if out is not None and out.shape != ret.shape: 

1106 raise ValueError("dimensions do not match") 

1107 

1108 return ret.sum(axis=axis, dtype=dtype, out=out) 

1109 

1110 def mean(self, axis=None, dtype=None, out=None): 

1111 """ 

1112 Compute the arithmetic mean along the specified axis. 

1113 

1114 Returns the average of the array/matrix elements. The average is taken 

1115 over all elements in the array/matrix by default, otherwise over the 

1116 specified axis. `float64` intermediate and return values are used 

1117 for integer inputs. 

1118 

1119 Parameters 

1120 ---------- 

1121 axis : {-2, -1, 0, 1, None} optional 

1122 Axis along which the mean is computed. The default is to compute 

1123 the mean of all elements in the array/matrix (i.e., `axis` = `None`). 

1124 dtype : data-type, optional 

1125 Type to use in computing the mean. For integer inputs, the default 

1126 is `float64`; for floating point inputs, it is the same as the 

1127 input dtype. 

1128 

1129 .. versionadded:: 0.18.0 

1130 

1131 out : np.matrix, optional 

1132 Alternative output matrix in which to place the result. It must 

1133 have the same shape as the expected output, but the type of the 

1134 output values will be cast if necessary. 

1135 

1136 .. versionadded:: 0.18.0 

1137 

1138 Returns 

1139 ------- 

1140 m : np.matrix 

1141 

1142 See Also 

1143 -------- 

1144 numpy.matrix.mean : NumPy's implementation of 'mean' for matrices 

1145 

1146 """ 

1147 def _is_integral(dtype): 

1148 return (np.issubdtype(dtype, np.integer) or 

1149 np.issubdtype(dtype, np.bool_)) 

1150 

1151 validateaxis(axis) 

1152 

1153 res_dtype = self.dtype.type 

1154 integral = _is_integral(self.dtype) 

1155 

1156 # output dtype 

1157 if dtype is None: 

1158 if integral: 

1159 res_dtype = np.float64 

1160 else: 

1161 res_dtype = np.dtype(dtype).type 

1162 

1163 # intermediate dtype for summation 

1164 inter_dtype = np.float64 if integral else res_dtype 

1165 inter_self = self.astype(inter_dtype) 

1166 

1167 if axis is None: 

1168 return (inter_self / np.array( 

1169 self.shape[0] * self.shape[1]))\ 

1170 .sum(dtype=res_dtype, out=out) 

1171 

1172 if axis < 0: 

1173 axis += 2 

1174 

1175 # axis = 0 or 1 now 

1176 if axis == 0: 

1177 return (inter_self * (1.0 / self.shape[0])).sum( 

1178 axis=0, dtype=res_dtype, out=out) 

1179 else: 

1180 return (inter_self * (1.0 / self.shape[1])).sum( 

1181 axis=1, dtype=res_dtype, out=out) 

1182 

1183 def diagonal(self, k=0): 

1184 """Returns the kth diagonal of the array/matrix. 

1185 

1186 Parameters 

1187 ---------- 

1188 k : int, optional 

1189 Which diagonal to get, corresponding to elements a[i, i+k]. 

1190 Default: 0 (the main diagonal). 

1191 

1192 .. versionadded:: 1.0 

1193 

1194 See also 

1195 -------- 

1196 numpy.diagonal : Equivalent numpy function. 

1197 

1198 Examples 

1199 -------- 

1200 >>> from scipy.sparse import csr_array 

1201 >>> A = csr_array([[1, 2, 0], [0, 0, 3], [4, 0, 5]]) 

1202 >>> A.diagonal() 

1203 array([1, 0, 5]) 

1204 >>> A.diagonal(k=1) 

1205 array([2, 3]) 

1206 """ 

1207 return self.tocsr().diagonal(k=k) 

1208 

1209 def trace(self, offset=0): 

1210 """Returns the sum along diagonals of the sparse array/matrix. 

1211 

1212 Parameters 

1213 ---------- 

1214 offset : int, optional 

1215 Which diagonal to get, corresponding to elements a[i, i+offset]. 

1216 Default: 0 (the main diagonal). 

1217 

1218 """ 

1219 return self.diagonal(k=offset).sum() 

1220 

1221 def setdiag(self, values, k=0): 

1222 """ 

1223 Set diagonal or off-diagonal elements of the array/matrix. 

1224 

1225 Parameters 

1226 ---------- 

1227 values : array_like 

1228 New values of the diagonal elements. 

1229 

1230 Values may have any length. If the diagonal is longer than values, 

1231 then the remaining diagonal entries will not be set. If values are 

1232 longer than the diagonal, then the remaining values are ignored. 

1233 

1234 If a scalar value is given, all of the diagonal is set to it. 

1235 

1236 k : int, optional 

1237 Which off-diagonal to set, corresponding to elements a[i,i+k]. 

1238 Default: 0 (the main diagonal). 

1239 

1240 """ 

1241 M, N = self.shape 

1242 if (k > 0 and k >= N) or (k < 0 and -k >= M): 

1243 raise ValueError("k exceeds array dimensions") 

1244 self._setdiag(np.asarray(values), k) 

1245 

1246 def _setdiag(self, values, k): 

1247 """This part of the implementation gets overridden by the 

1248 different formats. 

1249 """ 

1250 M, N = self.shape 

1251 if k < 0: 

1252 if values.ndim == 0: 

1253 # broadcast 

1254 max_index = min(M+k, N) 

1255 for i in range(max_index): 

1256 self[i - k, i] = values 

1257 else: 

1258 max_index = min(M+k, N, len(values)) 

1259 if max_index <= 0: 

1260 return 

1261 for i, v in enumerate(values[:max_index]): 

1262 self[i - k, i] = v 

1263 else: 

1264 if values.ndim == 0: 

1265 # broadcast 

1266 max_index = min(M, N-k) 

1267 for i in range(max_index): 

1268 self[i, i + k] = values 

1269 else: 

1270 max_index = min(M, N-k, len(values)) 

1271 if max_index <= 0: 

1272 return 

1273 for i, v in enumerate(values[:max_index]): 

1274 self[i, i + k] = v 

1275 

1276 def _process_toarray_args(self, order, out): 

1277 if out is not None: 

1278 if order is not None: 

1279 raise ValueError('order cannot be specified if out ' 

1280 'is not None') 

1281 if out.shape != self.shape or out.dtype != self.dtype: 

1282 raise ValueError('out array must be same dtype and shape as ' 

1283 'sparse array') 

1284 out[...] = 0. 

1285 return out 

1286 else: 

1287 return np.zeros(self.shape, dtype=self.dtype, order=order) 

1288 

1289 def _get_index_dtype(self, arrays=(), maxval=None, check_contents=False): 

1290 """ 

1291 Determine index dtype for array. 

1292 

1293 This wraps _sputils.get_index_dtype, providing compatibility for both 

1294 array and matrix API sparse matrices. Matrix API sparse matrices would 

1295 attempt to downcast the indices - which can be computationally 

1296 expensive and undesirable for users. The array API changes this 

1297 behaviour. 

1298 

1299 See discussion: https://github.com/scipy/scipy/issues/16774 

1300 

1301 The get_index_dtype import is due to implementation details of the test 

1302 suite. It allows the decorator ``with_64bit_maxval_limit`` to mock a 

1303 lower int32 max value for checks on the matrix API's downcasting 

1304 behaviour. 

1305 """ 

1306 from ._sputils import get_index_dtype 

1307 

1308 # Don't check contents for array API 

1309 return get_index_dtype(arrays, maxval, (check_contents and not isinstance(self, sparray))) 

1310 

1311 

1312 ## All methods below are deprecated and should be removed in 

1313 ## scipy 1.13.0 

1314 ## 

1315 ## Also uncomment the definition of shape above. 

1316 

1317 def get_shape(self): 

1318 """Get shape of a sparse array/matrix. 

1319 

1320 .. deprecated:: 1.11.0 

1321 This method will be removed in SciPy 1.13.0. 

1322 Use `X.shape` instead. 

1323 """ 

1324 msg = ( 

1325 "`get_shape` is deprecated and will be removed in v1.13.0; " 

1326 "use `X.shape` instead." 

1327 ) 

1328 warn(msg, DeprecationWarning, stacklevel=2) 

1329 

1330 return self._shape 

1331 

1332 def set_shape(self, shape): 

1333 """See `reshape`. 

1334 

1335 .. deprecated:: 1.11.0 

1336 This method will be removed in SciPy 1.13.0. 

1337 Use `X.reshape` instead. 

1338 """ 

1339 msg = ( 

1340 "Shape assignment is deprecated and will be removed in v1.13.0; " 

1341 "use `reshape` instead." 

1342 ) 

1343 warn(msg, DeprecationWarning, stacklevel=2) 

1344 

1345 # Make sure copy is False since this is in place 

1346 # Make sure format is unchanged because we are doing a __dict__ swap 

1347 new_self = self.reshape(shape, copy=False).asformat(self.format) 

1348 self.__dict__ = new_self.__dict__ 

1349 

1350 shape = property( 

1351 fget=lambda self: self._shape, 

1352 fset=set_shape, 

1353 doc="""The shape of the array. 

1354 

1355Note that, starting in SciPy 1.13.0, this property will no longer be 

1356settable. To change the array shape, use `X.reshape` instead. 

1357""" 

1358 ) # noqa: F811 

1359 

1360 def asfptype(self): 

1361 """Upcast array/matrix to a floating point format (if necessary) 

1362 

1363 .. deprecated:: 1.11.0 

1364 This method is for internal use only, and will be removed from the 

1365 public API in SciPy 1.13.0. 

1366 """ 

1367 msg = ( 

1368 "`asfptype` is an internal function, and is deprecated " 

1369 "as part of the public API. It will be removed in v1.13.0." 

1370 ) 

1371 warn(msg, DeprecationWarning, stacklevel=2) 

1372 return self._asfptype() 

1373 

1374 def getmaxprint(self): 

1375 """Maximum number of elements to display when printed. 

1376 

1377 .. deprecated:: 1.11.0 

1378 This method is for internal use only, and will be removed from the 

1379 public API in SciPy 1.13.0. 

1380 """ 

1381 msg = ( 

1382 "`getmaxprint` is an internal function, and is deprecated " 

1383 "as part of the public API. It will be removed in v1.13.0." 

1384 ) 

1385 warn(msg, DeprecationWarning, stacklevel=2) 

1386 return self._getmaxprint() 

1387 

1388 def getformat(self): 

1389 """Sparse array/matrix storage format. 

1390 

1391 .. deprecated:: 1.11.0 

1392 This method will be removed in SciPy 1.13.0. 

1393 Use `X.format` instead. 

1394 """ 

1395 msg = ( 

1396 "`getformat` is deprecated and will be removed in v1.13.0; " 

1397 "use `X.format` instead." 

1398 ) 

1399 warn(msg, DeprecationWarning, stacklevel=2) 

1400 return self.format 

1401 

1402 def getnnz(self, axis=None): 

1403 """Number of stored values, including explicit zeros. 

1404 

1405 .. deprecated:: 1.11.0 

1406 This method will be removed in SciPy 1.13.0. Use `X.nnz` 

1407 instead. The `axis` argument will no longer be supported; 

1408 please let us know if you still need this functionality. 

1409 

1410 Parameters 

1411 ---------- 

1412 axis : None, 0, or 1 

1413 Select between the number of values across the whole array/matrix, in 

1414 each column, or in each row. 

1415 

1416 See also 

1417 -------- 

1418 count_nonzero : Number of non-zero entries 

1419 """ 

1420 msg = ( 

1421 "`getnnz` is deprecated and will be removed in v1.13.0; " 

1422 "use `X.nnz` instead." 

1423 ) 

1424 warn(msg, DeprecationWarning, stacklevel=2) 

1425 return self._getnnz(axis=axis) 

1426 

1427 def getH(self): 

1428 """Return the Hermitian transpose of this array/matrix. 

1429 

1430 .. deprecated:: 1.11.0 

1431 This method will be removed in SciPy 1.13.0. 

1432 Use `X.conj().T` instead. 

1433 """ 

1434 msg = ( 

1435 "`getH` is deprecated and will be removed in v1.13.0; " 

1436 "use `X.conj().T` instead." 

1437 ) 

1438 warn(msg, DeprecationWarning, stacklevel=2) 

1439 return self.conjugate().transpose() 

1440 

1441 def getcol(self, j): 

1442 """Returns a copy of column j of the array/matrix, as an (m x 1) sparse 

1443 array/matrix (column vector). 

1444 

1445 .. deprecated:: 1.11.0 

1446 This method will be removed in SciPy 1.13.0. 

1447 Use array/matrix indexing instead. 

1448 """ 

1449 msg = ( 

1450 "`getcol` is deprecated and will be removed in v1.13.0; " 

1451 f"use `X[:, [{j}]]` instead." 

1452 ) 

1453 warn(msg, DeprecationWarning, stacklevel=2) 

1454 return self._getcol(j) 

1455 

1456 def getrow(self, i): 

1457 """Returns a copy of row i of the array/matrix, as a (1 x n) sparse 

1458 array/matrix (row vector). 

1459 

1460 .. deprecated:: 1.11.0 

1461 This method will be removed in SciPy 1.13.0. 

1462 Use array/matrix indexing instead. 

1463 """ 

1464 msg = ( 

1465 "`getrow` is deprecated and will be removed in v1.13.0; " 

1466 f"use `X[[{i}]]` instead." 

1467 ) 

1468 warn(msg, DeprecationWarning, stacklevel=2) 

1469 return self._getrow(i) 

1470 

1471 ## End 1.13.0 deprecated methods 

1472 

1473 

1474class sparray: 

1475 """A namespace class to separate sparray from spmatrix""" 

1476 pass 

1477 

1478sparray.__doc__ = _spbase.__doc__ 

1479 

1480 

1481def issparse(x): 

1482 """Is `x` of a sparse array or sparse matrix type? 

1483 

1484 Parameters 

1485 ---------- 

1486 x 

1487 object to check for being a sparse array or sparse matrix 

1488 

1489 Returns 

1490 ------- 

1491 bool 

1492 True if `x` is a sparse array or a sparse matrix, False otherwise 

1493 

1494 Examples 

1495 -------- 

1496 >>> import numpy as np 

1497 >>> from scipy.sparse import csr_array, csr_matrix, issparse 

1498 >>> issparse(csr_matrix([[5]])) 

1499 True 

1500 >>> issparse(csr_array([[5]])) 

1501 True 

1502 >>> issparse(np.array([[5]])) 

1503 False 

1504 >>> issparse(5) 

1505 False 

1506 """ 

1507 return isinstance(x, _spbase) 

1508 

1509 

1510def isspmatrix(x): 

1511 """Is `x` of a sparse matrix type? 

1512 

1513 Parameters 

1514 ---------- 

1515 x 

1516 object to check for being a sparse matrix 

1517 

1518 Returns 

1519 ------- 

1520 bool 

1521 True if `x` is a sparse matrix, False otherwise 

1522 

1523 Examples 

1524 -------- 

1525 >>> import numpy as np 

1526 >>> from scipy.sparse import csr_array, csr_matrix, isspmatrix 

1527 >>> isspmatrix(csr_matrix([[5]])) 

1528 True 

1529 >>> isspmatrix(csr_array([[5]])) 

1530 False 

1531 >>> isspmatrix(np.array([[5]])) 

1532 False 

1533 >>> isspmatrix(5) 

1534 False 

1535 """ 

1536 return isinstance(x, spmatrix)