Skip to content

Commit 5b646c4

Browse files
apulsiphergvegayon
andauthored
Export LFMCMC (#27)
* Create LFMCMC.R and lfmcmc.cpp * Fix pre-commit style failures * Using tidyverse 4.4.0 as base dev image * Fix roxygenize typo in Makefile * Run 'make docs' and add cpp11, NAMESPACE, and roxygen files * Add config.log and config.status to gitignore * Run pre-commit on existing docs files * Add epiworld_double macro to Makevars * Add run method to LFMCMC * Add set_observed_data to LFMCMC * Add set_proposal_fun, set_simulation_fun, set_summary_fun, and set_kernel_fun * Document LFMCMC functions * Add basic example and try resolving generic run class warning * Run roxygen2 on LFMCMC * Rename LFMCMC run function to run_lfmcmc * Add epiworld_double macro to Makevars.win * Create likelihood-free0mcmc.Rmd * Add TODO tags to mark needed work * Add seed, set_param_nams_, set_stats_names, print to lfmcmc * Update documentation on LFMCMC * Document params for print.epiworld_lfmcmc * Setup function ordering for likelihood-free-mcmc.Rmd * Make lfmcmc vignette simpler to start * Add set_simulation_fun in lfmcmc vignette * Try vignette without piping * Add UseMethod export for base version of LFMCMC class methods * Clean up vignette to separate failing block * Add create_LFMCMCMSimFun_cpp() * Add lambda return type * Fix lambda param mismatch with LFMCMCMSimFun and set correctly in se_simulation_fun_cpp * Add factory methods for summary, proposal, kernel functions * Add set_rand_engine function and update constructor to extract rand_engine from model * Document param in updated LFMCMC constructor * Update LFMCMC example in .R file * Make lfmcmc constructor more readable * Add factory methods for norm_reflective proposal function and gaussian kernel function * Delete prop and kernel function defs after using factory methods * Add cinttypes to .vscode/settings.json * Minor tweaks to lfmcmc vignette simfun * Minor changes and adding valgrind to docker * Add simpler use proposal/kernel functions * Clean up create sum and create sim fun in lfmcmc.cpp * Remove 'create' lfmcmc methods to instead create the function within the 'set' methods and add temp test code * New version of epiworld * Getting closer * Updating epiworld * Sync with latest version of epiworld * Add dev option to Makefile to build and install without vignettes * Now is running * Changing param * Clean up Makefile * Clean up comments and unneed function * Clean up LFMCMC vignette * Remove second parameter in R version of simulation and summary functions * Restore seed_lfmcmc_cpp() * Cleaning up files * Sync with C++ epiworld library * Remove seed_lfmcmc * Add seed to run_lfmcmc * Update LFMCMC.R to match order of lfmcmc.cpp * Add comment blocks to lfmcmc.cpp to improve file navigation * Implement set_kernel_fun * Implement set_proposal_fun * Update comments in vignette * Sync with c++ library * Fill out fields for roxygen docs of LFMCMC * Create test-lfmcmc.R and populate with example from vignette * Sync with C++ epiworld library * Sync with c++ epiworld library * Update version number to match C++ library --------- Co-authored-by: George G. Vega Yon <[email protected]>
1 parent e2797fa commit 5b646c4

30 files changed

+1414
-98
lines changed

Diff for: .devcontainer/Dockerfile

+2
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,6 @@ RUN install2.r cpp11 roxygen2 tinytest data.table netplot \
1010

1111
RUN install2.r languageserver
1212

13+
RUN apt-get update && apt-get install --no-install-recommends -y valgrind gdb
14+
1315
CMD ["bash"]

Diff for: .gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,6 @@ src/Makevars
2020
images
2121
inst/doc
2222
docs
23+
24+
config.log
25+
config.status

Diff for: .vscode/settings.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@
5454
"stdexcept": "cpp",
5555
"streambuf": "cpp",
5656
"typeinfo": "cpp",
57-
"thread": "cpp"
57+
"thread": "cpp",
58+
"cinttypes": "cpp"
5859
},
5960
"editor.indentSize": "tabSize",
6061
"[r]": {

Diff for: DESCRIPTION

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Package: epiworldR
22
Type: Package
33
Title: Fast Agent-Based Epi Models
4-
Version: 0.3-2
4+
Version: 0.4-3
55
Authors@R: c(
66
person(given="George", family="Vega Yon", role=c("aut","cre"),
77
email="[email protected]", comment = c(ORCID = "0000-0002-3171-0844")),

Diff for: Makefile

+8-3
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,14 @@ clean:
4646
sed -i -E 's/^library\(epiworldRdev\)/library(epiworldR)/g' README.*
4747

4848
docs:
49-
Rscript --vanilla -e 'roxygen2::roxigenize()'
50-
51-
.PHONY: build update check clean docs docker-debug
49+
Rscript --vanilla -e 'roxygen2::roxygenize()'
5250

5351
checkv: build
5452
R CMD check --as-cran --use-valgrind epiworldR*.tar.gz
53+
54+
# Builds and installs without vignettes
55+
dev: clean
56+
R CMD build --no-build-vignettes .
57+
R CMD INSTALL epiworldR_$(VERSION).tar.gz
58+
59+
.PHONY: build update check clean docs docker-debug dev

Diff for: NAMESPACE

+20
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ S3method(print,epiworld_agents_tools)
6262
S3method(print,epiworld_entities)
6363
S3method(print,epiworld_entity)
6464
S3method(print,epiworld_globalevent)
65+
S3method(print,epiworld_lfmcmc)
6566
S3method(print,epiworld_model)
6667
S3method(print,epiworld_saver)
6768
S3method(print,epiworld_tool)
@@ -73,13 +74,22 @@ S3method(queuing_on,epiworld_model)
7374
S3method(queuing_on,epiworld_seirconn)
7475
S3method(queuing_on,epiworld_sirconn)
7576
S3method(run,epiworld_model)
77+
S3method(run_lfmcmc,epiworld_lfmcmc)
7678
S3method(run_multiple,epiworld_model)
79+
S3method(set_kernel_fun,epiworld_lfmcmc)
7780
S3method(set_name,epiworld_model)
81+
S3method(set_observed_data,epiworld_lfmcmc)
82+
S3method(set_par_names,epiworld_lfmcmc)
7883
S3method(set_param,epiworld_model)
84+
S3method(set_proposal_fun,epiworld_lfmcmc)
85+
S3method(set_simulation_fun,epiworld_lfmcmc)
86+
S3method(set_stats_names,epiworld_lfmcmc)
87+
S3method(set_summary_fun,epiworld_lfmcmc)
7988
S3method(size,epiworld_model)
8089
S3method(summary,epiworld_model)
8190
S3method(verbose_off,epiworld_model)
8291
S3method(verbose_on,epiworld_model)
92+
export(LFMCMC)
8393
export(ModelDiffNet)
8494
export(ModelSEIR)
8595
export(ModelSEIRCONN)
@@ -167,6 +177,7 @@ export(rm_entity)
167177
export(rm_tool)
168178
export(rm_virus)
169179
export(run)
180+
export(run_lfmcmc)
170181
export(run_multiple)
171182
export(run_multiple_get_results)
172183
export(set_agents_data)
@@ -179,9 +190,12 @@ export(set_distribution_virus)
179190
export(set_incubation)
180191
export(set_incubation_fun)
181192
export(set_incubation_ptr)
193+
export(set_kernel_fun)
182194
export(set_name)
183195
export(set_name_tool)
184196
export(set_name_virus)
197+
export(set_observed_data)
198+
export(set_par_names)
185199
export(set_param)
186200
export(set_prob_death)
187201
export(set_prob_death_fun)
@@ -192,9 +206,13 @@ export(set_prob_infecting_ptr)
192206
export(set_prob_recovery)
193207
export(set_prob_recovery_fun)
194208
export(set_prob_recovery_ptr)
209+
export(set_proposal_fun)
195210
export(set_recovery_enhancer)
196211
export(set_recovery_enhancer_fun)
197212
export(set_recovery_enhancer_ptr)
213+
export(set_simulation_fun)
214+
export(set_stats_names)
215+
export(set_summary_fun)
198216
export(set_susceptibility_reduction)
199217
export(set_susceptibility_reduction_fun)
200218
export(set_susceptibility_reduction_ptr)
@@ -204,6 +222,8 @@ export(set_transmission_reduction_ptr)
204222
export(size)
205223
export(tool)
206224
export(tool_fun_logit)
225+
export(use_kernel_fun_gaussian)
226+
export(use_proposal_norm_reflective)
207227
export(verbose_off)
208228
export(verbose_on)
209229
export(virus)

Diff for: R/LFMCMC.R

+216
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
#' Likelihood-Free Markhov Chain Monte Carlo (LFMCMC)
2+
#'
3+
#'
4+
#' @aliases epiworld_lfmcmc
5+
#' @details
6+
#' Performs a Likelihood-Free Markhov Chain Monte Carlo simulation
7+
#' @param model A model of class [epiworld_model]
8+
#' @returns
9+
#' The `LFMCMC` function returns a model of class [epiworld_lfmcmc].
10+
#' @examples
11+
#' ## Setup an SIR model to use in the simulation
12+
#' model_seed <- 122
13+
#' model_sir <- ModelSIR(name = "COVID-19", prevalence = .1,
14+
#' transmission_rate = .9, recovery_rate = .3)
15+
#' agents_smallworld(
16+
#' model_sir,
17+
#' n = 1000,
18+
#' k = 5,
19+
#' d = FALSE,
20+
#' p = 0.01
21+
#' )
22+
#' verbose_off(model_sir)
23+
#' run(model_sir, ndays = 50, seed = model_seed)
24+
#'
25+
#' ## Setup LFMCMC
26+
#' # Extract the observed data from the model
27+
#' obs_data <- unname(as.integer(get_today_total(model_sir)))
28+
#'
29+
#' # Define the simulation function
30+
#' simfun <- function(params) {
31+
#' set_param(model_sir, "Recovery rate", params[1])
32+
#' set_param(model_sir, "Transmission rate", params[2])
33+
#' run(model_sir, ndays = 50)
34+
#' res <- unname(as.integer(get_today_total(model_sir)))
35+
#' return(res)
36+
#' }
37+
#'
38+
#' # Define the summary function
39+
#' sumfun <- function(dat) {
40+
#' return(dat)
41+
#' }
42+
#'
43+
#' # Create the LFMCMC model
44+
#' lfmcmc_model <- LFMCMC(model_sir) |>
45+
#' set_simulation_fun(simfun) |>
46+
#' set_summary_fun(sumfun) |>
47+
#' use_proposal_norm_reflective() |>
48+
#' use_kernel_fun_gaussian() |>
49+
#' set_observed_data(obs_data)
50+
#'
51+
#' ## Run LFMCMC simulation
52+
#' # Set initial parameters
53+
#' par0 <- as.double(c(0.1, 0.5))
54+
#' n_samp <- 2000
55+
#' epsil <- as.double(1.0)
56+
#'
57+
#' # Run the LFMCMC simulation
58+
#' run_lfmcmc(
59+
#' lfmcmc = lfmcmc_model,
60+
#' params_init_ = par0,
61+
#' n_samples_ = n_samp,
62+
#' epsilon_ = epsil,
63+
#' seed = model_seed
64+
#' )
65+
#'
66+
#' # Print the results
67+
#' set_stats_names(lfmcmc_model, get_states(model_sir))
68+
#' set_par_names(lfmcmc_model, c("Immune recovery", "Infectiousness"))
69+
#'
70+
#' print(lfmcmc_model)
71+
#' @export
72+
LFMCMC <- function(model) {
73+
if (!inherits(model, "epiworld_model"))
74+
stop("model should be of class 'epiworld_model'. It is of class ", class(model))
75+
76+
structure(
77+
LFMCMC_cpp(model),
78+
class = c("epiworld_lfmcmc")
79+
)
80+
}
81+
82+
#' @rdname LFMCMC
83+
#' @param lfmcmc LFMCMC model
84+
#' @param params_init_ Initial model parameters
85+
#' @param n_samples_ Number of samples
86+
#' @param epsilon_ Epsilon parameter
87+
#' @param seed Random engine seed
88+
#' @returns The simulated model of class [epiworld_lfmcmc].
89+
#' @export
90+
run_lfmcmc <- function(lfmcmc, params_init_, n_samples_, epsilon_, seed = NULL) UseMethod("run_lfmcmc")
91+
92+
#' @export
93+
run_lfmcmc.epiworld_lfmcmc <- function(lfmcmc, params_init_, n_samples_, epsilon_, seed = NULL) {
94+
if (length(seed)) set.seed(seed)
95+
run_lfmcmc_cpp(lfmcmc, params_init_, n_samples_, epsilon_, sample.int(1e4, 1))
96+
invisible(lfmcmc)
97+
}
98+
99+
#' @rdname LFMCMC
100+
#' @param lfmcmc LFMCMC model
101+
#' @param observed_data_ Observed data
102+
#' @returns The lfmcmc model with the observed data added
103+
#' @export
104+
set_observed_data <- function(lfmcmc, observed_data_) UseMethod("set_observed_data")
105+
106+
#' @export
107+
set_observed_data.epiworld_lfmcmc <- function(lfmcmc, observed_data_) {
108+
set_observed_data_cpp(lfmcmc, observed_data_)
109+
invisible(lfmcmc)
110+
}
111+
112+
#' @rdname LFMCMC
113+
#' @param lfmcmc LFMCMC model
114+
#' @param fun The LFMCMC proposal function
115+
#' @returns The lfmcmc model with the proposal function added
116+
#' @export
117+
set_proposal_fun <- function(lfmcmc, fun) UseMethod("set_proposal_fun")
118+
119+
#' @export
120+
set_proposal_fun.epiworld_lfmcmc <- function(lfmcmc, fun) {
121+
set_proposal_fun_cpp(lfmcmc, fun)
122+
invisible(lfmcmc)
123+
}
124+
125+
#' @rdname LFMCMC
126+
#' @param lfmcmc The LFMCMC model
127+
#' @returns The LFMCMC model with proposal function set to norm reflective
128+
#' @export
129+
use_proposal_norm_reflective <- function(lfmcmc) {
130+
use_proposal_norm_reflective_cpp(lfmcmc)
131+
invisible(lfmcmc)
132+
}
133+
134+
#' @rdname LFMCMC
135+
#' @param lfmcmc LFMCMC model
136+
#' @param fun The LFMCMC simulation function
137+
#' @returns The lfmcmc model with the simulation function added
138+
#' @export
139+
set_simulation_fun <- function(lfmcmc, fun) UseMethod("set_simulation_fun")
140+
141+
#' @export
142+
set_simulation_fun.epiworld_lfmcmc <- function(lfmcmc, fun) {
143+
set_simulation_fun_cpp(lfmcmc, fun)
144+
invisible(lfmcmc)
145+
}
146+
147+
#' @rdname LFMCMC
148+
#' @param lfmcmc LFMCMC model
149+
#' @param fun The LFMCMC sumamry function
150+
#' @returns The lfmcmc model with the summary function added
151+
#' @export
152+
set_summary_fun <- function(lfmcmc, fun) UseMethod("set_summary_fun")
153+
154+
#' @export
155+
set_summary_fun.epiworld_lfmcmc <- function(lfmcmc, fun) {
156+
set_summary_fun_cpp(lfmcmc, fun)
157+
invisible(lfmcmc)
158+
}
159+
160+
#' @rdname LFMCMC
161+
#' @param lfmcmc LFMCMC model
162+
#' @param fun The LFMCMC kernel function
163+
#' @returns The lfmcmc model with the kernel function added
164+
#' @export
165+
set_kernel_fun <- function(lfmcmc, fun) UseMethod("set_kernel_fun")
166+
167+
#' @export
168+
set_kernel_fun.epiworld_lfmcmc <- function(lfmcmc, fun) {
169+
set_kernel_fun_cpp(lfmcmc, fun)
170+
invisible(lfmcmc)
171+
}
172+
173+
#' @rdname LFMCMC
174+
#' @param lfmcmc The LFMCMC model
175+
#' @returns The LFMCMC model with kernel function set to gaussian
176+
#' @export
177+
use_kernel_fun_gaussian <- function(lfmcmc) {
178+
use_kernel_fun_gaussian_cpp(lfmcmc)
179+
invisible(lfmcmc)
180+
}
181+
182+
#' @rdname LFMCMC
183+
#' @param lfmcmc LFMCMC model
184+
#' @param names The model parameter names
185+
#' @returns The lfmcmc model with the parameter names added
186+
#' @export
187+
set_par_names <- function(lfmcmc, names) UseMethod("set_par_names")
188+
189+
#' @export
190+
set_par_names.epiworld_lfmcmc <- function(lfmcmc, names) {
191+
set_par_names_cpp(lfmcmc, names)
192+
invisible(lfmcmc)
193+
}
194+
195+
#' @rdname LFMCMC
196+
#' @param lfmcmc LFMCMC model
197+
#' @param names The model stats names
198+
#' @returns The lfmcmc model with the stats names added
199+
#' @export
200+
set_stats_names <- function(lfmcmc, names) UseMethod("set_stats_names")
201+
202+
#' @export
203+
set_stats_names.epiworld_lfmcmc <- function(lfmcmc, names) {
204+
set_stats_names_cpp(lfmcmc, names)
205+
invisible(lfmcmc)
206+
}
207+
208+
#' @rdname LFMCMC
209+
#' @param x LFMCMC model to print
210+
#' @param ... Ignored
211+
#' @returns The lfmcmc model
212+
#' @export
213+
print.epiworld_lfmcmc <- function(x, ...) {
214+
print_lfmcmc_cpp(x)
215+
invisible(x)
216+
}

Diff for: R/cpp11.R

+48
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,54 @@ ModelSEIRMixing_cpp <- function(name, n, prevalence, contact_rate, transmission_
220220
.Call(`_epiworldR_ModelSEIRMixing_cpp`, name, n, prevalence, contact_rate, transmission_rate, incubation_days, recovery_rate, contact_matrix)
221221
}
222222

223+
LFMCMC_cpp <- function(model) {
224+
.Call(`_epiworldR_LFMCMC_cpp`, model)
225+
}
226+
227+
run_lfmcmc_cpp <- function(lfmcmc, params_init_, n_samples_, epsilon_, seed) {
228+
.Call(`_epiworldR_run_lfmcmc_cpp`, lfmcmc, params_init_, n_samples_, epsilon_, seed)
229+
}
230+
231+
set_observed_data_cpp <- function(lfmcmc, observed_data_) {
232+
.Call(`_epiworldR_set_observed_data_cpp`, lfmcmc, observed_data_)
233+
}
234+
235+
set_proposal_fun_cpp <- function(lfmcmc, fun) {
236+
.Call(`_epiworldR_set_proposal_fun_cpp`, lfmcmc, fun)
237+
}
238+
239+
use_proposal_norm_reflective_cpp <- function(lfmcmc) {
240+
.Call(`_epiworldR_use_proposal_norm_reflective_cpp`, lfmcmc)
241+
}
242+
243+
set_simulation_fun_cpp <- function(lfmcmc, fun) {
244+
.Call(`_epiworldR_set_simulation_fun_cpp`, lfmcmc, fun)
245+
}
246+
247+
set_summary_fun_cpp <- function(lfmcmc, fun) {
248+
.Call(`_epiworldR_set_summary_fun_cpp`, lfmcmc, fun)
249+
}
250+
251+
set_kernel_fun_cpp <- function(lfmcmc, fun) {
252+
.Call(`_epiworldR_set_kernel_fun_cpp`, lfmcmc, fun)
253+
}
254+
255+
use_kernel_fun_gaussian_cpp <- function(lfmcmc) {
256+
.Call(`_epiworldR_use_kernel_fun_gaussian_cpp`, lfmcmc)
257+
}
258+
259+
set_par_names_cpp <- function(lfmcmc, names) {
260+
.Call(`_epiworldR_set_par_names_cpp`, lfmcmc, names)
261+
}
262+
263+
set_stats_names_cpp <- function(lfmcmc, names) {
264+
.Call(`_epiworldR_set_stats_names_cpp`, lfmcmc, names)
265+
}
266+
267+
print_lfmcmc_cpp <- function(lfmcmc) {
268+
.Call(`_epiworldR_print_lfmcmc_cpp`, lfmcmc)
269+
}
270+
223271
print_cpp <- function(m, lite) {
224272
.Call(`_epiworldR_print_cpp`, m, lite)
225273
}

0 commit comments

Comments
 (0)