|
a |
|
b/src/priors.cpp |
|
|
1 |
#include <Rcpp.h> |
|
|
2 |
#include <Rmath.h> |
|
|
3 |
#include "internals.h" |
|
|
4 |
|
|
|
5 |
|
|
|
6 |
// ON WHEN THESE ARE USED |
|
|
7 |
|
|
|
8 |
// These functions implement various default priors. The alternative to these |
|
|
9 |
// defaults is using user-specified closures, which only take one parameter |
|
|
10 |
// 'param', and have prior parameters enclosed or hard-coded. If user-specified |
|
|
11 |
// functions are using C/C++ code, we strongly recommend using the native R API |
|
|
12 |
// to distribution functions. For a list of available distributions, see: |
|
|
13 |
// https://cran.r-project.org/doc/manuals/r-release/R-exts.html#Distribution-functions |
|
|
14 |
|
|
|
15 |
|
|
|
16 |
|
|
|
17 |
|
|
|
18 |
// ON THE USE OF CLOSURES |
|
|
19 |
|
|
|
20 |
// User-specified prior functions are R closures which contain the prior |
|
|
21 |
// parameters, so that the evaluation of the prior is simple and takes a single |
|
|
22 |
// argument 'param'. On the C++ side, using closures would add unwanted |
|
|
23 |
// complexity to the code. Besides, closures would have to be created within the |
|
|
24 |
// movement functions, i.e. every time they are called. Therefore, the C++ |
|
|
25 |
// priors used by default are not closures, and take three arguments: |
|
|
26 |
|
|
|
27 |
// - param: a Rcpp:List containing parameters |
|
|
28 |
|
|
|
29 |
// - config: a Rcpp:List containing parameters for the priors in |
|
|
30 |
// config["prior_xxx"] where 'xxx' is the name of the relevant parameter |
|
|
31 |
|
|
|
32 |
// - custom_function: an optional custom prior function (closure); if NULL |
|
|
33 |
// (i.e. R_NilValue in C++) then the basic functions are used |
|
|
34 |
|
|
|
35 |
|
|
|
36 |
// The prior for the mutation rate 'mu' is an exponential distribution |
|
|
37 |
|
|
|
38 |
// [[Rcpp::export(rng = false)]] |
|
|
39 |
double cpp_prior_mu(Rcpp::List param, Rcpp::List config, |
|
|
40 |
Rcpp::RObject custom_function = R_NilValue) { |
|
|
41 |
|
|
|
42 |
if (custom_function == R_NilValue) { |
|
|
43 |
// note: R::dexp is parametrised by scale, not rate |
|
|
44 |
double scale = 1.0 / Rcpp::as<double>(config["prior_mu"]); |
|
|
45 |
|
|
|
46 |
return R::dexp(Rcpp::as<double>(param["mu"]), scale, true); |
|
|
47 |
} else { |
|
|
48 |
Rcpp::Function f = Rcpp::as<Rcpp::Function>(custom_function); |
|
|
49 |
|
|
|
50 |
return Rcpp::as<double>(f(param)); |
|
|
51 |
} |
|
|
52 |
|
|
|
53 |
} |
|
|
54 |
|
|
|
55 |
|
|
|
56 |
|
|
|
57 |
|
|
|
58 |
|
|
|
59 |
|
|
|
60 |
// The prior for the reporting probability 'pi' is a beta distribution |
|
|
61 |
|
|
|
62 |
// [[Rcpp::export(rng = false)]] |
|
|
63 |
double cpp_prior_pi(Rcpp::List param, Rcpp::List config, |
|
|
64 |
Rcpp::RObject custom_function = R_NilValue) { |
|
|
65 |
|
|
|
66 |
if (custom_function == R_NilValue) { |
|
|
67 |
Rcpp::NumericVector shape = config["prior_pi"]; |
|
|
68 |
|
|
|
69 |
return R::dbeta(Rcpp::as<double>(param["pi"]), |
|
|
70 |
(double) shape[0], |
|
|
71 |
(double) shape[1], |
|
|
72 |
true); |
|
|
73 |
} else { |
|
|
74 |
Rcpp::Function f = Rcpp::as<Rcpp::Function>(custom_function); |
|
|
75 |
|
|
|
76 |
return Rcpp::as<double>(f(param)); |
|
|
77 |
} |
|
|
78 |
|
|
|
79 |
} |
|
|
80 |
|
|
|
81 |
|
|
|
82 |
|
|
|
83 |
|
|
|
84 |
|
|
|
85 |
|
|
|
86 |
// The prior for the contact reporting coverage 'eps' is a beta distribution |
|
|
87 |
|
|
|
88 |
// [[Rcpp::export(rng = false)]] |
|
|
89 |
double cpp_prior_eps(Rcpp::List param, Rcpp::List config, |
|
|
90 |
Rcpp::RObject custom_function = R_NilValue) { |
|
|
91 |
|
|
|
92 |
if (custom_function == R_NilValue) { |
|
|
93 |
Rcpp::NumericVector shape = config["prior_eps"]; |
|
|
94 |
|
|
|
95 |
return R::dbeta(Rcpp::as<double>(param["eps"]), |
|
|
96 |
(double) shape[0], |
|
|
97 |
(double) shape[1], |
|
|
98 |
true); |
|
|
99 |
} else { |
|
|
100 |
Rcpp::Function f = Rcpp::as<Rcpp::Function>(custom_function); |
|
|
101 |
|
|
|
102 |
return Rcpp::as<double>(f(param)); |
|
|
103 |
} |
|
|
104 |
|
|
|
105 |
} |
|
|
106 |
|
|
|
107 |
|
|
|
108 |
|
|
|
109 |
|
|
|
110 |
|
|
|
111 |
|
|
|
112 |
// The prior for the non-transmision contact rate 'lambda' is a beta distribution |
|
|
113 |
|
|
|
114 |
// [[Rcpp::export(rng = false)]] |
|
|
115 |
double cpp_prior_lambda(Rcpp::List param, Rcpp::List config, |
|
|
116 |
Rcpp::RObject custom_function = R_NilValue) { |
|
|
117 |
|
|
|
118 |
if (custom_function == R_NilValue) { |
|
|
119 |
Rcpp::NumericVector shape = config["prior_lambda"]; |
|
|
120 |
|
|
|
121 |
return R::dbeta(Rcpp::as<double>(param["lambda"]), |
|
|
122 |
(double) shape[0], |
|
|
123 |
(double) shape[1], |
|
|
124 |
true); |
|
|
125 |
} else { |
|
|
126 |
Rcpp::Function f = Rcpp::as<Rcpp::Function>(custom_function); |
|
|
127 |
|
|
|
128 |
return Rcpp::as<double>(f(param)); |
|
|
129 |
} |
|
|
130 |
|
|
|
131 |
} |
|
|
132 |
|
|
|
133 |
|
|
|
134 |
|
|
|
135 |
|
|
|
136 |
|
|
|
137 |
|
|
|
138 |
// [[Rcpp::export(rng = false)]] |
|
|
139 |
double cpp_prior_all(Rcpp::List param, Rcpp::List config, |
|
|
140 |
Rcpp::RObject custom_functions = R_NilValue |
|
|
141 |
) { |
|
|
142 |
if (custom_functions == R_NilValue) { |
|
|
143 |
|
|
|
144 |
return cpp_prior_mu(param, config) + |
|
|
145 |
cpp_prior_pi(param, config) + |
|
|
146 |
cpp_prior_eps(param, config) + |
|
|
147 |
cpp_prior_lambda(param, config); |
|
|
148 |
|
|
|
149 |
} else { |
|
|
150 |
|
|
|
151 |
Rcpp::List list_functions = Rcpp::as<Rcpp::List>(custom_functions); |
|
|
152 |
|
|
|
153 |
return cpp_prior_mu(param, config, list_functions["mu"]) + |
|
|
154 |
cpp_prior_pi(param, config, list_functions["pi"]) + |
|
|
155 |
cpp_prior_eps(param, config, list_functions["eps"]) + |
|
|
156 |
cpp_prior_lambda(param, config, list_functions["lambda"]); |
|
|
157 |
} |
|
|
158 |
} |