Example #1
0
        /// <summary>
        /// Constructs a Gamma distribution with the given log mean and mean logarithm.
        /// </summary>
        /// <param name="logMean">Log of desired expected value.</param>
        /// <param name="meanLog">Desired expected logarithm.</param>
        /// <returns>A new Gamma distribution.</returns>
        /// <remarks>
        /// This function is significantly slower than the other constructors since it
        /// involves nonlinear optimization. The algorithm is a generalized Newton iteration,
        /// described in "Estimating a Gamma distribution" by T. Minka, 2002.
        /// </remarks>
        public static Gamma FromLogMeanAndMeanLog(double logMean, double meanLog)
        {
            // logMean = log(shape)-log(rate)
            // meanLog = Psi(shape)-log(rate)
            // delta = log(shape)-Psi(shape)
            double delta = logMean - meanLog;

            if (delta <= 2e-16)
            {
                return(Gamma.PointMass(Math.Exp(logMean)));
            }
            double shape = 0.5 / delta;

            for (int iter = 0; iter < 100; iter++)
            {
                double oldShape = shape;
                double g        = Math.Log(shape) - delta - MMath.Digamma(shape);
                shape /= 1 + g / (1 - shape * MMath.Trigamma(shape));
                if (Math.Abs(shape - oldShape) < 1e-8)
                {
                    break;
                }
            }
            if (Double.IsNaN(shape))
            {
                throw new Exception("shape is nan");
            }
            Gamma result = Gamma.FromShapeAndRate(shape, shape / Math.Exp(logMean));

            return(result);
        }
Example #2
0
        /// <summary>
        /// Constructs a Gamma distribution with the given mean and mean logarithm.
        /// </summary>
        /// <param name="mean">Desired expected value.</param>
        /// <param name="meanLog">Desired expected logarithm.</param>
        /// <returns>A new Gamma distribution.</returns>
        /// <remarks>This function is equivalent to maximum-likelihood estimation of a Gamma distribution
        /// from data given by sufficient statistics.
        /// This function is significantly slower than the other constructors since it
        /// involves nonlinear optimization. The algorithm is a generalized Newton iteration,
        /// described in "Estimating a Gamma distribution" by T. Minka, 2002.
        /// </remarks>
        public static Gamma FromMeanAndMeanLog(double mean, double meanLog)
        {
            double delta = Math.Log(mean) - meanLog;

            if (delta <= 2e-16)
            {
                return(Gamma.PointMass(mean));
            }
            double shape = 0.5 / delta;

            for (int iter = 0; iter < 100; iter++)
            {
                double oldShape = shape;
                double g        = Math.Log(shape) - delta - MMath.Digamma(shape);
                shape /= 1 + g / (1 - shape * MMath.Trigamma(shape));
                if (Math.Abs(shape - oldShape) < 1e-8)
                {
                    break;
                }
            }
            if (Double.IsNaN(shape))
            {
                throw new Exception("shape is nan");
            }
            return(Gamma.FromShapeAndRate(shape, shape / mean));
        }
Example #3
0
        /// <summary>
        /// Constructs a Gamma distribution with the given mean and mean logarithm.
        /// </summary>
        /// <param name="mean">Desired expected value.</param>
        /// <param name="logMeanMinusMeanLog">Logarithm of desired expected value minus desired expected logarithm.</param>
        /// <returns>A new Gamma distribution.</returns>
        /// <remarks>This function is equivalent to maximum-likelihood estimation of a Gamma distribution
        /// from data given by sufficient statistics.
        /// This function is significantly slower than the other constructors since it
        /// involves nonlinear optimization. The algorithm is a generalized Newton iteration,
        /// described in "Estimating a Gamma distribution" by T. Minka, 2002.
        /// </remarks>
        public static Gamma FromLogMeanMinusMeanLog(double mean, double logMeanMinusMeanLog)
        {
            if (logMeanMinusMeanLog <= 0)
            {
                return(Gamma.PointMass(mean));
            }
            double shape = 0.5 / logMeanMinusMeanLog;

            for (int iter = 0; iter < 100; iter++)
            {
                double g = LogMinusDigamma(shape) - logMeanMinusMeanLog;
                //Trace.WriteLine($"shape = {shape} g = {g}");
                if (MMath.AreEqual(g, 0))
                {
                    break;
                }
                shape /= 1 + g / (1 - shape * MMath.Trigamma(shape));
            }
            if (double.IsNaN(shape))
            {
                throw new InferRuntimeException("shape is nan");
            }
            if (shape > double.MaxValue)
            {
                return(Gamma.PointMass(mean));
            }
            return(Gamma.FromShapeAndRate(shape, shape / mean));
        }
Example #4
0
 public TruncatedGamma(Gamma Gamma, double lowerBound, double upperBound)
 {
     LowerBound = lowerBound;
     UpperBound = upperBound;
     if (lowerBound == upperBound)
     {
         this.Gamma = Gamma.PointMass(lowerBound);
     }
     else
     {
         this.Gamma = Gamma;
     }
 }
Example #5
0
 /// <summary>
 /// Create a truncated Gamma from untruncated (shape, scale) and bounds
 /// </summary>
 /// <param name="shape"></param>
 /// <param name="scale"></param>
 /// <param name="lowerBound"></param>
 /// <param name="upperBound"></param>
 public TruncatedGamma(double shape, double scale, double lowerBound, double upperBound)
 {
     LowerBound = lowerBound;
     UpperBound = upperBound;
     if (lowerBound == upperBound)
     {
         this.Gamma = Gamma.PointMass(lowerBound);
     }
     else
     {
         this.Gamma = Gamma.FromShapeAndScale(shape, scale);
     }
 }
Example #6
0
        /// <summary>
        /// Construct a Gamma distribution whose pdf has the given derivatives at a point.
        /// </summary>
        /// <param name="x">Cannot be negative</param>
        /// <param name="dLogP">Desired derivative of log-density at x</param>
        /// <param name="ddLogP">Desired second derivative of log-density at x</param>
        /// <param name="forceProper">If true and both derivatives cannot be matched by a proper distribution, match only the first.</param>
        /// <returns></returns>
        public static Gamma FromDerivatives(double x, double dLogP, double ddLogP, bool forceProper)
        {
            if (x < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(x), x, "x < 0");
            }
            double a;

            if (double.IsPositiveInfinity(x))
            {
                if (ddLogP < 0)
                {
                    return(Gamma.PointMass(x));
                }
                else if (ddLogP == 0)
                {
                    a = 0.0;
                }
                else if (forceProper)
                {
                    if (dLogP <= 0)
                    {
                        return(Gamma.FromShapeAndRate(1, -dLogP));
                    }
                    else
                    {
                        return(Gamma.PointMass(x));
                    }
                }
                else
                {
                    return(Gamma.FromShapeAndRate(-x, -x - dLogP));
                }
            }
            else
            {
                a = -x * x * ddLogP;
                if (a + 1 > double.MaxValue)
                {
                    return(Gamma.PointMass(x));
                }
            }
            if (forceProper)
            {
                if (dLogP <= 0)
                {
                    if (a < 0)
                    {
                        a = 0;
                    }
                }
                else
                {
                    double amin = x * dLogP;
                    if (a < amin)
                    {
                        return(Gamma.FromShapeAndRate(amin + 1, 0));
                    }
                }
            }
            double b = ((a == 0) ? 0 : (a / x)) - dLogP;

            if (forceProper)
            {
                // correct roundoff errors that might make b negative
                b = Math.Max(b, 0);
            }
            return(Gamma.FromShapeAndRate(a + 1, b));
        }