/// <summary> /// EP message to 'array'. /// </summary> /// <param name="allTrue">Incoming message from 'allTrue'. Must be a proper distribution. If uniform, the result will be uniform.</param> /// <param name="array">Incoming message from 'array'.</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 'array' as the random arguments are varied. /// The formula is <c>proj[p(array) sum_(allTrue) p(allTrue) factor(allTrue,array)]/p(array)</c>. /// </para></remarks> /// <exception cref="ImproperMessageException"><paramref name="allTrue"/> is not a proper distribution</exception> public static BernoulliList ArrayAverageConditional <BernoulliList>([SkipIfUniform] Bernoulli allTrue, IList <Bernoulli> array, BernoulliList result) where BernoulliList : IList <Bernoulli> { if (result.Count == 0) { } else if (result.Count == 1) { result[0] = allTrue; } else if (result.Count == 2) { result[0] = BooleanAndOp.AAverageConditional(allTrue, array[1]); result[1] = BooleanAndOp.BAverageConditional(allTrue, array[0]); } else // result.Count >= 3 { double notallTruePrevious = Double.NegativeInfinity; double[] notallTrueNext = new double[result.Count]; notallTrueNext[notallTrueNext.Length - 1] = Double.NegativeInfinity; for (int i = notallTrueNext.Length - 2; i >= 0; i--) { notallTrueNext[i] = Bernoulli.Or(-array[i + 1].LogOdds, notallTrueNext[i + 1]); } for (int i = 0; i < result.Count; i++) { double notallTrueExcept = Bernoulli.Or(notallTruePrevious, notallTrueNext[i]); result[i] = Bernoulli.FromLogOdds(-Bernoulli.Gate(-allTrue.LogOdds, notallTrueExcept)); notallTruePrevious = Bernoulli.Or(notallTruePrevious, -array[i].LogOdds); } } return(result); }
/// <summary> /// EP message to 'allTrue'. /// </summary> /// <param name="array">Incoming message from 'array'.</param> /// <returns>The outgoing EP message to the 'allTrue' argument.</returns> /// <remarks><para> /// The outgoing message is a distribution matching the moments of 'allTrue' as the random arguments are varied. /// The formula is <c>proj[p(allTrue) sum_(array) p(array) factor(allTrue,array)]/p(allTrue)</c>. /// </para></remarks> public static Bernoulli AllTrueAverageConditional(IList <Bernoulli> array) { double logOdds = Double.NegativeInfinity; for (int i = 0; i < array.Count; i++) { logOdds = Bernoulli.Or(logOdds, -array[i].LogOdds); } return(Bernoulli.FromLogOdds(-logOdds)); }
/// <summary> /// EP message to 'and'. /// </summary> /// <param name="A">Incoming message from 'a'.</param> /// <param name="B">Incoming message from 'b'.</param> /// <returns>The outgoing EP message to the 'and' argument.</returns> /// <remarks><para> /// The outgoing message is the integral of the factor times incoming messages, over all arguments except 'and'. /// The formula is <c>int f(and,x) q(x) dx</c> where <c>x = (a,b)</c>. /// </para></remarks> public static Bernoulli AndAverageConditional(Bernoulli A, Bernoulli B) { return(Bernoulli.FromLogOdds(-Bernoulli.Or(-A.LogOdds, -B.LogOdds))); }
/// <summary>EP message to <c>or</c>.</summary> /// <param name="A">Incoming message from <c>a</c>.</param> /// <param name="B">Incoming message from <c>b</c>.</param> /// <returns>The outgoing EP message to the <c>or</c> argument.</returns> /// <remarks> /// <para>The outgoing message is a distribution matching the moments of <c>or</c> as the random arguments are varied. The formula is <c>proj[p(or) sum_(a,b) p(a,b) factor(or,a,b)]/p(or)</c>.</para> /// </remarks> public static Bernoulli OrAverageConditional(Bernoulli A, Bernoulli B) { return(Bernoulli.FromLogOdds(Bernoulli.Or(A.LogOdds, B.LogOdds))); }