ParetoDistribution.java

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

  17. package org.apache.commons.math3.distribution;

  18. import org.apache.commons.math3.exception.NotStrictlyPositiveException;
  19. import org.apache.commons.math3.exception.NumberIsTooLargeException;
  20. import org.apache.commons.math3.exception.util.LocalizedFormats;
  21. import org.apache.commons.math3.random.RandomGenerator;
  22. import org.apache.commons.math3.random.Well19937c;
  23. import org.apache.commons.math3.util.FastMath;

  24. /**
  25.  * Implementation of the Pareto distribution.
  26.  *
  27.  * <p>
  28.  * <strong>Parameters:</strong>
  29.  * The probability distribution function of {@code X} is given by (for {@code x >= k}):
  30.  * <pre>
  31.  *  α * k^α / x^(α + 1)
  32.  * </pre>
  33.  * <p>
  34.  * <ul>
  35.  * <li>{@code k} is the <em>scale</em> parameter: this is the minimum possible value of {@code X},</li>
  36.  * <li>{@code α} is the <em>shape</em> parameter: this is the Pareto index</li>
  37.  * </ul>
  38.  *
  39.  * @see <a href="http://en.wikipedia.org/wiki/Pareto_distribution">
  40.  * Pareto distribution (Wikipedia)</a>
  41.  * @see <a href="http://mathworld.wolfram.com/ParetoDistribution.html">
  42.  * Pareto distribution (MathWorld)</a>
  43.  *
  44.  * @since 3.3
  45.  */
  46. public class ParetoDistribution extends AbstractRealDistribution {

  47.     /** Default inverse cumulative probability accuracy. */
  48.     public static final double DEFAULT_INVERSE_ABSOLUTE_ACCURACY = 1e-9;

  49.     /** Serializable version identifier. */
  50.     private static final long serialVersionUID = 20130424;

  51.     /** The scale parameter of this distribution. */
  52.     private final double scale;

  53.     /** The shape parameter of this distribution. */
  54.     private final double shape;

  55.     /** Inverse cumulative probability accuracy. */
  56.     private final double solverAbsoluteAccuracy;

  57.     /**
  58.      * Create a Pareto distribution with a scale of {@code 1} and a shape of {@code 1}.
  59.      */
  60.     public ParetoDistribution() {
  61.         this(1, 1);
  62.     }

  63.     /**
  64.      * Create a Pareto distribution using the specified scale and shape.
  65.      * <p>
  66.      * <b>Note:</b> this constructor will implicitly create an instance of
  67.      * {@link Well19937c} as random generator to be used for sampling only (see
  68.      * {@link #sample()} and {@link #sample(int)}). In case no sampling is
  69.      * needed for the created distribution, it is advised to pass {@code null}
  70.      * as random generator via the appropriate constructors to avoid the
  71.      * additional initialisation overhead.
  72.      *
  73.      * @param scale the scale parameter of this distribution
  74.      * @param shape the shape parameter of this distribution
  75.      * @throws NotStrictlyPositiveException if {@code scale <= 0} or {@code shape <= 0}.
  76.      */
  77.     public ParetoDistribution(double scale, double shape)
  78.         throws NotStrictlyPositiveException {
  79.         this(scale, shape, DEFAULT_INVERSE_ABSOLUTE_ACCURACY);
  80.     }

  81.     /**
  82.      * Create a Pareto distribution using the specified scale, shape and
  83.      * inverse cumulative distribution accuracy.
  84.      * <p>
  85.      * <b>Note:</b> this constructor will implicitly create an instance of
  86.      * {@link Well19937c} as random generator to be used for sampling only (see
  87.      * {@link #sample()} and {@link #sample(int)}). In case no sampling is
  88.      * needed for the created distribution, it is advised to pass {@code null}
  89.      * as random generator via the appropriate constructors to avoid the
  90.      * additional initialisation overhead.
  91.      *
  92.      * @param scale the scale parameter of this distribution
  93.      * @param shape the shape parameter of this distribution
  94.      * @param inverseCumAccuracy Inverse cumulative probability accuracy.
  95.      * @throws NotStrictlyPositiveException if {@code scale <= 0} or {@code shape <= 0}.
  96.      */
  97.     public ParetoDistribution(double scale, double shape, double inverseCumAccuracy)
  98.         throws NotStrictlyPositiveException {
  99.         this(new Well19937c(), scale, shape, inverseCumAccuracy);
  100.     }

  101.     /**
  102.      * Creates a Pareto distribution.
  103.      *
  104.      * @param rng Random number generator.
  105.      * @param scale Scale parameter of this distribution.
  106.      * @param shape Shape parameter of this distribution.
  107.      * @throws NotStrictlyPositiveException if {@code scale <= 0} or {@code shape <= 0}.
  108.      */
  109.     public ParetoDistribution(RandomGenerator rng, double scale, double shape)
  110.         throws NotStrictlyPositiveException {
  111.         this(rng, scale, shape, DEFAULT_INVERSE_ABSOLUTE_ACCURACY);
  112.     }

  113.     /**
  114.      * Creates a Pareto distribution.
  115.      *
  116.      * @param rng Random number generator.
  117.      * @param scale Scale parameter of this distribution.
  118.      * @param shape Shape parameter of this distribution.
  119.      * @param inverseCumAccuracy Inverse cumulative probability accuracy.
  120.      * @throws NotStrictlyPositiveException if {@code scale <= 0} or {@code shape <= 0}.
  121.      */
  122.     public ParetoDistribution(RandomGenerator rng,
  123.                               double scale,
  124.                               double shape,
  125.                               double inverseCumAccuracy)
  126.         throws NotStrictlyPositiveException {
  127.         super(rng);

  128.         if (scale <= 0) {
  129.             throw new NotStrictlyPositiveException(LocalizedFormats.SCALE, scale);
  130.         }

  131.         if (shape <= 0) {
  132.             throw new NotStrictlyPositiveException(LocalizedFormats.SHAPE, shape);
  133.         }

  134.         this.scale = scale;
  135.         this.shape = shape;
  136.         this.solverAbsoluteAccuracy = inverseCumAccuracy;
  137.     }

  138.     /**
  139.      * Returns the scale parameter of this distribution.
  140.      *
  141.      * @return the scale parameter
  142.      */
  143.     public double getScale() {
  144.         return scale;
  145.     }

  146.     /**
  147.      * Returns the shape parameter of this distribution.
  148.      *
  149.      * @return the shape parameter
  150.      */
  151.     public double getShape() {
  152.         return shape;
  153.     }

  154.     /**
  155.      * {@inheritDoc}
  156.      * <p>
  157.      * For scale {@code k}, and shape {@code α} of this distribution, the PDF
  158.      * is given by
  159.      * <ul>
  160.      * <li>{@code 0} if {@code x < k},</li>
  161.      * <li>{@code α * k^α / x^(α + 1)} otherwise.</li>
  162.      * </ul>
  163.      */
  164.     public double density(double x) {
  165.         if (x < scale) {
  166.             return 0;
  167.         }
  168.         return FastMath.pow(scale, shape) / FastMath.pow(x, shape + 1) * shape;
  169.     }

  170.     /** {@inheritDoc}
  171.      *
  172.      * See documentation of {@link #density(double)} for computation details.
  173.      */
  174.     @Override
  175.     public double logDensity(double x) {
  176.         if (x < scale) {
  177.             return Double.NEGATIVE_INFINITY;
  178.         }
  179.         return FastMath.log(scale) * shape - FastMath.log(x) * (shape + 1) + FastMath.log(shape);
  180.     }

  181.     /**
  182.      * {@inheritDoc}
  183.      * <p>
  184.      * For scale {@code k}, and shape {@code α} of this distribution, the CDF is given by
  185.      * <ul>
  186.      * <li>{@code 0} if {@code x < k},</li>
  187.      * <li>{@code 1 - (k / x)^α} otherwise.</li>
  188.      * </ul>
  189.      */
  190.     public double cumulativeProbability(double x)  {
  191.         if (x <= scale) {
  192.             return 0;
  193.         }
  194.         return 1 - FastMath.pow(scale / x, shape);
  195.     }

  196.     /**
  197.      * {@inheritDoc}
  198.      *
  199.      * @deprecated See {@link RealDistribution#cumulativeProbability(double,double)}
  200.      */
  201.     @Override
  202.     @Deprecated
  203.     public double cumulativeProbability(double x0, double x1)
  204.         throws NumberIsTooLargeException {
  205.         return probability(x0, x1);
  206.     }

  207.     /** {@inheritDoc} */
  208.     @Override
  209.     protected double getSolverAbsoluteAccuracy() {
  210.         return solverAbsoluteAccuracy;
  211.     }

  212.     /**
  213.      * {@inheritDoc}
  214.      * <p>
  215.      * For scale {@code k} and shape {@code α}, the mean is given by
  216.      * <ul>
  217.      * <li>{@code ∞} if {@code α <= 1},</li>
  218.      * <li>{@code α * k / (α - 1)} otherwise.</li>
  219.      * </ul>
  220.      */
  221.     public double getNumericalMean() {
  222.         if (shape <= 1) {
  223.             return Double.POSITIVE_INFINITY;
  224.         }
  225.         return shape * scale / (shape - 1);
  226.     }

  227.     /**
  228.      * {@inheritDoc}
  229.      * <p>
  230.      * For scale {@code k} and shape {@code α}, the variance is given by
  231.      * <ul>
  232.      * <li>{@code ∞} if {@code 1 < α <= 2},</li>
  233.      * <li>{@code k^2 * α / ((α - 1)^2 * (α - 2))} otherwise.</li>
  234.      * </ul>
  235.      */
  236.     public double getNumericalVariance() {
  237.         if (shape <= 2) {
  238.             return Double.POSITIVE_INFINITY;
  239.         }
  240.         double s = shape - 1;
  241.         return scale * scale * shape / (s * s) / (shape - 2);
  242.     }

  243.     /**
  244.      * {@inheritDoc}
  245.      * <p>
  246.      * The lower bound of the support is equal to the scale parameter {@code k}.
  247.      *
  248.      * @return lower bound of the support
  249.      */
  250.     public double getSupportLowerBound() {
  251.         return scale;
  252.     }

  253.     /**
  254.      * {@inheritDoc}
  255.      * <p>
  256.      * The upper bound of the support is always positive infinity no matter the parameters.
  257.      *
  258.      * @return upper bound of the support (always {@code Double.POSITIVE_INFINITY})
  259.      */
  260.     public double getSupportUpperBound() {
  261.         return Double.POSITIVE_INFINITY;
  262.     }

  263.     /** {@inheritDoc} */
  264.     public boolean isSupportLowerBoundInclusive() {
  265.         return true;
  266.     }

  267.     /** {@inheritDoc} */
  268.     public boolean isSupportUpperBoundInclusive() {
  269.         return false;
  270.     }

  271.     /**
  272.      * {@inheritDoc}
  273.      * <p>
  274.      * The support of this distribution is connected.
  275.      *
  276.      * @return {@code true}
  277.      */
  278.     public boolean isSupportConnected() {
  279.         return true;
  280.     }

  281.     /** {@inheritDoc} */
  282.     @Override
  283.     public double sample()  {
  284.         final double n = random.nextDouble();
  285.         return scale / FastMath.pow(n, 1 / shape);
  286.     }
  287. }