tomoto 0.1.4 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/ext/tomoto/ct.cpp +8 -4
- data/ext/tomoto/dmr.cpp +10 -4
- data/ext/tomoto/dt.cpp +13 -4
- data/ext/tomoto/extconf.rb +1 -1
- data/ext/tomoto/gdmr.cpp +14 -6
- data/ext/tomoto/hdp.cpp +9 -4
- data/ext/tomoto/hlda.cpp +9 -4
- data/ext/tomoto/hpa.cpp +9 -4
- data/ext/tomoto/lda.cpp +8 -4
- data/ext/tomoto/llda.cpp +8 -4
- data/ext/tomoto/mglda.cpp +11 -1
- data/ext/tomoto/pa.cpp +9 -4
- data/ext/tomoto/plda.cpp +8 -4
- data/ext/tomoto/slda.cpp +13 -5
- data/lib/tomoto/gdmr.rb +2 -2
- data/lib/tomoto/version.rb +1 -1
- data/vendor/EigenRand/EigenRand/Core.h +6 -1107
- data/vendor/EigenRand/EigenRand/Dists/Basic.h +490 -43
- data/vendor/EigenRand/EigenRand/Dists/Discrete.h +916 -285
- data/vendor/EigenRand/EigenRand/Dists/GammaPoisson.h +85 -36
- data/vendor/EigenRand/EigenRand/Dists/NormalExp.h +1038 -290
- data/vendor/EigenRand/EigenRand/EigenRand +2 -2
- data/vendor/EigenRand/EigenRand/Macro.h +4 -4
- data/vendor/EigenRand/EigenRand/MorePacketMath.h +54 -22
- data/vendor/EigenRand/EigenRand/MvDists/Multinomial.h +222 -0
- data/vendor/EigenRand/EigenRand/MvDists/MvNormal.h +492 -0
- data/vendor/EigenRand/EigenRand/PacketFilter.h +2 -2
- data/vendor/EigenRand/EigenRand/PacketRandomEngine.h +2 -2
- data/vendor/EigenRand/EigenRand/RandUtils.h +65 -11
- data/vendor/EigenRand/EigenRand/doc.h +142 -25
- data/vendor/EigenRand/LICENSE +1 -1
- data/vendor/EigenRand/README.md +109 -24
- data/vendor/tomotopy/README.kr.rst +27 -6
- data/vendor/tomotopy/README.rst +29 -8
- data/vendor/tomotopy/src/Labeling/FoRelevance.cpp +60 -12
- data/vendor/tomotopy/src/Labeling/FoRelevance.h +2 -2
- data/vendor/tomotopy/src/Labeling/Phraser.hpp +33 -21
- data/vendor/tomotopy/src/TopicModel/CT.h +8 -5
- data/vendor/tomotopy/src/TopicModel/CTModel.cpp +2 -6
- data/vendor/tomotopy/src/TopicModel/CTModel.hpp +29 -23
- data/vendor/tomotopy/src/TopicModel/DMR.h +33 -4
- data/vendor/tomotopy/src/TopicModel/DMRModel.cpp +2 -6
- data/vendor/tomotopy/src/TopicModel/DMRModel.hpp +231 -57
- data/vendor/tomotopy/src/TopicModel/DT.h +24 -5
- data/vendor/tomotopy/src/TopicModel/DTModel.cpp +2 -8
- data/vendor/tomotopy/src/TopicModel/DTModel.hpp +41 -28
- data/vendor/tomotopy/src/TopicModel/GDMR.h +31 -5
- data/vendor/tomotopy/src/TopicModel/GDMRModel.cpp +2 -7
- data/vendor/tomotopy/src/TopicModel/GDMRModel.hpp +211 -104
- data/vendor/tomotopy/src/TopicModel/HDP.h +11 -2
- data/vendor/tomotopy/src/TopicModel/HDPModel.cpp +2 -6
- data/vendor/tomotopy/src/TopicModel/HDPModel.hpp +52 -45
- data/vendor/tomotopy/src/TopicModel/HLDA.h +11 -2
- data/vendor/tomotopy/src/TopicModel/HLDAModel.cpp +2 -6
- data/vendor/tomotopy/src/TopicModel/HLDAModel.hpp +13 -16
- data/vendor/tomotopy/src/TopicModel/HPA.h +5 -2
- data/vendor/tomotopy/src/TopicModel/HPAModel.cpp +2 -6
- data/vendor/tomotopy/src/TopicModel/HPAModel.hpp +51 -21
- data/vendor/tomotopy/src/TopicModel/LDA.h +9 -2
- data/vendor/tomotopy/src/TopicModel/LDACVB0Model.hpp +8 -8
- data/vendor/tomotopy/src/TopicModel/LDAModel.cpp +2 -6
- data/vendor/tomotopy/src/TopicModel/LDAModel.hpp +70 -28
- data/vendor/tomotopy/src/TopicModel/LLDA.h +1 -2
- data/vendor/tomotopy/src/TopicModel/LLDAModel.cpp +2 -6
- data/vendor/tomotopy/src/TopicModel/LLDAModel.hpp +22 -12
- data/vendor/tomotopy/src/TopicModel/MGLDA.h +12 -3
- data/vendor/tomotopy/src/TopicModel/MGLDAModel.cpp +2 -10
- data/vendor/tomotopy/src/TopicModel/MGLDAModel.hpp +42 -19
- data/vendor/tomotopy/src/TopicModel/PA.h +9 -4
- data/vendor/tomotopy/src/TopicModel/PAModel.cpp +2 -6
- data/vendor/tomotopy/src/TopicModel/PAModel.hpp +48 -25
- data/vendor/tomotopy/src/TopicModel/PLDA.h +13 -2
- data/vendor/tomotopy/src/TopicModel/PLDAModel.cpp +2 -6
- data/vendor/tomotopy/src/TopicModel/PLDAModel.hpp +27 -19
- data/vendor/tomotopy/src/TopicModel/PT.h +12 -5
- data/vendor/tomotopy/src/TopicModel/PTModel.cpp +2 -3
- data/vendor/tomotopy/src/TopicModel/PTModel.hpp +29 -14
- data/vendor/tomotopy/src/TopicModel/SLDA.h +18 -6
- data/vendor/tomotopy/src/TopicModel/SLDAModel.cpp +2 -10
- data/vendor/tomotopy/src/TopicModel/SLDAModel.hpp +93 -43
- data/vendor/tomotopy/src/TopicModel/TopicModel.hpp +58 -23
- data/vendor/tomotopy/src/Utils/AliasMethod.hpp +6 -6
- data/vendor/tomotopy/src/Utils/Dictionary.h +11 -0
- data/vendor/tomotopy/src/Utils/SharedString.hpp +26 -1
- data/vendor/tomotopy/src/Utils/Trie.hpp +46 -21
- data/vendor/tomotopy/src/Utils/Utils.hpp +99 -14
- data/vendor/tomotopy/src/Utils/exception.h +1 -1
- data/vendor/tomotopy/src/Utils/math.h +5 -7
- data/vendor/tomotopy/src/Utils/serializer.hpp +329 -201
- data/vendor/tomotopy/src/Utils/text.hpp +8 -0
- data/vendor/tomotopy/src/Utils/tvector.hpp +49 -7
- metadata +9 -7
|
@@ -0,0 +1,492 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file MvNormal.h
|
|
3
|
+
* @author bab2min (bab2min@gmail.com)
|
|
4
|
+
* @brief
|
|
5
|
+
* @version 0.3.0
|
|
6
|
+
* @date 2020-10-07
|
|
7
|
+
*
|
|
8
|
+
* @copyright Copyright (c) 2020
|
|
9
|
+
*
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
#ifndef EIGENRAND_MVDISTS_MVNORMAL_H
|
|
13
|
+
#define EIGENRAND_MVDISTS_MVNORMAL_H
|
|
14
|
+
|
|
15
|
+
namespace Eigen
|
|
16
|
+
{
|
|
17
|
+
namespace Rand
|
|
18
|
+
{
|
|
19
|
+
namespace detail
|
|
20
|
+
{
|
|
21
|
+
template<typename _Scalar, Index Dim, typename _Mat>
|
|
22
|
+
Matrix<_Scalar, Dim, Dim> get_lt(const MatrixBase<_Mat>& mat)
|
|
23
|
+
{
|
|
24
|
+
LLT<Matrix<_Scalar, Dim, Dim>> llt(mat);
|
|
25
|
+
if (llt.info() == Eigen::Success)
|
|
26
|
+
{
|
|
27
|
+
return llt.matrixL();
|
|
28
|
+
}
|
|
29
|
+
else
|
|
30
|
+
{
|
|
31
|
+
SelfAdjointEigenSolver<Matrix<_Scalar, Dim, Dim>> solver(mat);
|
|
32
|
+
if (solver.info() != Eigen::Success)
|
|
33
|
+
{
|
|
34
|
+
throw std::runtime_error{ "The matrix cannot be solved!" };
|
|
35
|
+
}
|
|
36
|
+
return solver.eigenvectors() * solver.eigenvalues().cwiseMax(0).cwiseSqrt().asDiagonal();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
class FullMatrix {};
|
|
41
|
+
class LowerTriangular {};
|
|
42
|
+
class InvLowerTriangular {};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
constexpr detail::FullMatrix full_matrix;
|
|
46
|
+
constexpr detail::LowerTriangular lower_triangular;
|
|
47
|
+
constexpr detail::InvLowerTriangular inv_lower_triangular;
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @brief Generator of real vectors on a multivariate normal distribution
|
|
52
|
+
*
|
|
53
|
+
* @tparam _Scalar Numeric type
|
|
54
|
+
* @tparam Dim number of dimensions, or `Eigen::Dynamic`
|
|
55
|
+
*/
|
|
56
|
+
template<typename _Scalar, Index Dim = -1>
|
|
57
|
+
class MvNormalGen : public MvVecGenBase<MvNormalGen<_Scalar, Dim>, _Scalar, Dim>
|
|
58
|
+
{
|
|
59
|
+
Matrix<_Scalar, Dim, 1> mean;
|
|
60
|
+
Matrix<_Scalar, Dim, Dim> lt;
|
|
61
|
+
StdNormalGen<_Scalar> stdnorm;
|
|
62
|
+
|
|
63
|
+
public:
|
|
64
|
+
/**
|
|
65
|
+
* @brief Construct a new multivariate normal generator from lower triangular matrix of decomposed covariance
|
|
66
|
+
*
|
|
67
|
+
* @tparam MeanTy
|
|
68
|
+
* @tparam LTTy
|
|
69
|
+
* @param _mean mean vector of the distribution
|
|
70
|
+
* @param _lt lower triangular matrix of decomposed covariance
|
|
71
|
+
*/
|
|
72
|
+
template<typename MeanTy, typename LTTy>
|
|
73
|
+
MvNormalGen(const MatrixBase<MeanTy>& _mean, const MatrixBase<LTTy>& _lt, detail::LowerTriangular)
|
|
74
|
+
: mean{ _mean }, lt{ _lt }
|
|
75
|
+
{
|
|
76
|
+
eigen_assert(_mean.cols() == 1 && _mean.rows() == _lt.rows() && _lt.rows() == _lt.cols());
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* @brief Construct a new multivariate normal generator from covariance matrix
|
|
81
|
+
*
|
|
82
|
+
* @tparam MeanTy
|
|
83
|
+
* @tparam CovTy
|
|
84
|
+
* @param _mean mean vector of the distribution
|
|
85
|
+
* @param _cov covariance matrix (should be positive semi-definite)
|
|
86
|
+
*/
|
|
87
|
+
template<typename MeanTy, typename CovTy>
|
|
88
|
+
MvNormalGen(const MatrixBase<MeanTy>& _mean, const MatrixBase<CovTy>& _cov, detail::FullMatrix = {})
|
|
89
|
+
: MvNormalGen{ _mean, detail::template get_lt<_Scalar, Dim>(_cov), lower_triangular }
|
|
90
|
+
{
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
MvNormalGen(const MvNormalGen&) = default;
|
|
94
|
+
MvNormalGen(MvNormalGen&&) = default;
|
|
95
|
+
|
|
96
|
+
MvNormalGen& operator=(const MvNormalGen&) = default;
|
|
97
|
+
MvNormalGen& operator=(MvNormalGen&&) = default;
|
|
98
|
+
|
|
99
|
+
Index dims() const { return mean.rows(); }
|
|
100
|
+
|
|
101
|
+
template<typename Urng>
|
|
102
|
+
inline auto generate(Urng&& urng, Index samples)
|
|
103
|
+
-> decltype((lt * stdnorm.template generate<Matrix<_Scalar, Dim, -1>>(mean.rows(), samples, std::forward<Urng>(urng))).colwise() + mean)
|
|
104
|
+
{
|
|
105
|
+
return (lt * stdnorm.template generate<Matrix<_Scalar, Dim, -1>>(mean.rows(), samples, std::forward<Urng>(urng))).colwise() + mean;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
template<typename Urng>
|
|
109
|
+
inline auto generate(Urng&& urng)
|
|
110
|
+
-> decltype((lt * stdnorm.template generate<Matrix<_Scalar, Dim, 1>>(mean.rows(), 1, std::forward<Urng>(urng))).colwise() + mean)
|
|
111
|
+
{
|
|
112
|
+
return (lt * stdnorm.template generate<Matrix<_Scalar, Dim, 1>>(mean.rows(), 1, std::forward<Urng>(urng))).colwise() + mean;
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* @brief helper function constructing Eigen::Rand::MvNormal
|
|
118
|
+
*
|
|
119
|
+
* @tparam MeanTy
|
|
120
|
+
* @tparam CovTy
|
|
121
|
+
* @param mean mean vector of the distribution
|
|
122
|
+
* @param cov covariance matrix (should be positive semi-definite)
|
|
123
|
+
*/
|
|
124
|
+
template<typename MeanTy, typename CovTy>
|
|
125
|
+
inline auto makeMvNormalGen(const MatrixBase<MeanTy>& mean, const MatrixBase<CovTy>& cov)
|
|
126
|
+
-> MvNormalGen<typename MatrixBase<MeanTy>::Scalar, MatrixBase<MeanTy>::RowsAtCompileTime>
|
|
127
|
+
{
|
|
128
|
+
static_assert(
|
|
129
|
+
std::is_same<typename MatrixBase<MeanTy>::Scalar, typename MatrixBase<CovTy>::Scalar>::value,
|
|
130
|
+
"Derived::Scalar must be the same with `mean` and `cov`'s Scalar."
|
|
131
|
+
);
|
|
132
|
+
static_assert(
|
|
133
|
+
MatrixBase<MeanTy>::RowsAtCompileTime == MatrixBase<CovTy>::RowsAtCompileTime &&
|
|
134
|
+
MatrixBase<CovTy>::RowsAtCompileTime == MatrixBase<CovTy>::ColsAtCompileTime,
|
|
135
|
+
"assert: mean.RowsAtCompileTime == cov.RowsAtCompileTime && cov.RowsAtCompileTime == cov.ColsAtCompileTime"
|
|
136
|
+
);
|
|
137
|
+
return { mean, cov };
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* @brief helper function constructing Eigen::Rand::MvNormal
|
|
142
|
+
*
|
|
143
|
+
* @tparam MeanTy
|
|
144
|
+
* @tparam LTTy
|
|
145
|
+
* @param mean mean vector of the distribution
|
|
146
|
+
* @param lt lower triangular matrix of decomposed covariance
|
|
147
|
+
*/
|
|
148
|
+
template<typename MeanTy, typename LTTy>
|
|
149
|
+
inline auto makeMvNormalGenFromLt(const MatrixBase<MeanTy>& mean, const MatrixBase<LTTy>& lt)
|
|
150
|
+
-> MvNormalGen<typename MatrixBase<MeanTy>::Scalar, MatrixBase<MeanTy>::RowsAtCompileTime>
|
|
151
|
+
{
|
|
152
|
+
static_assert(
|
|
153
|
+
std::is_same<typename MatrixBase<MeanTy>::Scalar, typename MatrixBase<LTTy>::Scalar>::value,
|
|
154
|
+
"Derived::Scalar must be the same with `mean` and `lt`'s Scalar."
|
|
155
|
+
);
|
|
156
|
+
static_assert(
|
|
157
|
+
MatrixBase<MeanTy>::RowsAtCompileTime == MatrixBase<LTTy>::RowsAtCompileTime &&
|
|
158
|
+
MatrixBase<LTTy>::RowsAtCompileTime == MatrixBase<LTTy>::ColsAtCompileTime,
|
|
159
|
+
"assert: mean.RowsAtCompileTime == lt.RowsAtCompileTime && lt.RowsAtCompileTime == lt.ColsAtCompileTime"
|
|
160
|
+
);
|
|
161
|
+
return { mean, lt, lower_triangular };
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* @brief Generator of real matrices on a Wishart distribution
|
|
166
|
+
*
|
|
167
|
+
* @tparam _Scalar
|
|
168
|
+
* @tparam Dim number of dimensions, or `Eigen::Dynamic`
|
|
169
|
+
*/
|
|
170
|
+
template<typename _Scalar, Index Dim>
|
|
171
|
+
class WishartGen : public MvMatGenBase<WishartGen<_Scalar, Dim>, _Scalar, Dim>
|
|
172
|
+
{
|
|
173
|
+
Index df;
|
|
174
|
+
Matrix<_Scalar, Dim, Dim> chol;
|
|
175
|
+
StdNormalGen<_Scalar> stdnorm;
|
|
176
|
+
std::vector<ChiSquaredGen<_Scalar>> chisqs;
|
|
177
|
+
public:
|
|
178
|
+
/**
|
|
179
|
+
* @brief Construct a new Wishart generator from lower triangular matrix of decomposed scale
|
|
180
|
+
*
|
|
181
|
+
* @tparam ScaleTy
|
|
182
|
+
* @param _df degrees of freedom
|
|
183
|
+
* @param _lt lower triangular matrix of decomposed scale
|
|
184
|
+
*/
|
|
185
|
+
template<typename ScaleTy>
|
|
186
|
+
WishartGen(Index _df, const MatrixBase<ScaleTy>& _lt, detail::LowerTriangular)
|
|
187
|
+
: df{ _df }, chol{ _lt }
|
|
188
|
+
{
|
|
189
|
+
eigen_assert(df > chol.rows() - 1);
|
|
190
|
+
eigen_assert(chol.rows() == chol.cols());
|
|
191
|
+
|
|
192
|
+
for (Index i = 0; i < chol.rows(); ++i)
|
|
193
|
+
{
|
|
194
|
+
chisqs.emplace_back(df - i);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* @brief Construct a new Wishart generator from scale matrix
|
|
200
|
+
*
|
|
201
|
+
* @tparam ScaleTy
|
|
202
|
+
* @param _df degrees of freedom
|
|
203
|
+
* @param _lt scale matrix (should be positive definitive)
|
|
204
|
+
*/
|
|
205
|
+
template<typename ScaleTy>
|
|
206
|
+
WishartGen(Index _df, const MatrixBase<ScaleTy>& _scale, detail::FullMatrix = {})
|
|
207
|
+
: WishartGen{ _df, detail::template get_lt<_Scalar, Dim>(_scale), lower_triangular }
|
|
208
|
+
{
|
|
209
|
+
eigen_assert(_scale.rows() == _scale.cols());
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
WishartGen(const WishartGen&) = default;
|
|
213
|
+
WishartGen(WishartGen&&) = default;
|
|
214
|
+
|
|
215
|
+
WishartGen& operator=(const WishartGen&) = default;
|
|
216
|
+
WishartGen& operator=(WishartGen&&) = default;
|
|
217
|
+
|
|
218
|
+
Index dims() const { return chol.rows(); }
|
|
219
|
+
|
|
220
|
+
template<typename Urng>
|
|
221
|
+
inline Matrix<_Scalar, Dim, -1> generate(Urng&& urng, Index samples)
|
|
222
|
+
{
|
|
223
|
+
const Index dim = chol.rows();
|
|
224
|
+
const Index normSamples = samples * dim * (dim - 1) / 2;
|
|
225
|
+
using ArrayXs = Array<_Scalar, -1, 1>;
|
|
226
|
+
Matrix<_Scalar, Dim, -1> rand_mat(dim, dim * samples), tmp(dim, dim * samples);
|
|
227
|
+
|
|
228
|
+
_Scalar* ptr = tmp.data();
|
|
229
|
+
Map<ArrayXs>{ ptr, normSamples } = stdnorm.template generate<ArrayXs>(normSamples, 1, urng);
|
|
230
|
+
for (Index j = 0; j < samples; ++j)
|
|
231
|
+
{
|
|
232
|
+
for (Index i = 0; i < dim - 1; ++i)
|
|
233
|
+
{
|
|
234
|
+
rand_mat.col(i + j * dim).tail(dim - 1 - i) = Map<ArrayXs>{ ptr, dim - 1 - i };
|
|
235
|
+
ptr += dim - 1 - i;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
for (Index i = 0; i < dim; ++i)
|
|
240
|
+
{
|
|
241
|
+
_Scalar* ptr = tmp.data();
|
|
242
|
+
Map<ArrayXs>{ ptr, samples } = chisqs[i].template generate<ArrayXs>(samples, 1, urng).sqrt();
|
|
243
|
+
for (Index j = 0; j < samples; ++j)
|
|
244
|
+
{
|
|
245
|
+
rand_mat(i, i + j * dim) = *ptr++;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
for (Index j = 0; j < samples; ++j)
|
|
250
|
+
{
|
|
251
|
+
rand_mat.middleCols(j * dim, dim).template triangularView<StrictlyUpper>().setZero();
|
|
252
|
+
}
|
|
253
|
+
tmp.noalias() = chol * rand_mat;
|
|
254
|
+
|
|
255
|
+
for (Index j = 0; j < samples; ++j)
|
|
256
|
+
{
|
|
257
|
+
auto t = tmp.middleCols(j * dim, dim);
|
|
258
|
+
rand_mat.middleCols(j * dim, dim).noalias() = t * t.transpose();
|
|
259
|
+
}
|
|
260
|
+
return rand_mat;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
template<typename Urng>
|
|
264
|
+
inline Matrix<_Scalar, Dim, -1> generate(Urng&& urng)
|
|
265
|
+
{
|
|
266
|
+
const Index dim = chol.rows();
|
|
267
|
+
const Index normSamples = dim * (dim - 1) / 2;
|
|
268
|
+
using ArrayXs = Array<_Scalar, -1, 1>;
|
|
269
|
+
Matrix<_Scalar, Dim, Dim> rand_mat(dim, dim);
|
|
270
|
+
Map<ArrayXs>{ rand_mat.data(), normSamples } = stdnorm.template generate<ArrayXs>(normSamples, 1, urng);
|
|
271
|
+
|
|
272
|
+
for (Index i = 0; i < dim / 2; ++i)
|
|
273
|
+
{
|
|
274
|
+
rand_mat.col(dim - 2 - i).tail(i + 1) = rand_mat.col(i).head(i + 1);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
for (Index i = 0; i < dim; ++i)
|
|
278
|
+
{
|
|
279
|
+
rand_mat(i, i) = chisqs[i].template generate<Array<_Scalar, 1, 1>>(1, 1, urng).sqrt()(0);
|
|
280
|
+
}
|
|
281
|
+
rand_mat.template triangularView<StrictlyUpper>().setZero();
|
|
282
|
+
|
|
283
|
+
auto t = (chol * rand_mat).eval();
|
|
284
|
+
return (t * t.transpose()).eval();
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* @brief helper function constructing Eigen::Rand::WishartGen
|
|
290
|
+
*
|
|
291
|
+
* @tparam ScaleTy
|
|
292
|
+
* @param df degrees of freedom
|
|
293
|
+
* @param scale scale matrix (should be positive definitive)
|
|
294
|
+
*/
|
|
295
|
+
template<typename ScaleTy>
|
|
296
|
+
inline auto makeWishartGen(Index df, const MatrixBase<ScaleTy>& scale)
|
|
297
|
+
-> WishartGen<typename MatrixBase<ScaleTy>::Scalar, MatrixBase<ScaleTy>::RowsAtCompileTime>
|
|
298
|
+
{
|
|
299
|
+
static_assert(
|
|
300
|
+
MatrixBase<ScaleTy>::RowsAtCompileTime == MatrixBase<ScaleTy>::ColsAtCompileTime,
|
|
301
|
+
"assert: scale.RowsAtCompileTime == scale.ColsAtCompileTime"
|
|
302
|
+
);
|
|
303
|
+
return { df, scale };
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* @brief helper function constructing Eigen::Rand::WishartGen
|
|
308
|
+
*
|
|
309
|
+
* @tparam LTTy
|
|
310
|
+
* @param df degrees of freedom
|
|
311
|
+
* @param lt lower triangular matrix of decomposed scale
|
|
312
|
+
*/
|
|
313
|
+
template<typename LTTy>
|
|
314
|
+
inline auto makeWishartGenFromLt(Index df, const MatrixBase<LTTy>& lt)
|
|
315
|
+
-> WishartGen<typename MatrixBase<LTTy>::Scalar, MatrixBase<LTTy>::RowsAtCompileTime>
|
|
316
|
+
{
|
|
317
|
+
static_assert(
|
|
318
|
+
MatrixBase<LTTy>::RowsAtCompileTime == MatrixBase<LTTy>::ColsAtCompileTime,
|
|
319
|
+
"assert: lt.RowsAtCompileTime == lt.ColsAtCompileTime"
|
|
320
|
+
);
|
|
321
|
+
return { df, lt, lower_triangular };
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* @brief Generator of real matrices on a inverse Wishart distribution
|
|
326
|
+
*
|
|
327
|
+
* @tparam _Scalar
|
|
328
|
+
* @tparam Dim number of dimensions, or `Eigen::Dynamic`
|
|
329
|
+
*/
|
|
330
|
+
template<typename _Scalar, Index Dim>
|
|
331
|
+
class InvWishartGen : public MvMatGenBase<InvWishartGen<_Scalar, Dim>, _Scalar, Dim>
|
|
332
|
+
{
|
|
333
|
+
Index df;
|
|
334
|
+
Matrix<_Scalar, Dim, Dim> chol;
|
|
335
|
+
StdNormalGen<_Scalar> stdnorm;
|
|
336
|
+
std::vector<ChiSquaredGen<_Scalar>> chisqs;
|
|
337
|
+
public:
|
|
338
|
+
/**
|
|
339
|
+
* @brief Construct a new inverse Wishart generator
|
|
340
|
+
*
|
|
341
|
+
* @tparam ScaleTy
|
|
342
|
+
* @param _df degrees of freedom
|
|
343
|
+
* @param _ilt lower triangular matrix of decomposed inverse scale
|
|
344
|
+
*/
|
|
345
|
+
template<typename ScaleTy>
|
|
346
|
+
InvWishartGen(Index _df, const MatrixBase<ScaleTy>& _ilt, detail::InvLowerTriangular)
|
|
347
|
+
: df{ _df }, chol{ _ilt }
|
|
348
|
+
{
|
|
349
|
+
eigen_assert(df > chol.rows() - 1);
|
|
350
|
+
eigen_assert(chol.rows() == chol.cols());
|
|
351
|
+
|
|
352
|
+
for (Index i = 0; i < chol.rows(); ++i)
|
|
353
|
+
{
|
|
354
|
+
chisqs.emplace_back(df - i);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* @brief Construct a new inverse Wishart generator
|
|
360
|
+
*
|
|
361
|
+
* @tparam ScaleTy
|
|
362
|
+
* @param _df degrees of freedom
|
|
363
|
+
* @param _scale scale matrix (should be positive definitive)
|
|
364
|
+
*/
|
|
365
|
+
template<typename ScaleTy>
|
|
366
|
+
InvWishartGen(Index _df, const MatrixBase<ScaleTy>& _scale, detail::FullMatrix = {})
|
|
367
|
+
: InvWishartGen{ _df, detail::template get_lt<_Scalar, Dim>(_scale.inverse()), inv_lower_triangular }
|
|
368
|
+
{
|
|
369
|
+
eigen_assert(_scale.rows() == _scale.cols());
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
InvWishartGen(const InvWishartGen&) = default;
|
|
373
|
+
InvWishartGen(InvWishartGen&&) = default;
|
|
374
|
+
|
|
375
|
+
InvWishartGen& operator=(const InvWishartGen&) = default;
|
|
376
|
+
InvWishartGen& operator=(InvWishartGen&&) = default;
|
|
377
|
+
|
|
378
|
+
Index dims() const { return chol.rows(); }
|
|
379
|
+
|
|
380
|
+
template<typename Urng>
|
|
381
|
+
inline Matrix<_Scalar, Dim, -1> generate(Urng&& urng, Index samples)
|
|
382
|
+
{
|
|
383
|
+
const Index dim = chol.rows();
|
|
384
|
+
const Index normSamples = samples * dim * (dim - 1) / 2;
|
|
385
|
+
using ArrayXs = Array<_Scalar, -1, 1>;
|
|
386
|
+
Matrix<_Scalar, Dim, -1> rand_mat(dim, dim * samples), tmp(dim, dim * samples);
|
|
387
|
+
|
|
388
|
+
_Scalar* ptr = tmp.data();
|
|
389
|
+
Map<ArrayXs>{ ptr, normSamples } = stdnorm.template generate<ArrayXs>(normSamples, 1, urng);
|
|
390
|
+
for (Index j = 0; j < samples; ++j)
|
|
391
|
+
{
|
|
392
|
+
for (Index i = 0; i < dim - 1; ++i)
|
|
393
|
+
{
|
|
394
|
+
rand_mat.col(i + j * dim).tail(dim - 1 - i) = Map<ArrayXs>{ ptr, dim - 1 - i };
|
|
395
|
+
ptr += dim - 1 - i;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
for (Index i = 0; i < dim; ++i)
|
|
400
|
+
{
|
|
401
|
+
_Scalar* ptr = tmp.data();
|
|
402
|
+
Map<ArrayXs>{ ptr, samples } = chisqs[i].template generate<ArrayXs>(samples, 1, urng).sqrt();
|
|
403
|
+
for (Index j = 0; j < samples; ++j)
|
|
404
|
+
{
|
|
405
|
+
rand_mat(i, i + j * dim) = *ptr++;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
for (Index j = 0; j < samples; ++j)
|
|
410
|
+
{
|
|
411
|
+
rand_mat.middleCols(j * dim, dim).template triangularView<StrictlyUpper>().setZero();
|
|
412
|
+
}
|
|
413
|
+
tmp.noalias() = chol * rand_mat;
|
|
414
|
+
|
|
415
|
+
auto id = Eigen::Matrix<_Scalar, Dim, Dim>::Identity(dim, dim);
|
|
416
|
+
for (Index j = 0; j < samples; ++j)
|
|
417
|
+
{
|
|
418
|
+
auto t = tmp.middleCols(j * dim, dim);
|
|
419
|
+
auto u = rand_mat.middleCols(j * dim, dim);
|
|
420
|
+
u.noalias() = t.template triangularView<Lower>().solve(id);
|
|
421
|
+
t.noalias() = u.transpose() * u;
|
|
422
|
+
}
|
|
423
|
+
return tmp;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
template<typename Urng>
|
|
427
|
+
inline Matrix<_Scalar, Dim, -1> generate(Urng&& urng)
|
|
428
|
+
{
|
|
429
|
+
const Index dim = chol.rows();
|
|
430
|
+
const Index normSamples = dim * (dim - 1) / 2;
|
|
431
|
+
using ArrayXs = Array<_Scalar, -1, 1>;
|
|
432
|
+
Matrix<_Scalar, Dim, Dim> rand_mat(dim, dim);
|
|
433
|
+
Map<ArrayXs>{ rand_mat.data(), normSamples } = stdnorm.template generate<ArrayXs>(normSamples, 1, urng);
|
|
434
|
+
|
|
435
|
+
for (Index i = 0; i < dim / 2; ++i)
|
|
436
|
+
{
|
|
437
|
+
rand_mat.col(dim - 2 - i).tail(i + 1) = rand_mat.col(i).head(i + 1);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
for (Index i = 0; i < dim; ++i)
|
|
441
|
+
{
|
|
442
|
+
rand_mat(i, i) = chisqs[i].template generate<Array<_Scalar, 1, 1>>(1, 1, urng).sqrt()(0);
|
|
443
|
+
}
|
|
444
|
+
rand_mat.template triangularView<StrictlyUpper>().setZero();
|
|
445
|
+
|
|
446
|
+
auto t = (chol * rand_mat).eval();
|
|
447
|
+
auto id = Eigen::Matrix<_Scalar, Dim, Dim>::Identity(dim, dim);
|
|
448
|
+
rand_mat.noalias() = t.template triangularView<Lower>().solve(id);
|
|
449
|
+
|
|
450
|
+
return (rand_mat.transpose() * rand_mat).eval();
|
|
451
|
+
}
|
|
452
|
+
};
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* @brief helper function constructing Eigen::Rand::InvWishartGen
|
|
456
|
+
*
|
|
457
|
+
* @tparam ScaleTy
|
|
458
|
+
* @param df degrees of freedom
|
|
459
|
+
* @param scale scale matrix
|
|
460
|
+
*/
|
|
461
|
+
template<typename ScaleTy>
|
|
462
|
+
inline auto makeInvWishartGen(Index df, const MatrixBase<ScaleTy>& scale)
|
|
463
|
+
-> InvWishartGen<typename MatrixBase<ScaleTy>::Scalar, MatrixBase<ScaleTy>::RowsAtCompileTime>
|
|
464
|
+
{
|
|
465
|
+
static_assert(
|
|
466
|
+
MatrixBase<ScaleTy>::RowsAtCompileTime == MatrixBase<ScaleTy>::ColsAtCompileTime,
|
|
467
|
+
"assert: scale.RowsAtCompileTime == scale.ColsAtCompileTime"
|
|
468
|
+
);
|
|
469
|
+
return { df, scale };
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
* @brief helper function constructing Eigen::Rand::InvWishartGen
|
|
474
|
+
*
|
|
475
|
+
* @tparam ILTTy
|
|
476
|
+
* @param df degrees of freedom
|
|
477
|
+
* @param ilt lower triangular matrix of decomposed inverse scale
|
|
478
|
+
*/
|
|
479
|
+
template<typename ILTTy>
|
|
480
|
+
inline auto makeInvWishartGenFromIlt(Index df, const MatrixBase<ILTTy>& ilt)
|
|
481
|
+
-> InvWishartGen<typename MatrixBase<ILTTy>::Scalar, MatrixBase<ILTTy>::RowsAtCompileTime>
|
|
482
|
+
{
|
|
483
|
+
static_assert(
|
|
484
|
+
MatrixBase<ILTTy>::RowsAtCompileTime == MatrixBase<ILTTy>::ColsAtCompileTime,
|
|
485
|
+
"assert: ilt.RowsAtCompileTime == ilt.ColsAtCompileTime"
|
|
486
|
+
);
|
|
487
|
+
return { df, ilt, inv_lower_triangular };
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
#endif
|