Source code for mindspore.ops.function.sparse_func

# Copyright 2022 Huawei Technologies Co., Ltd
#
# 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.
# ============================================================================

"""Defines sparse operators with functional form."""

from __future__ import absolute_import
from mindspore.ops.operations.sparse_ops import (
    DenseToCSRSparseMatrix,
    CSRSparseMatrixToSparseTensor,
    SparseConcat,
    SparseAdd,
    SparseMatrixAdd,
    SparseMatrixSoftmax,
    CSRSparseMatrixToDense
)
from mindspore.ops.primitive import constexpr, Primitive
from mindspore.ops.operations.array_ops import GatherNd, Coalesce
from mindspore.ops.operations import _csr_ops
from mindspore.common import CSRTensor, COOTensor, Tensor
from mindspore.common import dtype as mstype
from mindspore.ops.composite.multitype_ops._constexpr_utils import raise_value_error, raise_type_error, make_tensor
from mindspore import log as logger

# utility functions and values
gather_nd = GatherNd()
dense_to_csr = DenseToCSRSparseMatrix()
csr_sparse_matrix_to_sparse_tensor = CSRSparseMatrixToSparseTensor()
batch_csr_pointers_empty = Tensor([0, -1], dtype=mstype.int32)
coalesce_op = Coalesce()
csr_sparse_matrix_to_dense = CSRSparseMatrixToDense()


@constexpr
def print_info(info):
    """Print given error info"""
    logger.error(info)


@constexpr
def _make_tensor(data):
    """Make Tensor"""
    return Tensor(data)


def is_scalar(tensor):
    """Determine whether tensor input is a scalar tensor."""
    if tensor.size != 1:
        return False
    return len(tensor.shape) <= 2


def coalesce(x_indices, x_values, x_shape):
    """
    Returns the coalesced sparse tensor of the input.

    Args:
        - **x_indices** (Tensor) - A 2-D Tensor, represents the indices of the nonzero elements of the sparse tensor.
          Supported data type is int64. It's elements should be non-negative. The shape is :math:`(y, x)`.
        - **x_values** (Tensor) - A 1-D Tensor, represents the values corresponding to the indices in `x_indices`.
          Supported data types are float16 and float32. The shape is :math:`(x,)`.
        - **x_shape** (Tensor) - A 1-D Tensor, specifies the shape of the sparse tensor.
          Supported data type is int64. The shape is :math:`(y,)`.

    Returns:
        - **y_indices** (Tensor) - A 2-D Tensor, represents the indices of the nonzero elements of the sparse tensor.
          Data type is int64. It's elements are non-negative. The shape is :math:`(y, z)`.
          `z` represents the number of different indices in `x_indices`.
        - **y_values** (Tensor) - A 1-D Tensor, represents the values corresponding to the indices in `y_indices`.
          Data type is the same as `x_values`'s. The shape is :math:`(z,)`.
        - **y_shape** (Tensor) - A 1-D Tensor, specifies the shape of the sparse tensor.
          Data type is int64. The shape is :math:`(y,)`.

    Raises:
        TypeError: If the data type of `x_values` is neither float32 nor float16.
        TypeError: If any of the data types of `x_indices` and `x_shape` is not int64.
        ValueError: If any of `x_values` and `x_shape` is not a 1-D tensor.
        ValueError: If `x_indices` is not a 2-D tensor.
        ValueError: If sizes of second dimension of `x_indices` and first dimension of `x_values` are not the same.
        ValueError: If sizes of first dimension of `x_indices` and first dimension of `x_shape` are not the same.
        ValueError: If any of the values of elements of `x_indices` is negative.
        ValueError: If any of the values of elements of `x_indices` exceed the limit set by `x_shape`.

    Supported Platforms:
        ``GPU``

    Examples:
        >>> import mindspore
        >>> import mindspore.ops as ops
        >>> from mindspore import Tensor
        >>> x_indices = Tensor([[0, 0, 1], [1, 1, 2]], dtype=ms.int64)
        >>> x_values = Tensor([1, 5, 4], dtype=ms.float32)
        >>> x_shape = Tensor([3, 3], dtype=ms.int64)
        >>> y_indices, y_values, y_shape = ops.coalesce(x_indices, x_values, x_shape)
        >>> print(y_indices)
        [[0 1]
         [1 2]]
        >>> print(y_values)
        [6. 4.]
        >>> print(y_shape)
        [3 3]
    """
    return coalesce_op(x_indices, x_values, x_shape)


coo2csr = _csr_ops.COO2CSR()

coo_tensor_get_dense_shape = Primitive('COOTensorGetDenseShape')

coo_tensor_get_indices = Primitive('COOTensorGetIndices')

coo_tensor_get_values = Primitive('COOTensorGetValues')


def csr_div(x, y):
    """
    Returns x / y where x is CSRTensor and y is Tensor.

    Note:
        This function returns the results of dense Tensor, represents the non-zero
        values of the CSRTensor. If user expects a CSRTensor as output, please directly
        use `/` operator instead. Only support dense tensor broadcast to sparse tensor
        at the moment.

    Args:
        x (CSRTensor): Sparse CSR Tensor.
        y (Tensor): Dense Tensor, its shape must be able to broadcast to x.

    Returns:
        Dense Tensor, represents the non-zero values of the result.

    Supported Platforms:
        ``GPU`` ``CPU``
    """
    if isinstance(y, (int, float, bool)):
        y = _make_tensor(y)
    if is_scalar(y):
        if y.ndim > x.ndim:
            raise_value_error("dense tensor cannot broadcast to the sparse tensor.")
        return (x.values / y).reshape(x.values.shape)
    return _csr_ops.CSRDiv()(x.indptr, x.indices, x.values, x.shape, y)


csr_gather = _csr_ops.CSRGather()


def csr_mul(x, y):
    """
    Returns x * y where x is CSRTensor and y is Tensor.

    Note:
        This function returns the results of dense Tensor, represents the non-zero
        values of the CSRTensor. If user expects a CSRTensor as output, please directly
        use `*` operator instead. Only support dense tensor broadcast to sparse tensor
        at the moment.

    Args:
        x (CSRTensor): Sparse CSR Tensor.
        y (Tensor): Dense Tensor, its shape must be able to broadcast to x.

    Returns:
        Dense Tensor, represents the non-zero values of the result.

    Supported Platforms:
        ``GPU`` ``CPU``
    """
    if isinstance(y, (int, float, bool)):
        y = _make_tensor(y)
    if is_scalar(y):
        if y.ndim > x.ndim:
            raise_value_error("dense tensor cannot broadcast to the sparse tensor.")
        return (x.values * y).reshape(x.values.shape)
    return _csr_ops.CSRMul()(x.indptr, x.indices, x.values, x.shape, y)


def csr_mv(csr_tensor, dense):
    """
    Sparse matrix-vector multiplication.

    Args:
        csr_tensor (CSRTensor): Sparse CSR Tensor.
        dense (Tensor): Dense Tensor.

    Returns:
        Dense Tensor.

    Supported Platforms:
        ``GPU`` ``CPU``
    """
    return _csr_ops.CSRMV()(csr_tensor.indptr, csr_tensor.indices, csr_tensor.values, csr_tensor.shape, dense)


def csr_reduce_sum(csr_tensor, axis):
    """
    Reduces a dimension of a CSRTensor by summing all elements in the dimension.

    Args:
        csr_tensor (CSRTensor): Sparse CSR Tensor.
        axis (int): Axis to be reduced.

    Returns:
        Dense Tensor, represents the non-zero values of the result.

    Supported Platforms:
        ``GPU`` ``CPU``
    """
    return _csr_ops.CSRReduceSum()(csr_tensor.indptr, csr_tensor.indices, csr_tensor.values, csr_tensor.shape, axis)


[docs]def csr_to_coo(tensor): """ Converts a CSRTensor to COOTensor. Note: Only 2-D CSRTensor is supported for now. Args: tensor (CSRTensor): A CSRTensor, must be 2-D. Returns: 2D COOTensor, the input tensor stored in COO format. Raises: TypeError: If input is not a COOTensor. ValueError: If input tensor is not 2-D. Supported Platforms: ``Ascend`` ``GPU`` ``CPU`` Examples: >>> from mindspore import Tensor, CSRTensor >>> indptr = Tensor([0, 1, 2]).astype("int32") >>> indices = Tensor([0, 1]).astype("int32") >>> values = Tensor([2, 1]).astype("float32") >>> shape = (2, 4) >>> x = CSRTensor(indptr, indices, values, shape) >>> output = ops.csr_to_coo(x) >>> print(output.indices) [[0 0] [1 1]] """ if not isinstance(tensor, CSRTensor): raise_type_error("For functional operator csr_to_coo, input argument must be a CSRTensor.") if len(tensor.shape) != 2: raise_value_error("Currently only support 2-D CSRTensor when converting to COOTensor.") shape = tensor.shape indices, values, _ = csr_sparse_matrix_to_sparse_tensor(Tensor(shape, mstype.int32), batch_csr_pointers_empty, tensor.indptr, tensor.indices, tensor.values) return COOTensor(indices, values, shape)
def csr_to_dense(csr_tensor): """ Converts a CSRTensor to its dense form. Note: Only 2-D CSRTensor is supported for now. Args: csr_tensor (CSRTensor): A CSRTensor, must be 2-D. Returns: Tensor. Raises: TypeError: If input is not a CSRTensor. ValueError: If input CSRTensor is not 2-D. Supported Platforms: ``GPU`` Examples: >>> from mindspore import Tensor, CSRTensor, ops >>> indptr = Tensor([0, 1, 2]).astype("int32") >>> indices = Tensor([0, 1]).astype("int32") >>> values = Tensor([2, 1]).astype("float32") >>> shape = (2, 4) >>> x = CSRTensor(indptr, indices, values, shape) >>> output = ops.csr_to_dense(x) >>> print(output) """ if not isinstance(csr_tensor, CSRTensor): raise_type_error("For functional operator csr_to_dense, input argument must be a CSRTensor.") if len(csr_tensor.shape) != 2: raise_value_error("Currently only support 2-D CSRTensor when converting to COOTensor.") shape = csr_tensor.shape return csr_sparse_matrix_to_dense(Tensor(shape, dtype=mstype.int32), batch_csr_pointers_empty, csr_tensor.indptr, csr_tensor.indices, csr_tensor.values) # deprecated, will be removed once `csr_to_coo` supports all backends. csr2coo = _csr_ops.CSR2COO() csr_tensor_get_dense_shape = Primitive('CSRTensorGetDenseShape') csr_tensor_get_indices = Primitive('CSRTensorGetIndices') csr_tensor_get_indptr = Primitive('CSRTensorGetIndptr') csr_tensor_get_values = Primitive('CSRTensorGetValues')
[docs]def dense_to_sparse_coo(tensor): """ Convert a Tensor to COOTensor. Note: Only 2-D tensor is supported for now. Args: tensor (Tensor): A dense tensor, must be 2-D. Returns: COOTensor, a sparse representation of the original dense tensor, containing the following parts. - indices (Tensor): 2-D integer tensor, indicates the positions of `values` of the dense tensor. - values (Tensor): 1-D tensor, indicates the non-zero values of the dense tensor. - shape (tuple(int)): the shape of the COOTensor, is the same as the original dense tensor. Raises: TypeError: If input is not a tensor. ValueError: If input tensor is not 2-D. Supported Platforms: ``GPU`` Examples: >>> from mindspore import Tensor, ops >>> import mindspore as ms >>> x = Tensor([[1, 0], [-5, 0]], ms.float32) >>> output = ops.dense_to_sparse_coo(x) >>> print(output.indices) [[0 0] [1 0]] >>> print(output.values) [ 1. -5.] >>> print(output.shape) (2, 2) """ if not isinstance(tensor, Tensor): raise_type_error("For functional operator dense_to_sparse_coo, input argument must be a Tensor.") if len(tensor.shape) != 2: raise_value_error("Currently only support 2-D Tensor when converting to COOTensor.") indices = tensor.nonzero().astype("int32") values = gather_nd(tensor, indices) return COOTensor(indices, values, tensor.shape)
[docs]def dense_to_sparse_csr(tensor): """ Convert a Tensor to CSRTensor. Note: Only 2-D tensor is supported for now. Args: tensor (Tensor): A dense tensor, must be 2-D. Returns: CSRTensor, a sparse representation of the original dense tensor, containing the following parts. - indptr (Tensor): 1-D integer tensor, indicates the start and end point for `values` in each row. - indices (Tensor): 1-D integer tensor, indicates the column positions of all non-zero values of the input. - values (Tensor): 1-D tensor, indicates the non-zero values of the dense tensor. - shape (tuple(int)): the shape of the CSRTensor, is the same as the original dense tensor. Raises: TypeError: If input is not a tensor. ValueError: If input tensor is not 2-D. Supported Platforms: ``GPU`` Examples: >>> from mindspore import Tensor, ops >>> import mindspore as ms >>> x = Tensor([[1, 0], [-5, 0]], ms.float32) >>> output = ops.dense_to_sparse_csr(x) >>> print(output.indptr) [0 1 2] >>> print(output.indices) [0 0] >>> print(output.shape) (2, 2) """ if not isinstance(tensor, Tensor): raise_type_error("For functional operator dense_to_sparse_csr, input argument must be a Tensor.") if len(tensor.shape) != 2: raise_value_error("Currently only support 2-D Tensor when converting to CSRTensor.") indices = tensor.nonzero().astype("int32") _, _, indptr, indices, values = dense_to_csr(tensor, indices) return CSRTensor(indptr, indices, values, tensor.shape)
def make_sparse_tensor(indices, values, dense_shape): """Call make_coo_tensor in this function.""" print_info("WARNING: 'SparseTensor' is deprecated from version 1.7 and will be removed in a future version. " + "Please use 'COOTensor' instead.") return make_coo_tensor(indices, values, dense_shape) make_coo_tensor = Primitive('MakeCOOTensor') make_csr_tensor = Primitive('MakeCSRTensor') make_row_tensor = Primitive('MakeRowTensor') row_tensor_get_values = Primitive('RowTensorGetValues') row_tensor_get_indices = Primitive('RowTensorGetIndices') row_tensor_get_dense_shape = Primitive('RowTensorGetDenseShape') row_tensor_add = Primitive('RowTensorAdd') @constexpr def _calc_out_shape(sp_input, concat_dim): "calculating the COOTensor output shape in sparse_concat" if isinstance(sp_input[0], tuple): out_shape_list = list(sp_input[0][2]) else: out_shape_list = list(sp_input[0].shape) for i in range(1, len(sp_input)): if isinstance(sp_input[i], tuple): out_shape_list[concat_dim] += sp_input[i][2][concat_dim] else: out_shape_list[concat_dim] += sp_input[i].shape[concat_dim] return tuple(out_shape_list) @constexpr def _set_sparse_concat_input(sp_input): "split COOTensor to normal tensor" if len(sp_input) < 2: raise_value_error("For sparse_concat, not support COOTensor input number < 2.") in_indices = [] in_values = [] in_shapes = [] for element in sp_input: if isinstance(element, tuple): in_indices.append(element[0]) in_values.append(element[1]) in_shapes.append(Tensor(element[2], dtype=mstype.int64)) else: in_indices.append(element.indices) in_values.append(element.values) in_shapes.append(Tensor(element.shape, dtype=mstype.int64)) return in_indices, in_values, in_shapes def sparse_concat(sp_input, concat_dim=0): """ concatenates the input SparseTensor(COO format) along the specified dimension. .. note: demo API now, and only supported CPU Args: sp_input (Union[list(COOTensor), tuple(COOTensor)) - the list of SparseTensor which need to concatenates. for COOTensor input. concat_dim (scalar): decide the dimension to concatenation along. The value must be in range [-rank, rank), where rank is the number of dimensions in each input SparseTensor. Default is 0. Outputs: - **output** (COOtensor) - the result of concatenates the input SparseTensor along the specified dimension. OutShape: OutShape[non concat_dim] is equal to InShape[non concat_dim] and OutShape[concat_dim] is all input concat_dim axis shape accumulate. Raises: ValueError: If only one sparse tensor input. ValueError: If Input COOTensor shape dim > 3. COOtensor shape dim size must be 2 now Supported Platforms: ``CPU`` Examples: >>> indices0 = Tensor([[0, 1], [1, 2]], dtype=mstype.int32) >>> values0 = Tensor([1, 2], dtype=mstype.int32) >>> shape0 = (3, 4) >>> input0 = COOTensor(indices0, values0, shape0) >>> indices1 = Tensor([[0, 0], [1, 1]], dtype=mstype.int32) >>> values1 = Tensor([3, 4], dtype=mstype.int32) >>> shape1 = (3, 4) >>> input1 = COOTensor(indices1, values1, shape1) >>> concat_dim = 1 >>> out = F.sparse_concat((input0, input1), concat_dim) >>> print(out) COOTensor(shape=[3, 8], dtype=Int32, indices=Tensor(shape=[4, 2], dtype=Int32, value= [[0 1] [0 4] [1 2] [1 5]]), values=Tensor(shape=[4], dtype=Int32, value=[1 3 2 4])) """ sparse_concat_op = SparseConcat(concat_dim) in_indices, in_values, in_shapes = _set_sparse_concat_input(sp_input) indices, values, _ = sparse_concat_op(in_indices, in_values, in_shapes) out_shape = _calc_out_shape(sp_input, concat_dim) return COOTensor(indices, values, out_shape) def sparse_add(x1, x2, thresh): """ Computes the sum of x1(COOTensor) and x2(COOTensor). Args: x1 (COOTensor): the first COOTensor to sum. x2 (COOTensor): the second COOTensor to sum. thresh (Tensor): A 0-D Tensor, represents the magnitude threshold that determines if an output value/index pair pair take space. Returns: A COOTensor, the result of sum. Raises: ValueError: If any input(x1/x2)'s indices's dim is not equal to 2. ValueError: If any input(x1/x2)'s values's dim is not equal to 1. ValueError: If any input(x1/x2)'s shape's dim is not equal to 1. ValueError: If thresh's dim is not equal to 0. TypeError: If any input(x1/x2)'s indices's type is not equal to int64. TypeError: If any input(x1/x2)'s shape's type is not equal to int64. ValueError: If any input(x1/x2)'s indices's length is not equal to its values's length. TypeError: If any input(x1/x2)'s values's type is not equal to anf of (int8/int16/int32/int64/float32/float64/complex64/complex128). TypeError: If thresh's type is not equal to anf of (int8/int16/int32/int64/float32/float64). TypeError: If x1's indices's type is not equal to x2's indices's type. TypeError: If x1's values's type is not equal to x2's values's type. TypeError: If x1's shape's type is not equal to x2's shape's type. TypeError: If (x1/x2)'s value's type is not matched with thresh's type. Supported Platforms: ``CPU`` ``GPU`` Examples: >>> from mindspore import Tensor, COOTensor >>> from mindspore import dtype as mstype >>> from mindspore import context >>> from mindspore import ops >>> indics0 = Tensor([[0, 1], [1, 2]], dtype=mstype.int64) >>> values0 = Tensor([1, 2], dtype=mstype.int32) >>> shape0 = (3, 4) >>> input0 = COOTensor(indics0, values0, shape0) >>> indics1 = Tensor([[0, 0], [1, 1]], dtype=mstype.int64) >>> values1 = Tensor([3, 4], dtype=mstype.int32) >>> shape1 = (3, 4) >>> input1 = COOTensor(indics1, values1, shape1) >>> thres = Tensor(0, dtype=mstype.int32) >>> out = ops.sparse_add(input0, input1, thres) >>> print(out) COOTensor(shape = [3, 4], dtype = Int32, indices=Tensor(shape=[4, 2], dtype = Int64, value=[[0 0], [0 1], [1 1], [1 2]]), values=Tensor(shape[4], dtype=Int32, value=[3 1 4 2])) """ x1_indices = x1.indices x1_values = x1.values x2_indices = x2.indices x2_values = x2.values den_shp = make_tensor(x1.shape, x1_indices.dtype) add_op = SparseAdd() indices, values, _ = add_op(x1_indices, x1_values, den_shp, x2_indices, x2_values, den_shp, thresh) return COOTensor(indices, values, x1.shape) def csr_softmax(logits, dtype): """ Calculates the softmax of a CSRTensorMatrix. Args: logits (CSRTensor): Sparse CSR Tensor. dtype (dtype): Data type. Returns: CSRTensor, a csr_tensor containing - **indptr** - indicates the start and end point for `values` in each row. - **indices** - the column positions of all non-zero values of the input. - **values** - the non-zero values of the dense tensor. - **shape** - the shape of the csr_tensor. Supported Platforms: ``GPU`` ``CPU`` Examples: >>> import mindspore as ms >>> import mindspore.common.dtype as mstype >>> from mindspore import Tensor, CSRTensor >>> from mindspore.ops.function import csr_softmax >>> logits_indptr = Tensor([0, 4, 6], dtype=mstype.int32) >>> logits_indices = Tensor([0, 2, 3, 4, 3, 4], dtype=mstype.int32) >>> logits_values = Tensor([1, 2, 3, 4, 1, 2], dtype=mstype.float32) >>> shape = (2, 6) >>> logits = CSRTensor(logits_indptr, logits_indices, logits_values, shape) >>> out = csr_softmax(logits, dtype=mstype.float32) >>> print(out) CSRTensor(shape=[2, 6], dtype=Float32, indptr=Tensor(shape=[3], dtype=Int32, value=[0 4 6]), indices=Tensor(shape=[6], dtype=Int32, value=[0 2 3 4 3 4]), values=Tensor(shape=[6], dtype=Float32, value=[ 3.20586003e-02 8.71443152e-02 2.36882806e-01 6.43914223e-01 2.68941432e-01 7.31058598e-01])) """ if not isinstance(logits, CSRTensor): raise_type_error("For functional operator sparse_matrix_softmax, logits must be type of CSRTensor.") sparse_matrix_softmax_op = SparseMatrixSoftmax(dtype) logits_batch_pointers = make_tensor([0, logits.values.shape[0]], mstype.int32) logits_shape = make_tensor(logits.shape, mstype.int32) shape, _, indptr, indices, values = sparse_matrix_softmax_op(logits_shape, logits_batch_pointers, logits.indptr, logits.indices, logits.values) output_shape = tuple(shape.asnumpy().tolist()) return CSRTensor(indptr=indptr, indices=indices, values=values, shape=output_shape) def csr_add(a, b, alpha, beta): """ Returns alpha * csr_a + beta * csr_b where both csr_a and csr_b are CSRTensor, alpha and beta are both Tensor. Args: a (CSRTensor): Sparse CSR Tensor. b (CSRTensor): Sparse CSR Tensor. alpha(Tensor): Dense Tensor, its shape must be able to broadcast to a. beta(Tensor): Dense Tensor, its shape must be able to broadcast to b. Returns: CSRTensor, a csr_tensor containing the following parts. - **indptr** - indicates the start and end point for `values` in each row. - **indices** - the column positions of all non-zero values of the input. - **values** - the non-zero values of the dense tensor. - **shape** - the shape of the csr_tensor. Supported Platforms: ``GPU`` ``CPU`` Examples: >>> import mindspore.common.dtype as mstype >>> from mindspore import Tensor, CSRTensor >>> from mindspore.ops.functional import csr_add >>> a_indptr = Tensor([0, 1, 2], dtype=mstype.int32) >>> a_indices = Tensor([0, 1], dtype=mstype.int32) >>> a_values = Tensor([1, 2], dtype=mstype.float32) >>> shape = (2, 6) >>> b_indptr = Tensor([0, 1, 2], dtype=mstype.int32) >>> b_indices = Tensor([0, 1], dtype=mstype.int32) >>> b_values = Tensor([1, 2], dtype=mstype.float32) >>> alpha = Tensor(1, mstype.float32) >>> beta = Tensor(1, mstype.float32) >>> csra = CSRTensor(a_indptr, a_indices, a_values, shape) >>> csrb = CSRTensor(b_indptr, b_indices, b_values, shape) >>> out = csr_add(csra, csrb, alpha, beta) >>> print(out) CSRTensor(shape=[2,6], dtype=Float32, indptr=Tensor(shape=[3], dtype=Int32, value = [0, 1, 2]), indices=Tensor(shape=[2], dtype=Int32, value = [0, 1]), values=Tensor(shape=[2], dtype=Float32, value = [2.0, 4.0])) """ if not isinstance(a, CSRTensor) or not isinstance(b, CSRTensor): raise_type_error("For functional operator csr_add, both inputs a and b must be type of CSRTensor.") if not isinstance(alpha, Tensor) or not isinstance(beta, Tensor): raise_type_error("For functional operator csr_add, both inputs alpha and beta must be Tensor.") csr_add_op = SparseMatrixAdd() a_batch_pointers = make_tensor([0, a.values.shape[0]], mstype.int32) b_batch_pointers = make_tensor([0, b.values.shape[0]], mstype.int32) a_shape = make_tensor(a.shape, mstype.int32) b_shape = make_tensor(b.shape, mstype.int32) _, _, indptr, indices, values = csr_add_op(a_shape, a_batch_pointers, a.indptr, a.indices, a.values, b_shape, b_batch_pointers, b.indptr, b.indices, b.values, alpha, beta) return CSRTensor(indptr, indices, values, a.shape) __all__ = [ 'coalesce', 'coo2csr', 'coo_tensor_get_dense_shape', 'coo_tensor_get_indices', 'coo_tensor_get_values', 'csr_div', 'csr_gather', 'csr_mul', 'csr_mv', 'csr_reduce_sum', 'csr_to_coo', 'csr2coo', 'csr_tensor_get_dense_shape', 'csr_tensor_get_indices', 'csr_tensor_get_indptr', 'csr_tensor_get_values', 'dense_to_sparse_coo', 'dense_to_sparse_csr', 'make_sparse_tensor', 'make_coo_tensor', 'make_csr_tensor', 'make_row_tensor', 'row_tensor_get_values', 'row_tensor_get_indices', 'row_tensor_get_dense_shape', 'row_tensor_add', 'sparse_add', 'sparse_concat', 'csr_add', 'csr_softmax', 'csr_to_dense' ] __all__.sort()