Author: tdunning
Date: Thu Sep 2 04:32:51 2010
New Revision: 991803
URL: http://svn.apache.org/viewvc?rev=991803&view=rev
Log:
MAHOUT-495 - Undeprecate Exponential distribution
Added:
mahout/trunk/math/src/test/java/org/apache/mahout/math/jet/random/ExponentialTest.java
Modified:
mahout/trunk/math/src/main/java/org/apache/mahout/math/jet/random/Exponential.java
Modified:
mahout/trunk/math/src/main/java/org/apache/mahout/math/jet/random/Exponential.java
URL:
http://svn.apache.org/viewvc/mahout/trunk/math/src/main/java/org/apache/mahout/math/jet/random/Exponential.java?rev=991803&r1=991802&r2=991803&view=diff
==============================================================================
---
mahout/trunk/math/src/main/java/org/apache/mahout/math/jet/random/Exponential.java
(original)
+++
mahout/trunk/math/src/main/java/org/apache/mahout/math/jet/random/Exponential.java
Thu Sep 2 04:32:51 2010
@@ -10,22 +10,30 @@ package org.apache.mahout.math.jet.rando
import org.apache.mahout.math.jet.random.engine.RandomEngine;
-/** @deprecated until unit tests are in place. Until this time, this
class/interface is unsupported. */
-...@deprecated
-public class Exponential extends AbstractContinousDistribution {
+import java.util.Locale;
+public class Exponential extends AbstractContinousDistribution {
+ // rate parameter for the distribution. Mean is 1/lambda.
private double lambda;
- // The uniform random number generated shared by all <b>static</b> methods.
- private static final Exponential shared = new Exponential(1.0,
makeDefaultGenerator());
-
- /** Constructs a Negative Exponential distribution. */
+ /**
+ * Provides a negative exponential distribution given a rate parameter
lambda and an underlying
+ * random number generator. The mean of this distribution will be equal to
1/lambda.
+ *
+ * @param lambda The rate parameter of the distribution.
+ * @param randomGenerator The PRNG that is used to generate values.
+ */
public Exponential(double lambda, RandomEngine randomGenerator) {
setRandomGenerator(randomGenerator);
setState(lambda);
}
- /** Returns the cumulative distribution function. */
+ /**
+ * Returns the cumulative distribution function.
+ * @param x The point at which the cumulative distribution function is to
be evaluated.
+ * @return Returns the integral from -infinity to x of the PDF, also known
as the cumulative distribution
+ * function.
+ */
public double cdf(double x) {
if (x <= 0.0) {
return 0.0;
@@ -33,18 +41,19 @@ public class Exponential extends Abstrac
return 1.0 - Math.exp(-x * lambda);
}
- /** Returns a random number from the distribution. */
+ /**
+ * Returns a random number from the distribution.
+ */
@Override
public double nextDouble() {
- return nextDouble(lambda);
- }
-
- /** Returns a random number from the distribution; bypasses the internal
state. */
- public double nextDouble(double lambda) {
- return -Math.log(randomGenerator.raw()) / lambda;
+ return -Math.log(1 - randomGenerator.raw()) / lambda;
}
- /** Returns the probability distribution function. */
+ /**
+ * Returns the value of the probability density function at a particular
point.
+ * @param x The point at which the probability density function is to be
evaluated.
+ * @return The value of the probability density function at the specified
point.
+ */
public double pdf(double x) {
if (x < 0.0) {
return 0.0;
@@ -52,21 +61,19 @@ public class Exponential extends Abstrac
return lambda * Math.exp(-x * lambda);
}
- /** Sets the mean. */
+ /**
+ * Sets the rate parameter.
+ * @param lambda The new value of the rate parameter.
+ */
public void setState(double lambda) {
this.lambda = lambda;
}
- /** Returns a random number from the distribution with the given lambda. */
- public static double staticNextDouble(double lambda) {
- synchronized (shared) {
- return shared.nextDouble(lambda);
- }
- }
-
- /** Returns a String representation of the receiver. */
+ /**
+ * Returns a String representation of the receiver.
+ */
public String toString() {
- return this.getClass().getName() + '(' + lambda + ')';
+ return String.format(Locale.ENGLISH, "%s(%.4f)",
this.getClass().getName(), lambda);
}
}
Added:
mahout/trunk/math/src/test/java/org/apache/mahout/math/jet/random/ExponentialTest.java
URL:
http://svn.apache.org/viewvc/mahout/trunk/math/src/test/java/org/apache/mahout/math/jet/random/ExponentialTest.java?rev=991803&view=auto
==============================================================================
---
mahout/trunk/math/src/test/java/org/apache/mahout/math/jet/random/ExponentialTest.java
(added)
+++
mahout/trunk/math/src/test/java/org/apache/mahout/math/jet/random/ExponentialTest.java
Thu Sep 2 04:32:51 2010
@@ -0,0 +1,93 @@
+/*
+ * 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.mahout.math.jet.random;
+
+import org.apache.mahout.math.jet.random.engine.MersenneTwister;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.Locale;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Created by IntelliJ IDEA. User: tdunning Date: Aug 31, 2010 Time: 7:14:19
PM To change this
+ * template use File | Settings | File Templates.
+ */
+public class ExponentialTest {
+ @Test
+ public void testCdf() {
+ Exponential dist = new Exponential(5.0, new MersenneTwister(1));
+ for (int i = 0; i < 1000; i++) {
+ double x = i / 50.0;
+ assertEquals(1 - Math.exp(-x * 5.0), dist.cdf(x), 1e-9);
+ }
+ }
+
+ @Test
+ public void testPdf() {
+ checkPdf(new Exponential(13.0, null), 13.0);
+ }
+
+ private void checkPdf(Exponential dist, double lambda) {
+ assertEquals(0, dist.pdf(-1), 0);
+ double sum = 0;
+ double dx = 0.001 / lambda;
+ for (double x = 0; x < 20/lambda;x+=dx) {
+ sum += x * dist.pdf(x) * dx;
+ assertEquals(Math.exp(-x * lambda) * lambda, dist.pdf(x), 1e-9);
+ }
+ assertEquals(1 / lambda, sum, 1e-6 / lambda);
+ }
+
+ @Test
+ public void testSetState() {
+ Exponential dist = new Exponential(13.0, null);
+ for (double lambda = 0.1; lambda < 1000; lambda *= 1.3) {
+ dist.setState(lambda);
+ checkPdf(dist, lambda);
+ }
+ }
+
+ @Test
+ public void testNextDouble() {
+ for (double lambda : new double[] {13.0, 0.02, 1.6}) {
+ Exponential dist = new Exponential(lambda, new MersenneTwister(1));
+ checkEmpiricalDistribution(dist, 10000, lambda);
+ }
+ }
+
+ private void checkEmpiricalDistribution(Exponential dist, int n, double
lambda) {
+ double[] x = new double[n];
+ for (int i = 0; i < n; i++) {
+ x[i] = dist.nextDouble();
+ }
+ Arrays.sort(x);
+ for (int i = 0; i < n; i++) {
+ double cumulative = (double) i / (n - 1);
+ assertEquals(String.format("lambda = %.3f", lambda), cumulative,
dist.cdf(x[i]), 0.02);
+ }
+ }
+
+ @Test
+ public void testToString() {
+ assertEquals("org.apache.mahout.math.jet.random.Exponential(3.1000)", new
Exponential(3.1, null).toString());
+ Locale.setDefault(Locale.GERMAN);
+ assertEquals("org.apache.mahout.math.jet.random.Exponential(3.1000)", new
Exponential(3.1, null).toString());
+ }
+}