added cauchy distribution

git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/math/trunk@155159 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Brent Worden 2005-02-24 03:59:05 +00:00
parent 0bc811fa7f
commit 19ddf2957e
10 changed files with 414 additions and 18 deletions

View File

@ -0,0 +1,59 @@
/*
* Copyright 2005 The Apache Software Foundation.
*
* Licensed 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.math.distribution;
/**
* Cauchy Distribution.
* Instances of CauchyDistribution objects should be created using
* {@link DistributionFactory#createCauchyDistribution(double, double)}.<p>
*
* <p>
* References:<p>
* <ul>
* <li><a href="http://mathworld.wolfram.com/CauchyDistribution.html">
* Cauchy Distribution</a></li>
* </ul>
* </p>
*
* @version $Revision: 1.8 $ $Date: 2004-06-23 11:26:18 -0500 (Wed, 23 Jun 2004) $
*/
public interface CauchyDistribution extends ContinuousDistribution {
/**
* Access the median.
* @return median for this distribution
*/
double getMedian();
/**
* Access the scale parameter.
* @return scale parameter for this distribution
*/
double getScale();
/**
* Modify the median.
* @param median for this distribution
*/
void setMedian(double median);
/**
* Modify the scale parameter.
* @param s scale parameter for this distribution
*/
void setScale(double s);
}

View File

@ -0,0 +1,194 @@
/*
* Copyright 2005 The Apache Software Foundation.
*
* Licensed 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.math.distribution;
import java.io.Serializable;
/**
* Default implementation of
* {@link org.apache.commons.math.distribution.CauchyDistribution}.
*
* @version $Revision: 1.13 $ $Date: 2004-07-24 16:41:37 -0500 (Sat, 24 Jul 2004) $
*/
public class CauchyDistributionImpl extends AbstractContinuousDistribution
implements CauchyDistribution, Serializable {
/** Serializable version identifier */
static final long serialVersionUID = 8589540077390120676L;
/** The median of this distribution. */
private double median = 0;
/** The scale of this distribution. */
private double scale = 1;
/**
* Creates normal distribution with the mean equal to zero and standard
* deviation equal to one.
*/
public CauchyDistributionImpl(){
this(0.0, 1.0);
}
/**
* Create a cauchy distribution using the given median and scale.
* @param median median for this distribution
* @param s scale parameter for this distribution
*/
public CauchyDistributionImpl(double median, double s){
super();
setMedian(median);
setScale(s);
}
/**
* For this disbution, X, this method returns P(X &lt; <code>x</code>).
* @param x the value at which the CDF is evaluated.
* @return CDF evaluted at <code>x</code>.
*/
public double cumulativeProbability(double x) {
return 0.5 + (Math.atan((x - median) / scale) / Math.PI);
}
/**
* Access the median.
* @return median for this distribution
*/
public double getMedian() {
return median;
}
/**
* Access the scale parameter.
* @return scale parameter for this distribution
*/
public double getScale() {
return scale;
}
/**
* For this distribution, X, this method returns the critical point x, such
* that P(X &lt; x) = <code>p</code>.
* <p>
* Returns <code>Double.NEGATIVE_INFINITY</code> for p=0 and
* <code>Double.POSITIVE_INFINITY</code> for p=1.
*
* @param p the desired probability
* @return x, such that P(X &lt; x) = <code>p</code>
* @throws IllegalArgumentException if <code>p</code> is not a valid
* probability.
*/
public double inverseCumulativeProbability(double p) {
double ret;
if (p < 0.0 || p > 1.0) {
throw new IllegalArgumentException
("probability argument must be between 0 and 1 (inclusive)");
} else if (p == 0) {
ret = Double.NEGATIVE_INFINITY;
} else if (p == 1) {
ret = Double.POSITIVE_INFINITY;
} else {
ret = median + scale * Math.tan(Math.PI * (p - .5));
}
return ret;
}
/**
* Modify the median.
* @param median for this distribution
*/
public void setMedian(double median) {
this.median = median;
}
/**
* Modify the scale parameter.
* @param s scale parameter for this distribution
* @throws IllegalArgumentException if <code>sd</code> is not positive.
*/
public void setScale(double s) {
if (s <= 0.0) {
throw new IllegalArgumentException(
"Scale must be positive.");
}
scale = s;
}
/**
* Access the domain value lower bound, based on <code>p</code>, used to
* bracket a CDF root. This method is used by
* {@link #inverseCumulativeProbability(double)} to find critical values.
*
* @param p the desired probability for the critical value
* @return domain value lower bound, i.e.
* P(X &lt; <i>lower bound</i>) &lt; <code>p</code>
*/
protected double getDomainLowerBound(double p) {
double ret;
if (p < .5) {
ret = -Double.MAX_VALUE;
} else {
ret = getMedian();
}
return ret;
}
/**
* Access the domain value upper bound, based on <code>p</code>, used to
* bracket a CDF root. This method is used by
* {@link #inverseCumulativeProbability(double)} to find critical values.
*
* @param p the desired probability for the critical value
* @return domain value upper bound, i.e.
* P(X &lt; <i>upper bound</i>) &gt; <code>p</code>
*/
protected double getDomainUpperBound(double p) {
double ret;
if (p < .5) {
ret = getMedian();
} else {
ret = Double.MAX_VALUE;
}
return ret;
}
/**
* Access the initial domain value, based on <code>p</code>, used to
* bracket a CDF root. This method is used by
* {@link #inverseCumulativeProbability(double)} to find critical values.
*
* @param p the desired probability for the critical value
* @return initial domain value
*/
protected double getInitialDomain(double p) {
double ret;
if (p < .5) {
ret = getMedian() - getScale();
} else if (p > .5) {
ret = getMedian() + getScale();
} else {
ret = getMedian();
}
return ret;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2003-2004 The Apache Software Foundation.
* Copyright 2003-2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -23,6 +23,7 @@ import org.apache.commons.discovery.tools.DiscoverClass;
* The following distributions are supported:
* <ul>
* <li>Binomial</li>
* <li>Cauchy</li>
* <li>Chi-Squared</li>
* <li>Exponential</li>
* <li>F</li>
@ -40,7 +41,7 @@ import org.apache.commons.discovery.tools.DiscoverClass;
* ChiSquaredDistribution chi = factory.createChiSquareDistribution(5.0);
* </pre>
*
* @version $Revision: 1.22 $ $Date: 2004/11/07 03:32:48 $
* @version $Revision: 1.22 $ $Date$
*/
public abstract class DistributionFactory {
/**
@ -78,6 +79,18 @@ public abstract class DistributionFactory {
public abstract BinomialDistribution createBinomialDistribution(
int numberOfTrials, double probabilityOfSuccess);
/**
* Create a new cauchy distribution with the given median and scale.
* @param median the median of the distribution
* @param scale the scale
* @return a new cauchy distribution
*/
public CauchyDistribution createCauchyDistribution(
double median, double scale)
{
return new CauchyDistributionImpl(median, scale);
}
/**
* Create a new chi-square distribution with the given degrees of freedom.
*

View File

@ -0,0 +1,96 @@
/*
* Copyright 2005 The Apache Software Foundation.
*
* Licensed 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.math.distribution;
/**
* Test cases for CauchyDistribution.
* Extends ContinuousDistributionAbstractTest. See class javadoc for
* ContinuousDistributionAbstractTest for details.
*
* @version $Revision: 1.8 $ $Date: 2004-07-24 16:41:37 -0500 (Sat, 24 Jul 2004) $
*/
public class CauchyDistributionTest extends ContinuousDistributionAbstractTest {
/**
* Constructor for CauchyDistributionTest.
* @param arg0
*/
public CauchyDistributionTest(String arg0) {
super(arg0);
}
//-------------- Implementations for abstract methods -----------------------
/** Creates the default continuous distribution instance to use in tests. */
public ContinuousDistribution makeDistribution() {
return DistributionFactory.newInstance().createCauchyDistribution(1.2, 2.1);
}
/** Creates the default cumulative probability distribution test input values */
public double[] makeCumulativeTestPoints() {
// quantiles computed using Mathematica
return new double[] {-667.2485619d, -65.6230835d, -25.48302995d,
-12.05887818d, -5.263135428d, 7.663135428d, 14.45887818d,
27.88302995d, 68.0230835d, 669.6485619d};
}
/** Creates the default cumulative probability density test expected values */
public double[] makeCumulativeTestValues() {
return new double[] {0.001d, 0.01d, 0.025d, 0.05d, 0.1d, 0.900d, 0.950d,
0.975d, 0.990d, 0.999d};
}
//---------------------------- Additional test cases -------------------------
public void testInverseCumulativeProbabilityExtremes() throws Exception {
setInverseCumulativeTestPoints(new double[] {0.0, 1.0});
setInverseCumulativeTestValues(
new double[] {Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY});
verifyInverseCumulativeProbabilities();
}
public void testMedian() {
CauchyDistribution distribution = (CauchyDistribution) getDistribution();
double expected = Math.random();
distribution.setMedian(expected);
assertEquals(expected, distribution.getMedian(), 0.0);
}
public void testScale() {
CauchyDistribution distribution = (CauchyDistribution) getDistribution();
double expected = Math.random();
distribution.setScale(expected);
assertEquals(expected, distribution.getScale(), 0.0);
}
public void testSetScale() {
CauchyDistribution distribution = (CauchyDistribution) getDistribution();
try {
distribution.setScale(0.0);
fail("Can not have 0.0 scale.");
} catch (IllegalArgumentException ex) {
// success
}
try {
distribution.setScale(-1.0);
fail("Can not have negative scale.");
} catch (IllegalArgumentException ex) {
// success
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2003-2004 The Apache Software Foundation.
* Copyright 2003-2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -19,7 +19,7 @@ package org.apache.commons.math.distribution;
import junit.framework.TestCase;
/**
* @version $Revision: 1.16 $ $Date: 2004/02/21 21:35:17 $
* @version $Revision: 1.16 $ $Date$
*/
public class DistributionFactoryImplTest extends TestCase {
/** */
@ -317,4 +317,12 @@ public class DistributionFactoryImplTest extends TestCase {
fail("valid sample size. IllegalArgumentException is not expected");
}
}
public void testHypergeometricDistributionSmallPopulationSize() {
try {
factory.createHypergeometricDistribution(5, 3, 10);
fail("sample size larger than population size. IllegalArgumentException expected");
} catch(IllegalArgumentException ex) {
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2003-2004 The Apache Software Foundation.
* Copyright 2003-2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -21,7 +21,7 @@ package org.apache.commons.math.distribution;
* Extends IntegerDistributionAbstractTest. See class javadoc for
* IntegerDistributionAbstractTest for details.
*
* @version $Revision: 1.13 $ $Date: 2004/11/07 03:32:49 $
* @version $Revision: 1.13 $ $Date$
*/
public class HypergeometricDistributionTest extends IntegerDistributionAbstractTest {
@ -117,4 +117,15 @@ public class HypergeometricDistributionTest extends IntegerDistributionAbstractT
verifyInverseCumulativeProbabilities();
}
public void testPopulationSize() {
HypergeometricDistribution dist = DistributionFactory.newInstance().createHypergeometricDistribution(5,3,5);
try {
dist.setPopulationSize(-1);
fail("negative population size. IllegalArgumentException expected");
} catch(IllegalArgumentException ex) {
}
dist.setPopulationSize(10);
assertEquals(10, dist.getPopulationSize());
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2004 The Apache Software Foundation.
* Copyright 2004-2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,7 +18,7 @@ package org.apache.commons.math.distribution;
/**
* <code>PoissonDistributionTest</code>
*
* @version $Revision: 1.2 $ $Date: 2004/11/07 20:39:15 $
* @version $Revision: 1.2 $ $Date$
*/
public class PoissonDistributionTest extends IntegerDistributionAbstractTest {
@ -102,7 +102,7 @@ public class PoissonDistributionTest extends IntegerDistributionAbstractTest {
* P(9900 &le; X &le; 10200) for X = Po(10000)
*/
public void testNormalApproximateProbability() throws Exception {
PoissonDistribution dist = new PoissonDistributionImpl(100);
PoissonDistribution dist = DistributionFactory.newInstance().createPoissonDistribution(100);
double result = dist.normalApproximateProbability(110)
- dist.normalApproximateProbability(89);
assertEquals(0.706281887248, result, 1E-10);
@ -117,9 +117,20 @@ public class PoissonDistributionTest extends IntegerDistributionAbstractTest {
* @throws Exception
*/
public void testDegenerateInverseCumulativeProbability() throws Exception {
PoissonDistribution dist = new PoissonDistributionImpl(
DEFAULT_TEST_POISSON_PARAMETER);
assertEquals(Integer.MAX_VALUE, dist.inverseCumulativeProbability(1.0d));
assertEquals(-1, dist.inverseCumulativeProbability(0d));
PoissonDistribution dist = DistributionFactory.newInstance().createPoissonDistribution(DEFAULT_TEST_POISSON_PARAMETER);
assertEquals(Integer.MAX_VALUE, dist.inverseCumulativeProbability(1.0d));
assertEquals(-1, dist.inverseCumulativeProbability(0d));
}
public void testMean() {
PoissonDistribution dist = DistributionFactory.newInstance().createPoissonDistribution(DEFAULT_TEST_POISSON_PARAMETER);
try {
dist.setMean(-1);
fail("negative mean. IllegalArgumentException expected");
} catch(IllegalArgumentException ex) {
}
dist.setMean(10.0);
assertEquals(10.0, dist.getMean(), 0.0);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2003-2004 The Apache Software Foundation.
* Copyright 2003-2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -43,13 +43,13 @@ public class TDistributionTest extends ContinuousDistributionAbstractTest {
public double[] makeCumulativeTestPoints() {
// quantiles computed using R version 1.8.1 (linux version)
return new double[] {-5.89343,-3.36493, -2.570582, -2.015048,
-1.475884, 5.89343, 3.36493, 2.570582,
-1.475884, 0.0, 5.89343, 3.36493, 2.570582,
2.015048, 1.475884};
}
/** Creates the default cumulative probability density test expected values */
public double[] makeCumulativeTestValues() {
return new double[] {0.001d, 0.01d, 0.025d, 0.05d, 0.1d, 0.999d,
return new double[] {0.001d, 0.01d, 0.025d, 0.05d, 0.1d, 0.0d, 0.999d,
0.990d, 0.975d, 0.950d, 0.900d};
}

View File

@ -39,6 +39,9 @@ The <action> type attribute can be add,update,fix,remove.
<body>
<release version="1.1" date="In Development"
description="Jakarta Commons Math 1.1 - Development">
<action dev="brentworden" type="add">
Added Cauchy distribution implementation.
</action>
<action dev="brentworden" type="add">
Added convience methods for rounding.
</action>

View File

@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!--
Copyright 2003-2004 The Apache Software Foundation
Copyright 2003-2005 The Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -17,7 +17,7 @@
-->
<?xml-stylesheet type="text/xsl" href="./xdoc.xsl"?>
<!-- $Revision: 1.3 $ $Date: 2004/11/09 12:41:37 $ -->
<!-- $Revision: 1.3 $ $Date$ -->
<document url="stat.html">
<properties>
<title>The Commons Math User Guide - Statistics</title>
@ -54,6 +54,7 @@ BinomialDistribution binomial = factory.createBinomialDistribution(10, .75);</so
<table>
<tr><th>Distribution</th><th>Factory Method</th><th>Parameters</th></tr>
<tr><td>Binomial</td><td>createBinomialDistribution</td><td><div>Number of trials</div><div>Probability of success</div></td></tr>
<tr><td>Cauchy</td><td>createCauchyDistribution</td><td><div>Median</div><div>Scale</div></td></tr>
<tr><td>Chi-Squared</td><td>createChiSquaredDistribution</td><td><div>Degrees of freedom</div></td></tr>
<tr><td>Exponential</td><td>createExponentialDistribution</td><td><div>Mean</div></td></tr>
<tr><td>F</td><td>createFDistribution</td><td><div>Numerator degrees of freedom</div><div>Denominator degrees of freedom</div></td></tr>