<commit_before># Hamiltonian Monte Carlo

Implementations of various Hamiltonian dynamics based MCMC samplers in idiomatic Python code. A modular design is used to as far as possible allowing mixing and matching elements of different proposed extensions to the original HMC algorithm proposed in Duane et al. (1987).

Users can either directly specific the required model derivatives or when available [autograd](https://github.com/HIPS/autograd) can be used to construct the required derivative functions using automatic differentiation.

## Dependencies

To install and use the package the minimal requirements are a Python 3 environment with `numpy` and `scipy` installed. If available `autograd` will be used to automatically compute the required derivatives of the model functions (providing they are specified
using functions from the `autograd.numpy` and `autograd.scipy` interfaces). If the `tqdm` package is available a simple progress bar will be shown during sampling.

## Implemented methods

Samplers

  * Static integration time with Metropolis sampling (Duane et al., 1987)
  * Random integration time with Metropolis sampling (Mackenzie, 1989)
  * Correlated momentum updates in Metropolis samplers (Horowitz, 1991)
  * Dynamic integration time with multinomial sampling (Betancourt, 2017)

Hamiltonian systems

  * Euclidean-metric systems - isotropic, diagonal and dense metrics
  * Riemannian-metric systems (Girolami and Calderhead, 2011) inluding the
    log density Hessian based *SoftAbs* metric (Betancourt, 2013)
  * Euclidean-metric systems subject to holonomic constraints (Hartmann and
    Schütte, 2005; Brubaker, Salzmann and Urtasun, 2012; Lelièvre, Rousset and
    Stoltz, 2018)

Numerical integrators

  * Explicit leapfrog for separable Hamiltonian systems
  * 'Split' leapfrog for Hamiltonian systems with an analytically tractable
    component for which the exact flow can be solved (Shahbaba et al., 2014)
  * Implicit leapfrog for non-separable Hamiltonian systems
  * Geodesic leapfrog for constrained Hamiltonian systems

## Example usage

A simple complete example of using the package to sample from a multivariate Gaussian distribution with randomly generated parameters is given below. Here an isotropic Euclidean metric Hamiltonian system is used (corresponding to a isotropic covariance Gaussian marginal distribution on the momenta) with the dynamic integration time HMC implementation described in Betancourt (2017), which is a extension of the NUTS algorithm (Hoffman and Gelman, 2014).

```python
import hmc
import autograd.numpy as np
import autograd.scipy.linalg as sla

# Generate random precision and mean parameters for a Gaussian
n_dim = 50
rng = np.random.RandomState(seed=1234)
rnd_eigvec, _ = sla.qr(rng.normal(size=(n_dim, n_dim)))
rnd_eigval = np.exp(rng.normal(size=n_dim) * 2)
prec = (rnd_eigvec / rnd_eigval) @ rnd_eigvec.T
mean = rng.normal(size=n_dim)

# Deine potential energy (negative log density) for a Gaussian
# target distribution. The derivative of this function will
# be calculated automatically using autograd
def pot_energy(pos):
    pos_minus_mean = pos - mean<commit_msg>Tidying up README.<commit_after># Hamiltonian Monte Carlo

Implementations of various Hamiltonian dynamics based Markov chain Monte Carlo (MCMC) samplers in idiomatic Python code. A modular design is used to as far as possible allowing mixing and matching elements of different proposed extensions to the original Hybrid Monte Carlo algorithm proposed in Duane et al. (1987).

## Dependencies

To install and use the package the minimal requirements are a Python 3 environment with [NumPy](http://www.numpy.org/) and [SciPy](https://www.scipy.org) installed. 

If available [autograd](https://github.com/HIPS/autograd) will be used to automatically compute the required derivatives of the model functions (providing they are specified using functions from the `autograd.numpy` and `autograd.scipy` interfaces). If the [tqdm](https://github.com/tqdm/tqdm) package is available a simple progress bar will be shown during sampling.

## Implemented methods

Samplers

  * Static integration time with Metropolis sampling (Duane et al., 1987)
  * Random integration time with Metropolis sampling (Mackenzie, 1989)
  * Correlated momentum updates in Metropolis samplers (Horowitz, 1991)
  * Dynamic integration time with multinomial sampling (Betancourt, 2017)

Hamiltonian systems

  * Euclidean-metric systems - isotropic, diagonal and dense metrics
  * Riemannian-metric systems (Girolami and Calderhead, 2011) inluding the
    log density Hessian based *SoftAbs* metric (Betancourt, 2013)
  * Euclidean-metric systems subject to holonomic constraints (Hartmann and
    Schütte, 2005; <NAME> and Urtasun, 2012; <NAME> and
    Stoltz, 2018)

Numerical integrators

  * Explicit leapfrog for separable Hamiltonian systems
  * 'Split' leapfrog for Hamiltonian systems with an analytically tractable
    component for which the exact flow can be solved (Shahbaba et al., 2014)
  * Implicit leapfrog for non-separable Hamiltonian systems
  * Geodesic leapfrog for constrained Hamiltonian systems

## Example usage

A simple complete example of using the package to sample from a multivariate Gaussian distribution with randomly generated parameters is given below. Here an isotropic Euclidean metric Hamiltonian system is used (corresponding to a isotropic covariance Gaussian marginal distribution on the momenta) with the dynamic integration time HMC implementation described in Betancourt (2017), which is a extension of the NUTS algorithm (<NAME>, 2014).

```python
import hmc
import autograd.numpy as np
import autograd.scipy.linalg as sla

# Generate random precision and mean parameters for a Gaussian
n_dim = 50
rng = np.random.RandomState(seed=1234)
rnd_eigvec, _ = sla.qr(rng.normal(size=(n_dim, n_dim)))
rnd_eigval = np.exp(rng.normal(size=n_dim) * 2)
prec = (rnd_eigvec / rnd_eigval) @ rnd_eigvec.T
mean = rng.normal(size=n_dim)

# Define potential energy (negative log density) for a Gaussian
# target distribution. The derivative of this function will
# be calculated automatically using autograd
def pot_energy(pos):
    pos_minus_mean = pos - mean
{'fraction_non_alphanumeric': 0.05751570807153214, 'fraction_numerical': 0.01933301111648139, 'mean_word_length': 5.080313418217434, 'pattern_counts': {'":': 0, '<': 6, '<?xml version=': 0, '>': 6, 'https://': 4, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '32371', 'n_tokens_mistral': 1836, 'n_tokens_neox': 1607, 'n_words': 754}