[Scipy-svn] r3160 - in trunk/Lib/sparse: . tests
scipy-svn@scip...
scipy-svn@scip...
Thu Jul 12 03:06:52 CDT 2007
Author: wnbell
Date: 2007-07-12 03:06:38 -0500 (Thu, 12 Jul 2007)
New Revision: 3160
Modified:
trunk/Lib/sparse/sparse.py
trunk/Lib/sparse/tests/test_sparse.py
Log:
reworked sum() for efficiency and simplicity. added unittests. added abs() to sparse matrices.
Modified: trunk/Lib/sparse/sparse.py
===================================================================
--- trunk/Lib/sparse/sparse.py 2007-07-12 07:23:55 UTC (rev 3159)
+++ trunk/Lib/sparse/sparse.py 2007-07-12 08:06:38 UTC (rev 3160)
@@ -1,8 +1,7 @@
""" Scipy 2D sparse matrix module.
Original code by Travis Oliphant.
-Modified and extended by Ed Schofield and Robert Cimrman.
-Revision of sparsetools by Nathan Bell
+Modified and extended by Ed Schofield, Robert Cimrman, and Nathan Bell
"""
import warnings
@@ -182,11 +181,15 @@
# and operations return in csc format
# thus, a new sparse matrix format just needs to define
# a tocsc method
+
+ def __abs__(self):
+ csc = self.tocsc()
+ return abs(csc)
def __add__(self, other):
csc = self.tocsc()
return csc + other
-
+
def __radd__(self, other): # other + self
csc = self.tocsc()
return csc.__radd__(other)
@@ -201,8 +204,12 @@
def __mul__(self, other):
csc = self.tocsc()
- return csc * other
+ return csc.__mul__(other)
+ def __rmul__(self, other):
+ csc = self.tocsc()
+ return csc.__rmul__(other)
+
def __truediv__(self, other):
if isscalarlike(other):
return self * (1./other)
@@ -219,11 +226,7 @@
def __pow__(self, other):
csc = self.tocsc()
return csc ** other
-
- def __rmul__(self, other):
- csc = self.tocsc()
- return csc.__rmul__(other)
-
+
def __neg__(self):
csc = self.tocsc()
return -csc
@@ -405,10 +408,8 @@
return self * o
elif axis == None:
# sum over rows and columns
- m, n = self.shape
- o0 = asmatrix(ones((1, m), dtype=self.dtype))
o1 = asmatrix(ones((n, 1), dtype=self.dtype))
- return (o0 * (self * o1)).A.squeeze()
+ return (self * o1).sum()
else:
raise ValueError, "axis out of bounds"
@@ -480,15 +481,17 @@
"elements (space for %d)\n\tin %s format>" % \
(self.shape + (self.dtype.type, self.getnnz(), self.nzmax, \
_formats[format][1]))
-
-
-
+
+ def __abs__(self):
+ return self.__class__((abs(self.data),self.indices.copy(),self.indptr.copy()), \
+ dims=self.shape,dtype=self.dtype,check=False)
+
def __add__(self, other, fn):
# First check if argument is a scalar
if isscalarlike(other):
# Now we would add this scalar to every element.
raise NotImplementedError, 'adding a scalar to a CSC or CSR ' \
- 'matrix is not yet supported'
+ 'matrix is not supported'
elif isspmatrix(other):
other = other.tocsc()
if (other.shape != self.shape):
@@ -506,26 +509,19 @@
raise TypeError, "unsupported type for sparse matrix addition"
- def __mul__(self, other):
+ def __mul__(self, other): # self * other
""" Scalar, vector, or matrix multiplication
"""
if isscalarlike(other):
- new = self.copy()
- new.data = other * new.data # allows type conversion
- new.dtype = new.data.dtype
- new.ftype = _transtabl[new.dtype.char]
- return new
+ return self.__class__((self.data * other, self.indices.copy(), self.indptr.copy()), \
+ dims=self.shape, check=False)
else:
return self.dot(other)
- def __rmul__(self, other): # other * self
+ def __rmul__(self, other): # other * self
if isscalarlike(other):
- new = self.copy()
- new.data = other * new.data # allows type conversion
- new.dtype = new.data.dtype
- new.ftype = _transtabl[new.dtype.char]
- return new
+ return self * other # use __mul__
else:
# Don't use asarray unless we have to
try:
@@ -545,7 +541,7 @@
case return the matrix power.)
"""
if isscalarlike(other):
- return self.__class_((self.data ** other, self.indices.copy(), self.indptr.copy()), \
+ return self.__class__((self.data ** other, self.indices.copy(), self.indptr.copy()), \
dims=self.shape, check=False)
elif isspmatrix(other):
@@ -615,7 +611,20 @@
self.indptr, self.indices, self.data)
return coo_matrix((data, (rows, cols)), self.shape)
+
+ def sum(self, axis=None):
+ """Sum the matrix over the given axis. If the axis is None, sum
+ over both rows and columns, returning a scalar.
+ """
+ # The spmatrix base class already does axis=0 and axis=1 efficiently
+ # so we only do the case axis=None here
+ if axis == None:
+ return self.data[:self.indptr[-1]].sum()
+ else:
+ return spmatrix.sum(self,axis)
+ raise ValueError, "axis out of bounds"
+
def copy(self):
return self.__class__((self.data.copy(),self.indices.copy(),self.indptr.copy()), \
self.shape, dtype=self.dtype, check=False)
@@ -867,7 +876,7 @@
"""
if isscalarlike(other):
raise NotImplementedError, 'adding a scalar to a CSC matrix is ' \
- 'not yet supported'
+ 'not supported'
elif isspmatrix(other):
ocs = other.tocsc()
if (ocs.shape != self.shape):
@@ -888,40 +897,15 @@
def __pow__(self, other):
return _cs_matrix.__pow__(self, other, cscelmulcsc)
+
+
def transpose(self, copy=False):
return _cs_matrix._transpose(self, csr_matrix, copy)
-
def conj(self, copy=False):
return _cs_matrix.conj(self, copy)
- def sum(self, axis=None):
- # Override the base class sum method for efficiency in the cases
- # axis=0 and axis=None.
- m, n = self.shape
- data = self.data
- if axis in (0, None):
- out = empty(n, dtype=self.dtype)
- # The first element in column j has index indptr[j], the last
- # indptr[j+1]
- indptr = self.indptr
- for i in xrange(n):
- out[i] = data[indptr[i] : indptr[i+1]].sum()
- if axis == 0:
- # Output is a (1 x n) dense matrix
- return asmatrix(out)
- else:
- return out.sum()
- else:
- index = self.indices
- out = zeros(m, dtype=self.dtype)
- # Loop over non-zeros
- for k in xrange(self.nnz):
- out[index[k]] += data[k]
- # Output is a (m x 1) dense matrix
- return asmatrix(out).T
-
def matvec(self, other):
return _cs_matrix._matvec(self, other, cscmux)
@@ -1258,39 +1242,12 @@
def conj(self, copy=False):
return _cs_matrix.conj(self, copy)
- def sum(self, axis=None):
- # Override the base class sum method for efficiency in the cases
- # axis=1 and axis=None.
- m, n = self.shape
- data = self.data
- if axis in (1, None):
- out = empty(m, dtype=self.dtype)
- # The first element in row i has index indptr[i], the last
- # indptr[i+1]
- indptr = self.indptr
- for i in xrange(m):
- out[i] = data[indptr[i] : indptr[i+1]].sum()
- if axis == 1:
- # Output is a (m x 1) dense matrix
- return asmatrix(out).T
- else:
- return out.sum()
- else:
- index = self.indices
- out = zeros(n, dtype=self.dtype)
- # Loop over non-zeros
- for k in xrange(self.nnz):
- out[index[k]] += data[k]
- # Output is a (1 x n) dense matrix
- return asmatrix(out)
-
def matvec(self, other):
return _cs_matrix._matvec(self, other, csrmux)
def matmat(self, other):
return _cs_matrix._matmat(self, other, csrmucsr)
-
def __getitem__(self, key):
if isinstance(key, tuple):
row = key[0]
Modified: trunk/Lib/sparse/tests/test_sparse.py
===================================================================
--- trunk/Lib/sparse/tests/test_sparse.py 2007-07-12 07:23:55 UTC (rev 3159)
+++ trunk/Lib/sparse/tests/test_sparse.py 2007-07-12 08:06:38 UTC (rev 3160)
@@ -38,6 +38,10 @@
assert_equal(self.datsp[1,0],3)
assert_equal(self.datsp[2,1],2)
+ def check_abs(self):
+ A = matrix([[-1, 0, 17],[0, -5, 0],[1, -4, 0],[0,0,0]],'d')
+ assert_equal(abs(A),abs(self.spmatrix(A)).todense())
+
def check_sum(self):
"""Does the matrix's sum(,axis=0) method work?
"""
@@ -88,6 +92,14 @@
a[-1,-2] = 7
assert_array_equal(a.todense(),[[0,3,0,8],[0,0,4,0],[2,0,7,0]])
+ def check_mul_scalar(self):
+ assert_array_equal(self.dat*2,(self.datsp*2).todense())
+ assert_array_equal(self.dat*17.3,(self.datsp*17.3).todense())
+
+ def check_rmul_scalar(self):
+ assert_array_equal(2*self.dat,(2*self.datsp).todense())
+ assert_array_equal(17.3*self.dat,(17.3*self.datsp).todense())
+
def check_add(self):
a = self.datsp
b = self.datsp.copy()
More information about the Scipy-svn
mailing list