20.4 Vectors with Varying Bounds
Stan only allows a single lower and upper bound to be declared in the constraints for a container data type. But suppose we have a vector of parameters and a vector of lower bounds? Then the transforms are calculated and their log Jacobians added to the log density accumulator; the Jacobian calculations are described in detail in the reference manual chapter on constrained parameter transforms.
Varying Lower Bounds
For example, suppose there is a vector parameter \(\alpha\) with a vector \(L\) of lower bounds. The simplest way to deal with this if \(L\) is a constant is to shift a lower-bounded parameter.
data {
int N;
vector[N] L; // lower bounds
...
parameters {
vector<lower=0>[N] alpha_raw;
...
transformed parameters {
vector[N] alpha = L + alpha_raw;
...
The Jacobian for adding a constant is one, so its log drops out of the log density.
Even if the lower bound is a parameter rather than data, there is no Jacobian required, because the transform from \((L, \alpha_{\mathrm raw})\) to \((L + \alpha_{\mathrm raw}, \alpha_{\mathrm raw}\) produces a Jacobian derivative matrix with a unit determinant.
It’s also possible implement the transform by directly transforming an unconstrained parameter and accounting for the Jacobian.
data {
int N;
vector[N] L; // lower bounds
...
parameters {
vector[N] alpha_raw;
...
transformed parameters {
vector[N] alpha = L + exp(alpha_raw);
...
model {
target += sum(alpha_raw); // log Jacobian
...
The adjustment in the the log Jacobian determinant of the transform mapping \(\alpha_{\mathrm{raw}}\) to \(\alpha = L + \exp(\alpha_{\mathrm{raw}})\). The details are simple in this case because the Jacobian is diagonal; see the reference manual chapter on constrained parameter transforms for full details. Here \(L\) can even be a vector containing parameters that don’t depend on \(\alpha_{\mathrm{raw}}\); if the bounds do depend on \(\alpha_{\mathrm{raw}}\) then a revised Jacobian needs to be calculated taking into account the dependencies.
Varying Upper and Lower Bounds
Suppose there are lower and upper bounds that vary by parameter. These can be applied to shift and rescale a parameter constrained to \((0, 1)\).
data {
int N;
vector[N] L; // lower bounds
vector[N] U; // upper bounds
...
parameters {
vector<lower=0, upper=1>[N] alpha_raw;
...
transformed parameters {
vector[N] alpha = L + (U - L) .* alpha_raw;
The expression U - L
is multiplied by alpha_raw
elementwise to produce a vector of variables in \((0, U-L)\), then
adding \(L\) results in a variable ranging between \((L, U)\).
In this case, it is important that \(L\) and \(U\) are constants, otherwise a Jacobian would be required when multiplying by \(U - L\).