RandLib 2.0.0
Probability distributions, fitting, and heavy-tail tools for C++20
Loading...
Searching...
No Matches
beta_binomial.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <functional>
4
10
11namespace randlib
12{
13
23template <typename IntType>
24class BetaBinomialRand final : public DiscreteDistribution<IntType>
25{
26 IntType variate(detail::EngineRef g) const override { return (*this)(g); }
27 void sample(detail::EngineRef g, std::span<IntType> outputData) const override;
28
29 IntType n = 1;
30 double pmfCoef = 0;
32
33public:
34 BetaBinomialRand(IntType number = 1, double shape1 = 1, double shape2 = 1);
35 [[nodiscard]] std::string Name() const override;
36 [[nodiscard]] Support SupportType() const override { return Support::Finite; }
37 [[nodiscard]] IntType MinValue() const override { return 0; }
38 [[nodiscard]] IntType MaxValue() const override { return n; }
39
40 void SetParameters(IntType number, double shape1, double shape2);
41 [[nodiscard]] inline IntType GetNumber() const noexcept { return n; }
42 [[nodiscard]] inline double GetAlpha() const { return B.GetAlpha(); }
43 [[nodiscard]] inline double GetBeta() const { return B.GetBeta(); }
44
45 [[nodiscard]] double P(const IntType &k) const override;
46 [[nodiscard]] double logP(const IntType &k) const override;
47 [[nodiscard]] double F(const IntType &k) const override;
48
49private:
50 template <std::uniform_random_bit_generator G>
51 IntType VariateUniform(G &g) const;
52 template <std::uniform_random_bit_generator G>
53 IntType VariateBeta(G &g) const;
54
55public:
56 template <std::uniform_random_bit_generator G>
57 [[nodiscard]] IntType operator()(G &g) const;
58
59 [[nodiscard]] long double Mean() const override;
60 [[nodiscard]] long double Variance() const override;
61 [[nodiscard]] IntType Mode() const override;
62 [[nodiscard]] long double Skewness() const override;
63 [[nodiscard]] long double ExcessKurtosis() const override;
64};
65
66} // namespace randlib
67
70
71namespace randlib
72{
73
74template <typename IntType>
75BetaBinomialRand<IntType>::BetaBinomialRand(IntType number, double shape1, double shape2)
76{
77 SetParameters(number, shape1, shape2);
78}
79
80template <typename IntType>
82{
83 return "Beta-Binomial(" + this->toStringWithPrecision(GetNumber()) + ", " +
84 this->toStringWithPrecision(GetAlpha()) + ", " + this->toStringWithPrecision(GetBeta()) + ")";
85}
86
87template <typename IntType>
88void BetaBinomialRand<IntType>::SetParameters(IntType number, double shape1, double shape2)
89{
90 if (!(shape1 > 0.0 && shape2 > 0.0))
91 throw std::invalid_argument("Beta-Binomial distribution: shape parameters should be positive");
92 if (!(number > 0))
93 throw std::invalid_argument("Beta-Binomial distribution: number should be positive");
94 n = number;
95 B.SetShapes(shape1, shape2);
96 pmfCoef = math::lfact(n);
97 pmfCoef -= std::lgammal(B.GetAlpha() + B.GetBeta() + n);
98 pmfCoef -= B.GetLogBetaFunction();
99}
100
101template <typename IntType>
102double BetaBinomialRand<IntType>::P(const IntType &k) const
103{
104 return (k < 0 || k > n) ? 0.0 : std::exp(logP(k));
105}
106
107template <typename IntType>
108double BetaBinomialRand<IntType>::logP(const IntType &k) const
109{
110 if (k < 0 || k > n)
111 return -INFINITY;
112 double y = std::lgammal(k + B.GetAlpha());
113 y += std::lgammal(n - k + B.GetBeta());
114 y -= math::lfact(k);
115 y -= math::lfact(n - k);
116 return pmfCoef + y;
117}
118
119template <typename IntType>
120double BetaBinomialRand<IntType>::F(const IntType &k) const
121{
122 if (k < 0)
123 return 0.0;
124 if (k >= n)
125 return 1.0;
126 double sum = 0.0;
127 int i = 0;
128 do {
129 sum += P(i);
130 } while (++i <= k);
131 return sum;
132}
133
134template <typename IntType>
135template <std::uniform_random_bit_generator G>
137{
139}
140
141template <typename IntType>
142template <std::uniform_random_bit_generator G>
143IntType BetaBinomialRand<IntType>::VariateBeta(G &g) const
144{
145 double p = B(g);
147}
148
149template <typename IntType>
150template <std::uniform_random_bit_generator G>
152{
153 return (B.GetAlpha() == 1 && B.GetBeta() == 1) ? VariateUniform(g) : VariateBeta(g);
154}
155
156template <typename IntType>
157void BetaBinomialRand<IntType>::sample(detail::EngineRef g, std::span<IntType> outputData) const
158{
159 if (B.GetAlpha() == 1 && B.GetBeta() == 1) {
160 for (IntType &var : outputData)
161 var = VariateUniform(g);
162 } else {
163 for (IntType &var : outputData)
164 var = VariateBeta(g);
165 }
166}
167
168template <typename IntType>
170{
171 double alpha = B.GetAlpha();
172 double beta = B.GetBeta();
173 return n * alpha / (alpha + beta);
174}
175
176template <typename IntType>
178{
179 double alpha = B.GetAlpha();
180 double beta = B.GetBeta();
181 double alphaPBeta = alpha + beta;
182 double numerator = n * alpha * beta * (alphaPBeta + n);
183 double denominator = alphaPBeta * alphaPBeta;
184 denominator *= (alphaPBeta + 1);
185 return numerator / denominator;
186}
187
188template <typename IntType>
190{
191 IntType mode = (IntType)(n * B.Mode());
192 double logPmode = this->logP(mode);
193 if (this->logP(mode + 1) > logPmode)
194 return mode + 1;
195 if (this->logP(mode - 1) > logPmode)
196 return mode - 1;
197 return mode;
198}
199
200template <typename IntType>
202{
203 long double alpha = B.GetAlpha();
204 long double beta = B.GetBeta();
205 long double alphaPBeta = alpha + beta;
206 long double res = (1 + alphaPBeta) / (n * alpha * beta * (alphaPBeta + n));
207 res = std::sqrt(res);
208 res *= (alphaPBeta + 2 * n) * (beta - alpha);
209 res /= alphaPBeta + 2;
210 return res;
211}
212
213template <typename IntType>
215{
216 long double alpha = B.GetAlpha();
217 long double beta = B.GetBeta();
218 long double alphaPBeta = alpha + beta;
219 long double alphaBetaN = alpha * beta * n;
220 long double res = alpha * beta * (n - 2);
221 res += 2 * (double)n * n;
222 res -= alphaBetaN * (6 - n) / alphaPBeta;
223 res -= 6 * alphaBetaN * n / (alphaPBeta * alphaPBeta);
224 res *= 3;
225 res += alphaPBeta * (alphaPBeta - 1 + 6 * n);
226 res *= alphaPBeta * alphaPBeta * (1 + alphaPBeta);
227 res /= (alphaBetaN * (alphaPBeta + 2) * (alphaPBeta + 3) * (alphaPBeta + n));
228 return res - 3.0;
229}
230
231} // namespace randlib
The BetaBinomialRand class Beta-Binomial distribution.
Definition beta_binomial.hpp:25
IntType GetNumber() const noexcept
Definition beta_binomial.hpp:41
std::string Name() const override
Definition beta_binomial.hpp:81
long double ExcessKurtosis() const override
Definition beta_binomial.hpp:214
double GetAlpha() const
Definition beta_binomial.hpp:42
BetaBinomialRand(IntType number=1, double shape1=1, double shape2=1)
Definition beta_binomial.hpp:75
void SetParameters(IntType number, double shape1, double shape2)
Definition beta_binomial.hpp:88
long double Variance() const override
Definition beta_binomial.hpp:177
double GetBeta() const
Definition beta_binomial.hpp:43
double logP(const IntType &k) const override
Definition beta_binomial.hpp:108
IntType operator()(G &g) const
Definition beta_binomial.hpp:151
IntType MaxValue() const override
Definition beta_binomial.hpp:38
IntType Mode() const override
Mode is the value, which has the largest probability to happen, or, in the case of continuous distrib...
Definition beta_binomial.hpp:189
double F(const IntType &k) const override
Definition beta_binomial.hpp:120
IntType MinValue() const override
Definition beta_binomial.hpp:37
long double Mean() const override
Definition beta_binomial.hpp:169
Support SupportType() const override
Definition beta_binomial.hpp:36
long double Skewness() const override
Definition beta_binomial.hpp:201
double P(const IntType &k) const override
Definition beta_binomial.hpp:102
double GetAlpha() const noexcept
Definition continuous/beta.hpp:128
double GetBeta() const noexcept
Definition continuous/beta.hpp:132
The BetaRand class Beta distribution.
Definition continuous/beta.hpp:246
The DiscreteDistribution class Abstract class for all discrete distributions.
Definition discrete.hpp:21
T Variate() const
Uses the engine of this object, so it is not thread-safe for one object; use operator() with one engi...
Definition distribution.hpp:133
static IntType StandardVariate(IntType minValue, IntType maxValue, G &g)
Definition uniform_discrete.hpp:137
The EngineRef class Non-owning, type-erased reference to any uniform random bit generator.
Definition engine/uniform.hpp:116
Real lfact(size_t n)
Calculate log(n!) using table values for small n <= 255 and built-in lgamma function for large n > 25...
Definition math/gamma.hpp:591
Definition bivariate_normal.hpp:10
Support
Shape of the support of a univariate distribution.
Definition univariate.hpp:15