# Select a random integer index in Stan

I want to generate a random integer between 1 to 3000. For that, first I generate a random value from (0,1) called`unif`, and then take the ceiling of `unif*3000`. To generate a uniform value I found the function `uniform_rng` where I defined in the generated quantities block, but I cant get the ceiling part of the code to work. In addition to that, I’m not sure if defining `unif` and ceiling of `unif*3000` inside generated quantities block is a good idea. It didn’t work inside the transformed parameters block and produced an error. Here is a small and simplified example of my code:

``````stan_model_hmc_whc2 <- "
data {
int D;
matrix[D, 1] u[3000];
matrix[1, L] mu[3000];
}
parameters {
matrix[1 1] eta;
}
transformed parameters {
// empty
}
}
model {
for (j in 1:L){
target += normal_lpdf(eta[j, ] | 0, 10);
}
for (i in 1:D){
target += normal_lpdf(u[i, idx] | mu[1,idx], 1);      // likelihood
}
}
generated quantities{
real unif = uniform_rng(0,1);
idx = ceil(unif * 3000);  //this line produces error
}
"
``````

Can anybody help me to on how to define a random integer between 0 and 3000?

Would this work?

So get idx and then loop from 1 to 3000, use continue to skip until correct n is found, Then break.

``````generated quantities{
real unif = uniform_rng(0,1);
real idx = unif * 3000;
for (n in 1:3000) {
if (n < idx) { continue }
...
break
}
}
``````
1 Like

Thank you. This works. Do you know why I can’t use `real unif = uniform_rng(0,1);` inside the transformed parameters block? It seems like `uniform_rng` only works inside the generated quantities block.

all `_rng` functions only work in `transformed data` and `generated quantities` blocks. I’m guessing the reasons they don’t allow it in `transformed parameters` and `model` blocks is that these produce discontinuities which cannot be handled by Stan.

I see. so if I use it like this:

``````transformed data {
real unif = uniform_rng(0,1);
real idx = ceil(unif * 3000);
}
``````

Is there a way to convert indx to an integer instead of using the for loop that you suggested? Are we allowed to have for loops inside transformed data block?

Why do you want to have random locations in transformed parameters?

You could provide random array with data (transformed data?)

yes you are right. It makes sense to have it in transformed data, not the transformed parameters. I ended up writting it like this:

``````transformed data {
real unif = uniform_rng(0,1);
real id = ceil(unif * 3000);
int idx;
for (n in 1:3000) {
if (n == id) {
idx = n;
break;
}
}
}
``````

If there is a better way to convert real to int please let me know. I used the for loop trick that you suggested and it worked for me.

1 Like