CauchyDistribution.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.OutOfRangeException;
  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 Cauchy distribution.
  26.  *
  27.  * @see <a href="http://en.wikipedia.org/wiki/Cauchy_distribution">Cauchy distribution (Wikipedia)</a>
  28.  * @see <a href="http://mathworld.wolfram.com/CauchyDistribution.html">Cauchy Distribution (MathWorld)</a>
  29.  * @since 1.1 (changed to concrete class in 3.0)
  30.  */
  31. public class CauchyDistribution extends AbstractRealDistribution {
  32.     /**
  33.      * Default inverse cumulative probability accuracy.
  34.      * @since 2.1
  35.      */
  36.     public static final double DEFAULT_INVERSE_ABSOLUTE_ACCURACY = 1e-9;
  37.     /** Serializable version identifier */
  38.     private static final long serialVersionUID = 8589540077390120676L;
  39.     /** The median of this distribution. */
  40.     private final double median;
  41.     /** The scale of this distribution. */
  42.     private final double scale;
  43.     /** Inverse cumulative probability accuracy */
  44.     private final double solverAbsoluteAccuracy;

  45.     /**
  46.      * Creates a Cauchy distribution with the median equal to zero and scale
  47.      * equal to one.
  48.      */
  49.     public CauchyDistribution() {
  50.         this(0, 1);
  51.     }

  52.     /**
  53.      * Creates a Cauchy distribution using the given median and scale.
  54.      * <p>
  55.      * <b>Note:</b> this constructor will implicitly create an instance of
  56.      * {@link Well19937c} as random generator to be used for sampling only (see
  57.      * {@link #sample()} and {@link #sample(int)}). In case no sampling is
  58.      * needed for the created distribution, it is advised to pass {@code null}
  59.      * as random generator via the appropriate constructors to avoid the
  60.      * additional initialisation overhead.
  61.      *
  62.      * @param median Median for this distribution.
  63.      * @param scale Scale parameter for this distribution.
  64.      */
  65.     public CauchyDistribution(double median, double scale) {
  66.         this(median, scale, DEFAULT_INVERSE_ABSOLUTE_ACCURACY);
  67.     }

  68.     /**
  69.      * Creates a Cauchy distribution using the given median and scale.
  70.      * <p>
  71.      * <b>Note:</b> this constructor will implicitly create an instance of
  72.      * {@link Well19937c} as random generator to be used for sampling only (see
  73.      * {@link #sample()} and {@link #sample(int)}). In case no sampling is
  74.      * needed for the created distribution, it is advised to pass {@code null}
  75.      * as random generator via the appropriate constructors to avoid the
  76.      * additional initialisation overhead.
  77.      *
  78.      * @param median Median for this distribution.
  79.      * @param scale Scale parameter for this distribution.
  80.      * @param inverseCumAccuracy Maximum absolute error in inverse
  81.      * cumulative probability estimates
  82.      * (defaults to {@link #DEFAULT_INVERSE_ABSOLUTE_ACCURACY}).
  83.      * @throws NotStrictlyPositiveException if {@code scale <= 0}.
  84.      * @since 2.1
  85.      */
  86.     public CauchyDistribution(double median, double scale,
  87.                               double inverseCumAccuracy) {
  88.         this(new Well19937c(), median, scale, inverseCumAccuracy);
  89.     }

  90.     /**
  91.      * Creates a Cauchy distribution.
  92.      *
  93.      * @param rng Random number generator.
  94.      * @param median Median for this distribution.
  95.      * @param scale Scale parameter for this distribution.
  96.      * @throws NotStrictlyPositiveException if {@code scale <= 0}.
  97.      * @since 3.3
  98.      */
  99.     public CauchyDistribution(RandomGenerator rng, double median, double scale) {
  100.         this(rng, median, scale, DEFAULT_INVERSE_ABSOLUTE_ACCURACY);
  101.     }

  102.     /**
  103.      * Creates a Cauchy distribution.
  104.      *
  105.      * @param rng Random number generator.
  106.      * @param median Median for this distribution.
  107.      * @param scale Scale parameter for this distribution.
  108.      * @param inverseCumAccuracy Maximum absolute error in inverse
  109.      * cumulative probability estimates
  110.      * (defaults to {@link #DEFAULT_INVERSE_ABSOLUTE_ACCURACY}).
  111.      * @throws NotStrictlyPositiveException if {@code scale <= 0}.
  112.      * @since 3.1
  113.      */
  114.     public CauchyDistribution(RandomGenerator rng,
  115.                               double median,
  116.                               double scale,
  117.                               double inverseCumAccuracy) {
  118.         super(rng);
  119.         if (scale <= 0) {
  120.             throw new NotStrictlyPositiveException(LocalizedFormats.SCALE, scale);
  121.         }
  122.         this.scale = scale;
  123.         this.median = median;
  124.         solverAbsoluteAccuracy = inverseCumAccuracy;
  125.     }

  126.     /** {@inheritDoc} */
  127.     public double cumulativeProbability(double x) {
  128.         return 0.5 + (FastMath.atan((x - median) / scale) / FastMath.PI);
  129.     }

  130.     /**
  131.      * Access the median.
  132.      *
  133.      * @return the median for this distribution.
  134.      */
  135.     public double getMedian() {
  136.         return median;
  137.     }

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

  146.     /** {@inheritDoc} */
  147.     public double density(double x) {
  148.         final double dev = x - median;
  149.         return (1 / FastMath.PI) * (scale / (dev * dev + scale * scale));
  150.     }

  151.     /**
  152.      * {@inheritDoc}
  153.      *
  154.      * Returns {@code Double.NEGATIVE_INFINITY} when {@code p == 0}
  155.      * and {@code Double.POSITIVE_INFINITY} when {@code p == 1}.
  156.      */
  157.     @Override
  158.     public double inverseCumulativeProbability(double p) throws OutOfRangeException {
  159.         double ret;
  160.         if (p < 0 || p > 1) {
  161.             throw new OutOfRangeException(p, 0, 1);
  162.         } else if (p == 0) {
  163.             ret = Double.NEGATIVE_INFINITY;
  164.         } else  if (p == 1) {
  165.             ret = Double.POSITIVE_INFINITY;
  166.         } else {
  167.             ret = median + scale * FastMath.tan(FastMath.PI * (p - .5));
  168.         }
  169.         return ret;
  170.     }

  171.     /** {@inheritDoc} */
  172.     @Override
  173.     protected double getSolverAbsoluteAccuracy() {
  174.         return solverAbsoluteAccuracy;
  175.     }

  176.     /**
  177.      * {@inheritDoc}
  178.      *
  179.      * The mean is always undefined no matter the parameters.
  180.      *
  181.      * @return mean (always Double.NaN)
  182.      */
  183.     public double getNumericalMean() {
  184.         return Double.NaN;
  185.     }

  186.     /**
  187.      * {@inheritDoc}
  188.      *
  189.      * The variance is always undefined no matter the parameters.
  190.      *
  191.      * @return variance (always Double.NaN)
  192.      */
  193.     public double getNumericalVariance() {
  194.         return Double.NaN;
  195.     }

  196.     /**
  197.      * {@inheritDoc}
  198.      *
  199.      * The lower bound of the support is always negative infinity no matter
  200.      * the parameters.
  201.      *
  202.      * @return lower bound of the support (always Double.NEGATIVE_INFINITY)
  203.      */
  204.     public double getSupportLowerBound() {
  205.         return Double.NEGATIVE_INFINITY;
  206.     }

  207.     /**
  208.      * {@inheritDoc}
  209.      *
  210.      * The upper bound of the support is always positive infinity no matter
  211.      * the parameters.
  212.      *
  213.      * @return upper bound of the support (always Double.POSITIVE_INFINITY)
  214.      */
  215.     public double getSupportUpperBound() {
  216.         return Double.POSITIVE_INFINITY;
  217.     }

  218.     /** {@inheritDoc} */
  219.     public boolean isSupportLowerBoundInclusive() {
  220.         return false;
  221.     }

  222.     /** {@inheritDoc} */
  223.     public boolean isSupportUpperBoundInclusive() {
  224.         return false;
  225.     }

  226.     /**
  227.      * {@inheritDoc}
  228.      *
  229.      * The support of this distribution is connected.
  230.      *
  231.      * @return {@code true}
  232.      */
  233.     public boolean isSupportConnected() {
  234.         return true;
  235.     }
  236. }