Beispiel #1
0
        /// <summary>
        /// Returns the exact distribution over the number of balls in an urn, given observations with replacement.
        /// </summary>
        /// <param name="maxBalls"></param>
        /// <param name="numObserved">Number of observations</param>
        /// <param name="numObservedTrue">Number of observations which were "true"</param>
        /// <param name="noise">Probability of the observation being flipped</param>
        /// <returns>The exact distribution over the number of balls (0,...,maxBalls)</returns>
        public Discrete BallCountingExact(int maxBalls, int numObserved, int numObservedTrue, double noise)
        {
            int numObservedFalse = numObserved - numObservedTrue;

            double[] probSize = new double[maxBalls + 1];
            for (int size = 0; size <= maxBalls; size++)
            {
                double prob = 0.0;
                for (int numTrue = 0; numTrue <= size; numTrue++)
                {
                    if (size == 0)
                    {
                        continue;
                    }
                    // numTrue ~ Binomial(size, 0.5)
                    double weight   = MMath.ChooseLn(size, numTrue) + size * System.Math.Log(0.5);
                    int    numFalse = size - numTrue;
                    double probTrue = (double)numTrue / size;
                    probTrue = (1 - noise) * probTrue + noise * (1 - probTrue);
                    if ((numObservedTrue > 0 && probTrue == 0.0) || (numObservedFalse > 0 && probTrue == 1.0))
                    {
                        continue;
                    }
                    // numObservedTrue ~ Binomial(numObserved, probTrue)
                    prob += System.Math.Exp(weight //+ MMath.ChooseLn(numObserved, numObservedTrue)
                                            + numObservedTrue * (numObservedTrue == 0 ? 0.0 : System.Math.Log(probTrue))
                                            + numObservedFalse * (numObservedFalse == 0 ? 0.0 : System.Math.Log(1 - probTrue)));
                }
                probSize[size] = prob;
            }
            return(new Discrete(probSize));
        }
        /// <summary>
        /// Evidence message for VMP
        /// </summary>
        /// <param name="sample">Constant value for 'sample'.</param>
        /// <param name="p">Incoming message from 'p'.</param>
        /// <param name="trialCount">Constant value for 'trialCount'.</param>
        /// <returns>Average of the factor's log-value across the given argument distributions</returns>
        /// <remarks><para>
        /// The formula for the result is <c>sum_(p) p(p) log(factor(sample,trialCount,p))</c>.
        /// Adding up these values across all factors and variables gives the log-evidence estimate for VMP.
        /// </para></remarks>
        public static double AverageLogFactor(int sample, Beta p, int trialCount)
        {
            double eLogP, eLogOneMinusP;

            p.GetMeanLogs(out eLogP, out eLogOneMinusP);
            return(MMath.ChooseLn(trialCount, sample) + sample * eLogP + (trialCount - sample) * eLogOneMinusP);
        }
        /// <summary>
        /// EP message to 'sample'
        /// </summary>
        /// <param name="p">Incoming message from 'p'.</param>
        /// <param name="trialCount">Incoming message from 'trialCount'.</param>
        /// <param name="result">Modified to contain the outgoing message</param>
        /// <returns><paramref name="result"/></returns>
        /// <remarks><para>
        /// The outgoing message is a distribution matching the moments of 'sample' as the random arguments are varied.
        /// The formula is <c>proj[p(sample) sum_(p,trialCount) p(p,trialCount) factor(sample,trialCount,p)]/p(sample)</c>.
        /// </para></remarks>
        public static Discrete SampleAverageConditional(Beta p, Discrete trialCount, Discrete result)
        {
            if (p.IsPointMass)
            {
                return(SampleAverageConditional(p.Point, trialCount, result));
            }
            if (trialCount.IsPointMass)
            {
                return(SampleAverageConditional(p, trialCount.Point, result));
            }
            // result must range from 0 to nMax
            if (result.Dimension < trialCount.Dimension)
            {
                throw new ArgumentException("result.Dimension (" + result.Dimension + ") < n.Dimension (" + trialCount.Dimension + ")");
            }
            Vector probs = result.GetWorkspace();
            double a     = p.TrueCount;
            double b     = p.FalseCount;

            // p(sample=k) = sum_(n>=k) p(n) nchoosek(n,k) p^k (1-p)^(n-k)
            //             = (p/(1-p))^k 1/k! sum_(n>=k) p(n) n!/(n-k)! (1-p)^n
            for (int k = 0; k < result.Dimension; k++)
            {
                double s = 0.0;
                for (int n = k; n < trialCount.Dimension; n++)
                {
                    s += trialCount[n] * Math.Exp(MMath.ChooseLn(n, k) + MMath.GammaLn(b + n - k) - MMath.GammaLn(a + b + n));
                }
                probs[k] = Math.Exp(MMath.GammaLn(a + k)) * s;
            }
            result.SetProbs(probs);
            return(result);
        }
        /// <summary>
        /// EP message to 'trialCount'
        /// </summary>
        /// <param name="sample">Incoming message from 'sample'.</param>
        /// <param name="p">Incoming message from 'p'.</param>
        /// <param name="result">Modified to contain the outgoing message</param>
        /// <returns><paramref name="result"/></returns>
        /// <remarks><para>
        /// The outgoing message is a distribution matching the moments of 'trialCount' as the random arguments are varied.
        /// The formula is <c>proj[p(trialCount) sum_(sample,p) p(sample,p) factor(sample,trialCount,p)]/p(trialCount)</c>.
        /// </para></remarks>
        public static Discrete TrialCountAverageConditional(Discrete sample, Beta p, Discrete result)
        {
            if (p.IsPointMass)
            {
                return(TrialCountAverageConditional(sample, p.Point, result));
            }
            if (sample.IsPointMass)
            {
                return(TrialCountAverageConditional(sample.Point, p, result));
            }
            // n must range from 0 to sampleMax
            if (result.Dimension < sample.Dimension)
            {
                throw new ArgumentException("result.Dimension (" + result.Dimension + ") < sample.Dimension (" + sample.Dimension + ")");
            }
            Vector probs = result.GetWorkspace();
            double a     = p.TrueCount;
            double b     = p.FalseCount;

            // p(n) = sum_(k<=n) p(k) nchoosek(n,k) p^k (1-p)^(n-k)
            for (int n = 0; n < result.Dimension; n++)
            {
                double s = 0.0;
                for (int k = 0; k <= n; k++)
                {
                    s += sample[k] * Math.Exp(MMath.ChooseLn(n, k) + MMath.GammaLn(a + k) + MMath.GammaLn(b + n - k));
                }
                probs[n] = Math.Exp(-MMath.GammaLn(a + b + n)) * s;
            }
            result.SetProbs(probs);
            return(result);
        }
        /// <summary>
        /// EP message to 'trialCount'
        /// </summary>
        /// <param name="sample">Incoming message from 'sample'.</param>
        /// <param name="p">Constant value for 'p'.</param>
        /// <param name="result">Modified to contain the outgoing message</param>
        /// <returns><paramref name="result"/></returns>
        /// <remarks><para>
        /// The outgoing message is a distribution matching the moments of 'trialCount' as the random arguments are varied.
        /// The formula is <c>proj[p(trialCount) sum_(sample) p(sample) factor(sample,trialCount,p)]/p(trialCount)</c>.
        /// </para></remarks>
        public static Discrete TrialCountAverageConditional(Discrete sample, double p, Discrete result)
        {
            if (sample.IsPointMass)
            {
                return(TrialCountAverageConditional(sample.Point, p, result));
            }
            // n must range from 0 to sampleMax
            if (result.Dimension < sample.Dimension)
            {
                throw new ArgumentException("result.Dimension (" + result.Dimension + ") < sample.Dimension (" + sample.Dimension + ")");
            }
            Vector probs      = result.GetWorkspace();
            double logp       = Math.Log(p);
            double log1minusp = Math.Log(1 - p);

            // p(n) = sum_(k<=n) p(k) nchoosek(n,k) p^k (1-p)^(n-k)
            for (int n = 0; n < result.Dimension; n++)
            {
                double s = 0.0;
                for (int k = 0; k <= n; k++)
                {
                    s += sample[k] * Math.Exp(MMath.ChooseLn(n, k) + k * (logp - log1minusp));
                }
                probs[n] = Math.Exp(n * log1minusp) * s;
            }
            result.SetProbs(probs);
            return(result);
        }
        /// <summary>
        /// EP message to 'sample'
        /// </summary>
        /// <param name="p">Constant value for 'p'.</param>
        /// <param name="trialCount">Incoming message from 'trialCount'.</param>
        /// <param name="result">Modified to contain the outgoing message</param>
        /// <returns><paramref name="result"/></returns>
        /// <remarks><para>
        /// The outgoing message is a distribution matching the moments of 'sample' as the random arguments are varied.
        /// The formula is <c>proj[p(sample) sum_(trialCount) p(trialCount) factor(sample,trialCount,p)]/p(sample)</c>.
        /// </para></remarks>
        public static Discrete SampleAverageConditional(double p, Discrete trialCount, Discrete result)
        {
            if (trialCount.IsPointMass)
            {
                return(SampleAverageConditional(p, trialCount.Point, result));
            }
            // result must range from 0 to nMax
            if (result.Dimension < trialCount.Dimension)
            {
                throw new ArgumentException("result.Dimension (" + result.Dimension + ") < n.Dimension (" + trialCount.Dimension + ")");
            }
            Vector probs      = result.GetWorkspace();
            double logp       = Math.Log(p);
            double log1minusp = Math.Log(1 - p);

            // p(sample=k) = sum_(n>=k) p(n) nchoosek(n,k) p^k (1-p)^(n-k)
            //             = (p/(1-p))^k 1/k! sum_(n>=k) p(n) n!/(n-k)! (1-p)^n
            for (int k = 0; k < result.Dimension; k++)
            {
                double s = 0.0;
                for (int n = k; n < trialCount.Dimension; n++)
                {
                    s += trialCount[n] * Math.Exp(MMath.ChooseLn(n, k) + n * log1minusp);
                }
                probs[k] = Math.Exp(k * (logp - log1minusp)) * s;
            }
            result.SetProbs(probs);
            return(result);
        }
Beispiel #7
0
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="BinomialOp"]/message_doc[@name="TrialCountAverageLogarithm(int, Beta, Discrete)"]/*'/>
        public static Discrete TrialCountAverageLogarithm(int sample, Beta p, Discrete result)
        {
            if (p.IsPointMass)
            {
                return(TrialCountAverageConditional(sample, p.Point, result));
            }
            Vector probs = result.GetWorkspace();
            double eLogP, eLogOneMinusP;

            p.GetMeanLogs(out eLogP, out eLogOneMinusP);
            // p(n) = nchoosek(n,k) p^k (1-p)^(n-k)
            for (int n = 0; n < result.Dimension; n++)
            {
                if (n < sample)
                {
                    probs[n] = double.NegativeInfinity;
                }
                else
                {
                    probs[n] = MMath.ChooseLn(n, sample) + sample * eLogP + (n - sample) * eLogOneMinusP;
                }
            }
            double max = probs.Max();

            probs.SetToFunction(probs, logp => Math.Exp(logp - max));
            result.SetProbs(probs);
            return(result);
        }
Beispiel #8
0
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="BinomialOp"]/message_doc[@name="TrialCountAverageConditional(int, Beta, Discrete)"]/*'/>
        public static Discrete TrialCountAverageConditional(int sample, Beta p, Discrete result)
        {
            if (p.IsPointMass)
            {
                return(TrialCountAverageConditional(sample, p.Point, result));
            }
            Vector probs = result.GetWorkspace();
            double a     = p.TrueCount;
            double b     = p.FalseCount;

            // p(n) = nchoosek(n,k) p^k (1-p)^(n-k)
            for (int n = 0; n < result.Dimension; n++)
            {
                if (n < sample)
                {
                    probs[n] = double.NegativeInfinity;
                }
                else
                {
                    probs[n] = MMath.ChooseLn(n, sample) + MMath.GammaLn(b + n - sample) - MMath.GammaLn(a + b + n);
                }
            }
            double max = probs.Max();

            probs.SetToFunction(probs, logp => Math.Exp(logp - max));
            result.SetProbs(probs);
            return(result);
        }
        /// <summary>
        /// Evidence message for EP
        /// </summary>
        /// <param name="sample">Constant value for 'sample'.</param>
        /// <param name="p">Incoming message from 'p'.</param>
        /// <param name="trialCount">Constant value for 'trialCount'.</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(sum_(p) p(p) factor(sample,trialCount,p))</c>.
        /// </para></remarks>
        public static double LogAverageFactor(int sample, Beta p, int trialCount)
        {
            double a = p.TrueCount;
            double b = p.FalseCount;

            return(MMath.ChooseLn(trialCount, sample) +
                   MMath.GammaLn(a + sample) - MMath.GammaLn(a) +
                   MMath.GammaLn(b + trialCount - sample) - MMath.GammaLn(b) +
                   MMath.GammaLn(a + b) - MMath.GammaLn(a + b + trialCount));
        }
        /// <summary>
        /// EP message to 'trialCount'
        /// </summary>
        /// <param name="sample">Constant value for 'sample'.</param>
        /// <param name="p">Constant value for 'p'.</param>
        /// <param name="result">Modified to contain the outgoing message</param>
        /// <returns><paramref name="result"/></returns>
        /// <remarks><para>
        /// The outgoing message is the factor viewed as a function of 'trialCount' conditioned on the given values.
        /// </para></remarks>
        public static Discrete TrialCountAverageConditional(int sample, double p, Discrete result)
        {
            Vector probs      = result.GetWorkspace();
            double logp       = Math.Log(p);
            double log1minusp = Math.Log(1 - p);

            // p(n) = nchoosek(n,k) p^k (1-p)^(n-k)
            for (int n = 0; n < result.Dimension; n++)
            {
                probs[n] = Math.Exp(MMath.ChooseLn(n, sample) + sample * logp + (n - sample) * log1minusp);
            }
            result.SetProbs(probs);
            return(result);
        }
        /// <summary>
        /// EP message to 'trialCount'
        /// </summary>
        /// <param name="sample">Constant value for 'sample'.</param>
        /// <param name="p">Incoming message from 'p'.</param>
        /// <param name="result">Modified to contain the outgoing message</param>
        /// <returns><paramref name="result"/></returns>
        /// <remarks><para>
        /// The outgoing message is a distribution matching the moments of 'trialCount' as the random arguments are varied.
        /// The formula is <c>proj[p(trialCount) sum_(p) p(p) factor(sample,trialCount,p)]/p(trialCount)</c>.
        /// </para></remarks>
        public static Discrete TrialCountAverageConditional(int sample, Beta p, Discrete result)
        {
            if (p.IsPointMass)
            {
                return(TrialCountAverageConditional(sample, p.Point, result));
            }
            Vector probs = result.GetWorkspace();
            double a     = p.TrueCount;
            double b     = p.FalseCount;

            // p(n) = nchoosek(n,k) p^k (1-p)^(n-k)
            for (int n = 0; n < result.Dimension; n++)
            {
                probs[n] = Math.Exp(MMath.ChooseLn(n, sample) + MMath.GammaLn(b + n - sample) - MMath.GammaLn(a + b + n));
            }
            result.SetProbs(probs);
            return(result);
        }
        /// <summary>
        /// EP message to 'sample'
        /// </summary>
        /// <param name="p">Constant value for 'p'.</param>
        /// <param name="trialCount">Constant value for 'trialCount'.</param>
        /// <param name="result">Modified to contain the outgoing message</param>
        /// <returns><paramref name="result"/></returns>
        /// <remarks><para>
        /// The outgoing message is the factor viewed as a function of 'sample' conditioned on the given values.
        /// </para></remarks>
        public static Discrete SampleAverageConditional(double p, int trialCount, Discrete result)
        {
            // result must range from 0 to n
            if (result.Dimension < trialCount + 1)
            {
                throw new ArgumentException("result.Dimension (" + result.Dimension + ") < n+1 (" + trialCount + "+1)");
            }
            Vector probs      = result.GetWorkspace();
            double logp       = Math.Log(p);
            double log1minusp = Math.Log(1 - p);

            probs.SetAllElementsTo(0.0);
            for (int k = 0; k <= trialCount; k++)
            {
                probs[k] = Math.Exp(MMath.ChooseLn(trialCount, k) + k * logp + (trialCount - k) * log1minusp);
            }
            result.SetProbs(probs);
            return(result);
        }
Beispiel #13
0
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="BinomialOp"]/message_doc[@name="TrialCountAverageConditional(int, double, Discrete)"]/*'/>
        public static Discrete TrialCountAverageConditional(int sample, double p, Discrete result)
        {
            Vector probs      = result.GetWorkspace();
            double logp       = Math.Log(p);
            double log1minusp = Math.Log(1 - p);

            // p(n) = nchoosek(n,k) p^k (1-p)^(n-k)
            for (int n = 0; n < result.Dimension; n++)
            {
                if (n < sample)
                {
                    probs[n] = double.NegativeInfinity;
                }
                else
                {
                    probs[n] = MMath.ChooseLn(n, sample) + sample * logp + (n - sample) * log1minusp;
                }
            }
            double max = probs.Max();

            probs.SetToFunction(probs, logprob => Math.Exp(logprob - max));
            result.SetProbs(probs);
            return(result);
        }
 /// <summary>
 /// Evidence message for EP
 /// </summary>
 /// <param name="sample">Constant value for 'sample'.</param>
 /// <param name="p">Constant value for 'p'.</param>
 /// <param name="trialCount">Constant value for 'trialCount'.</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,trialCount,p))</c>.
 /// </para></remarks>
 public static double LogAverageFactor(int sample, double p, int trialCount)
 {
     return(MMath.ChooseLn(trialCount, sample) + sample * Math.Log(p) + (trialCount - sample) * Math.Log(1 - p));
 }