search.ipynb 191 ko
Newer Older
Chipe1's avatar
Chipe1 a validé
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
Chipe1's avatar
Chipe1 a validé
   },
   "source": [
    "# Solving problems by Searching\n",
    "\n",
    "This notebook serves as supporting material for topics covered in **Chapter 3 - Solving Problems by Searching** and **Chapter 4 - Beyond Classical Search** from the book *Artificial Intelligence: A Modern Approach.* This notebook uses implementations from [search.py](https://github.com/aimacode/aima-python/blob/master/search.py) module. Let's start by importing everything from search module."
   "cell_type": "code",
   "execution_count": 1,
    "collapsed": true,
Anthony Marakis's avatar
Anthony Marakis a validé
   "outputs": [],
Chipe1's avatar
Chipe1 a validé
   "source": [
    "from search import *\n",
    "\n",
    "# Needed to hide warnings in the matplotlib sections\n",
    "import warnings\n",
    "warnings.filterwarnings(\"ignore\")"
Chipe1's avatar
Chipe1 a validé
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
Chipe1's avatar
Chipe1 a validé
   "source": [
    "## CONTENTS\n",
    "\n",
    "* Overview\n",
    "* Problem\n",
    "* Node\n",
Aman Deep Singh's avatar
Aman Deep Singh a validé
    "* Simple Problem Solving Agent Program\n",
    "* Search Algorithms Visualization\n",
    "* Breadth-First Tree Search\n",
    "* Breadth-First Search\n",
Vinay Varma's avatar
Vinay Varma a validé
    "* Best First Search\n",
    "* Uniform Cost Search\n",
Vinay Varma's avatar
Vinay Varma a validé
    "* Greedy Best First Search\n",
    "* A\\* Search\n",
Aman Deep Singh's avatar
Aman Deep Singh a validé
    "* Hill Climbing\n",
    "* Genetic Algorithm"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## OVERVIEW\n",
    "Here, we learn about problem solving. Building goal-based agents that can plan ahead to solve problems, in particular, navigation problem/route finding problem. First, we will start the problem solving by precisely defining **problems** and their **solutions**. We will look at several general-purpose search algorithms. Broadly, search algorithms are classified into two types:\n",
    "* **Uninformed search algorithms**: Search algorithms which explore the search space without having any information about the problem other than its definition.\n",
    "* Examples:\n",
    "    1. Breadth First Search\n",
    "    2. Depth First Search\n",
    "    3. Depth Limited Search\n",
    "    4. Iterative Deepening Search\n",
    "\n",
    "\n",
    "* **Informed search algorithms**: These type of algorithms leverage any information (heuristics, path cost) on the problem to search through the search space to find the solution efficiently.\n",
    "* Examples:\n",
    "    1. Best First Search\n",
    "    2. Uniform Cost Search\n",
    "    3. A\\* Search\n",
    "    4. Recursive Best First Search\n",
    "\n",
    "*Don't miss the visualisations of these algorithms solving the route-finding problem defined on Romania map at the end of this notebook.*"
Chipe1's avatar
Chipe1 a validé
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
Chipe1's avatar
Chipe1 a validé
   "source": [
    "## PROBLEM\n",
Chipe1's avatar
Chipe1 a validé
    "\n",
    "Let's see how we define a Problem. Run the next cell to see how abstract class `Problem` is defined in the search module."
jeff3456's avatar
jeff3456 a validé
  {
   "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\">Problem</span><span class=\"p\">(</span><span class=\"nb\">object</span><span class=\"p\">):</span>\n",
       "\n",
       "    <span class=\"sd\">&quot;&quot;&quot;The abstract class for a formal problem. You should subclass</span>\n",
       "<span class=\"sd\">    this and implement the methods actions and result, and possibly</span>\n",
       "<span class=\"sd\">    __init__, goal_test, and path_cost. Then you will create instances</span>\n",
       "<span class=\"sd\">    of your subclass and solve them with the various search functions.&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\">initial</span><span class=\"p\">,</span> <span class=\"n\">goal</span><span class=\"o\">=</span><span class=\"bp\">None</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;The constructor specifies the initial state, and possibly a goal</span>\n",
       "<span class=\"sd\">        state, if there is a unique goal. Your subclass&#39;s constructor can add</span>\n",
       "<span class=\"sd\">        other arguments.&quot;&quot;&quot;</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">initial</span> <span class=\"o\">=</span> <span class=\"n\">initial</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">goal</span> <span class=\"o\">=</span> <span class=\"n\">goal</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">actions</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">state</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;Return the actions that can be executed in the given</span>\n",
       "<span class=\"sd\">        state. The result would typically be a list, but if there are</span>\n",
       "<span class=\"sd\">        many actions, consider yielding them one at a time in an</span>\n",
       "<span class=\"sd\">        iterator, rather than building them all at once.&quot;&quot;&quot;</span>\n",
       "        <span class=\"k\">raise</span> <span class=\"ne\">NotImplementedError</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">result</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">state</span><span class=\"p\">,</span> <span class=\"n\">action</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;Return the state that results from executing the given</span>\n",
       "<span class=\"sd\">        action in the given state. The action must be one of</span>\n",
       "<span class=\"sd\">        self.actions(state).&quot;&quot;&quot;</span>\n",
       "        <span class=\"k\">raise</span> <span class=\"ne\">NotImplementedError</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> <span class=\"n\">state</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;Return True if the state is a goal. The default method compares the</span>\n",
       "<span class=\"sd\">        state to self.goal or checks for state in self.goal if it is a</span>\n",
       "<span class=\"sd\">        list, as specified in the constructor. Override this method if</span>\n",
       "<span class=\"sd\">        checking against a single self.goal is not enough.&quot;&quot;&quot;</span>\n",
       "        <span class=\"k\">if</span> <span class=\"nb\">isinstance</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">goal</span><span class=\"p\">,</span> <span class=\"nb\">list</span><span class=\"p\">):</span>\n",
       "            <span class=\"k\">return</span> <span class=\"n\">is_in</span><span class=\"p\">(</span><span class=\"n\">state</span><span class=\"p\">,</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">goal</span><span class=\"p\">)</span>\n",
       "        <span class=\"k\">else</span><span class=\"p\">:</span>\n",
       "            <span class=\"k\">return</span> <span class=\"n\">state</span> <span class=\"o\">==</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">goal</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">path_cost</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">c</span><span class=\"p\">,</span> <span class=\"n\">state1</span><span class=\"p\">,</span> <span class=\"n\">action</span><span class=\"p\">,</span> <span class=\"n\">state2</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;Return the cost of a solution path that arrives at state2 from</span>\n",
       "<span class=\"sd\">        state1 via action, assuming cost c to get up to state1. If the problem</span>\n",
       "<span class=\"sd\">        is such that the path doesn&#39;t matter, this function will only look at</span>\n",
       "<span class=\"sd\">        state2.  If the path does matter, it will consider c and maybe state1</span>\n",
       "<span class=\"sd\">        and action. The default method costs 1 for every step in the path.&quot;&quot;&quot;</span>\n",
       "        <span class=\"k\">return</span> <span class=\"n\">c</span> <span class=\"o\">+</span> <span class=\"mi\">1</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">value</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">state</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;For optimization problems, each state has a value.  Hill-climbing</span>\n",
       "<span class=\"sd\">        and related algorithms try to maximize this value.&quot;&quot;&quot;</span>\n",
       "        <span class=\"k\">raise</span> <span class=\"ne\">NotImplementedError</span>\n",
       "</pre></div>\n",
       "</body>\n",
       "</html>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
jeff3456's avatar
jeff3456 a validé
   "source": [
    "psource(Problem)"
Chipe1's avatar
Chipe1 a validé
   ]
  },
  {
   "cell_type": "markdown",
Chipe1's avatar
Chipe1 a validé
   "source": [
    "The `Problem` class has six methods.\n",
    "* `__init__(self, initial, goal)` : This is what is called a `constructor` and is the first method called when you create an instance of the class. `initial` specifies the initial state of our search problem. It represents the start state from where our agent begins its task of exploration to find the goal state(s) which is given in the `goal` parameter.\n",
    "\n",
    "\n",
    "* `actions(self, state)` : This method returns all the possible actions agent can execute in the given state `state`.\n",
    "\n",
    "\n",
Chipe1's avatar
Chipe1 a validé
    "* `result(self, state, action)` : This returns the resulting state if action `action` is taken in the state `state`. This `Problem` class only deals with deterministic outcomes. So we know for sure what every action in a state would result to.\n",
    "* `goal_test(self, state)` : Given a graph state, it checks if it is a terminal state. If the state is indeed a goal state, value of `True` is returned. Else, of course, `False` is returned.\n",
Chipe1's avatar
Chipe1 a validé
    "* `path_cost(self, c, state1, action, state2)` : Return the cost of the path that arrives at `state2` as a result of taking `action` from `state1`, assuming total cost of `c` to get up to `state1`.\n",
    "* `value(self, state)` : This acts as a bit of extra information in problems where we try to optimise a value when we cannot do a goal test."
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## NODE\n",
    "\n",
    "Let's see how we define a Node. Run the next cell to see how abstract class `Node` is defined in the search module."
   ]
  },
  {
   "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\">Node</span><span class=\"p\">:</span>\n",
       "\n",
       "    <span class=\"sd\">&quot;&quot;&quot;A node in a search tree. Contains a pointer to the parent (the node</span>\n",
       "<span class=\"sd\">    that this is a successor of) and to the actual state for this node. Note</span>\n",
       "<span class=\"sd\">    that if a state is arrived at by two paths, then there are two nodes with</span>\n",
       "<span class=\"sd\">    the same state.  Also includes the action that got us to this state, and</span>\n",
       "<span class=\"sd\">    the total path_cost (also known as g) to reach the node.  Other functions</span>\n",
       "<span class=\"sd\">    may add an f and h value; see best_first_graph_search and astar_search for</span>\n",
       "<span class=\"sd\">    an explanation of how the f and h values are handled. You will not need to</span>\n",
       "<span class=\"sd\">    subclass this class.&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\">state</span><span class=\"p\">,</span> <span class=\"n\">parent</span><span class=\"o\">=</span><span class=\"bp\">None</span><span class=\"p\">,</span> <span class=\"n\">action</span><span class=\"o\">=</span><span class=\"bp\">None</span><span class=\"p\">,</span> <span class=\"n\">path_cost</span><span class=\"o\">=</span><span class=\"mi\">0</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;Create a search tree Node, derived from a parent by an action.&quot;&quot;&quot;</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">state</span> <span class=\"o\">=</span> <span class=\"n\">state</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">parent</span> <span class=\"o\">=</span> <span class=\"n\">parent</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">action</span> <span class=\"o\">=</span> <span class=\"n\">action</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">path_cost</span> <span class=\"o\">=</span> <span class=\"n\">path_cost</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">depth</span> <span class=\"o\">=</span> <span class=\"mi\">0</span>\n",
       "        <span class=\"k\">if</span> <span class=\"n\">parent</span><span class=\"p\">:</span>\n",
       "            <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">depth</span> <span class=\"o\">=</span> <span class=\"n\">parent</span><span class=\"o\">.</span><span class=\"n\">depth</span> <span class=\"o\">+</span> <span class=\"mi\">1</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=\"s2\">&quot;&lt;Node {}&gt;&quot;</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=\"n\">state</span><span class=\"p\">)</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"fm\">__lt__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">node</span><span class=\"p\">):</span>\n",
       "        <span class=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">state</span> <span class=\"o\">&lt;</span> <span class=\"n\">node</span><span class=\"o\">.</span><span class=\"n\">state</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">expand</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">problem</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;List the nodes reachable in one step from this node.&quot;&quot;&quot;</span>\n",
       "        <span class=\"k\">return</span> <span class=\"p\">[</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">child_node</span><span class=\"p\">(</span><span class=\"n\">problem</span><span class=\"p\">,</span> <span class=\"n\">action</span><span class=\"p\">)</span>\n",
       "                <span class=\"k\">for</span> <span class=\"n\">action</span> <span class=\"ow\">in</span> <span class=\"n\">problem</span><span class=\"o\">.</span><span class=\"n\">actions</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">state</span><span class=\"p\">)]</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">child_node</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">problem</span><span class=\"p\">,</span> <span class=\"n\">action</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;[Figure 3.10]&quot;&quot;&quot;</span>\n",
       "        <span class=\"nb\">next</span> <span class=\"o\">=</span> <span class=\"n\">problem</span><span class=\"o\">.</span><span class=\"n\">result</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">state</span><span class=\"p\">,</span> <span class=\"n\">action</span><span class=\"p\">)</span>\n",
       "        <span class=\"k\">return</span> <span class=\"n\">Node</span><span class=\"p\">(</span><span class=\"nb\">next</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=\"n\">problem</span><span class=\"o\">.</span><span class=\"n\">path_cost</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">path_cost</span><span class=\"p\">,</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">state</span><span class=\"p\">,</span>\n",
       "                                      <span class=\"n\">action</span><span class=\"p\">,</span> <span class=\"nb\">next</span><span class=\"p\">))</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">solution</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;Return the sequence of actions to go from the root to this node.&quot;&quot;&quot;</span>\n",
       "        <span class=\"k\">return</span> <span class=\"p\">[</span><span class=\"n\">node</span><span class=\"o\">.</span><span class=\"n\">action</span> <span class=\"k\">for</span> <span class=\"n\">node</span> <span class=\"ow\">in</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">path</span><span class=\"p\">()[</span><span class=\"mi\">1</span><span class=\"p\">:]]</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">path</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;Return a list of nodes forming the path from the root to this node.&quot;&quot;&quot;</span>\n",
       "        <span class=\"n\">node</span><span class=\"p\">,</span> <span class=\"n\">path_back</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"p\">[]</span>\n",
       "        <span class=\"k\">while</span> <span class=\"n\">node</span><span class=\"p\">:</span>\n",
       "            <span class=\"n\">path_back</span><span class=\"o\">.</span><span class=\"n\">append</span><span class=\"p\">(</span><span class=\"n\">node</span><span class=\"p\">)</span>\n",
       "            <span class=\"n\">node</span> <span class=\"o\">=</span> <span class=\"n\">node</span><span class=\"o\">.</span><span class=\"n\">parent</span>\n",
       "        <span class=\"k\">return</span> <span class=\"nb\">list</span><span class=\"p\">(</span><span class=\"nb\">reversed</span><span class=\"p\">(</span><span class=\"n\">path_back</span><span class=\"p\">))</span>\n",
       "\n",
       "    <span class=\"c1\"># We want for a queue of nodes in breadth_first_search or</span>\n",
       "    <span class=\"c1\"># astar_search to have no duplicated states, so we treat nodes</span>\n",
       "    <span class=\"c1\"># with the same state as equal. [Problem: this may not be what you</span>\n",
       "    <span class=\"c1\"># want in other contexts.]</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"fm\">__eq__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">other</span><span class=\"p\">):</span>\n",
       "        <span class=\"k\">return</span> <span class=\"nb\">isinstance</span><span class=\"p\">(</span><span class=\"n\">other</span><span class=\"p\">,</span> <span class=\"n\">Node</span><span class=\"p\">)</span> <span class=\"ow\">and</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">state</span> <span class=\"o\">==</span> <span class=\"n\">other</span><span class=\"o\">.</span><span class=\"n\">state</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"fm\">__hash__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n",
       "        <span class=\"k\">return</span> <span class=\"nb\">hash</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">state</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(Node)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `Node` class has nine methods.\n",
    "\n",
Alan Oliveira's avatar
Alan Oliveira a validé
    "* `__init__(self, state, parent, action, path_cost)` : This method creates a node. `parent` represents the node that this is a successor of and `action` is the action required to get from the parent node to this node. `path_cost` is the cost to reach current node from parent node.\n",
    "\n",
    "* `__repr__(self)` : This returns the state of this node.\n",
    "\n",
    "* `__lt__(self, node)` : Given a `node`, this method returns `True` if the state of current node is less than the state of the `node`. Otherwise it returns `False`.\n",
    "\n",
Alan Oliveira's avatar
Alan Oliveira a validé
    "* `expand(self, problem)` : This method lists all the neighbouring(reachable in one step) nodes of current node. \n",
Alan Oliveira's avatar
Alan Oliveira a validé
    "* `child_node(self, problem, action)` : Given an `action`, this method returns the immediate neighbour that can be reached with that `action`.\n",
    "\n",
    "* `solution(self)` : This returns the sequence of actions required to reach this node from the root node. \n",
    "\n",
    "* `path(self)` : This returns a list of all the nodes that lies in the path from the root to this node.\n",
    "\n",
    "* `__eq__(self, other)` : This method returns `True` if the state of current node is equal to the other node. Else it returns `False`.\n",
    "\n",
    "* `__hash__(self)` : This returns the hash of the state of current node."
   ]
  },
Chipe1's avatar
Chipe1 a validé
  {
   "cell_type": "markdown",
Chipe1's avatar
Chipe1 a validé
   "source": [
    "We will use the abstract class `Problem` to define our real **problem** named `GraphProblem`. You can see how we define `GraphProblem` by running the next cell."
jeff3456's avatar
jeff3456 a validé
   ]
  },
   "execution_count": 4,
   "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\">GraphProblem</span><span class=\"p\">(</span><span class=\"n\">Problem</span><span class=\"p\">):</span>\n",
       "\n",
       "    <span class=\"sd\">&quot;&quot;&quot;The problem of searching a graph from one node to another.&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\">initial</span><span class=\"p\">,</span> <span class=\"n\">goal</span><span class=\"p\">,</span> <span class=\"n\">graph</span><span class=\"p\">):</span>\n",
       "        <span class=\"n\">Problem</span><span class=\"o\">.</span><span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">initial</span><span class=\"p\">,</span> <span class=\"n\">goal</span><span class=\"p\">)</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">graph</span> <span class=\"o\">=</span> <span class=\"n\">graph</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">actions</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">A</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;The actions at a graph node are just its neighbors.&quot;&quot;&quot;</span>\n",
       "        <span class=\"k\">return</span> <span class=\"nb\">list</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">graph</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">A</span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">keys</span><span class=\"p\">())</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">result</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">state</span><span class=\"p\">,</span> <span class=\"n\">action</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;The result of going to a neighbor is just that neighbor.&quot;&quot;&quot;</span>\n",
       "        <span class=\"k\">return</span> <span class=\"n\">action</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">path_cost</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">cost_so_far</span><span class=\"p\">,</span> <span class=\"n\">A</span><span class=\"p\">,</span> <span class=\"n\">action</span><span class=\"p\">,</span> <span class=\"n\">B</span><span class=\"p\">):</span>\n",
       "        <span class=\"k\">return</span> <span class=\"n\">cost_so_far</span> <span class=\"o\">+</span> <span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">graph</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">A</span><span class=\"p\">,</span> <span class=\"n\">B</span><span class=\"p\">)</span> <span class=\"ow\">or</span> <span class=\"n\">infinity</span><span class=\"p\">)</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">find_min_edge</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;Find minimum value of edges.&quot;&quot;&quot;</span>\n",
       "        <span class=\"n\">m</span> <span class=\"o\">=</span> <span class=\"n\">infinity</span>\n",
       "        <span class=\"k\">for</span> <span class=\"n\">d</span> <span class=\"ow\">in</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">graph</span><span class=\"o\">.</span><span class=\"n\">dict</span><span class=\"o\">.</span><span class=\"n\">values</span><span class=\"p\">():</span>\n",
       "            <span class=\"n\">local_min</span> <span class=\"o\">=</span> <span class=\"nb\">min</span><span class=\"p\">(</span><span class=\"n\">d</span><span class=\"o\">.</span><span class=\"n\">values</span><span class=\"p\">())</span>\n",
       "            <span class=\"n\">m</span> <span class=\"o\">=</span> <span class=\"nb\">min</span><span class=\"p\">(</span><span class=\"n\">m</span><span class=\"p\">,</span> <span class=\"n\">local_min</span><span class=\"p\">)</span>\n",
       "\n",
       "        <span class=\"k\">return</span> <span class=\"n\">m</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">h</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">node</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;h function is straight-line distance from a node&#39;s state to goal.&quot;&quot;&quot;</span>\n",
       "        <span class=\"n\">locs</span> <span class=\"o\">=</span> <span class=\"nb\">getattr</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">graph</span><span class=\"p\">,</span> <span class=\"s1\">&#39;locations&#39;</span><span class=\"p\">,</span> <span class=\"bp\">None</span><span class=\"p\">)</span>\n",
       "        <span class=\"k\">if</span> <span class=\"n\">locs</span><span class=\"p\">:</span>\n",
       "            <span class=\"k\">if</span> <span class=\"nb\">type</span><span class=\"p\">(</span><span class=\"n\">node</span><span class=\"p\">)</span> <span class=\"ow\">is</span> <span class=\"nb\">str</span><span class=\"p\">:</span>\n",
       "                <span class=\"k\">return</span> <span class=\"nb\">int</span><span class=\"p\">(</span><span class=\"n\">distance</span><span class=\"p\">(</span><span class=\"n\">locs</span><span class=\"p\">[</span><span class=\"n\">node</span><span class=\"p\">],</span> <span class=\"n\">locs</span><span class=\"p\">[</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">goal</span><span class=\"p\">]))</span>\n",
       "\n",
       "            <span class=\"k\">return</span> <span class=\"nb\">int</span><span class=\"p\">(</span><span class=\"n\">distance</span><span class=\"p\">(</span><span class=\"n\">locs</span><span class=\"p\">[</span><span class=\"n\">node</span><span class=\"o\">.</span><span class=\"n\">state</span><span class=\"p\">],</span> <span class=\"n\">locs</span><span class=\"p\">[</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">goal</span><span class=\"p\">]))</span>\n",
       "        <span class=\"k\">else</span><span class=\"p\">:</span>\n",
       "            <span class=\"k\">return</span> <span class=\"n\">infinity</span>\n",
       "</pre></div>\n",
       "</body>\n",
       "</html>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
Chipe1's avatar
Chipe1 a validé
   "source": [
    "psource(GraphProblem)"
Chipe1's avatar
Chipe1 a validé
   ]
  },
  {
   "cell_type": "markdown",
Chipe1's avatar
Chipe1 a validé
   "source": [
    "Now it's time to define our problem. We will define it by passing `initial`, `goal`, `graph` to `GraphProblem`. So, our problem is to find the goal state starting from the given initial state on the provided graph. Have a look at our romania_map, which is an Undirected Graph containing a dict of nodes as keys and neighbours as values."
Chipe1's avatar
Chipe1 a validé
   ]
  },
  {
   "cell_type": "code",
Anthony Marakis's avatar
Anthony Marakis a validé
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
Chipe1's avatar
Chipe1 a validé
   "outputs": [],
   "source": [
    "romania_map = UndirectedGraph(dict(\n",
    "    Arad=dict(Zerind=75, Sibiu=140, Timisoara=118),\n",
    "    Bucharest=dict(Urziceni=85, Pitesti=101, Giurgiu=90, Fagaras=211),\n",
    "    Craiova=dict(Drobeta=120, Rimnicu=146, Pitesti=138),\n",
    "    Drobeta=dict(Mehadia=75),\n",
    "    Eforie=dict(Hirsova=86),\n",
    "    Fagaras=dict(Sibiu=99),\n",
    "    Hirsova=dict(Urziceni=98),\n",
    "    Iasi=dict(Vaslui=92, Neamt=87),\n",
    "    Lugoj=dict(Timisoara=111, Mehadia=70),\n",
    "    Oradea=dict(Zerind=71, Sibiu=151),\n",
    "    Pitesti=dict(Rimnicu=97),\n",
    "    Rimnicu=dict(Sibiu=80),\n",
    "    Urziceni=dict(Vaslui=142)))\n",
    "\n",
    "romania_map.locations = dict(\n",
    "    Arad=(91, 492), Bucharest=(400, 327), Craiova=(253, 288),\n",
    "    Drobeta=(165, 299), Eforie=(562, 293), Fagaras=(305, 449),\n",
    "    Giurgiu=(375, 270), Hirsova=(534, 350), Iasi=(473, 506),\n",
    "    Lugoj=(165, 379), Mehadia=(168, 339), Neamt=(406, 537),\n",
    "    Oradea=(131, 571), Pitesti=(320, 368), Rimnicu=(233, 410),\n",
    "    Sibiu=(207, 457), Timisoara=(94, 410), Urziceni=(456, 350),\n",
    "    Vaslui=(509, 444), Zerind=(108, 531))"
Chipe1's avatar
Chipe1 a validé
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
Chipe1's avatar
Chipe1 a validé
   },
   "source": [
    "It is pretty straightforward to understand this `romania_map`. The first node **Arad** has three neighbours named **Zerind**, **Sibiu**, **Timisoara**. Each of these nodes are 75, 140, 118 units apart from **Arad** respectively. And the same goes with other nodes.\n",
    "\n",
    "And `romania_map.locations` contains the positions of each of the nodes. We will use the straight line distance (which is different from the one provided in `romania_map`) between two cities in algorithms like A\\*-search and Recursive Best First Search.\n",
    "\n",
    "**Define a problem:**\n",
    "Hmm... say we want to start exploring from **Arad** and try to find **Bucharest** in our romania_map. So, this is how we do it."
Chipe1's avatar
Chipe1 a validé
   ]
  },
  {
   "cell_type": "code",
Anthony Marakis's avatar
Anthony Marakis a validé
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
Chipe1's avatar
Chipe1 a validé
   "source": [
    "romania_problem = GraphProblem('Arad', 'Bucharest', romania_map)"
Chipe1's avatar
Chipe1 a validé
   ]
  },
  {
   "cell_type": "markdown",
   "source": [
    "### Romania Map Visualisation\n",
    "Let's have a visualisation of Romania map [Figure 3.2] from the book and see how different searching algorithms perform / how frontier expands in each search algorithm for a simple problem named `romania_problem`."
  {
   "cell_type": "markdown",
   "source": [
    "Have a look at `romania_locations`. It is a dictionary defined in search module. We will use these location values to draw the romania graph using **networkx**."
  {
   "cell_type": "code",
Anthony Marakis's avatar
Anthony Marakis a validé
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'Arad': (91, 492), 'Bucharest': (400, 327), 'Craiova': (253, 288), 'Drobeta': (165, 299), 'Eforie': (562, 293), 'Fagaras': (305, 449), 'Giurgiu': (375, 270), 'Hirsova': (534, 350), 'Iasi': (473, 506), 'Lugoj': (165, 379), 'Mehadia': (168, 339), 'Neamt': (406, 537), 'Oradea': (131, 571), 'Pitesti': (320, 368), 'Rimnicu': (233, 410), 'Sibiu': (207, 457), 'Timisoara': (94, 410), 'Urziceni': (456, 350), 'Vaslui': (509, 444), 'Zerind': (108, 531)}\n"
     ]
    }
   ],
   "source": [
    "romania_locations = romania_map.locations\n",
    "print(romania_locations)"
   ]
  },
  {
   "cell_type": "markdown",
    "Let's start the visualisations by importing necessary modules. We use networkx and matplotlib to show the map in the notebook and we use ipywidgets to interact with the map to see how the searching algorithm works."
  {
   "cell_type": "code",
Anthony Marakis's avatar
Anthony Marakis a validé
   "execution_count": 5,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "import networkx as nx\n",
    "import matplotlib.pyplot as plt\n",
    "from matplotlib import lines\n",
    "\n",
    "from ipywidgets import interact\n",
    "import ipywidgets as widgets\n",
    "from IPython.display import display\n",
  {
   "cell_type": "markdown",
   "source": [
    "Let's get started by initializing an empty graph. We will add nodes, place the nodes in their location as shown in the book, add edges to the graph."
   ]
  },
  {
   "cell_type": "code",
Anthony Marakis's avatar
Anthony Marakis a validé
   "execution_count": 6,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# initialise a graph\n",
    "G = nx.Graph()\n",
    "\n",
    "# use this while labeling nodes in the map\n",
    "node_labels = dict()\n",
    "# use this to modify colors of nodes while exploring the graph.\n",
    "# This is the only dict we send to `show_map(node_colors)` while drawing the map\n",
    "for n, p in romania_locations.items():\n",
    "    # add nodes from romania_locations\n",
    "    G.add_node(n)\n",
    "    # add nodes to node_labels\n",
    "    node_labels[n] = n\n",
    "    # node_colors to color nodes while exploring romania map\n",
    "    node_colors[n] = \"white\"\n",
    "# we'll save the initial node colors to a dict to use later\n",
    "initial_node_colors = dict(node_colors)\n",
    "    \n",
    "# positions for node labels\n",
    "node_label_pos = { k:[v[0],v[1]-10]  for k,v in romania_locations.items() }\n",
    "# use this while labeling edges\n",
    "edge_labels = dict()\n",
    "\n",
    "# add edges between cities in romania map - UndirectedGraph defined in search.py\n",
    "for node in romania_map.nodes():\n",
    "    connections = romania_map.get(node)\n",
    "    for connection in connections.keys():\n",
    "        distance = connections[connection]\n",
    "\n",
    "        # add edges to the graph\n",
    "        G.add_edge(node, connection)\n",
    "        # add distances to edge_labels\n",
    "        edge_labels[(node, connection)] = distance"
   ]
  },
  {
   "cell_type": "markdown",
    "We have completed building our graph based on romania_map and its locations. It's time to display it here in the notebook. This function `show_map(node_colors)` helps us do that. We will be calling this function later on to display the map at each and every interval step while searching, using variety of algorithms from the book."
   "execution_count": null,
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def show_map(node_colors):\n",
    "    # set the size of the plot\n",
    "    plt.figure(figsize=(18,13))\n",
    "    # draw the graph (both nodes and edges) with locations from romania_locations\n",
    "    nx.draw(G, pos = romania_locations, node_color = [node_colors[node] for node in G.nodes()])\n",
    "\n",
    "    # draw labels for nodes\n",
    "    node_label_handles = nx.draw_networkx_labels(G, pos = node_label_pos, labels = node_labels, font_size = 14)\n",
    "    # add a white bounding box behind the node labels\n",
    "    [label.set_bbox(dict(facecolor='white', edgecolor='none')) for label in node_label_handles.values()]\n",
    "\n",
    "    # add edge lables to the graph\n",
    "    nx.draw_networkx_edge_labels(G, pos = romania_locations, edge_labels=edge_labels, font_size = 14)\n",
    "    \n",
    "    # add a legend\n",
    "    white_circle = lines.Line2D([], [], color=\"white\", marker='o', markersize=15, markerfacecolor=\"white\")\n",
    "    orange_circle = lines.Line2D([], [], color=\"orange\", marker='o', markersize=15, markerfacecolor=\"orange\")\n",
    "    red_circle = lines.Line2D([], [], color=\"red\", marker='o', markersize=15, markerfacecolor=\"red\")\n",
    "    gray_circle = lines.Line2D([], [], color=\"gray\", marker='o', markersize=15, markerfacecolor=\"gray\")\n",
    "    green_circle = lines.Line2D([], [], color=\"green\", marker='o', markersize=15, markerfacecolor=\"green\")\n",
    "    plt.legend((white_circle, orange_circle, red_circle, gray_circle, green_circle),\n",
    "               ('Un-explored', 'Frontier', 'Currently Exploring', 'Explored', 'Final Solution'),\n",
    "               numpoints=1,prop={'size':16}, loc=(.8,.75))\n",
    "    \n",
    "    # show the plot. No need to use in notebooks. nx.draw will show the graph itself.\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "source": [
    "We can simply call the function with node_colors dictionary object to display it."
   ]
  },
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
  {
   "cell_type": "markdown",
   "source": [
    "Voila! You see, the romania map as shown in the Figure[3.2] in the book. Now, see how different searching algorithms perform with our problem statements."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## SIMPLE PROBLEM SOLVING AGENT PROGRAM\n",
    "\n",
Anthony Marakis's avatar
Anthony Marakis a validé
    "Let us now define a Simple Problem Solving Agent Program. Run the next cell to see how the abstract class `SimpleProblemSolvingAgentProgram` is defined in the search module."
   "execution_count": 13,
   "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\">SimpleProblemSolvingAgentProgram</span><span class=\"p\">:</span>\n",
       "\n",
       "    <span class=\"sd\">&quot;&quot;&quot;Abstract framework for a problem-solving agent. [Figure 3.1]&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\">initial_state</span><span class=\"o\">=</span><span class=\"bp\">None</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;State is an abstract representation of the state</span>\n",
       "<span class=\"sd\">        of the world, and seq is the list of actions required</span>\n",
       "<span class=\"sd\">        to get to a particular state from the initial state(root).&quot;&quot;&quot;</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">state</span> <span class=\"o\">=</span> <span class=\"n\">initial_state</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">seq</span> <span class=\"o\">=</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\">percept</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;[Figure 3.1] Formulate a goal and problem, then</span>\n",
       "<span class=\"sd\">        search for a sequence of actions to solve it.&quot;&quot;&quot;</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">state</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">update_state</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">state</span><span class=\"p\">,</span> <span class=\"n\">percept</span><span class=\"p\">)</span>\n",
       "        <span class=\"k\">if</span> <span class=\"ow\">not</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">seq</span><span class=\"p\">:</span>\n",
       "            <span class=\"n\">goal</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">formulate_goal</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">state</span><span class=\"p\">)</span>\n",
       "            <span class=\"n\">problem</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">formulate_problem</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">state</span><span class=\"p\">,</span> <span class=\"n\">goal</span><span class=\"p\">)</span>\n",
       "            <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">seq</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">search</span><span class=\"p\">(</span><span class=\"n\">problem</span><span class=\"p\">)</span>\n",
       "            <span class=\"k\">if</span> <span class=\"ow\">not</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">seq</span><span class=\"p\">:</span>\n",
       "                <span class=\"k\">return</span> <span class=\"bp\">None</span>\n",