https://mooseframework.inl.gov
Loading...
Searching...
No Matches
Beta.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
10#include "Beta.h"
11#include "math.h"
12#include "libmesh/utility.h"
13
14registerMooseObject("StochasticToolsApp", Beta);
15
18{
20 params.addClassDescription("Beta distribution");
21 params.addRequiredRangeCheckedParam<Real>("alpha", "alpha > 0", "Shape parameter 1.");
22 params.addRequiredRangeCheckedParam<Real>("beta", "beta > 0", "Shape parameter 2.");
23 return params;
24}
25
26Beta::Beta(const InputParameters & parameters)
27 : Distribution(parameters), _alpha(getParam<Real>("alpha")), _beta(getParam<Real>("beta"))
28{
29}
30
31Real
32Beta::pdf(const Real & x, const Real & alpha, const Real & beta)
33{
34 if (x <= 0.0 || x > 1.0)
35 return 0.0;
36 else
37 return std::pow(x, alpha - 1.0) * std::pow(1.0 - x, beta - 1.0) / betaFunction(alpha, beta);
38}
39
40Real
41Beta::cdf(const Real & x, const Real & alpha, const Real & beta)
42{
43 if (x <= 0.0)
44 return 0.0;
45 else if (x >= 1.0)
46 return 1.0;
47 else
48 return incompleteBeta(alpha, beta, x);
49}
50
51Real
52Beta::quantile(const Real & p, const Real & alpha, const Real & beta)
53{
54 return incompleteBetaInv(alpha, beta, p);
55}
56
57Real
58Beta::pdf(const Real & x) const
59{
60 return pdf(x, _alpha, _beta);
61}
62
63Real
64Beta::cdf(const Real & x) const
65{
66 return cdf(x, _alpha, _beta);
67}
68
69Real
70Beta::quantile(const Real & p) const
71{
72 return quantile(p, _alpha, _beta);
73}
74
75Real
76Beta::betaFunction(const Real & a, const Real & b)
77{
78 return std::tgamma(a) * std::tgamma(b) / std::tgamma(a + b);
79}
80
81Real
82Beta::incompleteBeta(const Real & a, const Real & b, const Real & x)
83{
84 if (x > ((a + 1.0) / (a + b + 2.0)))
85 return 1.0 - incompleteBeta(b, a, 1.0 - x);
86
87 const Real tol = 1e-14;
88 const unsigned int max_iter = 1e3;
89 const Real coef = std::pow(x, a) * std::pow(1.0 - x, b) / a / betaFunction(a, b);
90 Real fn = 1.0;
91 Real cn = 1.0;
92 Real dn = 0.0;
93 Real num;
94 Real m = 0.0;
95 for (unsigned int i = 0; i < max_iter; ++i)
96 {
97 if (i == 0)
98 num = 1.0;
99 else if (i % 2 == 0)
100 {
101 m = i / 2.0;
102 num = m * (b - m) * x / (a + 2.0 * m) / (a + 2.0 * m - 1.0);
103 }
104 else
105 {
106 m = (i - 1) / 2.0;
107 num = -(a + m) * (a + b + m) * x / (a + 2.0 * m) / (a + 2.0 * m + 1.0);
108 }
109
110 dn = 1.0 / (1.0 + num * dn);
111 cn = 1.0 + num / cn;
112 const Real cd = cn * dn;
113 fn *= cd;
114
115 if (std::abs(1.0 - cd) < tol)
116 return coef * (fn - 1.0);
117 }
118
119 mooseAssert(false, "Could not compute incomplete beta function.");
120 return coef * (fn - 1.0);
121}
122
123Real
124Beta::incompleteBetaInv(const Real & a, const Real & b, const Real & p)
125{
126 if (a < b)
127 return 1.0 - incompleteBetaInv(b, a, 1.0 - p);
128
129 // Try with Newton method
130 Real x = 0.5;
131 const Real tol = 1e-14;
132 const unsigned int max_iter = 1e3;
133 const Real scale = betaFunction(a, b);
134 Real f;
135 Real df;
136 for (unsigned int i = 0; i < max_iter; ++i)
137 {
138 f = incompleteBeta(a, b, x) - p;
139 if (std::abs(f) < tol)
140 return x;
141 df = std::pow(x, a - 1.0) * std::pow(1.0 - x, b - 1.0) / scale;
142 x -= f / df;
143 // There's a divergence so try out bisection
144 if (x < 0 || x > 1.0)
145 break;
146 }
147
148 // Try with bisection method
149 Real x1 = 0; // f(0) = -p
150 Real x2 = 1; // f(1) = 1 - p
151 for (unsigned int i = 0; i < max_iter; ++i)
152 {
153 x = (x2 + x1) / 2.0;
154 f = incompleteBeta(a, b, x) - p;
155 if (std::abs(f) < tol)
156 return x;
157 else if (f < 0)
158 x1 = x;
159 else
160 x2 = x;
161 }
162
163 mooseAssert(false, "Could not find inverse of incomplete gamma function.");
164 return x;
165}
registerMooseObject("StochasticToolsApp", Beta)
Real f(Real x)
Test function for Brents method.
const double tol
const std::vector< double > x
const Real p
Real scale
A class used to generate a Beta distribution.
Definition Beta.h:18
const Real & _alpha
Shape parameter 1.
Definition Beta.h:48
static Real incompleteBetaInv(const Real &a, const Real &b, const Real &p)
Inverse of lower incomplete beta function.
Definition Beta.C:124
static Real incompleteBeta(const Real &a, const Real &b, const Real &x)
Lower incomplete beta function.
Definition Beta.C:82
virtual Real cdf(const Real &x) const override
Definition Beta.C:64
static Real betaFunction(const Real &a, const Real &b)
Beta function: B(a,b) = Gamma(a)Gamma(b)/Gamma(a+b)
Definition Beta.C:76
virtual Real pdf(const Real &x) const override
Definition Beta.C:58
Beta(const InputParameters &parameters)
Definition Beta.C:26
virtual Real quantile(const Real &p) const override
Definition Beta.C:70
const Real & _beta
Shape parameter 2.
Definition Beta.h:50
static InputParameters validParams()
Definition Beta.C:17
static InputParameters validParams()
void addRequiredRangeCheckedParam(const std::string &name, const std::string &parsed_function, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)