/// <summary>
        /// Adds a weighted observation
        /// </summary>
        /// <param name="x"></param>
        /// <param name="weight"></param>
        public void Add(Matrix x, double weight)
        {
            // new_mean = mean + w/(count + w)*(x - mean)
            // new_var = count/(count + w)*(var + w/(count+w)*(x-mean)*(x-mean)')
            Count += weight;
            if (Count == 0)
            {
                return;
            }
            diff.SetToDifference(x, Mean);
            double s = weight / Count;

            Mean.SetToSum(1, Mean, s, diff);
            diff.SetToElementwiseProduct(diff, diff);
            Variance.SetToSum(1 - s, Variance, s * (1 - s), diff);
        }
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));
        }
        /// <summary>
        /// Adds a noisy observation.
        /// </summary>
        /// <param name="x"></param>
        /// <param name="noiseVariance"></param>
        /// <param name="weight"></param>
        public void Add(Vector x, PositiveDefiniteMatrix noiseVariance, double weight)
        {
            // new_cov = count/(count + w)*(cov + w/(count+w)*(x-mean)*(x-mean)') + w/(count+w)*noiseVariance
            Add(x, weight);
            if (count == 0)
            {
                return;
            }
            double s = weight / count;

            cov.SetToSum(1, cov, s, noiseVariance);
        }
Beispiel #4
0
        public static double LogAverageFactor([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
            return(VectorGaussian.GetLogProb(productMean, aMean * bPoint, variance));
        }
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="SumVectorGaussianOp"]/message_doc[@name="ArrayAverageConditional{TVectorGaussianList}(VectorGaussian, VectorGaussian, IList{VectorGaussian}, TVectorGaussianList)"]/*'/>
        public static TVectorGaussianList ArrayAverageConditional <TVectorGaussianList>(
            [SkipIfUniform] VectorGaussian sum,
            [Fresh] VectorGaussian to_sum,
            IList <VectorGaussian> array,
            TVectorGaussianList result)
            where TVectorGaussianList : IList <VectorGaussian>, SettableToUniform
        {
            // Check inputs for consistency
            int dimension = CheckArgumentConsistency(sum, to_sum, array, result);

            if (array.Count == 0)
            {
                return(result);
            }

            // It is tempting to put SkipIfAllUniform on array but this isn't correct if the array has one element
            if (array.Count == 1)
            {
                result[0].SetTo(sum);
                return(result);
            }

            if (!sum.IsProper())
            {
                foreach (VectorGaussian element in result)
                {
                    element.SetTo(sum);
                }

                return(result);
            }

            var elementMean     = Vector.Zero(dimension);
            var elementVariance = PositiveDefiniteMatrix.Identity(dimension);

            // Check if an element of the array is uniform
            int indexOfUniform = -1;

            for (int i = 0; i < array.Count; i++)
            {
                array[i].GetMeanAndVariance(elementMean, elementVariance);

                // Instead of testing IsUniform, we need to test the more strict requirement that all diagonal
                // elements of variance are infinite due to the way we are doing the computations
                if (IsUniform(elementVariance))
                {
                    if (indexOfUniform >= 0)
                    {
                        // More than one element of array is uniform
                        result.SetToUniform();
                        return(result);
                    }

                    indexOfUniform = i;
                }
            }

            Vector sumMean = Vector.Zero(dimension);
            PositiveDefiniteMatrix sumVariance = PositiveDefiniteMatrix.Identity(dimension);

            sum.GetMeanAndVariance(sumMean, sumVariance);

            Vector totalMean = Vector.Zero(sum.Dimension);
            PositiveDefiniteMatrix totalVariance = PositiveDefiniteMatrix.IdentityScaledBy(sum.Dimension, 0.0);

            if (indexOfUniform >= 0)
            {
                // Exactly one element of array is uniform
                for (int i = 0; i < array.Count; i++)
                {
                    if (i == indexOfUniform)
                    {
                        continue;
                    }

                    array[i].GetMeanAndVariance(elementMean, elementVariance);
                    totalMean.SetToSum(totalMean, elementMean);
                    totalVariance.SetToSum(totalVariance, elementVariance);
                    result[i].SetToUniform();
                }

                // totalMean = sum_{i except indexOfUniform} array[i].GetMean()
                // totalVariance = sum_{i except indexOfUniform} array[i].GetVariance()
                totalMean.SetToDifference(sumMean, totalMean);
                totalVariance.SetToSum(sumVariance, totalVariance);
                result[indexOfUniform].SetMeanAndVariance(totalMean, totalVariance);
                return(result);
            }

            // At this point, the array has no uniform elements

            // Get the mean and variance of sum of all Gaussians
            to_sum.GetMeanAndVariance(totalMean, totalVariance);

            // Subtract it off from the mean and variance of the incoming Gaussian from Sum
            totalMean.SetToDifference(sumMean, totalMean);
            totalVariance.SetToSum(totalVariance, sumVariance);

            for (int i = 0; i < array.Count; i++)
            {
                array[i].GetMeanAndVariance(elementMean, elementVariance);
                elementMean.SetToSum(elementMean, totalMean);
                elementVariance.SetToDifference(totalVariance, elementVariance);
                result[i].SetMeanAndVariance(elementMean, elementVariance);
            }

            return(result);
        }
Beispiel #6
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);
        }