Put constraints on parameters and transformed parameters

I have a mutilate data in my Stan model, which is either 1 or 0. Depending on its value I want to either include or exclude a parameter/transformed parameter in my model. Here is a simple example. For simplicity, I reduced the dimensions to 1,

    data {
       int D;  //number of data points
       matrix[D, 1] u;
       matrix[D, 1] x;
       int <lower=0, upper=1> mutilate;
    }
    parameters {
       matrix[1, 1] mu; 
       matrix[1, 1] alpha;
    }
    transformed parameters {
       matrix[D, 1] x_loc;
       vector[1] x_scale;
       matrix[N, N] sigma_xx;
       sigma_xx = alpha'*alpha + diag_matrix(rep_vector(1, N));
       x_scale = sqrt(diagonal(sigma_xx));
       for (i in 1:D){
           x_loc[i, ] = u[i, ] * alpha;
       }
    }
    model {
        target += normal_lpdf(mu[1,] | 0, 10);
        if (mutilate) 
                // do not modify
            else
                target += normal_lpdf(alpha[j, ] | 0, 1); 
        for (i in 1:D){
             target += normal_lpdf(u[i, ] | mu[1,], 1);      // likelihood
             if (mutilate) 
                // do not modify target with an x likelihood, x is a constant.
             else
                target += normal_lpdf(x[i, ] | x_loc[i, ], x_scale);
        }
    }

I want to put a condition on parameter alpha and x, if mutilated is 1 I want to include alpha, x, x_loc, x_scale, and sigma_xx in my model, and if mutilated is 0, I want to exclude them. How can I do that? I already put a condition on x inside the model block, but I don’t know how I can do that inside the parameters and transformed parameters block.

You can’t put conditional block inside parameters but you can make size zero-or-one arrays.
For eample

parameters {
   matrix[1, 1] mu; 
   matrix[1, 1] alpha[mutilate];
}
transformed parameters {
   matrix[D, 1] x_loc[mutilate];
   vector[1] x_scale[mutilate];
   matrix[N, N] sigma_xx[mutilate];
   if (mutilate) {
       sigma_xx[1] = alpha[1]'*alpha[1] + diag_matrix(rep_vector(1, N));
       x_scale[1] = sqrt(diagonal(sigma_xx[1]));
       for (i in 1:D){
           x_loc[1, i, ] = u[i, ] * alpha[1];
       }
    }
}

If mutilate=0 then alpha and the derived parameters are empty arrays. They don’t contain anything to print to output so they’re practically nonexistent.

2 Likes

That is a great idea. Thank you!

I ended up doing this trick because matrix[D, 1] x_loc[mutilate] trick didn’t work for me:

data {
        int D; //number of data points
        matrix[D, 1] u;
        matrix[D,1] x;
        int <lower=0, upper=1> not_mutilate;
    }
parameters {
       matrix[1, L] mu; 
       matrix[not_mutilate ? 1 : 0, not_mutilate ? 1 : 0] alpha;
    }
transformed parameters {
       matrix[not_mutilate ? D : 0, not_mutilate ? N : 0] x_loc;
       vector[not_mutilate ? N : 0] x_scale;
       matrix[not_mutilate ? N : 0, not_mutilate ? N : 0] sigma_xx;
       if (not_mutilate) {
          sigma_xx = alpha'*alpha + diag_matrix(rep_vector(1, N));
          x_scale = sqrt(diagonal(sigma_xx));
       }
       for (i in 1:D){
           if (not_mutilate) {
              x_train_loc[i, ] = u_train[i, ] * alpha;
           }
       }
    }
...