/// <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);
 }
Beispiel #2
0
 /// <summary>EP message to <c>array</c>.</summary>
 /// <param name="allTrue">Incoming message from <c>allTrue</c>. Must be a proper distribution. If uniform, the result will be uniform.</param>
 /// <param name="array">Constant value for <c>array</c>.</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 <c>array</c> 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>
 /// <typeparam name="BernoulliList">The type of the resulting array.</typeparam>
 public static BernoulliList ArrayAverageConditional <BernoulliList>([SkipIfUniform] Bernoulli allTrue, IList <bool> 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
         int trueCount       = 0;
         int firstFalseIndex = -1;
         for (int i = 0; i < array.Count; i++)
         {
             if (array[i])
             {
                 trueCount++;
             }
             else if (firstFalseIndex < 0)
             {
                 firstFalseIndex = i;
             }
         }
         if (trueCount == array.Count)
         {
             for (int i = 0; i < result.Count; i++)
             {
                 result[i] = BooleanAndOp.AAverageConditional(allTrue, true);
             }
         }
         else
         {
             for (int i = 0; i < result.Count; i++)
             {
                 result[i] = BooleanAndOp.AAverageConditional(allTrue, false);
             }
             if (trueCount == result.Count - 1)
             {
                 result[firstFalseIndex] = BooleanAndOp.AAverageConditional(allTrue, true);
             }
         }
     }
     return(result);
 }