예제 #1
0
        public static Gaussian BAverageConditional([SkipIfUniform] VectorGaussian product, [SkipIfUniform] VectorGaussian a, Gaussian b)
        {
            if (!b.IsPointMass)
            {
                throw new ArgumentException("b is not a point mass", nameof(b));
            }
            double bPoint      = b.Point;
            Vector productMean = Vector.Zero(product.Dimension);
            PositiveDefiniteMatrix productVariance = new PositiveDefiniteMatrix(product.Dimension, product.Dimension);

            product.GetMeanAndVariance(productMean, productVariance);
            Vector aMean = Vector.Zero(product.Dimension);
            PositiveDefiniteMatrix aVariance = new PositiveDefiniteMatrix(product.Dimension, product.Dimension);

            a.GetMeanAndVariance(aMean, aVariance);
            PositiveDefiniteMatrix variance = new PositiveDefiniteMatrix(product.Dimension, product.Dimension);

            variance.SetToSum(1, productVariance, bPoint * bPoint, aVariance);
            // variance = productVariance + aVariance * b^2
            PositiveDefiniteMatrix precision = variance.Inverse();
            Vector diff = aMean * bPoint;

            diff.SetToDifference(productMean, diff);
            // diff = productMean - aMean * b
            var    precisionDiff = precision * diff;
            double dlogf         = aMean.Inner(precisionDiff) + bPoint * (precisionDiff.Inner(aVariance * precisionDiff) - Matrix.TraceOfProduct(precision, aVariance));
            double ddlogf        = -1;

            return(Gaussian.FromDerivatives(bPoint, dlogf, ddlogf, GaussianProductOp.ForceProper));
        }
예제 #2
0
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="IntegralOp"]/message_doc[@name="UpperBoundAverageConditional(Gaussian, double, Func{double,double}, ITruncatableDistribution{double})"]/*'/>
        public static Gaussian UpperBoundAverageConditional(Gaussian integral, double upperBound, Func <double, double> func, ITruncatableDistribution <double> distribution)
        {
            CanGetLogProb <double> canGetLogProb = (CanGetLogProb <double>)distribution;
            double dlogf  = integral.MeanTimesPrecision * func(upperBound) * Math.Exp(canGetLogProb.GetLogProb(upperBound));
            double ddlogf = 0; // approximation ignoring integral.Precision

            return(Gaussian.FromDerivatives(upperBound, dlogf, ddlogf, false));
        }
예제 #3
0
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="RatioGaussianOp"]/message_doc[@name="ProbabilityAverageConditional(Gaussian, CanGetQuantile{double}, double)"]/*'/>
        public static Gaussian ProbabilityAverageConditional(Gaussian quantile, CanGetQuantile <double> canGetQuantile, double probability)
        {
            // The quantile function is the inverse function of the cdf.
            // The derivative of the quantile function is the reciprocal of the pdf.
            double x = canGetQuantile.GetQuantile(probability);
            CanGetLogProb <double> canGetLogProb = (CanGetLogProb <double>)canGetQuantile;
            double dlogp  = quantile.MeanTimesPrecision / Math.Exp(canGetLogProb.GetLogProb(x));
            double ddlogp = 0; // approximation ignoring quantile.Precision

            return(Gaussian.FromDerivatives(probability, dlogp, ddlogp, false));
        }
예제 #4
0
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="ProbBetweenOp"]/message_doc[@name="LowerBoundAverageConditional(Gaussian, CanGetProbLessThan{double}, double)"]/*'/>
        public static Gaussian LowerBoundAverageConditional(Gaussian probBetween, CanGetProbLessThan <double> canGetProbLessThan, double lowerBound)
        {
            CanGetLogProb <double> canGetLogProb = (CanGetLogProb <double>)canGetProbLessThan;
            // factor is N(ProbBetween(left, right); m, v)
            // logp = -(m - ProbBetween(left, right))^2/(2v)
            // dlogp = (m - ProbBetween(left, right))/v * dProbBetween(left, right)
            // dProbBetween(left, right)/dleft = -p(left)
            // ddlogp = (m - ProbBetween(left, right))/v * ddProbBetween(left, right) - dProbBetween(left, right)/v * dProbBetween(left, right)
            // (m - ProbBetween(left, right))/v -> m/v
            double dlogp  = -Math.Exp(canGetLogProb.GetLogProb(lowerBound)) * probBetween.MeanTimesPrecision;
            double ddlogp = 0; // approximation ignoring probBetween.Precision

            return(Gaussian.FromDerivatives(lowerBound, dlogp, ddlogp, false));
        }
예제 #5
0
 /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="RatioGaussianOp"]/message_doc[@name="AAverageConditional(Gaussian, Gaussian, Gaussian)"]/*'/>
 public static Gaussian BAverageConditional([SkipIfUniform] Gaussian ratio, [SkipIfUniform] Gaussian a, Gaussian b)
 {
     //if (string.Empty.Length == 0) return GaussianProductOp.BAverageConditional(Gaussian.FromNatural(a.MeanTimesPrecision, Math.Min(a.Precision, 1e16)), Gaussian.FromNatural(ratio.MeanTimesPrecision, ratio.Precision + 1e-16), b);
     if (b.IsPointMass && ratio.Precision == 0)
     {
         // f(b) = int_a N(m; a/b, v) p(a) da
         //      = N(m; ma/b, v + va/b^2)
         // logf = -0.5*log(v + va/b^2) -0.5*(m - ma/b)^2/(v + va/b^2)
         // dlogf = va/b^3/(v + va/b^2) -(m - ma/b)/(v + va/b^2)*(ma/b^2) + (m - ma/b)^2/(v + va/b^2)^2*(va/b^3)
         // -> -(m - ma/b)/v * (ma/b^2)
         double dlogp  = -a.GetMean() / (b.Point * b.Point) * ratio.MeanTimesPrecision;
         double ddlogp = 0;
         return(Gaussian.FromDerivatives(b.Point, dlogp, ddlogp, false));
     }
     else
     {
         throw new NotSupportedException();
     }
 }
예제 #6
0
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="ProbBetweenOp"]/message_doc[@name="UpperBoundAverageConditional(Gaussian, CanGetProbLessThan{double}, Gaussian)"]/*'/>
        public static Gaussian UpperBoundAverageConditional(Gaussian probBetween, CanGetProbLessThan <double> canGetProbLessThan, [RequiredArgument] Gaussian upperBound)
        {
            CanGetLogProb <double> canGetLogProb = (CanGetLogProb <double>)canGetProbLessThan;

            // factor is N(ProbBetween(left, right); m, v)
            if (upperBound.IsPointMass)
            {
                // logp = -(m - ProbBetween(left, right))^2/(2v)
                // dlogp = (m - ProbBetween(left, right))/v * dProbBetween(left, right)
                // dProbBetween(left, right)/dright = p(right)
                // ddlogp = (m - ProbBetween(left, right))/v * ddProbBetween(left, right) - dProbBetween(left, right)/v * dProbBetween(left, right)
                double dlogp  = Math.Exp(canGetLogProb.GetLogProb(upperBound.Point)) * probBetween.MeanTimesPrecision;
                double ddlogp = 0; // approximation ignoring probBetween.Precision
                return(Gaussian.FromDerivatives(upperBound.Point, dlogp, ddlogp, false));
            }
            else
            {
                throw new NotSupportedException();
            }
        }
예제 #7
0
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="MaxGaussianOp"]/message_doc[@name="AAverageConditional(Gaussian, Gaussian, Gaussian)"]/*'/>
        public static Gaussian AAverageConditional([SkipIfUniform] Gaussian max, [Proper] Gaussian a, [Proper] Gaussian b)
        {
            if (max.IsUniform())
            {
                return(Gaussian.Uniform());
            }
            if (!b.IsProper())
            {
                throw new ImproperMessageException(b);
            }

            double logw1, alpha1, vx1, mx1;
            double logw2, alpha2, vx2, mx2;
            double logz;

            ComputeStats(max, a, b, out logz, out logw1, out alpha1, out vx1, out mx1,
                         out logw2, out alpha2, out vx2, out mx2);
            double w1 = Math.Exp(logw1 - logz);
            double w2 = Math.Exp(logw2 - logz);
            bool   checkDerivatives = false;

            if (a.IsPointMass)
            {
                // f(a) = int p(x = max(a,b)) p(b) db
                // f(a) = p(x = a) p(a >= b) + p(x = b) p(a < b | x = b)
                // f(a) = N(a; mx, vx) phi((a - m2)/sqrt(v2)) + N(m2; mx, vx + v2) phi((mx2 - a)/sqrt(vx2))
                // f'(a) = (mx-a)/vx N(a; mx, vx) phi((a - m2)/sqrt(v2)) + N(a; mx, vx) N(a; m2, v2) - N(m2; mx, vx + v2) N(a; mx2, vx2)
                //       = (mx-a)/vx N(a; mx, vx) phi((a - m2)/sqrt(v2))
                // f''(a) = -1/vx N(a; mx, vx) phi((a - m2)/sqrt(v2)) + (mx-a)^2/vx^2 N(a; mx, vx) phi((a - m2)/sqrt(v2)) + (mx-a)/vx N(a; mx, vx) N(a; m2, v2)
                // ddlogf = f''(a)/f(a) - (f'(a)/f(a))^2 = (f''(a) f(a) - f'(a)^2)/f(a)^2
                double aPoint = a.Point;
                if (max.IsPointMass)
                {
                    return(max);
                }
                double z     = max.MeanTimesPrecision - aPoint * max.Precision;
                double alpha = z * w1;
                double beta  = (z * alpha1 - max.Precision + z * z) * w1 - alpha * alpha;
                if (b.IsPointMass && b.Point != aPoint)
                {
                    beta -= max.Precision * w2 * alpha2 * (b.Point - aPoint);
                }
                if (checkDerivatives)
                {
                    double m1 = a.GetMean();
                    double delta = m1 * 1e-6;
                    double logzd, logw1d, alpha1d, vx1d, mx1d, logw2d, alpha2d, vx2d, mx2d;
                    ComputeStats(max, Gaussian.FromMeanAndPrecision(m1 + delta, a.Precision), b, out logzd, out logw1d, out alpha1d, out vx1d, out mx1d, out logw2d, out alpha2d, out vx2d, out mx2d);
                    double logzd2;
                    ComputeStats(max, Gaussian.FromMeanAndPrecision(m1 - delta, a.Precision), b, out logzd2, out logw1d, out alpha1d, out vx1d, out mx1d, out logw2d, out alpha2d, out vx2d, out mx2d);
                    double alphaCheck = (logzd - logzd2) / (2 * delta);
                    double alphaError = Math.Abs(alpha - alphaCheck);
                    double betaCheck  = (logzd + logzd2 - 2 * logz) / (delta * delta);
                    double betaError  = Math.Abs(beta - betaCheck);
                    Console.WriteLine($"alpha={alpha} check={alphaCheck} error={alphaError} beta={beta} check={betaCheck} error={betaError}");
                }
                return(Gaussian.FromDerivatives(aPoint, alpha, beta, ForceProper));
            }
            bool useMessage = (w1 > 0) || (logw2 > -100);

            if (useMessage)
            {
                // vx1 = 1/(1/vx + 1/v1) = vx*v1/(vx + v1)
                double z, alpha, beta;
                if (max.IsPointMass)
                {
                    if (w2 == 0)
                    {
                        return(max);
                    }
                    z     = max.Point * a.Precision - a.MeanTimesPrecision;
                    alpha = z * w1 - w2 * alpha2;
                    beta  = (z * z - a.Precision) * w1 - z * alpha2 * w2 - alpha * alpha;
                }
                else
                {
                    //z = vx1 * (max.MeanTimesPrecision * a.Precision - a.MeanTimesPrecision * max.Precision);
                    z     = (max.MeanTimesPrecision - a.GetMean() * max.Precision) / (max.Precision / a.Precision + 1);
                    alpha = z * w1 - vx1 * max.Precision * w2 * alpha2;
                    if (w2 == 0)
                    {
                        //beta = (z * alpha1 - max.Precision) / (max.Precision / a.Precision + 1);
                        //double resultPrecision = a.Precision * beta / (-a.Precision - beta);
                        //resultPrecision = beta / (-1 - beta/a.Precision);
                        //resultPrecision = 1 / (-1/beta - 1 / a.Precision);
                        //resultPrecision = a.Precision / (-a.Precision / beta - 1);
                        //resultPrecision = a.Precision / (-(a.Precision + max.Precision) / (z * alpha1 - max.Precision) - 1);
                        //resultPrecision = -a.Precision / ((a.Precision + z*alpha1) / (z * alpha1 - max.Precision));
                        double zalpha1         = z * alpha1;
                        double denom           = (1 + zalpha1 / a.Precision);
                        double resultPrecision = (max.Precision - zalpha1) / denom;
                        //double weight = (max.Precision - z * alpha1) / (a.Precision + z * alpha1);
                        //double weightPlus1 = (max.Precision + a.Precision) / (a.Precision + z * alpha1);
                        //double resultMeanTimesPrecision = weight * (a.MeanTimesPrecision + alpha) + alpha;
                        //resultMeanTimesPrecision = weight * a.MeanTimesPrecision + weightPlus1 * alpha;
                        //double resultMeanTimesPrecision = (a.Precision * max.MeanTimesPrecision - z * alpha1 * a.MeanTimesPrecision) / (a.Precision + z * alpha1);
                        double resultMeanTimesPrecision = (max.MeanTimesPrecision - zalpha1 * a.GetMean()) / denom;
                        return(Gaussian.FromNatural(resultMeanTimesPrecision, resultPrecision));
                    }
                    else
                    {
                        beta = ((z * alpha1 - max.Precision) * vx1 * a.Precision + z * z) * w1
                               - max.Precision * vx1 * w2 * alpha2 * (mx2 * a.Precision - a.MeanTimesPrecision) / (vx2 * a.Precision + 1) - alpha * alpha;
                    }
                }
                //Console.WriteLine($"z={z} w1={w1:r} w2={w2:r} logw2={logw2} alpha1={alpha1} alpha2={alpha2} alpha={alpha:r} beta={beta:r}");
                if (checkDerivatives)
                {
                    double m1 = a.GetMean();
                    double delta = m1 * 1e-6;
                    double logzd, logw1d, alpha1d, vx1d, mx1d, logw2d, alpha2d, vx2d, mx2d;
                    ComputeStats(max, Gaussian.FromMeanAndPrecision(m1 + delta, a.Precision), b, out logzd, out logw1d, out alpha1d, out vx1d, out mx1d, out logw2d, out alpha2d, out vx2d, out mx2d);
                    double logzd2;
                    ComputeStats(max, Gaussian.FromMeanAndPrecision(m1 - delta, a.Precision), b, out logzd2, out logw1d, out alpha1d, out vx1d, out mx1d, out logw2d, out alpha2d, out vx2d, out mx2d);
                    double alphaCheck = (logzd - logzd2) / (2 * delta);
                    double alphaError = Math.Abs(alpha - alphaCheck);
                    double betaCheck  = (logzd + logzd2 - 2 * logz) / (delta * delta);
                    double betaError  = Math.Abs(beta - betaCheck);
                    Console.WriteLine($"alpha={alpha} check={alphaCheck} error={alphaError} beta={beta} check={betaCheck} error={betaError}");
                }
                return(GaussianOp.GaussianFromAlphaBeta(a, alpha, -beta, ForceProper));
            }
            else
            {
                double m1, v1, m2, v2;
                a.GetMeanAndVariance(out m1, out v1);
                b.GetMeanAndVariance(out m2, out v2);
                // the posterior is a mixture model with weights exp(logw1-logz), exp(logw2-logz) and distributions
                // N(a; mx1, vx1) phi((a - m2)/sqrt(v2)) / phi((mx1 - m2)/sqrt(vx1 + v2))
                // N(a; m1, v1) phi((mx2 - a)/sqrt(vx2)) / phi((mx2 - m1)/sqrt(vx2 + v1))
                // the moments of the posterior are computed via the moments of these two components.
                if (vx1 == 0)
                {
                    alpha1 = 0;
                }
                if (vx2 == 0)
                {
                    alpha2 = 0;
                }
                double mc1 = mx1;
                if (alpha1 != 0) // avoid 0*infinity
                {
                    mc1 += alpha1 * vx1;
                }
                alpha2 = -alpha2;
                double mc2 = m1;
                if (alpha2 != 0) // avoid 0*infinity
                {
                    mc2 += alpha2 * v1;
                }
                // z2 = (mx2 - m1) / Math.Sqrt(vx2 + v1)
                // logw2 = MMath.NormalCdfLn(z2);
                // alpha2 = -Math.Exp(Gaussian.GetLogProb(mx2, m1, vx2 + v1) - logw2);
                //        = -1/sqrt(vx2+v1)/NormalCdfRatio(z2)
                // m1 + alpha2*v1 = sqrt(vx2+v1)*(m1/sqrt(vx2+v1) - v1/(vx2+v1)/NormalCdfRatio(z2))
                //                = sqrt(vx2+v1)*(mx2/sqrt(vx2+v1) - z2 - v1/(vx2+v1)/NormalCdfRatio(z2))
                //                = sqrt(vx2+v1)*(mx2/sqrt(vx2+v1) - dY/Y)  if vx2=0
                double       z2 = 0, Y = 0, dY = 0;
                const double z2small = 0;
                if (vx2 == 0)
                {
                    z2 = (mx2 - m1) / Math.Sqrt(vx2 + v1);
                    if (z2 < z2small)
                    {
                        Y   = MMath.NormalCdfRatio(z2);
                        dY  = MMath.NormalCdfMomentRatio(1, z2);
                        mc2 = mx2 - Math.Sqrt(v1) * dY / Y;
                    }
                }
                double m = w1 * mc1 + w2 * mc2;
                double beta1;
                if (alpha1 == 0)
                {
                    beta1 = 0;  // avoid 0*infinity
                }
                else
                {
                    double r1 = (mx1 - m2) / (vx1 + v2);
                    beta1 = alpha1 * (alpha1 + r1);
                }
                double beta2;
                if (alpha2 == 0)
                {
                    beta2 = 0;  // avoid 0*infinity
                }
                else
                {
                    double r2 = (mx2 - m1) / (vx2 + v1);
                    beta2 = alpha2 * (alpha2 - r2);
                }
                double vc1 = vx1 * (1 - vx1 * beta1);
                double vc2;
                if (vx2 == 0 && z2 < z2small)
                {
                    // beta2 = alpha2 * (alpha2 - z2/sqrt(v1))
                    // vc2 = v1 - v1^2 * alpha2 * (alpha2 - z2/sqrt(v1))
                    //     = v1 - v1*dY/Y^2
                    //     =approx v1/z2^2
                    // posterior E[x^2] = v - v*dY/Y^2 + v*dY^2/Y^2 = v - v*dY/Y^2*(1 - dY) = v + v*z*dY/Y = v*d2Y/Y
                    //vc2 = v1 * (1 - dY / (Y * Y));
                    double d2Y  = 2 * MMath.NormalCdfMomentRatio(2, z2);
                    double dYiY = dY / Y;
                    vc2 = v1 * (d2Y / Y - dYiY * dYiY);
                }
                else if (beta2 == 0)
                {
                    vc2 = v1;
                }
                else
                {
                    vc2 = v1 * (1 - v1 * beta2);
                }
                double   diff   = mc1 - mc2;
                double   v      = w1 * vc1 + w2 * vc2 + w1 * w2 * diff * diff;
                Gaussian result = new Gaussian(m, v);
                //Console.WriteLine($"z2={z2} m={m} v={v} vc2={vc2} diff={diff}");
                result.SetToRatio(result, a, ForceProper);
                if (Double.IsNaN(result.Precision) || Double.IsNaN(result.MeanTimesPrecision))
                {
                    throw new InferRuntimeException($"result is NaN.  max={max}, a={a}, b={b}");
                }
                return(result);
            }
        }
예제 #8
0
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="ArrayFromVectorOp"]/message_doc[@name="ArrayAverageConditional{GaussianList}(IList{Gaussian}, VectorGaussian, GaussianList)"]/*'/>
        /// <typeparam name="GaussianList">The type of the resulting array.</typeparam>
        public static GaussianList ArrayAverageConditional <GaussianList>(
            [NoInit] IList <Gaussian> array, [SkipIfUniform] VectorGaussian vector, GaussianList result)
            where GaussianList : IList <Gaussian>
        {
            if (result.Count != vector.Dimension)
            {
                throw new ArgumentException("vector.Dimension (" + vector.Dimension + ") != result.Count (" + result.Count + ")");
            }
            int  length       = result.Count;
            bool allPointMass = array.All(g => g.IsPointMass);

            if (allPointMass)
            {
                // efficient special case
                for (int i = 0; i < length; i++)
                {
                    double x = array[i].Point;
                    // -prec*(x-m) = -prec*x + prec*m
                    double dlogp = vector.MeanTimesPrecision[i];
                    for (int j = 0; j < length; j++)
                    {
                        dlogp -= vector.Precision[i, j] * array[j].Point;
                    }
                    double ddlogp = -vector.Precision[i, i];
                    result[i] = Gaussian.FromDerivatives(x, dlogp, ddlogp, false);
                }
            }
            else if (vector.IsPointMass)
            {
                // efficient special case
                Vector mean = vector.Point;
                for (int i = 0; i < length; i++)
                {
                    result[i] = Gaussian.PointMass(mean[i]);
                }
            }
            else if (vector.IsUniform())
            {
                for (int i = 0; i < length; i++)
                {
                    result[i] = Gaussian.Uniform();
                }
            }
            else if (array.Any(g => g.IsPointMass))
            {
                // Z = N(m1; m2, V1+V2)
                // logZ = -0.5 (m1-m2)'inv(V1+V2)(m1-m2)
                // dlogZ = (m1-m2)'inv(V1+V2) dm2
                // ddlogZ = -dm2'inv(V1+V2) dm2
                Vector mean = Vector.Zero(length);
                PositiveDefiniteMatrix variance = new PositiveDefiniteMatrix(length, length);
                vector.GetMeanAndVariance(mean, variance);
                for (int i = 0; i < length; i++)
                {
                    if (array[i].IsUniform())
                    {
                        continue;
                    }
                    double m, v;
                    array[i].GetMeanAndVariance(out m, out v);
                    variance[i, i] += v;
                    mean[i]        -= m;
                }
                PositiveDefiniteMatrix precision = variance.Inverse();
                Vector meanTimesPrecision        = precision * mean;
                for (int i = 0; i < length; i++)
                {
                    if (array[i].IsUniform())
                    {
                        result[i] = Gaussian.FromMeanAndVariance(mean[i], variance[i, i]);
                    }
                    else
                    {
                        double alpha = meanTimesPrecision[i];
                        double beta  = precision[i, i];
                        result[i] = GaussianOp.GaussianFromAlphaBeta(array[i], alpha, beta, false);
                    }
                }
            }
            else
            {
                // Compute inv(V1+V2)*(m1-m2) as inv(V2)*inv(inv(V1) + inv(V2))*(inv(V1)*m1 + inv(V2)*m2) - inv(V2)*m2 = inv(V2)*(m - m2)
                // Compute inv(V1+V2) as inv(V2)*inv(inv(V1) + inv(V2))*inv(V2) - inv(V2)
                PositiveDefiniteMatrix precision = (PositiveDefiniteMatrix)vector.Precision.Clone();
                Vector meanTimesPrecision        = vector.MeanTimesPrecision.Clone();
                for (int i = 0; i < length; i++)
                {
                    Gaussian g = array[i];
                    precision[i, i]       += g.Precision;
                    meanTimesPrecision[i] += g.MeanTimesPrecision;
                }
                bool fastMethod = true;
                if (fastMethod)
                {
                    bool isPosDef;
                    // this destroys precision
                    LowerTriangularMatrix precisionChol = precision.CholeskyInPlace(out isPosDef);
                    if (!isPosDef)
                    {
                        throw new PositiveDefiniteMatrixException();
                    }
                    // variance = inv(precisionChol*precisionChol') = inv(precisionChol)'*inv(precisionChol) = varianceChol*varianceChol'
                    // this destroys meanTimesPrecision
                    var mean = meanTimesPrecision.PredivideBy(precisionChol);
                    mean = mean.PredivideByTranspose(precisionChol);
                    var varianceCholTranspose = precisionChol;
                    // this destroys precisionChol
                    varianceCholTranspose.SetToInverse(precisionChol);
                    for (int i = 0; i < length; i++)
                    {
                        Gaussian g           = array[i];
                        double   variance_ii = GetSquaredLengthOfColumn(varianceCholTranspose, i);
                        // works when g is uniform, but not when g is point mass
                        result[i] = Gaussian.FromMeanAndVariance(mean[i], variance_ii) / g;
                    }
                }
                else
                {
                    // equivalent to above, but slower
                    PositiveDefiniteMatrix variance = precision.Inverse();
                    var mean = variance * meanTimesPrecision;
                    for (int i = 0; i < length; i++)
                    {
                        Gaussian g = array[i];
                        // works when g is uniform, but not when g is point mass
                        result[i] = Gaussian.FromMeanAndVariance(mean[i], variance[i, i]) / g;
                    }
                }
            }
            return(result);
        }
예제 #9
0
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="MatrixVectorProductOp"]/message_doc[@name="AAverageConditional(VectorGaussian, DistributionArray2D{Gaussian, double}, Vector, PositiveDefiniteMatrix, DistributionStructArray2D{Gaussian, double})"]/*'/>
        public static DistributionStructArray2D <Gaussian, double> AAverageConditional([SkipIfUniform] VectorGaussian product, DistributionArray2D <Gaussian, double> A, Vector BMean, PositiveDefiniteMatrix BVariance, DistributionStructArray2D <Gaussian, double> result)
        {
            if (product.IsUniform())
            {
                result.SetToUniform();
                return(result);
            }
            if (!A.IsPointMass)
            {
                throw new ArgumentException("A is not a point mass");
            }
            // logZ = log N(mProduct; A*BMean, vProduct + A*BVariance*A')
            //      = -0.5 (mProduct - A*BMean)' inv(vProduct + A*BVariance*A') (mProduct - A*BMean) - 0.5 logdet(vProduct + A*BVariance*A')
            //      = -0.5 (mProduct - A*BMean)' pPrec inv(pProduct + pProduct*A*BVariance*A'*pProduct) pProduct (mProduct - A*BMean)
            //        - 0.5 logdet(pProduct + pProduct*A*BVariance*A'*pProduct) + logdet(pProduct)
            // dlogZ   = 0.5 (dA*BMean)' pProduct inv(pProduct + pProduct*A*BVariance*A'*pProduct) pProduct (mProduct - A*BMean)
            //         +0.5 (mProduct - A*BMean)' pProduct inv(pProduct + pProduct*A*BVariance*A'*pProduct) pProduct (dA*BMean)
            //         +0.5 (mProduct - A*BMean)' pProduct inv(pProduct + pProduct*A*BVariance*A'*pProduct) (pProduct*dA*BVariance*A'*pProduct + pProduct*A*BVariance*dA'*pProduct) inv(pProduct + pProduct*A*BVariance*A'*pProduct) pProduct (mProduct - A*BMean)
            //         - 0.5 tr(inv(pProduct + pProduct*A*BVariance*A'*pProduct) (pProduct*dA*BVariance*A'*pProduct + pProduct*A*BVariance*dA'*pProduct))
            // dlogZ/dA = pProduct inv(pProduct + pProduct*A*BVariance*A'*pProduct) pProduct (mProduct - A*BMean) BMean'
            //          + pProduct inv(pProduct + pProduct*A*BVariance*A'*pProduct) pProduct (mProduct - A*BMean) (mProduct - A*BMean)' pProduct inv(pProduct + pProduct*A*BVariance*A'*pProduct) pProduct*A*BVariance
            //          - pProduct inv(pProduct + pProduct*A*BVariance*A'*pProduct) pProduct A*BVariance
            var Amatrix                 = new Matrix(A.Point);
            var pProductA               = product.Precision * Amatrix;
            var pProductABV             = pProductA * BVariance;
            PositiveDefiniteMatrix prec = new PositiveDefiniteMatrix(product.Dimension, product.Dimension);

            prec.SetToSum(product.Precision, pProductABV * pProductA.Transpose());
            // pProductA is now free
            for (int i = 0; i < prec.Rows; i++)
            {
                if (prec[i, i] == 0)
                {
                    prec[i, i] = 1;
                }
            }
            var v           = prec.Inverse();
            var ABM         = Amatrix * BMean;
            var pProductABM = product.Precision * ABM;
            var diff        = pProductABM;

            diff.SetToDifference(product.MeanTimesPrecision, pProductABM);
            // ABM is now free
            var pProductV     = product.Precision * v;
            var pProductVdiff = ABM;

            pProductVdiff.SetToProduct(pProductV, diff);
            var Vdiff = v * diff;

            pProductV.Scale(-1);
            pProductV.SetToSumWithOuter(pProductV, 1, pProductVdiff, Vdiff);
            Matrix dlogZ = pProductA;

            dlogZ.SetToProduct(pProductV, pProductABV);
            dlogZ.SetToSumWithOuter(dlogZ, 1, pProductVdiff, BMean);
            int rows = A.GetLength(0);
            int cols = A.GetLength(1);

            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < cols; j++)
                {
                    double dlogp = dlogZ[i, j];
                    // for now, we don't compute the second derivative.
                    double ddlogp = -1;
                    result[i, j] = Gaussian.FromDerivatives(A[i, j].Point, dlogp, ddlogp, false);
                }
            }
            return(result);
        }
예제 #10
0
        public static Gaussian DAverageConditional([SkipIfUniform] Gamma exp, [Proper] Gaussian d)
        {
            // as a function of d, the factor is Ga(exp(d); shape, rate) = exp(d*(shape-1) -rate*exp(d))
            if (exp.IsUniform())
            {
                return(Gaussian.Uniform());
            }
            if (exp.IsPointMass)
            {
                return(ExpOp.DAverageConditional(exp.Point));
            }
            if (exp.Rate < 0)
            {
                throw new ImproperMessageException(exp);
            }
            if (exp.Rate == 0)
            {
                return(Gaussian.FromNatural(exp.Shape - 1, 0));
            }
            if (d.IsUniform())
            {
                if (exp.Shape <= 1)
                {
                    throw new ArgumentException("The posterior has infinite variance due to input of Exp distributed as " + d + " and output of Exp distributed as " + exp +
                                                " (shape <= 1)");
                }
                // posterior for d is a shifted log-Gamma distribution:
                // exp((a-1)*d - b*exp(d)) =propto exp(a*(d+log(b)) - exp(d+log(b)))
                // we find the Gaussian with same moments.
                // u = d+log(b)
                // E[u] = digamma(a-1)
                // E[d] = E[u]-log(b) = digamma(a-1)-log(b)
                // var(d) = var(u) = trigamma(a-1)
                double lnRate = Math.Log(exp.Rate);
                return(new Gaussian(MMath.Digamma(exp.Shape - 1) - lnRate, MMath.Trigamma(exp.Shape - 1)));
            }
            double aMinus1 = exp.Shape - 1;
            double b       = exp.Rate;

            if (d.IsPointMass)
            {
                double x      = d.Point;
                double expx   = Math.Exp(x);
                double dlogf  = aMinus1 - b * expx;
                double ddlogf = -b * expx;
                return(Gaussian.FromDerivatives(x, dlogf, ddlogf, true));
            }
            double dmode, dmin, dmax;

            GetIntegrationBounds(exp, d, out dmode, out dmin, out dmax);
            double expmode = Math.Exp(dmode);
            int    n       = QuadratureNodeCount;
            double inc     = (dmax - dmin) / (n - 1);
            MeanVarianceAccumulator mva = new MeanVarianceAccumulator();

            for (int i = 0; i < n; i++)
            {
                double x          = dmin + i * inc;
                double xMinusMode = x - dmode;
                double diff       = aMinus1 * xMinusMode - b * (Math.Exp(x) - expmode)
                                    - 0.5 * ((x * x - dmode * dmode) * d.Precision - 2 * xMinusMode * d.MeanTimesPrecision);
                double p = Math.Exp(diff);
                mva.Add(x, p);
                if (double.IsNaN(mva.Variance))
                {
                    throw new Exception();
                }
            }
            double   dMean     = mva.Mean;
            double   dVariance = mva.Variance;
            Gaussian result    = Gaussian.FromMeanAndVariance(dMean, dVariance);

            result.SetToRatio(result, d, true);
            return(result);
        }