Last time on FAIC I implemented our first discrete distribution, the “choose an integer between min and max” distribution. I thought I might knock out a couple more of the easy discrete distributions. The easiest discrete distribution of all is of course the trivial distribution:

public sealed class Singleton<T> : IDiscreteDistribution<T>

{

private readonly T t;

public static Singleton<T> Distribution(T t) =>

new Singleton<T>(t);

private Singleton(T t) => this.t = t;

public T Sample() => t;

public IEnumerable<T> Support()

{

yield return t;

}

public int Weight(T t) =>

EqualityComparer<T>.Default

.Equals(this.t, t) ? 1 : 0;

public override string ToString() =>

$”Singleton[{t}]”;

}

That is, the probability distribution where 100% of the time it returns the same value. You’ll also sometimes see distributions like this called the “Dirac delta” or the “Kronecker delta”, but we’re not doing quantum physics here, so I’m going to just call this the singleton distribution and be done with it.

**Aside:** I wish the Enumerable class had the corresponding method: take an item, return the sequence containing only that item. As we just saw, it’s easy to implement; because it is not in the framework, I’ve implemented it literally dozens of times! It is weird to me that the “extract the value of a singleton sequence” is a member of Enumerable, but the inverse operation is not.

**Aside:** This is the first distribution we’ve seen that does not necessarily have some sort of number as its output. You might be thinking that maybe our distribution type should never have been generic in the first place, if the only distributions I’m going to come up with are either numeric-valued or trivial. But worry not! In the next episodes we’ll see how we can naturally use more complex types in probability distributions.

Let’s look at another integer-valued distribution. The Bernoulli distribution considers the question “what if we flipped a possibly-unfair coin, and scored 1 for a head and 0 for a tail?” The parameter to the distribution is traditionally the probability of heads in our coin, between 0.0 and 1.0. However, as I noted last time, at least for now I’m going to try to avoid double weights. Instead, we’ll think of this distribution as “odds”. Instead of saying “0.7 chance of getting a 1”, we’ll say “we get three zeros for every seven ones”:

public sealed class Bernoulli :

IDiscreteDistribution<int>

{

public static IDiscreteDistribution<int> Distribution(

int zero, int one)

{

if (zero < 0 || one < 0 || zero == 0 && one == 0)

throw new ArgumentException();

if (zero == 0) return Singleton<int>.Distribution(1);

if (one == 0) return Singleton<int>.Distribution(0);

return new Bernoulli(zero, one);

}

public int Zero { get; }

public int One { get; }

private Bernoulli(int zero, int one)

{

this.Zero = zero;

this.One = one;

}

public int Sample() =>

(SCU.Distribution.Sample() <=

((double)Zero) / (Zero + One)) ? 0 : 1;

public IEnumerable<int> Support() =>

Enumerable.Range(0, 2);

public int Weight(int x) => x == 0 ? Zero : x == 1 ? One : 0;

public override string ToString() =>

$”Bernoulli[{this.Zero}, {this.One}]”;

}

And sure enough, if we graph it out:

Bernoulli.Distribution(1, 3).Histogram()

We get what you’d expect: three times as many heads as tails:

0|************* 1|****************************************

**Next time on FAIC:** We’ll stop making new implementations of classic probability distributions and look at how to extend the ones we’ve got.

Is there a reason why `Singleton.Weight(T)` is implemented as `Support().Contains(t)`, instead of simply `this.t == t`?

Try writing it the way you suggest and see what happens!

That said, your point is germane. I could have written EqualityComparer<T>.Default.Equals(this.t, t).

The real answer is: I copy-pasted the code from another class I had already written because I’m lazy.

about == vs EqualityComparer, I had integers in mind, even though I registered the class was generic…

Being lazy is a good reason though. 🙂

My guess: it relies on the interface more than the internals, meaning we could change the internals or the implementation Support without changing Weight

I guess it’s technically true that System.Linq.Enumerable doesn’t have a method dedicated to the singleton enumeration. But, perhaps Microsoft decided that with the Repeat() method, that sufficed, and that it would clutter the API to add another method that was basically the equivalent to Repeat(x, 1).

Of course, that doesn’t explain why Empty() wound up being included, since one could produce the same result by calling Repeat(default(X), 0). Seems like a similar enough argument would apply.

But maybe that’s just where they decided to draw the line. After all, if a method to return a 1-element sequence was justified, maybe a method to return a 2-element sequence would be too. And a 3-element? Tuples as sequences anyone? It’s a slippery slope. 🙂

My personal limit on these things is indicated by how I count: zero, one, many 🙂

I feel like this is a troll, but maybe I’ve been reading too much Pratchett.

The missing method that bugs me is IEnumerable.Concat(T). Why must I create some kind of sequence when I just want to append a single item? And also, why don’t we have “yield foreach” or “yield all”? 😛

Append() does exactly that. while Prepend() adds its it to the front of the sequence.

Append and Prepend were added in .NET 4.7.1

I’m trying to copy the code out of the blog and run it in LINQPad, and apart from all the smart quotes, etc, causing grief, I can’t get it to compile. Is there a online repo that I could pull the code from to get it all in a compilable form?

1. Convert EN DASH (U+2013) to HYPHEN-MINUS (HYPHEN-MINUS)

2. Convert LEFT DOUBLE QUOTATION MARK (U+201C) and RIGHT DOUBLE QUOTATION MARK (U+201D) to QUOTATION MARK (U+0022)

3. Convert LEFT SINGLE QUOTATION MARK (U+2018) and RIGHT SINGLE QUOTATION MARK (U+2019) to APOSTROPHE (U+0027)

4. Move using alias directives (using XXX = YYY) to ‘Additional Namespace Imports’ with the ‘using’ keyword removed (XXX = YYY)

Now it should compile with no issues

WordPress automatically converts straight quotes to smart quotes, minus to en dash, and so on. It is infuriating. Sorry about that.

I’ve put the code up on GitHub and added a link. I’ll add a new branch each episode!

Thank you.

Pingback: Dew Drop – February 15, 2019 (#2900) | Morning Dew

Pingback: Fixing Random, part 6 | Fabulous adventures in coding