All Downloads are FREE. Search and download functionalities are using the official Maven repository.

breeze.stats.distributions.LogNormal.scala Maven / Gradle / Ivy

There is a newer version: 1.0
Show newest version
package breeze.stats.distributions

import scala.runtime.ScalaRunTime
import breeze.optimize.DiffFunction
import breeze.numerics._
import scala.math.exp
import scala.math.log
import scala.math.sqrt

/**
 * A log normal distribution is distributed such that log X ~ Normal(\mu, \sigma)
 *
 * TODO: it should be possible to specify distributions like this by using an [[breeze.util.Isomorphism]]
 * instances.
 *
 * @author dlwh
 **/
case class LogNormal(mu: Double, sigma: Double)
                    (implicit rand: RandBasis = Rand)
  extends ContinuousDistr[Double] with Moments[Double, Double] with HasCdf with HasInverseCdf {
  private val myGaussian = Gaussian(mu, sigma)
  require(sigma > 0, "Sigma must be positive, but got " + sigma)
  /**
   * Gets one sample from the distribution. Equivalent to sample()
   */
  def draw(): Double = {
    exp(myGaussian.draw())
  }


  def unnormalizedLogPdf(x: Double): Double = {
    if (x <= 0.0) return Double.NegativeInfinity
    val logx = log(x)
    val rad = (logx - mu)/sigma
    -(rad * rad / 2) - logx
  }

  lazy val logNormalizer: Double = log(sqrt(2 * Math.PI)) + log(sigma)

  /**
   * Computes the inverse cdf of the p-value for this gaussian.
   *
   * @param p: a probability in [0,1]
   * @return x s.t. cdf(x) = numYes
   */
  def inverseCdf(p: Double) = exp(myGaussian.inverseCdf(p))

  /**
   * Computes the cumulative density function of the value x.
   */
  def cdf(x: Double) = myGaussian.cdf(log(x))


  override def probability(x: Double, y: Double): Double = {
    myGaussian.probability(log(x), log(y))
  }

  override def toString: String = ScalaRunTime._toString(this)

  def mean: Double = exp(mu + sigma * sigma / 2)

  def variance: Double = expm1(sigma * sigma) * exp(2 * mu + sigma * sigma)

  def entropy: Double = 0.5 + 0.5 * math.log(2 * math.Pi * sigma * sigma) + mu

  def mode: Double = exp(mu - sigma * sigma)


}


object LogNormal extends ExponentialFamily[LogNormal,Double] with ContinuousDistributionUFuncProvider[Double,LogNormal] {
  type Parameter = (Double,Double)

  import Gaussian.SufficientStatistic
  type SufficientStatistic = Gaussian.SufficientStatistic

  def emptySufficientStatistic = Gaussian.emptySufficientStatistic

  def sufficientStatisticFor(t: Double) = {
    SufficientStatistic(1,math.log(t),0)
  }

  def mle(stats: SufficientStatistic): (Double, Double) =  Gaussian.mle(stats)

  def distribution(p: (Double, Double)) = new LogNormal(p._1,math.sqrt(p._2))

  def likelihoodFunction(stats: SufficientStatistic):DiffFunction[(Double,Double)] = Gaussian.likelihoodFunction(stats)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy