Interface
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,
scratch::ParticleScratch)
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)
returns:
hat | centred | approximation | approximation of |
---|---|---|---|
false | false | $V_p^N(f)$ | ${\rm var} \left \{ \gamma_p^N(f)/\gamma_p(1) \right \}$ |
false | true | $V_p^N(f-\eta_p^N(f))$ | $\mathbb{E}\left[\left\{ \eta_p^N(f)-\eta_p(f)\right\} ^2\right]$ |
true | false | $\hat{V}_p^N(f)$ | ${\rm var}\left\{ \hat{\gamma}_p^N(f)/\hat{\gamma}_p(1)\right\}$ |
true | true | $\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:
name | value |
---|---|
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:
name | value |
---|---|
smcio.zetas | $\zeta_n^1, \ldots, \zeta_n^N$ |
smcio.ws | $\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},
refout::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.