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 2013/10/20 22:42:42 UTC
svn commit: r1533974 - in /commons/proper/math/trunk: ./ src/changes/
src/main/java/org/apache/commons/math3/distribution/
src/test/java/org/apache/commons/math3/distribution/
Author: psteitz
Date: Sun Oct 20 20:42:41 2013
New Revision: 1533974
URL: http://svn.apache.org/r1533974
Log:
Added logDensity methods to AbstractReal/IntegerDistribution with naive default implementations and improved implementations for some current distributions.
JIRA: MATH-1039
Patch provided by Aleksei Dievskii
Modified:
commons/proper/math/trunk/pom.xml
commons/proper/math/trunk/src/changes/changes.xml
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/AbstractIntegerDistribution.java
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/AbstractRealDistribution.java
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/BetaDistribution.java
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/BinomialDistribution.java
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/ChiSquaredDistribution.java
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/ExponentialDistribution.java
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/FDistribution.java
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/GammaDistribution.java
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/GeometricDistribution.java
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/HypergeometricDistribution.java
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/LevyDistribution.java
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/LogNormalDistribution.java
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/NormalDistribution.java
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/ParetoDistribution.java
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/PascalDistribution.java
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/PoissonDistribution.java
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/TDistribution.java
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/WeibullDistribution.java
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/ZipfDistribution.java
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/IntegerDistributionAbstractTest.java
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/LevyDistributionTest.java
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/PoissonDistributionTest.java
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/RealDistributionAbstractTest.java
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/ZipfDistributionTest.java
Modified: commons/proper/math/trunk/pom.xml
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/pom.xml?rev=1533974&r1=1533973&r2=1533974&view=diff
==============================================================================
--- commons/proper/math/trunk/pom.xml (original)
+++ commons/proper/math/trunk/pom.xml Sun Oct 20 20:42:41 2013
@@ -181,6 +181,9 @@
<name>Larry Diamond</name>
</contributor>
<contributor>
+ <name>Aleksei Dievskii</name>
+ </contributor>
+ <contributor>
<name>Rodrigo di Lorenzo Lopes</name>
</contributor>
<contributor>
Modified: commons/proper/math/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/changes/changes.xml?rev=1533974&r1=1533973&r2=1533974&view=diff
==============================================================================
--- commons/proper/math/trunk/src/changes/changes.xml (original)
+++ commons/proper/math/trunk/src/changes/changes.xml Sun Oct 20 20:42:41 2013
@@ -51,6 +51,10 @@ If the output is not quite correct, chec
</properties>
<body>
<release version="x.y" date="TBD" description="TBD">
+ <action dev="psteitz" type="update" issue="MATH-1039" due-to="Aleksei Dievskii">
+ Added logDensity methods to AbstractReal/IntegerDistribution with naive default
+ implementations and improved implementations for some current distributions.
+ </action>
<action dev="psteitz" type="add" issue="MATH-1038" due-to="Thorsten Schaefer">
Added ConfidenceInterval class and BinomialConfidenceInterval providing several
estimators for confidence intervals for binomial probabilities.
Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/AbstractIntegerDistribution.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/AbstractIntegerDistribution.java?rev=1533974&r1=1533973&r2=1533974&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/AbstractIntegerDistribution.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/AbstractIntegerDistribution.java Sun Oct 20 20:42:41 2013
@@ -232,4 +232,23 @@ public abstract class AbstractIntegerDis
}
return result;
}
+
+ /**
+ * For a random variable {@code X} whose values are distributed according to
+ * this distribution, this method returns {@code log(P(X = x))}, where
+ * {@code log} is the natural logarithm. In other words, this method
+ * represents the logarithm of the probability mass function (PMF) for the
+ * distribution. Note that due to the floating point precision and
+ * under/overflow issues, this method will for some distributions be more
+ * precise and faster than computing the logarithm of
+ * {@link #probability(int)}.
+ * <p>
+ * The default implementation simply computes the logarithm of {@code probability(x)}.</p>
+ *
+ * @param x the point at which the PMF is evaluated
+ * @return the logarithm of the value of the probability mass function at {@code x}
+ */
+ public double logProbability(int x) {
+ return FastMath.log(probability(x));
+ }
}
Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/AbstractRealDistribution.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/AbstractRealDistribution.java?rev=1533974&r1=1533973&r2=1533974&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/AbstractRealDistribution.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/AbstractRealDistribution.java Sun Oct 20 20:42:41 2013
@@ -286,5 +286,23 @@ implements RealDistribution, Serializabl
public double probability(double x) {
return 0d;
}
+
+ /**
+ * Returns the natural logarithm of the probability density function (PDF) of this distribution
+ * evaluated at the specified point {@code x}. In general, the PDF is the derivative of the
+ * {@link #cumulativeProbability(double) CDF}. If the derivative does not exist at {@code x},
+ * then an appropriate replacement should be returned, e.g. {@code Double.POSITIVE_INFINITY},
+ * {@code Double.NaN}, or the limit inferior or limit superior of the difference quotient. Note
+ * that due to the floating point precision and under/overflow issues, this method will for some
+ * distributions be more precise and faster than computing the logarithm of
+ * {@link #density(double)}. The default implementation simply computes the logarithm of
+ * {@code density(x)}.
+ *
+ * @param x the point at which the PDF is evaluated
+ * @return the logarithm of the value of the probability density function at point {@code x}
+ */
+ public double logDensity(double x) {
+ return FastMath.log(density(x));
+ }
}
Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/BetaDistribution.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/BetaDistribution.java?rev=1533974&r1=1533973&r2=1533974&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/BetaDistribution.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/BetaDistribution.java Sun Oct 20 20:42:41 2013
@@ -156,6 +156,29 @@ public class BetaDistribution extends Ab
}
}
+ /** {@inheritDoc} **/
+ @Override
+ public double logDensity(double x) {
+ recomputeZ();
+ if (x < 0 || x > 1) {
+ return Double.NEGATIVE_INFINITY;
+ } else if (x == 0) {
+ if (alpha < 1) {
+ throw new NumberIsTooSmallException(LocalizedFormats.CANNOT_COMPUTE_BETA_DENSITY_AT_0_FOR_SOME_ALPHA, alpha, 1, false);
+ }
+ return Double.NEGATIVE_INFINITY;
+ } else if (x == 1) {
+ if (beta < 1) {
+ throw new NumberIsTooSmallException(LocalizedFormats.CANNOT_COMPUTE_BETA_DENSITY_AT_1_FOR_SOME_BETA, beta, 1, false);
+ }
+ return Double.NEGATIVE_INFINITY;
+ } else {
+ double logX = FastMath.log(x);
+ double log1mX = FastMath.log1p(-x);
+ return (alpha - 1) * logX + (beta - 1) * log1mX - z;
+ }
+ }
+
/** {@inheritDoc} */
public double cumulativeProbability(double x) {
if (x <= 0) {
Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/BinomialDistribution.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/BinomialDistribution.java?rev=1533974&r1=1533973&r2=1533974&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/BinomialDistribution.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/BinomialDistribution.java Sun Oct 20 20:42:41 2013
@@ -110,6 +110,20 @@ public class BinomialDistribution extend
return ret;
}
+ /** {@inheritDoc} **/
+ @Override
+ public double logProbability(int x) {
+ double ret;
+ if (x < 0 || x > numberOfTrials) {
+ ret = Double.NEGATIVE_INFINITY;
+ } else {
+ ret = SaddlePointExpansion.logBinomialProbability(x,
+ numberOfTrials, probabilityOfSuccess,
+ 1.0 - probabilityOfSuccess);
+ }
+ return ret;
+ }
+
/** {@inheritDoc} */
public double cumulativeProbability(int x) {
double ret;
Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/ChiSquaredDistribution.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/ChiSquaredDistribution.java?rev=1533974&r1=1533973&r2=1533974&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/ChiSquaredDistribution.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/ChiSquaredDistribution.java Sun Oct 20 20:42:41 2013
@@ -108,6 +108,12 @@ public class ChiSquaredDistribution exte
return gamma.density(x);
}
+ /** {@inheritDoc} **/
+ @Override
+ public double logDensity(double x) {
+ return gamma.logDensity(x);
+ }
+
/** {@inheritDoc} */
public double cumulativeProbability(double x) {
return gamma.cumulativeProbability(x);
Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/ExponentialDistribution.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/ExponentialDistribution.java?rev=1533974&r1=1533973&r2=1533974&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/ExponentialDistribution.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/ExponentialDistribution.java Sun Oct 20 20:42:41 2013
@@ -56,6 +56,8 @@ public class ExponentialDistribution ext
private static final double[] EXPONENTIAL_SA_QI;
/** The mean of this distribution. */
private final double mean;
+ /** The logarithm of the mean, stored to reduce computing time. **/
+ private final double logMean;
/** Inverse cumulative probability accuracy. */
private final double solverAbsoluteAccuracy;
@@ -144,6 +146,7 @@ public class ExponentialDistribution ext
throw new NotStrictlyPositiveException(LocalizedFormats.MEAN, mean);
}
this.mean = mean;
+ logMean = FastMath.log(mean);
solverAbsoluteAccuracy = inverseCumAccuracy;
}
@@ -164,6 +167,12 @@ public class ExponentialDistribution ext
return FastMath.exp(-x / mean) / mean;
}
+ /** {@inheritDoc} **/
+ @Override
+ public double logDensity(double x) {
+ return -x / mean - logMean;
+ }
+
/**
* {@inheritDoc}
*
Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/FDistribution.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/FDistribution.java?rev=1533974&r1=1533973&r2=1533974&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/FDistribution.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/FDistribution.java Sun Oct 20 20:42:41 2013
@@ -154,6 +154,21 @@ public class FDistribution extends Abstr
Beta.logBeta(nhalf, mhalf));
}
+ /** {@inheritDoc} **/
+ @Override
+ public double logDensity(double x) {
+ final double nhalf = numeratorDegreesOfFreedom / 2;
+ final double mhalf = denominatorDegreesOfFreedom / 2;
+ final double logx = FastMath.log(x);
+ final double logn = FastMath.log(numeratorDegreesOfFreedom);
+ final double logm = FastMath.log(denominatorDegreesOfFreedom);
+ final double lognxm = FastMath.log(numeratorDegreesOfFreedom * x +
+ denominatorDegreesOfFreedom);
+ return nhalf * logn + nhalf * logx - logx +
+ mhalf * logm - nhalf * lognxm - mhalf * lognxm -
+ Beta.logBeta(nhalf, mhalf);
+ }
+
/**
* {@inheritDoc}
*
Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/GammaDistribution.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/GammaDistribution.java?rev=1533974&r1=1533973&r2=1533974&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/GammaDistribution.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/GammaDistribution.java Sun Oct 20 20:42:41 2013
@@ -58,6 +58,15 @@ public class GammaDistribution extends A
private final double densityPrefactor1;
/**
* The constant value of
+ * {@code log(shape / scale * sqrt(e / (2 * pi * (shape + g + 0.5))) / L(shape))},
+ * where {@code L(shape)} is the Lanczos approximation returned by
+ * {@link Gamma#lanczos(double)}. This prefactor is used in
+ * {@link #logDensity(double)}, when no overflow occurs with the natural
+ * calculation.
+ */
+ private final double logDensityPrefactor1;
+ /**
+ * The constant value of
* {@code shape * sqrt(e / (2 * pi * (shape + g + 0.5))) / L(shape)},
* where {@code L(shape)} is the Lanczos approximation returned by
* {@link Gamma#lanczos(double)}. This prefactor is used in
@@ -66,6 +75,15 @@ public class GammaDistribution extends A
*/
private final double densityPrefactor2;
/**
+ * The constant value of
+ * {@code log(shape * sqrt(e / (2 * pi * (shape + g + 0.5))) / L(shape))},
+ * where {@code L(shape)} is the Lanczos approximation returned by
+ * {@link Gamma#lanczos(double)}. This prefactor is used in
+ * {@link #logDensity(double)}, when overflow occurs with the natural
+ * calculation.
+ */
+ private final double logDensityPrefactor2;
+ /**
* Lower bound on {@code y = x / scale} for the selection of the computation
* method in {@link #density(double)}. For {@code y <= minY}, the natural
* calculation overflows.
@@ -159,9 +177,14 @@ public class GammaDistribution extends A
this.shiftedShape = shape + Gamma.LANCZOS_G + 0.5;
final double aux = FastMath.E / (2.0 * FastMath.PI * shiftedShape);
this.densityPrefactor2 = shape * FastMath.sqrt(aux) / Gamma.lanczos(shape);
+ this.logDensityPrefactor2 = FastMath.log(shape) + 0.5 * FastMath.log(aux) -
+ FastMath.log(Gamma.lanczos(shape));
this.densityPrefactor1 = this.densityPrefactor2 / scale *
FastMath.pow(shiftedShape, -shape) *
FastMath.exp(shape + Gamma.LANCZOS_G);
+ this.logDensityPrefactor1 = this.logDensityPrefactor2 - FastMath.log(scale) -
+ FastMath.log(shiftedShape) * shape +
+ shape + Gamma.LANCZOS_G;
this.minY = shape + Gamma.LANCZOS_G - FastMath.log(Double.MAX_VALUE);
this.maxLogY = FastMath.log(Double.MAX_VALUE) / (shape - 1.0);
}
@@ -271,6 +294,32 @@ public class GammaDistribution extends A
FastMath.pow(y, shape - 1);
}
+ /** {@inheritDoc} **/
+ @Override
+ public double logDensity(double x) {
+ /* see the comment in {@link #density(double)} for computation details
+ */
+ if (x < 0) {
+ return Double.NEGATIVE_INFINITY;
+ }
+ final double y = x / scale;
+ if ((y <= minY) || (FastMath.log(y) >= maxLogY)) {
+ /*
+ * Overflow.
+ */
+ final double aux1 = (y - shiftedShape) / shiftedShape;
+ final double aux2 = shape * (FastMath.log1p(aux1) - aux1);
+ final double aux3 = -y * (Gamma.LANCZOS_G + 0.5) / shiftedShape +
+ Gamma.LANCZOS_G + aux2;
+ return logDensityPrefactor2 - FastMath.log(x) + aux3;
+ }
+ /*
+ * Natural calculation.
+ */
+ return logDensityPrefactor1 - y +
+ FastMath.log(y) * (shape - 1);
+ }
+
/**
* {@inheritDoc}
*
Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/GeometricDistribution.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/GeometricDistribution.java?rev=1533974&r1=1533973&r2=1533974&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/GeometricDistribution.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/GeometricDistribution.java Sun Oct 20 20:42:41 2013
@@ -86,6 +86,19 @@ public class GeometricDistribution exten
}
/** {@inheritDoc} */
+ @Override
+ public double logProbability(int x) {
+ double ret;
+ if (x < 0) {
+ ret = Double.NEGATIVE_INFINITY;
+ } else {
+ final double p = probabilityOfSuccess;
+ ret = x * FastMath.log1p(-p) + FastMath.log(p);
+ }
+ return ret;
+ }
+
+ /** {@inheritDoc} */
public double cumulativeProbability(int x) {
double ret;
if (x < 0) {
Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/HypergeometricDistribution.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/HypergeometricDistribution.java?rev=1533974&r1=1533973&r2=1533974&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/HypergeometricDistribution.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/HypergeometricDistribution.java Sun Oct 20 20:42:41 2013
@@ -214,6 +214,30 @@ public class HypergeometricDistribution
return ret;
}
+ /** {@inheritDoc} */
+ @Override
+ public double logProbability(int x) {
+ double ret;
+
+ int[] domain = getDomain(populationSize, numberOfSuccesses, sampleSize);
+ if (x < domain[0] || x > domain[1]) {
+ ret = Double.NEGATIVE_INFINITY;
+ } else {
+ double p = (double) sampleSize / (double) populationSize;
+ double q = (double) (populationSize - sampleSize) / (double) populationSize;
+ double p1 = SaddlePointExpansion.logBinomialProbability(x,
+ numberOfSuccesses, p, q);
+ double p2 =
+ SaddlePointExpansion.logBinomialProbability(sampleSize - x,
+ populationSize - numberOfSuccesses, p, q);
+ double p3 =
+ SaddlePointExpansion.logBinomialProbability(sampleSize, populationSize, p, q);
+ ret = p1 + p2 - p3;
+ }
+
+ return ret;
+ }
+
/**
* For this distribution, {@code X}, this method returns {@code P(X >= x)}.
*
Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/LevyDistribution.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/LevyDistribution.java?rev=1533974&r1=1533973&r2=1533974&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/LevyDistribution.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/LevyDistribution.java Sun Oct 20 20:42:41 2013
@@ -80,6 +80,21 @@ public class LevyDistribution extends Ab
}
/** {@inheritDoc}
+ *
+ * See documentation of {@link #density(double)} for computation details.
+ */
+ @Override
+ public double logDensity(double x) {
+ if (x < mu) {
+ return Double.NaN;
+ }
+
+ final double delta = x - mu;
+ final double f = halfC / delta;
+ return 0.5 * FastMath.log(f / FastMath.PI) - f - FastMath.log(delta);
+ }
+
+ /** {@inheritDoc}
* <p>
* From Wikipedia: the cumulative distribution function is
* </p>
Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/LogNormalDistribution.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/LogNormalDistribution.java?rev=1533974&r1=1533973&r2=1533974&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/LogNormalDistribution.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/LogNormalDistribution.java Sun Oct 20 20:42:41 2013
@@ -71,6 +71,8 @@ public class LogNormalDistribution exten
/** The shape parameter of this distribution. */
private final double shape;
+ /** The value of {@code log(shape) + 0.5 * log(2*PI)} stored for faster computation. */
+ private final double logShapePlusHalfLog2Pi;
/** Inverse cumulative probability accuracy. */
private final double solverAbsoluteAccuracy;
@@ -149,6 +151,7 @@ public class LogNormalDistribution exten
this.scale = scale;
this.shape = shape;
+ this.logShapePlusHalfLog2Pi = FastMath.log(shape) + 0.5 * FastMath.log(2 * FastMath.PI);
this.solverAbsoluteAccuracy = inverseCumAccuracy;
}
@@ -190,6 +193,21 @@ public class LogNormalDistribution exten
return FastMath.exp(-0.5 * x1 * x1) / (shape * SQRT2PI * x);
}
+ /** {@inheritDoc}
+ *
+ * See documentation of {@link #density(double)} for computation details.
+ */
+ @Override
+ public double logDensity(double x) {
+ if (x <= 0) {
+ return Double.NEGATIVE_INFINITY;
+ }
+ final double logX = FastMath.log(x);
+ final double x0 = logX - scale;
+ final double x1 = x0 / shape;
+ return -0.5 * x1 * x1 - (logShapePlusHalfLog2Pi + logX);
+ }
+
/**
* {@inheritDoc}
*
Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/NormalDistribution.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/NormalDistribution.java?rev=1533974&r1=1533973&r2=1533974&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/NormalDistribution.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/NormalDistribution.java Sun Oct 20 20:42:41 2013
@@ -49,6 +49,8 @@ public class NormalDistribution extends
private final double mean;
/** Standard deviation of this distribution. */
private final double standardDeviation;
+ /** The value of {@code log(sd) + 0.5*log(2*pi)} stored for faster computation. */
+ private final double logStandardDeviationPlusHalfLog2Pi;
/** Inverse cumulative probability accuracy. */
private final double solverAbsoluteAccuracy;
@@ -124,6 +126,7 @@ public class NormalDistribution extends
this.mean = mean;
standardDeviation = sd;
+ logStandardDeviationPlusHalfLog2Pi = FastMath.log(sd) + 0.5 * FastMath.log(2 * FastMath.PI);
solverAbsoluteAccuracy = inverseCumAccuracy;
}
@@ -152,6 +155,13 @@ public class NormalDistribution extends
return FastMath.exp(-0.5 * x1 * x1) / (standardDeviation * SQRT2PI);
}
+ /** {@inheritDoc} */
+ public double logDensity(double x) {
+ final double x0 = x - mean;
+ final double x1 = x0 / standardDeviation;
+ return -0.5 * x1 * x1 - logStandardDeviationPlusHalfLog2Pi;
+ }
+
/**
* {@inheritDoc}
*
Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/ParetoDistribution.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/ParetoDistribution.java?rev=1533974&r1=1533973&r2=1533974&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/ParetoDistribution.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/ParetoDistribution.java Sun Oct 20 20:42:41 2013
@@ -174,6 +174,18 @@ public class ParetoDistribution extends
return FastMath.pow(scale, shape) / FastMath.pow(x, shape + 1) * shape;
}
+ /** {@inheritDoc}
+ *
+ * See documentation of {@link #density(double)} for computation details.
+ */
+ @Override
+ public double logDensity(double x) {
+ if (x < scale) {
+ return Double.NEGATIVE_INFINITY;
+ }
+ return FastMath.log(scale) * shape - FastMath.log(x) * (shape + 1) + FastMath.log(shape);
+ }
+
/**
* {@inheritDoc}
* <p>
Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/PascalDistribution.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/PascalDistribution.java?rev=1533974&r1=1533973&r2=1533974&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/PascalDistribution.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/PascalDistribution.java Sun Oct 20 20:42:41 2013
@@ -68,6 +68,12 @@ public class PascalDistribution extends
private final int numberOfSuccesses;
/** The probability of success. */
private final double probabilityOfSuccess;
+ /** The value of {@code log(p)}, where {@code p} is the probability of success,
+ * stored for faster computation. */
+ private final double logProbabilityOfSuccess;
+ /** The value of {@code log(1-p)}, where {@code p} is the probability of success,
+ * stored for faster computation. */
+ private final double log1mProbabilityOfSuccess;
/**
* Create a Pascal distribution with the given number of successes and
@@ -112,6 +118,8 @@ public class PascalDistribution extends
numberOfSuccesses = r;
probabilityOfSuccess = p;
+ logProbabilityOfSuccess = FastMath.log(p);
+ log1mProbabilityOfSuccess = FastMath.log1p(-p);
}
/**
@@ -147,6 +155,21 @@ public class PascalDistribution extends
}
/** {@inheritDoc} */
+ @Override
+ public double logProbability(int x) {
+ double ret;
+ if (x < 0) {
+ ret = Double.NEGATIVE_INFINITY;
+ } else {
+ ret = CombinatoricsUtils.binomialCoefficientLog(x +
+ numberOfSuccesses - 1, numberOfSuccesses - 1) +
+ logProbabilityOfSuccess * numberOfSuccesses +
+ log1mProbabilityOfSuccess * x;
+ }
+ return ret;
+ }
+
+ /** {@inheritDoc} */
public double cumulativeProbability(int x) {
double ret;
if (x < 0) {
Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/PoissonDistribution.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/PoissonDistribution.java?rev=1533974&r1=1533973&r2=1533974&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/PoissonDistribution.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/PoissonDistribution.java Sun Oct 20 20:42:41 2013
@@ -175,6 +175,22 @@ public class PoissonDistribution extends
}
/** {@inheritDoc} */
+ @Override
+ public double logProbability(int x) {
+ double ret;
+ if (x < 0 || x == Integer.MAX_VALUE) {
+ ret = Double.NEGATIVE_INFINITY;
+ } else if (x == 0) {
+ ret = -mean;
+ } else {
+ ret = -SaddlePointExpansion.getStirlingError(x) -
+ SaddlePointExpansion.getDeviancePart(x, mean) -
+ 0.5 * FastMath.log(MathUtils.TWO_PI) - 0.5 * FastMath.log(x);
+ }
+ return ret;
+ }
+
+ /** {@inheritDoc} */
public double cumulativeProbability(int x) {
if (x < 0) {
return 0;
Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/TDistribution.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/TDistribution.java?rev=1533974&r1=1533973&r2=1533974&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/TDistribution.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/TDistribution.java Sun Oct 20 20:42:41 2013
@@ -130,6 +130,18 @@ public class TDistribution extends Abstr
}
/** {@inheritDoc} */
+ @Override
+ public double logDensity(double x) {
+ final double n = degreesOfFreedom;
+ final double nPlus1Over2 = (n + 1) / 2;
+ return Gamma.logGamma(nPlus1Over2) -
+ 0.5 * (FastMath.log(FastMath.PI) +
+ FastMath.log(n)) -
+ Gamma.logGamma(n / 2) -
+ nPlus1Over2 * FastMath.log(1 + x * x / n);
+ }
+
+ /** {@inheritDoc} */
public double cumulativeProbability(double x) {
double ret;
if (x == 0) {
Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/WeibullDistribution.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/WeibullDistribution.java?rev=1533974&r1=1533973&r2=1533974&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/WeibullDistribution.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/WeibullDistribution.java Sun Oct 20 20:42:41 2013
@@ -175,6 +175,26 @@ public class WeibullDistribution extends
}
/** {@inheritDoc} */
+ @Override
+ public double logDensity(double x) {
+ if (x < 0) {
+ return Double.NEGATIVE_INFINITY;
+ }
+
+ final double xscale = x / scale;
+ final double logxscalepow = FastMath.log(xscale) * (shape - 1);
+
+ /*
+ * FastMath.pow(x / scale, shape) =
+ * FastMath.pow(xscale, shape) =
+ * FastMath.pow(xscale, shape - 1) * xscale
+ */
+ final double xscalepowshape = FastMath.exp(logxscalepow) * xscale;
+
+ return FastMath.log(shape / scale) + logxscalepow - xscalepowshape;
+ }
+
+ /** {@inheritDoc} */
public double cumulativeProbability(double x) {
double ret;
if (x <= 0.0) {
Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/ZipfDistribution.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/ZipfDistribution.java?rev=1533974&r1=1533973&r2=1533974&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/ZipfDistribution.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/ZipfDistribution.java Sun Oct 20 20:42:41 2013
@@ -115,6 +115,16 @@ public class ZipfDistribution extends Ab
}
/** {@inheritDoc} */
+ @Override
+ public double logProbability(int x) {
+ if (x <= 0 || x > numberOfElements) {
+ return Double.NEGATIVE_INFINITY;
+ }
+
+ return -FastMath.log(x) * exponent - FastMath.log(generalizedHarmonic(numberOfElements, exponent));
+ }
+
+ /** {@inheritDoc} */
public double cumulativeProbability(final int x) {
if (x <= 0) {
return 0.0;
Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/IntegerDistributionAbstractTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/IntegerDistributionAbstractTest.java?rev=1533974&r1=1533973&r2=1533974&view=diff
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/IntegerDistributionAbstractTest.java (original)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/IntegerDistributionAbstractTest.java Sun Oct 20 20:42:41 2013
@@ -18,6 +18,7 @@ package org.apache.commons.math3.distrib
import org.apache.commons.math3.TestUtils;
import org.apache.commons.math3.exception.MathIllegalArgumentException;
+import org.apache.commons.math3.util.FastMath;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
@@ -60,6 +61,9 @@ public abstract class IntegerDistributio
/** Values used to test probability density calculations */
private double[] densityTestValues;
+ /** Values used to test logarithmic probability density calculations */
+ private double[] logDensityTestValues;
+
/** Arguments used to test cumulative probability density calculations */
private int[] cumulativeTestPoints;
@@ -83,6 +87,22 @@ public abstract class IntegerDistributio
/** Creates the default probability density test expected values */
public abstract double[] makeDensityTestValues();
+ /** Creates the default logarithmic probability density test expected values.
+ *
+ * The default implementation simply computes the logarithm of all the values in
+ * {@link #makeDensityTestValues()}.
+ *
+ * @return double[] the default logarithmic probability density test expected values.
+ */
+ public double[] makeLogDensityTestValues() {
+ final double[] densityTestValues = makeDensityTestValues();
+ final double[] logDensityTestValues = new double[densityTestValues.length];
+ for (int i = 0; i < densityTestValues.length; i++) {
+ logDensityTestValues[i] = FastMath.log(densityTestValues[i]);
+ }
+ return logDensityTestValues;
+ }
+
/** Creates the default cumulative probability density test input values */
public abstract int[] makeCumulativeTestPoints();
@@ -105,6 +125,7 @@ public abstract class IntegerDistributio
distribution = makeDistribution();
densityTestPoints = makeDensityTestPoints();
densityTestValues = makeDensityTestValues();
+ logDensityTestValues = makeLogDensityTestValues();
cumulativeTestPoints = makeCumulativeTestPoints();
cumulativeTestValues = makeCumulativeTestValues();
inverseCumulativeTestPoints = makeInverseCumulativeTestPoints();
@@ -119,6 +140,7 @@ public abstract class IntegerDistributio
distribution = null;
densityTestPoints = null;
densityTestValues = null;
+ logDensityTestValues = null;
cumulativeTestPoints = null;
cumulativeTestValues = null;
inverseCumulativeTestPoints = null;
@@ -140,6 +162,19 @@ public abstract class IntegerDistributio
}
/**
+ * Verifies that logarithmic probability density calculations match expected values
+ * using current test instance data.
+ */
+ protected void verifyLogDensities() {
+ for (int i = 0; i < densityTestPoints.length; i++) {
+ // FIXME: when logProbability methods are added to IntegerDistribution in 4.0, remove cast below
+ Assert.assertEquals("Incorrect log density value returned for " + densityTestPoints[i],
+ logDensityTestValues[i],
+ ((AbstractIntegerDistribution) distribution).logProbability(densityTestPoints[i]), tolerance);
+ }
+ }
+
+ /**
* Verifies that cumulative probability density calculations match expected values
* using current test instance data
*/
@@ -176,6 +211,15 @@ public abstract class IntegerDistributio
}
/**
+ * Verifies that logarithmic probability density calculations match expected values
+ * using default test instance data
+ */
+ @Test
+ public void testLogDensities() {
+ verifyLogDensities();
+ }
+
+ /**
* Verifies that cumulative probability density calculations match expected values
* using default test instance data
*/
Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/LevyDistributionTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/LevyDistributionTest.java?rev=1533974&r1=1533973&r2=1533974&view=diff
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/LevyDistributionTest.java (original)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/LevyDistributionTest.java Sun Oct 20 20:42:41 2013
@@ -68,4 +68,15 @@ public class LevyDistributionTest extend
};
}
+ /**
+ * Creates the default logarithmic probability density test expected values.
+ * Reference values are from R, version 2.14.1.
+ */
+ @Override
+ public double[] makeLogDensityTestValues() {
+ return new double[] {
+ -1987.561573341398d, -14.469328620160d, -3.843764717971d,
+ -0.883485488811d, 0.076793740349d, -1.127785768948d,
+ -2.650679030597d, -3.644945255983d};
+ }
}
Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/PoissonDistributionTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/PoissonDistributionTest.java?rev=1533974&r1=1533973&r2=1533974&view=diff
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/PoissonDistributionTest.java (original)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/PoissonDistributionTest.java Sun Oct 20 20:42:41 2013
@@ -67,6 +67,18 @@ public class PoissonDistributionTest ext
0.156293451851d, 0.00529247667642d, 8.27746364655e-09};
}
+ /**
+ * Creates the default logarithmic probability density test expected values.
+ * Reference values are from R, version 2.14.1.
+ */
+ @Override
+ public double[] makeLogDensityTestValues() {
+ return new double[] { Double.NEGATIVE_INFINITY, -4.000000000000d,
+ -2.613705638880d, -1.920558458320d, -1.632876385868d,
+ -1.632876385868d, -1.856019937183d, -5.241468961877d,
+ -18.609729238356d};
+ }
+
/**
* Creates the default cumulative probability density test input values.
*/
Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/RealDistributionAbstractTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/RealDistributionAbstractTest.java?rev=1533974&r1=1533973&r2=1533974&view=diff
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/RealDistributionAbstractTest.java (original)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/RealDistributionAbstractTest.java Sun Oct 20 20:42:41 2013
@@ -95,6 +95,9 @@ public abstract class RealDistributionAb
/** Values used to test density calculations */
private double[] densityTestValues;
+ /** Values used to test logarithmic density calculations */
+ private double[] logDensityTestValues;
+
//-------------------- Abstract methods -----------------------------------
/** Creates the default continuous distribution instance to use in tests. */
@@ -109,6 +112,18 @@ public abstract class RealDistributionAb
/** Creates the default density test expected values */
public abstract double[] makeDensityTestValues();
+ /** Creates the default logarithmic density test expected values.
+ * The default implementation simply computes the logarithm
+ * of each value returned by {@link #makeDensityTestValues()}.*/
+ public double[] makeLogDensityTestValues() {
+ final double[] densityTestValues = makeDensityTestValues();
+ final double[] logDensityTestValues = new double[densityTestValues.length];
+ for (int i = 0; i < densityTestValues.length; i++) {
+ logDensityTestValues[i] = FastMath.log(densityTestValues[i]);
+ }
+ return logDensityTestValues;
+ }
+
//---- Default implementations of inverse test data generation methods ----
/** Creates the default inverse cumulative probability test input values */
@@ -134,6 +149,7 @@ public abstract class RealDistributionAb
inverseCumulativeTestPoints = makeInverseCumulativeTestPoints();
inverseCumulativeTestValues = makeInverseCumulativeTestValues();
densityTestValues = makeDensityTestValues();
+ logDensityTestValues = makeLogDensityTestValues();
}
/**
@@ -147,6 +163,7 @@ public abstract class RealDistributionAb
inverseCumulativeTestPoints = null;
inverseCumulativeTestValues = null;
densityTestValues = null;
+ logDensityTestValues = null;
}
//-------------------- Verification methods -------------------------------
@@ -208,6 +225,19 @@ public abstract class RealDistributionAb
}
}
+ /**
+ * Verifies that logarithmic density calculations match expected values
+ */
+ protected void verifyLogDensities() {
+ // FIXME: when logProbability methods are added to RealDistribution in 4.0, remove cast below
+ for (int i = 0; i < cumulativeTestPoints.length; i++) {
+ TestUtils.assertEquals("Incorrect probability density value returned for "
+ + cumulativeTestPoints[i], logDensityTestValues[i],
+ ((AbstractRealDistribution) distribution).logDensity(cumulativeTestPoints[i]),
+ getTolerance());
+ }
+ }
+
//------------------------ Default test cases -----------------------------
/**
@@ -238,6 +268,15 @@ public abstract class RealDistributionAb
}
/**
+ * Verifies that logarithmic density calculations return expected values
+ * for default test instance data
+ */
+ @Test
+ public void testLogDensities() {
+ verifyLogDensities();
+ }
+
+ /**
* Verifies that probability computations are consistent
*/
@Test
Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/ZipfDistributionTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/ZipfDistributionTest.java?rev=1533974&r1=1533973&r2=1533974&view=diff
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/ZipfDistributionTest.java (original)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/ZipfDistributionTest.java Sun Oct 20 20:42:41 2013
@@ -73,6 +73,17 @@ public class ZipfDistributionTest extend
0.0569028586912, 0.0487738788782, 0.0426771440184, 0.0379352391275, 0.0341417152147, 0};
}
+ /**
+ * Creates the default logarithmic probability density test expected values.
+ * Reference values are from R, version 2.14.1.
+ */
+ @Override
+ public double[] makeLogDensityTestValues() {
+ return new double[] {Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY,
+ -1.0746d, -1.7678d, -2.1733d, -2.4609d, -2.6841d, -2.8664d, -3.0206d, -3.1541d,
+ -3.2719d, -3.3772d, Double.NEGATIVE_INFINITY};
+ }
+
/** Creates the default cumulative probability density test input values */
@Override
public int[] makeCumulativeTestPoints() {