LevyDistribution.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.  *      https://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. /*
  18.  * This is not the original file distributed by the Apache Software Foundation
  19.  * It has been modified by the Hipparchus project
  20.  */
  21. package org.hipparchus.distribution.continuous;

  22. import org.hipparchus.exception.MathIllegalArgumentException;
  23. import org.hipparchus.special.Erf;
  24. import org.hipparchus.util.FastMath;
  25. import org.hipparchus.util.MathUtils;

  26. /**
  27.  * This class implements the <a href="http://en.wikipedia.org/wiki/L%C3%A9vy_distribution">
  28.  * L&eacute;vy distribution</a>.
  29.  */
  30. public class LevyDistribution extends AbstractRealDistribution {

  31.     /** Serializable UID. */
  32.     private static final long serialVersionUID = 20130314L;

  33.     /** Location parameter. */
  34.     private final double mu;

  35.     /** Scale parameter. */
  36.     private final double c;  // Setting this to 1 returns a cumProb of 1.0

  37.     /** Half of c (for calculations). */
  38.     private final double halfC;

  39.     /**
  40.      * Build a new instance.
  41.      *
  42.      * @param mu location parameter
  43.      * @param c scale parameter
  44.      */
  45.     public LevyDistribution(final double mu, final double c) {
  46.         super();
  47.         this.mu    = mu;
  48.         this.c     = c;
  49.         this.halfC = 0.5 * c;
  50.     }


  51.     /** {@inheritDoc}
  52.     * <p>
  53.     * From Wikipedia: The probability density function of the L&eacute;vy distribution
  54.     * over the domain is
  55.     * </p>
  56.     * \[
  57.     * f(x; \mu, c) = \sqrt{\frac{c}{2\pi}} \frac{e^{\frac{-c}{2 (x - \mu)}}}{(x - \mu)^\frac{3}{2}}
  58.     * \]
  59.     * <p>
  60.     * For this distribution, {@code X}, this method returns {@code P(X < x)}.
  61.     * If {@code x} is less than location parameter &mu;, {@code Double.NaN} is
  62.     * returned, as in these cases the distribution is not defined.
  63.     * </p>
  64.     */
  65.     @Override
  66.     public double density(final double x) {
  67.         if (x < mu) {
  68.             return Double.NaN;
  69.         }

  70.         final double delta = x - mu;
  71.         final double f     = halfC / delta;
  72.         return FastMath.sqrt(f / FastMath.PI) * FastMath.exp(-f) /delta;
  73.     }

  74.     /** {@inheritDoc}
  75.      *
  76.      * See documentation of {@link #density(double)} for computation details.
  77.      */
  78.     @Override
  79.     public double logDensity(double x) {
  80.         if (x < mu) {
  81.             return Double.NaN;
  82.         }

  83.         final double delta = x - mu;
  84.         final double f     = halfC / delta;
  85.         return 0.5 * FastMath.log(f / FastMath.PI) - f - FastMath.log(delta);
  86.     }

  87.     /** {@inheritDoc}
  88.      * <p>
  89.      * From Wikipedia: the cumulative distribution function is
  90.      * </p>
  91.      * <pre>
  92.      * f(x; u, c) = erfc (&radic; (c / 2 (x - u )))
  93.      * </pre>
  94.      */
  95.     @Override
  96.     public double cumulativeProbability(final double x) {
  97.         if (x < mu) {
  98.             return Double.NaN;
  99.         }
  100.         return Erf.erfc(FastMath.sqrt(halfC / (x - mu)));
  101.     }

  102.     /** {@inheritDoc} */
  103.     @Override
  104.     public double inverseCumulativeProbability(final double p) throws MathIllegalArgumentException {
  105.         MathUtils.checkRangeInclusive(p, 0, 1);
  106.         final double t = Erf.erfcInv(p);
  107.         return mu + halfC / (t * t);
  108.     }

  109.     /** Get the scale parameter of the distribution.
  110.      * @return scale parameter of the distribution
  111.      */
  112.     public double getScale() {
  113.         return c;
  114.     }

  115.     /** Get the location parameter of the distribution.
  116.      * @return location parameter of the distribution
  117.      */
  118.     public double getLocation() {
  119.         return mu;
  120.     }

  121.     /** {@inheritDoc} */
  122.     @Override
  123.     public double getNumericalMean() {
  124.         return Double.POSITIVE_INFINITY;
  125.     }

  126.     /** {@inheritDoc} */
  127.     @Override
  128.     public double getNumericalVariance() {
  129.         return Double.POSITIVE_INFINITY;
  130.     }

  131.     /** {@inheritDoc} */
  132.     @Override
  133.     public double getSupportLowerBound() {
  134.         return mu;
  135.     }

  136.     /** {@inheritDoc} */
  137.     @Override
  138.     public double getSupportUpperBound() {
  139.         return Double.POSITIVE_INFINITY;
  140.     }

  141.     /** {@inheritDoc} */
  142.     @Override
  143.     public boolean isSupportConnected() {
  144.         return true;
  145.     }

  146. }