Hi,
I’m trying to model activity propagation in a network with N nodes for N_TS time points that spreads as described by the following evolution equation:
\frac{dx_i}{dt}\tau_i = -x_i(t) + s\phi\big(x_i(t)\big) + g\Bigg(\sum_{j\neq i}^{N} W_{ij}\phi\big(x_j(t)\big)\Bigg) + I_i(t)
This is the first time I’m trying to solve an ODE in a Stan model so it’s very possible that I’ve made other mistakes as well. I haven’t even gotten to the point of testing the actual model yet because I can’t compile it due to the following error:
Compiling Stan program...
/
Semantic error in '/var/folders/10/zpzbg__x3hlc56gwq9zf6r600000gn/T/RtmphjhKZn/model-e51f176820ee.stan', line 120, column 22 to column 82:
-------------------------------------------------
118: // states x are estimated as parameters z with some uncertainty.
119: // these estimated parameters are used in the model description to relate them to measured data
120: vector[N] z[N_TS] = ode_rk45(dx_dt, z_init, t0, ts, N, N_t, I, ts, s, g, b, tau);
^
121: }
122:
-------------------------------------------------
Ill-typed arguments supplied to function 'ode_rk45'. Available signatures:
(real, vector, ...) => vector, vector, real, real[], ...
.
Instead supplied arguments of incompatible type:
(real, vector, int, vector[], vector, vector, real, real, real, real) => vector, vector, real, real[], int, vector[], vector, real[], real, real, real, real.
The supplied arguments of type real
and vector
look like they should agree with the required signature for the ode_rk45
function so I’m not sure how to debug this. As I said, it is entirely possible that the error lies somewhere else but I’m not sure where to start. Any help would be appreciated.
Here’s the full model:
functions {
real phi(real a){
real out = (exp(2*a)-1)/(exp(2*a)+1);
return out;
}
// From
// https://canada1.discourse-cdn.com/flex030/uploads/mc_stan/original/1X/25b0af2e6aba491a267c45fa090c6374ad57c4b4.pdf
// https://discourse.mc-stan.org/t/zero-chain-movement-mixing-in-forced-ode-model/921
int find_interval_elem(real x, vector sorted, int start_ind){
int res;
int N;
int max_iter;
real left;
real right;
int left_ind;
int right_ind;
int iter;
N = num_elements(sorted);
if(N == 0) return(0);
left_ind = start_ind;
right_ind = N;
max_iter = 100 * N;
left = sorted[left_ind ] - x;
right = sorted[right_ind] - x;
if(0 <= left) return(left_ind-1);
if(0 == right) return(N-1);
if(0 > right) return(N);
iter = 1;
while((right_ind - left_ind) > 1 && iter != max_iter) {
int mid_ind;
real mid;
// is there a controlled way without being yelled at with a
// warning?
mid_ind = (left_ind + right_ind) / 2;
mid = sorted[mid_ind] - x;
if (mid == 0) return(mid_ind-1);
if (left * mid < 0) { right = mid; right_ind = mid_ind; }
if (right * mid < 0) { left = mid; left_ind = mid_ind; }
iter = iter + 1;
}
if(iter == max_iter)
print("Maximum number of iterations reached.");
return(left_ind);
}
vector dx_dt(real t, // time
vector x, // system state {1 x N - network activity for each time point}
int N,
vector[] N_t, //vector array
vector I,
vector ts,
real s,
real g,
real b,
real tau) {
vector[N] res;
int d = find_interval_elem(t, ts, 1);
for (i in 1:N){
res[i] = (-x[i] + s * phi(x[i]) + g *N_t[d, i] + b * I[d])/tau;
}
// returns change for one time point for all nodes
return res;
}
}
data {
int<lower = 0> N_TS; // number of measurement times
int<lower = 0> N; // number of nodes
real t0;
real ts[N_TS]; // measurement times > 0
vector[N] y_init; // initial measured activity level
// Arrays are declared by enclosing the dimensions in square brackets following the name of the variable.
// this is an array of length N_TS consisting of (column) vectors of length N
// Each array element is like a row
vector[N] y[N_TS]; // measured activity level with nodes in cols and timepoints in rows
matrix[N, N] W;// adjacency matrix
vector[N_TS] I; // task stimulation
}
transformed data{
vector[N] N_t[N_TS];
for(i in 1:N){
for(t in 1:N_TS){
//row of incoming connections to node i of length n
//multiplied with activity (column) vector of length n for all nodes at time t
N_t[t, i] = dot_product(W[i,], y[t]);
}
}
}
parameters {
real<lower = 0> s; // self coupling
real<lower = 0> g; // global coupling
real<lower = 0> b; // task modulation
real<lower = 0> tau; // time constant
real<lower = 0> sigma; // measurement error
vector[N] x_init;
}
transformed parameters {
// states x are estimated as parameters z with some uncertainty.
// these estimated parameters are used in the model description to relate them to measured data
vector[N] x[N_TS] = ode_rk45(dx_dt, x_init, t0, ts, N, N_t, I, ts, s, g, b, tau);
}
model {
s ~ lognormal(-1, 1);
g ~ lognormal(-1, 1);
beta ~ lognormal(-1, 1);
tau ~ normal(1, 0.5);
sigma ~ lognormal(-1, 1);
for (k in 1:N) {
y_init[k] ~ lognormal(log(x_init[k]), sigma);
y[ , k] ~ lognormal(log(x[, k]), sigma[k]);
}
}