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 */ 017 018package org.apache.commons.math3.distribution; 019 020import org.apache.commons.math3.exception.NotStrictlyPositiveException; 021import org.apache.commons.math3.exception.NumberIsTooLargeException; 022import org.apache.commons.math3.exception.util.LocalizedFormats; 023import org.apache.commons.math3.random.RandomGenerator; 024import org.apache.commons.math3.random.Well19937c; 025import org.apache.commons.math3.util.FastMath; 026 027/** 028 * Implementation of the Pareto distribution. 029 * 030 * <p> 031 * <strong>Parameters:</strong> 032 * The probability distribution function of {@code X} is given by (for {@code x >= k}): 033 * <pre> 034 * α * k^α / x^(α + 1) 035 * </pre> 036 * <p> 037 * <ul> 038 * <li>{@code k} is the <em>scale</em> parameter: this is the minimum possible value of {@code X},</li> 039 * <li>{@code α} is the <em>shape</em> parameter: this is the Pareto index</li> 040 * </ul> 041 * 042 * @see <a href="http://en.wikipedia.org/wiki/Pareto_distribution"> 043 * Pareto distribution (Wikipedia)</a> 044 * @see <a href="http://mathworld.wolfram.com/ParetoDistribution.html"> 045 * Pareto distribution (MathWorld)</a> 046 * 047 * @since 3.3 048 */ 049public class ParetoDistribution extends AbstractRealDistribution { 050 051 /** Default inverse cumulative probability accuracy. */ 052 public static final double DEFAULT_INVERSE_ABSOLUTE_ACCURACY = 1e-9; 053 054 /** Serializable version identifier. */ 055 private static final long serialVersionUID = 20130424; 056 057 /** The scale parameter of this distribution. */ 058 private final double scale; 059 060 /** The shape parameter of this distribution. */ 061 private final double shape; 062 063 /** Inverse cumulative probability accuracy. */ 064 private final double solverAbsoluteAccuracy; 065 066 /** 067 * Create a Pareto distribution with a scale of {@code 1} and a shape of {@code 1}. 068 */ 069 public ParetoDistribution() { 070 this(1, 1); 071 } 072 073 /** 074 * Create a Pareto distribution using the specified scale and shape. 075 * <p> 076 * <b>Note:</b> this constructor will implicitly create an instance of 077 * {@link Well19937c} as random generator to be used for sampling only (see 078 * {@link #sample()} and {@link #sample(int)}). In case no sampling is 079 * needed for the created distribution, it is advised to pass {@code null} 080 * as random generator via the appropriate constructors to avoid the 081 * additional initialisation overhead. 082 * 083 * @param scale the scale parameter of this distribution 084 * @param shape the shape parameter of this distribution 085 * @throws NotStrictlyPositiveException if {@code scale <= 0} or {@code shape <= 0}. 086 */ 087 public ParetoDistribution(double scale, double shape) 088 throws NotStrictlyPositiveException { 089 this(scale, shape, DEFAULT_INVERSE_ABSOLUTE_ACCURACY); 090 } 091 092 /** 093 * Create a Pareto distribution using the specified scale, shape and 094 * inverse cumulative distribution accuracy. 095 * <p> 096 * <b>Note:</b> this constructor will implicitly create an instance of 097 * {@link Well19937c} as random generator to be used for sampling only (see 098 * {@link #sample()} and {@link #sample(int)}). In case no sampling is 099 * needed for the created distribution, it is advised to pass {@code null} 100 * as random generator via the appropriate constructors to avoid the 101 * additional initialisation overhead. 102 * 103 * @param scale the scale parameter of this distribution 104 * @param shape the shape parameter of this distribution 105 * @param inverseCumAccuracy Inverse cumulative probability accuracy. 106 * @throws NotStrictlyPositiveException if {@code scale <= 0} or {@code shape <= 0}. 107 */ 108 public ParetoDistribution(double scale, double shape, double inverseCumAccuracy) 109 throws NotStrictlyPositiveException { 110 this(new Well19937c(), scale, shape, inverseCumAccuracy); 111 } 112 113 /** 114 * Creates a Pareto distribution. 115 * 116 * @param rng Random number generator. 117 * @param scale Scale parameter of this distribution. 118 * @param shape Shape parameter of this distribution. 119 * @throws NotStrictlyPositiveException if {@code scale <= 0} or {@code shape <= 0}. 120 */ 121 public ParetoDistribution(RandomGenerator rng, double scale, double shape) 122 throws NotStrictlyPositiveException { 123 this(rng, scale, shape, DEFAULT_INVERSE_ABSOLUTE_ACCURACY); 124 } 125 126 /** 127 * Creates a Pareto distribution. 128 * 129 * @param rng Random number generator. 130 * @param scale Scale parameter of this distribution. 131 * @param shape Shape parameter of this distribution. 132 * @param inverseCumAccuracy Inverse cumulative probability accuracy. 133 * @throws NotStrictlyPositiveException if {@code scale <= 0} or {@code shape <= 0}. 134 */ 135 public ParetoDistribution(RandomGenerator rng, 136 double scale, 137 double shape, 138 double inverseCumAccuracy) 139 throws NotStrictlyPositiveException { 140 super(rng); 141 142 if (scale <= 0) { 143 throw new NotStrictlyPositiveException(LocalizedFormats.SCALE, scale); 144 } 145 146 if (shape <= 0) { 147 throw new NotStrictlyPositiveException(LocalizedFormats.SHAPE, shape); 148 } 149 150 this.scale = scale; 151 this.shape = shape; 152 this.solverAbsoluteAccuracy = inverseCumAccuracy; 153 } 154 155 /** 156 * Returns the scale parameter of this distribution. 157 * 158 * @return the scale parameter 159 */ 160 public double getScale() { 161 return scale; 162 } 163 164 /** 165 * Returns the shape parameter of this distribution. 166 * 167 * @return the shape parameter 168 */ 169 public double getShape() { 170 return shape; 171 } 172 173 /** 174 * {@inheritDoc} 175 * <p> 176 * For scale {@code k}, and shape {@code α} of this distribution, the PDF 177 * is given by 178 * <ul> 179 * <li>{@code 0} if {@code x < k},</li> 180 * <li>{@code α * k^α / x^(α + 1)} otherwise.</li> 181 * </ul> 182 */ 183 public double density(double x) { 184 if (x < scale) { 185 return 0; 186 } 187 return FastMath.pow(scale, shape) / FastMath.pow(x, shape + 1) * shape; 188 } 189 190 /** {@inheritDoc} 191 * 192 * See documentation of {@link #density(double)} for computation details. 193 */ 194 @Override 195 public double logDensity(double x) { 196 if (x < scale) { 197 return Double.NEGATIVE_INFINITY; 198 } 199 return FastMath.log(scale) * shape - FastMath.log(x) * (shape + 1) + FastMath.log(shape); 200 } 201 202 /** 203 * {@inheritDoc} 204 * <p> 205 * For scale {@code k}, and shape {@code α} of this distribution, the CDF is given by 206 * <ul> 207 * <li>{@code 0} if {@code x < k},</li> 208 * <li>{@code 1 - (k / x)^α} otherwise.</li> 209 * </ul> 210 */ 211 public double cumulativeProbability(double x) { 212 if (x <= scale) { 213 return 0; 214 } 215 return 1 - FastMath.pow(scale / x, shape); 216 } 217 218 /** 219 * {@inheritDoc} 220 * 221 * @deprecated See {@link RealDistribution#cumulativeProbability(double,double)} 222 */ 223 @Override 224 @Deprecated 225 public double cumulativeProbability(double x0, double x1) 226 throws NumberIsTooLargeException { 227 return probability(x0, x1); 228 } 229 230 /** {@inheritDoc} */ 231 @Override 232 protected double getSolverAbsoluteAccuracy() { 233 return solverAbsoluteAccuracy; 234 } 235 236 /** 237 * {@inheritDoc} 238 * <p> 239 * For scale {@code k} and shape {@code α}, the mean is given by 240 * <ul> 241 * <li>{@code ∞} if {@code α <= 1},</li> 242 * <li>{@code α * k / (α - 1)} otherwise.</li> 243 * </ul> 244 */ 245 public double getNumericalMean() { 246 if (shape <= 1) { 247 return Double.POSITIVE_INFINITY; 248 } 249 return shape * scale / (shape - 1); 250 } 251 252 /** 253 * {@inheritDoc} 254 * <p> 255 * For scale {@code k} and shape {@code α}, the variance is given by 256 * <ul> 257 * <li>{@code ∞} if {@code 1 < α <= 2},</li> 258 * <li>{@code k^2 * α / ((α - 1)^2 * (α - 2))} otherwise.</li> 259 * </ul> 260 */ 261 public double getNumericalVariance() { 262 if (shape <= 2) { 263 return Double.POSITIVE_INFINITY; 264 } 265 double s = shape - 1; 266 return scale * scale * shape / (s * s) / (shape - 2); 267 } 268 269 /** 270 * {@inheritDoc} 271 * <p> 272 * The lower bound of the support is equal to the scale parameter {@code k}. 273 * 274 * @return lower bound of the support 275 */ 276 public double getSupportLowerBound() { 277 return scale; 278 } 279 280 /** 281 * {@inheritDoc} 282 * <p> 283 * The upper bound of the support is always positive infinity no matter the parameters. 284 * 285 * @return upper bound of the support (always {@code Double.POSITIVE_INFINITY}) 286 */ 287 public double getSupportUpperBound() { 288 return Double.POSITIVE_INFINITY; 289 } 290 291 /** {@inheritDoc} */ 292 public boolean isSupportLowerBoundInclusive() { 293 return true; 294 } 295 296 /** {@inheritDoc} */ 297 public boolean isSupportUpperBoundInclusive() { 298 return false; 299 } 300 301 /** 302 * {@inheritDoc} 303 * <p> 304 * The support of this distribution is connected. 305 * 306 * @return {@code true} 307 */ 308 public boolean isSupportConnected() { 309 return true; 310 } 311 312 /** {@inheritDoc} */ 313 @Override 314 public double sample() { 315 final double n = random.nextDouble(); 316 return scale / FastMath.pow(n, 1 / shape); 317 } 318}