From 19ddf2957ed5cb8072b969bf12ec046ac0ac3ccb Mon Sep 17 00:00:00 2001
From: Brent Worden
Date: Thu, 24 Feb 2005 03:59:05 +0000
Subject: [PATCH] added cauchy distribution
git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/math/trunk@155159 13f79535-47bb-0310-9956-ffa450edef68
---
.../math/distribution/CauchyDistribution.java | 59 ++++++
.../distribution/CauchyDistributionImpl.java | 194 ++++++++++++++++++
.../distribution/DistributionFactory.java | 17 +-
.../distribution/CauchyDistributionTest.java | 96 +++++++++
.../DistributionFactoryImplTest.java | 12 +-
.../HypergeometricDistributionTest.java | 15 +-
.../distribution/PoissonDistributionTest.java | 25 ++-
.../math/distribution/TDistributionTest.java | 6 +-
xdocs/changes.xml | 3 +
xdocs/userguide/distribution.xml | 5 +-
10 files changed, 414 insertions(+), 18 deletions(-)
create mode 100644 src/java/org/apache/commons/math/distribution/CauchyDistribution.java
create mode 100644 src/java/org/apache/commons/math/distribution/CauchyDistributionImpl.java
create mode 100644 src/test/org/apache/commons/math/distribution/CauchyDistributionTest.java
diff --git a/src/java/org/apache/commons/math/distribution/CauchyDistribution.java b/src/java/org/apache/commons/math/distribution/CauchyDistribution.java
new file mode 100644
index 000000000..3f802e709
--- /dev/null
+++ b/src/java/org/apache/commons/math/distribution/CauchyDistribution.java
@@ -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)}.
+ *
+ *
+ * References:
+ *
+ *
+ *
+ * @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);
+}
diff --git a/src/java/org/apache/commons/math/distribution/CauchyDistributionImpl.java b/src/java/org/apache/commons/math/distribution/CauchyDistributionImpl.java
new file mode 100644
index 000000000..3bee81611
--- /dev/null
+++ b/src/java/org/apache/commons/math/distribution/CauchyDistributionImpl.java
@@ -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 < x
).
+ * @param x the value at which the CDF is evaluated.
+ * @return CDF evaluted at x
.
+ */
+ 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 < x) = p
.
+ *
+ * Returns Double.NEGATIVE_INFINITY
for p=0 and
+ * Double.POSITIVE_INFINITY
for p=1.
+ *
+ * @param p the desired probability
+ * @return x, such that P(X < x) = p
+ * @throws IllegalArgumentException if p
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 sd
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 p
, 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 < lower bound) < p
+ */
+ 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 p
, 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 < upper bound) > p
+ */
+ 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 p
, 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;
+ }
+}
diff --git a/src/java/org/apache/commons/math/distribution/DistributionFactory.java b/src/java/org/apache/commons/math/distribution/DistributionFactory.java
index afe23b2bf..c0c2a949d 100644
--- a/src/java/org/apache/commons/math/distribution/DistributionFactory.java
+++ b/src/java/org/apache/commons/math/distribution/DistributionFactory.java
@@ -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:
*
* - Binomial
+ * - Cauchy
* - Chi-Squared
* - Exponential
* - F
@@ -40,7 +41,7 @@ import org.apache.commons.discovery.tools.DiscoverClass;
* ChiSquaredDistribution chi = factory.createChiSquareDistribution(5.0);
*
*
- * @version $Revision: 1.22 $ $Date: 2004/11/07 03:32:48 $
+ * @version $Revision: 1.22 $ $Date$
*/
public abstract class DistributionFactory {
/**
@@ -77,6 +78,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.
diff --git a/src/test/org/apache/commons/math/distribution/CauchyDistributionTest.java b/src/test/org/apache/commons/math/distribution/CauchyDistributionTest.java
new file mode 100644
index 000000000..43fd3aeea
--- /dev/null
+++ b/src/test/org/apache/commons/math/distribution/CauchyDistributionTest.java
@@ -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
+ }
+ }
+}
diff --git a/src/test/org/apache/commons/math/distribution/DistributionFactoryImplTest.java b/src/test/org/apache/commons/math/distribution/DistributionFactoryImplTest.java
index 236456d01..61cfa918e 100644
--- a/src/test/org/apache/commons/math/distribution/DistributionFactoryImplTest.java
+++ b/src/test/org/apache/commons/math/distribution/DistributionFactoryImplTest.java
@@ -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) {
+ }
+ }
}
diff --git a/src/test/org/apache/commons/math/distribution/HypergeometricDistributionTest.java b/src/test/org/apache/commons/math/distribution/HypergeometricDistributionTest.java
index b28d39047..700fdc45a 100644
--- a/src/test/org/apache/commons/math/distribution/HypergeometricDistributionTest.java
+++ b/src/test/org/apache/commons/math/distribution/HypergeometricDistributionTest.java
@@ -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());
+ }
}
diff --git a/src/test/org/apache/commons/math/distribution/PoissonDistributionTest.java b/src/test/org/apache/commons/math/distribution/PoissonDistributionTest.java
index b98c9b7f4..b6b197617 100644
--- a/src/test/org/apache/commons/math/distribution/PoissonDistributionTest.java
+++ b/src/test/org/apache/commons/math/distribution/PoissonDistributionTest.java
@@ -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;
/**
* PoissonDistributionTest
*
- * @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 ≤ X ≤ 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);
}
}
\ No newline at end of file
diff --git a/src/test/org/apache/commons/math/distribution/TDistributionTest.java b/src/test/org/apache/commons/math/distribution/TDistributionTest.java
index 52d4e884e..7f8ad6b1e 100644
--- a/src/test/org/apache/commons/math/distribution/TDistributionTest.java
+++ b/src/test/org/apache/commons/math/distribution/TDistributionTest.java
@@ -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};
}
diff --git a/xdocs/changes.xml b/xdocs/changes.xml
index 5869afe98..8b11e7776 100644
--- a/xdocs/changes.xml
+++ b/xdocs/changes.xml
@@ -39,6 +39,9 @@ The type attribute can be add,update,fix,remove.
+
+ Added Cauchy distribution implementation.
+
Added convience methods for rounding.
diff --git a/xdocs/userguide/distribution.xml b/xdocs/userguide/distribution.xml
index 2f2c9363e..c2cb33d12 100644
--- a/xdocs/userguide/distribution.xml
+++ b/xdocs/userguide/distribution.xml
@@ -1,7 +1,7 @@
-
+
The Commons Math User Guide - Statistics
@@ -54,6 +54,7 @@ BinomialDistribution binomial = factory.createBinomialDistribution(10, .75);
Distribution | Factory Method | Parameters |
Binomial | createBinomialDistribution | Number of trials Probability of success |
+ Cauchy | createCauchyDistribution | Median Scale |
Chi-Squared | createChiSquaredDistribution | Degrees of freedom |
Exponential | createExponentialDistribution | Mean |
F | createFDistribution | Numerator degrees of freedom Denominator degrees of freedom |