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

(just for my self-learning)[Hackathon 3rd No.23] add paddle.incubate.sparse.is_same_shape #45493

Closed
Show file tree
Hide file tree
Changes from all 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
13 changes: 13 additions & 0 deletions paddle/fluid/pybind/eager_method.cc
Expand Up @@ -1543,6 +1543,15 @@ static PyObject* tensor_method_is_sparse_coo(TensorObject* self,
EAGER_CATCH_AND_THROW_RETURN_NULL
}

static PyObject* tensor_method_is_same_shape(TensorObject* self,
PyObject* args,
PyObject* kwargs) {
EAGER_TRY
auto other = CastPyArg2Tensor(PyTuple_GET_ITEM(args, 0), 0);
return ToPyObject(self->tensor.shape() == other.shape());
EAGER_CATCH_AND_THROW_RETURN_NULL
}

static PyObject* tensor_method_is_sparse_csr(TensorObject* self,
PyObject* args,
PyObject* kwargs) {
Expand Down Expand Up @@ -1964,6 +1973,10 @@ PyMethodDef variable_methods[] = {
(PyCFunction)(void (*)(void))tensor_method_is_sparse_csr,
METH_VARARGS | METH_KEYWORDS,
NULL},
{"is_same_shape",
(PyCFunction)(void (*)(void))tensor_method_is_same_shape,
METH_VARARGS | METH_KEYWORDS,
NULL},
{"to_sparse_csr",
(PyCFunction)(void (*)(void))tensor_method_to_sparse_csr,
METH_VARARGS | METH_KEYWORDS,
Expand Down
2 changes: 1 addition & 1 deletion paddle/fluid/pybind/pybind.cc
Expand Up @@ -608,7 +608,7 @@ PYBIND11_MODULE(core_noavx, m) {
dmt,
platform::errors::InvalidArgument(
"from_dlpack received an invalid capsule. "
"Note that a DLPack tensor can be consumed only once."));
"Note that a DLPack tensor can be consumed only once. "));

PyCapsule_SetName(dltensor->ptr(), "used_dltensor");
DLTensor dl = dmt->dl_tensor;
Expand Down
125 changes: 125 additions & 0 deletions python/paddle/fluid/tests/unittests/test_sparse_is_same_shape.py
@@ -0,0 +1,125 @@
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import print_function
import unittest

import paddle
from paddle.incubate.sparse.binary import is_same_shape


class TestSparseIsSameShapeAPI(unittest.TestCase):
"""
test paddle.incubate.sparse.is_same_shape
"""

def setUp(self):
self.shapes = [[2, 5, 8], [3, 4]]
self.tensors = [
paddle.rand(self.shapes[0]),
paddle.rand(self.shapes[0]),
paddle.rand(self.shapes[1])
]
self.sparse_dim = 2

def test_dense_dense(self):
self.assertTrue(is_same_shape(self.tensors[0], self.tensors[1]))
self.assertFalse(is_same_shape(self.tensors[0], self.tensors[2]))
self.assertFalse(is_same_shape(self.tensors[1], self.tensors[2]))

def test_dense_csr(self):
self.assertTrue(
is_same_shape(self.tensors[0], self.tensors[1].to_sparse_csr()))
self.assertFalse(
is_same_shape(self.tensors[0], self.tensors[2].to_sparse_csr()))
self.assertFalse(
is_same_shape(self.tensors[1], self.tensors[2].to_sparse_csr()))

def test_dense_coo(self):
self.assertTrue(
is_same_shape(self.tensors[0],
self.tensors[1].to_sparse_coo(self.sparse_dim)))
self.assertFalse(
is_same_shape(self.tensors[0],
self.tensors[2].to_sparse_coo(self.sparse_dim)))
self.assertFalse(
is_same_shape(self.tensors[1],
self.tensors[2].to_sparse_coo(self.sparse_dim)))

def test_csr_dense(self):
self.assertTrue(
is_same_shape(self.tensors[0].to_sparse_csr(), self.tensors[1]))
self.assertFalse(
is_same_shape(self.tensors[0].to_sparse_csr(), self.tensors[2]))
self.assertFalse(
is_same_shape(self.tensors[1].to_sparse_csr(), self.tensors[2]))

def test_csr_csr(self):
self.assertTrue(
is_same_shape(self.tensors[0].to_sparse_csr(),
self.tensors[1].to_sparse_csr()))
self.assertFalse(
is_same_shape(self.tensors[0].to_sparse_csr(),
self.tensors[2].to_sparse_csr()))
self.assertFalse(
is_same_shape(self.tensors[1].to_sparse_csr(),
self.tensors[2].to_sparse_csr()))

def test_csr_coo(self):
self.assertTrue(
is_same_shape(self.tensors[0].to_sparse_csr(),
self.tensors[1].to_sparse_coo(self.sparse_dim)))
self.assertFalse(
is_same_shape(self.tensors[0].to_sparse_csr(),
self.tensors[2].to_sparse_coo(self.sparse_dim)))
self.assertFalse(
is_same_shape(self.tensors[1].to_sparse_csr(),
self.tensors[2].to_sparse_coo(self.sparse_dim)))

def test_coo_dense(self):
self.assertTrue(
is_same_shape(self.tensors[0].to_sparse_coo(self.sparse_dim),
self.tensors[1]))
self.assertFalse(
is_same_shape(self.tensors[0].to_sparse_coo(self.sparse_dim),
self.tensors[2]))
self.assertFalse(
is_same_shape(self.tensors[1].to_sparse_coo(self.sparse_dim),
self.tensors[2]))

def test_coo_csr(self):
self.assertTrue(
is_same_shape(self.tensors[0].to_sparse_coo(self.sparse_dim),
self.tensors[1].to_sparse_csr()))
self.assertFalse(
is_same_shape(self.tensors[0].to_sparse_coo(self.sparse_dim),
self.tensors[2].to_sparse_csr()))
self.assertFalse(
is_same_shape(self.tensors[1].to_sparse_coo(self.sparse_dim),
self.tensors[2].to_sparse_csr()))

def test_coo_coo(self):
self.assertTrue(
is_same_shape(self.tensors[0].to_sparse_coo(self.sparse_dim),
self.tensors[1].to_sparse_coo(self.sparse_dim)))
self.assertFalse(
is_same_shape(self.tensors[0].to_sparse_coo(self.sparse_dim),
self.tensors[2].to_sparse_coo(self.sparse_dim)))
self.assertFalse(
is_same_shape(self.tensors[1].to_sparse_coo(self.sparse_dim),
self.tensors[2].to_sparse_coo(self.sparse_dim)))


if __name__ == "__main__":
unittest.main()
2 changes: 2 additions & 0 deletions python/paddle/incubate/sparse/__init__.py
Expand Up @@ -42,6 +42,7 @@
from .binary import divide
from .binary import multiply
from .binary import subtract
from .binary import is_same_shape

from .multiary import addmm

Expand Down Expand Up @@ -77,4 +78,5 @@
'multiply',
'divide',
'coalesce',
'is_same_shape'
]
54 changes: 39 additions & 15 deletions python/paddle/incubate/sparse/binary.py
Expand Up @@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from paddle import _C_ops, _legacy_C_ops
from paddle import _C_ops
from paddle.fluid.framework import dygraph_only, core

__all__ = []
Expand Down Expand Up @@ -94,7 +94,7 @@ def matmul(x, y, name=None):
# [2., 2.],
# [3., 3.]])
"""
return _C_ops.sparse_matmul(x, y)
return _C_ops.final_state_sparse_matmul(x, y)


@dygraph_only
Expand Down Expand Up @@ -154,7 +154,7 @@ def masked_matmul(x, y, mask, name=None):
# values=[0.98986477, 0.97800624, 1.14591956, 0.68561077, 0.94714981])

"""
return _C_ops.sparse_masked_matmul(x, y, mask)
return _C_ops.final_state_sparse_masked_matmul(x, y, mask)


@dygraph_only
Expand Down Expand Up @@ -210,7 +210,7 @@ def mv(x, vec, name=None):
# [-3.85499096, -2.42975140, -1.75087738])

"""
return _C_ops.sparse_mv(x, vec)
return _C_ops.final_state_sparse_mv(x, vec)


def add(x, y, name=None):
Expand Down Expand Up @@ -253,8 +253,8 @@ def add(x, y, name=None):

"""
if y.dtype != x.dtype:
y = _C_ops.sparse_cast(y, None, x.dtype)
return _C_ops.sparse_add(x, y)
y = _C_ops.final_state_sparse_cast(y, None, x.dtype)
return _C_ops.final_state_sparse_add(x, y)


@dygraph_only
Expand Down Expand Up @@ -298,8 +298,8 @@ def subtract(x, y, name=None):

"""
if y.dtype != x.dtype:
y = _C_ops.sparse_cast(y, None, x.dtype)
return _C_ops.sparse_subtract(x, y)
y = _C_ops.final_state_sparse_cast(y, None, x.dtype)
return _C_ops.final_state_sparse_subtract(x, y)


@dygraph_only
Expand Down Expand Up @@ -343,11 +343,11 @@ def multiply(x, y, name=None):

"""
if isinstance(y, (int, float)):
return _C_ops.sparse_scale(x, float(y), 0.0, True)
return _C_ops.final_state_sparse_scale(x, float(y), 0.0, True)
else:
if y.dtype != x.dtype:
y = _C_ops.sparse_cast(y, None, x.dtype)
return _C_ops.sparse_multiply(x, y)
y = _C_ops.final_state_sparse_cast(y, None, x.dtype)
return _C_ops.final_state_sparse_multiply(x, y)


@dygraph_only
Expand Down Expand Up @@ -391,11 +391,35 @@ def divide(x, y, name=None):

"""
if x.dtype in _int_dtype_:
x = _C_ops.sparse_cast(x, None, core.VarDesc.VarType.FP32)
x = _C_ops.final_state_sparse_cast(x, None, core.VarDesc.VarType.FP32)

if isinstance(y, (int, float)):
return _C_ops.sparse_divide_scalar(x, float(y))
return _C_ops.final_state_sparse_divide_scalar(x, float(y))
else:
if y.dtype != x.dtype:
y = _C_ops.sparse_cast(y, None, x.dtype)
return _C_ops.sparse_divide(x, y)
y = _C_ops.final_state_sparse_cast(y, None, x.dtype)
return _C_ops.final_state_sparse_divide(x, y)


@dygraph_only
def is_same_shape(x, y):
"""
Check whether x.shape equal to y.shape.
Args:
x (Tensor): The input tensor. It can be DenseTensor/SparseCooTensor/SparseCsrTensor.
y (Tensor): The input tensor. It can be DenseTensor/SparseCooTensor/SparseCsrTensor.
Returns:
bool: True for same shape and False for different shape.
Examples:
.. code-block:: python
import paddle
x = paddle.rand([2, 3, 8])
y = paddle.rand([2, 3, 8])
y = y.to_sparse_csr()
z = paddle.rand([2, 5])
paddle.incubate.sparse.is_same_shape(x, y)
# True
paddle.incubate.sparse.is_same_shape(x, z)
# False
"""
return x.is_same_shape(y)