Skip to main content

Fast Simulation of Hyperplane-Truncated Multivatiate Normal Distributions

Project description

htnorm

This repo provides a C implementation of a fast and exact sampling algorithm for a multivariate normal distribution (MVN) truncated on a hyperplane as described here

This repo implements the following from the paper:

  • Efficient sampling from a MVN truncated on a hyperplane:

    hptrunc

  • Efficient sampling from a MVN with a stuctured precision matrix that is a sum of an invertible matrix and a low rank matrix:

    struc

  • Efficient sampling from a MVN with a structured precision and mean:

    strucmean

The algorithms implemented have the following practical applications:

  • Topic models when unknown parameters can be interpreted as fractions.
  • Admixture models
  • discrete graphical models
  • Sampling from the posterior distribution of an Intrinsic Conditional Autoregressive prior icar
  • Sampling from the posterior conditional distributions of various bayesian regression problems.

Dependencies

  • A C compiler that implements the C99 standard or later
  • An installation of LAPACK.

Usage

Building a shared library of htnorm can be done with the following:

# optionally set path to LAPACK shared library
$ export LIBS_DIR="some/path/to/lib/"
$ make lib

Afterwards the shared library will be found in a lib/ directory of the project root, and the library can be linked dynamically via -lhtnorm.

The puplic interface exposes the samplers through the function declarations

 int htn_hyperplane_truncated_mvn(rng_t* rng, const ht_config_t* conf, double* out);
 int htn_structured_precision_mvn(rng_t* rng, const sp_config_t* conf, double* out);

The details of the parameters are documented in ther header files "htnorm.h".

Random number generation is done using PCG64 or Xoroshiro128plus bitgenerators. The interface allows using a custom bitgenerator, and the details are documented in the header file "rng.h".

Example

#include "htnorm.h"

int main (void)
{
    ...
    // instantiate a random number generator
    rng_t* rng = rng_new_pcg64_seeded(12345);
    ht_config_t config;
    init_ht_config(&config, ...);
    double* out = ...; // array to store the samples
    int res = htn_hyperplane_truncated_mvn(rng, &config, out);
    // res contains a number that indicates whether sampling failed or not.
    ...
    // finally free the RNG pointer at some point
    rng_free(rng);
    ...
    return 0;
}

Python Interface

PyPI - Wheel PyPI

Dependencies

  • NumPy >= 1.17

A high level python interface to the library is also provided. Linux users can install it using wheels via pip (thus not needing to worry about availability of C libraries),

pip install -U pyhtnorm

Wheels are not provided for MacOS. To install via pip, one can run the following commands:

#set the path to LAPACK shared library
export LIBS_DIR=<some directory>
pip install -U pyhtnorm

Alternatively, one can install it from source. This requires an installation of poetry and the following shell commands:

$ git clone https://github.com/zoj613/htnorm.git
$ cd htnorm/
$ poetry install
# add htnorm to python's path
$ export PYTHONPATH=$PWD:$PYTHONPATH

Below is an example of how to use htnorm in python to sample from a multivariate gaussian truncated on the hyperplane sumzero (i.e. making sure the sampled values sum to zero). The python interface is such that the code can be easily integrated into other existing libraries. Since v1.0.0, it supports passing a numpy.random.Generator instance as a parameter to aid reproducibility.

from pyhtnorm import hyperplane_truncated_mvnorm, structured_precision_mvnorm
import numpy as np

rng = np.random.default_rng()

# generate example input
k1, k2 = 1000, 1
temp = rng.random((k1, k1))
cov = temp @ temp.T
G = np.ones((k2, k1))
r = np.zeros(k2)
mean = rng.random(k1)

# passing `random_state` is optional. If the argument is not used, a fresh
# random generator state is instantiated internally using system entropy.
o = hyperplane_truncated_mvnorm(mean, cov, G, r, random_state=rng)
print(o.sum())  # verify if sampled values sum to zero
# alternatively one can pass an array to store the results in
hyperplane_truncated_mvnorm(mean, cov, G, r, out=o)

For more information about the function's arguments, refer to its docstring.

A pure numpy implementation is demonstrated in this example script.

R Interface

One can also use the package in R. To install, use one the following commands:

devtools::install_github("zoj613/htnorm")
pak::pkg_install("zoj613/htnorm")

Below is an R translation of the above python example:

library(htnorm)

# make dummy data
mean <- rnorm(1000)
cov <- matrix(rnorm(1000 * 1000), ncol=1000)
cov <- cov %*% t(cov)
G <- matrix(rep(1, 1000), ncol=1000)
r <- c(0)

# initialize the Generator instance
rng <- HTNGenerator(seed=12345, gen="pcg64")

samples <- rng$hyperplane_truncated_mvnorm(mean, cov, G, r)
#verify if sampled values sum to zero
sum(samples)

# optionally pass a vector to store the results in
out <- rep(0, 1000)
rng$hyperplane_truncated_mvnorm(mean, cov, G, r, out = out)
sum(out)  #verify

out <- rep(0, 1000)
eig <- eigen(cov)
phi <- eig$vectors
omega <- diag(eig$values)
a <- diag(runif(length(mean)))
rng$structured_precision_mvnorm(mean, a, phi, omega, a_type = "diagonal", out = out)

Licensing

htnorm is free software made available under the BSD-3 License. For details see the LICENSE file.

References

  • Cong, Yulai; Chen, Bo; Zhou, Mingyuan. Fast Simulation of Hyperplane-Truncated Multivariate Normal Distributions. Bayesian Anal. 12 (2017), no. 4, 1017--1037. doi:10.1214/17-BA1052.
  • Bhattacharya, A., Chakraborty, A., and Mallick, B. K. (2016). “Fast sampling with Gaussian scale mixture priors in high-dimensional regression.” Biometrika, 103(4):985.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyhtnorm-2.0.0.tar.gz (156.6 kB view details)

Uploaded Source

Built Distributions

pyhtnorm-2.0.0-cp39-cp39-manylinux_2_12_x86_64.manylinux1_x86_64.whl (9.8 MB view details)

Uploaded CPython 3.9 manylinux: glibc 2.12+ x86-64

pyhtnorm-2.0.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (10.8 MB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ x86-64

pyhtnorm-2.0.0-cp39-cp39-manylinux2010_x86_64.manylinux_2_12_x86_64.whl (9.8 MB view details)

Uploaded CPython 3.9 manylinux: glibc 2.12+ x86-64

pyhtnorm-2.0.0-cp38-cp38-manylinux2014_x86_64.manylinux_2_12_x86_64.whl (10.8 MB view details)

Uploaded CPython 3.8 manylinux: glibc 2.12+ x86-64

pyhtnorm-2.0.0-cp38-cp38-manylinux2010_x86_64.manylinux_2_12_x86_64.whl (9.8 MB view details)

Uploaded CPython 3.8 manylinux: glibc 2.12+ x86-64

pyhtnorm-2.0.0-cp38-cp38-manylinux1_x86_64.manylinux_2_12_x86_64.whl (9.8 MB view details)

Uploaded CPython 3.8 manylinux: glibc 2.12+ x86-64

pyhtnorm-2.0.0-cp38-cp38-manylinux1_x86_64.manylinux_2_5_x86_64.whl (13.1 MB view details)

Uploaded CPython 3.8 manylinux: glibc 2.5+ x86-64

pyhtnorm-2.0.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (10.8 MB view details)

Uploaded CPython 3.7m manylinux: glibc 2.17+ x86-64

pyhtnorm-2.0.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl (9.8 MB view details)

Uploaded CPython 3.7m manylinux: glibc 2.12+ x86-64

pyhtnorm-2.0.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux1_x86_64.whl (9.8 MB view details)

Uploaded CPython 3.7m manylinux: glibc 2.12+ x86-64

pyhtnorm-2.0.0-cp37-cp37m-manylinux1_x86_64.manylinux_2_5_x86_64.whl (13.1 MB view details)

Uploaded CPython 3.7m manylinux: glibc 2.5+ x86-64

File details

Details for the file pyhtnorm-2.0.0.tar.gz.

File metadata

  • Download URL: pyhtnorm-2.0.0.tar.gz
  • Upload date:
  • Size: 156.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.6.1 requests/2.25.1 setuptools/49.2.1 requests-toolbelt/0.9.1 tqdm/4.54.1 CPython/3.8.6

File hashes

Hashes for pyhtnorm-2.0.0.tar.gz
Algorithm Hash digest
SHA256 960fd7e63f64845699a4e12ed56920c328a60849dc0b6299052da75f8515757f
MD5 12cd9bf55774d598d753e6b5476dd278
BLAKE2b-256 44b0a382488c9facc378761d419ae149a01d11fe300fbaf5907f6e9b590379ee

See more details on using hashes here.

File details

Details for the file pyhtnorm-2.0.0-cp39-cp39-manylinux_2_12_x86_64.manylinux1_x86_64.whl.

File metadata

File hashes

Hashes for pyhtnorm-2.0.0-cp39-cp39-manylinux_2_12_x86_64.manylinux1_x86_64.whl
Algorithm Hash digest
SHA256 7c997708ac56a5f376905d20a10731ba3b57dc30bf3f7ce8074cd9a044d939cf
MD5 9233b97b2c09bbd452f888de835a74a7
BLAKE2b-256 7fb2caca6f650654999411a6943fdc1026e0d0efecf318df9ca3e7903ac049cf

See more details on using hashes here.

File details

Details for the file pyhtnorm-2.0.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for pyhtnorm-2.0.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 6bf28e127e5f3d46b9c471efa8adcf3a1ce90e107c66fb75e9ccdf2fdadb9d31
MD5 8c2d1306f16c34330c547f533c0fd907
BLAKE2b-256 3d7c24639b7f3ad79bec46ef71ebf7844c4ebf22d5811f76e97ebe90c07b7203

See more details on using hashes here.

File details

Details for the file pyhtnorm-2.0.0-cp39-cp39-manylinux2010_x86_64.manylinux_2_12_x86_64.whl.

File metadata

File hashes

Hashes for pyhtnorm-2.0.0-cp39-cp39-manylinux2010_x86_64.manylinux_2_12_x86_64.whl
Algorithm Hash digest
SHA256 f3484a8a8a294a79a23f4e2bac0778e84e33fc3a067666025bf7a7fc7459de18
MD5 5d2103c3626bf66b6a1e6e01c5b513d8
BLAKE2b-256 fc9fde7bc68e1fe4f7acbca734cfce6b60897ac1f614eecc7869f1c2efd1d5ca

See more details on using hashes here.

File details

Details for the file pyhtnorm-2.0.0-cp38-cp38-manylinux2014_x86_64.manylinux_2_12_x86_64.whl.

File metadata

File hashes

Hashes for pyhtnorm-2.0.0-cp38-cp38-manylinux2014_x86_64.manylinux_2_12_x86_64.whl
Algorithm Hash digest
SHA256 b5aa5d87d9c889d2fb8dba05f9793807bca0ff8fc1653bb675a4d3a0c3e7d501
MD5 3e70ce2a7af637c203dc34cf698872b5
BLAKE2b-256 0afc5036e745d7032d2b0fcae0f484d5616ff74de4be574e392f19d429f41ccb

See more details on using hashes here.

File details

Details for the file pyhtnorm-2.0.0-cp38-cp38-manylinux2010_x86_64.manylinux_2_12_x86_64.whl.

File metadata

File hashes

Hashes for pyhtnorm-2.0.0-cp38-cp38-manylinux2010_x86_64.manylinux_2_12_x86_64.whl
Algorithm Hash digest
SHA256 4747cca624ebda6266a701c6b921ba835215833b0d702d57ab16ef9e2c81feb5
MD5 5422dcbed85094396955b852c0294931
BLAKE2b-256 60edb80b1d03b697c0ad4b0b5ac350e588f1c4b3e201614751522054740bc2f3

See more details on using hashes here.

File details

Details for the file pyhtnorm-2.0.0-cp38-cp38-manylinux1_x86_64.manylinux_2_12_x86_64.whl.

File metadata

File hashes

Hashes for pyhtnorm-2.0.0-cp38-cp38-manylinux1_x86_64.manylinux_2_12_x86_64.whl
Algorithm Hash digest
SHA256 ad653de4f86c67e9779cd0912e3dbd5f1b03385b3652518adcab871674e033f1
MD5 ebdcdcf6b1259d79d5ee337e2d6c7a16
BLAKE2b-256 8c6931661b44dc3be194b13115b83d0db7bff8023c6a6f3fc3b9f84dfdde6715

See more details on using hashes here.

File details

Details for the file pyhtnorm-2.0.0-cp38-cp38-manylinux1_x86_64.manylinux_2_5_x86_64.whl.

File metadata

File hashes

Hashes for pyhtnorm-2.0.0-cp38-cp38-manylinux1_x86_64.manylinux_2_5_x86_64.whl
Algorithm Hash digest
SHA256 0444538868a2d82e7f4741ee7d84d6f0b23a82c52e0acc02056852eae0a554fd
MD5 6e3166e87fc10e7bc46274213c8073a2
BLAKE2b-256 977604bdaee1c0e4c7c7810e993760a973760867db3a7b5f5b09681e33511cf5

See more details on using hashes here.

File details

Details for the file pyhtnorm-2.0.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pyhtnorm-2.0.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 01784eb27e2648e099ed0d8e3ef3295946cd5d258f0fd37980ddba51045de9fb
MD5 b6e42a72e917fc73e90a63044563db06
BLAKE2b-256 8604d30c942c09f7e6b1d0bff3c191b943b998ee38a27004e16f3d48e0f812aa

See more details on using hashes here.

File details

Details for the file pyhtnorm-2.0.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl.

File metadata

File hashes

Hashes for pyhtnorm-2.0.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl
Algorithm Hash digest
SHA256 468e46898d3859f15065ec96083c51d3b8702558d7b297fe748715a750bab8c2
MD5 d43eb6cf0ad7ab3a29a3dbbf03b88802
BLAKE2b-256 e74da7fe6073283145811bf71c79b6a82907df0a3f1c06ece2002c4d48273be6

See more details on using hashes here.

File details

Details for the file pyhtnorm-2.0.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux1_x86_64.whl.

File metadata

File hashes

Hashes for pyhtnorm-2.0.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux1_x86_64.whl
Algorithm Hash digest
SHA256 7b0ba7f0d5656c243193b6137bad9d1f886fd6969b356fa22629e5e5c64c3f40
MD5 18ecfaf83eea063557c63b6593e5999b
BLAKE2b-256 6bfa75a57f26829e478920e87597d82059e7176c09707e3e3bc33a5a836e115b

See more details on using hashes here.

File details

Details for the file pyhtnorm-2.0.0-cp37-cp37m-manylinux1_x86_64.manylinux_2_5_x86_64.whl.

File metadata

File hashes

Hashes for pyhtnorm-2.0.0-cp37-cp37m-manylinux1_x86_64.manylinux_2_5_x86_64.whl
Algorithm Hash digest
SHA256 41c5c98e16cd3eaefcd6d8a525742ccad11244e9eb4a29416ff733fe3453d0a4
MD5 048a89e0532aecc2a1ade9529d564b92
BLAKE2b-256 f5e09bdfefbc6dd496bb6656970b24db3ede4bc9b578c9f235d3a7f51ec074cd

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page