18.4 Functions acting as random number generators
A user-specified function can be declared to act as a (pseudo) random
number generator (PRNG) by giving it a name that ends in _rng
.
Giving a function a name that ends in _rng
allows it to access
built-in functions and user-defined functions that end in
_rng
, which includes all the built-in PRNG functions. Only
functions ending in _rng
are able access the built-in PRNG
functions. The use of functions ending in _rng
must therefore
be restricted to transformed data and generated quantities blocks like
other PRNG functions; they may also be used in the bodies of other
user-defined functions ending in _rng
.
For example, the following function generates an \(N \times K\) data matrix, the first column of which is filled with 1 values for the intercept and the remaining entries of which have values drawn from a standard normal PRNG.
matrix predictors_rng(int N, int K) {
matrix[N, K] x;
for (n in 1:N) {
x[n, 1] = 1.0; // intercept
for (k in 2:K)
x[n, k] = normal_rng(0, 1);
}
return x;
}
The following function defines a simulator for regression outcomes
based on a data matrix x
, coefficients beta
, and noise
scale sigma
.
vector regression_rng(vector beta, matrix x, real sigma) {
vector[rows(x)] y;
vector[rows(x)] mu;
mu = x * beta;
for (n in 1:rows(x))
y[n] = normal_rng(mu[n], sigma);
return y;
}
These might be used in a generated quantity block to simulate some fake data from a fitted regression model as follows.
parameters {
vector[K] beta;
real<lower=0> sigma;
...
generated quantities {
matrix[N_sim, K] x_sim;
vector[N_sim] y_sim;
x_sim = predictors_rng(N_sim, K);
y_sim = regression_rng(beta, x_sim, sigma);
}
A more sophisticated simulation might fit a multivariate normal to the
predictors x
and use the resulting parameters to generate
multivariate normal draws for x_sim
.