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 = (array_ops.shape(self.spectrum) if spectrum_shape is None else spectrum_shape) return spectrum_shape[-self.block_depth:]
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="LinearOperatorLogIdentity"): 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(LinearOperatorLogIdentity, 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) 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()
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 `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 self.shape.is_fully_defined(): return linear_operator_util.shape_tensor(self.shape.as_list()) else: return self._shape_tensor()
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): # Prefer to use statically defined shape if available. if self.shape.is_fully_defined(): return linear_operator_util.shape_tensor(self.shape.as_list()) else: return self._shape_tensor()
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): # Prefer to use statically defined shape if available. if self.batch_shape.is_fully_defined(): return linear_operator_util.shape_tensor( self.batch_shape.as_list(), name="batch_shape") else: return self.shape_tensor()[:-2]
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): # Prefer to use statically defined shape if available. if self.batch_shape.is_fully_defined(): return linear_operator_util.shape_tensor( self.batch_shape.as_list(), name="batch_shape") else: return self.shape_tensor()[:-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 `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
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
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. """ parameters = dict(num_rows=num_rows, multiplier=multiplier, is_non_singular=is_non_singular, is_self_adjoint=is_self_adjoint, is_positive_definite=is_positive_definite, is_square=is_square, assert_proper_shapes=assert_proper_shapes, name=name) 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 self._multiplier.dtype.is_complex: 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.base_dtype, is_non_singular=is_non_singular, is_self_adjoint=is_self_adjoint, is_positive_definite=is_positive_definite, is_square=is_square, parameters=parameters, 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() 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, 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). """ parameters = dict(num_rows=num_rows, batch_shape=batch_shape, dtype=dtype, is_non_singular=is_non_singular, is_self_adjoint=is_self_adjoint, is_positive_definite=is_positive_definite, is_square=is_square, assert_proper_shapes=assert_proper_shapes, name=name) 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, parameters=parameters, 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 = 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()
def __init__(self, num_rows, num_columns=None, batch_shape=None, dtype=None, is_non_singular=False, is_self_adjoint=True, is_positive_definite=False, is_square=True, assert_proper_shapes=False, name="LinearOperatorZeros"): r"""Initialize a `LinearOperatorZeros`. The `LinearOperatorZeros` 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 zero matrix. num_columns: Scalar non-negative integer `Tensor`. Number of columns in the corresponding zero matrix. If `None`, defaults to the value of `num_rows`. 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 `num_columns` 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 and is_square: raise ValueError("A zero operator is always self adjoint.") if is_non_singular: raise ValueError("A zero operator is always singular.") if is_positive_definite: raise ValueError("A zero operator is always not positive-definite.") super(LinearOperatorZeros, 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) self._num_rows = linear_operator_util.shape_tensor( num_rows, name="num_rows") self._num_rows_static = tensor_util.constant_value(self._num_rows) if num_columns is None: num_columns = num_rows self._num_columns = linear_operator_util.shape_tensor( num_columns, name="num_columns") self._num_columns_static = tensor_util.constant_value(self._num_columns) self._check_domain_range_possibly_add_asserts() if (self._num_rows_static is not None and self._num_columns_static is not None): if is_square and self._num_rows_static != self._num_columns_static: raise ValueError( "LinearOperatorZeros initialized as is_square=True, but got " "num_rows({}) != num_columns({})".format( self._num_rows_static, self._num_columns_static)) 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()
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 if not is_square: raise ValueError("A ScaledIdentity operator is always square.") 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, is_square=is_square, 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)