All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.commons.statistics.distribution.TriangularDistribution Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.commons.statistics.distribution;

/**
 * Implementation of the triangular distribution.
 *
 * 

The probability density function of \( X \) is: * *

\[ f(x; a, b, c) = \begin{cases} * \frac{2(x-a)}{(b-a)(c-a)} & \text{for } a \le x \lt c \\ * \frac{2}{b-a} & \text{for } x = c \\ * \frac{2(b-x)}{(b-a)(b-c)} & \text{for } c \lt x \le b \\ * \end{cases} \] * *

for \( -\infty \lt a \le c \le b \lt \infty \) and * \( x \in [a, b] \). * * @see Triangular distribution (Wikipedia) * @see Triangular distribution (MathWorld) */ public final class TriangularDistribution extends AbstractContinuousDistribution { /** Lower limit of this distribution (inclusive). */ private final double a; /** Upper limit of this distribution (inclusive). */ private final double b; /** Mode of this distribution. */ private final double c; /** Cached value ((b - a) * (c - a). */ private final double divisor1; /** Cached value ((b - a) * (b - c)). */ private final double divisor2; /** Cumulative probability at the mode. */ private final double cdfMode; /** Survival probability at the mode. */ private final double sfMode; /** * @param a Lower limit of this distribution (inclusive). * @param c Mode of this distribution. * @param b Upper limit of this distribution (inclusive). */ private TriangularDistribution(double a, double c, double b) { this.a = a; this.c = c; this.b = b; divisor1 = (b - a) * (c - a); divisor2 = (b - a) * (b - c); cdfMode = (c - a) / (b - a); sfMode = (b - c) / (b - a); } /** * Creates a triangular distribution. * * @param a Lower limit of this distribution (inclusive). * @param c Mode of this distribution. * @param b Upper limit of this distribution (inclusive). * @return the distribution * @throws IllegalArgumentException if {@code a >= b}, if {@code c > b} or if * {@code c < a}. */ public static TriangularDistribution of(double a, double c, double b) { if (a >= b) { throw new DistributionException(DistributionException.INVALID_RANGE_LOW_GTE_HIGH, a, b); } if (c < a) { throw new DistributionException(DistributionException.TOO_SMALL, c, a); } if (c > b) { throw new DistributionException(DistributionException.TOO_LARGE, c, b); } return new TriangularDistribution(a, c, b); } /** * Gets the mode parameter of this distribution. * * @return the mode. */ public double getMode() { return c; } /** {@inheritDoc} */ @Override public double density(double x) { if (x < a) { return 0; } if (x < c) { final double divident = 2 * (x - a); return divident / divisor1; } if (x == c) { return 2 / (b - a); } if (x <= b) { final double divident = 2 * (b - x); return divident / divisor2; } return 0; } /** {@inheritDoc} */ @Override public double cumulativeProbability(double x) { if (x <= a) { return 0; } if (x < c) { final double divident = (x - a) * (x - a); return divident / divisor1; } if (x == c) { return cdfMode; } if (x < b) { final double divident = (b - x) * (b - x); return 1 - (divident / divisor2); } return 1; } /** {@inheritDoc} */ @Override public double survivalProbability(double x) { // By symmetry: if (x <= a) { return 1; } if (x < c) { final double divident = (x - a) * (x - a); return 1 - (divident / divisor1); } if (x == c) { return sfMode; } if (x < b) { final double divident = (b - x) * (b - x); return divident / divisor2; } return 0; } /** {@inheritDoc} */ @Override public double inverseCumulativeProbability(double p) { ArgumentUtils.checkProbability(p); if (p == 0) { return a; } if (p == 1) { return b; } if (p < cdfMode) { return a + Math.sqrt(p * divisor1); } return b - Math.sqrt((1 - p) * divisor2); } /** {@inheritDoc} */ @Override public double inverseSurvivalProbability(double p) { // By symmetry: ArgumentUtils.checkProbability(p); if (p == 1) { return a; } if (p == 0) { return b; } if (p >= sfMode) { return a + Math.sqrt((1 - p) * divisor1); } return b - Math.sqrt(p * divisor2); } /** * {@inheritDoc} * *

For lower limit \( a \), upper limit \( b \), and mode \( c \), * the mean is \( (a + b + c) / 3 \). */ @Override public double getMean() { return (a + b + c) / 3; } /** * {@inheritDoc} * *

For lower limit \( a \), upper limit \( b \), and mode \( c \), * the variance is \( (a^2 + b^2 + c^2 - ab - ac - bc) / 18 \). */ @Override public double getVariance() { return (a * a + b * b + c * c - a * b - a * c - b * c) / 18; } /** * {@inheritDoc} * *

The lower bound of the support is equal to the lower limit parameter * {@code a} of the distribution. */ @Override public double getSupportLowerBound() { return a; } /** * {@inheritDoc} * *

The upper bound of the support is equal to the upper limit parameter * {@code b} of the distribution. */ @Override public double getSupportUpperBound() { return b; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy