def _block_shape_tensor(self, spectrum_shape=None): if self.block_shape.is_fully_defined(): return linear_operator_util.shape_tensor( self.block_shape.as_list(), name="block_shape") spectrum_shape = (prefer_static.shape(self.spectrum) if spectrum_shape is None else spectrum_shape) return spectrum_shape[-self.block_depth:]
def _batch_shape_tensor(self, shape=None): # `shape` may be passed in if this can be pre-computed in a # more efficient manner, e.g. without excessive Tensor conversions. if self.batch_shape.is_fully_defined(): return linear_operator_util.shape_tensor( self.batch_shape.as_list(), name="batch_shape") else: shape = self.shape_tensor() if shape is None else shape return shape[:-2]
def shape_tensor(self, name="shape_tensor"): """Shape of this `LinearOperator`, determined at runtime. If this operator acts like the batch matrix `A` with `tensor_shape.TensorShape(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): # Prefer to use statically defined shape if available. if tensor_shape.TensorShape(self.shape).is_fully_defined(): return linear_operator_util.shape_tensor(tensor_shape.TensorShape(self.shape).as_list()) else: return self._shape_tensor()
def __init__(self, num_rows, multiplier, is_non_singular=None, is_self_adjoint=None, is_positive_definite=None, is_square=True, assert_proper_shapes=False, name="LinearOperatorScaledIdentity"): r"""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, 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 is_square: Expect that this operator acts like square [batch] 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. """ self._assert_proper_shapes = assert_proper_shapes with ops.name_scope(name, values=[multiplier, num_rows]): self._multiplier = linear_operator_util.convert_nonref_to_tensor( multiplier, name="multiplier") # Check and auto-set hints. if not np.issubdtype(self._multiplier.dtype, np.complexfloating): if is_self_adjoint is False: # pylint: disable=g-bool-id-comparison raise ValueError( "A real diagonal operator is always self adjoint.") else: is_self_adjoint = True if not is_square: raise ValueError("A ScaledIdentity operator is always square.") linear_operator_util.assert_not_ref_type(num_rows, "num_rows") 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, is_square=is_square, name=name) self._num_rows = linear_operator_util.shape_tensor(num_rows, name="num_rows") self._num_rows_static = (self._num_rows) self._check_num_rows_possibly_add_asserts() self._num_rows_cast_to_dtype = _ops.cast(self._num_rows, self.dtype) self._num_rows_cast_to_real_dtype = _ops.cast( self._num_rows, dtypes.real_dtype(self.dtype))
def __init__(self, num_rows, batch_shape=None, dtype=None, is_non_singular=True, is_self_adjoint=True, is_positive_definite=True, is_square=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 is_square: Expect that this operator acts like square [batch] 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}`. TypeError: If `num_rows` or `batch_shape` is ref-type (e.g. Variable). """ 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.") if not is_square: raise ValueError("An identity operator is always square.") super(LinearOperatorIdentity, self).__init__(dtype=dtype, is_non_singular=is_non_singular, is_self_adjoint=is_self_adjoint, is_positive_definite=is_positive_definite, is_square=is_square, name=name) linear_operator_util.assert_not_ref_type(num_rows, "num_rows") linear_operator_util.assert_not_ref_type(batch_shape, "batch_shape") self._num_rows = linear_operator_util.shape_tensor(num_rows, name="num_rows") self._num_rows_static = (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 = (self._batch_shape_arg) self._check_batch_shape_possibly_add_asserts()