{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# What is a distribution?\n", "\n", "An object-oriented exploration of one of the most useful concepts in statistics.\n", "\n", "Copyright 2016 Allen Downey\n", "\n", "MIT License: http://opensource.org/licenses/MIT" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from __future__ import print_function, division\n", "\n", "%matplotlib inline\n", "%precision 6\n", "\n", "import warnings\n", "warnings.filterwarnings('ignore')\n", "\n", "from thinkbayes2 import Pmf, Cdf\n", "import thinkplot\n", "\n", "import numpy as np\n", "from numpy.fft import fft, ifft" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": true }, "outputs": [], "source": [ "from inspect import getsourcelines\n", "\n", "def show_code(func):\n", " lines, _ = getsourcelines(func)\n", " for line in lines:\n", " print(line, end='')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Playing dice with the universe\n", "\n", "One of the recurring themes of my books is the use of object-oriented programming to explore mathematical ideas. Many mathematical entities are hard to define because they are so abstract. Representing them in Python puts the focus on what operations each entity supports -- that is, what the objects can *do* -- rather than on what they *are*.\n", "\n", "In this notebook, I explore the idea of a probability distribution, which is one of the most important ideas in statistics, but also one of the hardest to explain.\n", "\n", "To keep things concrete, I'll start with one of the usual examples: rolling dice. When you roll a standard six-sided die, there are six possible outcomes -- numbers 1 through 6 -- and all outcomes are equally likely.\n", "\n", "If you roll two dice and add up the total, there are 11 possible outcomes -- numbers 2 through 12 -- but they are not equally likely. The least likely outcomes, 2 and 12, only happen once in 36 tries; the most likely outcome happens 1 times in 6.\n", "\n", "And if you roll three dice and add them up, you get a different set of possible outcomes with a different set of probabilities.\n", "\n", "What I've just described are three random number generators, which are also called **random processes**. The output from a random process is a **random variable**, or more generally a set of random variables. And each random variable has **probability distribution**, which is the set of possible outcomes and the corresponding set of probabilities.\n", "\n", "There are many ways to represent a probability distribution. The most obvious is a **probability mass function**, or PMF, which is a function that maps from each possible outcome to its probability. And in Python, the most obvious way to represent a PMF is a dictionary that maps from outcomes to probabilities.\n", "\n", "`thinkbayes2` provides a class called `Pmf` that represents a probability mass function. Each `Pmf` contains a dictionary named `d` that contains the values and probabilities. To show how this class is used, I'll create a `Pmf` that represents a six-sided die:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1 1\n", "2 1\n", "3 1\n", "4 1\n", "5 1\n", "6 1\n" ] } ], "source": [ "d6 = Pmf()\n", "for x in range(1, 7):\n", " d6[x] = 1\n", "\n", "d6.Print()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Initially the \"probabilities\" are all 1, so the total probability in the `Pmf` is 6, which doesn't make a lot of sense. In a proper, meaningful, PMF, the probabilities add up to 1, which implies that one outcome, and only one outcome, will occur (for any given roll of the die).\n", "\n", "We can take this \"unnormalized\" distribution and make it a proper `Pmf` using the `Normalize` method. Here's what the method looks like:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " def Normalize(self, fraction=1):\n", " \"\"\"Normalizes this PMF so the sum of all probs is fraction.\n", "\n", " Args:\n", " fraction: what the total should be after normalization\n", "\n", " Returns: the total probability before normalizing\n", " \"\"\"\n", " if self.log:\n", " raise ValueError(\"Normalize: Pmf is under a log transform\")\n", "\n", " total = self.Total()\n", " if total == 0:\n", " raise ValueError('Normalize: total probability is zero.')\n", "\n", " factor = fraction / total\n", " for x in self.d:\n", " self.d[x] *= factor\n", "\n", " return total\n" ] } ], "source": [ "show_code(Pmf.Normalize)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`Normalize` adds up the probabilities in the PMF and divides through by the total. The result is a `Pmf` with probabilities that add to 1.\n", "\n", "Here's how it's used:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1 0.16666666666666666\n", "2 0.16666666666666666\n", "3 0.16666666666666666\n", "4 0.16666666666666666\n", "5 0.16666666666666666\n", "6 0.16666666666666666\n" ] } ], "source": [ "d6.Normalize()\n", "d6.Print()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The fundamental operation provided by a `Pmf` is a \"lookup\"; that is, we can look up an outcome and get the corresponding probability. `Pmf` provides `__getitem__`, so we can use bracket notation to look up an outcome:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "0.166667" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d6[3]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And if you look up a value that's not in the `Pmf`, the probability is 0." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "0" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d6[7]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Exerise:** Create a `Pmf` that represents a six-sided die that is red on two sides and blue on the other four." ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "blue 0.6666666666666666\n", "red 0.3333333333333333\n" ] } ], "source": [ "# Solution\n", "\n", "die = Pmf(dict(red=2, blue=4))\n", "die.Normalize()\n", "die.Print()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Is that all there is?\n", "\n", "So is a `Pmf` a distribution? No. At least in this framework, a `Pmf` is one of several representations of a distribution. Other representations include the **cumulative distribution function**, or CDF, and the **characteristic function**.\n", "\n", "These representations are equivalent in the sense that they all contain the same informaton; if I give you any one of them, you can figure out the others (and we'll see how soon).\n", "\n", "So why would we want different representations of the same information? The fundamental reason is that there are many different operations we would like to perform with distributions; that is, questions we would like to answer. Some representations are better for some operations, but none of them is the best for all operations.\n", "\n", "So what are the questions we would like a distribution to answer? They include:\n", "\n", "* What is the probability of a given outcome?\n", "* What is the mean of the outcomes, taking into account their probabilities?\n", "* What is the variance, and other moments, of the outcome?\n", "* What is the probability that the outcome exceeds (or falls below) a threshold?\n", "* What is the median of the outcomes, that is, the 50th percentile?\n", "* What are the other percentiles?\n", "* How can get generate a random sample from this distribution, with the appropriate probabilities?\n", "* If we run two random processes and choose the maximum of the outcomes (or minimum), what is the distribution of the result?\n", "* If we run two random processes and add up the results, what is the distribution of the sum?\n", "\n", "Each of these questions corresponds to a method we would like a distribution to provide. But as I said, there is no one representation that answers all of them easily and efficiently. So let's look at the different representations and see what they can do.\n", "\n", "Getting back to the `Pmf`, we've already seen how to look up the probability of a given outcome. Here's the code:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " def __getitem__(self, value):\n", " return self.d.get(value, 0)\n" ] } ], "source": [ "show_code(Pmf.__getitem__)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Python dictionaries are implemented using hash tables, so we expect `__getitem__` to be fast. In terms of algorithmic complexity, it is constant time, or $O(1)$.\n", "\n", "## Moments and expecations\n", "\n", "The `Pmf` representation is also good for computing mean, variance, and other moments. Here's the implementation of `Pmf.Mean`:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " def Mean(self):\n", " \"\"\"Computes the mean of a PMF.\n", "\n", " Returns:\n", " float mean\n", " \"\"\"\n", " return sum(p * x for x, p in self.Items())\n" ] } ], "source": [ "show_code(Pmf.Mean)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This implementation is efficient, in the sense that it is $O(n)$, and because it uses a comprehension to traverse the outcomes, the overhead is low. \n", "\n", "The implementation of `Pmf.Var` is similar:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " def Var(self, mu=None):\n", " \"\"\"Computes the variance of a PMF.\n", "\n", " mu: the point around which the variance is computed;\n", " if omitted, computes the mean\n", "\n", " returns: float variance\n", " \"\"\"\n", " if mu is None:\n", " mu = self.Mean()\n", "\n", " return sum(p * (x-mu)**2 for x, p in self.Items())\n" ] } ], "source": [ "show_code(Pmf.Var)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And here's how they are used:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(3.500000, 2.916667)" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d6.Mean(), d6.Var()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The structure of `Mean` and `Var` is the same: they traverse the outcomes and their probabilities, `x` and `p`, and add up the product of `p` and some function of `x`.\n", "\n", "We can generalize this structure to compute the **expectation** of any function of `x`, which is defined as\n", "\n", "$E[f] = \\sum_x p(x) f(x)$\n", "\n", "`Pmf` provides `Expect`, which takes a function object, `func`, and returns the expectation of `func`:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " def Expect(self, func):\n", " \"\"\"Computes the expectation of func(x).\n", "\n", " Returns:\n", " expectation\n", " \"\"\"\n", " return np.sum(p * func(x) for x, p in self.Items()) \n" ] } ], "source": [ "show_code(Pmf.Expect)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As an example, we can use `Expect` to compute the third central moment of the distribution: " ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "0.000000" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mu = d6.Mean()\n", "d6.Expect(lambda x: (x-mu)**3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Because the distribution is symmetric, the third central moment is 0." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Addition\n", "\n", "The next question we'll answer is the last one on the list: if we run two random processes and add up the results, what is the distribution of the sum? In other words, if the result of the first process is a random variable, $X$, and the result of the second is $Y$, what is the distribution of $X+Y$?\n", "\n", "The `Pmf` representation of the distribution can answer this question pretty well, but we'll see later that the characteristic function is even better.\n", "\n", "Here's the implementation:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " def AddPmf(self, other):\n", " \"\"\"Computes the Pmf of the sum of values drawn from self and other.\n", "\n", " other: another Pmf\n", "\n", " returns: new Pmf\n", " \"\"\"\n", " pmf = Pmf()\n", " for v1, p1 in self.Items():\n", " for v2, p2 in other.Items():\n", " pmf.Incr(v1 + v2, p1 * p2)\n", " return pmf\n" ] } ], "source": [ "show_code(Pmf.AddPmf)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The outer loop traverses the outcomes and probabilities of the first `Pmf`; the inner loop traverses the second `Pmf`. Each time through the loop, we compute the sum of the outcome pair, `v1` and `v2`, and the probability that the pair occurs.\n", "\n", "Note that this method implicitly assumes that the two processes are independent; that is, the outcome from one does not affect the other. That's why we can compute the probability of the pair by multiplying the probabilities of the outcomes.\n", "\n", "To demonstrate this method, we'll start with `d6` again. Here's what it looks like:" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": false }, "outputs": [ { "data": { "image/png": "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\nFCwhEBFRsP8PFY7fR/zwSqIAAAAASUVORK5CYII=\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "thinkplot.Pdf(d6)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When we use the `+` operator, Python invokes `__add__`, which invokes `AddPmf`, which returns a new `Pmf` object. Here's the `Pmf` that represents the sum of two dice:" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": false }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "twice = d6 + d6\n", "thinkplot.Pdf(twice, color='green')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And here's the `Pmf` that represents the sum of three dice." ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": false }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "thrice = twice + d6\n", "thinkplot.Pdf(d6)\n", "thinkplot.Pdf(twice, color='green')\n", "thinkplot.Pdf(thrice, color='red')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As we add up more dice, the result converges to the bell shape of the Gaussian distribution." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Exercise:** If you did the previous exercise, you have a `Pmf` that represents a die with red on 2 sides and blue on the other 4. Use the `+` operator to compute the outcomes of rolling two of these dice and the probabilities of the outcomes.\n", "\n", "Note: if you represent the outcomes as strings, `AddPmf` concatenates them instead of adding, which actually works." ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "blueblue 0.4444444444444444\n", "bluered 0.2222222222222222\n", "redblue 0.2222222222222222\n", "redred 0.1111111111111111\n" ] } ], "source": [ "# Solution\n", "\n", "dice = die + die\n", "dice.Print()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Cumulative probabilities" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The next few questions on the list are related to the median and other percentiles. They are harder to answer with the `Pmf` representation, but easier with a **cumulative distribution function** (CDF).\n", "\n", "A CDF is a map from an outcome, $x$, to its cumulative probability, which is the probability that the outcome is less than or equal to $x$. In math notation:\n", "\n", "$CDF(x) = Prob(X \\le x)$\n", "\n", "where $X$ is the outcome of a random process, and $x$ is the threshold we are interested in. For example, if $CDF$ is the cumulative distribution for the sum of three dice, the probability of getting 5 or less is $CDF(5)$, and the probability of getting 6 or more is $1 - CDF(5)$.\n", "\n", "`thinkbayes2` provides a class called Cdf that represents a cumulative distribution function. It uses a sorted list of outcomes and the corresponding list of cumulative probabilities. The `__init__` method is complicated because it accepts a lot of different parameters. The important part is the last 4 lines." ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " def __init__(self, obj=None, ps=None, label=None):\n", " \"\"\"Initializes.\n", " \n", " If ps is provided, obj must be the corresponding list of values.\n", "\n", " obj: Hist, Pmf, Cdf, Pdf, dict, pandas Series, list of pairs\n", " ps: list of cumulative probabilities\n", " label: string label\n", " \"\"\"\n", " self.label = label if label is not None else DEFAULT_LABEL\n", "\n", " if isinstance(obj, (_DictWrapper, Cdf, Pdf)):\n", " if not label:\n", " self.label = label if label is not None else obj.label\n", "\n", " if obj is None:\n", " # caller does not provide obj, make an empty Cdf\n", " self.xs = np.asarray([])\n", " self.ps = np.asarray([])\n", " if ps is not None:\n", " logging.warning(\"Cdf: can't pass ps without also passing xs.\")\n", " return\n", " else:\n", " # if the caller provides xs and ps, just store them \n", " if ps is not None:\n", " if isinstance(ps, str):\n", " logging.warning(\"Cdf: ps can't be a string\")\n", "\n", " self.xs = np.asarray(obj)\n", " self.ps = np.asarray(ps)\n", " return\n", "\n", " # caller has provided just obj, not ps\n", " if isinstance(obj, Cdf):\n", " self.xs = copy.copy(obj.xs)\n", " self.ps = copy.copy(obj.ps)\n", " return\n", "\n", " if isinstance(obj, _DictWrapper):\n", " dw = obj\n", " else:\n", " dw = Hist(obj)\n", "\n", " if len(dw) == 0:\n", " self.xs = np.asarray([])\n", " self.ps = np.asarray([])\n", " return\n", "\n", " xs, freqs = zip(*sorted(dw.Items()))\n", " self.xs = np.asarray(xs)\n", " self.ps = np.cumsum(freqs, dtype=np.float)\n", " self.ps /= self.ps[-1]\n" ] } ], "source": [ "show_code(Cdf.__init__)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`xs` is the sorted list of values, and `freqs` are their frequencies or probabilities.\n", "\n", "`ps` is the list of cumulative frequencies or probabilities, which we normalize by dividing through by the last element.\n", "\n", "Here's how we use it to create a `Cdf` object for the sum of three dice:" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3 0.00462962962963\n", "4 0.0185185185185\n", "5 0.0462962962963\n", "6 0.0925925925926\n", "7 0.162037037037\n", "8 0.259259259259\n", "9 0.375\n", "10 0.5\n", "11 0.625\n", "12 0.740740740741\n", "13 0.837962962963\n", "14 0.907407407407\n", "15 0.953703703704\n", "16 0.981481481481\n", "17 0.99537037037\n", "18 1.0\n" ] } ], "source": [ "cdf = Cdf(thrice)\n", "cdf.Print()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Because we have to sort the values, the time to compute a `Cdf` is $O(n \\log n)$.\n", "\n", "Here's what the CDF looks like:" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": false }, "outputs": [ { "data": { "image/png": "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\nAAAAAElFTkSuQmCC\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "thinkplot.Cdf(cdf);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The range of the CDF is always from 0 to 1.\n", "\n", "Now we can compute $CDF(x)$ by searching the `xs` to find the right location, or index, and then looking up the corresponding probability. Because the `xs` are sorted, we can use bisection search, which is $O(\\log n)$.\n", "\n", "`Cdf` provides `Probs`, which takes an array of values and returns the corresponding probabilities:" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " def Probs(self, xs):\n", " \"\"\"Gets probabilities for a sequence of values.\n", "\n", " xs: any sequence that can be converted to NumPy array\n", "\n", " returns: NumPy array of cumulative probabilities\n", " \"\"\"\n", " xs = np.asarray(xs)\n", " index = np.searchsorted(self.xs, xs, side='right')\n", " ps = self.ps[index-1]\n", " ps[xs < self.xs[0]] = 0\n", " return ps\n" ] } ], "source": [ "show_code(Cdf.Probs)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The details here are a little tricky because we have to deal with some \"off by one\" problems, and if any of the values are less than the smallest value in the `Cdf`, we have to handle that as a special case. But the basic idea is simple, and the implementation is efficient.\n", "\n", "Now we can look up probabilities for a sequence of values:" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ 0. , 0.5, 1. ])" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cdf.Probs((2, 10, 18))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`Cdf` also provides `__getitem__`, so we can use brackets to look up a single value:" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "0.046296" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cdf[5]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Exercise:** If you roll three dice, what is the probability of getting 15 or more?" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "0.092593" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Solution\n", "\n", "1 - cdf[14]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Reverse lookup\n", "\n", "You might wonder why I represent a `Cdf` with two lists rather than a dictionary. After all, a dictionary lookup is constant time and bisection search is logarithmic. The reason is that we often want to use a `Cdf` to do a reverse lookup; that is, given a probability, we would like to find the corresponding value. With two sorted lists, a reverse lookup has the same performance as a forward loopup, $O(\\log n)$.\n", "\n", "Here's the implementation:" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " def Values(self, ps=None):\n", " \"\"\"Returns InverseCDF(p), the value that corresponds to probability p.\n", "\n", " If ps is not provided, returns all values.\n", "\n", " Args:\n", " ps: NumPy array of numbers in the range [0, 1]\n", "\n", " Returns:\n", " NumPy array of values\n", " \"\"\"\n", " if ps is None:\n", " return self.xs\n", "\n", " ps = np.asarray(ps)\n", " if np.any(ps < 0) or np.any(ps > 1):\n", " raise ValueError('Probability p must be in range [0, 1]')\n", "\n", " index = np.searchsorted(self.ps, ps, side='left')\n", " return self.xs[index]\n" ] } ], "source": [ "show_code(Cdf.Values)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And here's an example that finds the 10th, 50th, and 90th percentiles:" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ 7, 10, 14])" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cdf.Values((0.1, 0.5, 0.9))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `Cdf` representation is also good at generating random samples, by choosing a probability uniformly from 0 to 1 and finding the corresponding value. Here's the method `Cdf` provides:" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " def Sample(self, n):\n", " \"\"\"Generates a random sample from this distribution.\n", " \n", " n: int length of the sample\n", " returns: NumPy array\n", " \"\"\"\n", " ps = np.random.random(n)\n", " return self.ValueArray(ps)\n" ] } ], "source": [ "show_code(Cdf.Sample)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The result is a NumPy array with the given `shape`. The time to generate each random choice is $O(\\log n)$\n", "\n", "Here are some examples that use it." ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([15])" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cdf.Sample(1)" ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([10, 9, 6, 13, 14, 9])" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cdf.Sample(6)" ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[10, 7],\n", " [12, 14]])" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cdf.Sample((2, 2))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Exercise:** Write a function that takes a `Cdf` object and returns the interquartile range (IQR), which is the difference between the 75th and 25th percentiles." ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "5" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Solution\n", "\n", "def iqr(cdf):\n", " values = cdf.Values((0.25, 0.75))\n", " return np.diff(values)[0]\n", "\n", "iqr(cdf)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Max and min\n", "\n", "The `Cdf` representation is particularly good for finding the distribution of a maximum. For example, in Dungeons and Dragons, players create characters with random properties like strength and intelligence. The properties are generated by rolling three dice and adding them, so the CDF for each property is the `Cdf` we used in this example. Each character has 6 properties, so we might wonder what the distribution is for the best of the six.\n", "\n", "Here's the method that computes it:" ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " def Max(self, k):\n", " \"\"\"Computes the CDF of the maximum of k selections from this dist.\n", "\n", " k: int\n", "\n", " returns: new Cdf\n", " \"\"\"\n", " cdf = self.Copy()\n", " cdf.ps **= k\n", " return cdf\n" ] } ], "source": [ "show_code(Cdf.Max)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To get the distribution of the maximum, we make a new `Cdf` with the same values as the original, and with the `ps` raised to the `k`th power. Simple, right?\n", "\n", "To see how it works, suppose you generate six properties and your best is only a 10. That's unlucky, but you might wonder how unlucky. So, what is the chance of rolling 3 dice six times, and never getting anything better than 10?\n", "\n", "Well, that means that all six values were 10 or less. The probability that each of them is 10 or less is $CDF(10)$, because that's what the CDF means. So the probability that all 6 are 10 or less is $CDF(10)^6$. \n", "\n", "Now we can generalize that by replacing $10$ with any value of $x$ and $6$ with any integer $k$. The result is $CDF(x)^k$, which is the probability that all $k$ rolls are $x$ or less, and that is the CDF of the maximum.\n", "\n", "Here's how we use `Cdf.Max`:" ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "collapsed": false }, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXcAAAEACAYAAABI5zaHAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAEKBJREFUeJzt3X+s3XV9x/HnC2nZpg5Fo8YyUFFgIwoSxpjb9CputC6z\nRv7gR6KCmQEi2rhFYS4L9w+TqcNMGCp0Q6Zmjm7U2G6xyFi5WVwA6YSCUqCOBdqCOPyxRRdLKe/9\ncQ7d3en9cW57zj3nfvp8JDc53+/5nO955d72dT73c873e1NVSJLactioA0iSBs9yl6QGWe6S1CDL\nXZIaZLlLUoMsd0lq0LzlnuT6JE8kuXeOMVcn2Z7kniSnDDaiJGmh+pm53wCcNdudSVYBx1XVa4CL\ngGsHlE2SdIDmLfeq+gbwozmGrAa+2B17J3BkkpcOJp4k6UAMYs19BbBj2vau7j5J0oj4hqokNejw\nARxjF/BL07aP7u7bTxIvZCNJB6CqspDx/c7c0/2ayUbg3QBJzgB+XFVPzBFw7L+uuOKKkWcwpzmX\nakZzDvbrnR/83EI6fZ95Z+5JvgxMAC9K8ihwBbC809O1tqq+luRtSb4L/BS48ICSSJIGZt5yr6rz\n+xhz6WDiSJIGwTdUZzAxMTHqCH0x52AthZxLISOYcxykavHe40xSi/l8krSYNmzeyrpNW9j91J6B\nHvcrV19CDekNVUnSPIZR7AfKcpekARmXYofBfM5dktRj/VUXD+xYufqSBT/GmbskNchyl6QGWe6S\n1CDLXZIaZLlLUoMsd0lqkOUuSQ2y3CWpQZa7JDXIcpekBlnuktQgy12SGmS5S1KDvCqkpEPSsP6w\nxrhw5i7pkDTMYj9i+bKhHHchLHdJh6RhFvs5q04byrEXwmUZSYe8Qf5hjXHhzF2SGmS5S1KDLHdJ\napDlLkkNstwlqUGWuyQ1yHKXpAZZ7pLUIMtdkhpkuUtSgyx3SWqQ5S5JDbLcJalBlrskNaivck+y\nMskDSR5KctkM9/9iko1J7klyX5ILBp5UktS3ecs9yWHANcBZwEnAeUlO7Bn2fuA7VXUK8GbgU0m8\nVrwkjUg/M/fTge1V9UhV7QFuBFb3jCng+d3bzwd+UFVPDy6mJGkh+in3FcCOads7u/umuwb4lSSP\nAVuBNYOJJ0k6EINaOjkLuLuq3pLkOOCfkryuqn7SO3BycnLf7YmJCSYmJgYUQZLaMDU1xdTU1EEd\nI1U194DkDGCyqlZ2ty8Hqqo+MW3MPwJ/WlX/2t3+Z+CyqtrSc6ya7/kkaTGcvebafbfH/W+oJqGq\nspDH9LMscxfw6iTHJlkOnAts7BnzCPDWboiXAscDDy8kiCRpcOZdlqmqvUkuBW6h82JwfVVtS3JR\n5+5aC3wM+Osk93Yf9pGq+uHQUkuS5tTXmntV3Qyc0LPvumm3H6ez7i5JGgOeoSpJDbLcJalBlrsk\nNchyl6QGWe6S1CAv7iVp7G3YvJV1m7aw+6k9o46yZDhzlzT2hlnsRyxfNpTjjprlLmnsDbPYz1l1\n2lCOPWouy0haUsb9OjDjwpm7JDXIcpekBlnuktQgy12SGmS5S1KDLHdJapDlLkkNstwlqUGWuyQ1\nyHKXpAZZ7pLUIMtdkhpkuUtSgyx3SWqQ5S5JDbLcJalBlrskNchyl6QGWe6S1CDLXZIaZLlLUoMs\nd0lqkOUuSQ2y3CWpQZa7JDXIcpekBvVV7klWJnkgyUNJLptlzESSu5N8O8ltg40pSVqIw+cbkOQw\n4BrgTOAx4K4kG6rqgWljjgQ+A/xOVe1K8uJhBZYkza+fmfvpwPaqeqSq9gA3Aqt7xpwPrK+qXQBV\n9eRgY0qSFqKfcl8B7Ji2vbO7b7rjgaOS3JbkriTvGlRASdLCzbsss4DjnAq8BXgucHuS26vquwM6\nviRpAfop913AMdO2j+7um24n8GRV/Qz4WZJ/AU4G9iv3ycnJfbcnJiaYmJhYWGJJatzU1BRTU1MH\ndYxU1dwDkucAD9J5Q/Vx4JvAeVW1bdqYE4G/AFYCRwB3AudU1f09x6r5nk+Sep295tp9t9dfdfEI\nk4xGEqoqC3nMvDP3qtqb5FLgFjpr9NdX1bYkF3XurrVV9UCSrwP3AnuBtb3FLklaPH2tuVfVzcAJ\nPfuu69m+ErhycNEkSQfKM1QlqUGWuyQ1yHKXpAZZ7pLUoEGdxCRJAGzYvJV1m7aw+6k9o45ySHPm\nLmmghlnsRyxfNpTjtshylzRQwyz2c1adNpRjt8hlGUlDcyieTTounLlLUoMsd0lqkOUuSQ2y3CWp\nQZa7JDXIcpekBlnuktQgy12SGmS5S1KDLHdJapDlLkkNstwlqUGWuyQ1yHKXpAZZ7pLUIMtdkhpk\nuUtSgyx3SWqQ5S5JDbLcJalBlrskNchyl6QGWe6S1CDLXZIaZLlLUoMsd0lqkOUuSQ2y3CWpQX2V\ne5KVSR5I8lCSy+YY96tJ9iR55+AiSpIWat5yT3IYcA1wFnAScF6SE2cZ93Hg64MOKUlamH5m7qcD\n26vqkaraA9wIrJ5h3AeAm4DvDzCfJOkA9FPuK4Ad07Z3dvftk+TlwDuq6nNABhdPknQgBvWG6qeB\n6WvxFrwkjdDhfYzZBRwzbfvo7r7pTgNuTBLgxcCqJHuqamPvwSYnJ/fdnpiYYGJiYoGRJaltU1NT\nTE1NHdQxUlVzD0ieAzwInAk8DnwTOK+qts0y/gbgH6rqKzPcV/M9n6Sl7ew11+67vf6qi0eYpB1J\nqKoFrYjMO3Ovqr1JLgVuobOMc31VbUtyUefuWtv7kIUEkCQNXj/LMlTVzcAJPfuum2XseweQS5J0\nEDxDVZIaZLlLUoMsd0lqkOUuSQ2y3CWpQZa7JDXIcpekBvX1OXdJbdqweSvrNm1h91N7Rh1FA+bM\nXTqEDbPYj1i+bCjHVX8sd+kQNsxiP2fVaUM5tvrjsowkwIt8tcaZuyQ1yHKXpAZZ7pLUIMtdkhpk\nuUtSgyx3SWqQ5S5JDbLcJalBlrskNchyl6QGWe6S1CDLXZIaZLlLUoMsd0lqkOUuSQ2y3CWpQZa7\nJDXIcpekBlnuktQgy12SGmS5S1KDLHdJapDlLkkNstwlqUGWuyQ1qK9yT7IyyQNJHkpy2Qz3n59k\na/frG0leO/iokqR+zVvuSQ4DrgHOAk4CzktyYs+wh4E3VtXJwMeAvxx0UElS//qZuZ8ObK+qR6pq\nD3AjsHr6gKq6o6r+q7t5B7BisDElSQvRT7mvAHZM297J3OX9+8CmgwklSTo4hw/yYEneDFwI/OZs\nYyYnJ/fdnpiYYGJiYpARJGnJm5qaYmpq6qCOkaqae0ByBjBZVSu725cDVVWf6Bn3OmA9sLKq/n2W\nY9V8zydp8Zy95tp9t9dfdfEIk2guSaiqLOQx/SzL3AW8OsmxSZYD5wIbe574GDrF/q7Zil2StHjm\nXZapqr1JLgVuofNicH1VbUtyUefuWgv8CXAU8NkkAfZU1enDDC5Jml1fa+5VdTNwQs++66bdfh/w\nvsFGkyQdKM9QlaQGWe6S1KCBfhRS0vBs2LyVdZu2sPupPaOOoiXAmbu0RAyz2I9Yvmwox9XoWO7S\nEjHMYj9n1WlDObZGx2UZaQnyhCPNx5m7JDXIcpekBlnuktQgy12SGmS5S1KDLHdJapDlLkkNstwl\nqUGWuyQ1yHKXpAZZ7pLUIMtdkhpkuUtSgyx3SWqQ5S5JDbLcJalBlrskNchyl6QGWe6S1CD/hqo0\nJBs2b2Xdpi1D+8PW0lycuUtDMqxiP2L5soEfU+2x3KUhGVaxn7PqtIEfV+1xWUZaBOuvunjUEXSI\nceYuSQ2y3CWpQZa7JDXIcpekBlnuktQgy12SGtTXRyGTrAQ+TefF4Pqq+sQMY64GVgE/BS6oqnsG\nGVQaJs8mVWvmnbknOQy4BjgLOAk4L8mJPWNWAcdV1WuAi4Brh5B10UxNTY06Ql/MOTjrNm1h58Pf\nGcqxB3lG6VL4XoI5x0E/yzKnA9ur6pGq2gPcCKzuGbMa+CJAVd0JHJnkpQNNuoiWyg/cnIOz+6k9\n/OfOhwZ+3EGfUboUvpdgznHQz7LMCmDHtO2ddAp/rjG7uvueOKh00gyGvYTi2aRqwZK+/MDZa4az\n+nP/HVu470fjv7JkzsHzolxqRapq7gHJGcBkVa3sbl8O1PQ3VZNcC9xWVeu62w8Ab6qqJ3qONfeT\nSZJmVFVZyPh+Zu53Aa9OcizwOHAucF7PmI3A+4F13ReDH/cW+4GEkyQdmHnLvar2JrkUuIX/+yjk\ntiQXde6utVX1tSRvS/JdOh+FvHC4sSVJc5l3WUaStPQsyhmqSY5OsjnJd5Lcl+SDi/G8ByLJYUm+\nlWTjqLPMJsmRSf4+ybbu9/TXRp1pJkk+lOTbSe5N8jdJlo86E0CS65M8keTeaftemOSWJA8m+XqS\nI0eZsZtpppyf7P7c70myPskvjjJjN9N+Oafd94dJnkly1Ciy9WSZMWeSD3S/p/cl+fio8k3LM9PP\n/eQktye5O8k3k8z7+drFuvzA08AfVNVJwK8D7+89EWqMrAHuH3WIeVwFfK2qfhk4Gdg24jz7SfJy\n4APAqVX1OjpLgOeONtU+N9A5KW+6y4Fbq+oEYDPwR4uean8z5bwFOKmqTgG2M745SXI08NvAI4ue\naGb75UwyAfwe8Nqqei1w5Qhy9Zrp+/lJ4Iqqej1wBfBn8x1kUcq9qr737OUIquondMpoxWI890J0\n/zG+DfirUWeZTXem9ltVdQNAVT1dVf894lizeQ7w3CSHA78APDbiPABU1TeAH/XsXg18oXv7C8A7\nFjXUDGbKWVW3VtUz3c07gKMXPViPWb6fAH8OfHiR48xqlpyXAB+vqqe7Y55c9GA9Zsn5DPDsb5Mv\noHMu0ZwW/cJhSV4BnALcudjP3Ydn/zGO8xsRrwSeTHJDd/lobZKfH3WoXlX1GPAp4FE6/xB/XFW3\njjbVnF7y7Ce8qup7wEtGnKcf7wU2jTrETJK8HdhRVfeNOss8jgfemOSOJLf1s9wxIh8CrkzyKJ1Z\n/Ly/sS1quSd5HnATsKY7gx8bSX4XeKL7G0a6X+PocOBU4DNVdSrwP3SWFMZKkhfQmQ0fC7wceF6S\n80ebakHG+QWeJH8M7KmqL486S6/uZOOjdJYP9u0eUZz5HA68sKrOAD4C/N2I88zmEjq9eQydov/8\nfA9YtHLv/mp+E/ClqtqwWM+7AL8BvD3Jw8DfAm9O8sURZ5rJTjozoi3d7ZvolP24eSvwcFX9sKr2\nAl8B3jDiTHN54tnrISV5GfD9EeeZVZIL6CwfjuuL5XHAK4CtSf6DztLRvyUZx9+GdtD5t0lV3QU8\nk+RFo400o/dU1VcBquom9r8EzH4Wc+b+eeD+qrpqEZ+zb1X10ao6pqpeReeNv81V9e5R5+rVXTrY\nkeT47q4zGc83gB8Fzkjyc0lCJ+c4vfHb+9vZRuCC7u33AOMyAfl/ObuX3/4w8Paq2j2yVPvbl7Oq\nvl1VL6uqV1XVK+lMSF5fVePwgtn7c/8q8BaA7v+pZVX1g1EE69Gbc1eSNwEkOROY/yp3VTX0Lzqz\n4r3APcDdwLeAlYvx3AeY903AxlHnmCPfyXTOHL6HzqzjyFFnmiXnFXQK/V46b1IuG3Wmbq4v03lz\ndzedF6ELgRcCtwIP0vlEygvGNOd2Op8++Vb367PjmLPn/oeBo8YxJ51lmS8B9wFb6Fw2ZRxzvqGb\n727gdjovlnMex5OYJKlB/pk9SWqQ5S5JDbLcJalBlrskNchyl6QGWe6S1CDLXZIaZLlLUoP+F/Hl\nGrF2aP3eAAAAAElFTkSuQmCC\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "best = cdf.Max(6)\n", "thinkplot.Cdf(best);" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "0.015625" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "best[10]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "So the chance of generating a character whose best property is 10 is less than 2%." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Exercise:** Write a function that takes a CDF and returns the CDF of the *minimum* of `k` values.\n", "\n", "Hint: If the minimum is less than $x$, that means all `k` values must be less than $x$." ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "collapsed": false }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Solution\n", "\n", "def Min(cdf, k):\n", " return Cdf(cdf.xs, 1 - (1-cdf.ps)**k)\n", "\n", "worst = Min(cdf, 6)\n", "thinkplot.Cdf(worst);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Characteristic function\n", "\n", "At this point we've answered all the questions on the list, but I want to come back to addition, because the algorithm we used with the `Pmf` representation is not as efficient as it could be. It enumerates all pairs of outcomes, so if there are $n$ values in each `Pmf`, the run time is $O(n^2)$. We can do better.\n", "\n", "The key is the **characteristic function**, which is the Fourier transform (FT) of the PMF. If you are familiar with the Fourier transform and the Convolution Theorem, keep reading. Otherwise, skip the rest of this cell and get to the code, which is much simpler than the explanation.\n", "\n", "### Details for people who know about convolution\n", "\n", "If you are familiar with the FT in the context of spectral analysis of signals, you might wonder why we would possibly want to compute the FT of a PMF. The reason is the Convolution Theorem.\n", "\n", "It turns out that the algorithm we used to \"add\" two `Pmf` objects is a form of convolution. To see how that works, suppose we are computing the distribution of $Z = X+Y$. To make things concrete, let's compute the probability that the sum, $Z$ is 5. To do that, we can enumerate all possible values of $X$ like this:\n", "\n", "$Prob(Z=5) = \\sum_x Prob(X=x) \\cdot Prob(Y=5-x)$\n", "\n", "Now we can write each of those probabilities in terms of the PMF of $X$, $Y$, and $Z$:\n", "\n", "$PMF_Z(5) = \\sum_x PMF_X(x) \\cdot PMF_Y(5-x)$\n", "\n", "And now we can generalize by replacing 5 with any value of $z$:\n", "\n", "$PMF_Z(z) = \\sum_x PMF_X(x) \\cdot PMF_Y(z-x)$\n", "\n", "You might recognize that computation as convolution, denoted with the operator $\\ast$. \n", "\n", "$PMF_Z = PMF_X \\ast PMF_Y$\n", "\n", "Now, according to the Convolution Theorem:\n", "\n", "$FT(PMF_X \\ast Y) = FT(PMF_X) \\cdot FT(PMF_Y)$\n", "\n", "Or, taking the inverse FT of both sides:\n", "\n", "$PMF_X \\ast PMF_Y = IFT(FT(PMF_X) \\cdot FT(PMF_Y))$\n", "\n", "In words, to compute the convolution of $PMF_X$ and $PMF_Y$, we can compute the FT of $PMF_X$ and $PMF_Y$ and multiply them together, then compute the inverse FT of the result.\n", "\n", "Let's see how that works. Here's a class that represents a characteristic function." ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "\n", "class CharFunc:\n", " \n", " def __init__(self, hs):\n", " \"\"\"Initializes the CF.\n", " \n", " hs: NumPy array of complex\n", " \"\"\"\n", " self.hs = hs\n", "\n", " def __mul__(self, other):\n", " \"\"\"Computes the elementwise product of two CFs.\"\"\"\n", " return CharFunc(self.hs * other.hs)\n", " \n", " def make_pmf(self, thresh=1e-11):\n", " \"\"\"Converts a CF to a PMF.\n", " \n", " Values with probabilities below `thresh` are dropped.\n", " \"\"\"\n", " ps = ifft(self.hs)\n", " d = dict((i, p) for i, p in enumerate(ps.real) if p > thresh)\n", " return Pmf(d)\n", " \n", " def plot_cf(self, **options):\n", " \"\"\"Plots the real and imaginary parts of the CF.\"\"\"\n", " n = len(self.hs)\n", " xs = np.arange(-n//2, n//2)\n", " hs = np.roll(self.hs, len(self.hs) // 2)\n", " plt.plot(xs, hs.real, label='real', **options)\n", " plt.plot(xs, hs.imag, label='imag', **options)\n", " plt.legend()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The attribute, `hs`, is the Fourier transform of the `Pmf`, represented as a NumPy array of complex numbers.\n", "\n", "The following function takes a dictionary that maps from outcomes to their probabilities, and computes the FT of the PDF:" ] }, { "cell_type": "code", "execution_count": 39, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def compute_fft(d, n=256):\n", " \"\"\"Computes the FFT of a PMF of integers.\n", " \n", " Values must be integers less than `n`.\n", " \"\"\"\n", " xs, freqs = zip(*d.items())\n", " ps = np.zeros(256)\n", " ps[xs,] = freqs\n", " hs = fft(ps)\n", " return hs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`fft` computes the Fast Fourier Transform (FFT), which is called \"fast\" because the run time is $O(n \\log n)$.\n", "\n", "Here's what the characteristic function looks like for the sum of three dice (plotting the real and imaginary parts of `hs`):" ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "collapsed": false }, "outputs": [ { "data": { "image/png": "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\nIqBBwN66AAAAAElFTkSuQmCC\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "hs = compute_fft(thrice.d)\n", "cf = CharFunc(hs)\n", "cf.plot_cf()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The characteristic function contains all of the information from the `Pmf`, but it is encoded in a form that is hard to interpret. However, if we are given a characteristic function, we can find the corresponding `Pmf`.\n", "\n", "`CharFunc` provides `make_pmf`, which uses the inverse FFT to get back to the `Pmf` representation. Here's the code:" ] }, { "cell_type": "code", "execution_count": 41, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " def make_pmf(self, thresh=1e-11):\n", " \"\"\"Converts a CF to a PMF.\n", " \n", " Values with probabilities below `thresh` are dropped.\n", " \"\"\"\n", " ps = ifft(self.hs)\n", " d = dict((i, p) for i, p in enumerate(ps.real) if p > thresh)\n", " return Pmf(d)\n" ] } ], "source": [ "show_code(CharFunc.make_pmf)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And here's an example:" ] }, { "cell_type": "code", "execution_count": 42, "metadata": { "collapsed": false }, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAX0AAAEACAYAAABfxaZOAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3Xl0VFW6///3k5EZQzPP8yiDQEMEJIGADDIJ2iKTfW2v\nOCHa99utv+67Wrz9vd/Vdt++jTi02rbaQRAFERERhYTIPBPAABIGQ5jnGUKG5/dHlSeVGEgCqZxK\n6nmtlbWyT51T9SEkT53aZ5+9RVUxxhgTHELcDmCMMab0WNE3xpggYkXfGGOCiBV9Y4wJIlb0jTEm\niFjRN8aYIFKkoi8ig0Vkt4jsEZEXCni8jYisEZFrIvLrAh4PEZEtIrKwJEIbY4y5NYUWfREJAV4H\nBgEdgIdFpG2+3U4DU4C/3OBppgI7byOnMcaYElCUM/0eQKqqpqlqJjAHGOm7g6qeUtXNQFb+g0Wk\nITAUeLcE8hpjjLkNRSn6DYB0n/Yh77ai+hvwG8Bu/TXGGJf59UKuiNwHHFfVZEC8X8YYY1wSVoR9\nDgONfdoNvduKojcwQkSGAhWBqiISr6qT8u8oIvZJwBhjiklVi3UyXZQz/Y1ASxFpIiIRwFjgZqNw\nnACq+jtVbayqzb3HJRZU8H32D+ivl156yfUMltNyWk7L+ePXrSj0TF9Vs0XkGeAbPG8S/1TVXSIy\n2fOwviMidYBNQFUgR0SmAu1V9dItpTLGGOMXReneQVWXAG3ybXvb5/vjQKNCnuNb4NtbyGiMMaaE\n2B25xRAbG+t2hCKxnCXLcpYsy+kuudV+oZImIhooWYwxpiwQEdQPF3KNMcaUE1b0jTEmiFjRN8aY\nIGJF3xhjgogVfWOMCSJW9I0xJohY0TfGmCBiRd8YY4KIFX1jjAkiVvSNMSaIWNE3xpggYkXfGGOC\niBV9Y4wJIlb0jTEmiFjRN8aYIGJF3xhjgkiRlks0JhhtTkkj/vN1HDlxrsSfu3mjWjz2QG9aNalT\n4s9tzM3YylnG5JNxPZP4z9exZFWKX18nRIQHB3djzMCuhIbah25TfLeycpYVfWN8HDh0iunxCRw6\nfrbUXrNNs7o8O6E/dWtWK7XXNOWDFX1jblFOTg4LErYx56uNZGfnONt7dGzKEw/FUKVSZIm91smz\nl3htViK79x9ztlWIDOexMX2I7dEakWL9DZsgZkXfmFtw8sxFZnyYyM59R51tkRHh/GpML/r3bOuX\nIpyTk8P8Zcl8/NUmcnJy32SiOzfniYf6UrVyhRJ/TVP++K3oi8hgYDqe0T7/VNVX8j3eBngf6Ar8\nTlX/17u9IRAP1AFygH+o6owbvIYVfVPqVm3ey9ufrODKtevOtpaNazN1Yn/q177D76+/N+0E02cm\ncPTkeWdbVLVKTJnQn85tGvr99U3Z5peiLyIhwB4gDjgCbATGqupun31qAk2AUcBZn6JfF6irqski\nUgXYDIz0PdbnOazom1Jz+WoG/5i7ipWbU51tAowZ1I0H7+1KWFhoqWW5lpHJBwvWsHTNrjzbh8d2\nYtywHkSE2yA7UzB/Ff1o4CVVHeJtvwho/rN972MvARd/LPoFPL4AeE1VEwp4zIq+KRUpe48w48NE\nTp295GyrXaMqUyfG0bZ5XddybdjxA29+lMTFy9ecbY3r1eC5SQNoUr+Ga7lM4LqVol+UcWINgHSf\n9iHvtmIRkaZAF2B9cY81piRkZWXz4cJ1vPTawjwFP7ZHG/762wddLfjguWj8txd/wV3tGjnbDh49\nw2//+imLkrZjJ0WmJJTK50Zv1848YKqqXrrRftOmTXO+j42NJTY21u/ZTHA4dPws0+MTOHDolLOt\ncsVInhjbl15dWriYLK+oapX4/eShLFmVwr8WrCUzK5usrGze/2wNm1MOMmVCP2pUr+x2TOOSpKQk\nkpKSbus5itq9M01VB3vbxereEZEwYBHwlaq+epPXse4dU+JUla9X7eSDBWvIzMp2tnds3YAp4/vx\nszuquJju5tKPed6ofjic+0ZVpVIkTzwUw91dmruYzAQKf/XphwLf47mQexTYADysqrsK2Pcl4JKq\n/tVnWzxwSlV/XcjrWNE3Jer8xau8MTuJzTvTnG2hoSFMGN6T4bGdysR4+KysbD5avJHPE5Lx/evo\n37MtvxrTmwqR4a5lM+7z95DNV8kdsvknEZmM54z/HRGpA2wCquIZmnkJaA90BlYAOwD1fv1OVZcU\n8BpW9E2J2ZSSxhuzk7hw6aqzrVHdKJ6bFEfTBjXdC3aLduw5zGuzEjl97rKzrW7NakydGEfrpjZ/\nT7Cym7NM0Mu4nsm/Fqzj69V55825L6YjE4b3LNPDHy9dyeCduStZvWWvsy1EhAcGdeOBe23+nmBk\nRd8EtX0HTzI9fhlH8t3o9Mz4fnRp2+gmR5YdqsrKzam8M3cVV31uKGvVpDZTJ8ZRr1Z1F9OZ0mZF\n3wStlL1HePnNRXnmzenZqRlPPNSXalUqupjMP06cuciMmYns2p87dUSlChH86T9G06AU7iQ2gcGK\nvglKl65k8OtXPnH6u/09b06gyMnJ4bOEZOYszp2/p1nDmvzp+ftL9Y5i4x5/3ZxlTMBSVd7+ZIVT\n8KtUiuR/fjOGuOh25brgA4SEhDBmYFf+OGWE059/4NAp5ize6HIyE8is6JsybcWmVNZs3ee0nxwb\nUyoTpQWSts3rMnF4tNNekJBMyt4jLiYygcyKvimzjp++wDtzVzrtuOi2RHcOzpuWhsV2pFNrz6yc\nCrw6M4FLVzLcDWUCkhV9UyZlZ+fw6sxErmVkAlCvVnUeHd3b5VTuERGmTOjnLPZy+txl3v5khc3X\nY37Cir4pkz5duoXvD3hWngoJCeG5iXFBf3dqjeqVeXJsjNNes3UfKzal3uQIE4ys6JsyZ88Px5m7\nZLPTfmhId1o2qe1iosAR3bk5cdFtnfY7c1dy/PQFFxOZQGNF35QpV69dZ3p8Ajnebot2zesxekAX\nl1MFlkdH93YWWb+WkcmrMxPz3L9ggpsVfVOm/HP+aufMtWKFCJ6d2J+QEPs19lUhMpznJw1wfi7f\nHzjGp0u3uJzKBAr7azFlxprkfSxf/73TnvzgPdSuUdXFRIGrZZPaPDSku9Oeu2Qze3447mIiEyis\n6Jsy4dTZS7w1Z4XTvqdbK+7p3srFRIFv9IAuzmpgOaq8OjMhz3w9JjhZ0TcBT1V5bVYil696xp3X\niqrKvz/Yx+VUgS8kJISpE+OoWCECgGOnLvDe/DUupzJus6JvAt7C5dv5LtVzh6kAz07sT+WKke6G\nKiNq16jK4z5vkInrd7M2eb+LiYzbrOibgHbg0ClmLVrvtEcP7Er7FvVcTFT29O3emj7dWjrtv8/5\nNs/C8Ca4WNE3ASvjeibT4xOc4YYtGtXiF4O7uZyqbHr8wXuoGeVZD/jy1Qxen73c7tYNUlb0TcCK\n/3wdh46fBSAiPIznJsXZlMG3qHLFSKZOjOPHeUd37DnMwuXbXc1k3GFF3wSkTSlpLFmVu+Thr8b0\nDrrZM0ta+xb1GD2wq9OetWg9Bw6dcjGRcYMVfRNwzl28whuzk5x2z07N8kwtYG7dLwZ3o0WjWoBn\n0rrp8QlkXM90OZUpTVb0TUBRVd6YncSFS1cBzxq3T46NKfcLopSWsLBQpk6KcxaIP3T8LPGfr3M5\nlSlNVvRNQPl61U627DzotKdM6E/VyhVcTFT+NKh9B78akzsN9ZJVKWxOSXMxkSlNVvRNwEg/dpYP\nFuTePDQsphOd2zR0MVH5FRfdlh4dmzrt12cncf7iVdfymNJTpKIvIoNFZLeI7BGRFwp4vI2IrBGR\nayLy6+IcawxAZmY20+MTyMzKBqBxvRqMH97D5VTll4jw5NgYoqpVAuDCpau8MTvJhnEGgUKLvoiE\nAK8Dg4AOwMMikv+q2mlgCvCXWzjWGD5avIEfDntGkoSFhfL8IwOcfmfjH9WqVGTKhP5Oe/PONL5e\ntdPFRKY0FOVMvweQqqppqpoJzAFG+u6gqqdUdTOQVdxjjdmx5zALE7c57Ukjomlcr4aLiYJH5zYN\nGRbTyWl/sGAN6cfOupjI+FtRin4DIN2nfci7rShu51gTBC5evsaMDxP5sVPhrnaNGNr3TlczBZvx\nw3s4b7KZWd5utsxsl1MZfwmoz8/Tpk1zvo+NjSU2Nta1LMb/VJW3Pl7BmfOXAahauQJPj+tnwzNL\nmedu5wH89q+fkpWVzQ+HT/HR4g1MGnm329FMPklJSSQlJd3WcxSl6B8GGvu0G3q3FUWxjvUt+qb8\nS9qwh3Xbcmd8fOrhWOfCoildTerXYNKIaN6bvxqAhYnbuKtdYzq2tg/mgST/yfDLL79c7OcoSvfO\nRqCliDQRkQhgLLDwJvv7nqYV91gTJI6ePM8/5q1y2gN7tcszhNCUvqF976RL20YAKDDjw0QuXr7m\nbihT4got+qqaDTwDfAOkAHNUdZeITBaRxwFEpI6IpAPPA78XkYMiUuVGx/rrH2PKhuzsHF6dmXv7\nf/1a1fnlqF4upzIiwtPjYp2b4c6cv8zbn6y0YZzljATKf6iIaKBkMf61bO0u/j7nW8CzutOfnr+f\nFo1ruZzK/GjDjh945d0lTvsPTw2zm+QClIigqsW6CGZ35JpSlZOTw2fLtjrtBwd1tYIfYHp0bEq/\nnm2c9vylW1xMY0qaFX1TqtYk7+fYqQuAZ4734bGdCjnCuOEXg7sT4h1F9V3qEVLTjrucyJQUK/qm\n1Kgq85fmnuUP6Xuns2i3CSy1a1TNs8Si7/+bKdus6JtSs3VXOmlHTgOeseH32U1YAe3+AXc532/Y\n8YPdqVtOWNE3pcb3bHFgr3ZUq1LRxTSmMI3r1eDndzZ12r7XYkzZZUXflIrd+4+xa/9RAEJDQxjR\nr7PLiUxRjB6Ye7a/cvNeTpy56GIaUxKs6JtS4XuW37d7K2pGVXExjSmq1k3r0KFlfcAz8sp3YjxT\nNlnRN36XduQ0m3d6VmYS8vYVm8Dne7a/bO0uW2yljLOib/zuU5+z/J6dmtGg9h0upjHF1blNQ5o1\nrAl4ZuH88tsdLicyt8OKvvGroyfPs2bLXqc9emBXF9OYWyEiec72v1r5HVeuXncxkbkdVvSNX32e\nmOzMld+pdUO7+7aMiu7UjPq1qgNw5dp1lqxKcTmRuVVW9I3fnDl/mcT13ztt37NFU7aEhIQwakAX\np73o2+1cz8y/UJ4pC6zoG79ZlLSd7OwcAFo1qc2dreq7nMjcjpjuralRvTIA5y9eJXHd94UcYQKR\nFX3jF5euZLDEZ5Ht+wfcZStilXFhYaF57q/4PDHZeVM3ZYcVfeMXX638zpkvv2GdKFsgpZwY2Ksd\nVSpFAnDizEVWb91byBEm0FjRNyUu43pmnmF99w/oYmf55USFyHCG9u3otOcvS7ZFVsoYK/qmxC1b\nu9tZZq9WVFX6dG1ZyBGmLBna904iI8IBSD96hk0paS4nMsVhRd+UqKysbD5PTHbaI/p3Iiws1MVE\npqRVrVyBe3u1c9rzl261s/0yxIq+KVErN+/l9LnLAFSrUpG46LYuJzL+MLxfJ0JDPeVjzw/H2bnv\nqMuJTFFZ0TclRlXzTL97X0xHpxvAlC8/u6MKsT9v7bRt2uWyw4q+KTHrtx/g8IlzgOeC35B7Oric\nyPjTqLgu/Hh5fuuudA4cOuVqHlM0VvRNifjJUoh9OlC5YqSLiYy/1a99B9FdWjjtT21JxTLBir4p\nETv2HGZf+knAcxPPfbbgeVAY4zO1xrrkfRzxftIzgatIRV9EBovIbhHZIyIv3GCfGSKSKiLJItLF\nZ/vzIvKdiGwXkVkiYithl0Pzffp043q2JapaJRfTmNLSrGFN7mrXCAAFFiQk3/wA47pCi76IhACv\nA4OADsDDItI23z5DgBaq2gqYDLzl3V4fmAJ0VdVOQBgwtkT/BcZ1e9NOsGPPYQBCRBgZZ0shBhPf\nRXGSNu7h9LlLLqYxhSnKmX4PIFVV01Q1E5gDjMy3z0ggHkBV1wPVRaSO97FQoLKIhAGVgCMlktwE\nDN+z/N5dW1LnZ9VcTGNKW/sW9WjTrC4A2dk5fLF8u8uJzM0Upeg3ANJ92oe82262z2GggaoeAf4K\nHPRuO6eqy249rgk06cfOsn77AadtSyEGn/yLrHyzZpdzR7YJPGH+fHIRuQPPp4AmwHlgnoiMU9XZ\nBe0/bdo05/vY2FhiY2P9Gc+UAN8+3O4dmtCkfg0X0xi3dGvfmMb1anDw6BkyrmeyeMV3PDSku9ux\nyp2kpCSSkpJu6zmksNunRSQamKaqg73tFwFV1Vd89nkLWK6qH3vbu4EY4B5gkKr+u3f7RKCnqj5T\nwOuo3cpdtpw8c5Gn/vgROTme6XX/33OjnI/5Jvis3JTK9JkJAFSpFMnb0yZQIdJuzvMnEUFVizWb\nYVG6dzYCLUWkiXfkzVhgYb59FgKTvCGi8XTjHMfTrRMtIhXEM81iHLCrOAFN4Fq4fJtT8H37dU1w\n6nVXC+d6zqUrGSxdY3/qgajQoq+q2cAzwDdACjBHVXeJyGQRedy7z2LggIjsBd4GnvJu3wDMA7YC\n2wAB3vHHP8SUrvMXr+b5o7YFz01oaAgj++eO3Fq4fBuZmdkuJjIFKbR7p7RY907ZMnvRBj5dugWA\npg1q8j+/GWNz5huuZ2bx5MuzOXfxCgBPPRxDXHS7Qo4yt8pf3TvG5HHl6nW+Wvmd0x490JZCNB4R\n4WEMi81dZOWzZclOF6AJDFb0TbF9vTqFK9euA1C/VnXu7tzM5UQmkAzq3YFKFTw33h89eZ612w4U\ncoQpTVb0TbFcz8xiUVLuUoijBnQhJMR+jUyuShUjGHLPnU7bFlkJLPbXaopl+frvnf7aGtUrE9O9\ndSFHmGB0X0xHwr0rpv1w+BTJuw+5nMj8yIq+KbLs7Jw8N2ON6NfZlkI0BapetSID8yypuMXFNMaX\nFX1TZGu27uPEmYuA5+Yb3z9qY/Ib0a+z0/W3c99Rvj9wzOVEBqzomyJS1TwTqw3t29HutjQ3VatG\nVfp2b+W059siKwHBir4pks07D3Lw6BkAIiPCGdr3zkKOMCbvkoqbUtJIO3LG1TzGir4pgvxLId7b\nqx1VK1dwMZEpKxrVjaJHp9whvbaAuvus6JtC+fbHhoaGMLyfLYVoim60z3Tbq7fs5fjpCy6mMVb0\nTaF8z85if96an91RxcU0pqxp2aQ2HVt7luDIUeXzhG0uJwpuVvTNTe1NO8HWXZ71cQRPH60xxeV7\ntp+wfjenztqSim6xom9uSFV5f8Eapx3dpQX1a9/hYiJTVnVs3YAWjWoBkJWVzaxF611OFLys6Jsb\nWpO8n937c/vyx933c5cTmbJKRJg0Mtppr9iUSmracRcTBS8r+qZA1zOzmPn5Oqc9pM+ddpZvbsud\nrRrQo2NTp/3+Z2ttTh4XWNE3BVqUtIOTZ3Pvvn1wcDeXE5nyYNLIuwkN9ZSd7w8cY03yfpcTBR8r\n+uYnzl284iyQAvDQkO5UqRTpYiJTXtSrVZ2hPjNwzvx8Hdczs1xMFHys6JufmLN4I9cyMgFoWCeK\ne3u1dzmRKU8eHNzNOYk4efZinqm6jf9Z0Td5pB05zTKftW8fGXW3zaRpSlTlipE8PLSH0/506RZn\num7jf1b0jUNVef+zNfx4aa1L20Z0bd/Y1UymfBrYqx0N60QBcC0jk4++3OhyouBhRd84NqWksWPP\nYQBCRHhk1N0uJzLlVWhoSJ7fr4S1u/jh8CkXEwUPK/oG8NwwE79grdMe2Ks9jevVcDGRKe+6tm/M\nXe0aAaDg+ZRpQzj9zoq+AWDJqhSOnDwPQKUKETw0pLvLiUwweGRUL0LEM/nyd6lH2PhdmsuJyr8i\nFX0RGSwiu0Vkj4i8cIN9ZohIqogki0gXn+3VRWSuiOwSkRQR6VlS4U3JuHj5Gp8s2ey0HxjUjepV\nK7qYyASLRnWjuLd37uiw+M/XkpWV7WKi8q/Qoi8iIcDrwCCgA/CwiLTNt88QoIWqtgImA2/5PPwq\nsFhV2wGdgV2YgPLJkk1cvpoBQN2a1fKMozbG3x4a0p1KFSIAOHryPF+tTHE5UflWlDP9HkCqqqap\naiYwBxiZb5+RQDyAqq4HqotIHRGpBtyjqu97H8tSVZtMO4AcOn6WJat2Ou2JI6IJD7chmqb0VKtS\nMc8d358s2cTFy9dcTFS+FaXoNwDSfdqHvNtuts9h77ZmwCkReV9EtojIOyJi/QYBJH7BOnJycgBo\n36IePX1WOTKmtAy9507q1qwGwJVr1/n4q00uJyq/wkrh+bsCT6vqJhGZDrwIvFTQztOmTXO+j42N\nJTY21s/xgtu27w+xeafnwpkAj47ujYjc/CBj/CAsLJRJI+/mz//8GoCvV6UwqE8HGtWNcjlZYElK\nSiIpKem2nkMKGyIlItHANFUd7G2/CKiqvuKzz1vAclX92NveDcR4H16rqs292/sAL6jq8AJeR224\nVunJzs7hP/4yj3TvYuf9erbhmXH9XE5lgpmq8tLrX5Cy9wjgGdL5+8lDXU4V2EQEVS3WmVpRunc2\nAi1FpImIRABjgYX59lkITPKGiAbOqepxVT0OpItIa+9+ccBOjOsS1u12Cn5kRDjj7utRyBHG+JeI\n8G/39+LHCrZl50GSd6ff9BhTfIUWfVXNBp4BvgFSgDmquktEJovI4959FgMHRGQv8DbwlM9TPAvM\nEpFkPKN3/l8J/xtMMV2+msFHi3Nvex898C5qVK/sYiJjPJo1rEm/nrmDAz/4bA3Z2TkuJip/Cu3e\nKS3WvVN6Zi5cx4KEZABqRlXhtd+PJSLc35d3jCmasxeu8PQfPyLjumem18cfvIdBfTq4nCow+at7\nx5Qjx05d4Iuk7U574vBoK/gmoERVq8TogbkLqX+0eKNzH4m5fVb0g8zMz9c6H5dbNalN764tXE5k\nzE+N6NeJmlFVAM8d4/O+3lLIEaaorOgHkZS9R1i3/YDTtiGaJlBFhIcxcXjuQupfrtjBUe/cUOb2\nWNEPEqrKBz6zaPbu2pLWTeu4mMiYm+vdtYXzO5qdncOHC9e5nKh8sKIfJJI27GF/+kkAwsNCmTjc\n5r0zge3HIZw/Wrf9gDOG39w6K/pB4FpGJrMWrXfaI/t3plaNqi4mMqZoWjetwz3dWjltm3P/9lnR\nDwKfJSRz9oJnDdKoapW4f8BdhRxhTOCYMLwn4d51mg8cOkXShj0uJyrbrOiXc6fOXuJz75h8gHH3\n9aBCZLiLiYwpnppRVRgZ5yzRwaxF67mWkeliorLNin459+EX68n0LkrRtEFN+vVs43IiY4rv/rgu\nRFWrBHhu3vps2VaXE5VdVvTLsdS046zcnOq0Hx3dy4ZomjKpQmQ444flDj74PHEbJ89cdDFR2WVF\nv5xSVd7/LHeIZnSnZnRoWd/FRMbcntgerWnWsCYAmVnZfOgzOMEUnRX9cmr11n18f+AYAKGhIUwY\nEV3IEcYENhHh0dG9nfaqzXvZ88NxFxOVTVb0y6HrmVl8uDD3LOi+vh2pV6u6i4mMKRntW9Qj2md1\nNxvCWXxW9MuhL5K2c/Ksp7+zauUKPDCoq8uJjCk5E0feTWiop3Tt+eE4q7fsczlR2WJFv5w5e+EK\nn36TO7Jh7JCfU7lipIuJjClZdWtWY1hMR6cdv3At1zOzXExUtljRL2dmL9rgzEPeqG4UA3u1czmR\nMSVvzL1dqValIgCnz11m4fLthRxhfmRFvxzZte8oy9fvdtqPjOrlfAw2pjypXDGSsUO6O+1Pv9li\ns3AWkVWEcuLy1QxenZnIj5e0urZvzF3tGrmayRh/GnB3OxrXqwF4Bi9Mj08gy3sjorkxK/rlxLvz\nVjkXbytViGDyL/q6nMgY/woNDeGZcf0ICfGUsb0HTzD3G1tspTBW9MuBVZv3smJT7p23T4yNcVYd\nMqY8a9G4Fg8P/bnT/vTrzezef8zFRIHPin4Zd+LMRd7+ZIXTjvl5a3rfZUsgmuAxKq4z7VvUA0CB\n6fEJtqbuTVjRL8NycnJ47cNErly7DkDtGlV5bEwfl1MZU7pCQkKYOjGOShUiADh59iLvzlvlcqrA\nZUW/DPssIZmd+44CIOD5xa8Y4W4oY1xQM6oKkx/KvY61YlMqqzbvdTFR4CpS0ReRwSKyW0T2iMgL\nN9hnhoikikiyiHTJ91iIiGwRkYUlEdrA3rQTzFm8yWk/MLgbbZvXdTGRMe7q07UlMT9v7bTf/mSF\nzcRZgEKLvoiEAK8Dg4AOwMMi0jbfPkOAFqraCpgMvJXvaaYCO0skseFaRiavzkwgJycHgFZNavPg\nvd1cTmWM+x4b04fa3qVAr1y7zowPE52/E+NRlDP9HkCqqqapaiYwBxiZb5+RQDyAqq4HqotIHQAR\naQgMBd4tsdRB7oMFazjivRElMiKcqRPj7CYsY4BKFSOYOjGOH1eN2LnvKAsStrmaKdAUpVI0ANJ9\n2oe82262z2Gfff4G/AawqfBKwIYdP7B0zS6n/e8P9LEZNI3x0bZ5XcYMyv3k+9Hijew7eNLFRIEl\nzJ9PLiL3AcdVNVlEYoGbLts0bdo05/vY2FhiY2P9Ga/MOXP+Mm/MXu607+7SgtgerW9yhDHB6ReD\nurFtdzqpaSfIyclhevwy/vKbB8r8+tBJSUkkJSXd1nNIYXNRi0g0ME1VB3vbLwKqqq/47PMWsFxV\nP/a2dwMxePryJwBZQEWgKjBfVScV8Dpq82LfmKryx79/ybbvDwFQo3pl/veFB6lauYLLyYwJTEdP\nnuc//jzPmYBwYK92PPFQjMupSpaIoKrFWgO1KN07G4GWItJERCKAsUD+UTgLgUneENHAOVU9rqq/\nU9XGqtrce1xiQQXfFO7Lb3c4BV+AZyf0t4JvzE3Uq1Wdx8bkrrS1dM0uNuz4wb1AAaLQoq+q2cAz\nwDdACjBHVXeJyGQRedy7z2LggIjsBd4GnvJj5qCTduQ0M7/IXQlrRP/OdGyd/7KKMSa/fj3bEN25\nudN+86Mkzpy/7GIi9xXavVNarHunYNczs/jtX+eTfvQMAE0b1ORPz99PeHioy8mMKRsuXr7Gr1+Z\n6xT7Lm0XR7J+AAARDklEQVQb8Z9PDEWkWL0iAclf3TvGRbO+2OAU/PCwUJ6bFGcF35hiqFq5As9O\n6O+MIknenc7iFd+5mslNVvQDWPLudBZ9m7si0C9H9aJR3SgXExlTNnVs3YDh/To77fiF60g7csbF\nRO6xoh+gLly6ymsf5g7P7Na+CYP6tHcxkTFl27j7etC0QU0AsrKymR6/LCjX1rWiH4BUlTc/+pZz\nF68AUK1KRZ4eF1su+iCNcUt4uLd7NMzTPXrw6BlmfbHB5VSlz4p+AFq2dhcbv/vBaT8zLpbqVSu6\nF8iYcqJR3Sh+OaqX01707XaSd6ff5Ijyx4p+gDl84hzvzV/jtAf36UC3Dk1cTGRM+TKoT3u6tc/9\nm3p91nIuXLrqYqLSZUU/gGRlZfNqfILTz9iwThSPjLrb5VTGlC8iwlPjYqhWxfPp+eyFK7z18QqC\nZci4Ff0A8smSzexL90wMFRoawnOT4ogI9+v0SMYEpTuqVuLpcbFOe/32AySs2+1eoFJkRT9ApOw9\nwvylW5z2+GE9adawpouJjCnfundowqDeHZz2Pz9dzeET51xMVDqs6AeAy1czmPFhojP39J2t6jOi\nXydXMxkTDB4ZFU3DOp57X65nZvFqfAJZWdkup/IvK/oB4J25Kzl19hIAlStGMmV8fxueaUwpiIwI\n57lJuYsQ7Us/ySdLNrucyr+s6LtsxaY9eRZwfnJsDDWjqriYyJjg0qxhTcYP6+m05y/dws59R11M\n5F9W9F104sxF3pm7ymn369mGu7s0v8kRxhh/GNGvE3e2qg94lvibMTORy1cz3A3lJ1b0XXI9M4vp\n8QlcvXYdgLo1q/Gr0b0LOcoY4w8iwpTx/alcMRKAk2cv8vc55XMYpxV9F2RlZfO/Hyzj+wPHAAgR\nYerEOCpWiHA5mTHBq2ZUFZ4Y29dpr03ex3vzV5e7wm9Fv5SpKq/PTsozzcL44T1p3bSOa5mMMR69\nurTIM4xz8Yrv+OjLjS4mKnlW9EuRqvLO3JWs3JzqbBsV14WR/Tvf5ChjTGl67IHe9LqrhdP+dOkW\n5i/d6mKikmVFv5SoKjMXruOb1Tudbff2bs+E4T1teKYxASQkJISpE/rnmZ9n1qL1LFmZ4mKqkmNF\nv5R8unQrnyduc9p9u7fi8QfvsYJvTAAKCwvl/zw60BnRA/CPeSv5duMeF1OVDCv6peDLb3fw0Ze5\n83b36NiUZ8b1s4JvTACLCA/jxccG06pJbWfb67OWs27bfhdT3T4r+n6WuG43781f7bQ7tW7Irx8Z\n6NwBaIwJXBUrRPD7yUNpXK8GADmq/O+/lpXpOfit8vjR6q37ePOjJKfdplldXnhskC1sbkwZUrVy\nBV56ehj1alUHIDs7hz/9Ywm7yuhdu1b0/WRzShqvzkxwJlFr2qAmv588hAqR4a7mMsYU3x1VK/HS\nU8P42R2VAcjMyua/3/mK/d6p0MuSIhV9ERksIrtFZI+IvHCDfWaISKqIJItIF++2hiKSKCIpIrJD\nRJ4tyfCBKmXvEf7y3jdkZ+cA0KD2Hfzhyfucu/2MMWVPrRpVmfb0cGfp0qvXrvPym4tIP3bW5WTF\nU2jRF5EQ4HVgENABeFhE2ubbZwjQQlVbAZOBt7wPZQG/VtUOwN3A0/mPLW9S047z329/RaZ3etZa\nUVX5w1PDbI1bY8qB+rXv4KWnhjkncJeuZPDyG19w7NQFl5MVXVHO9HsAqaqapqqZwBxgZL59RgLx\nAKq6HqguInVU9ZiqJnu3XwJ2AQ1KLH2ASTtyhj/+fTEZ1zMBiKpWiZeeHmazZhpTjjSp/zP+84mh\nREZ4umrPXrjCy298welzl1xOVjRFKfoNAN9L1Yf4aeHOv8/h/PuISFOgC7C+uCHLgqMnz/Nfby5y\nZuarUimSPzyVe/HHGFN+tG5ah989PpjwMM+gjBNnLvJfb35ZJhZYL5UFWEWkCjAPmOo94y/QtGnT\nnO9jY2OJjY31e7aScOrsJV5+YxHnLl4BoEJkOH94cpgzzMsYU/7c2aoB/+fRe3nl3a/Jycnh0PGz\n/Nffv+TlZ4b77fpdUlISSUlJt/UcUtgMciISDUxT1cHe9ouAquorPvu8BSxX1Y+97d1AjKoeF5Ew\nYBHwlaq+epPX0bI4m935i1f5z1cXcOTkeQDCw0L5w1PDaN+insvJjDGlYfXWffztg6XOSL02zery\nhyfvK5WReiKCqhbrLs+idO9sBFqKSBMRiQDGAgvz7bMQmOQNEQ2cU9Xj3sfeA3berOCXVZeuZPDy\nm4ucgh8aGsILjw22gm9MEOl9VwuefDjGaX9/4Bh//ufXZGYG5lq7hRZ9Vc0GngG+AVKAOaq6S0Qm\ni8jj3n0WAwdEZC/wNvAkgIj0BsYD/UVkq4hsEZHBfvq3lKprGZn837e+JO3IaQAEeH7SAO5q18jd\nYMaYUhcX3Y5fjurltLd9f4i/xS9zhm0HkkK7d0pLWereuZ6ZxX+/vZjvUo8426aM70dsjzYupjLG\nuO2TJZv4+KtNTrtv91Y8O6G/3+bZ8lf3jvGRlZXNX99fmqfgP/ZAHyv4xhgeHNSNEf1y18dYsSmV\nf8xdFVCrb1nRL4acnBxmzFrOppQ0Z9u4YT0Ycs+dLqYyxgQKEWHSyGgG9mrnbPt6dQqzvgickepW\n9ItIVXn7k5Ws3rLX2XZ/XBfGDOzqYipjTKARER5/8B56d23pbPssIZlPl25xMVUuK/pFkJWVzT/m\nrmLZ2l3OtkG9OzB+eE8XUxljAlVISAjPju9H9w65q2/NXrSBT5ducb2rxy7kFuLQ8bNMj0/gwKFT\nzjZ/X5wxxpQPBQ366NS6IVMm9KNG9cq3/fy3ciHXiv4NqCpfr9rJBwvWOJOnAUR3bs6vHxlgi6AY\nY4rkWkYmf3zrS3bvP+Zsq1IpkiceiuHuLs1v67mt6JeQcxev8MbsJLbsPOhsCwsLZcKwngyL7Whn\n+MaYYsnKymbO4o0sSEjGt8r169mGX43uTcUKEbf0vFb0S8CmlDTemJ2UZ+KkxvVq8NykOJrU/5l7\nwYwxZV7K3iPM+DCRU2dzpyCrW7MaUyfG0bppnWI/nxX925BxPZMPFqzlm9U782wfFtOJ8cN7EBFe\nKnPTGWPKuctXM3hn7kpWbc4dCRgiwphBXXnw3m7F6jq2on+L9h08yfT4Zc4cOuCZC3/KhP50btPQ\nlUzGmPJt5aZU3pm7kivXrjvbWjWpzdSJcUWekt2KfjHl5OTwWUIycxZvIicnd46M6E7NeGJsDFUr\nVyjVPMaY4HLizEVe+zCRnT6LrEdGhPOrMb3o37NtodcPregXw4kzF5kxM5Fd+/P+sP/9gT7E9mht\nF2uNMaUiJyeHBQnbmPPVxjwTtBXl5NOKfhGoqmc+jHmruOrzsap10zo8O6G/rXRljHHF/vST/O1f\nP+1mfmZ8P7q0LXj2Xiv6hbh0xXMBxXcqhRARHhzcjTEDu9rYe2OMqzKuZ/KvBev4enVKnu33xXRk\nwvCePxlQYkX/Jr5LPcyMDxM5fe6ys+12hkoZY4y/FDR0vFHdKJ5/ZECeoeNW9AuQmZnNR4s3sDBx\nW56bIvr3bMuvxvQulSXNjDGmuM5fvMobs5PYvDN3Vt/Q0BAmDO/J8NhOiIgV/fzSj3nmzfnhcO68\nOVUqRfLk2BiiO9/e7c/GGONvqsrSNbt4b/7qPNPBdGzdgCnj+1EzqqoVffD8oJasSuFfC9bm+UF1\nbtOQZ8aXzERHxhhTWg6fOMf0+AT2p590tlWuGMnMVx61on/2whXemL2crbvSnW1hYaFMGhHN0L53\n2lBMY0yZlJWVzSdLNjN/6Ranq3r+jCeLXfTL3dwCBw6dylPwPfPmDKBJ/RoupjLGmNsTFhbKuGE9\n6NKuETNmJnLy7MVbep5yd6YP8O68VXy18jtG9OvMuPt6EB4eWiLPa4wxgeDy1QzenbeK5yYNsO4d\n8CxckJp2gg4t65fI8xljTCC6ldE7RbobSUQGi8huEdkjIi/cYJ8ZIpIqIski0qU4x5a0iPAwK/jG\nGFOAQou+iIQArwODgA7AwyLSNt8+Q4AWqtoKmAy8VdRjy5KkpCS3IxSJ5SxZlrNkWU53FeVMvweQ\nqqppqpoJzAFG5ttnJBAPoKrrgeoiUqeIx5YZZeWXwHKWLMtZsiynu4pS9BsA6T7tQ95tRdmnKMca\nY4wpJf6aYcwGwxtjTAAqdPSOiEQD01R1sLf9IqCq+orPPm8By1X1Y297NxADNCvsWJ/nCIxhRMYY\nU4b44+asjUBLEWkCHAXGAg/n22ch8DTwsfdN4pyqHheRU0U49paCG2OMKb5Ci76qZovIM8A3eLqD\n/qmqu0RksudhfUdVF4vIUBHZC1wG/u1mx/rtX2OMMeamAubmLGOMMf7n6lJRItJQRBJFJEVEdojI\ns27mKYyIhIjIFhFZ6HaWGxGR6iIyV0R2eX+uPd3OVBAReV5EvhOR7SIyS0Qi3M4EICL/FJHjIrLd\nZ1uUiHwjIt+LyNci4vqamjfI+Wfv/3uyiHwqItUCLaPPY/8hIjki4vqkWDfKKSJTvD/PHSLyJ7fy\n+eQp6P+8s4isFZGtIrJBRLoX9jxurw+YBfxaVTsAdwNPB/jNW1OBnW6HKMSrwGJVbQd0BgKuO01E\n6gNTgK6q2glPN+NYd1M53sdzM6GvF4FlqtoGSAT+v1JP9VMF5fwG6KCqXYBU3M9ZUEZEpCEwEEj7\nyRHu+ElOEYkFhgMdVbUj8D8u5MqvoJ/nn4GXVPUu4CXgL4U9iatFX1WPqWqy9/tLeApUQI7j9/6i\nDgXedTvLjXjP7O5R1fcBVDVLVS+4HOtGQoHKIhIGVAKOuJwHAFVdBZzNt3kk8C/v9/8CRpVqqAIU\nlFNVl6lqjre5DmhY6sHy5inoZwnwN+A3pRznhm6Q80ngT6qa5d3n1E8OLGU3yJkD/PjJ8w7gcGHP\n4/aZvkNEmgJdgPXuJrmhH39RA/kiSDPglIi87+2GekdEKrodKj9VPQL8FTiI55f0nKouczfVTdVW\n1ePgOVEBarucpygeBb5yO0R+IjICSFfVHW5nKURroK+IrBOR5UXpNnHJ88D/iMhBPGf9hX66C4ii\nLyJVgHnAVO8Zf0ARkfuA495PJULg3nwWBnQF3lDVrsAVPF0TAUVE7sBz9twEqA9UEZFx7qYqlkB+\n40dEfg9kqupst7P48p6A/A5PN4Sz2aU4hQkDolQ1Gvgt8InLeW7kSTx1szGeN4D3CjvA9aLv/Xg/\nD5ipqp+7necGegMjRGQ/8BHQT0TiXc5UkEN4zqI2edvz8LwJBJoBwH5VPaOq2cB8oJfLmW7muHcu\nKUSkLnDC5Tw3JCK/xNMNGYhvoi2ApsA2ETmAp/tps4gE4iendDy/l6jqRiBHRH7mbqQCPaKqCwBU\ndR6e+c5uyvWij+edaaeqvup2kBtR1d+pamNVbY7ngmOiqk5yO1d+3i6IdBFp7d0UR2BeeD4IRItI\nBfGsXxlHYF1wzv9pbiHwS+/3jwCBcnKSJ6eIDMbTBTlCVTNcS5WXk1FVv1PVuqraXFWb4TlJuUtV\nA+FNNP//+QKgP4D37ylcVU+7ESyf/DkPi0gMgIjEAXsKfQZVde0Lzxl0NpAMbAW2AIPdzFSEzDHA\nQrdz3CRfZzx3USfjOVOp7namG+R8CU+h347n4mi425m8uWbjuaicgefN6d+AKGAZ8D2eETJ3BGjO\nVDwjYrZ4v94MtIz5Ht8P1AjQn2UYMBPYAWwCYgI0Zy9vvq3AWjxvojd9Hrs5yxhjgkggdO8YY4wp\nJVb0jTEmiFjRN8aYIGJF3xhjgogVfWOMCSJW9I0xJohY0TfGmCBiRd8YY4LI/w/EahOh+WGXuwAA\nAABJRU5ErkJggg==\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "thinkplot.Pdf(cf.make_pmf())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we can use the characteristic function to compute a convolution. `CharFunc` provides `__mul__`, which multiplies the `hs` elementwise and returns a new `CharFunc` object:" ] }, { "cell_type": "code", "execution_count": 43, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " def __mul__(self, other):\n", " \"\"\"Computes the elementwise product of two CFs.\"\"\"\n", " return CharFunc(self.hs * other.hs)\n" ] } ], "source": [ "show_code(CharFunc.__mul__)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And here's how we can use it to compute the distribution of the sum of 6 dice." ] }, { "cell_type": "code", "execution_count": 44, "metadata": { "collapsed": false }, "outputs": [ { "data": { "image/png": "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\nAAAASUVORK5CYII=\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "sixth = (cf * cf).make_pmf()\n", "thinkplot.Pdf(sixth)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here are the probabilities, mean, and variance." ] }, { "cell_type": "code", "execution_count": 45, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "6 2.14334705076e-05\n", "7 0.000128600823045\n", "8 0.000450102880659\n", "9 0.00120027434842\n", "10 0.00270061728395\n", "11 0.0054012345679\n", "12 0.00977366255144\n", "13 0.0162037037037\n", "14 0.0248842592593\n", "15 0.0357081618656\n", "16 0.0481610082305\n", "17 0.0612139917695\n", "18 0.0735382373114\n", "19 0.0837191358025\n", "20 0.0904706790123\n", "21 0.0928497942387\n", "22 0.0904706790123\n", "23 0.0837191358025\n", "24 0.0735382373114\n", "25 0.0612139917695\n", "26 0.0481610082305\n", "27 0.0357081618656\n", "28 0.0248842592593\n", "29 0.0162037037037\n", "30 0.00977366255144\n", "31 0.0054012345679\n", "32 0.00270061728395\n", "33 0.00120027434842\n", "34 0.000450102880658\n", "35 0.000128600823045\n", "36 2.14334705075e-05\n" ] } ], "source": [ "sixth.Print()" ] }, { "cell_type": "code", "execution_count": 46, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(21.000000, 17.500000)" ] }, "execution_count": 46, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sixth.Mean(), sixth.Var()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This might seem like a roundabout way to compute a convolution, but it is efficient. The time to Compute the `CharFunc` objects is $O(n \\log n)$. Multiplying them together is $O(n)$. And converting back to a `Pmf` is $O(n \\log n)$.\n", "\n", "So the whole process is $O(n \\log n)$, which is better than `Pmf.__add__`, which is $O(n^2)$." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Exercise:** Plot the magnitude of `cf.hs` using `np.abs`. What does that shape look like?\n", "\n", "Hint: it might be clearer if you us `np.roll` to put the peak of the CF in the middle." ] }, { "cell_type": "code", "execution_count": 47, "metadata": { "collapsed": false }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "#Solution\n", "\n", "n = len(cf.hs)\n", "mags = np.abs(cf.hs)\n", "plt.plot(np.roll(mags, n//2))\n", "None\n", "\n", "# The result approximates a Gaussian curve because \n", "# the PMF is approximately Gaussian and the FT of a \n", "# Gaussian is also Gaussian" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Distributions\n", "\n", "Finally, let's back to the question we started with: *what is a distribution?*\n", "\n", "I've said that `Pmf`, `Cdf`, and `CharFunc` are different ways to represent the same information. For the questions we want to answer, some representations are better than others. But how should we represent the distribution itself?\n", "\n", "One option is to treat each representation as a **mixin**; that is, a class that provides a set of capabilities. A distribution inherits all of the capabilities from all of the representations. Here's a class that shows what I mean:" ] }, { "cell_type": "code", "execution_count": 48, "metadata": { "collapsed": false }, "outputs": [], "source": [ "class Dist(Pmf, Cdf, CharFunc):\n", " \n", " def __init__(self, d):\n", " \"\"\"Initializes the Dist.\n", " \n", " Calls all three __init__ methods.\n", " \"\"\"\n", " Pmf.__init__(self, d)\n", " Cdf.__init__(self, d)\n", " CharFunc.__init__(self, compute_fft(d))\n", " \n", " def __add__(self, other):\n", " \"\"\"Computes the distribution of the sum using Pmf.__add__.\n", " \"\"\"\n", " pmf = Pmf.__add__(self, other)\n", " return Dist(pmf.d)\n", " \n", " def __mul__(self, other):\n", " \"\"\"Computes the distribution of the sum using CharFunc.__mul__.\n", " \"\"\"\n", " pmf = CharFunc.__mul__(self, other).make_pmf()\n", " return Dist(pmf.d)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When you create a `Dist`, you provide a dictionary of values and probabilities.\n", "\n", "`Dist.__init__` calls the other three `__init__` methods to create the `Pmf`, `Cdf`, and `CharFunc` representations. The result is an object that has all the attributes and methods of the three representations.\n", "\n", "As an example, I'll create a `Dist` that represents the sum of six dice:" ] }, { "cell_type": "code", "execution_count": 49, "metadata": { "collapsed": false }, "outputs": [ { "data": { "image/png": "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\nAAAASUVORK5CYII=\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "dist = Dist(sixth.d)\n", "thinkplot.Pdf(dist)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We inherit `__getitem__` from `Pmf`, so we can look up the probability of a value." ] }, { "cell_type": "code", "execution_count": 50, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "0.092850" ] }, "execution_count": 50, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dist[21]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We also get mean and variance from `Pmf`:" ] }, { "cell_type": "code", "execution_count": 51, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(21.000000, 17.500000)" ] }, "execution_count": 51, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dist.Mean(), dist.Var()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "But we can also use methods from `Cdf`, like `ValueArray`:" ] }, { "cell_type": "code", "execution_count": 52, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([18, 21, 24])" ] }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dist.ValueArray((0.25, 0.5, 0.75))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And `Probs`" ] }, { "cell_type": "code", "execution_count": 53, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[0.073538, 0.092850, 0.073538]" ] }, "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dist.Probs((18, 21, 24))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And `Sample`" ] }, { "cell_type": "code", "execution_count": 54, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([22, 19, 20, 21, 26, 26, 23, 16, 20, 19])" ] }, "execution_count": 54, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dist.Sample(10)" ] }, { "cell_type": "code", "execution_count": 55, "metadata": { "collapsed": false }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "thinkplot.Cdf(dist.Max(6));" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`Dist.__add__` uses `Pmf.__add__`, which performs convolution the slow way:" ] }, { "cell_type": "code", "execution_count": 56, "metadata": { "collapsed": false }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "twelfth = dist + dist\n", "thinkplot.Pdf(twelfth)" ] }, { "cell_type": "code", "execution_count": 57, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "42.000000" ] }, "execution_count": 57, "metadata": {}, "output_type": "execute_result" } ], "source": [ "twelfth.Mean()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`Dist.__mul__` uses `CharFunc.__mul__`, which performs convolution the fast way." ] }, { "cell_type": "code", "execution_count": 58, "metadata": { "collapsed": false }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "twelfth_fft = dist * dist\n", "thinkplot.Pdf(twelfth_fft)" ] }, { "cell_type": "code", "execution_count": 59, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "42.000000" ] }, "execution_count": 59, "metadata": {}, "output_type": "execute_result" } ], "source": [ "twelfth_fft.Mean()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Either way, we get the answer, which is 42." ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "## Summary\n", "\n", "Abstractly, a distribution is an entity that can answer questions about the outcomes of random variables and their probabilities. There are many ways to represent a distribution; each representation is equivalent to the others in the sense that they contain the same information, and you can convert from any of them to the others. \n", "\n", "Some representations make it easy and efficient to answer some questions, but none of the representations is best for all of the questions.\n", "\n", "In my implementation, a `Dist` object has the attributes and methods of all representations. From a software engineering point of view, that might not be the best design, but it is meant to illustrate what it means to be a distribution.\n", "\n", "In short, if you give me any representation of a distribution, you have told me everything I need to know to answer questions about the possible outcomes and their probabilities. Converting from one representation to another is mostly a matter of convenience and computational efficiency.\n", "\n", "Conversely, if you are trying to find the distribution of a random variable, you can do it by computing whichever representation is easiest to figure out." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.1" } }, "nbformat": 4, "nbformat_minor": 0 }