Type LinearOperatorCirculant2D
Namespace tensorflow.linalg
Parent _BaseLinearOperatorCirculant
Interfaces ILinearOperatorCirculant2D
`LinearOperator` acting like a block circulant matrix. This operator acts like a block circulant matrix `A` with
shape `[B1,...,Bb, N, N]` for some `b >= 0`. The first `b` indices index a
batch member. For every batch index `(i1,...,ib)`, `A[i1,...,ib, : :]` is
an `N x N` matrix. This matrix `A` is not materialized, but for
purposes of broadcasting this shape will be relevant. #### Description in terms of block circulant matrices If `A` is block circulant, with block sizes `N0, N1` (`N0 * N1 = N`):
`A` has a block circulant structure, composed of `N0 x N0` blocks, with each
block an `N1 x N1` circulant matrix. For example, with `W`, `X`, `Y`, `Z` each circulant, ```
A = |W Z Y X|
|X W Z Y|
|Y X W Z|
|Z Y X W|
``` Note that `A` itself will not in general be circulant. #### Description in terms of the frequency spectrum There is an equivalent description in terms of the [batch] spectrum `H` and
Fourier transforms. Here we consider `A.shape = [N, N]` and ignore batch
dimensions. If `H.shape = [N0, N1]`, (`N0 * N1 = N`):
Loosely speaking, matrix multiplication is equal to the action of a
Fourier multiplier: `A u = IDFT2[ H DFT2[u] ]`.
Precisely speaking, given `[N, R]` matrix `u`, let `DFT2[u]` be the
`[N0, N1, R]` `Tensor` defined by re-shaping `u` to `[N0, N1, R]` and taking
a two dimensional DFT across the first two dimensions. Let `IDFT2` be the
inverse of `DFT2`. Matrix multiplication may be expressed columnwise: ```(A u)_r = IDFT2[ H * (DFT2[u])_r ]``` #### Operator properties deduced from the spectrum. * This operator is positive definite if and only if `Real{H} > 0`. A general property of Fourier transforms is the correspondence between
Hermitian functions and real valued transforms. Suppose `H.shape = [B1,...,Bb, N0, N1]`, we say that `H` is a Hermitian
spectrum if, with `%` indicating modulus division, ```
H[..., n0 % N0, n1 % N1] = ComplexConjugate[ H[..., (-n0) % N0, (-n1) % N1 ].
``` * This operator corresponds to a real matrix if and only if `H` is Hermitian.
* This operator is self-adjoint if and only if `H` is real. See e.g. "Discrete-Time Signal Processing", Oppenheim and Schafer. ### Example of a self-adjoint positive definite operator
#### Example of defining in terms of a real convolution kernel,
#### Performance Suppose `operator` is a `LinearOperatorCirculant` of shape `[N, N]`,
and `x.shape = [N, R]`. Then * `operator.matmul(x)` is `O(R*N*Log[N])`
* `operator.solve(x)` is `O(R*N*Log[N])`
* `operator.determinant()` involves a size `N` `reduce_prod`. If instead `operator` and `x` have shape `[B1,...,Bb, N, N]` and
`[B1,...,Bb, N, R]`, every operation increases in complexity by `B1*...*Bb`. #### Matrix property hints This `LinearOperator` is initialized with boolean flags of the form `is_X`,
for `X = non_singular, self_adjoint, positive_definite, square`.
These have the following meaning
* If `is_X == True`, callers should expect the operator to have the
property `X`. This is a promise that should be fulfilled, but is *not* a
runtime assert. For example, finite floating point precision may result
in these promises being violated.
* If `is_X == False`, callers should expect the operator to not have `X`.
* If `is_X == None` (the default), callers should have no expectation either
way.
Show Example
# spectrum is real ==> operator is self-adjoint # spectrum is positive ==> operator is positive definite spectrum = [[1., 2., 3.], [4., 5., 6.], [7., 8., 9.]] operator = LinearOperatorCirculant2D(spectrum) # IFFT[spectrum] operator.convolution_kernel() ==> [[5.0+0.0j, -0.5-.3j, -0.5+.3j], [-1.5-.9j, 0, 0], [-1.5+.9j, 0, 0]] operator.to_dense() ==> Complex self adjoint 9 x 9 matrix.
Methods
- assert_hermitian_spectrum
- assert_hermitian_spectrum_dyn
- block_shape_tensor
- block_shape_tensor_dyn
- convolution_kernel
- convolution_kernel_dyn
- matvec
- matvec
- matvec
- matvec_dyn
- to_dense_dyn
Properties
- batch_shape
- batch_shape_dyn
- block_depth
- block_depth_dyn
- block_shape
- block_shape_dyn
- domain_dimension
- domain_dimension_dyn
- dtype
- dtype_dyn
- graph_parents
- graph_parents_dyn
- is_non_singular
- is_non_singular_dyn
- is_positive_definite
- is_positive_definite_dyn
- is_self_adjoint
- is_self_adjoint_dyn
- is_square
- is_square_dyn
- name
- name_dyn
- name_scope
- name_scope_dyn
- PythonObject
- range_dimension
- range_dimension_dyn
- shape
- shape_dyn
- spectrum
- spectrum_dyn
- submodules
- submodules_dyn
- tensor_rank
- tensor_rank_dyn
- trainable_variables
- trainable_variables_dyn
- variables
- variables_dyn
Public instance methods
object assert_hermitian_spectrum(string name)
object assert_hermitian_spectrum_dyn(ImplicitContainer<T> name)
object block_shape_tensor()
object block_shape_tensor_dyn()
object convolution_kernel(string name)
object convolution_kernel_dyn(ImplicitContainer<T> name)
Tensor matvec(ValueTuple<PythonClassContainer, PythonClassContainer> x, bool adjoint, string name)
Transform [batch] vector `x` with left multiplication: `x --> Ax`.
Parameters
-
ValueTuple<PythonClassContainer, PythonClassContainer>
x - `Tensor` with compatible shape and same `dtype` as `self`. `x` is treated as a [batch] vector meaning for every set of leading dimensions, the last dimension defines a vector. See class docstring for definition of compatibility.
-
bool
adjoint - Python `bool`. If `True`, left multiply by the adjoint: `A^H x`.
-
string
name - A name for this `Op`.
Returns
-
Tensor
- A `Tensor` with shape `[..., M]` and same `dtype` as `self`.
Show Example
# Make an operator acting like batch matric A. Assume A.shape = [..., M, N] operator = LinearOperator(...) X =... # shape [..., N], batch vector Y = operator.matvec(X) Y.shape ==> [..., M] Y[..., :] = sum_j A[..., :, j] X[..., j]
Tensor matvec(IndexedSlices x, bool adjoint, string name)
Transform [batch] vector `x` with left multiplication: `x --> Ax`.
Parameters
-
IndexedSlices
x - `Tensor` with compatible shape and same `dtype` as `self`. `x` is treated as a [batch] vector meaning for every set of leading dimensions, the last dimension defines a vector. See class docstring for definition of compatibility.
-
bool
adjoint - Python `bool`. If `True`, left multiply by the adjoint: `A^H x`.
-
string
name - A name for this `Op`.
Returns
-
Tensor
- A `Tensor` with shape `[..., M]` and same `dtype` as `self`.
Show Example
# Make an operator acting like batch matric A. Assume A.shape = [..., M, N] operator = LinearOperator(...) X =... # shape [..., N], batch vector Y = operator.matvec(X) Y.shape ==> [..., M] Y[..., :] = sum_j A[..., :, j] X[..., j]
Tensor matvec(IGraphNodeBase x, bool adjoint, string name)
Transform [batch] vector `x` with left multiplication: `x --> Ax`.
Parameters
-
IGraphNodeBase
x - `Tensor` with compatible shape and same `dtype` as `self`. `x` is treated as a [batch] vector meaning for every set of leading dimensions, the last dimension defines a vector. See class docstring for definition of compatibility.
-
bool
adjoint - Python `bool`. If `True`, left multiply by the adjoint: `A^H x`.
-
string
name - A name for this `Op`.
Returns
-
Tensor
- A `Tensor` with shape `[..., M]` and same `dtype` as `self`.
Show Example
# Make an operator acting like batch matric A. Assume A.shape = [..., M, N] operator = LinearOperator(...) X =... # shape [..., N], batch vector Y = operator.matvec(X) Y.shape ==> [..., M] Y[..., :] = sum_j A[..., :, j] X[..., j]
object matvec_dyn(object x, ImplicitContainer<T> adjoint, ImplicitContainer<T> name)
Transform [batch] vector `x` with left multiplication: `x --> Ax`.
Parameters
-
object
x - `Tensor` with compatible shape and same `dtype` as `self`. `x` is treated as a [batch] vector meaning for every set of leading dimensions, the last dimension defines a vector. See class docstring for definition of compatibility.
-
ImplicitContainer<T>
adjoint - Python `bool`. If `True`, left multiply by the adjoint: `A^H x`.
-
ImplicitContainer<T>
name - A name for this `Op`.
Returns
-
object
- A `Tensor` with shape `[..., M]` and same `dtype` as `self`.
Show Example
# Make an operator acting like batch matric A. Assume A.shape = [..., M, N] operator = LinearOperator(...) X =... # shape [..., N], batch vector Y = operator.matvec(X) Y.shape ==> [..., M] Y[..., :] = sum_j A[..., :, j] X[..., j]
object to_dense_dyn(ImplicitContainer<T> name)
Return a dense (batch) matrix representing this operator.