umontreal.iro.lecuyer.probdist.JohnsonSBDist Maven / Gradle / Ivy
Show all versions of ssj Show documentation
/*
* Class: JohnsonSBDist
* Description: Johnson S_Bdistribution
* Environment: Java
* Software: SSJ
* Copyright (C) 2001 Pierre L'Ecuyer and Université de Montréal
* Organization: DIRO, Université de Montréal
* @author
* @since
* SSJ is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License (GPL) as published by the
* Free Software Foundation, either version 3 of the License, or
* any later version.
* SSJ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* A copy of the GNU General Public License is available at
GPL licence site.
*/
package umontreal.iro.lecuyer.probdist;
import umontreal.iro.lecuyer.util.Num;
/**
* Extends the class {@link ContinuousDistribution} for
* the Johnson SB distribution
* with shape parameters γ and
* δ > 0, location parameter ξ,
* and scale parameter λ > 0.
* Denoting
* y = (x - ξ)/λ, the density is
*
*
*
* f (x) = δ/(λy(1-y)(2π)1/2exp(- (1/2)[γ + δln(y/(1 - y))]2)) for ξ < x < ξ + λ,
*
* and 0 elsewhere. The distribution function is
*
*
*
* F(x) = Φ[γ + δln(y/(1 - y))], for ξ < x < ξ + λ,
*
* where Φ is the standard normal distribution function.
* The inverse distribution function is
*
*
*
* F-1(u) = ξ + λ(1/(1 + e-v(u))) for 0 <= u <= 1,
*
* where
*
*
*
* v(u) = [Φ-1(u) - γ]/δ.
*
*
*
* This class relies on the methods {@link NormalDist#cdf01 NormalDist.cdf01} and
* {@link NormalDist#inverseF01 NormalDist.inverseF01}
* of {@link NormalDist} to approximate Φ and Φ-1.
*
*/
public class JohnsonSBDist extends ContinuousDistribution {
private double gamma;
private double delta;
private double xi;
private double lambda;
/**
* Constructs a JohnsonSBDist object
* with shape parameters γ and δ,
* location parameter ξ and scale parameter λ.
*
*/
public JohnsonSBDist (double gamma, double delta,
double xi, double lambda) {
setParams (gamma, delta, xi, lambda);
}
public double density (double x) {
return density (gamma, delta, xi, lambda, x);
}
public double cdf (double x) {
return cdf (gamma, delta, xi, lambda, x);
}
public double barF (double x) {
return barF (gamma, delta, xi, lambda, x);
}
public double inverseF (double u){
return inverseF (gamma, delta, xi, lambda, u);
}
/**
* Computes the density function.
*
*/
public static double density (double gamma, double delta,
double xi, double lambda, double x) {
if (lambda <= 0)
throw new IllegalArgumentException ("lambda <= 0");
if (delta <= 0)
throw new IllegalArgumentException ("delta <= 0");
if (x <= xi || x >= (xi+lambda))
return 0.0;
double y = (x - xi)/lambda;
double t1 = gamma + delta*Math.log (y/(1.0 - y));
return delta/(lambda*y*(1.0 - y)*Math.sqrt (2.0*Math.PI))*
Math.exp (-t1*t1/2.0);
}
/**
* Computes the distribution function.
*
*/
public static double cdf (double gamma, double delta,
double xi, double lambda, double x) {
if (lambda <= 0)
throw new IllegalArgumentException ("lambda <= 0");
if (delta <= 0)
throw new IllegalArgumentException ("delta <= 0");
if (x <= xi)
return 0.0;
if (x >= xi+lambda)
return 1.0;
double y = (x - xi)/lambda;
return NormalDist.cdf01 (gamma + delta*Math.log (y/(1.0 - y)));
}
/**
* Computes the complementary distribution.
*
*/
public static double barF (double gamma, double delta,
double xi, double lambda, double x) {
if (lambda <= 0)
throw new IllegalArgumentException ("lambda <= 0");
if (delta <= 0)
throw new IllegalArgumentException ("delta <= 0");
if (x <= xi)
return 1.0;
if (x >= xi+lambda)
return 0.0;
double y = (x - xi)/lambda;
return NormalDist.barF01 (gamma + delta*Math.log (y/(1.0 - y)));
}
/**
* Computes the inverse of the distribution.
*
*/
public static double inverseF (double gamma, double delta,
double xi, double lambda, double u) {
if (lambda <= 0)
throw new IllegalArgumentException ("lambda <= 0");
if (delta <= 0)
throw new IllegalArgumentException ("delta <= 0");
if (u > 1.0 || u < 0.0)
throw new IllegalArgumentException ("u not in [0,1]");
double v, z;
if (u >= 1.0) // if u == 1, in fact
return xi+lambda;
if (u <= 0.0) // if u == 0, in fact
return xi;
z = NormalDist.inverseF01 (u);
v = (z - gamma)/delta;
if ((z >= XBIG) || (v >= Num.DBL_MAX_EXP*Num.LN2))
return xi + lambda;
if ((z <= -XBIG) || (v <= -Num.DBL_MAX_EXP*Num.LN2))
return xi;
v = Math.exp (v);
return (xi + (xi+lambda)*v)/(1.0 + v);
}
/**
* Returns the value of γ for this object.
*
*/
public double getGamma() {
return gamma;
}
/**
* Returns the value of δ for this object.
*
*/
public double getDelta() {
return delta;
}
/**
* Returns the value of ξ for this object.
*
*/
public double getXi() {
return xi;
}
/**
* Returns the value of λ for this object.
*
*/
public double getLambda() {
return lambda;
}
/**
* Sets the value of the parameters γ, δ, ξ and
* λ for this object.
*
*/
public void setParams(double gamma, double delta, double xi,
double lambda) {
if (lambda <= 0)
throw new IllegalArgumentException ("lambda <= 0");
if (delta <= 0)
throw new IllegalArgumentException ("delta <= 0");
this.gamma = gamma;
this.delta = delta;
this.xi = xi;
this.lambda = lambda;
supportA = xi;
supportB = xi + lambda;
}
/**
* Return a table containing the parameters of the current distribution.
* This table is put in regular order: [γ, δ, ξ, λ].
*
*
*/
public double[] getParams () {
double[] retour = {gamma, delta, xi, lambda};
return retour;
}
public String toString () {
return getClass().getSimpleName() + " : gamma = " + gamma + ", delta = " + delta + ", xi = " + xi + ", lambda = " + lambda;
}
}