-
Notifications
You must be signed in to change notification settings - Fork 4
/
htnorm.h
133 lines (121 loc) · 4.55 KB
/
htnorm.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/* Copyright (c) 2020, Zolisa Bleki
*
* SPDX-License-Identifier: BSD-3-Clause
*
* Fast Simulation of Hyperplane-Truncated Multivaariate Normal Distributions.
*
* This library implements the algorithms 2, 4 and the one in example 4 of
* Cong, Y., Chen, B., & Zhou, M. (2017).
*
* Algorithm 2 allows fast and exact sampling from a multivariate normal (MVN)
* distribution that is trancated on a hyperplane.
*
* Algorthm 4 allows efficient sampling from a MVN with a structured precision
* matrix.
*
* Algorithm described in example 4 allows efficient sampling from a MVN with
* a structured precision matrix and a structured mean dependent on the
* structure of the precision matrix.
*
* References:
* 1) Cong, Y., Chen, B., & Zhou, M. (2017). Fast simulation of
* hyperplane-truncated multivariate normal distributions. Bayesian Analysis,
* 12(4), 1017-1037.
*/
#ifndef HTNORM_HTNORM_H
#define HTNORM_HTNORM_H
#include <stdbool.h>
#include <stddef.h>
#include "htnorm_rng.h"
typedef enum {NORMAL, DIAGONAL, IDENTITY} type_t;
typedef struct {
// number of rows of the G matrix
size_t gnrow;
// number of columns of the G matrix
size_t gncol;
// mean vector
const double* mean;
// covariance
const double* cov;
// G matrix with LHS of the hyperplane
const double* g;
// r vector with the RHS of the equation: Gx = r
const double* r;
// whether the covariance is diagonal;
bool diag;
} ht_config_t;
// helper function to initialize values of the ht_config_t struct
void init_ht_config(ht_config_t* conf, size_t gnrow, size_t gncol,
const double* mean, const double* cov, const double* g,
const double* r, bool diag);
typedef struct {
// Whether matrix A is regular (0), diagonal (1) or identity (2)
type_t a_id;
// Whether matrix Omega is regular (0), diagonal (1) or identity (2)
type_t o_id;
// number of rows of phi matrix
size_t pnrow;
// number of columns of phi matrix
size_t pncol;
// mean vector
const double* mean;
// array with elements of the A matrix
const double* a;
// array with elements of the phi matrix
const double* phi;
// array with elements of the omega matrix
const double* omega;
// whether the mean is structure (i.e. made up of the covariance matrix)
bool struct_mean;
} sp_config_t;
// helper function to initialize values of the sp_config_t struct
void init_sp_config(sp_config_t* conf, size_t pnrow, size_t pncol, const double* mean,
const double* a, const double* phi, const double* omega,
bool struct_mean, type_t a_id, type_t o_id);
/* Sample from a multivariate normal distribution truncated on a hyperplane.
*
* Generate sample x from the distribution: N(mean, cov) truncated on the plane
* {x | Gx = r}, where the rank of G is less than that of the covariance.
*
* Paramaters
* ----------
* rng:
* A pointer to the `rng_t` struct (The random number generator).
* conf:
* A pointer to the input configuration struct `ht_config_t`.
* out:
* An array to store the generated samples.
*
* Returns
* -------
* Zero if the sampling was successful. A positive integer is returned if the
* sampled failed because the covariance is not positive definite or if a
* factorization of the covariance was not successful. A negative integer is
* returned if one of the inputs contains an illegal value (non-numerical/NaN).
*/
int htn_hyperplane_truncated_mvn(rng_t* rng, const ht_config_t* conf, double* restrict out);
/* Sample from a MVN with a structured precision matrix and/or structured mean.
*
* Sample from a MVN: N(mean, (A + phi^T * Omega * phi)^-1) or
* N((A + phi^T * Omega * phi)^-1 * phi^T * t, (A + phi^T * Omega * phi)^-1))
* This algorithm in very efficient and ideal when the dimension of matrix A
* is greater than that of matrix Omega.
*
* Parameters
* ----------
* rng:
* A pointer to the `rng_t` struct (The random number generator).
* conf:
* A pointer to the input configuration struct `sp_config_t`.
* out:
* An array to store the generated samples.
*
* Returns
* -------
* Zero if the sampling was successful. A positive integer is returned if the
* sampled failed because the covariance is not positive definite or if a
* factorization of the covariance was not successful. A negative integer is
* returned if one of the inputs contains an illegal value (non-numerical/NaN).
* */
int htn_structured_precision_mvn(rng_t* rng, const sp_config_t* conf, double* restrict out);
#endif