/// <summary> /// Get the average logarithm of that distribution under this distribution, i.e. int this(x) log( that(x) ) dx /// </summary> /// <param name="that"></param> /// <returns></returns> public double GetAverageLog(TruncatedGamma that) { if (IsPointMass) { if (that.IsPointMass && this.Point == that.Point) { return(0.0); } else { return(that.GetLogProb(this.Point)); } } else if (this.LowerBound < that.LowerBound || this.UpperBound > that.UpperBound) { return(double.NegativeInfinity); } else if (that.IsPointMass) { return(Double.NegativeInfinity); } else if (!IsProper()) { throw new ImproperDistributionException(this); } else { double m = GetMean(); double meanLog = GetMeanLog(); return((that.Gamma.Shape - 1) * meanLog - that.Gamma.Rate * m - that.GetLogNormalizer()); } }
public static TruncatedGamma Uniform() { var result = new TruncatedGamma(); result.SetToUniform(); return(result); }
/// <summary> /// Operator overload for exponentation /// </summary> /// <param name="dist"></param> /// <param name="exponent"></param> /// <returns></returns> public static TruncatedGamma operator ^(TruncatedGamma dist, double exponent) { var result = new TruncatedGamma(); result.SetToPower(dist, exponent); return(result); }
/// <summary> /// Operator overload for division /// </summary> /// <param name="numerator"></param> /// <param name="denominator"></param> /// <returns></returns> public static TruncatedGamma operator /(TruncatedGamma numerator, TruncatedGamma denominator) { var result = new TruncatedGamma(); result.SetToRatio(numerator, denominator); return(result); }
/// <summary> /// Operator overload for product. /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> public static TruncatedGamma operator *(TruncatedGamma a, TruncatedGamma b) { TruncatedGamma result = new TruncatedGamma(); result.SetToProduct(a, b); return(result); }
public static TruncatedGamma PointMass(double point) { var result = new TruncatedGamma(); result.Point = point; result.LowerBound = 0; result.UpperBound = double.PositiveInfinity; return(result); }
/// <summary> /// The maximum difference between the parameters of this distribution and that /// </summary> /// <param name="thatd"></param> /// <returns></returns> public double MaxDiff(object thatd) { if (!(thatd is TruncatedGamma)) { return(Double.PositiveInfinity); } TruncatedGamma that = (TruncatedGamma)thatd; double diff1 = Gamma.MaxDiff(that.Gamma); double diff3 = MMath.AbsDiff(LowerBound, that.LowerBound); double diff4 = MMath.AbsDiff(UpperBound, that.UpperBound); return(Math.Max(diff1, Math.Max(diff3, diff4))); }
/// <summary> /// Set the parameters to match the moments of a mixture distribution. /// </summary> /// <param name="dist1">The first distribution</param> /// <param name="weight1">The first weight</param> /// <param name="dist2">The second distribution</param> /// <param name="weight2">The second weight</param> public void SetToSum(double weight1, TruncatedGamma dist1, double weight2, TruncatedGamma dist2) { if (weight1 + weight2 == 0) { SetToUniform(); } else if (weight1 + weight2 < 0) { throw new ArgumentException("weight1 (" + weight1 + ") + weight2 (" + weight2 + ") < 0"); } else if (weight1 == 0) { SetTo(dist2); } else if (weight2 == 0) { SetTo(dist1); } // if dist1 == dist2 then we must return dist1, with no roundoff error else if (dist1.Equals(dist2)) { SetTo(dist1); } else if (double.IsPositiveInfinity(weight1)) { if (double.IsPositiveInfinity(weight2)) { throw new ArgumentException("both weights are infinity"); } else { SetTo(dist1); } } else if (double.IsPositiveInfinity(weight2)) { SetTo(dist2); } else if (dist1.LowerBound == dist2.LowerBound && dist1.UpperBound == dist2.UpperBound) { Gamma.SetToSum(weight1, dist1.Gamma, weight2, dist2.Gamma); } else { throw new NotImplementedException(); } }
/// <summary> /// Get the logarithm of the average value of that distribution under this distribution, i.e. log(int this(x) that(x) dx) /// </summary> /// <param name="that"></param> /// <returns></returns> public double GetLogAverageOf(TruncatedGamma that) { if (IsPointMass) { return(that.GetLogProb(Point)); } else if (that.IsPointMass) { return(GetLogProb(that.Point)); } else { // neither this nor that is a point mass. TruncatedGamma product = this * that; return(product.GetLogNormalizer() - this.GetLogNormalizer() - that.GetLogNormalizer()); } }
/// <summary> /// Set this equal to (dist)^exponent /// </summary> /// <param name="dist"></param> /// <param name="exponent"></param> public void SetToPower(TruncatedGamma dist, double exponent) { if (exponent == 0) { SetToUniform(); } else { if (exponent < 0 && !((dist.LowerBound == 0) && double.IsPositiveInfinity(dist.UpperBound))) { throw new DivideByZeroException("The exponent is negative and the bounds are finite"); } LowerBound = dist.LowerBound; UpperBound = dist.UpperBound; Gamma.SetToPower(dist.Gamma, exponent); } }
/// <summary> /// Set this distribution equal to the product of a and b /// </summary> /// <param name="a"></param> /// <param name="b"></param> public void SetToProduct(TruncatedGamma a, TruncatedGamma b) { LowerBound = Math.Max(a.LowerBound, b.LowerBound); UpperBound = Math.Min(a.UpperBound, b.UpperBound); if (LowerBound > UpperBound) { throw new AllZeroException(); } if (LowerBound == UpperBound) { Gamma.Point = LowerBound; } else { Gamma.SetToProduct(a.Gamma, b.Gamma); } }
/// <summary> /// Set this equal to numerator/denominator /// </summary> /// <param name="numerator"></param> /// <param name="denominator"></param> /// <param name="forceProper"></param> public void SetToRatio(TruncatedGamma numerator, TruncatedGamma denominator, bool forceProper = false) { if (numerator.IsPointMass) { if (denominator.IsPointMass) { if (numerator.Point.Equals(denominator.Point)) { SetToUniform(); } else { throw new DivideByZeroException(); } } else { if (denominator.LowerBound < numerator.Point && numerator.Point < denominator.UpperBound) { Point = numerator.Point; } else { throw new DivideByZeroException(); } } } else if (denominator.IsPointMass) { throw new DivideByZeroException(); } else { if (numerator.LowerBound >= denominator.LowerBound && numerator.UpperBound <= denominator.UpperBound) { LowerBound = numerator.LowerBound; UpperBound = numerator.UpperBound; Gamma.SetToRatio(numerator.Gamma, denominator.Gamma, forceProper); } else { throw new DivideByZeroException(); } } }
/// <summary> /// Get the integral of this distribution times another distribution raised to a power. /// </summary> /// <param name="that"></param> /// <param name="power"></param> /// <returns></returns> public double GetLogAverageOfPower(TruncatedGamma that, double power) { if (IsPointMass) { return(power * that.GetLogProb(Point)); } else if (that.IsPointMass) { if (power < 0) { throw new DivideByZeroException("The exponent is negative and the distribution is a point mass"); } return(this.GetLogProb(that.Point)); } else { var product = this * (that ^ power); return(product.GetLogNormalizer() - this.GetLogNormalizer() - power * that.GetLogNormalizer()); } }
/// <summary> /// Create a new TruncatedGamma distribution equal to that /// </summary> /// <param name="that"></param> public TruncatedGamma(TruncatedGamma that) : this() { SetTo(that); }
/// <summary> /// Set this distribution equal to value. /// </summary> /// <param name="value"></param> public void SetTo(TruncatedGamma value) { Gamma.SetTo(value.Gamma); LowerBound = value.LowerBound; UpperBound = value.UpperBound; }
/// <inheritdoc/> public double GetProbBetween(double lowerBound, double upperBound) { return(TruncatedGamma.GammaProbBetween(Shape, Rate, lowerBound, upperBound)); }