User guide#
The Sequential Monte Carlo (SMC) loop in sequince is built from a set of
composable steps. Each step inspects the current ParticleState,
optionally consumes observations and shared configuration, and returns an updated
state. At the end of each loop iteration, a set of callbacks are executed
that can perform operations like logging, diagnostics, and plotting.
The SequentialMonteCarlo class drives the loop by
sequentially executing the configured steps and callbacks at every iteration.
Configuring the runner#
The runner accepts a steps sequence containing callables that conform to the
SMCStep protocol defined in sequince.steps.base. Similarly, the runner
accepts a sequence of optional callbacks that adhere to the
SMCCallback protocol in sequince.callbacks.
The quickest way to build a useful pipeline is to reuse the pre-built helper:
from sequince import make_standard_bayesian_smc
from sequince.callbackss import TracePlot
smc, posterior, shared_context = make_standard_bayesian_smc(
log_prior,
log_likelihood,
mutation="emcee",
callbacks = [TracePlot()], # Optional
)
make_standard_bayesian_smc wires together
AdaptiveTemperedWeighting,
SystematicResampling, and a mutation step
chosen via the mutation argument. Pass mutation="minipcn" to opt into
the MiniPCNMutation transition kernel or
mutation="none" to skip rejuvenation.
BlackJAX mutation#
Install the optional BlackJAX integration with uv add "sequince[blackjax]".
BlackJAX mutation requires JAX-backed particles and JAX-compatible target
functions. NUTS is the default algorithm:
import jax.numpy as jnp
smc, posterior, metadata = make_standard_bayesian_smc(
log_prior,
log_likelihood,
mutation="blackjax",
mutation_n_steps=20,
mutation_kwargs={
"algorithm": "nuts",
"algorithm_kwargs": {
"step_size": 0.1,
"inverse_mass_matrix": jnp.ones(n_dimensions),
},
},
)
algorithm may also be "hmc", "random-walk", or a callable that
constructs a BlackJAX sampling algorithm from the current scalar log-density.
Acceptance and divergence diagnostics are returned in the mutation step output
under "acceptance" and "divergence". Per-iteration step outputs are
available through SMCResult.outputs.
If you need full control, construct SequentialMonteCarlo manually by
instantiating step and callback objects and supplying them in the desired order:
from sequince import SequentialMonteCarlo
from sequince.steps import (
AdaptiveTemperedWeighting,
SystematicResampling,
EmceeMutation,
)
from sequince.callbacks import TracePlot
smc = SequentialMonteCarlo(
steps=[
AdaptiveTemperedWeighting(posterior, target_ess_ratio=0.8),
SystematicResampling(always_resample=True),
EmceeMutation(posterior, n_steps=10),
],
callbacks=[TracePlot()], # Optional
)
Working with particle state#
ParticleState stores the particle locations,
log-weights, accumulated log-evidence, and auxiliary metadata. A few convenience
methods are helpful when implementing new steps:
ParticleState.normalize()Returns a fresh state with renormalised weights while keeping the original untouched.
ParticleState.resample(indices)Constructs a new state from ancestor indices, resetting the weights to a uniform distribution.
ParticleState.with_updates(**kwargs)Produces a copy with selected fields replaced.
When possible, treat the state as immutable and return a new instance instead of
mutating in place. This keeps the iteration trace recorded in
SMCResults consistent and easier to debug.
Incorporating observations#
The runner accepts an optional iterable of observations. Each iteration pulls
the next observation (if available) and exposes it through the
StepContext supplied to steps. This allows for
particle filtering style updates where likelihood evaluations depend on time
indexed data.
Custom steps and callbacks#
To implement bespoke step logic, derive from
SMCStep. Override the apply method to
perform work and return (state, context, output). StepContext.shared
contains read-only user data, while current cross-step coordination values live
in StepContext.metadata. Update metadata with
context.with_metadata(...) and return the replacement context. Historical
diagnostics belong in the explicit step output; the runner stores ordered
per-iteration output tuples on SMCResult.
Similarly, custom callbacks can be implemented by sub-classing
SMCCallback and overriding the apply method
Callbacks are provided with the current state, context, and result history. An
observational callback returns None; a callback that updates metadata or
stop controls returns a replacement context.
See sequince.steps and sequince.callbacks for a catalogue of the built-in components.