/* *
 * Title:        

* Description:

* Copyright: Copyright (c)

* Company:

* @author * @version 1.0 */ package umontreal.iro.lecuyer.probdist; import java.util.Arrays; /** * Extends the class {@link ContinuousDistribution} for * the triangular distribution with domain [a, b] and mode * (or shape parameter) m, where * a <= m <= b. * The density function is *

*

*
* * * * * * * * * * * * * *
f (x) =2(x - a)/[(b - a)(m - a)]         for a <= x <= m,
f (x) =2(b - x)/[(b - a)(b - m)]         for m <= x <= b,
f (x) =0         elsewhere,
*

* the distribution function is *

*

*
* * * * * * * * * * * * * * * * * *
F(x) =0         for x < a,
F(x) =(x - a)2/[(b - a)(m - a)]         if a <= x <= m,
F(x) =1 - (b - x)2/[(b - a)(b - m)]         if m <= x <= b,
F(x) =1         for x > b,
*

* and the inverse distribution function is given by *

*

*
* * * * * * * * * *
F-1(u) =a + ((b - a)(m - a)u)1/2         if 0 <= u <= (m - a)/(b - a),
F-1(u) =b - ((b - a)(b - m)(1 - u))1/2         if (m - a)/(b - a <= u <= 1.
*

* */ public class TriangularDist extends ContinuousDistribution { private double a; private double b; private double m; /** * Constructs a TriangularDist object with default parameters * a = 0, b = 1, and m = 0.5. * */ public TriangularDist() { setParams (0.0, 1.0, 0.5); } /** * Constructs a TriangularDist object with parameters a = 0 , * b = 1 and m = m. * */ public TriangularDist (double m) { setParams (0.0, 1.0, m); } /** * Constructs a TriangularDist object with * parameters a, b and m. * */ public TriangularDist (double a, double b, double m) { setParams (a, b, m); } public double density (double x) { return density (a, b, m, x); } public double cdf (double x) { return cdf (a, b, m, x); } public double barF (double x) { return barF (a, b, m, x); } public double inverseF (double u){ return inverseF (a, b, m, u); } public double getMean() { return TriangularDist.getMean (a, b, m); } public double getVariance() { return TriangularDist.getVariance (a, b, m); } public double getStandardDeviation() { return TriangularDist.getStandardDeviation (a, b, m); } /** * Computes the density function. * */ public static double density (double a, double b, double m, double x) { if (m < a || m > b) throw new IllegalArgumentException ("m is not in [a,b]"); if (x < a || x > b) return 0.0; else if (x <= m && m != a) return 2.0*(x - a)/((b - a)*(m - a)); else return 2.0*(b - x)/((b - a)*(b - m)); } /** * Computes the distribution function. * */ public static double cdf (double a, double b, double m, double x) { if (m < a || m > b) throw new IllegalArgumentException ("m is not in [a,b]"); if (x <= a) return 0.0; else if (x <= m && m != a) return (x - a)*(x - a)/((b - a)*(m - a)); else if (x < b) return 1.0 - (b - x)*(b - x)/((b - a)*(b - m)); else return 1.0; } /** * Computes the complementary distribution function. * */ public static double barF (double a, double b, double m, double x) { if (m < a || m > b) throw new IllegalArgumentException ("m is not in [a,b]"); if (x <= a) return 1.0; else if (x <= m && m != a) return 1.0 - (x - a)*(x - a)/((b - a)*(m - a)); else if (x < b) return (b - x)*(b - x)/((b - a)*(b - m)); else return 0.0; } /** * Computes the inverse distribution function. * */ public static double inverseF (double a, double b, double m, double u) { if (m < a || m > b) throw new IllegalArgumentException ("m is not in [a,b]"); if (u < 0.0 || u > 1.0) throw new IllegalArgumentException ("u is not in [0,1]"); if (u <= 0.0) return a; if (u >= 1.0) return b; // the code is taken and adapted from unuran // file /distributions/c_triangular_gen.c double h = (m - a)/(b - a); return u <= h && m != a ? a + Math.sqrt ((b - a)*(m - a)*u) : b - Math.sqrt ((b - a)*(b - m)*(1 - u)); } /** * Estimates the parameter m of the triangular distribution using the * maximum likelihood method, from the n observations x[i], * * i = 0, 1,…, n - 1. The estimated parameter is returned in a one-element * array: [hat(m)]. See. * * @param x the list of observations used to evaluate parameters * * @param n the number of observations used to evaluate parameters * * @param a lower limit of range * * @param b upper limit of range * * @return returns the parameter [m] * */ public static double[] getMLE (double[] x, int n, double a, double b) { if (n <= 0) throw new IllegalArgumentException ("n <= 0"); double[] Y = new double[n]; // sorted x[i] System.arraycopy (x, 0, Y, 0, n); Arrays.sort (Y); int rmax = -1; double prodmax = -1.0e300; final double ba = b - a; double z; int i; for (int r = 0; r < n; r++) { z = (Y[r] - a) / ba; if ((z <= (double)r/n) || (z >= (double)(r + 1)/n)) continue; // MLE cannot be there double prod = 1.0; double d = Y[r] - a; for (i = 0; i < r; i++) prod *= (Y[i] - a)/d; d = b - Y[r]; for (i = r+1; i < n; i++) prod *= (b - Y[i])/d; if (prod > prodmax) { prodmax = prod; rmax = r; } } if (rmax < 0) throw new UnsupportedOperationException ( " data cannot fit a triangular distribution"); double[] param = new double[1]; param[0] = Y[rmax]; return param; } /** * Creates a new instance of a triangular distribution with parameters * a and b. m is estimated using the maximum * likelihood method based on the n observations * x[i], * i = 0, 1,…, n - 1. * * @param x the list of observations used to evaluate parameters * * @param n the number of observations used to evaluate parameters * * @param a lower limit of range * * @param b upper limit of range * * */ public static TriangularDist getInstanceFromMLE (double[] x, int n, double a, double b) { double param[] = getMLE (x, n, a, b); return new TriangularDist (a, b, param[0]); } /** * Computes and returns the mean * E[X] = (a + b + m)/3 * of the triangular distribution with parameters a, b, m. * * @return the mean of the triangular distribution * */ public static double getMean (double a, double b, double m) { if ((a == 0.0 && b == 1.0) && (m < 0 || m > 1)) throw new IllegalArgumentException ("m is not in [0,1]"); else if (m < a || m > b) throw new IllegalArgumentException ("m is not in [a,b]"); return ((a + b + m) / 3.0); } /** * Computes and returns the variance * * Var[X] = (a2 + b2 + m2 - ab - am - bm)/18 * of the triangular distribution with parameters a, b, m. * * @return the variance of the triangular distribution * */ public static double getVariance (double a, double b, double m) { if ((a == 0.0 && b == 1.0) && (m < 0 || m > 1)) throw new IllegalArgumentException ("m is not in [0,1]"); else if (m < a || m > b) throw new IllegalArgumentException ("m is not in [a,b]"); return ((a * a + b * b + m * m - a * b - a * m - b * m) / 18.0); } /** * Computes and returns the standard deviation * of the triangular distribution with parameters a, b, m. * * @return the standard deviation of the triangular distribution * */ public static double getStandardDeviation (double a, double b, double m) { return Math.sqrt (TriangularDist.getVariance (a, b, m)); } /** * Returns the value of a for this object. * */ public double getA() { return a; } /** * Returns the value of b for this object. * */ public double getB() { return b; } /** * Returns the value of m for this object. * */ public double getM() { return m; } /** * Sets the value of the parameters a, b and m for this object. * */ public void setParams (double a, double b, double m) { if ((a == 0.0 && b == 1.0) && (m < 0 || m > 1)) throw new IllegalArgumentException ("m is not in [0,1]"); else if (a >= b) throw new IllegalArgumentException ("a >= b"); else if (m < a || m > b) throw new IllegalArgumentException ("m is not in [a,b]"); this.a = a; this.b = b; this.m = m; supportA = a; supportB = b; } /** * Return a table containing the parameters of the current distribution. * This table is put in regular order: [a, b, m]. * */ public double[] getParams () { double[] retour = {a, b, m}; return retour; } /** * Returns a String containing information about the current distribution. * */ public String toString () { return getClass().getSimpleName() + " : a = " + a + ", b = " + b + ", m = " + m; } }

Ads help maintain this website.