# Design

This page explains the default implementations and design choices of AbstractMCMC. It is not intended for users but for developers that want to implement the AbstractMCMC interface for Markov chain Monte Carlo sampling. The user-facing API is explained in API.

## Overview

AbstractMCMC provides a default implementation of the user-facing interface described in API. You can completely neglect these and define your own implementation of the interface. However, as described below, in most use cases the default implementation allows you to obtain support of parallel sampling, progress logging, callbacks, iterators, and transducers for free by just defining the sampling step of your inference algorithm, drastically reducing the amount of code you have to write. In general, the docstrings of the functions described below might be helpful if you intend to make use of the default implementations.

## Basic structure

The simplified structure for regular sampling (the actual implementation contains some additional error checks and support for progress logging and callbacks) is

```
StatsBase.sample(
rng::Random.AbstractRNG,
model::AbstractMCMC.AbstractModel,
sampler::AbstractMCMC.AbstractSampler,
nsamples::Integer;
chain_type = ::Type{Any},
kwargs...
)
# Obtain the initial sample and state.
sample, state = AbstractMCMC.step(rng, model, sampler; kwargs...)
# Save the sample.
samples = AbstractMCMC.samples(sample, model, sampler, N; kwargs...)
samples = AbstractMCMC.save!!(samples, sample, 1, model, sampler, N; kwargs...)
# Step through the sampler.
for i in 2:N
# Obtain the next sample and state.
sample, state = AbstractMCMC.step(rng, model, sampler, state; kwargs...)
# Save the sample.
samples = AbstractMCMC.save!!(samples, sample, i, model, sampler, N; kwargs...)
end
return AbstractMCMC.bundle_samples(samples, model, sampler, state, chain_type; kwargs...)
end
```

All other default implementations make use of the same structure and in particular call the same methods.

## Sampling step

The only method for which no default implementation is provided (and hence which downstream packages *have* to implement) is `AbstractMCMC.step`

. It defines the sampling step of the inference method.

`AbstractMCMC.step`

— Function`step(rng, model, sampler[, state; kwargs...])`

Return a 2-tuple of the next sample and the next state of the MCMC `sampler`

for `model`

.

Samples describe the results of a single step of the `sampler`

. As an example, a sample might include a vector of parameters sampled from a prior distribution.

When sampling using `sample`

, every `step`

call after the first has access to the current `state`

of the sampler.

## Collecting samples

This section does not apply to the iterator and transducer interface.

After the initial sample is obtained, the default implementations for regular and parallel sampling (not for the iterator and the transducer since it is not needed there) create a container for all samples (the initial one and all subsequent samples) using `AbstractMCMC.samples`

.

`AbstractMCMC.samples`

— Function`samples(sample, model, sampler[, N; kwargs...])`

Generate a container for the samples of the MCMC `sampler`

for the `model`

, whose first sample is `sample`

.

The method can be called with and without a predefined number `N`

of samples.

In each step, the sample is saved in the container by `AbstractMCMC.save!!`

. The notation `!!`

follows the convention of the package BangBang.jl which is used in the default implementation of `AbstractMCMC.save!!`

. It indicates that the sample is pushed to the container but a "widening" fallback is used if the container type does not allow to save the sample. Therefore `AbstractMCMC.save!!`

*always has* to return the container.

`AbstractMCMC.save!!`

— Function`save!!(samples, sample, iteration, model, sampler[, N; kwargs...])`

Save the `sample`

of the MCMC `sampler`

at the current `iteration`

in the container of `samples`

.

The function can be called with and without a predefined number `N`

of samples. By default, AbstractMCMC uses `push!!`

from the Julia package BangBang to append to the container, and widen its type if needed.

For most use cases the default implementation of `AbstractMCMC.samples`

and `AbstractMCMC.save!!`

should work out of the box and hence need not to be overloaded in downstream code.

## Creating chains

This section does not apply to the iterator and transducer interface.

At the end of the sampling procedure for regular and paralle sampling we transform the collection of samples to the desired output type by calling `AbstractMCMC.bundle_samples`

.

`AbstractMCMC.bundle_samples`

— Function`bundle_samples(samples, model, sampler, state, chain_type[; kwargs...])`

Bundle all `samples`

that were sampled from the `model`

with the given `sampler`

in a chain.

The final `state`

of the `sampler`

can be included in the chain. The type of the chain can be specified with the `chain_type`

argument.

By default, this method returns `samples`

.

The default implementation should be fine in most use cases, but downstream packages could, e.g., save the final state of the sampler as well if they overload `AbstractMCMC.bundle_samples`

.