MATH-1443: Depend on "Commons Statistics".

Deleted all classes that have a counterpart in "Commons Statistics".
This commit is contained in:
Gilles 2018-01-25 18:36:19 +01:00
parent 3e24c28e68
commit ef84681392
52 changed files with 0 additions and 10236 deletions

View File

@ -1,245 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.exception.NumberIsTooSmallException;
import org.apache.commons.math4.exception.util.LocalizedFormats;
import org.apache.commons.numbers.gamma.RegularizedBeta;
import org.apache.commons.numbers.gamma.LogGamma;
import org.apache.commons.math4.util.FastMath;
import org.apache.commons.rng.UniformRandomProvider;
import org.apache.commons.rng.sampling.distribution.ContinuousSampler;
import org.apache.commons.rng.sampling.distribution.ChengBetaSampler;
/**
* Implements the Beta distribution.
*
* @see <a href="http://en.wikipedia.org/wiki/Beta_distribution">Beta distribution</a>
* @since 2.0 (changed to concrete class in 3.0)
*/
public class BetaDistribution extends AbstractRealDistribution {
/**
* Default inverse cumulative probability accuracy.
* @since 2.1
*/
public static final double DEFAULT_INVERSE_ABSOLUTE_ACCURACY = 1e-9;
/** Serializable version identifier. */
private static final long serialVersionUID = 20160311L;
/** First shape parameter. */
private final double alpha;
/** Second shape parameter. */
private final double beta;
/** Normalizing factor used in density computations.*/
private final double z;
/** Inverse cumulative probability accuracy. */
private final double solverAbsoluteAccuracy;
/**
* Creates a new instance.
*
* @param alpha First shape parameter (must be positive).
* @param beta Second shape parameter (must be positive).
*/
public BetaDistribution(double alpha, double beta) {
this(alpha, beta, DEFAULT_INVERSE_ABSOLUTE_ACCURACY);
}
/**
* Creates a new instance.
*
* @param alpha First shape parameter (must be positive).
* @param beta Second shape parameter (must be positive).
* @param inverseCumAccuracy Maximum absolute error in inverse
* cumulative probability estimates (defaults to
* {@link #DEFAULT_INVERSE_ABSOLUTE_ACCURACY}).
*
* @since 3.1
*/
public BetaDistribution(double alpha,
double beta,
double inverseCumAccuracy) {
this.alpha = alpha;
this.beta = beta;
z = LogGamma.value(alpha) + LogGamma.value(beta) - LogGamma.value(alpha + beta);
solverAbsoluteAccuracy = inverseCumAccuracy;
}
/**
* Access the first shape parameter, {@code alpha}.
*
* @return the first shape parameter.
*/
public double getAlpha() {
return alpha;
}
/**
* Access the second shape parameter, {@code beta}.
*
* @return the second shape parameter.
*/
public double getBeta() {
return beta;
}
/** {@inheritDoc} */
@Override
public double density(double x) {
final double logDensity = logDensity(x);
return logDensity == Double.NEGATIVE_INFINITY ? 0 : FastMath.exp(logDensity);
}
/** {@inheritDoc} **/
@Override
public double logDensity(double x) {
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} */
@Override
public double cumulativeProbability(double x) {
if (x <= 0) {
return 0;
} else if (x >= 1) {
return 1;
} else {
return RegularizedBeta.value(x, alpha, beta);
}
}
/**
* Return the absolute accuracy setting of the solver used to estimate
* inverse cumulative probabilities.
*
* @return the solver absolute accuracy.
* @since 2.1
*/
@Override
protected double getSolverAbsoluteAccuracy() {
return solverAbsoluteAccuracy;
}
/**
* {@inheritDoc}
*
* For first shape parameter {@code alpha} and second shape parameter
* {@code beta}, the mean is {@code alpha / (alpha + beta)}.
*/
@Override
public double getNumericalMean() {
final double a = getAlpha();
return a / (a + getBeta());
}
/**
* {@inheritDoc}
*
* For first shape parameter {@code alpha} and second shape parameter
* {@code beta}, the variance is
* {@code (alpha * beta) / [(alpha + beta)^2 * (alpha + beta + 1)]}.
*/
@Override
public double getNumericalVariance() {
final double a = getAlpha();
final double b = getBeta();
final double alphabetasum = a + b;
return (a * b) / ((alphabetasum * alphabetasum) * (alphabetasum + 1));
}
/**
* {@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}
*
* The support of this distribution is connected.
*
* @return {@code true}
*/
@Override
public boolean isSupportConnected() {
return true;
}
/**
* {@inheritDoc}
*
* Sampling is performed using Cheng's algorithm:
* <blockquote>
* <pre>
* R. C. H. Cheng,
* "Generating beta variates with nonintegral shape parameters",
* Communications of the ACM, 21, 317-322, 1978.
* </pre>
* </blockquote>
*/
@Override
public RealDistribution.Sampler createSampler(final UniformRandomProvider rng) {
return new RealDistribution.Sampler() {
/**
* Beta distribution sampler.
*/
private final ContinuousSampler sampler =
new ChengBetaSampler(rng, alpha, beta);
/**{@inheritDoc} */
@Override
public double sample() {
return sampler.sample();
}
};
}
}

View File

@ -1,178 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.exception.NotPositiveException;
import org.apache.commons.math4.exception.OutOfRangeException;
import org.apache.commons.math4.exception.util.LocalizedFormats;
import org.apache.commons.numbers.gamma.RegularizedBeta;
import org.apache.commons.math4.util.FastMath;
/**
* Implementation of the binomial distribution.
*
* @see <a href="http://en.wikipedia.org/wiki/Binomial_distribution">Binomial distribution (Wikipedia)</a>
* @see <a href="http://mathworld.wolfram.com/BinomialDistribution.html">Binomial Distribution (MathWorld)</a>
*/
public class BinomialDistribution extends AbstractIntegerDistribution {
/** Serializable version identifier. */
private static final long serialVersionUID = 6751309484392813623L;
/** The number of trials. */
private final int numberOfTrials;
/** The probability of success. */
private final double probabilityOfSuccess;
/**
* Creates a binomial distribution.
*
* @param trials Number of trials.
* @param p Probability of success.
* @throws NotPositiveException if {@code trials < 0}.
* @throws OutOfRangeException if {@code p < 0} or {@code p > 1}.
*/
public BinomialDistribution(int trials,
double p) {
if (trials < 0) {
throw new NotPositiveException(LocalizedFormats.NUMBER_OF_TRIALS,
trials);
}
if (p < 0 || p > 1) {
throw new OutOfRangeException(p, 0, 1);
}
probabilityOfSuccess = p;
numberOfTrials = trials;
}
/**
* Access the number of trials for this distribution.
*
* @return the number of trials.
*/
public int getNumberOfTrials() {
return numberOfTrials;
}
/**
* Access the probability of success for this distribution.
*
* @return the probability of success.
*/
public double getProbabilityOfSuccess() {
return probabilityOfSuccess;
}
/** {@inheritDoc} */
@Override
public double probability(int x) {
final double logProbability = logProbability(x);
return logProbability == Double.NEGATIVE_INFINITY ? 0 : FastMath.exp(logProbability);
}
/** {@inheritDoc} **/
@Override
public double logProbability(int x) {
if (numberOfTrials == 0) {
return (x == 0) ? 0. : Double.NEGATIVE_INFINITY;
}
double ret;
if (x < 0 || x > numberOfTrials) {
ret = Double.NEGATIVE_INFINITY;
} else {
ret = SaddlePointExpansion.logBinomialProbability(x,
numberOfTrials, probabilityOfSuccess,
1.0 - probabilityOfSuccess);
}
return ret;
}
/** {@inheritDoc} */
@Override
public double cumulativeProbability(int x) {
double ret;
if (x < 0) {
ret = 0.0;
} else if (x >= numberOfTrials) {
ret = 1.0;
} else {
ret = 1.0 - RegularizedBeta.value(probabilityOfSuccess,
x + 1.0, numberOfTrials - x);
}
return ret;
}
/**
* {@inheritDoc}
*
* For {@code n} trials and probability parameter {@code p}, the mean is
* {@code n * p}.
*/
@Override
public double getNumericalMean() {
return numberOfTrials * probabilityOfSuccess;
}
/**
* {@inheritDoc}
*
* For {@code n} trials and probability parameter {@code p}, the variance is
* {@code n * p * (1 - p)}.
*/
@Override
public double getNumericalVariance() {
final double p = probabilityOfSuccess;
return numberOfTrials * p * (1 - p);
}
/**
* {@inheritDoc}
*
* The lower bound of the support is always 0 except for the probability
* parameter {@code p = 1}.
*
* @return lower bound of the support (0 or the number of trials)
*/
@Override
public int getSupportLowerBound() {
return probabilityOfSuccess < 1.0 ? 0 : numberOfTrials;
}
/**
* {@inheritDoc}
*
* The upper bound of the support is the number of trials except for the
* probability parameter {@code p = 0}.
*
* @return upper bound of the support (number of trials or 0)
*/
@Override
public int getSupportUpperBound() {
return probabilityOfSuccess > 0.0 ? numberOfTrials : 0;
}
/**
* {@inheritDoc}
*
* The support of this distribution is connected.
*
* @return {@code true}
*/
@Override
public boolean isSupportConnected() {
return true;
}
}

View File

@ -1,206 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.math4.exception.OutOfRangeException;
import org.apache.commons.math4.exception.util.LocalizedFormats;
import org.apache.commons.math4.util.FastMath;
/**
* Implementation of the Cauchy distribution.
*
* @see <a href="http://en.wikipedia.org/wiki/Cauchy_distribution">Cauchy distribution (Wikipedia)</a>
* @see <a href="http://mathworld.wolfram.com/CauchyDistribution.html">Cauchy Distribution (MathWorld)</a>
* @since 1.1 (changed to concrete class in 3.0)
*/
public class CauchyDistribution extends AbstractRealDistribution {
/**
* Default inverse cumulative probability accuracy.
* @since 2.1
*/
public static final double DEFAULT_INVERSE_ABSOLUTE_ACCURACY = 1e-9;
/** Serializable version identifier */
private static final long serialVersionUID = 20160311L;
/** The median of this distribution. */
private final double median;
/** The scale of this distribution. */
private final double scale;
/** Inverse cumulative probability accuracy */
private final double solverAbsoluteAccuracy;
/**
* Creates a Cauchy distribution with the median equal to zero and scale
* equal to one.
*/
public CauchyDistribution() {
this(0, 1);
}
/**
* Creates a distribution.
*
* @param median Median for this distribution.
* @param scale Scale parameter for this distribution.
* @throws NotStrictlyPositiveException if {@code scale <= 0}.
*/
public CauchyDistribution(double median,
double scale) {
this(median, scale, DEFAULT_INVERSE_ABSOLUTE_ACCURACY);
}
/**
* Creates a distribution.
*
* @param median Median for this distribution.
* @param scale Scale parameter for this distribution.
* @param inverseCumAccuracy Maximum absolute error in inverse
* cumulative probability estimates
* (defaults to {@link #DEFAULT_INVERSE_ABSOLUTE_ACCURACY}).
* @throws NotStrictlyPositiveException if {@code scale <= 0}.
*/
public CauchyDistribution(double median,
double scale,
double inverseCumAccuracy) {
if (scale <= 0) {
throw new NotStrictlyPositiveException(LocalizedFormats.SCALE, scale);
}
this.scale = scale;
this.median = median;
solverAbsoluteAccuracy = inverseCumAccuracy;
}
/** {@inheritDoc} */
@Override
public double cumulativeProbability(double x) {
return 0.5 + (FastMath.atan((x - median) / scale) / FastMath.PI);
}
/**
* Access the median.
*
* @return the median for this distribution.
*/
public double getMedian() {
return median;
}
/**
* Access the scale parameter.
*
* @return the scale parameter for this distribution.
*/
public double getScale() {
return scale;
}
/** {@inheritDoc} */
@Override
public double density(double x) {
final double dev = x - median;
return (1 / FastMath.PI) * (scale / (dev * dev + scale * scale));
}
/**
* {@inheritDoc}
*
* Returns {@code Double.NEGATIVE_INFINITY} when {@code p == 0}
* and {@code Double.POSITIVE_INFINITY} when {@code p == 1}.
*/
@Override
public double inverseCumulativeProbability(double p) throws OutOfRangeException {
double ret;
if (p < 0 || p > 1) {
throw new OutOfRangeException(p, 0, 1);
} else if (p == 0) {
ret = Double.NEGATIVE_INFINITY;
} else if (p == 1) {
ret = Double.POSITIVE_INFINITY;
} else {
ret = median + scale * FastMath.tan(FastMath.PI * (p - .5));
}
return ret;
}
/** {@inheritDoc} */
@Override
protected double getSolverAbsoluteAccuracy() {
return solverAbsoluteAccuracy;
}
/**
* {@inheritDoc}
*
* The mean is always undefined no matter the parameters.
*
* @return mean (always Double.NaN)
*/
@Override
public double getNumericalMean() {
return Double.NaN;
}
/**
* {@inheritDoc}
*
* The variance is always undefined no matter the parameters.
*
* @return variance (always Double.NaN)
*/
@Override
public double getNumericalVariance() {
return Double.NaN;
}
/**
* {@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 support of this distribution is connected.
*
* @return {@code true}
*/
@Override
public boolean isSupportConnected() {
return true;
}
}

View File

@ -1,154 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
/**
* Implementation of the chi-squared distribution.
*
* @see <a href="http://en.wikipedia.org/wiki/Chi-squared_distribution">Chi-squared distribution (Wikipedia)</a>
* @see <a href="http://mathworld.wolfram.com/Chi-SquaredDistribution.html">Chi-squared Distribution (MathWorld)</a>
*/
public class ChiSquaredDistribution extends AbstractRealDistribution {
/**
* Default inverse cumulative probability accuracy
* @since 2.1
*/
public static final double DEFAULT_INVERSE_ABSOLUTE_ACCURACY = 1e-9;
/** Serializable version identifier */
private static final long serialVersionUID = 20160311L;
/** Internal Gamma distribution. */
private final GammaDistribution gamma;
/** Inverse cumulative probability accuracy */
private final double solverAbsoluteAccuracy;
/**
* Creates distribution with the given degrees of freedom.
*
* @param degreesOfFreedom Degrees of freedom.
*/
public ChiSquaredDistribution(double degreesOfFreedom) {
this(degreesOfFreedom, DEFAULT_INVERSE_ABSOLUTE_ACCURACY);
}
/**
* Creates a distribution with the given degrees of freedom and
* inverse cumulative probability accuracy.
*
* @param degreesOfFreedom Degrees of freedom.
* @param inverseCumAccuracy the maximum absolute error in inverse
* cumulative probability estimates (defaults to
* {@link #DEFAULT_INVERSE_ABSOLUTE_ACCURACY}).
*
* @since 2.1
*/
public ChiSquaredDistribution(double degreesOfFreedom,
double inverseCumAccuracy) {
gamma = new GammaDistribution(degreesOfFreedom / 2, 2);
solverAbsoluteAccuracy = inverseCumAccuracy;
}
/**
* Access the number of degrees of freedom.
*
* @return the degrees of freedom.
*/
public double getDegreesOfFreedom() {
return gamma.getShape() * 2.0;
}
/** {@inheritDoc} */
@Override
public double density(double x) {
return gamma.density(x);
}
/** {@inheritDoc} **/
@Override
public double logDensity(double x) {
return gamma.logDensity(x);
}
/** {@inheritDoc} */
@Override
public double cumulativeProbability(double x) {
return gamma.cumulativeProbability(x);
}
/** {@inheritDoc} */
@Override
protected double getSolverAbsoluteAccuracy() {
return solverAbsoluteAccuracy;
}
/**
* {@inheritDoc}
*
* For {@code k} degrees of freedom, the mean is {@code k}.
*/
@Override
public double getNumericalMean() {
return getDegreesOfFreedom();
}
/**
* {@inheritDoc}
*
* @return {@code 2 * k}, where {@code k} is the number of degrees of freedom.
*/
@Override
public double getNumericalVariance() {
return 2 * getDegreesOfFreedom();
}
/**
* {@inheritDoc}
*
* The lower bound of the support is always 0 no matter the
* degrees of freedom.
*
* @return zero.
*/
@Override
public double getSupportLowerBound() {
return 0;
}
/**
* {@inheritDoc}
*
* The upper bound of the support is always positive infinity no matter the
* degrees of freedom.
*
* @return {@code Double.POSITIVE_INFINITY}.
*/
@Override
public double getSupportUpperBound() {
return Double.POSITIVE_INFINITY;
}
/**
* {@inheritDoc}
*
* The support of this distribution is connected.
*
* @return {@code true}
*/
@Override
public boolean isSupportConnected() {
return true;
}
}

View File

@ -1,123 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.exception.OutOfRangeException;
import org.apache.commons.rng.UniformRandomProvider;
/**
* Implementation of the constant real distribution.
*
* @since 3.4
*/
public class ConstantRealDistribution extends AbstractRealDistribution {
/** Serialization ID */
private static final long serialVersionUID = -4157745166772046273L;
/** Constant value of the distribution */
private final double value;
/**
* Create a constant real distribution with the given value.
*
* @param value the constant value of this distribution
*/
public ConstantRealDistribution(double value) {
this.value = value;
}
/** {@inheritDoc} */
@Override
public double density(double x) {
return x == value ? 1 : 0;
}
/** {@inheritDoc} */
@Override
public double cumulativeProbability(double x) {
return x < value ? 0 : 1;
}
/** {@inheritDoc} */
@Override
public double inverseCumulativeProbability(final double p)
throws OutOfRangeException {
if (p < 0.0 || p > 1.0) {
throw new OutOfRangeException(p, 0, 1);
}
return value;
}
/**
* {@inheritDoc}
*/
@Override
public double getNumericalMean() {
return value;
}
/**
* {@inheritDoc}
*/
@Override
public double getNumericalVariance() {
return 0;
}
/**
* {@inheritDoc}
*/
@Override
public double getSupportLowerBound() {
return value;
}
/**
* {@inheritDoc}
*/
@Override
public double getSupportUpperBound() {
return value;
}
/**
* {@inheritDoc}
*/
@Override
public boolean isSupportConnected() {
return true;
}
/**
* {@inheritDoc}
*
* @param rng Not used: distribution contains a single value.
* @return the value of the distribution.
*/
@Override
public RealDistribution.Sampler createSampler(final UniformRandomProvider rng) {
return new RealDistribution.Sampler() {
/** {@inheritDoc} */
@Override
public double sample() {
return value;
}
};
}
}

View File

@ -1,235 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.math4.exception.OutOfRangeException;
import org.apache.commons.math4.exception.util.LocalizedFormats;
import org.apache.commons.math4.util.FastMath;
import org.apache.commons.rng.UniformRandomProvider;
import org.apache.commons.rng.sampling.distribution.ContinuousSampler;
import org.apache.commons.rng.sampling.distribution.AhrensDieterExponentialSampler;
/**
* Implementation of the exponential distribution.
*
* @see <a href="http://en.wikipedia.org/wiki/Exponential_distribution">Exponential distribution (Wikipedia)</a>
* @see <a href="http://mathworld.wolfram.com/ExponentialDistribution.html">Exponential distribution (MathWorld)</a>
*/
public class ExponentialDistribution extends AbstractRealDistribution {
/**
* Default inverse cumulative probability accuracy.
* @since 2.1
*/
public static final double DEFAULT_INVERSE_ABSOLUTE_ACCURACY = 1e-9;
/** Serializable version identifier */
private static final long serialVersionUID = 20160311L;
/** 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;
/**
* Creates a distribution.
*
* @param mean mean of this distribution.
*/
public ExponentialDistribution(double mean) {
this(mean, DEFAULT_INVERSE_ABSOLUTE_ACCURACY);
}
/**
* Creates a distribution.
*
* @param mean Mean of this distribution.
* @param inverseCumAccuracy Maximum absolute error in inverse
* cumulative probability estimates (defaults to
* {@link #DEFAULT_INVERSE_ABSOLUTE_ACCURACY}).
* @throws NotStrictlyPositiveException if {@code mean <= 0}.
*
* @since 2.1
*/
public ExponentialDistribution(double mean,
double inverseCumAccuracy)
throws NotStrictlyPositiveException {
if (mean <= 0) {
throw new NotStrictlyPositiveException(LocalizedFormats.MEAN, mean);
}
this.mean = mean;
logMean = FastMath.log(mean);
solverAbsoluteAccuracy = inverseCumAccuracy;
}
/**
* Access the mean.
*
* @return the mean.
*/
public double getMean() {
return mean;
}
/** {@inheritDoc} */
@Override
public double density(double x) {
final double logDensity = logDensity(x);
return logDensity == Double.NEGATIVE_INFINITY ? 0 : FastMath.exp(logDensity);
}
/** {@inheritDoc} **/
@Override
public double logDensity(double x) {
if (x < 0) {
return Double.NEGATIVE_INFINITY;
}
return -x / mean - logMean;
}
/**
* {@inheritDoc}
*
* The implementation of this method is based on:
* <ul>
* <li>
* <a href="http://mathworld.wolfram.com/ExponentialDistribution.html">
* Exponential Distribution</a>, equation (1).</li>
* </ul>
*/
@Override
public double cumulativeProbability(double x) {
double ret;
if (x <= 0.0) {
ret = 0.0;
} else {
ret = 1.0 - FastMath.exp(-x / mean);
}
return ret;
}
/**
* {@inheritDoc}
*
* Returns {@code 0} when {@code p= = 0} and
* {@code Double.POSITIVE_INFINITY} when {@code p == 1}.
*/
@Override
public double inverseCumulativeProbability(double p) throws OutOfRangeException {
double ret;
if (p < 0.0 || p > 1.0) {
throw new OutOfRangeException(p, 0.0, 1.0);
} else if (p == 1.0) {
ret = Double.POSITIVE_INFINITY;
} else {
ret = -mean * FastMath.log(1.0 - p);
}
return ret;
}
/** {@inheritDoc} */
@Override
protected double getSolverAbsoluteAccuracy() {
return solverAbsoluteAccuracy;
}
/**
* {@inheritDoc}
*
* For mean parameter {@code k}, the mean is {@code k}.
*/
@Override
public double getNumericalMean() {
return getMean();
}
/**
* {@inheritDoc}
*
* For mean parameter {@code k}, the variance is {@code k^2}.
*/
@Override
public double getNumericalVariance() {
final double m = getMean();
return m * m;
}
/**
* {@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}
*
* The support of this distribution is connected.
*
* @return {@code true}
*/
@Override
public boolean isSupportConnected() {
return true;
}
/**
* {@inheritDoc}
*
* <p>Sampling algorithm uses the
* <a href="http://www.jesus.ox.ac.uk/~clifford/a5/chap1/node5.html">
* inversion method</a> to generate exponentially distributed
* random values from uniform deviates.
* </p>
*/
@Override
public RealDistribution.Sampler createSampler(final UniformRandomProvider rng) {
return new RealDistribution.Sampler() {
/**
* Exponential distribution sampler.
*/
private final ContinuousSampler sampler =
new AhrensDieterExponentialSampler(rng, mean);
/**{@inheritDoc} */
@Override
public double sample() {
return sampler.sample();
}
};
}
}

View File

@ -1,267 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.math4.exception.util.LocalizedFormats;
import org.apache.commons.numbers.gamma.LogBeta;
import org.apache.commons.numbers.gamma.RegularizedBeta;
import org.apache.commons.math4.util.FastMath;
/**
* Implementation of the F-distribution.
*
* @see <a href="http://en.wikipedia.org/wiki/F-distribution">F-distribution (Wikipedia)</a>
* @see <a href="http://mathworld.wolfram.com/F-Distribution.html">F-distribution (MathWorld)</a>
*/
public class FDistribution extends AbstractRealDistribution {
/**
* Default inverse cumulative probability accuracy.
* @since 2.1
*/
public static final double DEFAULT_INVERSE_ABSOLUTE_ACCURACY = 1e-9;
/** Serializable version identifier. */
private static final long serialVersionUID = -8516354193418641566L;
/** The numerator degrees of freedom. */
private final double numeratorDegreesOfFreedom;
/** The numerator degrees of freedom. */
private final double denominatorDegreesOfFreedom;
/** Inverse cumulative probability accuracy. */
private final double solverAbsoluteAccuracy;
/** Cached numerical variance */
private double numericalVariance = Double.NaN;
/** Whether or not the numerical variance has been calculated */
private boolean numericalVarianceIsCalculated = false;
/**
* Creates a using the given degrees of freedom.
*
* @param numeratorDegreesOfFreedom Numerator degrees of freedom.
* @param denominatorDegreesOfFreedom Denominator degrees of freedom.
* @throws NotStrictlyPositiveException if
* {@code numeratorDegreesOfFreedom <= 0} or
* {@code denominatorDegreesOfFreedom <= 0}.
*/
public FDistribution(double numeratorDegreesOfFreedom,
double denominatorDegreesOfFreedom)
throws NotStrictlyPositiveException {
this(numeratorDegreesOfFreedom, denominatorDegreesOfFreedom,
DEFAULT_INVERSE_ABSOLUTE_ACCURACY);
}
/**
* Creates a distribution.
*
* @param numeratorDegreesOfFreedom Numerator degrees of freedom.
* @param denominatorDegreesOfFreedom Denominator degrees of freedom.
* @param inverseCumAccuracy the maximum absolute error in inverse
* cumulative probability estimates.
* @throws NotStrictlyPositiveException if {@code numeratorDegreesOfFreedom <= 0} or
* {@code denominatorDegreesOfFreedom <= 0}.
*/
public FDistribution(double numeratorDegreesOfFreedom,
double denominatorDegreesOfFreedom,
double inverseCumAccuracy)
throws NotStrictlyPositiveException {
if (numeratorDegreesOfFreedom <= 0) {
throw new NotStrictlyPositiveException(LocalizedFormats.DEGREES_OF_FREEDOM,
numeratorDegreesOfFreedom);
}
if (denominatorDegreesOfFreedom <= 0) {
throw new NotStrictlyPositiveException(LocalizedFormats.DEGREES_OF_FREEDOM,
denominatorDegreesOfFreedom);
}
this.numeratorDegreesOfFreedom = numeratorDegreesOfFreedom;
this.denominatorDegreesOfFreedom = denominatorDegreesOfFreedom;
solverAbsoluteAccuracy = inverseCumAccuracy;
}
/**
* {@inheritDoc}
*
* @since 2.1
*/
@Override
public double density(double x) {
return FastMath.exp(logDensity(x));
}
/** {@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 -
LogBeta.value(nhalf, mhalf);
}
/**
* {@inheritDoc}
*
* The implementation of this method is based on
* <ul>
* <li>
* <a href="http://mathworld.wolfram.com/F-Distribution.html">
* F-Distribution</a>, equation (4).
* </li>
* </ul>
*/
@Override
public double cumulativeProbability(double x) {
double ret;
if (x <= 0) {
ret = 0;
} else {
double n = numeratorDegreesOfFreedom;
double m = denominatorDegreesOfFreedom;
ret = RegularizedBeta.value((n * x) / (m + n * x),
0.5 * n,
0.5 * m);
}
return ret;
}
/**
* Access the numerator degrees of freedom.
*
* @return the numerator degrees of freedom.
*/
public double getNumeratorDegreesOfFreedom() {
return numeratorDegreesOfFreedom;
}
/**
* Access the denominator degrees of freedom.
*
* @return the denominator degrees of freedom.
*/
public double getDenominatorDegreesOfFreedom() {
return denominatorDegreesOfFreedom;
}
/** {@inheritDoc} */
@Override
protected double getSolverAbsoluteAccuracy() {
return solverAbsoluteAccuracy;
}
/**
* {@inheritDoc}
*
* For denominator degrees of freedom parameter {@code b}, the mean is
* <ul>
* <li>if {@code b > 2} then {@code b / (b - 2)},</li>
* <li>else undefined ({@code Double.NaN}).
* </ul>
*/
@Override
public double getNumericalMean() {
final double denominatorDF = getDenominatorDegreesOfFreedom();
if (denominatorDF > 2) {
return denominatorDF / (denominatorDF - 2);
}
return Double.NaN;
}
/**
* {@inheritDoc}
*
* For numerator degrees of freedom parameter {@code a} and denominator
* degrees of freedom parameter {@code b}, the variance is
* <ul>
* <li>
* if {@code b > 4} then
* {@code [2 * b^2 * (a + b - 2)] / [a * (b - 2)^2 * (b - 4)]},
* </li>
* <li>else undefined ({@code Double.NaN}).
* </ul>
*/
@Override
public double getNumericalVariance() {
if (!numericalVarianceIsCalculated) {
numericalVariance = calculateNumericalVariance();
numericalVarianceIsCalculated = true;
}
return numericalVariance;
}
/**
* used by {@link #getNumericalVariance()}
*
* @return the variance of this distribution
*/
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;
}
/**
* {@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 support of this distribution is connected.
*
* @return {@code true}
*/
@Override
public boolean isSupportConnected() {
return true;
}
}

View File

@ -1,397 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.math4.exception.util.LocalizedFormats;
import org.apache.commons.numbers.gamma.LanczosApproximation;
import org.apache.commons.numbers.gamma.RegularizedGamma;
import org.apache.commons.math4.util.FastMath;
import org.apache.commons.rng.UniformRandomProvider;
import org.apache.commons.rng.sampling.distribution.ContinuousSampler;
import org.apache.commons.rng.sampling.distribution.AhrensDieterMarsagliaTsangGammaSampler;
/**
* Implementation of the Gamma distribution.
*
* @see <a href="http://en.wikipedia.org/wiki/Gamma_distribution">Gamma distribution (Wikipedia)</a>
* @see <a href="http://mathworld.wolfram.com/GammaDistribution.html">Gamma distribution (MathWorld)</a>
*/
public class GammaDistribution extends AbstractRealDistribution {
/**
* Default inverse cumulative probability accuracy.
* @since 2.1
*/
public static final double DEFAULT_INVERSE_ABSOLUTE_ACCURACY = 1e-9;
/** Lanczos constant. */
private static final double LANCZOS_G = LanczosApproximation.g();
/** Serializable version identifier. */
private static final long serialVersionUID = 20160311L;
/** The shape parameter. */
private final double shape;
/** The scale parameter. */
private final double scale;
/**
* The constant value of {@code shape + g + 0.5}, where {@code g} is the
* Lanczos constant {@link LanczosApproximation#g()}.
*/
private final double shiftedShape;
/**
* The constant value of
* {@code shape / scale * sqrt(e / (2 * pi * (shape + g + 0.5))) / L(shape)},
* where {@code L(shape)} is the Lanczos approximation returned by
* {@link LanczosApproximation#value(double)}. This prefactor is used in
* {@link #density(double)}, when no overflow occurs with the natural
* calculation.
*/
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 LanczosApproximation#value(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 LanczosApproximation#value(double)}. This prefactor is used in
* {@link #density(double)}, when overflow occurs with the natural
* calculation.
*/
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 LanczosApproximation#value(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.
*/
private final double minY;
/**
* Upper bound on {@code log(y)} ({@code y = x / scale}) for the selection
* of the computation method in {@link #density(double)}. For
* {@code log(y) >= maxLogY}, the natural calculation overflows.
*/
private final double maxLogY;
/** Inverse cumulative probability accuracy. */
private final double solverAbsoluteAccuracy;
/**
* Creates a distribution.
*
* @param shape the shape parameter
* @param scale the scale parameter
* @throws NotStrictlyPositiveException if {@code shape <= 0} or
* {@code scale <= 0}.
*/
public GammaDistribution(double shape, double scale)
throws NotStrictlyPositiveException {
this(shape, scale, DEFAULT_INVERSE_ABSOLUTE_ACCURACY);
}
/**
* Creates a distribution.
*
* @param shape the shape parameter
* @param scale the scale parameter
* @param inverseCumAccuracy the maximum absolute error in inverse
* cumulative probability estimates (defaults to
* {@link #DEFAULT_INVERSE_ABSOLUTE_ACCURACY}).
* @throws NotStrictlyPositiveException if {@code shape <= 0} or
* {@code scale <= 0}.
*/
public GammaDistribution(double shape,
double scale,
double inverseCumAccuracy)
throws NotStrictlyPositiveException {
if (shape <= 0) {
throw new NotStrictlyPositiveException(LocalizedFormats.SHAPE, shape);
}
if (scale <= 0) {
throw new NotStrictlyPositiveException(LocalizedFormats.SCALE, scale);
}
this.shape = shape;
this.scale = scale;
this.solverAbsoluteAccuracy = inverseCumAccuracy;
this.shiftedShape = shape + LANCZOS_G + 0.5;
final double aux = FastMath.E / (2.0 * FastMath.PI * shiftedShape);
this.densityPrefactor2 = shape * FastMath.sqrt(aux) / LanczosApproximation.value(shape);
this.logDensityPrefactor2 = FastMath.log(shape) + 0.5 * FastMath.log(aux) -
FastMath.log(LanczosApproximation.value(shape));
this.densityPrefactor1 = this.densityPrefactor2 / scale *
FastMath.pow(shiftedShape, -shape) *
FastMath.exp(shape + LANCZOS_G);
this.logDensityPrefactor1 = this.logDensityPrefactor2 - FastMath.log(scale) -
FastMath.log(shiftedShape) * shape +
shape + LANCZOS_G;
this.minY = shape + LANCZOS_G - FastMath.log(Double.MAX_VALUE);
this.maxLogY = FastMath.log(Double.MAX_VALUE) / (shape - 1.0);
}
/**
* Returns the shape parameter of {@code this} distribution.
*
* @return the shape parameter
* @since 3.1
*/
public double getShape() {
return shape;
}
/**
* Returns the scale parameter of {@code this} distribution.
*
* @return the scale parameter
* @since 3.1
*/
public double getScale() {
return scale;
}
/** {@inheritDoc} */
@Override
public double density(double x) {
/* The present method must return the value of
*
* 1 x a - x
* ---------- (-) exp(---)
* x Gamma(a) b b
*
* where a is the shape parameter, and b the scale parameter.
* Substituting the Lanczos approximation of Gamma(a) leads to the
* following expression of the density
*
* a e 1 y a
* - sqrt(------------------) ---- (-----------) exp(a - y + g),
* x 2 pi (a + g + 0.5) L(a) a + g + 0.5
*
* where y = x / b. The above formula is the "natural" computation, which
* is implemented when no overflow is likely to occur. If overflow occurs
* with the natural computation, the following identity is used. It is
* based on the BOOST library
* http://www.boost.org/doc/libs/1_35_0/libs/math/doc/sf_and_dist/html/math_toolkit/special/sf_gamma/igamma.html
* Formula (15) needs adaptations, which are detailed below.
*
* y a
* (-----------) exp(a - y + g)
* a + g + 0.5
* y - a - g - 0.5 y (g + 0.5)
* = exp(a log1pm(---------------) - ----------- + g),
* a + g + 0.5 a + g + 0.5
*
* where log1pm(z) = log(1 + z) - z. Therefore, the value to be
* returned is
*
* a e 1
* - sqrt(------------------) ----
* x 2 pi (a + g + 0.5) L(a)
* y - a - g - 0.5 y (g + 0.5)
* * exp(a log1pm(---------------) - ----------- + g).
* a + g + 0.5 a + g + 0.5
*/
if (x < 0) {
return 0;
}
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 * (LANCZOS_G + 0.5) / shiftedShape + LANCZOS_G + aux2;
return densityPrefactor2 / x * FastMath.exp(aux3);
}
/*
* Natural calculation.
*/
return densityPrefactor1 * FastMath.exp(-y) * 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 * (LANCZOS_G + 0.5) / shiftedShape + LANCZOS_G + aux2;
return logDensityPrefactor2 - FastMath.log(x) + aux3;
}
/*
* Natural calculation.
*/
return logDensityPrefactor1 - y + FastMath.log(y) * (shape - 1);
}
/**
* {@inheritDoc}
*
* The implementation of this method is based on:
* <ul>
* <li>
* <a href="http://mathworld.wolfram.com/Chi-SquaredDistribution.html">
* Chi-Squared Distribution</a>, equation (9).
* </li>
* <li>Casella, G., &amp; Berger, R. (1990). <i>Statistical Inference</i>.
* Belmont, CA: Duxbury Press.
* </li>
* </ul>
*/
@Override
public double cumulativeProbability(double x) {
double ret;
if (x <= 0) {
ret = 0;
} else {
ret = RegularizedGamma.P.value(shape, x / scale);
}
return ret;
}
/** {@inheritDoc} */
@Override
protected double getSolverAbsoluteAccuracy() {
return solverAbsoluteAccuracy;
}
/**
* {@inheritDoc}
*
* For shape parameter {@code alpha} and scale parameter {@code beta}, the
* mean is {@code alpha * beta}.
*/
@Override
public double getNumericalMean() {
return shape * scale;
}
/**
* {@inheritDoc}
*
* For shape parameter {@code alpha} and scale parameter {@code beta}, the
* variance is {@code alpha * beta^2}.
*
* @return {@inheritDoc}
*/
@Override
public double getNumericalVariance() {
return shape * scale * scale;
}
/**
* {@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 support of this distribution is connected.
*
* @return {@code true}
*/
@Override
public boolean isSupportConnected() {
return true;
}
/**
* {@inheritDoc}
*
* <p>
* Sampling algorithms:
* <ul>
* <li>
* For {@code 0 < shape < 1}:
* <blockquote>
* Ahrens, J. H. and Dieter, U.,
* <i>Computer methods for sampling from gamma, beta, Poisson and binomial distributions,</i>
* Computing, 12, 223-246, 1974.
* </blockquote>
* </li>
* <li>
* For {@code shape >= 1}:
* <blockquote>
* Marsaglia and Tsang, <i>A Simple Method for Generating
* Gamma Variables.</i> ACM Transactions on Mathematical Software,
* Volume 26 Issue 3, September, 2000.
* </blockquote>
* </li>
* </ul>
*/
@Override
public RealDistribution.Sampler createSampler(final UniformRandomProvider rng) {
return new RealDistribution.Sampler() {
/**
* Gamma distribution sampler.
*/
private final ContinuousSampler sampler =
new AhrensDieterMarsagliaTsangGammaSampler(rng, scale, shape);
/**{@inheritDoc} */
@Override
public double sample() {
return sampler.sample();
}
};
}
}

View File

@ -1,170 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.exception.OutOfRangeException;
import org.apache.commons.math4.exception.util.LocalizedFormats;
import org.apache.commons.math4.util.FastMath;
/**
* Implementation of the geometric distribution.
*
* @see <a href="http://en.wikipedia.org/wiki/Geometric_distribution">Geometric distribution (Wikipedia)</a>
* @see <a href="http://mathworld.wolfram.com/GeometricDistribution.html">Geometric Distribution (MathWorld)</a>
* @since 3.3
*/
public class GeometricDistribution extends AbstractIntegerDistribution {
/** Serializable version identifier. */
private static final long serialVersionUID = 20160318L;
/** The probability of success. */
private final double probabilityOfSuccess;
/** {@code log(p)} where p is the probability of success. */
private final double logProbabilityOfSuccess;
/** {@code log(1 - p)} where p is the probability of success. */
private final double log1mProbabilityOfSuccess;
/**
* Creates a geometric distribution.
*
* @param p Probability of success.
* @throws OutOfRangeException if {@code p <= 0} or {@code p > 1}.
*/
public GeometricDistribution(double p) {
if (p <= 0 || p > 1) {
throw new OutOfRangeException(LocalizedFormats.OUT_OF_RANGE_LEFT, p, 0, 1);
}
probabilityOfSuccess = p;
logProbabilityOfSuccess = FastMath.log(p);
log1mProbabilityOfSuccess = FastMath.log1p(-p);
}
/**
* Access the probability of success for this distribution.
*
* @return the probability of success.
*/
public double getProbabilityOfSuccess() {
return probabilityOfSuccess;
}
/** {@inheritDoc} */
@Override
public double probability(int x) {
if (x < 0) {
return 0.0;
} else {
return FastMath.exp(log1mProbabilityOfSuccess * x) * probabilityOfSuccess;
}
}
/** {@inheritDoc} */
@Override
public double logProbability(int x) {
if (x < 0) {
return Double.NEGATIVE_INFINITY;
} else {
return x * log1mProbabilityOfSuccess + logProbabilityOfSuccess;
}
}
/** {@inheritDoc} */
@Override
public double cumulativeProbability(int x) {
if (x < 0) {
return 0.0;
} else {
return -FastMath.expm1(log1mProbabilityOfSuccess * (x + 1));
}
}
/**
* {@inheritDoc}
*
* For probability parameter {@code p}, the mean is {@code (1 - p) / p}.
*/
@Override
public double getNumericalMean() {
return (1 - probabilityOfSuccess) / probabilityOfSuccess;
}
/**
* {@inheritDoc}
*
* For probability parameter {@code p}, the variance is
* {@code (1 - p) / (p * p)}.
*/
@Override
public double getNumericalVariance() {
return (1 - probabilityOfSuccess) / (probabilityOfSuccess * probabilityOfSuccess);
}
/**
* {@inheritDoc}
*
* The lower bound of the support is always 0.
*
* @return lower bound of the support (always 0)
*/
@Override
public int getSupportLowerBound() {
return 0;
}
/**
* {@inheritDoc}
*
* The upper bound of the support is infinite (which we approximate as
* {@code Integer.MAX_VALUE}).
*
* @return upper bound of the support (always Integer.MAX_VALUE)
*/
@Override
public int getSupportUpperBound() {
return Integer.MAX_VALUE;
}
/**
* {@inheritDoc}
*
* The support of this distribution is connected.
*
* @return {@code true}
*/
@Override
public boolean isSupportConnected() {
return true;
}
/**
* {@inheritDoc}
*/
@Override
public int inverseCumulativeProbability(double p) throws OutOfRangeException {
if (p < 0 || p > 1) {
throw new OutOfRangeException(p, 0, 1);
}
if (p == 1) {
return Integer.MAX_VALUE;
}
if (p == 0) {
return 0;
}
return Math.max(0, (int) Math.ceil(FastMath.log1p(-p)/log1mProbabilityOfSuccess-1));
}
}

View File

@ -1,141 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.math4.exception.OutOfRangeException;
import org.apache.commons.math4.exception.util.LocalizedFormats;
import org.apache.commons.math4.util.FastMath;
import org.apache.commons.math4.util.MathUtils;
/**
* This class implements the Gumbel distribution.
*
* @see <a href="http://en.wikipedia.org/wiki/Gumbel_distribution">Gumbel Distribution (Wikipedia)</a>
* @see <a href="http://mathworld.wolfram.com/GumbelDistribution.html">Gumbel Distribution (Mathworld)</a>
*
* @since 3.4
*/
public class GumbelDistribution extends AbstractRealDistribution {
/** Serializable version identifier. */
private static final long serialVersionUID = 20160311L;
/**
* Approximation of Euler's constant
* see http://mathworld.wolfram.com/Euler-MascheroniConstantApproximations.html
*/
private static final double EULER = FastMath.PI / (2 * FastMath.E);
/** The location parameter. */
private final double mu;
/** The scale parameter. */
private final double beta;
/**
* Creates a distribution.
*
* @param mu location parameter
* @param beta scale parameter (must be positive)
* @throws NotStrictlyPositiveException if {@code beta <= 0}
*/
public GumbelDistribution(double mu, double beta) {
if (beta <= 0) {
throw new NotStrictlyPositiveException(LocalizedFormats.SCALE, beta);
}
this.beta = beta;
this.mu = mu;
}
/**
* Access the location parameter, {@code mu}.
*
* @return the location parameter.
*/
public double getLocation() {
return mu;
}
/**
* Access the scale parameter, {@code beta}.
*
* @return the scale parameter.
*/
public double getScale() {
return beta;
}
/** {@inheritDoc} */
@Override
public double density(double x) {
final double z = (x - mu) / beta;
final double t = FastMath.exp(-z);
return FastMath.exp(-z - t) / beta;
}
/** {@inheritDoc} */
@Override
public double cumulativeProbability(double x) {
final double z = (x - mu) / beta;
return FastMath.exp(-FastMath.exp(-z));
}
/** {@inheritDoc} */
@Override
public double inverseCumulativeProbability(double p) throws OutOfRangeException {
if (p < 0.0 || p > 1.0) {
throw new OutOfRangeException(p, 0.0, 1.0);
} else if (p == 0) {
return Double.NEGATIVE_INFINITY;
} else if (p == 1) {
return Double.POSITIVE_INFINITY;
}
return mu - FastMath.log(-FastMath.log(p)) * beta;
}
/** {@inheritDoc} */
@Override
public double getNumericalMean() {
return mu + EULER * beta;
}
/** {@inheritDoc} */
@Override
public double getNumericalVariance() {
return (MathUtils.PI_SQUARED) / 6.0 * (beta * beta);
}
/** {@inheritDoc} */
@Override
public double getSupportLowerBound() {
return Double.NEGATIVE_INFINITY;
}
/** {@inheritDoc} */
@Override
public double getSupportUpperBound() {
return Double.POSITIVE_INFINITY;
}
/** {@inheritDoc} */
@Override
public boolean isSupportConnected() {
return true;
}
}

View File

@ -1,325 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.exception.NotPositiveException;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.math4.exception.NumberIsTooLargeException;
import org.apache.commons.math4.exception.util.LocalizedFormats;
import org.apache.commons.math4.util.FastMath;
/**
* Implementation of the hypergeometric distribution.
*
* @see <a href="http://en.wikipedia.org/wiki/Hypergeometric_distribution">Hypergeometric distribution (Wikipedia)</a>
* @see <a href="http://mathworld.wolfram.com/HypergeometricDistribution.html">Hypergeometric distribution (MathWorld)</a>
*/
public class HypergeometricDistribution extends AbstractIntegerDistribution {
/** Serializable version identifier. */
private static final long serialVersionUID = 20160318L;
/** The number of successes in the population. */
private final int numberOfSuccesses;
/** The population size. */
private final int populationSize;
/** The sample size. */
private final int sampleSize;
/** Cached numerical variance */
private double numericalVariance = Double.NaN;
/** Whether or not the numerical variance has been calculated */
private boolean numericalVarianceIsCalculated = false;
/**
* Creates a new hypergeometric distribution.
*
* @param populationSize Population size.
* @param numberOfSuccesses Number of successes in the population.
* @param sampleSize Sample size.
* @throws NotPositiveException if {@code numberOfSuccesses < 0}.
* @throws NotStrictlyPositiveException if {@code populationSize <= 0}.
* @throws NumberIsTooLargeException if {@code numberOfSuccesses > populationSize},
* or {@code sampleSize > populationSize}.
*/
public HypergeometricDistribution(int populationSize,
int numberOfSuccesses,
int sampleSize)
throws NotPositiveException,
NotStrictlyPositiveException,
NumberIsTooLargeException {
if (populationSize <= 0) {
throw new NotStrictlyPositiveException(LocalizedFormats.POPULATION_SIZE,
populationSize);
}
if (numberOfSuccesses < 0) {
throw new NotPositiveException(LocalizedFormats.NUMBER_OF_SUCCESSES,
numberOfSuccesses);
}
if (sampleSize < 0) {
throw new NotPositiveException(LocalizedFormats.NUMBER_OF_SAMPLES,
sampleSize);
}
if (numberOfSuccesses > populationSize) {
throw new NumberIsTooLargeException(LocalizedFormats.NUMBER_OF_SUCCESS_LARGER_THAN_POPULATION_SIZE,
numberOfSuccesses, populationSize, true);
}
if (sampleSize > populationSize) {
throw new NumberIsTooLargeException(LocalizedFormats.SAMPLE_SIZE_LARGER_THAN_POPULATION_SIZE,
sampleSize, populationSize, true);
}
this.numberOfSuccesses = numberOfSuccesses;
this.populationSize = populationSize;
this.sampleSize = sampleSize;
}
/** {@inheritDoc} */
@Override
public double cumulativeProbability(int x) {
double ret;
int[] domain = getDomain(populationSize, numberOfSuccesses, sampleSize);
if (x < domain[0]) {
ret = 0.0;
} else if (x >= domain[1]) {
ret = 1.0;
} else {
ret = innerCumulativeProbability(domain[0], x, 1);
}
return ret;
}
/**
* Return the domain for the given hypergeometric distribution parameters.
*
* @param n Population size.
* @param m Number of successes in the population.
* @param k Sample size.
* @return a two element array containing the lower and upper bounds of the
* hypergeometric distribution.
*/
private int[] getDomain(int n, int m, int k) {
return new int[] { getLowerDomain(n, m, k), getUpperDomain(m, k) };
}
/**
* Return the lowest domain value for the given hypergeometric distribution
* parameters.
*
* @param n Population size.
* @param m Number of successes in the population.
* @param k Sample size.
* @return the lowest domain value of the hypergeometric distribution.
*/
private int getLowerDomain(int n, int m, int k) {
return FastMath.max(0, m - (n - k));
}
/**
* Access the number of successes.
*
* @return the number of successes.
*/
public int getNumberOfSuccesses() {
return numberOfSuccesses;
}
/**
* Access the population size.
*
* @return the population size.
*/
public int getPopulationSize() {
return populationSize;
}
/**
* Access the sample size.
*
* @return the sample size.
*/
public int getSampleSize() {
return sampleSize;
}
/**
* Return the highest domain value for the given hypergeometric distribution
* parameters.
*
* @param m Number of successes in the population.
* @param k Sample size.
* @return the highest domain value of the hypergeometric distribution.
*/
private int getUpperDomain(int m, int k) {
return FastMath.min(k, m);
}
/** {@inheritDoc} */
@Override
public double probability(int x) {
final double logProbability = logProbability(x);
return logProbability == Double.NEGATIVE_INFINITY ? 0 : FastMath.exp(logProbability);
}
/** {@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)}.
*
* @param x Value at which the CDF is evaluated.
* @return the upper tail CDF for this distribution.
* @since 1.1
*/
public double upperCumulativeProbability(int x) {
double ret;
final int[] domain = getDomain(populationSize, numberOfSuccesses, sampleSize);
if (x <= domain[0]) {
ret = 1.0;
} else if (x > domain[1]) {
ret = 0.0;
} else {
ret = innerCumulativeProbability(domain[1], x, -1);
}
return ret;
}
/**
* For this distribution, {@code X}, this method returns
* {@code P(x0 <= X <= x1)}.
* This probability is computed by summing the point probabilities for the
* values {@code x0, x0 + 1, x0 + 2, ..., x1}, in the order directed by
* {@code dx}.
*
* @param x0 Inclusive lower bound.
* @param x1 Inclusive upper bound.
* @param dx Direction of summation (1 indicates summing from x0 to x1, and
* 0 indicates summing from x1 to x0).
* @return {@code P(x0 <= X <= x1)}.
*/
private double innerCumulativeProbability(int x0, int x1, int dx) {
double ret = probability(x0);
while (x0 != x1) {
x0 += dx;
ret += probability(x0);
}
return ret;
}
/**
* {@inheritDoc}
*
* For population size {@code N}, number of successes {@code m}, and sample
* size {@code n}, the mean is {@code n * m / N}.
*/
@Override
public double getNumericalMean() {
return getSampleSize() * (getNumberOfSuccesses() / (double) getPopulationSize());
}
/**
* {@inheritDoc}
*
* For population size {@code N}, number of successes {@code m}, and sample
* size {@code n}, the variance is
* {@code [n * m * (N - n) * (N - m)] / [N^2 * (N - 1)]}.
*/
@Override
public double getNumericalVariance() {
if (!numericalVarianceIsCalculated) {
numericalVariance = calculateNumericalVariance();
numericalVarianceIsCalculated = true;
}
return numericalVariance;
}
/**
* Used by {@link #getNumericalVariance()}.
*
* @return the variance of this distribution
*/
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));
}
/**
* {@inheritDoc}
*
* For population size {@code N}, number of successes {@code m}, and sample
* size {@code n}, the lower bound of the support is
* {@code 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 {@code m} and sample size {@code n}, the upper
* bound of the support is {@code min(m, n)}.
*
* @return upper bound of the support
*/
@Override
public int getSupportUpperBound() {
return FastMath.min(getNumberOfSuccesses(), getSampleSize());
}
/**
* {@inheritDoc}
*
* The support of this distribution is connected.
*
* @return {@code true}
*/
@Override
public boolean isSupportConnected() {
return true;
}
}

View File

@ -1,135 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.math4.exception.OutOfRangeException;
import org.apache.commons.math4.exception.util.LocalizedFormats;
import org.apache.commons.math4.util.FastMath;
/**
* This class implements the Laplace distribution.
*
* @see <a href="http://en.wikipedia.org/wiki/Laplace_distribution">Laplace distribution (Wikipedia)</a>
*
* @since 3.4
*/
public class LaplaceDistribution extends AbstractRealDistribution {
/** Serializable version identifier. */
private static final long serialVersionUID = 20160311L;
/** The location parameter. */
private final double mu;
/** The scale parameter. */
private final double beta;
/**
* Creates a distribution.
*
* @param mu location parameter
* @param beta scale parameter (must be positive)
* @throws NotStrictlyPositiveException if {@code beta <= 0}
*/
public LaplaceDistribution(double mu, double beta) {
if (beta <= 0.0) {
throw new NotStrictlyPositiveException(LocalizedFormats.NOT_POSITIVE_SCALE, beta);
}
this.mu = mu;
this.beta = beta;
}
/**
* Access the location parameter, {@code mu}.
*
* @return the location parameter.
*/
public double getLocation() {
return mu;
}
/**
* Access the scale parameter, {@code beta}.
*
* @return the scale parameter.
*/
public double getScale() {
return beta;
}
/** {@inheritDoc} */
@Override
public double density(double x) {
return FastMath.exp(-FastMath.abs(x - mu) / beta) / (2.0 * beta);
}
/** {@inheritDoc} */
@Override
public double cumulativeProbability(double x) {
if (x <= mu) {
return FastMath.exp((x - mu) / beta) / 2.0;
} else {
return 1.0 - FastMath.exp((mu - x) / beta) / 2.0;
}
}
/** {@inheritDoc} */
@Override
public double inverseCumulativeProbability(double p) throws OutOfRangeException {
if (p < 0.0 || p > 1.0) {
throw new OutOfRangeException(p, 0.0, 1.0);
} else if (p == 0) {
return Double.NEGATIVE_INFINITY;
} else if (p == 1) {
return Double.POSITIVE_INFINITY;
}
double x = (p > 0.5) ? -Math.log(2.0 - 2.0 * p) : Math.log(2.0 * p);
return mu + beta * x;
}
/** {@inheritDoc} */
@Override
public double getNumericalMean() {
return mu;
}
/** {@inheritDoc} */
@Override
public double getNumericalVariance() {
return 2.0 * beta * beta;
}
/** {@inheritDoc} */
@Override
public double getSupportLowerBound() {
return Double.NEGATIVE_INFINITY;
}
/** {@inheritDoc} */
@Override
public double getSupportUpperBound() {
return Double.POSITIVE_INFINITY;
}
/** {@inheritDoc} */
@Override
public boolean isSupportConnected() {
return true;
}
}

View File

@ -1,166 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.exception.OutOfRangeException;
import org.apache.commons.numbers.gamma.Erfc;
import org.apache.commons.numbers.gamma.InverseErfc;
import org.apache.commons.math4.util.FastMath;
/**
* This class implements the <a href="http://en.wikipedia.org/wiki/L%C3%A9vy_distribution">
* L&eacute;vy distribution</a>.
*
* @since 3.2
*/
public class LevyDistribution extends AbstractRealDistribution {
/** Serializable UID. */
private static final long serialVersionUID = 20630311L;
/** Location parameter. */
private final double mu;
/** Scale parameter. */
private final double c; // Setting this to 1 returns a cumProb of 1.0
/** Half of c (for calculations). */
private final double halfC;
/**
* Creates a distribution.
*
* @param mu location
* @param c scale parameter
*/
public LevyDistribution(final double mu, final double c) {
this.mu = mu;
this.c = c;
this.halfC = 0.5 * c;
}
/** {@inheritDoc}
* <p>
* From Wikipedia: The probability density function of the L&eacute;vy distribution
* over the domain is
* </p>
* <div style="white-space: pre"><code>
* f(x; &mu;, c) = &radic;(c / 2&pi;) * e<sup>-c / 2 (x - &mu;)</sup> / (x - &mu;)<sup>3/2</sup>
* </code></div>
* <p>
* For this distribution, {@code X}, this method returns {@code P(X < x)}.
* If {@code x} is less than location parameter &mu;, {@code Double.NaN} is
* returned, as in these cases the distribution is not defined.
* </p>
*/
@Override
public double density(final double x) {
if (x < mu) {
return Double.NaN;
}
final double delta = x - mu;
final double f = halfC / delta;
return FastMath.sqrt(f / FastMath.PI) * FastMath.exp(-f) /delta;
}
/** {@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>
* <pre>
* f(x; u, c) = erfc (&radic; (c / 2 (x - u )))
* </pre>
*/
@Override
public double cumulativeProbability(final double x) {
if (x < mu) {
return Double.NaN;
}
return Erfc.value(FastMath.sqrt(halfC / (x - mu)));
}
/** {@inheritDoc} */
@Override
public double inverseCumulativeProbability(final double p) throws OutOfRangeException {
if (p < 0.0 || p > 1.0) {
throw new OutOfRangeException(p, 0, 1);
}
final double t = InverseErfc.value(p);
return mu + halfC / (t * t);
}
/** Get the scale parameter of the distribution.
* @return scale parameter of the distribution
*/
public double getScale() {
return c;
}
/** Get the location parameter of the distribution.
* @return location parameter of the distribution
*/
public double getLocation() {
return mu;
}
/** {@inheritDoc} */
@Override
public double getNumericalMean() {
return Double.POSITIVE_INFINITY;
}
/** {@inheritDoc} */
@Override
public double getNumericalVariance() {
return Double.POSITIVE_INFINITY;
}
/** {@inheritDoc} */
@Override
public double getSupportLowerBound() {
return mu;
}
/** {@inheritDoc} */
@Override
public double getSupportUpperBound() {
return Double.POSITIVE_INFINITY;
}
/** {@inheritDoc} */
@Override
public boolean isSupportConnected() {
return true;
}
}

View File

@ -1,312 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.math4.exception.NumberIsTooLargeException;
import org.apache.commons.math4.exception.util.LocalizedFormats;
import org.apache.commons.numbers.gamma.Erf;
import org.apache.commons.numbers.gamma.ErfDifference;
import org.apache.commons.math4.util.FastMath;
import org.apache.commons.rng.UniformRandomProvider;
import org.apache.commons.rng.sampling.distribution.ContinuousSampler;
import org.apache.commons.rng.sampling.distribution.LogNormalSampler;
import org.apache.commons.rng.sampling.distribution.ZigguratNormalizedGaussianSampler;
/**
* Implementation of the log-normal (gaussian) distribution.
*
* <p>
* <strong>Parameters:</strong>
* {@code X} is log-normally distributed if its natural logarithm {@code log(X)}
* is normally distributed. The probability distribution function of {@code X}
* is given by (for {@code x > 0})
* </p>
* <p>
* {@code exp(-0.5 * ((ln(x) - m) / s)^2) / (s * sqrt(2 * pi) * x)}
* </p>
* <ul>
* <li>{@code m} is the <em>scale</em> parameter: this is the mean of the
* normally distributed natural logarithm of this distribution,</li>
* <li>{@code s} is the <em>shape</em> parameter: this is the standard
* deviation of the normally distributed natural logarithm of this
* distribution.
* </ul>
*
* @see <a href="http://en.wikipedia.org/wiki/Log-normal_distribution">
* Log-normal distribution (Wikipedia)</a>
* @see <a href="http://mathworld.wolfram.com/LogNormalDistribution.html">
* Log Normal distribution (MathWorld)</a>
*
* @since 3.0
*/
public class LogNormalDistribution extends AbstractRealDistribution {
/** Default inverse cumulative probability accuracy. */
public static final double DEFAULT_INVERSE_ABSOLUTE_ACCURACY = 1e-9;
/** Serializable version identifier. */
private static final long serialVersionUID = 20120112;
/** &radic;(2 &pi;) */
private static final double SQRT2PI = FastMath.sqrt(2 * FastMath.PI);
/** &radic;(2) */
private static final double SQRT2 = FastMath.sqrt(2.0);
/** The scale parameter of this distribution. */
private final double scale;
/** 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;
/**
* Creates a log-normal distribution, where the mean and standard deviation
* of the {@link NormalDistribution normally distributed} natural
* logarithm of the log-normal distribution are equal to zero and one
* respectively. In other words, the scale of the returned distribution is
* {@code 0}, while its shape is {@code 1}.
*/
public LogNormalDistribution() {
this(0, 1);
}
/**
* Creates a log-normal distribution.
*
* @param scale Scale parameter of this distribution.
* @param shape Shape parameter of this distribution.
* @throws NotStrictlyPositiveException if {@code shape <= 0}.
*/
public LogNormalDistribution(double scale, double shape)
throws NotStrictlyPositiveException {
this(scale, shape, DEFAULT_INVERSE_ABSOLUTE_ACCURACY);
}
/**
* Creates a log-normal distribution.
*
* @param scale Scale parameter of this distribution.
* @param shape Shape parameter of this distribution.
* @param inverseCumAccuracy Inverse cumulative probability accuracy.
* @throws NotStrictlyPositiveException if {@code shape <= 0}.
*/
public LogNormalDistribution(double scale,
double shape,
double inverseCumAccuracy)
throws NotStrictlyPositiveException {
if (shape <= 0) {
throw new NotStrictlyPositiveException(LocalizedFormats.SHAPE, shape);
}
this.scale = scale;
this.shape = shape;
this.logShapePlusHalfLog2Pi = FastMath.log(shape) + 0.5 * FastMath.log(2 * FastMath.PI);
this.solverAbsoluteAccuracy = inverseCumAccuracy;
}
/**
* Returns the scale parameter of this distribution.
*
* @return the scale parameter
*/
public double getScale() {
return scale;
}
/**
* Returns the shape parameter of this distribution.
*
* @return the shape parameter
*/
public double getShape() {
return shape;
}
/**
* {@inheritDoc}
*
* For scale {@code m}, and shape {@code s} of this distribution, the PDF
* is given by
* <ul>
* <li>{@code 0} if {@code x <= 0},</li>
* <li>{@code exp(-0.5 * ((ln(x) - m) / s)^2) / (s * sqrt(2 * pi) * x)}
* otherwise.</li>
* </ul>
*/
@Override
public double density(double x) {
if (x <= 0) {
return 0;
}
final double x0 = FastMath.log(x) - scale;
final double x1 = x0 / shape;
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}
*
* For scale {@code m}, and shape {@code s} of this distribution, the CDF
* is given by
* <ul>
* <li>{@code 0} if {@code x <= 0},</li>
* <li>{@code 0} if {@code ln(x) - m < 0} and {@code m - ln(x) > 40 * s}, as
* in these cases the actual value is within {@code Double.MIN_VALUE} of 0,
* <li>{@code 1} if {@code ln(x) - m >= 0} and {@code ln(x) - m > 40 * s},
* as in these cases the actual value is within {@code Double.MIN_VALUE} of
* 1,</li>
* <li>{@code 0.5 + 0.5 * erf((ln(x) - m) / (s * sqrt(2))} otherwise.</li>
* </ul>
*/
@Override
public double cumulativeProbability(double x) {
if (x <= 0) {
return 0;
}
final double dev = FastMath.log(x) - scale;
if (FastMath.abs(dev) > 40 * shape) {
return dev < 0 ? 0.0d : 1.0d;
}
return 0.5 + 0.5 * Erf.value(dev / (shape * SQRT2));
}
/** {@inheritDoc} */
@Override
public double probability(double x0,
double x1)
throws NumberIsTooLargeException {
if (x0 > x1) {
throw new NumberIsTooLargeException(LocalizedFormats.LOWER_ENDPOINT_ABOVE_UPPER_ENDPOINT,
x0, x1, true);
}
if (x0 <= 0 || x1 <= 0) {
return super.probability(x0, x1);
}
final double denom = shape * SQRT2;
final double v0 = (FastMath.log(x0) - scale) / denom;
final double v1 = (FastMath.log(x1) - scale) / denom;
return 0.5 * ErfDifference.value(v0, v1);
}
/** {@inheritDoc} */
@Override
protected double getSolverAbsoluteAccuracy() {
return solverAbsoluteAccuracy;
}
/**
* {@inheritDoc}
*
* For scale {@code m} and shape {@code s}, the mean is
* {@code exp(m + s^2 / 2)}.
*/
@Override
public double getNumericalMean() {
double s = shape;
return FastMath.exp(scale + (s * s / 2));
}
/**
* {@inheritDoc}
*
* For scale {@code m} and shape {@code s}, the variance is
* {@code (exp(s^2) - 1) * exp(2 * m + s^2)}.
*/
@Override
public double getNumericalVariance() {
final double s = shape;
final double ss = s * s;
return (FastMath.expm1(ss)) * FastMath.exp(2 * scale + ss);
}
/**
* {@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
* {@code Double.POSITIVE_INFINITY})
*/
@Override
public double getSupportUpperBound() {
return Double.POSITIVE_INFINITY;
}
/**
* {@inheritDoc}
*
* The support of this distribution is connected.
*
* @return {@code true}
*/
@Override
public boolean isSupportConnected() {
return true;
}
/** {@inheritDoc} */
@Override
public RealDistribution.Sampler createSampler(final UniformRandomProvider rng) {
return new RealDistribution.Sampler() {
/**
* Log normal distribution sampler.
*/
private final ContinuousSampler sampler =
new LogNormalSampler(new ZigguratNormalizedGaussianSampler(rng), scale, shape);
/**{@inheritDoc} */
@Override
public double sample() {
return sampler.sample();
}
};
}
}

View File

@ -1,136 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.math4.exception.OutOfRangeException;
import org.apache.commons.math4.exception.util.LocalizedFormats;
import org.apache.commons.math4.util.FastMath;
import org.apache.commons.math4.util.MathUtils;
/**
* This class implements the Logistic distribution.
*
* @see <a href="http://en.wikipedia.org/wiki/Logistic_distribution">Logistic Distribution (Wikipedia)</a>
* @see <a href="http://mathworld.wolfram.com/LogisticDistribution.html">Logistic Distribution (Mathworld)</a>
*
* @since 3.4
*/
public class LogisticDistribution extends AbstractRealDistribution {
/** Serializable version identifier. */
private static final long serialVersionUID = 20160311L;
/** The location parameter. */
private final double mu;
/** The scale parameter. */
private final double s;
/**
* Creates a distribution.
*
* @param mu location parameter
* @param s scale parameter (must be positive)
* @throws NotStrictlyPositiveException if {@code beta <= 0}
*/
public LogisticDistribution(double mu,
double s) {
if (s <= 0.0) {
throw new NotStrictlyPositiveException(LocalizedFormats.NOT_POSITIVE_SCALE, s);
}
this.mu = mu;
this.s = s;
}
/**
* Access the location parameter, {@code mu}.
*
* @return the location parameter.
*/
public double getLocation() {
return mu;
}
/**
* Access the scale parameter, {@code s}.
*
* @return the scale parameter.
*/
public double getScale() {
return s;
}
/** {@inheritDoc} */
@Override
public double density(double x) {
double z = (x - mu) / s;
double v = FastMath.exp(-z);
return 1 / s * v / ((1.0 + v) * (1.0 + v));
}
/** {@inheritDoc} */
@Override
public double cumulativeProbability(double x) {
double z = 1 / s * (x - mu);
return 1.0 / (1.0 + FastMath.exp(-z));
}
/** {@inheritDoc} */
@Override
public double inverseCumulativeProbability(double p) throws OutOfRangeException {
if (p < 0.0 || p > 1.0) {
throw new OutOfRangeException(p, 0.0, 1.0);
} else if (p == 0) {
return 0.0;
} else if (p == 1) {
return Double.POSITIVE_INFINITY;
}
return s * Math.log(p / (1.0 - p)) + mu;
}
/** {@inheritDoc} */
@Override
public double getNumericalMean() {
return mu;
}
/** {@inheritDoc} */
@Override
public double getNumericalVariance() {
return (MathUtils.PI_SQUARED / 3.0) * (1.0 / (s * s));
}
/** {@inheritDoc} */
@Override
public double getSupportLowerBound() {
return Double.NEGATIVE_INFINITY;
}
/** {@inheritDoc} */
@Override
public double getSupportUpperBound() {
return Double.POSITIVE_INFINITY;
}
/** {@inheritDoc} */
@Override
public boolean isSupportConnected() {
return true;
}
}

View File

@ -1,157 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.math4.exception.NumberIsTooSmallException;
import org.apache.commons.math4.exception.util.LocalizedFormats;
import org.apache.commons.numbers.gamma.Gamma;
import org.apache.commons.numbers.gamma.RegularizedGamma;
import org.apache.commons.math4.util.FastMath;
/**
* This class implements the Nakagami distribution.
*
* @see <a href="http://en.wikipedia.org/wiki/Nakagami_distribution">Nakagami Distribution (Wikipedia)</a>
*
* @since 3.4
*/
public class NakagamiDistribution extends AbstractRealDistribution {
/** Default inverse cumulative probability accuracy. */
public static final double DEFAULT_INVERSE_ABSOLUTE_ACCURACY = 1e-9;
/** Serializable version identifier. */
private static final long serialVersionUID = 20160311L;
/** The shape parameter. */
private final double mu;
/** The scale parameter. */
private final double omega;
/** Inverse cumulative probability accuracy. */
private final double inverseAbsoluteAccuracy;
/**
* Creates a distribution.
*
* @param mu shape parameter
* @param omega scale parameter (must be positive)
* @throws NumberIsTooSmallException if {@code mu < 0.5}
* @throws NotStrictlyPositiveException if {@code omega <= 0}
*/
public NakagamiDistribution(double mu,
double omega) {
this(mu, omega, DEFAULT_INVERSE_ABSOLUTE_ACCURACY);
}
/**
* Creates a distribution.
*
* @param mu shape parameter
* @param omega scale parameter (must be positive)
* @param inverseAbsoluteAccuracy the maximum absolute error in inverse
* cumulative probability estimates (defaults to {@link #DEFAULT_INVERSE_ABSOLUTE_ACCURACY}).
* @throws NumberIsTooSmallException if {@code mu < 0.5}
* @throws NotStrictlyPositiveException if {@code omega <= 0}
*/
public NakagamiDistribution(double mu,
double omega,
double inverseAbsoluteAccuracy) {
if (mu < 0.5) {
throw new NumberIsTooSmallException(mu, 0.5, true);
}
if (omega <= 0) {
throw new NotStrictlyPositiveException(LocalizedFormats.NOT_POSITIVE_SCALE, omega);
}
this.mu = mu;
this.omega = omega;
this.inverseAbsoluteAccuracy = inverseAbsoluteAccuracy;
}
/**
* Access the shape parameter, {@code mu}.
*
* @return the shape parameter.
*/
public double getShape() {
return mu;
}
/**
* Access the scale parameter, {@code omega}.
*
* @return the scale parameter.
*/
public double getScale() {
return omega;
}
/** {@inheritDoc} */
@Override
protected double getSolverAbsoluteAccuracy() {
return inverseAbsoluteAccuracy;
}
/** {@inheritDoc} */
@Override
public double density(double x) {
if (x <= 0) {
return 0.0;
}
return 2.0 * FastMath.pow(mu, mu) / (Gamma.value(mu) * FastMath.pow(omega, mu)) *
FastMath.pow(x, 2 * mu - 1) * FastMath.exp(-mu * x * x / omega);
}
/** {@inheritDoc} */
@Override
public double cumulativeProbability(double x) {
return RegularizedGamma.P.value(mu, mu * x * x / omega);
}
/** {@inheritDoc} */
@Override
public double getNumericalMean() {
return Gamma.value(mu + 0.5) / Gamma.value(mu) * FastMath.sqrt(omega / mu);
}
/** {@inheritDoc} */
@Override
public double getNumericalVariance() {
double v = Gamma.value(mu + 0.5) / Gamma.value(mu);
return omega * (1 - 1 / mu * v * v);
}
/** {@inheritDoc} */
@Override
public double getSupportLowerBound() {
return 0;
}
/** {@inheritDoc} */
@Override
public double getSupportUpperBound() {
return Double.POSITIVE_INFINITY;
}
/** {@inheritDoc} */
@Override
public boolean isSupportConnected() {
return true;
}
}

View File

@ -1,261 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.math4.exception.NumberIsTooLargeException;
import org.apache.commons.math4.exception.OutOfRangeException;
import org.apache.commons.math4.exception.util.LocalizedFormats;
import org.apache.commons.numbers.gamma.Erfc;
import org.apache.commons.numbers.gamma.InverseErf;
import org.apache.commons.numbers.gamma.ErfDifference;
import org.apache.commons.math4.util.FastMath;
import org.apache.commons.rng.UniformRandomProvider;
import org.apache.commons.rng.sampling.distribution.ContinuousSampler;
import org.apache.commons.rng.sampling.distribution.GaussianSampler;
import org.apache.commons.rng.sampling.distribution.MarsagliaNormalizedGaussianSampler;
/**
* Implementation of the normal (gaussian) distribution.
*
* @see <a href="http://en.wikipedia.org/wiki/Normal_distribution">Normal distribution (Wikipedia)</a>
* @see <a href="http://mathworld.wolfram.com/NormalDistribution.html">Normal distribution (MathWorld)</a>
*/
public class NormalDistribution extends AbstractRealDistribution {
/**
* Default inverse cumulative probability accuracy.
* @since 2.1
*/
public static final double DEFAULT_INVERSE_ABSOLUTE_ACCURACY = 1e-9;
/** Serializable version identifier. */
private static final long serialVersionUID = 8589540077390120676L;
/** &radic;(2) */
private static final double SQRT2 = FastMath.sqrt(2.0);
/** Mean of this distribution. */
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;
/**
* Create a normal distribution with mean equal to zero and standard
* deviation equal to one.
*/
public NormalDistribution() {
this(0, 1);
}
/**
* Creates a distribution.
*
* @param mean Mean for this distribution.
* @param sd Standard deviation for this distribution.
* @throws NotStrictlyPositiveException if {@code sd <= 0}.
*/
public NormalDistribution(double mean,
double sd)
throws NotStrictlyPositiveException {
this(mean, sd, DEFAULT_INVERSE_ABSOLUTE_ACCURACY);
}
/**
* Creates a distribution.
*
* @param mean Mean for this distribution.
* @param sd Standard deviation for this distribution.
* @param inverseCumAccuracy Inverse cumulative probability accuracy.
* @throws NotStrictlyPositiveException if {@code sd <= 0}.
*/
public NormalDistribution(double mean,
double sd,
double inverseCumAccuracy)
throws NotStrictlyPositiveException {
if (sd <= 0) {
throw new NotStrictlyPositiveException(LocalizedFormats.STANDARD_DEVIATION, sd);
}
this.mean = mean;
standardDeviation = sd;
logStandardDeviationPlusHalfLog2Pi = FastMath.log(sd) + 0.5 * FastMath.log(2 * FastMath.PI);
solverAbsoluteAccuracy = inverseCumAccuracy;
}
/**
* Access the mean.
*
* @return the mean for this distribution.
*/
public double getMean() {
return mean;
}
/**
* Access the standard deviation.
*
* @return the standard deviation for this distribution.
*/
public double getStandardDeviation() {
return standardDeviation;
}
/** {@inheritDoc} */
@Override
public double density(double x) {
return FastMath.exp(logDensity(x));
}
/** {@inheritDoc} */
@Override
public double logDensity(double x) {
final double x0 = x - mean;
final double x1 = x0 / standardDeviation;
return -0.5 * x1 * x1 - logStandardDeviationPlusHalfLog2Pi;
}
/**
* {@inheritDoc}
*
* If {@code x} is more than 40 standard deviations from the mean, 0 or 1
* is returned, as in these cases the actual value is within
* {@code Double.MIN_VALUE} of 0 or 1.
*/
@Override
public double cumulativeProbability(double x) {
final double dev = x - mean;
if (FastMath.abs(dev) > 40 * standardDeviation) {
return dev < 0 ? 0.0d : 1.0d;
}
return 0.5 * Erfc.value(-dev / (standardDeviation * SQRT2));
}
/** {@inheritDoc}
* @since 3.2
*/
@Override
public double inverseCumulativeProbability(final double p) throws OutOfRangeException {
if (p < 0.0 || p > 1.0) {
throw new OutOfRangeException(p, 0, 1);
}
return mean + standardDeviation * SQRT2 * InverseErf.value(2 * p - 1);
}
/** {@inheritDoc} */
@Override
public double probability(double x0,
double x1)
throws NumberIsTooLargeException {
if (x0 > x1) {
throw new NumberIsTooLargeException(LocalizedFormats.LOWER_ENDPOINT_ABOVE_UPPER_ENDPOINT,
x0, x1, true);
}
final double denom = standardDeviation * SQRT2;
final double v0 = (x0 - mean) / denom;
final double v1 = (x1 - mean) / denom;
return 0.5 * ErfDifference.value(v0, v1);
}
/** {@inheritDoc} */
@Override
protected double getSolverAbsoluteAccuracy() {
return solverAbsoluteAccuracy;
}
/**
* {@inheritDoc}
*
* For mean parameter {@code mu}, the mean is {@code mu}.
*/
@Override
public double getNumericalMean() {
return getMean();
}
/**
* {@inheritDoc}
*
* For standard deviation parameter {@code s}, the variance is {@code s^2}.
*/
@Override
public double getNumericalVariance() {
final double s = getStandardDeviation();
return s * s;
}
/**
* {@inheritDoc}
*
* The lower bound of the support is always negative infinity
* no matter the parameters.
*
* @return lower bound of the support (always
* {@code 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
* {@code Double.POSITIVE_INFINITY})
*/
@Override
public double getSupportUpperBound() {
return Double.POSITIVE_INFINITY;
}
/**
* {@inheritDoc}
*
* The support of this distribution is connected.
*
* @return {@code true}
*/
@Override
public boolean isSupportConnected() {
return true;
}
/** {@inheritDoc} */
@Override
public RealDistribution.Sampler createSampler(final UniformRandomProvider rng) {
return new RealDistribution.Sampler() {
/**
* Gaussian distribution sampler.
*/
private final ContinuousSampler sampler =
new GaussianSampler(new MarsagliaNormalizedGaussianSampler(rng),
mean, standardDeviation);
/**{@inheritDoc} */
@Override
public double sample() {
return sampler.sample();
}
};
}
}

View File

@ -1,269 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.math4.exception.util.LocalizedFormats;
import org.apache.commons.math4.util.FastMath;
import org.apache.commons.rng.UniformRandomProvider;
import org.apache.commons.rng.sampling.distribution.ContinuousSampler;
import org.apache.commons.rng.sampling.distribution.InverseTransformParetoSampler;
/**
* Implementation of the Pareto distribution.
*
* <p>
* <strong>Parameters:</strong>
* The probability distribution function of {@code X} is given by (for {@code x >= k}):
* <pre>
* α * k^α / x^(α + 1)
* </pre>
* <ul>
* <li>{@code k} is the <em>scale</em> parameter: this is the minimum possible value of {@code X},</li>
* <li>{@code α} is the <em>shape</em> parameter: this is the Pareto index</li>
* </ul>
*
* @see <a href="http://en.wikipedia.org/wiki/Pareto_distribution">
* Pareto distribution (Wikipedia)</a>
* @see <a href="http://mathworld.wolfram.com/ParetoDistribution.html">
* Pareto distribution (MathWorld)</a>
*
* @since 3.3
*/
public class ParetoDistribution extends AbstractRealDistribution {
/** Default inverse cumulative probability accuracy. */
public static final double DEFAULT_INVERSE_ABSOLUTE_ACCURACY = 1e-9;
/** Serializable version identifier. */
private static final long serialVersionUID = 20160311L;
/** The scale parameter of this distribution. */
private final double scale;
/** The shape parameter of this distribution. */
private final double shape;
/** Inverse cumulative probability accuracy. */
private final double solverAbsoluteAccuracy;
/**
* Creates a Pareto distribution with a scale of {@code 1} and a shape of {@code 1}.
*/
public ParetoDistribution() {
this(1, 1);
}
/**
* Creates a Pareto distribution.
*
* @param scale the scale parameter of this distribution
* @param shape the shape parameter of this distribution
* @throws NotStrictlyPositiveException if {@code scale <= 0} or {@code shape <= 0}.
*/
public ParetoDistribution(double scale,
double shape)
throws NotStrictlyPositiveException {
this(scale, shape, DEFAULT_INVERSE_ABSOLUTE_ACCURACY);
}
/**
* Creates a Pareto distribution.
*
* @param scale Scale parameter of this distribution.
* @param shape Shape parameter of this distribution.
* @param inverseCumAccuracy Inverse cumulative probability accuracy.
* @throws NotStrictlyPositiveException if {@code scale <= 0} or {@code shape <= 0}.
*/
public ParetoDistribution(double scale,
double shape,
double inverseCumAccuracy)
throws NotStrictlyPositiveException {
if (scale <= 0) {
throw new NotStrictlyPositiveException(LocalizedFormats.SCALE, scale);
}
if (shape <= 0) {
throw new NotStrictlyPositiveException(LocalizedFormats.SHAPE, shape);
}
this.scale = scale;
this.shape = shape;
this.solverAbsoluteAccuracy = inverseCumAccuracy;
}
/**
* Returns the scale parameter of this distribution.
*
* @return the scale parameter
*/
public double getScale() {
return scale;
}
/**
* Returns the shape parameter of this distribution.
*
* @return the shape parameter
*/
public double getShape() {
return shape;
}
/**
* {@inheritDoc}
* <p>
* For scale {@code k}, and shape {@code α} of this distribution, the PDF
* is given by
* <ul>
* <li>{@code 0} if {@code x < k},</li>
* <li>{@code α * k^α / x^(α + 1)} otherwise.</li>
* </ul>
*/
@Override
public double density(double x) {
if (x < scale) {
return 0;
}
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>
* For scale {@code k}, and shape {@code α} of this distribution, the CDF is given by
* <ul>
* <li>{@code 0} if {@code x < k},</li>
* <li>{@code 1 - (k / x)^α} otherwise.</li>
* </ul>
*/
@Override
public double cumulativeProbability(double x) {
if (x <= scale) {
return 0;
}
return 1 - FastMath.pow(scale / x, shape);
}
/** {@inheritDoc} */
@Override
protected double getSolverAbsoluteAccuracy() {
return solverAbsoluteAccuracy;
}
/**
* {@inheritDoc}
* <p>
* For scale {@code k} and shape {@code α}, the mean is given by
* <ul>
* <li>{@code } if {@code α <= 1},</li>
* <li>{@code α * k / (α - 1)} otherwise.</li>
* </ul>
*/
@Override
public double getNumericalMean() {
if (shape <= 1) {
return Double.POSITIVE_INFINITY;
}
return shape * scale / (shape - 1);
}
/**
* {@inheritDoc}
* <p>
* For scale {@code k} and shape {@code α}, the variance is given by
* <ul>
* <li>{@code } if {@code 1 < α <= 2},</li>
* <li>{@code k^2 * α / ((α - 1)^2 * (α - 2))} otherwise.</li>
* </ul>
*/
@Override
public double getNumericalVariance() {
if (shape <= 2) {
return Double.POSITIVE_INFINITY;
}
double s = shape - 1;
return scale * scale * shape / (s * s) / (shape - 2);
}
/**
* {@inheritDoc}
* <p>
* The lower bound of the support is equal to the scale parameter {@code k}.
*
* @return lower bound of the support
*/
@Override
public double getSupportLowerBound() {
return scale;
}
/**
* {@inheritDoc}
* <p>
* The upper bound of the support is always positive infinity no matter the parameters.
*
* @return upper bound of the support (always {@code Double.POSITIVE_INFINITY})
*/
@Override
public double getSupportUpperBound() {
return Double.POSITIVE_INFINITY;
}
/**
* {@inheritDoc}
* <p>
* The support of this distribution is connected.
*
* @return {@code true}
*/
@Override
public boolean isSupportConnected() {
return true;
}
/** {@inheritDoc} */
@Override
public RealDistribution.Sampler createSampler(final UniformRandomProvider rng) {
return new RealDistribution.Sampler() {
/**
* Pareto distribution sampler.
*/
private final ContinuousSampler sampler =
new InverseTransformParetoSampler(rng, scale, shape);
/**{@inheritDoc} */
@Override
public double sample() {
return sampler.sample();
}
};
}
}

View File

@ -1,228 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.math4.exception.OutOfRangeException;
import org.apache.commons.math4.exception.util.LocalizedFormats;
import org.apache.commons.numbers.combinatorics.BinomialCoefficientDouble;
import org.apache.commons.numbers.combinatorics.LogBinomialCoefficient;
import org.apache.commons.numbers.gamma.RegularizedBeta;
import org.apache.commons.math4.util.FastMath;
/**
* <p>
* Implementation of the Pascal distribution. The Pascal distribution is a
* special case of the Negative Binomial distribution where the number of
* successes parameter is an integer.
* </p>
* <p>
* There are various ways to express the probability mass and distribution
* functions for the Pascal distribution. The present implementation represents
* the distribution of the number of failures before {@code r} successes occur.
* This is the convention adopted in e.g.
* <a href="http://mathworld.wolfram.com/NegativeBinomialDistribution.html">MathWorld</a>,
* but <em>not</em> in
* <a href="http://en.wikipedia.org/wiki/Negative_binomial_distribution">Wikipedia</a>.
* </p>
* <p>
* For a random variable {@code X} whose values are distributed according to this
* distribution, the probability mass function is given by<br>
* {@code P(X = k) = C(k + r - 1, r - 1) * p^r * (1 - p)^k,}<br>
* where {@code r} is the number of successes, {@code p} is the probability of
* success, and {@code X} is the total number of failures. {@code C(n, k)} is
* the binomial coefficient ({@code n} choose {@code k}). The mean and variance
* of {@code X} are<br>
* {@code E(X) = (1 - p) * r / p, var(X) = (1 - p) * r / p^2.}<br>
* Finally, the cumulative distribution function is given by<br>
* {@code P(X <= k) = I(p, r, k + 1)},
* where I is the regularized incomplete Beta function.
* </p>
*
* @see <a href="http://en.wikipedia.org/wiki/Negative_binomial_distribution">
* Negative binomial distribution (Wikipedia)</a>
* @see <a href="http://mathworld.wolfram.com/NegativeBinomialDistribution.html">
* Negative binomial distribution (MathWorld)</a>
* @since 1.2 (changed to concrete class in 3.0)
*/
public class PascalDistribution extends AbstractIntegerDistribution {
/** Serializable version identifier. */
private static final long serialVersionUID = 6751309484392813623L;
/** The number of successes. */
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
* probability of success.
*
* @param r Number of successes.
* @param p Probability of success.
* @throws NotStrictlyPositiveException if the number of successes is not positive
* @throws OutOfRangeException if the probability of success is not in the
* range {@code [0, 1]}.
*/
public PascalDistribution(int r,
double p)
throws NotStrictlyPositiveException,
OutOfRangeException {
if (r <= 0) {
throw new NotStrictlyPositiveException(LocalizedFormats.NUMBER_OF_SUCCESSES,
r);
}
if (p < 0 || p > 1) {
throw new OutOfRangeException(p, 0, 1);
}
numberOfSuccesses = r;
probabilityOfSuccess = p;
logProbabilityOfSuccess = FastMath.log(p);
log1mProbabilityOfSuccess = FastMath.log1p(-p);
}
/**
* Access the number of successes for this distribution.
*
* @return the number of successes.
*/
public int getNumberOfSuccesses() {
return numberOfSuccesses;
}
/**
* Access the probability of success for this distribution.
*
* @return the probability of success.
*/
public double getProbabilityOfSuccess() {
return probabilityOfSuccess;
}
/** {@inheritDoc} */
@Override
public double probability(int x) {
double ret;
if (x < 0) {
ret = 0.0;
} else {
ret = BinomialCoefficientDouble.value(x +
numberOfSuccesses - 1, numberOfSuccesses - 1) *
FastMath.pow(probabilityOfSuccess, numberOfSuccesses) *
FastMath.pow(1.0 - probabilityOfSuccess, x);
}
return ret;
}
/** {@inheritDoc} */
@Override
public double logProbability(int x) {
double ret;
if (x < 0) {
ret = Double.NEGATIVE_INFINITY;
} else {
ret = LogBinomialCoefficient.value(x +
numberOfSuccesses - 1, numberOfSuccesses - 1) +
logProbabilityOfSuccess * numberOfSuccesses +
log1mProbabilityOfSuccess * x;
}
return ret;
}
/** {@inheritDoc} */
@Override
public double cumulativeProbability(int x) {
double ret;
if (x < 0) {
ret = 0.0;
} else {
ret = RegularizedBeta.value(probabilityOfSuccess,
numberOfSuccesses, x + 1.0);
}
return ret;
}
/**
* {@inheritDoc}
*
* For number of successes {@code r} and probability of success {@code p},
* the mean is {@code r * (1 - p) / p}.
*/
@Override
public double getNumericalMean() {
final double p = getProbabilityOfSuccess();
final double r = getNumberOfSuccesses();
return (r * (1 - p)) / p;
}
/**
* {@inheritDoc}
*
* For number of successes {@code r} and probability of success {@code p},
* the variance is {@code r * (1 - p) / p^2}.
*/
@Override
public double getNumericalVariance() {
final double p = getProbabilityOfSuccess();
final double r = getNumberOfSuccesses();
return r * (1 - p) / (p * p);
}
/**
* {@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 symbolized by {@code Integer.MAX_VALUE}.
*
* @return upper bound of the support (always {@code Integer.MAX_VALUE}
* for positive infinity)
*/
@Override
public int getSupportUpperBound() {
return Integer.MAX_VALUE;
}
/**
* {@inheritDoc}
*
* The support of this distribution is connected.
*
* @return {@code true}
*/
@Override
public boolean isSupportConnected() {
return true;
}
}

View File

@ -1,259 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.math4.exception.util.LocalizedFormats;
import org.apache.commons.numbers.gamma.RegularizedGamma;
import org.apache.commons.math4.util.FastMath;
import org.apache.commons.math4.util.MathUtils;
import org.apache.commons.rng.UniformRandomProvider;
import org.apache.commons.rng.sampling.distribution.DiscreteSampler;
import org.apache.commons.rng.sampling.distribution.PoissonSampler;
/**
* Implementation of the Poisson distribution.
*
* @see <a href="http://en.wikipedia.org/wiki/Poisson_distribution">Poisson distribution (Wikipedia)</a>
* @see <a href="http://mathworld.wolfram.com/PoissonDistribution.html">Poisson distribution (MathWorld)</a>
*/
public class PoissonDistribution extends AbstractIntegerDistribution {
/**
* Default maximum number of iterations for cumulative probability calculations.
* @since 2.1
*/
private static final int DEFAULT_MAX_ITERATIONS = 10000000;
/**
* Default convergence criterion.
* @since 2.1
*/
private static final double DEFAULT_EPSILON = 1e-12;
/** Serializable version identifier. */
private static final long serialVersionUID = -3349935121172596109L;
/** Distribution used to compute normal approximation. */
private final NormalDistribution normal;
/** Mean of the distribution. */
private final double mean;
/** Maximum number of iterations for cumulative probability. */
private final int maxIterations;
/** Convergence criterion for cumulative probability. */
private final double epsilon;
/**
* Creates a new Poisson distribution with specified mean.
*
* @param p the Poisson mean
* @throws NotStrictlyPositiveException if {@code p <= 0}.
*/
public PoissonDistribution(double p)
throws NotStrictlyPositiveException {
this(p, DEFAULT_EPSILON, DEFAULT_MAX_ITERATIONS);
}
/**
* Creates a new Poisson distribution with specified mean, convergence
* criterion and maximum number of iterations.
*
* @param p Poisson mean.
* @param epsilon Convergence criterion for cumulative probabilities.
* @param maxIterations the maximum number of iterations for cumulative
* probabilities.
* @throws NotStrictlyPositiveException if {@code p <= 0}.
* @since 2.1
*/
public PoissonDistribution(double p,
double epsilon,
int maxIterations)
throws NotStrictlyPositiveException {
if (p <= 0) {
throw new NotStrictlyPositiveException(LocalizedFormats.MEAN, p);
}
mean = p;
this.epsilon = epsilon;
this.maxIterations = maxIterations;
normal = new NormalDistribution(p, FastMath.sqrt(p),
NormalDistribution.DEFAULT_INVERSE_ABSOLUTE_ACCURACY);
}
/**
* Creates a new Poisson distribution with the specified mean and
* convergence criterion.
*
* @param p Poisson mean.
* @param epsilon Convergence criterion for cumulative probabilities.
* @throws NotStrictlyPositiveException if {@code p <= 0}.
* @since 2.1
*/
public PoissonDistribution(double p, double epsilon)
throws NotStrictlyPositiveException {
this(p, epsilon, DEFAULT_MAX_ITERATIONS);
}
/**
* Creates a new Poisson distribution with the specified mean and maximum
* number of iterations.
*
* @param p Poisson mean.
* @param maxIterations Maximum number of iterations for cumulative
* probabilities.
* @since 2.1
*/
public PoissonDistribution(double p, int maxIterations) {
this(p, DEFAULT_EPSILON, maxIterations);
}
/**
* Get the mean for the distribution.
*
* @return the mean for the distribution.
*/
public double getMean() {
return mean;
}
/** {@inheritDoc} */
@Override
public double probability(int x) {
final double logProbability = logProbability(x);
return logProbability == Double.NEGATIVE_INFINITY ? 0 : FastMath.exp(logProbability);
}
/** {@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} */
@Override
public double cumulativeProbability(int x) {
if (x < 0) {
return 0;
}
if (x == Integer.MAX_VALUE) {
return 1;
}
return RegularizedGamma.Q.value((double) x + 1, mean, epsilon,
maxIterations);
}
/**
* Calculates the Poisson distribution function using a normal
* approximation. The {@code N(mean, sqrt(mean))} distribution is used
* to approximate the Poisson distribution. The computation uses
* "half-correction" (evaluating the normal distribution function at
* {@code x + 0.5}).
*
* @param x Upper bound, inclusive.
* @return the distribution function value calculated using a normal
* approximation.
*/
public double normalApproximateProbability(int x) {
// calculate the probability using half-correction
return normal.cumulativeProbability(x + 0.5);
}
/**
* {@inheritDoc}
*
* For mean parameter {@code p}, the mean is {@code p}.
*/
@Override
public double getNumericalMean() {
return getMean();
}
/**
* {@inheritDoc}
*
* For mean parameter {@code p}, the variance is {@code p}.
*/
@Override
public double getNumericalVariance() {
return getMean();
}
/**
* {@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 {@code Integer.MAX_VALUE}.
*
* @return upper bound of the support (always {@code Integer.MAX_VALUE} for
* positive infinity)
*/
@Override
public int getSupportUpperBound() {
return Integer.MAX_VALUE;
}
/**
* {@inheritDoc}
*
* The support of this distribution is connected.
*
* @return {@code true}
*/
@Override
public boolean isSupportConnected() {
return true;
}
/**{@inheritDoc} */
@Override
public IntegerDistribution.Sampler createSampler(final UniformRandomProvider rng) {
return new IntegerDistribution.Sampler() {
/**
* Poisson distribution sampler.
*/
private final DiscreteSampler sampler =
new PoissonSampler(rng, mean);
/**{@inheritDoc} */
@Override
public int sample() {
return sampler.sample();
}
};
}
}

View File

@ -1,218 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.math4.exception.util.LocalizedFormats;
import org.apache.commons.numbers.gamma.RegularizedBeta;
import org.apache.commons.numbers.gamma.LogGamma;
import org.apache.commons.math4.util.FastMath;
/**
* Implementation of Student's t-distribution.
*
* @see "<a href='http://en.wikipedia.org/wiki/Student&apos;s_t-distribution'>Student's t-distribution (Wikipedia)</a>"
* @see "<a href='http://mathworld.wolfram.com/Studentst-Distribution.html'>Student's t-distribution (MathWorld)</a>"
*/
public class TDistribution extends AbstractRealDistribution {
/**
* Default inverse cumulative probability accuracy.
* @since 2.1
*/
public static final double DEFAULT_INVERSE_ABSOLUTE_ACCURACY = 1e-9;
/** Serializable version identifier */
private static final long serialVersionUID = 20160311L;
/** The degrees of freedom. */
private final double degreesOfFreedom;
/** Inverse cumulative probability accuracy. */
private final double solverAbsoluteAccuracy;
/** Static computation factor based on degreesOfFreedom. */
private final double factor;
/**
* Creates a distribution.
*
* @param degreesOfFreedom Degrees of freedom.
* @throws NotStrictlyPositiveException if {@code degreesOfFreedom <= 0}
*/
public TDistribution(double degreesOfFreedom)
throws NotStrictlyPositiveException {
this(degreesOfFreedom, DEFAULT_INVERSE_ABSOLUTE_ACCURACY);
}
/**
* Creates a distribution.
*
* @param degreesOfFreedom Degrees of freedom.
* @param inverseCumAccuracy the maximum absolute error in inverse
* cumulative probability estimates
* (defaults to {@link #DEFAULT_INVERSE_ABSOLUTE_ACCURACY}).
* @throws NotStrictlyPositiveException if {@code degreesOfFreedom <= 0}
*/
public TDistribution(double degreesOfFreedom,
double inverseCumAccuracy)
throws NotStrictlyPositiveException {
if (degreesOfFreedom <= 0) {
throw new NotStrictlyPositiveException(LocalizedFormats.DEGREES_OF_FREEDOM,
degreesOfFreedom);
}
this.degreesOfFreedom = degreesOfFreedom;
solverAbsoluteAccuracy = inverseCumAccuracy;
final double n = degreesOfFreedom;
final double nPlus1Over2 = (n + 1) / 2;
factor = LogGamma.value(nPlus1Over2) -
0.5 * (FastMath.log(FastMath.PI) + FastMath.log(n)) -
LogGamma.value(n / 2);
}
/**
* Access the degrees of freedom.
*
* @return the degrees of freedom.
*/
public double getDegreesOfFreedom() {
return degreesOfFreedom;
}
/** {@inheritDoc} */
@Override
public double density(double x) {
return FastMath.exp(logDensity(x));
}
/** {@inheritDoc} */
@Override
public double logDensity(double x) {
final double n = degreesOfFreedom;
final double nPlus1Over2 = (n + 1) / 2;
return factor - nPlus1Over2 * FastMath.log(1 + x * x / n);
}
/** {@inheritDoc} */
@Override
public double cumulativeProbability(double x) {
double ret;
if (x == 0) {
ret = 0.5;
} else {
double t =
RegularizedBeta.value(degreesOfFreedom / (degreesOfFreedom + (x * x)),
0.5 * degreesOfFreedom,
0.5);
if (x < 0.0) {
ret = 0.5 * t;
} else {
ret = 1.0 - 0.5 * t;
}
}
return ret;
}
/** {@inheritDoc} */
@Override
protected double getSolverAbsoluteAccuracy() {
return solverAbsoluteAccuracy;
}
/**
* {@inheritDoc}
*
* For degrees of freedom parameter {@code df}, the mean is
* <ul>
* <li>if {@code df > 1} then {@code 0},</li>
* <li>else undefined ({@code Double.NaN}).</li>
* </ul>
*/
@Override
public double getNumericalMean() {
final double df = getDegreesOfFreedom();
if (df > 1) {
return 0;
}
return Double.NaN;
}
/**
* {@inheritDoc}
*
* For degrees of freedom parameter {@code df}, the variance is
* <ul>
* <li>if {@code df > 2} then {@code df / (df - 2)},</li>
* <li>if {@code 1 < df <= 2} then positive infinity
* ({@code Double.POSITIVE_INFINITY}),</li>
* <li>else undefined ({@code Double.NaN}).</li>
* </ul>
*/
@Override
public double getNumericalVariance() {
final double df = getDegreesOfFreedom();
if (df > 2) {
return df / (df - 2);
}
if (df > 1 && df <= 2) {
return Double.POSITIVE_INFINITY;
}
return Double.NaN;
}
/**
* {@inheritDoc}
*
* The lower bound of the support is always negative infinity no matter the
* parameters.
*
* @return lower bound of the support (always
* {@code 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
* {@code Double.POSITIVE_INFINITY})
*/
@Override
public double getSupportUpperBound() {
return Double.POSITIVE_INFINITY;
}
/**
* {@inheritDoc}
*
* The support of this distribution is connected.
*
* @return {@code true}
*/
@Override
public boolean isSupportConnected() {
return true;
}
}

View File

@ -1,253 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.exception.NumberIsTooLargeException;
import org.apache.commons.math4.exception.NumberIsTooSmallException;
import org.apache.commons.math4.exception.OutOfRangeException;
import org.apache.commons.math4.exception.util.LocalizedFormats;
import org.apache.commons.math4.util.FastMath;
/**
* Implementation of the triangular real distribution.
*
* @see <a href="http://en.wikipedia.org/wiki/Triangular_distribution">
* Triangular distribution (Wikipedia)</a>
*
* @since 3.0
*/
public class TriangularDistribution extends AbstractRealDistribution {
/** Serializable version identifier. */
private static final long serialVersionUID = 20160311L;
/** Lower limit of this distribution (inclusive). */
private final double a;
/** Upper limit of this distribution (inclusive). */
private final double b;
/** Mode of this distribution. */
private final double c;
/** Inverse cumulative probability accuracy. */
private final double solverAbsoluteAccuracy;
/**
* Creates a distribution.
*
* @param a Lower limit of this distribution (inclusive).
* @param b Upper limit of this distribution (inclusive).
* @param c Mode of this distribution.
* @throws NumberIsTooLargeException if {@code a >= b} or if {@code c > b}.
* @throws NumberIsTooSmallException if {@code c < a}.
* @since 3.1
*/
public TriangularDistribution(double a,
double c,
double b)
throws NumberIsTooLargeException,
NumberIsTooSmallException {
if (a >= b) {
throw new NumberIsTooLargeException(
LocalizedFormats.LOWER_BOUND_NOT_BELOW_UPPER_BOUND,
a, b, false);
}
if (c < a) {
throw new NumberIsTooSmallException(
LocalizedFormats.NUMBER_TOO_SMALL, c, a, true);
}
if (c > b) {
throw new NumberIsTooLargeException(
LocalizedFormats.NUMBER_TOO_LARGE, c, b, true);
}
this.a = a;
this.c = c;
this.b = b;
solverAbsoluteAccuracy = FastMath.max(FastMath.ulp(a), FastMath.ulp(b));
}
/**
* Returns the mode {@code c} of this distribution.
*
* @return the mode {@code c} of this distribution
*/
public double getMode() {
return c;
}
/**
* {@inheritDoc}
*
* <p>
* For this distribution, the returned value is not really meaningful,
* since exact formulas are implemented for the computation of the
* {@link #inverseCumulativeProbability(double)} (no solver is invoked).
* </p>
* <p>
* For lower limit {@code a} and upper limit {@code b}, the current
* implementation returns {@code max(ulp(a), ulp(b)}.
* </p>
*/
@Override
protected double getSolverAbsoluteAccuracy() {
return solverAbsoluteAccuracy;
}
/**
* {@inheritDoc}
*
* For lower limit {@code a}, upper limit {@code b} and mode {@code c}, the
* PDF is given by
* <ul>
* <li>{@code 2 * (x - a) / [(b - a) * (c - a)]} if {@code a <= x < c},</li>
* <li>{@code 2 / (b - a)} if {@code x = c},</li>
* <li>{@code 2 * (b - x) / [(b - a) * (b - c)]} if {@code c < x <= b},</li>
* <li>{@code 0} otherwise.
* </ul>
*/
@Override
public double density(double x) {
if (x < a) {
return 0;
}
if (a <= x && x < c) {
double divident = 2 * (x - a);
double divisor = (b - a) * (c - a);
return divident / divisor;
}
if (x == c) {
return 2 / (b - a);
}
if (c < x && x <= b) {
double divident = 2 * (b - x);
double divisor = (b - a) * (b - c);
return divident / divisor;
}
return 0;
}
/**
* {@inheritDoc}
*
* For lower limit {@code a}, upper limit {@code b} and mode {@code c}, the
* CDF is given by
* <ul>
* <li>{@code 0} if {@code x < a},</li>
* <li>{@code (x - a)^2 / [(b - a) * (c - a)]} if {@code a <= x < c},</li>
* <li>{@code (c - a) / (b - a)} if {@code x = c},</li>
* <li>{@code 1 - (b - x)^2 / [(b - a) * (b - c)]} if {@code c < x <= b},</li>
* <li>{@code 1} if {@code x > b}.</li>
* </ul>
*/
@Override
public double cumulativeProbability(double x) {
if (x < a) {
return 0;
}
if (a <= x && x < c) {
double divident = (x - a) * (x - a);
double divisor = (b - a) * (c - a);
return divident / divisor;
}
if (x == c) {
return (c - a) / (b - a);
}
if (c < x && x <= b) {
double divident = (b - x) * (b - x);
double divisor = (b - a) * (b - c);
return 1 - (divident / divisor);
}
return 1;
}
/**
* {@inheritDoc}
*
* For lower limit {@code a}, upper limit {@code b}, and mode {@code c},
* the mean is {@code (a + b + c) / 3}.
*/
@Override
public double getNumericalMean() {
return (a + b + c) / 3;
}
/**
* {@inheritDoc}
*
* For lower limit {@code a}, upper limit {@code b}, and mode {@code c},
* the variance is {@code (a^2 + b^2 + c^2 - a * b - a * c - b * c) / 18}.
*/
@Override
public double getNumericalVariance() {
return (a * a + b * b + c * c - a * b - a * c - b * c) / 18;
}
/**
* {@inheritDoc}
*
* The lower bound of the support is equal to the lower limit parameter
* {@code a} of the distribution.
*
* @return lower bound of the support
*/
@Override
public double getSupportLowerBound() {
return a;
}
/**
* {@inheritDoc}
*
* The upper bound of the support is equal to the upper limit parameter
* {@code b} of the distribution.
*
* @return upper bound of the support
*/
@Override
public double getSupportUpperBound() {
return b;
}
/**
* {@inheritDoc}
*
* The support of this distribution is connected.
*
* @return {@code true}
*/
@Override
public boolean isSupportConnected() {
return true;
}
/** {@inheritDoc} */
@Override
public double inverseCumulativeProbability(double p)
throws OutOfRangeException {
if (p < 0 || p > 1) {
throw new OutOfRangeException(p, 0, 1);
}
if (p == 0) {
return a;
}
if (p == 1) {
return b;
}
if (p < (c - a) / (b - a)) {
return a + FastMath.sqrt(p * (b - a) * (c - a));
}
return b - FastMath.sqrt((1 - p) * (b - a) * (b - c));
}
}

View File

@ -1,165 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.exception.NumberIsTooLargeException;
import org.apache.commons.math4.exception.util.LocalizedFormats;
import org.apache.commons.rng.UniformRandomProvider;
import org.apache.commons.rng.sampling.distribution.DiscreteSampler;
import org.apache.commons.rng.sampling.distribution.DiscreteUniformSampler;
/**
* Implementation of the <a href="http://en.wikipedia.org/wiki/Uniform_distribution_(discrete)">
* uniform integer distribution</a>.
*
* @since 3.0
*/
public class UniformIntegerDistribution extends AbstractIntegerDistribution {
/** Serializable version identifier. */
private static final long serialVersionUID = 20160308L;
/** Lower bound (inclusive) of this distribution. */
private final int lower;
/** Upper bound (inclusive) of this distribution. */
private final int upper;
/** "upper" + "lower" (to avoid overflow). */
private final double upperPlusLower;
/** "upper" - "lower" (to avoid overflow). */
private final double upperMinusLower;
/**
* Creates a new uniform integer distribution using the given lower and
* upper bounds (both inclusive).
*
* @param lower Lower bound (inclusive) of this distribution.
* @param upper Upper bound (inclusive) of this distribution.
* @throws NumberIsTooLargeException if {@code lower > upper}.
*/
public UniformIntegerDistribution(int lower,
int upper)
throws NumberIsTooLargeException {
if (lower > upper) {
throw new NumberIsTooLargeException(
LocalizedFormats.LOWER_BOUND_NOT_BELOW_UPPER_BOUND,
lower, upper, true);
}
this.lower = lower;
this.upper = upper;
upperPlusLower = (double) upper + (double) lower;
upperMinusLower = (double) upper - (double) lower;
}
/** {@inheritDoc} */
@Override
public double probability(int x) {
if (x < lower || x > upper) {
return 0;
}
return 1.0 / (upperMinusLower + 1);
}
/** {@inheritDoc} */
@Override
public double cumulativeProbability(int x) {
if (x < lower) {
return 0;
}
if (x > upper) {
return 1;
}
return (x - lower + 1.0) / (upperMinusLower + 1.0);
}
/**
* {@inheritDoc}
*
* For lower bound {@code lower} and upper bound {@code upper}, the mean is
* {@code 0.5 * (lower + upper)}.
*/
@Override
public double getNumericalMean() {
return 0.5 * upperPlusLower;
}
/**
* {@inheritDoc}
*
* For lower bound {@code lower} and upper bound {@code upper}, and
* {@code n = upper - lower + 1}, the variance is {@code (n^2 - 1) / 12}.
*/
@Override
public double getNumericalVariance() {
double n = upperMinusLower + 1;
return (n * n - 1) / 12.0;
}
/**
* {@inheritDoc}
*
* The lower bound of the support is equal to the lower bound parameter
* of the distribution.
*
* @return lower bound of the support
*/
@Override
public int getSupportLowerBound() {
return lower;
}
/**
* {@inheritDoc}
*
* The upper bound of the support is equal to the upper bound parameter
* of the distribution.
*
* @return upper bound of the support
*/
@Override
public int getSupportUpperBound() {
return upper;
}
/**
* {@inheritDoc}
*
* The support of this distribution is connected.
*
* @return {@code true}
*/
@Override
public boolean isSupportConnected() {
return true;
}
/**{@inheritDoc} */
@Override
public IntegerDistribution.Sampler createSampler(final UniformRandomProvider rng) {
return new IntegerDistribution.Sampler() {
/**
* Discrete uniform distribution sampler.
*/
private final DiscreteSampler sampler =
new DiscreteUniformSampler(rng, lower, upper);
/**{@inheritDoc} */
@Override
public int sample() {
return sampler.sample();
}
};
}
}

View File

@ -1,180 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.exception.NumberIsTooLargeException;
import org.apache.commons.math4.exception.OutOfRangeException;
import org.apache.commons.math4.exception.util.LocalizedFormats;
import org.apache.commons.rng.UniformRandomProvider;
import org.apache.commons.rng.sampling.distribution.ContinuousSampler;
import org.apache.commons.rng.sampling.distribution.ContinuousUniformSampler;
/**
* Implementation of the uniform real distribution.
*
* @see <a href="http://en.wikipedia.org/wiki/Uniform_distribution_(continuous)"
* >Uniform distribution (continuous), at Wikipedia</a>
*
* @since 3.0
*/
public class UniformRealDistribution extends AbstractRealDistribution {
/** Serializable version identifier. */
private static final long serialVersionUID = 20160311L;
/** Lower bound of this distribution (inclusive). */
private final double lower;
/** Upper bound of this distribution (exclusive). */
private final double upper;
/**
* Create a standard uniform real distribution with lower bound (inclusive)
* equal to zero and upper bound (exclusive) equal to one.
*/
public UniformRealDistribution() {
this(0, 1);
}
/**
* Creates a uniform distribution.
*
* @param lower Lower bound of this distribution (inclusive).
* @param upper Upper bound of this distribution (exclusive).
* @throws NumberIsTooLargeException if {@code lower >= upper}.
*/
public UniformRealDistribution(double lower,
double upper)
throws NumberIsTooLargeException {
if (lower >= upper) {
throw new NumberIsTooLargeException(
LocalizedFormats.LOWER_BOUND_NOT_BELOW_UPPER_BOUND,
lower, upper, false);
}
this.lower = lower;
this.upper = upper;
}
/** {@inheritDoc} */
@Override
public double density(double x) {
if (x < lower || x > upper) {
return 0.0;
}
return 1 / (upper - lower);
}
/** {@inheritDoc} */
@Override
public double cumulativeProbability(double x) {
if (x <= lower) {
return 0;
}
if (x >= upper) {
return 1;
}
return (x - lower) / (upper - lower);
}
/** {@inheritDoc} */
@Override
public double inverseCumulativeProbability(final double p)
throws OutOfRangeException {
if (p < 0.0 || p > 1.0) {
throw new OutOfRangeException(p, 0, 1);
}
return p * (upper - lower) + lower;
}
/**
* {@inheritDoc}
*
* For lower bound {@code lower} and upper bound {@code upper}, the mean is
* {@code 0.5 * (lower + upper)}.
*/
@Override
public double getNumericalMean() {
return 0.5 * (lower + upper);
}
/**
* {@inheritDoc}
*
* For lower bound {@code lower} and upper bound {@code upper}, the
* variance is {@code (upper - lower)^2 / 12}.
*/
@Override
public double getNumericalVariance() {
double ul = upper - lower;
return ul * ul / 12;
}
/**
* {@inheritDoc}
*
* The lower bound of the support is equal to the lower bound parameter
* of the distribution.
*
* @return lower bound of the support
*/
@Override
public double getSupportLowerBound() {
return lower;
}
/**
* {@inheritDoc}
*
* The upper bound of the support is equal to the upper bound parameter
* of the distribution.
*
* @return upper bound of the support
*/
@Override
public double getSupportUpperBound() {
return upper;
}
/**
* {@inheritDoc}
*
* The support of this distribution is connected.
*
* @return {@code true}
*/
@Override
public boolean isSupportConnected() {
return true;
}
/** {@inheritDoc} */
@Override
public RealDistribution.Sampler createSampler(final UniformRandomProvider rng) {
return new RealDistribution.Sampler() {
/**
* Uniform distribution sampler.
*/
private final ContinuousSampler sampler =
new ContinuousUniformSampler(rng, lower, upper);
/**{@inheritDoc} */
@Override
public double sample() {
return sampler.sample();
}
};
}
}

View File

@ -1,297 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.math4.exception.OutOfRangeException;
import org.apache.commons.math4.exception.util.LocalizedFormats;
import org.apache.commons.numbers.gamma.LogGamma;
import org.apache.commons.math4.util.FastMath;
/**
* Implementation of the Weibull distribution. This implementation uses the
* two parameter form of the distribution defined by
* <a href="http://mathworld.wolfram.com/WeibullDistribution.html">
* Weibull Distribution</a>, equations (1) and (2).
*
* @see <a href="http://en.wikipedia.org/wiki/Weibull_distribution">Weibull distribution (Wikipedia)</a>
* @see <a href="http://mathworld.wolfram.com/WeibullDistribution.html">Weibull distribution (MathWorld)</a>
*
* @since 1.1
*/
public class WeibullDistribution extends AbstractRealDistribution {
/**
* Default inverse cumulative probability accuracy.
* @since 2.1
*/
public static final double DEFAULT_INVERSE_ABSOLUTE_ACCURACY = 1e-9;
/** Serializable version identifier. */
private static final long serialVersionUID = 20160311L;
/** The shape parameter. */
private final double shape;
/** The scale parameter. */
private final double scale;
/** Inverse cumulative probability accuracy. */
private final double solverAbsoluteAccuracy;
/** Cached numerical mean */
private double numericalMean = Double.NaN;
/** Whether or not the numerical mean has been calculated */
private boolean numericalMeanIsCalculated = false;
/** Cached numerical variance */
private double numericalVariance = Double.NaN;
/** Whether or not the numerical variance has been calculated */
private boolean numericalVarianceIsCalculated = false;
/**
* Creates a distribution.
*
* @param alpha Shape parameter.
* @param beta Scale parameter.
* @throws NotStrictlyPositiveException if {@code alpha <= 0} or
* {@code beta <= 0}.
*/
public WeibullDistribution(double alpha, double beta)
throws NotStrictlyPositiveException {
this(alpha, beta, DEFAULT_INVERSE_ABSOLUTE_ACCURACY);
}
/**
* Creates a distribution.
*
* @param alpha Shape parameter.
* @param beta Scale parameter.
* @param inverseCumAccuracy Maximum absolute error in inverse
* cumulative probability estimates
* (defaults to {@link #DEFAULT_INVERSE_ABSOLUTE_ACCURACY}).
* @throws NotStrictlyPositiveException if {@code alpha <= 0} or {@code beta <= 0}.
*/
public WeibullDistribution(double alpha,
double beta,
double inverseCumAccuracy)
throws NotStrictlyPositiveException {
if (alpha <= 0) {
throw new NotStrictlyPositiveException(LocalizedFormats.SHAPE,
alpha);
}
if (beta <= 0) {
throw new NotStrictlyPositiveException(LocalizedFormats.SCALE,
beta);
}
scale = beta;
shape = alpha;
solverAbsoluteAccuracy = inverseCumAccuracy;
}
/**
* Access the shape parameter, {@code alpha}.
*
* @return the shape parameter, {@code alpha}.
*/
public double getShape() {
return shape;
}
/**
* Access the scale parameter, {@code beta}.
*
* @return the scale parameter, {@code beta}.
*/
public double getScale() {
return scale;
}
/** {@inheritDoc} */
@Override
public double density(double x) {
if (x < 0) {
return 0;
}
final double xscale = x / scale;
final double xscalepow = FastMath.pow(xscale, shape - 1);
/*
* FastMath.pow(x / scale, shape) =
* FastMath.pow(xscale, shape) =
* FastMath.pow(xscale, shape - 1) * xscale
*/
final double xscalepowshape = xscalepow * xscale;
return (shape / scale) * xscalepow * FastMath.exp(-xscalepowshape);
}
/** {@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} */
@Override
public double cumulativeProbability(double x) {
double ret;
if (x <= 0.0) {
ret = 0.0;
} else {
ret = 1.0 - FastMath.exp(-FastMath.pow(x / scale, shape));
}
return ret;
}
/**
* {@inheritDoc}
*
* Returns {@code 0} when {@code p == 0} and
* {@code Double.POSITIVE_INFINITY} when {@code p == 1}.
*/
@Override
public double inverseCumulativeProbability(double p) {
double ret;
if (p < 0.0 || p > 1.0) {
throw new OutOfRangeException(p, 0.0, 1.0);
} else if (p == 0) {
ret = 0.0;
} else if (p == 1) {
ret = Double.POSITIVE_INFINITY;
} else {
ret = scale * FastMath.pow(-FastMath.log1p(-p), 1.0 / shape);
}
return ret;
}
/**
* Return the absolute accuracy setting of the solver used to estimate
* inverse cumulative probabilities.
*
* @return the solver absolute accuracy.
* @since 2.1
*/
@Override
protected double getSolverAbsoluteAccuracy() {
return solverAbsoluteAccuracy;
}
/**
* {@inheritDoc}
*
* The mean is {@code scale * Gamma(1 + (1 / shape))}, where {@code Gamma()}
* is the Gamma-function.
*/
@Override
public double getNumericalMean() {
if (!numericalMeanIsCalculated) {
numericalMean = calculateNumericalMean();
numericalMeanIsCalculated = true;
}
return numericalMean;
}
/**
* used by {@link #getNumericalMean()}
*
* @return the mean of this distribution
*/
protected double calculateNumericalMean() {
final double sh = getShape();
final double sc = getScale();
return sc * FastMath.exp(LogGamma.value(1 + (1 / sh)));
}
/**
* {@inheritDoc}
*
* The variance is {@code scale^2 * Gamma(1 + (2 / shape)) - mean^2}
* where {@code Gamma()} is the Gamma-function.
*/
@Override
public double getNumericalVariance() {
if (!numericalVarianceIsCalculated) {
numericalVariance = calculateNumericalVariance();
numericalVarianceIsCalculated = true;
}
return numericalVariance;
}
/**
* used by {@link #getNumericalVariance()}
*
* @return the variance of this distribution
*/
protected double calculateNumericalVariance() {
final double sh = getShape();
final double sc = getScale();
final double mn = getNumericalMean();
return (sc * sc) * FastMath.exp(LogGamma.value(1 + (2 / sh))) -
(mn * mn);
}
/**
* {@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
* {@code Double.POSITIVE_INFINITY})
*/
@Override
public double getSupportUpperBound() {
return Double.POSITIVE_INFINITY;
}
/**
* {@inheritDoc}
*
* The support of this distribution is connected.
*
* @return {@code true}
*/
@Override
public boolean isSupportConnected() {
return true;
}
}

View File

@ -1,278 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.math4.exception.util.LocalizedFormats;
import org.apache.commons.math4.util.FastMath;
import org.apache.commons.rng.UniformRandomProvider;
import org.apache.commons.rng.sampling.distribution.DiscreteSampler;
import org.apache.commons.rng.sampling.distribution.RejectionInversionZipfSampler;
/**
* Implementation of the Zipf distribution.
* <p>
* <strong>Parameters:</strong>
* For a random variable {@code X} whose values are distributed according to this
* distribution, the probability mass function is given by
* <pre>
* P(X = k) = H(N,s) * 1 / k^s for {@code k = 1,2,...,N}.
* </pre>
* {@code H(N,s)} is the normalizing constant
* which corresponds to the generalized harmonic number of order N of s.
* <ul>
* <li>{@code N} is the number of elements</li>
* <li>{@code s} is the exponent</li>
* </ul>
* @see <a href="https://en.wikipedia.org/wiki/Zipf's_law">Zipf's law (Wikipedia)</a>
* @see <a href="https://en.wikipedia.org/wiki/Harmonic_number#Generalized_harmonic_numbers">Generalized harmonic numbers</a>
*/
public class ZipfDistribution extends AbstractIntegerDistribution {
/** Serializable version identifier. */
private static final long serialVersionUID = 20150501L;
/** Number of elements. */
private final int numberOfElements;
/** Exponent parameter of the distribution. */
private final double exponent;
/** Cached values of the nth generalized harmonic. */
private final double nthHarmonic;
/** Cached numerical mean */
private double numericalMean = Double.NaN;
/** Whether or not the numerical mean has been calculated */
private boolean numericalMeanIsCalculated = false;
/** Cached numerical variance */
private double numericalVariance = Double.NaN;
/** Whether or not the numerical variance has been calculated */
private boolean numericalVarianceIsCalculated = false;
/**
* Creates a distribution.
*
* @param numberOfElements Number of elements.
* @param exponent Exponent.
* @exception NotStrictlyPositiveException if {@code numberOfElements <= 0}
* or {@code exponent <= 0}.
*/
public ZipfDistribution(int numberOfElements,
double exponent)
throws NotStrictlyPositiveException {
if (numberOfElements <= 0) {
throw new NotStrictlyPositiveException(LocalizedFormats.DIMENSION,
numberOfElements);
}
if (exponent <= 0) {
throw new NotStrictlyPositiveException(LocalizedFormats.EXPONENT,
exponent);
}
this.numberOfElements = numberOfElements;
this.exponent = exponent;
this.nthHarmonic = generalizedHarmonic(numberOfElements, exponent);
}
/**
* Get the number of elements (e.g. corpus size) for the distribution.
*
* @return the number of elements
*/
public int getNumberOfElements() {
return numberOfElements;
}
/**
* Get the exponent characterizing the distribution.
*
* @return the exponent
*/
public double getExponent() {
return exponent;
}
/** {@inheritDoc} */
@Override
public double probability(final int x) {
if (x <= 0 || x > numberOfElements) {
return 0.0;
}
return (1.0 / FastMath.pow(x, exponent)) / nthHarmonic;
}
/** {@inheritDoc} */
@Override
public double logProbability(int x) {
if (x <= 0 || x > numberOfElements) {
return Double.NEGATIVE_INFINITY;
}
return -FastMath.log(x) * exponent - FastMath.log(nthHarmonic);
}
/** {@inheritDoc} */
@Override
public double cumulativeProbability(final int x) {
if (x <= 0) {
return 0.0;
} else if (x >= numberOfElements) {
return 1.0;
}
return generalizedHarmonic(x, exponent) / nthHarmonic;
}
/**
* {@inheritDoc}
*
* For number of elements {@code N} and exponent {@code s}, the mean is
* {@code Hs1 / Hs}, where
* <ul>
* <li>{@code Hs1 = generalizedHarmonic(N, s - 1)},</li>
* <li>{@code Hs = generalizedHarmonic(N, s)}.</li>
* </ul>
*/
@Override
public double getNumericalMean() {
if (!numericalMeanIsCalculated) {
numericalMean = calculateNumericalMean();
numericalMeanIsCalculated = true;
}
return numericalMean;
}
/**
* Used by {@link #getNumericalMean()}.
*
* @return the mean of this distribution
*/
protected double calculateNumericalMean() {
final int N = getNumberOfElements();
final double s = getExponent();
final double Hs1 = generalizedHarmonic(N, s - 1);
final double Hs = nthHarmonic;
return Hs1 / Hs;
}
/**
* {@inheritDoc}
*
* For number of elements {@code N} and exponent {@code s}, the mean is
* {@code (Hs2 / Hs) - (Hs1^2 / Hs^2)}, where
* <ul>
* <li>{@code Hs2 = generalizedHarmonic(N, s - 2)},</li>
* <li>{@code Hs1 = generalizedHarmonic(N, s - 1)},</li>
* <li>{@code Hs = generalizedHarmonic(N, s)}.</li>
* </ul>
*/
@Override
public double getNumericalVariance() {
if (!numericalVarianceIsCalculated) {
numericalVariance = calculateNumericalVariance();
numericalVarianceIsCalculated = true;
}
return numericalVariance;
}
/**
* Used by {@link #getNumericalVariance()}.
*
* @return the variance of this distribution
*/
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 = nthHarmonic;
return (Hs2 / Hs) - ((Hs1 * Hs1) / (Hs * Hs));
}
/**
* Calculates the Nth generalized harmonic number. See
* <a href="http://mathworld.wolfram.com/HarmonicSeries.html">Harmonic
* Series</a>.
*
* @param n Term in the series to calculate (must be larger than 1)
* @param m Exponent (special case {@code m = 1} is the harmonic series).
* @return the n<sup>th</sup> generalized harmonic number.
*/
private double generalizedHarmonic(final int n, final double m) {
double value = 0;
for (int k = n; k > 0; --k) {
value += 1.0 / FastMath.pow(k, m);
}
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}
*
* The support of this distribution is connected.
*
* @return {@code true}
*/
@Override
public boolean isSupportConnected() {
return true;
}
/**{@inheritDoc} */
@Override
public IntegerDistribution.Sampler createSampler(final UniformRandomProvider rng) {
return new IntegerDistribution.Sampler() {
/**
* Zipf distribution sampler.
*/
private final DiscreteSampler sampler =
new RejectionInversionZipfSampler(rng, numberOfElements, exponent);
/**{@inheritDoc} */
@Override
public int sample() {
return sampler.sample();
}
};
}
}

View File

@ -1,386 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import java.util.Arrays;
import org.apache.commons.statistics.distribution.ContinuousDistribution;
import org.apache.commons.rng.simple.RandomSource;
import org.apache.commons.rng.UniformRandomProvider;
import org.apache.commons.math4.stat.StatUtils;
import org.apache.commons.math4.stat.inference.KolmogorovSmirnovTest;
import org.apache.commons.math4.stat.inference.InferenceTestUtils;
import org.junit.Assert;
import org.junit.Test;
public class BetaDistributionTest {
static final double[] alphaBetas = {0.1, 1, 10, 100, 1000};
static final double epsilon = StatUtils.min(alphaBetas);
@Test
public void testCumulative() {
double[] x = new double[]{-0.1, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1};
// all test data computed using R 2.5
checkCumulative(0.1, 0.1,
x, new double[]{
0.0000000000, 0.0000000000, 0.4063850939, 0.4397091902, 0.4628041861,
0.4821200456, 0.5000000000, 0.5178799544, 0.5371958139, 0.5602908098,
0.5936149061, 1.0000000000, 1.0000000000});
checkCumulative(0.1, 0.5,
x, new double[]{
0.0000000000, 0.0000000000, 0.7048336221, 0.7593042194, 0.7951765304,
0.8234948385, 0.8480017124, 0.8706034370, 0.8926585878, 0.9156406404,
0.9423662883, 1.0000000000, 1.0000000000});
checkCumulative(0.1, 1.0,
x, new double[]{
0.0000000000, 0.0000000000, 0.7943282347, 0.8513399225, 0.8865681506,
0.9124435366, 0.9330329915, 0.9502002165, 0.9649610951, 0.9779327685,
0.9895192582, 1.0000000000, 1.0000000000});
checkCumulative(0.1, 2.0,
x, new double[]{
0.0000000000, 0.0000000000, 0.8658177758, 0.9194471163, 0.9486279211,
0.9671901487, 0.9796846411, 0.9882082252, 0.9939099280, 0.9974914239,
0.9994144508, 1.0000000000, 1.0000000000});
checkCumulative(0.1, 4.0,
x, new double[]{
0.0000000000, 0.0000000000, 0.9234991121, 0.9661958941, 0.9842285085,
0.9928444112, 0.9970040660, 0.9989112804, 0.9996895625, 0.9999440793,
0.9999967829, 1.0000000000, 1.0000000000});
checkCumulative(0.5, 0.1,
x, new double[]{
0.00000000000, 0.00000000000, 0.05763371168, 0.08435935962,
0.10734141216, 0.12939656302, 0.15199828760, 0.17650516146,
0.20482346963, 0.24069578055, 0.29516637795, 1.00000000000, 1.00000000000});
checkCumulative(0.5, 0.5,
x, new double[]{
0.0000000000, 0.0000000000, 0.2048327647, 0.2951672353, 0.3690101196,
0.4359057832, 0.5000000000, 0.5640942168, 0.6309898804, 0.7048327647,
0.7951672353, 1.0000000000, 1.0000000000});
checkCumulative(0.5, 1.0,
x, new double[]{
0.0000000000, 0.0000000000, 0.3162277660, 0.4472135955, 0.5477225575,
0.6324555320, 0.7071067812, 0.7745966692, 0.8366600265, 0.8944271910,
0.9486832981, 1.0000000000, 1.0000000000});
checkCumulative(0.5, 2.0,
x, new double[]{
0.0000000000, 0.0000000000, 0.4585302607, 0.6260990337, 0.7394254526,
0.8221921916, 0.8838834765, 0.9295160031, 0.9621590305, 0.9838699101,
0.9961174630, 1.0000000000, 1.0000000000});
checkCumulative(0.5, 4.0,
x, new double[]{
0.0000000000, 0.0000000000, 0.6266250826, 0.8049844719, 0.8987784842,
0.9502644369, 0.9777960959, 0.9914837366, 0.9974556254, 0.9995223859,
0.9999714889, 1.0000000000, 1.0000000000});
checkCumulative(1.0, 0.1,
x, new double[]{
0.00000000000, 0.00000000000, 0.01048074179, 0.02206723146,
0.03503890488, 0.04979978349, 0.06696700846, 0.08755646344,
0.11343184943, 0.14866007748, 0.20567176528, 1.00000000000, 1.00000000000});
checkCumulative(1.0, 0.5,
x, new double[]{
0.00000000000, 0.00000000000, 0.05131670195, 0.10557280900,
0.16333997347, 0.22540333076, 0.29289321881, 0.36754446797,
0.45227744249, 0.55278640450, 0.68377223398, 1.00000000000, 1.00000000000});
checkCumulative(1, 1,
x, new double[]{
0.0, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.0});
checkCumulative(1, 2,
x, new double[]{
0.00, 0.00, 0.19, 0.36, 0.51, 0.64, 0.75, 0.84, 0.91, 0.96, 0.99, 1.00, 1.00});
checkCumulative(1, 4,
x, new double[]{
0.0000, 0.0000, 0.3439, 0.5904, 0.7599, 0.8704, 0.9375, 0.9744, 0.9919,
0.9984, 0.9999, 1.0000, 1.0000});
checkCumulative(2.0, 0.1,
x, new double[]{
0.0000000000000, 0.0000000000000, 0.0005855492117, 0.0025085760862,
0.0060900720266, 0.0117917748341, 0.0203153588864, 0.0328098512512,
0.0513720788952, 0.0805528836776, 0.1341822241505, 1.0000000000000, 1.0000000000000});
checkCumulative(2, 1,
x, new double[]{
0.00, 0.00, 0.01, 0.04, 0.09, 0.16, 0.25, 0.36, 0.49, 0.64, 0.81, 1.00, 1.00});
checkCumulative(2.0, 0.5,
x, new double[]{
0.000000000000, 0.000000000000, 0.003882537047, 0.016130089900,
0.037840969486, 0.070483996910, 0.116116523517, 0.177807808356,
0.260574547368, 0.373900966300, 0.541469739276, 1.000000000000, 1.000000000000});
checkCumulative(2, 2,
x, new double[]{
0.000, 0.000, 0.028, 0.104, 0.216, 0.352, 0.500, 0.648, 0.784, 0.896, 0.972, 1.000, 1.000});
checkCumulative(2, 4,
x, new double[]{
0.00000, 0.00000, 0.08146, 0.26272, 0.47178, 0.66304, 0.81250, 0.91296,
0.96922, 0.99328, 0.99954, 1.00000, 1.00000});
checkCumulative(4.0, 0.1,
x, new double[]{
0.000000000e+00, 0.000000000e+00, 3.217128269e-06, 5.592070271e-05,
3.104375474e-04, 1.088719595e-03, 2.995933981e-03, 7.155588777e-03,
1.577149153e-02, 3.380410585e-02, 7.650088789e-02, 1.000000000e+00, 1.000000000e+00});
checkCumulative(4.0, 0.5,
x, new double[]{
0.000000000e+00, 0.000000000e+00, 2.851114863e-05, 4.776140576e-04,
2.544374616e-03, 8.516263371e-03, 2.220390414e-02, 4.973556312e-02,
1.012215158e-01, 1.950155281e-01, 3.733749174e-01, 1.000000000e+00, 1.000000000e+00});
checkCumulative(4, 1,
x, new double[]{
0.0000, 0.0000, 0.0001, 0.0016, 0.0081, 0.0256, 0.0625, 0.1296, 0.2401,
0.4096, 0.6561, 1.0000, 1.0000});
checkCumulative(4, 2,
x, new double[]{
0.00000, 0.00000, 0.00046, 0.00672, 0.03078, 0.08704, 0.18750, 0.33696,
0.52822, 0.73728, 0.91854, 1.00000, 1.00000});
checkCumulative(4, 4,
x, new double[]{
0.000000, 0.000000, 0.002728, 0.033344, 0.126036, 0.289792, 0.500000,
0.710208, 0.873964, 0.966656, 0.997272, 1.000000, 1.000000});
}
private void checkCumulative(double alpha, double beta, double[] x, double[] cumes) {
BetaDistribution d = new BetaDistribution(alpha, beta);
for (int i = 0; i < x.length; i++) {
Assert.assertEquals(cumes[i], d.cumulativeProbability(x[i]), 1e-8);
}
for (int i = 1; i < x.length - 1; i++) {
Assert.assertEquals(x[i], d.inverseCumulativeProbability(cumes[i]), 1e-5);
}
}
@Test
public void testDensity() {
double[] x = new double[]{1e-6, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9};
checkDensity(0.1, 0.1,
x, new double[]{
12741.2357380649, 0.4429889586665234, 2.639378715e-01, 2.066393611e-01,
1.832401831e-01, 1.766302780e-01, 1.832404579e-01, 2.066400696e-01,
2.639396531e-01, 4.429925026e-01});
checkDensity(0.1, 0.5,
x, new double[]{
2.218377102e+04, 7.394524202e-01, 4.203020268e-01, 3.119435533e-01,
2.600787829e-01, 2.330648626e-01, 2.211408259e-01, 2.222728708e-01,
2.414013907e-01, 3.070567405e-01});
checkDensity(0.1, 1.0,
x, new double[]{
2.511886432e+04, 7.943210858e-01, 4.256680458e-01, 2.955218303e-01,
2.281103709e-01, 1.866062624e-01, 1.583664652e-01, 1.378514078e-01,
1.222414585e-01, 1.099464743e-01});
checkDensity(0.1, 2.0,
x, new double[]{
2.763072312e+04, 7.863770012e-01, 3.745874120e-01, 2.275514842e-01,
1.505525939e-01, 1.026332391e-01, 6.968107049e-02, 4.549081293e-02,
2.689298641e-02, 1.209399123e-02});
checkDensity(0.1, 4.0,
x, new double[]{
2.997927462e+04, 6.911058917e-01, 2.601128486e-01, 1.209774010e-01,
5.880564714e-02, 2.783915474e-02, 1.209657335e-02, 4.442148268e-03,
1.167143939e-03, 1.312171805e-04});
checkDensity(0.5, 0.1,
x, new double[]{
88.3152184726, 0.3070542841, 0.2414007269, 0.2222727015,
0.2211409364, 0.2330652355, 0.2600795198, 0.3119449793,
0.4203052841, 0.7394649088});
checkDensity(0.5, 0.5,
x, new double[]{
318.3100453389, 1.0610282383, 0.7957732234, 0.6946084565,
0.6497470636, 0.6366197724, 0.6497476051, 0.6946097796,
0.7957762075, 1.0610376697});
checkDensity(0.5, 1.0,
x, new double[]{
500.0000000000, 1.5811309244, 1.1180311937, 0.9128694077,
0.7905684268, 0.7071060741, 0.6454966865, 0.5976138778,
0.5590166450, 0.5270459839});
checkDensity(0.5, 2.0,
x, new double[]{
749.99925000000, 2.134537420613655, 1.34163575536, 0.95851150881,
0.71151039830, 0.53032849490, 0.38729704363, 0.26892534859,
0.16770415497, 0.07905610701});
checkDensity(0.5, 4.0,
x, new double[]{
1.093746719e+03, 2.52142232809988, 1.252190241e+00, 6.849343920e-01,
3.735417140e-01, 1.933481570e-01, 9.036885833e-02, 3.529621669e-02,
9.782644546e-03, 1.152878503e-03});
checkDensity(1.0, 0.1,
x, new double[]{
0.1000000900, 0.1099466942, 0.1222417336, 0.1378517623, 0.1583669403,
0.1866069342, 0.2281113974, 0.2955236034, 0.4256718768,
0.7943353837});
checkDensity(1.0, 0.5,
x, new double[]{
0.5000002500, 0.5270465695, 0.5590173438, 0.5976147315, 0.6454977623,
0.7071074883, 0.7905704033, 0.9128724506,
1.1180367838, 1.5811467358});
checkDensity(1, 1,
x, new double[]{
1, 1, 1,
1, 1, 1, 1,
1, 1, 1});
checkDensity(1, 2,
x, new double[]{
1.999998, 1.799998, 1.599998, 1.399998, 1.199998, 0.999998, 0.799998,
0.599998, 0.399998,
0.199998});
checkDensity(1, 4,
x, new double[]{
3.999988000012, 2.915990280011, 2.047992320010, 1.371994120008,
0.863995680007, 0.499997000006, 0.255998080005, 0.107998920004,
0.031999520002, 0.003999880001});
checkDensity(2.0, 0.1,
x, new double[]{
1.100000990e-07, 1.209425730e-02, 2.689331586e-02, 4.549123318e-02,
6.968162794e-02, 1.026340191e-01, 1.505537732e-01, 2.275534997e-01,
3.745917198e-01, 7.863929037e-01});
checkDensity(2.0, 0.5,
x, new double[]{
7.500003750e-07, 7.905777599e-02, 1.677060417e-01, 2.689275256e-01,
3.872996256e-01, 5.303316769e-01, 7.115145488e-01, 9.585174425e-01,
1.341645818e+00, 2.134537420613655});
checkDensity(2, 1,
x, new double[]{
0.000002, 0.200002, 0.400002, 0.600002, 0.800002, 1.000002, 1.200002,
1.400002, 1.600002,
1.800002});
checkDensity(2, 2,
x, new double[]{
5.9999940e-06, 5.4000480e-01, 9.6000360e-01, 1.2600024e+00,
1.4400012e+00, 1.5000000e+00, 1.4399988e+00, 1.2599976e+00,
9.5999640e-01, 5.3999520e-01});
checkDensity(2, 4,
x, new double[]{
0.00001999994, 1.45800971996, 2.04800255997, 2.05799803998,
1.72799567999, 1.24999500000, 0.76799552000, 0.37799676001,
0.12799824001, 0.01799948000});
checkDensity(4.0, 0.1,
x, new double[]{
1.193501074e-19, 1.312253162e-04, 1.167181580e-03, 4.442248535e-03,
1.209679109e-02, 2.783958903e-02, 5.880649983e-02, 1.209791638e-01,
2.601171405e-01, 6.911229392e-01});
checkDensity(4.0, 0.5,
x, new double[]{
1.093750547e-18, 1.152948959e-03, 9.782950259e-03, 3.529697305e-02,
9.037036449e-02, 1.933508639e-01, 3.735463833e-01, 6.849425461e-01,
1.252205894e+00, 2.52142232809988});
checkDensity(4, 1,
x, new double[]{
4.000000000e-18, 4.000120001e-03, 3.200048000e-02, 1.080010800e-01,
2.560019200e-01, 5.000030000e-01, 8.640043200e-01, 1.372005880e+00,
2.048007680e+00, 2.916009720e+00});
checkDensity(4, 2,
x, new double[]{
1.999998000e-17, 1.800052000e-02, 1.280017600e-01, 3.780032400e-01,
7.680044800e-01, 1.250005000e+00, 1.728004320e+00, 2.058001960e+00,
2.047997440e+00, 1.457990280e+00});
checkDensity(4, 4,
x, new double[]{
1.399995800e-16, 1.020627216e-01, 5.734464512e-01, 1.296547409e+00,
1.935364838e+00, 2.187500000e+00, 1.935355162e+00, 1.296532591e+00,
5.734335488e-01, 1.020572784e-01});
}
@SuppressWarnings("boxing")
private void checkDensity(double alpha, double beta, double[] x, double[] expected) {
BetaDistribution d = new BetaDistribution(alpha, beta);
for (int i = 0; i < x.length; i++) {
Assert.assertEquals(String.format("density at x=%.1f for alpha=%.1f, beta=%.1f", x[i], alpha, beta), expected[i], d.density(x[i]), 1e-5);
}
}
@Test
public void testMoments() {
final double tol = 1e-9;
BetaDistribution dist;
dist = new BetaDistribution(1, 1);
Assert.assertEquals(dist.getNumericalMean(), 0.5, tol);
Assert.assertEquals(dist.getNumericalVariance(), 1.0 / 12.0, tol);
dist = new BetaDistribution(2, 5);
Assert.assertEquals(dist.getNumericalMean(), 2.0 / 7.0, tol);
Assert.assertEquals(dist.getNumericalVariance(), 10.0 / (49.0 * 8.0), tol);
}
@Test
public void testMomentsSampling() {
final UniformRandomProvider rng = RandomSource.create(RandomSource.WELL_1024_A,
123456789L);
final int numSamples = 1000;
for (final double alpha : alphaBetas) {
for (final double beta : alphaBetas) {
final BetaDistribution betaDistribution = new BetaDistribution(alpha, beta);
final double[] observed = AbstractRealDistribution.sample(numSamples,
betaDistribution.createSampler(rng));
Arrays.sort(observed);
final String distribution = String.format("Beta(%.2f, %.2f)", alpha, beta);
Assert.assertEquals(String.format("E[%s]", distribution),
betaDistribution.getNumericalMean(),
StatUtils.mean(observed), epsilon);
Assert.assertEquals(String.format("Var[%s]", distribution),
betaDistribution.getNumericalVariance(),
StatUtils.variance(observed), epsilon);
}
}
}
@Test
public void testGoodnessOfFit() {
final UniformRandomProvider rng = RandomSource.create(RandomSource.WELL_19937_A,
123456789L);
final int numSamples = 1000;
final double level = 0.01;
for (final double alpha : alphaBetas) {
for (final double beta : alphaBetas) {
final org.apache.commons.statistics.distribution.BetaDistribution betaDistribution =
new org.apache.commons.statistics.distribution.BetaDistribution(alpha, beta);
final ContinuousDistribution.Sampler sampler = betaDistribution.createSampler(rng);
final double[] observed = AbstractRealDistribution.sample(numSamples, sampler);
Assert.assertFalse("G goodness-of-fit test rejected null at alpha = " + level,
gTest(betaDistribution, observed) < level);
Assert.assertFalse("KS goodness-of-fit test rejected null at alpha = " + level,
new KolmogorovSmirnovTest().kolmogorovSmirnovTest(betaDistribution, observed) < level);
}
}
}
private double gTest(final ContinuousDistribution expectedDistribution, final double[] values) {
final int numBins = values.length / 30;
final double[] breaks = new double[numBins];
for (int b = 0; b < breaks.length; b++) {
breaks[b] = expectedDistribution.inverseCumulativeProbability((double) b / numBins);
}
final long[] observed = new long[numBins];
for (final double value : values) {
int b = 0;
do {
b++;
} while (b < numBins && value >= breaks[b]);
observed[b - 1]++;
}
final double[] expected = new double[numBins];
Arrays.fill(expected, (double) values.length / numBins);
return InferenceTestUtils.gTest(expected, observed);
}
}

View File

@ -1,175 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
* or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.distribution.BinomialDistribution;
import org.apache.commons.math4.distribution.IntegerDistribution;
import org.junit.Assert;
import org.junit.Test;
/**
* Test cases for BinomialDistribution. Extends IntegerDistributionAbstractTest.
* See class javadoc for IntegerDistributionAbstractTest for details.
*
*/
public class BinomialDistributionTest extends IntegerDistributionAbstractTest {
/**
* Constructor to override default tolerance.
*/
public BinomialDistributionTest() {
setTolerance(1e-12);
}
// -------------- Implementations for abstract methods
// -----------------------
/** Creates the default discrete distribution instance to use in tests. */
@Override
public IntegerDistribution makeDistribution() {
return new BinomialDistribution(10, 0.70);
}
/** Creates the default probability density test input values. */
@Override
public int[] makeDensityTestPoints() {
return new int[] { -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
}
/**
* Creates the default probability density test expected values.
* Reference values are from R, version 2.15.3.
*/
@Override
public double[] makeDensityTestValues() {
return new double[] { 0d, 0.0000059049d, 0.000137781d, 0.0014467005,
0.009001692, 0.036756909, 0.1029193452, 0.200120949, 0.266827932,
0.2334744405, 0.121060821, 0.0282475249, 0d };
}
/** Creates the default cumulative probability density test input values */
@Override
public int[] makeCumulativeTestPoints() {
return makeDensityTestPoints();
}
/**
* Creates the default cumulative probability density test expected values.
* Reference values are from R, version 2.15.3.
*/
@Override
public double[] makeCumulativeTestValues() {
return new double[] { 0d, 5.9049e-06, 0.0001436859, 0.0015903864, 0.0105920784, 0.0473489874,
0.1502683326, 0.3503892816, 0.6172172136, 0.8506916541, 0.9717524751, 1d, 1d };
}
/** Creates the default inverse cumulative probability test input values */
@Override
public double[] makeInverseCumulativeTestPoints() {
return new double[] { 0, 0.001d, 0.010d, 0.025d, 0.050d, 0.100d,
0.999d, 0.990d, 0.975d, 0.950d, 0.900d, 1 };
}
/**
* Creates the default inverse cumulative probability density test expected
* values
*/
@Override
public int[] makeInverseCumulativeTestValues() {
return new int[] { 0, 2, 3, 4, 5, 5, 10, 10, 10, 9, 9, 10 };
}
// ----------------- Additional test cases ---------------------------------
/** Test degenerate case p = 0 */
@Test
public void testDegenerate0() {
BinomialDistribution dist = new BinomialDistribution(5, 0.0d);
setDistribution(dist);
setCumulativeTestPoints(new int[] { -1, 0, 1, 5, 10 });
setCumulativeTestValues(new double[] { 0d, 1d, 1d, 1d, 1d });
setDensityTestPoints(new int[] { -1, 0, 1, 10, 11 });
setDensityTestValues(new double[] { 0d, 1d, 0d, 0d, 0d });
setInverseCumulativeTestPoints(new double[] { 0.1d, 0.5d });
setInverseCumulativeTestValues(new int[] { 0, 0 });
verifyDensities();
verifyCumulativeProbabilities();
verifyInverseCumulativeProbabilities();
Assert.assertEquals(dist.getSupportLowerBound(), 0);
Assert.assertEquals(dist.getSupportUpperBound(), 0);
}
/** Test degenerate case p = 1 */
@Test
public void testDegenerate1() {
BinomialDistribution dist = new BinomialDistribution(5, 1.0d);
setDistribution(dist);
setCumulativeTestPoints(new int[] { -1, 0, 1, 2, 5, 10 });
setCumulativeTestValues(new double[] { 0d, 0d, 0d, 0d, 1d, 1d });
setDensityTestPoints(new int[] { -1, 0, 1, 2, 5, 10 });
setDensityTestValues(new double[] { 0d, 0d, 0d, 0d, 1d, 0d });
setInverseCumulativeTestPoints(new double[] { 0.1d, 0.5d });
setInverseCumulativeTestValues(new int[] { 5, 5 });
verifyDensities();
verifyCumulativeProbabilities();
verifyInverseCumulativeProbabilities();
Assert.assertEquals(dist.getSupportLowerBound(), 5);
Assert.assertEquals(dist.getSupportUpperBound(), 5);
}
/** Test degenerate case n = 0 */
@Test
public void testDegenerate2() {
BinomialDistribution dist = new BinomialDistribution(0, 0.01d);
setDistribution(dist);
setCumulativeTestPoints(new int[] { -1, 0, 1, 2, 5, 10 });
setCumulativeTestValues(new double[] { 0d, 1d, 1d, 1d, 1d, 1d });
setDensityTestPoints(new int[] { -1, 0, 1, 2, 5, 10 });
setDensityTestValues(new double[] { 0d, 1d, 0d, 0d, 0d, 0d });
setInverseCumulativeTestPoints(new double[] { 0.1d, 0.5d });
setInverseCumulativeTestValues(new int[] { 0, 0 });
verifyDensities();
verifyCumulativeProbabilities();
verifyInverseCumulativeProbabilities();
Assert.assertEquals(dist.getSupportLowerBound(), 0);
Assert.assertEquals(dist.getSupportUpperBound(), 0);
}
@Test
public void testMoments() {
final double tol = 1e-9;
BinomialDistribution dist;
dist = new BinomialDistribution(10, 0.5);
Assert.assertEquals(dist.getNumericalMean(), 10d * 0.5d, tol);
Assert.assertEquals(dist.getNumericalVariance(), 10d * 0.5d * 0.5d, tol);
dist = new BinomialDistribution(30, 0.3);
Assert.assertEquals(dist.getNumericalMean(), 30d * 0.3d, tol);
Assert.assertEquals(dist.getNumericalVariance(), 30d * 0.3d * (1d - 0.3d), tol);
}
@Test
public void testMath718() {
// for large trials the evaluation of ContinuedFraction was inaccurate
// do a sweep over several large trials to test if the current implementation is
// numerically stable.
for (int trials = 500000; trials < 20000000; trials += 100000) {
BinomialDistribution dist = new BinomialDistribution(trials, 0.5);
int p = dist.inverseCumulativeProbability(0.5);
Assert.assertEquals(trials / 2, p);
}
}
}

View File

@ -1,122 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.distribution.CauchyDistribution;
import org.apache.commons.math4.distribution.NormalDistribution;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.junit.Assert;
import org.junit.Test;
/**
* Test cases for CauchyDistribution.
* Extends ContinuousDistributionAbstractTest. See class javadoc for
* ContinuousDistributionAbstractTest for details.
*
*/
public class CauchyDistributionTest extends RealDistributionAbstractTest {
// --------------------- Override tolerance --------------
protected double defaultTolerance = NormalDistribution.DEFAULT_INVERSE_ABSOLUTE_ACCURACY;
@Override
public void setUp() {
super.setUp();
setTolerance(defaultTolerance);
}
//-------------- Implementations for abstract methods -----------------------
/** Creates the default continuous distribution instance to use in tests. */
@Override
public CauchyDistribution makeDistribution() {
return new CauchyDistribution(1.2, 2.1);
}
/** Creates the default cumulative probability distribution test input values */
@Override
public double[] makeCumulativeTestPoints() {
// quantiles computed using R 2.9.2
return new double[] {-667.24856187, -65.6230835029, -25.4830299460, -12.0588781808,
-5.26313542807, 669.64856187, 68.0230835029, 27.8830299460, 14.4588781808, 7.66313542807};
}
/** Creates the default cumulative probability density test expected values */
@Override
public double[] makeCumulativeTestValues() {
return new double[] {0.001, 0.01, 0.025, 0.05, 0.1, 0.999,
0.990, 0.975, 0.950, 0.900};
}
/** Creates the default probability density test expected values */
@Override
public double[] makeDensityTestValues() {
return new double[] {1.49599158008e-06, 0.000149550440335, 0.000933076881878, 0.00370933207799, 0.0144742330437,
1.49599158008e-06, 0.000149550440335, 0.000933076881878, 0.00370933207799, 0.0144742330437};
}
//---------------------------- Additional test cases -------------------------
@Test
public void testInverseCumulativeProbabilityExtremes() {
setInverseCumulativeTestPoints(new double[] {0.0, 1.0});
setInverseCumulativeTestValues(
new double[] {Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY});
verifyInverseCumulativeProbabilities();
}
@Test
public void testMedian() {
CauchyDistribution distribution = (CauchyDistribution) getDistribution();
Assert.assertEquals(1.2, distribution.getMedian(), 0.0);
}
@Test
public void testScale() {
CauchyDistribution distribution = (CauchyDistribution) getDistribution();
Assert.assertEquals(2.1, distribution.getScale(), 0.0);
}
@Test
public void testPreconditions() {
try {
new CauchyDistribution(0, 0);
Assert.fail("Cannot have zero scale");
} catch (NotStrictlyPositiveException ex) {
// Expected.
}
try {
new CauchyDistribution(0, -1);
Assert.fail("Cannot have negative scale");
} catch (NotStrictlyPositiveException ex) {
// Expected.
}
}
@Test
public void testMoments() {
CauchyDistribution dist;
dist = new CauchyDistribution(10.2, 0.15);
Assert.assertTrue(Double.isNaN(dist.getNumericalMean()));
Assert.assertTrue(Double.isNaN(dist.getNumericalVariance()));
dist = new CauchyDistribution(23.12, 2.12);
Assert.assertTrue(Double.isNaN(dist.getNumericalMean()));
Assert.assertTrue(Double.isNaN(dist.getNumericalVariance()));
}
}

View File

@ -1,137 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.distribution.ChiSquaredDistribution;
import org.junit.Assert;
import org.junit.Test;
/**
* Test cases for {@link ChiSquaredDistribution}.
*
* @see RealDistributionAbstractTest
*/
public class ChiSquaredDistributionTest extends RealDistributionAbstractTest {
//-------------- Implementations for abstract methods -----------------------
/** Creates the default continuous distribution instance to use in tests. */
@Override
public ChiSquaredDistribution makeDistribution() {
return new ChiSquaredDistribution(5.0);
}
/** Creates the default cumulative probability distribution test input values */
@Override
public double[] makeCumulativeTestPoints() {
// quantiles computed using R version 2.9.2
return new double[] {0.210212602629, 0.554298076728, 0.831211613487, 1.14547622606, 1.61030798696,
20.5150056524, 15.0862724694, 12.8325019940, 11.0704976935, 9.23635689978};
}
/** Creates the default cumulative probability density test expected values */
@Override
public double[] makeCumulativeTestValues() {
return new double[] {0.001, 0.01, 0.025, 0.05, 0.1, 0.999, 0.990, 0.975, 0.950, 0.900};
}
/** Creates the default inverse cumulative probability test input values */
@Override
public double[] makeInverseCumulativeTestPoints() {
return new double[] {0, 0.001d, 0.01d, 0.025d, 0.05d, 0.1d, 0.999d,
0.990d, 0.975d, 0.950d, 0.900d, 1};
}
/** Creates the default inverse cumulative probability density test expected values */
@Override
public double[] makeInverseCumulativeTestValues() {
return new double[] {0, 0.210212602629, 0.554298076728, 0.831211613487, 1.14547622606, 1.61030798696,
20.5150056524, 15.0862724694, 12.8325019940, 11.0704976935, 9.23635689978,
Double.POSITIVE_INFINITY};
}
/** Creates the default probability density test expected values */
@Override
public double[] makeDensityTestValues() {
return new double[] {0.0115379817652, 0.0415948507811, 0.0665060119842, 0.0919455953114, 0.121472591024,
0.000433630076361, 0.00412780610309, 0.00999340341045, 0.0193246438937, 0.0368460089216};
}
// --------------------- Override tolerance --------------
@Override
public void setUp() {
super.setUp();
setTolerance(1e-9);
}
//---------------------------- Additional test cases -------------------------
@Test
public void testSmallDf() {
setDistribution(new ChiSquaredDistribution(0.1d));
setTolerance(1E-4);
// quantiles computed using R version 1.8.1 (linux version)
setCumulativeTestPoints(new double[] {1.168926E-60, 1.168926E-40, 1.063132E-32,
1.144775E-26, 1.168926E-20, 5.472917, 2.175255, 1.13438,
0.5318646, 0.1526342});
setInverseCumulativeTestValues(getCumulativeTestPoints());
setInverseCumulativeTestPoints(getCumulativeTestValues());
verifyCumulativeProbabilities();
verifyInverseCumulativeProbabilities();
}
@Test
public void testDfAccessors() {
ChiSquaredDistribution distribution = (ChiSquaredDistribution) getDistribution();
Assert.assertEquals(5d, distribution.getDegreesOfFreedom(), Double.MIN_VALUE);
}
@Test
public void testDensity() {
double[] x = new double[]{-0.1, 1e-6, 0.5, 1, 2, 5};
//R 2.5: print(dchisq(x, df=1), digits=10)
checkDensity(1, x, new double[]{0.00000000000, 398.94208093034, 0.43939128947, 0.24197072452, 0.10377687436, 0.01464498256});
//R 2.5: print(dchisq(x, df=0.1), digits=10)
checkDensity(0.1, x, new double[]{0.000000000e+00, 2.486453997e+04, 7.464238732e-02, 3.009077718e-02, 9.447299159e-03, 8.827199396e-04});
//R 2.5: print(dchisq(x, df=2), digits=10)
checkDensity(2, x, new double[]{0.00000000000, 0.49999975000, 0.38940039154, 0.30326532986, 0.18393972059, 0.04104249931});
//R 2.5: print(dchisq(x, df=10), digits=10)
checkDensity(10, x, new double[]{0.000000000e+00, 1.302082682e-27, 6.337896998e-05, 7.897534632e-04, 7.664155024e-03, 6.680094289e-02});
}
private void checkDensity(double df, double[] x, double[] expected) {
ChiSquaredDistribution d = new ChiSquaredDistribution(df);
for (int i = 0; i < x.length; i++) {
Assert.assertEquals(expected[i], d.density(x[i]), 1e-5);
}
}
@Test
public void testMoments() {
final double tol = 1e-9;
ChiSquaredDistribution dist;
dist = new ChiSquaredDistribution(1500);
Assert.assertEquals(dist.getNumericalMean(), 1500, tol);
Assert.assertEquals(dist.getNumericalVariance(), 3000, tol);
dist = new ChiSquaredDistribution(1.12);
Assert.assertEquals(dist.getNumericalMean(), 1.12, tol);
Assert.assertEquals(dist.getNumericalVariance(), 2.24, tol);
}
}

View File

@ -1,94 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.distribution.ConstantRealDistribution;
import org.apache.commons.math4.distribution.RealDistribution;
import org.junit.Assert;
import org.junit.Test;
/**
* Test cases for ConstantRealDistribution.
*/
public class ConstantRealDistributionTest extends RealDistributionAbstractTest {
// --- Override tolerance -------------------------------------------------
@Override
public void setUp() {
super.setUp();
setTolerance(0);
}
//--- Implementations for abstract methods --------------------------------
/** Creates the default uniform real distribution instance to use in tests. */
@Override
public ConstantRealDistribution makeDistribution() {
return new ConstantRealDistribution(1);
}
/** Creates the default cumulative probability distribution test input values */
@Override
public double[] makeCumulativeTestPoints() {
return new double[] {0, 0.5, 1};
}
/** Creates the default cumulative probability distribution test expected values */
@Override
public double[] makeCumulativeTestValues() {
return new double[] {0, 0, 1};
}
/** Creates the default probability density test expected values */
@Override
public double[] makeDensityTestValues() {
return new double[] {0, 0, 1};
}
/** Override default test, verifying that inverse cum is constant */
@Override
@Test
public void testInverseCumulativeProbabilities() {
RealDistribution dist = getDistribution();
for (double x : getCumulativeTestValues()) {
Assert.assertEquals(1,dist.inverseCumulativeProbability(x), 0);
}
}
//--- Additional test cases -----------------------------------------------
@Test
public void testMeanVariance() {
ConstantRealDistribution dist;
dist = new ConstantRealDistribution(-1);
Assert.assertEquals(dist.getNumericalMean(), -1, 0d);
Assert.assertEquals(dist.getNumericalVariance(), 0, 0d);
}
@Test
@Override
public void testSampler() {
final double value = 12.345;
final RealDistribution.Sampler sampler = new ConstantRealDistribution(value).createSampler(null);
for (int i = 0; i < 10; i++) {
Assert.assertEquals(value, sampler.sample(), 0);
}
}
}

View File

@ -1,135 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.distribution.ExponentialDistribution;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.math4.util.FastMath;
import org.apache.commons.numbers.core.Precision;
import org.junit.Assert;
import org.junit.Test;
/**
* Test cases for ExponentialDistribution.
* Extends ContinuousDistributionAbstractTest. See class javadoc for
* ContinuousDistributionAbstractTest for details.
*
*/
public class ExponentialDistributionTest extends RealDistributionAbstractTest {
// --------------------- Override tolerance --------------
@Override
public void setUp() {
super.setUp();
setTolerance(1E-9);
}
//-------------- Implementations for abstract methods -----------------------
/** Creates the default continuous distribution instance to use in tests. */
@Override
public ExponentialDistribution makeDistribution() {
return new ExponentialDistribution(5.0);
}
/** Creates the default cumulative probability distribution test input values */
@Override
public double[] makeCumulativeTestPoints() {
// quantiles computed using R version 2.9.2
return new double[] {0.00500250166792, 0.0502516792675, 0.126589039921, 0.256466471938,
0.526802578289, 34.5387763949, 23.0258509299, 18.4443972706, 14.9786613678, 11.5129254650};
}
/** Creates the default cumulative probability density test expected values */
@Override
public double[] makeCumulativeTestValues() {
return new double[] {0.001, 0.01, 0.025, 0.05, 0.1, 0.999,
0.990, 0.975, 0.950, 0.900};
}
/** Creates the default probability density test expected values */
@Override
public double[] makeDensityTestValues() {
return new double[] {0.1998, 0.198, 0.195, 0.19, 0.18, 0.000200000000000,
0.00200000000002, 0.00499999999997, 0.00999999999994, 0.0199999999999};
}
//------------ Additional tests -------------------------------------------
@Test
public void testCumulativeProbabilityExtremes() {
setCumulativeTestPoints(new double[] {-2, 0});
setCumulativeTestValues(new double[] {0, 0});
verifyCumulativeProbabilities();
}
@Test
public void testInverseCumulativeProbabilityExtremes() {
setInverseCumulativeTestPoints(new double[] {0, 1});
setInverseCumulativeTestValues(new double[] {0, Double.POSITIVE_INFINITY});
verifyInverseCumulativeProbabilities();
}
@Test
public void testCumulativeProbability2() {
double actual = getDistribution().probability(0.25, 0.75);
Assert.assertEquals(0.0905214, actual, 10e-4);
}
@Test
public void testDensity() {
ExponentialDistribution d1 = new ExponentialDistribution(1);
Assert.assertTrue(Precision.equals(0.0, d1.density(-1e-9), 1));
Assert.assertTrue(Precision.equals(1.0, d1.density(0.0), 1));
Assert.assertTrue(Precision.equals(0.0, d1.density(1000.0), 1));
Assert.assertTrue(Precision.equals(FastMath.exp(-1), d1.density(1.0), 1));
Assert.assertTrue(Precision.equals(FastMath.exp(-2), d1.density(2.0), 1));
ExponentialDistribution d2 = new ExponentialDistribution(3);
Assert.assertTrue(Precision.equals(1/3.0, d2.density(0.0), 1));
// computed using print(dexp(1, rate=1/3), digits=10) in R 2.5
Assert.assertEquals(0.2388437702, d2.density(1.0), 1e-8);
// computed using print(dexp(2, rate=1/3), digits=10) in R 2.5
Assert.assertEquals(0.1711390397, d2.density(2.0), 1e-8);
}
@Test
public void testMeanAccessors() {
ExponentialDistribution distribution = (ExponentialDistribution) getDistribution();
Assert.assertEquals(5d, distribution.getMean(), Double.MIN_VALUE);
}
@Test(expected=NotStrictlyPositiveException.class)
public void testPreconditions() {
new ExponentialDistribution(0);
}
@Test
public void testMoments() {
final double tol = 1e-9;
ExponentialDistribution dist;
dist = new ExponentialDistribution(11d);
Assert.assertEquals(dist.getNumericalMean(), 11d, tol);
Assert.assertEquals(dist.getNumericalVariance(), 11d * 11d, tol);
dist = new ExponentialDistribution(10.5d);
Assert.assertEquals(dist.getNumericalMean(), 10.5d, tol);
Assert.assertEquals(dist.getNumericalVariance(), 10.5d * 10.5d, tol);
}
}

View File

@ -1,159 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.distribution.FDistribution;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.junit.Assert;
import org.junit.Test;
/**
* Test cases for FDistribution.
* Extends ContinuousDistributionAbstractTest. See class javadoc for
* ContinuousDistributionAbstractTest for details.
*
*/
public class FDistributionTest extends RealDistributionAbstractTest {
//-------------- Implementations for abstract methods -----------------------
/** Creates the default continuous distribution instance to use in tests. */
@Override
public FDistribution makeDistribution() {
return new FDistribution(5.0, 6.0);
}
/** Creates the default cumulative probability distribution test input values */
@Override
public double[] makeCumulativeTestPoints() {
// quantiles computed using R version 2.9.2
return new double[] {0.0346808448626, 0.0937009113303, 0.143313661184, 0.202008445998, 0.293728320107,
20.8026639595, 8.74589525602, 5.98756512605, 4.38737418741, 3.10751166664};
}
/** Creates the default cumulative probability density test expected values */
@Override
public double[] makeCumulativeTestValues() {
return new double[] {0.001, 0.01, 0.025, 0.05, 0.1, 0.999, 0.990, 0.975, 0.950, 0.900};
}
/** Creates the default probability density test expected values */
@Override
public double[] makeDensityTestValues() {
return new double[] {0.0689156576706, 0.236735653193, 0.364074131941, 0.481570789649, 0.595880479994,
0.000133443915657, 0.00286681303403, 0.00969192007502, 0.0242883861471, 0.0605491314658};
}
// --------------------- Override tolerance --------------
@Override
public void setUp() {
super.setUp();
setTolerance(1e-9);
}
//---------------------------- Additional test cases -------------------------
@Test
public void testCumulativeProbabilityExtremes() {
setCumulativeTestPoints(new double[] {-2, 0});
setCumulativeTestValues(new double[] {0, 0});
verifyCumulativeProbabilities();
}
@Test
public void testInverseCumulativeProbabilityExtremes() {
setInverseCumulativeTestPoints(new double[] {0, 1});
setInverseCumulativeTestValues(new double[] {0, Double.POSITIVE_INFINITY});
verifyInverseCumulativeProbabilities();
}
@Test
public void testDfAccessors() {
FDistribution dist = (FDistribution) getDistribution();
Assert.assertEquals(5d, dist.getNumeratorDegreesOfFreedom(), Double.MIN_VALUE);
Assert.assertEquals(6d, dist.getDenominatorDegreesOfFreedom(), Double.MIN_VALUE);
}
@Test
public void testPreconditions() {
try {
new FDistribution(0, 1);
Assert.fail("Expecting NotStrictlyPositiveException for df = 0");
} catch (NotStrictlyPositiveException ex) {
// Expected.
}
try {
new FDistribution(1, 0);
Assert.fail("Expecting NotStrictlyPositiveException for df = 0");
} catch (NotStrictlyPositiveException ex) {
// Expected.
}
}
@Test
public void testLargeDegreesOfFreedom() {
FDistribution fd = new FDistribution(100000, 100000);
double p = fd.cumulativeProbability(.999);
double x = fd.inverseCumulativeProbability(p);
Assert.assertEquals(.999, x, 1.0e-5);
}
@Test
public void testSmallDegreesOfFreedom() {
FDistribution fd = new FDistribution(1, 1);
double p = fd.cumulativeProbability(0.975);
double x = fd.inverseCumulativeProbability(p);
Assert.assertEquals(0.975, x, 1.0e-5);
fd = new FDistribution(1, 2);
p = fd.cumulativeProbability(0.975);
x = fd.inverseCumulativeProbability(p);
Assert.assertEquals(0.975, x, 1.0e-5);
}
@Test
public void testMoments() {
final double tol = 1e-9;
FDistribution dist;
dist = new FDistribution(1, 2);
Assert.assertTrue(Double.isNaN(dist.getNumericalMean()));
Assert.assertTrue(Double.isNaN(dist.getNumericalVariance()));
dist = new FDistribution(1, 3);
Assert.assertEquals(dist.getNumericalMean(), 3d / (3d - 2d), tol);
Assert.assertTrue(Double.isNaN(dist.getNumericalVariance()));
dist = new FDistribution(1, 5);
Assert.assertEquals(dist.getNumericalMean(), 5d / (5d - 2d), tol);
Assert.assertEquals(dist.getNumericalVariance(), (2d * 5d * 5d * 4d) / 9d, tol);
}
@Test
public void testMath785() {
// this test was failing due to inaccurate results from ContinuedFraction.
try {
double prob = 0.01;
FDistribution f = new FDistribution(200000, 200000);
double result = f.inverseCumulativeProbability(prob);
Assert.assertTrue(result < 1.0);
} catch (Exception e) {
Assert.fail("Failing to calculate inverse cumulative probability");
}
}
}

View File

@ -1,358 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.apache.commons.math4.distribution.GammaDistribution;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.numbers.gamma.LanczosApproximation;
import org.apache.commons.math4.stat.descriptive.SummaryStatistics;
import org.apache.commons.math4.util.FastMath;
import org.junit.Assert;
import org.junit.Test;
/**
* Test cases for GammaDistribution.
* Extends ContinuousDistributionAbstractTest. See class javadoc for
* ContinuousDistributionAbstractTest for details.
*
*/
public class GammaDistributionTest extends RealDistributionAbstractTest {
//-------------- Implementations for abstract methods -----------------------
/** Creates the default continuous distribution instance to use in tests. */
@Override
public GammaDistribution makeDistribution() {
return new GammaDistribution(4d, 2d);
}
/** Creates the default cumulative probability distribution test input values */
@Override
public double[] makeCumulativeTestPoints() {
// quantiles computed using R version 2.9.2
return new double[] {0.857104827257, 1.64649737269, 2.17973074725, 2.7326367935, 3.48953912565,
26.1244815584, 20.0902350297, 17.5345461395, 15.5073130559, 13.3615661365};
}
/** Creates the default cumulative probability density test expected values */
@Override
public double[] makeCumulativeTestValues() {
return new double[] {0.001, 0.01, 0.025, 0.05, 0.1, 0.999, 0.990, 0.975, 0.950, 0.900};
}
/** Creates the default probability density test expected values */
@Override
public double[] makeDensityTestValues() {
return new double[] {0.00427280075546, 0.0204117166709, 0.0362756163658, 0.0542113174239, 0.0773195272491,
0.000394468852816, 0.00366559696761, 0.00874649473311, 0.0166712508128, 0.0311798227954};
}
// --------------------- Override tolerance --------------
@Override
public void setUp() {
super.setUp();
setTolerance(1e-9);
}
//---------------------------- Additional test cases -------------------------
@Test
public void testParameterAccessors() {
GammaDistribution distribution = (GammaDistribution) getDistribution();
Assert.assertEquals(4d, distribution.getShape(), 0);
Assert.assertEquals(2d, distribution.getScale(), 0);
}
@Test
public void testPreconditions() {
try {
new GammaDistribution(0, 1);
Assert.fail("Expecting NotStrictlyPositiveException for alpha = 0");
} catch (NotStrictlyPositiveException ex) {
// Expected.
}
try {
new GammaDistribution(1, 0);
Assert.fail("Expecting NotStrictlyPositiveException for alpha = 0");
} catch (NotStrictlyPositiveException ex) {
// Expected.
}
}
@Test
public void testProbabilities() {
testProbability(-1.000, 4.0, 2.0, .0000);
testProbability(15.501, 4.0, 2.0, .9499);
testProbability(0.504, 4.0, 1.0, .0018);
testProbability(10.011, 1.0, 2.0, .9933);
testProbability(5.000, 2.0, 2.0, .7127);
}
@Test
public void testValues() {
testValue(15.501, 4.0, 2.0, .9499);
testValue(0.504, 4.0, 1.0, .0018);
testValue(10.011, 1.0, 2.0, .9933);
testValue(5.000, 2.0, 2.0, .7127);
}
private void testProbability(double x, double a, double b, double expected) {
GammaDistribution distribution = new GammaDistribution( a, b );
double actual = distribution.cumulativeProbability(x);
Assert.assertEquals("probability for " + x, expected, actual, 10e-4);
}
private void testValue(double expected, double a, double b, double p) {
GammaDistribution distribution = new GammaDistribution( a, b );
double actual = distribution.inverseCumulativeProbability(p);
Assert.assertEquals("critical value for " + p, expected, actual, 10e-4);
}
@Test
public void testDensity() {
double[] x = new double[]{-0.1, 1e-6, 0.5, 1, 2, 5};
// R2.5: print(dgamma(x, shape=1, rate=1), digits=10)
checkDensity(1, 1, x, new double[]{0.000000000000, 0.999999000001, 0.606530659713, 0.367879441171, 0.135335283237, 0.006737946999});
// R2.5: print(dgamma(x, shape=2, rate=1), digits=10)
checkDensity(2, 1, x, new double[]{0.000000000000, 0.000000999999, 0.303265329856, 0.367879441171, 0.270670566473, 0.033689734995});
// R2.5: print(dgamma(x, shape=4, rate=1), digits=10)
checkDensity(4, 1, x, new double[]{0.000000000e+00, 1.666665000e-19, 1.263605541e-02, 6.131324020e-02, 1.804470443e-01, 1.403738958e-01});
// R2.5: print(dgamma(x, shape=4, rate=10), digits=10)
checkDensity(4, 10, x, new double[]{0.000000000e+00, 1.666650000e-15, 1.403738958e+00, 7.566654960e-02, 2.748204830e-05, 4.018228850e-17});
// R2.5: print(dgamma(x, shape=.1, rate=10), digits=10)
checkDensity(0.1, 10, x, new double[]{0.000000000e+00, 3.323953832e+04, 1.663849010e-03, 6.007786726e-06, 1.461647647e-10, 5.996008322e-24});
// R2.5: print(dgamma(x, shape=.1, rate=20), digits=10)
checkDensity(0.1, 20, x, new double[]{0.000000000e+00, 3.562489883e+04, 1.201557345e-05, 2.923295295e-10, 3.228910843e-19, 1.239484589e-45});
// R2.5: print(dgamma(x, shape=.1, rate=4), digits=10)
checkDensity(0.1, 4, x, new double[]{0.000000000e+00, 3.032938388e+04, 3.049322494e-02, 2.211502311e-03, 2.170613371e-05, 5.846590589e-11});
// R2.5: print(dgamma(x, shape=.1, rate=1), digits=10)
checkDensity(0.1, 1, x, new double[]{0.000000000e+00, 2.640334143e+04, 1.189704437e-01, 3.866916944e-02, 7.623306235e-03, 1.663849010e-04});
}
private void checkDensity(double alpha, double rate, double[] x, double[] expected) {
GammaDistribution d = new GammaDistribution(alpha, 1 / rate);
for (int i = 0; i < x.length; i++) {
Assert.assertEquals(expected[i], d.density(x[i]), 1e-5);
}
}
@Test
public void testInverseCumulativeProbabilityExtremes() {
setInverseCumulativeTestPoints(new double[] {0, 1});
setInverseCumulativeTestValues(new double[] {0, Double.POSITIVE_INFINITY});
verifyInverseCumulativeProbabilities();
}
@Test
public void testMoments() {
final double tol = 1e-9;
GammaDistribution dist;
dist = new GammaDistribution(1, 2);
Assert.assertEquals(dist.getNumericalMean(), 2, tol);
Assert.assertEquals(dist.getNumericalVariance(), 4, tol);
dist = new GammaDistribution(1.1, 4.2);
Assert.assertEquals(dist.getNumericalMean(), 1.1d * 4.2d, tol);
Assert.assertEquals(dist.getNumericalVariance(), 1.1d * 4.2d * 4.2d, tol);
}
private static final double HALF_LOG_2_PI = 0.5 * FastMath.log(2.0 * FastMath.PI);
public static double logGamma(double x) {
/*
* This is a copy of
* double Gamma.logGamma(double)
* prior to MATH-849
*/
double ret;
if (Double.isNaN(x) || (x <= 0.0)) {
ret = Double.NaN;
} else {
double sum = LanczosApproximation.value(x);
double tmp = x + LanczosApproximation.g() + .5;
ret = ((x + .5) * FastMath.log(tmp)) - tmp +
HALF_LOG_2_PI + FastMath.log(sum / x);
}
return ret;
}
public static double density(final double x, final double shape,
final double scale) {
/*
* This is a copy of
* double GammaDistribution.density(double)
* prior to MATH-753.
*/
if (x < 0) {
return 0;
}
return FastMath.pow(x / scale, shape - 1) / scale *
FastMath.exp(-x / scale) / FastMath.exp(logGamma(shape));
}
/*
* MATH-753: large values of x or shape parameter cause density(double) to
* overflow. Reference data is generated with the Maxima script
* gamma-distribution.mac, which can be found in
* src/test/resources/org/apache/commons/math4/distribution.
*/
private void doTestMath753(final double shape,
final double meanNoOF, final double sdNoOF,
final double meanOF, final double sdOF,
final String resourceName) throws IOException {
final GammaDistribution distribution = new GammaDistribution(shape, 1.0);
final SummaryStatistics statOld = new SummaryStatistics();
final SummaryStatistics statNewNoOF = new SummaryStatistics();
final SummaryStatistics statNewOF = new SummaryStatistics();
final InputStream resourceAsStream;
resourceAsStream = this.getClass().getResourceAsStream(resourceName);
Assert.assertNotNull("Could not find resource " + resourceName,
resourceAsStream);
final BufferedReader in;
in = new BufferedReader(new InputStreamReader(resourceAsStream));
try {
for (String line = in.readLine(); line != null; line = in.readLine()) {
if (line.startsWith("#")) {
continue;
}
final String[] tokens = line.split(", ");
Assert.assertTrue("expected two floating-point values",
tokens.length == 2);
final double x = Double.parseDouble(tokens[0]);
final String msg = "x = " + x + ", shape = " + shape +
", scale = 1.0";
final double expected = Double.parseDouble(tokens[1]);
final double ulp = FastMath.ulp(expected);
final double actualOld = density(x, shape, 1.0);
final double actualNew = distribution.density(x);
final double errOld, errNew;
errOld = FastMath.abs((actualOld - expected) / ulp);
errNew = FastMath.abs((actualNew - expected) / ulp);
if (Double.isNaN(actualOld) || Double.isInfinite(actualOld)) {
Assert.assertFalse(msg, Double.isNaN(actualNew));
Assert.assertFalse(msg, Double.isInfinite(actualNew));
statNewOF.addValue(errNew);
} else {
statOld.addValue(errOld);
statNewNoOF.addValue(errNew);
}
}
if (statOld.getN() != 0) {
/*
* If no overflow occurs, check that new implementation is
* better than old one.
*/
final StringBuilder sb = new StringBuilder("shape = ");
sb.append(shape);
sb.append(", scale = 1.0\n");
sb.append("Old implementation\n");
sb.append("------------------\n");
sb.append(statOld.toString());
sb.append("New implementation\n");
sb.append("------------------\n");
sb.append(statNewNoOF.toString());
final String msg = sb.toString();
final double oldMin = statOld.getMin();
final double newMin = statNewNoOF.getMin();
Assert.assertTrue(msg, newMin <= oldMin);
final double oldMax = statOld.getMax();
final double newMax = statNewNoOF.getMax();
Assert.assertTrue(msg, newMax <= oldMax);
final double oldMean = statOld.getMean();
final double newMean = statNewNoOF.getMean();
Assert.assertTrue(msg, newMean <= oldMean);
final double oldSd = statOld.getStandardDeviation();
final double newSd = statNewNoOF.getStandardDeviation();
Assert.assertTrue(msg, newSd <= oldSd);
Assert.assertTrue(msg, newMean <= meanNoOF);
Assert.assertTrue(msg, newSd <= sdNoOF);
}
if (statNewOF.getN() != 0) {
final double newMean = statNewOF.getMean();
final double newSd = statNewOF.getStandardDeviation();
final StringBuilder sb = new StringBuilder("shape = ");
sb.append(shape);
sb.append(", scale = 1.0");
sb.append(", max. mean error (ulps) = ");
sb.append(meanOF);
sb.append(", actual mean error (ulps) = ");
sb.append(newMean);
sb.append(", max. sd of error (ulps) = ");
sb.append(sdOF);
sb.append(", actual sd of error (ulps) = ");
sb.append(newSd);
final String msg = sb.toString();
Assert.assertTrue(msg, newMean <= meanOF);
Assert.assertTrue(msg, newSd <= sdOF);
}
} catch (IOException e) {
Assert.fail(e.getMessage());
} finally {
in.close();
}
}
@Test
public void testMath753Shape1() throws IOException {
doTestMath753(1.0, 1.5, 0.5, 0.0, 0.0, "gamma-distribution-shape-1.csv");
}
@Test
public void testMath753Shape8() throws IOException {
doTestMath753(8.0, 1.5, 1.0, 0.0, 0.0, "gamma-distribution-shape-8.csv");
}
@Test
public void testMath753Shape10() throws IOException {
doTestMath753(10.0, 1.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-10.csv");
}
@Test
public void testMath753Shape100() throws IOException {
doTestMath753(100.0, 1.5, 1.0, 0.0, 0.0, "gamma-distribution-shape-100.csv");
}
@Test
public void testMath753Shape142() throws IOException {
doTestMath753(142.0, 3.3, 1.6, 40.0, 40.0, "gamma-distribution-shape-142.csv");
}
@Test
public void testMath753Shape1000() throws IOException {
doTestMath753(1000.0, 1.0, 1.0, 160.0, 220.0, "gamma-distribution-shape-1000.csv");
}
}

View File

@ -1,172 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
* or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.distribution.GeometricDistribution;
import org.apache.commons.math4.distribution.IntegerDistribution;
import org.junit.Assert;
import org.junit.Test;
/**
* Test cases for GeometricDistribution.
* <p>
* See class javadoc for IntegerDistributionAbstractTest for details.
*
* @since 3.3
*/
public class GeometricDistributionTest extends IntegerDistributionAbstractTest {
/**
* Constructor to override default tolerance.
*/
public GeometricDistributionTest() {
setTolerance(1e-12);
}
// -------------- Implementations for abstract methods --------------------
/** Creates the default discrete distribution instance to use in tests. */
@Override
public IntegerDistribution makeDistribution() {
return new GeometricDistribution(0.40);
}
/** Creates the default probability density test input values */
@Override
public int[] makeDensityTestPoints() {
return new int[] { -1, 0, 1, 2, 3, 4, 5, 6, 7, 8,
9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 20, 21, 22, 23, 24, 25, 26, 27, 28 };
}
/**
* Creates the default probability density test expected values.
* Reference values are from R, version version 2.15.3.
*/
@Override
public double[] makeDensityTestValues() {
return new double[] {
0d, 0.4, 0.24, 0.144, 0.0864, 0.05184, 0.031104, 0.0186624,
0.01119744, 0.006718464, 0.0040310784, 0.00241864704,
0.001451188224,0.0008707129344, 0.00052242776064, 0.000313456656384,
0.00018807399383, 0.000112844396298, 6.77066377789e-05, 4.06239826674e-05,
2.43743896004e-05, 1.46246337603e-05, 8.77478025615e-06, 5.26486815369e-06,
3.15892089221e-06, 1.89535253533e-06, 1.1372115212e-06, 6.82326912718e-07,
4.09396147631e-07, 2.45637688579e-07
};
}
/**
* Creates the default log probability density test expected values.
* Reference values are from R, version version 2.14.1.
*/
@Override
public double[] makeLogDensityTestValues() {
return new double[] {
Double.NEGATIVE_INFINITY, -0.916290731874155, -1.42711635564015, -1.93794197940614,
-2.44876760317213, -2.95959322693812, -3.47041885070411, -3.9812444744701,
-4.49207009823609, -5.00289572200208, -5.51372134576807, -6.02454696953406,
-6.53537259330005, -7.04619821706604, -7.55702384083203, -8.06784946459802,
-8.57867508836402, -9.08950071213001, -9.600326335896, -10.111151959662,
-10.621977583428, -11.132803207194, -11.64362883096, -12.154454454726,
-12.6652800784919, -13.1761057022579, -13.6869313260239, -14.1977569497899,
-14.7085825735559, -15.2194081973219
};
}
/** Creates the default cumulative probability density test input values */
@Override
public int[] makeCumulativeTestPoints() {
return makeDensityTestPoints();
}
/** Creates the default cumulative probability density test expected values */
@Override
public double[] makeCumulativeTestValues() {
final double[] densities = makeDensityTestValues();
final int n = densities.length;
final double[] ret = new double[n];
ret[0] = densities[0];
for (int i = 1; i < n; i++) {
ret[i] = ret[i - 1] + densities[i];
}
return ret;
}
/** Creates the default inverse cumulative probability test input values */
@Override
public double[] makeInverseCumulativeTestPoints() {
return new double[] {
0.000, 0.005, 0.010, 0.015, 0.020, 0.025, 0.030, 0.035, 0.040,
0.045, 0.050, 0.055, 0.060, 0.065, 0.070, 0.075, 0.080, 0.085,
0.090, 0.095, 0.100, 0.105, 0.110, 0.115, 0.120, 0.125, 0.130,
0.135, 0.140, 0.145, 0.150, 0.155, 0.160, 0.165, 0.170, 0.175,
0.180, 0.185, 0.190, 0.195, 0.200, 0.205, 0.210, 0.215, 0.220,
0.225, 0.230, 0.235, 0.240, 0.245, 0.250, 0.255, 0.260, 0.265,
0.270, 0.275, 0.280, 0.285, 0.290, 0.295, 0.300, 0.305, 0.310,
0.315, 0.320, 0.325, 0.330, 0.335, 0.340, 0.345, 0.350, 0.355,
0.360, 0.365, 0.370, 0.375, 0.380, 0.385, 0.390, 0.395, 0.400,
0.405, 0.410, 0.415, 0.420, 0.425, 0.430, 0.435, 0.440, 0.445,
0.450, 0.455, 0.460, 0.465, 0.470, 0.475, 0.480, 0.485, 0.490,
0.495, 0.500, 0.505, 0.510, 0.515, 0.520, 0.525, 0.530, 0.535,
0.540, 0.545, 0.550, 0.555, 0.560, 0.565, 0.570, 0.575, 0.580,
0.585, 0.590, 0.595, 0.600, 0.605, 0.610, 0.615, 0.620, 0.625,
0.630, 0.635, 0.640, 0.645, 0.650, 0.655, 0.660, 0.665, 0.670,
0.675, 0.680, 0.685, 0.690, 0.695, 0.700, 0.705, 0.710, 0.715,
0.720, 0.725, 0.730, 0.735, 0.740, 0.745, 0.750, 0.755, 0.760,
0.765, 0.770, 0.775, 0.780, 0.785, 0.790, 0.795, 0.800, 0.805,
0.810, 0.815, 0.820, 0.825, 0.830, 0.835, 0.840, 0.845, 0.850,
0.855, 0.860, 0.865, 0.870, 0.875, 0.880, 0.885, 0.890, 0.895,
0.900, 0.905, 0.910, 0.915, 0.920, 0.925, 0.930, 0.935, 0.940,
0.945, 0.950, 0.955, 0.960, 0.965, 0.970, 0.975, 0.980, 0.985,
0.990, 0.995, 1.000
};
}
/**
* Creates the default inverse cumulative probability density test expected
* values
*/
@Override
public int[] makeInverseCumulativeTestValues() {
return new int[] {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5,
5, 5, 6, 6, 6, 6, 7, 7, 8, 9, 10, Integer.MAX_VALUE
};
}
// ----------------- Additional test cases ---------------------------------
@Test
public void testMoments() {
final double tol = 1e-9;
GeometricDistribution dist;
dist = new GeometricDistribution(0.5);
Assert.assertEquals(dist.getNumericalMean(), (1.0d - 0.5d) / 0.5d, tol);
Assert.assertEquals(dist.getNumericalVariance(), (1.0d - 0.5d) / (0.5d * 0.5d), tol);
dist = new GeometricDistribution(0.3);
Assert.assertEquals(dist.getNumericalMean(), (1.0d - 0.3d) / 0.3d, tol);
Assert.assertEquals(dist.getNumericalVariance(), (1.0d - 0.3d) / (0.3d * 0.3d), tol);
}
}

View File

@ -1,72 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.distribution.GumbelDistribution;
import org.apache.commons.numbers.core.Precision;
import org.junit.Assert;
import org.junit.Test;
/**
* Test cases for GumbelDistribution.
*/
public class GumbelDistributionTest extends RealDistributionAbstractTest {
@Test
public void testParameters() {
GumbelDistribution d = makeDistribution();
Assert.assertEquals(0.5, d.getLocation(), Precision.EPSILON);
Assert.assertEquals(2, d.getScale(), Precision.EPSILON);
}
@Test
public void testSupport() {
GumbelDistribution d = makeDistribution();
Assert.assertTrue(Double.isInfinite(d.getSupportLowerBound()));
Assert.assertTrue(Double.isInfinite(d.getSupportUpperBound()));
Assert.assertTrue(d.isSupportConnected());
}
@Override
public GumbelDistribution makeDistribution() {
return new GumbelDistribution(0.5, 2);
}
@Override
public double[] makeCumulativeTestPoints() {
return new double[] {
-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5
};
}
@Override
public double[] makeDensityTestValues() {
return new double[] {
1.258262e-06, 3.594689e-04, 9.115766e-03, 5.321100e-02, 1.274352e-01, 1.777864e-01,
1.787177e-01, 1.472662e-01, 1.075659e-01, 7.302736e-02, 4.742782e-02
};
}
@Override
public double[] makeCumulativeTestValues() {
return new double[] {
1.608760e-07, 7.577548e-05, 3.168165e-03, 3.049041e-02, 1.203923e-01, 2.769203e-01,
4.589561e-01, 6.235249e-01, 7.508835e-01, 8.404869e-01, 8.999652e-01
};
}
}

View File

@ -1,354 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.TestUtils;
import org.apache.commons.math4.distribution.HypergeometricDistribution;
import org.apache.commons.math4.distribution.IntegerDistribution;
import org.apache.commons.math4.exception.NotPositiveException;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.math4.exception.NumberIsTooLargeException;
import org.apache.commons.numbers.core.Precision;
import org.apache.commons.rng.simple.RandomSource;
import org.junit.Assert;
import org.junit.Test;
/**
* Test cases for HyperGeometriclDistribution.
* Extends IntegerDistributionAbstractTest. See class javadoc for
* IntegerDistributionAbstractTest for details.
*
*/
public class HypergeometricDistributionTest extends IntegerDistributionAbstractTest {
/**
* Constructor to override default tolerance.
*/
public HypergeometricDistributionTest() {
setTolerance(1e-12);
}
//-------------- Implementations for abstract methods -----------------------
/** Creates the default discrete distribution instance to use in tests. */
@Override
public IntegerDistribution makeDistribution() {
return new HypergeometricDistribution(10, 5, 5);
}
/** Creates the default probability density test input values */
@Override
public int[] makeDensityTestPoints() {
return new int[] {-1, 0, 1, 2, 3, 4, 5, 10};
}
/**
* Creates the default probability density test expected values
* Reference values are from R, version 2.15.3.
*/
@Override
public double[] makeDensityTestValues() {
return new double[] {0d, 0.00396825396825, 0.0992063492063, 0.396825396825, 0.396825396825,
0.0992063492063, 0.00396825396825, 0d};
}
/**
* Creates the default probability log density test expected values
* Reference values are from R, version 2.14.1.
*/
@Override
public double[] makeLogDensityTestValues() {
//-Inf -Inf
return new double[] {Double.NEGATIVE_INFINITY, -5.52942908751142, -2.31055326264322, -0.924258901523332,
-0.924258901523332, -2.31055326264322, -5.52942908751142, Double.NEGATIVE_INFINITY};
}
/** Creates the default cumulative probability density test input values */
@Override
public int[] makeCumulativeTestPoints() {
return makeDensityTestPoints();
}
/**
* Creates the default cumulative probability density test expected values
* Reference values are from R, version 2.15.3.
*/
@Override
public double[] makeCumulativeTestValues() {
return new double[] {0d, 0.00396825396825, 0.103174603175, .5, 0.896825396825, 0.996031746032,
1, 1};
}
/** Creates the default inverse cumulative probability test input values */
@Override
public double[] makeInverseCumulativeTestPoints() {
return new double[] {0d, 0.001d, 0.010d, 0.025d, 0.050d, 0.100d, 0.999d,
0.990d, 0.975d, 0.950d, 0.900d, 1d};
}
/** Creates the default inverse cumulative probability density test expected values */
@Override
public int[] makeInverseCumulativeTestValues() {
return new int[] {0, 0, 1, 1, 1, 1, 5, 4, 4, 4, 4, 5};
}
//-------------------- Additional test cases ------------------------------
/** Verify that if there are no failures, mass is concentrated on sampleSize */
@Test
public void testDegenerateNoFailures() {
HypergeometricDistribution dist = new HypergeometricDistribution(5,5,3);
setDistribution(dist);
setCumulativeTestPoints(new int[] {-1, 0, 1, 3, 10 });
setCumulativeTestValues(new double[] {0d, 0d, 0d, 1d, 1d});
setDensityTestPoints(new int[] {-1, 0, 1, 3, 10});
setDensityTestValues(new double[] {0d, 0d, 0d, 1d, 0d});
setInverseCumulativeTestPoints(new double[] {0.1d, 0.5d});
setInverseCumulativeTestValues(new int[] {3, 3});
verifyDensities();
verifyCumulativeProbabilities();
verifyInverseCumulativeProbabilities();
Assert.assertEquals(dist.getSupportLowerBound(), 3);
Assert.assertEquals(dist.getSupportUpperBound(), 3);
}
/** Verify that if there are no successes, mass is concentrated on 0 */
@Test
public void testDegenerateNoSuccesses() {
HypergeometricDistribution dist = new HypergeometricDistribution(5,0,3);
setDistribution(dist);
setCumulativeTestPoints(new int[] {-1, 0, 1, 3, 10 });
setCumulativeTestValues(new double[] {0d, 1d, 1d, 1d, 1d});
setDensityTestPoints(new int[] {-1, 0, 1, 3, 10});
setDensityTestValues(new double[] {0d, 1d, 0d, 0d, 0d});
setInverseCumulativeTestPoints(new double[] {0.1d, 0.5d});
setInverseCumulativeTestValues(new int[] {0, 0});
verifyDensities();
verifyCumulativeProbabilities();
verifyInverseCumulativeProbabilities();
Assert.assertEquals(dist.getSupportLowerBound(), 0);
Assert.assertEquals(dist.getSupportUpperBound(), 0);
}
/** Verify that if sampleSize = populationSize, mass is concentrated on numberOfSuccesses */
@Test
public void testDegenerateFullSample() {
HypergeometricDistribution dist = new HypergeometricDistribution(5,3,5);
setDistribution(dist);
setCumulativeTestPoints(new int[] {-1, 0, 1, 3, 10 });
setCumulativeTestValues(new double[] {0d, 0d, 0d, 1d, 1d});
setDensityTestPoints(new int[] {-1, 0, 1, 3, 10});
setDensityTestValues(new double[] {0d, 0d, 0d, 1d, 0d});
setInverseCumulativeTestPoints(new double[] {0.1d, 0.5d});
setInverseCumulativeTestValues(new int[] {3, 3});
verifyDensities();
verifyCumulativeProbabilities();
verifyInverseCumulativeProbabilities();
Assert.assertEquals(dist.getSupportLowerBound(), 3);
Assert.assertEquals(dist.getSupportUpperBound(), 3);
}
@Test
public void testPreconditions() {
try {
new HypergeometricDistribution(0, 3, 5);
Assert.fail("negative population size. NotStrictlyPositiveException expected");
} catch(NotStrictlyPositiveException ex) {
// Expected.
}
try {
new HypergeometricDistribution(5, -1, 5);
Assert.fail("negative number of successes. NotPositiveException expected");
} catch(NotPositiveException ex) {
// Expected.
}
try {
new HypergeometricDistribution(5, 3, -1);
Assert.fail("negative sample size. NotPositiveException expected");
} catch(NotPositiveException ex) {
// Expected.
}
try {
new HypergeometricDistribution(5, 6, 5);
Assert.fail("numberOfSuccesses > populationSize. NumberIsTooLargeException expected");
} catch(NumberIsTooLargeException ex) {
// Expected.
}
try {
new HypergeometricDistribution(5, 3, 6);
Assert.fail("sampleSize > populationSize. NumberIsTooLargeException expected");
} catch(NumberIsTooLargeException ex) {
// Expected.
}
}
@Test
public void testAccessors() {
HypergeometricDistribution dist = new HypergeometricDistribution(5, 3, 4);
Assert.assertEquals(5, dist.getPopulationSize());
Assert.assertEquals(3, dist.getNumberOfSuccesses());
Assert.assertEquals(4, dist.getSampleSize());
}
@Test
public void testLargeValues() {
int populationSize = 3456;
int sampleSize = 789;
int numberOfSucceses = 101;
double[][] data = {
{0.0, 2.75646034603961e-12, 2.75646034603961e-12, 1.0},
{1.0, 8.55705370142386e-11, 8.83269973602783e-11, 0.999999999997244},
{2.0, 1.31288129219665e-9, 1.40120828955693e-9, 0.999999999911673},
{3.0, 1.32724172984193e-8, 1.46736255879763e-8, 0.999999998598792},
{4.0, 9.94501711734089e-8, 1.14123796761385e-7, 0.999999985326375},
{5.0, 5.89080768883643e-7, 7.03204565645028e-7, 0.999999885876203},
{20.0, 0.0760051397707708, 0.27349758476299, 0.802507555007781},
{21.0, 0.087144222047629, 0.360641806810619, 0.72650241523701},
{22.0, 0.0940378846881819, 0.454679691498801, 0.639358193189381},
{23.0, 0.0956897500614809, 0.550369441560282, 0.545320308501199},
{24.0, 0.0919766921922999, 0.642346133752582, 0.449630558439718},
{25.0, 0.083641637261095, 0.725987771013677, 0.357653866247418},
{96.0, 5.93849188852098e-57, 1.0, 6.01900244560712e-57},
{97.0, 7.96593036832547e-59, 1.0, 8.05105570861321e-59},
{98.0, 8.44582921934367e-61, 1.0, 8.5125340287733e-61},
{99.0, 6.63604297068222e-63, 1.0, 6.670480942963e-63},
{100.0, 3.43501099007557e-65, 1.0, 3.4437972280786e-65},
{101.0, 8.78623800302957e-68, 1.0, 8.78623800302957e-68},
};
testHypergeometricDistributionProbabilities(populationSize, sampleSize, numberOfSucceses, data);
}
private void testHypergeometricDistributionProbabilities(int populationSize, int sampleSize, int numberOfSucceses, double[][] data) {
HypergeometricDistribution dist = new HypergeometricDistribution(populationSize, numberOfSucceses, sampleSize);
for (int i = 0; i < data.length; ++i) {
int x = (int)data[i][0];
double pmf = data[i][1];
double actualPmf = dist.probability(x);
TestUtils.assertRelativelyEquals("Expected equals for <"+x+"> pmf",pmf, actualPmf, 1.0e-9);
double cdf = data[i][2];
double actualCdf = dist.cumulativeProbability(x);
TestUtils.assertRelativelyEquals("Expected equals for <"+x+"> cdf",cdf, actualCdf, 1.0e-9);
double cdf1 = data[i][3];
double actualCdf1 = dist.upperCumulativeProbability(x);
TestUtils.assertRelativelyEquals("Expected equals for <"+x+"> cdf1",cdf1, actualCdf1, 1.0e-9);
}
}
@Test
public void testMoreLargeValues() {
int populationSize = 26896;
int sampleSize = 895;
int numberOfSucceses = 55;
double[][] data = {
{0.0, 0.155168304750504, 0.155168304750504, 1.0},
{1.0, 0.29437545000746, 0.449543754757964, 0.844831695249496},
{2.0, 0.273841321577003, 0.723385076334967, 0.550456245242036},
{3.0, 0.166488572570786, 0.889873648905753, 0.276614923665033},
{4.0, 0.0743969744713231, 0.964270623377076, 0.110126351094247},
{5.0, 0.0260542785784855, 0.990324901955562, 0.0357293766229237},
{20.0, 3.57101101678792e-16, 1.0, 3.78252101622096e-16},
{21.0, 2.00551638598312e-17, 1.0, 2.11509999433041e-17},
{22.0, 1.04317070180562e-18, 1.0, 1.09583608347287e-18},
{23.0, 5.03153504903308e-20, 1.0, 5.266538166725e-20},
{24.0, 2.2525984149695e-21, 1.0, 2.35003117691919e-21},
{25.0, 9.3677424515947e-23, 1.0, 9.74327619496943e-23},
{50.0, 9.83633962945521e-69, 1.0, 9.8677629437617e-69},
{51.0, 3.13448949497553e-71, 1.0, 3.14233143064882e-71},
{52.0, 7.82755221928122e-74, 1.0, 7.84193567329055e-74},
{53.0, 1.43662126065532e-76, 1.0, 1.43834540093295e-76},
{54.0, 1.72312692517348e-79, 1.0, 1.7241402776278e-79},
{55.0, 1.01335245432581e-82, 1.0, 1.01335245432581e-82},
};
testHypergeometricDistributionProbabilities(populationSize, sampleSize, numberOfSucceses, data);
}
@Test
public void testMoments() {
final double tol = 1e-9;
HypergeometricDistribution dist;
dist = new HypergeometricDistribution(1500, 40, 100);
Assert.assertEquals(dist.getNumericalMean(), 40d * 100d / 1500d, tol);
Assert.assertEquals(dist.getNumericalVariance(), ( 100d * 40d * (1500d - 100d) * (1500d - 40d) ) / ( (1500d * 1500d * 1499d) ), tol);
dist = new HypergeometricDistribution(3000, 55, 200);
Assert.assertEquals(dist.getNumericalMean(), 55d * 200d / 3000d, tol);
Assert.assertEquals(dist.getNumericalVariance(), ( 200d * 55d * (3000d - 200d) * (3000d - 55d) ) / ( (3000d * 3000d * 2999d) ), tol);
}
@Test
public void testMath644() {
int N = 14761461; // population
int m = 1035; // successes in population
int n = 1841; // number of trials
int k = 0;
final HypergeometricDistribution dist = new HypergeometricDistribution(N, m, n);
Assert.assertTrue(Precision.compareTo(1.0, dist.upperCumulativeProbability(k), 1) == 0);
Assert.assertTrue(Precision.compareTo(dist.cumulativeProbability(k), 0.0, 1) > 0);
// another way to calculate the upper cumulative probability
double upper = 1.0 - dist.cumulativeProbability(k) + dist.probability(k);
Assert.assertTrue(Precision.compareTo(1.0, upper, 1) == 0);
}
@Test
public void testZeroTrial() {
final int n = 11; // population
final int m = 4; // successes in population
final int s = 0; // number of trials
final HypergeometricDistribution dist = new HypergeometricDistribution(n, m, 0);
for (int i = 1; i <= n; i++) {
final double p = dist.probability(i);
Assert.assertEquals("p=" + p, 0, p, 0d);
}
}
@Test
public void testMath1356() {
final int n = 11; // population
final int m = 11; // successes in population
for (int s = 0; s <= n; s++) {
final HypergeometricDistribution dist = new HypergeometricDistribution(n, m, s);
final double p = dist.probability(s);
Assert.assertEquals("p=" + p, 1, p, 0d);
}
}
@Test
public void testMath1021() {
final int N = 43130568;
final int m = 42976365;
final int n = 50;
final IntegerDistribution.Sampler dist =
new HypergeometricDistribution(N, m, n).createSampler(RandomSource.create(RandomSource.WELL_512_A));
for (int i = 0; i < 100; i++) {
final int sample = dist.sample();
Assert.assertTrue("sample=" + sample, 0 <= sample);
Assert.assertTrue("sample=" + sample, sample <= n);
}
}
}

View File

@ -1,73 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.distribution.LaplaceDistribution;
import org.apache.commons.numbers.core.Precision;
import org.junit.Assert;
import org.junit.Test;
/**
* Test cases for LaplaceDistribution.
*/
public class LaplaceDistributionTest extends RealDistributionAbstractTest {
@Test
public void testParameters() {
LaplaceDistribution d = makeDistribution();
Assert.assertEquals(0, d.getLocation(), Precision.EPSILON);
Assert.assertEquals(1, d.getScale(), Precision.EPSILON);
}
@Test
public void testSupport() {
LaplaceDistribution d = makeDistribution();
Assert.assertTrue(Double.isInfinite(d.getSupportLowerBound()));
Assert.assertTrue(Double.isInfinite(d.getSupportUpperBound()));
Assert.assertTrue(d.isSupportConnected());
}
@Override
public LaplaceDistribution makeDistribution() {
return new LaplaceDistribution(0, 1);
}
@Override
public double[] makeCumulativeTestPoints() {
return new double[] {
-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5
};
}
@Override
public double[] makeDensityTestValues() {
return new double[] {
0.003368973, 0.009157819, 0.024893534, 0.067667642, 0.183939721,
0.500000000, 0.183939721, 0.067667642, 0.024893534, 0.009157819, 0.003368973
};
}
@Override
public double[] makeCumulativeTestValues() {
return new double[] {
0.003368973, 0.009157819, 0.024893534, 0.067667642, 0.183939721,
0.500000000, 0.816060279, 0.932332358, 0.975106466, 0.990842181, 0.996631027
};
}
}

View File

@ -1,82 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.distribution.LevyDistribution;
import org.apache.commons.numbers.core.Precision;
import org.junit.Assert;
import org.junit.Test;
public class LevyDistributionTest extends RealDistributionAbstractTest {
@Test
public void testParameters() {
LevyDistribution d = makeDistribution();
Assert.assertEquals(1.2, d.getLocation(), Precision.EPSILON);
Assert.assertEquals(0.4, d.getScale(), Precision.EPSILON);
}
@Test
public void testSupport() {
LevyDistribution d = makeDistribution();
Assert.assertEquals(d.getLocation(), d.getSupportLowerBound(), Precision.EPSILON);
Assert.assertTrue(Double.isInfinite(d.getSupportUpperBound()));
Assert.assertTrue(d.isSupportConnected());
}
@Override
public LevyDistribution makeDistribution() {
return new LevyDistribution(1.2, 0.4);
}
@Override
public double[] makeCumulativeTestPoints() {
return new double[] {
1.2001, 1.21, 1.225, 1.25, 1.3, 1.9, 3.4, 5.6
};
}
@Override
public double[] makeCumulativeTestValues() {
// values computed with R and function plevy from rmutil package
return new double[] {
0, 2.53962850749e-10, 6.33424836662e-05, 0.00467773498105,
0.0455002638964, 0.449691797969, 0.669815357599, 0.763024600553
};
}
@Override
public double[] makeDensityTestValues() {
// values computed with R and function dlevy from rmutil package
return new double[] {
0, 5.20056373765e-07, 0.0214128361224, 0.413339707082, 1.07981933026,
0.323749319161, 0.0706032550094, 0.026122839884
};
}
/**
* 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};
}
}

View File

@ -1,254 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.distribution.LogNormalDistribution;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.junit.Assert;
import org.junit.Test;
/**
* Test cases for {@link LogNormalDistribution}. Extends
* {@link RealDistributionAbstractTest}. See class javadoc of that class
* for details.
*
* @since 3.0
*/
public class LogNormalDistributionTest extends RealDistributionAbstractTest {
//-------------- Implementations for abstract methods -----------------------
/** Creates the default real distribution instance to use in tests. */
@Override
public LogNormalDistribution makeDistribution() {
return new LogNormalDistribution(2.1, 1.4);
}
/** Creates the default cumulative probability distribution test input values */
@Override
public double[] makeCumulativeTestPoints() {
// quantiles computed using R
return new double[] { -2.226325228634938, -1.156887023657177,
-0.643949578356075, -0.2027950777320613,
0.305827808237559, 6.42632522863494,
5.35688702365718, 4.843949578356074,
4.40279507773206, 3.89417219176244 };
}
/** Creates the default cumulative probability density test expected values */
@Override
public double[] makeCumulativeTestValues() {
return new double[] { 0, 0, 0, 0, 0.00948199951485, 0.432056525076,
0.381648158697, 0.354555726206, 0.329513316888,
0.298422824228 };
}
/** Creates the default probability density test expected values */
@Override
public double[] makeDensityTestValues() {
return new double[] { 0, 0, 0, 0, 0.0594218160072, 0.0436977691036,
0.0508364857798, 0.054873528325, 0.0587182664085,
0.0636229042785 };
}
/**
* Creates the default inverse cumulative probability distribution test
* input values.
*/
@Override
public double[] makeInverseCumulativeTestPoints() {
// Exclude the test points less than zero, as they have cumulative
// probability of zero, meaning the inverse returns zero, and not the
// points less than zero.
double[] points = makeCumulativeTestValues();
double[] points2 = new double[points.length - 4];
System.arraycopy(points, 4, points2, 0, points2.length - 4);
return points2;
//return Arrays.copyOfRange(points, 4, points.length - 4);
}
/**
* Creates the default inverse cumulative probability test expected
* values.
*/
@Override
public double[] makeInverseCumulativeTestValues() {
// Exclude the test points less than zero, as they have cumulative
// probability of zero, meaning the inverse returns zero, and not the
// points less than zero.
double[] points = makeCumulativeTestPoints();
double[] points2 = new double[points.length - 4];
System.arraycopy(points, 4, points2, 0, points2.length - 4);
return points2;
//return Arrays.copyOfRange(points, 1, points.length - 4);
}
// --------------------- Override tolerance --------------
@Override
public void setUp() {
super.setUp();
setTolerance(LogNormalDistribution.DEFAULT_INVERSE_ABSOLUTE_ACCURACY);
}
//---------------------------- Additional test cases -------------------------
private void verifyQuantiles() {
LogNormalDistribution distribution = (LogNormalDistribution)getDistribution();
double mu = distribution.getScale();
double sigma = distribution.getShape();
setCumulativeTestPoints( new double[] { mu - 2 *sigma, mu - sigma,
mu, mu + sigma, mu + 2 * sigma,
mu + 3 * sigma,mu + 4 * sigma,
mu + 5 * sigma });
verifyCumulativeProbabilities();
}
@Test
public void testQuantiles() {
setCumulativeTestValues(new double[] {0, 0.0396495152787,
0.16601209243, 0.272533253269,
0.357618409638, 0.426488363093,
0.483255136841, 0.530823013877});
setDensityTestValues(new double[] {0, 0.0873055825147, 0.0847676303432,
0.0677935186237, 0.0544105523058,
0.0444614628804, 0.0369750288945,
0.0312206409653});
verifyQuantiles();
verifyDensities();
setDistribution(new LogNormalDistribution(0, 1));
setCumulativeTestValues(new double[] {0, 0, 0, 0.5, 0.755891404214,
0.864031392359, 0.917171480998,
0.946239689548});
setDensityTestValues(new double[] {0, 0, 0, 0.398942280401,
0.156874019279, 0.07272825614,
0.0381534565119, 0.0218507148303});
verifyQuantiles();
verifyDensities();
setDistribution(new LogNormalDistribution(0, 0.1));
setCumulativeTestValues(new double[] {0, 0, 0, 1.28417563064e-117,
1.39679883412e-58,
1.09839325447e-33,
2.52587961726e-20,
2.0824223487e-12});
setDensityTestValues(new double[] {0, 0, 0, 2.96247992535e-114,
1.1283370232e-55, 4.43812313223e-31,
5.85346445002e-18,
2.9446618076e-10});
verifyQuantiles();
verifyDensities();
}
@Test
public void testInverseCumulativeProbabilityExtremes() {
setInverseCumulativeTestPoints(new double[] {0, 1});
setInverseCumulativeTestValues(
new double[] {0, Double.POSITIVE_INFINITY});
verifyInverseCumulativeProbabilities();
}
@Test
public void testGetScale() {
LogNormalDistribution distribution = (LogNormalDistribution)getDistribution();
Assert.assertEquals(2.1, distribution.getScale(), 0);
}
@Test
public void testGetShape() {
LogNormalDistribution distribution = (LogNormalDistribution)getDistribution();
Assert.assertEquals(1.4, distribution.getShape(), 0);
}
@Test(expected=NotStrictlyPositiveException.class)
public void testPreconditions() {
new LogNormalDistribution(1, 0);
}
@Test
public void testDensity() {
double [] x = new double[]{-2, -1, 0, 1, 2};
// R 2.13: print(dlnorm(c(-2,-1,0,1,2)), digits=10)
checkDensity(0, 1, x, new double[] { 0.0000000000, 0.0000000000,
0.0000000000, 0.3989422804,
0.1568740193 });
// R 2.13: print(dlnorm(c(-2,-1,0,1,2), mean=1.1), digits=10)
checkDensity(1.1, 1, x, new double[] { 0.0000000000, 0.0000000000,
0.0000000000, 0.2178521770,
0.1836267118});
}
private void checkDensity(double scale, double shape, double[] x,
double[] expected) {
LogNormalDistribution d = new LogNormalDistribution(scale, shape);
for (int i = 0; i < x.length; i++) {
Assert.assertEquals(expected[i], d.density(x[i]), 1e-9);
}
}
/**
* Check to make sure top-coding of extreme values works correctly.
* Verifies fixes for JIRA MATH-167, MATH-414
*/
@Test
public void testExtremeValues() {
LogNormalDistribution d = new LogNormalDistribution(0, 1);
for (int i = 0; i < 1e5; i++) { // make sure no convergence exception
double upperTail = d.cumulativeProbability(i);
if (i <= 72) { // make sure not top-coded
Assert.assertTrue(upperTail < 1.0d);
}
else { // make sure top coding not reversed
Assert.assertTrue(upperTail > 0.99999);
}
}
Assert.assertEquals(d.cumulativeProbability(Double.MAX_VALUE), 1, 0);
Assert.assertEquals(d.cumulativeProbability(-Double.MAX_VALUE), 0, 0);
Assert.assertEquals(d.cumulativeProbability(Double.POSITIVE_INFINITY), 1, 0);
Assert.assertEquals(d.cumulativeProbability(Double.NEGATIVE_INFINITY), 0, 0);
}
@Test
public void testMeanVariance() {
final double tol = 1e-9;
LogNormalDistribution dist;
dist = new LogNormalDistribution(0, 1);
Assert.assertEquals(dist.getNumericalMean(), 1.6487212707001282, tol);
Assert.assertEquals(dist.getNumericalVariance(),
4.670774270471604, tol);
dist = new LogNormalDistribution(2.2, 1.4);
Assert.assertEquals(dist.getNumericalMean(), 24.046753552064498, tol);
Assert.assertEquals(dist.getNumericalVariance(),
3526.913651880464, tol);
dist = new LogNormalDistribution(-2000.9, 10.4);
Assert.assertEquals(dist.getNumericalMean(), 0.0, tol);
Assert.assertEquals(dist.getNumericalVariance(), 0.0, tol);
}
@Test
public void testTinyVariance() {
LogNormalDistribution dist = new LogNormalDistribution(0, 1e-9);
double t = dist.getNumericalVariance();
Assert.assertEquals(1e-18, t, 1e-20);
}
}

View File

@ -1,73 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.distribution.LogisticDistribution;
import org.apache.commons.numbers.core.Precision;
import org.junit.Assert;
import org.junit.Test;
/**
* Test cases for LogisticsDistribution.
*/
public class LogisticsDistributionTest extends RealDistributionAbstractTest {
@Test
public void testParameters() {
LogisticDistribution d = makeDistribution();
Assert.assertEquals(2, d.getLocation(), Precision.EPSILON);
Assert.assertEquals(5, d.getScale(), Precision.EPSILON);
}
@Test
public void testSupport() {
LogisticDistribution d = makeDistribution();
Assert.assertTrue(Double.isInfinite(d.getSupportLowerBound()));
Assert.assertTrue(Double.isInfinite(d.getSupportUpperBound()));
Assert.assertTrue(d.isSupportConnected());
}
@Override
public LogisticDistribution makeDistribution() {
return new LogisticDistribution(2, 5);
}
@Override
public double[] makeCumulativeTestPoints() {
return new double[] {
-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5
};
}
@Override
public double[] makeDensityTestValues() {
return new double[] {
0.03173698, 0.03557889, 0.03932239, 0.04278194, 0.04575685, 0.04805215,
0.04950331, 0.05000000, 0.04950331, 0.04805215, 0.04575685
};
}
@Override
public double[] makeCumulativeTestValues() {
return new double[] {
0.1978161, 0.2314752, 0.2689414, 0.3100255, 0.3543437, 0.4013123,
0.4501660, 0.5000000, 0.5498340, 0.5986877, 0.6456563
};
}
}

View File

@ -1,73 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.distribution.NakagamiDistribution;
import org.apache.commons.numbers.core.Precision;
import org.junit.Assert;
import org.junit.Test;
/**
* Test cases for NakagamiDistribution.
*/
public class NakagamiDistributionTest extends RealDistributionAbstractTest {
@Test
public void testParameters() {
NakagamiDistribution d = makeDistribution();
Assert.assertEquals(0.5, d.getShape(), Precision.EPSILON);
Assert.assertEquals(1, d.getScale(), Precision.EPSILON);
}
@Test
public void testSupport() {
NakagamiDistribution d = makeDistribution();
Assert.assertEquals(d.getSupportLowerBound(), 0, Precision.EPSILON);
Assert.assertTrue(Double.isInfinite(d.getSupportUpperBound()));
Assert.assertTrue(d.isSupportConnected());
}
@Override
public NakagamiDistribution makeDistribution() {
return new NakagamiDistribution(0.5, 1);
}
@Override
public double[] makeCumulativeTestPoints() {
return new double[] {
0, 0.2, 0.4, 0.6, 0.8, 1, 1.2, 1.4, 1.6, 1.8, 2
};
}
@Override
public double[] makeDensityTestValues() {
return new double[] {
0.0000000, 0.7820854, 0.7365403, 0.6664492, 0.5793831, 0.4839414,
0.3883721, 0.2994549, 0.2218417, 0.1579003, 0.1079819
};
}
@Override
public double[] makeCumulativeTestValues() {
return new double[] {
0.0000000, 0.1585194, 0.3108435, 0.4514938, 0.5762892, 0.6826895,
0.7698607, 0.8384867, 0.8904014, 0.9281394, 0.9544997
};
}
}

View File

@ -1,216 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.distribution.NormalDistribution;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.junit.Assert;
import org.junit.Test;
/**
* Test cases for {@link NormalDistribution}. Extends
* {@link RealDistributionAbstractTest}. See class javadoc of that class
* for details.
*
*/
public class NormalDistributionTest extends RealDistributionAbstractTest {
//-------------- Implementations for abstract methods -----------------------
/** Creates the default real distribution instance to use in tests. */
@Override
public NormalDistribution makeDistribution() {
return new NormalDistribution(2.1, 1.4);
}
/** Creates the default cumulative probability distribution test input values */
@Override
public double[] makeCumulativeTestPoints() {
// quantiles computed using R
return new double[] {-2.226325228634938d, -1.156887023657177d, -0.643949578356075d, -0.2027950777320613d, 0.305827808237559d,
6.42632522863494d, 5.35688702365718d, 4.843949578356074d, 4.40279507773206d, 3.89417219176244d};
}
/** Creates the default cumulative probability density test expected values */
@Override
public double[] makeCumulativeTestValues() {
return new double[] {0.001d, 0.01d, 0.025d, 0.05d, 0.1d, 0.999d,
0.990d, 0.975d, 0.950d, 0.900d};
}
/** Creates the default probability density test expected values */
@Override
public double[] makeDensityTestValues() {
return new double[] {0.00240506434076, 0.0190372444310, 0.0417464784322, 0.0736683145538, 0.125355951380,
0.00240506434076, 0.0190372444310, 0.0417464784322, 0.0736683145538, 0.125355951380};
}
// --------------------- Override tolerance --------------
protected double defaultTolerance = NormalDistribution.DEFAULT_INVERSE_ABSOLUTE_ACCURACY;
@Override
public void setUp() {
super.setUp();
setTolerance(defaultTolerance);
}
//---------------------------- Additional test cases -------------------------
private void verifyQuantiles() {
NormalDistribution distribution = (NormalDistribution) getDistribution();
double mu = distribution.getMean();
double sigma = distribution.getStandardDeviation();
setCumulativeTestPoints( new double[] {mu - 2 *sigma, mu - sigma,
mu, mu + sigma, mu + 2 * sigma, mu + 3 * sigma, mu + 4 * sigma,
mu + 5 * sigma});
// Quantiles computed using R (same as Mathematica)
setCumulativeTestValues(new double[] {0.02275013194817921, 0.158655253931457, 0.5, 0.841344746068543,
0.977249868051821, 0.99865010196837, 0.999968328758167, 0.999999713348428});
verifyCumulativeProbabilities();
}
@Test
public void testQuantiles() {
setDensityTestValues(new double[] {0.0385649760808, 0.172836231799, 0.284958771715, 0.172836231799, 0.0385649760808,
0.00316560600853, 9.55930184035e-05, 1.06194251052e-06});
verifyQuantiles();
verifyDensities();
setDistribution(new NormalDistribution(0, 1));
setDensityTestValues(new double[] {0.0539909665132, 0.241970724519, 0.398942280401, 0.241970724519, 0.0539909665132,
0.00443184841194, 0.000133830225765, 1.48671951473e-06});
verifyQuantiles();
verifyDensities();
setDistribution(new NormalDistribution(0, 0.1));
setDensityTestValues(new double[] {0.539909665132, 2.41970724519, 3.98942280401, 2.41970724519,
0.539909665132, 0.0443184841194, 0.00133830225765, 1.48671951473e-05});
verifyQuantiles();
verifyDensities();
}
@Test
public void testInverseCumulativeProbabilityExtremes() {
setInverseCumulativeTestPoints(new double[] {0, 1});
setInverseCumulativeTestValues(
new double[] {Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY});
verifyInverseCumulativeProbabilities();
}
// MATH-1257
@Test
public void testCumulativeProbability() {
final RealDistribution dist = new NormalDistribution(0, 1);
double x = -10;
double expected = 7.61985e-24;
double v = dist.cumulativeProbability(x);
double tol = 1e-5;
Assert.assertEquals(1, v / expected, 1e-5);
}
@Test
public void testGetMean() {
NormalDistribution distribution = (NormalDistribution) getDistribution();
Assert.assertEquals(2.1, distribution.getMean(), 0);
}
@Test
public void testGetStandardDeviation() {
NormalDistribution distribution = (NormalDistribution) getDistribution();
Assert.assertEquals(1.4, distribution.getStandardDeviation(), 0);
}
@Test(expected=NotStrictlyPositiveException.class)
public void testPreconditions() {
new NormalDistribution(1, 0);
}
@Test
public void testDensity() {
double [] x = new double[]{-2, -1, 0, 1, 2};
// R 2.5: print(dnorm(c(-2,-1,0,1,2)), digits=10)
checkDensity(0, 1, x, new double[]{0.05399096651, 0.24197072452, 0.39894228040, 0.24197072452, 0.05399096651});
// R 2.5: print(dnorm(c(-2,-1,0,1,2), mean=1.1), digits=10)
checkDensity(1.1, 1, x, new double[]{0.003266819056,0.043983595980,0.217852177033,0.396952547477,0.266085249899});
}
private void checkDensity(double mean, double sd, double[] x, double[] expected) {
NormalDistribution d = new NormalDistribution(mean, sd);
for (int i = 0; i < x.length; i++) {
Assert.assertEquals(expected[i], d.density(x[i]), 1e-9);
}
}
/**
* Check to make sure top-coding of extreme values works correctly.
* Verifies fixes for JIRA MATH-167, MATH-414
*/
@Test
public void testExtremeValues() {
NormalDistribution distribution = new NormalDistribution(0, 1);
for (int i = 0; i < 100; i++) { // make sure no convergence exception
double lowerTail = distribution.cumulativeProbability(-i);
double upperTail = distribution.cumulativeProbability(i);
if (i < 9) { // make sure not top-coded
// For i = 10, due to bad tail precision in erf (MATH-364), 1 is returned
// TODO: once MATH-364 is resolved, replace 9 with 30
Assert.assertTrue(lowerTail > 0.0d);
Assert.assertTrue(upperTail < 1.0d);
}
else { // make sure top coding not reversed
Assert.assertTrue(lowerTail < 0.00001);
Assert.assertTrue(upperTail > 0.99999);
}
}
Assert.assertEquals(distribution.cumulativeProbability(Double.MAX_VALUE), 1, 0);
Assert.assertEquals(distribution.cumulativeProbability(-Double.MAX_VALUE), 0, 0);
Assert.assertEquals(distribution.cumulativeProbability(Double.POSITIVE_INFINITY), 1, 0);
Assert.assertEquals(distribution.cumulativeProbability(Double.NEGATIVE_INFINITY), 0, 0);
}
@Test
public void testMath280() {
NormalDistribution normal = new NormalDistribution(0,1);
double result = normal.inverseCumulativeProbability(0.9986501019683698);
Assert.assertEquals(3.0, result, defaultTolerance);
result = normal.inverseCumulativeProbability(0.841344746068543);
Assert.assertEquals(1.0, result, defaultTolerance);
result = normal.inverseCumulativeProbability(0.9999683287581673);
Assert.assertEquals(4.0, result, defaultTolerance);
result = normal.inverseCumulativeProbability(0.9772498680518209);
Assert.assertEquals(2.0, result, defaultTolerance);
}
@Test
public void testMoments() {
final double tol = 1e-9;
NormalDistribution dist;
dist = new NormalDistribution(0, 1);
Assert.assertEquals(dist.getNumericalMean(), 0, tol);
Assert.assertEquals(dist.getNumericalVariance(), 1, tol);
dist = new NormalDistribution(2.2, 1.4);
Assert.assertEquals(dist.getNumericalMean(), 2.2, tol);
Assert.assertEquals(dist.getNumericalVariance(), 1.4 * 1.4, tol);
dist = new NormalDistribution(-2000.9, 10.4);
Assert.assertEquals(dist.getNumericalMean(), -2000.9, tol);
Assert.assertEquals(dist.getNumericalVariance(), 10.4 * 10.4, tol);
}
}

View File

@ -1,206 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.distribution.ParetoDistribution;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.junit.Assert;
import org.junit.Test;
/**
* Test cases for {@link ParetoDistribution}.
* <p>
* Extends {@link RealDistributionAbstractTest}. See class javadoc of that class for details.
*
* @since 3.3
*/
public class ParetoDistributionTest extends RealDistributionAbstractTest {
//-------------- Implementations for abstract methods -----------------------
/** Creates the default real distribution instance to use in tests. */
@Override
public ParetoDistribution makeDistribution() {
return new ParetoDistribution(2.1, 1.4);
}
/** Creates the default cumulative probability distribution test input values */
@Override
public double[] makeCumulativeTestPoints() {
// quantiles computed using R
return new double[] { -2.226325228634938, -1.156887023657177, -0.643949578356075, -0.2027950777320613, 0.305827808237559,
+6.42632522863494, 5.35688702365718, 4.843949578356074, 4.40279507773206, 3.89417219176244 };
}
/** Creates the default cumulative probability density test expected values */
@Override
public double[] makeCumulativeTestValues() {
return new double[] { 0, 0, 0, 0, 0, 0.791089998892, 0.730456085931, 0.689667290488, 0.645278794701, 0.578763688757 };
}
/** Creates the default probability density test expected values */
@Override
public double[] makeDensityTestValues() {
return new double[] { 0, 0, 0, 0, 0, 0.0455118580441, 0.070444173646, 0.0896924681582, 0.112794186114, 0.151439332084 };
}
/**
* Creates the default inverse cumulative probability distribution test input values.
*/
@Override
public double[] makeInverseCumulativeTestPoints() {
// Exclude the test points less than zero, as they have cumulative
// probability of zero, meaning the inverse returns zero, and not the
// points less than zero.
double[] points = makeCumulativeTestValues();
double[] points2 = new double[points.length - 5];
System.arraycopy(points, 5, points2, 0, points.length - 5);
return points2;
}
/**
* Creates the default inverse cumulative probability test expected values.
*/
@Override
public double[] makeInverseCumulativeTestValues() {
// Exclude the test points less than zero, as they have cumulative
// probability of zero, meaning the inverse returns zero, and not the
// points less than zero.
double[] points = makeCumulativeTestPoints();
double[] points2 = new double[points.length - 5];
System.arraycopy(points, 5, points2, 0, points.length - 5);
return points2;
}
// --------------------- Override tolerance --------------
@Override
public void setUp() {
super.setUp();
setTolerance(ParetoDistribution.DEFAULT_INVERSE_ABSOLUTE_ACCURACY);
}
//---------------------------- Additional test cases -------------------------
private void verifyQuantiles() {
ParetoDistribution distribution = (ParetoDistribution)getDistribution();
double mu = distribution.getScale();
double sigma = distribution.getShape();
setCumulativeTestPoints( new double[] { mu - 2 *sigma, mu - sigma,
mu, mu + sigma,
mu + 2 * sigma, mu + 3 * sigma,
mu + 4 * sigma, mu + 5 * sigma });
verifyCumulativeProbabilities();
}
@Test
public void testQuantiles() {
setCumulativeTestValues(new double[] {0, 0, 0, 0.510884134236, 0.694625688662, 0.785201995008, 0.837811522357, 0.871634279326});
setDensityTestValues(new double[] {0, 0, 0.666666666, 0.195646346305, 0.0872498032394, 0.0477328899983, 0.0294888141169, 0.0197485724114});
verifyQuantiles();
verifyDensities();
setDistribution(new ParetoDistribution(1, 1));
setCumulativeTestValues(new double[] {0, 0, 0, 0.5, 0.666666666667, 0.75, 0.8, 0.833333333333});
setDensityTestValues(new double[] {0, 0, 1.0, 0.25, 0.111111111111, 0.0625, 0.04, 0.0277777777778});
verifyQuantiles();
verifyDensities();
setDistribution(new ParetoDistribution(0.1, 0.1));
setCumulativeTestValues(new double[] {0, 0, 0, 0.0669670084632, 0.104041540159, 0.129449436704, 0.148660077479, 0.164041197922});
setDensityTestValues(new double[] {0, 0, 1.0, 0.466516495768, 0.298652819947, 0.217637640824, 0.170267984504, 0.139326467013});
verifyQuantiles();
verifyDensities();
}
@Test
public void testInverseCumulativeProbabilityExtremes() {
setInverseCumulativeTestPoints(new double[] {0, 1});
setInverseCumulativeTestValues(new double[] {2.1, Double.POSITIVE_INFINITY});
verifyInverseCumulativeProbabilities();
}
@Test
public void testGetScale() {
ParetoDistribution distribution = (ParetoDistribution)getDistribution();
Assert.assertEquals(2.1, distribution.getScale(), 0);
}
@Test
public void testGetShape() {
ParetoDistribution distribution = (ParetoDistribution)getDistribution();
Assert.assertEquals(1.4, distribution.getShape(), 0);
}
@Test(expected=NotStrictlyPositiveException.class)
public void testPreconditions() {
new ParetoDistribution(1, 0);
}
@Test
public void testDensity() {
double [] x = new double[]{-2, -1, 0, 1, 2};
// R 2.14: print(dpareto(c(-2,-1,0,1,2), scale=1, shape=1), digits=10)
checkDensity(1, 1, x, new double[] { 0.00, 0.00, 0.00, 1.00, 0.25 });
// R 2.14: print(dpareto(c(-2,-1,0,1,2), scale=1.1, shape=1), digits=10)
checkDensity(1.1, 1, x, new double[] { 0.000, 0.000, 0.000, 0.000, 0.275 });
}
private void checkDensity(double scale, double shape, double[] x,
double[] expected) {
ParetoDistribution d = new ParetoDistribution(scale, shape);
for (int i = 0; i < x.length; i++) {
Assert.assertEquals(expected[i], d.density(x[i]), 1e-9);
}
}
/**
* Check to make sure top-coding of extreme values works correctly.
*/
@Test
public void testExtremeValues() {
ParetoDistribution d = new ParetoDistribution(1, 1);
for (int i = 0; i < 1e5; i++) { // make sure no convergence exception
double upperTail = d.cumulativeProbability(i);
if (i <= 1000) { // make sure not top-coded
Assert.assertTrue(upperTail < 1.0d);
}
else { // make sure top coding not reversed
Assert.assertTrue(upperTail > 0.999);
}
}
Assert.assertEquals(d.cumulativeProbability(Double.MAX_VALUE), 1, 0);
Assert.assertEquals(d.cumulativeProbability(-Double.MAX_VALUE), 0, 0);
Assert.assertEquals(d.cumulativeProbability(Double.POSITIVE_INFINITY), 1, 0);
Assert.assertEquals(d.cumulativeProbability(Double.NEGATIVE_INFINITY), 0, 0);
}
@Test
public void testMeanVariance() {
final double tol = 1e-9;
ParetoDistribution dist;
dist = new ParetoDistribution(1, 1);
Assert.assertEquals(dist.getNumericalMean(), Double.POSITIVE_INFINITY, tol);
Assert.assertEquals(dist.getNumericalVariance(), Double.POSITIVE_INFINITY, tol);
dist = new ParetoDistribution(2.2, 2.4);
Assert.assertEquals(dist.getNumericalMean(), 3.771428571428, tol);
Assert.assertEquals(dist.getNumericalVariance(), 14.816326530, tol);
}
}

View File

@ -1,135 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.distribution.IntegerDistribution;
import org.apache.commons.math4.distribution.NormalDistribution;
import org.apache.commons.math4.distribution.PascalDistribution;
import org.junit.Assert;
import org.junit.Test;
/**
* Test cases for PascalDistribution.
* Extends IntegerDistributionAbstractTest. See class javadoc for
* IntegerDistributionAbstractTest for details.
*
*/
public class PascalDistributionTest extends IntegerDistributionAbstractTest {
// --------------------- Override tolerance --------------
protected double defaultTolerance = NormalDistribution.DEFAULT_INVERSE_ABSOLUTE_ACCURACY;
@Override
public void setUp() {
super.setUp();
setTolerance(defaultTolerance);
}
//-------------- Implementations for abstract methods -----------------------
/** Creates the default discrete distribution instance to use in tests. */
@Override
public IntegerDistribution makeDistribution() {
return new PascalDistribution(10,0.70);
}
/** Creates the default probability density test input values */
@Override
public int[] makeDensityTestPoints() {
return new int[] {-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
}
/** Creates the default probability density test expected values */
@Override
public double[] makeDensityTestValues() {
return new double[] {0, 0.0282475249, 0.0847425747, 0.139825248255, 0.167790297906, 0.163595540458,
0.137420253985, 0.103065190489, 0.070673273478, 0.0450542118422, 0.0270325271053,
0.0154085404500, 0.0084046584273};
}
/** Creates the default cumulative probability density test input values */
@Override
public int[] makeCumulativeTestPoints() {
return makeDensityTestPoints();
}
/** Creates the default cumulative probability density test expected values */
@Override
public double[] makeCumulativeTestValues() {
return new double[] {0, 0.0282475249, 0.1129900996, 0.252815347855, 0.420605645761, 0.584201186219,
0.721621440204, 0.824686630693, 0.895359904171, 0.940414116013, 0.967446643119,
0.982855183569, 0.991259841996};
}
/** Creates the default inverse cumulative probability test input values */
@Override
public double[] makeInverseCumulativeTestPoints() {
return new double[] {0.0, 0.001, 0.010, 0.025, 0.050, 0.100, 0.999,
0.990, 0.975, 0.950, 0.900, 1.0};
}
/** Creates the default inverse cumulative probability density test expected values */
@Override
public int[] makeInverseCumulativeTestValues() {
return new int[] {0, 0, 0, 0, 1, 1, 14, 11, 10, 9, 8, Integer.MAX_VALUE};
}
//----------------- Additional test cases ---------------------------------
/** Test degenerate case p = 0 */
@Test
public void testDegenerate0() {
setDistribution(new PascalDistribution(5, 0.0d));
setCumulativeTestPoints(new int[] {-1, 0, 1, 5, 10 });
setCumulativeTestValues(new double[] {0d, 0d, 0d, 0d, 0d});
setDensityTestPoints(new int[] {-1, 0, 1, 10, 11});
setDensityTestValues(new double[] {0d, 0d, 0d, 0d, 0d});
setInverseCumulativeTestPoints(new double[] {0.1d, 0.5d});
setInverseCumulativeTestValues(new int[] {Integer.MAX_VALUE, Integer.MAX_VALUE});
verifyDensities();
verifyCumulativeProbabilities();
verifyInverseCumulativeProbabilities();
}
/** Test degenerate case p = 1 */
@Test
public void testDegenerate1() {
setDistribution(new PascalDistribution(5, 1.0d));
setCumulativeTestPoints(new int[] {-1, 0, 1, 2, 5, 10 });
setCumulativeTestValues(new double[] {0d, 1d, 1d, 1d, 1d, 1d});
setDensityTestPoints(new int[] {-1, 0, 1, 2, 5, 10});
setDensityTestValues(new double[] {0d, 1d, 0d, 0d, 0d, 0d});
setInverseCumulativeTestPoints(new double[] {0.1d, 0.5d});
setInverseCumulativeTestValues(new int[] {0, 0});
verifyDensities();
verifyCumulativeProbabilities();
verifyInverseCumulativeProbabilities();
}
@Test
public void testMoments() {
final double tol = 1e-9;
PascalDistribution dist;
dist = new PascalDistribution(10, 0.5);
Assert.assertEquals(dist.getNumericalMean(), ( 10d * 0.5d ) / 0.5d, tol);
Assert.assertEquals(dist.getNumericalVariance(), ( 10d * 0.5d ) / (0.5d * 0.5d), tol);
dist = new PascalDistribution(25, 0.7);
Assert.assertEquals(dist.getNumericalMean(), ( 25d * 0.3d ) / 0.7d, tol);
Assert.assertEquals(dist.getNumericalVariance(), ( 25d * 0.3d ) / (0.7d * 0.7d), tol);
}
}

View File

@ -1,248 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.distribution.IntegerDistribution;
import org.apache.commons.math4.distribution.PoissonDistribution;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.math4.util.FastMath;
import org.junit.Assert;
import org.junit.Test;
/**
* <code>PoissonDistributionTest</code>
*
*/
public class PoissonDistributionTest extends IntegerDistributionAbstractTest {
/**
* Poisson parameter value for the test distribution.
*/
private static final double DEFAULT_TEST_POISSON_PARAMETER = 4.0;
/**
* Constructor.
*/
public PoissonDistributionTest() {
setTolerance(1e-12);
}
/**
* Creates the default discrete distribution instance to use in tests.
*/
@Override
public IntegerDistribution makeDistribution() {
return new PoissonDistribution(DEFAULT_TEST_POISSON_PARAMETER);
}
/**
* Creates the default probability density test input values.
*/
@Override
public int[] makeDensityTestPoints() {
return new int[] { -1, 0, 1, 2, 3, 4, 5, 10, 20};
}
/**
* Creates the default probability density test expected values.
* These and all other test values are generated by R, version 1.8.1
*/
@Override
public double[] makeDensityTestValues() {
return new double[] { 0d, 0.0183156388887d, 0.073262555555d,
0.14652511111d, 0.195366814813d, 0.195366814813,
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.
*/
@Override
public int[] makeCumulativeTestPoints() {
return new int[] { -1, 0, 1, 2, 3, 4, 5, 10, 20 };
}
/**
* Creates the default cumulative probability density test expected values.
*/
@Override
public double[] makeCumulativeTestValues() {
return new double[] { 0d, 0.0183156388887d, 0.0915781944437d,
0.238103305554d, 0.433470120367d, 0.62883693518,
0.78513038703d, 0.99716023388d, 0.999999998077 };
}
/**
* Creates the default inverse cumulative probability test input values.
*/
@Override
public double[] makeInverseCumulativeTestPoints() {
IntegerDistribution dist = getDistribution();
return new double[] { 0d, 0.018315638886d, 0.018315638890d,
0.091578194441d, 0.091578194445d, 0.238103305552d,
0.238103305556d, dist.cumulativeProbability(3),
dist.cumulativeProbability(4), dist.cumulativeProbability(5),
dist.cumulativeProbability(10), dist.cumulativeProbability(20)};
}
/**
* Creates the default inverse cumulative probability density test expected values.
*/
@Override
public int[] makeInverseCumulativeTestValues() {
return new int[] { 0, 0, 1, 1, 2, 2, 3, 3, 4, 5, 10, 20};
}
/**
* Test the normal approximation of the Poisson distribution by
* calculating P(90 &le; X &le; 110) for X = Po(100) and
* P(9900 &le; X &le; 10200) for X = Po(10000)
*/
@Test
public void testNormalApproximateProbability() {
PoissonDistribution dist = new PoissonDistribution(100);
double result = dist.normalApproximateProbability(110)
- dist.normalApproximateProbability(89);
Assert.assertEquals(0.706281887248, result, 1E-10);
dist = new PoissonDistribution(10000);
result = dist.normalApproximateProbability(10200)
- dist.normalApproximateProbability(9899);
Assert.assertEquals(0.820070051552, result, 1E-10);
}
/**
* Test the degenerate cases of a 0.0 and 1.0 inverse cumulative probability.
*/
@Test
public void testDegenerateInverseCumulativeProbability() {
PoissonDistribution dist = new PoissonDistribution(DEFAULT_TEST_POISSON_PARAMETER);
Assert.assertEquals(Integer.MAX_VALUE, dist.inverseCumulativeProbability(1.0d));
Assert.assertEquals(0, dist.inverseCumulativeProbability(0d));
}
@Test(expected=NotStrictlyPositiveException.class)
public void testNegativeMean() {
new PoissonDistribution(-1);
}
@Test
public void testMean() {
PoissonDistribution dist = new PoissonDistribution(10.0);
Assert.assertEquals(10.0, dist.getMean(), 0.0);
}
@Test
public void testLargeMeanCumulativeProbability() {
double mean = 1.0;
while (mean <= 10000000.0) {
PoissonDistribution dist = new PoissonDistribution(mean);
double x = mean * 2.0;
double dx = x / 10.0;
double p = Double.NaN;
double sigma = FastMath.sqrt(mean);
while (x >= 0) {
try {
p = dist.cumulativeProbability((int) x);
Assert.assertFalse("NaN cumulative probability returned for mean = " +
mean + " x = " + x,Double.isNaN(p));
if (x > mean - 2 * sigma) {
Assert.assertTrue("Zero cum probaility returned for mean = " +
mean + " x = " + x, p > 0);
}
} catch (Exception ex) {
Assert.fail("mean of " + mean + " and x of " + x + " caused " + ex.getMessage());
}
x -= dx;
}
mean *= 10.0;
}
}
/**
* JIRA: MATH-282
*/
@Test
public void testCumulativeProbabilitySpecial() {
PoissonDistribution dist;
dist = new PoissonDistribution(9120);
checkProbability(dist, 9075);
checkProbability(dist, 9102);
dist = new PoissonDistribution(5058);
checkProbability(dist, 5044);
dist = new PoissonDistribution(6986);
checkProbability(dist, 6950);
}
private void checkProbability(PoissonDistribution dist, int x) {
double p = dist.cumulativeProbability(x);
Assert.assertFalse("NaN cumulative probability returned for mean = " +
dist.getMean() + " x = " + x, Double.isNaN(p));
Assert.assertTrue("Zero cum probability returned for mean = " +
dist.getMean() + " x = " + x, p > 0);
}
@Test
public void testLargeMeanInverseCumulativeProbability() {
double mean = 1.0;
while (mean <= 100000.0) { // Extended test value: 1E7. Reduced to limit run time.
PoissonDistribution dist = new PoissonDistribution(mean);
double p = 0.1;
double dp = p;
while (p < .99) {
try {
int ret = dist.inverseCumulativeProbability(p);
// Verify that returned value satisties definition
Assert.assertTrue(p <= dist.cumulativeProbability(ret));
Assert.assertTrue(p > dist.cumulativeProbability(ret - 1));
} catch (Exception ex) {
Assert.fail("mean of " + mean + " and p of " + p + " caused " + ex.getMessage());
}
p += dp;
}
mean *= 10.0;
}
}
@Test
public void testMoments() {
final double tol = 1e-9;
PoissonDistribution dist;
dist = new PoissonDistribution(1);
Assert.assertEquals(dist.getNumericalMean(), 1, tol);
Assert.assertEquals(dist.getNumericalVariance(), 1, tol);
dist = new PoissonDistribution(11.23);
Assert.assertEquals(dist.getNumericalMean(), 11.23, tol);
Assert.assertEquals(dist.getNumericalVariance(), 11.23, tol);
}
}

View File

@ -1,173 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.junit.Assert;
import org.junit.Test;
import org.apache.commons.math4.TestUtils;
import org.apache.commons.math4.distribution.TDistribution;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
/**
* Test cases for TDistribution.
* Extends ContinuousDistributionAbstractTest. See class javadoc for
* ContinuousDistributionAbstractTest for details.
*
*/
public class TDistributionTest extends RealDistributionAbstractTest {
//-------------- Implementations for abstract methods -----------------------
/** Creates the default continuous distribution instance to use in tests. */
@Override
public TDistribution makeDistribution() {
return new TDistribution(5.0);
}
/** Creates the default cumulative probability distribution test input values */
@Override
public double[] makeCumulativeTestPoints() {
// quantiles computed using R version 2.9.2
return new double[] {-5.89342953136, -3.36492999891, -2.57058183564, -2.01504837333, -1.47588404882,
5.89342953136, 3.36492999891, 2.57058183564, 2.01504837333, 1.47588404882};
}
/** Creates the default cumulative probability density test expected values */
@Override
public double[] makeCumulativeTestValues() {
return new double[] {0.001, 0.01, 0.025, 0.05, 0.1, 0.999,
0.990, 0.975, 0.950, 0.900};
}
/** Creates the default probability density test expected values */
@Override
public double[] makeDensityTestValues() {
return new double[] {0.000756494565517, 0.0109109752919, 0.0303377878006, 0.0637967988952, 0.128289492005,
0.000756494565517, 0.0109109752919, 0.0303377878006, 0.0637967988952, 0.128289492005};
}
// --------------------- Override tolerance --------------
@Override
public void setUp() {
super.setUp();
setTolerance(1E-9);
}
//---------------------------- Additional test cases -------------------------
/**
* @see <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=27243">
* Bug report that prompted this unit test.</a>
*/
@Test
public void testCumulativeProbabilityAgainstStackOverflow() {
TDistribution td = new TDistribution(5.);
td.cumulativeProbability(.1);
td.cumulativeProbability(.01);
}
@Test
public void testSmallDf() {
setDistribution(new TDistribution(1d));
// quantiles computed using R version 2.9.2
setCumulativeTestPoints(new double[] {-318.308838986, -31.8205159538, -12.7062047362,
-6.31375151468, -3.07768353718, 318.308838986, 31.8205159538, 12.7062047362,
6.31375151468, 3.07768353718});
setDensityTestValues(new double[] {3.14158231817e-06, 0.000314055924703, 0.00195946145194,
0.00778959736375, 0.0303958893917, 3.14158231817e-06, 0.000314055924703,
0.00195946145194, 0.00778959736375, 0.0303958893917});
setInverseCumulativeTestValues(getCumulativeTestPoints());
verifyCumulativeProbabilities();
verifyInverseCumulativeProbabilities();
verifyDensities();
}
@Test
public void testInverseCumulativeProbabilityExtremes() {
setInverseCumulativeTestPoints(new double[] {0, 1});
setInverseCumulativeTestValues(
new double[] {Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY});
verifyInverseCumulativeProbabilities();
}
@Test
public void testCumulativeProbablilityExtremes() {
TDistribution dist;
for (int i = 1; i < 11; i++) {
dist = new TDistribution(i * 5);
Assert.assertEquals(1,
dist.cumulativeProbability(Double.POSITIVE_INFINITY), Double.MIN_VALUE);
Assert.assertEquals(0,
dist.cumulativeProbability(Double.NEGATIVE_INFINITY), Double.MIN_VALUE);
}
}
@Test
public void testDfAccessors() {
TDistribution dist = (TDistribution) getDistribution();
Assert.assertEquals(5d, dist.getDegreesOfFreedom(), Double.MIN_VALUE);
}
@Test(expected=NotStrictlyPositiveException.class)
public void testPreconditions() {
new TDistribution(0);
}
@Test
public void testMoments() {
final double tol = 1e-9;
TDistribution dist;
dist = new TDistribution(1);
Assert.assertTrue(Double.isNaN(dist.getNumericalMean()));
Assert.assertTrue(Double.isNaN(dist.getNumericalVariance()));
dist = new TDistribution(1.5);
Assert.assertEquals(dist.getNumericalMean(), 0, tol);
Assert.assertTrue(Double.isInfinite(dist.getNumericalVariance()));
dist = new TDistribution(5);
Assert.assertEquals(dist.getNumericalMean(), 0, tol);
Assert.assertEquals(dist.getNumericalVariance(), 5d / (5d - 2d), tol);
}
/*
* Adding this test to benchmark against tables published by NIST
* http://itl.nist.gov/div898/handbook/eda/section3/eda3672.htm
* Have chosen tabulated results for degrees of freedom 2,10,30,100
* Have chosen problevels from 0.10 to 0.001
*/
@Test
public void nistData(){
double[] prob = new double[]{ 0.10,0.05,0.025,0.01,0.005,0.001};
double[] args2 = new double[]{1.886,2.920,4.303,6.965,9.925,22.327};
double[] args10 = new double[]{1.372,1.812,2.228,2.764,3.169,4.143};
double[] args30 = new double[]{1.310,1.697,2.042,2.457,2.750,3.385};
double[] args100= new double[]{1.290,1.660,1.984,2.364,2.626,3.174};
TestUtils.assertEquals(prob, makeNistResults(args2, 2), 1.0e-4);
TestUtils.assertEquals(prob, makeNistResults(args10, 10), 1.0e-4);
TestUtils.assertEquals(prob, makeNistResults(args30, 30), 1.0e-4);
TestUtils.assertEquals(prob, makeNistResults(args100, 100), 1.0e-4);
return;
}
private double[] makeNistResults(double[] args, int df){
TDistribution td = new TDistribution(df);
double[] res = new double[ args.length ];
for( int i = 0 ; i < res.length ; i++){
res[i] = 1.0 - td.cumulativeProbability(args[i]);
}
return res;
}
}

View File

@ -1,194 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.distribution.TriangularDistribution;
import org.apache.commons.math4.exception.NumberIsTooLargeException;
import org.apache.commons.math4.exception.NumberIsTooSmallException;
import org.junit.Assert;
import org.junit.Test;
/**
* Test cases for {@link TriangularDistribution}. See class javadoc for
* {@link RealDistributionAbstractTest} for further details.
*/
public class TriangularDistributionTest extends RealDistributionAbstractTest {
// --- Override tolerance -------------------------------------------------
@Override
public void setUp() {
super.setUp();
setTolerance(1e-4);
}
//--- Implementations for abstract methods --------------------------------
/**
* Creates the default triangular distribution instance to use in tests.
*/
@Override
public TriangularDistribution makeDistribution() {
// Left side 5 wide, right side 10 wide.
return new TriangularDistribution(-3, 2, 12);
}
/**
* Creates the default cumulative probability distribution test input
* values.
*/
@Override
public double[] makeCumulativeTestPoints() {
return new double[] { -3.0001, // below lower limit
-3.0, // at lower limit
-2.0, -1.0, 0.0, 1.0, // on lower side
2.0, // at mode
3.0, 4.0, 10.0, 11.0, // on upper side
12.0, // at upper limit
12.0001 // above upper limit
};
}
/**
* Creates the default cumulative probability density test expected values.
*/
@Override
public double[] makeCumulativeTestValues() {
// Top at 2 / (b - a) = 2 / (12 - -3) = 2 / 15 = 7.5
// Area left = 7.5 * 5 * 0.5 = 18.75 (1/3 of the total area)
// Area right = 7.5 * 10 * 0.5 = 37.5 (2/3 of the total area)
// Area total = 18.75 + 37.5 = 56.25
// Derivative left side = 7.5 / 5 = 1.5
// Derivative right side = -7.5 / 10 = -0.75
double third = 1 / 3.0;
double left = 18.75;
double area = 56.25;
return new double[] { 0.0,
0.0,
0.75 / area, 3 / area, 6.75 / area, 12 / area,
third,
(left + 7.125) / area, (left + 13.5) / area,
(left + 36) / area, (left + 37.125) / area,
1.0,
1.0
};
}
/**
* Creates the default inverse cumulative probability distribution test
* input values.
*/
@Override
public double[] makeInverseCumulativeTestPoints() {
// Exclude the points outside the limits, as they have cumulative
// probability of zero and one, meaning the inverse returns the
// limits and not the points outside the limits.
double[] points = makeCumulativeTestValues();
double[] points2 = new double[points.length-2];
System.arraycopy(points, 1, points2, 0, points2.length);
return points2;
//return Arrays.copyOfRange(points, 1, points.length - 1);
}
/**
* Creates the default inverse cumulative probability density test expected
* values.
*/
@Override
public double[] makeInverseCumulativeTestValues() {
// Exclude the points outside the limits, as they have cumulative
// probability of zero and one, meaning the inverse returns the
// limits and not the points outside the limits.
double[] points = makeCumulativeTestPoints();
double[] points2 = new double[points.length-2];
System.arraycopy(points, 1, points2, 0, points2.length);
return points2;
//return Arrays.copyOfRange(points, 1, points.length - 1);
}
/** Creates the default probability density test expected values. */
@Override
public double[] makeDensityTestValues() {
return new double[] { 0,
0,
2 / 75.0, 4 / 75.0, 6 / 75.0, 8 / 75.0,
10 / 75.0,
9 / 75.0, 8 / 75.0, 2 / 75.0, 1 / 75.0,
0,
0
};
}
//--- Additional test cases -----------------------------------------------
/** Test lower bound getter. */
@Test
public void testGetLowerBound() {
TriangularDistribution distribution = makeDistribution();
Assert.assertEquals(-3.0, distribution.getSupportLowerBound(), 0);
}
/** Test upper bound getter. */
@Test
public void testGetUpperBound() {
TriangularDistribution distribution = makeDistribution();
Assert.assertEquals(12.0, distribution.getSupportUpperBound(), 0);
}
/** Test pre-condition for equal lower/upper limit. */
@Test(expected=NumberIsTooLargeException.class)
public void testPreconditions1() {
new TriangularDistribution(0, 0, 0);
}
/** Test pre-condition for lower limit larger than upper limit. */
@Test(expected=NumberIsTooLargeException.class)
public void testPreconditions2() {
new TriangularDistribution(1, 1, 0);
}
/** Test pre-condition for mode larger than upper limit. */
@Test(expected=NumberIsTooLargeException.class)
public void testPreconditions3() {
new TriangularDistribution(0, 2, 1);
}
/** Test pre-condition for mode smaller than lower limit. */
@Test(expected=NumberIsTooSmallException.class)
public void testPreconditions4() {
new TriangularDistribution(2, 1, 3);
}
/** Test mean/variance. */
@Test
public void testMeanVariance() {
TriangularDistribution dist;
dist = new TriangularDistribution(0, 0.5, 1.0);
Assert.assertEquals(dist.getNumericalMean(), 0.5, 0);
Assert.assertEquals(dist.getNumericalVariance(), 1 / 24.0, 0);
dist = new TriangularDistribution(0, 1, 1);
Assert.assertEquals(dist.getNumericalMean(), 2 / 3.0, 0);
Assert.assertEquals(dist.getNumericalVariance(), 1 / 18.0, 0);
dist = new TriangularDistribution(-3, 2, 12);
Assert.assertEquals(dist.getNumericalMean(), 3 + (2 / 3.0), 0);
Assert.assertEquals(dist.getNumericalVariance(), 175 / 18.0, 0);
}
}

View File

@ -1,142 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.junit.Assert;
import org.junit.Test;
import org.apache.commons.math4.distribution.IntegerDistribution;
import org.apache.commons.math4.distribution.UniformIntegerDistribution;
import org.apache.commons.math4.exception.NumberIsTooLargeException;
import org.apache.commons.numbers.core.Precision;
/**
* Test cases for UniformIntegerDistribution. See class javadoc for
* {@link IntegerDistributionAbstractTest} for further details.
*/
public class UniformIntegerDistributionTest extends IntegerDistributionAbstractTest {
// --- Override tolerance -------------------------------------------------
@Override
public void setUp() {
super.setUp();
setTolerance(1e-9);
}
//--- Implementations for abstract methods --------------------------------
/** Creates the default discrete distribution instance to use in tests. */
@Override
public IntegerDistribution makeDistribution() {
return new UniformIntegerDistribution(-3, 5);
}
/** Creates the default probability density test input values. */
@Override
public int[] makeDensityTestPoints() {
return new int[] {-4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6};
}
/** Creates the default probability density test expected values. */
@Override
public double[] makeDensityTestValues() {
double d = 1.0 / (5 - -3 + 1);
return new double[] {0, d, d, d, d, d, d, d, d, d, 0};
}
/** Creates the default cumulative probability density test input values. */
@Override
public int[] makeCumulativeTestPoints() {
return makeDensityTestPoints();
}
/** Creates the default cumulative probability density test expected values. */
@Override
public double[] makeCumulativeTestValues() {
return new double[] {0, 1 / 9.0, 2 / 9.0, 3 / 9.0, 4 / 9.0, 5 / 9.0,
6 / 9.0, 7 / 9.0, 8 / 9.0, 1, 1};
}
/** Creates the default inverse cumulative probability test input values */
@Override
public double[] makeInverseCumulativeTestPoints() {
return new double[] {0, 0.001, 0.010, 0.025, 0.050, 0.100, 0.200,
0.5, 0.999, 0.990, 0.975, 0.950, 0.900, 1};
}
/** Creates the default inverse cumulative probability density test expected values */
@Override
public int[] makeInverseCumulativeTestValues() {
return new int[] {-3, -3, -3, -3, -3, -3, -2, 1, 5, 5, 5, 5, 5, 5};
}
//--- Additional test cases -----------------------------------------------
/** Test mean/variance. */
@Test
public void testMoments() {
UniformIntegerDistribution dist;
dist = new UniformIntegerDistribution(0, 5);
Assert.assertEquals(dist.getNumericalMean(), 2.5, 0);
Assert.assertEquals(dist.getNumericalVariance(), 35 / 12.0, 0);
dist = new UniformIntegerDistribution(0, 1);
Assert.assertEquals(dist.getNumericalMean(), 0.5, 0);
Assert.assertEquals(dist.getNumericalVariance(), 3 / 12.0, 0);
}
// MATH-1141
@Test
public void testPreconditionUpperBoundInclusive() {
try {
new UniformIntegerDistribution(1, 0);
} catch (NumberIsTooLargeException e) {
// Expected.
}
// Degenerate case is allowed.
new UniformIntegerDistribution(0, 0);
}
// MATH-1396
@Test
public void testLargeRangeSubtractionOverflow() {
final int hi = Integer.MAX_VALUE / 2 + 10;
UniformIntegerDistribution dist = new UniformIntegerDistribution(-hi, hi - 1);
final double tol = Math.ulp(1d);
Assert.assertEquals(0.5 / hi, dist.probability(123456), tol);
Assert.assertEquals(0.5, dist.cumulativeProbability(-1), tol);
Assert.assertTrue(Precision.equals((Math.pow(2d * hi, 2) - 1) / 12, dist.getNumericalVariance(), 1));
}
// MATH-1396
@Test
public void testLargeRangeAdditionOverflow() {
final int hi = Integer.MAX_VALUE / 2 + 10;
UniformIntegerDistribution dist = new UniformIntegerDistribution(hi - 1, hi + 1);
final double tol = Math.ulp(1d);
Assert.assertEquals(1d / 3d, dist.probability(hi), tol);
Assert.assertEquals(2d / 3d, dist.cumulativeProbability(hi), tol);
Assert.assertTrue(Precision.equals(hi, dist.getNumericalMean(), 1));
}
}

View File

@ -1,125 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.distribution.UniformRealDistribution;
import org.apache.commons.math4.exception.NumberIsTooLargeException;
import org.junit.Assert;
import org.junit.Test;
/**
* Test cases for UniformRealDistribution. See class javadoc for
* {@link RealDistributionAbstractTest} for further details.
*/
public class UniformRealDistributionTest extends RealDistributionAbstractTest {
// --- Override tolerance -------------------------------------------------
@Override
public void setUp() {
super.setUp();
setTolerance(1e-4);
}
//--- Implementations for abstract methods --------------------------------
/** Creates the default uniform real distribution instance to use in tests. */
@Override
public UniformRealDistribution makeDistribution() {
return new UniformRealDistribution(-0.5, 1.25);
}
/** Creates the default cumulative probability distribution test input values */
@Override
public double[] makeCumulativeTestPoints() {
return new double[] {-0.5001, -0.5, -0.4999, -0.25, -0.0001, 0.0,
0.0001, 0.25, 1.0, 1.2499, 1.25, 1.2501};
}
/** Creates the default cumulative probability density test expected values */
@Override
public double[] makeCumulativeTestValues() {
return new double[] {0.0, 0.0, 0.0001, 0.25/1.75, 0.4999/1.75,
0.5/1.75, 0.5001/1.75, 0.75/1.75, 1.5/1.75,
1.7499/1.75, 1.0, 1.0};
}
/** Creates the default probability density test expected values */
@Override
public double[] makeDensityTestValues() {
double d = 1 / 1.75;
return new double[] {0, d, d, d, d, d, d, d, d, d, d, 0};
}
//--- Additional test cases -----------------------------------------------
/** Test lower bound getter. */
@Test
public void testGetLowerBound() {
UniformRealDistribution distribution = makeDistribution();
Assert.assertEquals(-0.5, distribution.getSupportLowerBound(), 0);
}
/** Test upper bound getter. */
@Test
public void testGetUpperBound() {
UniformRealDistribution distribution = makeDistribution();
Assert.assertEquals(1.25, distribution.getSupportUpperBound(), 0);
}
/** Test pre-condition for equal lower/upper bound. */
@Test(expected=NumberIsTooLargeException.class)
public void testPreconditions1() {
new UniformRealDistribution(0, 0);
}
/** Test pre-condition for lower bound larger than upper bound. */
@Test(expected=NumberIsTooLargeException.class)
public void testPreconditions2() {
new UniformRealDistribution(1, 0);
}
/** Test mean/variance. */
@Test
public void testMeanVariance() {
UniformRealDistribution dist;
dist = new UniformRealDistribution(0, 1);
Assert.assertEquals(dist.getNumericalMean(), 0.5, 0);
Assert.assertEquals(dist.getNumericalVariance(), 1/12.0, 0);
dist = new UniformRealDistribution(-1.5, 0.6);
Assert.assertEquals(dist.getNumericalMean(), -0.45, 0);
Assert.assertEquals(dist.getNumericalVariance(), 0.3675, 0);
dist = new UniformRealDistribution(-0.5, 1.25);
Assert.assertEquals(dist.getNumericalMean(), 0.375, 0);
Assert.assertEquals(dist.getNumericalVariance(), 0.2552083333333333, 0);
}
/**
* Check accuracy of analytical inverse CDF. Fails if a solver is used
* with the default accuracy.
*/
@Test
public void testInverseCumulativeDistribution() {
UniformRealDistribution dist = new UniformRealDistribution(0, 1e-9);
Assert.assertEquals(2.5e-10, dist.inverseCumulativeProbability(0.25), 0);
}
}

View File

@ -1,126 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.distribution.WeibullDistribution;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.numbers.gamma.LogGamma;
import org.apache.commons.math4.util.FastMath;
import org.junit.Assert;
import org.junit.Test;
/**
* Test cases for WeibullDistribution.
* Extends ContinuousDistributionAbstractTest. See class javadoc for
* ContinuousDistributionAbstractTest for details.
*
*/
public class WeibullDistributionTest extends RealDistributionAbstractTest {
//-------------- Implementations for abstract methods -----------------------
/** Creates the default continuous distribution instance to use in tests. */
@Override
public WeibullDistribution makeDistribution() {
return new WeibullDistribution(1.2, 2.1);
}
/** Creates the default cumulative probability distribution test input values */
@Override
public double[] makeCumulativeTestPoints() {
// quantiles computed using R version 2.9.2
return new double[] {0.00664355180993, 0.0454328283309, 0.0981162737374, 0.176713524579, 0.321946865392,
10.5115496887, 7.4976304671, 6.23205600701, 5.23968436955, 4.2079028257};
}
/** Creates the default cumulative probability density test expected values */
@Override
public double[] makeCumulativeTestValues() {
return new double[] {0.001, 0.01, 0.025, 0.05, 0.1, 0.999, 0.990, 0.975, 0.950, 0.900};
}
/** Creates the default probability density test expected values */
@Override
public double[] makeDensityTestValues() {
return new double[] {0.180535929306, 0.262801138133, 0.301905425199, 0.330899152971,
0.353441418887, 0.000788590320203, 0.00737060094841, 0.0177576041516, 0.0343043442574, 0.065664589369};
}
//---------------------------- Additional test cases -------------------------
@Test
public void testInverseCumulativeProbabilitySmallPAccuracy() {
WeibullDistribution dist = new WeibullDistribution(2, 3);
double t = dist.inverseCumulativeProbability(1e-17);
// Analytically, answer is solution to 1e-17 = 1-exp(-(x/3)^2)
// x = sqrt(-9*log(1-1e-17))
// If we're not careful, answer will be 0. Answer below is computed with care in Octave:
Assert.assertEquals(9.48683298050514e-9, t, 1e-17);
}
@Test
public void testInverseCumulativeProbabilityExtremes() {
setInverseCumulativeTestPoints(new double[] {0.0, 1.0});
setInverseCumulativeTestValues(
new double[] {0.0, Double.POSITIVE_INFINITY});
verifyInverseCumulativeProbabilities();
}
@Test
public void testAlpha() {
WeibullDistribution dist = new WeibullDistribution(1, 2);
Assert.assertEquals(1, dist.getShape(), 0);
try {
new WeibullDistribution(0, 2);
Assert.fail("NotStrictlyPositiveException expected");
} catch (NotStrictlyPositiveException e) {
// Expected.
}
}
@Test
public void testBeta() {
WeibullDistribution dist = new WeibullDistribution(1, 2);
Assert.assertEquals(2, dist.getScale(), 0);
try {
new WeibullDistribution(1, 0);
Assert.fail("NotStrictlyPositiveException expected");
} catch (NotStrictlyPositiveException e) {
// Expected.
}
}
@Test
public void testMoments() {
final double tol = 1e-9;
WeibullDistribution dist;
dist = new WeibullDistribution(2.5, 3.5);
// In R: 3.5*gamma(1+(1/2.5)) (or emperically: mean(rweibull(10000, 2.5, 3.5)))
Assert.assertEquals(dist.getNumericalMean(), 3.5 * FastMath.exp(LogGamma.value(1 + (1 / 2.5))), tol);
Assert.assertEquals(dist.getNumericalVariance(), (3.5 * 3.5) *
FastMath.exp(LogGamma.value(1 + (2 / 2.5))) -
(dist.getNumericalMean() * dist.getNumericalMean()), tol);
dist = new WeibullDistribution(10.4, 2.222);
Assert.assertEquals(dist.getNumericalMean(), 2.222 * FastMath.exp(LogGamma.value(1 + (1 / 10.4))), tol);
Assert.assertEquals(dist.getNumericalVariance(), (2.222 * 2.222) *
FastMath.exp(LogGamma.value(1 + (2 / 10.4))) -
(dist.getNumericalMean() * dist.getNumericalMean()), tol);
}
}

View File

@ -1,197 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.distribution;
import org.apache.commons.math4.TestUtils;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.rng.simple.RandomSource;
import org.apache.commons.math4.util.FastMath;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
/**
* Test cases for {@link ZipfDistribution}.
* Extends IntegerDistributionAbstractTest.
* See class javadoc for IntegerDistributionAbstractTest for details.
*/
public class ZipfDistributionTest extends IntegerDistributionAbstractTest {
/**
* Constructor to override default tolerance.
*/
public ZipfDistributionTest() {
setTolerance(1e-12);
}
@Test(expected=NotStrictlyPositiveException.class)
public void testPreconditions1() {
new ZipfDistribution(0, 1);
}
@Test(expected=NotStrictlyPositiveException.class)
public void testPreconditions2() {
new ZipfDistribution(1, 0);
}
//-------------- Implementations for abstract methods -----------------------
/** Creates the default discrete distribution instance to use in tests. */
@Override
public IntegerDistribution makeDistribution() {
return new ZipfDistribution(10, 1);
}
/** Creates the default probability density test input values */
@Override
public int[] makeDensityTestPoints() {
return new int[] {-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
}
/**
* Creates the default probability density test expected values.
* Reference values are from R, version 2.15.3 (VGAM package 0.9-0).
*/
@Override
public double[] makeDensityTestValues() {
return new double[] {0d, 0d, 0.341417152147, 0.170708576074, 0.113805717382, 0.0853542880369, 0.0682834304295,
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.07465022926458, -1.76779740982453, -2.17326251793269, -2.46094459038447,
-2.68408814169868, -2.86640969849264, -3.0205603783199, -3.15409177094442,
-3.2718748066008, -3.37723532225863, Double.NEGATIVE_INFINITY};
}
/** Creates the default cumulative probability density test input values */
@Override
public int[] makeCumulativeTestPoints() {
return makeDensityTestPoints();
}
/** Creates the default cumulative probability density test expected values */
@Override
public double[] makeCumulativeTestValues() {
return new double[] {0, 0, 0.341417152147, 0.512125728221, 0.625931445604, 0.71128573364,
0.77956916407, 0.836472022761, 0.885245901639, 0.927923045658, 0.965858284785, 1d, 1d};
}
/** Creates the default inverse cumulative probability test input values */
@Override
public double[] makeInverseCumulativeTestPoints() {
return new double[] {0d, 0.001d, 0.010d, 0.025d, 0.050d, 0.3413d, 0.3415d, 0.999d,
0.990d, 0.975d, 0.950d, 0.900d, 1d};
}
/** Creates the default inverse cumulative probability density test expected values */
@Override
public int[] makeInverseCumulativeTestValues() {
return new int[] {1, 1, 1, 1, 1, 1, 2, 10, 10, 10, 9, 8, 10};
}
@Test
public void testMoments() {
final double tol = 1e-9;
ZipfDistribution dist;
dist = new ZipfDistribution(2, 0.5);
Assert.assertEquals(dist.getNumericalMean(), FastMath.sqrt(2), tol);
Assert.assertEquals(dist.getNumericalVariance(), 0.24264068711928521, tol);
}
/**
* Test sampling for various number of points and exponents.
*/
@Test
public void testSamplingExtended() {
int sampleSize = 1000;
int[] numPointsValues = {
2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30, 35, 40, 45, 50, 60, 70, 80, 90, 100
};
double[] exponentValues = {
1e-10, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 2e-1, 5e-1,
1. - 1e-9, 1.0, 1. + 1e-9, 1.1, 1.2, 1.3, 1.5, 1.6, 1.7, 1.8, 2.0,
2.5, 3.0, 4., 5., 6., 7., 8., 9., 10., 20., 30., 100., 150.
};
for (int numPoints : numPointsValues) {
for (double exponent : exponentValues) {
double weightSum = 0.;
double[] weights = new double[numPoints];
for (int i = numPoints; i>=1; i-=1) {
weights[i-1] = Math.pow(i, -exponent);
weightSum += weights[i-1];
}
// Use fixed seed, the test is expected to fail for more than 50% of all
// seeds because each test case can fail with probability 0.001, the chance
// that all test cases do not fail is 0.999^(32*22) = 0.49442874426
IntegerDistribution.Sampler distribution =
new ZipfDistribution(numPoints, exponent).createSampler(RandomSource.create(RandomSource.WELL_19937_C, 6));
double[] expectedCounts = new double[numPoints];
long[] observedCounts = new long[numPoints];
for (int i = 0; i < numPoints; i++) {
expectedCounts[i] = sampleSize * (weights[i]/weightSum);
}
int[] sample = AbstractIntegerDistribution.sample(sampleSize, distribution);
for (int s : sample) {
observedCounts[s-1]++;
}
TestUtils.assertChiSquareAccept(expectedCounts, observedCounts, 0.001);
}
}
}
@Ignore
@Test
public void testSamplerPerformance() {
int[] numPointsValues = {1, 2, 5, 10, 100, 1000, 10000};
double[] exponentValues = {1e-3, 1e-2, 1e-1, 1., 2., 5., 10.};
int numGeneratedSamples = 1000000;
long sum = 0;
for (int numPoints : numPointsValues) {
for (double exponent : exponentValues) {
long start = System.currentTimeMillis();
final int[] randomNumberCounter = new int[1];
final IntegerDistribution.Sampler distribution =
new ZipfDistribution(numPoints, exponent).createSampler(RandomSource.create(RandomSource.WELL_1024_A));
for (int i = 0; i < numGeneratedSamples; ++i) {
sum += distribution.sample();
}
long end = System.currentTimeMillis();
System.out.println("n = " + numPoints + ", exponent = " + exponent + ", avg number consumed random values = " + (double)(randomNumberCounter[0])/numGeneratedSamples + ", measured time = " + (end-start)/1000. + "s");
}
}
System.out.println(sum);
}
}