/// <summary> /// Construct a Gamma distribution whose pdf has the given derivatives at a point. /// </summary> /// <param name="x">Must be positive</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 ArgumentException("x <= 0"); } double a = -x * x * ddLogP; if (ddLogP == 0.0) { a = 0.0; // in case x is infinity } if (forceProper) { if (dLogP < 0) { if (a < 0) { a = 0; } } else { double amin = x * dLogP; if (a < amin) { a = amin; } } } double b = a / x - dLogP; if (forceProper) { // correct roundoff errors that might make b negative b = Math.Max(b, 0); } return(Gamma.FromShapeAndRate(a + 1, b)); }
/// <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)); }
/// <summary> /// Adds a GammaPower distribution item to the estimator /// </summary> /// <param name="distribution">The distribution instance to add</param> /// <param name="weight">The weight of the sample</param> public void Add(GammaPower distribution, double weight) { gammaEstimator.Add(Gamma.FromShapeAndRate(distribution.Shape, distribution.Rate), weight); }