RandLib 2.0.0
Probability distributions, fitting, and heavy-tail tools for C++20
Loading...
Searching...
No Matches
beta_prime.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <span>
4
10
12
13namespace randlib
14{
15
30template <typename RealType>
31class BetaPrimeRand final : public ContinuousDistribution<RealType>
32{
33 RealType variate(detail::EngineRef g) const override { return (*this)(g); }
34 void sample(detail::EngineRef g, std::span<RealType> outputData) const override;
35
36 double alpha = 1;
37 double beta = 1;
39
40public:
41 BetaPrimeRand(double shape1 = 1, double shape2 = 1);
42 [[nodiscard]] std::string Name() const override;
43 void SetShapes(double shape1, double shape2);
44 [[nodiscard]] inline double GetAlpha() const noexcept { return alpha; }
45 [[nodiscard]] inline double GetBeta() const noexcept { return beta; }
46
47 [[nodiscard]] Support SupportType() const override { return Support::RightSemiFinite; }
48 [[nodiscard]] RealType MinValue() const override { return 0; }
49 [[nodiscard]] RealType MaxValue() const override { return INFINITY; }
50
51 [[nodiscard]] double f(const RealType &x) const override;
52 [[nodiscard]] double logf(const RealType &x) const override;
53 [[nodiscard]] double F(const RealType &x) const override;
54 [[nodiscard]] double S(const RealType &x) const override;
55
56private:
57 RealType fromBetaVariate(const RealType &betaVar) const;
58
59public:
60 template <std::uniform_random_bit_generator G>
61 [[nodiscard]] RealType operator()(G &g) const;
62
63 [[nodiscard]] long double Mean() const override;
64 [[nodiscard]] long double Variance() const override;
65 [[nodiscard]] RealType Median() const override;
66 [[nodiscard]] RealType Mode() const override;
67 [[nodiscard]] long double Skewness() const override;
68 [[nodiscard]] long double ExcessKurtosis() const override;
69
70private:
71 RealType quantileImpl(double p) const override;
72 RealType quantileImpl1m(double p) const override;
73
74 std::complex<double> CFImpl(double t) const override;
75
76public:
80 [[nodiscard]] inline double GetBetaFunction() const { return B.GetBetaFunction(); }
81
85 [[nodiscard]] inline double GetLogBetaFunction() const { return B.GetLogBetaFunction(); }
86
91 RANDLIB_DEPRECATED_FIT_MEMBER void FitAlpha(std::span<const RealType> sample);
92
97 RANDLIB_DEPRECATED_FIT_MEMBER void FitBeta(std::span<const RealType> sample);
98
103 RANDLIB_DEPRECATED_FIT_MEMBER void Fit(std::span<const RealType> sample);
104};
105
106} // namespace randlib
107
108namespace randlib
109{
110
111template <typename RealType>
112BetaPrimeRand<RealType>::BetaPrimeRand(double shape1, double shape2)
113{
114 SetShapes(shape1, shape2);
115}
116
117template <typename RealType>
119{
120 return "Beta Prime(" + this->toStringWithPrecision(GetAlpha()) + ", " + this->toStringWithPrecision(GetBeta()) +
121 ")";
122}
123
124template <typename RealType>
125void BetaPrimeRand<RealType>::SetShapes(double shape1, double shape2)
126{
127 if (!(shape1 > 0 && shape2 > 0))
128 throw std::invalid_argument("Beta-prime distribution: shapes should be positive");
129 B.SetShapes(shape1, shape2);
130 alpha = B.GetAlpha();
131 beta = B.GetBeta();
132}
133
134template <typename RealType>
135double BetaPrimeRand<RealType>::f(const RealType &x) const
136{
137 if (x < 0.0)
138 return 0.0;
139 if (x == 0.0) {
140 if (alpha == 1.0)
141 return 1.0 / GetBetaFunction();
142 return (alpha > 1) ? 0.0 : INFINITY;
143 }
144 return std::exp(logf(x));
145}
146
147template <typename RealType>
148double BetaPrimeRand<RealType>::logf(const RealType &x) const
149{
150 if (x < 0.0)
151 return -INFINITY;
152 if (x == 0.0) {
153 if (alpha == 1.0)
154 return -GetLogBetaFunction();
155 return (alpha > 1) ? -INFINITY : INFINITY;
156 }
157 double y = (alpha - 1) * std::log(x);
158 y -= (alpha + beta) * std::log1pl(x);
159 return y - GetLogBetaFunction();
160}
161
162template <typename RealType>
163double BetaPrimeRand<RealType>::F(const RealType &x) const
164{
165 if (x <= 0)
166 return 0;
167 if (std::isinf(x))
168 return 1;
170 return math::ibeta(x / (1.0 + x), alpha, beta, GetLogBetaFunction(), std::log(x) - std::log1pl(x), -std::log1pl(x));
171}
172
173template <typename RealType>
174double BetaPrimeRand<RealType>::S(const RealType &x) const
175{
176 if (x <= 0)
177 return 1;
178 if (std::isinf(x))
179 return 0;
181 double y = 1.0 / (1.0 + x);
182 return math::ibeta(y, beta, alpha, GetLogBetaFunction(), -std::log1pl(x), std::log(x) - std::log1pl(x));
183}
184
185template <typename RealType>
186RealType BetaPrimeRand<RealType>::fromBetaVariate(const RealType &betaVar) const
187{
188 if (betaVar > 1e-5)
189 return betaVar / (1.0 - betaVar);
190 RealType logVar = std::log(betaVar), log1mVar = std::log1p(-betaVar);
191 return std::exp(logVar - log1mVar);
192}
193
194template <typename RealType>
195template <std::uniform_random_bit_generator G>
197{
198 double x = B(g);
199 return fromBetaVariate(x);
200}
201
202template <typename RealType>
203void BetaPrimeRand<RealType>::sample(detail::EngineRef g, std::span<RealType> outputData) const
204{
205 B.Sample(g, outputData);
206 for (RealType &var : outputData)
207 var = fromBetaVariate(var);
208}
209
210template <typename RealType>
212{
213 return (beta > 1) ? alpha / (beta - 1) : INFINITY;
214}
215
216template <typename RealType>
218{
219 if (beta <= 2)
220 return INFINITY;
221 double betam1 = beta - 1;
222 double numerator = alpha * (alpha + betam1);
223 double denominator = (betam1 - 1) * betam1 * betam1;
224 return numerator / denominator;
225}
226
227template <typename RealType>
229{
230 return (alpha == beta) ? 1.0 : quantileImpl(0.5);
231}
232
233template <typename RealType>
235{
236 return (alpha < 1) ? 0 : (alpha - 1) / (beta + 1);
237}
238
239template <typename RealType>
241{
242 if (beta <= 3)
243 return INFINITY;
244 long double aux = alpha + beta - 1;
245 long double skewness = (beta - 2) / (alpha * aux);
246 skewness = std::sqrt(skewness);
247 aux += alpha;
248 aux += aux;
249 return aux * skewness / (beta - 3);
250}
251
252template <typename RealType>
254{
255 if (beta <= 4)
256 return INFINITY;
257 long double betam1 = beta - 1;
258 long double numerator = betam1 * betam1 * (beta - 2) / (alpha * (alpha + betam1));
259 numerator += 5 * beta - 11;
260 long double denominator = (beta - 3) * (beta - 4);
261 return 6 * numerator / denominator;
262}
263
264template <typename RealType>
265RealType BetaPrimeRand<RealType>::quantileImpl(double p) const
266{
268 double y = B.Quantile(p);
269 return ContinuousDistribution<RealType>::quantileImpl(p, y / (1.0 - y));
270}
271
272template <typename RealType>
273RealType BetaPrimeRand<RealType>::quantileImpl1m(double p) const
274{
275 double y = B.Quantile1m(p);
277}
278
279template <typename RealType>
280std::complex<double> BetaPrimeRand<RealType>::CFImpl(double t) const
281{
282 return this->integrateCharacteristicFunction(t);
283}
284
285template <typename RealType>
286void BetaPrimeRand<RealType>::FitAlpha(std::span<const RealType> sample)
287{
288 if (!this->allElementsArePositive(sample))
289 throw this->fitError(FitErrorCode::WrongSample, this->POSITIVITY_VIOLATION);
290 long double lnG = this->GetSampleLogMean(sample) - B.GetSampleLog1pMeanNorm(sample);
291 long double mean = 0.5;
292 if (beta != 1.0) {
293 mean = 0.0;
294 for (const RealType &var : sample)
295 mean += var / (1.0 + var);
296 mean /= sample.size();
297 }
298 B.FitAlpha(lnG, mean);
299 SetShapes(B.GetAlpha(), beta);
300}
301
302template <typename RealType>
303void BetaPrimeRand<RealType>::FitBeta(std::span<const RealType> sample)
304{
305 if (!this->allElementsArePositive(sample))
306 throw this->fitError(FitErrorCode::WrongSample, this->POSITIVITY_VIOLATION);
307 long double lnG1m = -B.GetSampleLog1pMeanNorm(sample);
308 long double mean = 0.5;
309 if (alpha != 1.0) {
310 mean = 0.0;
311 for (const RealType &var : sample)
312 mean += var / (1.0 + var);
313 mean /= sample.size();
314 }
315 B.FitBeta(lnG1m, mean);
316 SetShapes(alpha, B.GetBeta());
317}
318
319template <typename RealType>
320void BetaPrimeRand<RealType>::Fit(std::span<const RealType> sample)
321{
322 if (!this->allElementsArePositive(sample))
323 throw this->fitError(FitErrorCode::WrongSample, this->POSITIVITY_VIOLATION);
324 long double lnG1m = -B.GetSampleLog1pMeanNorm(sample);
325 long double lnG = this->GetSampleLogMean(sample) + lnG1m;
326 long double m = 0.0, v = 0.0;
327 int n = sample.size();
328 for (int i = 0; i < n; ++i) {
329 double x = sample[i] / (1.0 + sample[i]);
330 double diff = x - m;
331 m += diff / (i + 1);
332 v += diff * (x - m);
333 }
334 B.FitShapes(lnG, lnG1m, m, v / n);
335 SetShapes(B.GetAlpha(), B.GetBeta());
336}
337
338} // namespace randlib
339
The BetaPrimeRand class Beta-prime distribution.
Definition beta_prime.hpp:32
RealType MinValue() const override
Definition beta_prime.hpp:48
void FitBeta(std::span< const RealType > sample)
fit β by maximum-likelihood
Definition beta_prime.hpp:303
long double Skewness() const override
Definition beta_prime.hpp:240
double GetAlpha() const noexcept
Definition beta_prime.hpp:44
void SetShapes(double shape1, double shape2)
Definition beta_prime.hpp:125
double GetBetaFunction() const
Definition beta_prime.hpp:80
RealType operator()(G &g) const
Definition beta_prime.hpp:196
void FitAlpha(std::span< const RealType > sample)
fit α by maximum-likelihood
Definition beta_prime.hpp:286
long double ExcessKurtosis() const override
Definition beta_prime.hpp:253
void Fit(std::span< const RealType > sample)
fit shapes by maximum-likelihood
Definition beta_prime.hpp:320
RealType Mode() const override
Mode is the value, which has the largest probability to happen, or, in the case of continuous distrib...
Definition beta_prime.hpp:234
std::string Name() const override
Definition beta_prime.hpp:118
RealType Median() const override
Definition beta_prime.hpp:228
double f(const RealType &x) const override
Definition beta_prime.hpp:135
BetaPrimeRand(double shape1=1, double shape2=1)
Definition beta_prime.hpp:112
long double Mean() const override
Definition beta_prime.hpp:211
Support SupportType() const override
Definition beta_prime.hpp:47
double S(const RealType &x) const override
Definition beta_prime.hpp:174
double F(const RealType &x) const override
Definition beta_prime.hpp:163
double GetBeta() const noexcept
Definition beta_prime.hpp:45
long double Variance() const override
Definition beta_prime.hpp:217
RealType MaxValue() const override
Definition beta_prime.hpp:49
double GetLogBetaFunction() const
Definition beta_prime.hpp:85
double logf(const RealType &x) const override
Definition beta_prime.hpp:148
The BetaRand class Beta distribution.
Definition continuous/beta.hpp:246
The ContinuousDistribution class Abstract class for all continuous distributions.
Definition continuous.hpp:22
RealType quantileImpl(double p, RealType initValue) const override
Definition continuous.hpp:140
RealType quantileImpl1m(double p, RealType initValue) const override
Definition continuous.hpp:152
void Sample(std::span< T > outputData) const
Fills the output with variates drawn with the engine of this object.
Definition distribution.hpp:139
T Quantile(double p) const
Definition univariate.hpp:307
The EngineRef class Non-owning, type-erased reference to any uniform random bit generator.
Definition engine/uniform.hpp:116
#define RANDLIB_DETAIL_SUPPRESS_DEPRECATED_END
Definition fwd.hpp:26
#define RANDLIB_DETAIL_SUPPRESS_DEPRECATED_BEGIN
Definition fwd.hpp:25
#define RANDLIB_DEPRECATED_FIT_MEMBER
Definition fwd.hpp:9
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
@ WrongSample
the sample could not have been drawn from this distribution
Support
Shape of the support of a univariate distribution.
Definition univariate.hpp:15
@ RightSemiFinite
[a, ∞)