/// <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 'a'. /// </summary> /// <param name="and">Incoming message from 'and'. Must be a proper distribution. If uniform, the result will be uniform.</param> /// <param name="B">Incoming message from 'b'.</param> /// <returns>The outgoing EP message to the 'a' argument.</returns> /// <remarks><para> /// The outgoing message is the integral of the factor times incoming messages, over all arguments except 'a'. /// The formula is <c>int f(a,x) q(x) dx</c> where <c>x = (and,b)</c>. /// </para></remarks> /// <exception cref="ImproperMessageException"><paramref name="and"/> is not a proper distribution</exception> public static Bernoulli AAverageConditional([SkipIfUniform] Bernoulli and, Bernoulli B) { if (B.IsPointMass) { return(AAverageConditional(and, B.Point)); } return(Bernoulli.FromLogOdds(-Bernoulli.Gate(-and.LogOdds, -B.LogOdds))); }