primarycensored
Loading...
Searching...
No Matches
primarycensored.stan
Go to the documentation of this file.
1
15real primarycensored_log_normalizer(real log_cdf_D, real log_cdf_L, real L) {
16 if (L > 0) {
17 return log_diff_exp(log_cdf_D, log_cdf_L);
18 } else {
19 return log_cdf_D;
20 }
21}
22
36real primarycensored_apply_truncation(real log_cdf, real log_cdf_L,
37 real log_normalizer, real L) {
38 if (L > 0) {
39 return log_diff_exp(log_cdf, log_cdf_L) - log_normalizer;
40 } else {
41 return log_cdf - log_normalizer;
42 }
43}
44
60 data real L, data real D,
61 int dist_id, array[] real params, data real pwindow,
62 int primary_id, array[] real primary_params
63) {
64 vector[2] result;
65
66 // Get CDF at lower truncation point L
67 if (L <= 0) {
68 result[1] = negative_infinity();
69 } else {
70 result[1] = primarycensored_lcdf(
71 L | dist_id, params, pwindow, 0, positive_infinity(),
72 primary_id, primary_params
73 );
74 }
75
76 // Get CDF at upper truncation point D
77 if (is_inf(D)) {
78 result[2] = 0;
79 } else {
80 result[2] = primarycensored_lcdf(
81 D | dist_id, params, pwindow, 0, positive_infinity(),
82 primary_id, primary_params
83 );
84 }
85
86 return result;
87}
88
105real primarycensored_cdf(data real d, int dist_id, array[] real params,
106 data real pwindow, data real L, data real D,
107 int primary_id,
108 array[] real primary_params) {
109 real result;
110 if (d <= L) {
111 return 0;
112 }
113
114 if (d >= D) {
115 return 1;
116 }
117
118 // Check if an analytical solution exists
119 if (check_for_analytical(dist_id, primary_id)) {
120 // Use analytical solution
122 d | dist_id, params, pwindow, L, D, primary_id, primary_params
123 );
124 } else {
125 // Use numerical integration for other cases
126 real lower_bound = max({d - pwindow, 1e-6});
127 int n_params = num_elements(params);
128 int n_primary_params = num_elements(primary_params);
129 array[n_params + n_primary_params] real theta = append_array(params, primary_params);
130 array[4] int ids = {dist_id, primary_id, n_params, n_primary_params};
131
132 vector[1] y0 = rep_vector(0.0, 1);
133 result = ode_rk45(primarycensored_ode, y0, lower_bound, {d}, theta, {d, pwindow}, ids)[1, 1];
134
135 // Apply truncation normalization on log scale for numerical stability
136 if (!is_inf(D) || L > 0) {
137 real log_result = log(result);
138 vector[2] bounds = primarycensored_truncation_bounds(
139 L, D, dist_id, params, pwindow, primary_id, primary_params
140 );
141 real log_cdf_L = bounds[1];
142 real log_cdf_D = bounds[2];
143
144 real log_normalizer = primarycensored_log_normalizer(log_cdf_D, log_cdf_L, L);
146 log_result, log_cdf_L, log_normalizer, L
147 );
148 result = exp(log_result);
149 }
150 }
151
152 return result;
153}
154
186real primarycensored_lcdf(data real d, int dist_id, array[] real params,
187 data real pwindow, data real L, data real D,
188 int primary_id,
189 array[] real primary_params) {
190 real result;
191
192 if (d <= L) {
193 return negative_infinity();
194 }
195
196 if (d >= D) {
197 return 0;
198 }
199
200 // Check if an analytical solution exists
201 if (check_for_analytical(dist_id, primary_id)) {
203 d | dist_id, params, pwindow, 0, positive_infinity(), primary_id, primary_params
204 );
205 } else {
206 // Use numerical integration
207 result = log(primarycensored_cdf(
208 d | dist_id, params, pwindow, 0, positive_infinity(), primary_id, primary_params
209 ));
210 }
211
212 // Handle truncation normalization
213 if (!is_inf(D) || L > 0) {
214 vector[2] bounds = primarycensored_truncation_bounds(
215 L, D, dist_id, params, pwindow, primary_id, primary_params
216 );
217 real log_cdf_L = bounds[1];
218 real log_cdf_D = bounds[2];
219
220 real log_normalizer = primarycensored_log_normalizer(log_cdf_D, log_cdf_L, L);
221 result = primarycensored_apply_truncation(result, log_cdf_L, log_normalizer, L);
222 }
223
224 return result;
225}
226
260real primarycensored_lpmf(data int d, int dist_id, array[] real params,
261 data real pwindow, data real d_upper,
262 data real L, data real D, int primary_id,
263 array[] real primary_params) {
264 if (d_upper > D) {
265 reject("Upper truncation point is greater than D. It is ", d_upper,
266 " and D is ", D, ". Resolve this by increasing D to be greater or equal to d + swindow or decreasing swindow.");
267 }
268 if (d_upper <= d) {
269 reject("Upper truncation point is less than or equal to d. It is ", d_upper,
270 " and d is ", d, ". Resolve this by increasing d to be less than d_upper.");
271 }
272 if (d < L) {
273 return negative_infinity();
274 }
275 real log_cdf_upper = primarycensored_lcdf(
276 d_upper | dist_id, params, pwindow, 0, positive_infinity(), primary_id, primary_params
277 );
278 real log_cdf_lower = primarycensored_lcdf(
279 d | dist_id, params, pwindow, 0, positive_infinity(), primary_id, primary_params
280 );
281
282 // Apply truncation normalization: log((F(d_upper) - F(d)) / (F(D) - F(L)))
283 if (!is_inf(D) || L > 0) {
284 real log_cdf_D;
285 real log_cdf_L;
286
287 // Get CDF at lower truncation point L
288 if (L <= 0) {
289 // No left truncation
290 log_cdf_L = negative_infinity();
291 } else if (d == L) {
292 // Reuse already computed CDF at d
293 log_cdf_L = log_cdf_lower;
294 } else {
295 // Compute CDF at L directly
296 log_cdf_L = primarycensored_lcdf(
297 L | dist_id, params, pwindow, 0, positive_infinity(),
298 primary_id, primary_params
299 );
300 }
301
302 // Get CDF at upper truncation point D
303 if (d_upper == D) {
304 log_cdf_D = log_cdf_upper;
305 } else if (is_inf(D)) {
306 log_cdf_D = 0;
307 } else {
308 log_cdf_D = primarycensored_lcdf(
309 D | dist_id, params, pwindow, 0, positive_infinity(),
310 primary_id, primary_params
311 );
312 }
313
314 real log_normalizer = primarycensored_log_normalizer(log_cdf_D, log_cdf_L, L);
315 return log_diff_exp(log_cdf_upper, log_cdf_lower) - log_normalizer;
316 } else {
317 return log_diff_exp(log_cdf_upper, log_cdf_lower);
318 }
319}
320
353real primarycensored_pmf(data int d, int dist_id, array[] real params,
354 data real pwindow, data real d_upper,
355 data real L, data real D, int primary_id,
356 array[] real primary_params) {
357 return exp(
359 d | dist_id, params, pwindow, d_upper, L, D, primary_id, primary_params
360 )
361 );
362}
363
406 int max_delay, data real L, data real D, int dist_id,
407 array[] real params, data real pwindow,
408 int primary_id, array[] real primary_params
409) {
410
411 int upper_interval = max_delay + 1;
412 vector[upper_interval] log_pmfs;
413 vector[upper_interval] log_cdfs;
414 real log_normalizer;
415
416 // Check if D is at least max_delay + 1
417 if (D < upper_interval) {
418 reject("D must be at least max_delay + 1");
419 }
420
421 // Compute log CDFs (without truncation normalization)
422 // Start from max(1, floor(L)) to avoid computing unused CDFs when L > 0
423 int start_idx = L > 0 ? max(1, to_int(floor(L))) : 1;
424 for (d in start_idx:upper_interval) {
425 log_cdfs[d] = primarycensored_lcdf(
426 d | dist_id, params, pwindow, 0, positive_infinity(), primary_id,
427 primary_params
428 );
429 }
430
431 // Get CDF at lower truncation point L
432 real log_cdf_L;
433 if (L <= 0) {
434 // No left truncation
435 log_cdf_L = negative_infinity();
436 } else if (L <= upper_interval && floor(L) == L) {
437 // L is an integer within computed range, reuse cached value
438 log_cdf_L = log_cdfs[to_int(L)];
439 } else {
440 // L is outside computed range or non-integer, compute directly
441 log_cdf_L = primarycensored_lcdf(
442 L | dist_id, params, pwindow, 0, positive_infinity(),
443 primary_id, primary_params
444 );
445 }
446
447 // Compute log normalizer: log(F(D) - F(L))
448 real log_cdf_D;
449 if (D > upper_interval) {
450 if (is_inf(D)) {
451 log_cdf_D = 0; // log(1) = 0 for infinite D
452 } else {
453 log_cdf_D = primarycensored_lcdf(
454 D | dist_id, params, pwindow, 0, positive_infinity(),
455 primary_id, primary_params
456 );
457 }
458 } else {
459 log_cdf_D = log_cdfs[upper_interval];
460 }
461
462 log_normalizer = primarycensored_log_normalizer(log_cdf_D, log_cdf_L, L);
463
464 // Compute log PMFs: log((F(d) - F(d-1)) / (F(D) - F(L)))
465 for (d in 1:upper_interval) {
466 if (d <= L) {
467 // Delay interval [d-1, d) is entirely at or below L
468 log_pmfs[d] = negative_infinity();
469 } else if (d - 1 < L) {
470 // L falls within interval [d-1, d), so compute mass in [L, d)
471 log_pmfs[d] = log_diff_exp(log_cdfs[d], log_cdf_L) - log_normalizer;
472 } else if (d == 1) {
473 // First interval [0, 1) with L <= 0: F(0) = 0, so PMF = F(1) / normalizer
474 log_pmfs[d] = log_cdfs[d] - log_normalizer;
475 } else {
476 // Standard case: PMF = (F(d) - F(d-1)) / normalizer
477 log_pmfs[d] = log_diff_exp(log_cdfs[d], log_cdfs[d-1]) - log_normalizer;
478 }
479 }
480
481 return log_pmfs;
482}
483
523 int max_delay, data real L, data real D, int dist_id,
524 array[] real params, data real pwindow,
525 int primary_id,
526 array[] real primary_params
527) {
528 return exp(
530 max_delay, L, D, dist_id, params, pwindow, primary_id, primary_params
531 )
532 );
533}
int check_for_analytical(int dist_id, int primary_id)
vector primarycensored_ode(real t, vector y, array[] real theta, array[] real x_r, array[] int x_i)
real primarycensored_pmf(data int d, int dist_id, array[] real params, data real pwindow, data real d_upper, data real L, data real D, int primary_id, array[] real primary_params)
real primarycensored_lpmf(data int d, int dist_id, array[] real params, data real pwindow, data real d_upper, data real L, data real D, int primary_id, array[] real primary_params)
real primarycensored_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 primarycensored_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)
vector primarycensored_sone_pmf_vectorized(int max_delay, data real L, data real D, int dist_id, array[] real params, data real pwindow, int primary_id, array[] real primary_params)
vector primarycensored_sone_lpmf_vectorized(int max_delay, data real L, data real D, int dist_id, array[] real params, data real pwindow, int primary_id, array[] real primary_params)
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_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 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, int dist_id, array[] real params, data real pwindow, int primary_id, array[] real primary_params)