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
This commit is contained in:
Phil Steitz 2006-02-26 16:14:03 +00:00
parent c8cd287a53
commit e6e3bee13f
6 changed files with 320 additions and 0 deletions

View File

@ -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("<name-of-this-file>")
#
# 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)

View File

@ -33,6 +33,7 @@ import org.apache.commons.discovery.tools.DiscoverClass;
* <li>Normal</li>
* <li>Student's t</li>
* <li>Weibull</li>
* <li>Pascal</li>
* </ul>
*
* Common usage:<pre>
@ -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

View File

@ -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);
}
}

View File

@ -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)}.
*
* <p>
* References:
* <ul>
* <li><a href="http://mathworld.wolfram.com/NegativeBinomialDistribution.html">
* Negative Binomial Distribution</a></li>
* </ul>
* </p>
*
* @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);
}

View File

@ -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();
}
}

View File

@ -43,6 +43,9 @@ Commons Math Release Notes</title>
Made ComplexFormat format double values with a provided NumberFormat
instance instead of using the real part format for all values.
</action>
<action dev="psteitz" type="update" issue="38766">
Added Pascal distribution implementation.
</action>
</release>
<release version="1.1" date="2005-12-17"
description="This is a maintenance release containing bug fixes and enhancements.