What's in a FlexiChain?
A FlexiChain{T}, at its core, is a wrapper around a dictionary which maps keys to matrices of size (niters x nchains).
Let's start by loading an example FlexiChain.
using FlexiChainschain = FlexiChains.EXAMPLE_CHAIN╭─FlexiChain (10 iterations, 2 chains) ────────────────────────────────────────╮
│ ↓ iter = 101:110 │
│ → chain = 1:2 │
│ │
│ Parameters (3) ── VarName │
│ Float64 mu, tau │
│ Vector{Float64} theta (8,) │
│ │
│ Extras (2) │
│ Float64 logjoint │
│ Bool is_divergent │
╰──────────────────────────────────────────────────────────────────────────────╯Keys: parameters and extras
Each key in a FlexiChain{T} can be either:
- a
Parameter{<:T}, or - an
Extra.
Each Parameter or Extra itself carries a name, which can be retrieved with FlexiChains.get_name.
using FlexiChains: get_name, Parametername = FlexiChains.get_name(FlexiChains.Parameter(@vn(mu)))name, typeof(name)(mu, VarName{:mu, VarNames.Iden})For a Parameter{T}, the name must be a T. For an Extra, the name must always be a Symbol, regardless of the parameter key type.
You can list all keys, all parameters, or all extras:
keys(chain)KeySet for a OrderedCollections.OrderedDict{Union{FlexiChains.Extra, FlexiChains.Parameter{var"#s91"}} where var"#s91"<:VarName, Matrix} with 5 entries. Keys:
Parameter(mu)
Parameter(tau)
Parameter(theta)
Extra(:logjoint)
Extra(:is_divergent)FlexiChains.parameters(chain)3-element Vector{VarName}:
mu
tau
thetaFlexiChains.extras(chain)2-element Vector{FlexiChains.Extra}:
Extra(:logjoint)
Extra(:is_divergent)Values: matrices
Because each key maps to a different matrix, FlexiChains can store values of different types and sizes.
For example, mu is stored as Float64, and theta as a Vector{Float64}. Indexing into a chain returns an niters x nchains matrix of these samples:
chain[@vn(mu)]┌ 10×2 DimArray{Float64, 2} Parameter(mu) ┐
├─────────────────────────────────────────┴─────────────── dims ┐
↓ iter Sampled{Int64} 101:110 ForwardOrdered Regular Points,
→ chain Sampled{Int64} 1:2 ForwardOrdered Regular Points
└───────────────────────────────────────────────────────────────┘
↓ → 1 2
101 11.3517 4.78008
102 11.3517 4.59214
103 11.3517 5.68752
104 11.3517 7.10065
⋮
107 1.30113 5.48149
108 0.915619 6.2456
109 0.284842 6.25491
110 0.516548 1.47832chain[:is_divergent]┌ 10×2 DimArray{Bool, 2} Extra(:is_divergent) ┐
├─────────────────────────────────────────────┴─────────── dims ┐
↓ iter Sampled{Int64} 101:110 ForwardOrdered Regular Points,
→ chain Sampled{Int64} 1:2 ForwardOrdered Regular Points
└───────────────────────────────────────────────────────────────┘
↓ → 1 2
101 0 0
102 0 0
103 0 0
104 1 0
⋮
107 1 0
108 0 0
109 0 0
110 0 0In this introductory page we don't go into the details of indexing; there's one full page on that.
To obtain the number of iterations or chains, you can use FlexiChains.niters and FlexiChains.nchains:
FlexiChains.niters(chain), FlexiChains.nchains(chain)(10, 2)Alternatively, size(chain) returns (niters, nchains):
size(chain)(10, 2)Notice that there is no measure of the number of parameters. Unlike other chains packages, such as MCMCChains.jl, FlexiChains does not have a third 'parameter axis'. If you want to get such a number, you can use length(keys(chain)) or length(FlexiChains.parameters(chain)).