...

/

Conditional Probabilistic Reasoning

Conditional Probabilistic Reasoning

In this lesson, we will learn how to express probabilities with extra conditions.

Expressing Probabilities With an Extra Condition

We’re going to spend the next lessons in this course on expressing probabilities that have some sort of extra condition associated with them.

We’ll start with a simple example: We want to roll a fair six-sided die, but discard the threes. Why? Maybe we dislike threes. Doesn’t matter; we will want to be able to create new distributions by putting conditions on other distributions, so let’s figure out how to do so.

Now, of course, we could create the desired distribution easily enough; as we know from the previous lesson, it is

WeightedInteger.Distribution(0, 1, 1, 0, 1, 1, 1)

But suppose we have a distribution already in hand which we wish to apply a condition to, post hoc. We can see how to do that easily. It’s a variation on our “projected” distribution from a while back:

public sealed class Conditioned<T> : IDiscreteDistribution<T>
{
  private readonly List<T> support;
  private readonly IDiscreteDistribution<T> underlying;
  private readonly Func<T, bool> predicate;

  public static IDiscreteDistribution<T> Distribution(IDiscreteDistribution<T> underlying, Func<T, bool> predicate)
  {
    var d = new Conditioned<T>(underlying, predicate);
    if (d.support.Count == 0)
      throw new ArgumentException();

    if (d.support.Count == 1)
      return Singleton<T>.Distribution(d.support[0]);

    return d;
  }

  private Conditioned(IDiscreteDistribution<T> underlying, Func<T, bool> predicate)
  {
    this.underlying = underlying;
    this.predicate = predicate;
    this.support = underlying.Support()
      .Where(predicate)
      .ToList();
  }

  public T Sample()
  {
    while (true) // Notice this loop
    {
      T t = this.underlying.Sample();
      if (this.predicate(t))
          return t;
    }
  }

  public IEnumerable<T> Support() => this.support.Select(x => x);

  public int Weight(T t) => predicate(t) ? underlying.Weight(t) : 0;
}

Projected Distributions

Given our discussion a few lessons back about projected distributions and the fact that creating them has the same signature as Select, we are going to make a helper method:

public static IDiscreteDistribution<T> Where<T>(
    this IDiscreteDistribution<T> d,
    Func<T, bool> predicate) =>
  Conditioned<T>.Distribution(d, predicate);

Now we can use the comprehension syntax again:

var noThrees = from roll in SDU.Distribution(1, 6)
               where roll != 3
               select roll;
Console.WriteLine(noThrees.Histogram());

And we get as expected, no threes:

1|***************************************
2|***************************************
4|***************************************
5|*
...