Use an R function to specify the prior distribution of parameters for a nested sampling run.
Usage
create_prior(
fn,
rowwise_fn,
...,
.n_dim = NULL,
.varnames = NULL,
.name_repair = c("unique", "universal", "check_unique"),
.lower = -Inf,
.upper = Inf
)
Arguments
- fn, rowwise_fn
Choose one of
fn
orrowwise_fn
:fn
: A function. Takes a vector of unit cube coordinates and returns a vector of parameters of the same length.rowwise_fn
: A function. Takes a matrix of unit cube coordinates and returns a matrix of parameters with identical dimensions.
- ...
Named arguments to
fn
orrowwise_fn
that should be partially applied.- .n_dim
An optional positive integer. The number of dimensions of the prior distribution. If left
NULL
, this is inferred from the common length of the vector-valued parameters (see Note).- .varnames
An optional character vector. Names for the variables in the prior distribution.
- .name_repair
An optional, case-sensitive string. How to repair
varnames
. Options are"unique"
(default),"universal"
, or"check_unique"
. Seevctrs::vec_as_names()
for details.- .lower, .upper
Numeric vectors. Expected bounds for the parameter vectors after hypercube transformation.
Value
A named list with class ernest_prior
, containing:
fn
: The prior transformation function.n_dim
: Number of dimensions in the prior space.lower
,upper
: Bounds for the prior distribution, recycled to lengthn_dim
.
Additionally, the object has a varnames
attribute.
Details
The unit hypercube transformation encodes points in the parameter space as independent and identically distributed points within a unit hypercube. Nested sampling implementations, including ernest, use this transformation to simplify likelihood-restricted prior sampling and avoid unnecessary rejection steps.
create_prior
allows you to specify your own prior distribution by providing
a transformation function. For factorisable priors, this function can simply
transform each value in (0, 1) using the inverse cumulative distribution
function (CDF) for each parameter. For more complex cases, you can specify
hierarchical or conditionally dependent priors (see Examples).
create_prior
performs regularity checks on your prior function to catch
basic errors that may affect nested sampling. To pass these checks, fn
or
rowwise_fn
must:
Return a finite double vector of length
n_dim
when givenrep(0.5, n_dim)
;Return a finite double matrix of parameters with the same dimensions, all within the bounds
lower
andupper
(if provided), when given a random matrix of sizec(5, n_dim)
.
Ernest will wrap fn
so it can accept a matrix of parameters. If you have a
more efficient implementation that handles vectors and matrices, consider
providing rowwise_fn
instead.
Note
The vector-valued parameters in this function are recycled to length
n_dim
if it is an integer, or to a common length if n_dim = NULL
. See
vctrs::vector_recycling_rules for additional information on
recycling.
Examples
# 3D uniform prior in the range [-10, 10]
unif <- function(x) {
-10 + x * 20
}
prior <- create_prior(unif, .n_dim = 3, .lower = -10, .upper = 10)
#> New names:
#> • `` -> `...1`
#> • `` -> `...2`
#> • `` -> `...3`
prior$fn(c(0.25, 0.5, 0.75))
#> [1] -5 0 5
mat <- matrix(c(0.25, 0.5, 0.75, 0.1, 0.2, 0.3), ncol = 3, byrow = TRUE)
prior$fn(mat)
#> [,1] [,2] [,3]
#> [1,] -5 0 5
#> [2,] -8 -6 -4
# A normal prior with parameterised mean and standard deviation
hier_f <- function(theta) {
mu <- qnorm(theta[1], mean = 5) # mu ~ N(5, 1)
sigma <- 10 ^ qunif(theta[2], min = -1, max = 1) # log10(sigma) ~ U[-1, 1]
x <- qnorm(theta[3], mu, sigma) # X ~ N(mu, sigma)
c(mu, sigma, x)
}
create_prior(
hier_f,
.varnames = c("mu", "sigma", "x"),
.lower = c(-Inf, 0, -Inf)
)
#> Prior distribution <ernest_prior>
#>
#> Names: "mu", "sigma", and "x"
#> Bounds:
#> → Lower: -Inf, 0, and -Inf
#> → Upper: Inf, Inf, and Inf
# Using `rowwise_fn` should be done with care
bb_p <- function(x) {
beta <- stats::qbeta(x[1], 5, 5)
bern <- stats::qbinom(x[2], size = 1, beta)
c(beta, bern)
}
try(
create_prior(
rowwise_fn = bb_p,
.varnames = c("beta", "bern")
)
)
#> Error in create_prior(rowwise_fn = bb_p, .varnames = c("beta", "bern")) :
#> Can't validate `rowwise_fn` as a valid prior.
#> Caused by error in `prior$fn()`:
#> ! `prior(unit)` must return a matrix of equal dim. to `unit`.
#> ✖ Expected dim(y) = 10 x 2.
#> ✖ Returned dim(y) = .
create_prior(bb_p, .varnames = c("beta", "bern"))
#> Prior distribution <ernest_prior>
#>
#> Names: "beta" and "bern"