/** * Cumulative Poisson Probability (lower culmulative distribution) - CDF * The probability that the Poisson random variable is greater than some specified lower limit, * and less than some specified upper limit. * * k λˣℯ^⁻λ * P(k,λ) = ∑ ------ * ₓ₌₀ xᵢ! * * @param int $k events in the interval * @param float $λ average number of successful events per interval * * @return float The cumulative Poisson probability */ public static function CDF(int $k, float $λ) : float { Support::checkLimits(self::LIMITS, ['k' => $k, 'λ' => $λ]); return array_sum(array_map(function ($k) use($λ) { return self::PMF($k, $λ); }, range(0, $k))); }
/** * Mean of the distribution * * μ = ∞ for a ≤ 1 * * ab * μ = ----- for a > 1 * a - 1 * * @param number $a shape parameter * @param number $b scale parameter * * @return number */ public static function mean($a, $b) { Support::checkLimits(self::LIMITS, ['a' => $a, 'b' => $b]); if ($a <= 1) { return INF; } return $a * $b / ($a - 1); }
/** * Probability mass function * * b(x; r, p) = ₓ₋₁Cᵣ₋₁ pʳ * (1 - p)ˣ⁻ʳ * * @param int $x number of trials required to produce r successes * @param int $r number of successful events * @param float $p probability of success on an individual trial * * @return float */ public static function PMF(int $x, int $r, float $p) : float { Support::checkLimits(self::LIMITS, ['x' => $x, 'r' => $r, 'p' => $p]); $ₓ₋₁Cᵣ₋₁ = Combinatorics::combinations($x - 1, $r - 1); $pʳ = pow($p, $r); $⟮1 − p⟯ˣ⁻ʳ = pow(1 - $p, $x - $r); return $ₓ₋₁Cᵣ₋₁ * $pʳ * $⟮1 − p⟯ˣ⁻ʳ; }
/** * Binomial distribution - cumulative distribution function * Computes and sums the binomial distribution at each of the values in r. * * @param int $n number of events * @param int $r number of successful events * @param float $P probability of success * * @return float */ public static function CDF(int $n, int $r, float $p) : float { Support::checkLimits(self::LIMITS, ['n' => $n, 'r' => $r, 'p' => $p]); $cumulative_probability = 0; for ($i = $r; $i >= 0; $i--) { $cumulative_probability += self::PMF($n, $i, $p); } return $cumulative_probability; }
/** * Bernoulli distribution - cumulative distribution function * * https://en.wikipedia.org/wiki/Bernoulli_distribution * * 0 for k < 0 * 1 - p for 0 ≤ k < 1 * 1 for k ≥ 1 * * @param int $k number of successes k ∈ {0, 1} * @param float $p success probability 0 < p < 1 * * @return float */ public static function CDF(int $k, float $p) : float { Support::checkLimits(self::LIMITS, ['p' => $p]); if ($k < 0) { return 0; } if ($k < 1) { return 1 - $p; } return 1; }
/** * Cumulative distribution function * P value for a z score. * * @param number $z random variable * * @return float f(z|μ,σ) */ public static function CDF($z) { Support::checkLimits(self::LIMITS, ['z' => $z]); return Normal::CDF($z, self::μ, self::σ); }
/** * Mean of the distribution * * μ = exp(μ + σ²/2) * * @param number $μ * @param number $σ * * @return number */ public static function mean($μ, $σ) { Support::checkLimits(self::LIMITS, ['μ' => $μ, 'σ' => $σ]); return exp($μ + $σ ** 2 / 2); }
/** * Mean of the distribution * * μ = λ⁻¹ * * @param float $λ often called the rate parameter * * @return number */ public static function mean(float $λ) { Support::checkLimits(self::LIMITS, ['λ' => $λ]); return 1 / $λ; }
/** * Median of the distribution * * μ = 0 * * @param number $ν Degrees of freedom * * @return number */ public static function median($ν) { Support::checkLimits(self::LIMITS, ['ν' => $ν]); return 0; }
/** * Regularized incomplete beta function - Iₓ(a, b) * * https://en.wikipedia.org/wiki/Beta_function#Incomplete_beta_function * * This function looks at the values of x, a, and b, and determines which algorithm is best to calculate * the value of Iₓ(a, b) * * http://www.boost.org/doc/libs/1_35_0/libs/math/doc/sf_and_dist/html/math_toolkit/special/sf_beta/ibeta_function.html * https://github.com/boostorg/math/blob/develop/include/boost/math/special_functions/beta.hpp * * @param $x Upper limit of the integration 0 ≦ x ≦ 1 * @param $a Shape parameter a > 0 * @param $b Shape parameter b > 0 * * @return number */ public static function regularizedIncompleteBeta($x, $a, $b) { $limits = ['x' => '[0, 1]', 'a' => '(0,∞)', 'b' => '(0,∞)']; Support::checkLimits($limits, ['x' => $x, 'a' => $a, 'b' => $b]); if ($x == 1 || $x == 0) { return $x; } if ($a == 1) { return 1 - (1 - $x) ** $b; } if ($b == 1) { return $x ** $a; } if ($x > 0.9 || $b > $a && $x > 0.5) { $y = 1 - $x; return 1 - self::regularizedIncompleteBeta($y, $b, $a); } if ($a > 1 && $b > 1) { // Tolerance on evaluating the continued fraction. $tol = 1.0E-15; $dif = $tol + 1; // Initialize // We will calculate the continuous fraction with a minimum depth of 10. $m = 10; // Counter do { $I_new = self::iBetaCF($m, $x, $a, $b); if ($m > 10) { $dif = abs(($I - $I_new) / $I_new); } $I = $I_new; $m++; } while ($dif > $tol); return $I; } else { if ($a <= 1) { // We shift a up by one, to the region that the continuous fraction works best. $offset = $x ** $a * (1 - $x) ** $b / $a / self::beta($a, $b); return self::regularizedIncompleteBeta($x, $a + 1, $b) + $offset; } else { // $b <= 1 // We shift a up by one, to the region that the continuous fraction works best. $offset = $x ** $a * (1 - $x) ** $b / $b / self::beta($a, $b); return self::regularizedIncompleteBeta($x, $a, $b + 1) - $offset; } } }
/** * Inverse CDF (Quantile function) * * Q(p;x₀,γ) = x₀ + γ tan[π(p - ½)] * * @param number $p * @param number $x₀ * @param number $γ * * @return number */ public static function inverse($p, ...$params) { $x₀ = $params[0]; $γ = $params[1]; Support::checkLimits(self::LIMITS, ['x₀' => $x₀, 'γ' => $γ, 'p' => $p]); $π = \M_PI; return $x₀ + $γ * tan($π * ($p - 0.5)); }
/** * Mean of the distribution * * α * μ = ----- * α + β * * @param number $α shape parameter α > 0 * @param number $β shape parameter β > 0 * * @return number */ public static function mean($α, $β) { Support::checkLimits(self::LIMITS, ['α' => $α, 'β' => $β]); return $α / ($α + $β); }
/** * Inverse CDF (Quantile function) * * / p \ 1/β * F⁻¹(p;α,β) = α | ----- | * \ 1 - p / * * @param number $p * @param number $α * @param number $β * * @return number */ public static function inverse($p, ...$params) { $α = $params[0]; $β = $params[1]; Support::checkLimits(self::LIMITS, ['α' => $α, 'β' => $β, 'p' => $p]); return $α * ($p / (1 - $p)) ** (1 / $β); }
/** * Mean of the distribution * * μ = k * * @param int $k degrees of freedom > 0 * * @return int k */ public static function mean(int $k) { Support::checkLimits(self::LIMITS, ['k' => $k]); return $k; }
/** * Geometric distribution - cumulative distribution function (lower cumulative) * * The probability distribution of the number Y = X − 1 of failures * before the first success, supported on the set { 0, 1, 2, 3, ... } * https://en.wikipedia.org/wiki/Geometric_distribution * * k failures where k ∈ {0, 1, 2, 3, ...} * * pmf = 1 - (1 - p)ᵏ⁺¹ * * @param int $k number of trials k ≥ 0 * @param float $p success probability 0 < p ≤ 1 * * @return float */ public static function CDF(int $k, float $p) : float { Support::checkLimits(self::LIMITS, ['k' => $k, 'p' => $p]); $⟮1 − p⟯ᵏ⁺¹ = pow(1 - $p, $k + 1); return 1 - $⟮1 − p⟯ᵏ⁺¹; }
/** * Inverse CDF (Quantile function) * * Q(p;k,λ) = λ(-ln(1 - p))¹/ᵏ * * @param number $p * @param number $k * @param number $λ * * @return number */ public static function inverse($p, ...$params) { $k = $params[0]; $λ = $params[1]; Support::checkLimits(self::LIMITS, ['k' => $k, 'λ' => $λ, 'p' => $p]); return $λ * (-1 * log(1 - $p)) ** (1 / $k); }
/** * Mean of the distribution * _ * /ν Γ((ν - 1)/2) * E[T] = μ / - ------------ if ν > 1 * √ 2 Γ(ν/2) * * = Does not exist if ν ≤ 1 * * @param int $ν Degrees of freedom * @param number $μ Noncentrality parameter * * @return number */ public static function mean(int $ν, $μ) { Support::checkLimits(self::LIMITS, ['ν' => $ν, 'μ' => $μ]); if ($ν == 1) { return \NAN; } return $μ * sqrt($ν / 2) * Special::gamma(($ν - 1) / 2) / Special::gamma($ν / 2); }
/** * Inverse CDF (quantile function) * * / p \ * Q(p;μ,s) = μ + s ln| ----- | * \ 1 - p / * * @param number $p * @param number $μ * @param number $s * * @return number */ public static function inverse($p, ...$params) { $μ = $params[0]; $s = $params[1]; Support::checkLimits(self::LIMITS, ['μ' => $μ, 's' => $s, 'p' => $p]); return $μ + $s * log($p / (1 - $p)); }
/** * Mean of the distribution * * μ = μ * * @param number $μ location parameter * @param number $b scale parameter (diversity) b > 0 * * @return μ */ public static function mean($μ, $b) { Support::checkLimits(self::LIMITS, ['μ' => $μ, 'b' => $b]); return $μ; }
/** * Cumulative distribution function * * / d₁ d₂ \ * I | --, -- | * ᵈ¹ˣ \ 2 2 / * ------ * ᵈ¹ˣ⁺ᵈ² * * Where I is the regularized incomplete beta function. * * @param number $x percentile ≥ 0 * @param int $d₁ degree of freedom v1 > 0 * @param int $d₂ degree of freedom v2 > 0 * * @return number */ public static function CDF($x, int $d₁, int $d₂) { Support::checkLimits(self::LIMITS, ['x' => $x, 'd₁' => $d₁, 'd₂' => $d₂]); $ᵈ¹ˣ/d₁x+d₂ = $d₁ * $x / ($d₁ * $x + $d₂); return Special::regularizedIncompleteBeta($ᵈ¹ˣ/d₁x+d₂, $d₁ / 2, $d₂ / 2); }