Probability Distribution Monad with Round Numbers
In this lesson, we will learn an example of probability distribution monads by using rounded numbers.
We'll cover the following...
In the previous lesson, we made a correct, efficient implementation of SelectMany
to bind a likelihood function and projection onto a prior, and gave a simple example.
Example with Rounded Numbers
We deliberately chose “weird” numbers for all the weights; let’s do that same example again but with more “nice round number” weights:
var prior = new List<Height>() { Tall, Medium, Short}.ToWeighted(60, 30, 10);
[...]
IDiscreteDistribution<Severity> likelihood(Height h)
{
switch(h)
{
case Tall: return severity.ToWeighted(45, 55, 0);
case Medium: return severity.ToWeighted(0, 70, 30);
default: return severity.ToWeighted(0, 0, 1);
}
}
[... projection as before ...]
Console.WriteLine(prior.SelectMany(likelihood, projection).ShowWeights());
This produces the output:
DoubleDose:270000
NormalDose:540000
HalfDose:190000
which is correct, but you’ll notice how multiplying the weights during the SelectMany
made for some unnecessarily large weights. If we then did another SelectMany
on this thing, they’d get even larger, and we’d be getting into integer overflow territory.
Integer overflow is always possible in the system we’ve developed so far in this course, and we are deliberately glossing over this serious problem. A better implementation would either use doubles for weights, which have a much larger range, or arbitrary-precision integers, or arbitrary-precision rationals. We are using integers to keep it simple, but as with many aspects of the code in this course, that would become problematic in a realistic implementation.
One thing we can do to tame this slightly is to reduce all the weights when possible, in this case, we could ...