lib/distribution/f/ruby.rb
module Distribution
module F
# Continuous random number distributions are defined by a probability density function, p(x), such that the probability of x occurring in the infinitesimal range x to x+dx is p dx.
# The cumulative distribution function for the lower tail P(x) is defined by the integral,
# P(x) = \int_{-\infty}^{x} dx' p(x')
# and gives the probability of a variate taking a value less than x.
# The cumulative distribution function for the upper tail Q(x) is defined by the integral,
# Q(x) = \int_{x}^{+\infty} dx' p(x')
# and gives the probability of a variate taking a value greater than x.
# The upper and lower cumulative distribution functions are related by P(x) + Q(x) = 1 and satisfy 0 <= P(x) <= 1, 0 <= Q(x).
module Ruby_
extend Distribution::MathExtension
# functions needed:
# - pdf
# - cdf (lower cumulative function, P(x))
# - Q(x), upper cumulative function
# - mean
# - mode
# - kurtosis
# - skewness
# - entropy
# - "fit" (maximum likelihood?)
# - expected value (given a function)
# - lower-tail quantile -> P
# - upper tail quantile -> Q
class << self
# F Distribution (Ruby) -- Probability Density Function
def pdf(x, n, m)
x = x.to_f
numerator = ((n * x)**n * (m**m)) / (n * x + m)**(n + m)
denominator = x * Math.beta(n / 2.0, m / 2.0)
Math.sqrt(numerator) / denominator
end
# Cumulative Distribution Function.
def cdf(x, n, m)
x = x.to_f
xx = (x * n).to_f / (x * n + m).to_f
regularized_beta(xx, n / 2.0, m / 2.0)
end
# Upper cumulative function.
#
# If cdf(x, n, m) = p, then q(x, n, m) = 1 - p
def q(x, n, m)
1.0 - cdf(x, n, m)
end
# Return the F value corresponding to `probability` with degrees of
# freedom `n` and `m`.
#
# If x = quantile(p, n, m), then cdf(x, n, m) = p.
#
# Taken from:
# https://github.com/JuliaLang/Rmath-julia/blob/master/src/qf.c
def quantile(probability, n, m)
return Float::NAN if n <= 0.0 || m <= 0.0
if n == Float::INFINITY || n == -Float::INFINITY || m == Float::INFINITY || m == -Float::INFINITY
return 1.0
end
if n <= m && m > 4e5
return Distribution::ChiSquare.p_value(probability, n) / n.to_f
elsif n > 4e5 # thus n > m
return m.to_f / Distribution::ChiSquare.p_value(1.0 - probability, m)
else
# O problema está aqui.
tmp = Distribution::Beta.p_value(1.0 - probability, m.to_f / 2, n.to_f / 2)
value = (1.0 / tmp - 1.0) * (m.to_f / n.to_f)
return value.nan? ? Float::NAN : value
end
end
alias_method :p_value, :quantile
# Complementary quantile function.
#
# def cquantile(prob, n, m)
# quantile(1.0 - probability, n, m)
# end
# Return the corresponding F value for a p-value `y` with `n` and `m`
# degrees of freedom.
#
# @param y [Float] Value corresponding to the desired p-value. Between 0 and 1.
# @param n [Float] Degree of freedom of the first random variable.
# @param m [Float] Degree of freedom of the second random variable.
# @return [Float] Value of the F distribution that gives a p-value of `y`.
def mean
end
def mode
end
def skewness
end
def kurtosis
end
def entropy
end
end
end
end
end