Skip to contents

Some corehydro verbs call a function you write and hand it the seeded random number generator the run is using: the proposal function of a Gibbs sampler, the resample function of a bootstrap. rng_uniform() and rng_integers() are how that generator is drawn from.

Usage

rng_uniform(rng, n)

rng_integers(rng, n, min, max)

Arguments

rng

the handle your callback was given. It cannot be created any other way.

n

how many values to draw; a single positive whole number. A fractional n is an error, not a silent truncation, and the identical call in Python is refused the same way.

min, max

the bounds for rng_integers(). min is included and max is EXCLUDED, matching the ported Numerics Next(minInclusive, maxExclusive) a C# proposal is written against, so rng_integers(rng, 1, 0, 10) draws one of 0:9. Both must be whole numbers, and the range between them can be at most 2147483647 wide (the ported generator draws an integer span, and C# throws for a wider one).

Value

rng_uniform() a numeric vector of length n with values in [0, 1); rng_integers() an integer vector of length n.

Details

Use them for every random number your callback needs. Reaching for R's own generator (stats::runif(), base::sample()) instead is not an error and will not be caught, but it silently breaks two guarantees corehydro otherwise makes: the run stops being reproducible from its seed, and it stops agreeing with the identical run in Python. The handle draws from the same Mersenne Twister the core seeded, so both hold.

Lifetime

The handle borrows the generator for the duration of the one call it was given to. It is not an object to keep. Storing it and drawing from it after your callback has returned raises an error ("this random number generator handle is no longer valid"), which is deliberate: the generator it pointed at no longer exists, and reading it would crash the session rather than merely misbehave.

See also

mcmc_posterior(), whose proposal argument is the verb that hands you a handle, and stats::runif() for ordinary R random numbers, which is what to use anywhere OUTSIDE a corehydro callback.

Examples

# The Gibbs proposal is the surface that hands you a handle. This model's full conditional
# really is uniform: with x_i ~ Uniform(mu - 1, mu + 1) and a flat prior, mu given the data is
# Uniform(max(x) - 1, min(x) + 1), so one uniform draw IS the Gibbs step.
x <- c(4.9, 5.1, 5.0, 5.2, 4.8)
ll <- function(p) if (all(abs(x - p[1]) <= 1)) 0 else -Inf
proposal <- function(parameters, rng) {
  lo <- max(x) - 1
  hi <- min(x) + 1
  lo + rng_uniform(rng, 1) * (hi - lo)
}
fit <- mcmc_posterior(ll, distribution("Uniform", c(0, 10)),
                      sampler = "Gibbs", proposal = proposal,
                      iterations = 200, seed = 12345, initialize = "Randomize")
fit$posterior_mean
#> [1] 5.003371

# rng_integers() draws whole numbers on [min, max) off the same stream -- a resampling
# proposal, say, picking one of the observations by index.
pick_one <- function(parameters, rng) x[rng_integers(rng, 1, 1, length(x) + 1)]
mcmc_posterior(ll, distribution("Uniform", c(0, 10)),
               sampler = "Gibbs", proposal = pick_one,
               iterations = 200, seed = 12345, initialize = "Randomize")$posterior_mean
#> [1] 4.9992