001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.math3.distribution; 018 019import org.apache.commons.math3.exception.NotStrictlyPositiveException; 020import org.apache.commons.math3.exception.OutOfRangeException; 021import org.apache.commons.math3.exception.util.LocalizedFormats; 022import org.apache.commons.math3.random.RandomGenerator; 023import org.apache.commons.math3.random.Well19937c; 024import org.apache.commons.math3.util.FastMath; 025import org.apache.commons.math3.util.MathUtils; 026 027/** 028 * This class implements the Gumbel distribution. 029 * 030 * @see <a href="http://en.wikipedia.org/wiki/Gumbel_distribution">Gumbel Distribution (Wikipedia)</a> 031 * @see <a href="http://mathworld.wolfram.com/GumbelDistribution.html">Gumbel Distribution (Mathworld)</a> 032 * 033 * @since 3.4 034 */ 035public class GumbelDistribution extends AbstractRealDistribution { 036 037 /** Serializable version identifier. */ 038 private static final long serialVersionUID = 20141003; 039 040 /** 041 * Approximation of Euler's constant 042 * see http://mathworld.wolfram.com/Euler-MascheroniConstantApproximations.html 043 */ 044 private static final double EULER = FastMath.PI / (2 * FastMath.E); 045 046 /** The location parameter. */ 047 private final double mu; 048 /** The scale parameter. */ 049 private final double beta; 050 051 /** 052 * Build a new instance. 053 * <p> 054 * <b>Note:</b> this constructor will implicitly create an instance of 055 * {@link Well19937c} as random generator to be used for sampling only (see 056 * {@link #sample()} and {@link #sample(int)}). In case no sampling is 057 * needed for the created distribution, it is advised to pass {@code null} 058 * as random generator via the appropriate constructors to avoid the 059 * additional initialisation overhead. 060 * 061 * @param mu location parameter 062 * @param beta scale parameter (must be positive) 063 * @throws NotStrictlyPositiveException if {@code beta <= 0} 064 */ 065 public GumbelDistribution(double mu, double beta) { 066 this(new Well19937c(), mu, beta); 067 } 068 069 /** 070 * Build a new instance. 071 * 072 * @param rng Random number generator 073 * @param mu location parameter 074 * @param beta scale parameter (must be positive) 075 * @throws NotStrictlyPositiveException if {@code beta <= 0} 076 */ 077 public GumbelDistribution(RandomGenerator rng, double mu, double beta) { 078 super(rng); 079 080 if (beta <= 0) { 081 throw new NotStrictlyPositiveException(LocalizedFormats.SCALE, beta); 082 } 083 084 this.beta = beta; 085 this.mu = mu; 086 } 087 088 /** 089 * Access the location parameter, {@code mu}. 090 * 091 * @return the location parameter. 092 */ 093 public double getLocation() { 094 return mu; 095 } 096 097 /** 098 * Access the scale parameter, {@code beta}. 099 * 100 * @return the scale parameter. 101 */ 102 public double getScale() { 103 return beta; 104 } 105 106 /** {@inheritDoc} */ 107 public double density(double x) { 108 final double z = (x - mu) / beta; 109 final double t = FastMath.exp(-z); 110 return FastMath.exp(-z - t) / beta; 111 } 112 113 /** {@inheritDoc} */ 114 public double cumulativeProbability(double x) { 115 final double z = (x - mu) / beta; 116 return FastMath.exp(-FastMath.exp(-z)); 117 } 118 119 /** {@inheritDoc} */ 120 @Override 121 public double inverseCumulativeProbability(double p) throws OutOfRangeException { 122 if (p < 0.0 || p > 1.0) { 123 throw new OutOfRangeException(p, 0.0, 1.0); 124 } else if (p == 0) { 125 return Double.NEGATIVE_INFINITY; 126 } else if (p == 1) { 127 return Double.POSITIVE_INFINITY; 128 } 129 return mu - FastMath.log(-FastMath.log(p)) * beta; 130 } 131 132 /** {@inheritDoc} */ 133 public double getNumericalMean() { 134 return mu + EULER * beta; 135 } 136 137 /** {@inheritDoc} */ 138 public double getNumericalVariance() { 139 return (MathUtils.PI_SQUARED) / 6.0 * (beta * beta); 140 } 141 142 /** {@inheritDoc} */ 143 public double getSupportLowerBound() { 144 return Double.NEGATIVE_INFINITY; 145 } 146 147 /** {@inheritDoc} */ 148 public double getSupportUpperBound() { 149 return Double.POSITIVE_INFINITY; 150 } 151 152 /** {@inheritDoc} */ 153 public boolean isSupportLowerBoundInclusive() { 154 return false; 155 } 156 157 /** {@inheritDoc} */ 158 public boolean isSupportUpperBoundInclusive() { 159 return false; 160 } 161 162 /** {@inheritDoc} */ 163 public boolean isSupportConnected() { 164 return true; 165 } 166 167}