'Reverse broadcast from shape(grad_op_tree) to shape(x)
Arguments:
grad_op_tree (OpTreeNode or Tensor): The OpTreeNode to broadcast.
x (OpTreeNode or Tensor): Provides the dimension to be broadcasted to.
be: (Backend): The backend to be used.
Returns:
OpTreeNode or Tensor: The broadcasted result.'

@staticmethod
def _unbroadcast(grad_op_tree, x, be):

    if ((not grad_op_tree) or (not x)):
        return grad_op_tree
    if (type(x) in _scalar_types):
        return 0.0
    in_shape = x.shape
    out_shape = grad_op_tree.shape
    if (in_shape == out_shape):
        return grad_op_tree
    elif ((len(in_shape) == 2) and (len(out_shape) == 2)):
        if (in_shape == (1, 1)):
            return be.sum(grad_op_tree)
        elif ((in_shape[0] == out_shape[0]) and (in_shape[1] == 1)):
            return be.sum(grad_op_tree, axis=1)
        elif ((in_shape[0] == 1) and (in_shape[1] == out_shape[1])):
            return be.sum(grad_op_tree, axis=0)
        elif (((out_shape[0] == in_shape[0]) and (out_shape[1] == 1)) or ((out_shape[0] == 1) and (out_shape[1] == in_shape[1]))):
            return ((0 * x) + grad_op_tree)
        else:
            return NotImplemented
    else:
        return NotImplemented
