user2089357
user2089357

Reputation: 125

stan - difficulty vectorizing

I have:

mu_x - a 10x10 matrix of real values

ptype - a 10000 long vector

sender_name_type - a 10000 long vector

I'd like to find the values of

x_real - a 10000 long vector

The code I currently have, and works, is:

for(i in 1:N){
  if(x_available[i]){
    x_real[i]~normal(x[i],0.01);} else{
    x_real[i]~normal(mu_x[ptype[i],sender_name_type[i]],0.1);
  }
}

I'd like however, to vectorize it. To do that, I'd first need to deal with the if clause. To do that, I tried just adding two distributions, like so:

x_real ~ normal(mu_x[ptype,sender_name_type],0.1) * (1-x_avaiable) + normal(x,0.01) * x_available;

However, Rstan seems to not handle adding/multiplying distributions. The second approach I tried was like so:

x_real ~ normal(mu_x[ptype,sender_name_type],0.1);
x_real[x_available == 1] ~ normal(x,0.01);

Which is similar to the first approach, but it redefines the rows of x_real, for which the condition is met. However, it gives me the error of

No matches for:

real[] ~ normal(matrix, real)

How can I vectorize my current solution, if possible? Are there any other ways I could speed it up?

Upvotes: 2

Views: 942

Answers (1)

Ben Goodrich
Ben Goodrich

Reputation: 4990

The Stan language does not flatten when you use multiple indices like [ptype,sender_name_type]. Nor does the Stan language support indexing by logical condition, such as [x_available == 1].

The way to do something like this is loop to set up the arguments, and then evaluate the likelihood in one step to avoid unnecessary memory allocations. In your case, it would look like

vector[N] x_hat;
vector[N] noise;
for (i in 1:N) {
  x_hat[i] = x_available[i] ? x[i] : mu_x[ptype[i],sender_name_type[i]];
  noise[i] = x_available[i] ? 0.01 : 0.1;
}
target += normal_lpdf(x_real | x_hat, noise);

Upvotes: 2

Related Questions