primarycensored
Loading...
Searching...
No Matches
primarycensored_analytical_cdf.stan
Go to the documentation of this file.
1
10int check_for_analytical(int dist_id, int primary_id) {
11 if (dist_id == 2 && primary_id == 1) return 1; // Gamma delay with Uniform primary
12 if (dist_id == 1 && primary_id == 1) return 1; // Lognormal delay with Uniform primary
13 if (dist_id == 3 && primary_id == 1) return 1; // Weibull delay with Uniform primary
14 return 0; // No analytical solution for other combinations
15}
16
29real primarycensored_gamma_uniform_lcdf(data real d, real q, array[] real params, data real pwindow) {
30 real shape = params[1];
31 real rate = params[2];
32 real log_window = log(pwindow);
33 // log E where E = k * theta = shape / rate is the mean of the delay
34 real log_E = log(shape) - log(rate);
35
36 // F_T(d; k) and the recursion to F_T(d; k+1):
37 // P(k+1, y) = P(k, y) - y^k e^{-y} / Gamma(k+1), with y = rate * d
38 real log_F_T_d_k = gamma_lcdf(d | shape, rate);
39 real gamma_kp1_pdf_log_d
40 = shape * log(rate * d) - rate * d - lgamma(shape + 1);
41 real log_F_T_d_kp1 = log_diff_exp(log_F_T_d_k, gamma_kp1_pdf_log_d);
42
43 // q-dependent terms. Final algebra is unified; only a guard to avoid
44 // log_diff_exp(-inf, -inf) and log(0) when q == 0 (q is data, so autodiff
45 // is unaffected by this branch).
46 real log_q_F_T_q; // log(q * F_T(q; k))
47 real log_E_tF_T_q; // log(E * F_T(q; k+1))
48 if (q > 0) {
49 real log_F_T_q_k = gamma_lcdf(q | shape, rate);
50 real gamma_kp1_pdf_log_q
51 = shape * log(rate * q) - rate * q - lgamma(shape + 1);
52 real log_F_T_q_kp1 = log_diff_exp(log_F_T_q_k, gamma_kp1_pdf_log_q);
53 log_q_F_T_q = log(q) + log_F_T_q_k;
54 log_E_tF_T_q = log_E + log_F_T_q_kp1;
55 } else {
56 log_q_F_T_q = negative_infinity();
57 log_E_tF_T_q = negative_infinity();
58 }
59
60 // Unified form: F_{S+}(d) = (A - B) / w_P with A, B sums of positives:
61 // A = d * F_T(d; k) + E * F_T(q; k+1)
62 // B = q * F_T(q; k) + E * F_T(d; k+1)
63 // Ordering A >= B is guaranteed by F_{S+}(d) >= 0.
64 real log_A = log_sum_exp(log(d) + log_F_T_d_k, log_E_tF_T_q);
65 real log_B = log_sum_exp(log_q_F_T_q, log_E + log_F_T_d_kp1);
66
67 return log_diff_exp(log_A, log_B) - log_window;
68}
69
82real primarycensored_lognormal_uniform_lcdf(data real d, real q, array[] real params, data real pwindow) {
83 real mu = params[1];
84 real sigma = params[2];
85 real mu_sigma2 = mu + square(sigma);
86 real log_window = log(pwindow);
87 // log E where E = exp(mu + sigma^2/2) is the mean of the delay
88 real log_E = mu + 0.5 * square(sigma);
89
90 real log_F_T_d = lognormal_lcdf(d | mu, sigma);
91 real log_tF_T_d = lognormal_lcdf(d | mu_sigma2, sigma);
92
93 // q-dependent terms (guard only to avoid log(0); final algebra is unified).
94 real log_q_F_T_q; // log(q * F_T(q))
95 real log_E_tF_T_q; // log(E * tilde F_T(q))
96 if (q > 0) {
97 real log_F_T_q = lognormal_lcdf(q | mu, sigma);
98 real log_tF_T_q = lognormal_lcdf(q | mu_sigma2, sigma);
99 log_q_F_T_q = log(q) + log_F_T_q;
100 log_E_tF_T_q = log_E + log_tF_T_q;
101 } else {
102 log_q_F_T_q = negative_infinity();
103 log_E_tF_T_q = negative_infinity();
104 }
105
106 // Unified form: F_{S+}(d) = (A - B) / w_P with
107 // A = d * F_T(d) + E * tilde F_T(q)
108 // B = q * F_T(q) + E * tilde F_T(d)
109 // Ordering A >= B is guaranteed by F_{S+}(d) >= 0.
110 real log_A = log_sum_exp(log(d) + log_F_T_d, log_E_tF_T_q);
111 real log_B = log_sum_exp(log_q_F_T_q, log_E + log_tF_T_d);
112
113 return log_diff_exp(log_A, log_B) - log_window;
114}
115
130real log_weibull_g(real t, real shape, real scale) {
131 real x = pow(t * inv(scale), shape);
132 real a = 1 + inv(shape);
133 return log(gamma_p(a, x)) + lgamma(a);
134}
135
148real primarycensored_weibull_uniform_lcdf(data real d, real q, array[] real params, data real pwindow) {
149 real shape = params[1];
150 real scale = params[2];
151 real log_window = log(pwindow);
152 real log_scale = log(scale);
153
154 // For Weibull: E = scale (lambda) and tilde F_T(t) = g(t; lambda, k), so
155 // log(E * tilde F_T(t)) = log(scale) + log_weibull_g(t, shape, scale).
156 real log_F_T_d = weibull_lcdf(d | shape, scale);
157 real log_E_tF_T_d = log_scale + log_weibull_g(d, shape, scale);
158
159 // q-dependent terms (guard only to avoid log(0); final algebra is unified).
160 real log_q_F_T_q; // log(q * F_T(q))
161 real log_E_tF_T_q; // log(E * tilde F_T(q)) = log(scale * g(q; lambda, k))
162 if (q > 0) {
163 log_q_F_T_q = log(q) + weibull_lcdf(q | shape, scale);
164 log_E_tF_T_q = log_scale + log_weibull_g(q, shape, scale);
165 } else {
166 log_q_F_T_q = negative_infinity();
167 log_E_tF_T_q = negative_infinity();
168 }
169
170 // Unified form: F_{S+}(d) = (A - B) / w_P with
171 // A = d * F_T(d) + scale * g(q; lambda, k)
172 // B = q * F_T(q) + scale * g(d; lambda, k)
173 // Ordering A >= B is guaranteed by F_{S+}(d) >= 0.
174 real log_A = log_sum_exp(log(d) + log_F_T_d, log_E_tF_T_q);
175 real log_B = log_sum_exp(log_q_F_T_q, log_E_tF_T_d);
176
177 return log_diff_exp(log_A, log_B) - log_window;
178}
179
185real primarycensored_analytical_lcdf_raw(data real d, int dist_id,
186 array[] real params,
187 data real pwindow,
188 int primary_id) {
189 real q = max({d - pwindow, 0});
190
191 if (dist_id == 2 && primary_id == 1) {
192 return primarycensored_gamma_uniform_lcdf(d | q, params, pwindow);
193 } else if (dist_id == 1 && primary_id == 1) {
194 return primarycensored_lognormal_uniform_lcdf(d | q, params, pwindow);
195 } else if (dist_id == 3 && primary_id == 1) {
196 return primarycensored_weibull_uniform_lcdf(d | q, params, pwindow);
197 }
198 return negative_infinity();
199}
200
217real primarycensored_analytical_lcdf(data real d, int dist_id,
218 array[] real params,
219 data real pwindow, data real L,
220 data real D, int primary_id,
221 array[] real primary_params) {
222 if (d <= L) return negative_infinity();
223 if (d >= D) return 0;
224
226 d, dist_id, params, pwindow, primary_id
227 );
228
229 // Apply truncation normalization
230 if (!is_inf(D) || L > 0) {
231 vector[2] bounds = primarycensored_truncation_bounds(
232 L, D, dist_id, params, pwindow, primary_id, primary_params
233 );
234 real log_cdf_L = bounds[1];
235 real log_cdf_D = bounds[2];
236
237 real log_normalizer = primarycensored_log_normalizer(log_cdf_D, log_cdf_L, L);
238 result = primarycensored_apply_truncation(result, log_cdf_L, log_normalizer, L);
239 }
240
241 return result;
242}
243
260real primarycensored_analytical_cdf(data real d, int dist_id,
261 array[] real params,
262 data real pwindow, data real L,
263 data real D, int primary_id,
264 array[] real primary_params) {
265 return exp(primarycensored_analytical_lcdf(d | dist_id, params, pwindow, L, D, primary_id, primary_params));
266}
real log_weibull_g(real t, real shape, real scale)
int check_for_analytical(int dist_id, int primary_id)
real primarycensored_analytical_lcdf_raw(data real d, int dist_id, array[] real params, data real pwindow, int primary_id)
real primarycensored_weibull_uniform_lcdf(data real d, real q, array[] real params, data real pwindow)
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_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 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)