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

scipy-svn at scipy.org scipy-svn at scipy.org
Wed Dec 19 12:37:36 EST 2007


Author: wnbell
Date: 2007-12-19 11:37:30 -0600 (Wed, 19 Dec 2007)
New Revision: 3689

Modified:
   trunk/scipy/sparse/compressed.py
   trunk/scipy/sparse/coo.py
   trunk/scipy/sparse/dia.py
   trunk/scipy/sparse/dok.py
   trunk/scipy/sparse/tests/test_base.py
Log:
allow all sparse matrices to be initialized with dense matrices and anything that works in asarray()
added a few related unittests



Modified: trunk/scipy/sparse/compressed.py
===================================================================
--- trunk/scipy/sparse/compressed.py	2007-12-19 02:08:27 UTC (rev 3688)
+++ trunk/scipy/sparse/compressed.py	2007-12-19 17:37:30 UTC (rev 3689)
@@ -37,19 +37,8 @@
         if dims is not None:
             warn("nzmax= is deprecated", DeprecationWarning)
 
-        if isdense(arg1):
-            # Convert the dense array or matrix arg1 to sparse format
-            if rank(arg1) == 1:
-                # Convert to a row vector
-                arg1 = arg1.reshape(1, arg1.shape[0])
-            if rank(arg1) == 2:
-                from coo import coo_matrix
-                self.shape = arg1.shape
-                self._set_self( self.__class__(coo_matrix(arg1)) )
-            else:
-                raise ValueError, "dense array must have rank 1 or 2"
 
-        elif isspmatrix(arg1):
+        if isspmatrix(arg1):
             if arg1.format == self.format and copy:
                 arg1 = arg1.copy()
             else:
@@ -75,16 +64,21 @@
                     # (data, indices, indptr) format
                     (data, indices, indptr) = arg1
                     self.indices = array(indices, copy=copy)
-                    self.indptr  = array(indptr,  copy=copy)
-                    self.data    = array(data,    copy=copy, \
-                            dtype=getdtype(dtype, data))
+                    self.indptr  = array(indptr, copy=copy)
+                    self.data    = array(data, copy=copy, dtype=getdtype(dtype, data))
                 else:
                     raise ValueError, "unrecognized form for" \
                             " %s_matrix constructor" % self.format
 
         else:
-            raise ValueError, "unrecognized form for" \
-                    " %s_matrix constructor" % self.format
+            #must be dense
+            try:
+                arg1 = asarray(arg1)
+            except:
+                raise ValueError, "unrecognized form for" \
+                        " %s_matrix constructor" % self.format
+            from coo import coo_matrix
+            self._set_self( self.__class__(coo_matrix(arg1)) )
 
         # Read matrix dimensions given, if any
         if shape is not None:

Modified: trunk/scipy/sparse/coo.py
===================================================================
--- trunk/scipy/sparse/coo.py	2007-12-19 02:08:27 UTC (rev 3688)
+++ trunk/scipy/sparse/coo.py	2007-12-19 17:37:30 UTC (rev 3689)
@@ -6,7 +6,7 @@
 from warnings import warn 
 
 from numpy import array, asarray, empty, intc, zeros, bincount, \
-        unique, searchsorted
+        unique, searchsorted, atleast_2d
 
 from sparsetools import coo_tocsr, coo_tocsc
 from base import spmatrix, isspmatrix
@@ -142,12 +142,12 @@
             else:
                 #dense argument
                 try:
-                    M = asarray(arg1)
+                    M = atleast_2d(asarray(arg1))
                 except:
                     raise TypeError, "invalid input format"
     
                 if len(M.shape) != 2:
-                    raise TypeError, "expected rank 2 array or matrix"
+                    raise TypeError, "expected rank <= 2 array or matrix"
                 self.shape = M.shape
                 self.row,self.col = (M != 0).nonzero()
                 self.data  = M[self.row,self.col]
@@ -278,6 +278,74 @@
 
         return dok
 
+#    def tobsr(self,blocksize=None):
+#        if blocksize in [None, (1,1)]:
+#            return self.tocsr().tobsr()
+#        else:
+#            from bsr import bsr_matrix
+#            data,indices,indptr = self._toblock(blocksize,'bsr')
+#            return bsr_matrix((data,indices,indptr),shape=self.shape)
+#
+#    def tobsc(self,blocksize=None):
+#        if blocksize in [None, (1,1)]:
+#            return self.tocsc().tobsc()
+#        else:
+#            from bsc import bsc_matrix
+#            data,indices,indptr = self._toblock(blocksize,'bsc')
+#            return bsc_matrix((data,indices,indptr),shape=self.shape)
+#
+#    def _toblock(self,blocksize,format):
+#        """generic function to convert to BSR/BSC/BOO formats"""
+#        M,N = self.shape
+#        X,Y = blocksize
+#    
+#        if (M % X) != 0 or (N % Y) != 0:
+#            raise ValueError, 'shape must be multiple of blocksize'
+#    
+#        i_block,i_sub = divmod(self.row, X)
+#        j_block,j_sub = divmod(self.col, Y)
+#    
+#        if format in ['bsr','boo']:
+#            perm = lexsort( keys=[j_block,i_block] )
+#        else:
+#            perm = lexsort( keys=[i_block,j_block] )
+#    
+#        i_block = i_block[perm]
+#        j_block = j_block[perm]
+#    
+#        mask = (i_block[1:] != i_block[:-1]) + (j_block[1:] != j_block[:-1])
+#        mask = concatenate((array([True]),mask))
+#    
+#        #map self.data[n] -> data[map[n],i_sub[n],j_sub[n]]
+#        map = cumsum(mask)
+#        num_blocks = map[-1]
+#        map -= 1
+#        
+#        iperm = empty_like(perm) #inverse permutation
+#        iperm[perm] = arange(len(perm))
+#        
+#        data = zeros( (num_blocks,X,Y), dtype=self.dtype )
+#        data[map[iperm],i_sub,j_sub] = self.data
+#    
+#        row = i_block[mask]
+#        col = j_block[mask]
+#    
+#        #row,col,data form BOO format 
+#    
+#        if format == 'boo':
+#            return data,(row,col)
+#        elif format == 'bsr':
+#            temp = cumsum(bincount(row))
+#            indptr = zeros( M/X + 1, dtype=intc )
+#            indptr[1:len(temp)+1] = temp
+#            indptr[len(temp)+1:] = temp[-1]
+#            return data,col,indptr
+#        else:
+#            temp = cumsum(bincount(col))
+#            indptr = zeros( N/Y + 1, dtype=intc )
+#            indptr[1:len(temp)+1] = temp
+#            indptr[len(temp)+1:] = temp[-1]
+#            return data,row,indptr
 
 
 from sputils import _isinstance

Modified: trunk/scipy/sparse/dia.py
===================================================================
--- trunk/scipy/sparse/dia.py	2007-12-19 02:08:27 UTC (rev 3688)
+++ trunk/scipy/sparse/dia.py	2007-12-19 17:37:30 UTC (rev 3689)
@@ -15,7 +15,7 @@
 
     This can be instantiated in several ways:
       - dia_matrix(D)
-        with a dense matrix or rank-2 ndarray D
+        with a dense matrix
 
       - dia_matrix(S)
         with another sparse matrix S (equivalent to S.todia())
@@ -58,14 +58,11 @@
             self.data  = arg1.data
             self.diags = arg1.diags
             self.shape = arg1.shape
-        elif isdense(arg1) or isspmatrix(arg1):
-            if isdense(arg1):
-                #convert to COO first, then to DIA
-                from coo import coo_matrix
-                A = coo_matrix(arg1).todia()
+        elif isspmatrix(arg1):
+            if isspmatrix_dia(arg1) and copy:
+                A = arg1.copy()
             else:
-                A = arg1.todia()
-  
+                A = arg1.todia() 
             self.data  = A.data
             self.diags = A.diags
             self.shape = A.shape
@@ -88,7 +85,20 @@
                     self.data  = atleast_2d(array(arg1[0],dtype=dtype,copy=copy))
                     self.diags = atleast_1d(array(arg1[1],dtype='i',copy=copy))
                     self.shape = shape
+        else:
+            #must be dense, convert to COO first, then to DIA
+            try:
+                arg1 = asarray(arg1)
+            except:
+                raise ValueError, "unrecognized form for" \
+                        " %s_matrix constructor" % self.format
+            from coo import coo_matrix
+            A = coo_matrix(arg1).todia()
+            self.data  = A.data
+            self.diags = A.diags
+            self.shape = A.shape
 
+
         #check format
         if self.diags.ndim != 1:
             raise ValueError,'diags array must have rank 1'

Modified: trunk/scipy/sparse/dok.py
===================================================================
--- trunk/scipy/sparse/dok.py	2007-12-19 02:08:27 UTC (rev 3688)
+++ trunk/scipy/sparse/dok.py	2007-12-19 17:37:30 UTC (rev 3689)
@@ -40,14 +40,17 @@
                 self.update( A )
                 self.shape = A.shape
                 self.dtype = A.dtype
-            elif isdense(A):
+            else:
+                #must be dense, convert to COO first, then to DOK
+                try:
+                    A = asarray(A)
+                except:
+                    raise ValueError, "unrecognized form for" \
+                            " %s_matrix constructor" % self.format
                 from coo import coo_matrix
                 self.update( coo_matrix(A).todok() )
                 self.shape = A.shape
                 self.dtype = A.dtype
-            else:
-                raise TypeError, "argument should be a tuple of dimensions " \
-                        "or a sparse or dense matrix"
 
     def getnnz(self):
         return dict.__len__(self)

Modified: trunk/scipy/sparse/tests/test_base.py
===================================================================
--- trunk/scipy/sparse/tests/test_base.py	2007-12-19 02:08:27 UTC (rev 3688)
+++ trunk/scipy/sparse/tests/test_base.py	2007-12-19 17:37:30 UTC (rev 3689)
@@ -27,6 +27,7 @@
 
 
 #TODO test spmatrix(DENSE) and spmatrix(SPARSE) for all combos
+#TODO test spmatrix( [[1,2],[3,4]] ) format
 #TODO check that invalid shape in constructor raises exception
 #TODO check that spmatrix( ... , copy=X ) is respected
 class _TestCommon:
@@ -80,6 +81,8 @@
     def check_fromdense(self):
         A = matrix([[1,0,0],[2,3,4],[0,5,0],[0,0,0]])
         assert_array_equal(self.spmatrix(A).todense(),A)
+        assert_array_equal(self.spmatrix(A.A).todense(),A)
+        assert_array_equal(self.spmatrix(A.tolist()).todense(),A)
 
     def check_todense(self):
         chk = self.datsp.todense()
@@ -1184,7 +1187,7 @@
         assert_array_equal(coo.row,[])
         assert_array_equal(coo.col,[])
         assert_array_equal(coo.data,[])
-        assert_array_equal(zeros((4,3)),coo.todense())
+        assert_array_equal(coo.todense(),zeros((4,3)))
 
     def check_constructor4(self):
         """from dense matrix"""
@@ -1192,8 +1195,14 @@
                            [7,0,3,0],
                            [0,4,0,0]])
         coo = coo_matrix(mat)
-        assert_array_equal(mat,coo.todense())
+        assert_array_equal(coo.todense(),mat)
 
+        #upgrade rank 1 arrays to row matrix
+        mat = numpy.array([0,1,0,0])
+        coo = coo_matrix(mat)
+        assert_array_equal(coo.todense(),mat.reshape(1,-1))
+
+
 class TestDIA(_TestCommon, _TestArithmetic, NumpyTestCase):
     spmatrix = dia_matrix
 




More information about the Scipy-svn mailing list