Skip to main content

Sequential Monte Carlo for Apple silicon, built on MLX

Project description

smcx

CI PyPI License

Sequential Monte Carlo in JAX: particle filters, adaptive tempered SMC, and SMC² with a small, flat API. Runs on CPU, CUDA, and TPU through stock JAX, and on Apple-silicon GPUs through the optional jax-mps backend.

smcx succeeds smcjax; all of its functionality was ported forward and extended.

Install

pip install smcx            # CPU / CUDA / TPU via your jax install
pip install "smcx[metal]"   # + jax-mps for Apple-silicon GPUs

What's in the box

  • Filters: bootstrap_filter, guided_filter (general g·f/q proposal weights), auxiliary_filter (twisted potentials), and liu_west_filter (joint state–parameter, labeled approximate).
  • Static targets: temper — adaptive tempered SMC with an ESS-bisection schedule and covariance-adapted random-walk moves.
  • Parameter inference: smc2 — nested SMC² with vmapped inner filters and PMMH rejuvenation.
  • Resampling: systematic, stratified, multinomial, and residual — one contract, log-domain weights throughout, float32-safe query grids.
  • Diagnostics: ESS traces, quantile tail-ESS, Pareto-k reliability, CRPS, cumulative log score, Bayes factors, posterior-predictive sampling, and a one-call diagnose summary.
  • store_history=False on every filter drops memory from O(T·N) to O(N) with a bit-identical evidence estimate.

Every sampler is validated against exact references — Kalman oracles for the filters, conjugate evidence for tempering, grid-integrated posteriors for SMC² — with Monte-Carlo-calibrated gates, not loose tolerances.

Quick start

import jax.numpy as jnp
import jax.random as jr

import smcx

# A 1-D linear-Gaussian state-space model.
A, Q, R = 0.9, 0.5, 0.3


def init(key, n):
    return jr.normal(key, (n, 1))


def transition(key, z):
    return A * z + jnp.sqrt(Q) * jr.normal(key, z.shape)


def log_observation(y, z):
    return -0.5 * (jnp.log(2 * jnp.pi * R) + (y[0] - z[0]) ** 2 / R)


post = smcx.bootstrap_filter(
    jr.key(0),
    init,
    transition,
    log_observation,
    emissions,
    num_particles=10_000,
)
post.marginal_loglik  # unbiased evidence estimate (log-domain)
smcx.diagnose(post)  # ESS / diversity / Pareto-k health summary

Callbacks are per-particle; smcx vmaps them internally. Everything takes an explicit PRNG key, and posteriors are NamedTuples — ordinary JAX pytrees.

Apple silicon

The [metal] extra runs the same code on M-series GPUs via jax-mps. Filter correctness on Metal is gate-verified in this repository's test suite (SMCX_TEST_PLATFORM=mps runs it on the GPU), and several of the performance fixes that make the backend fast for SMC-shaped workloads were contributed upstream from this project (jax-mps #215, #216, #220). Metal is float32-only; the suite runs float64 on CPU and float32 on Metal automatically.

Development

Requires Python 3.11+ and uv.

git clone https://github.com/michaelellis003/smcx.git
cd smcx
uv sync
uv run pre-commit install
uv run pre-commit install --hook-type commit-msg
uv run pre-commit install --hook-type pre-push

A Makefile covers common tasks:

make test        # lint + pytest
make lint        # ruff check, format check, license headers, ty
make format      # add license headers, ruff format, ruff fix
make docs        # build docs

Releases are automated: python-semantic-release reads conventional commits on merge to main, bumps the version, tags, and publishes.

Design notes

Decision records live in docs/adr/ and dated evidence in docs/research/ — including the benchmark study that shaped the architecture: a native-MLX implementation of this library was built, measured against jax-mps on equal terms, and retired when the measurements showed the compatibility path could be made equally fast with fixes contributed upstream (docs/research/2026-07-16-jax-mps-internals.md). The MLX implementation remains in git history at the mlx-final tag.

Acknowledgments

smcx's design draws on the SMC ecosystem: smcjax (the predecessor library), particles and Chopin & Papaspiliopoulos's An Introduction to Sequential Monte Carlo (the Feynman-Kac architecture), BlackJAX (the resampling contract), Dynamax (container conventions), TensorFlow Probability (criterion/trace hooks), and design lessons from PyMC, FilterPy, pfilter, pyfilter, Stone Soup, pomp, nimbleSMC, and ArviZ. See CITATION.cff for formal references and docs/research/licensing.md for the full provenance record.

License

Apache-2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

smcx-1.0.0.tar.gz (32.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

smcx-1.0.0-py3-none-any.whl (41.3 kB view details)

Uploaded Python 3

File details

Details for the file smcx-1.0.0.tar.gz.

File metadata

  • Download URL: smcx-1.0.0.tar.gz
  • Upload date:
  • Size: 32.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for smcx-1.0.0.tar.gz
Algorithm Hash digest
SHA256 e6ae4305ed5983ec21b47daed97f61b9846ef3bba16dab1f92de474383582b7a
MD5 b0ed5362b3b6743469f114bac8fea226
BLAKE2b-256 d2fe38d6a410dadb28d99917236fd23a183c5f01d8ce901a4fb1439bf6bd7a2b

See more details on using hashes here.

Provenance

The following attestation bundles were made for smcx-1.0.0.tar.gz:

Publisher: release.yml on michaelellis003/smcx

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file smcx-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: smcx-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 41.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for smcx-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 508ea132ef3ba7f007788dea7af2e88f4baad91ea09d82cb0925a16a3b885650
MD5 35b4864628f5698d7b21a56a80bb5d3d
BLAKE2b-256 89e91d6fa1c354a3b27ae64114abf4b3611ef5dbd5561e0c97496ef0150c911d

See more details on using hashes here.

Provenance

The following attestation bundles were made for smcx-1.0.0-py3-none-any.whl:

Publisher: release.yml on michaelellis003/smcx

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page