From e6e3bee13f311a237dac3b94c2bc03b02da1480e Mon Sep 17 00:00:00 2001
From: Phil Steitz
Date: Sun, 26 Feb 2006 16:14:03 +0000
Subject: [PATCH] Added Pascal distribution contributed in BZ #38766.
git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/math/trunk@381115 13f79535-47bb-0310-9956-ffa450edef68
---
src/experimental/R/pascalTestCases | 127 ++++++++++++++++++
.../distribution/DistributionFactory.java | 12 ++
.../distribution/DistributionFactoryImpl.java | 12 ++
.../math/distribution/PascalDistribution.java | 62 +++++++++
.../distribution/PascalDistributionTest.java | 104 ++++++++++++++
xdocs/changes.xml | 3 +
6 files changed, 320 insertions(+)
create mode 100644 src/experimental/R/pascalTestCases
create mode 100644 src/java/org/apache/commons/math/distribution/PascalDistribution.java
create mode 100644 src/test/org/apache/commons/math/distribution/PascalDistributionTest.java
diff --git a/src/experimental/R/pascalTestCases b/src/experimental/R/pascalTestCases
new file mode 100644
index 000000000..0a40ba1d8
--- /dev/null
+++ b/src/experimental/R/pascalTestCases
@@ -0,0 +1,127 @@
+# Copyright 2006 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.
+#
+#------------------------------------------------------------------------------
+# R source file to validate Pascal distribution tests in
+# org.apache.commons.math.distribution.PascalDistributionTest
+#
+# To run the test, install R, put this file and testFunctions
+# into the same directory, launch R from this directory and then enter
+# source("")
+#
+# R functions used
+# dnbinom(x, size, prob, mu, log = FALSE) <- density
+# pnbinom(q, size, prob, mu, lower.tail = TRUE, log.p = FALSE) <- distribution
+# qnbinom(p, size, prob, mu, lower.tail = TRUE, log.p = FALSE) <- quantiles
+#------------------------------------------------------------------------------
+tol <- 1E-4 # error tolerance for tests
+#------------------------------------------------------------------------------
+# Function definitions
+
+source("testFunctions") # utility test functions
+
+# function to verify density computations
+
+verifyDensity <- function(points, expected, size, p, tol) {
+ rDensityValues <- rep(0, length(points))
+ i <- 0
+ for (point in points) {
+ i <- i + 1
+ rDensityValues[i] <- dnbinom(point, size, p)
+ }
+ output <- c("Density test size = ", size, ", p = ", p)
+ if (assertEquals(expected,rDensityValues,tol,"Density Values")) {
+ displayPadded(output, SUCCEEDED, WIDTH)
+ } else {
+ displayPadded(output, FAILED, WIDTH)
+ }
+}
+
+# function to verify distribution computations
+
+verifyDistribution <- function(points, expected, size, p, tol) {
+ rDistValues <- rep(0, length(points))
+ i <- 0
+ for (point in points) {
+ i <- i + 1
+ rDistValues[i] <- pnbinom(point, size, p)
+ }
+ output <- c("Distribution test size = ", size, ", p = ", p)
+ if (assertEquals(expected,rDistValues,tol,"Distribution Values")) {
+ displayPadded(output, SUCCEEDED, WIDTH)
+ } else {
+ displayPadded(output, FAILED, WIDTH)
+ }
+}
+
+#--------------------------------------------------------------------------
+cat("Negative Binomial test cases\n")
+
+size <- 10.0
+probability <- 0.70
+
+densityPoints <- c(-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)
+densityValues <- c(0, 0.02824, 0.08474, 0.13982,
+ 0.16779, 0.16359, 0.1374, 0.10306, 0.070673, 0.04505, 0.02703,
+ 0.01540, 0.0084)
+distributionValues <- c(0, 0.02824, 0.11299, 0.25281, 0.42060, 0.58420,
+ 0.72162, 0.82468, 0.89535, 0.94041, 0.967446, 0.98285, 0.99125)
+inverseCumPoints <- c( 0, 0.001, 0.010, 0.025, 0.050, 0.100, 0.999,
+ 0.990, 0.975, 0.950, 0.900)
+inverseCumValues <- c(-1, -1, -1, -1, 0, 0, 13, 10, 9, 8, 7)
+
+verifyDensity(densityPoints,densityValues,size,probability,tol)
+verifyDistribution(densityPoints, distributionValues, size, probability, tol)
+
+i <- 0
+rInverseCumValues <- rep(0,length(inverseCumPoints))
+for (point in inverseCumPoints) {
+ i <- i + 1
+ rInverseCumValues[i] <- qnbinom(point, size, probability)
+}
+
+output <- c("Inverse Distribution test n = ", size, ", p = ", probability)
+# R defines quantiles from the right, need to subtract one
+if (assertEquals(inverseCumValues, rInverseCumValues-1, tol,
+ "Inverse Dist Values")) {
+ displayPadded(output, SUCCEEDED, 80)
+} else {
+ displayPadded(output, FAILED, 80)
+}
+
+# Degenerate cases
+
+size <- 5
+probability <- 0.0
+
+densityPoints <- c(-1, 0, 1, 10, 11)
+densityValues <- c(0, 0, 0, 0, 0)
+distributionPoints <- c(-1, 0, 1, 5, 10)
+distributionValues <- c(0, 0, 0, 0, 0)
+
+verifyDensity(densityPoints,densityValues,size,probability,tol)
+verifyDistribution(distributionPoints,distributionValues,size,probability,tol)
+
+size <- 5
+probability <- 1.0
+
+densityPoints <- c(-1, 0, 1, 2, 5, 10)
+densityValues <- c(0, 1, 0, 0, 1, 0)
+distributionPoints <- c(-1, 0, 1, 2, 5, 10)
+distributionValues <- c(0, 1, 1, 1, 1, 1)
+
+verifyDensity(densityPoints,densityValues,size,probability,tol)
+verifyDistribution(distributionPoints,distributionValues,size,probability,tol)
+
+displayDashes(WIDTH)
diff --git a/src/java/org/apache/commons/math/distribution/DistributionFactory.java b/src/java/org/apache/commons/math/distribution/DistributionFactory.java
index cef3b6da0..d1e48e001 100644
--- a/src/java/org/apache/commons/math/distribution/DistributionFactory.java
+++ b/src/java/org/apache/commons/math/distribution/DistributionFactory.java
@@ -33,6 +33,7 @@ import org.apache.commons.discovery.tools.DiscoverClass;
* Normal
* Student's t
* Weibull
+ * Pascal
*
*
* Common usage:
@@ -80,6 +81,17 @@ public abstract class DistributionFactory {
public abstract BinomialDistribution createBinomialDistribution(
int numberOfTrials, double probabilityOfSuccess);
+ /**
+ * Create a Pascal distribution with the given number of successes and
+ * probability of success.
+ *
+ * @param numberOfSuccesses the number of successes.
+ * @param probabilityOfSuccess the probability of success
+ * @return a new Pascal distribution
+ */
+ public abstract PascalDistribution createPascalDistribution(
+ int numberOfSuccesses, double probabilityOfSuccess);
+
/**
* Create a new cauchy distribution with the given median and scale.
* @param median the median of the distribution
diff --git a/src/java/org/apache/commons/math/distribution/DistributionFactoryImpl.java b/src/java/org/apache/commons/math/distribution/DistributionFactoryImpl.java
index f72d7b8a9..986353d96 100644
--- a/src/java/org/apache/commons/math/distribution/DistributionFactoryImpl.java
+++ b/src/java/org/apache/commons/math/distribution/DistributionFactoryImpl.java
@@ -154,4 +154,16 @@ public class DistributionFactoryImpl extends DistributionFactory {
return new PoissonDistributionImpl(lambda);
}
+ /**
+ * Create a Pascal distribution with the given number of successes and
+ * probability of success.
+ *
+ * @param numberOfSuccesses the number of successes.
+ * @param probabilityOfSuccess the probability of success
+ * @return a new Pascal distribution
+ */
+ public PascalDistribution createPascalDistribution(int numberOfSuccesses, double probabilityOfSuccess) {
+ return new PascalDistributionImpl(numberOfSuccesses, probabilityOfSuccess);
+ }
+
}
diff --git a/src/java/org/apache/commons/math/distribution/PascalDistribution.java b/src/java/org/apache/commons/math/distribution/PascalDistribution.java
new file mode 100644
index 000000000..14b1e12fa
--- /dev/null
+++ b/src/java/org/apache/commons/math/distribution/PascalDistribution.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2006 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;
+
+/**
+ * The Pascal Distribution.
+ *
+ * Instances of PascalDistribution objects should be created using
+ * {@link DistributionFactory#createPascalDistribution(int, double)}.
+ *
+ *
+ * References:
+ *
+ *
+ *
+ * @version $Revision:$
+ */
+public interface PascalDistribution extends IntegerDistribution {
+ /**
+ * Access the number of successes for this distribution.
+ *
+ * @return the number of successes
+ */
+ int getNumberOfSuccesses();
+
+ /**
+ * Access the probability of success for this distribution.
+ *
+ * @return the probability of success
+ */
+ double getProbabilityOfSuccess();
+
+ /**
+ * Change the number of successes for this distribution.
+ *
+ * @param successes the new number of successes
+ */
+ void setNumberOfSuccesses(int successes);
+
+ /**
+ * Change the probability of success for this distribution.
+ *
+ * @param p the new probability of success
+ */
+ void setProbabilityOfSuccess(double p);
+}
\ No newline at end of file
diff --git a/src/test/org/apache/commons/math/distribution/PascalDistributionTest.java b/src/test/org/apache/commons/math/distribution/PascalDistributionTest.java
new file mode 100644
index 000000000..bc0bd3b92
--- /dev/null
+++ b/src/test/org/apache/commons/math/distribution/PascalDistributionTest.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2006 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 PascalDistribution.
+ * Extends IntegerDistributionAbstractTest. See class javadoc for
+ * IntegerDistributionAbstractTest for details.
+ *
+ * @version $Revision:$ $Date:$
+ */
+public class PascalDistributionTest extends IntegerDistributionAbstractTest {
+
+ /**
+ * Constructor for PascalDistributionTest.
+ * @param name
+ */
+ public PascalDistributionTest(String name) {
+ super(name);
+ }
+
+ //-------------- Implementations for abstract methods -----------------------
+
+ /** Creates the default discrete distribution instance to use in tests. */
+ public IntegerDistribution makeDistribution() {
+ return DistributionFactory.newInstance().createPascalDistribution(10,0.70);
+ }
+
+ /** Creates the default probability density test input values */
+ public int[] makeDensityTestPoints() {
+ return new int[] {-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
+ }
+
+ /** Creates the default probability density test expected values */
+ public double[] makeDensityTestValues() {
+ return new double[] {0d, 0.02824d, 0.08474d, 0.13982d,
+ 0.16779d, 0.16359d, 0.1374d, 0.10306d, 0.070673d, 0.04505d, 0.02703d, 0.01540d, 0.0084};
+ }
+
+ /** Creates the default cumulative probability density test input values */
+ public int[] makeCumulativeTestPoints() {
+ return makeDensityTestPoints();
+ }
+
+ /** Creates the default cumulative probability density test expected values */
+ public double[] makeCumulativeTestValues() {
+ return new double[] {0d, 0.02824d, 0.11299d, 0.25281d, 0.42060d, 0.58420d,
+ 0.72162d, 0.82468d, 0.89535d, 0.94041d, 0.967446d, 0.98285, 0.99125d};
+ }
+
+ /** Creates the default inverse cumulative probability test input values */
+ public double[] makeInverseCumulativeTestPoints() {
+ return new double[] {0, 0.001d, 0.010d, 0.025d, 0.050d, 0.100d, 0.999d,
+ 0.990d, 0.975d, 0.950d, 0.900d, 1};
+ }
+
+ /** Creates the default inverse cumulative probability density test expected values */
+ public int[] makeInverseCumulativeTestValues() {
+ return new int[] {-1, -1, -1, -1, 0, 0, 13, 10, 9, 8, 7, Integer.MAX_VALUE};
+ }
+
+ //----------------- Additional test cases ---------------------------------
+
+ /** Test degenerate case p = 0 */
+ public void testDegenerate0() throws Exception {
+ setDistribution(DistributionFactory.newInstance().createPascalDistribution(5,0.0d));
+ setCumulativeTestPoints(new int[] {-1, 0, 1, 5, 10 });
+ setCumulativeTestValues(new double[] {0d, 0d, 0d, 0d, 0d});
+ setDensityTestPoints(new int[] {-1, 0, 1, 10, 11});
+ setDensityTestValues(new double[] {0d, 0d, 0d, 0d, 0d});
+ setInverseCumulativeTestPoints(new double[] {0.1d, 0.5d});
+ setInverseCumulativeTestValues(new int[] {Integer.MAX_VALUE - 1, Integer.MAX_VALUE - 1});
+ verifyDensities();
+ verifyCumulativeProbabilities();
+ verifyInverseCumulativeProbabilities();
+ }
+
+ /** Test degenerate case p = 1 */
+ public void testDegenerate1() throws Exception {
+ setDistribution(DistributionFactory.newInstance().createPascalDistribution(5,1.0d));
+ setCumulativeTestPoints(new int[] {-1, 0, 1, 2, 5, 10 });
+ setCumulativeTestValues(new double[] {0d, 1d, 1d, 1d, 1d, 1d});
+ setDensityTestPoints(new int[] {-1, 0, 1, 2, 5, 10});
+ setDensityTestValues(new double[] {0d, 1d, 0d, 0d, 0d, 0d});
+ setInverseCumulativeTestPoints(new double[] {0.1d, 0.5d});
+ setInverseCumulativeTestValues(new int[] {-1, -1});
+ verifyDensities();
+ verifyCumulativeProbabilities();
+ verifyInverseCumulativeProbabilities();
+ }
+}
diff --git a/xdocs/changes.xml b/xdocs/changes.xml
index b59638409..5bc8e5bb3 100644
--- a/xdocs/changes.xml
+++ b/xdocs/changes.xml
@@ -43,6 +43,9 @@ Commons Math Release Notes
Made ComplexFormat format double values with a provided NumberFormat
instance instead of using the real part format for all values.
+
+ Added Pascal distribution implementation.
+