Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Parallel Kalman Filter & SSM Natural Parameters

This notebook demonstrates the parallel (associative-scan) Kalman filter and smoother, the Joseph-form covariance update, and the natural/expectation parameter representations of linear-Gaussian state-space models.

What you’ll learn:

  1. Running gaussx.parallel_kalman_filter and gaussx.parallel_rts_smoother
  2. Verifying equivalence with the sequential Kalman filter
  3. The Joseph-form covariance update for numerical stability
  4. Converting SSM parameters to natural parameters (BlockTriDiag precision)
  5. Converting smoother output to expectation parameters and back

Background: why parallelism matters

The standard Kalman filter is inherently sequential: each step depends on the previous filtered state. On modern accelerators (GPU/TPU) this sequential bottleneck limits throughput for long time series.

The associative-scan formulation (Sarkka & Garcia-Fernandez, 2021) reformulates the Kalman recursion as a parallel prefix sum over a semigroup of affine transformations. This enables O(log⁡T)O(\log T) parallel depth instead of O(T)O(T) sequential steps, while producing identical results up to floating-point precision.

In gaussx, parallel_kalman_filter and parallel_rts_smoother provide the same interface as their sequential counterparts but use dense array operations that are faster on GPU/TPU for long sequences.

Define the model

We reuse the damped oscillator from the sequential Kalman filter notebook. The 2D state xt=[position,velocity]⊤x_t = [\text{position}, \text{velocity}]^\top follows a discretized spring-mass-damper system, and only position is observed with noise.

  • AA: discretized spring-mass-damper transition
  • H=[10]H = \begin{bmatrix} 1 & 0 \end{bmatrix} (observe position only)
  • QQ: process noise driving the oscillator
  • R=[0.5]R = [0.5]: observation noise variance
A =
 [[ 1.     0.1  ]
 [-0.1    0.985]]
H = [[1. 0.]]
Q =
 [[0.0001 0.0015]
 [0.0015 0.03  ]]
R = [[0.5]]

Simulate data

Generate T=200T = 200 time steps from the model. The true trajectory is sampled from the generative process so the Kalman filter assumptions are satisfied.

true_states shape: (200, 2)
observations shape: (200, 1)

Run parallel Kalman filter and smoother

Parallel filtered means shape: (200, 2)
Parallel log-likelihood: -223.3188576581507
Parallel smoothed means shape: (200, 2)
Parallel smoothed covs shape: (200, 2, 2)

Compare with sequential Kalman filter

The parallel and sequential implementations should produce identical results (up to floating-point precision). We verify this by comparing filtered means, covariances, and the log-likelihood.

Max abs diff (filtered means): 1.05e-15
Max abs diff (filtered covs):  4.44e-16
Abs diff (log-likelihood):     0.00e+00
Max abs diff (smoothed means): 4.00e-15
Max abs diff (smoothed covs):  8.88e-16

Joseph-form covariance update

The standard Kalman update computes the posterior covariance as P=(I−KH)PpredP = (I - KH) P_{\text{pred}}, but this can lose symmetry or positive definiteness due to round-off. The Joseph form is more robust:

P=(I−KH)Ppred(I−KH)⊤+KRK⊤P = (I - KH) P_{\text{pred}} (I - KH)^\top + K R K^\top

We manually compute the Kalman gain at one time step and compare both formulas.

Time step 50:
Kalman gain K =
[[0.16284017]
 [0.13551443]]

Standard update P =
[[0.08142008 0.06775721]
 [0.06775721 0.21846408]]

Joseph update P =
[[0.08142008 0.06775721]
 [0.06775721 0.21846408]]

Max abs difference: 9.71e-17

Standard symmetry error: 1.94e-16
Joseph symmetry error:   0.00e+00

SSM natural parameters

A linear-Gaussian state-space model defines a joint Gaussian p(x0,…,xT−1)p(x_0, \ldots, x_{T-1}) whose precision matrix is block-tridiagonal. The function ssm_to_naturals extracts the natural parameters (θ1,θ2)(\theta_1, \theta_2) where θ2=−12Λ\theta_2 = -\tfrac{1}{2}\Lambda is stored as a BlockTriDiag operator.

The API expects Q to have shape (N, d, d) where Q[0] is the initial covariance P0P_0 and Q[1:] contains the process noise at each step.

A_full shape: (199, 2, 2)
Q_full shape: (200, 2, 2)
Q_full[0] (= P_0):
 [[4. 0.]
 [0. 4.]]
theta_linear shape: (400,)
theta_precision type: BlockTriDiag
theta_precision diagonal shape: (200, 2, 2)
theta_precision sub_diagonal shape: (199, 2, 2)

Inspect the BlockTriDiag structure

The BlockTriDiag operator stores (N, d, d) diagonal blocks and (N-1, d, d) sub-diagonal blocks. Its dense representation is a (Nd×Nd)(Nd \times Nd) matrix with the characteristic banded sparsity pattern of a Gauss-Markov chain.

Dense precision shape: (400, 400)
Round-trip A max error: 1.8197554574328478e-11
Round-trip Q max error: 8.177721610991284e-09
Round-trip mu_0 max error: 0.0
Round-trip P_0 max error: 8.177721610991284e-09

SSM expectation parameters

Given smoothed marginals (mt,Pt)(m_t, P_t) and cross-covariances Ct=Cov(xt+1,xt∣y1:T)C_t = \text{Cov}(x_{t+1}, x_t \mid y_{1:T}), we can compute the expectation parameters of the joint Gaussian:

  • η1=E[x]\eta_1 = E[x] (concatenated means)
  • η2\eta_2: a BlockTriDiag with diagonal blocks E[xtxt⊤]E[x_t x_t^\top] and sub-diagonal blocks E[xt+1xt⊤]E[x_{t+1} x_t^\top]

The cross-covariance is computed from the smoother gain: Ct=GtPt+1∣TC_t = G_t P_{t+1|T} where Gt=Pt∣tA⊤Pt+1∣t−1G_t = P_{t|t} A^\top P_{t+1|t}^{-1}.

Cross-covariances shape: (199, 2, 2)
eta1 shape: (400,)
eta2 type: BlockTriDiag
eta2 diagonal shape: (200, 2, 2)
eta2 sub_diagonal shape: (199, 2, 2)
Round-trip means max error: 0.0
Round-trip covs max error: 8.604228440844963e-16
Round-trip cross_covs max error: 8.604228440844963e-16

Visualizations

BlockTriDiag sparsity pattern

The precision matrix of a Gauss-Markov chain has a characteristic block-tridiagonal sparsity pattern. We visualize the first few blocks to see this structure clearly.

<Figure size 1400x500 with 3 Axes>

Filtered vs smoothed estimates

<Figure size 1200x700 with 2 Axes>

Summary

  • Parallel Kalman filter: gaussx.parallel_kalman_filter produces identical results to the sequential gaussx.kalman_filter but uses dense array operations suited for GPU/TPU acceleration.
  • Parallel RTS smoother: gaussx.parallel_rts_smoother likewise matches the sequential smoother.
  • Joseph-form update: gaussx.joseph_update computes the Kalman covariance update in a numerically stable form that preserves symmetry and positive-definiteness.
  • Natural parameters: gaussx.ssm_to_naturals extracts the block-tridiagonal precision (as a BlockTriDiag operator) and the linear natural parameter from SSM matrices. gaussx.naturals_to_ssm inverts this exactly.
  • Expectation parameters: gaussx.ssm_to_expectations converts smoother marginals (means, covariances, cross-covariances) to expectation parameters with BlockTriDiag second moments. gaussx.expectations_to_ssm inverts this exactly.
  • The BlockTriDiag operator exploits Gauss-Markov sparsity for O(Nd3)O(Nd^3) operations instead of O((Nd)3)O((Nd)^3) dense cost.

References

  • Sarkka, S. & Garcia-Fernandez, A. F. (2021). Temporal parallelization of Bayesian smoothers. IEEE Trans. Automatic Control, 66(1), 299--306.
  • Kalman, R. E. (1960). A new approach to linear filtering and prediction problems. J. Basic Engineering, 82(1), 35--45.
  • Rauch, H. E., Tung, F., & Striebel, C. T. (1965). Maximum likelihood estimates of linear dynamic systems. AIAA Journal, 3(8), 1445--1450.
  • Sarkka, S. (2013). Bayesian Filtering and Smoothing. Cambridge University Press.