/// <summary> /// Operator overload for exponentation /// </summary> /// <param name="dist"></param> /// <param name="exponent"></param> /// <returns></returns> public static TruncatedGaussian operator ^(TruncatedGaussian dist, double exponent) { var result = new TruncatedGaussian(); result.SetToPower(dist, exponent); return(result); }
/// <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(TruncatedGaussian 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, v; GetMeanAndVariance(out m, out v); return(-0.5 * that.Gaussian.Precision * (m * m + v) + that.Gaussian.MeanTimesPrecision * m - that.GetLogNormalizer()); } }
/// <summary> /// Operator overload for division /// </summary> /// <param name="numerator"></param> /// <param name="denominator"></param> /// <returns></returns> public static TruncatedGaussian operator /(TruncatedGaussian numerator, TruncatedGaussian denominator) { var result = new TruncatedGaussian(); result.SetToRatio(numerator, denominator); return(result); }
/// <summary> /// Operator overload for product. /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> public static TruncatedGaussian operator *(TruncatedGaussian a, TruncatedGaussian b) { TruncatedGaussian result = new TruncatedGaussian(); result.SetToProduct(a, b); return(result); }
/// <summary> /// Create a point mass distribution. /// </summary> /// <param name="point">The location of the point mass</param> /// <returns>A new TruncatedGaussian with all probability concentrated on the given point.</returns> public static TruncatedGaussian PointMass(double point) { var result = new TruncatedGaussian(); result.Point = point; return(result); }
/// <summary> /// Construct a uniform truncated Gaussian. This is mathematically equivalent to /// a uniform Gaussian. /// </summary> /// <returns></returns> public static TruncatedGaussian Uniform() { var result = new TruncatedGaussian(); result.SetToUniform(); return(result); }
/// <summary> /// Set this distribution equal to the product of a and b /// </summary> /// <param name="a"></param> /// <param name="b"></param> public void SetToProduct(TruncatedGaussian a, TruncatedGaussian b) { LowerBound = Math.Max(a.LowerBound, b.LowerBound); UpperBound = Math.Min(a.UpperBound, b.UpperBound); if (LowerBound > UpperBound) { throw new AllZeroException(); } Gaussian.SetToProduct(a.Gaussian, b.Gaussian); }
/// <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 TruncatedGaussian)) { return(Double.PositiveInfinity); } TruncatedGaussian that = (TruncatedGaussian)thatd; double diff1 = Gaussian.MaxDiff(that.Gaussian); 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, TruncatedGaussian dist1, double weight2, TruncatedGaussian 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) { Gaussian.SetToSum(weight1, dist1.Gaussian, weight2, dist2.Gaussian); } 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(TruncatedGaussian that) { if (IsPointMass) { return(that.GetLogProb(Point)); } else if (that.IsPointMass) { return(GetLogProb(that.Point)); } else { // neither this nor that is a point mass. TruncatedGaussian 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(TruncatedGaussian dist, double exponent) { if (exponent == 0) { SetToUniform(); } else { if (exponent < 0 && !(double.IsNegativeInfinity(dist.LowerBound) && double.IsPositiveInfinity(dist.UpperBound))) { throw new DivideByZeroException("The exponent is negative and the bounds are finite"); } LowerBound = dist.LowerBound; UpperBound = dist.UpperBound; Gaussian.SetToPower(dist.Gaussian, exponent); } }
/// <summary> /// Set this equal to numerator/denominator /// </summary> /// <param name="numerator"></param> /// <param name="denominator"></param> public void SetToRatio(TruncatedGaussian numerator, TruncatedGaussian denominator) { 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; Gaussian.SetToRatio(numerator.Gaussian, denominator.Gaussian); } 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(TruncatedGaussian 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 TruncatedGaussian distribution equal to that /// </summary> /// <param name="that"></param> public TruncatedGaussian(TruncatedGaussian that) : this() { SetTo(that); }
/// <summary> /// Set this distribution equal to value. /// </summary> /// <param name="value"></param> public void SetTo(TruncatedGaussian value) { Gaussian.SetTo(value.Gaussian); LowerBound = value.LowerBound; UpperBound = value.UpperBound; }