Skip to main content

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 CI Codecov PyPI - License

Dependencies

  • NumPy >= 1.19.0

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

pip install -U pyhtnorm

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

pip install -U pyhtnorm

Alternatively, one can install it from source using the following shell commands:

$ git clone https://github.com/zoj613/htnorm.git
$ cd htnorm/
$ export PYHT_LIBS_DIR=<some directory with blas and lapack shared library files> # this is optional
$ pip install .

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.

Metadata

Release files for pyhtnorm 2.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pyhtnorm 2.0.1
File Size Uploaded
pyhtnorm-2.0.1.tar.gz 38.6 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for pyhtnorm 2.0.1
File
pyhtnorm-2.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.11 CPython 3.11 Linux glibc 2.17+ x86-64 Details
pyhtnorm-2.0.1-cp311-cp311-macosx_10_9_x86_64.whl CPython 3.11 CPython 3.11 macOS 10.9+ x86-64 Details
pyhtnorm-2.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.10 CPython 3.10 Linux glibc 2.17+ x86-64 Details
pyhtnorm-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl CPython 3.10 CPython 3.10 macOS 10.9+ x86-64 Details
pyhtnorm-2.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.9 CPython 3.9 Linux glibc 2.17+ x86-64 Details
pyhtnorm-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl CPython 3.9 CPython 3.9 macOS 10.9+ x86-64 Details
pyhtnorm-2.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.8 CPython 3.8 Linux glibc 2.17+ x86-64 Details
pyhtnorm-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl CPython 3.8 CPython 3.8 macOS 10.9+ x86-64 Details

Total release size: 115.0 MB

Release files / pyhtnorm-2.0.1.tar.gz

Download URL pyhtnorm-2.0.1.tar.gz
Size 38.6 kB
Tags Source
SHA-256 checksum
How to use checksums
c1353b3fb0acbf2df4d188ce041b43a75db3c45eccb25e79e33d9a94679d2608
BLAKE2b-256 checksum
How to use checksums
d5e016e3cc7b20399c75c79a64bc60b0be45f8426c33cf2c8754a8622e4a1183
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/4.0.1 CPython/3.11.3

Release files / pyhtnorm-2.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL pyhtnorm-2.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 13.5 MB
Tags CPython 3.11 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
a384c615d09ae0e733757cffba09d2a3972ce5afdf30891ff4f1a52bef81a73b
BLAKE2b-256 checksum
How to use checksums
3a30c8604109e155287fee015a1495595344127c1841458d0a4ae71855ecec14
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/4.0.1 CPython/3.11.3

Release files / pyhtnorm-2.0.1-cp311-cp311-macosx_10_9_x86_64.whl

Download URL pyhtnorm-2.0.1-cp311-cp311-macosx_10_9_x86_64.whl
Size 15.2 MB
Tags CPython 3.11 macOS 10.9+ x86-64
SHA-256 checksum
How to use checksums
21e5db826231b8d8c378d58618513729b1fd514d4fdab504fdf4ff0e07a32b5a
BLAKE2b-256 checksum
How to use checksums
70bd45ff993aae27f2278f89b6777db4dde6ec97dfa12364ca9ff744caca2dd6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/4.0.1 CPython/3.11.3

Release files / pyhtnorm-2.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL pyhtnorm-2.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 13.5 MB
Tags CPython 3.10 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
e7047acc40d85d68009260c9e3cf860973d2e13af4e45d5116eff54f4abf7793
BLAKE2b-256 checksum
How to use checksums
f393043d97b4815d47848b7fdce47889f69185065997e502dd0e7e3a1ccbf4fe
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/4.0.1 CPython/3.11.3

Release files / pyhtnorm-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl

Download URL pyhtnorm-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl
Size 15.3 MB
Tags CPython 3.10 macOS 10.9+ x86-64
SHA-256 checksum
How to use checksums
f589a4aeae468eb17a5793b1b9fc6cd118b688cd8bc5af44cdc211a8d86830ff
BLAKE2b-256 checksum
How to use checksums
db5013f5bdd0238398c145a09d8aa41d6650957b19c40def1e0d4a571057344f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/4.0.1 CPython/3.11.3

Release files / pyhtnorm-2.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL pyhtnorm-2.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 13.5 MB
Tags CPython 3.9 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
e96846678eec54f2de46740439fe33687058e67de5e9c260ad1f9349738a7c67
BLAKE2b-256 checksum
How to use checksums
78488e84f98beb9edefe017d2e71294126b5855d491882c584e5504f337286b4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/4.0.1 CPython/3.11.3

Release files / pyhtnorm-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl

Download URL pyhtnorm-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl
Size 15.3 MB
Tags CPython 3.9 macOS 10.9+ x86-64
SHA-256 checksum
How to use checksums
c2562ea8114cf5bd81c8f50f010f1d4f1298def05b6efd65803bdd6e6c4c5aa0
BLAKE2b-256 checksum
How to use checksums
b7219eeb11e4b4e1b46882284253deb61cd17df28609af2b6abf76dd86b7846a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/4.0.1 CPython/3.11.3

Release files / pyhtnorm-2.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL pyhtnorm-2.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 13.5 MB
Tags CPython 3.8 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
9b24a6569ab2e25ddbe8cd651fd8e7b1f986855934c9660e7417a84ce58ae0c0
BLAKE2b-256 checksum
How to use checksums
a060086bd7d03137e0904922c9ee9516161a59358987d54d62593c4997e83ca6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/4.0.1 CPython/3.11.3

Release files / pyhtnorm-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl

Download URL pyhtnorm-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl
Size 15.2 MB
Tags CPython 3.8 macOS 10.9+ x86-64
SHA-256 checksum
How to use checksums
0eed634d5aefd5296305de0160702c51c2c1c84bd3ed36b40d0f5b8c13bed76f
BLAKE2b-256 checksum
How to use checksums
0636dbe4c61584053f912a36808b52088ec5a44855f18c5f795d5262f830fd68
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/4.0.1 CPython/3.11.3

Release history Release notifications | RSS feed

This release

2.0.1 This release

9 release files

1.0.0

17 release files

0.2.0

10 release files

0.1.1

10 release files

0.1.0

10 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page