23template <
typename IntType>
33 TrinomialRand(
int number,
double probability1,
double probability2);
34 [[nodiscard]] std::string
Name()
const override;
36 void SetParameters(
int number,
double probability1,
double probability2);
37 [[nodiscard]]
inline int GetNumber() const noexcept {
return n; }
44 template <std::uniform_random_bit_generator G>
57template <
typename IntType>
60 SetParameters(number, probability1, probability2);
63template <
typename IntType>
66 return "Trinomial(" + this->toStringWithPrecision(GetNumber()) +
", " +
67 this->toStringWithPrecision(GetFirstProbability()) +
", " +
68 this->toStringWithPrecision(GetSecondProbability()) +
")";
71template <
typename IntType>
74 if (!(probability1 >= 0.0 && probability2 >= 0.0 && probability1 + probability2 <= 1.0))
75 throw std::invalid_argument(
"Probabilities of Trinomial distribution should be positive and their sum should "
76 "be not greater than 1, but they're equal to " +
77 std::to_string(probability1) +
" and " + std::to_string(probability2));
79 throw std::invalid_argument(
"Number of Trinomial distribution should be positive, but it's equal to " +
80 std::to_string(number));
82 double p1 = probability1, p2 = probability2;
84 this->X.SetParameters(n, p1);
85 this->Y.SetParameters(n, p2);
87 log1mProb = std::log1pl(-p1 - p2);
88 p1_1mp2 = (p2 == 1.0) ? 0.0 : p1 / (1.0 - p2);
89 p2_1mp1 = (p1 == 1.0) ? 0.0 : p2 / (1.0 - p1);
92template <
typename IntType>
95 IntType x = point.first, y = point.second;
96 return (x < 0 || x > n || y < 0 || y > n) ? 0.0 : std::exp(logP(point));
99template <
typename IntType>
102 IntType x = point.first, y = point.second;
103 if (x < 0 || y < 0 || x > n || y > n - x)
105 IntType nmxmy = n - x - y;
106 double res = this->X.GetLogFactorialN();
111 res += x * this->X.GetLogProbability();
113 res += y * this->Y.GetLogProbability();
115 res += nmxmy * log1mProb;
119template <
typename IntType>
122 int x = point.first, y = point.second;
125 double p1 = this->X.GetProbability(), p2 = this->Y.GetProbability();
127 return (x >= n) ? 1.0 : 0.0;
129 return (y >= n) ? 1.0 : 0.0;
136 double ratio = (1 - p2 - p1) / (1 - p2);
137 for (
int i = 0; i <= y; ++i) {
138 int nmimx = n - i - x;
139 double prob1 = (nmimx > 0) ?
math::ibeta(ratio, nmimx, x + 1) : 1.0;
140 double prob2 = this->Y.P(i);
141 sum += prob1 * prob2;
145 double ratio = (1 - p1 - p2) / (1 - p1);
146 for (
int i = 0; i <= x; ++i) {
147 IntType nmimy = n - i - y;
148 double prob1 = (nmimy > 0) ?
math::ibeta(ratio, nmimy, y + 1) : 1.0;
149 double prob2 = this->X.P(i);
150 sum += prob1 * prob2;
155template <
typename IntType>
156template <std::uniform_random_bit_generator G>
159 if (this->X.GetProbability() == 1.0)
161 if (this->Y.GetProbability() == 1.0)
163 if (this->X.GetProbability() > this->Y.GetProbability()) {
164 IntType x = this->X(g);
168 IntType y = this->Y(g);
173template <
typename IntType>
176 long double p1 = this->X.GetProbability(), p2 = this->Y.GetProbability();
177 if (!(p1 > 0.0L && p1 < 1.0L && p2 > 0.0L && p2 < 1.0L))
179 return -std::sqrt(p1 * p2 / ((1.0L - p1) * (1.0L - p2)));
182template <
typename IntType>
185 IntType modeX =
static_cast<IntType
>(std::floor(n * this->X.GetProbability()));
186 IntType modeY =
static_cast<IntType
>(std::floor(n * this->Y.GetProbability()));
187 modeY = std::min(modeY,
static_cast<IntType
>(n - modeX));
189 double modeValue = logP(mode);
193 double bestValue = modeValue;
194 auto consider = [
this, &best, &bestValue](IntType x, IntType y) {
195 double value = logP(std::make_pair(x, y));
196 if (value > bestValue) {
197 best = std::make_pair(x, y);
202 if (mode.first + mode.second < n) {
203 consider(mode.first + 1, mode.second);
204 consider(mode.first, mode.second + 1);
206 if (mode.first > 0) {
207 consider(mode.first - 1, mode.second);
208 consider(mode.first - 1, mode.second + 1);
210 if (mode.second > 0) {
211 consider(mode.first, mode.second - 1);
212 consider(mode.first + 1, mode.second - 1);
217 modeValue = bestValue;
T2 Y
2nd marginal distributions
Definition bivariate.hpp:20
T1 X
1st marginal distributions
Definition bivariate.hpp:19
The DiscreteBivariateDistribution class Abstract class for all bivariate probability distributions ...
Definition discrete_bivariate.hpp:18
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
The TrinomialRand class Trinomial distribution.
Definition trinomial.hpp:25
std::string Name() const override
Definition trinomial.hpp:64
double logP(const Pair< IntType > &point) const override
Definition trinomial.hpp:100
double GetFirstProbability() const
Definition trinomial.hpp:38
Pair< IntType > operator()(G &g) const
Definition trinomial.hpp:157
TrinomialRand(int number, double probability1, double probability2)
Definition trinomial.hpp:58
Pair< IntType > Mode() const override
Definition trinomial.hpp:183
void SetParameters(int number, double probability1, double probability2)
Definition trinomial.hpp:72
int GetNumber() const noexcept
Definition trinomial.hpp:37
double GetSecondProbability() const
Definition trinomial.hpp:39
double P(const Pair< IntType > &point) const override
Definition trinomial.hpp:93
long double Correlation() const override
Definition trinomial.hpp:174
double F(const Pair< IntType > &point) const override
Definition trinomial.hpp:120
The EngineRef class Non-owning, type-erased reference to any uniform random bit generator.
Definition engine/uniform.hpp:116
constexpr long double ln3
Definition constants.hpp:19
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
Real ibeta(Real x, std::type_identity_t< Real > a, std::type_identity_t< Real > b, std::type_identity_t< Real > logBetaFun, std::type_identity_t< Real > logX, std::type_identity_t< Real > log1mX)
Fast calculation of regularized beta function, using precalculated values.
Definition math/beta.hpp:250
Definition bivariate_normal.hpp:10
std::pair< T, T > Pair
Definition fwd.hpp:33
Pair< int > IntPair
Definition fwd.hpp:38