From 0f004b25f755c6f334cec6ae27383c88ba34b9c1 Mon Sep 17 00:00:00 2001 From: Mikkel Meyer Andersen Date: Mon, 27 Dec 2010 09:51:56 +0000 Subject: [PATCH] Fixes MATH-385 git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1053032 13f79535-47bb-0310-9956-ffa450edef68 --- .../AbstractContinuousDistribution.java | 14 +++ .../distribution/AbstractDistribution.java | 95 +++++++++++++++++++ .../AbstractIntegerDistribution.java | 38 ++++++++ .../distribution/BetaDistributionImpl.java | 67 +++++++++++++ .../BinomialDistributionImpl.java | 54 +++++++++++ .../distribution/CauchyDistributionImpl.java | 62 +++++++++++- .../ChiSquaredDistributionImpl.java | 62 ++++++++++++ .../math/distribution/Distribution.java | 55 +++++++++++ .../ExponentialDistributionImpl.java | 62 ++++++++++++ .../math/distribution/FDistributionImpl.java | 89 +++++++++++++++++ .../distribution/GammaDistributionImpl.java | 64 +++++++++++++ .../HypergeometricDistributionImpl.java | 65 +++++++++++++ .../distribution/NormalDistributionImpl.java | 62 ++++++++++++ .../distribution/PascalDistributionImpl.java | 65 +++++++++++++ .../distribution/PoissonDistributionImpl.java | 56 +++++++++++ .../math/distribution/TDistributionImpl.java | 85 +++++++++++++++++ .../distribution/WeibullDistributionImpl.java | 72 ++++++++++++++ .../distribution/ZipfDistributionImpl.java | 72 ++++++++++++++ .../distribution/BetaDistributionTest.java | 14 +++ .../BinomialDistributionTest.java | 13 +++ .../distribution/CauchyDistributionTest.java | 13 +++ .../ChiSquareDistributionTest.java | 13 +++ .../ExponentialDistributionTest.java | 13 +++ .../math/distribution/FDistributionTest.java | 17 ++++ .../distribution/GammaDistributionTest.java | 13 +++ .../HypergeometricDistributionTest.java | 13 +++ .../distribution/NormalDistributionTest.java | 16 ++++ .../distribution/PascalDistributionTest.java | 13 +++ .../distribution/PoissonDistributionTest.java | 13 +++ .../math/distribution/TDistributionTest.java | 17 ++++ .../distribution/WeibullDistributionTest.java | 20 ++++ .../distribution/ZipfDistributionTest.java | 11 +++ 32 files changed, 1337 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/apache/commons/math/distribution/AbstractContinuousDistribution.java b/src/main/java/org/apache/commons/math/distribution/AbstractContinuousDistribution.java index 0fce633cc..7f232c19c 100644 --- a/src/main/java/org/apache/commons/math/distribution/AbstractContinuousDistribution.java +++ b/src/main/java/org/apache/commons/math/distribution/AbstractContinuousDistribution.java @@ -219,4 +219,18 @@ public abstract class AbstractContinuousDistribution protected double getSolverAbsoluteAccuracy() { return solverAbsoluteAccuracy; } + + /** + * Access the lower bound of the support. + * + * @return lower bound of the support (might be Double.NEGATIVE_INFINITY) + */ + public abstract double getSupportLowerBound(); + + /** + * Access the upper bound of the support. + * + * @return upper bound of the support (might be Double.POSITIVE_INFINITY) + */ + public abstract double getSupportUpperBound(); } diff --git a/src/main/java/org/apache/commons/math/distribution/AbstractDistribution.java b/src/main/java/org/apache/commons/math/distribution/AbstractDistribution.java index 7d4a1ce7d..ed59f6743 100644 --- a/src/main/java/org/apache/commons/math/distribution/AbstractDistribution.java +++ b/src/main/java/org/apache/commons/math/distribution/AbstractDistribution.java @@ -33,6 +33,12 @@ public abstract class AbstractDistribution /** Serializable version identifier */ private static final long serialVersionUID = -38038050983108802L; + private double numericalMean = Double.NaN; + private boolean numericalMeanIsCalculated = false; + + private double numericalVariance = Double.NaN; + private boolean numericalVarianceIsCalculated = false; + /** * Default constructor. */ @@ -65,4 +71,93 @@ public abstract class AbstractDistribution } return cumulativeProbability(x1) - cumulativeProbability(x0); } + + /** + * Use this method to actually calculate the mean for the + * specific distribution. Use {@link #getNumericalMean()} + * (which implements caching) to actually get the mean. + * + * @return the mean or Double.NaN if it's not defined + */ + protected abstract double calculateNumericalMean(); + + /** + * Use this method to get the numerical value of the mean of this + * distribution. + * + * @return the mean or Double.NaN if it's not defined + */ + public double getNumericalMean() { + if (!numericalMeanIsCalculated) { + numericalMean = calculateNumericalMean(); + numericalMeanIsCalculated = true; + } + + return numericalMean; + } + + /** + * Use this method to actually calculate the variance for the + * specific distribution. Use {@link #getNumericalVariance()} + * (which implements caching) to actually get the variance. + * + * @return the variance or Double.NaN if it's not defined + */ + protected abstract double calculateNumericalVariance(); + + /** + * Use this method to get the numerical value of the variance of this + * distribution. + * + * @return the variance (possibly Double.POSITIVE_INFINITY as + * for certain cases in {@link TDistributionImpl}) or + * Double.NaN if it's not defined + */ + public double getNumericalVariance() { + if (!numericalVarianceIsCalculated) { + numericalVariance = calculateNumericalVariance(); + numericalVarianceIsCalculated = true; + } + + return numericalVariance; + } + + /** + * Use this method to get information about whether the lower bound + * of the support is inclusive or not. + * + * @return whether the lower bound of the support is inclusive or not + */ + public abstract boolean isSupportLowerBoundInclusive(); + + /** + * Use this method to get information about whether the upper bound + * of the support is inclusive or not. + * + * @return whether the upper bound of the support is inclusive or not + */ + public abstract boolean isSupportUpperBoundInclusive(); + + /** + * Use this method to get information about whether the support is connected, + * i.e. whether all values between the lower and upper bound of the support + * is included in the support. + * + * For {@link AbstractIntegerDistribution} the support is discrete, so + * if this is true, then the support is + * {lower bound, lower bound + 1, ..., upper bound}. + * + * For {@link AbstractContinuousDistribution} the support is continuous, so + * if this is true, then the support is the interval + * [lower bound, upper bound] + * where the limits are inclusive or not according to + * {@link #isSupportLowerBoundInclusive()} and {@link #isSupportUpperBoundInclusive()} + * (in the example both are true). If both are false, then the support is the interval + * (lower bound, upper bound) + * + * @return whether the support limits given by subclassed methods are connected or not + */ + public boolean isSupportConnected() { + return true; + } } diff --git a/src/main/java/org/apache/commons/math/distribution/AbstractIntegerDistribution.java b/src/main/java/org/apache/commons/math/distribution/AbstractIntegerDistribution.java index 256fe7428..7625c0333 100644 --- a/src/main/java/org/apache/commons/math/distribution/AbstractIntegerDistribution.java +++ b/src/main/java/org/apache/commons/math/distribution/AbstractIntegerDistribution.java @@ -289,4 +289,42 @@ public abstract class AbstractIntegerDistribution extends AbstractDistribution * @return the domain value upper bound, i.e. {@code P(X < 'upper bound') > p}. */ protected abstract int getDomainUpperBound(double p); + + /** + * Access the lower bound of the support. + * + * @return lower bound of the support (Integer.MIN_VALUE for negative infinity) + */ + public abstract int getSupportLowerBound(); + + /** + * Access the upper bound of the support. + * + * @return upper bound of the support (Integer.MAX_VALUE for positive infinity) + */ + public abstract int getSupportUpperBound(); + + /** + * Use this method to get information about whether the lower bound + * of the support is inclusive or not. For discrete support, + * only true here is meaningful. + * + * @return true (always but at Integer.MIN_VALUE because of the nature of discrete support) + */ + @Override + public boolean isSupportLowerBoundInclusive() { + return true; + } + + /** + * Use this method to get information about whether the upper bound + * of the support is inclusive or not. For discrete support, + * only true here is meaningful. + * + * @return true (always but at Integer.MAX_VALUE because of the nature of discrete support) + */ + @Override + public boolean isSupportUpperBoundInclusive() { + return true; + } } diff --git a/src/main/java/org/apache/commons/math/distribution/BetaDistributionImpl.java b/src/main/java/org/apache/commons/math/distribution/BetaDistributionImpl.java index 06812be8a..f02bb2cb4 100644 --- a/src/main/java/org/apache/commons/math/distribution/BetaDistributionImpl.java +++ b/src/main/java/org/apache/commons/math/distribution/BetaDistributionImpl.java @@ -184,4 +184,71 @@ public class BetaDistributionImpl protected double getSolverAbsoluteAccuracy() { return solverAbsoluteAccuracy; } + + /** + * {@inheritDoc} + * + * The lower bound of the support is always 0 no matter the parameters. + * + * @return lower bound of the support (always 0) + */ + @Override + public double getSupportLowerBound() { + return 0; + } + + /** + * {@inheritDoc} + * + * The upper bound of the support is always 1 no matter the parameters. + * + * @return upper bound of the support (always 1) + */ + @Override + public double getSupportUpperBound() { + return 1; + } + + /** + * {@inheritDoc} + * + * For first shape parameter s1 and + * second shape parameter s2, the mean is + * s1 / (s1 + s2) + * + * @return {@inheritDoc} + */ + @Override + protected double calculateNumericalMean() { + final double alpha = getAlpha(); + return alpha / (alpha + getBeta()); + } + + /** + * {@inheritDoc} + * + * For first shape parameter s1 and + * second shape parameter s2, + * the variance is + * [ s1 * s2 ] / [ (s1 + s2)^2 * (s1 + s2 + 1) ] + * + * @return {@inheritDoc} + */ + @Override + protected double calculateNumericalVariance() { + final double alpha = getAlpha(); + final double beta = getBeta(); + final double alphabetasum = alpha + beta; + return (alpha * beta) / ((alphabetasum * alphabetasum) * (alphabetasum + 1)); + } + + @Override + public boolean isSupportLowerBoundInclusive() { + return false; + } + + @Override + public boolean isSupportUpperBoundInclusive() { + return false; + } } diff --git a/src/main/java/org/apache/commons/math/distribution/BinomialDistributionImpl.java b/src/main/java/org/apache/commons/math/distribution/BinomialDistributionImpl.java index a75b1f53a..dcea662de 100644 --- a/src/main/java/org/apache/commons/math/distribution/BinomialDistributionImpl.java +++ b/src/main/java/org/apache/commons/math/distribution/BinomialDistributionImpl.java @@ -164,4 +164,58 @@ public class BinomialDistributionImpl extends AbstractIntegerDistribution // use default bisection impl return super.inverseCumulativeProbability(p); } + + /** + * {@inheritDoc} + * + * The lower bound of the support is always 0 no matter the number of trials + * and probability parameter. + * + * @return lower bound of the support (always 0) + */ + @Override + public int getSupportLowerBound() { + return 0; + } + + /** + * {@inheritDoc} + * + * The upper bound of the support is the number of trials. + * + * @return upper bound of the support (equal to number of trials) + */ + @Override + public int getSupportUpperBound() { + return getNumberOfTrials(); + } + + /** + * {@inheritDoc} + * + * For n number of trials and + * probability parameter p, the mean is + * n * p + * + * @return {@inheritDoc} + */ + @Override + protected double calculateNumericalMean() { + return (double)getNumberOfTrials() * getProbabilityOfSuccess(); + } + + /** + * {@inheritDoc} + * + * For n number of trials and + * probability parameter p, the variance is + * n * p * (1 - p) + * + * @return {@inheritDoc} + */ + @Override + protected double calculateNumericalVariance() { + final double p = getProbabilityOfSuccess(); + return (double)getNumberOfTrials() * p * (1 - p); + } } diff --git a/src/main/java/org/apache/commons/math/distribution/CauchyDistributionImpl.java b/src/main/java/org/apache/commons/math/distribution/CauchyDistributionImpl.java index 7d13c8afd..b67fc2236 100644 --- a/src/main/java/org/apache/commons/math/distribution/CauchyDistributionImpl.java +++ b/src/main/java/org/apache/commons/math/distribution/CauchyDistributionImpl.java @@ -163,7 +163,7 @@ public class CauchyDistributionImpl extends AbstractContinuousDistribution } return ret; - } + } /** * Access the domain value upper bound, based on p, used to @@ -220,4 +220,64 @@ public class CauchyDistributionImpl extends AbstractContinuousDistribution protected double getSolverAbsoluteAccuracy() { return solverAbsoluteAccuracy; } + + /** + * {@inheritDoc} + * + * The lower bound of the support is always negative infinity no matter + * the parameters. + * + * @return lower bound of the support (always Double.NEGATIVE_INFINITY) + */ + @Override + public double getSupportLowerBound() { + return Double.NEGATIVE_INFINITY; + } + + /** + * {@inheritDoc} + * + * The upper bound of the support is always positive infinity no matter + * the parameters. + * + * @return upper bound of the support (always Double.POSITIVE_INFINITY) + */ + @Override + public double getSupportUpperBound() { + return Double.POSITIVE_INFINITY; + } + + /** + * {@inheritDoc} + * + * The mean is always undefined no matter the parameters. + * + * @return mean (always Double.NaN) + */ + @Override + protected double calculateNumericalMean() { + return Double.NaN; + } + + /** + * {@inheritDoc} + * + * The variance is always undefined no matter the parameters. + * + * @return variance (always Double.NaN) + */ + @Override + protected double calculateNumericalVariance() { + return Double.NaN; + } + + @Override + public boolean isSupportLowerBoundInclusive() { + return false; + } + + @Override + public boolean isSupportUpperBoundInclusive() { + return false; + } } diff --git a/src/main/java/org/apache/commons/math/distribution/ChiSquaredDistributionImpl.java b/src/main/java/org/apache/commons/math/distribution/ChiSquaredDistributionImpl.java index 7a78be737..2ea2fe3b4 100644 --- a/src/main/java/org/apache/commons/math/distribution/ChiSquaredDistributionImpl.java +++ b/src/main/java/org/apache/commons/math/distribution/ChiSquaredDistributionImpl.java @@ -193,4 +193,66 @@ public class ChiSquaredDistributionImpl protected double getSolverAbsoluteAccuracy() { return solverAbsoluteAccuracy; } + + /** + * {@inheritDoc} + * + * The lower bound of the support is always 0 no matter the + * degrees of freedom. + * + * @return lower bound of the support (always 0) + */ + @Override + public double getSupportLowerBound() { + return 0; + } + + /** + * {@inheritDoc} + * + * The upper bound of the support is always positive infinity no matter the + * degrees of freedom. + * + * @return upper bound of the support (always Double.POSITIVE_INFINITY) + */ + @Override + public double getSupportUpperBound() { + return Double.POSITIVE_INFINITY; + } + + /** + * {@inheritDoc} + * + * For k degrees of freedom, the mean is + * k + * + * @return {@inheritDoc} + */ + @Override + protected double calculateNumericalMean() { + return getDegreesOfFreedom(); + } + + /** + * {@inheritDoc} + * + * For k degrees of freedom, the variance is + * 2 * k + * + * @return {@inheritDoc} + */ + @Override + protected double calculateNumericalVariance() { + return 2*getDegreesOfFreedom(); + } + + @Override + public boolean isSupportLowerBoundInclusive() { + return true; + } + + @Override + public boolean isSupportUpperBoundInclusive() { + return false; + } } diff --git a/src/main/java/org/apache/commons/math/distribution/Distribution.java b/src/main/java/org/apache/commons/math/distribution/Distribution.java index fda80033b..3edc3a4d2 100644 --- a/src/main/java/org/apache/commons/math/distribution/Distribution.java +++ b/src/main/java/org/apache/commons/math/distribution/Distribution.java @@ -52,4 +52,59 @@ public interface Distribution { * @throws IllegalArgumentException if x0 > x1 */ double cumulativeProbability(double x0, double x1) throws MathException; + + /** + * Use this method to get the numerical value of the mean of this + * distribution. + * + * @return the mean or Double.NaN if it's not defined + */ + double getNumericalMean(); + + /** + * Use this method to get the numerical value of the variance of this + * distribution. + * + * @return the variance (possibly Double.POSITIVE_INFINITY as + * for certain cases in {@link TDistributionImpl}) or + * Double.NaN if it's not defined + */ + double getNumericalVariance(); + + /** + * Use this method to get information about whether the lower bound + * of the support is inclusive or not. + * + * @return whether the lower bound of the support is inclusive or not + */ + boolean isSupportLowerBoundInclusive(); + + /** + * Use this method to get information about whether the upper bound + * of the support is inclusive or not. + * + * @return whether the upper bound of the support is inclusive or not + */ + boolean isSupportUpperBoundInclusive(); + + /** + * Use this method to get information about whether the support is connected, + * i.e. whether all values between the lower and upper bound of the support + * is included in the support. + * + * For {@link AbstractIntegerDistribution} the support is discrete, so + * if this is true, then the support is + * {lower bound, lower bound + 1, ..., upper bound}. + * + * For {@link AbstractContinuousDistribution} the support is continuous, so + * if this is true, then the support is the interval + * [lower bound, upper bound] + * where the limits are inclusive or not according to + * {@link #isSupportLowerBoundInclusive()} and {@link #isSupportUpperBoundInclusive()} + * (in the example both are true). If both are false, then the support is the interval + * (lower bound, upper bound) + * + * @return whether the support limits given by subclassed methods are connected or not + */ + boolean isSupportConnected(); } diff --git a/src/main/java/org/apache/commons/math/distribution/ExponentialDistributionImpl.java b/src/main/java/org/apache/commons/math/distribution/ExponentialDistributionImpl.java index 5782c0462..1e685d499 100644 --- a/src/main/java/org/apache/commons/math/distribution/ExponentialDistributionImpl.java +++ b/src/main/java/org/apache/commons/math/distribution/ExponentialDistributionImpl.java @@ -222,4 +222,66 @@ public class ExponentialDistributionImpl extends AbstractContinuousDistribution protected double getSolverAbsoluteAccuracy() { return solverAbsoluteAccuracy; } + + /** + * {@inheritDoc} + * + * The lower bound of the support is always 0 no matter the mean parameter. + * + * @return lower bound of the support (always 0) + */ + @Override + public double getSupportLowerBound() { + return 0; + } + + /** + * {@inheritDoc} + * + * The upper bound of the support is always positive infinity + * no matter the mean parameter. + * + * @return upper bound of the support (always Double.POSITIVE_INFINITY) + */ + @Override + public double getSupportUpperBound() { + return Double.POSITIVE_INFINITY; + } + + /** + * {@inheritDoc} + * + * For mean parameter k, the mean is + * k + * + * @return {@inheritDoc} + */ + @Override + protected double calculateNumericalMean() { + return getMean(); + } + + /** + * {@inheritDoc} + * + * For mean parameter k, the variance is + * k^2 + * + * @return {@inheritDoc} + */ + @Override + protected double calculateNumericalVariance() { + final double mean = getMean(); + return mean * mean; + } + + @Override + public boolean isSupportLowerBoundInclusive() { + return true; + } + + @Override + public boolean isSupportUpperBoundInclusive() { + return false; + } } diff --git a/src/main/java/org/apache/commons/math/distribution/FDistributionImpl.java b/src/main/java/org/apache/commons/math/distribution/FDistributionImpl.java index 8fdf19ebe..88fd82b08 100644 --- a/src/main/java/org/apache/commons/math/distribution/FDistributionImpl.java +++ b/src/main/java/org/apache/commons/math/distribution/FDistributionImpl.java @@ -235,4 +235,93 @@ public class FDistributionImpl protected double getSolverAbsoluteAccuracy() { return solverAbsoluteAccuracy; } + + /** + * {@inheritDoc} + * + * The lower bound of the support is always 0 no matter the parameters. + * + * @return lower bound of the support (always 0) + */ + @Override + public double getSupportLowerBound() { + return 0; + } + + /** + * {@inheritDoc} + * + * The upper bound of the support is always positive infinity + * no matter the parameters. + * + * @return upper bound of the support (always Double.POSITIVE_INFINITY) + */ + @Override + public double getSupportUpperBound() { + return Double.POSITIVE_INFINITY; + } + + /** + * {@inheritDoc} + * + * For denominator degrees of freedom parameter b, + * the mean is + * + * + * @return {@inheritDoc} + */ + @Override + protected double calculateNumericalMean() { + final double denominatorDF = getDenominatorDegreesOfFreedom(); + + if (denominatorDF > 2) { + return denominatorDF / (denominatorDF - 2); + } + + return Double.NaN; + } + + /** + * {@inheritDoc} + * + * For numerator degrees of freedom parameter a + * and denominator degrees of freedom parameter b, + * the variance is + * + * + * @return {@inheritDoc} + */ + @Override + protected double calculateNumericalVariance() { + final double denominatorDF = getDenominatorDegreesOfFreedom(); + + if (denominatorDF > 4) { + final double numeratorDF = getNumeratorDegreesOfFreedom(); + final double denomDFMinusTwo = denominatorDF - 2; + + return ( 2 * (denominatorDF * denominatorDF) * (numeratorDF + denominatorDF - 2) ) + / ( (numeratorDF * (denomDFMinusTwo * denomDFMinusTwo) * (denominatorDF - 4)) ); + } + + return Double.NaN; + } + + @Override + public boolean isSupportLowerBoundInclusive() { + return true; + } + + @Override + public boolean isSupportUpperBoundInclusive() { + return false; + } } diff --git a/src/main/java/org/apache/commons/math/distribution/GammaDistributionImpl.java b/src/main/java/org/apache/commons/math/distribution/GammaDistributionImpl.java index cc6f66ac7..864161c13 100644 --- a/src/main/java/org/apache/commons/math/distribution/GammaDistributionImpl.java +++ b/src/main/java/org/apache/commons/math/distribution/GammaDistributionImpl.java @@ -237,4 +237,68 @@ public class GammaDistributionImpl extends AbstractContinuousDistribution protected double getSolverAbsoluteAccuracy() { return solverAbsoluteAccuracy; } + + /** + * {@inheritDoc} + * + * The lower bound of the support is always 0 no matter the parameters. + * + * @return lower bound of the support (always 0) + */ + @Override + public double getSupportLowerBound() { + return 0; + } + + /** + * {@inheritDoc} + * + * The upper bound of the support is always positive infinity + * no matter the parameters. + * + * @return upper bound of the support (always Double.POSITIVE_INFINITY) + */ + @Override + public double getSupportUpperBound() { + return Double.POSITIVE_INFINITY; + } + + /** + * {@inheritDoc} + * + * For shape parameter alpha and scale + * parameter beta, the mean is + * alpha * beta + * + * @return {@inheritDoc} + */ + @Override + protected double calculateNumericalMean() { + return getAlpha() * getBeta(); + } + + /** + * {@inheritDoc} + * + * For shape parameter alpha and scale + * parameter beta, the variance is + * alpha * beta^2 + * + * @return {@inheritDoc} + */ + @Override + protected double calculateNumericalVariance() { + final double beta = getBeta(); + return getAlpha() * beta * beta; + } + + @Override + public boolean isSupportLowerBoundInclusive() { + return true; + } + + @Override + public boolean isSupportUpperBoundInclusive() { + return false; + } } diff --git a/src/main/java/org/apache/commons/math/distribution/HypergeometricDistributionImpl.java b/src/main/java/org/apache/commons/math/distribution/HypergeometricDistributionImpl.java index 9fca2f2bb..0c7fb5ca1 100644 --- a/src/main/java/org/apache/commons/math/distribution/HypergeometricDistributionImpl.java +++ b/src/main/java/org/apache/commons/math/distribution/HypergeometricDistributionImpl.java @@ -284,4 +284,69 @@ public class HypergeometricDistributionImpl extends AbstractIntegerDistribution } return ret; } + + /** + * {@inheritDoc} + * + * For population size N, + * number of successes m, and + * sample size n, + * the lower bound of the support is + * max(0, n + m - N) + * + * @return lower bound of the support + */ + @Override + public int getSupportLowerBound() { + return FastMath.max(0, + getSampleSize() + getNumberOfSuccesses() - getPopulationSize()); + } + + /** + * {@inheritDoc} + * + * For number of successes m and + * sample size n, + * the upper bound of the support is + * min(m, n) + * + * @return upper bound of the support + */ + @Override + public int getSupportUpperBound() { + return FastMath.min(getNumberOfSuccesses(), getSampleSize()); + } + + /** + * {@inheritDoc} + * + * For population size N, + * number of successes m, and + * sample size n, the mean is + * n * m / N + * + * @return {@inheritDoc} + */ + @Override + protected double calculateNumericalMean() { + return (double)(getSampleSize() * getNumberOfSuccesses()) / (double)getPopulationSize(); + } + + /** + * {@inheritDoc} + * + * For population size N, + * number of successes m, and + * sample size n, the variance is + * [ n * m * (N - n) * (N - m) ] / [ N^2 * (N - 1) ] + * + * @return {@inheritDoc} + */ + @Override + protected double calculateNumericalVariance() { + final double N = getPopulationSize(); + final double m = getNumberOfSuccesses(); + final double n = getSampleSize(); + return ( n * m * (N - n) * (N - m) ) / ( (N*N * (N - 1)) ); + } } diff --git a/src/main/java/org/apache/commons/math/distribution/NormalDistributionImpl.java b/src/main/java/org/apache/commons/math/distribution/NormalDistributionImpl.java index 4f3a618d8..7a5bec6df 100644 --- a/src/main/java/org/apache/commons/math/distribution/NormalDistributionImpl.java +++ b/src/main/java/org/apache/commons/math/distribution/NormalDistributionImpl.java @@ -241,4 +241,66 @@ public class NormalDistributionImpl extends AbstractContinuousDistribution return ret; } + + /** + * {@inheritDoc} + * + * The lower bound of the support is always negative infinity + * no matter the parameters. + * + * @return lower bound of the support (always Double.NEGATIVE_INFINITY) + */ + @Override + public double getSupportLowerBound() { + return Double.NEGATIVE_INFINITY; + } + + /** + * {@inheritDoc} + * + * The upper bound of the support is always positive infinity + * no matter the parameters. + * + * @return upper bound of the support (always Double.POSITIVE_INFINITY) + */ + @Override + public double getSupportUpperBound() { + return Double.POSITIVE_INFINITY; + } + + /** + * {@inheritDoc} + * + * For mean parameter mu, the mean is mu + * + * @return {@inheritDoc} + */ + @Override + protected double calculateNumericalMean() { + return getMean(); + } + + /** + * {@inheritDoc} + * + * For standard deviation parameter s, + * the variance is s^2 + * + * @return {@inheritDoc} + */ + @Override + protected double calculateNumericalVariance() { + final double s = getStandardDeviation(); + return s * s; + } + + @Override + public boolean isSupportLowerBoundInclusive() { + return false; + } + + @Override + public boolean isSupportUpperBoundInclusive() { + return false; + } } diff --git a/src/main/java/org/apache/commons/math/distribution/PascalDistributionImpl.java b/src/main/java/org/apache/commons/math/distribution/PascalDistributionImpl.java index 3f2d7dd1e..9e7029fd7 100644 --- a/src/main/java/org/apache/commons/math/distribution/PascalDistributionImpl.java +++ b/src/main/java/org/apache/commons/math/distribution/PascalDistributionImpl.java @@ -165,4 +165,69 @@ public class PascalDistributionImpl extends AbstractIntegerDistribution return ret; } + + /** + * {@inheritDoc} + * + * The lower bound of the support is always 0 no matter the parameters. + * + * @return lower bound of the support (always 0) + */ + @Override + public int getSupportLowerBound() { + return 0; + } + + /** + * {@inheritDoc} + * + * The upper bound of the support is always positive infinity + * no matter the parameters. Positive infinity is symbolised + * by Integer.MAX_VALUE together with + * {@link #isSupportUpperBoundInclusive()} being false + * + * @return upper bound of the support (always Integer.MAX_VALUE for positive infinity) + */ + @Override + public int getSupportUpperBound() { + return Integer.MAX_VALUE; + } + + /** + * {@inheritDoc} + * + * For number of successes r and + * probability of success p, the mean is + * ( r * p ) / ( 1 - p ) + * + * @return {@inheritDoc} + */ + @Override + protected double calculateNumericalMean() { + final double p = getProbabilityOfSuccess(); + final double r = getNumberOfSuccesses(); + return ( r * p ) / ( 1 - p ); + } + + /** + * {@inheritDoc} + * + * For number of successes r and + * probability of success p, the mean is + * ( r * p ) / ( 1 - p )^2 + * + * @return {@inheritDoc} + */ + @Override + protected double calculateNumericalVariance() { + final double p = getProbabilityOfSuccess(); + final double r = getNumberOfSuccesses(); + final double pInv = 1 - p; + return ( r * p ) / (pInv * pInv); + } + + @Override + public boolean isSupportUpperBoundInclusive() { + return false; + } } diff --git a/src/main/java/org/apache/commons/math/distribution/PoissonDistributionImpl.java b/src/main/java/org/apache/commons/math/distribution/PoissonDistributionImpl.java index 35261f5f7..688850c13 100644 --- a/src/main/java/org/apache/commons/math/distribution/PoissonDistributionImpl.java +++ b/src/main/java/org/apache/commons/math/distribution/PoissonDistributionImpl.java @@ -230,4 +230,60 @@ public class PoissonDistributionImpl extends AbstractIntegerDistribution protected int getDomainUpperBound(double p) { return Integer.MAX_VALUE; } + + /** + * {@inheritDoc} + * + * The lower bound of the support is always 0 no matter the mean parameter. + * + * @return lower bound of the support (always 0) + */ + @Override + public int getSupportLowerBound() { + return 0; + } + + /** + * {@inheritDoc} + * + * The upper bound of the support is positive infinity, + * regardless of the parameter values. There is no integer infinity, + * so this method returns Integer.MAX_VALUE and + * {@link #isSupportUpperBoundInclusive()} returns true. + * + * @return upper bound of the support (always Integer.MAX_VALUE for positive infinity) + */ + @Override + public int getSupportUpperBound() { + return Integer.MAX_VALUE; + } + + /** + * {@inheritDoc} + * + * For mean parameter p, the mean is p + * + * @return {@inheritDoc} + */ + @Override + protected double calculateNumericalMean() { + return getMean(); + } + + /** + * {@inheritDoc} + * + * For mean parameter p, the variance is p + * + * @return {@inheritDoc} + */ + @Override + protected double calculateNumericalVariance() { + return getMean(); + } + + @Override + public boolean isSupportUpperBoundInclusive() { + return true; + } } diff --git a/src/main/java/org/apache/commons/math/distribution/TDistributionImpl.java b/src/main/java/org/apache/commons/math/distribution/TDistributionImpl.java index 3b0daadb2..1255a2b6f 100644 --- a/src/main/java/org/apache/commons/math/distribution/TDistributionImpl.java +++ b/src/main/java/org/apache/commons/math/distribution/TDistributionImpl.java @@ -199,4 +199,89 @@ public class TDistributionImpl protected double getSolverAbsoluteAccuracy() { return solverAbsoluteAccuracy; } + + /** + * {@inheritDoc} + * + * The lower bound of the support is always negative infinity + * no matter the parameters. + * + * @return lower bound of the support (always Double.NEGATIVE_INFINITY) + */ + @Override + public double getSupportLowerBound() { + return Double.NEGATIVE_INFINITY; + } + + /** + * {@inheritDoc} + * + * The upper bound of the support is always positive infinity + * no matter the parameters. + * + * @return upper bound of the support (always Double.POSITIVE_INFINITY) + */ + @Override + public double getSupportUpperBound() { + return Double.POSITIVE_INFINITY; + } + + /** + * {@inheritDoc} + * + * For degrees of freedom parameter df, the mean is + * + * + * @return {@inheritDoc} + */ + @Override + protected double calculateNumericalMean() { + final double df = getDegreesOfFreedom(); + + if (df > 1) { + return 0; + } + + return Double.NaN; + } + + /** + * {@inheritDoc} + * + * For degrees of freedom parameter df, the variance is + * + * + * @return {@inheritDoc} + */ + @Override + protected double calculateNumericalVariance() { + final double df = getDegreesOfFreedom(); + + if (df > 2) { + return df / (df - 2); + } + + if (df > 1 && df <= 2) { + return Double.POSITIVE_INFINITY; + } + + return Double.NaN; + } + + @Override + public boolean isSupportLowerBoundInclusive() { + return false; + } + + @Override + public boolean isSupportUpperBoundInclusive() { + return false; + } } diff --git a/src/main/java/org/apache/commons/math/distribution/WeibullDistributionImpl.java b/src/main/java/org/apache/commons/math/distribution/WeibullDistributionImpl.java index ff899678e..a096ffbf7 100644 --- a/src/main/java/org/apache/commons/math/distribution/WeibullDistributionImpl.java +++ b/src/main/java/org/apache/commons/math/distribution/WeibullDistributionImpl.java @@ -22,6 +22,7 @@ import java.io.Serializable; import org.apache.commons.math.exception.OutOfRangeException; import org.apache.commons.math.exception.NotStrictlyPositiveException; import org.apache.commons.math.exception.util.LocalizedFormats; +import org.apache.commons.math.special.Gamma; import org.apache.commons.math.util.FastMath; /** @@ -215,4 +216,75 @@ public class WeibullDistributionImpl extends AbstractContinuousDistribution protected double getSolverAbsoluteAccuracy() { return solverAbsoluteAccuracy; } + + /** + * {@inheritDoc} + * + * The lower bound of the support is always 0 no matter the parameters. + * + * @return lower bound of the support (always 0) + */ + @Override + public double getSupportLowerBound() { + return 0; + } + + /** + * {@inheritDoc} + * + * The upper bound of the support is always positive infinity + * no matter the parameters. + * + * @return upper bound of the support (always Double.POSITIVE_INFINITY) + */ + @Override + public double getSupportUpperBound() { + return Double.POSITIVE_INFINITY; + } + + /** + * {@inheritDoc} + * + * The mean is scale * Gamma(1 + (1 / shape)) + * where Gamma(...) is the Gamma-function + * + * @return {@inheritDoc} + */ + @Override + protected double calculateNumericalMean() { + final double shape = getShape(); + final double scale = getScale(); + + return scale * FastMath.exp(Gamma.logGamma(1 + (1 / shape))); + } + + /** + * {@inheritDoc} + * + * The variance is + * scale^2 * Gamma(1 + (2 / shape)) - mean^2 + * where Gamma(...) is the Gamma-function + * + * @return {@inheritDoc} + */ + @Override + protected double calculateNumericalVariance() { + final double shape = getShape(); + final double scale = getScale(); + final double mean = getNumericalMean(); + + return (scale * scale) * + FastMath.exp(Gamma.logGamma(1 + (2 / shape))) - + (mean * mean); + } + + @Override + public boolean isSupportLowerBoundInclusive() { + return true; + } + + @Override + public boolean isSupportUpperBoundInclusive() { + return false; + } } diff --git a/src/main/java/org/apache/commons/math/distribution/ZipfDistributionImpl.java b/src/main/java/org/apache/commons/math/distribution/ZipfDistributionImpl.java index 928ae8514..40e793017 100644 --- a/src/main/java/org/apache/commons/math/distribution/ZipfDistributionImpl.java +++ b/src/main/java/org/apache/commons/math/distribution/ZipfDistributionImpl.java @@ -147,4 +147,76 @@ public class ZipfDistributionImpl extends AbstractIntegerDistribution } return value; } + + /** + * {@inheritDoc} + * + * The lower bound of the support is always 1 no matter the parameters. + * + * @return lower bound of the support (always 1) + */ + @Override + public int getSupportLowerBound() { + return 1; + } + + /** + * {@inheritDoc} + * + * The upper bound of the support is the number of elements + * + * @return upper bound of the support + */ + @Override + public int getSupportUpperBound() { + return getNumberOfElements(); + } + + /** + * {@inheritDoc} + * + * For number of elements N and exponent s, the mean is + * Hs1 / Hs where + * + * + * @return {@inheritDoc} + */ + @Override + protected double calculateNumericalMean() { + final int N = getNumberOfElements(); + final double s = getExponent(); + + final double Hs1 = generalizedHarmonic(N, s - 1); + final double Hs = generalizedHarmonic(N, s); + + return Hs1 / Hs; + } + + /** + * {@inheritDoc} + * + * For number of elements N and exponent s, the mean is + * (Hs2 / Hs) - (Hs1^2 / Hs^2) where + * + * + * @return {@inheritDoc} + */ + @Override + protected double calculateNumericalVariance() { + final int N = getNumberOfElements(); + final double s = getExponent(); + + final double Hs2 = generalizedHarmonic(N, s - 2); + final double Hs1 = generalizedHarmonic(N, s - 1); + final double Hs = generalizedHarmonic(N, s); + + return (Hs2 / Hs) - ((Hs1 * Hs1) / (Hs * Hs)); + } } diff --git a/src/test/java/org/apache/commons/math/distribution/BetaDistributionTest.java b/src/test/java/org/apache/commons/math/distribution/BetaDistributionTest.java index 5faac01ce..60c12be00 100644 --- a/src/test/java/org/apache/commons/math/distribution/BetaDistributionTest.java +++ b/src/test/java/org/apache/commons/math/distribution/BetaDistributionTest.java @@ -18,6 +18,7 @@ package org.apache.commons.math.distribution; import junit.framework.TestCase; import org.apache.commons.math.MathException; +import org.apache.commons.math.util.FastMath; public class BetaDistributionTest extends TestCase { public void testCumulative() throws MathException { @@ -286,4 +287,17 @@ public class BetaDistributionTest extends TestCase { assertEquals(String.format("density at x=%.1f for alpha=%.1f, beta=%.1f", x[i], alpha, beta), expected[i], d.density(x[i]), 1e-5); } } + + public void testMomonts() { + final double tol = 1e-9; + BetaDistribution dist; + + dist = new BetaDistributionImpl(1, 1); + assertEquals(dist.getNumericalMean(), 0.5, tol); + assertEquals(dist.getNumericalVariance(), 1.0 / 12.0, tol); + + dist = new BetaDistributionImpl(2, 5); + assertEquals(dist.getNumericalMean(), 2.0 / 7.0, tol); + assertEquals(dist.getNumericalVariance(), 10.0 / (49.0 * 8.0), tol); + } } diff --git a/src/test/java/org/apache/commons/math/distribution/BinomialDistributionTest.java b/src/test/java/org/apache/commons/math/distribution/BinomialDistributionTest.java index c6073670d..95da3f7d6 100644 --- a/src/test/java/org/apache/commons/math/distribution/BinomialDistributionTest.java +++ b/src/test/java/org/apache/commons/math/distribution/BinomialDistributionTest.java @@ -113,4 +113,17 @@ public class BinomialDistributionTest extends IntegerDistributionAbstractTest { verifyInverseCumulativeProbabilities(); } + public void testMomonts() { + final double tol = 1e-9; + BinomialDistribution dist; + + dist = new BinomialDistributionImpl(10, 0.5); + assertEquals(dist.getNumericalMean(), 10d * 0.5d, tol); + assertEquals(dist.getNumericalVariance(), 10d * 0.5d * 0.5d, tol); + + dist = new BinomialDistributionImpl(30, 0.3); + assertEquals(dist.getNumericalMean(), 30d * 0.3d, tol); + assertEquals(dist.getNumericalVariance(), 30d * 0.3d * (1d - 0.3d), tol); + } + } diff --git a/src/test/java/org/apache/commons/math/distribution/CauchyDistributionTest.java b/src/test/java/org/apache/commons/math/distribution/CauchyDistributionTest.java index 2ca88611f..9fee30228 100644 --- a/src/test/java/org/apache/commons/math/distribution/CauchyDistributionTest.java +++ b/src/test/java/org/apache/commons/math/distribution/CauchyDistributionTest.java @@ -107,4 +107,17 @@ public class CauchyDistributionTest extends ContinuousDistributionAbstractTest // Expected. } } + + public void testMomonts() { + final double tol = 1e-9; + CauchyDistribution dist; + + dist = new CauchyDistributionImpl(10.2, 0.15); + assertEquals(dist.getNumericalMean(), Double.NaN, tol); + assertEquals(dist.getNumericalVariance(), Double.NaN, tol); + + dist = new CauchyDistributionImpl(23.12, 2.12); + assertEquals(dist.getNumericalMean(), Double.NaN, tol); + assertEquals(dist.getNumericalVariance(), Double.NaN, tol); + } } diff --git a/src/test/java/org/apache/commons/math/distribution/ChiSquareDistributionTest.java b/src/test/java/org/apache/commons/math/distribution/ChiSquareDistributionTest.java index a24207d09..40b232f63 100644 --- a/src/test/java/org/apache/commons/math/distribution/ChiSquareDistributionTest.java +++ b/src/test/java/org/apache/commons/math/distribution/ChiSquareDistributionTest.java @@ -124,4 +124,17 @@ public class ChiSquareDistributionTest extends ContinuousDistributionAbstractTes } } + public void testMomonts() { + final double tol = 1e-9; + ChiSquaredDistribution dist; + + dist = new ChiSquaredDistributionImpl(1500); + assertEquals(dist.getNumericalMean(), 1500, tol); + assertEquals(dist.getNumericalVariance(), 3000, tol); + + dist = new ChiSquaredDistributionImpl(1.12); + assertEquals(dist.getNumericalMean(), 1.12, tol); + assertEquals(dist.getNumericalVariance(), 2.24, tol); + } + } diff --git a/src/test/java/org/apache/commons/math/distribution/ExponentialDistributionTest.java b/src/test/java/org/apache/commons/math/distribution/ExponentialDistributionTest.java index d7ae22051..6db45ceab 100644 --- a/src/test/java/org/apache/commons/math/distribution/ExponentialDistributionTest.java +++ b/src/test/java/org/apache/commons/math/distribution/ExponentialDistributionTest.java @@ -122,4 +122,17 @@ public class ExponentialDistributionTest extends ContinuousDistributionAbstractT // Expected. } } + + public void testMomonts() { + final double tol = 1e-9; + ExponentialDistribution dist; + + dist = new ExponentialDistributionImpl(11d); + assertEquals(dist.getNumericalMean(), 11d, tol); + assertEquals(dist.getNumericalVariance(), 11d * 11d, tol); + + dist = new ExponentialDistributionImpl(10.5d); + assertEquals(dist.getNumericalMean(), 10.5d, tol); + assertEquals(dist.getNumericalVariance(), 10.5d * 10.5d, tol); + } } diff --git a/src/test/java/org/apache/commons/math/distribution/FDistributionTest.java b/src/test/java/org/apache/commons/math/distribution/FDistributionTest.java index aef67aa6f..1e42de7d4 100644 --- a/src/test/java/org/apache/commons/math/distribution/FDistributionTest.java +++ b/src/test/java/org/apache/commons/math/distribution/FDistributionTest.java @@ -124,4 +124,21 @@ public class FDistributionTest extends ContinuousDistributionAbstractTest { x = fd.inverseCumulativeProbability(p); assertEquals(0.975, x, 1.0e-5); } + + public void testMomonts() { + final double tol = 1e-9; + FDistribution dist; + + dist = new FDistributionImpl(1, 2); + assertEquals(dist.getNumericalMean(), Double.NaN, tol); + assertEquals(dist.getNumericalVariance(), Double.NaN, tol); + + dist = new FDistributionImpl(1, 3); + assertEquals(dist.getNumericalMean(), 3d / (3d - 2d), tol); + assertEquals(dist.getNumericalVariance(), Double.NaN, tol); + + dist = new FDistributionImpl(1, 5); + assertEquals(dist.getNumericalMean(), 5d / (5d - 2d), tol); + assertEquals(dist.getNumericalVariance(), (2d * 5d * 5d * 4d) / 9d, tol); + } } diff --git a/src/test/java/org/apache/commons/math/distribution/GammaDistributionTest.java b/src/test/java/org/apache/commons/math/distribution/GammaDistributionTest.java index c9205d059..f3518cc86 100644 --- a/src/test/java/org/apache/commons/math/distribution/GammaDistributionTest.java +++ b/src/test/java/org/apache/commons/math/distribution/GammaDistributionTest.java @@ -153,4 +153,17 @@ public class GammaDistributionTest extends ContinuousDistributionAbstractTest { setInverseCumulativeTestValues(new double[] {0, Double.POSITIVE_INFINITY}); verifyInverseCumulativeProbabilities(); } + + public void testMomonts() { + final double tol = 1e-9; + GammaDistribution dist; + + dist = new GammaDistributionImpl(1, 2); + assertEquals(dist.getNumericalMean(), 2, tol); + assertEquals(dist.getNumericalVariance(), 4, tol); + + dist = new GammaDistributionImpl(1.1, 4.2); + assertEquals(dist.getNumericalMean(), 1.1d * 4.2d, tol); + assertEquals(dist.getNumericalVariance(), 1.1d * 4.2d * 4.2d, tol); + } } diff --git a/src/test/java/org/apache/commons/math/distribution/HypergeometricDistributionTest.java b/src/test/java/org/apache/commons/math/distribution/HypergeometricDistributionTest.java index e310b42a5..350cbfad5 100644 --- a/src/test/java/org/apache/commons/math/distribution/HypergeometricDistributionTest.java +++ b/src/test/java/org/apache/commons/math/distribution/HypergeometricDistributionTest.java @@ -242,4 +242,17 @@ public class HypergeometricDistributionTest extends IntegerDistributionAbstractT }; testHypergeometricDistributionProbabilities(populationSize, sampleSize, numberOfSucceses, data); } + + public void testMomonts() { + final double tol = 1e-9; + HypergeometricDistribution dist; + + dist = new HypergeometricDistributionImpl(1500, 40, 100); + assertEquals(dist.getNumericalMean(), 40d * 100d / 1500d, tol); + assertEquals(dist.getNumericalVariance(), ( 100d * 40d * (1500d - 100d) * (1500d - 40d) ) / ( (1500d * 1500d * 1499d) ), tol); + + dist = new HypergeometricDistributionImpl(3000, 55, 200); + assertEquals(dist.getNumericalMean(), 55d * 200d / 3000d, tol); + assertEquals(dist.getNumericalVariance(), ( 200d * 55d * (3000d - 200d) * (3000d - 55d) ) / ( (3000d * 3000d * 2999d) ), tol); + } } diff --git a/src/test/java/org/apache/commons/math/distribution/NormalDistributionTest.java b/src/test/java/org/apache/commons/math/distribution/NormalDistributionTest.java index f8ebebf68..ad9e4f571 100644 --- a/src/test/java/org/apache/commons/math/distribution/NormalDistributionTest.java +++ b/src/test/java/org/apache/commons/math/distribution/NormalDistributionTest.java @@ -190,4 +190,20 @@ public class NormalDistributionTest extends ContinuousDistributionAbstractTest assertEquals(2.0, result, defaultTolerance); } + public void testMomonts() { + final double tol = 1e-9; + NormalDistribution dist; + + dist = new NormalDistributionImpl(0, 1); + assertEquals(dist.getNumericalMean(), 0, tol); + assertEquals(dist.getNumericalVariance(), 1, tol); + + dist = new NormalDistributionImpl(2.2, 1.4); + assertEquals(dist.getNumericalMean(), 2.2, tol); + assertEquals(dist.getNumericalVariance(), 1.4 * 1.4, tol); + + dist = new NormalDistributionImpl(-2000.9, 10.4); + assertEquals(dist.getNumericalMean(), -2000.9, tol); + assertEquals(dist.getNumericalVariance(), 10.4 * 10.4, tol); + } } diff --git a/src/test/java/org/apache/commons/math/distribution/PascalDistributionTest.java b/src/test/java/org/apache/commons/math/distribution/PascalDistributionTest.java index fbff95006..2e64a4b42 100644 --- a/src/test/java/org/apache/commons/math/distribution/PascalDistributionTest.java +++ b/src/test/java/org/apache/commons/math/distribution/PascalDistributionTest.java @@ -119,4 +119,17 @@ public class PascalDistributionTest extends IntegerDistributionAbstractTest { verifyCumulativeProbabilities(); verifyInverseCumulativeProbabilities(); } + + public void testMomonts() { + final double tol = 1e-9; + PascalDistribution dist; + + dist = new PascalDistributionImpl(10, 0.5); + assertEquals(dist.getNumericalMean(), ( 10d * 0.5d ) / 0.5d, tol); + assertEquals(dist.getNumericalVariance(), ( 10d * 0.5d ) / (0.5d * 0.5d), tol); + + dist = new PascalDistributionImpl(25, 0.3); + assertEquals(dist.getNumericalMean(), ( 25d * 0.3d ) / 0.7d, tol); + assertEquals(dist.getNumericalVariance(), ( 25d * 0.3d ) / (0.7d * 0.7d), tol); + } } diff --git a/src/test/java/org/apache/commons/math/distribution/PoissonDistributionTest.java b/src/test/java/org/apache/commons/math/distribution/PoissonDistributionTest.java index a02d1bb19..24add9c9c 100644 --- a/src/test/java/org/apache/commons/math/distribution/PoissonDistributionTest.java +++ b/src/test/java/org/apache/commons/math/distribution/PoissonDistributionTest.java @@ -218,4 +218,17 @@ public class PoissonDistributionTest extends IntegerDistributionAbstractTest { mean *= 10.0; } } + + public void testMomonts() { + final double tol = 1e-9; + PoissonDistribution dist; + + dist = new PoissonDistributionImpl(1); + assertEquals(dist.getNumericalMean(), 1, tol); + assertEquals(dist.getNumericalVariance(), 1, tol); + + dist = new PoissonDistributionImpl(11.23); + assertEquals(dist.getNumericalMean(), 11.23, tol); + assertEquals(dist.getNumericalVariance(), 11.23, tol); + } } diff --git a/src/test/java/org/apache/commons/math/distribution/TDistributionTest.java b/src/test/java/org/apache/commons/math/distribution/TDistributionTest.java index c01cc6c9f..d677e30f7 100644 --- a/src/test/java/org/apache/commons/math/distribution/TDistributionTest.java +++ b/src/test/java/org/apache/commons/math/distribution/TDistributionTest.java @@ -118,4 +118,21 @@ public class TDistributionTest extends ContinuousDistributionAbstractTest { // expected } } + + public void testMomonts() { + final double tol = 1e-9; + TDistribution dist; + + dist = new TDistributionImpl(1); + assertEquals(dist.getNumericalMean(), Double.NaN, tol); + assertEquals(dist.getNumericalVariance(), Double.NaN, tol); + + dist = new TDistributionImpl(1.5); + assertEquals(dist.getNumericalMean(), 0, tol); + assertEquals(dist.getNumericalVariance(), Double.POSITIVE_INFINITY, tol); + + dist = new TDistributionImpl(5); + assertEquals(dist.getNumericalMean(), 0, tol); + assertEquals(dist.getNumericalVariance(), 5d / (5d - 2d), tol); + } } diff --git a/src/test/java/org/apache/commons/math/distribution/WeibullDistributionTest.java b/src/test/java/org/apache/commons/math/distribution/WeibullDistributionTest.java index 07eea822f..65d988fb2 100644 --- a/src/test/java/org/apache/commons/math/distribution/WeibullDistributionTest.java +++ b/src/test/java/org/apache/commons/math/distribution/WeibullDistributionTest.java @@ -17,6 +17,8 @@ package org.apache.commons.math.distribution; +import org.apache.commons.math.special.Gamma; +import org.apache.commons.math.util.FastMath; import org.apache.commons.math.exception.NotStrictlyPositiveException; /** @@ -95,4 +97,22 @@ public class WeibullDistributionTest extends ContinuousDistributionAbstractTest // Expected. } } + + public void testMomonts() { + final double tol = 1e-9; + WeibullDistribution dist; + + dist = new WeibullDistributionImpl(2.5, 3.5); + // In R: 3.5*gamma(1+(1/2.5)) (or emperically: mean(rweibull(10000, 2.5, 3.5))) + assertEquals(dist.getNumericalMean(), 3.5 * FastMath.exp(Gamma.logGamma(1 + (1 / 2.5))), tol); + assertEquals(dist.getNumericalVariance(), (3.5 * 3.5) * + FastMath.exp(Gamma.logGamma(1 + (2 / 2.5))) - + (dist.getNumericalMean() * dist.getNumericalMean()), tol); + + dist = new WeibullDistributionImpl(10.4, 2.222); + assertEquals(dist.getNumericalMean(), 2.222 * FastMath.exp(Gamma.logGamma(1 + (1 / 10.4))), tol); + assertEquals(dist.getNumericalVariance(), (2.222 * 2.222) * + FastMath.exp(Gamma.logGamma(1 + (2 / 10.4))) - + (dist.getNumericalMean() * dist.getNumericalMean()), tol); + } } diff --git a/src/test/java/org/apache/commons/math/distribution/ZipfDistributionTest.java b/src/test/java/org/apache/commons/math/distribution/ZipfDistributionTest.java index cc8fbd9dc..f47b578b5 100644 --- a/src/test/java/org/apache/commons/math/distribution/ZipfDistributionTest.java +++ b/src/test/java/org/apache/commons/math/distribution/ZipfDistributionTest.java @@ -19,6 +19,8 @@ package org.apache.commons.math.distribution; import org.apache.commons.math.exception.NotStrictlyPositiveException; +import org.apache.commons.math.util.FastMath; + /** * Test cases for {@link ZipfDistribution}. * Extends IntegerDistributionAbstractTest. See class javadoc for @@ -92,4 +94,13 @@ public class ZipfDistributionTest extends IntegerDistributionAbstractTest { public int[] makeInverseCumulativeTestValues() { return new int[] {0, 0, 0, 0, 0, 0, 1, 9, 9, 9, 8, 7, 10}; } + + public void testMomonts() { + final double tol = 1e-9; + ZipfDistribution dist; + + dist = new ZipfDistributionImpl(2, 0.5); + assertEquals(dist.getNumericalMean(), FastMath.sqrt(2), tol); + assertEquals(dist.getNumericalVariance(), 0.24264068711928521, tol); + } }