Skip to content

Add @ operator (simplify) #16

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

Merged
merged 26 commits into from
May 9, 2017
Merged

Add @ operator (simplify) #16

merged 26 commits into from
May 9, 2017

Conversation

DavidMertz
Copy link

This supersedes the closed https://github.com/mrocklin/sparse/pull/14.

This request simply adds the __matmul__ and __rmatmul__ with no behavior other than that delegated to sparse.dot(). Checks for "correct" non-combination of lists with COOs remains. A more specific return NotImplemented is returned for things lacking an .ndim, which gives us a better error of:

TypeError: unsupported operand type(s) for @: 'list' and 'COO'

@DavidMertz DavidMertz mentioned this pull request May 3, 2017
la = a.tolist()
lb = b.tolist()
la, lb # silencing flake8

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are not used anymore, I think

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

sa = COO.from_numpy(a)
sb = COO.from_numpy(b)

assert_eq(a.dot(b), sa.dot(sb))
assert_eq(np.dot(a, b), sparse.dot(sa, sb))

if sys.version_info >= (3, 5):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than an explicit version check, perhaps we could check hasattr(operator, 'matmul')

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? But OK, changed.

assert_eq(eval("sa @ sb"), sparse.dot(sa, sb))

# Test that SOO's and np.array's combine correctly
assert_eq(eval("a @ sb"), eval("sa @ b"))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could also check np.dot(sa, sb). If the classes are set up correctly, this should know how to delegate to sparse.dot (though I think it requires __numpy_ufunc__)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This gets a failure that doesn't seem straightforward to fix. But moreover, I wouldn't really expect it to work as a user.

sparse/core.py:448: in __mul__
    return self.elemwise_binary(operator.mul, other)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <COO: shape=(3, 4, 5), dtype=float64, nnz=6>
func = <built-in function mul>
other = <COO: shape=(5, 6), dtype=float64, nnz=4>, args = (), kwargs = {}

    def elemwise_binary(self, func, other, *args, **kwargs):
        assert isinstance(other, COO)
        if kwargs.pop('check', True) and func(0, 0, *args, **kwargs) != 0:
            raise ValueError("Performing this operation would produce "
                    "a dense result: %s" % str(func))
        if self.shape != other.shape:
>           raise NotImplementedError("Broadcasting is not supported")
E           NotImplementedError: Broadcasting is not supported

sparse/core.py:478: NotImplementedError

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Weird.. that error comes from the fact that np.dot(sa, sb) ends up calling sa.__mul__(sb), which... I have no idea why it would do that.

sparse/core.py Outdated
@@ -681,6 +686,8 @@ def tensordot(a, b, axes=2):


def dot(a, b):
if not hasattr(a, 'ndim') or not hasattr(b, 'ndim'):
return NotImplemented
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be raise NotImplementedError, because dot is often called on its own. You could catch the NotImplementedError and return NotImplemented within __matmul__ if you want to use it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@DavidMertz
Copy link
Author

I've pushed out the changes in response to review.

@DavidMertz DavidMertz mentioned this pull request May 4, 2017
@jakevdp
Copy link
Contributor

jakevdp commented May 8, 2017

I think this is good to merge, but first it needs to be rebased against master, and I also think the commit history should be cleaned up (though I'm not sure of @mrocklin's philosophy on that...)

@mrocklin
Copy link
Contributor

mrocklin commented May 8, 2017 via email

@DavidMertz
Copy link
Author

I'm lacking some git-fu to cleanup merge conflicts in rebasing and also prune commit history. Would it be OK/reasonable if I simply open a new PR using a different branch of my fork (where hopefully I can clean the commit history)?

@mrocklin
Copy link
Contributor

mrocklin commented May 9, 2017 via email

David Mertz added 3 commits May 9, 2017 11:56
# This is the 1st commit message:
# This is a combination of 3 commits.
# This is the 1st commit message:
# This is a combination of 3 commits.
# This is the 1st commit message:
# This is a combination of 4 commits.
# This is the 1st commit message:
Add @ operator (__matmul__ and __rmatmul__) and tests.  Do not implem ent coersion of Python lists/tuples.

# This is the commit message pydata#2:

test for __rmatmul__

# This is the commit message pydata#3:

Better implementation of __rmatmul__ and test that exercises the actual code, not NumPy's

# The commit message pydata#4 will be skipped:

#	Cleanup tests of coersion failure

# The commit message pydata#2 will be skipped:

#	# This is a combination of 2 commits.
#	# This is the 1st commit message:
#
#	Resolve merge conflict in rebasing
#
#	# The commit message pydata#2 will be skipped:
#
#	#	test for __rmatmul__

# The commit message pydata#3 will be skipped:

#	Resolve merge conflict in rebasing

# The commit message pydata#2 will be skipped:

#	test for __rmatmul__

# The commit message pydata#3 will be skipped:

#	Better implementation of __rmatmul__ and test that exercises the actual code, not NumPy's

# This is the commit message pydata#2:

Remove handling of lists etc.

# The commit message pydata#3 will be skipped:

#	Remove handling of lists etc.
David Mertz added 5 commits May 9, 2017 12:03
# This is the 1st commit message:
# This is a combination of 2 commits.
# This is the 1st commit message:

# This is a combination of 2 commits.
# This is the 1st commit message:

Resolve merge on rebase

# The commit message pydata#2 will be skipped:

#	Resolve merge on rebase

# The commit message pydata#2 will be skipped:

#	Better implementation of __rmatmul__ and test that exercises the actual code, not NumPy's

# The commit message pydata#2 will be skipped:

#	Remove handling of lists etc.

# The commit message pydata#3 will be skipped:

#	Remove handling of lists etc.
@jakevdp jakevdp merged commit 26d9a61 into pydata:master May 9, 2017
@jakevdp
Copy link
Contributor

jakevdp commented May 9, 2017

Merged – thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants