Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement spmatrix that is a base class of sparse matrixes #40

Merged
merged 8 commits into from
Jun 22, 2017
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
39 changes: 39 additions & 0 deletions cupy/sparse/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from cupy.sparse.base import issparse # NOQA
from cupy.sparse.base import isspmatrix # NOQA
from cupy.sparse.base import spmatrix # NOQA

# TODO(unno): implement bsr_matrix
# TODO(unno): implement coo_matrix
# TODO(unno): implement csc_matrix
# TODO(unno): implement csr_matrix
# TODO(unno): implement dia_matrix
# TODO(unno): implement dok_matrix
# TODO(unno): implement lil_matrix

# TODO(unno): implement eye
# TODO(unno): implement identity
# TODO(unno): implement kron
# TODO(unno): implement kronsum
# TODO(unno): implement diags
# TODO(unno): implement spdiags
# TODO(unno): implement block_diag
# TODO(unno): implement tril
# TODO(unno): implement triu
# TODO(unno): implement bmat
# TODO(unno): implement hstack
# TODO(unno): implement vstack
# TODO(unno): implement rand
# TODO(unno): implement random

# TODO(unno): implement save_npz
# TODO(unno): implement load_npz

# TODO(unno): implement find

# TODO(unno): implement isspmatrix_csc(x)
# TODO(unno): implement isspmatrix_csr(x)
# TODO(unno): implement isspmatrix_bsr(x)
# TODO(unno): implement isspmatrix_lil(x)
# TODO(unno): implement isspmatrix_dok(x)
# TODO(unno): implement isspmatrix_coo(x)
# TODO(unno): implement isspmatrix_dia(x)
315 changes: 315 additions & 0 deletions cupy/sparse/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,315 @@
# Modified work:
# Copyright (c) 2017 Preferred Networks, inc.

# Partially copied from SciPy (scipy/sparse/base.py)
# Copyright (c) 2001, 2002 Enthought, Inc.
# Copyright (c) 2003-2013 SciPy Developers.
# Licensed under 3-Clause BSD License
# see https://www.scipy.org/scipylib/license.html


import numpy
import six

from cupy.core import core


class spmatrix(object):

"""Base class of all sparse matrixes.

See :class:`scipy.sparse.spmatrix`
"""

__array_priority__ = 101

def __init__(self, maxprint=50):
if self.__class__ == spmatrix:
raise ValueError(
'This class is not intended to be instantiated directly.')
self.maxprint = maxprint

@property
def device(self):
"""CUDA device on which this array resides."""
raise NotImplementedError

def get(self, stream=None):
"""Return a copy of the array on host memory.

Args:
stream (cupy.cuda.Stream): CUDA stream object. If it is given, the
copy runs asynchronously. Otherwise, the copy is synchronous.

Returns:
scipy.sparse.spmatrix: An array on host memory.

"""
raise NotImplementedError

def __len__(self):
raise TypeError('sparse matrix length is ambiguous; '
'use getnnz() or shape[0]')

def __str__(self):
return str(self.get())

def __iter__(self):
for r in six.moves.range(self.shape[0]):
yield self[r, :]

def __bool__(self):
if self.shape == (1, 1):
return self.nnz != 0
else:
raise ValueError('The truth value of an array with more than one '
'element is ambiguous. Use a.any() or a.all().')

__nonzero__ = __bool__

def __eq__(self, other):
return self.tocsr().__eq__(other)

def __ne__(self, other):
return self.tocsr().__ne__(other)

def __lt__(self, other):
return self.tocsr().__lt__(other)

def __gt__(self, other):
return self.tocsr().__gt__(other)

def __le__(self, other):
return self.tocsr().__le__(other)

def __ge__(self, other):
return self.tocsr().__ge__(other)

def __abs__(self):
return self.tocsr().__abs__()

def __add__(self, other):
return self.tocsr().__add__(other)

def __radd__(self, other):
return self.tocsr().__radd__(other)

def __sub__(self, other):
return self.tocsr().__sub__(other)

def __rsub__(self, other):
return self.tocsr().__rsub__(other)

def __mul__(self, other):
return self.tocsr().__mul__(other)

def __rmul__(self, other):
return self.tocsr().__rmul__(other)

def __div__(self, other):
return self.tocsr().__div__(other)

def __rdiv__(self, other):
return self.tocsr().__rdiv__(other)

def __truediv__(self, other):
return self.tocsr().__truediv__(other)

def __rtruediv__(self, other):
return self.tocsr().__rdtrueiv__(other)

def __neg__(self):
return -self.tocsr()

def __iadd__(self, other):
return NotImplementedError

def __isub__(self, other):
return NotImplementedError

def __imul__(self, other):
return NotImplementedError

def __idiv__(self, other):
return self.__itruediv__(other)

def __itruediv__(self, other):
return NotImplementedError

def __pow__(self, other):
return self.tocsr().__pow__(other)

@property
def A(self):
return self.toarray()

@property
def T(self):
return self.transpose()

@property
def H(self):
return self.getH()

@property
def ndim(self):
return 2

@property
def size(self):
return self.getnnz()

@property
def nnz(self):
return self.getnnz()

@property
def shape(self):
return self.get_shape()

@shape.setter
def shape(self, value):
self.set_shape(value)

def asformat(self, format):
"""Return this matrix in a given sparse format.

Args:
format (str or None): Format you need.
"""
if format is None or format == self.format:
return self
else:
return getattr(self, 'to' + format)()

def asfptype(self):
"""Upcast matrix to a floating point format (if necessary)"""
if self.dtype.kind == 'f':
return self
else:
typ = numpy.result_type(self.dtype, 'f')
return self.astype(typ)

def astype(self, t):
return self.tocsr().astype(t).asformat(self.format)

def conj(self):
return self.tocsr().conj()

def conjugate(self):
return self.conj()

def copy(self):
"""Returns a copy of this matrix."""
return self.__class__(self, copy=True)

def count_nonzero(self):
"""Number of non-zero entries, equivalent to"""
raise NotImplementedError

def diagonal(self):
"""Returns the main diagonal of the matrix"""
return self.tocsr().diagonal()

def dot(self, other):
"""Ordinary dot product"""
return self * other

def getH(self):
return self.transpose().conj()

def get_shape(self):
raise NotImplementedError

# TODO(unno): Implement getcol

def getformat(self):
return self.format

def getmaxprint(self):
return self.maxprint

def getnnz(self, axis=None):
"""Number of stored values, including explicit zeros."""
raise NotImplementedError

# TODO(unno): Implement getrow

def maximum(self, other):
return self.tocsr().maximum(other)

# TODO(unno): Implement mean

def minimum(self, other):
return self.tocsr().minimum(other)

def multiply(self, other):
"""Point-wise multiplication by another matrix"""
return self.tocsr().multiply(other)

# TODO(unno): Implement nonzero

def power(self, n, dtype=None):
return self.tocsr().power(n, dtype=dtype)

def reshape(self, shape, order='C'):
"""Gives a new shape to a sparse matrix without changing its data."""
raise NotImplementedError

def set_shape(self, shape):
self.reshape(shape)

# TODO(unno): Implement setdiag

# TODO(unno): Implement sum

def toarray(self, order=None, out=None):
"""Return a dense ndarray representation of this matrix."""
raise self.tocsr().tocarray(order=order, out=out)

def tobsr(self, blocksize=None, copy=False):
"""Convert this matrix to Block Sparse Row format."""
self.tocsr(copy=copy).tobsr(copy=False)

def tocoo(self, copy=False):
"""Convert this matrix to COOrdinate format."""
self.tocsr(copy=copy).tocoo(copy=False)

def tocsc(self, copy=False):
"""Convert this matrix to Compressed Sparse Column format."""
self.tocsr(copy=copy).tocsc(copy=False)

def tocsr(self, copy=False):
"""Convert this matrix to Compressed Sparse Row format."""
raise NotImplementedError

def todense(self, order=None, out=None):
"""Return a dense matrix representation of this matrix."""
return self.toarray(order=order, out=out)

def todia(self, copy=False):
"""Convert this matrix to sparse DIAgonal format."""
self.tocsr(copy=copy).todia(copy=False)

def todok(self, copy=False):
"""Convert this matrix to Dictionary Of Keys format."""
self.tocsr(copy=copy).todok(copy=False)

def tolil(self, copy=False):
"""Convert this matrix to LInked List format."""
self.tocsr(copy=copy).tolil(copy=False)

def transpose(self, axes=None, copy=False):
"""Reverses the dimensions of the sparse matrix."""
self.tocsr(copy=copy).transpopse(axes=None, copy=False)


def issparse(x):
return isinstance(x, spmatrix)


isspmatrix = issparse


def isdense(x):
return isinstance(x, core.ndarray)
1 change: 1 addition & 0 deletions cupy/testing/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
numpy_cupy_array_equal = helper.numpy_cupy_array_equal
numpy_cupy_array_list_equal = helper.numpy_cupy_array_list_equal
numpy_cupy_array_less = helper.numpy_cupy_array_less
numpy_cupy_equal = helper.numpy_cupy_equal
numpy_cupy_raises = helper.numpy_cupy_raises
for_dtypes = helper.for_dtypes
for_all_dtypes = helper.for_all_dtypes
Expand Down