12#ifndef EIGENRAND_MVDISTS_MULTINOMIAL_H
13#define EIGENRAND_MVDISTS_MULTINOMIAL_H
25 template<
typename _Scalar = int32_t, Index Dim = -1>
28 static_assert(std::is_same<_Scalar, int32_t>::value,
"`MultinomialGen` needs integral types.");
30 Matrix<double, Dim, 1> probs;
40 template<
typename WeightTy>
42 : trials{ _trials }, probs{ _weights.template cast<double>() },
discrete(probs.data(), probs.data() + probs.size())
44 eigen_assert(_weights.cols() == 1);
45 for (Index i = 0; i < probs.size(); ++i)
47 eigen_assert(probs[i] >= 0);
58 Index dims()
const {
return probs.rows(); }
60 template<
typename Urng>
61 inline Matrix<_Scalar, Dim, -1> generate(Urng&& urng, Index samples)
63 const Index dim = probs.size();
64 Matrix<_Scalar, Dim, -1> ret(dim, samples);
65 if (trials < std::max(30 * (dim - 1), (Index)100))
67 for (Index s = 0; s < samples; ++s)
69 ret.col(s) = generate(urng);
74 Array<_Scalar, 1, -1> r_trials{ samples }, t{ samples };
75 Map<
const Array<float, -1, 1>> fr_trials{
reinterpret_cast<float*
>(r_trials.data()), samples };
76 Map<Array<float, -1, 1>> ft{
reinterpret_cast<float*
>(t.data()), samples };
77 r_trials.setConstant(trials);
78 ft = impl::binomial(urng, fr_trials, probs[0]);
80 ret.row(0) = t.matrix();
81 double rest_p = 1 - probs[0];
82 for (Index i = 1; i < dim - 1; ++i)
84 ft = impl::binomial(urng, fr_trials, probs[i] / rest_p);
86 ret.row(i) = t.matrix();
90 ret.row(dim - 1) = r_trials;
95 template<
typename Urng>
96 inline Matrix<_Scalar, Dim, 1> generate(Urng&& urng)
98 const Index dim = probs.size();
99 Matrix<_Scalar, Dim, 1> ret(dim);
103 auto d =
discrete.template generate<Matrix<_Scalar, 16, 1>>(16, 1, urng);
104 Matrix<_Scalar, 16, 1> buf;
106 for (i = 0; i < (trials & ~15); i += 16)
109 for (Index j = 0; j < 16; ++j)
114 buf.middleRows(0, trials - i) = d.middleRows(0, trials - i);
115 for (Index j = 0; j < trials - i; ++j)
146 template<
typename IntTy,
typename WeightTy>
159 template<
typename _Scalar, Index Dim = -1>
162 static_assert(std::is_floating_point<_Scalar>::value,
"`DirichletGen` needs floating point types.");
164 Matrix<_Scalar, Dim, 1> alpha;
165 std::vector<GammaGen<_Scalar>> gammas;
173 template<
typename AlphaTy>
177 eigen_assert(_alpha.cols() == 1);
178 for (Index i = 0; i < alpha.size(); ++i)
180 eigen_assert(alpha[i] > 0);
181 gammas.emplace_back(alpha[i]);
188 Index dims()
const {
return alpha.rows(); }
190 template<
typename Urng>
191 inline Matrix<_Scalar, Dim, -1> generate(Urng&& urng, Index samples)
193 const Index dim = alpha.size();
194 Matrix<_Scalar, Dim, -1> ret(dim, samples);
195 Matrix<_Scalar, -1, 1> tmp(samples);
196 for (Index i = 0; i < dim; ++i)
198 tmp = gammas[i].generateLike(tmp, urng);
199 ret.row(i) = tmp.transpose();
201 ret.array().rowwise() /= ret.array().colwise().sum();
205 template<
typename Urng>
206 inline Matrix<_Scalar, Dim, 1> generate(Urng&& urng)
208 const Index dim = alpha.size();
209 Matrix<_Scalar, Dim, 1> ret(dim);
210 for (Index i = 0; i < dim; ++i)
212 ret[i] = gammas[i].template generate<Matrix<_Scalar, 1, 1>>(1, 1, urng)(0);
227 template<
typename AlphaTy>
Generator of reals on a Dirichlet distribution.
Definition: Multinomial.h:161
DirichletGen(const MatrixBase< AlphaTy > &_alpha)
Construct a new Dirichlet generator.
Definition: Multinomial.h:174
Generator of integers on the interval [0, n), where the probability of each individual integer i is p...
Definition: Discrete.h:329
Generator of real vectors on a multinomial distribution.
Definition: Multinomial.h:27
MultinomialGen(_Scalar _trials, const MatrixBase< WeightTy > &_weights)
Construct a new multinomial generator.
Definition: Multinomial.h:41
Base class of all multivariate random vector generators.
Definition: Basic.h:160
auto makeMultinomialGen(IntTy trials, const MatrixBase< WeightTy > &probs) -> MultinomialGen< IntTy, MatrixBase< WeightTy >::RowsAtCompileTime >
helper function constructing Eigen::Rand::MultinomialGen
Definition: Multinomial.h:147
auto makeDirichletGen(const MatrixBase< AlphaTy > &alpha) -> DirichletGen< typename MatrixBase< AlphaTy >::Scalar, MatrixBase< AlphaTy >::RowsAtCompileTime >
helper function constructing Eigen::Rand::DirichletGen
Definition: Multinomial.h:228
const DiscreteType< Derived, Urng > discrete(Index rows, Index cols, Urng &&urng, RealIter first, RealIter last)
generates random integers on the interval [0, n), where the probability of each individual integer i ...
Definition: Discrete.h:1580