/// <summary>EP message to <c>mean</c>.</summary> /// <param name="sample">Incoming message from <c>sample</c>. Must be a proper distribution. If uniform, the result will be uniform.</param> /// <param name="mean">Incoming message from <c>mean</c>. Must be a proper distribution. If uniform, the result will be uniform.</param> /// <returns>The outgoing EP message to the <c>mean</c> argument.</returns> /// <remarks> /// <para>The outgoing message is a distribution matching the moments of <c>mean</c> as the random arguments are varied. The formula is <c>proj[p(mean) sum_(sample) p(sample) factor(sample,mean)]/p(mean)</c>.</para> /// </remarks> /// <exception cref="ImproperMessageException"> /// <paramref name="sample" /> is not a proper distribution.</exception> /// <exception cref="ImproperMessageException"> /// <paramref name="mean" /> is not a proper distribution.</exception> public static Gamma MeanAverageConditional([SkipIfUniform] Poisson sample, [Proper] Gamma mean) { if (sample.IsUniform()) { return(Gamma.Uniform()); } if (sample.IsPointMass) { return(MeanAverageConditional(sample.Point)); } if (sample.Precision != 0) { throw new NotImplementedException("sample.Precision != 0 is not implemented"); } // Z = int_m sum_x r^x m^x exp(-m)/x! q(m) // = int_m exp(rm -m) q(m) // = (1 + (1-r)/b)^(-a) // logZ = -a log(1 + (1-r)/b) // alpha = -b dlogZ/db // = -a(1-r)/(b + (1-r)) // beta = -b dalpha/db // = -ba(1-r)/(b + (1-r))^2 double omr = 1 - sample.Rate; double denom = 1 / (mean.Rate + omr); double alpha = -mean.Shape * omr * denom; double beta = mean.Rate * alpha * denom; return(GaussianOp.GammaFromAlphaBeta(mean, alpha, beta, ForceProper)); }
public static GammaPower GammaPowerFromDerivLogZ(GammaPower a, double dlogZ, double ddlogZ) { bool method1 = false; if (method1) { GetPosteriorMeanAndVariance(Gamma.FromShapeAndRate(a.Shape, a.Rate), dlogZ, ddlogZ, out double iaMean, out double iaVariance); Gamma ia = Gamma.FromMeanAndVariance(iaMean, iaVariance); return(GammaPower.FromShapeAndRate(ia.Shape, ia.Rate, a.Power) / a); } else { double alpha = -a.Rate * dlogZ; // dalpha/dr = -dlogZ - r*ddlogZ // beta = -r * dalpha/dr double beta = a.Rate * dlogZ + a.Rate * a.Rate * ddlogZ; Gamma prior = Gamma.FromShapeAndRate(a.Shape, a.Rate); // ia is the marginal of a^(1/a.Power) Gamma ia = GaussianOp.GammaFromAlphaBeta(prior, alpha, beta, true) * prior; return(GammaPower.FromShapeAndRate(ia.Shape, ia.Rate, a.Power) / a); } }