Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create view/python reference on scipy sparse matrix?

I am working on an algorithm that uses diagonal and first off-diagonal blocks of a large (will be e06 x e06) block diagonal sparse matrix.

Right now I create a dict that stores the blocks in such a way that I can access the blocks in a matrix like fashion. For example B[0,0](5x5) gives the first block of matrix A(20x20), assuming 5x5 blocks and that matrix A is of type sparse.lil.

This works fine but takes horribly long too run. It is inefficient because it copies the data, as this reference revealed to my astonishment: GetItem Method

Is there a way to only store a view on a sparse matrix in a dict? I would like to change the content and still be able to use the same identifiers. It is fine if it takes a little longer as it should only be done once. The blocks will have many different dimensions and shapes.

like image 647
Jonas Avatar asked Oct 10 '22 20:10

Jonas


1 Answers

As far as I know, all of the various sparse matricies in scipy.sparse return copies rather than a view of some sort. (Some of the others may be significantly faster at doing so than lil_matrix, though!)

One way of doing what you want is to just work with slice objects. For example:

import scipy.sparse

class SparseBlocks(object):
    def __init__(self, data, chunksize=5):
        self.data = data
        self.chunksize = chunksize
    def _convert_slices(self, slices):
        newslices = []
        for axslice in slices:
            if isinstance(axslice, slice):
                start, stop = axslice.start, axslice.stop
                if axslice.start is not None:
                    start *= self.chunksize
                if axslice.stop is not None:
                    stop *= self.chunksize
                axslice = slice(start, stop, None)
            elif axslice is not None:
                axslice = slice(axslice, axslice+self.chunksize)
            newslices.append(axslice)
        return tuple(newslices)

    def __getitem__(self, item):
        item = self._convert_slices(item)
        return self.data.__getitem__(item)
    def __setitem__(self, item, value):
        item = self._convert_slices(item)
        return self.data.__setitem__(item, value)

data = scipy.sparse.lil_matrix((20,20))
s = SparseBlocks(data)
s[0,0] = 1
print s.data

Now, whenever we modify s[whatever] it will modify s.data of the appropriate chunk. In other words, s[0,0] will return or set s.data[:5, :5], and so on.

like image 168
Joe Kington Avatar answered Oct 27 '22 12:10

Joe Kington