/// <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); }
/// <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); }
/// <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); }
/// <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)); }