/// <summary>
 /// Gets the expected logarithm of that distribution under this distribution.
 /// </summary>
 /// <param name="that">The distribution to take the logarithm of.</param>
 /// <returns><c>sum_x this.Evaluate(x)*Math.Log(that.Evaluate(x))</c></returns>
 /// <remarks>This is also known as the cross entropy.</remarks>
 public double GetAverageLog(Gaussian that)
 {
     if (that.IsPointMass)
     {
         if (this.IsPointMass && this.Point == that.Point)
         {
             return(0.0);
         }
         else
         {
             return(Double.NegativeInfinity);
         }
     }
     else if (!IsProper())
     {
         throw new ImproperDistributionException(this);
     }
     else
     {
         // that.Precision != inf
         double mean, variance;
         GetMeanAndVariance(out mean, out variance);
         return(that.GetLogProb(mean) - 0.5 * that.Precision * variance);
     }
 }
Exemple #2
0
        /// <summary>
        /// Get the log probability density at value.
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public double GetLogProb(double value)
        {
            // p(x) = sum_k N(x + L*k; m, v)
            //      = a/(2*pi) + a/pi sum_{k=1}^inf cos(a*k*(x-m)) exp(-(a*k)^2 v/2) where a = 2*pi/L
            double m, v;

            Gaussian.GetMeanAndVariance(out m, out v);
            if (v < 0.15)
            {
                // use Gaussian summation formula
                double result = double.NegativeInfinity;
                for (int k = -1; k <= 1; k++)
                {
                    double logp = Gaussian.GetLogProb(value + k * Period);
                    result = MMath.LogSumExp(result, logp);
                }
                return(result);
            }
            else
            {
                // v >= 0.15
                // use the cosine formula
                double result  = 0.5;
                double aOverPi = 2 / Period;
                double a       = aOverPi * Math.PI;
                double diff    = value - m;
                double vHalf   = v * 0.5;
                for (int k = 1; k <= 8; k++)
                {
                    double ak = a * k;
                    result += Math.Cos(ak * diff) * Math.Exp(-ak * ak * vHalf);
                }
                return(Math.Log(result * aOverPi));
            }
        }
 /// <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(Gaussian 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>
 /// Gets the integral of the product of two Gaussians.
 /// </summary>
 /// <param name="that"></param>
 /// <remarks>
 /// <c>this = N(x;m1,v1)</c>.
 /// <c>that = N(x;m2,v2)</c>.
 /// <c>int_(-infinity)^(infinity) N(x;m1,v1) N(x;m2,v2) dx = N(m1; m2, v1+v2)</c>.
 /// When improper, the density is redefined to be <c>exp(-0.5*x^2*(1/v) + x*(m/v))</c>,
 /// i.e. we drop the terms <c>exp(-m^2/(2v))/sqrt(2*pi*v)</c>.
 /// </remarks>
 /// <returns>log(N(m1;m2,v1+v2)).</returns>
 public double GetLogAverageOf(Gaussian that)
 {
     if (IsPointMass)
     {
         return(that.GetLogProb(Point));
     }
     else if (that.IsPointMass)
     {
         return(GetLogProb(that.Point));
     }
     else
     {
         // neither this nor that is a point mass.
         // int_x N(x;m1,v1) N(x;m2,v2) dx = N(m1;m2,v1+v2)
         // (m1-m2)^2/(v1+v2) = (m1-m2)^2/(v1*v2*product.Prec)
         // (m1-m2)^2/(v1*v2) = (m1/(v1*v2) - m2/(v1*v2))^2 *v1*v2
         Gaussian product = this * that;
         //if (!product.IsProper()) throw new ArgumentException("The product is improper.");
         return(product.GetLogNormalizer() - this.GetLogNormalizer() - that.GetLogNormalizer());
     }
 }