primarycensored
Loading...
Searching...
No Matches
primarycensored_analytical_cdf.stan
Go to the documentation of this file.
1
15int check_for_uniform_terms(int dist_id, int primary_id) {
16 if (primary_id != 1) return 0;
17 return dist_id == 2 || dist_id == 1 || dist_id == 3 || dist_id == 5;
18}
19
37int check_for_analytical(int dist_id, int primary_id) {
38 // Gamma, Lognormal, Weibull and generalised gamma with a Uniform primary
39 if (check_for_uniform_terms(dist_id, primary_id)) return 1;
40 // Keep this primary list in sync with `primary_lcdf`; see the note above.
41 if (dist_id == 26 || dist_id == 27 || dist_id == 28) {
42 return primary_id == 1 || primary_id == 2;
43 }
44 return 0; // No analytical solution for other combinations
45}
46
68real primarycensored_uniform_lcdf_from_terms(vector terms_d, vector terms_q,
69 data real pwindow) {
70 real log_A = log_sum_exp(terms_d[1], terms_q[2]);
71 real log_B = log_sum_exp(terms_q[1], terms_d[2]);
72 // Deep enough into the lower tail every term underflows together. Both
73 // are then `-inf` and `log_diff_exp` would give NaN, so return the limit
74 // directly.
75 if (log_A == negative_infinity() && log_B == negative_infinity()) {
76 return negative_infinity();
77 }
78 return log_diff_exp(log_A, log_B) - log(pwindow);
79}
80
92 array[] real params) {
93 if (t <= 0) {
94 return rep_vector(negative_infinity(), 2);
95 }
96 real shape = params[1];
97 real rate = params[2];
98 // log E where E = k * theta = shape / rate is the mean of the delay
99 real log_E = log(shape) - log(rate);
100 // F_T(t; k) and the recursion to F_T(t; k+1):
101 // P(k+1, y) = P(k, y) - y^k e^{-y} / Gamma(k+1), with y = rate * t
102 real log_F_T_k = gamma_lcdf(t | shape, rate);
103 real gamma_kp1_pdf_log = shape * log(rate * t) - rate * t
104 - lgamma(shape + 1);
105 real log_F_T_kp1 = log_diff_exp(log_F_T_k, gamma_kp1_pdf_log);
106 return [log(t) + log_F_T_k, log_E + log_F_T_kp1]';
107}
108
123vector primarycensored_lognormal_uniform_terms(real t,
124 array[] real params) {
125 real mu = params[1];
126 real sigma = params[2];
127 real mu_sigma2 = mu + square(sigma);
128 // log E where E = exp(mu + sigma^2/2) is the mean of the delay
129 real log_E = mu + 0.5 * square(sigma);
130 real log_t_F_T = lognormal_lcdf_underflows(t, mu, sigma)
131 ? negative_infinity()
132 : log(t) + lognormal_lcdf(t | mu, sigma);
133 real log_E_tF_T = lognormal_lcdf_underflows(t, mu_sigma2, sigma)
134 ? negative_infinity()
135 : log_E + lognormal_lcdf(t | mu_sigma2, sigma);
136 return [log_t_F_T, log_E_tF_T]';
137}
138
153real log_weibull_g(real t, real shape, real scale) {
154 real x = pow(t * inv(scale), shape);
155 real a = 1 + inv(shape);
156 // gamma_lcdf(x | a, 1) is log(gamma_p(a, x)), but reverse-mode gamma_p()
157 // returns zero gradients for x / a > 10
158 // (https://github.com/stan-dev/math/issues/2006). gamma_lcdf() has the
159 // same value and computes its own gradients without that cutoff.
160 return gamma_lcdf(x | a, 1) + lgamma(a);
161}
162
176 array[] real params) {
177 if (t <= 0) {
178 return rep_vector(negative_infinity(), 2);
179 }
180 real shape = params[1];
181 real scale = params[2];
182 return [
183 log(t) + weibull_lcdf(t | shape, scale),
184 log(scale) + log_weibull_g(t, shape, scale)
185 ]';
186}
187
205vector primarycensored_gengamma_uniform_terms(real t,
206 array[] real params) {
207 if (t <= 0) {
208 return rep_vector(negative_infinity(), 2);
209 }
210 real shape = params[1];
211 real scale = params[2];
212 real k = params[3];
213 real k_shift = k + inv(shape);
214 real log_E = log(scale) + lgamma(k_shift) - lgamma(k);
215 return [
216 log(t) + gengamma_lcdf(t | shape, scale, k),
217 log_E + gengamma_lcdf(t | shape, scale, k_shift)
218 ]';
219}
220
233vector primarycensored_uniform_terms(real t, data int dist_id,
234 array[] real params) {
235 if (dist_id == 2) {
236 return primarycensored_gamma_uniform_terms(t, params);
237 } else if (dist_id == 1) {
239 } else if (dist_id == 3) {
241 } else if (dist_id == 5) {
243 }
244 reject("Invalid distribution identifier: ", dist_id);
245}
246
259real primarycensored_gamma_uniform_lcdf(data real d, real q,
260 array[] real params,
261 data real pwindow) {
264 primarycensored_gamma_uniform_terms(q, params), pwindow
265 );
266}
267
281 array[] real params,
282 data real pwindow) {
286 );
287}
288
302 array[] real params,
303 data real pwindow) {
306 primarycensored_weibull_uniform_terms(q, params), pwindow
307 );
308}
309
324 array[] real params,
325 data real pwindow) {
329 );
330}
331
337real primarycensored_analytical_lcdf_raw(data real d, int dist_id,
338 array[] real params,
339 data real pwindow,
340 int primary_id,
341 array[] real primary_params) {
342 real q = max({d - pwindow, 0});
343
344 if (dist_id == 2 && primary_id == 1) {
345 return primarycensored_gamma_uniform_lcdf(d | q, params, pwindow);
346 } else if (dist_id == 1 && primary_id == 1) {
347 return primarycensored_lognormal_uniform_lcdf(d | q, params, pwindow);
348 } else if (dist_id == 3 && primary_id == 1) {
349 return primarycensored_weibull_uniform_lcdf(d | q, params, pwindow);
350 } else if (dist_id == 5 && primary_id == 1) {
351 return primarycensored_gengamma_uniform_lcdf(d | q, params, pwindow);
352 } else if (dist_id == 26) {
353 // params = [boundaries (K+1), pmf (K)]; length 2*K + 1.
354 int K = (size(params) - 1) %/% 2;
355 return discretestep_lcdf(
356 d | to_vector(segment(params, 1, K + 1)),
357 to_vector(segment(params, K + 2, K)),
358 primary_id, primary_params, pwindow
359 );
360 } else if (dist_id == 27 || dist_id == 28) {
361 // params = [boundaries (K+1), hazards (K)]; length 2*K + 1. The last
362 // hazard must equal 1. RW (27) and RE (28) only differ in their
363 // prior so they share this likelihood dispatch.
364 int K = (size(params) - 1) %/% 2;
365 return discretehazard_lcdf(
366 d | to_vector(segment(params, 1, K + 1)),
367 to_vector(segment(params, K + 2, K)),
368 primary_id, primary_params, pwindow
369 );
370 }
371 return negative_infinity();
372}
373
390real primarycensored_analytical_lcdf(data real d, int dist_id,
391 array[] real params,
392 data real pwindow, data real L,
393 data real D, int primary_id,
394 array[] real primary_params) {
395 if (d <= L) return negative_infinity();
396 if (d >= D) return 0;
397
399 d, dist_id, params, pwindow, primary_id, primary_params
400 );
401
402 // Apply truncation normalization
403 if (!is_inf(D) || L > 0) {
404 vector[2] bounds = primarycensored_truncation_bounds(
405 L, D, dist_id, params, pwindow, primary_id, primary_params
406 );
407 real log_cdf_L = bounds[1];
408 real log_cdf_D = bounds[2];
409
410 real log_normalizer = primarycensored_log_normalizer(log_cdf_D, log_cdf_L, L);
411 result = primarycensored_apply_truncation(result, log_cdf_L, log_normalizer, L);
412 }
413
414 return result;
415}
416
433real primarycensored_analytical_cdf(data real d, int dist_id,
434 array[] real params,
435 data real pwindow, data real L,
436 data real D, int primary_id,
437 array[] real primary_params) {
438 return exp(primarycensored_analytical_lcdf(d | dist_id, params, pwindow, L, D, primary_id, primary_params));
439}
440
459int check_for_analytical_vectorized(int dist_id, int primary_id,
460 data real pwindow) {
461 return check_for_uniform_terms(dist_id, primary_id) &&
462 pwindow >= 1 && floor(pwindow) == pwindow;
463}
464
486 data int n,
487 data int dist_id,
488 array[] real params,
489 data real pwindow) {
490 int pw = to_int(pwindow);
491 vector[n] log_cdfs;
492 // terms[t + 1] holds the terms at delay t
493 array[n + 1] vector[2] terms;
494 for (t in max(start - pw, 0):n) {
495 terms[t + 1] = primarycensored_uniform_terms(t, dist_id, params);
496 }
497 for (d in start:n) {
499 terms[d + 1], terms[max(d - pw, 0) + 1], pwindow
500 );
501 }
502 return log_cdfs;
503}
real log_weibull_g(real t, real shape, real scale)
vector primarycensored_weibull_uniform_terms(real t, array[] real params)
vector primarycensored_lognormal_uniform_terms(real t, array[] real params)
vector primarycensored_gengamma_uniform_terms(real t, array[] real params)
int check_for_uniform_terms(int dist_id, int primary_id)
vector primarycensored_gamma_uniform_terms(real t, array[] real params)
int check_for_analytical_vectorized(int dist_id, int primary_id, data real pwindow)
vector primarycensored_uniform_terms(real t, data int dist_id, array[] real params)
real primarycensored_uniform_lcdf_from_terms(vector terms_d, vector terms_q, data real pwindow)
int check_for_analytical(int dist_id, int primary_id)
real primarycensored_weibull_uniform_lcdf(data real d, real q, array[] real params, data real pwindow)
vector primarycensored_analytical_lcdf_vectorized(data int start, data int n, data int dist_id, array[] real params, data real pwindow)
real primarycensored_analytical_lcdf_raw(data real d, int dist_id, array[] real params, data real pwindow, int primary_id, array[] real primary_params)
real primarycensored_lognormal_uniform_lcdf(data real d, real q, array[] real params, data real pwindow)
real primarycensored_analytical_lcdf(data real d, int dist_id, array[] real params, data real pwindow, data real L, data real D, int primary_id, array[] real primary_params)
real primarycensored_gengamma_uniform_lcdf(data real d, real q, array[] real params, data real pwindow)
real primarycensored_gamma_uniform_lcdf(data real d, real q, array[] real params, data real pwindow)
real primarycensored_analytical_cdf(data real d, int dist_id, array[] real params, data real pwindow, data real L, data real D, int primary_id, array[] real primary_params)
real discretestep_lcdf(data real d, vector boundaries, vector pmf, int primary_id, array[] real primary_params, data real pwindow)
real discretehazard_lcdf(data real d, vector boundaries, vector hazards, int primary_id, array[] real primary_params, data real pwindow)
real primarycensored_apply_truncation(real log_cdf, real log_cdf_L, real log_normalizer, real L)
real primarycensored_log_normalizer(real log_cdf_D, real log_cdf_L, real L)
vector primarycensored_truncation_bounds(data real L, data real D, data int dist_id, array[] real params, data real pwindow, data int primary_id, array[] real primary_params)