planning.ipynb 397 ko
Newer Older
Kaivalya Rawal's avatar
Kaivalya Rawal a validé
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "# Planning\n",
    "#### Chapters 10-11\n",
    "----"
Kaivalya Rawal's avatar
Kaivalya Rawal a validé
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This notebook serves as supporting material for topics covered in **Chapter 10 - Classical Planning** and **Chapter 11 - Planning and Acting in the Real World** from the book *[Artificial Intelligence: A Modern Approach](http://aima.cs.berkeley.edu)*. \n",
    "This notebook uses implementations from the [planning.py](https://github.com/aimacode/aima-python/blob/master/planning.py) module. \n",
    "See the [intro notebook](https://github.com/aimacode/aima-python/blob/master/intro.ipynb) for instructions.\n",
Kaivalya Rawal's avatar
Kaivalya Rawal a validé
    "\n",
    "We'll start by looking at `PlanningProblem` and `Action` data types for defining problems and actions. \n",
    "Then, we will see how to use them by trying to plan a trip from *Sibiu* to *Bucharest* across the familiar map of Romania, from [search.ipynb](https://github.com/aimacode/aima-python/blob/master/search.ipynb) \n",
    "followed by some common planning problems and methods of solving them.\n",
Kaivalya Rawal's avatar
Kaivalya Rawal a validé
    "\n",
    "Let's start by importing everything from the planning module."
jeff3456's avatar
jeff3456 a validé
  {
   "cell_type": "code",
Kaivalya Rawal's avatar
Kaivalya Rawal a validé
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from planning import *\n",
    "from notebook import psource"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## CONTENTS\n",
    "\n",
    "**Classical Planning**\n",
    "- PlanningProblem\n",
    "- Action\n",
    "- Planning Problems\n",
    "    * Air cargo problem\n",
    "    * Spare tire problem\n",
    "    * Three block tower problem\n",
    "    * Shopping Problem\n",
    "    * Socks and shoes problem\n",
    "    * Cake problem\n",
    "- Solving Planning Problems\n",
    "    * GraphPlan\n",
    "    * Linearize\n",
    "    * PartialOrderPlanner\n",
    "<br>\n",
    "\n",
    "**Planning in the real world**\n",
    "- Problem\n",
    "- HLA\n",
    "- Planning Problems\n",
    "    * Job shop problem\n",
    "    * Double tennis problem\n",
    "- Solving Planning Problems\n",
    "    * Hierarchical Search\n",
    "    * Angelic Search"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## PlanningProblem\n",
    "\n",
    "PDDL stands for Planning Domain Definition Language.\n",
    "The `PlanningProblem` class is used to represent planning problems in this module. The following attributes are essential to be able to define a problem:\n",
    "* an initial state\n",
    "* a set of goals\n",
    "* a set of viable actions that can be executed in the search space of the problem\n",
    "\n",
    "View the source to see how the Python code tries to realise these."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "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\">class</span> <span class=\"nc\">PlanningProblem</span><span class=\"p\">:</span>\n",
       "    <span class=\"sd\">&quot;&quot;&quot;</span>\n",
       "<span class=\"sd\">    Planning Domain Definition Language (PlanningProblem) used to define a search problem.</span>\n",
       "<span class=\"sd\">    It stores states in a knowledge base consisting of first order logic statements.</span>\n",
       "<span class=\"sd\">    The conjunction of these logical statements completely defines a state.</span>\n",
       "<span class=\"sd\">    &quot;&quot;&quot;</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">init</span><span class=\"p\">,</span> <span class=\"n\">goals</span><span class=\"p\">,</span> <span class=\"n\">actions</span><span class=\"p\">):</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">init</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">convert</span><span class=\"p\">(</span><span class=\"n\">init</span><span class=\"p\">)</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">goals</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">convert</span><span class=\"p\">(</span><span class=\"n\">goals</span><span class=\"p\">)</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">actions</span> <span class=\"o\">=</span> <span class=\"n\">actions</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">convert</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">clauses</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;Converts strings into exprs&quot;&quot;&quot;</span>\n",
       "        <span class=\"k\">if</span> <span class=\"ow\">not</span> <span class=\"nb\">isinstance</span><span class=\"p\">(</span><span class=\"n\">clauses</span><span class=\"p\">,</span> <span class=\"n\">Expr</span><span class=\"p\">):</span>\n",
       "            <span class=\"k\">if</span> <span class=\"nb\">len</span><span class=\"p\">(</span><span class=\"n\">clauses</span><span class=\"p\">)</span> <span class=\"o\">&gt;</span> <span class=\"mi\">0</span><span class=\"p\">:</span>\n",
       "                <span class=\"n\">clauses</span> <span class=\"o\">=</span> <span class=\"n\">expr</span><span class=\"p\">(</span><span class=\"n\">clauses</span><span class=\"p\">)</span>\n",
       "            <span class=\"k\">else</span><span class=\"p\">:</span>\n",
       "                <span class=\"n\">clauses</span> <span class=\"o\">=</span> <span class=\"p\">[]</span>\n",
       "        <span class=\"k\">try</span><span class=\"p\">:</span>\n",
       "            <span class=\"n\">clauses</span> <span class=\"o\">=</span> <span class=\"n\">conjuncts</span><span class=\"p\">(</span><span class=\"n\">clauses</span><span class=\"p\">)</span>\n",
       "        <span class=\"k\">except</span> <span class=\"ne\">AttributeError</span><span class=\"p\">:</span>\n",
       "            <span class=\"n\">clauses</span> <span class=\"o\">=</span> <span class=\"n\">clauses</span>\n",
       "\n",
       "        <span class=\"n\">new_clauses</span> <span class=\"o\">=</span> <span class=\"p\">[]</span>\n",
       "        <span class=\"k\">for</span> <span class=\"n\">clause</span> <span class=\"ow\">in</span> <span class=\"n\">clauses</span><span class=\"p\">:</span>\n",
       "            <span class=\"k\">if</span> <span class=\"n\">clause</span><span class=\"o\">.</span><span class=\"n\">op</span> <span class=\"o\">==</span> <span class=\"s1\">&#39;~&#39;</span><span class=\"p\">:</span>\n",
       "                <span class=\"n\">new_clauses</span><span class=\"o\">.</span><span class=\"n\">append</span><span class=\"p\">(</span><span class=\"n\">expr</span><span class=\"p\">(</span><span class=\"s1\">&#39;Not&#39;</span> <span class=\"o\">+</span> <span class=\"nb\">str</span><span class=\"p\">(</span><span class=\"n\">clause</span><span class=\"o\">.</span><span class=\"n\">args</span><span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">])))</span>\n",
       "            <span class=\"k\">else</span><span class=\"p\">:</span>\n",
       "                <span class=\"n\">new_clauses</span><span class=\"o\">.</span><span class=\"n\">append</span><span class=\"p\">(</span><span class=\"n\">clause</span><span class=\"p\">)</span>\n",
       "        <span class=\"k\">return</span> <span class=\"n\">new_clauses</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">goal_test</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;Checks if the goals have been reached&quot;&quot;&quot;</span>\n",
       "        <span class=\"k\">return</span> <span class=\"nb\">all</span><span class=\"p\">(</span><span class=\"n\">goal</span> <span class=\"ow\">in</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">init</span> <span class=\"k\">for</span> <span class=\"n\">goal</span> <span class=\"ow\">in</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">goals</span><span class=\"p\">)</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">act</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">action</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;</span>\n",
       "<span class=\"sd\">        Performs the action given as argument.</span>\n",
       "<span class=\"sd\">        Note that action is an Expr like expr(&#39;Remove(Glass, Table)&#39;) or expr(&#39;Eat(Sandwich)&#39;)</span>\n",
       "<span class=\"sd\">        &quot;&quot;&quot;</span>       \n",
       "        <span class=\"n\">action_name</span> <span class=\"o\">=</span> <span class=\"n\">action</span><span class=\"o\">.</span><span class=\"n\">op</span>\n",
       "        <span class=\"n\">args</span> <span class=\"o\">=</span> <span class=\"n\">action</span><span class=\"o\">.</span><span class=\"n\">args</span>\n",
       "        <span class=\"n\">list_action</span> <span class=\"o\">=</span> <span class=\"n\">first</span><span class=\"p\">(</span><span class=\"n\">a</span> <span class=\"k\">for</span> <span class=\"n\">a</span> <span class=\"ow\">in</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">actions</span> <span class=\"k\">if</span> <span class=\"n\">a</span><span class=\"o\">.</span><span class=\"n\">name</span> <span class=\"o\">==</span> <span class=\"n\">action_name</span><span class=\"p\">)</span>\n",
       "        <span class=\"k\">if</span> <span class=\"n\">list_action</span> <span class=\"ow\">is</span> <span class=\"bp\">None</span><span class=\"p\">:</span>\n",
       "            <span class=\"k\">raise</span> <span class=\"ne\">Exception</span><span class=\"p\">(</span><span class=\"s2\">&quot;Action &#39;{}&#39; not found&quot;</span><span class=\"o\">.</span><span class=\"n\">format</span><span class=\"p\">(</span><span class=\"n\">action_name</span><span class=\"p\">))</span>\n",
       "        <span class=\"k\">if</span> <span class=\"ow\">not</span> <span class=\"n\">list_action</span><span class=\"o\">.</span><span class=\"n\">check_precond</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">init</span><span class=\"p\">,</span> <span class=\"n\">args</span><span class=\"p\">):</span>\n",
       "            <span class=\"k\">raise</span> <span class=\"ne\">Exception</span><span class=\"p\">(</span><span class=\"s2\">&quot;Action &#39;{}&#39; pre-conditions not satisfied&quot;</span><span class=\"o\">.</span><span class=\"n\">format</span><span class=\"p\">(</span><span class=\"n\">action</span><span class=\"p\">))</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">init</span> <span class=\"o\">=</span> <span class=\"n\">list_action</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">init</span><span class=\"p\">,</span> <span class=\"n\">args</span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">clauses</span>\n",
       "</pre></div>\n",
       "</body>\n",
       "</html>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "psource(PlanningProblem)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `init` attribute is an expression that forms the initial knowledge base for the problem.\n",
    "<br>\n",
    "The `goals` attribute is an expression that indicates the goals to be reached by the problem.\n",
    "<br>\n",
    "Lastly, `actions` contains a list of `Action` objects that may be executed in the search space of the problem.\n",
    "<br>\n",
    "The `goal_test` method checks if the goal has been reached.\n",
    "<br>\n",
    "The `act` method acts out the given action and updates the current state.\n",
    "<br>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ACTION\n",
    "\n",
    "To be able to model a planning problem properly, it is essential to be able to represent an Action. Each action we model requires at least three things:\n",
    "* preconditions that the action must meet\n",
    "* the effects of executing the action\n",
    "* some expression that represents the action"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The module models actions using the `Action` class"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "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\">class</span> <span class=\"nc\">Action</span><span class=\"p\">:</span>\n",
       "    <span class=\"sd\">&quot;&quot;&quot;</span>\n",
       "<span class=\"sd\">    Defines an action schema using preconditions and effects.</span>\n",
       "<span class=\"sd\">    Use this to describe actions in PlanningProblem.</span>\n",
       "<span class=\"sd\">    action is an Expr where variables are given as arguments(args).</span>\n",
       "<span class=\"sd\">    Precondition and effect are both lists with positive and negative literals.</span>\n",
       "<span class=\"sd\">    Negative preconditions and effects are defined by adding a &#39;Not&#39; before the name of the clause</span>\n",
       "<span class=\"sd\">    Example:</span>\n",
       "<span class=\"sd\">    precond = [expr(&quot;Human(person)&quot;), expr(&quot;Hungry(Person)&quot;), expr(&quot;NotEaten(food)&quot;)]</span>\n",
       "<span class=\"sd\">    effect = [expr(&quot;Eaten(food)&quot;), expr(&quot;Hungry(person)&quot;)]</span>\n",
       "<span class=\"sd\">    eat = Action(expr(&quot;Eat(person, food)&quot;), precond, effect)</span>\n",
       "<span class=\"sd\">    &quot;&quot;&quot;</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">action</span><span class=\"p\">,</span> <span class=\"n\">precond</span><span class=\"p\">,</span> <span class=\"n\">effect</span><span class=\"p\">):</span>\n",
       "        <span class=\"k\">if</span> <span class=\"nb\">isinstance</span><span class=\"p\">(</span><span class=\"n\">action</span><span class=\"p\">,</span> <span class=\"nb\">str</span><span class=\"p\">):</span>\n",
       "            <span class=\"n\">action</span> <span class=\"o\">=</span> <span class=\"n\">expr</span><span class=\"p\">(</span><span class=\"n\">action</span><span class=\"p\">)</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">name</span> <span class=\"o\">=</span> <span class=\"n\">action</span><span class=\"o\">.</span><span class=\"n\">op</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">args</span> <span class=\"o\">=</span> <span class=\"n\">action</span><span class=\"o\">.</span><span class=\"n\">args</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">precond</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">convert</span><span class=\"p\">(</span><span class=\"n\">precond</span><span class=\"p\">)</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">effect</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">convert</span><span class=\"p\">(</span><span class=\"n\">effect</span><span class=\"p\">)</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"fm\">__call__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">kb</span><span class=\"p\">,</span> <span class=\"n\">args</span><span class=\"p\">):</span>\n",
       "        <span class=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">act</span><span class=\"p\">(</span><span class=\"n\">kb</span><span class=\"p\">,</span> <span class=\"n\">args</span><span class=\"p\">)</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"fm\">__repr__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n",
       "        <span class=\"k\">return</span> <span class=\"s1\">&#39;{}({})&#39;</span><span class=\"o\">.</span><span class=\"n\">format</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"vm\">__class__</span><span class=\"o\">.</span><span class=\"vm\">__name__</span><span class=\"p\">,</span> <span class=\"n\">Expr</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">name</span><span class=\"p\">,</span> <span class=\"o\">*</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">args</span><span class=\"p\">))</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">convert</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">clauses</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;Converts strings into Exprs&quot;&quot;&quot;</span>\n",
       "        <span class=\"k\">if</span> <span class=\"nb\">isinstance</span><span class=\"p\">(</span><span class=\"n\">clauses</span><span class=\"p\">,</span> <span class=\"n\">Expr</span><span class=\"p\">):</span>\n",
       "            <span class=\"n\">clauses</span> <span class=\"o\">=</span> <span class=\"n\">conjuncts</span><span class=\"p\">(</span><span class=\"n\">clauses</span><span class=\"p\">)</span>\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=\"nb\">len</span><span class=\"p\">(</span><span class=\"n\">clauses</span><span class=\"p\">)):</span>\n",
       "                <span class=\"k\">if</span> <span class=\"n\">clauses</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"p\">]</span><span class=\"o\">.</span><span class=\"n\">op</span> <span class=\"o\">==</span> <span class=\"s1\">&#39;~&#39;</span><span class=\"p\">:</span>\n",
       "                    <span class=\"n\">clauses</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">expr</span><span class=\"p\">(</span><span class=\"s1\">&#39;Not&#39;</span> <span class=\"o\">+</span> <span class=\"nb\">str</span><span class=\"p\">(</span><span class=\"n\">clauses</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"p\">]</span><span class=\"o\">.</span><span class=\"n\">args</span><span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]))</span>\n",
       "        <span class=\"k\">elif</span> <span class=\"nb\">isinstance</span><span class=\"p\">(</span><span class=\"n\">clauses</span><span class=\"p\">,</span> <span class=\"nb\">str</span><span class=\"p\">):</span>\n",
       "            <span class=\"n\">clauses</span> <span class=\"o\">=</span> <span class=\"n\">clauses</span><span class=\"o\">.</span><span class=\"n\">replace</span><span class=\"p\">(</span><span class=\"s1\">&#39;~&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;Not&#39;</span><span class=\"p\">)</span>\n",
       "            <span class=\"k\">if</span> <span class=\"nb\">len</span><span class=\"p\">(</span><span class=\"n\">clauses</span><span class=\"p\">)</span> <span class=\"o\">&gt;</span> <span class=\"mi\">0</span><span class=\"p\">:</span>\n",
       "                <span class=\"n\">clauses</span> <span class=\"o\">=</span> <span class=\"n\">expr</span><span class=\"p\">(</span><span class=\"n\">clauses</span><span class=\"p\">)</span>\n",
       "            <span class=\"k\">try</span><span class=\"p\">:</span>\n",
       "                <span class=\"n\">clauses</span> <span class=\"o\">=</span> <span class=\"n\">conjuncts</span><span class=\"p\">(</span><span class=\"n\">clauses</span><span class=\"p\">)</span>\n",
       "            <span class=\"k\">except</span> <span class=\"ne\">AttributeError</span><span class=\"p\">:</span>\n",
       "                <span class=\"k\">pass</span>\n",
       "        <span class=\"k\">return</span> <span class=\"n\">clauses</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">substitute</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">e</span><span class=\"p\">,</span> <span class=\"n\">args</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;Replaces variables in expression with their respective Propositional symbol&quot;&quot;&quot;</span>\n",
       "\n",
       "        <span class=\"n\">new_args</span> <span class=\"o\">=</span> <span class=\"nb\">list</span><span class=\"p\">(</span><span class=\"n\">e</span><span class=\"o\">.</span><span class=\"n\">args</span><span class=\"p\">)</span>\n",
       "        <span class=\"k\">for</span> <span class=\"n\">num</span><span class=\"p\">,</span> <span class=\"n\">x</span> <span class=\"ow\">in</span> <span class=\"nb\">enumerate</span><span class=\"p\">(</span><span class=\"n\">e</span><span class=\"o\">.</span><span class=\"n\">args</span><span class=\"p\">):</span>\n",
       "            <span class=\"k\">for</span> <span class=\"n\">i</span><span class=\"p\">,</span> <span class=\"n\">_</span> <span class=\"ow\">in</span> <span class=\"nb\">enumerate</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">args</span><span class=\"p\">):</span>\n",
       "                <span class=\"k\">if</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">args</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"p\">]</span> <span class=\"o\">==</span> <span class=\"n\">x</span><span class=\"p\">:</span>\n",
       "                    <span class=\"n\">new_args</span><span class=\"p\">[</span><span class=\"n\">num</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">args</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"p\">]</span>\n",
       "        <span class=\"k\">return</span> <span class=\"n\">Expr</span><span class=\"p\">(</span><span class=\"n\">e</span><span class=\"o\">.</span><span class=\"n\">op</span><span class=\"p\">,</span> <span class=\"o\">*</span><span class=\"n\">new_args</span><span class=\"p\">)</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">check_precond</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">kb</span><span class=\"p\">,</span> <span class=\"n\">args</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;Checks if the precondition is satisfied in the current state&quot;&quot;&quot;</span>\n",
       "\n",
       "        <span class=\"k\">if</span> <span class=\"nb\">isinstance</span><span class=\"p\">(</span><span class=\"n\">kb</span><span class=\"p\">,</span> <span class=\"nb\">list</span><span class=\"p\">):</span>\n",
       "            <span class=\"n\">kb</span> <span class=\"o\">=</span> <span class=\"n\">FolKB</span><span class=\"p\">(</span><span class=\"n\">kb</span><span class=\"p\">)</span>\n",
       "        <span class=\"k\">for</span> <span class=\"n\">clause</span> <span class=\"ow\">in</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">precond</span><span class=\"p\">:</span>\n",
       "            <span class=\"k\">if</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">substitute</span><span class=\"p\">(</span><span class=\"n\">clause</span><span class=\"p\">,</span> <span class=\"n\">args</span><span class=\"p\">)</span> <span class=\"ow\">not</span> <span class=\"ow\">in</span> <span class=\"n\">kb</span><span class=\"o\">.</span><span class=\"n\">clauses</span><span class=\"p\">:</span>\n",
       "                <span class=\"k\">return</span> <span class=\"bp\">False</span>\n",
       "        <span class=\"k\">return</span> <span class=\"bp\">True</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">act</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">kb</span><span class=\"p\">,</span> <span class=\"n\">args</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;Executes the action on the state&#39;s knowledge base&quot;&quot;&quot;</span>\n",
       "\n",
       "        <span class=\"k\">if</span> <span class=\"nb\">isinstance</span><span class=\"p\">(</span><span class=\"n\">kb</span><span class=\"p\">,</span> <span class=\"nb\">list</span><span class=\"p\">):</span>\n",
       "            <span class=\"n\">kb</span> <span class=\"o\">=</span> <span class=\"n\">FolKB</span><span class=\"p\">(</span><span class=\"n\">kb</span><span class=\"p\">)</span>\n",
       "\n",
       "        <span class=\"k\">if</span> <span class=\"ow\">not</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">check_precond</span><span class=\"p\">(</span><span class=\"n\">kb</span><span class=\"p\">,</span> <span class=\"n\">args</span><span class=\"p\">):</span>\n",
       "            <span class=\"k\">raise</span> <span class=\"ne\">Exception</span><span class=\"p\">(</span><span class=\"s1\">&#39;Action pre-conditions not satisfied&#39;</span><span class=\"p\">)</span>\n",
       "        <span class=\"k\">for</span> <span class=\"n\">clause</span> <span class=\"ow\">in</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">effect</span><span class=\"p\">:</span>\n",
       "            <span class=\"n\">kb</span><span class=\"o\">.</span><span class=\"n\">tell</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">substitute</span><span class=\"p\">(</span><span class=\"n\">clause</span><span class=\"p\">,</span> <span class=\"n\">args</span><span class=\"p\">))</span>\n",
       "            <span class=\"k\">if</span> <span class=\"n\">clause</span><span class=\"o\">.</span><span class=\"n\">op</span><span class=\"p\">[:</span><span class=\"mi\">3</span><span class=\"p\">]</span> <span class=\"o\">==</span> <span class=\"s1\">&#39;Not&#39;</span><span class=\"p\">:</span>\n",
       "                <span class=\"n\">new_clause</span> <span class=\"o\">=</span> <span class=\"n\">Expr</span><span class=\"p\">(</span><span class=\"n\">clause</span><span class=\"o\">.</span><span class=\"n\">op</span><span class=\"p\">[</span><span class=\"mi\">3</span><span class=\"p\">:],</span> <span class=\"o\">*</span><span class=\"n\">clause</span><span class=\"o\">.</span><span class=\"n\">args</span><span class=\"p\">)</span>\n",
       "\n",
       "                <span class=\"k\">if</span> <span class=\"n\">kb</span><span class=\"o\">.</span><span class=\"n\">ask</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">substitute</span><span class=\"p\">(</span><span class=\"n\">new_clause</span><span class=\"p\">,</span> <span class=\"n\">args</span><span class=\"p\">))</span> <span class=\"ow\">is</span> <span class=\"ow\">not</span> <span class=\"bp\">False</span><span class=\"p\">:</span>\n",
       "                    <span class=\"n\">kb</span><span class=\"o\">.</span><span class=\"n\">retract</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">substitute</span><span class=\"p\">(</span><span class=\"n\">new_clause</span><span class=\"p\">,</span> <span class=\"n\">args</span><span class=\"p\">))</span>\n",
       "            <span class=\"k\">else</span><span class=\"p\">:</span>\n",
       "                <span class=\"n\">new_clause</span> <span class=\"o\">=</span> <span class=\"n\">Expr</span><span class=\"p\">(</span><span class=\"s1\">&#39;Not&#39;</span> <span class=\"o\">+</span> <span class=\"n\">clause</span><span class=\"o\">.</span><span class=\"n\">op</span><span class=\"p\">,</span> <span class=\"o\">*</span><span class=\"n\">clause</span><span class=\"o\">.</span><span class=\"n\">args</span><span class=\"p\">)</span>\n",
       "\n",
       "                <span class=\"k\">if</span> <span class=\"n\">kb</span><span class=\"o\">.</span><span class=\"n\">ask</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">substitute</span><span class=\"p\">(</span><span class=\"n\">new_clause</span><span class=\"p\">,</span> <span class=\"n\">args</span><span class=\"p\">))</span> <span class=\"ow\">is</span> <span class=\"ow\">not</span> <span class=\"bp\">False</span><span class=\"p\">:</span>    \n",
       "                    <span class=\"n\">kb</span><span class=\"o\">.</span><span class=\"n\">retract</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">substitute</span><span class=\"p\">(</span><span class=\"n\">new_clause</span><span class=\"p\">,</span> <span class=\"n\">args</span><span class=\"p\">))</span>\n",
       "\n",
       "        <span class=\"k\">return</span> <span class=\"n\">kb</span>\n",
       "</pre></div>\n",
       "</body>\n",
       "</html>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "psource(Action)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This class represents an action given the expression, the preconditions and its effects. \n",
    "A list `precond` stores the preconditions of the action and a list `effect` stores its effects.\n",
    "Negative preconditions and effects are input using a `~` symbol before the clause, which are internally prefixed with a `Not` to make it easier to work with.\n",
    "For example, the negation of `At(obj, loc)` will be input as `~At(obj, loc)` and internally represented as `NotAt(obj, loc)`. \n",
    "This equivalently creates a new clause for each negative literal, removing the hassle of maintaining two separate knowledge bases.\n",
    "This greatly simplifies algorithms like `GraphPlan` as we will see later.\n",
    "The `convert` method takes an input string, parses it, removes conjunctions if any and returns a list of `Expr` objects.\n",
    "The `check_precond` method checks if the preconditions for that action are valid, given a `kb`.\n",
    "The `act` method carries out the action on the given knowledge base."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now lets try to define a planning problem using these tools. Since we already know about the map of Romania, lets see if we can plan a trip across a simplified map of Romania.\n",
    "\n",
    "Here is our simplified map definition:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from utils import *\n",
    "# this imports the required expr so we can create our knowledge base\n",
    "\n",
    "knowledge_base = [\n",
    "    expr(\"Connected(Bucharest,Pitesti)\"),\n",
    "    expr(\"Connected(Pitesti,Rimnicu)\"),\n",
    "    expr(\"Connected(Rimnicu,Sibiu)\"),\n",
    "    expr(\"Connected(Sibiu,Fagaras)\"),\n",
    "    expr(\"Connected(Fagaras,Bucharest)\"),\n",
    "    expr(\"Connected(Pitesti,Craiova)\"),\n",
    "    expr(\"Connected(Craiova,Rimnicu)\")\n",
    "    ]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let us add some logic propositions to complete our knowledge about travelling around the map. These are the typical symmetry and transitivity properties of connections on a map. We can now be sure that our `knowledge_base` understands what it truly means for two locations to be connected in the sense usually meant by humans when we use the term.\n",
    "\n",
    "Let's also add our starting location - *Sibiu* to the map."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "knowledge_base.extend([\n",
    "     expr(\"Connected(x,y) ==> Connected(y,x)\"),\n",
    "     expr(\"Connected(x,y) & Connected(y,z) ==> Connected(x,z)\"),\n",
    "     expr(\"At(Sibiu)\")\n",
    "    ])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We now have a complete knowledge base, which can be seen like this:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[Connected(Bucharest, Pitesti),\n",
       " Connected(Pitesti, Rimnicu),\n",
       " Connected(Rimnicu, Sibiu),\n",
       " Connected(Sibiu, Fagaras),\n",
       " Connected(Fagaras, Bucharest),\n",
       " Connected(Pitesti, Craiova),\n",
       " Connected(Craiova, Rimnicu),\n",
       " (Connected(x, y) ==> Connected(y, x)),\n",
       " ((Connected(x, y) & Connected(y, z)) ==> Connected(x, z)),\n",
       " At(Sibiu)]"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "knowledge_base"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We now define possible actions to our problem. We know that we can drive between any connected places. But, as is evident from [this](https://en.wikipedia.org/wiki/List_of_airports_in_Romania) list of Romanian airports, we can also fly directly between Sibiu, Bucharest, and Craiova.\n",
    "\n",
    "We can define these flight actions like this:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "#Sibiu to Bucharest\n",
    "precond = 'At(Sibiu)'\n",
    "effect = 'At(Bucharest) & ~At(Sibiu)'\n",
    "fly_s_b = Action('Fly(Sibiu, Bucharest)', precond, effect)\n",
    "\n",
    "#Bucharest to Sibiu\n",
    "precond = 'At(Bucharest)'\n",
    "effect = 'At(Sibiu) & ~At(Bucharest)'\n",
    "fly_b_s = Action('Fly(Bucharest, Sibiu)', precond, effect)\n",
    "\n",
    "#Sibiu to Craiova\n",
    "precond = 'At(Sibiu)'\n",
    "effect = 'At(Craiova) & ~At(Sibiu)'\n",
    "fly_s_c = Action('Fly(Sibiu, Craiova)', precond, effect)\n",
    "\n",
    "#Craiova to Sibiu\n",
    "precond = 'At(Craiova)'\n",
    "effect = 'At(Sibiu) & ~At(Craiova)'\n",
    "fly_c_s = Action('Fly(Craiova, Sibiu)', precond, effect)\n",
    "\n",
    "#Bucharest to Craiova\n",
    "precond = 'At(Bucharest)'\n",
    "effect = 'At(Craiova) & ~At(Bucharest)'\n",
    "fly_b_c = Action('Fly(Bucharest, Craiova)', precond, effect)\n",
    "\n",
    "#Craiova to Bucharest\n",
    "precond = 'At(Craiova)'\n",
    "effect = 'At(Bucharest) & ~At(Craiova)'\n",
    "fly_c_b = Action('Fly(Craiova, Bucharest)', precond, effect)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And the drive actions like this."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "#Drive\n",
    "precond = 'At(x)'\n",
    "effect = 'At(y) & ~At(x)'\n",
    "drive = Action('Drive(x, y)', precond, effect)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Our goal is defined as"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "goals = 'At(Bucharest)'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Finally, we can define a a function that will tell us when we have reached our destination, Bucharest."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def goal_test(kb):\n",
    "    return kb.ask(expr('At(Bucharest)'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Thus, with all the components in place, we can define the planning problem."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "prob = PlanningProblem(knowledge_base, goals, [fly_s_b, fly_b_s, fly_s_c, fly_c_s, fly_b_c, fly_c_b, drive])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## PLANNING PROBLEMS\n",
    "---\n",
    "\n",
    "## Air Cargo Problem"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In the Air Cargo problem, we start with cargo at two airports, SFO and JFK. Our goal is to send each cargo to the other airport. We have two airplanes to help us accomplish the task. \n",
    "The problem can be defined with three actions: Load, Unload and Fly. \n",
    "Let us look how the `air_cargo` problem has been defined in the module. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "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\">air_cargo</span><span class=\"p\">():</span>\n",
       "    <span class=\"sd\">&quot;&quot;&quot;</span>\n",
       "<span class=\"sd\">    [Figure 10.1] AIR-CARGO-PROBLEM</span>\n",
       "\n",
       "<span class=\"sd\">    An air-cargo shipment problem for delivering cargo to different locations,</span>\n",
       "<span class=\"sd\">    given the starting location and airplanes.</span>\n",
       "\n",
       "<span class=\"sd\">    Example:</span>\n",
       "<span class=\"sd\">    &gt;&gt;&gt; from planning import *</span>\n",
       "<span class=\"sd\">    &gt;&gt;&gt; ac = air_cargo()</span>\n",
       "<span class=\"sd\">    &gt;&gt;&gt; ac.goal_test()</span>\n",
       "<span class=\"sd\">    False</span>\n",
       "<span class=\"sd\">    &gt;&gt;&gt; ac.act(expr(&#39;Load(C2, P2, JFK)&#39;))</span>\n",
       "<span class=\"sd\">    &gt;&gt;&gt; ac.act(expr(&#39;Load(C1, P1, SFO)&#39;))</span>\n",
       "<span class=\"sd\">    &gt;&gt;&gt; ac.act(expr(&#39;Fly(P1, SFO, JFK)&#39;))</span>\n",
       "<span class=\"sd\">    &gt;&gt;&gt; ac.act(expr(&#39;Fly(P2, JFK, SFO)&#39;))</span>\n",
       "<span class=\"sd\">    &gt;&gt;&gt; ac.act(expr(&#39;Unload(C2, P2, SFO)&#39;))</span>\n",
       "<span class=\"sd\">    &gt;&gt;&gt; ac.goal_test()</span>\n",
       "<span class=\"sd\">    False</span>\n",
       "<span class=\"sd\">    &gt;&gt;&gt; ac.act(expr(&#39;Unload(C1, P1, JFK)&#39;))</span>\n",
       "<span class=\"sd\">    &gt;&gt;&gt; ac.goal_test()</span>\n",
       "<span class=\"sd\">    True</span>\n",
       "<span class=\"sd\">    &gt;&gt;&gt;</span>\n",
       "<span class=\"sd\">    &quot;&quot;&quot;</span>\n",
       "    <span class=\"k\">return</span> <span class=\"n\">PlanningProblem</span><span class=\"p\">(</span><span class=\"n\">init</span><span class=\"o\">=</span><span class=\"s1\">&#39;At(C1, SFO) &amp; At(C2, JFK) &amp; At(P1, SFO) &amp; At(P2, JFK) &amp; Cargo(C1) &amp; Cargo(C2) &amp; Plane(P1) &amp; Plane(P2) &amp; Airport(SFO) &amp; Airport(JFK)&#39;</span><span class=\"p\">,</span> \n",
       "                <span class=\"n\">goals</span><span class=\"o\">=</span><span class=\"s1\">&#39;At(C1, JFK) &amp; At(C2, SFO)&#39;</span><span class=\"p\">,</span>\n",
       "                <span class=\"n\">actions</span><span class=\"o\">=</span><span class=\"p\">[</span><span class=\"n\">Action</span><span class=\"p\">(</span><span class=\"s1\">&#39;Load(c, p, a)&#39;</span><span class=\"p\">,</span> \n",
       "                                <span class=\"n\">precond</span><span class=\"o\">=</span><span class=\"s1\">&#39;At(c, a) &amp; At(p, a) &amp; Cargo(c) &amp; Plane(p) &amp; Airport(a)&#39;</span><span class=\"p\">,</span>\n",
       "                                <span class=\"n\">effect</span><span class=\"o\">=</span><span class=\"s1\">&#39;In(c, p) &amp; ~At(c, a)&#39;</span><span class=\"p\">),</span>\n",
       "                         <span class=\"n\">Action</span><span class=\"p\">(</span><span class=\"s1\">&#39;Unload(c, p, a)&#39;</span><span class=\"p\">,</span>\n",
       "                                <span class=\"n\">precond</span><span class=\"o\">=</span><span class=\"s1\">&#39;In(c, p) &amp; At(p, a) &amp; Cargo(c) &amp; Plane(p) &amp; Airport(a)&#39;</span><span class=\"p\">,</span>\n",
       "                                <span class=\"n\">effect</span><span class=\"o\">=</span><span class=\"s1\">&#39;At(c, a) &amp; ~In(c, p)&#39;</span><span class=\"p\">),</span>\n",
       "                         <span class=\"n\">Action</span><span class=\"p\">(</span><span class=\"s1\">&#39;Fly(p, f, to)&#39;</span><span class=\"p\">,</span>\n",
       "                                <span class=\"n\">precond</span><span class=\"o\">=</span><span class=\"s1\">&#39;At(p, f) &amp; Plane(p) &amp; Airport(f) &amp; Airport(to)&#39;</span><span class=\"p\">,</span>\n",
       "                                <span class=\"n\">effect</span><span class=\"o\">=</span><span class=\"s1\">&#39;At(p, to) &amp; ~At(p, f)&#39;</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(air_cargo)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**At(c, a):** The cargo **'c'** is at airport **'a'**.\n",
    "\n",
    "**~At(c, a):** The cargo **'c'** is _not_ at airport **'a'**.\n",
    "\n",
    "**In(c, p):** Cargo **'c'** is in plane **'p'**.\n",
    "\n",
    "**~In(c, p):** Cargo **'c'** is _not_ in plane **'p'**.\n",
    "\n",
    "**Cargo(c):** Declare **'c'** as cargo.\n",
    "\n",
    "**Plane(p):** Declare **'p'** as plane.\n",
    "\n",
    "**Airport(a):** Declare **'a'** as airport.\n",
    "\n",
    "\n",
    "\n",
    "In the `initial_state`, we have cargo C1, plane P1 at airport SFO and cargo C2, plane P2 at airport JFK. \n",
    "Our goal state is to have cargo C1 at airport JFK and cargo C2 at airport SFO. We will discuss on how to achieve this. Let us now define an object of the `air_cargo` problem:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "airCargo = air_cargo()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Before taking any actions, we will check if `airCargo` has reached its goal:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "False\n"
     ]
    }
   ],
   "source": [
    "print(airCargo.goal_test())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It returns False because the goal state is not yet reached. Now, we define the sequence of actions that it should take in order to achieve the goal.\n",
    "The actions are then carried out on the `airCargo` PlanningProblem.\n",
    "\n",
    "The actions available to us are the following: Load, Unload, Fly\n",
    "\n",
    "**Load(c, p, a):** Load cargo **'c'** into plane **'p'** from airport **'a'**.\n",
    "\n",
    "**Fly(p, f, t):** Fly the plane **'p'** from airport **'f'** to airport **'t'**.\n",
    "\n",
    "**Unload(c, p, a):** Unload cargo **'c'** from plane **'p'** to airport **'a'**.\n",
    "\n",
    "This problem can have multiple valid solutions.\n",
    "One such solution is shown below."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "solution = [expr(\"Load(C1 , P1, SFO)\"),\n",
    "            expr(\"Fly(P1, SFO, JFK)\"),\n",
    "            expr(\"Unload(C1, P1, JFK)\"),\n",
    "            expr(\"Load(C2, P2, JFK)\"),\n",
    "            expr(\"Fly(P2, JFK, SFO)\"),\n",
    "            expr(\"Unload (C2, P2, SFO)\")] \n",
    "\n",
    "for action in solution:\n",
    "    airCargo.act(action)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As the `airCargo` has taken all the steps it needed in order to achieve the goal, we can now check if it has acheived its goal:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n"
     ]
    }
   ],
   "source": [
    "print(airCargo.goal_test())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},