diff --git a/paddle/fluid/pybind/eager_method.cc b/paddle/fluid/pybind/eager_method.cc index 94756a41f850369c7d062cf828ded3d66f5bb099..7c2065b33db366b8331f65f0c1ec65e89b04f5ff 100644 --- a/paddle/fluid/pybind/eager_method.cc +++ b/paddle/fluid/pybind/eager_method.cc @@ -1571,6 +1571,15 @@ static PyObject* tensor_method_to_sparse_csr(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__inplace_version(TensorObject* self, PyObject* args, PyObject* kwargs) { @@ -1966,6 +1975,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, diff --git a/python/paddle/fluid/tests/unittests/test_sparse_is_same_shape.py b/python/paddle/fluid/tests/unittests/test_sparse_is_same_shape.py new file mode 100644 index 0000000000000000000000000000000000000000..aac5d04a763381cd841a9fd7d2abb0c25cdc4e95 --- /dev/null +++ b/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() diff --git a/python/paddle/incubate/sparse/__init__.py b/python/paddle/incubate/sparse/__init__.py index 8408c3ca2773062aa419b953ea75249f299be700..de89f46438a352014daa2309f37045a995022aaa 100644 --- a/python/paddle/incubate/sparse/__init__.py +++ b/python/paddle/incubate/sparse/__init__.py @@ -42,6 +42,7 @@ from .binary import add from .binary import divide from .binary import multiply from .binary import subtract +from .binary import is_same_shape from .multiary import addmm @@ -77,4 +78,5 @@ __all__ = [ 'multiply', 'divide', 'coalesce', + 'is_same_shape', ] diff --git a/python/paddle/incubate/sparse/binary.py b/python/paddle/incubate/sparse/binary.py index 93ce90c9f021a586ea654ed6a811e674a496b38d..6c78628d27037ae2c3d12309d0c9b122380204d2 100644 --- a/python/paddle/incubate/sparse/binary.py +++ b/python/paddle/incubate/sparse/binary.py @@ -399,3 +399,36 @@ def divide(x, y, name=None): if y.dtype != x.dtype: y = _C_ops.sparse_cast(y, None, x.dtype) return _C_ops.sparse_divide(x, y) + + +@dygraph_only +def is_same_shape(x, y): + """ + Return the results of shape comparison between two Tensors, check whether x.shape equal to y.shape. + Any two type Tensor among DenseTensor/SparseCooTensor/SparseCsrTensor are supported. + + 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)