Author: psteitz
Date: Sun May 30 18:30:50 2010
New Revision: 949553
URL: http://svn.apache.org/viewvc?rev=949553&view=rev
Log:
Added random data generation methods to RandomDataImpl for the remaining
distributions in the distributions package. Added a generic nextInversionDeviate method that
takes a discrete or continuous distribution as argument and generates
a random deviate from the distribution.
JIRA: MATH-310
Modified:
commons/proper/math/trunk/src/main/java/org/apache/commons/math/random/RandomDataImpl.java
commons/proper/math/trunk/src/site/xdoc/changes.xml
commons/proper/math/trunk/src/site/xdoc/userguide/random.xml
commons/proper/math/trunk/src/test/java/org/apache/commons/math/random/RandomDataTest.java
Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math/random/RandomDataImpl.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/random/RandomDataImpl.java?rev=949553&r1=949552&r2=949553&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math/random/RandomDataImpl.java
(original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/random/RandomDataImpl.java
Sun May 30 18:30:50 2010
@@ -24,7 +24,21 @@ import java.security.NoSuchAlgorithmExce
import java.security.NoSuchProviderException;
import java.util.Collection;
+import org.apache.commons.math.MathException;
import org.apache.commons.math.MathRuntimeException;
+import org.apache.commons.math.distribution.BetaDistributionImpl;
+import org.apache.commons.math.distribution.BinomialDistributionImpl;
+import org.apache.commons.math.distribution.CauchyDistributionImpl;
+import org.apache.commons.math.distribution.ChiSquaredDistributionImpl;
+import org.apache.commons.math.distribution.ContinuousDistribution;
+import org.apache.commons.math.distribution.FDistributionImpl;
+import org.apache.commons.math.distribution.GammaDistributionImpl;
+import org.apache.commons.math.distribution.HypergeometricDistributionImpl;
+import org.apache.commons.math.distribution.IntegerDistribution;
+import org.apache.commons.math.distribution.PascalDistributionImpl;
+import org.apache.commons.math.distribution.TDistributionImpl;
+import org.apache.commons.math.distribution.WeibullDistributionImpl;
+import org.apache.commons.math.distribution.ZipfDistributionImpl;
import org.apache.commons.math.util.MathUtils;
/**
@@ -62,7 +76,7 @@ import org.apache.commons.math.util.Math
* it any easier to predict subsequent values.</li>
* <li>
* When a new <code>RandomDataImpl</code> is created, the underlying random
- * number generators are <strong>not</strong> intialized. If you do not
+ * number generators are <strong>not</strong> initialized. If you do not
* explicitly seed the default non-secure generator, it is seeded with the
* current time in milliseconds on first use. The same holds for the secure
* generator. If you provide a <code>RandomGenerator</code> to the constructor,
@@ -507,6 +521,159 @@ public class RandomDataImpl implements R
}
/**
+ * Generates a random value from the {@link BetaDistributionImpl Beta Distribution}.
+ * This implementation uses {@link #nextInversionDeviate(ContinuousDistribution) inversion}
+ * to generate random values.
+ *
+ * @param alpha first distribution shape parameter
+ * @param beta second distribution shape parameter
+ * @return random value sampled from the beta(alpha, beta) distribution
+ * @throws MathException if an error occurs generating the random value
+ */
+ public double nextBeta(double alpha, double beta) throws MathException {
+ return nextInversionDeviate(new BetaDistributionImpl(alpha, beta));
+ }
+
+ /**
+ * Generates a random value from the {@link BinomialDistributionImpl Binomial Distribution}.
+ * This implementation uses {@link #nextInversionDeviate(ContinuousDistribution) inversion}
+ * to generate random values.
+ *
+ * @param numberOfTrials number of trials of the Binomial distribution
+ * @param probabilityOfSuccess probability of success of the Binomial distribution
+ * @return random value sampled from the Binomial(numberOfTrials, probabilityOfSuccess)
distribution
+ * @throws MathException if an error occurs generating the random value
+ */
+ public int nextBinomial(int numberOfTrials, double probabilityOfSuccess) throws MathException
{
+ return nextInversionDeviate(new BinomialDistributionImpl(numberOfTrials, probabilityOfSuccess));
+ }
+
+ /**
+ * Generates a random value from the {@link CauchyDistributionImpl Cauchy Distribution}.
+ * This implementation uses {@link #nextInversionDeviate(ContinuousDistribution) inversion}
+ * to generate random values.
+ *
+ * @param median the median of the Cauchy distribution
+ * @param scale the scale parameter of the Cauchy distribution
+ * @return random value sampled from the Cauchy(median, scale) distribution
+ * @throws MathException if an error occurs generating the random value
+ */
+ public double nextCauchy(double median, double scale) throws MathException {
+ return nextInversionDeviate(new CauchyDistributionImpl(median, scale));
+ }
+
+ /**
+ * Generates a random value from the {@link ChiSquaredDistributionImpl ChiSquare Distribution}.
+ * This implementation uses {@link #nextInversionDeviate(ContinuousDistribution) inversion}
+ * to generate random values.
+ *
+ * @param df the degrees of freedom of the ChiSquare distribution
+ * @return random value sampled from the ChiSquare(df) distribution
+ * @throws MathException if an error occurs generating the random value
+ */
+ public double nextChiSquare(double df) throws MathException {
+ return nextInversionDeviate(new ChiSquaredDistributionImpl(df));
+ }
+
+ /**
+ * Generates a random value from the {@link FDistributionImpl F Distribution}.
+ * This implementation uses {@link #nextInversionDeviate(ContinuousDistribution) inversion}
+ * to generate random values.
+ *
+ * @param numeratorDf the numerator degrees of freedom of the F distribution
+ * @param denominatorDf the denominator degrees of freedom of the F distribution
+ * @return random value sampled from the F(numeratorDf, denominatorDf) distribution
+ * @throws MathException if an error occurs generating the random value
+ */
+ public double nextF(double numeratorDf, double denominatorDf) throws MathException {
+ return nextInversionDeviate(new FDistributionImpl(numeratorDf, denominatorDf));
+ }
+
+ /**
+ * Generates a random value from the {@link GammaDistributionImpl Gamma Distribution}.
+ * This implementation uses {@link #nextInversionDeviate(ContinuousDistribution) inversion}
+ * to generate random values.
+ *
+ * @param shape the median of the Gamma distribution
+ * @param scale the scale parameter of the Gamma distribution
+ * @return random value sampled from the Gamma(shape, scale) distribution
+ * @throws MathException if an error occurs generating the random value
+ */
+ public double nextGamma(double shape, double scale) throws MathException {
+ return nextInversionDeviate(new GammaDistributionImpl(shape, scale));
+ }
+
+ /**
+ * Generates a random value from the {@link HypergeometricDistributionImpl Hypergeometric
Distribution}.
+ * This implementation uses {@link #nextInversionDeviate(IntegerDistribution) inversion}
+ * to generate random values.
+ *
+ * @param populationSize the population size of the Hypergeometric distribution
+ * @param numberOfSuccesses number of successes in the population of the Hypergeometric
distribution
+ * @param sampleSize the sample size of the Hypergeometric distribution
+ * @return random value sampled from the Hypergeometric(numberOfSuccesses, sampleSize)
distribution
+ * @throws MathException if an error occurs generating the random value
+ */
+ public int nextHypergeometric(int populationSize, int numberOfSuccesses, int sampleSize)
throws MathException {
+ return nextInversionDeviate(new HypergeometricDistributionImpl(populationSize, numberOfSuccesses,
sampleSize));
+ }
+
+ /**
+ * Generates a random value from the {@link PascalDistributionImpl Pascal Distribution}.
+ * This implementation uses {@link #nextInversionDeviate(IntegerDistribution) inversion}
+ * to generate random values.
+ *
+ * @param r the number of successes of the Pascal distribution
+ * @param p the probability of success of the Pascal distribution
+ * @return random value sampled from the Pascal(r, p) distribution
+ * @throws MathException if an error occurs generating the random value
+ */
+ public int nextPascal(int r, double p) throws MathException {
+ return nextInversionDeviate(new PascalDistributionImpl(r, p));
+ }
+
+ /**
+ * Generates a random value from the {@link TDistributionImpl T Distribution}.
+ * This implementation uses {@link #nextInversionDeviate(ContinuousDistribution) inversion}
+ * to generate random values.
+ *
+ * @param df the degrees of freedom of the T distribution
+ * @return random value from the T(df) distribution
+ * @throws MathException if an error occurs generating the random value
+ */
+ public double nextT(double df) throws MathException {
+ return nextInversionDeviate(new TDistributionImpl(df));
+ }
+
+ /**
+ * Generates a random value from the {@link WeibullDistributionImpl Weibull Distribution}.
+ * This implementation uses {@link #nextInversionDeviate(ContinuousDistribution) inversion}
+ * to generate random values.
+ *
+ * @param shape the shape parameter of the Weibull distribution
+ * @param scale the scale parameter of the Weibull distribution
+ * @return random value sampled from the Weibull(shape, size) distribution
+ * @throws MathException if an error occurs generating the random value
+ */
+ public double nextWeibull(double shape, double scale) throws MathException {
+ return nextInversionDeviate(new WeibullDistributionImpl(shape, scale));
+ }
+
+ /**
+ * Generates a random value from the {@link ZipfDistributionImpl Zipf Distribution}.
+ * This implementation uses {@link #nextInversionDeviate(IntegerDistribution) inversion}
+ * to generate random values.
+ *
+ * @param numberOfElements the number of elements of the ZipfDistribution
+ * @param exponent the exponent of the ZipfDistribution
+ * @return random value sampled from the Zipf(numberOfElements, exponent) distribution
+ * @throws MathException if an error occurs generating the random value
+ */
+ public int nextZipf(int numberOfElements, double exponent) throws MathException {
+ return nextInversionDeviate(new ZipfDistributionImpl(numberOfElements, exponent));
+ }
+
+ /**
* Returns the RandomGenerator used to generate non-secure random data.
* <p>
* Creates and initializes a default generator if null.
@@ -705,6 +872,37 @@ public class RandomDataImpl implements R
return result;
}
+ /**
+ * Generate a random deviate from the given distribution using the
+ * <a href="http://en.wikipedia.org/wiki/Inverse_transform_sampling"> inversion
method.</a>
+ *
+ * @param distribution Continuous distribution to generate a random value from
+ * @return a random value sampled from the given distribution
+ * @throws MathException if an error occurs computing the inverse cumulative distribution
function
+ */
+ public double nextInversionDeviate(ContinuousDistribution distribution) throws MathException
{
+ return distribution.inverseCumulativeProbability(nextUniform(0, 1));
+
+ }
+
+ /**
+ * Generate a random deviate from the given distribution using the
+ * <a href="http://en.wikipedia.org/wiki/Inverse_transform_sampling"> inversion
method.</a>
+ *
+ * @param distribution Integer distribution to generate a random value from
+ * @return a random value sampled from the given distribution
+ * @throws MathException if an error occurs computing the inverse cumulative distribution
function
+ */
+ public int nextInversionDeviate(IntegerDistribution distribution) throws MathException
{
+ final double target = nextUniform(0, 1);
+ final int glb = distribution.inverseCumulativeProbability(target);
+ if (distribution.cumulativeProbability(glb) == 1.0d) { // No mass above
+ return glb;
+ } else {
+ return glb + 1;
+ }
+ }
+
// ------------------------Private methods----------------------------------
/**
Modified: commons/proper/math/trunk/src/site/xdoc/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/site/xdoc/changes.xml?rev=949553&r1=949552&r2=949553&view=diff
==============================================================================
--- commons/proper/math/trunk/src/site/xdoc/changes.xml (original)
+++ commons/proper/math/trunk/src/site/xdoc/changes.xml Sun May 30 18:30:50 2010
@@ -52,6 +52,11 @@ The <action> type attribute can be add,u
If the output is not quite correct, check for invisible trailing spaces!
-->
<release version="2.2" date="TBD" description="TBD">
+ <action dev="psteitz" type="update" issue="MATH-310">
+ Added random data generation methods to RandomDataImpl for the remaining distributions
in the
+ distributions package. Added a generic nextInversionDeviate method that takes a discrete
+ or continuous distribution as argument and generates a random deviate from the distribution.
+ </action>
<action dev="luc" type="fix" issue="MATH-362" >
Fixed Levenberg-Marquardt optimizer that did not use the vectorial convergence checker.
Now this optimizer can use either the general vectorial convergence checker or its
own
Modified: commons/proper/math/trunk/src/site/xdoc/userguide/random.xml
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/site/xdoc/userguide/random.xml?rev=949553&r1=949552&r2=949553&view=diff
==============================================================================
--- commons/proper/math/trunk/src/site/xdoc/userguide/random.xml (original)
+++ commons/proper/math/trunk/src/site/xdoc/userguide/random.xml Sun May 30 18:30:50 2010
@@ -83,20 +83,13 @@
probability distribution</a> basically amounts to asserting that different
ranges in the set of possible values of a random variable have
different probabilities of containing the value. Commons Math supports
- generating random sequences from the following probability distributions.
+ generating random sequences from each of the distributions in the
+ <a href="../apidocs/org/apache/commons/math/distribution/package-summary.html">
+ distributions</a> package.
The javadoc for the <code>nextXxx</code> methods in
- <code>RandomDataImpl</code> describes the algorithms used to generate
- random deviates from each of these distributions.
- <ul>
- <li><a href="http://www.itl.nist.gov/div898/handbook/eda/section3/eda3662.htm">
- uniform distribution</a></li>
- <li><a href="http://www.itl.nist.gov/div898/handbook/eda/section3/eda3667.htm">
- exponential distribution</a></li>
- <li><a href="http://www.itl.nist.gov/div898/handbook/eda/section3/eda366j.htm">
- poisson distribution</a></li>
- <li><a href="http://www.itl.nist.gov/div898/handbook/eda/section3/eda3661.htm">
- Gaussian distribution</a></li>
- </ul>
+ <a href="../apidocs/org/apache/commons/math/random/RandomDataImpl.html">
+ RandomDataImpl</a> describes the algorithms used to generate
+ random deviates.
</dd>
<dt>Cryptographically secure random sequences</dt>
<dd>It is possible for a sequence of numbers to appear random, but
Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math/random/RandomDataTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math/random/RandomDataTest.java?rev=949553&r1=949552&r2=949553&view=diff
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math/random/RandomDataTest.java
(original)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math/random/RandomDataTest.java
Sun May 30 18:30:50 2010
@@ -24,8 +24,25 @@ import java.util.List;
import junit.framework.AssertionFailedError;
import org.apache.commons.math.RetryTestCase;
+import org.apache.commons.math.TestUtils;
+import org.apache.commons.math.distribution.BetaDistributionImpl;
+import org.apache.commons.math.distribution.BinomialDistributionImpl;
+import org.apache.commons.math.distribution.BinomialDistributionTest;
+import org.apache.commons.math.distribution.CauchyDistributionImpl;
+import org.apache.commons.math.distribution.ChiSquaredDistributionImpl;
+import org.apache.commons.math.distribution.ContinuousDistribution;
+import org.apache.commons.math.distribution.FDistributionImpl;
+import org.apache.commons.math.distribution.GammaDistributionImpl;
+import org.apache.commons.math.distribution.HypergeometricDistributionImpl;
+import org.apache.commons.math.distribution.HypergeometricDistributionTest;
+import org.apache.commons.math.distribution.PascalDistributionImpl;
+import org.apache.commons.math.distribution.PascalDistributionTest;
import org.apache.commons.math.distribution.PoissonDistribution;
import org.apache.commons.math.distribution.PoissonDistributionImpl;
+import org.apache.commons.math.distribution.TDistributionImpl;
+import org.apache.commons.math.distribution.WeibullDistributionImpl;
+import org.apache.commons.math.distribution.ZipfDistributionImpl;
+import org.apache.commons.math.distribution.ZipfDistributionTest;
import org.apache.commons.math.stat.Frequency;
import org.apache.commons.math.stat.descriptive.SummaryStatistics;
import org.apache.commons.math.stat.inference.ChiSquareTest;
@@ -45,13 +62,13 @@ public class RandomDataTest extends Retr
randomData = new RandomDataImpl();
}
- protected long smallSampleSize = 1000;
- protected double[] expected = { 250, 250, 250, 250 };
- protected int largeSampleSize = 10000;
- private String[] hex = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
+ protected final long smallSampleSize = 1000;
+ protected final double[] expected = { 250, 250, 250, 250 };
+ protected final int largeSampleSize = 10000;
+ private final String[] hex = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
"a", "b", "c", "d", "e", "f" };
protected RandomDataImpl randomData = null;
- protected ChiSquareTestImpl testStatistic = new ChiSquareTestImpl();
+ protected final ChiSquareTestImpl testStatistic = new ChiSquareTestImpl();
public void testNextIntExtremeValues() {
int x = randomData.nextInt(Integer.MIN_VALUE, Integer.MAX_VALUE);
@@ -774,4 +791,259 @@ public class RandomDataTest extends Retr
fail("permutation not found");
return -1;
}
+
+ public void testNextInversionDeviate() throws Exception {
+ // Set the seed for the default random generator
+ randomData.reSeed(100);
+ double[] quantiles = new double[10];
+ for (int i = 0; i < 10; i++) {
+ quantiles[i] = randomData.nextUniform(0, 1);
+ }
+ // Reseed again so the inversion generator gets the same sequence
+ randomData.reSeed(100);
+ BetaDistributionImpl betaDistribution = new BetaDistributionImpl(2, 4);
+ /*
+ * Generate a sequence of deviates using inversion - the distribution function
+ * evaluated at the random value from the distribution should match the uniform
+ * random value used to generate it, which is stored in the quantiles[] array.
+ */
+ for (int i = 0; i < 10; i++) {
+ double value = randomData.nextInversionDeviate(betaDistribution);
+ assertEquals(betaDistribution.cumulativeProbability(value), quantiles[i], 10E-9);
+ }
+ }
+
+ public void testNextBeta() throws Exception {
+ double[] quartiles = getDistributionQuartiles(new BetaDistributionImpl(2,5));
+ long[] counts = new long[4];
+ randomData.reSeed(1000);
+ for (int i = 0; i < 1000; i++) {
+ double value = randomData.nextBeta(2, 5);
+ updateCounts(value, counts, quartiles);
+ }
+ TestUtils.assertChiSquareAccept(quartiles, expected, counts, 0.001);
+ }
+
+ public void testNextCauchy() throws Exception {
+ double[] quartiles = getDistributionQuartiles(new CauchyDistributionImpl(1.2, 2.1));
+ long[] counts = new long[4];
+ randomData.reSeed(1000);
+ for (int i = 0; i < 1000; i++) {
+ double value = randomData.nextCauchy(1.2, 2.1);
+ updateCounts(value, counts, quartiles);
+ }
+ TestUtils.assertChiSquareAccept(quartiles, expected, counts, 0.001);
+ }
+
+ public void testNextChiSquare() throws Exception {
+ double[] quartiles = getDistributionQuartiles(new ChiSquaredDistributionImpl(12));
+ long[] counts = new long[4];
+ randomData.reSeed(1000);
+ for (int i = 0; i < 1000; i++) {
+ double value = randomData.nextChiSquare(12);
+ updateCounts(value, counts, quartiles);
+ }
+ TestUtils.assertChiSquareAccept(quartiles, expected, counts, 0.001);
+ }
+
+ public void testNextF() throws Exception {
+ double[] quartiles = getDistributionQuartiles(new FDistributionImpl(12, 5));
+ long[] counts = new long[4];
+ randomData.reSeed(1000);
+ for (int i = 0; i < 1000; i++) {
+ double value = randomData.nextF(12, 5);
+ updateCounts(value, counts, quartiles);
+ }
+ TestUtils.assertChiSquareAccept(quartiles, expected, counts, 0.001);
+ }
+
+ public void testNextGamma() throws Exception {
+ double[] quartiles = getDistributionQuartiles(new GammaDistributionImpl(4, 2));
+ long[] counts = new long[4];
+ randomData.reSeed(1000);
+ for (int i = 0; i < 1000; i++) {
+ double value = randomData.nextGamma(4, 2);
+ updateCounts(value, counts, quartiles);
+ }
+ TestUtils.assertChiSquareAccept(quartiles, expected, counts, 0.001);
+ }
+
+ public void testNextT() throws Exception {
+ double[] quartiles = getDistributionQuartiles(new TDistributionImpl(10));
+ long[] counts = new long[4];
+ randomData.reSeed(1000);
+ for (int i = 0; i < 1000; i++) {
+ double value = randomData.nextT(10);
+ updateCounts(value, counts, quartiles);
+ }
+ TestUtils.assertChiSquareAccept(quartiles, expected, counts, 0.001);
+ }
+
+ public void testNextWeibull() throws Exception {
+ double[] quartiles = getDistributionQuartiles(new WeibullDistributionImpl(1.2, 2.1));
+ long[] counts = new long[4];
+ randomData.reSeed(1000);
+ for (int i = 0; i < 1000; i++) {
+ double value = randomData.nextWeibull(1.2, 2.1);
+ updateCounts(value, counts, quartiles);
+ }
+ TestUtils.assertChiSquareAccept(quartiles, expected, counts, 0.001);
+ }
+
+ /**
+ * Computes the 25th, 50th and 75th percentiles of the given distribution and returns
+ * these values in an array.
+ */
+ private double[] getDistributionQuartiles(ContinuousDistribution distribution) throws
Exception {
+ double[] quantiles = new double[3];
+ quantiles[0] = distribution.inverseCumulativeProbability(0.25d);
+ quantiles[1] = distribution.inverseCumulativeProbability(0.5d);
+ quantiles[2] = distribution.inverseCumulativeProbability(0.75d);
+ return quantiles;
+ }
+
+ /**
+ * Updates observed counts of values in quartiles.
+ * counts[0] <-> 1st quartile ... counts[3] <-> top quartile
+ */
+ private void updateCounts(double value, long[] counts, double[] quantiles) {
+ if (value < quantiles[0]) {
+ counts[0]++;
+ } else if (value > quantiles[2]) {
+ counts[3]++;
+ } else if (value > quantiles[1]) {
+ counts[2]++;
+ } else {
+ counts[1]++;
+ }
+ }
+
+ public void testNextBinomial() throws Exception {
+ BinomialDistributionTest testInstance = new BinomialDistributionTest("");
+ int[] densityPoints = testInstance.makeDensityTestPoints();
+ double[] densityValues = testInstance.makeDensityTestValues();
+ int sampleSize = 1000;
+ int length = eliminateZeroMassPoints(densityPoints, densityValues);
+ BinomialDistributionImpl distribution = (BinomialDistributionImpl) testInstance.makeDistribution();
+ double[] expectedCounts = new double[length];
+ long[] observedCounts = new long[length];
+ for (int i = 0; i < length; i++) {
+ expectedCounts[i] = sampleSize * densityValues[i];
+ }
+ randomData.reSeed(1000);
+ for (int i = 0; i < sampleSize; i++) {
+ int value = randomData.nextBinomial(distribution.getNumberOfTrials(),
+ distribution.getProbabilityOfSuccess());
+ for (int j = 0; j < length; j++) {
+ if (value == densityPoints[j]) {
+ observedCounts[j]++;
+ }
+ }
+ }
+ TestUtils.assertChiSquareAccept(densityPoints, expectedCounts, observedCounts, .001);
+ }
+
+ public void testNextHypergeometric() throws Exception {
+ HypergeometricDistributionTest testInstance = new HypergeometricDistributionTest("");
+ int[] densityPoints = testInstance.makeDensityTestPoints();
+ double[] densityValues = testInstance.makeDensityTestValues();
+ int sampleSize = 1000;
+ int length = eliminateZeroMassPoints(densityPoints, densityValues);
+ HypergeometricDistributionImpl distribution = (HypergeometricDistributionImpl) testInstance.makeDistribution();
+ double[] expectedCounts = new double[length];
+ long[] observedCounts = new long[length];
+ for (int i = 0; i < length; i++) {
+ expectedCounts[i] = sampleSize * densityValues[i];
+ }
+ randomData.reSeed(1000);
+ for (int i = 0; i < sampleSize; i++) {
+ int value = randomData.nextHypergeometric(distribution.getPopulationSize(),
+ distribution.getNumberOfSuccesses(), distribution.getSampleSize());
+ for (int j = 0; j < length; j++) {
+ if (value == densityPoints[j]) {
+ observedCounts[j]++;
+ }
+ }
+ }
+ TestUtils.assertChiSquareAccept(densityPoints, expectedCounts, observedCounts, .001);
+ }
+
+ public void testNextPascal() throws Exception {
+ PascalDistributionTest testInstance = new PascalDistributionTest("");
+ int[] densityPoints = testInstance.makeDensityTestPoints();
+ double[] densityValues = testInstance.makeDensityTestValues();
+ int sampleSize = 1000;
+ int length = eliminateZeroMassPoints(densityPoints, densityValues);
+ PascalDistributionImpl distribution = (PascalDistributionImpl) testInstance.makeDistribution();
+ double[] expectedCounts = new double[length];
+ long[] observedCounts = new long[length];
+ for (int i = 0; i < length; i++) {
+ expectedCounts[i] = sampleSize * densityValues[i];
+ }
+ randomData.reSeed(1000);
+ for (int i = 0; i < sampleSize; i++) {
+ int value = randomData.nextPascal(distribution.getNumberOfSuccesses(), distribution.getProbabilityOfSuccess());
+ for (int j = 0; j < length; j++) {
+ if (value == densityPoints[j]) {
+ observedCounts[j]++;
+ }
+ }
+ }
+ TestUtils.assertChiSquareAccept(densityPoints, expectedCounts, observedCounts, .001);
+ }
+
+ public void testNextZipf() throws Exception {
+ ZipfDistributionTest testInstance = new ZipfDistributionTest("");
+ int[] densityPoints = testInstance.makeDensityTestPoints();
+ double[] densityValues = testInstance.makeDensityTestValues();
+ int sampleSize = 1000;
+ int length = eliminateZeroMassPoints(densityPoints, densityValues);
+ ZipfDistributionImpl distribution = (ZipfDistributionImpl) testInstance.makeDistribution();
+ double[] expectedCounts = new double[length];
+ long[] observedCounts = new long[length];
+ for (int i = 0; i < length; i++) {
+ expectedCounts[i] = sampleSize * densityValues[i];
+ }
+ randomData.reSeed(1000);
+ for (int i = 0; i < sampleSize; i++) {
+ int value = randomData.nextZipf(distribution.getNumberOfElements(), distribution.getExponent());
+ for (int j = 0; j < length; j++) {
+ if (value == densityPoints[j]) {
+ observedCounts[j]++;
+ }
+ }
+ }
+ TestUtils.assertChiSquareAccept(densityPoints, expectedCounts, observedCounts, .001);
+ }
+
+ /**
+ * Eliminates points with zero mass from densityPoints and densityValues parallel
+ * arrays. Returns the number of positive mass points and collapses the arrays so
+ * that the first <returned value> elements of the input arrays represent the positive
+ * mass points.
+ */
+ private int eliminateZeroMassPoints(int[] densityPoints, double[] densityValues) {
+ int positiveMassCount = 0;
+ for (int i = 0; i < densityValues.length; i++) {
+ if (densityValues[i] > 0) {
+ positiveMassCount++;
+ }
+ }
+ if (positiveMassCount < densityValues.length) {
+ int[] newPoints = new int[positiveMassCount];
+ double[] newValues = new double[positiveMassCount];
+ int j = 0;
+ for (int i = 0; i < densityValues.length; i++) {
+ if (densityValues[i] > 0) {
+ newPoints[j] = densityPoints[i];
+ newValues[j] = densityValues[i];
+ j++;
+ }
+ }
+ System.arraycopy(newPoints,0,densityPoints,0,positiveMassCount);
+ System.arraycopy(newValues,0,densityValues,0,positiveMassCount);
+ }
+ return positiveMassCount;
+ }
+
}
|