package de.lmu.ifi.dbs.elki.math.statistics.distribution; /* This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ import java.util.Random; import de.lmu.ifi.dbs.elki.math.MathUtil; import de.lmu.ifi.dbs.elki.utilities.Alias; /** * Log-Normal distribution. * * The parameterization of this class is somewhere inbetween of GNU R and SciPy. * Similar to GNU R we use the logmean and logstddev. Similar to Scipy, we also * have a location parameter that shifts the distribution. * * Our implementation maps to SciPy's as follows: * scipy.stats.lognorm(logstddev, shift, math.exp(logmean)) * * @author Erich Schubert */ @Alias({ "lognormal" }) public class LogNormalDistribution implements Distribution { /** * Mean value for the generator */ private double logmean; /** * Standard deviation */ private double logstddev; /** * Additional shift factor */ private double shift = 0.; /** * The random generator. */ private Random random; /** * Constructor for Log-Normal distribution * * @param logmean Mean * @param logstddev Standard Deviation * @param shift Shifting offset * @param random Random generator */ public LogNormalDistribution(double logmean, double logstddev, double shift, Random random) { super(); this.logmean = logmean; this.logstddev = logstddev; this.shift = shift; this.random = random; } /** * Constructor. * * @param logmean Mean * @param logstddev Standard deviation * @param shift Shifting offset */ public LogNormalDistribution(double logmean, double logstddev, double shift) { this(logmean, logstddev, shift, null); } @Override public double pdf(double val) { return pdf(val - shift, logmean, logstddev); } @Override public double cdf(double val) { return cdf(val - shift, logmean, logstddev); } @Override public double quantile(double val) { return quantile(val, logmean, logstddev) + shift; } /** * Probability density function of the normal distribution. * *
   * 1/(SQRT(2*pi)*sigma*x) * e^(-log(x-mu)^2/2sigma^2)
   * 
* * * @param x The value. * @param mu The mean. * @param sigma The standard deviation. * @return PDF of the given normal distribution at x. */ public static double pdf(double x, double mu, double sigma) { if (x <= 0.) { return 0.; } final double x_mu = Math.log(x) - mu; final double sigmasq = sigma * sigma; return 1 / (MathUtil.SQRTTWOPI * sigma * x) * Math.exp(-.5 * x_mu * x_mu / sigmasq); } /** * Cumulative probability density function (CDF) of a normal distribution. * * @param x value to evaluate CDF at * @param mu Mean value * @param sigma Standard deviation. * @return The CDF of the given normal distribution at x. */ public static double cdf(double x, double mu, double sigma) { if (x <= 0.) { return 0.; } return .5 * (1 + NormalDistribution.erf((Math.log(x) - mu) / (MathUtil.SQRT2 * sigma))); } /** * Inverse cumulative probability density function (probit) of a normal * distribution. * * @param x value to evaluate probit function at * @param mu Mean value * @param sigma Standard deviation. * @return The probit of the given normal distribution at x. */ public static double quantile(double x, double mu, double sigma) { return Math.exp(mu + sigma * NormalDistribution.standardNormalQuantile(x)); } @Override public double nextRandom() { return Math.exp(logmean + random.nextGaussian() * logstddev) + shift; } @Override public String toString() { return "LogNormalDistribution(logmean=" + logmean + ", logstddev=" + logstddev + ", shift=" + shift + ")"; } }