epinowcast
Loading...
Searching...
No Matches
arima_kernel.stan
Go to the documentation of this file.
1
36vector pacf_to_phi(vector r) {
37 int p = num_elements(r);
38 if (p == 0) return r;
39 vector[p] phi = r;
40 vector[p] work = r;
41 for (k in 2:p) {
42 for (j in 1:(k - 1)) {
43 work[j] = phi[j] - r[k] * phi[k - j];
44 }
45 for (j in 1:(k - 1)) {
46 phi[j] = work[j];
47 }
48 phi[k] = r[k];
49 }
50 return phi;
51}
52
59vector arma_impulse(vector phi, vector theta, int T) {
60 int p = num_elements(phi);
61 int q = num_elements(theta);
62 vector[T] psi = rep_vector(0.0, T);
63 psi[1] = 1.0;
64 for (t in 2:T) {
65 real s = 0.0;
66 int kmax = min(p, t - 1);
67 for (k in 1:kmax) s += phi[k] * psi[t - k];
68 if (t - 1 <= q) s += theta[t - 1];
69 psi[t] = s;
70 }
71 return psi;
72}
73
82matrix lower_toeplitz(vector psi) {
83 int T = num_elements(psi);
84 matrix[T, T] K = rep_matrix(0.0, T, T);
85 for (s in 1:T) {
86 K[s:T, s] = head(psi, T - s + 1);
87 }
88 return K;
89}
90
99matrix cumulative_op(int T, int d) {
100 if (d == 0) return diag_matrix(rep_vector(1.0, T));
101 matrix[T, T] D1 = rep_matrix(0.0, T, T);
102 for (s in 1:T) {
103 D1[s:T, s] = rep_vector(1.0, T - s + 1);
104 }
105 matrix[T, T] D = D1;
106 for (i in 2:d) D = D * D1;
107 return D;
108}
109
121matrix arima_kernel_matrix(vector phi, vector theta, int d, int T) {
122 vector[T] psi = arma_impulse(phi, theta, T);
123 matrix[T, T] K = lower_toeplitz(psi);
124 for (i in 1:d) {
125 for (col in 1:T) {
126 K[, col] = cumulative_sum(K[, col]);
127 }
128 }
129 return K;
130}
131
145matrix arima_filter(matrix Z, vector phi, vector theta, int d) {
146 int T = rows(Z);
147 int G = cols(Z);
148 if (num_elements(phi) == 0 && num_elements(theta) == 0) {
149 if (d == 0) return Z;
150 matrix[T, G] result = Z;
151 for (i in 1:d) {
152 for (g in 1:G) {
153 result[, g] = cumulative_sum(result[, g]);
154 }
155 }
156 return result;
157 }
158 return arima_kernel_matrix(phi, theta, d, T) * Z;
159}
160
185vector apply_arima_residual(vector base, int n_obs,
186 int present, int T, int G,
187 int p, int d, int q,
188 matrix z, vector pacf, vector theta,
189 array[] real sigma,
190 array[] int flat_idx) {
191 if (!present) return base;
192 vector[p] phi = pacf_to_phi(pacf);
193 matrix[T, G] eps = sigma[1] * arima_filter(z, phi, theta, d);
194 // Vectorised gather: flat_idx is precomputed in transformed data
195 // as (group_idx - 1) * T + time_idx, so to_vector(eps) (column-
196 // major flatten) [flat_idx] returns the per-observation residuals
197 // in one shot, replacing the previous element-by-element loop.
198 return base + to_vector(eps)[flat_idx];
199}
vector apply_arima_residual(vector base, int n_obs, int present, int T, int G, int p, int d, int q, matrix z, vector pacf, vector theta, array[] real sigma, array[] int flat_idx)
matrix lower_toeplitz(vector psi)
vector arma_impulse(vector phi, vector theta, int T)
vector pacf_to_phi(vector r)
matrix cumulative_op(int T, int d)
matrix arima_filter(matrix Z, vector phi, vector theta, int d)
matrix arima_kernel_matrix(vector phi, vector theta, int d, int T)