knowledge.ipynb 91,4 ko
Newer Older
{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# KNOWLEDGE\n",
    "\n",
    "The [knowledge](https://github.com/aimacode/aima-python/blob/master/knowledge.py) module covers **Chapter 19: Knowledge in Learning** from Stuart Russel's and Peter Norvig's book *Artificial Intelligence: A Modern Approach*.\n",
    "\n",
    "Execute the cell below to get started."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [],
   "source": [
    "from knowledge import *\n",
    "\n",
    "from notebook import pseudocode, psource"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## CONTENTS\n",
    "\n",
    "* Overview\n",
    "* Current-Best Learning\n",
    "* Version-Space Learning"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## OVERVIEW\n",
    "\n",
    "Like the [learning module](https://github.com/aimacode/aima-python/blob/master/learning.ipynb), this chapter focuses on methods for generating a model/hypothesis for a domain. Unlike though the learning chapter, here we use prior knowledge to help us learn from new experiences and find a proper hypothesis.\n",
    "\n",
    "### First-Order Logic\n",
    "\n",
    "Usually knowledge in this field is represented as **first-order logic**, a type of logic that uses variables and quantifiers in logical sentences. Hypotheses are represented by logical sentences with variables, while examples are logical sentences with set values instead of variables. The goal is to assign a value to a special first-order logic predicate, called **goal predicate**, for new examples given a hypothesis. We learn this hypothesis by infering knowledge from some given examples.\n",
    "\n",
    "### Representation\n",
    "\n",
    "In this module, we use dictionaries to represent examples, with keys the attribute names and values the corresponding example values. Examples also have an extra boolean field, 'GOAL', for the goal predicate. A hypothesis is represented as a list of dictionaries. Each dictionary in that list represents a disjunction. Inside these dictionaries/disjunctions we have conjunctions.\n",
    "\n",
    "For example, say we want to predict if an animal (cat or dog) will take an umbrella given whether or not it rains or the animal wears a coat. The goal value is 'take an umbrella' and is denoted by the key 'GOAL'. An example:\n",
    "\n",
    "`{'Species': 'Cat', 'Coat': 'Yes', 'Rain': 'Yes', 'GOAL': True}`\n",
    "\n",
    "A hypothesis can be the following:\n",
    "\n",
    "`[{'Species': 'Cat'}]`\n",
    "\n",
    "which means an animal will take an umbrella if and only if it is a cat.\n",
    "\n",
    "### Consistency\n",
    "\n",
    "We say that an example `e` is **consistent** with an hypothesis `h` if the assignment from the hypothesis for `e` is the same as `e['GOAL']`. If the above example and hypothesis are `e` and `h` respectively, then `e` is consistent with `h` since `e['Species'] == 'Cat'`. For `e = {'Species': 'Dog', 'Coat': 'Yes', 'Rain': 'Yes', 'GOAL': True}`, the example is no longer consistent with `h`, since the value assigned to `e` is *False* while `e['GOAL']` is *True*."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "## CURRENT-BEST LEARNING\n",
    "\n",
    "### Overview\n",
    "\n",
    "In **Current-Best Learning**, we start with a hypothesis and we refine it as we iterate through the examples. For each example, there are three possible outcomes. The example is consistent with the hypothesis, the example is a **false positive** (real value is false but got predicted as true) and **false negative** (real value is true but got predicted as false). Depending on the outcome we refine the hypothesis accordingly:\n",
    "\n",
    "* Consistent: We do not change the hypothesis and we move on to the next example.\n",
    "\n",
    "* False Positive: We **specialize** the hypothesis, which means we add a conjunction.\n",
    "\n",
    "* False Negative: We **generalize** the hypothesis, either by removing a conjunction or a disjunction, or by adding a disjunction.\n",
    "\n",
    "When specializing and generalizing, we should take care to not create inconsistencies with previous examples. To avoid that caveat, backtracking is needed. Thankfully, there is not just one specialization or generalization, so we have a lot to choose from. We will go through all the specialization/generalizations and we will refine our hypothesis as the first specialization/generalization consistent with all the examples seen up to that point."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Pseudocode"
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/markdown": [
       "### AIMA3e\n",
       "__function__ Current-Best-Learning(_examples_, _h_) __returns__ a hypothesis or fail  \n",
       " __if__ _examples_ is empty __then__  \n",
       "   __return__ _h_  \n",
       " _e_ ← First(_examples_)  \n",
       " __if__ _e_ is consistent with _h_ __then__  \n",
       "   __return__ Current-Best-Learning(Rest(_examples_), _h_)  \n",
       " __else if__ _e_ is a false positive for _h_ __then__  \n",
       "   __for each__ _h'_ __in__ specializations of _h_ consistent with _examples_ seen so far __do__  \n",
       "     _h''_ ← Current-Best-Learning(Rest(_examples_), _h'_)  \n",
       "     __if__ _h''_ ≠ _fail_ __then return__ _h''_  \n",
       " __else if__ _e_ is a false negative for _h_ __then__  \n",
       "   __for each__ _h'_ __in__ generalizations of _h_ consistent with _examples_ seen so far __do__  \n",
       "     _h''_ ← Current-Best-Learning(Rest(_examples_), _h'_)  \n",
       "     __if__ _h''_ ≠ _fail_ __then return__ _h''_  \n",
       " __return__ _fail_  \n",
       "\n",
       "---\n",
       "__Figure ??__ The current-best-hypothesis learning algorithm. It searches for a consistent hypothesis that fits all the examples and backtracks when no consistent specialization/generalization can be found. To start the algorithm, any hypothesis can be passed in; it will be specialized or generalized as needed."
      ],
      "text/plain": [
       "<IPython.core.display.Markdown object>"
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
    "pseudocode('Current-Best-Learning')"
   "cell_type": "markdown",
   "metadata": {},
    "### Implementation\n",
    "\n",
    "As mentioned previously, examples are dictionaries (with keys the attribute names) and hypotheses are lists of dictionaries (each dictionary is a disjunction). Also, in the hypothesis, we denote the *NOT* operation with an exclamation mark (!).\n",
    "\n",
    "We have functions to calculate the list of all specializations/generalizations, to check if an example is consistent/false positive/false negative with a hypothesis. We also have an auxiliary function to add a disjunction (or operation) to a hypothesis, and two other functions to check consistency of all (or just the negative) examples.\n",
    "\n",
    "You can read the source by running the cell below:"
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\"\n",
       "   \"http://www.w3.org/TR/html4/strict.dtd\">\n",
       "\n",
       "<html>\n",
       "<head>\n",
       "  <title></title>\n",
       "  <meta http-equiv=\"content-type\" content=\"text/html; charset=None\">\n",
       "  <style type=\"text/css\">\n",
       "td.linenos { background-color: #f0f0f0; padding-right: 10px; }\n",
       "span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }\n",
       "pre { line-height: 125%; }\n",
       "body .hll { background-color: #ffffcc }\n",
       "body  { background: #f8f8f8; }\n",
       "body .c { color: #408080; font-style: italic } /* Comment */\n",
       "body .err { border: 1px solid #FF0000 } /* Error */\n",
       "body .k { color: #008000; font-weight: bold } /* Keyword */\n",
       "body .o { color: #666666 } /* Operator */\n",
       "body .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
       "body .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
       "body .cp { color: #BC7A00 } /* Comment.Preproc */\n",
       "body .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
       "body .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
       "body .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
       "body .gd { color: #A00000 } /* Generic.Deleted */\n",
       "body .ge { font-style: italic } /* Generic.Emph */\n",
       "body .gr { color: #FF0000 } /* Generic.Error */\n",
       "body .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
       "body .gi { color: #00A000 } /* Generic.Inserted */\n",
       "body .go { color: #888888 } /* Generic.Output */\n",
       "body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
       "body .gs { font-weight: bold } /* Generic.Strong */\n",
       "body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
       "body .gt { color: #0044DD } /* Generic.Traceback */\n",
       "body .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
       "body .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
       "body .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
       "body .kp { color: #008000 } /* Keyword.Pseudo */\n",
       "body .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
       "body .kt { color: #B00040 } /* Keyword.Type */\n",
       "body .m { color: #666666 } /* Literal.Number */\n",
       "body .s { color: #BA2121 } /* Literal.String */\n",
       "body .na { color: #7D9029 } /* Name.Attribute */\n",
       "body .nb { color: #008000 } /* Name.Builtin */\n",
       "body .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
       "body .no { color: #880000 } /* Name.Constant */\n",
       "body .nd { color: #AA22FF } /* Name.Decorator */\n",
       "body .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
       "body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
       "body .nf { color: #0000FF } /* Name.Function */\n",
       "body .nl { color: #A0A000 } /* Name.Label */\n",
       "body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
       "body .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
       "body .nv { color: #19177C } /* Name.Variable */\n",
       "body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
       "body .w { color: #bbbbbb } /* Text.Whitespace */\n",
       "body .mb { color: #666666 } /* Literal.Number.Bin */\n",
       "body .mf { color: #666666 } /* Literal.Number.Float */\n",
       "body .mh { color: #666666 } /* Literal.Number.Hex */\n",
       "body .mi { color: #666666 } /* Literal.Number.Integer */\n",
       "body .mo { color: #666666 } /* Literal.Number.Oct */\n",
       "body .sa { color: #BA2121 } /* Literal.String.Affix */\n",
       "body .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
       "body .sc { color: #BA2121 } /* Literal.String.Char */\n",
       "body .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
       "body .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
       "body .s2 { color: #BA2121 } /* Literal.String.Double */\n",
       "body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
       "body .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
       "body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
       "body .sx { color: #008000 } /* Literal.String.Other */\n",
       "body .sr { color: #BB6688 } /* Literal.String.Regex */\n",
       "body .s1 { color: #BA2121 } /* Literal.String.Single */\n",
       "body .ss { color: #19177C } /* Literal.String.Symbol */\n",
       "body .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
       "body .fm { color: #0000FF } /* Name.Function.Magic */\n",
       "body .vc { color: #19177C } /* Name.Variable.Class */\n",
       "body .vg { color: #19177C } /* Name.Variable.Global */\n",
       "body .vi { color: #19177C } /* Name.Variable.Instance */\n",
       "body .vm { color: #19177C } /* Name.Variable.Magic */\n",
       "body .il { color: #666666 } /* Literal.Number.Integer.Long */\n",
       "\n",
       "  </style>\n",
       "</head>\n",
       "<body>\n",
       "<h2></h2>\n",
       "\n",
       "<div class=\"highlight\"><pre><span></span><span class=\"k\">def</span> <span class=\"nf\">current_best_learning</span><span class=\"p\">(</span><span class=\"n\">examples</span><span class=\"p\">,</span> <span class=\"n\">h</span><span class=\"p\">,</span> <span class=\"n\">examples_so_far</span><span class=\"o\">=</span><span class=\"bp\">None</span><span class=\"p\">):</span>\n",
       "    <span class=\"sd\">&quot;&quot;&quot; [Figure 19.2]</span>\n",
       "<span class=\"sd\">    The hypothesis is a list of dictionaries, with each dictionary representing</span>\n",
       "<span class=\"sd\">    a disjunction.&quot;&quot;&quot;</span>\n",
       "    <span class=\"k\">if</span> <span class=\"ow\">not</span> <span class=\"n\">examples</span><span class=\"p\">:</span>\n",
       "        <span class=\"k\">return</span> <span class=\"n\">h</span>\n",
       "\n",
       "    <span class=\"n\">examples_so_far</span> <span class=\"o\">=</span> <span class=\"n\">examples_so_far</span> <span class=\"ow\">or</span> <span class=\"p\">[]</span>\n",
       "    <span class=\"n\">e</span> <span class=\"o\">=</span> <span class=\"n\">examples</span><span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span>\n",
       "    <span class=\"k\">if</span> <span class=\"n\">is_consistent</span><span class=\"p\">(</span><span class=\"n\">e</span><span class=\"p\">,</span> <span class=\"n\">h</span><span class=\"p\">):</span>\n",
       "        <span class=\"k\">return</span> <span class=\"n\">current_best_learning</span><span class=\"p\">(</span><span class=\"n\">examples</span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"p\">:],</span> <span class=\"n\">h</span><span class=\"p\">,</span> <span class=\"n\">examples_so_far</span> <span class=\"o\">+</span> <span class=\"p\">[</span><span class=\"n\">e</span><span class=\"p\">])</span>\n",
       "    <span class=\"k\">elif</span> <span class=\"n\">false_positive</span><span class=\"p\">(</span><span class=\"n\">e</span><span class=\"p\">,</span> <span class=\"n\">h</span><span class=\"p\">):</span>\n",
       "        <span class=\"k\">for</span> <span class=\"n\">h2</span> <span class=\"ow\">in</span> <span class=\"n\">specializations</span><span class=\"p\">(</span><span class=\"n\">examples_so_far</span> <span class=\"o\">+</span> <span class=\"p\">[</span><span class=\"n\">e</span><span class=\"p\">],</span> <span class=\"n\">h</span><span class=\"p\">):</span>\n",
       "            <span class=\"n\">h3</span> <span class=\"o\">=</span> <span class=\"n\">current_best_learning</span><span class=\"p\">(</span><span class=\"n\">examples</span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"p\">:],</span> <span class=\"n\">h2</span><span class=\"p\">,</span> <span class=\"n\">examples_so_far</span> <span class=\"o\">+</span> <span class=\"p\">[</span><span class=\"n\">e</span><span class=\"p\">])</span>\n",
       "            <span class=\"k\">if</span> <span class=\"n\">h3</span> <span class=\"o\">!=</span> <span class=\"s1\">&#39;FAIL&#39;</span><span class=\"p\">:</span>\n",
       "                <span class=\"k\">return</span> <span class=\"n\">h3</span>\n",
       "    <span class=\"k\">elif</span> <span class=\"n\">false_negative</span><span class=\"p\">(</span><span class=\"n\">e</span><span class=\"p\">,</span> <span class=\"n\">h</span><span class=\"p\">):</span>\n",
       "        <span class=\"k\">for</span> <span class=\"n\">h2</span> <span class=\"ow\">in</span> <span class=\"n\">generalizations</span><span class=\"p\">(</span><span class=\"n\">examples_so_far</span> <span class=\"o\">+</span> <span class=\"p\">[</span><span class=\"n\">e</span><span class=\"p\">],</span> <span class=\"n\">h</span><span class=\"p\">):</span>\n",
       "            <span class=\"n\">h3</span> <span class=\"o\">=</span> <span class=\"n\">current_best_learning</span><span class=\"p\">(</span><span class=\"n\">examples</span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"p\">:],</span> <span class=\"n\">h2</span><span class=\"p\">,</span> <span class=\"n\">examples_so_far</span> <span class=\"o\">+</span> <span class=\"p\">[</span><span class=\"n\">e</span><span class=\"p\">])</span>\n",
       "            <span class=\"k\">if</span> <span class=\"n\">h3</span> <span class=\"o\">!=</span> <span class=\"s1\">&#39;FAIL&#39;</span><span class=\"p\">:</span>\n",
       "                <span class=\"k\">return</span> <span class=\"n\">h3</span>\n",
       "\n",
       "    <span class=\"k\">return</span> <span class=\"s1\">&#39;FAIL&#39;</span>\n",
       "\n",
       "\n",
       "<span class=\"k\">def</span> <span class=\"nf\">specializations</span><span class=\"p\">(</span><span class=\"n\">examples_so_far</span><span class=\"p\">,</span> <span class=\"n\">h</span><span class=\"p\">):</span>\n",
       "    <span class=\"sd\">&quot;&quot;&quot;Specialize the hypothesis by adding AND operations to the disjunctions&quot;&quot;&quot;</span>\n",
       "    <span class=\"n\">hypotheses</span> <span class=\"o\">=</span> <span class=\"p\">[]</span>\n",
       "\n",
       "    <span class=\"k\">for</span> <span class=\"n\">i</span><span class=\"p\">,</span> <span class=\"n\">disj</span> <span class=\"ow\">in</span> <span class=\"nb\">enumerate</span><span class=\"p\">(</span><span class=\"n\">h</span><span class=\"p\">):</span>\n",
       "        <span class=\"k\">for</span> <span class=\"n\">e</span> <span class=\"ow\">in</span> <span class=\"n\">examples_so_far</span><span class=\"p\">:</span>\n",
       "            <span class=\"k\">for</span> <span class=\"n\">k</span><span class=\"p\">,</span> <span class=\"n\">v</span> <span class=\"ow\">in</span> <span class=\"n\">e</span><span class=\"o\">.</span><span class=\"n\">items</span><span class=\"p\">():</span>\n",
       "                <span class=\"k\">if</span> <span class=\"n\">k</span> <span class=\"ow\">in</span> <span class=\"n\">disj</span> <span class=\"ow\">or</span> <span class=\"n\">k</span> <span class=\"o\">==</span> <span class=\"s1\">&#39;GOAL&#39;</span><span class=\"p\">:</span>\n",
       "                    <span class=\"k\">continue</span>\n",
       "\n",
       "                <span class=\"n\">h2</span> <span class=\"o\">=</span> <span class=\"n\">h</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"p\">]</span><span class=\"o\">.</span><span class=\"n\">copy</span><span class=\"p\">()</span>\n",
       "                <span class=\"n\">h2</span><span class=\"p\">[</span><span class=\"n\">k</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;!&#39;</span> <span class=\"o\">+</span> <span class=\"n\">v</span>\n",
       "                <span class=\"n\">h3</span> <span class=\"o\">=</span> <span class=\"n\">h</span><span class=\"o\">.</span><span class=\"n\">copy</span><span class=\"p\">()</span>\n",
       "                <span class=\"n\">h3</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">h2</span>\n",
       "                <span class=\"k\">if</span> <span class=\"n\">check_all_consistency</span><span class=\"p\">(</span><span class=\"n\">examples_so_far</span><span class=\"p\">,</span> <span class=\"n\">h3</span><span class=\"p\">):</span>\n",
       "                    <span class=\"n\">hypotheses</span><span class=\"o\">.</span><span class=\"n\">append</span><span class=\"p\">(</span><span class=\"n\">h3</span><span class=\"p\">)</span>\n",
       "\n",
       "    <span class=\"n\">shuffle</span><span class=\"p\">(</span><span class=\"n\">hypotheses</span><span class=\"p\">)</span>\n",
       "    <span class=\"k\">return</span> <span class=\"n\">hypotheses</span>\n",
       "\n",
       "\n",
       "<span class=\"k\">def</span> <span class=\"nf\">generalizations</span><span class=\"p\">(</span><span class=\"n\">examples_so_far</span><span class=\"p\">,</span> <span class=\"n\">h</span><span class=\"p\">):</span>\n",
       "    <span class=\"sd\">&quot;&quot;&quot;Generalize the hypothesis. First delete operations</span>\n",
       "<span class=\"sd\">    (including disjunctions) from the hypothesis. Then, add OR operations.&quot;&quot;&quot;</span>\n",
       "    <span class=\"n\">hypotheses</span> <span class=\"o\">=</span> <span class=\"p\">[]</span>\n",
       "\n",
       "    <span class=\"c1\"># Delete disjunctions</span>\n",
       "    <span class=\"n\">disj_powerset</span> <span class=\"o\">=</span> <span class=\"n\">powerset</span><span class=\"p\">(</span><span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"nb\">len</span><span class=\"p\">(</span><span class=\"n\">h</span><span class=\"p\">)))</span>\n",
       "    <span class=\"k\">for</span> <span class=\"n\">disjs</span> <span class=\"ow\">in</span> <span class=\"n\">disj_powerset</span><span class=\"p\">:</span>\n",
       "        <span class=\"n\">h2</span> <span class=\"o\">=</span> <span class=\"n\">h</span><span class=\"o\">.</span><span class=\"n\">copy</span><span class=\"p\">()</span>\n",
       "        <span class=\"k\">for</span> <span class=\"n\">d</span> <span class=\"ow\">in</span> <span class=\"nb\">reversed</span><span class=\"p\">(</span><span class=\"nb\">list</span><span class=\"p\">(</span><span class=\"n\">disjs</span><span class=\"p\">)):</span>\n",
       "            <span class=\"k\">del</span> <span class=\"n\">h2</span><span class=\"p\">[</span><span class=\"n\">d</span><span class=\"p\">]</span>\n",
       "\n",
       "        <span class=\"k\">if</span> <span class=\"n\">check_all_consistency</span><span class=\"p\">(</span><span class=\"n\">examples_so_far</span><span class=\"p\">,</span> <span class=\"n\">h2</span><span class=\"p\">):</span>\n",
       "            <span class=\"n\">hypotheses</span> <span class=\"o\">+=</span> <span class=\"n\">h2</span>\n",
       "\n",
       "    <span class=\"c1\"># Delete AND operations in disjunctions</span>\n",
       "    <span class=\"k\">for</span> <span class=\"n\">i</span><span class=\"p\">,</span> <span class=\"n\">disj</span> <span class=\"ow\">in</span> <span class=\"nb\">enumerate</span><span class=\"p\">(</span><span class=\"n\">h</span><span class=\"p\">):</span>\n",
       "        <span class=\"n\">a_powerset</span> <span class=\"o\">=</span> <span class=\"n\">powerset</span><span class=\"p\">(</span><span class=\"n\">disj</span><span class=\"o\">.</span><span class=\"n\">keys</span><span class=\"p\">())</span>\n",
       "        <span class=\"k\">for</span> <span class=\"n\">attrs</span> <span class=\"ow\">in</span> <span class=\"n\">a_powerset</span><span class=\"p\">:</span>\n",
       "            <span class=\"n\">h2</span> <span class=\"o\">=</span> <span class=\"n\">h</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"p\">]</span><span class=\"o\">.</span><span class=\"n\">copy</span><span class=\"p\">()</span>\n",
       "            <span class=\"k\">for</span> <span class=\"n\">a</span> <span class=\"ow\">in</span> <span class=\"n\">attrs</span><span class=\"p\">:</span>\n",
       "                <span class=\"k\">del</span> <span class=\"n\">h2</span><span class=\"p\">[</span><span class=\"n\">a</span><span class=\"p\">]</span>\n",
       "\n",
       "            <span class=\"k\">if</span> <span class=\"n\">check_all_consistency</span><span class=\"p\">(</span><span class=\"n\">examples_so_far</span><span class=\"p\">,</span> <span class=\"p\">[</span><span class=\"n\">h2</span><span class=\"p\">]):</span>\n",
       "                <span class=\"n\">h3</span> <span class=\"o\">=</span> <span class=\"n\">h</span><span class=\"o\">.</span><span class=\"n\">copy</span><span class=\"p\">()</span>\n",
       "                <span class=\"n\">h3</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">h2</span><span class=\"o\">.</span><span class=\"n\">copy</span><span class=\"p\">()</span>\n",
       "                <span class=\"n\">hypotheses</span> <span class=\"o\">+=</span> <span class=\"n\">h3</span>\n",
       "\n",
       "    <span class=\"c1\"># Add OR operations</span>\n",
       "    <span class=\"k\">if</span> <span class=\"n\">hypotheses</span> <span class=\"o\">==</span> <span class=\"p\">[]</span> <span class=\"ow\">or</span> <span class=\"n\">hypotheses</span> <span class=\"o\">==</span> <span class=\"p\">[{}]:</span>\n",
       "        <span class=\"n\">hypotheses</span> <span class=\"o\">=</span> <span class=\"n\">add_or</span><span class=\"p\">(</span><span class=\"n\">examples_so_far</span><span class=\"p\">,</span> <span class=\"n\">h</span><span class=\"p\">)</span>\n",
       "    <span class=\"k\">else</span><span class=\"p\">:</span>\n",
       "        <span class=\"n\">hypotheses</span><span class=\"o\">.</span><span class=\"n\">extend</span><span class=\"p\">(</span><span class=\"n\">add_or</span><span class=\"p\">(</span><span class=\"n\">examples_so_far</span><span class=\"p\">,</span> <span class=\"n\">h</span><span class=\"p\">))</span>\n",
       "\n",
       "    <span class=\"n\">shuffle</span><span class=\"p\">(</span><span class=\"n\">hypotheses</span><span class=\"p\">)</span>\n",
       "    <span class=\"k\">return</span> <span class=\"n\">hypotheses</span>\n",
       "</pre></div>\n",
       "</body>\n",
       "</html>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
    "psource(current_best_learning, specializations, generalizations)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can view the auxiliary functions in the [knowledge module](https://github.com/aimacode/aima-python/blob/master/knowledge.py). A few notes on the functionality of some of the important methods:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* `specializations`: For each disjunction in the hypothesis, it adds a conjunction for values in the examples encountered so far (if the conjunction is consistent with all the examples). It returns a list of hypotheses.\n",
    "\n",
    "* `generalizations`: It adds to the list of hypotheses in three phases. First it deletes disjunctions, then it deletes conjunctions and finally it adds a disjunction.\n",
    "\n",
    "* `add_or`: Used by `generalizations` to add an *or operation* (a disjunction) to the hypothesis. Since the last example is the problematic one which wasn't consistent with the hypothesis, it will model the new disjunction to that example. It creates a disjunction for each combination of attributes in the example and returns the new hypotheses consistent with the negative examples encountered so far. We do not need to check the consistency of positive examples, since they are already consistent with at least one other disjunction in the hypotheses' set, so this new disjunction doesn't affect them. In other words, if the value of a positive example is negative under the disjunction, it doesn't matter since we know there exists a disjunction consistent with the example."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Since the algorithm stops searching the specializations/generalizations after the first consistent hypothesis is found, usually you will get different results each time you run the code."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Examples\n",
    "\n",
    "We will take a look at two examples. The first is a trivial one, while the second is a bit more complicated (you can also find it in the book).\n",
    "\n",
    "First we have the \"animals taking umbrellas\" example. Here we want to find a hypothesis to predict whether or not an animal will take an umbrella. The attributes are `Species`, `Rain` and `Coat`. The possible values are `[Cat, Dog]`, `[Yes, No]` and `[Yes, No]` respectively. Below we give seven examples (with `GOAL` we denote whether an animal will take an umbrella or not):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [],
   "source": [
    "animals_umbrellas = [\n",
    "    {'Species': 'Cat', 'Rain': 'Yes', 'Coat': 'No', 'GOAL': True},\n",
    "    {'Species': 'Cat', 'Rain': 'Yes', 'Coat': 'Yes', 'GOAL': True},\n",
    "    {'Species': 'Dog', 'Rain': 'Yes', 'Coat': 'Yes', 'GOAL': True},\n",
    "    {'Species': 'Dog', 'Rain': 'Yes', 'Coat': 'No', 'GOAL': False},\n",
    "    {'Species': 'Dog', 'Rain': 'No', 'Coat': 'No', 'GOAL': False},\n",
    "    {'Species': 'Cat', 'Rain': 'No', 'Coat': 'No', 'GOAL': False},\n",
    "    {'Species': 'Cat', 'Rain': 'No', 'Coat': 'Yes', 'GOAL': True}\n",
    "]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let our initial hypothesis be `[{'Species': 'Cat'}]`. That means every cat will be taking an umbrella. We can see that this is not true, but it doesn't matter since we will refine the hypothesis using the Current-Best algorithm. First, let's see how that initial hypothesis fares to have a point of reference."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "True\n",
      "False\n",
      "False\n",
      "False\n",
      "True\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "initial_h = [{'Species': 'Cat'}]\n",
    "\n",
    "for e in animals_umbrellas:\n",
    "    print(guess_value(e, initial_h))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We got 5/7 correct. Not terribly bad, but we can do better. Let's run the algorithm and see how that performs."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "True\n",
      "True\n",
      "False\n",
      "False\n",
      "False\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "h = current_best_learning(animals_umbrellas, initial_h)\n",
    "\n",
    "for e in animals_umbrellas:\n",
    "    print(guess_value(e, h))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We got everything right! Let's print our hypothesis:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[{'Species': 'Cat', 'Rain': '!No'}, {'Rain': 'Yes', 'Coat': '!No'}, {'Rain': 'No', 'Coat': 'Yes'}]\n"
     ]
    }
   ],
   "source": [
    "print(h)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If an example meets any of the disjunctions in the list, it will be `True`, otherwise it will be `False`.\n",
    "\n",
    "Let's move on to a bigger example, the \"Restaurant\" example from the book. The attributes for each example are the following:\n",
    "\n",
    "* Alternative option (`Alt`)\n",
    "* Bar to hang out/wait (`Bar`)\n",
    "* Day is Friday (`Fri`)\n",
    "* Is hungry (`Hun`)\n",
    "* How much does it cost (`Price`, takes values in [$, $$, $$$])\n",
    "* How many patrons are there (`Pat`, takes values in [None, Some, Full])\n",
    "* Is raining (`Rain`)\n",
    "* Has made reservation (`Res`)\n",
    "* Type of restaurant (`Type`, takes values in [French, Thai, Burger, Italian])\n",
    "* Estimated waiting time (`Est`, takes values in [0-10, 10-30, 30-60, >60])\n",
    "\n",
    "We want to predict if someone will wait or not (Goal = WillWait). Below we show twelve examples found in the book."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![restaurant](images/restaurant.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "With the function `r_example` we will build the dictionary examples:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "def r_example(Alt, Bar, Fri, Hun, Pat, Price, Rain, Res, Type, Est, GOAL):\n",
    "    return {'Alt': Alt, 'Bar': Bar, 'Fri': Fri, 'Hun': Hun, 'Pat': Pat,\n",
    "            'Price': Price, 'Rain': Rain, 'Res': Res, 'Type': Type, 'Est': Est,\n",
    "            'GOAL': GOAL}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "In code:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "restaurant = [\n",
    "    r_example('Yes', 'No', 'No', 'Yes', 'Some', '$$$', 'No', 'Yes', 'French', '0-10', True),\n",
    "    r_example('Yes', 'No', 'No', 'Yes', 'Full', '$', 'No', 'No', 'Thai', '30-60', False),\n",
    "    r_example('No', 'Yes', 'No', 'No', 'Some', '$', 'No', 'No', 'Burger', '0-10', True),\n",
    "    r_example('Yes', 'No', 'Yes', 'Yes', 'Full', '$', 'Yes', 'No', 'Thai', '10-30', True),\n",
    "    r_example('Yes', 'No', 'Yes', 'No', 'Full', '$$$', 'No', 'Yes', 'French', '>60', False),\n",
    "    r_example('No', 'Yes', 'No', 'Yes', 'Some', '$$', 'Yes', 'Yes', 'Italian', '0-10', True),\n",
    "    r_example('No', 'Yes', 'No', 'No', 'None', '$', 'Yes', 'No', 'Burger', '0-10', False),\n",
    "    r_example('No', 'No', 'No', 'Yes', 'Some', '$$', 'Yes', 'Yes', 'Thai', '0-10', True),\n",
    "    r_example('No', 'Yes', 'Yes', 'No', 'Full', '$', 'Yes', 'No', 'Burger', '>60', False),\n",
    "    r_example('Yes', 'Yes', 'Yes', 'Yes', 'Full', '$$$', 'No', 'Yes', 'Italian', '10-30', False),\n",
    "    r_example('No', 'No', 'No', 'No', 'None', '$', 'No', 'No', 'Thai', '0-10', False),\n",
    "    r_example('Yes', 'Yes', 'Yes', 'Yes', 'Full', '$', 'No', 'No', 'Burger', '30-60', True)\n",
    "]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Say our initial hypothesis is that there should be an alternative option and let's run the algorithm."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "False\n",
      "True\n",
      "True\n",
      "False\n",
      "True\n",
      "False\n",
      "True\n",
      "False\n",
      "False\n",
      "False\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "initial_h = [{'Alt': 'Yes'}]\n",
    "h = current_best_learning(restaurant, initial_h)\n",
    "for e in restaurant:\n",
    "    print(guess_value(e, h))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The predictions are correct. Let's see the hypothesis that accomplished that:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[{'Alt': 'Yes', 'Type': '!Thai', 'Hun': '!No', 'Pat': '!Full'}, {'Alt': 'No', 'Bar': 'Yes', 'Hun': 'No', 'Price': '$', 'Rain': 'No', 'Res': 'No'}, {'Pat': 'Full', 'Price': '$', 'Rain': 'Yes', 'Type': '!Burger'}, {'Price': '$$', 'Type': 'Italian'}, {'Bar': 'No', 'Hun': 'Yes', 'Pat': 'Some', 'Price': '$$', 'Rain': 'Yes', 'Res': 'Yes', 'Type': 'Thai', 'Est': '0-10'}, {'Bar': 'Yes', 'Fri': 'Yes', 'Hun': 'Yes', 'Pat': 'Full', 'Rain': 'No', 'Res': 'No', 'Type': 'Burger'}]\n"
     ]
    }
   ],
   "source": [
    "print(h)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It might be quite complicated, with many disjunctions if we are unlucky, but it will always be correct, as long as a correct hypothesis exists."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## VERSION-SPACE LEARNING\n",
    "\n",
    "### Overview\n",
    "\n",
    "**Version-Space Learning** is a general method of learning in logic based domains. We generate the set of all the possible hypotheses in the domain and then we iteratively remove hypotheses inconsistent with the examples. The set of remaining hypotheses is called **version space**. Because hypotheses are being removed until we end up with a set of hypotheses consistent with all the examples, the algorithm is sometimes called **candidate elimination** algorithm.\n",
    "\n",
    "After we update the set on an example, all the hypotheses in the set are consistent with that example. So, when all the examples have been parsed, all the remaining hypotheses in the set are consistent with all the examples. That means we can pick hypotheses at random and we will always get a valid hypothesis."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
    "### Pseudocode"
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/markdown": [
       "### AIMA3e\n",
       "__function__ Version-Space-Learning(_examples_) __returns__ a version space  \n",
       "&emsp;__local variables__: _V_, the version space: the set of all hypotheses  \n",
       "\n",
       "&emsp;_V_ &larr; the set of all hypotheses  \n",
       "&emsp;__for each__ example _e_ in _examples_ __do__  \n",
       "&emsp;&emsp;&emsp;__if__ _V_ is not empty __then__ _V_ &larr; Version-Space-Update(_V_, _e_)  \n",
       "&emsp;__return__ _V_  \n",
       "\n",
       "---\n",
       "__function__ Version-Space-Update(_V_, _e_) __returns__ an updated version space  \n",
       "&emsp;_V_ &larr; \\{_h_ &isin; _V_ : _h_ is consistent with _e_\\}  \n",
       "\n",
       "---\n",
       "__Figure ??__ The version space learning algorithm. It finds a subset of _V_ that is consistent with all the _examples_."
      ],
      "text/plain": [
       "<IPython.core.display.Markdown object>"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
    "pseudocode('Version-Space-Learning')"
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "### Implementation\n",
    "\n",
    "The set of hypotheses is represented by a list and each hypothesis is represented by a list of dictionaries, each dictionary a disjunction. For each example in the given examples we update the version space with the function `version_space_update`. In the end, we return the version-space.\n",
    "\n",
    "Before we can start updating the version space, we need to generate it. We do that with the `all_hypotheses` function, which builds a list of all the possible hypotheses (including hypotheses with disjunctions). The function works like this: first it finds the possible values for each attribute (using `values_table`), then it builds all the attribute combinations (and adds them to the hypotheses set) and finally it builds the combinations of all the disjunctions (which in this case are the hypotheses build by the attribute combinations).\n",
    "\n",
    "You can read the code for all the functions by running the cells below:"
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\"\n",
       "   \"http://www.w3.org/TR/html4/strict.dtd\">\n",
       "\n",
       "<html>\n",
       "<head>\n",
       "  <title></title>\n",
       "  <meta http-equiv=\"content-type\" content=\"text/html; charset=None\">\n",
       "  <style type=\"text/css\">\n",
       "td.linenos { background-color: #f0f0f0; padding-right: 10px; }\n",
       "span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }\n",
       "pre { line-height: 125%; }\n",
       "body .hll { background-color: #ffffcc }\n",
       "body  { background: #f8f8f8; }\n",
       "body .c { color: #408080; font-style: italic } /* Comment */\n",
       "body .err { border: 1px solid #FF0000 } /* Error */\n",
       "body .k { color: #008000; font-weight: bold } /* Keyword */\n",
       "body .o { color: #666666 } /* Operator */\n",
       "body .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
       "body .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
       "body .cp { color: #BC7A00 } /* Comment.Preproc */\n",
       "body .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
       "body .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
       "body .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
       "body .gd { color: #A00000 } /* Generic.Deleted */\n",
       "body .ge { font-style: italic } /* Generic.Emph */\n",
       "body .gr { color: #FF0000 } /* Generic.Error */\n",
       "body .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
       "body .gi { color: #00A000 } /* Generic.Inserted */\n",
       "body .go { color: #888888 } /* Generic.Output */\n",
       "body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
       "body .gs { font-weight: bold } /* Generic.Strong */\n",
       "body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
       "body .gt { color: #0044DD } /* Generic.Traceback */\n",
       "body .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
       "body .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
       "body .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
       "body .kp { color: #008000 } /* Keyword.Pseudo */\n",
       "body .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
       "body .kt { color: #B00040 } /* Keyword.Type */\n",
       "body .m { color: #666666 } /* Literal.Number */\n",
       "body .s { color: #BA2121 } /* Literal.String */\n",
       "body .na { color: #7D9029 } /* Name.Attribute */\n",
       "body .nb { color: #008000 } /* Name.Builtin */\n",
       "body .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
       "body .no { color: #880000 } /* Name.Constant */\n",
       "body .nd { color: #AA22FF } /* Name.Decorator */\n",
       "body .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
       "body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
       "body .nf { color: #0000FF } /* Name.Function */\n",
       "body .nl { color: #A0A000 } /* Name.Label */\n",
       "body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
       "body .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
       "body .nv { color: #19177C } /* Name.Variable */\n",
       "body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
       "body .w { color: #bbbbbb } /* Text.Whitespace */\n",
       "body .mb { color: #666666 } /* Literal.Number.Bin */\n",
       "body .mf { color: #666666 } /* Literal.Number.Float */\n",
       "body .mh { color: #666666 } /* Literal.Number.Hex */\n",
       "body .mi { color: #666666 } /* Literal.Number.Integer */\n",
       "body .mo { color: #666666 } /* Literal.Number.Oct */\n",
       "body .sa { color: #BA2121 } /* Literal.String.Affix */\n",
       "body .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
       "body .sc { color: #BA2121 } /* Literal.String.Char */\n",
       "body .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
       "body .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
       "body .s2 { color: #BA2121 } /* Literal.String.Double */\n",
       "body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
       "body .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
       "body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
       "body .sx { color: #008000 } /* Literal.String.Other */\n",
       "body .sr { color: #BB6688 } /* Literal.String.Regex */\n",
       "body .s1 { color: #BA2121 } /* Literal.String.Single */\n",
       "body .ss { color: #19177C } /* Literal.String.Symbol */\n",
       "body .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
       "body .fm { color: #0000FF } /* Name.Function.Magic */\n",
       "body .vc { color: #19177C } /* Name.Variable.Class */\n",
       "body .vg { color: #19177C } /* Name.Variable.Global */\n",
       "body .vi { color: #19177C } /* Name.Variable.Instance */\n",
       "body .vm { color: #19177C } /* Name.Variable.Magic */\n",
       "body .il { color: #666666 } /* Literal.Number.Integer.Long */\n",
       "\n",
       "  </style>\n",
       "</head>\n",
       "<body>\n",
       "<h2></h2>\n",
       "\n",
       "<div class=\"highlight\"><pre><span></span><span class=\"k\">def</span> <span class=\"nf\">version_space_learning</span><span class=\"p\">(</span><span class=\"n\">examples</span><span class=\"p\">):</span>\n",
       "    <span class=\"sd\">&quot;&quot;&quot; [Figure 19.3]</span>\n",
       "<span class=\"sd\">    The version space is a list of hypotheses, which in turn are a list</span>\n",
       "<span class=\"sd\">    of dictionaries/disjunctions.&quot;&quot;&quot;</span>\n",
       "    <span class=\"n\">V</span> <span class=\"o\">=</span> <span class=\"n\">all_hypotheses</span><span class=\"p\">(</span><span class=\"n\">examples</span><span class=\"p\">)</span>\n",
       "    <span class=\"k\">for</span> <span class=\"n\">e</span> <span class=\"ow\">in</span> <span class=\"n\">examples</span><span class=\"p\">:</span>\n",
       "        <span class=\"k\">if</span> <span class=\"n\">V</span><span class=\"p\">:</span>\n",
       "            <span class=\"n\">V</span> <span class=\"o\">=</span> <span class=\"n\">version_space_update</span><span class=\"p\">(</span><span class=\"n\">V</span><span class=\"p\">,</span> <span class=\"n\">e</span><span class=\"p\">)</span>\n",
       "\n",
       "    <span class=\"k\">return</span> <span class=\"n\">V</span>\n",
       "\n",
       "\n",
       "<span class=\"k\">def</span> <span class=\"nf\">version_space_update</span><span class=\"p\">(</span><span class=\"n\">V</span><span class=\"p\">,</span> <span class=\"n\">e</span><span class=\"p\">):</span>\n",
       "    <span class=\"k\">return</span> <span class=\"p\">[</span><span class=\"n\">h</span> <span class=\"k\">for</span> <span class=\"n\">h</span> <span class=\"ow\">in</span> <span class=\"n\">V</span> <span class=\"k\">if</span> <span class=\"n\">is_consistent</span><span class=\"p\">(</span><span class=\"n\">e</span><span class=\"p\">,</span> <span class=\"n\">h</span><span class=\"p\">)]</span>\n",
       "</pre></div>\n",
       "</body>\n",
       "</html>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
    "psource(version_space_learning, version_space_update)"
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\"\n",
       "   \"http://www.w3.org/TR/html4/strict.dtd\">\n",
       "\n",
       "<html>\n",
       "<head>\n",
       "  <title></title>\n",
       "  <meta http-equiv=\"content-type\" content=\"text/html; charset=None\">\n",
       "  <style type=\"text/css\">\n",
       "td.linenos { background-color: #f0f0f0; padding-right: 10px; }\n",
       "span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }\n",
       "pre { line-height: 125%; }\n",
       "body .hll { background-color: #ffffcc }\n",
       "body  { background: #f8f8f8; }\n",
       "body .c { color: #408080; font-style: italic } /* Comment */\n",
       "body .err { border: 1px solid #FF0000 } /* Error */\n",
       "body .k { color: #008000; font-weight: bold } /* Keyword */\n",
       "body .o { color: #666666 } /* Operator */\n",
       "body .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
       "body .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
       "body .cp { color: #BC7A00 } /* Comment.Preproc */\n",
       "body .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
       "body .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
       "body .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
       "body .gd { color: #A00000 } /* Generic.Deleted */\n",
       "body .ge { font-style: italic } /* Generic.Emph */\n",
       "body .gr { color: #FF0000 } /* Generic.Error */\n",
       "body .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
       "body .gi { color: #00A000 } /* Generic.Inserted */\n",
       "body .go { color: #888888 } /* Generic.Output */\n",
       "body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
       "body .gs { font-weight: bold } /* Generic.Strong */\n",
       "body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
       "body .gt { color: #0044DD } /* Generic.Traceback */\n",
       "body .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
       "body .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
       "body .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
       "body .kp { color: #008000 } /* Keyword.Pseudo */\n",
       "body .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
       "body .kt { color: #B00040 } /* Keyword.Type */\n",
       "body .m { color: #666666 } /* Literal.Number */\n",
       "body .s { color: #BA2121 } /* Literal.String */\n",
       "body .na { color: #7D9029 } /* Name.Attribute */\n",
       "body .nb { color: #008000 } /* Name.Builtin */\n",
       "body .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
       "body .no { color: #880000 } /* Name.Constant */\n",
       "body .nd { color: #AA22FF } /* Name.Decorator */\n",
       "body .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
       "body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
       "body .nf { color: #0000FF } /* Name.Function */\n",
       "body .nl { color: #A0A000 } /* Name.Label */\n",
       "body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
       "body .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
       "body .nv { color: #19177C } /* Name.Variable */\n",
       "body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
       "body .w { color: #bbbbbb } /* Text.Whitespace */\n",
       "body .mb { color: #666666 } /* Literal.Number.Bin */\n",
       "body .mf { color: #666666 } /* Literal.Number.Float */\n",
       "body .mh { color: #666666 } /* Literal.Number.Hex */\n",
       "body .mi { color: #666666 } /* Literal.Number.Integer */\n",
       "body .mo { color: #666666 } /* Literal.Number.Oct */\n",
       "body .sa { color: #BA2121 } /* Literal.String.Affix */\n",
       "body .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
       "body .sc { color: #BA2121 } /* Literal.String.Char */\n",
       "body .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
       "body .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
       "body .s2 { color: #BA2121 } /* Literal.String.Double */\n",
       "body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
       "body .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
       "body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
       "body .sx { color: #008000 } /* Literal.String.Other */\n",
       "body .sr { color: #BB6688 } /* Literal.String.Regex */\n",
       "body .s1 { color: #BA2121 } /* Literal.String.Single */\n",
       "body .ss { color: #19177C } /* Literal.String.Symbol */\n",
       "body .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
       "body .fm { color: #0000FF } /* Name.Function.Magic */\n",
       "body .vc { color: #19177C } /* Name.Variable.Class */\n",
       "body .vg { color: #19177C } /* Name.Variable.Global */\n",
       "body .vi { color: #19177C } /* Name.Variable.Instance */\n",
       "body .vm { color: #19177C } /* Name.Variable.Magic */\n",
       "body .il { color: #666666 } /* Literal.Number.Integer.Long */\n",
       "\n",
       "  </style>\n",
       "</head>\n",
       "<body>\n",
       "<h2></h2>\n",
       "\n",
       "<div class=\"highlight\"><pre><span></span><span class=\"k\">def</span> <span class=\"nf\">all_hypotheses</span><span class=\"p\">(</span><span class=\"n\">examples</span><span class=\"p\">):</span>\n",
       "    <span class=\"sd\">&quot;&quot;&quot;Build a list of all the possible hypotheses&quot;&quot;&quot;</span>\n",
       "    <span class=\"n\">values</span> <span class=\"o\">=</span> <span class=\"n\">values_table</span><span class=\"p\">(</span><span class=\"n\">examples</span><span class=\"p\">)</span>\n",
       "    <span class=\"n\">h_powerset</span> <span class=\"o\">=</span> <span class=\"n\">powerset</span><span class=\"p\">(</span><span class=\"n\">values</span><span class=\"o\">.</span><span class=\"n\">keys</span><span class=\"p\">())</span>\n",
       "    <span class=\"n\">hypotheses</span> <span class=\"o\">=</span> <span class=\"p\">[]</span>\n",
       "    <span class=\"k\">for</span> <span class=\"n\">s</span> <span class=\"ow\">in</span> <span class=\"n\">h_powerset</span><span class=\"p\">:</span>\n",
       "        <span class=\"n\">hypotheses</span><span class=\"o\">.</span><span class=\"n\">extend</span><span class=\"p\">(</span><span class=\"n\">build_attr_combinations</span><span class=\"p\">(</span><span class=\"n\">s</span><span class=\"p\">,</span> <span class=\"n\">values</span><span class=\"p\">))</span>\n",
       "\n",
       "    <span class=\"n\">hypotheses</span><span class=\"o\">.</span><span class=\"n\">extend</span><span class=\"p\">(</span><span class=\"n\">build_h_combinations</span><span class=\"p\">(</span><span class=\"n\">hypotheses</span><span class=\"p\">))</span>\n",
       "\n",
       "    <span class=\"k\">return</span> <span class=\"n\">hypotheses</span>\n",
       "\n",
       "\n",
       "<span class=\"k\">def</span> <span class=\"nf\">values_table</span><span class=\"p\">(</span><span class=\"n\">examples</span><span class=\"p\">):</span>\n",
       "    <span class=\"sd\">&quot;&quot;&quot;Build a table with all the possible values for each attribute.</span>\n",
       "<span class=\"sd\">    Returns a dictionary with keys the attribute names and values a list</span>\n",
       "<span class=\"sd\">    with the possible values for the corresponding attribute.&quot;&quot;&quot;</span>\n",
       "    <span class=\"n\">values</span> <span class=\"o\">=</span> <span class=\"n\">defaultdict</span><span class=\"p\">(</span><span class=\"k\">lambda</span><span class=\"p\">:</span> <span class=\"p\">[])</span>\n",
       "    <span class=\"k\">for</span> <span class=\"n\">e</span> <span class=\"ow\">in</span> <span class=\"n\">examples</span><span class=\"p\">:</span>\n",
       "        <span class=\"k\">for</span> <span class=\"n\">k</span><span class=\"p\">,</span> <span class=\"n\">v</span> <span class=\"ow\">in</span> <span class=\"n\">e</span><span class=\"o\">.</span><span class=\"n\">items</span><span class=\"p\">():</span>\n",
       "            <span class=\"k\">if</span> <span class=\"n\">k</span> <span class=\"o\">==</span> <span class=\"s1\">&#39;GOAL&#39;</span><span class=\"p\">:</span>\n",
       "                <span class=\"k\">continue</span>\n",
       "\n",
       "            <span class=\"n\">mod</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;!&#39;</span>\n",
       "            <span class=\"k\">if</span> <span class=\"n\">e</span><span class=\"p\">[</span><span class=\"s1\">&#39;GOAL&#39;</span><span class=\"p\">]:</span>\n",
       "                <span class=\"n\">mod</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;&#39;</span>\n",
       "\n",
       "            <span class=\"k\">if</span> <span class=\"n\">mod</span> <span class=\"o\">+</span> <span class=\"n\">v</span> <span class=\"ow\">not</span> <span class=\"ow\">in</span> <span class=\"n\">values</span><span class=\"p\">[</span><span class=\"n\">k</span><span class=\"p\">]:</span>\n",
       "                <span class=\"n\">values</span><span class=\"p\">[</span><span class=\"n\">k</span><span class=\"p\">]</span><span class=\"o\">.</span><span class=\"n\">append</span><span class=\"p\">(</span><span class=\"n\">mod</span> <span class=\"o\">+</span> <span class=\"n\">v</span><span class=\"p\">)</span>\n",
       "\n",
       "    <span class=\"n\">values</span> <span class=\"o\">=</span> <span class=\"nb\">dict</span><span class=\"p\">(</span><span class=\"n\">values</span><span class=\"p\">)</span>\n",
       "    <span class=\"k\">return</span> <span class=\"n\">values</span>\n",
       "</pre></div>\n",
       "</body>\n",
       "</html>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
    "psource(all_hypotheses, values_table)"
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\"\n",
       "   \"http://www.w3.org/TR/html4/strict.dtd\">\n",
       "\n",
       "<html>\n",
       "<head>\n",
       "  <title></title>\n",
       "  <meta http-equiv=\"content-type\" content=\"text/html; charset=None\">\n",
       "  <style type=\"text/css\">\n",
       "td.linenos { background-color: #f0f0f0; padding-right: 10px; }\n",
       "span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }\n",
       "pre { line-height: 125%; }\n",
       "body .hll { background-color: #ffffcc }\n",
       "body  { background: #f8f8f8; }\n",
       "body .c { color: #408080; font-style: italic } /* Comment */\n",
       "body .err { border: 1px solid #FF0000 } /* Error */\n",
       "body .k { color: #008000; font-weight: bold } /* Keyword */\n",
       "body .o { color: #666666 } /* Operator */\n",
       "body .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
       "body .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
       "body .cp { color: #BC7A00 } /* Comment.Preproc */\n",
       "body .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
       "body .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
       "body .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
       "body .gd { color: #A00000 } /* Generic.Deleted */\n",
       "body .ge { font-style: italic } /* Generic.Emph */\n",
       "body .gr { color: #FF0000 } /* Generic.Error */\n",
       "body .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
       "body .gi { color: #00A000 } /* Generic.Inserted */\n",
       "body .go { color: #888888 } /* Generic.Output */\n",
       "body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
       "body .gs { font-weight: bold } /* Generic.Strong */\n",
       "body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
       "body .gt { color: #0044DD } /* Generic.Traceback */\n",
       "body .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
       "body .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
       "body .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
       "body .kp { color: #008000 } /* Keyword.Pseudo */\n",
       "body .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
       "body .kt { color: #B00040 } /* Keyword.Type */\n",
       "body .m { color: #666666 } /* Literal.Number */\n",
       "body .s { color: #BA2121 } /* Literal.String */\n",
       "body .na { color: #7D9029 } /* Name.Attribute */\n",
       "body .nb { color: #008000 } /* Name.Builtin */\n",
       "body .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
       "body .no { color: #880000 } /* Name.Constant */\n",
       "body .nd { color: #AA22FF } /* Name.Decorator */\n",
       "body .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
       "body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
       "body .nf { color: #0000FF } /* Name.Function */\n",
       "body .nl { color: #A0A000 } /* Name.Label */\n",
       "body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
       "body .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
       "body .nv { color: #19177C } /* Name.Variable */\n",
       "body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
       "body .w { color: #bbbbbb } /* Text.Whitespace */\n",
       "body .mb { color: #666666 } /* Literal.Number.Bin */\n",
       "body .mf { color: #666666 } /* Literal.Number.Float */\n",
       "body .mh { color: #666666 } /* Literal.Number.Hex */\n",
       "body .mi { color: #666666 } /* Literal.Number.Integer */\n",
       "body .mo { color: #666666 } /* Literal.Number.Oct */\n",
       "body .sa { color: #BA2121 } /* Literal.String.Affix */\n",
       "body .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
       "body .sc { color: #BA2121 } /* Literal.String.Char */\n",
       "body .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
       "body .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
       "body .s2 { color: #BA2121 } /* Literal.String.Double */\n",
       "body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
       "body .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
       "body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
       "body .sx { color: #008000 } /* Literal.String.Other */\n",
       "body .sr { color: #BB6688 } /* Literal.String.Regex */\n",
       "body .s1 { color: #BA2121 } /* Literal.String.Single */\n",
       "body .ss { color: #19177C } /* Literal.String.Symbol */\n",
       "body .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
       "body .fm { color: #0000FF } /* Name.Function.Magic */\n",
       "body .vc { color: #19177C } /* Name.Variable.Class */\n",
       "body .vg { color: #19177C } /* Name.Variable.Global */\n",
       "body .vi { color: #19177C } /* Name.Variable.Instance */\n",
       "body .vm { color: #19177C } /* Name.Variable.Magic */\n",
       "body .il { color: #666666 } /* Literal.Number.Integer.Long */\n",
       "\n",
       "  </style>\n",
       "</head>\n",
       "<body>\n",
       "<h2></h2>\n",
       "\n",
       "<div class=\"highlight\"><pre><span></span><span class=\"k\">def</span> <span class=\"nf\">build_attr_combinations</span><span class=\"p\">(</span><span class=\"n\">s</span><span class=\"p\">,</span> <span class=\"n\">values</span><span class=\"p\">):</span>\n",
       "    <span class=\"sd\">&quot;&quot;&quot;Given a set of attributes, builds all the combinations of values.</span>\n",
       "<span class=\"sd\">    If the set holds more than one attribute, recursively builds the</span>\n",
       "<span class=\"sd\">    combinations.&quot;&quot;&quot;</span>\n",
       "    <span class=\"k\">if</span> <span class=\"nb\">len</span><span class=\"p\">(</span><span class=\"n\">s</span><span class=\"p\">)</span> <span class=\"o\">==</span> <span class=\"mi\">1</span><span class=\"p\">:</span>\n",
       "        <span class=\"c1\"># s holds just one attribute, return its list of values</span>\n",
       "        <span class=\"n\">k</span> <span class=\"o\">=</span> <span class=\"n\">values</span><span class=\"p\">[</span><span class=\"n\">s</span><span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]]</span>\n",
       "        <span class=\"n\">h</span> <span class=\"o\">=</span> <span class=\"p\">[[{</span><span class=\"n\">s</span><span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]:</span> <span class=\"n\">v</span><span class=\"p\">}]</span> <span class=\"k\">for</span> <span class=\"n\">v</span> <span class=\"ow\">in</span> <span class=\"n\">values</span><span class=\"p\">[</span><span class=\"n\">s</span><span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]]]</span>\n",
       "        <span class=\"k\">return</span> <span class=\"n\">h</span>\n",
       "\n",
       "    <span class=\"n\">h</span> <span class=\"o\">=</span> <span class=\"p\">[]</span>\n",
       "    <span class=\"k\">for</span> <span class=\"n\">i</span><span class=\"p\">,</span> <span class=\"n\">a</span> <span class=\"ow\">in</span> <span class=\"nb\">enumerate</span><span class=\"p\">(</span><span class=\"n\">s</span><span class=\"p\">):</span>\n",
       "        <span class=\"n\">rest</span> <span class=\"o\">=</span> <span class=\"n\">build_attr_combinations</span><span class=\"p\">(</span><span class=\"n\">s</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"o\">+</span><span class=\"mi\">1</span><span class=\"p\">:],</span> <span class=\"n\">values</span><span class=\"p\">)</span>\n",
       "        <span class=\"k\">for</span> <span class=\"n\">v</span> <span class=\"ow\">in</span> <span class=\"n\">values</span><span class=\"p\">[</span><span class=\"n\">a</span><span class=\"p\">]:</span>\n",
       "            <span class=\"n\">o</span> <span class=\"o\">=</span> <span class=\"p\">{</span><span class=\"n\">a</span><span class=\"p\">:</span> <span class=\"n\">v</span><span class=\"p\">}</span>\n",
       "            <span class=\"k\">for</span> <span class=\"n\">r</span> <span class=\"ow\">in</span> <span class=\"n\">rest</span><span class=\"p\">:</span>\n",
       "                <span class=\"n\">t</span> <span class=\"o\">=</span> <span class=\"n\">o</span><span class=\"o\">.</span><span class=\"n\">copy</span><span class=\"p\">()</span>\n",
       "                <span class=\"k\">for</span> <span class=\"n\">d</span> <span class=\"ow\">in</span> <span class=\"n\">r</span><span class=\"p\">:</span>\n",
       "                    <span class=\"n\">t</span><span class=\"o\">.</span><span class=\"n\">update</span><span class=\"p\">(</span><span class=\"n\">d</span><span class=\"p\">)</span>\n",
       "                <span class=\"n\">h</span><span class=\"o\">.</span><span class=\"n\">append</span><span class=\"p\">([</span><span class=\"n\">t</span><span class=\"p\">])</span>\n",
       "\n",
       "    <span class=\"k\">return</span> <span class=\"n\">h</span>\n",
       "\n",
       "\n",
       "<span class=\"k\">def</span> <span class=\"nf\">build_h_combinations</span><span class=\"p\">(</span><span class=\"n\">hypotheses</span><span class=\"p\">):</span>\n",
       "    <span class=\"sd\">&quot;&quot;&quot;Given a set of hypotheses, builds and returns all the combinations of the</span>\n",
       "<span class=\"sd\">    hypotheses.&quot;&quot;&quot;</span>\n",
       "    <span class=\"n\">h</span> <span class=\"o\">=</span> <span class=\"p\">[]</span>\n",
       "    <span class=\"n\">h_powerset</span> <span class=\"o\">=</span> <span class=\"n\">powerset</span><span class=\"p\">(</span><span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"nb\">len</span><span class=\"p\">(</span><span class=\"n\">hypotheses</span><span class=\"p\">)))</span>\n",
       "\n",
       "    <span class=\"k\">for</span> <span class=\"n\">s</span> <span class=\"ow\">in</span> <span class=\"n\">h_powerset</span><span class=\"p\">:</span>\n",
       "        <span class=\"n\">t</span> <span class=\"o\">=</span> <span class=\"p\">[]</span>\n",
       "        <span class=\"k\">for</span> <span class=\"n\">i</span> <span class=\"ow\">in</span> <span class=\"n\">s</span><span class=\"p\">:</span>\n",
       "            <span class=\"n\">t</span><span class=\"o\">.</span><span class=\"n\">extend</span><span class=\"p\">(</span><span class=\"n\">hypotheses</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"p\">])</span>\n",
       "        <span class=\"n\">h</span><span class=\"o\">.</span><span class=\"n\">append</span><span class=\"p\">(</span><span class=\"n\">t</span><span class=\"p\">)</span>\n",
       "\n",
       "    <span class=\"k\">return</span> <span class=\"n\">h</span>\n",
       "</pre></div>\n",
       "</body>\n",
       "</html>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
    "psource(build_attr_combinations, build_h_combinations)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Example\n",
    "\n",
    "Since the set of all possible hypotheses is enormous and would take a long time to generate, we will come up with another, even smaller domain. We will try and predict whether we will have a party or not given the availability of pizza and soda. Let's do it:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [],
   "source": [
    "party = [\n",
    "    {'Pizza': 'Yes', 'Soda': 'No', 'GOAL': True},\n",
    "    {'Pizza': 'Yes', 'Soda': 'Yes', 'GOAL': True},\n",
    "    {'Pizza': 'No', 'Soda': 'No', 'GOAL': False}\n",
    "]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Even though it is obvious that no-pizza no-party, we will run the algorithm and see what other hypotheses are valid."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "True\n",
      "False\n"
     ]
    }
   ],
   "source": [
    "V = version_space_learning(party)\n",
    "for e in party:\n",
    "    guess = False\n",
    "    for h in V:\n",
    "        if guess_value(e, h):\n",
    "            guess = True\n",
    "            break\n",
    "\n",
    "    print(guess)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The results are correct for the given examples. Let's take a look at the version space:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "959\n",
      "[{'Pizza': 'Yes'}, {'Soda': 'Yes'}]\n",
      "[{'Pizza': 'Yes'}, {'Pizza': '!No', 'Soda': 'No'}]\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "print(len(V))\n",
    "\n",
    "print(V[5])\n",
    "print(V[10])\n",
    "\n",
    "print([{'Pizza': 'Yes'}] in V)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "There are almost 1000 hypotheses in the set. You can see that even with just two attributes the version space in very large.\n",
    "\n",
    "Our initial prediction is indeed in the set of hypotheses. Also, the two other random hypotheses we got are consistent with the examples (since they both include the \"Pizza is available\" disjunction)."
   ]
1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Minimal Consistent Determination"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This algorithm is based on a straightforward attempt to find the simplest determination consistent with the observations. A determinaton P > Q says that if any examples match on P, then they must also match on Q. A determination is therefore consistent with a set of examples if every pair that matches on the predicates on the left-hand side also matches on the goal predicate."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Pseudocode"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "Lets look at the pseudocode for this algorithm"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/markdown": [
       "### AIMA3e\n",
       "__function__ Minimal-Consistent-Det(_E_, _A_) __returns__ a set of attributes  \n",
       "&emsp;__inputs__: _E_, a set of examples  \n",
       "&emsp;&emsp;&emsp;&emsp;&emsp;_A_, a set of attributes, of size _n_  \n",
       "\n",
       "&emsp;__for__ _i_ = 0 __to__ _n_ __do__  \n",
       "&emsp;&emsp;&emsp;__for each__ subset _A<sub>i</sub>_ of _A_ of size _i_ __do__  \n",
       "&emsp;&emsp;&emsp;&emsp;&emsp;__if__ Consistent-Det?(_A<sub>i</sub>_, _E_) __then return__ _A<sub>i</sub>_  \n",
       "\n",
       "---\n",
       "__function__ Consistent-Det?(_A_, _E_) __returns__ a truth value  \n",
       "&emsp;__inputs__: _A_, a set of attributes  \n",
       "&emsp;&emsp;&emsp;&emsp;&emsp;_E_, a set of examples  \n",
       "&emsp;__local variables__: _H_, a hash table  \n",
       "\n",
       "&emsp;__for each__ example _e_ __in__ _E_ __do__  \n",
       "&emsp;&emsp;&emsp;__if__ some example in _H_ has the same values as _e_ for the attributes _A_  \n",
       "&emsp;&emsp;&emsp;&emsp;but a different classification __then return__ _false_  \n",
       "&emsp;&emsp;&emsp;store the class of _e_ in_H_, indexed by the values for attributes _A_ of the example _e_  \n",
       "&emsp;__return__ _true_  \n",
       "\n",
       "---\n",
       "__Figure ??__ An algorithm for finding a minimal consistent determination."
      ],
      "text/plain": [
       "<IPython.core.display.Markdown object>"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pseudocode('Minimal-Consistent-Det')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can read the code for the above algorithm by running the cells below:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\"\n",
       "   \"http://www.w3.org/TR/html4/strict.dtd\">\n",
       "\n",
       "<html>\n",
       "<head>\n",
       "  <title></title>\n",
       "  <meta http-equiv=\"content-type\" content=\"text/html; charset=None\">\n",
       "  <style type=\"text/css\">\n",
       "td.linenos { background-color: #f0f0f0; padding-right: 10px; }\n",
       "span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }\n",
       "pre { line-height: 125%; }\n",
       "body .hll { background-color: #ffffcc }\n",
       "body  { background: #f8f8f8; }\n",
       "body .c { color: #408080; font-style: italic } /* Comment */\n",
       "body .err { border: 1px solid #FF0000 } /* Error */\n",
       "body .k { color: #008000; font-weight: bold } /* Keyword */\n",
       "body .o { color: #666666 } /* Operator */\n",
       "body .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
       "body .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
       "body .cp { color: #BC7A00 } /* Comment.Preproc */\n",
       "body .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
       "body .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
       "body .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
       "body .gd { color: #A00000 } /* Generic.Deleted */\n",
       "body .ge { font-style: italic } /* Generic.Emph */\n",
       "body .gr { color: #FF0000 } /* Generic.Error */\n",
       "body .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
       "body .gi { color: #00A000 } /* Generic.Inserted */\n",
       "body .go { color: #888888 } /* Generic.Output */\n",
       "body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
       "body .gs { font-weight: bold } /* Generic.Strong */\n",
       "body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
       "body .gt { color: #0044DD } /* Generic.Traceback */\n",
       "body .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
       "body .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
       "body .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
       "body .kp { color: #008000 } /* Keyword.Pseudo */\n",
       "body .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
       "body .kt { color: #B00040 } /* Keyword.Type */\n",
       "body .m { color: #666666 } /* Literal.Number */\n",
       "body .s { color: #BA2121 } /* Literal.String */\n",
       "body .na { color: #7D9029 } /* Name.Attribute */\n",
       "body .nb { color: #008000 } /* Name.Builtin */\n",
       "body .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
       "body .no { color: #880000 } /* Name.Constant */\n",
       "body .nd { color: #AA22FF } /* Name.Decorator */\n",
       "body .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
       "body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
       "body .nf { color: #0000FF } /* Name.Function */\n",
       "body .nl { color: #A0A000 } /* Name.Label */\n",
       "body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
       "body .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
       "body .nv { color: #19177C } /* Name.Variable */\n",
       "body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
       "body .w { color: #bbbbbb } /* Text.Whitespace */\n",
       "body .mb { color: #666666 } /* Literal.Number.Bin */\n",
       "body .mf { color: #666666 } /* Literal.Number.Float */\n",
       "body .mh { color: #666666 } /* Literal.Number.Hex */\n",
       "body .mi { color: #666666 } /* Literal.Number.Integer */\n",
       "body .mo { color: #666666 } /* Literal.Number.Oct */\n",
       "body .sa { color: #BA2121 } /* Literal.String.Affix */\n",
       "body .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
       "body .sc { color: #BA2121 } /* Literal.String.Char */\n",
       "body .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
       "body .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
       "body .s2 { color: #BA2121 } /* Literal.String.Double */\n",
       "body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
       "body .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
       "body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
       "body .sx { color: #008000 } /* Literal.String.Other */\n",
       "body .sr { color: #BB6688 } /* Literal.String.Regex */\n",
       "body .s1 { color: #BA2121 } /* Literal.String.Single */\n",
       "body .ss { color: #19177C } /* Literal.String.Symbol */\n",
       "body .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
       "body .fm { color: #0000FF } /* Name.Function.Magic */\n",
       "body .vc { color: #19177C } /* Name.Variable.Class */\n",
       "body .vg { color: #19177C } /* Name.Variable.Global */\n",
       "body .vi { color: #19177C } /* Name.Variable.Instance */\n",
       "body .vm { color: #19177C } /* Name.Variable.Magic */\n",
       "body .il { color: #666666 } /* Literal.Number.Integer.Long */\n",
       "\n",
       "  </style>\n",
       "</head>\n",
       "<body>\n",
       "<h2></h2>\n",
       "\n",
       "<div class=\"highlight\"><pre><span></span><span class=\"k\">def</span> <span class=\"nf\">minimal_consistent_det</span><span class=\"p\">(</span><span class=\"n\">E</span><span class=\"p\">,</span> <span class=\"n\">A</span><span class=\"p\">):</span>\n",
       "    <span class=\"sd\">&quot;&quot;&quot;Return a minimal set of attributes which give consistent determination&quot;&quot;&quot;</span>\n",
       "    <span class=\"n\">n</span> <span class=\"o\">=</span> <span class=\"nb\">len</span><span class=\"p\">(</span><span class=\"n\">A</span><span class=\"p\">)</span>\n",
       "\n",
       "    <span class=\"k\">for</span> <span class=\"n\">i</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">n</span> <span class=\"o\">+</span> <span class=\"mi\">1</span><span class=\"p\">):</span>\n",
       "        <span class=\"k\">for</span> <span class=\"n\">A_i</span> <span class=\"ow\">in</span> <span class=\"n\">combinations</span><span class=\"p\">(</span><span class=\"n\">A</span><span class=\"p\">,</span> <span class=\"n\">i</span><span class=\"p\">):</span>\n",
       "            <span class=\"k\">if</span> <span class=\"n\">consistent_det</span><span class=\"p\">(</span><span class=\"n\">A_i</span><span class=\"p\">,</span> <span class=\"n\">E</span><span class=\"p\">):</span>\n",
       "                <span class=\"k\">return</span> <span class=\"nb\">set</span><span class=\"p\">(</span><span class=\"n\">A_i</span><span class=\"p\">)</span>\n",
       "</pre></div>\n",
       "</body>\n",
       "</html>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "psource(minimal_consistent_det)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\"\n",
       "   \"http://www.w3.org/TR/html4/strict.dtd\">\n",
       "\n",
       "<html>\n",
       "<head>\n",
       "  <title></title>\n",
       "  <meta http-equiv=\"content-type\" content=\"text/html; charset=None\">\n",
       "  <style type=\"text/css\">\n",
       "td.linenos { background-color: #f0f0f0; padding-right: 10px; }\n",
       "span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }\n",
       "pre { line-height: 125%; }\n",
       "body .hll { background-color: #ffffcc }\n",
       "body  { background: #f8f8f8; }\n",
       "body .c { color: #408080; font-style: italic } /* Comment */\n",
       "body .err { border: 1px solid #FF0000 } /* Error */\n",
       "body .k { color: #008000; font-weight: bold } /* Keyword */\n",
       "body .o { color: #666666 } /* Operator */\n",
       "body .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
       "body .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
       "body .cp { color: #BC7A00 } /* Comment.Preproc */\n",
       "body .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
       "body .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
       "body .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
       "body .gd { color: #A00000 } /* Generic.Deleted */\n",
       "body .ge { font-style: italic } /* Generic.Emph */\n",
       "body .gr { color: #FF0000 } /* Generic.Error */\n",
       "body .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
       "body .gi { color: #00A000 } /* Generic.Inserted */\n",
       "body .go { color: #888888 } /* Generic.Output */\n",
       "body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
       "body .gs { font-weight: bold } /* Generic.Strong */\n",
       "body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
       "body .gt { color: #0044DD } /* Generic.Traceback */\n",
       "body .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
       "body .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
       "body .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
       "body .kp { color: #008000 } /* Keyword.Pseudo */\n",
       "body .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
       "body .kt { color: #B00040 } /* Keyword.Type */\n",
       "body .m { color: #666666 } /* Literal.Number */\n",
       "body .s { color: #BA2121 } /* Literal.String */\n",
       "body .na { color: #7D9029 } /* Name.Attribute */\n",
       "body .nb { color: #008000 } /* Name.Builtin */\n",
       "body .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
       "body .no { color: #880000 } /* Name.Constant */\n",
       "body .nd { color: #AA22FF } /* Name.Decorator */\n",
       "body .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
       "body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
       "body .nf { color: #0000FF } /* Name.Function */\n",
       "body .nl { color: #A0A000 } /* Name.Label */\n",
       "body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
       "body .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
       "body .nv { color: #19177C } /* Name.Variable */\n",
       "body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
       "body .w { color: #bbbbbb } /* Text.Whitespace */\n",
       "body .mb { color: #666666 } /* Literal.Number.Bin */\n",
       "body .mf { color: #666666 } /* Literal.Number.Float */\n",
       "body .mh { color: #666666 } /* Literal.Number.Hex */\n",
       "body .mi { color: #666666 } /* Literal.Number.Integer */\n",
       "body .mo { color: #666666 } /* Literal.Number.Oct */\n",
       "body .sa { color: #BA2121 } /* Literal.String.Affix */\n",
       "body .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
       "body .sc { color: #BA2121 } /* Literal.String.Char */\n",
       "body .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
       "body .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
       "body .s2 { color: #BA2121 } /* Literal.String.Double */\n",
       "body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
       "body .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
       "body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
       "body .sx { color: #008000 } /* Literal.String.Other */\n",
       "body .sr { color: #BB6688 } /* Literal.String.Regex */\n",
       "body .s1 { color: #BA2121 } /* Literal.String.Single */\n",
       "body .ss { color: #19177C } /* Literal.String.Symbol */\n",
       "body .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
       "body .fm { color: #0000FF } /* Name.Function.Magic */\n",
       "body .vc { color: #19177C } /* Name.Variable.Class */\n",
       "body .vg { color: #19177C } /* Name.Variable.Global */\n",
       "body .vi { color: #19177C } /* Name.Variable.Instance */\n",
       "body .vm { color: #19177C } /* Name.Variable.Magic */\n",
       "body .il { color: #666666 } /* Literal.Number.Integer.Long */\n",
       "\n",
       "  </style>\n",
       "</head>\n",
       "<body>\n",
       "<h2></h2>\n",
       "\n",
       "<div class=\"highlight\"><pre><span></span><span class=\"k\">def</span> <span class=\"nf\">consistent_det</span><span class=\"p\">(</span><span class=\"n\">A</span><span class=\"p\">,</span> <span class=\"n\">E</span><span class=\"p\">):</span>\n",
       "    <span class=\"sd\">&quot;&quot;&quot;Check if the attributes(A) is consistent with the examples(E)&quot;&quot;&quot;</span>\n",
       "    <span class=\"n\">H</span> <span class=\"o\">=</span> <span class=\"p\">{}</span>\n",
       "\n",
       "    <span class=\"k\">for</span> <span class=\"n\">e</span> <span class=\"ow\">in</span> <span class=\"n\">E</span><span class=\"p\">:</span>\n",
       "        <span class=\"n\">attr_values</span> <span class=\"o\">=</span> <span class=\"nb\">tuple</span><span class=\"p\">(</span><span class=\"n\">e</span><span class=\"p\">[</span><span class=\"n\">attr</span><span class=\"p\">]</span> <span class=\"k\">for</span> <span class=\"n\">attr</span> <span class=\"ow\">in</span> <span class=\"n\">A</span><span class=\"p\">)</span>\n",
       "        <span class=\"k\">if</span> <span class=\"n\">attr_values</span> <span class=\"ow\">in</span> <span class=\"n\">H</span> <span class=\"ow\">and</span> <span class=\"n\">H</span><span class=\"p\">[</span><span class=\"n\">attr_values</span><span class=\"p\">]</span> <span class=\"o\">!=</span> <span class=\"n\">e</span><span class=\"p\">[</span><span class=\"s1\">&#39;GOAL&#39;</span><span class=\"p\">]:</span>\n",
       "            <span class=\"k\">return</span> <span class=\"bp\">False</span>\n",
       "        <span class=\"n\">H</span><span class=\"p\">[</span><span class=\"n\">attr_values</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">e</span><span class=\"p\">[</span><span class=\"s1\">&#39;GOAL&#39;</span><span class=\"p\">]</span>\n",
       "\n",
       "    <span class=\"k\">return</span> <span class=\"bp\">True</span>\n",
       "</pre></div>\n",
       "</body>\n",
       "</html>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "psource(consistent_det)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Example:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We already know that no-pizza-no-party but we will still check it through the `minimal_consistent_det` algorithm."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'Pizza'}\n"
     ]
    }
   ],
   "source": [
    "print(minimal_consistent_det(party, {'Pizza', 'Soda'}))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can also check it on some other example. Let's consider the following example :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [],
   "source": [
    "conductance = [\n",
    "    {'Sample': 'S1', 'Mass': 12, 'Temp': 26, 'Material': 'Cu', 'Size': 3, 'GOAL': 0.59},\n",
    "    {'Sample': 'S1', 'Mass': 12, 'Temp': 100, 'Material': 'Cu', 'Size': 3, 'GOAL': 0.57},\n",
    "    {'Sample': 'S2', 'Mass': 24, 'Temp': 26, 'Material': 'Cu', 'Size': 6, 'GOAL': 0.59},\n",
    "    {'Sample': 'S3', 'Mass': 12, 'Temp': 26, 'Material': 'Pb', 'Size': 2, 'GOAL': 0.05},\n",
    "    {'Sample': 'S3', 'Mass': 12, 'Temp': 100, 'Material': 'Pb', 'Size': 2, 'GOAL': 0.04},\n",
    "    {'Sample': 'S4', 'Mass': 18, 'Temp': 100, 'Material': 'Pb', 'Size': 3, 'GOAL': 0.04},\n",
    "    {'Sample': 'S4', 'Mass': 18, 'Temp': 100, 'Material': 'Pb', 'Size': 3, 'GOAL': 0.04},\n",
    "    {'Sample': 'S5', 'Mass': 24, 'Temp': 100, 'Material': 'Pb', 'Size': 4, 'GOAL': 0.04},\n",
    "    {'Sample': 'S6', 'Mass': 36, 'Temp': 26, 'Material': 'Pb', 'Size': 6, 'GOAL': 0.05},\n",
    "]\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now, we check the `minimal_consistent_det` algorithm on the above example:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'Temp', 'Material'}\n"
     ]
    }
   ],
   "source": [
    "print(minimal_consistent_det(conductance, {'Mass', 'Temp', 'Material', 'Size'}))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'Temp', 'Size', 'Mass'}\n"
     ]
    }
   ],
   "source": [
    "print(minimal_consistent_det(conductance, {'Mass', 'Temp', 'Size'}))\n"
   ]
  }
 ],
 "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",
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}