Week 2 – Events

Last week we talked about building sets. This week, we built events and the formalism behind them. An events is a set attached to a probability space. For example if we have three colored dice we can talk about the events that the red die will be even. We represent this as a pair of a probability space and a set (reddie, {2,4,6}).

A probability space represents the outcome of some random process like the rolling of a die. It is a name attached to a sample space like {1,2,3,4,5,6} and a way to measure the probability of events P(reddie, {2,4,6}) == 1/2

Working with events is a lot like working with sets. We can intersect them (event that red_die is even and that red die is greater than 3), measure them (P(reddie, {2,4,6})) and consider products (red_die is even and blue_die is odd). The difference is that we get to use and need to keep track of the underlying probability space. For example the event that blue_die is odd or blue_die is even is very different from blue_die is odd or red_die is even.

This week I built the formalism behind ProbabilitySpaces, ProbabilityMeasures, and Events. I implemented this for FiniteProbabilitySpaces and have examples with dice, coins, etc… working well.

# Construct a red die using the full complexity
# A dict holding probabilities
>>> pdf = dict((i,Rational(1,6)) for i in [1,2,3,4,5,6]) 
# Build a measure from this probability density function
>>> P = FiniteProbabilityMeasure(pdf) 
# The set of possible outcomes
>>> sample_space = FiniteSet(1,2,3,4,5,6) 
# Build a ProbabilitySpace
>>> red_die = ProbabilitySpace('red_die', sample_space, P) 
# Construct an event
>>> red_die_even = Event(red_die, FiniteSet(2,4,6))
# Measure the probability
>>> red_die_even.measure 

# There are some methods to construct simple spaces more quickly
>>> red_die = FiniteProbabilitySpace(pdf)
# And some common built-in examples
>>> red_die = Die(6, name='red')
>>> blue_die = Die(6, name='blue')

# Building Events is still clunky though
>>> red_even = Event(red_die, FiniteSet(2,4,6))
>>> blue_even = Event(blue_die, FiniteSet(2,4,6))

# But the mechanics work just right
>>> red_even & blue_even
{blue, red} in {2, 4, 6} x {2, 4, 6}

>>> red_odd = red_even.complement
>>> (red_odd & blue_even).measure

>>> red_odd & red_even
red in ∅

# A complex example computing the pdf of the sum of two dice
>>> d = {} # Will hold the pdf
>>> for elem in (red_die * blue_die).sample_space_event:
... val = sum(list(elem.set)[0])
... d[val] = d.get(val,0) + elem.measure
d == {2: 1/36, 3: 1/18, 4: 1/12, 5: 1/9, 6: 5/36, 7: 1/6, 8: 5/36, 9: 1/9, 10: 1/12, 11: 1/18, 12: 1/36}

The mechanics for dealing with finite discrete events is present. The last example is something that should be easily expressible with Random Variables. If you’d like to play with things then I suggest looking at the branch rv_start on my github repository

Hopes for next week:

  • Build documentation for Sets (the organization has been relatively finalized)
  • Build events on the real line
  • Build basic random variables.
Things which are currently on my mind for the future:
The syntax to build arbitrary events is somewhat cumbersome and not something I would hand to a user. My plan is for events to be generated through operations on random variables (ideally something like red_die % 2 == 0 would be an event). It is proving complex to find the right organization of operators that is both expressive for users and provides a clean infrastructure.
Random variables will be operands in functions (like sin(X), X a random variable). Unfortunately sin has no idea how it should act on a random variable. I could go through sympy and add logic to all of the fundamental functions. I’m hesitant to change core SymPy code for my not-yet-provably-useful module.
Eventually I would like to send random variables through arbitrary user-defined functions, not just symbolic SymPy functions. An interesting example is a function which writes a value to a file. This function should return a random variable (or random action if we consider side-effects) from which we could draw samples if desired. What’s the best way to organize this in Python though? I’ve been looking at Lazy Evaluation libraries.

About mrocklin

PhD student studying Computational Mathematics at the University of Chicago.
This entry was posted in Uncategorized. Bookmark the permalink.

3 Responses to Week 2 – Events

  1. asmeurer says:

    What would sin(X) do that would have to be changed in sin?

    • mrocklin says:

      When you evaluate sin(X) the result will be another random variable with a modified probability density function. The logic for this is straightforward but does need to be implemented some place. I don’t think this should be implemented in sin but sin would have to test if its argument was random and direct things to wherever this computation should take place. If you’re interested in exactly what sin would have to do I’ll direct you to the wikipedia article:

      In an ideal world the operand (in this case the random variable X) would be able to take control. This is the case for some functions like abs which just call the object’s __abs__ method. I can’t find any evidence that this is possible generally in the Python language although I’d be thrilled if I was incorrect.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s