You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ps...@apache.org on 2014/06/22 20:53:27 UTC
svn commit: r1604639 - in /commons/proper/math/trunk/src: changes/
main/java/org/apache/commons/math3/distribution/
main/java/org/apache/commons/math3/random/
test/java/org/apache/commons/math3/distribution/
test/java/org/apache/commons/math3/random/
Author: psteitz
Date: Sun Jun 22 18:53:27 2014
New Revision: 1604639
URL: http://svn.apache.org/r1604639
Log:
Constrained EmpiricalDistribution sample/getNextValue methods to return
values within the range of the data; correctly linked RandomGenerator to
superclass so that RealDistribution reseedRandomGenerator method works.
JIRA: MATH-984
Added:
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/ConstantRealDistribution.java (with props)
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/ConstantRealDistributionTest.java (with props)
Modified:
commons/proper/math/trunk/src/changes/changes.xml
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/random/EmpiricalDistribution.java
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/random/EmpiricalDistributionTest.java
Modified: commons/proper/math/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/changes/changes.xml?rev=1604639&r1=1604638&r2=1604639&view=diff
==============================================================================
--- commons/proper/math/trunk/src/changes/changes.xml (original)
+++ commons/proper/math/trunk/src/changes/changes.xml Sun Jun 22 18:53:27 2014
@@ -73,6 +73,11 @@ Users are encouraged to upgrade to this
2. A few methods in the FastMath class are in fact slower that their
counterpart in either Math or StrictMath (cf. MATH-740 and MATH-901).
">
+ <action dev="psteitz" type="fix" issue="MATH-984">
+ Constrained EmpiricalDistribution sample/getNextValue methods to return
+ values within the range of the data; correctly linked RandomGenerator to
+ superclass so that RealDistribution reseedRandomGenerator method works.
+ </action>
<action dev="luc" type="add" issue="MATH-1120" due-to="Venkatesha Murthy">
Added several different estimation types and NaN handling strategies for Percentile.
</action>
Added: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/ConstantRealDistribution.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/ConstantRealDistribution.java?rev=1604639&view=auto
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/ConstantRealDistribution.java (added)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/ConstantRealDistribution.java Sun Jun 22 18:53:27 2014
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.math3.distribution;
+
+import org.apache.commons.math3.exception.OutOfRangeException;
+
+/**
+ * Implementation of the constant real distribution.
+ *
+ * @version $Id$
+ * @since 3.4
+ */
+public class ConstantRealDistribution extends AbstractRealDistribution {
+
+ /** Serialization ID */
+ private static final long serialVersionUID = -4157745166772046273L;
+
+ /** Constant value of the distribution */
+ private final double value;
+
+ /**
+ * Create a constant real distribution with the given value.
+ *
+ * @param value the constant value of this distribution
+ */
+ public ConstantRealDistribution(double value) {
+ super(null); // Avoid creating RandomGenerator
+ this.value = value;
+ }
+
+ /** {@inheritDoc} */
+ public double density(double x) {
+ return x == value ? 1 : 0;
+ }
+
+ /** {@inheritDoc} */
+ public double cumulativeProbability(double x) {
+ return x < value ? 0 : 1;
+ }
+
+ @Override
+ public double inverseCumulativeProbability(final double p)
+ throws OutOfRangeException {
+ if (p < 0.0 || p > 1.0) {
+ throw new OutOfRangeException(p, 0, 1);
+ }
+ return value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public double getNumericalMean() {
+ return value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public double getNumericalVariance() {
+ return 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public double getSupportLowerBound() {
+ return value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public double getSupportUpperBound() {
+ return value;
+ }
+
+ /** {@inheritDoc} */
+ public boolean isSupportLowerBoundInclusive() {
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ public boolean isSupportUpperBoundInclusive() {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isSupportConnected() {
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public double sample() {
+ return value;
+ }
+
+ /**
+ * Override with no-op (there is no generator).
+ * @param seed (ignored)
+ */
+ @Override
+ public void reseedRandomGenerator(long seed) {}
+}
Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/ConstantRealDistribution.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/ConstantRealDistribution.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/random/EmpiricalDistribution.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/random/EmpiricalDistribution.java?rev=1604639&r1=1604638&r2=1604639&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/random/EmpiricalDistribution.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/random/EmpiricalDistribution.java Sun Jun 22 18:53:27 2014
@@ -29,6 +29,7 @@ import java.util.ArrayList;
import java.util.List;
import org.apache.commons.math3.distribution.AbstractRealDistribution;
+import org.apache.commons.math3.distribution.ConstantRealDistribution;
import org.apache.commons.math3.distribution.NormalDistribution;
import org.apache.commons.math3.distribution.RealDistribution;
import org.apache.commons.math3.exception.MathIllegalStateException;
@@ -212,7 +213,7 @@ public class EmpiricalDistribution exten
*/
private EmpiricalDistribution(int binCount,
RandomDataGenerator randomData) {
- super(null);
+ super(randomData.getRandomGenerator());
this.binCount = binCount;
this.randomData = randomData;
binStats = new ArrayList<SummaryStatistics>();
@@ -478,23 +479,7 @@ public class EmpiricalDistribution exten
throw new MathIllegalStateException(LocalizedFormats.DISTRIBUTION_NOT_LOADED);
}
- // Start with a uniformly distributed random number in (0,1)
- final double x = randomData.nextUniform(0,1);
-
- // Use this to select the bin and generate a Gaussian within the bin
- for (int i = 0; i < binCount; i++) {
- if (x <= upperBounds[i]) {
- SummaryStatistics stats = binStats.get(i);
- if (stats.getN() > 0) {
- if (stats.getStandardDeviation() > 0) { // more than one obs
- return getKernel(stats).sample();
- } else {
- return stats.getMean(); // only one obs in bin
- }
- }
- }
- }
- throw new MathIllegalStateException(LocalizedFormats.NO_BIN_SELECTED);
+ return sample();
}
/**
@@ -772,15 +757,6 @@ public class EmpiricalDistribution exten
* @since 3.1
*/
@Override
- public double sample() {
- return getNextValue();
- }
-
- /**
- * {@inheritDoc}
- * @since 3.1
- */
- @Override
public void reseedRandomGenerator(long seed) {
randomData.reSeed(seed);
}
@@ -843,15 +819,20 @@ public class EmpiricalDistribution exten
}
/**
- * The within-bin smoothing kernel.
+ * The within-bin smoothing kernel. Returns a Gaussian distribution
+ * parameterized by {@code bStats}, unless the bin contains only one
+ * observation, in which case a constant distribution is returned.
*
* @param bStats summary statistics for the bin
* @return within-bin kernel parameterized by bStats
*/
protected RealDistribution getKernel(SummaryStatistics bStats) {
- // Default to Gaussian
- return new NormalDistribution(randomData.getRandomGenerator(),
+ if (bStats.getN() == 1) {
+ return new ConstantRealDistribution(bStats.getMean());
+ } else {
+ return new NormalDistribution(randomData.getRandomGenerator(),
bStats.getMean(), bStats.getStandardDeviation(),
NormalDistribution.DEFAULT_INVERSE_ABSOLUTE_ACCURACY);
+ }
}
}
Added: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/ConstantRealDistributionTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/ConstantRealDistributionTest.java?rev=1604639&view=auto
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/ConstantRealDistributionTest.java (added)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/ConstantRealDistributionTest.java Sun Jun 22 18:53:27 2014
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.math3.distribution;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Test cases for ConstantRealDistribution.
+ */
+public class ConstantRealDistributionTest extends RealDistributionAbstractTest {
+
+ // --- Override tolerance -------------------------------------------------
+
+ @Override
+ public void setUp() {
+ super.setUp();
+ setTolerance(0);
+ }
+
+ //--- Implementations for abstract methods --------------------------------
+
+ /** Creates the default uniform real distribution instance to use in tests. */
+ @Override
+ public ConstantRealDistribution makeDistribution() {
+ return new ConstantRealDistribution(1);
+ }
+
+ /** Creates the default cumulative probability distribution test input values */
+ @Override
+ public double[] makeCumulativeTestPoints() {
+ return new double[] {0, 0.5, 1};
+ }
+
+ /** Creates the default cumulative probability distribution test expected values */
+ @Override
+ public double[] makeCumulativeTestValues() {
+ return new double[] {0, 0, 1};
+ }
+
+ /** Creates the default probability density test expected values */
+ @Override
+ public double[] makeDensityTestValues() {
+ return new double[] {0, 0, 1};
+ }
+
+ /** Override default test, verifying that inverse cum is constant */
+ @Override
+ @Test
+ public void testInverseCumulativeProbabilities() {
+ RealDistribution dist = getDistribution();
+ for (double x : getCumulativeTestValues()) {
+ Assert.assertEquals(1,dist.inverseCumulativeProbability(x), 0);
+ }
+ }
+
+ //--- Additional test cases -----------------------------------------------
+
+ @Test
+ public void testMeanVariance() {
+ ConstantRealDistribution dist;
+
+ dist = new ConstantRealDistribution(-1);
+ Assert.assertEquals(dist.getNumericalMean(), -1, 0d);
+ Assert.assertEquals(dist.getNumericalVariance(), 0, 0d);
+ }
+
+ @Test
+ public void testSampling() {
+ ConstantRealDistribution dist = new ConstantRealDistribution(0);
+ for (int i = 0; i < 10; i++) {
+ Assert.assertEquals(0, dist.sample(), 0);
+ }
+
+ }
+}
Propchange: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/ConstantRealDistributionTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/ConstantRealDistributionTest.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/random/EmpiricalDistributionTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/random/EmpiricalDistributionTest.java?rev=1604639&r1=1604638&r2=1604639&view=diff
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math3/random/EmpiricalDistributionTest.java (original)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math3/random/EmpiricalDistributionTest.java Sun Jun 22 18:53:27 2014
@@ -29,6 +29,7 @@ import org.apache.commons.math3.analysis
import org.apache.commons.math3.analysis.integration.BaseAbstractUnivariateIntegrator;
import org.apache.commons.math3.analysis.integration.IterativeLegendreGaussIntegrator;
import org.apache.commons.math3.distribution.AbstractRealDistribution;
+import org.apache.commons.math3.distribution.ConstantRealDistribution;
import org.apache.commons.math3.distribution.NormalDistribution;
import org.apache.commons.math3.distribution.RealDistribution;
import org.apache.commons.math3.distribution.RealDistributionAbstractTest;
@@ -409,6 +410,31 @@ public final class EmpiricalDistribution
}
}
+ /**
+ * MATH-984
+ * Verify that sampled values do not go outside of the range of the data.
+ */
+ @Test
+ public void testSampleValuesRange() {
+ // Concentrate values near the endpoints of (0, 1).
+ // Unconstrained Gaussian kernel would generate values outside the interval.
+ final double[] data = new double[100];
+ for (int i = 0; i < 50; i++) {
+ data[i] = 1 / ((double) i + 1);
+ }
+ for (int i = 51; i < 100; i++) {
+ data[i] = 1 - 1 / (100 - (double) i + 2);
+ }
+ EmpiricalDistribution dist = new EmpiricalDistribution(10);
+ dist.load(data);
+ dist.reseedRandomGenerator(1000);
+ for (int i = 0; i < 1000; i++) {
+ final double dev = dist.sample();
+ Assert.assertTrue(dev < 1);
+ Assert.assertTrue(dev > 0);
+ }
+ }
+
/**
* Find the bin that x belongs (relative to {@link #makeDistribution()}).
*/
@@ -503,7 +529,7 @@ public final class EmpiricalDistribution
// Use constant distribution equal to bin mean within bin
@Override
protected RealDistribution getKernel(SummaryStatistics bStats) {
- return new ConstantDistribution(bStats.getMean());
+ return new ConstantRealDistribution(bStats.getMean());
}
}
@@ -521,68 +547,4 @@ public final class EmpiricalDistribution
UniformRealDistribution.DEFAULT_INVERSE_ABSOLUTE_ACCURACY);
}
}
-
- /**
- * Distribution that takes just one value.
- */
- private class ConstantDistribution extends AbstractRealDistribution {
- private static final long serialVersionUID = 1L;
-
- /** Singleton value in the sample space */
- private final double c;
-
- public ConstantDistribution(double c) {
- this.c = c;
- }
-
- public double density(double x) {
- return 0;
- }
-
- public double cumulativeProbability(double x) {
- return x < c ? 0 : 1;
- }
-
- @Override
- public double inverseCumulativeProbability(double p) {
- if (p < 0.0 || p > 1.0) {
- throw new OutOfRangeException(p, 0, 1);
- }
- return c;
- }
-
- public double getNumericalMean() {
- return c;
- }
-
- public double getNumericalVariance() {
- return 0;
- }
-
- public double getSupportLowerBound() {
- return c;
- }
-
- public double getSupportUpperBound() {
- return c;
- }
-
- public boolean isSupportLowerBoundInclusive() {
- return false;
- }
-
- public boolean isSupportUpperBoundInclusive() {
- return true;
- }
-
- public boolean isSupportConnected() {
- return true;
- }
-
- @Override
- public double sample() {
- return c;
- }
-
- }
}