23template <
typename IntType>
28 std::vector<double> prob{1.0};
30 std::vector<double> lower{1.0};
31 std::vector<double> upper{1.0};
32 std::vector<IntType> guide{0};
36 [[nodiscard]] std::string
Name()
const override;
38 [[nodiscard]] IntType
MinValue()
const override {
return 0; }
39 [[nodiscard]] IntType
MaxValue()
const override {
return K - 1; }
44 [[nodiscard]]
double P(
const IntType &k)
const override;
45 [[nodiscard]]
double logP(
const IntType &k)
const override;
46 [[nodiscard]]
double F(
const IntType &k)
const override;
47 [[nodiscard]]
double S(
const IntType &k)
const override;
48 template <std::uniform_random_bit_generator G>
51 [[nodiscard]]
long double Mean()
const override;
52 [[nodiscard]]
long double Variance()
const override;
53 [[nodiscard]] IntType
Mode()
const override;
56 IntType quantileImpl(
double p)
const override;
57 IntType quantileImpl1m(
double p)
const override;
58 std::complex<double> CFImpl(
double t)
const override;
68template <
typename IntType>
71 SetProbabilities(std::move(probabilities));
74template <
typename IntType>
77 std::string str =
"Categorical(";
78 for (
int i = 0; i != K - 1; ++i)
79 str += this->toStringWithPrecision(prob[i]) +
", ";
80 return str + this->toStringWithPrecision(prob[K - 1]) +
")";
83template <
typename IntType>
86 if (probabilities.empty())
87 throw std::invalid_argument(
"Categorical distribution: there should be at least one probability");
88 for (
double probability : probabilities) {
89 if (!(probability >= 0.0))
90 throw std::invalid_argument(
"Categorical distribution: probabilities should be non-negative");
92 double sum = std::accumulate(probabilities.begin(), probabilities.end(), 0.0);
93 if (!(std::fabs(sum - 1.0) <= 1e-12 * probabilities.size()))
94 throw std::invalid_argument(
"Categorical distribution: probability parameters should sum to 1");
95 prob = std::move(probabilities);
102 double partial = 0.0;
103 for (IntType k = 0; k != K; ++k)
104 lower[k] = (partial += prob[k]);
106 for (IntType k = K - 1; k >= 0; --k)
107 upper[k] = (partial += prob[k]);
110 for (IntType j = 0; j != K; ++j) {
111 const double level =
static_cast<double>(j) / K;
112 while (k < K - 1 && lower[k] < level)
118template <
typename IntType>
121 return (k < 0 || k >= K) ? 0.0 : prob[k];
124template <
typename IntType>
127 return std::log(P(k));
130template <
typename IntType>
137 return (2 * k <= K) ? lower[k] : 1.0 - upper[k + 1];
140template <
typename IntType>
147 return (2 * k <= K) ? 1.0 - lower[k] : upper[k + 1];
150template <
typename IntType>
151template <std::uniform_random_bit_generator G>
155 return quantileImpl(U);
158template <
typename IntType>
161 long double sum = 0.0;
162 for (
int i = 1; i != K; ++i)
167template <
typename IntType>
170 long double mean = 0.0, secMom = 0.0;
171 for (
int i = 1; i != K; ++i) {
172 long double aux = i * prob[i];
176 return secMom - mean * mean;
179template <
typename IntType>
182 auto maxProbIt = std::max_element(prob.begin(), prob.end());
183 return std::distance(prob.begin(), maxProbIt);
186template <
typename IntType>
190 const IntType j = std::min(
static_cast<IntType
>(p * K), K - 1);
191 IntType k = guide[j];
192 while (k > 0 && lower[k - 1] >= p)
194 while (k < K - 1 && lower[k] < p)
199template <
typename IntType>
200IntType CategoricalRand<IntType>::quantileImpl1m(
double p)
const
203 IntType low = 0, high = K;
204 while (high - low > 1) {
205 const IntType middle = low + (high - low) / 2;
206 if (upper[middle] > p)
214template <
typename IntType>
215std::complex<double> CategoricalRand<IntType>::CFImpl(
double t)
const
219 for (
int i = 0; i != K; ++i) {
220 re += prob[i] * std::cos(t * i);
221 im += prob[i] * std::sin(t * i);
223 return std::complex<double>(re, im);
The CategoricalRand class
Definition categorical.hpp:25
void SetProbabilities(std::vector< double > &&probabilities)
Definition categorical.hpp:84
IntType MinValue() const override
Definition categorical.hpp:38
long double Variance() const override
Definition categorical.hpp:168
IntType Mode() const override
Mode is the value, which has the largest probability to happen, or, in the case of continuous distrib...
Definition categorical.hpp:180
IntType MaxValue() const override
Definition categorical.hpp:39
std::vector< double > GetProbabilities()
Definition categorical.hpp:42
long double Mean() const override
Definition categorical.hpp:159
Support SupportType() const override
Definition categorical.hpp:37
IntType operator()(G &g) const
Definition categorical.hpp:152
double P(const IntType &k) const override
Definition categorical.hpp:119
std::string Name() const override
Definition categorical.hpp:75
double logP(const IntType &k) const override
Definition categorical.hpp:125
double S(const IntType &k) const override
Definition categorical.hpp:141
double F(const IntType &k) const override
Definition categorical.hpp:131
CategoricalRand(std::vector< double > &&probabilities={1.0})
Definition categorical.hpp:69
The DiscreteDistribution class Abstract class for all discrete distributions.
Definition discrete.hpp:21
The EngineRef class Non-owning, type-erased reference to any uniform random bit generator.
Definition engine/uniform.hpp:116
Real standardNormal(G &g)
Ziggurat algorithm of Marsaglia and Tsang with 256 layers and an explicit sign bit.
Definition variates.hpp:45
Definition bivariate_normal.hpp:10
Support
Shape of the support of a univariate distribution.
Definition univariate.hpp:15