diff --git a/NAMESPACE b/NAMESPACE index 6b4bd81..85ad16a 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -83,7 +83,9 @@ S3method(set_param,epiworld_model) S3method(size,epiworld_model) S3method(summary,epiworld_model) S3method(today,epiworld_model) +S3method(verbose_off,epiworld_lfmcmc) S3method(verbose_off,epiworld_model) +S3method(verbose_on,epiworld_lfmcmc) S3method(verbose_on,epiworld_model) export(LFMCMC) export(ModelDiffNet) diff --git a/R/LFMCMC.R b/R/LFMCMC.R index d048a27..156071e 100644 --- a/R/LFMCMC.R +++ b/R/LFMCMC.R @@ -67,6 +67,7 @@ stopifnot_lfmcmc <- function(x) { #' epsil <- 1.0 #' #' # Run the LFMCMC simulation +#' verbose_off(lfmcmc_model) #' run_lfmcmc( #' lfmcmc = lfmcmc_model, #' params_init_ = par0, @@ -382,3 +383,22 @@ get_n_samples <- function(lfmcmc) { get_n_samples_cpp(lfmcmc) } + +#' @rdname LFMCMC +#' @export +#' @returns +#' - The `verbose_on` and `verbose_off` functions return the same model, however +#' `verbose_off` returns the model with no progress bar. +#' @details +#' The `verbose_on` and `verbose_off` functions activate and deactivate printing +#' progress on screen, respectively. Both functions return the model (`x`) invisibly. + +#' @export +verbose_off.epiworld_lfmcmc <- function(x) { + invisible(verbose_off_lfmcmc_cpp(x)) +} + +#' @export +verbose_on.epiworld_lfmcmc <- function(x) { + invisible(verbose_on_lfmcmc_cpp(x)) +} diff --git a/R/cpp11.R b/R/cpp11.R index 6690f71..ad8f431 100644 --- a/R/cpp11.R +++ b/R/cpp11.R @@ -300,6 +300,14 @@ get_n_params_cpp <- function(lfmcmc) { .Call(`_epiworldR_get_n_params_cpp`, lfmcmc) } +verbose_off_lfmcmc_cpp <- function(lfmcmc) { + .Call(`_epiworldR_verbose_off_lfmcmc_cpp`, lfmcmc) +} + +verbose_on_lfmcmc_cpp <- function(lfmcmc) { + .Call(`_epiworldR_verbose_on_lfmcmc_cpp`, lfmcmc) +} + print_cpp <- function(m, lite) { .Call(`_epiworldR_print_cpp`, m, lite) } diff --git a/inst/include/epiworld/math/lfmcmc/lfmcmc-bones.hpp b/inst/include/epiworld/math/lfmcmc/lfmcmc-bones.hpp index 4ec81cc..ace7b63 100755 --- a/inst/include/epiworld/math/lfmcmc/lfmcmc-bones.hpp +++ b/inst/include/epiworld/math/lfmcmc/lfmcmc-bones.hpp @@ -170,6 +170,7 @@ class LFMCMC { std::chrono::time_point m_start_time; std::chrono::time_point m_end_time; + // Timing // std::chrono::milliseconds std::chrono::duration m_elapsed_time = std::chrono::duration::zero(); @@ -183,6 +184,10 @@ class LFMCMC { void chrono_start(); void chrono_end(); + + // Progress + bool verbose = true; + Progress progress_bar; public: @@ -254,6 +259,8 @@ class LFMCMC { std::vector< epiworld_double > get_mean_stats(); // Printing + LFMCMC & verbose_off(); + LFMCMC & verbose_on(); void print(size_t burnin = 0u) const; }; diff --git a/inst/include/epiworld/math/lfmcmc/lfmcmc-meat.hpp b/inst/include/epiworld/math/lfmcmc/lfmcmc-meat.hpp index a44b6f0..c4f68f4 100755 --- a/inst/include/epiworld/math/lfmcmc/lfmcmc-meat.hpp +++ b/inst/include/epiworld/math/lfmcmc/lfmcmc-meat.hpp @@ -263,6 +263,13 @@ inline void LFMCMC::run( for (size_t k = 0u; k < m_n_params; ++k) m_accepted_params[k] = m_initial_params[k]; + // Init progress bar + progress_bar = Progress(m_n_samples, 80); + if (verbose) { + progress_bar.next(); + } + + // Run LFMCMC for (size_t i = 1u; i < m_n_samples; ++i) { // Step 1: Generate a proposal and store it in m_current_params @@ -319,6 +326,9 @@ inline void LFMCMC::run( for (size_t k = 0u; k < m_n_params; ++k) m_accepted_params[i * m_n_params + k] = m_previous_params[k]; + if (verbose) { + progress_bar.next(); + } } // End timing @@ -544,4 +554,18 @@ inline std::vector< epiworld_double > LFMCMC::get_mean_stats() } +template +inline LFMCMC & LFMCMC::verbose_off() +{ + verbose = false; + return *this; +} + +template +inline LFMCMC & LFMCMC::verbose_on() +{ + verbose = true; + return *this; +} + #endif \ No newline at end of file diff --git a/inst/tinytest/test-lfmcmc.R b/inst/tinytest/test-lfmcmc.R index ccba27e..38c214c 100644 --- a/inst/tinytest/test-lfmcmc.R +++ b/inst/tinytest/test-lfmcmc.R @@ -60,6 +60,7 @@ par0 <- c(0.1, 0.5) n_samp <- 2000 epsil <- 1.0 +expect_silent(verbose_off(lfmcmc_model)) expect_silent(run_lfmcmc( lfmcmc = lfmcmc_model, params_init_ = par0, @@ -79,6 +80,17 @@ expect_error(print(lfmcmc_model, burnin = n_samp + 50), "burnin is greater than expect_error(print(lfmcmc_model, burnin = -n_samp / 2), "argument must be a non-negative integer") expect_error(print(lfmcmc_model, burnin = "n_samp"), "argument must be an integer") +# Check verbose_on ------------------------------------------------------------- +expect_silent(verbose_on(lfmcmc_model)) +expect_stdout(run_lfmcmc( + lfmcmc = lfmcmc_model, + params_init_ = par0, + n_samples_ = n_samp, + epsilon_ = epsil, + seed = model_seed +)) +verbose_off(lfmcmc_model) + # Check LFMCMC getters --------------------------------------------------------- expect_equal(get_n_samples(lfmcmc_model), n_samp) @@ -196,6 +208,7 @@ lfmcmc_model <- LFMCMC() |> set_observed_data(Y) # Run LFMCMC +verbose_off(lfmcmc_model) x <- run_lfmcmc( lfmcmc = lfmcmc_model, params_init_ = c(0, 1), diff --git a/man/LFMCMC.Rd b/man/LFMCMC.Rd index b05c5aa..c03f34a 100644 --- a/man/LFMCMC.Rd +++ b/man/LFMCMC.Rd @@ -22,6 +22,7 @@ \alias{get_n_params} \alias{get_n_stats} \alias{get_n_samples} +\alias{verbose_off.epiworld_lfmcmc} \title{Likelihood-Free Markhov Chain Monte Carlo (LFMCMC)} \usage{ LFMCMC(model = NULL) @@ -63,6 +64,8 @@ get_n_params(lfmcmc) get_n_stats(lfmcmc) get_n_samples(lfmcmc) + +\method{verbose_off}{epiworld_lfmcmc}(x) } \arguments{ \item{model}{A model of class \link{epiworld_model} or \code{NULL} (see details).} @@ -142,6 +145,11 @@ samples and the number of columns equal to the number of statistics. return the number of parameters, statistics, and samples for the given LFMCMC model, respectively. } + +\itemize{ +\item The \code{verbose_on} and \code{verbose_off} functions return the same model, however +\code{verbose_off} returns the model with no progress bar. +} } \description{ Likelihood-Free Markhov Chain Monte Carlo (LFMCMC) @@ -151,6 +159,9 @@ Performs a Likelihood-Free Markhov Chain Monte Carlo simulation. When \code{model} is not \code{NULL}, the model uses the same random-number generator engine as the model. Otherwise, when \code{model} is \code{NULL}, a new random-number generator engine is created. + +The \code{verbose_on} and \code{verbose_off} functions activate and deactivate printing +progress on screen, respectively. Both functions return the model (\code{x}) invisibly. } \examples{ ## Setup an SIR model to use in the simulation @@ -200,6 +211,7 @@ n_samp <- 2000 epsil <- 1.0 # Run the LFMCMC simulation +verbose_off(lfmcmc_model) run_lfmcmc( lfmcmc = lfmcmc_model, params_init_ = par0, diff --git a/src/cpp11.cpp b/src/cpp11.cpp index 54130e9..71aa01b 100644 --- a/src/cpp11.cpp +++ b/src/cpp11.cpp @@ -530,6 +530,20 @@ extern "C" SEXP _epiworldR_get_n_params_cpp(SEXP lfmcmc) { return cpp11::as_sexp(get_n_params_cpp(cpp11::as_cpp>(lfmcmc))); END_CPP11 } +// lfmcmc.cpp +SEXP verbose_off_lfmcmc_cpp(SEXP lfmcmc); +extern "C" SEXP _epiworldR_verbose_off_lfmcmc_cpp(SEXP lfmcmc) { + BEGIN_CPP11 + return cpp11::as_sexp(verbose_off_lfmcmc_cpp(cpp11::as_cpp>(lfmcmc))); + END_CPP11 +} +// lfmcmc.cpp +SEXP verbose_on_lfmcmc_cpp(SEXP lfmcmc); +extern "C" SEXP _epiworldR_verbose_on_lfmcmc_cpp(SEXP lfmcmc) { + BEGIN_CPP11 + return cpp11::as_sexp(verbose_on_lfmcmc_cpp(cpp11::as_cpp>(lfmcmc))); + END_CPP11 +} // model.cpp SEXP print_cpp(SEXP m, bool lite); extern "C" SEXP _epiworldR_print_cpp(SEXP m, SEXP lite) { @@ -1212,7 +1226,9 @@ static const R_CallMethodDef CallEntries[] = { {"_epiworldR_use_kernel_fun_gaussian_cpp", (DL_FUNC) &_epiworldR_use_kernel_fun_gaussian_cpp, 1}, {"_epiworldR_use_proposal_norm_reflective_cpp", (DL_FUNC) &_epiworldR_use_proposal_norm_reflective_cpp, 1}, {"_epiworldR_verbose_off_cpp", (DL_FUNC) &_epiworldR_verbose_off_cpp, 1}, + {"_epiworldR_verbose_off_lfmcmc_cpp", (DL_FUNC) &_epiworldR_verbose_off_lfmcmc_cpp, 1}, {"_epiworldR_verbose_on_cpp", (DL_FUNC) &_epiworldR_verbose_on_cpp, 1}, + {"_epiworldR_verbose_on_lfmcmc_cpp", (DL_FUNC) &_epiworldR_verbose_on_lfmcmc_cpp, 1}, {"_epiworldR_virus_cpp", (DL_FUNC) &_epiworldR_virus_cpp, 8}, {"_epiworldR_virus_fun_logit_cpp", (DL_FUNC) &_epiworldR_virus_fun_logit_cpp, 3}, {"_epiworldR_virus_set_state_cpp", (DL_FUNC) &_epiworldR_virus_set_state_cpp, 4}, diff --git a/src/lfmcmc.cpp b/src/lfmcmc.cpp index 66286f3..d1dc170 100644 --- a/src/lfmcmc.cpp +++ b/src/lfmcmc.cpp @@ -305,4 +305,22 @@ int get_n_params_cpp(SEXP lfmcmc) { } +[[cpp11::register]] +SEXP verbose_off_lfmcmc_cpp(SEXP lfmcmc) { + + WrapLFMCMC(lfmcmc_ptr)(lfmcmc); + lfmcmc_ptr->verbose_off(); + return lfmcmc; + +} + +[[cpp11::register]] +SEXP verbose_on_lfmcmc_cpp(SEXP lfmcmc) { + + WrapLFMCMC(lfmcmc_ptr)(lfmcmc); + lfmcmc_ptr->verbose_on(); + return lfmcmc; + +} + #undef WrapLFMCMC diff --git a/vignettes/likelihood-free-mcmc.Rmd b/vignettes/likelihood-free-mcmc.Rmd index 19225c1..6ea74a9 100644 --- a/vignettes/likelihood-free-mcmc.Rmd +++ b/vignettes/likelihood-free-mcmc.Rmd @@ -108,6 +108,7 @@ n_samp <- 2000 epsil <- 1.0 # Run the LFMCMC simulation +verbose_off(lfmcmc_model) run_lfmcmc( lfmcmc = lfmcmc_model, params_init_ = par0,