factorial() public static method

Factorial (iterative) Represents the number of ways to arrange n things (permutations) n! = n(n - 1)(n - 2) ・・・ (n - (n - 1))
public static factorial ( integer $n ) : integer
$n integer
return integer number of permutations of n
Ejemplo n.º 1
0
 /**
  * Poisson distribution - probability mass function
  * A discrete probability distribution that expresses the probability of a given number of events
  * occurring in a fixed interval of time and/or space if these events occur with a known average
  * rate and independently of the time since the last event.
  * https://en.wikipedia.org/wiki/Poisson_distribution
  *
  *                              λᵏℯ^⁻λ
  * P(k events in an interval) = ------
  *                                k!
  *
  * @param  int   $k events in the interval
  * @param  float $λ average number of successful events per interval
  *
  * @return float The Poisson probability of observing k successful events in an interval
  */
 public static function PMF(int $k, float $λ) : float
 {
     Support::checkLimits(self::LIMITS, ['k' => $k, 'λ' => $λ]);
     $λᵏℯ^−λ = pow($λ, $k) * exp(-$λ);
     $k! = Combinatorics::factorial($k);
     return $λᵏℯ^−λ / $k!;
 }
Ejemplo n.º 2
0
 /**
  * Multinomial distribution (multivariate) - probability mass function
  *
  * https://en.wikipedia.org/wiki/Multinomial_distribution
  *
  *          n!
  * pmf = ------- p₁ˣ¹⋯pkˣᵏ
  *       x₁!⋯xk!
  *
  * n = number of trials (sum of the frequencies) = x₁ + x₂ + ⋯ xk
  *
  * @param  array $frequencies
  * @param  array $probabilities
  *
  * @return float
  */
 public static function PMF(array $frequencies, array $probabilities) : float
 {
     // Must have a probability for each frequency
     if (count($frequencies) !== count($probabilities)) {
         throw new Exception\BadDataException('Number of frequencies does not match number of probabilities.');
     }
     // Probabilities must add up to 1
     if (round(array_sum($probabilities), 1) != 1) {
         throw new Exception\BadDataException('Probabilities do not add up to 1.');
     }
     $n = array_sum($frequencies);
     $n! = Combinatorics::factorial($n);
     $x₁!⋯xk! = array_product(array_map('MathPHP\\Probability\\Combinatorics::factorial', $frequencies));
     $p₁ˣ¹⋯pkˣᵏ = array_product(array_map(function ($x, $p) {
         return $p ** $x;
     }, $frequencies, $probabilities));
     return $n! / $x₁!⋯xk! * $p₁ˣ¹⋯pkˣᵏ;
 }
Ejemplo n.º 3
0
 /**
  * Gamma function - Stirling approximation
  * https://en.wikipedia.org/wiki/Gamma_function
  * https://en.wikipedia.org/wiki/Stirling%27s_approximation
  * https://www.wolframalpha.com/input/?i=Gamma(n)&lk=3
  *
  * For postive integers:
  *  Γ(n) = (n - 1)!
  *
  * For positive real numbers -- approximation:
  *                   ___
  *         __       / 1  /         1      \ n
  *  Γ(n)≈ √2π ℯ⁻ⁿ  /  - | n + ----------- |
  *                √   n  \    12n - 1/10n /
  *
  * @param number $n
  *
  * @return number
  */
 public static function gammaStirling($n)
 {
     // Basic integer/factorial cases
     if ($n == 0) {
         return \INF;
     }
     // Negative integer, or negative int as a float
     if ((is_int($n) || is_numeric($n) && abs($n - round($n)) < 1.0E-5) && $n < 0) {
         return -\INF;
     }
     // Positive integer, or postive int as a float
     if ((is_int($n) || is_numeric($n) && abs($n - round($n)) < 1.0E-5) && $n > 0) {
         return Combinatorics::factorial(round($n) - 1);
     }
     // Compute parts of equation
     $√2π = sqrt(2 * \M_PI);
     $ℯ⁻ⁿ = exp(-$n);
     $√1/n = sqrt(1 / $n);
     $⟮n + 1/⟮12n − 1/10n⟯⟯ⁿ = pow($n + 1 / (12 * $n - 1 / (10 * $n)), $n);
     /**
      * Put it all together:
      *                   ___
      *         __       / 1  /         1      \ n
      *  Γ(n)≈ √2π ℯ⁻ⁿ  /  - | n + ----------- |
      *                √   n  \    12n - 1/10n /
      */
     return $√2π * $ℯ⁻ⁿ * $√1/n * $⟮n + 1/⟮12n − 1/10n⟯⟯ⁿ;
 }
Ejemplo n.º 4
0
 /**
  * F used within CDF
  *                          _                                        _
  *                   1  ∞  |        /    1  ν \          /       ν \  |
  * Fᵥ,ᵤ(x) = Φ(-μ) + -  ∑  |  pⱼIy | j + -, -  | + qⱼIy | j + 1, -  | |
  *                   2 ʲ⁼⁰ |_       \    2  2 /          \       2 / _|
  *
  *  where
  *   Φ       = cumulative distribution function of the standard normal distribution
  *   Iy(a,b) = regularized incomplete beta function
  *
  *          x²
  *   y = ------
  *       x² + ν
  *
  *        1      /  μ² \   / μ² \ʲ
  *   pⱼ = -- exp| - -   | |  -   |
  *        j!     \  2  /   \ 2  /
  *
  *              μ          /  μ² \   / μ² \ʲ
  *   qⱼ = ------------ exp| - -   | |  -   |
  *        √2Γ(j + 3/2)     \  2  /   \ 2  /
  *
  * @param number $x
  * @param int    $ν Degrees of freedom
  * @param number $μ Noncentrality parameter
  *
  * @return number
  */
 private static function F($x, int $ν, $μ)
 {
     Support::checkLimits(self::LIMITS, ['x' => $x, 'ν' => $ν, 'μ' => $μ]);
     $Φ = StandardNormal::CDF(-$μ);
     $y = $x ** 2 / ($x ** 2 + $ν);
     $sum = $Φ;
     $tol = 1.0E-8;
     $j = 0;
     do {
         $exp = exp(-1 * $μ ** 2 / 2) * ($μ ** 2 / 2) ** $j;
         $pⱼ = 1 / Combinatorics::factorial($j) * $exp;
         $qⱼ = $μ / sqrt(2) / Special::gamma($j + 3 / 2) * $exp;
         $I1 = Special::regularizedIncompleteBeta($y, $j + 1 / 2, $ν / 2);
         $I2 = Special::regularizedIncompleteBeta($y, $j + 1, $ν / 2);
         $delta = $pⱼ * $I1 + $qⱼ * $I2;
         $sum += $delta / 2;
         $j += 1;
     } while ($delta / $sum > $tol || $j < 10);
     return $sum;
 }