def __init__(self,
               num_rows,
               multiplier,
               is_non_singular=None,
               is_self_adjoint=None,
               is_positive_definite=None,
               assert_proper_shapes=False,
               name="LinearOperatorScaledIdentity"):
    """Initialize a `LinearOperatorScaledIdentity`.

    The `LinearOperatorScaledIdentity` is initialized with `num_rows`, which
    determines the size of each identity matrix, and a `multiplier`,
    which defines `dtype`, batch shape, and scale of each matrix.

    This operator is able to broadcast the leading (batch) dimensions.

    Args:
      num_rows:  Scalar non-negative integer `Tensor`.  Number of rows in the
        corresponding identity matrix.
      multiplier:  `Tensor` of shape `[B1,...,Bb]`, or `[]` (a scalar).
      is_non_singular:  Expect that this operator is non-singular.
      is_self_adjoint:  Expect that this operator is equal to its hermitian
        transpose.
      is_positive_definite:  Expect that this operator is positive definite.
      assert_proper_shapes:  Python `bool`.  If `False`, only perform static
        checks that initialization and method arguments have proper shape.
        If `True`, and static checks are inconclusive, add asserts to the graph.
      name: A name for this `LinearOperator`

    Raises:
      ValueError:  If `num_rows` is determined statically to be non-scalar, or
        negative.
    """
    self._assert_proper_shapes = assert_proper_shapes

    with ops.name_scope(name, values=[multiplier, num_rows]):
      self._multiplier = ops.convert_to_tensor(multiplier, name="multiplier")

      super(LinearOperatorScaledIdentity, self).__init__(
          dtype=self._multiplier.dtype,
          is_non_singular=is_non_singular,
          is_self_adjoint=is_self_adjoint,
          is_positive_definite=is_positive_definite,
          name=name)

      # Shape [B1,...Bb, 1, 1]
      self._multiplier_matrix = array_ops.expand_dims(
          array_ops.expand_dims(self.multiplier, -1), -1)
      self._multiplier_matrix_conj = math_ops.conj(
          self._multiplier_matrix)
      self._abs_multiplier = math_ops.abs(self.multiplier)

      self._num_rows = linear_operator_util.shape_tensor(
          num_rows, name="num_rows")
      self._num_rows_static = tensor_util.constant_value(self._num_rows)
      self._check_num_rows_possibly_add_asserts()
      self._num_rows_cast_to_dtype = math_ops.cast(self._num_rows, self.dtype)
      self._num_rows_cast_to_real_dtype = math_ops.cast(
          self._num_rows, self.dtype.real_dtype)
  def __init__(self,
               num_rows,
               multiplier,
               is_non_singular=None,
               is_self_adjoint=None,
               is_positive_definite=None,
               assert_proper_shapes=False,
               name="LinearOperatorScaledIdentity"):
    """Initialize a `LinearOperatorScaledIdentity`.

    The `LinearOperatorScaledIdentity` is initialized with `num_rows`, which
    determines the size of each identity matrix, and a `multiplier`,
    which defines `dtype`, batch shape, and scale of each matrix.

    This operator is able to broadcast the leading (batch) dimensions.

    Args:
      num_rows:  Scalar non-negative integer `Tensor`.  Number of rows in the
        corresponding identity matrix.
      multiplier:  `Tensor` of shape `[B1,...,Bb]`, or `[]` (a scalar).
      is_non_singular:  Expect that this operator is non-singular.
      is_self_adjoint:  Expect that this operator is equal to its hermitian
        transpose.
      is_positive_definite:  Expect that this operator is positive definite.
      assert_proper_shapes:  Python `bool`.  If `False`, only perform static
        checks that initialization and method arguments have proper shape.
        If `True`, and static checks are inconclusive, add asserts to the graph.
      name: A name for this `LinearOperator`

    Raises:
      ValueError:  If `num_rows` is determined statically to be non-scalar, or
        negative.
    """
    self._assert_proper_shapes = assert_proper_shapes

    with ops.name_scope(name, values=[multiplier, num_rows]):
      self._multiplier = ops.convert_to_tensor(multiplier, name="multiplier")

      super(LinearOperatorScaledIdentity, self).__init__(
          dtype=self._multiplier.dtype,
          is_non_singular=is_non_singular,
          is_self_adjoint=is_self_adjoint,
          is_positive_definite=is_positive_definite,
          name=name)

      # Shape [B1,...Bb, 1, 1]
      self._multiplier_matrix = array_ops.expand_dims(
          array_ops.expand_dims(self.multiplier, -1), -1)
      self._multiplier_matrix_conj = math_ops.conj(
          self._multiplier_matrix)
      self._abs_multiplier = math_ops.abs(self.multiplier)

      self._num_rows = linear_operator_util.shape_tensor(
          num_rows, name="num_rows")
      self._num_rows_static = tensor_util.constant_value(self._num_rows)
      self._check_num_rows_possibly_add_asserts()
      self._num_rows_cast_to_dtype = math_ops.cast(self._num_rows, self.dtype)
      self._num_rows_cast_to_real_dtype = math_ops.cast(
          self._num_rows, self.dtype.real_dtype)
예제 #3
0
  def batch_shape_tensor(self, name="batch_shape_tensor"):
    """Shape of batch dimensions of this operator, determined at runtime.

    If this operator acts like the batch matrix `A` with
    `A.shape = [B1,...,Bb, M, N]`, then this returns a `Tensor` holding
    `[B1,...,Bb]`.

    Args:
      name:  A name for this `Op.

    Returns:
      `int32` `Tensor`
    """
    # Derived classes get this "for free" once .shape() is implemented.
    with self._name_scope(name):
      if self._cached_batch_shape_tensor is None:
        # Prefer to use statically defined shape if available.
        if self.batch_shape.is_fully_defined():
          self._cached_batch_shape_tensor = linear_operator_util.shape_tensor(
              self.batch_shape.as_list(), name="batch_shape")
        else:
          self._cached_batch_shape_tensor = self.shape_tensor()[:-2]
      return self._cached_batch_shape_tensor
예제 #4
0
  def shape_tensor(self, name="shape_tensor"):
    """Shape of this `LinearOperator`, determined at runtime.

    If this operator acts like the batch matrix `A` with
    `A.shape = [B1,...,Bb, M, N]`, then this returns a `Tensor` holding
    `[B1,...,Bb, M, N]`, equivalent to `tf.shape(A)`.

    Args:
      name:  A name for this `Op.

    Returns:
      `int32` `Tensor`
    """
    with self._name_scope(name):
      # Be clean by avoiding adding shape Ops to the graph too many times.
      if self._cached_shape_tensor is None:
        # Prefer to use statically defined shape if available.
        if self.shape.is_fully_defined():
          self._cached_shape_tensor = linear_operator_util.shape_tensor(
              self.shape.as_list())
        else:
          self._cached_shape_tensor = self._shape_tensor()
      return self._cached_shape_tensor
예제 #5
0
    def batch_shape_tensor(self, name="batch_shape_tensor"):
        """Shape of batch dimensions of this operator, determined at runtime.

    If this operator acts like the batch matrix `A` with
    `A.shape = [B1,...,Bb, M, N]`, then this returns a `Tensor` holding
    `[B1,...,Bb]`.

    Args:
      name:  A name for this `Op.

    Returns:
      `int32` `Tensor`
    """
        # Derived classes get this "for free" once .shape() is implemented.
        with self._name_scope(name):
            if self._cached_batch_shape_tensor is None:
                # Prefer to use statically defined shape if available.
                if self.batch_shape.is_fully_defined():
                    self._cached_batch_shape_tensor = linear_operator_util.shape_tensor(
                        self.batch_shape.as_list(), name="batch_shape")
                else:
                    self._cached_batch_shape_tensor = self.shape_tensor()[:-2]
            return self._cached_batch_shape_tensor
예제 #6
0
    def shape_tensor(self, name="shape_tensor"):
        """Shape of this `LinearOperator`, determined at runtime.

    If this operator acts like the batch matrix `A` with
    `A.shape = [B1,...,Bb, M, N]`, then this returns a `Tensor` holding
    `[B1,...,Bb, M, N]`, equivalent to `tf.shape(A)`.

    Args:
      name:  A name for this `Op.

    Returns:
      `int32` `Tensor`
    """
        with self._name_scope(name):
            # Be clean by avoiding adding shape Ops to the graph too many times.
            if self._cached_shape_tensor is None:
                # Prefer to use statically defined shape if available.
                if self.shape.is_fully_defined():
                    self._cached_shape_tensor = linear_operator_util.shape_tensor(
                        self.shape.as_list())
                else:
                    self._cached_shape_tensor = self._shape_tensor()
            return self._cached_shape_tensor
예제 #7
0
    def __init__(self,
                 num_rows,
                 batch_shape=None,
                 dtype=None,
                 is_non_singular=True,
                 is_self_adjoint=True,
                 is_positive_definite=True,
                 assert_proper_shapes=False,
                 name="LinearOperatorIdentity"):
        r"""Initialize a `LinearOperatorIdentity`.

    The `LinearOperatorIdentity` is initialized with arguments defining `dtype`
    and shape.

    This operator is able to broadcast the leading (batch) dimensions, which
    sometimes requires copying data.  If `batch_shape` is `None`, the operator
    can take arguments of any batch shape without copying.  See examples.

    Args:
      num_rows:  Scalar non-negative integer `Tensor`.  Number of rows in the
        corresponding identity matrix.
      batch_shape:  Optional `1-D` integer `Tensor`.  The shape of the leading
        dimensions.  If `None`, this operator has no leading dimensions.
      dtype:  Data type of the matrix that this operator represents.
      is_non_singular:  Expect that this operator is non-singular.
      is_self_adjoint:  Expect that this operator is equal to its hermitian
        transpose.
      is_positive_definite:  Expect that this operator is positive definite,
        meaning the quadratic form `x^H A x` has positive real part for all
        nonzero `x`.  Note that we do not require the operator to be
        self-adjoint to be positive-definite.  See:
        https://en.wikipedia.org/wiki/Positive-definite_matrix\
            #Extension_for_non_symmetric_matrices
      assert_proper_shapes:  Python `bool`.  If `False`, only perform static
        checks that initialization and method arguments have proper shape.
        If `True`, and static checks are inconclusive, add asserts to the graph.
      name: A name for this `LinearOperator`

    Raises:
      ValueError:  If `num_rows` is determined statically to be non-scalar, or
        negative.
      ValueError:  If `batch_shape` is determined statically to not be 1-D, or
        negative.
      ValueError:  If any of the following is not `True`:
        `{is_self_adjoint, is_non_singular, is_positive_definite}`.
    """
        dtype = dtype or dtypes.float32
        self._assert_proper_shapes = assert_proper_shapes

        with ops.name_scope(name):
            dtype = dtypes.as_dtype(dtype)
            if not is_self_adjoint:
                raise ValueError(
                    "An identity operator is always self adjoint.")
            if not is_non_singular:
                raise ValueError(
                    "An identity operator is always non-singular.")
            if not is_positive_definite:
                raise ValueError(
                    "An identity operator is always positive-definite.")

            super(LinearOperatorIdentity,
                  self).__init__(dtype=dtype,
                                 is_non_singular=is_non_singular,
                                 is_self_adjoint=is_self_adjoint,
                                 is_positive_definite=is_positive_definite,
                                 name=name)

            self._num_rows = linear_operator_util.shape_tensor(num_rows,
                                                               name="num_rows")
            self._num_rows_static = tensor_util.constant_value(self._num_rows)
            self._check_num_rows_possibly_add_asserts()

            if batch_shape is None:
                self._batch_shape_arg = None
            else:
                self._batch_shape_arg = linear_operator_util.shape_tensor(
                    batch_shape, name="batch_shape_arg")
                self._batch_shape_static = tensor_util.constant_value(
                    self._batch_shape_arg)
                self._check_batch_shape_possibly_add_asserts()
예제 #8
0
  def __init__(self,
               num_rows,
               batch_shape=None,
               dtype=None,
               is_non_singular=True,
               is_self_adjoint=True,
               is_positive_definite=True,
               assert_proper_shapes=False,
               name="LinearOperatorIdentity"):
    """Initialize a `LinearOperatorIdentity`.

    The `LinearOperatorIdentity` is initialized with arguments defining `dtype`
    and shape.

    This operator is able to broadcast the leading (batch) dimensions, which
    sometimes requires copying data.  If `batch_shape` is `None`, the operator
    can take arguments of any batch shape without copying.  See examples.

    Args:
      num_rows:  Scalar non-negative integer `Tensor`.  Number of rows in the
        corresponding identity matrix.
      batch_shape:  Optional `1-D` integer `Tensor`.  The shape of the leading
        dimensions.  If `None`, this operator has no leading dimensions.
      dtype:  Data type of the matrix that this operator represents.
      is_non_singular:  Expect that this operator is non-singular.
      is_self_adjoint:  Expect that this operator is equal to its hermitian
        transpose.
      is_positive_definite:  Expect that this operator is positive definite.
      assert_proper_shapes:  Python `bool`.  If `False`, only perform static
        checks that initialization and method arguments have proper shape.
        If `True`, and static checks are inconclusive, add asserts to the graph.
      name: A name for this `LinearOperator`

    Raises:
      ValueError:  If `num_rows` is determined statically to be non-scalar, or
        negative.
      ValueError:  If `batch_shape` is determined statically to not be 1-D, or
        negative.
      ValueError:  If any of the following is not `True`:
        `{is_self_adjoint, is_non_singular, is_positive_definite}`.
    """
    dtype = dtype or dtypes.float32
    self._assert_proper_shapes = assert_proper_shapes

    with ops.name_scope(name):
      dtype = dtypes.as_dtype(dtype)
      if not is_self_adjoint:
        raise ValueError("An identity operator is always self adjoint.")
      if not is_non_singular:
        raise ValueError("An identity operator is always non-singular.")
      if not is_positive_definite:
        raise ValueError("An identity operator is always positive-definite.")

      super(LinearOperatorIdentity, self).__init__(
          dtype=dtype,
          is_non_singular=is_non_singular,
          is_self_adjoint=is_self_adjoint,
          is_positive_definite=is_positive_definite,
          name=name)

      self._num_rows = linear_operator_util.shape_tensor(
          num_rows, name="num_rows")
      self._num_rows_static = tensor_util.constant_value(self._num_rows)
      self._check_num_rows_possibly_add_asserts()

      if batch_shape is None:
        self._batch_shape_arg = None
      else:
        self._batch_shape_arg = linear_operator_util.shape_tensor(
            batch_shape, name="batch_shape_arg")
        self._batch_shape_static = tensor_util.constant_value(
            self._batch_shape_arg)
        self._check_batch_shape_possibly_add_asserts()