Return-Path: Delivered-To: apmail-commons-commits-archive@minotaur.apache.org Received: (qmail 88107 invoked from network); 31 May 2010 23:39:53 -0000 Received: from unknown (HELO mail.apache.org) (140.211.11.3) by 140.211.11.9 with SMTP; 31 May 2010 23:39:53 -0000 Received: (qmail 59713 invoked by uid 500); 31 May 2010 23:39:53 -0000 Delivered-To: apmail-commons-commits-archive@commons.apache.org Received: (qmail 59644 invoked by uid 500); 31 May 2010 23:39:53 -0000 Mailing-List: contact commits-help@commons.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@commons.apache.org Delivered-To: mailing list commits@commons.apache.org Received: (qmail 59637 invoked by uid 99); 31 May 2010 23:39:53 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 31 May 2010 23:39:53 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 31 May 2010 23:39:48 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 5246423889EB; Mon, 31 May 2010 23:39:26 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r949895 - in /commons/proper/math/trunk/src: main/java/org/apache/commons/math/ main/java/org/apache/commons/math/distribution/ site/xdoc/ test/java/org/apache/commons/math/ test/java/org/apache/commons/math/distribution/ test/java/org/apac... Date: Mon, 31 May 2010 23:39:26 -0000 To: commits@commons.apache.org From: psteitz@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20100531233926.5246423889EB@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: psteitz Date: Mon May 31 23:39:25 2010 New Revision: 949895 URL: http://svn.apache.org/viewvc?rev=949895&view=rev Log: Added sampling methods to the distribution classes, based on the random data generation methods in the random package. JIRA: MATH-310 Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math/MessagesResources_fr.java commons/proper/math/trunk/src/main/java/org/apache/commons/math/distribution/AbstractContinuousDistribution.java commons/proper/math/trunk/src/main/java/org/apache/commons/math/distribution/AbstractIntegerDistribution.java commons/proper/math/trunk/src/main/java/org/apache/commons/math/distribution/ExponentialDistributionImpl.java commons/proper/math/trunk/src/main/java/org/apache/commons/math/distribution/NormalDistributionImpl.java commons/proper/math/trunk/src/main/java/org/apache/commons/math/distribution/PoissonDistributionImpl.java commons/proper/math/trunk/src/site/xdoc/changes.xml commons/proper/math/trunk/src/test/java/org/apache/commons/math/TestUtils.java commons/proper/math/trunk/src/test/java/org/apache/commons/math/distribution/ContinuousDistributionAbstractTest.java commons/proper/math/trunk/src/test/java/org/apache/commons/math/distribution/IntegerDistributionAbstractTest.java 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/MessagesResources_fr.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/MessagesResources_fr.java?rev=949895&r1=949894&r2=949895&view=diff ============================================================================== --- commons/proper/math/trunk/src/main/java/org/apache/commons/math/MessagesResources_fr.java (original) +++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/MessagesResources_fr.java Mon May 31 23:39:25 2010 @@ -753,6 +753,10 @@ public class MessagesResources_fr { "Discrete cumulative probability function returned NaN for argument {0}", "Discr\u00e8tes fonction de probabilit\u00e9 cumulative retourn\u00e9 NaN \u00e0 l''argument de {0}" }, + // org.apache.commons.math.distribution.AbstractIntegerDistribution + // org.apache.commons.math.distribution.AbstractContinuousDistribution + { "Sample size must be positive", + "Taille de l'\u00e9chantillon doit \u00eatre positif" }, // org.apache.commons.math.distribution.BinomialDistributionImpl { "number of trials must be non-negative ({0})", Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math/distribution/AbstractContinuousDistribution.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/distribution/AbstractContinuousDistribution.java?rev=949895&r1=949894&r2=949895&view=diff ============================================================================== --- commons/proper/math/trunk/src/main/java/org/apache/commons/math/distribution/AbstractContinuousDistribution.java (original) +++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/distribution/AbstractContinuousDistribution.java Mon May 31 23:39:25 2010 @@ -25,6 +25,7 @@ import org.apache.commons.math.MathRunti import org.apache.commons.math.analysis.UnivariateRealFunction; import org.apache.commons.math.analysis.solvers.BrentSolver; import org.apache.commons.math.analysis.solvers.UnivariateRealSolverUtils; +import org.apache.commons.math.random.RandomDataImpl; /** * Base class for continuous distributions. Default implementations are @@ -39,6 +40,12 @@ public abstract class AbstractContinuous /** Serializable version identifier */ private static final long serialVersionUID = -38038050983108802L; + + /** + * RandomData instance used to generate samples from the distribution + * @since 2.2 + */ + protected final RandomDataImpl randomData = new RandomDataImpl(); /** * Solver absolute accuracy for inverse cum computation @@ -102,7 +109,7 @@ public abstract class AbstractContinuous } }; - // Try to bracket root, test domain endoints if this fails + // Try to bracket root, test domain endpoints if this fails double lowerBound = getDomainLowerBound(p); double upperBound = getDomainUpperBound(p); double[] bracket = null; @@ -135,6 +142,50 @@ public abstract class AbstractContinuous } /** + * Reseeds the random generator used to generate samples. + * + * @param seed the new seed + * @since 2.2 + */ + public void reseedRandomGenerator(long seed) { + randomData.reSeed(seed); + } + + /** + * Generates a random value sampled from this distribution. The default + * implementation uses the + * inversion method. + * + * @return random value + * @since 2.2 + * @throws MathException if an error occurs generating the random value + */ + public double sample() throws MathException { + return randomData.nextInversionDeviate(this); + } + + /** + * Generates a random sample from the distribution. The default implementation + * generates the sample by calling {@link #sample()} in a loop. + * + * @param sampleSize number of random values to generate + * @since 2.2 + * @return an array representing the random sample + * @throws MathException if an error occurs generating the sample + * @throws IllegalArgumentException if sampleSize is not positive + */ + public double[] sample(int sampleSize) throws MathException { + if (sampleSize <= 0) { + MathRuntimeException.createIllegalArgumentException("Sample size must be positive"); + } + double[] out = new double[sampleSize]; + for (int i = 0; i < sampleSize; i++) { + out[i] = sample(); + } + return out; + } + + /** * 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. @@ -175,4 +226,5 @@ public abstract class AbstractContinuous protected double getSolverAbsoluteAccuracy() { return solverAbsoluteAccuracy; } + } Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math/distribution/AbstractIntegerDistribution.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/distribution/AbstractIntegerDistribution.java?rev=949895&r1=949894&r2=949895&view=diff ============================================================================== --- commons/proper/math/trunk/src/main/java/org/apache/commons/math/distribution/AbstractIntegerDistribution.java (original) +++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/distribution/AbstractIntegerDistribution.java Mon May 31 23:39:25 2010 @@ -21,6 +21,7 @@ import java.io.Serializable; import org.apache.commons.math.FunctionEvaluationException; import org.apache.commons.math.MathException; import org.apache.commons.math.MathRuntimeException; +import org.apache.commons.math.random.RandomDataImpl; /** @@ -45,6 +46,12 @@ public abstract class AbstractIntegerDis private static final long serialVersionUID = -1146319659338487221L; /** + * RandomData instance used to generate samples from the distribution + * @since 2.2 + */ + protected final RandomDataImpl randomData = new RandomDataImpl(); + + /** * Default constructor. */ protected AbstractIntegerDistribution() { @@ -209,7 +216,51 @@ public abstract class AbstractIntegerDis } /** - * Computes the cumulative probablity function and checks for NaN values returned. + * Reseeds the random generator used to generate samples. + * + * @param seed the new seed + * @since 2.2 + */ + public void reseedRandomGenerator(long seed) { + randomData.reSeed(seed); + } + + /** + * Generates a random value sampled from this distribution. The default + * implementation uses the + * inversion method. + * + * @return random value + * @since 2.2 + * @throws MathException if an error occurs generating the random value + */ + public int sample() throws MathException { + return randomData.nextInversionDeviate(this); + } + + /** + * Generates a random sample from the distribution. The default implementation + * generates the sample by calling {@link #sample()} in a loop. + * + * @param sampleSize number of random values to generate + * @since 2.2 + * @return an array representing the random sample + * @throws MathException if an error occurs generating the sample + * @throws IllegalArgumentException if sampleSize is not positive + */ + public int[] sample(int sampleSize) throws MathException { + if (sampleSize <= 0) { + MathRuntimeException.createIllegalArgumentException("Sample size must be positive"); + } + int[] out = new int[sampleSize]; + for (int i = 0; i < sampleSize; i++) { + out[i] = sample(); + } + return out; + } + + /** + * Computes the cumulative probability function and checks for NaN values returned. * Throws MathException if the value is NaN. Wraps and rethrows any MathException encountered * evaluating the cumulative probability function in a FunctionEvaluationException. Throws * FunctionEvaluationException of the cumulative probability function returns NaN. Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math/distribution/ExponentialDistributionImpl.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/distribution/ExponentialDistributionImpl.java?rev=949895&r1=949894&r2=949895&view=diff ============================================================================== --- commons/proper/math/trunk/src/main/java/org/apache/commons/math/distribution/ExponentialDistributionImpl.java (original) +++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/distribution/ExponentialDistributionImpl.java Mon May 31 23:39:25 2010 @@ -176,6 +176,23 @@ public class ExponentialDistributionImpl } /** + * Generates a random value sampled from this distribution. + * + *

Algorithm Description: Uses the Inversion + * Method to generate exponentially distributed random values from + * uniform deviates.

+ * + * @return random value + * @since 2.2 + * @throws MathException if an error occurs generating the random value + */ + @Override + public double sample() throws MathException { + return randomData.nextExponential(mean); + } + + /** * Access the domain value lower bound, based on p, used to * bracket a CDF root. * Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math/distribution/NormalDistributionImpl.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/distribution/NormalDistributionImpl.java?rev=949895&r1=949894&r2=949895&view=diff ============================================================================== --- commons/proper/math/trunk/src/main/java/org/apache/commons/math/distribution/NormalDistributionImpl.java (original) +++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/distribution/NormalDistributionImpl.java Mon May 31 23:39:25 2010 @@ -229,6 +229,18 @@ public class NormalDistributionImpl exte } /** + * Generates a random value sampled from this distribution. + * + * @return random value + * @since 2.2 + * @throws MathException if an error occurs generating the random value + */ + @Override + public double sample() throws MathException { + return randomData.nextGaussian(mean, standardDeviation); + } + + /** * 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. Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math/distribution/PoissonDistributionImpl.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/distribution/PoissonDistributionImpl.java?rev=949895&r1=949894&r2=949895&view=diff ============================================================================== --- commons/proper/math/trunk/src/main/java/org/apache/commons/math/distribution/PoissonDistributionImpl.java (original) +++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/distribution/PoissonDistributionImpl.java Mon May 31 23:39:25 2010 @@ -238,6 +238,28 @@ public class PoissonDistributionImpl ext } /** + * Generates a random value sampled from this distribution. + * + *

Algorithm Description: + *

  • For small means, uses simulation of a Poisson process + * using Uniform deviates, as described + * here. + * The Poisson process (and hence value returned) is bounded by 1000 * mean.
  • < + * + *
  • For large means, uses the rejection algorithm described in
    + * Devroye, Luc. (1981).The Computer Generation of Poisson Random Variables + * Computing vol. 26 pp. 197-207.

+ * + * @return random value + * @since 2.2 + * @throws MathException if an error occurs generating the random value + */ + @Override + public int sample() throws MathException { + return (int) Math.min(randomData.nextPoisson(mean), Integer.MAX_VALUE); + } + + /** * 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. 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=949895&r1=949894&r2=949895&view=diff ============================================================================== --- commons/proper/math/trunk/src/site/xdoc/changes.xml (original) +++ commons/proper/math/trunk/src/site/xdoc/changes.xml Mon May 31 23:39:25 2010 @@ -56,6 +56,7 @@ The type attribute can be add,u 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. + Also added sampling methods based on the implementations in RandomDataImpl to distributions. Fixed Levenberg-Marquardt optimizer that did not use the vectorial convergence checker. Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math/TestUtils.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math/TestUtils.java?rev=949895&r1=949894&r2=949895&view=diff ============================================================================== --- commons/proper/math/trunk/src/test/java/org/apache/commons/math/TestUtils.java (original) +++ commons/proper/math/trunk/src/test/java/org/apache/commons/math/TestUtils.java Mon May 31 23:39:25 2010 @@ -29,6 +29,7 @@ import junit.framework.AssertionFailedEr import org.apache.commons.math.complex.Complex; import org.apache.commons.math.complex.ComplexFormat; +import org.apache.commons.math.distribution.ContinuousDistribution; import org.apache.commons.math.linear.FieldMatrix; import org.apache.commons.math.linear.RealMatrix; import org.apache.commons.math.stat.inference.ChiSquareTest; @@ -437,5 +438,78 @@ public class TestUtils { } assertChiSquareAccept(labels, expected, observed, alpha); } - + + /** + * Asserts the null hypothesis for a ChiSquare test. Fails and dumps arguments and test + * statistics if the null hypothesis can be rejected with confidence 100 * (1 - alpha)% + * + * @param expected expected counts + * @param observed observed counts + * @param alpha significance level of the test + */ + public static void assertChiSquareAccept(double[] expected, long[] observed, double alpha) throws Exception { + String[] labels = new String[expected.length]; + for (int i = 0; i < labels.length; i++) { + labels[i] = Integer.toString(i + 1); + } + assertChiSquareAccept(labels, expected, observed, alpha); + } + + /** + * Computes the 25th, 50th and 75th percentiles of the given distribution and returns + * these values in an array. + */ + public static 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 + */ + public static void updateCounts(double value, long[] counts, double[] quartiles) { + if (value < quartiles[0]) { + counts[0]++; + } else if (value > quartiles[2]) { + counts[3]++; + } else if (value > quartiles[1]) { + counts[2]++; + } else { + counts[1]++; + } + } + + /** + * 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 elements of the input arrays represent the positive + * mass points. + */ + public static 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; + } } Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math/distribution/ContinuousDistributionAbstractTest.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math/distribution/ContinuousDistributionAbstractTest.java?rev=949895&r1=949894&r2=949895&view=diff ============================================================================== --- commons/proper/math/trunk/src/test/java/org/apache/commons/math/distribution/ContinuousDistributionAbstractTest.java (original) +++ commons/proper/math/trunk/src/test/java/org/apache/commons/math/distribution/ContinuousDistributionAbstractTest.java Mon May 31 23:39:25 2010 @@ -256,6 +256,23 @@ public abstract class ContinuousDistribu // expected } } + + /** + * Test sampling + */ + public void testSampling() throws Exception { + AbstractContinuousDistribution dist = (AbstractContinuousDistribution) makeDistribution(); + final int sampleSize = 1000; + double[] sample = dist.sample(sampleSize); + double[] quartiles = TestUtils.getDistributionQuartiles(dist); + double[] expected = {250, 250, 250, 250}; + long[] counts = new long[4]; + dist.reseedRandomGenerator(1000); // Use fixed seed + for (int i = 0; i < sampleSize; i++) { + TestUtils.updateCounts(sample[i], counts, quartiles); + } + TestUtils.assertChiSquareAccept(expected, counts, 0.001); + } //------------------ Getters / Setters for test instance data ----------- /** Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math/distribution/IntegerDistributionAbstractTest.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math/distribution/IntegerDistributionAbstractTest.java?rev=949895&r1=949894&r2=949895&view=diff ============================================================================== --- commons/proper/math/trunk/src/test/java/org/apache/commons/math/distribution/IntegerDistributionAbstractTest.java (original) +++ commons/proper/math/trunk/src/test/java/org/apache/commons/math/distribution/IntegerDistributionAbstractTest.java Mon May 31 23:39:25 2010 @@ -16,6 +16,8 @@ */ package org.apache.commons.math.distribution; +import org.apache.commons.math.TestUtils; + import junit.framework.TestCase; /** @@ -269,6 +271,32 @@ public abstract class IntegerDistributio // expected } } + + /** + * Test sampling + */ + public void testSampling() throws Exception { + int[] densityPoints = makeDensityTestPoints(); + double[] densityValues = makeDensityTestValues(); + int sampleSize = 1000; + int length = TestUtils.eliminateZeroMassPoints(densityPoints, densityValues); + AbstractIntegerDistribution distribution = (AbstractIntegerDistribution) makeDistribution(); + double[] expectedCounts = new double[length]; + long[] observedCounts = new long[length]; + for (int i = 0; i < length; i++) { + expectedCounts[i] = sampleSize * densityValues[i]; + } + distribution.reseedRandomGenerator(1000); // Use fixed seed + int[] sample = distribution.sample(sampleSize); + for (int i = 0; i < sampleSize; i++) { + for (int j = 0; j < length; j++) { + if (sample[i] == densityPoints[j]) { + observedCounts[j]++; + } + } + } + TestUtils.assertChiSquareAccept(densityPoints, expectedCounts, observedCounts, .001); + } //------------------ Getters / Setters for test instance data ----------- /** 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=949895&r1=949894&r2=949895&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 Mon May 31 23:39:25 2010 @@ -815,108 +815,80 @@ public class RandomDataTest extends Retr } public void testNextBeta() throws Exception { - double[] quartiles = getDistributionQuartiles(new BetaDistributionImpl(2,5)); + double[] quartiles = TestUtils.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.updateCounts(value, counts, quartiles); } - TestUtils.assertChiSquareAccept(quartiles, expected, counts, 0.001); + TestUtils.assertChiSquareAccept(expected, counts, 0.001); } public void testNextCauchy() throws Exception { - double[] quartiles = getDistributionQuartiles(new CauchyDistributionImpl(1.2, 2.1)); + double[] quartiles = TestUtils.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.updateCounts(value, counts, quartiles); } - TestUtils.assertChiSquareAccept(quartiles, expected, counts, 0.001); + TestUtils.assertChiSquareAccept(expected, counts, 0.001); } public void testNextChiSquare() throws Exception { - double[] quartiles = getDistributionQuartiles(new ChiSquaredDistributionImpl(12)); + double[] quartiles = TestUtils.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.updateCounts(value, counts, quartiles); } - TestUtils.assertChiSquareAccept(quartiles, expected, counts, 0.001); + TestUtils.assertChiSquareAccept(expected, counts, 0.001); } public void testNextF() throws Exception { - double[] quartiles = getDistributionQuartiles(new FDistributionImpl(12, 5)); + double[] quartiles = TestUtils.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.updateCounts(value, counts, quartiles); } - TestUtils.assertChiSquareAccept(quartiles, expected, counts, 0.001); + TestUtils.assertChiSquareAccept(expected, counts, 0.001); } public void testNextGamma() throws Exception { - double[] quartiles = getDistributionQuartiles(new GammaDistributionImpl(4, 2)); + double[] quartiles = TestUtils.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.updateCounts(value, counts, quartiles); } - TestUtils.assertChiSquareAccept(quartiles, expected, counts, 0.001); + TestUtils.assertChiSquareAccept(expected, counts, 0.001); } public void testNextT() throws Exception { - double[] quartiles = getDistributionQuartiles(new TDistributionImpl(10)); + double[] quartiles = TestUtils.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.updateCounts(value, counts, quartiles); } - TestUtils.assertChiSquareAccept(quartiles, expected, counts, 0.001); + TestUtils.assertChiSquareAccept(expected, counts, 0.001); } public void testNextWeibull() throws Exception { - double[] quartiles = getDistributionQuartiles(new WeibullDistributionImpl(1.2, 2.1)); + double[] quartiles = TestUtils.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.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]++; - } + TestUtils.assertChiSquareAccept(expected, counts, 0.001); } public void testNextBinomial() throws Exception { @@ -924,7 +896,7 @@ public class RandomDataTest extends Retr int[] densityPoints = testInstance.makeDensityTestPoints(); double[] densityValues = testInstance.makeDensityTestValues(); int sampleSize = 1000; - int length = eliminateZeroMassPoints(densityPoints, densityValues); + int length = TestUtils.eliminateZeroMassPoints(densityPoints, densityValues); BinomialDistributionImpl distribution = (BinomialDistributionImpl) testInstance.makeDistribution(); double[] expectedCounts = new double[length]; long[] observedCounts = new long[length]; @@ -949,7 +921,7 @@ public class RandomDataTest extends Retr int[] densityPoints = testInstance.makeDensityTestPoints(); double[] densityValues = testInstance.makeDensityTestValues(); int sampleSize = 1000; - int length = eliminateZeroMassPoints(densityPoints, densityValues); + int length = TestUtils.eliminateZeroMassPoints(densityPoints, densityValues); HypergeometricDistributionImpl distribution = (HypergeometricDistributionImpl) testInstance.makeDistribution(); double[] expectedCounts = new double[length]; long[] observedCounts = new long[length]; @@ -974,7 +946,7 @@ public class RandomDataTest extends Retr int[] densityPoints = testInstance.makeDensityTestPoints(); double[] densityValues = testInstance.makeDensityTestValues(); int sampleSize = 1000; - int length = eliminateZeroMassPoints(densityPoints, densityValues); + int length = TestUtils.eliminateZeroMassPoints(densityPoints, densityValues); PascalDistributionImpl distribution = (PascalDistributionImpl) testInstance.makeDistribution(); double[] expectedCounts = new double[length]; long[] observedCounts = new long[length]; @@ -998,7 +970,7 @@ public class RandomDataTest extends Retr int[] densityPoints = testInstance.makeDensityTestPoints(); double[] densityValues = testInstance.makeDensityTestValues(); int sampleSize = 1000; - int length = eliminateZeroMassPoints(densityPoints, densityValues); + int length = TestUtils.eliminateZeroMassPoints(densityPoints, densityValues); ZipfDistributionImpl distribution = (ZipfDistributionImpl) testInstance.makeDistribution(); double[] expectedCounts = new double[length]; long[] observedCounts = new long[length]; @@ -1017,34 +989,4 @@ public class RandomDataTest extends Retr 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 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; - } - }