{"id":18032595,"url":"https://github.com/kthohr/mcmc","last_synced_at":"2025-07-31T10:04:04.823Z","repository":{"id":81973045,"uuid":"100142889","full_name":"kthohr/mcmc","owner":"kthohr","description":"A C++ library of Markov Chain Monte Carlo (MCMC) methods","archived":false,"fork":false,"pushed_at":"2024-02-08T19:36:40.000Z","size":222,"stargazers_count":180,"open_issues_count":3,"forks_count":47,"subscribers_count":15,"default_branch":"master","last_synced_at":"2025-06-20T21:49:11.244Z","etag":null,"topics":["armadillo","automatic-differentiation","cpp","cpp11","de","differential-evolution","eigen","eigen3","hamiltonian-monte-carlo","hmc","langevin-diffusion","mala","markov-chain-monte-carlo","mcmc","metropolis-hastings","riemannian-manifold"],"latest_commit_sha":null,"homepage":"https://mcmclib.readthedocs.io/en/latest/","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kthohr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-08-12T23:32:25.000Z","updated_at":"2025-06-07T07:49:34.000Z","dependencies_parsed_at":"2023-03-12T14:25:37.325Z","dependency_job_id":"f52a74b0-8f46-462a-8bf8-c5cfd983c5ea","html_url":"https://github.com/kthohr/mcmc","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/kthohr/mcmc","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kthohr%2Fmcmc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kthohr%2Fmcmc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kthohr%2Fmcmc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kthohr%2Fmcmc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kthohr","download_url":"https://codeload.github.com/kthohr/mcmc/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kthohr%2Fmcmc/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268021915,"owners_count":24182763,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-31T02:00:08.723Z","response_time":66,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["armadillo","automatic-differentiation","cpp","cpp11","de","differential-evolution","eigen","eigen3","hamiltonian-monte-carlo","hmc","langevin-diffusion","mala","markov-chain-monte-carlo","mcmc","metropolis-hastings","riemannian-manifold"],"created_at":"2024-10-30T10:14:10.589Z","updated_at":"2025-07-31T10:04:04.735Z","avatar_url":"https://github.com/kthohr.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MCMCLib \u0026nbsp; [![Build Status](https://github.com/kthohr/mcmc/actions/workflows/main.yml/badge.svg)](https://github.com/kthohr/mcmc/actions/workflows/main.yml) [![Coverage Status](https://codecov.io/github/kthohr/mcmc/coverage.svg?branch=master)](https://codecov.io/github/kthohr/mcmc?branch=master) [![License](https://img.shields.io/badge/Licence-Apache%202.0-blue.svg)](./LICENSE) [![Documentation Status](https://readthedocs.org/projects/mcmclib/badge/?version=latest)](https://mcmclib.readthedocs.io/en/latest/?badge=latest)\n\nMCMCLib is a lightweight C++ library of Markov Chain Monte Carlo (MCMC) methods.\n\nFeatures:\n\n* A C++11/14/17 library of well-known MCMC algorithms.\n* Parallelized samplers designed for multi-modal distributions, including:\n    - Adaptive Equi-Energy Sampler (AEES)\n    - Differential Evolution (DE)\n* For fast and efficient matrix-based computation, MCMCLib supports the following templated linear algebra libraries:\n  * [Armadillo](http://arma.sourceforge.net/)\n  * [Eigen](http://eigen.tuxfamily.org/index.php) (version \u003e= 3.4.0)\n* Automatic differentiation functionality is available through use of the [Autodiff library](https://autodiff.github.io)\n* OpenMP-accelerated algorithms for parallel computation. \n* Straightforward linking with parallelized BLAS libraries, such as [OpenBLAS](https://github.com/xianyi/OpenBLAS).\n* Available as a single precision (``float``) or double precision (``double``) library.\n* Available as a header-only library, or as a compiled shared library.\n* Released under a permissive, non-GPL license.\n\n### Contents:\n* [Algorithms](#algorithms)\n* [Documentation](#documentation)\n* [General API](#api)\n* [Installation](#installation)\n* [R Compatibility](#r-compatibility)\n* [Examples](#examples)\n* [Automatic Differentiation](#automatic-differentiation)\n* [Author and License](#author)\n\n## Algorithms\n\nA list of currently available algorithms includes:\n\n* Adaptive Equi-Energy Sampler (AEES)\n* Differential Evolution (DE-MCMC)\n* Hamiltonian Monte Carlo (HMC)\n* Metropolis-adjusted Langevin algorithm (MALA)\n* No-U-Turn Sampler (NUTS)\n* Random Walk Metropolis-Hastings (RWMH)\n* Riemannian Manifold Hamiltonian Monte Carlo (RM-HMC)\n\n## Documentation\n\nFull documentation is available online:\n\n[![Documentation Status](https://readthedocs.org/projects/mcmclib/badge/?version=latest)](https://mcmclib.readthedocs.io/en/latest/?badge=latest)\n\nA PDF version of the documentation is available [here](https://buildmedia.readthedocs.org/media/pdf/mcmclib/latest/mcmclib.pdf).\n\n## API\n\nThe MCMCLib API follows a relatively simple convention, with most algorithms called in the following manner:\n```\nalgorithm_id(\u003cinitial values\u003e, \u003clog posterior kernel function of the target distribution\u003e, \u003cstorage for posterior draws\u003e, \u003cadditional data for the log posterior kernel function\u003e);\n```\nThe inputs, in order, are:\n* A vector of initial values used to define the starting point of the algorithm.\n* A user-specified function that returns the log posterior kernel value of the target distribution.\n* An array to store the posterior draws.\n* The final input is optional: it is any object that contains additional data necessary to evaluate the log posterior kernel function.\n\nFor example, the RWMH algorithm is called using:\n\n``` cpp\nbool rwmh(const ColVec_t\u0026 initial_vals, std::function\u003cfp_t (const ColVec_t\u0026 vals_inp, void* target_data)\u003e target_log_kernel, Mat_t\u0026 draws_out, void* target_data);\n```\n\nwhere ``ColVec_t`` is used to represent, e.g., ``arma::vec`` or ``Eigen::VectorXd`` types.\n\n## Installation\n\nMCMCLib is available as a compiled shared library, or as header-only library, for Unix-alike systems only (e.g., popular Linux-based distros, as well as macOS). Use of this library with Windows-based systems, with or without MSVC, **is not supported**.\n\n### Requirements\n\nMCMCLib requires either the Armadillo or Eigen C++ linear algebra libraries. (Note that Eigen version 3.4.0 requires a C++14-compatible compiler.)\n\nBefore including the header files, define **one** of the following:\n``` cpp\n#define MCMC_ENABLE_ARMA_WRAPPERS\n#define MCMC_ENABLE_EIGEN_WRAPPERS\n```\n\nExample:\n``` cpp\n#define MCMC_ENABLE_EIGEN_WRAPPERS\n#include \"mcmc.hpp\"\n```\n\n### Installation Method 1: Shared Library\n\nThe library can be installed on Unix-alike systems via the standard `./configure \u0026\u0026 make` method.\n\nFirst clone the library and any necessary submodules:\n\n``` bash\n# clone mcmc into the current directory\ngit clone https://github.com/kthohr/mcmc ./mcmc\n\n# change directory\ncd ./mcmc\n\n# clone necessary submodules\ngit submodule update --init\n```\n\nSet (one) of the following environment variables *before* running `configure`:\n\n``` bash\nexport ARMA_INCLUDE_PATH=/path/to/armadillo\nexport EIGEN_INCLUDE_PATH=/path/to/eigen\n```\n\nFinally:\n\n``` bash\n# build and install with Eigen\n./configure -i \"/usr/local\" -l eigen -p\nmake\nmake install\n```\n\nThe final command will install MCMCLib into `/usr/local`.\n\nConfiguration options (see `./configure -h`):\n\n\u0026nbsp; \u0026nbsp; \u0026nbsp; **Primary**\n* `-h` print help\n* `-i` installation path; default: the build directory\n* `-f` floating-point precision mode; default: `double`\n* `-l` specify the choice of linear algebra library; choose `arma` or `eigen`\n* `-m` specify the BLAS and Lapack libraries to link with; for example, `-m \"-lopenblas\"` or `-m \"-framework Accelerate\"`\n* `-o` compiler optimization options; defaults to `-O3 -march=native -ffp-contract=fast -flto -DARMA_NO_DEBUG`\n* `-p` enable OpenMP parallelization features (*recommended*)\n\n\u0026nbsp; \u0026nbsp; \u0026nbsp; **Secondary**\n* `-c` a coverage build (used with Codecov)\n* `-d` a 'development' build\n* `-g` a debugging build (optimization flags set to `-O0 -g`)\n\n\u0026nbsp; \u0026nbsp; \u0026nbsp; **Special**\n* `--header-only-version` generate a header-only version of MCMCLib (see [below](#installation-method-2-header-only-library))\n\u003c!-- * `-R` RcppArmadillo compatible build by setting the appropriate R library directories (R, Rcpp, and RcppArmadillo) --\u003e\n\n## Installation Method 2: Header-only Library\n\nMCMCLib is also available as a header-only library (i.e., without the need to compile a shared library). Simply run `configure` with the `--header-only-version` option:\n\n```bash\n./configure --header-only-version\n```\n\nThis will create a new directory, `header_only_version`, containing a copy of MCMCLib, modified to work on an inline basis. With this header-only version, simply include the header files (`#include \"mcmc.hpp`) and set the include path to the `head_only_version` directory (e.g.,`-I/path/to/mcmclib/header_only_version`).\n\n## R Compatibility\n\nTo use MCMCLib with an R package, first generate a header-only version of the library (see [above](#installation-method-2-header-only-library)). Then simply add a compiler definition before including the MCMCLib files.\n\n* For RcppArmadillo:\n```cpp\n#define MCMC_USE_RCPP_ARMADILLO\n#include \"mcmc.hpp\"\n```\n\nAt this time, builds using `RcppEigen` are not supported as MCMCLib requires a version of Eigen \u003e= v3.4.0.\n\n## Example\n\nTo illustrate MCMCLib at work, consider the problem of sampling values of the mean parameter of a normal distribution.\n\nCode:\n\n``` cpp\n#define MCMC_ENABLE_EIGEN_WRAPPERS\n#include \"mcmc.hpp\"\n\ninline\nEigen::VectorXd\neigen_randn_colvec(size_t nr)\n{\n    static std::mt19937 gen{ std::random_device{}() };\n    static std::normal_distribution\u003c\u003e dist;\n\n    return Eigen::VectorXd{ nr }.unaryExpr([\u0026](double x) { (void)(x); return dist(gen); });\n}\n\nstruct norm_data_t {\n    double sigma;\n    Eigen::VectorXd x;\n \n    double mu_0;\n    double sigma_0;\n};\n\ndouble ll_dens(const Eigen::VectorXd\u0026 vals_inp, void* ll_data)\n{\n    const double pi = 3.14159265358979;\n\n    //\n\n    const double mu = vals_inp(0);\n \n    norm_data_t* dta = reinterpret_cast\u003cnorm_data_t*\u003e(ll_data);\n    const double sigma = dta-\u003esigma;\n    const Eigen::VectorXd x = dta-\u003ex;\n \n    const int n_vals = x.size();\n \n    //\n \n    const double ret = - n_vals * (0.5 * std::log(2*pi) + std::log(sigma)) - (x.array() - mu).pow(2).sum() / (2*sigma*sigma);\n \n    //\n \n    return ret;\n}\n \ndouble log_pr_dens(const Eigen::VectorXd\u0026 vals_inp, void* ll_data)\n{\n    const double pi = 3.14159265358979;\n\n    //\n\n    norm_data_t* dta = reinterpret_cast\u003c norm_data_t* \u003e(ll_data);\n \n    const double mu_0 = dta-\u003emu_0;\n    const double sigma_0 = dta-\u003esigma_0;\n \n    const double x = vals_inp(0);\n \n    const double ret = - 0.5*std::log(2*pi) - std::log(sigma_0) - std::pow(x - mu_0,2) / (2*sigma_0*sigma_0);\n \n    return ret;\n}\n \ndouble log_target_dens(const Eigen::VectorXd\u0026 vals_inp, void* ll_data)\n{\n    return ll_dens(vals_inp,ll_data) + log_pr_dens(vals_inp,ll_data);\n}\n \nint main()\n{\n    const int n_data = 100;\n    const double mu = 2.0;\n \n    norm_data_t dta;\n    dta.sigma = 1.0;\n    dta.mu_0 = 1.0;\n    dta.sigma_0 = 2.0;\n \n    Eigen::VectorXd x_dta = mu + eigen_randn_colvec(n_data).array();\n    dta.x = x_dta;\n \n    Eigen::VectorXd initial_val(1);\n    initial_val(0) = 1.0;\n\n    //\n\n    mcmc::algo_settings_t settings;\n\n    settings.rwmh_settings.par_scale = 0.4;\n    settings.rwmh_settings.n_burnin_draws = 2000;\n    settings.rwmh_settings.n_keep_draws = 2000;\n\n    //\n\n    Eigen::MatrixXd draws_out;\n    mcmc::rwmh(initial_val, log_target_dens, draws_out, \u0026dta, settings);\n\n    //\n  \n    std::cout \u003c\u003c \"rwmh mean:\\n\" \u003c\u003c draws_out.colwise().mean() \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"acceptance rate: \" \u003c\u003c static_cast\u003cdouble\u003e(settings.rwmh_settings.n_accept_draws) / settings.rwmh_settings.n_keep_draws \u003c\u003c std::endl;\n    \n    //\n \n    return 0;\n}\n```\n\nOn x86-based computers, this example can be compiled using:\n\n``` bash\ng++ -Wall -std=c++14 -O3 -mcpu=native -ffp-contract=fast -I$EIGEN_INCLUDE_PATH -I./../../include/ rwmh_normal_mean.cpp -o rwmh_normal_mean.out -L./../.. -lmcmc\n```\n\nCheck the `/examples` directory for additional examples, and https://mcmclib.readthedocs.io/en/latest/ for a detailed description of each algorithm.\n\n## Automatic Differentiation\n\nBy combining Eigen with the [Autodiff library](https://autodiff.github.io), MCMCLib provides experimental support for automatic differentiation. \n\nThe example below uses forward-mode automatic differentiation to compute the gradient of the Gaussian likelihood function, and the HMC algorithm to sample from the posterior distribution of the mean and variance parameters.\n\n``` cpp\n#define MCMC_ENABLE_EIGEN_WRAPPERS\n#include \"mcmc.hpp\"\n\n#include \u003cautodiff/forward/real.hpp\u003e\n#include \u003cautodiff/forward/real/eigen.hpp\u003e\n\ninline\nEigen::VectorXd\neigen_randn_colvec(size_t nr)\n{\n    static std::mt19937 gen{ std::random_device{}() };\n    static std::normal_distribution\u003c\u003e dist;\n\n    return Eigen::VectorXd{ nr }.unaryExpr([\u0026](double x) { (void)(x); return dist(gen); });\n}\n\nstruct norm_data_t {\n    Eigen::VectorXd x;\n};\n\ndouble ll_dens(const Eigen::VectorXd\u0026 vals_inp, Eigen::VectorXd* grad_out, void* ll_data)\n{\n    const double pi = 3.14159265358979;\n  \n    norm_data_t* dta = reinterpret_cast\u003cnorm_data_t*\u003e(ll_data);\n    const Eigen::VectorXd x = dta-\u003ex;\n  \n    //\n\n    autodiff::real u;\n    autodiff::ArrayXreal xd = vals_inp.eval();\n\n    std::function\u003cautodiff::real (const autodiff::ArrayXreal\u0026 vals_inp)\u003e normal_dens_log_form \\\n    = [x, pi](const autodiff::ArrayXreal\u0026 vals_inp) -\u003e autodiff::real\n    {\n        autodiff::real mu    = vals_inp(0);\n        autodiff::real sigma = vals_inp(1);\n\n        return - x.size() * (0.5 * std::log(2*pi) + autodiff::detail::log(sigma)) - (x.array() - mu).pow(2).sum() / (2*sigma*sigma);\n    };\n  \n    //\n\n    if (grad_out) {\n        Eigen::VectorXd grad_tmp = autodiff::gradient(normal_dens_log_form, autodiff::wrt(xd), autodiff::at(xd), u);\n\n        *grad_out = grad_tmp;\n    } else {\n        u = normal_dens_log_form(xd);\n    }\n  \n    //\n  \n    return u.val();\n}\n  \ndouble log_target_dens(const Eigen::VectorXd\u0026 vals_inp, Eigen::VectorXd* grad_out, void* ll_data)\n{\n    return ll_dens(vals_inp,grad_out,ll_data);\n}\n\nint main()\n{\n    const int n_data = 1000;\n\n    const double mu = 2.0;\n    const double sigma = 2.0;\n  \n    norm_data_t dta;\n  \n    Eigen::VectorXd x_dta = mu + sigma * eigen_randn_colvec(n_data).array();\n    dta.x = x_dta;\n  \n    Eigen::VectorXd initial_val(2);\n    initial_val(0) = mu + 1; // mu\n    initial_val(1) = sigma + 1; // sigma\n  \n    mcmc::algo_settings_t settings;\n  \n    settings.hmc_settings.step_size = 0.08;\n    settings.hmc_settings.n_burnin_draws = 2000;\n    settings.hmc_settings.n_keep_draws = 2000;\n\n    //\n  \n    Eigen::MatrixXd draws_out;\n    mcmc::hmc(initial_val, log_target_dens, draws_out, \u0026dta, settings);\n\n    //\n  \n    std::cout \u003c\u003c \"hmc mean:\\n\" \u003c\u003c draws_out.colwise().mean() \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"acceptance rate: \" \u003c\u003c static_cast\u003cdouble\u003e(settings.hmc_settings.n_accept_draws) / settings.hmc_settings.n_keep_draws \u003c\u003c std::endl;\n\n    //\n \n    return 0;\n}\n```\n\nCompile with:\n\n``` bash\ng++ -Wall -std=c++17 -O3 -march=native -ffp-contract=fast -I/path/to/eigen -I/path/to/autodiff -I/path/to/mcmc/include hmc_normal_autodiff.cpp -o hmc_normal_autodiff.cpp -L/path/to/mcmc/lib -lmcmc\n```\n\nSee the [documentation](https://mcmclib.readthedocs.io/en/latest/autodiff.html) for more details on this topic.\n\n## Author\n\nKeith O'Hara\n\n## License\n\nApache Version 2\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkthohr%2Fmcmc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkthohr%2Fmcmc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkthohr%2Fmcmc/lists"}