markovflow.block_tri_diag

Module representing block tridiagonal matrices.

Module Contents

class BlockTriDiagonal(diagonal: tf.Tensor, symmetric: bool, sub_diagonal: Optional[tf.Tensor] = None)[source]

Bases: abc.ABC

Abstract class representing a block tridiagonal matrix.

All precisions in Markovflow are of this form, so this class provides an adapter between the TensorFlow banded_matrices and the MarkovFlow code.

Parameters
  • diagonal – A tensor with shape [... outer_dim, inner_dim, inner_dim].

  • symmetric – Whether the block tridiagonal matrix will be symmetric.

  • sub_diagonal – A tensor with shape [... outer_dim - 1, inner_dim, inner_dim].

property as_bandbanded_matrices.banded.BandedMatrixTensor[source]

Return a TensorFlow tensor (or NumPy array) representing a banded matrix.

The (dense) tensor should be of dimension \(K×N\), where \(K\) is the bandwidth of the represented \(N×N\) matrix.

property bandwidthint[source]

Return the (lower) bandwidth of the tensor.

property batch_shapetf.TensorShape[source]

Return the batch shape of this object.

property inner_dimint[source]

Return the inner dimension of the block tridiagonal matrix. That is, the dimensions of the block.

property outer_dimtf.Tensor[source]

Return the outer dimension of the block tridiagonal matrix. That is, the number of blocks.

property block_diagonaltf.Tensor[source]

Return the block diagonal.

Returns

Diagonal with shape [... outer_dim, inner_dim, inner_dim].

property block_sub_diagonalOptional[tf.Tensor][source]

Return the block sub-diagonal, if it exists.

Returns

Sub-diagonal with shape [... outer_dim, inner_dim, inner_dim] or None.

to_dense()tf.Tensor[source]

Convert this object to a dense tensor.

This is useful mainly for debugging and testing purposes.

Returns

A tensor with shape [... outer_dim * inner_dim, outer_dim * inner_dim]

dense_mult(right: tf.Tensor, transpose_left: bool = False)tf.Tensor[source]

Multiply a dense vector by this object.

If this object is \(L\) and right is \(x\), calculate \(Lx\) as a dense tensor.

Parameters
  • right – A tensor with shape [... outer_dim, inner_dim].

  • transpose_left – Whether to transpose \(L\) before multiplying.

Returns

A tensor with shape [... outer_dim, inner_dim].

abstract __add__(other)[source]

Add two BlockTriDiagonal tensors together.

_convert_to_band()banded_matrices.banded.BandedMatrixTensor[source]
Returns

A BandedMatrixTensor representation of this matrix

_flatten_right(right: tf.Tensor)tf.Tensor[source]

Reshape the rhs for banded_ops compatibility. See also self._assert_compatible_right_shape.

Parameters

right – the tensor whose shape we want to alter.

_unflatten_right(flat_right: tf.Tensor)tf.Tensor[source]

Reshape the rhs for banded_ops compatibility. See also self._assert_compatible_right_shape.

Parameters

flat_right – the tensor whose shape we want to alter.

_assert_compatible_right_shape(right: tf.Tensor)None[source]

Make sure the Tensor ‘right’ is a suitable right-hand-side tensor for multiplication and solving. The inner and outer dims should match, and the broadcast_dim should be compatible.

Parameters

right – the tensor whose shape we want to check.

class LowerTriangularBlockTriDiagonal(diagonal: tf.Tensor, sub_diagonal: Optional[tf.Tensor] = None)[source]

Bases: BlockTriDiagonal

Represents a lower triangular block tridiagonal matrix:

[D₁              ]
[A₁ D₂           ]
[    A₂ D₃       ]
[        ᨞  ᨞    ]
[         Aₙ₋₁ Dₙ]

This is typically the Cholesky of a SymmetricBlockTriDiagonal.

Each matrix \(Dᵢ\) is lower triangular and square with dimension inner_dim. \(Aᵢ\) is square with dimension inner_dim.

The outer_dim is \(n\); that is, the number of block matrices on the main diagonal.

\(Dᵢ\) are the diagonal matrices and \(Aᵢ\) are the sub-diagonal matrices.

Parameters
  • diagonal – A tensor with shape [... outer_dim, inner_dim, inner_dim].

  • sub_diagonal – A tensor with shape [... outer_dim - 1, inner_dim, inner_dim].

block_diagonal_of_inverse()tf.Tensor[source]

If this object is \(L\) and \(M = LLᵀ\), return the block diagonal elements of \(M⁻¹\).

\(M⁻¹\) will not, in general, be a banded matrix, and we are normally interested only in the diagonal elements.

Returns

A tensor with shape [... outer_dim, inner_dim, inner_dim].

solve(right: tf.Tensor, transpose_left: bool = False)tf.Tensor[source]

If this object is \(L\) and right is \(x\), calculate \(L⁻¹ x\) as a dense tensor.

Parameters
  • right – A tensor with shape [... outer_dim, inner_dim].

  • transpose_left – Whether to transpose \(L\) before solving.

Returns

A tensor with shape [... outer_dim, inner_dim].

abs_log_det()tf.Tensor[source]

Return the absolute log determinant of this matrix. This is just the log of the product of diagonal elements (since it is lower triangular).

For numerical stability and nicer gradients, we do:

\[log |L| = Σₙ log |Lₙₙ| = Σₙ ½ log |Lₙₙ|²\]
Returns

A tensor with shape batch_shape, representing the log determinant.

__add__(other: LowerTriangularBlockTriDiagonal)LowerTriangularBlockTriDiagonal[source]

Add two LowerTriangularBlockTriDiagonal tensors together.

class SymmetricBlockTriDiagonal(diagonal: tf.Tensor, sub_diagonal: Optional[tf.Tensor] = None)[source]

Bases: BlockTriDiagonal

Represents a symmetric block tridiagonal matrix:

[D₁ A₁ᵀ              ]
[A₁ D₂  A₂ᵀ          ]
[    A₂ D₃ A₂ᵀ       ]
[        ᨞  ᨞   Aₙ₋₁ᵀ]
[         Aₙ₋₁  Dₙ   ]

This is the form of the precision matrix for a StateSpaceModel.

Each matrix \(Dᵢ\) is symmetric square with dimension inner_dim. \(Aᵢ\) is square with dimension inner_dim.

The outer_dim is \(n\); that is, the number of block matrices on the main diagonal.

\(Dᵢ\) are the diagonal matrices and \(Aᵢ\) are the sub-diagonal matrices.

Parameters
  • diagonal – A tensor with shape [... outer_dim, inner_dim, inner_dim].

  • sub_diagonal – A tensor with shape [... outer_dim - 1, inner_dim, inner_dim].

__add__(other: SymmetricBlockTriDiagonal)SymmetricBlockTriDiagonal[source]

Add two SymmetricBlockTriDiagonal tensors together.

property choleskyLowerTriangularBlockTriDiagonal[source]

Calculates the Cholesky factorisation of this matrix.

Cholesky factorisations require a symmetric matrix. The cholesky_band matrix only operates on the lower triangle, so no copy is needed.

Cholesky factorisations preserve band structure, so the result is a LowerTriangularBlockTriDiagonal with the same shape.

Returns

A matrix of the same shape, representing the Cholesky.

upper_diagonal_lower()Tuple[LowerTriangularBlockTriDiagonal, LowerTriangularBlockTriDiagonal][source]

For this matrix, calculate the \(UDUᵀ\) factorisation. This is where:

Uᵀ =  [ I             ]       D = [ D₀          ]
      [U₁ᵀ, I         ]           [    D₁       ]
      [    U₂ᵀ, I     ]           [       ᨞     ]
      [         ᨞  ᨞ ]            [         ᨞  ]
      [         Uₙᵀ, I]           [           Dₙ]

\(D₀, D₁... Dₙ\) are symmetric.

This is related to the Cholesky \(LLᵀ\) and \(LDLᵀ\) decompositions, but is more natural when dealing with the inverses of matrices. That is, if \(K⁻¹ = UDUᵀ\) then \(K = LD⁻¹Lᵀ\) where \(L=U⁻ᵀ\).

This can be used to find the StateSpaceModel that represents this SymmetricBlockTriDiagonal, since:

\[K⁻¹ = A⁻ᵀ Q⁻¹ A⁻¹\]

Hence we can identify the state transition matrices \(Aᵢ = -Uᵢᵀ\) and the initial and process noise covariance matrices \(D₀= P₀⁻¹, Dᵢ= Qᵢ⁻¹\) with the above form:

\[\begin{split}K = &| D₀ + U₁ D₁ U₁ᵀ &| U₁ D₁ &| 0...\\ &| D₁ U₁ᵀ &| D₁ + U₂ D₂ U₂ᵀ &| U₂ D₂ &| 0...\\ &| 0 &| D₂ U₂ᵀ &| D₂ + D₃ U₃ D₃ᵀ &| U₃ D₃ &| 0...\\ ...\end{split}\]

We can write the following recurrence relation:

\[\begin{split}&Dₙ = Kₙₙ\\ &Dₖ = Kₖₖ - Kₖₖ₊₁ᵀ Dₖ₊₁⁻¹Kₖₖ₊₁\\ &Uₖᵀ = Dₖ⁻¹ Kₖₖ₋₁\end{split}\]

…where \(Kⱼₖ\) is the block matrix at location j, k of this matrix. This method allows us to return the posterior from a KalmanFilter as a StateSpaceModel.

Returns

A tuple of \(Uᵀ\) and chol_D.

_banded_to_block_tri(banded: banded_matrices.banded.BandedMatrixTensor, block_size: int)LowerTriangularBlockTriDiagonal[source]

Convert a banded matrix to a LowerTriangularBlockTriDiagonal.

NOTE This is designed for internal use with this module as it doesn’t check the shapes, so may not work for `BandedMatrixTensor`s that aren’t LowerTriangularBlockTriDiagonal.