Specifying an SMC model

We recall from the Introduction that the SMC algorithm is defined in terms of $M_1, \ldots, M_n$ and $G_1, \ldots, G_n$.

A model of type SMCModel can be created by calling

model = SMCModel(M!, lG, maxn::Int64, Particle, ParticleScratch)

where Particle and ParticleScratch are user-defined types, M! is a void function

M!(newParticle::Particle, rng::RNG, p::Int64, particle::Particle,

and lG is a function returning a Float64

lG(p::Int64, particle::Particle, scratch::ParticleScratch)

The RNG type is defined by the RNGPool package.

There is a correspondence between the function M! and $M_1, \ldots, M_n$: calling M!(x', rng, p, x, scratch), should make $x'$ a realization of a sample from $M_p(x, \cdot)$ with the convention that $M_1(x,\cdot) = M_1(\cdot)$ for any $x$. Similarly, lG and $G_1, \ldots, G_n$ correspond in that lG(p,x) $ = \log G_p(x)$. Logarithms are used to avoid numerical issues. maxn is the maximum value of n for which M! and lG are well-defined; users may choose to run the SMC algorithm for any integer value of n up to and including maxn.

The types Particle and ParticleScratch must have constructors that take no arguments. One may choose ParticleScratch = Nothing, in which case nothing will be passed to M! and lG. Using scratch space is optional but can significantly improve performance in certain scenarios; it provides a mechanism for users to avoid dynamic memory allocations in M! and/or lG. This scratch space will be used by every particle associated with a given thread. A thread-specific pseudo-random number generator (RNG) rng will be passed to the M! function by the algorithm, and should be used in lieu of Julia's global RNG.

Running the SMC algorithm

The SMC algorithm is run by calling

smc!(model::SMCModel, smcio::SMCIO)

The second argument, smcio, is a struct containing inputs and outputs for the smc! algorithm. It is straightforward to construct and involves specifying the number of particles N, the number of iterations n, the number of threads nthreads, whether the entire history of the particle system should be recorded fullOutput, and an effective sample size threshold essThreshold that is explained on the adaptive resampling page, and can be safely ignored on a first reading. smcio can be created by calling

smcio = SMCIO{model.particle, model.pScratch}(N::Int64, n::Int64,
  nthreads::Int64, fullOutput::Bool, essThreshold::Float64 = 2.0)

Currently N must be an integer multiple of nthreads; this may change in the future.

Extracting the main outputs

A vector of approximations $(\log\hat{Z}_1^N, \ldots, \log\hat{Z}_n^N)$ is stored in smcio.logZhats, which can be used in conjunction with SequentialMonteCarlo.eta to produce the approximations $\gamma_p^N(f)$ or $\hat{\gamma}_p^N(f)$.

One can extract the approximation $\eta_p^N(f)$ or $\hat{\eta}_p^N(f)$ by calling

SequentialMonteCarlo.eta(smcio, f, hat::Bool, p::Int64)

with hat determining which approximation is returned. Calling this function with p < smcio.n requires smcio.fullOutput = true.

One can extract the approximations $(\eta^N_p(f) \geq 0, \log |\gamma^N_p(f)|)$ or $(\hat{\eta}^N_p(f) \geq 0, \log |\hat{\gamma}^N_p(f)|)$ by calling

SequentialMonteCarlo.slgamma(smcio, f, hat::Bool, p::Int64)

with hat determining which approximation is returned. Calling this function with p < smcio.n requires smcio.fullOutput = true.

If smcio.fullOutput = true one can call SequentialMonteCarlo.allEtas or SequentialMonteCarlo.allGammas to obtain a vector of outputs of SequentialMonteCarlo.eta or SequentialMonteCarlo.slgamma, respectively.

Variance estimators

The following functions relate to the approximations detailed in the variance estimators page.

The function

SequentialMonteCarlo.V(smcio, f, hat::Bool, centred::Bool, p::Int64)


hatcentredapproximationapproximation of
falsefalse$V_p^N(f)$${\rm var} \left \{ \gamma_p^N(f)/\gamma_p(1) \right \}$
falsetrue$V_p^N(f-\eta_p^N(f))$$\mathbb{E}\left[\left\{ \eta_p^N(f)-\eta_p(f)\right\} ^2\right]$
truefalse$\hat{V}_p^N(f)$${\rm var}\left\{ \hat{\gamma}_p^N(f)/\hat{\gamma}_p(1)\right\}$
truetrue$\hat{V}_p^N(f-\hat{\eta}_p^N(f))$$\mathbb{E}\left[\left\{ \hat{\eta}_p^N(f)-\hat{\eta}_p(f)\right\} ^2\right]$

Calling SequentialMonteCarlo.V with p < smcio.n requires smcio.fullOutput = true.

A vector of the quantities $\hat{V}_1^N(1),\ldots,\hat{V}_n^N(1)$ is stored in smcio.Vhat1s. These are approximations of the relative variances of $\hat{Z}_1^N,\ldots,\hat{Z}_n^N$ = exp.(smcio.logZhats), i.e. the variances of $\hat{Z}_1^N/\hat{Z}_1,\ldots,\hat{Z}_n^N/\hat{Z}_n$.

When smcio.fullOutput = true, a vector of the approximations $v^N_{p,n}(f)$ or $\hat{v}^N_{p,n}(f)$ for $p \in \{1,\ldots,n\}$ can be obtained by calling

SequentialMonteCarlo.vpns(smcio, f, hat::Bool, centred::Bool, n::Int64)

One can choose n < smcio.n. If only the sum of one of these vectors is desired, i.e. $v_n^N(f)$ or $\hat{v}^N_n(f)$, this can be obtained be calling

SequentialMonteCarlo.v(smcio, f, hat::Bool, centred::Bool, n::Int64)

Adaptive resampling

The adaptive resampling mechanism is activated by choosing essThreshold <= 1.0. A vector of Bool values indicating whether or not resampling took place at each time can be accessed as smcio.resample, which has length smcio.n - 1 and is corresponds exactly to the random variables $R_1, \ldots, R_{n-1}$ defined in the SMC with adaptive resampling algorithm.

Accessing the particle system

If smcio.fullOutput == true, one can access:

smcio.allZetas[p]$\zeta_p^1, \ldots, \zeta_p^N$
smcio.allWs[p]$\propto G_p(\zeta_p^1), \ldots, G_p(\zeta_p^N)$
smcio.allEves[p]$E_p^1, \ldots, E_p^N$
smcio.allAs[p]$A_p^1, \ldots, A_p^N$

Note that smcio.allAs has length smcio.n-1 while the others in the table above have length smcio.n.

Even if smcio.fullOutput == false, one can access:

smcio.zetas$\zeta_n^1, \ldots, \zeta_n^N$$\propto G_n(\zeta_n^1),\ldots,G_n(\zeta_n^N)$
smcio.eves$E_n^1, \ldots, E_n^N$
smcio.esses$\mathcal{E}_{1}^N, \ldots, \mathcal{E}_{n}^N$

Conditional SMC

The cSMC algorithm can be called as follows:

csmc!(model::SMCModel, smcio::SMCIO, ref::Vector{Particle},

where ref is the input reference path and refout the output path. It is permitted for ref and refout to be the same vector.