[Scipy-svn] r3750 - in trunk/scipy/sparse: . tests

scipy-svn at scipy.org scipy-svn at scipy.org
Sun Dec 30 19:53:58 EST 2007


Author: wnbell
Date: 2007-12-30 18:53:54 -0600 (Sun, 30 Dec 2007)
New Revision: 3750

Modified:
   trunk/scipy/sparse/base.py
   trunk/scipy/sparse/compressed.py
   trunk/scipy/sparse/coo.py
   trunk/scipy/sparse/csc.py
   trunk/scipy/sparse/csr.py
   trunk/scipy/sparse/dia.py
   trunk/scipy/sparse/tests/test_base.py
Log:
consolidated csr/csc_matrix setitem
added SparseEfficiencyWarning


Modified: trunk/scipy/sparse/base.py
===================================================================
--- trunk/scipy/sparse/base.py	2007-12-30 11:09:48 UTC (rev 3749)
+++ trunk/scipy/sparse/base.py	2007-12-31 00:53:54 UTC (rev 3750)
@@ -1,6 +1,7 @@
 """Base class for sparse matrices"""
 
-__all__ = ['spmatrix','isspmatrix','issparse']
+__all__ = ['spmatrix', 'isspmatrix', 'issparse',
+        'SparseWarning','SparseEfficiencyWarning']
 
 from warnings import warn
 
@@ -9,6 +10,11 @@
 from sputils import isdense, isscalarlike, isintlike
 
 
+class SparseWarning(Warning): pass
+class SparseFormatWarning(SparseWarning): pass
+class SparseEfficiencyWarning(SparseWarning): pass
+
+
 # The formats that we might potentially understand.
 _formats = {'csc':[0, "Compressed Sparse Column"],
             'csr':[1, "Compressed Sparse Row"],
@@ -273,7 +279,7 @@
             raise ValueError,'exponent must be an integer'
         elif isspmatrix(other):
             warn('Using ** for elementwise multiplication is deprecated.'\
-                    'Use .multiply() instead',DeprecationWarning)
+                    'Use .multiply() instead', DeprecationWarning)
             return self.multiply(other)
         else:
             raise NotImplementedError
@@ -477,6 +483,7 @@
 
     def save(self, file_name, format = '%d %d %f\n'):
         #deprecated on Dec 14 2007
+        #remove after 0.7 release
         warn('save() is deprecated, consider using mmwrite() or savemat()' \
                 ' provided by scipy.io instead',
                 DeprecationWarning)

Modified: trunk/scipy/sparse/compressed.py
===================================================================
--- trunk/scipy/sparse/compressed.py	2007-12-30 11:09:48 UTC (rev 3749)
+++ trunk/scipy/sparse/compressed.py	2007-12-31 00:53:54 UTC (rev 3750)
@@ -8,9 +8,9 @@
 import numpy
 from numpy import array, matrix, asarray, asmatrix, zeros, rank, intc, \
         empty, hstack, isscalar, ndarray, shape, searchsorted, empty_like, \
-        where
+        where, concatenate
 
-from base import spmatrix, isspmatrix
+from base import spmatrix, isspmatrix, SparseEfficiencyWarning
 from data import _data_matrix
 import sparsetools
 from sputils import upcast, to_native, isdense, isshape, getdtype, \
@@ -35,7 +35,7 @@
             warn("dims= is deprecated, use shape= instead", DeprecationWarning)
             shape=dims
         
-        if dims is not None:
+        if nzmax is not None:
             warn("nzmax= is deprecated", DeprecationWarning)
 
 
@@ -393,9 +393,9 @@
     def _get_single_element(self,row,col):
         M, N = self.shape
         if (row < 0):
-            row = M + row
+            row += M
         if (col < 0):
-            col = N + col
+            col += N
         if not (0<=row<M) or not (0<=col<N):
             raise IndexError, "index out of bounds"
         
@@ -466,7 +466,59 @@
         return self.__class__((data, index, indptr), shape=shape, \
                               dtype=self.dtype)
 
+    def __setitem__(self, key, val):
+        if isinstance(key, tuple):
+            row,col = key
+            if not (isscalarlike(row) and isscalarlike(col)):
+                raise NotImplementedError("Fancy indexing in assignment not "
+                                          "supported for csr matrices.")
+            M, N = self.shape
+            if (row < 0):
+                row += M
+            if (col < 0):
+                col += N
+            if not (0<=row<M) or not (0<=col<N):
+                raise IndexError, "index out of bounds"
+        
+            major_index, minor_index = self._swap((row,col))
+        
+            start = self.indptr[major_index]
+            end   = self.indptr[major_index+1]
+            indxs = where(minor_index == self.indices[start:end])[0]
 
+            num_matches = len(indxs)
+
+            if num_matches == 0:
+                #entry not already present
+                warn('changing the sparsity structure of a %s_matrix is expensive. ' \
+                        'lil_matrix is more efficient.' % self.format, \
+                        SparseEfficiencyWarning)
+                self.sort_indices()
+   
+                #no harm if not sorted
+                newindx = self.indices[start:end].searchsorted(minor_index)
+                newindx += start
+
+                val = array([val],dtype=self.data.dtype)
+                minor_index = array([minor_index],dtype=self.indices.dtype)
+                self.data    = concatenate((self.data[:newindx],val,self.data[newindx:]))
+                self.indices = concatenate((self.indices[:newindx],minor_index,self.indices[newindx:]))
+
+                self.indptr[major_index+1:] += 1
+
+            elif num_matches == 1:
+                #entry appears exactly once
+                self.data[start:end][indxs[0]] = val
+            else:
+                #entry appears more than once
+                raise ValueError,'nonzero entry (%d,%d) occurs more than once' % (row,col)
+
+            self.check_format(full_check=True)
+        else:
+            # We should allow slices here!
+            raise IndexError, "invalid index"
+
+
     # conversion methods
     def todia(self):
         return self.tocoo(copy=False).todia()

Modified: trunk/scipy/sparse/coo.py
===================================================================
--- trunk/scipy/sparse/coo.py	2007-12-30 11:09:48 UTC (rev 3749)
+++ trunk/scipy/sparse/coo.py	2007-12-31 00:53:54 UTC (rev 3750)
@@ -248,7 +248,8 @@
                       indptr, indices, data)
 
             A = csc_matrix((data, indices, indptr), self.shape)
-            A.sum_duplicates()
+            if sum_duplicates:
+                A.sum_duplicates()
             return A
 
     def tocsr(self,sum_duplicates=True):
@@ -272,7 +273,6 @@
 
             A = csr_matrix((data, indices, indptr), self.shape)
             if sum_duplicates:
-                A.sort_indices()
                 A.sum_duplicates()
             return A
     

Modified: trunk/scipy/sparse/csc.py
===================================================================
--- trunk/scipy/sparse/csc.py	2007-12-30 11:09:48 UTC (rev 3749)
+++ trunk/scipy/sparse/csc.py	2007-12-31 00:53:54 UTC (rev 3750)
@@ -9,7 +9,7 @@
         empty, hstack, isscalar, ndarray, shape, searchsorted, where, \
         concatenate
 
-from base import spmatrix,isspmatrix
+from base import spmatrix, isspmatrix
 from sparsetools import csc_tocsr
 from sputils import upcast, to_native, isdense, isshape, getdtype, \
         isscalarlike
@@ -104,52 +104,6 @@
         for r in xrange(self.shape[0]):
             yield csr[r,:]
 
-    def __setitem__(self, key, val):
-        if isinstance(key, tuple):
-            row = key[0]
-            col = key[1]
-            if not (isscalarlike(row) and isscalarlike(col)):
-                raise NotImplementedError("Fancy indexing in assignments not"
-                                          "supported for csc matrices.")
-            M, N = self.shape
-            if (row < 0):
-                row = M + row
-            if (col < 0):
-                col = N + col
-            if (row < 0) or (col < 0):
-                raise IndexError, "index out of bounds"
-            if (col >= N):
-                self.indptr = resize1d(self.indptr, col+2)
-                self.indptr[N+1:] = self.indptr[N]
-                N = col+1
-            if (row >= M):
-                M = row+1
-            self.shape = (M, N)
-
-            indxs = numpy.where(row == self.indices[self.indptr[col]:self.indptr[col+1]])
-    
-            if len(indxs[0]) == 0:
-                #value not present
-                newindx = self.indices[self.indptr[col]:self.indptr[col+1]].searchsorted(row)
-                newindx += self.indptr[col]
-
-                val = array([val],dtype=self.data.dtype)
-                row = array([row],dtype=self.indices.dtype)
-                self.data    = concatenate((self.data[:newindx],val,self.data[newindx:]))
-                self.indices = concatenate((self.indices[:newindx],row,self.indices[newindx:]))
-
-                self.indptr[col+1:] += 1
-            elif len(indxs[0]) == 1:
-                #value already present
-                self.data[self.indptr[col]:self.indptr[col+1]][indxs[0]] = val
-            else:
-                raise IndexError, "row index occurs more than once"
-
-            self.check_format(full_check=False)
-        else:
-            # We should allow slices here!
-            raise IndexError, "invalid index"
-
     def rowcol(self, ind):
         row = self.indices[ind]
         col = searchsorted(self.indptr, ind+1)-1
@@ -173,17 +127,8 @@
         from csr import csr_matrix
         return csr_matrix((data, indices, indptr), self.shape)
 
-#    def tobsc(self,blocksize=None, copy=True):
-#        if blocksize in [None, (1,1)]:
-#            from bsc import bsc_matrix
-#            arg1 = (self.data.reshape(-1,1,1),self.indices,self.indptr)  
-#            return bsc_matrix( arg1, shape=self.shape, copy=copy )
-#        else:
-#            #TODO make this more efficient
-#            return self.tocoo(copy=False).tobsc(blocksize=blocksize)
-#    
     def tobsr(self, blocksize=None):
-        if blocksize in [None, (1,1)]:
+        if blocksize == (1,1):
             from bsr import bsr_matrix
             csr = self.tocsr()
             arg1 = (csr.data.reshape(-1,1,1),csr.indices,csr.indptr)  

Modified: trunk/scipy/sparse/csr.py
===================================================================
--- trunk/scipy/sparse/csr.py	2007-12-30 11:09:48 UTC (rev 3749)
+++ trunk/scipy/sparse/csr.py	2007-12-31 00:53:54 UTC (rev 3750)
@@ -10,7 +10,7 @@
         empty, hstack, isscalar, ndarray, shape, searchsorted, where, \
         concatenate
 
-from base import spmatrix,isspmatrix
+from base import spmatrix, isspmatrix
 from sparsetools import csr_tocsc
 from sputils import upcast, to_native, isdense, isshape, getdtype, \
         isscalarlike, isintlike
@@ -102,54 +102,6 @@
         return csc_matrix((self.data,self.indices,self.indptr),(N,M),copy=copy)
 
 
-    def __setitem__(self, key, val):
-        if isinstance(key, tuple):
-            row = key[0]
-            col = key[1]
-            if not (isscalarlike(row) and isscalarlike(col)):
-                raise NotImplementedError("Fancy indexing in assignment not "
-                                          "supported for csr matrices.")
-            M, N = self.shape
-            if (row < 0):
-                row = M + row
-            if (col < 0):
-                col = N + col
-            if (row < 0) or (col < 0):
-                raise IndexError, "index out of bounds"
-            if (row >= M):
-                self.indptr = resize1d(self.indptr, row+2)
-                self.indptr[M+1:] = self.indptr[M]
-                M = row+1
-            if (col >= N):
-                N = col+1
-            self.shape = (M, N)
-
-            indxs = numpy.where(col == self.indices[self.indptr[row]:self.indptr[row+1]])
-
-            if len(indxs[0]) == 0:
-                #value not present
-                self.sort_indices()
-                newindx = self.indices[self.indptr[row]:self.indptr[row+1]].searchsorted(col)
-                newindx += self.indptr[row]
-
-                val = array([val],dtype=self.data.dtype)
-                col = array([col],dtype=self.indices.dtype)
-                self.data    = concatenate((self.data[:newindx],val,self.data[newindx:]))
-                self.indices = concatenate((self.indices[:newindx],col,self.indices[newindx:]))
-
-                self.indptr[row+1:] += 1
-
-            elif len(indxs[0]) == 1:
-                #value already present
-                self.data[self.indptr[row]:self.indptr[row+1]][indxs[0]] = val
-            else:
-                raise IndexError, "row index occurs more than once"
-
-            self.check_format(full_check=True)
-        else:
-            # We should allow slices here!
-            raise IndexError, "invalid index"
-
     def rowcol(self, ind):
         col = self.indices[ind]
         row = searchsorted(self.indptr, ind+1)-1
@@ -192,7 +144,7 @@
         return csc_matrix((data, indices, indptr), self.shape)
 
     def tobsr(self,blocksize=None,copy=True):
-        if blocksize in [None, (1,1)]:
+        if blocksize == (1,1):
             from bsr import bsr_matrix
             arg1 = (self.data.reshape(-1,1,1),self.indices,self.indptr)  
             return bsr_matrix( arg1, shape=self.shape, copy=copy )

Modified: trunk/scipy/sparse/dia.py
===================================================================
--- trunk/scipy/sparse/dia.py	2007-12-30 11:09:48 UTC (rev 3749)
+++ trunk/scipy/sparse/dia.py	2007-12-31 00:53:54 UTC (rev 3750)
@@ -208,12 +208,12 @@
             return self
 
     def tocsr(self):
-        #TODO optimize COO->CSR
-        return self.tocoo().tocsr()
+        #this could be faster
+        return self.tocoo().tocsr(sum_duplicates=False)
 
     def tocsc(self):
-        #TODO optimize COO->CSC
-        return self.tocoo().tocsc()
+        #this could be faster
+        return self.tocoo().tocsc(sum_duplicates=False)
 
     def tocoo(self):
         num_data = len(self.data)

Modified: trunk/scipy/sparse/tests/test_base.py
===================================================================
--- trunk/scipy/sparse/tests/test_base.py	2007-12-30 11:09:48 UTC (rev 3749)
+++ trunk/scipy/sparse/tests/test_base.py	2007-12-31 00:53:54 UTC (rev 3750)
@@ -22,7 +22,7 @@
 set_package_path()
 from scipy.sparse import csc_matrix, csr_matrix, dok_matrix, \
         coo_matrix, lil_matrix, dia_matrix, bsr_matrix, \
-        extract_diagonal, speye, spkron
+        extract_diagonal, speye, spkron, SparseEfficiencyWarning
 from scipy.linsolve import splu
 restore_path()
 
@@ -482,6 +482,8 @@
 
 class _TestGetSet:
     def check_setelement(self):
+        import warnings
+        warnings.simplefilter('ignore',SparseEfficiencyWarning)
         a = self.spmatrix((3,4))
         a[1,2] = 4.0
         a[0,1] = 3




More information about the Scipy-svn mailing list