Save the date! Google I/O returns May 18-20 Register now

tf.linalg.LinearOperator

Base class defining a [batch of] linear operator[s].

Inherits From: Module

Subclasses of LinearOperator provide access to common methods on a (batch) matrix, without the need to materialize the matrix. This allows:

  • Matrix free computations
  • Operators that take advantage of special structure, while providing a consistent API to users.

Subclassing

To enable a public method, subclasses should implement the leading-underscore version of the method. The argument signature should be identical except for the omission of name="...". For example, to enable matmul(x, adjoint=False, name="matmul") a subclass should implement _matmul(x, adjoint=False).

Performance contract

Subclasses should only implement the assert methods (e.g. assert_non_singular) if they can be done in less than O(N^3) time.

Class docstrings should contain an explanation of computational complexity. Since this is a high-performance library, attention should be paid to detail, and explanations can include constants as well as Big-O notation.

Shape compatibility

LinearOperator subclasses should operate on a [batch] matrix with compatible shape. Class docstrings should define what is meant by compatible shape. Some subclasses may not support batching.

Examples:

x is a batch matrix with compatible shape for matmul if

operator.shape = [B1,...,Bb] + [M, N],  b >= 0,
x.shape =   [B1,...,Bb] + [N, R]

rhs is a batch matrix with compatible shape for solve if

operator.shape = [B1,...,Bb] + [M, N],  b >= 0,
rhs.shape =   [B1,...,Bb] + [M, R]

Example docstring for subclasses.

This operator acts like a (batch) matrix A with shape [B1,...,Bb, M, N] for some b >= 0. The first b indices index a batch member. For every batch index (i1,...,ib), A[i1,...,ib, : :] is an m x n matrix. Again, this matrix A may not be materialized, but for purposes of identifying and working with compatible arguments the shape is relevant.

Examples:

some_tensor = ... shape = ????
operator = MyLinOp(some_tensor)

operator.shape()
==> [2, 4, 4]

operator.log_abs_determinant()
==> Shape [2] Tensor

x = ... Shape [2, 4, 5] Tensor

operator.matmul(x)
==> Shape [2, 4, 5] Tensor

Shape compatibility

This operator acts on batch matrices with compatible shape. FILL IN WHAT IS MEANT BY COMPATIBLE SHAPE

Performance

FILL THIS IN

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.

Initialization parameters

All subclasses of LinearOperator are expected to pass a parameters argument to super().__init__(). This should be a dict containing the unadulterated arguments passed to the subclass __init__. For example, MyLinearOperator with an initializer should look like:

def __init__(self, operator, is_square=False, name=None):
   parameters = dict(
       operator=operator,
       is_square=is_square,
       name=name
   )
   ...
   super().__init__(..., parameters=parameters)
 ```

 Users can then access `my_linear_operator.parameters` to see all arguments
 passed to its initializer.

<!-- Tabular view -->
 <table class="responsive fixed orange">
<colgroup><col width="214px"><col></colgroup>
<tr><th colspan="2"><h2 class="add-link">Args</h2></th></tr>

<tr>
<td>
`dtype`
</td>
<td>
The type of the this `LinearOperator`.  Arguments to `matmul` and
`solve` will have to be this type.
</td>
</tr><tr>
<td>
`graph_parents`
</td>
<td>
(Deprecated) Python list of graph prerequisites of this
`LinearOperator` Typically tensors that are passed during initialization
</td>
</tr><tr>
<td>
`is_non_singular`
</td>
<td>
Expect that this operator is non-singular.
</td>
</tr><tr>
<td>
`is_self_adjoint`
</td>
<td>
Expect that this operator is equal to its hermitian
transpose.  If `dtype` is real, this is equivalent to being symmetric.
</td>
</tr><tr>
<td>
`is_positive_definite`
</td>
<td>
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:
<a href="https://en.wikipedia.org/wiki/Positive-definite_matrix#Extension_for_non-symmetric_matrices">https://en.wikipedia.org/wiki/Positive-definite_matrix#Extension_for_non-symmetric_matrices</a>
</td>
</tr><tr>
<td>
`is_square`
</td>
<td>
Expect that this operator acts like square [batch] matrices.
</td>
</tr><tr>
<td>
`name`
</td>
<td>
A name for this `LinearOperator`.
</td>
</tr><tr>
<td>
`parameters`
</td>
<td>
Python `dict` of parameters used to instantiate this
`LinearOperator`.
</td>
</tr>
</table>



<!-- Tabular view -->
 <table class="responsive fixed orange">
<colgroup><col width="214px"><col></colgroup>
<tr><th colspan="2"><h2 class="add-link">Raises</h2></th></tr>

<tr>
<td>
`ValueError`
</td>
<td>
If any member of graph_parents is `None` or not a `Tensor`.
</td>
</tr><tr>
<td>
`ValueError`
</td>
<td>
If hints are set incorrectly.
</td>
</tr>
</table>





<!-- Tabular view -->
 <table class="responsive fixed orange">
<colgroup><col width="214px"><col></colgroup>
<tr><th colspan="2"><h2 class="add-link">Attributes</h2></th></tr>

<tr>
<td>
`H`
</td>
<td>
Returns the adjoint of the current `LinearOperator`.

Given `A` representing this `LinearOperator`, return `A*`.
Note that calling `self.adjoint()` and `self.H` are equivalent.
</td>
</tr><tr>
<td>
`batch_shape`
</td>
<td>
`TensorShape` of batch dimensions of this `LinearOperator`.

If this operator acts like the batch matrix `A` with
`A.shape = [B1,...,Bb, M, N]`, then this returns
`TensorShape([B1,...,Bb])`, equivalent to `A.shape[:-2]`
</td>
</tr><tr>
<td>
`domain_dimension`
</td>
<td>
Dimension (in the sense of vector spaces) of the domain of this operator.

If this operator acts like the batch matrix `A` with
`A.shape = [B1,...,Bb, M, N]`, then this returns `N`.
</td>
</tr><tr>
<td>
`dtype`
</td>
<td>
The `DType` of `Tensor`s handled by this `LinearOperator`.
</td>
</tr><tr>
<td>
`graph_parents`
</td>
<td>
List of graph dependencies of this `LinearOperator`. (deprecated)

Warning: THIS FUNCTION IS DEPRECATED. It will be removed in a future version.
Instructions for updating:
Do not call `graph_parents`.
</td>
</tr><tr>
<td>
`is_non_singular`
</td>
<td>

</td>
</tr><tr>
<td>
`is_positive_definite`
</td>
<td>

</td>
</tr><tr>
<td>
`is_self_adjoint`
</td>
<td>

</td>
</tr><tr>
<td>
`is_square`
</td>
<td>
Return `True/False` depending on if this operator is square.
</td>
</tr><tr>
<td>
`parameters`
</td>
<td>
Dictionary of parameters used to instantiate this `LinearOperator`.
</td>
</tr><tr>
<td>
`range_dimension`
</td>
<td>
Dimension (in the sense of vector spaces) of the range of this operator.

If this operator acts like the batch matrix `A` with
`A.shape = [B1,...,Bb, M, N]`, then this returns `M`.
</td>
</tr><tr>
<td>
`shape`
</td>
<td>
`TensorShape` of this `LinearOperator`.

If this operator acts like the batch matrix `A` with
`A.shape = [B1,...,Bb, M, N]`, then this returns
`TensorShape([B1,...,Bb, M, N])`, equivalent to `A.shape`.
</td>
</tr><tr>
<td>
`tensor_rank`
</td>
<td>
Rank (in the sense of tensors) of matrix corresponding to this operator.

If this operator acts like the batch matrix `A` with
`A.shape = [B1,...,Bb, M, N]`, then this returns `b + 2`.
</td>
</tr>
</table>



## Methods

<h3 id="add_to_tensor"><code>add_to_tensor</code></h3>

<a target="_blank" href="https://github.com/tensorflow/tensorflow/blob/v2.4.1/tensorflow/python/ops/linalg/linear_operator.py#L1077-L1090">View source</a>

<pre class="devsite-click-to-copy prettyprint lang-py tfo-signature-link">
<code>add_to_tensor(
    x, name=&#x27;add_to_tensor&#x27;
)
</code></pre>

Add matrix represented by this operator to `x`.  Equivalent to `A + x`.


<!-- Tabular view -->
 <table class="responsive fixed orange">
<colgroup><col width="214px"><col></colgroup>
<tr><th colspan="2">Args</th></tr>

<tr>
<td>
`x`
</td>
<td>
`Tensor` with same `dtype` and shape broadcastable to `self.shape`.
</td>
</tr><tr>
<td>
`name`
</td>
<td>
A name to give this `Op`.
</td>
</tr>
</table>



<!-- Tabular view -->
 <table class="responsive fixed orange">
<colgroup><col width="214px"><col></colgroup>
<tr><th colspan="2">Returns</th></tr>
<tr class="alt">
<td colspan="2">
A `Tensor` with broadcast shape and same `dtype` as `self`.
</td>
</tr>

</table>



<h3 id="adjoint"><code>adjoint</code></h3>

<a target="_blank" href="https://github.com/tensorflow/tensorflow/blob/v2.4.1/tensorflow/python/ops/linalg/linear_operator.py#L933-L948">View source</a>

<pre class="devsite-click-to-copy prettyprint lang-py tfo-signature-link">
<code>adjoint(
    name=&#x27;adjoint&#x27;
)
</code></pre>

Returns the adjoint of the current `LinearOperator`.

Given `A` representing this `LinearOperator`, return `A*`.
Note that calling `self.adjoint()` and `self.H` are equivalent.

<!-- Tabular view -->
 <table class="responsive fixed orange">
<colgroup><col width="214px"><col></colgroup>
<tr><th colspan="2">Args</th></tr>

<tr>
<td>
`name`
</td>
<td>
A name for this `Op`.
</td>
</tr>
</table>



<!-- Tabular view -->
 <table class="responsive fixed orange">
<colgroup><col width="214px"><col></colgroup>
<tr><th colspan="2">Returns</th></tr>
<tr class="alt">
<td colspan="2">
`LinearOperator` which represents the adjoint of this `LinearOperator`.
</td>
</tr>

</table>



<h3 id="assert_non_singular"><code>assert_non_singular</code></h3>

<a target="_blank" href="https://github.com/tensorflow/tensorflow/blob/v2.4.1/tensorflow/python/ops/linalg/linear_operator.py#L541-L559">View source</a>

<pre class="devsite-click-to-copy prettyprint lang-py tfo-signature-link">
<code>assert_non_singular(
    name=&#x27;assert_non_singular&#x27;
)
</code></pre>

Returns an `Op` that asserts this operator is non singular.

This operator is considered non-singular if

ConditionNumber < max{100, range_dimension, domain_dimension} * eps, eps := np.finfo(self.dtype.as_numpy_dtype).eps ```

Args
name A string name to prepend to created ops.

Returns
An Assert Op, that, when run, will raise an InvalidArgumentError if the operator is singular.

assert_positive_definite

View source

Returns an Op that asserts this operator is positive definite.

Here, positive definite means that 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.

Args
name A name to give this Op.

Returns
An Assert Op, that, when run, will raise an InvalidArgumentError if the operator is not positive definite.

assert_self_adjoint

View source

Returns an Op that asserts this operator is self-adjoint.

Here we check that this operator is exactly equal to its hermitian transpose.

Args
name A string name to prepend to created ops.

Returns
An Assert Op, that, when run, will raise an InvalidArgumentError if the operator is not self-adjoint.

batch_shape_tensor

View source

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

cholesky

View source

Returns a Cholesky factor as a LinearOperator.

Given A representing this LinearOperator, if A is positive definite self-adjoint, return L, where A = L L^T, i.e. the cholesky decomposition.

Args
name A name for this Op.

Returns
LinearOperator which represents the lower triangular matrix in the Cholesky decomposition.

Raises
ValueError When the LinearOperator is not hinted to be positive definite and self adjoint.

cond

View source

Returns the condition number of this linear operator.

Args
name A name for this Op.

Returns
Shape [B1,...,Bb] Tensor of same dtype as self.

determinant

View source

Determinant for every batch member.

Args
name A name for this Op.

Returns
Tensor with shape self.batch_shape and same dtype as self.

Raises
NotImplementedError If self.is_square is False.

diag_part

View source

Efficiently get the [batch] diagonal part of this operator.

If this operator has shape [B1,...,Bb, M, N], this returns a Tensor diagonal, of shape [B1,...,Bb, min(M, N)], where diagonal[b1,...,bb, i] = self.to_dense()[b1,...,bb, i, i].

my_operator = LinearOperatorDiag([1., 2.])

# Efficiently get the diagonal
my_operator.diag_part()
==> [1., 2.]

# Equivalent, but inefficient method
tf.linalg.diag_part(my_operator.to_dense())
==> [1., 2.]

Args
name A name for this Op.

Returns
diag_part A Tensor of same dtype as self.

domain_dimension_tensor

View source

Dimension (in the sense of vector spaces) of the domain 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 N.

Args
name A name for this Op.