Skip to content

Instantly share code, notes, and snippets.

@jml
Last active September 19, 2015 12:32
Show Gist options
  • Select an option

  • Save jml/afc58f0d7869ca3a7102 to your computer and use it in GitHub Desktop.

Select an option

Save jml/afc58f0d7869ca3a7102 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Being ridiculously blessed beyond any merit of my own, the biggest problem facing me today is deciding what to have for breakfast.\n",
"\n",
"I don't know what I want for breakfast _right now_, but I've got a set of fairly consistent preferences:\n",
"\n",
" 1. Eggs benedict\n",
" 2. Bacon and eggs\n",
" 3. French toast with bacon\n",
" 4. Pancakes\n",
" 5. Vegemite on toast\n",
"\n",
"Let's encode this in Python:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"breakfasts = [\n",
" 'eggs benedict',\n",
" 'bacon and eggs',\n",
" 'french toast with bacon',\n",
" 'pancakes',\n",
" 'vegemite on toast',\n",
"]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Actually, I like bacon & eggs about equally as much as I like french toast, so let's represent that by making each priority level a list of options:"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"breakfasts = [\n",
" ['eggs benedict'],\n",
" ['bacon and eggs', 'french toast with bacon'],\n",
" ['pancakes'],\n",
" ['vegemite on toast'],\n",
"]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"What I want to do is to randomly choose a breakfast so that I'm most likely to get eggs benedict, then next most likely to get bacon and eggs or french toast, then pancakes, then vegemite coming out as least likely.\n",
"\n",
"There's probably some well-established way of doing this, but I'm just going to muck around and see what I can find."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Since this is a [partial ordering](https://en.wikipedia.org/wiki/Partially_ordered_set), and because I've spent way too much time swotting up for job interviews my natural response is to put it into a graph."
]
},
{
"cell_type": "code",
"execution_count": 47,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x1066e0790>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%matplotlib inline\n",
"\n",
"import networkx\n",
"\n",
"g = networkx.DiGraph()\n",
"g.add_edge('eggs benedict', 'bacon and eggs')\n",
"g.add_edge('eggs benedict', 'french toast with bacon')\n",
"g.add_edge('bacon and eggs', 'pancakes')\n",
"g.add_edge('french toast with bacon', 'pancakes')\n",
"g.add_edge('pancakes', 'vegemite on toast')\n",
"\n",
"networkx.draw(g, with_labels=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"My initial idea is that we'd randomly pick a root node (i.e. one with no parents), and then given some fixed probability `p` (e.g. `p = 0.75`), we'd decide whether to move on to the next level, at which point we'd pick a node at random from the child nodes.\n",
"\n",
"However, this is way too complicated. Writing up even a little bit of the required code makes it really obvious."
]
},
{
"cell_type": "code",
"execution_count": 49,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAd8AAAFBCAYAAAA2bKVrAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzs3Xl8TOf+B/DPTDayymQTkchmaWJvKWqtolTUckW0/ET0\nolqlbl1UlCIVihYtTRVdrqXtbZSk1L6UKrULLU0iiyS27Ps2398f4dyEqCCZyfJ5v1553Tlztu+Z\n1P3kec6Z51GJiICIiIh0Rq3vAoiIiOoahi8REZGOMXyJiIh0jOFLRESkYwxfIiIiHWP4EhER6RjD\nl4iISMcYvkRERDrG8CUiItIxhi8REZGOMXyJiIh0jOFLRESkYwxfIiIiHWP4EhER6RjDl4iISMcY\nvkRERDrG8CUiItIxhi8REZGOMXyJiIh0jOFLRESkYwxfIiIiHWP4EhER6RjDl4iISMcYvkRERDrG\n8CUiItIxhi8REZGOMXyJiIh0jOFLRESkYwxfIiIiHWP4EhER6RjDl4iISMcYvkRERDrG8CUiItIx\nhi8REZGOMXyJiIh0jOFLRESkYwxfIiIiHWP4EhER6RjDl4iISMcYvkRERDrG8CUiItIxhi8REZGO\nMXyJiIh0jOFLRESkYwxfIiIiHWP4EhER6RjDl4iISMcYvkRERDrG8CUiItIxhi8REZGOMXyJiIh0\njOFLRESkYwxfIiIiHWP4EhER6RjDl4iISMcYvkRERDpmqO8CqHzp6elITk4GANjY2MDKykrPFRER\nUWVhy7cayc/Px+bNm9GtbVs42dmhd5s26N2mDZzs7NCtbVts3rwZBQUF+i6TiIiekEpERN9FEPDt\nli2YMmECWolgUmYmfPC/bolCAGEAVpubI0KtxoqQEIzw89NfsURE9EQYvtXAyuXLsTQwEFtzc/H0\nQ7Y9BWCIqSneWbAAb02bpovyiIiokjF8dej111+Hk5MTAgMDlfe+3bIF0wMCcCQ3Fy4VPE4cgK6m\npvhw3Tq2gImIaiCGr54cPHgQo0aNQlFmJnZkZKD9I+5/CsBLlpaIu3ULxsbGT1TLvHnzEBUVhW++\n+eaJjvMw/v7+cHZ2xoIFC6r0PERE1R0fuNKj3NxctNRqHzl4AeBpAN5aLUJDQyu7LCIiqmpSCwQH\nB8s//vGPMu+99dZb8tZbb4mISFpamgQEBIijo6M4OTlJYGCgFBcXi4hIcXGxTJs2TWxtbcXNzU1W\nrVolKpVKWf93+27YsEG6dOkib7/9tjRo0EA8PDzk6NGjsn79enF2dhZ7e3v56quvlJrGjBkjgYGB\nkp2dLfXq1RMAUg8QC0CSANECsggQD0BsAPEFJAUQecDPBEDqGRuLRqORQYMGSWJionIulUoln332\nmTRt2lQaNGggb7zxRrmf3c6dO8XY2FiMjIzE3Nxc2rZtKyIiCQkJ4uPjIxqNRjw9PWXt2rXKPseP\nH5dOnTpJgwYNxNHRUd58800pKChQ1k+dOlXs7e3F0tJSWrVqJRERERISEiJGRkZibGws5ubmMmjQ\noMf+fRMR1XS1InxjY2PF1NRUMjMzRUSkqKhIHB0d5fjx4yIiMnjwYJk4caLk5OTIzZs3pWPHjhIS\nEiIiImvWrBEvLy9JSEiQ1NRU6d27t6jVaiVg/27fDRs2iKGhoXz55Zei1WolMDBQnJyclDDavXu3\nWFhYSHZ2toiI+Pv7y5w5c0REJDw8XFSAFJYK048B6QxIAiAFd8J15AOCdx8gtoDUMzSUmzdvyuTJ\nk6V79+7KZ6JSqcTHx0fS09MlLi5O7Ozs5Oeffy7385s3b56MHj26zHvdunWTN954Q/Lz8+Xs2bNi\nZ2cn+/fvFxGRU6dOyfHjx6W4uFhiYmLkqaeeko8//lhERH7++Wd5+umnJT09XURE/vzzT0lKSrrv\n+omI6rJaEb4iIl27dpWvv/5aRER2794tHh4eIiJy/fp1MTExkdzcXGXbTZs2Sa9evUREpFevXvL5\n558r6/bu3au0fB+274YNG6Rp06bKuvPnz4tKpZKbN28q79nY2Mi5c+dEpCR8AgMDRURk48aNYqBS\nlQnUp+6E6t3lRECMACkuJ3wDAJkBSBMzM4mOjpasrCwxMjKS2NhYESkJ36NHjyp1+Pr6SnBwcLmf\n3dy5c2XUqFHKclxcnBgYGEhWVpby3qxZs8Tf37/c/T/66CMZMmSIiIjs27dPmjVrJr/99pvyB8xd\npa+fiKguqzUjXL3yyivYvHkzRo8ejU2bNuHVV18FAMTGxqKwsBCOjo7KtlqtFi4uJc8WJyUlwdnZ\nWVnXuHFj5fXD9gUABwcH5XX9+vUBAHZ2dmXey8rKqtA1xAAYgrI34g0B3ADgeM+2SQCeKbVsZmYG\nGxsbJCQkKPU1bNhQWW9qalrhOhITE6HRaGBmZqa85+LigpMnTwIArly5gmnTpuHUqVPIyclBUVER\n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\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x105fddf90>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"def make_ordering_graph(priorities):\n",
" \"\"\"\n",
" Take a list of lists and turn it into a graph \n",
" representing the partial ordering.\n",
" \"\"\"\n",
" g = networkx.DiGraph()\n",
" for i in range(len(priorities) - 1):\n",
" level = priorities[i]\n",
" next_level = priorities[i + 1]\n",
" for item in level:\n",
" for next_item in next_level:\n",
" g.add_edge(item, next_item)\n",
" return g\n",
"\n",
"g = make_ordering_graph(breakfasts)\n",
"networkx.draw(g, with_labels=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We've got three nested loops, and the subgraph of any one priority level and the next is fully connected, which is a hint that graphs maybe aren't the right fit. Shocking, I know.\n",
"\n",
"But it also helps us see the core of the idea:"
]
},
{
"cell_type": "code",
"execution_count": 98,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"'eggs benedict'"
]
},
"execution_count": 98,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import random\n",
"\n",
"def random_preference(priorities, p):\n",
" \"\"\"\n",
" Randomly choose something from a prioritised list.\n",
" \"\"\"\n",
" assert 0 < p < 1\n",
" for level in priorities[:-1]:\n",
" if random.random() <= p:\n",
" return random.choice(level)\n",
" return random.choice(priorities[-1])\n",
"\n",
"random_preference(breakfasts, 0.5)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"My hunch is that given the priorities and `p` we could probably construct a vector of weighted probabilities algebraically. However, that would require reaching for pen and paper to do the maths, so let's try to figure it out with computers."
]
},
{
"cell_type": "code",
"execution_count": 99,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"Counter({'bacon and eggs': 12749,\n",
" 'eggs benedict': 49808,\n",
" 'french toast with bacon': 12306,\n",
" 'pancakes': 12548,\n",
" 'vegemite on toast': 12589})"
]
},
"execution_count": 99,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from collections import Counter\n",
"\n",
"def count_results(n, f, *args, **kwargs):\n",
" c = Counter()\n",
" for i in range(n):\n",
" c[f(*args, **kwargs)] += 1\n",
" return c\n",
"\n",
"count_results(100000, random_preference, breakfasts, 0.5)"
]
},
{
"cell_type": "code",
"execution_count": 100,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"Counter({'bacon and eggs': 936219,\n",
" 'eggs benedict': 7502546,\n",
" 'french toast with bacon': 935817,\n",
" 'pancakes': 468401,\n",
" 'vegemite on toast': 157017})"
]
},
"execution_count": 100,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"count_results(10000000, random_preference, breakfasts, 0.75)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"OK, that makes sense. The probability of level `i` getting selected is `p * (1 - p) ** i`, and the probability of any item in that level being selected is that divided by the number of things in that level. Or something like that.\n",
"\n",
"I'm not certain about the way we always select something from the lowest priority when the loop falls through. Wouldn't it be better to loop back around and try again? After all, with a `p = 0.5`, we are ending up with equal chance of getting the least-favoured item as the second-least."
]
},
{
"cell_type": "code",
"execution_count": 101,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"Counter({'bacon and eggs': 937454,\n",
" 'eggs benedict': 7500646,\n",
" 'french toast with bacon': 936469,\n",
" 'pancakes': 469202,\n",
" 'vegemite on toast': 156229})"
]
},
"execution_count": 101,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def random_preference_loopback(priorities, p):\n",
" \"\"\"\n",
" Randomly choose something from a prioritised list.\n",
" \"\"\"\n",
" assert 0 < p < 1\n",
" while True:\n",
" for level in priorities:\n",
" if random.random() <= p:\n",
" return random.choice(level)\n",
"\n",
"count_results(int(1e7), random_preference, breakfasts, 0.75)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Hmm. That doesn't look much different. I wonder why?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here's the deterministic way to generate the random weightings:"
]
},
{
"cell_type": "code",
"execution_count": 103,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[(0.75, 'eggs benedict'),\n",
" (0.09375, 'bacon and eggs'),\n",
" (0.09375, 'french toast with bacon'),\n",
" (0.046875, 'pancakes'),\n",
" (0.015625, 'vegemite on toast')]"
]
},
"execution_count": 103,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def priority_weighting(priorities, p):\n",
" \"\"\"\n",
" Generate weightings for a prioritised list.\n",
" \"\"\"\n",
" assert 0 < p < 1\n",
" weightings = []\n",
" for i, level in enumerate(priorities[:-1]):\n",
" q = p * (1 - p) ** i / len(level)\n",
" weightings.extend([(q, item) for item in level])\n",
" # XXX: I don't know why this is different, or why \n",
" # this calculation works.\n",
" q = (1 - p) ** (i + 1) / len(level)\n",
" for item in priorities[-1]:\n",
" weightings.extend([(q, item) for item in priorities[-1]])\n",
" return weightings \n",
"\n",
"priority_weighting(breakfasts, 0.75)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Double check the numbers add up:"
]
},
{
"cell_type": "code",
"execution_count": 107,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"1.0"
]
},
"execution_count": 107,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sum(zip(*priority_weighting(breakfasts, 0.75))[0])"
]
},
{
"cell_type": "code",
"execution_count": 104,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[(0.5, 'eggs benedict'),\n",
" (0.125, 'bacon and eggs'),\n",
" (0.125, 'french toast with bacon'),\n",
" (0.125, 'pancakes'),\n",
" (0.125, 'vegemite on toast')]"
]
},
"execution_count": 104,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"priority_weighting(breakfasts, 0.5)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Looks like it's returning the \"right\" numbers, but as the comment in the code indicates, I don't really understand what's going on with the last level. Any thoughts?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 2",
"language": "python",
"name": "python2"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.10"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment