/* *
* Title:
* Description:
* Copyright: Copyright (c)
* Company:
* @author
* @version 1.0
*/
package umontreal.iro.lecuyer.probdist;
import umontreal.iro.lecuyer.util.Num;
import umontreal.iro.lecuyer.util.RootFinder;
import umontreal.iro.lecuyer.functions.MathFunction;
/**
* Extends the class {@link DiscreteDistributionInt} for
* the logarithmic distribution. It has shape parameter
* θ, where
* 0 < θ < 1.
* Its mass function is
*
*
*
* p(x) = - θx/(x log(1 - θ) for x = 1, 2, 3,...
*
* Its distribution function is
*
*
*
* F(x) = -1/log(1-θ)∑i=1xθi/i, & for x > 0.
*
*
*/
public class LogarithmicDist extends DiscreteDistributionInt {
private double theta;
private double t;
private static class Function implements MathFunction {
protected double mean;
public Function (double mean) {
this.mean = mean;
}
public double evaluate (double x) {
if (x <= 0.0 || x >= 1.0) return 1.0e200;
return (x + mean * (1.0 - x) * Math.log1p (-x));
}
}
/**
* Constructs a logarithmic distribution with parameter θ =
* theta.
*
*/
public LogarithmicDist (double theta) {
setTheta (theta);
}
public double prob (int x) {
if (x < 1)
return 0;
return t*Math.pow (theta, x)/x;
}
public double cdf (int x) {
if (x < 1)
return 0;
double res = prob (1);
double term = res;
for (int i = 2; i <= x; i++) {
term *= theta;
res += term/i;
}
return res;
}
public double barF (int x) {
if (x <= 1)
return 1.0;
double res = prob (x);
double term = res;
int i = x + 1;
while (term > EPSILON) {
term *= theta*(i-1)/i;
res += term;
}
return res;
}
public int inverseFInt (double u) {
return inverseF (theta, u);
}
public double getMean() {
return LogarithmicDist.getMean (theta);
}
public double getVariance() {
return LogarithmicDist.getVariance (theta);
}
public double getStandardDeviation() {
return LogarithmicDist.getStandardDeviation (theta);
}
/**
* Computes the logarithmic probability p(x).
*
*/
public static double prob (double theta, int x) {
if (theta <= 0 || theta >= 1)
throw new IllegalArgumentException ("theta not in range (0,1)");
if (x < 1)
return 0;
return -1.0/Math.log1p(-theta) * Math.pow (theta, x)/x;
}
/**
* Computes the distribution function F(x).
*
*/
public static double cdf (double theta, int x) {
if (theta <= 0 || theta >= 1)
throw new IllegalArgumentException ("theta not in range (0,1)");
if (x < 1)
return 0;
double res = prob (theta, 1);
double term = res;
for (int i = 2; i <= x; i++) {
term *= theta;
res += term/i;
}
return res;
}
/**
* Computes the complementary distribution function.
* WARNING: The complementary distribution function is defined as
*
* bar(F)(x) = P[X >= x].
*
*/
public static double barF (double theta, int x) {
if (theta <= 0 || theta >= 1)
throw new IllegalArgumentException ("theta not in range (0,1)");
if (x <= 1)
return 1.0;
double res = prob (theta, x);
double term = res;
int i = x + 1;
while (term > EPSILON) {
term *= theta*(i-1)/i;
res += term;
}
return res;
}
public static int inverseF (double theta, double u) {
throw new UnsupportedOperationException();
}
/**
* Estimates the parameter θ of the logarithmic distribution
* using the maximum likelihood method, from the n observations
* x[i],
* i = 0, 1,…, n - 1. The estimate is returned in element 0
* of the returned array.
*
* @param x the list of observations used to evaluate parameters
*
* @param n the number of observations used to evaluate parameters
*
* @return returns the parameter [
* hat(&thetas;)]
*
*/
public static double[] getMLE (int[] x, int n) {
if (n <= 0)
throw new IllegalArgumentException ("n <= 0");
double parameters[];
parameters = new double[1];
double sum = 0.0;
for (int i = 0; i < n; i++) {
sum += x[i];
}
double mean = (double) sum / (double) n;
Function f = new Function (mean);
parameters[0] = RootFinder.brentDekker (1e-15, 1.0-1e-15, f, 1e-7);
return parameters;
}
/**
* Creates a new instance of a logarithmic distribution with parameter
* θ estimated using the maximum likelihood method based on the n
* observations x[i],
* i = 0, 1,…, n - 1.
*
* @param x the list of observations to use to evaluate parameters
*
* @param n the number of observations to use to evaluate parameters
*
*
*/
public static LogarithmicDist getInstanceFromMLE (int[] x, int n) {
double parameters[] = getMLE (x, n);
return new LogarithmicDist (parameters[0]);
}
/**
* Computes and returns the mean
* of the logarithmic distribution with parameter θ = theta.
*
* @return the mean of the logarithmic distribution
*
* E[X] = - θ/((1 - θ)ln(1 - θ))
*
*/
public static double getMean (double theta) {
if (theta <= 0.0 || theta >= 1.0)
throw new IllegalArgumentException ("theta not in range (0,1)");
return ((-1 / Math.log1p(-theta)) * (theta / (1 - theta)));
}
/**
* Computes and returns the variance
* of the logarithmic distribution with parameter θ = theta.
*
* @return the variance of the logarithmic distribution
*
* Var[X] = - θ(θ + ln(1 - θ))/((1 - θ)2(ln(1 - θ))2)
*
*/
public static double getVariance (double theta) {
if (theta <= 0.0 || theta >= 1.0)
throw new IllegalArgumentException ("theta not in range (0,1)");
double v = Math.log1p(-theta);
return ((-theta * (theta + v)) / ((1 - theta) * (1 - theta) * v * v));
}
/**
* Computes and returns the standard deviation of the
* logarithmic distribution with parameter θ = theta.
*
* @return the standard deviation of the logarithmic distribution
*
*/
public static double getStandardDeviation (double theta) {
return Math.sqrt (LogarithmicDist.getVariance (theta));
}
/**
* Returns the θ associated with this object.
*
*/
public double getTheta() {
return theta;
}
/**
* Sets the θ associated with this object.
*
*/
public void setTheta (double theta) {
if (theta <= 0 || theta >= 1)
throw new IllegalArgumentException ("theta not in range (0,1)");
this.theta = theta;
t = -1.0/Math.log1p (-theta);
supportA = 1;
}
/**
* Return a table containing the parameters of the current distribution.
*
*
*/
public double[] getParams () {
double[] retour = {theta};
return retour;
}
public String toString () {
return getClass().getSimpleName() + " : theta = " + theta;
}
}
Ads help maintain this website.