MATH-1443: Depend on "Commons Statistics".
Deleted all classes that have a counterpart in "Commons Statistics".
This commit is contained in:
parent
3e24c28e68
commit
ef84681392
|
@ -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();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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., & 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();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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é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évy distribution
|
||||
* over the domain is
|
||||
* </p>
|
||||
* <div style="white-space: pre"><code>
|
||||
* f(x; μ, c) = √(c / 2π) * e<sup>-c / 2 (x - μ)</sup> / (x - μ)<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 μ, {@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 (√ (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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
/** √(2 π) */
|
||||
private static final double SQRT2PI = FastMath.sqrt(2 * FastMath.PI);
|
||||
|
||||
/** √(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();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
/** √(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();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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'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;
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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()));
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
};
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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};
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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 ≤ X ≤ 110) for X = Po(100) and
|
||||
* P(9900 ≤ X ≤ 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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue