Beispiel #1
0
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="WishartFromShapeAndRateOp_Laplace2"]/message_doc[@name="RateAverageConditional(Wishart, double, Wishart, Wishart, Wishart)"]/*'/>
        public static Wishart RateAverageConditional([SkipIfUniform] Wishart sample, double shape, Wishart rate, Wishart to_rate, Wishart result)
        {
            if (sample.IsPointMass)
            {
                return(WishartFromShapeAndRateOp.RateAverageConditional(sample.Point, shape, result));
            }
            // f(Y,R) = |Y|^(a-c) |R|^a exp(-tr(YR))
            // p(Y) = |Y|^(a_y-c) exp(-tr(YB_y)
            // p(R) = |R|^(a_r-c) exp(-tr(RB_r)
            // int_Y f(Y,R) p(Y) dY = |R|^a |R+B_y|^-(a+a_y-c)
            int     dim                    = sample.Dimension;
            double  c                      = 0.5 * (dim + 1);
            double  shape2                 = shape - c + sample.Shape;
            Wishart ratePost               = rate * to_rate;
            PositiveDefiniteMatrix r       = ratePost.GetMean();
            PositiveDefiniteMatrix rby     = r + sample.Rate;
            PositiveDefiniteMatrix invrby  = rby.Inverse();
            PositiveDefiniteMatrix rInvrby = rby;

            rInvrby.SetToProduct(r, invrby);
            double xxddlogp              = Matrix.TraceOfProduct(rInvrby, rInvrby) * shape2;
            double delta                 = -xxddlogp / dim;
            PositiveDefiniteMatrix invR  = r.Inverse();
            PositiveDefiniteMatrix dlogp = invrby;

            dlogp.Scale(-shape2);
            LowerTriangularMatrix rChol = new LowerTriangularMatrix(dim, dim);

            rChol.SetToCholesky(r);
            result.SetDerivatives(rChol, invR, dlogp, xxddlogp, GammaFromShapeAndRateOp.ForceProper, shape);
            return(result);
        }
Beispiel #2
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));
        }
Beispiel #3
0
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="WishartFromShapeAndRateOp_Laplace2"]/message_doc[@name="SampleAverageConditional(Wishart, double, Wishart, Wishart, Wishart, Wishart)"]/*'/>
        public static Wishart SampleAverageConditional([NoInit] Wishart sample, double shape, [Proper] Wishart rate, [NoInit] Wishart to_rate, [NoInit] Wishart to_sample, Wishart result)
        {
            if (sample.IsUniform())
            {
                return(SampleAverageConditional2(shape, rate, to_rate, result));
            }
            // f(Y,R) = |Y|^(a-c) |R|^a exp(-tr(YR))
            // p(Y) = |Y|^(a_y-c) exp(-tr(YB_y)
            // p(R) = |R|^(a_r-c) exp(-tr(RB_r)
            // int_R f(Y,R) p(R) dR = |Y|^(a-c) |Y+B_r|^-(a+a_r)
            int     dim        = sample.Dimension;
            double  c          = 0.5 * (dim + 1);
            double  shape2     = shape + rate.Shape;
            Wishart samplePost = sample * to_sample;

            if (!samplePost.IsProper())
            {
                return(SampleAverageConditional2(shape, rate, to_rate, result));
            }
            PositiveDefiniteMatrix y           = samplePost.GetMean();
            PositiveDefiniteMatrix yPlusBr     = y + rate.Rate;
            PositiveDefiniteMatrix invyPlusBr  = yPlusBr.Inverse();
            PositiveDefiniteMatrix yInvyPlusBr = yPlusBr;

            yInvyPlusBr.SetToProduct(y, invyPlusBr);
            double xxddlogf             = shape2 * Matrix.TraceOfProduct(yInvyPlusBr, yInvyPlusBr);
            PositiveDefiniteMatrix invY = y.Inverse();
            //double delta = -xxddlogf / dim;
            //result.Shape = delta + shape;
            //result.Rate.SetToSum(delta, invY, shape2, invyPlusBr);
            LowerTriangularMatrix yChol = new LowerTriangularMatrix(dim, dim);

            yChol.SetToCholesky(y);
            PositiveDefiniteMatrix dlogp = invyPlusBr;

            dlogp.Scale(-shape2);
            result.SetDerivatives(yChol, invY, dlogp, xxddlogf, GammaFromShapeAndRateOp.ForceProper, shape - c);
            if (result.Rate.Any(x => double.IsNaN(x)))
            {
                throw new Exception("result.Rate is nan");
            }
            return(result);
        }
Beispiel #4
0
        /// <summary>
        /// Function to recalulate KBB and InvKBB
        /// </summary>
        protected void Recalculate()
        {
            int numBas  = NumberBasisPoints;
            int numFeat = NumberFeatures;

            if (prior == null || numBas <= 0 || numFeat <= 0)
            {
                ClearCachedValues();
            }
            else
            {
                kBB    = prior.Covariance(basis);
                invKBB = kBB.Inverse();
                //invKBB = new PositiveDefiniteMatrix(NumberBasisPoints, NumberBasisPoints);
                //LowerTriangularMatrix lt = new LowerTriangularMatrix(NumberBasisPoints, NumberBasisPoints);
                //lt.SetToCholesky(kBB);
                //invKBB.SetToIdentity();
                //invKBB.PredivideBy(lt);
                //invKBB.PredivideByTranspose(lt);
            }
        }
		/// <summary>
		/// Evidence message for EP
		/// </summary>
		/// <param name="Sample">Constant value for 'sample'.</param>
		/// <param name="MeanMean">Buffer 'MeanMean'.</param>
		/// <param name="MeanVariance">Buffer 'MeanVariance'.</param>
		/// <param name="Precision">Constant value for 'precision'.</param>
		/// <returns>Logarithm of the factor's average value across the given argument distributions</returns>
		/// <remarks><para>
		/// The formula for the result is <c>log(factor(sample,mean,precision))</c>.
		/// </para></remarks>
		public static double LogAverageFactor(Vector Sample,
			[Fresh] Vector MeanMean,
			[Fresh] PositiveDefiniteMatrix MeanVariance,
			PositiveDefiniteMatrix Precision)
		{
			return VectorGaussian.GetLogProb(Sample, MeanMean, Precision.Inverse() + MeanVariance);
		}
Beispiel #6
0
		/// <summary>
		/// Function to recalulate KBB and InvKBB
		/// </summary>
		protected void Recalculate()
		{
			int numBas = NumberBasisPoints;
			int numFeat = NumberFeatures;

			if (prior == null || numBas <= 0 || numFeat <= 0) {
				ClearCachedValues();
			} else {
				kBB = prior.Covariance(basis);
				invKBB = kBB.Inverse();
				//invKBB = new PositiveDefiniteMatrix(NumberBasisPoints, NumberBasisPoints);
				//LowerTriangularMatrix lt = new LowerTriangularMatrix(NumberBasisPoints, NumberBasisPoints);
				//lt.SetToCholesky(kBB);
				//invKBB.SetToIdentity();
				//invKBB.PredivideBy(lt);
				//invKBB.PredivideByTranspose(lt);
			}
		}
Beispiel #7
0
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="ArrayFromVectorOp"]/message_doc[@name="ArrayAverageConditional{GaussianList}(IList{Gaussian}, VectorGaussianMoments, GaussianList)"]/*'/>
        /// <typeparam name="GaussianList">The type of the resulting array.</typeparam>
        public static GaussianList ArrayAverageConditional <GaussianList>(
            [NoInit] IList <Gaussian> array, [SkipIfUniform] VectorGaussianMoments 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;

            if (array.All(g => g.IsUniform()) || vector.IsUniform() || vector.IsPointMass)
            {
                for (int i = 0; i < length; i++)
                {
                    result[i] = Gaussian.FromMeanAndVariance(vector.Mean[i], vector.Variance[i, i]);
                }
            }
            else
            {
                // 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
                VectorGaussianMoments product = new VectorGaussianMoments(length);
                Vector mean = product.Mean;
                PositiveDefiniteMatrix variance = product.Variance;
                vector.GetMeanAndVariance(mean, variance);
                for (int i = 0; i < length; i++)
                {
                    double m, v;
                    array[i].GetMeanAndVariance(out m, out v);
                    variance[i, i] += v;
                    mean[i]        -= m;
                }
                double offset = 1e-10;
                for (int i = 0; i < length; i++)
                {
                    variance[i, i] += offset;
                }
                PositiveDefiniteMatrix precision = variance.Inverse();
                Vector meanTimesPrecision        = precision * mean;
                double precisionThreshold        = 1;
                if (array.Any(g => g.Precision <= precisionThreshold))
                {
                    // compute the posterior mean and variance
                    product.SetToProduct(vector, array);
                    mean     = product.Mean;
                    variance = product.Variance;
                }
                for (int i = 0; i < length; i++)
                {
                    if (array[i].Precision <= precisionThreshold)
                    {
                        result[i] = Gaussian.FromMeanAndVariance(mean[i], variance[i, i]) / array[i];
                    }
                    else
                    {
                        double alpha = meanTimesPrecision[i];
                        double beta  = precision[i, i];
                        if (double.IsNaN(alpha))
                        {
                            throw new Exception("alpha is NaN");
                        }
                        if (double.IsNaN(beta))
                        {
                            throw new Exception("beta is NaN");
                        }
                        result[i] = GaussianOp.GaussianFromAlphaBeta(array[i], alpha, beta, false);
                        if (double.IsNaN(result[i].MeanTimesPrecision))
                        {
                            throw new Exception("result is NaN");
                        }
                        if (result[i].Precision < 0)
                        {
                            throw new Exception("result is improper");
                        }
                    }
                }
            }
            return(result);
        }
Beispiel #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);
        }
Beispiel #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);
        }