Skip to contents

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 or rowwise_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 or rowwise_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". See vctrs::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 length n_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 given rep(0.5, n_dim);

  • Return a finite double matrix of parameters with the same dimensions, all within the bounds lower and upper (if provided), when given a random matrix of size c(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"