Fast Simulation of Hyperplane-Truncated Multivatiate Normal Distributions
Project description
htnorm
This repo provides a C implementation of a fast and exact sampler from 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:
-
efficient sampling from a MVN with a stuctured precision matrix:
-
efficent sampling frfom a MVN with a structured precision and mean:
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 posterior distribution of an Intrinsic Conditional Autoregressive prior icar
- Sampling from posterior conditional distributions of various bayesian regression problems.
Dependencies
- a C compiler that supports the C99 standard or later
- an installation of BLAS and LAPACK that exposes its C interface via the headers
<cblas.h>
and<lapacke.h>
(e.g openBLAS).
Usage
Building a shared library of htnorm
can be done with the following:
# optionally set path to CBLAS and LAPACKE headers using INCLUDE_DIRS environmental variable
$ export INCLUDE_DIRS="some/path/to/headers"
# optionally set path to BLAS installation shared library
$ export LIBS_DIR="some/path/to/library/"
# optionally set the linker flag for your BLAS installation (e.g -lopenblas)
$ export LIBS=<flag here>
$ 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 API 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 API allows using a custom generator, and the details are documented in the header file "rng.h".
Examples
#include "htnorm.h"
int main ()
{
...
// instantiate a random number generator
rng_t* rng = rng_new_pcg64();
ht_config_t config;
config.g = ...; // G matrix
config.gnrow = ...; // number of rows of G
config.gncol = ...; // number of columns of G
cofig.r = ...; // r array
config.mean = ...; // mean array
config.cov = ...; // the convariance matrix
confi.diag = ...; // whether covariance is diagonal
double* samples = ...; // array to store the samples
// now call the sampler
int res_info = htn_hyperplane_truncated_mvn(rng, &config, samples);
// res_info contains a number that indicates whether sampling failed or not.
...
// finally free the RNG pointer at some point
rng_free(rng);
...
return 0;
}
Python API
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 pyhtnorm
Wheels are not provided for MacOS. To install via pip, one can run the following commands:
#set the path to BLAS installation headers
export INCLUDE_DIR=<path/to/headers>
#set the path to BLAS shared library
export LIBS_DIR=<some directory>
#set the name of the BLAS shared library (e.g. "openblas")
export LIBS=<lib name>
# finally install via pip so the compilation and linking can be done correctly
pip install 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 (i.e. making sure the sampled values sum to zero)
from pyhtnorm import HTNGenerator
import numpy as np
rng = HTNGenerator()
# generate example input
k1 = 1000
k2 = 1
npy_rng = np.random.default_rng()
temp = npy_rng.random((k1, k1))
cov = temp @ temp.T + np.diag(npy_rng.random(k1))
G = np.ones((k2, k1))
r = np.zeros(k2)
mean = npy_rng.random(k1)
samples = rng.hyperplane_truncated_mvnorm(mean, cov, G, r)
# verify if sampled values sum to zero
print(sum(samples))
# alternatively one can pass an array to store the results in
out = np.empty(k1)
rng.hyperplane_truncated_mvnorm(mean, cov, G, r, out=out)
# verify
print(out.sum())
For more details about the parameters of the HTNGenerator
and its methods,
see the docstrings via python's help
function.
The python API also exposes the HTNGenerator
class as a Cython extension type
that can be "cimported" in a cython script.
R API
One can also access the API in R. To install the package, use:
devtools::install_github("zoj613/htnorm")
Note that you must have the cblas and lapacke headers available before installation.
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)
# alternatively one can pass a vector to store the results in
out <- rep(0, 1000)
rng$hyperplane_truncated_mvnorm(mean, cov, G, r, out = out)
#verify
sum(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
Built Distributions
File details
Details for the file pyhtnorm-0.2.0.tar.gz
.
File metadata
- Download URL: pyhtnorm-0.2.0.tar.gz
- Upload date:
- Size: 158.2 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
Algorithm | Hash digest | |
---|---|---|
SHA256 | 1a9a00796587bba859cef07cc2347cfc4c798d27a9352acf399ca8d45a95de2e |
|
MD5 | 56ace13d5ad08f7a84d5c976e7d52664 |
|
BLAKE2b-256 | 4a513f78fd7d536660ca4dd60b95762c7728c0567e5c839cb1d665e6f82386ae |
File details
Details for the file pyhtnorm-0.2.0-cp38-cp38-manylinux2014_x86_64.whl
.
File metadata
- Download URL: pyhtnorm-0.2.0-cp38-cp38-manylinux2014_x86_64.whl
- Upload date:
- Size: 11.0 MB
- Tags: CPython 3.8
- 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
Algorithm | Hash digest | |
---|---|---|
SHA256 | e5c75e01900ce3ab990e76bf9315f5c018f4d31a3d361d0dba1bc0d0fe56f725 |
|
MD5 | cb9bba727263fb88b7570dd84e59a5ba |
|
BLAKE2b-256 | 0437905d09d0ffcf25f1334fc81051b26f2c0845b35bb7eb1b2ffc53aeae9560 |
File details
Details for the file pyhtnorm-0.2.0-cp38-cp38-manylinux2010_x86_64.whl
.
File metadata
- Download URL: pyhtnorm-0.2.0-cp38-cp38-manylinux2010_x86_64.whl
- Upload date:
- Size: 10.0 MB
- Tags: CPython 3.8, manylinux: glibc 2.12+ x86-64
- 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
Algorithm | Hash digest | |
---|---|---|
SHA256 | f3b4e4bbcc91bbddca041e9a6a29f6e88069f38e69bdb7c37fdae1bfb631a711 |
|
MD5 | 8641ec8152d0067a1f88b55d9a3fd846 |
|
BLAKE2b-256 | 8f78c10c16a2809c61371ef32999562cef420fa1c1bcdeb88aab957ea3ad6bc8 |
File details
Details for the file pyhtnorm-0.2.0-cp38-cp38-manylinux1_x86_64.whl
.
File metadata
- Download URL: pyhtnorm-0.2.0-cp38-cp38-manylinux1_x86_64.whl
- Upload date:
- Size: 14.1 MB
- Tags: CPython 3.8
- 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
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2797eafef8cea01a2b66782c0a07c975ff339a54102cd21b419a6a5efcca89b6 |
|
MD5 | b436bf869a3b870ae70500d2f2cf1839 |
|
BLAKE2b-256 | c979591e20a25a6937cc704a2944bda7f9c88f25b89a8a61f4c37c286a886cf0 |
File details
Details for the file pyhtnorm-0.2.0-cp37-cp37m-manylinux2014_x86_64.whl
.
File metadata
- Download URL: pyhtnorm-0.2.0-cp37-cp37m-manylinux2014_x86_64.whl
- Upload date:
- Size: 10.9 MB
- Tags: CPython 3.7m
- 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
Algorithm | Hash digest | |
---|---|---|
SHA256 | 0174db278ea27c475afceb36033bb4c5f12d52e4d0b2eda2af64cf796740213a |
|
MD5 | fd9f8129fd48eb08208b09afec9f4b75 |
|
BLAKE2b-256 | e6ae358262f253482da4c7a9a637cc0ee6c43b6cb9b89178fb54a3bf63cb0f77 |
File details
Details for the file pyhtnorm-0.2.0-cp37-cp37m-manylinux2010_x86_64.whl
.
File metadata
- Download URL: pyhtnorm-0.2.0-cp37-cp37m-manylinux2010_x86_64.whl
- Upload date:
- Size: 9.9 MB
- Tags: CPython 3.7m, manylinux: glibc 2.12+ x86-64
- 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
Algorithm | Hash digest | |
---|---|---|
SHA256 | 8781ed7b6ce531226f3c460ae6de566dca57d49540f85aa44260a816cdd89c63 |
|
MD5 | 499a20a5d0762d448602d84d992176aa |
|
BLAKE2b-256 | a145c105cc1aab8f857f20a8cf49de3573e8503c6f6fcb09d2d0e287d9c53165 |
File details
Details for the file pyhtnorm-0.2.0-cp37-cp37m-manylinux1_x86_64.whl
.
File metadata
- Download URL: pyhtnorm-0.2.0-cp37-cp37m-manylinux1_x86_64.whl
- Upload date:
- Size: 14.1 MB
- Tags: CPython 3.7m
- 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
Algorithm | Hash digest | |
---|---|---|
SHA256 | b6378235acb4e459b80ad6adadf4cda2b61f4faa965b20ba2a852cab95aecdf9 |
|
MD5 | a513f697467cf53c63fe8d1a9f5e9ee2 |
|
BLAKE2b-256 | 12ed1faa477e80fe2e492989a77065bf010fdb4d7464c1678d57732612e303f1 |
File details
Details for the file pyhtnorm-0.2.0-cp36-cp36m-manylinux2014_x86_64.whl
.
File metadata
- Download URL: pyhtnorm-0.2.0-cp36-cp36m-manylinux2014_x86_64.whl
- Upload date:
- Size: 10.9 MB
- Tags: CPython 3.6m
- 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
Algorithm | Hash digest | |
---|---|---|
SHA256 | f3f38a7f9e8021c73e95cc9b94b638d89b51a8574ada87e4e7ba4c7109e75f63 |
|
MD5 | eebc47c21a8f8880d3b28578cf81d08a |
|
BLAKE2b-256 | 6a7f2bfe045502da4997a0dd9d02fe88f1167bce190ad4ba81df530f08f30672 |
File details
Details for the file pyhtnorm-0.2.0-cp36-cp36m-manylinux2010_x86_64.whl
.
File metadata
- Download URL: pyhtnorm-0.2.0-cp36-cp36m-manylinux2010_x86_64.whl
- Upload date:
- Size: 9.9 MB
- Tags: CPython 3.6m, manylinux: glibc 2.12+ x86-64
- 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
Algorithm | Hash digest | |
---|---|---|
SHA256 | d319593cd6775f1a3852e0c192e11ae02b04ea852d8702e0120445e602bb235a |
|
MD5 | b66e2006f4cf8ba519a6ba8c84559897 |
|
BLAKE2b-256 | b37de20b5cd983ef76978c1575d1cf31948ab92b19d26470c8868c4ad897d03b |
File details
Details for the file pyhtnorm-0.2.0-cp36-cp36m-manylinux1_x86_64.whl
.
File metadata
- Download URL: pyhtnorm-0.2.0-cp36-cp36m-manylinux1_x86_64.whl
- Upload date:
- Size: 14.1 MB
- Tags: CPython 3.6m
- 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
Algorithm | Hash digest | |
---|---|---|
SHA256 | ca9331bf3570bf4ffe4552ff450edd31be366abd2e340b8ad0c9f089efd18a78 |
|
MD5 | 5811634b48f192ae2f5598a5157be633 |
|
BLAKE2b-256 | eed9b47fe213b899a5acadc19623f48a300dcae49b0251b774759fe061596aac |