Concatenating N vectors

Hi, I have N vectors v_n of dimension K x 1, I would like to concatenate all these vectors into a a unique vector of dimension N*K.
Obviously I cannot use append_row, I tried with for loop but I could not do it. Any idea? Thanks in advance.

You would need to define your own function that creates an N*K vector and copies each vector into it, try something like (untested):

functions {
  vector append_vector(vector[] vector_arr) {
    int dims[2] = dims(vector_arr);
    vector[dims[1]*dims[2]] rtn;

    for(i in 1:dims[1]) {
      rtn[(1+(i-1)*dims[2]):(i*dims[2])] = vector_arr[i];
    }

    return rtn;
  }
}

Thanks a lot for the answer, but I am not sure I understand (I am sort of new to Stan).

The function takes as second input the array of N vectors v_n correct? What is the first input?

Also, I tried to put it on Stan and it says “variable identifier (name) may not be reserved word” at the second line.

The function takes as second input the array of N vectors v_n correct? What is the first input?

The function only takes one input, the array of vectors. When there’s a function declaration like:

vector append_vector(vector[] vector_arr)

The first vector is the return type of the function and the section vector[] vector_arr indicates that the function takes a single argument (vector_arr) that is an array of vectors (vector[]).

Also, I tried to put it on Stan and it says “variable identifier (name) may not be reserved word” at the second line.

Ah right, that’s because I was using dims as a variable, which is also the name of a function. Try this instead:

functions {
  vector append_vector(vector[] vector_arr) {
    int v_dims[2] = dims(vector_arr);
    vector[v_dims[1]*v_dims[2]] rtn;

    rtn[1:v_dims[2]] = vector_arr[1];

    for(i in 2:v_dims[1]) {
      rtn[(1+(i-1)*v_dims[2]):(i*v_dims[2])] = vector_arr[i];
    }

    return rtn;
  }
}
3 Likes

Thanks again, now it is all very clear. My last question is that, I defined the vectors:

parameters {
  vector[K] v[N];
}

How do I generate an array with all the ordered vectors v_n ? If I use simply v, does Stan treat it as an array?

The function does not work for whomever reads this post.

Hi, a user on this forum created a function to concatenate J column vectors of dimension K, but I cannot understand why it is not working. I am probably doing something wrong, but I am fairly new to Stan.

This is the function:

 vector append_vector(vector[] vector_arr) {
    int v_dims[2] = dims(vector_arr);
    vector[v_dims[1]*v_dims[2]] rtn;

    rtn[1:v_dims[2]] = vector_arr[1];

    for(i in 2:v_dims[1]) {
      rtn[(1+(i-1)*v_dims[2]):(i*v_dims[2])] = vector_arr[i];
    }

    return rtn;
  }

And this is how I use it:

vector[K] beta[J];
vector[J*K] Beta

Beta = append_vector(beta[])

The input of the function is an array of vectors, what am I doing wrong? How do I transform the betas in an array of vectors?

I think this has to be changed to

Beta = append_vector(beta)

and it should work (ignoring the missing semicolon).

This was the first thing I tried, it tells me the dimensions do not match at line

Beta = append_vector(beta)

But it also tells me this for the line

“int v_dims[2] = dims(vector_arr)”, so maybe also the function is wrong?

Is there a way to test the function and understand what it is creating, without running the entire model?

Huh, how very awkward.

I think the best way to do this is to build an as-simple-as-possible model which uses the function and let it sample with few warmup/sampling iterations. Case in point:

functions{
  vector append_vector(vector[] vector_arr) {
   int v_dims[1] = dims(vector_arr);
   print("HELLO?", v_dims, dims(vector_arr));
   vector[v_dims[1]*v_dims[2]] rtn;

   rtn[1:v_dims[2]] = vector_arr[1];

   for(i in 2:v_dims[1]) {
     rtn[(1+(i-1)*v_dims[2]):(i*v_dims[2])] = vector_arr[i];
   }

   return rtn;
 }
}
transformed data{
  int K = 2;
  int J = 3;
}
parameters {
  vector[K] beta[J];
}
transformed parameters{
  vector[J*K] Beta = append_vector(beta);
}
model {
  for(j in 1:J){
    beta[j] ~ normal(0,1);
  }
}

yields, for me

HELLO?[3,2,1][3,2,1]

which I find very strange. My stan version as reported in the header of the csv file is:

# stan_version_major = 2
# stan_version_minor = 26
# stan_version_patch = 1

So the function does not work basically. Do you have any idea how to concatenate J column vectors?

Btw thank you, you have been very helpful

Well it should work, but there appears to be a big somewhere (on Stan’s side).

Try setting the length of v_dims to 3.

I noticed you changed v_dims[2] with v_dims[1] in the second line of your code. This also confused me, since one of the two is not defined in the code. Maybe this causes the issue?

I think the issue is with the dims() function, maybe with num_elements() it works.

Rstan has Expose user-defined Stan functions to <span style="R">R</span> for testing and simulation — expose_stan_functions • rstan (which still requires compilation)

Yes this is the weirdest to me thing, that this works. The compiler should be able to infer the appropriate length at compile time…

So there does not seem to be a solution yet :/

It seems such an easy problem but nobody manages to figure it out…

Please avoid opening multiple threads to continue an existing topic.

By selecting only the first two dims and only using the loop, the following function works:

functions {
  vector append_vector(vector[] vector_arr) {
    int v_dims[2] = dims(vector_arr)[{1,2}];
    vector[v_dims[1]*v_dims[2]] rtn;

    for(i in 1:v_dims[1]) {
      rtn[(1+(i-1)*v_dims[2]):(i*v_dims[2])] = vector_arr[i];
    }

    return rtn;
  }
}

Tested:

library(rstan)
#> Loading required package: StanHeaders
#> Loading required package: ggplot2
#> rstan (Version 2.21.2, GitRev: 2e1f913d3ca3)
#> For execution on a local, multicore CPU with excess RAM we recommend calling
#> options(mc.cores = parallel::detectCores()).
#> To avoid recompilation of unchanged Stan programs, we recommend calling
#> rstan_options(auto_write = TRUE)

modcode = "functions {
  vector append_vector(vector[] vector_arr) {
    int v_dims[2] = dims(vector_arr)[{1,2}];
    vector[v_dims[1]*v_dims[2]] rtn;

    for(i in 1:v_dims[1]) {
      rtn[(1+(i-1)*v_dims[2]):(i*v_dims[2])] = vector_arr[i];
    }

    return rtn;
  }
}"

expose_stan_functions(stanc(model_code=modcode))

append_vector(list(c(1,2,3),c(4,5,6)))
#> [1] 1 2 3 4 5 6

Created on 2021-07-20 by the reprex package (v2.0.0)

1 Like

It works now, I apologize for the additional thread, I was in a bit of a hurry. Thanks a lot to both of you. So that small mistake in dims(vector_arr)[{1,2}] caused the issue?

Yep, I believe so

Note: I merged the two threads