{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Search Paths\n",
    "\n",
    "In the last reading, we learned about how to check whether there is a path from node A to node B.\n",
    "\n",
    "In this reading, we'll do additional things:\n",
    "\n",
    "1. return the path (a list of nodes) found instead of just True/False\n",
    "2. learn BFS, an alternative to DFS that is guaranteed to find the shortest path"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from graphviz import Graph, Digraph"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Review\n",
    "\n",
    "Let's revisit the graph search from the end of the last reading (only change is addition of `__repr__`):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<!-- Generated by graphviz version 2.44.1 (20200629.0846)\n",
       " -->\n",
       "<!-- Pages: 1 -->\n",
       "<svg width=\"134pt\" height=\"188pt\"\n",
       " viewBox=\"0.00 0.00 134.00 188.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 184)\">\n",
       "<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-184 130,-184 130,4 -4,4\"/>\n",
       "<!-- A -->\n",
       "<g id=\"node1\" class=\"node\">\n",
       "<title>A</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"27\" cy=\"-162\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"27\" y=\"-158.3\" font-family=\"Times,serif\" font-size=\"14.00\">A</text>\n",
       "</g>\n",
       "<!-- B -->\n",
       "<g id=\"node2\" class=\"node\">\n",
       "<title>B</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"99\" cy=\"-162\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"99\" y=\"-158.3\" font-family=\"Times,serif\" font-size=\"14.00\">B</text>\n",
       "</g>\n",
       "<!-- C -->\n",
       "<g id=\"node3\" class=\"node\">\n",
       "<title>C</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"71\" cy=\"-90\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"71\" y=\"-86.3\" font-family=\"Times,serif\" font-size=\"14.00\">C</text>\n",
       "</g>\n",
       "<!-- B&#45;&gt;C -->\n",
       "<g id=\"edge1\" class=\"edge\">\n",
       "<title>B&#45;&gt;C</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M92.36,-144.41C89.09,-136.22 85.06,-126.14 81.38,-116.95\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"84.55,-115.45 77.59,-107.47 78.05,-118.05 84.55,-115.45\"/>\n",
       "</g>\n",
       "<!-- D -->\n",
       "<g id=\"node4\" class=\"node\">\n",
       "<title>D</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"98\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"98\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">D</text>\n",
       "</g>\n",
       "<!-- C&#45;&gt;D -->\n",
       "<g id=\"edge2\" class=\"edge\">\n",
       "<title>C&#45;&gt;D</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M77.4,-72.41C80.51,-64.34 84.33,-54.43 87.83,-45.35\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"91.13,-46.55 91.46,-35.96 84.6,-44.03 91.13,-46.55\"/>\n",
       "</g>\n",
       "<!-- D&#45;&gt;B -->\n",
       "<g id=\"edge3\" class=\"edge\">\n",
       "<title>D&#45;&gt;B</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M101.65,-36.09C103.68,-46.43 105.98,-59.91 107,-72 108.34,-87.94 108.2,-92.04 107,-108 106.36,-116.48 105.16,-125.66 103.88,-133.96\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"100.42,-133.45 102.25,-143.89 107.32,-134.59 100.42,-133.45\"/>\n",
       "</g>\n",
       "</g>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "<__main__.mygraph at 0x7fd079488790>"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "class mygraph:\n",
    "    def __init__(self):\n",
    "        self.nodes = {}\n",
    "    \n",
    "    def node(self, name):\n",
    "        self.nodes[name] = Node(self, name)\n",
    "    \n",
    "    def edge(self, src, dst):\n",
    "        for name in [src, dst]:\n",
    "            if not name in self.nodes:\n",
    "                self.node(name)\n",
    "        self.nodes[src].children.append(self.nodes[dst])\n",
    "        \n",
    "    def _repr_svg_(self):\n",
    "        g = Digraph()\n",
    "        for n in self.nodes:\n",
    "            g.node(n)\n",
    "            for child in self.nodes[n].children:\n",
    "                g.edge(n, child.name)\n",
    "        return g._repr_image_svg_xml()\n",
    "    \n",
    "    def find(self, src, dst):\n",
    "        self.visited = set()\n",
    "        return self.nodes[src].find(dst)\n",
    "\n",
    "class Node:\n",
    "    def __init__(self, graph, name):\n",
    "        self.graph = graph\n",
    "        self.name = name\n",
    "        self.children = []\n",
    "        \n",
    "    def __repr__(self):\n",
    "        return \"node %s\" % self.name\n",
    "        \n",
    "    def find(self, dst):\n",
    "        if self.name in self.graph.visited:\n",
    "            return False\n",
    "        self.graph.visited.add(self.name)\n",
    "\n",
    "        if self.name == dst:\n",
    "            return True\n",
    "        for child in self.children:\n",
    "            if child.find(dst):\n",
    "                return True\n",
    "        return False\n",
    "\n",
    "g = mygraph()\n",
    "g.node(\"A\")\n",
    "g.edge(\"B\", \"C\")\n",
    "g.edge(\"C\", \"D\")\n",
    "g.edge(\"D\", \"B\")\n",
    "g"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "False\n",
      "True\n",
      "False\n"
     ]
    }
   ],
   "source": [
    "print(g.find(\"A\", \"A\"))\n",
    "print(g.find(\"A\", \"B\"))\n",
    "print(g.find(\"B\", \"D\"))\n",
    "print(g.find(\"B\", \"A\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Getting the Path\n",
    "\n",
    "Rather than just determine if there is a path, let's output what it is.  We'll modify the `find` method.  If there's a path, it should return it as a list (or tuple!) of nodes traversed.  If there is not a path, it should return None.\n",
    "\n",
    "The logic works like this: if the X node is a child of the W node, and we've found an `(X,Y,Z)` path, then `(W,X,Y,Z)` is also a valid path.  On line 11, we're using tuple concatenation to create a new tuple based on the one the child found, but with the parent added to the beginning."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<!-- Generated by graphviz version 2.44.1 (20200629.0846)\n",
       " -->\n",
       "<!-- Pages: 1 -->\n",
       "<svg width=\"134pt\" height=\"188pt\"\n",
       " viewBox=\"0.00 0.00 134.00 188.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 184)\">\n",
       "<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-184 130,-184 130,4 -4,4\"/>\n",
       "<!-- A -->\n",
       "<g id=\"node1\" class=\"node\">\n",
       "<title>A</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"27\" cy=\"-162\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"27\" y=\"-158.3\" font-family=\"Times,serif\" font-size=\"14.00\">A</text>\n",
       "</g>\n",
       "<!-- B -->\n",
       "<g id=\"node2\" class=\"node\">\n",
       "<title>B</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"99\" cy=\"-162\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"99\" y=\"-158.3\" font-family=\"Times,serif\" font-size=\"14.00\">B</text>\n",
       "</g>\n",
       "<!-- C -->\n",
       "<g id=\"node3\" class=\"node\">\n",
       "<title>C</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"71\" cy=\"-90\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"71\" y=\"-86.3\" font-family=\"Times,serif\" font-size=\"14.00\">C</text>\n",
       "</g>\n",
       "<!-- B&#45;&gt;C -->\n",
       "<g id=\"edge1\" class=\"edge\">\n",
       "<title>B&#45;&gt;C</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M92.36,-144.41C89.09,-136.22 85.06,-126.14 81.38,-116.95\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"84.55,-115.45 77.59,-107.47 78.05,-118.05 84.55,-115.45\"/>\n",
       "</g>\n",
       "<!-- D -->\n",
       "<g id=\"node4\" class=\"node\">\n",
       "<title>D</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"98\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"98\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">D</text>\n",
       "</g>\n",
       "<!-- C&#45;&gt;D -->\n",
       "<g id=\"edge2\" class=\"edge\">\n",
       "<title>C&#45;&gt;D</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M77.4,-72.41C80.51,-64.34 84.33,-54.43 87.83,-45.35\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"91.13,-46.55 91.46,-35.96 84.6,-44.03 91.13,-46.55\"/>\n",
       "</g>\n",
       "<!-- D&#45;&gt;B -->\n",
       "<g id=\"edge3\" class=\"edge\">\n",
       "<title>D&#45;&gt;B</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M101.65,-36.09C103.68,-46.43 105.98,-59.91 107,-72 108.34,-87.94 108.2,-92.04 107,-108 106.36,-116.48 105.16,-125.66 103.88,-133.96\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"100.42,-133.45 102.25,-143.89 107.32,-134.59 100.42,-133.45\"/>\n",
       "</g>\n",
       "</g>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "<__main__.mygraph at 0x7fd07948ab20>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def find_v2(self, dst):\n",
    "    if self.name in self.graph.visited:\n",
    "        return None\n",
    "\n",
    "    if self.name == dst:\n",
    "        return (self.name, )\n",
    "\n",
    "    for child in self.children:\n",
    "        path = child.find(dst)\n",
    "        if path != None:\n",
    "            return (self.name, ) + path\n",
    "\n",
    "    return None\n",
    "\n",
    "# monkey patching lets us redefine a method in\n",
    "# a class, without recreating the whole class\n",
    "# (not a recommended practice, but means we don't\n",
    "# need to show the complete new version of Node)\n",
    "Node.find = find_v2\n",
    "\n",
    "g = mygraph()\n",
    "g.node(\"A\")\n",
    "g.edge(\"B\", \"C\")\n",
    "g.edge(\"C\", \"D\")\n",
    "g.edge(\"D\", \"B\")\n",
    "g"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "None\n"
     ]
    }
   ],
   "source": [
    "path = g.find(\"A\", \"B\")\n",
    "print(path)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "('C', 'D', 'B')\n"
     ]
    }
   ],
   "source": [
    "path = g.find(\"C\", \"B\")\n",
    "print(path)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Multiple Paths\n",
    "\n",
    "What if there are multiple paths?  Which will we return?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<!-- Generated by graphviz version 2.44.1 (20200629.0846)\n",
       " -->\n",
       "<!-- Pages: 1 -->\n",
       "<svg width=\"90pt\" height=\"332pt\"\n",
       " viewBox=\"0.00 0.00 90.00 332.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 328)\">\n",
       "<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-328 86,-328 86,4 -4,4\"/>\n",
       "<!-- A -->\n",
       "<g id=\"node1\" class=\"node\">\n",
       "<title>A</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"27\" cy=\"-306\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"27\" y=\"-302.3\" font-family=\"Times,serif\" font-size=\"14.00\">A</text>\n",
       "</g>\n",
       "<!-- E -->\n",
       "<g id=\"node2\" class=\"node\">\n",
       "<title>E</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"27\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"27\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">E</text>\n",
       "</g>\n",
       "<!-- A&#45;&gt;E -->\n",
       "<g id=\"edge1\" class=\"edge\">\n",
       "<title>A&#45;&gt;E</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M23.75,-287.89C21.95,-277.54 19.91,-264.06 19,-252 13.01,-172.22 13.01,-151.78 19,-72 19.64,-63.52 20.84,-54.34 22.12,-46.04\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"25.58,-46.55 23.75,-36.11 18.68,-45.41 25.58,-46.55\"/>\n",
       "</g>\n",
       "<!-- B -->\n",
       "<g id=\"node3\" class=\"node\">\n",
       "<title>B</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"55\" cy=\"-234\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"55\" y=\"-230.3\" font-family=\"Times,serif\" font-size=\"14.00\">B</text>\n",
       "</g>\n",
       "<!-- A&#45;&gt;B -->\n",
       "<g id=\"edge2\" class=\"edge\">\n",
       "<title>A&#45;&gt;B</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M33.64,-288.41C36.91,-280.22 40.94,-270.14 44.62,-260.95\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"47.95,-262.05 48.41,-251.47 41.45,-259.45 47.95,-262.05\"/>\n",
       "</g>\n",
       "<!-- C -->\n",
       "<g id=\"node4\" class=\"node\">\n",
       "<title>C</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"55\" cy=\"-162\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"55\" y=\"-158.3\" font-family=\"Times,serif\" font-size=\"14.00\">C</text>\n",
       "</g>\n",
       "<!-- B&#45;&gt;C -->\n",
       "<g id=\"edge3\" class=\"edge\">\n",
       "<title>B&#45;&gt;C</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M55,-215.7C55,-207.98 55,-198.71 55,-190.11\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"58.5,-190.1 55,-180.1 51.5,-190.1 58.5,-190.1\"/>\n",
       "</g>\n",
       "<!-- D -->\n",
       "<g id=\"node5\" class=\"node\">\n",
       "<title>D</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"55\" cy=\"-90\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"55\" y=\"-86.3\" font-family=\"Times,serif\" font-size=\"14.00\">D</text>\n",
       "</g>\n",
       "<!-- C&#45;&gt;D -->\n",
       "<g id=\"edge4\" class=\"edge\">\n",
       "<title>C&#45;&gt;D</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M55,-143.7C55,-135.98 55,-126.71 55,-118.11\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"58.5,-118.1 55,-108.1 51.5,-118.1 58.5,-118.1\"/>\n",
       "</g>\n",
       "<!-- D&#45;&gt;E -->\n",
       "<g id=\"edge5\" class=\"edge\">\n",
       "<title>D&#45;&gt;E</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M48.36,-72.41C45.09,-64.22 41.06,-54.14 37.38,-44.95\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"40.55,-43.45 33.59,-35.47 34.05,-46.05 40.55,-43.45\"/>\n",
       "</g>\n",
       "</g>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "<__main__.mygraph at 0x7fd07948a940>"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "g = mygraph()\n",
    "g.edge(\"A\", \"E\")\n",
    "g.edge(\"A\", \"B\")\n",
    "g.edge(\"B\", \"C\")\n",
    "g.edge(\"C\", \"D\")\n",
    "g.edge(\"D\", \"E\")\n",
    "g"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "('A', 'E')"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "g.find(\"A\", \"E\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Nice, it found the shortest one!  But what if we build the same graphs, but adding the edges in a different order?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<!-- Generated by graphviz version 2.44.1 (20200629.0846)\n",
       " -->\n",
       "<!-- Pages: 1 -->\n",
       "<svg width=\"89pt\" height=\"332pt\"\n",
       " viewBox=\"0.00 0.00 89.00 332.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 328)\">\n",
       "<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-328 85,-328 85,4 -4,4\"/>\n",
       "<!-- A -->\n",
       "<g id=\"node1\" class=\"node\">\n",
       "<title>A</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"54\" cy=\"-306\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"54\" y=\"-302.3\" font-family=\"Times,serif\" font-size=\"14.00\">A</text>\n",
       "</g>\n",
       "<!-- B -->\n",
       "<g id=\"node2\" class=\"node\">\n",
       "<title>B</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"27\" cy=\"-234\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"27\" y=\"-230.3\" font-family=\"Times,serif\" font-size=\"14.00\">B</text>\n",
       "</g>\n",
       "<!-- A&#45;&gt;B -->\n",
       "<g id=\"edge1\" class=\"edge\">\n",
       "<title>A&#45;&gt;B</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M47.6,-288.41C44.49,-280.34 40.67,-270.43 37.17,-261.35\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"40.4,-260.03 33.54,-251.96 33.87,-262.55 40.4,-260.03\"/>\n",
       "</g>\n",
       "<!-- E -->\n",
       "<g id=\"node3\" class=\"node\">\n",
       "<title>E</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"54\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"54\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">E</text>\n",
       "</g>\n",
       "<!-- A&#45;&gt;E -->\n",
       "<g id=\"edge2\" class=\"edge\">\n",
       "<title>A&#45;&gt;E</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M57.65,-287.91C59.68,-277.57 61.98,-264.09 63,-252 69.72,-172.28 69.72,-151.72 63,-72 62.28,-63.5 60.93,-54.31 59.49,-46.01\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"62.91,-45.29 57.65,-36.09 56.03,-46.56 62.91,-45.29\"/>\n",
       "</g>\n",
       "<!-- C -->\n",
       "<g id=\"node4\" class=\"node\">\n",
       "<title>C</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"27\" cy=\"-162\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"27\" y=\"-158.3\" font-family=\"Times,serif\" font-size=\"14.00\">C</text>\n",
       "</g>\n",
       "<!-- B&#45;&gt;C -->\n",
       "<g id=\"edge3\" class=\"edge\">\n",
       "<title>B&#45;&gt;C</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M27,-215.7C27,-207.98 27,-198.71 27,-190.11\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"30.5,-190.1 27,-180.1 23.5,-190.1 30.5,-190.1\"/>\n",
       "</g>\n",
       "<!-- D -->\n",
       "<g id=\"node5\" class=\"node\">\n",
       "<title>D</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"27\" cy=\"-90\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"27\" y=\"-86.3\" font-family=\"Times,serif\" font-size=\"14.00\">D</text>\n",
       "</g>\n",
       "<!-- C&#45;&gt;D -->\n",
       "<g id=\"edge4\" class=\"edge\">\n",
       "<title>C&#45;&gt;D</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M27,-143.7C27,-135.98 27,-126.71 27,-118.11\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"30.5,-118.1 27,-108.1 23.5,-118.1 30.5,-118.1\"/>\n",
       "</g>\n",
       "<!-- D&#45;&gt;E -->\n",
       "<g id=\"edge5\" class=\"edge\">\n",
       "<title>D&#45;&gt;E</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M33.4,-72.41C36.51,-64.34 40.33,-54.43 43.83,-45.35\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"47.13,-46.55 47.46,-35.96 40.6,-44.03 47.13,-46.55\"/>\n",
       "</g>\n",
       "</g>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "<__main__.mygraph at 0x7fd079490130>"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "g = mygraph()\n",
    "g.edge(\"A\", \"B\")\n",
    "g.edge(\"B\", \"C\")\n",
    "g.edge(\"C\", \"D\")\n",
    "g.edge(\"D\", \"E\")\n",
    "g.edge(\"A\", \"E\") # we used to add this first, now last\n",
    "g"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "('A', 'B', 'C', 'D', 'E')"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "g.find(\"A\", \"E\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Yuck!  If Google Maps gave me these directions for getting from city A to E, then I might just switch to Apple Maps.\n",
    "\n",
    "The search pattern we're using is known as \"depth first search\", or DFS.  It explores one child completely (including all that child's descendents) before checking if the other children know a path.\n",
    "\n",
    "The alternative to DFS is BFS, or \"breadth first search\".  This algorithm will explore all children before exploring grandchildren, before exploring great grandchildren, etc.\n",
    "\n",
    "The algorithm for BFS is not recursive, but many find it less intuitive that recursive DFS.  The strategy is to keep a \"TODO\" list of all nodes that need to be visited.  The list is used as a *queue*, meaning the first nodes added to the list will be the first ones visited.  When a child is explored, we generally discover grandchildren, but rather than explore those grandchildren immediately (as in DFS), we add those grandchildren to the end of the TODO queue, to be processed eventually after the other children.\n",
    "\n",
    "Let's try it:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<!-- Generated by graphviz version 2.44.1 (20200629.0846)\n",
       " -->\n",
       "<!-- Pages: 1 -->\n",
       "<svg width=\"278pt\" height=\"188pt\"\n",
       " viewBox=\"0.00 0.00 278.00 188.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 184)\">\n",
       "<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-184 274,-184 274,4 -4,4\"/>\n",
       "<!-- A -->\n",
       "<g id=\"node1\" class=\"node\">\n",
       "<title>A</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"135\" cy=\"-162\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"135\" y=\"-158.3\" font-family=\"Times,serif\" font-size=\"14.00\">A</text>\n",
       "</g>\n",
       "<!-- B -->\n",
       "<g id=\"node2\" class=\"node\">\n",
       "<title>B</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"99\" cy=\"-90\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"99\" y=\"-86.3\" font-family=\"Times,serif\" font-size=\"14.00\">B</text>\n",
       "</g>\n",
       "<!-- A&#45;&gt;B -->\n",
       "<g id=\"edge1\" class=\"edge\">\n",
       "<title>A&#45;&gt;B</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M126.65,-144.76C122.29,-136.28 116.85,-125.71 111.96,-116.2\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"114.99,-114.44 107.3,-107.15 108.77,-117.64 114.99,-114.44\"/>\n",
       "</g>\n",
       "<!-- C -->\n",
       "<g id=\"node3\" class=\"node\">\n",
       "<title>C</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"171\" cy=\"-90\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"171\" y=\"-86.3\" font-family=\"Times,serif\" font-size=\"14.00\">C</text>\n",
       "</g>\n",
       "<!-- A&#45;&gt;C -->\n",
       "<g id=\"edge2\" class=\"edge\">\n",
       "<title>A&#45;&gt;C</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M143.35,-144.76C147.71,-136.28 153.15,-125.71 158.04,-116.2\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"161.23,-117.64 162.7,-107.15 155.01,-114.44 161.23,-117.64\"/>\n",
       "</g>\n",
       "<!-- D -->\n",
       "<g id=\"node4\" class=\"node\">\n",
       "<title>D</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"27\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"27\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">D</text>\n",
       "</g>\n",
       "<!-- B&#45;&gt;D -->\n",
       "<g id=\"edge3\" class=\"edge\">\n",
       "<title>B&#45;&gt;D</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M84.43,-74.83C74.25,-64.94 60.48,-51.55 48.97,-40.36\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"51.41,-37.85 41.8,-33.38 46.53,-42.87 51.41,-37.85\"/>\n",
       "</g>\n",
       "<!-- E -->\n",
       "<g id=\"node5\" class=\"node\">\n",
       "<title>E</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"99\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"99\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">E</text>\n",
       "</g>\n",
       "<!-- B&#45;&gt;E -->\n",
       "<g id=\"edge4\" class=\"edge\">\n",
       "<title>B&#45;&gt;E</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M99,-71.7C99,-63.98 99,-54.71 99,-46.11\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"102.5,-46.1 99,-36.1 95.5,-46.1 102.5,-46.1\"/>\n",
       "</g>\n",
       "<!-- F -->\n",
       "<g id=\"node6\" class=\"node\">\n",
       "<title>F</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"171\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"171\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">F</text>\n",
       "</g>\n",
       "<!-- C&#45;&gt;F -->\n",
       "<g id=\"edge5\" class=\"edge\">\n",
       "<title>C&#45;&gt;F</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M171,-71.7C171,-63.98 171,-54.71 171,-46.11\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"174.5,-46.1 171,-36.1 167.5,-46.1 174.5,-46.1\"/>\n",
       "</g>\n",
       "<!-- G -->\n",
       "<g id=\"node7\" class=\"node\">\n",
       "<title>G</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"243\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"243\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">G</text>\n",
       "</g>\n",
       "<!-- C&#45;&gt;G -->\n",
       "<g id=\"edge6\" class=\"edge\">\n",
       "<title>C&#45;&gt;G</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M185.57,-74.83C195.75,-64.94 209.52,-51.55 221.03,-40.36\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"223.47,-42.87 228.2,-33.38 218.59,-37.85 223.47,-42.87\"/>\n",
       "</g>\n",
       "</g>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "<__main__.mygraph at 0x7fd079490220>"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def find_bfs(self, dst):\n",
    "    # the first node to explore is the starting point\n",
    "    todo = [self]\n",
    "\n",
    "    # keep looping while there are unexplored nodes\n",
    "    while len(todo) > 0:\n",
    "        print(\"TODO:\", todo)\n",
    "        curr = todo.pop(0) # pop from beginning\n",
    "\n",
    "        print(\"VISITING:\", curr)\n",
    "        if curr.name == dst:\n",
    "            return True\n",
    "        else:\n",
    "            for child in curr.children:\n",
    "                if not child.name in self.graph.visited:\n",
    "                    todo.append(child) # add to end\n",
    "                    self.graph.visited.add(child.name)\n",
    "\n",
    "    # nothing left to check, and we haven't already returned True\n",
    "    return False\n",
    "\n",
    "Node.find = find_bfs\n",
    "\n",
    "g = mygraph()\n",
    "g.edge(\"A\", \"B\")\n",
    "g.edge(\"A\", \"C\")\n",
    "g.edge(\"B\", \"D\")\n",
    "g.edge(\"B\", \"E\")\n",
    "g.edge(\"C\", \"F\")\n",
    "g.edge(\"C\", \"G\")\n",
    "g"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "TODO: [node A]\n",
      "VISITING: node A\n",
      "TODO: [node B, node C]\n",
      "VISITING: node B\n",
      "TODO: [node C, node D, node E]\n",
      "VISITING: node C\n",
      "TODO: [node D, node E, node F, node G]\n",
      "VISITING: node D\n",
      "TODO: [node E, node F, node G]\n",
      "VISITING: node E\n",
      "TODO: [node F, node G]\n",
      "VISITING: node F\n",
      "TODO: [node G]\n",
      "VISITING: node G\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "g.find(\"A\", \"G\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Cool!  We're searching one level at a time.  But did you notice we lost some functionality?  We aren't keeping track of how we got to the final node.  There are often multiple ways to reach a node, so we should add a `back` attribute to backtrack how we got there."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<!-- Generated by graphviz version 2.44.1 (20200629.0846)\n",
       " -->\n",
       "<!-- Pages: 1 -->\n",
       "<svg width=\"278pt\" height=\"188pt\"\n",
       " viewBox=\"0.00 0.00 278.00 188.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 184)\">\n",
       "<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-184 274,-184 274,4 -4,4\"/>\n",
       "<!-- A -->\n",
       "<g id=\"node1\" class=\"node\">\n",
       "<title>A</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"135\" cy=\"-162\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"135\" y=\"-158.3\" font-family=\"Times,serif\" font-size=\"14.00\">A</text>\n",
       "</g>\n",
       "<!-- B -->\n",
       "<g id=\"node2\" class=\"node\">\n",
       "<title>B</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"99\" cy=\"-90\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"99\" y=\"-86.3\" font-family=\"Times,serif\" font-size=\"14.00\">B</text>\n",
       "</g>\n",
       "<!-- A&#45;&gt;B -->\n",
       "<g id=\"edge1\" class=\"edge\">\n",
       "<title>A&#45;&gt;B</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M126.65,-144.76C122.29,-136.28 116.85,-125.71 111.96,-116.2\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"114.99,-114.44 107.3,-107.15 108.77,-117.64 114.99,-114.44\"/>\n",
       "</g>\n",
       "<!-- C -->\n",
       "<g id=\"node3\" class=\"node\">\n",
       "<title>C</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"171\" cy=\"-90\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"171\" y=\"-86.3\" font-family=\"Times,serif\" font-size=\"14.00\">C</text>\n",
       "</g>\n",
       "<!-- A&#45;&gt;C -->\n",
       "<g id=\"edge2\" class=\"edge\">\n",
       "<title>A&#45;&gt;C</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M143.35,-144.76C147.71,-136.28 153.15,-125.71 158.04,-116.2\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"161.23,-117.64 162.7,-107.15 155.01,-114.44 161.23,-117.64\"/>\n",
       "</g>\n",
       "<!-- D -->\n",
       "<g id=\"node4\" class=\"node\">\n",
       "<title>D</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"27\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"27\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">D</text>\n",
       "</g>\n",
       "<!-- B&#45;&gt;D -->\n",
       "<g id=\"edge3\" class=\"edge\">\n",
       "<title>B&#45;&gt;D</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M84.43,-74.83C74.25,-64.94 60.48,-51.55 48.97,-40.36\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"51.41,-37.85 41.8,-33.38 46.53,-42.87 51.41,-37.85\"/>\n",
       "</g>\n",
       "<!-- E -->\n",
       "<g id=\"node5\" class=\"node\">\n",
       "<title>E</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"99\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"99\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">E</text>\n",
       "</g>\n",
       "<!-- B&#45;&gt;E -->\n",
       "<g id=\"edge4\" class=\"edge\">\n",
       "<title>B&#45;&gt;E</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M99,-71.7C99,-63.98 99,-54.71 99,-46.11\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"102.5,-46.1 99,-36.1 95.5,-46.1 102.5,-46.1\"/>\n",
       "</g>\n",
       "<!-- F -->\n",
       "<g id=\"node6\" class=\"node\">\n",
       "<title>F</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"171\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"171\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">F</text>\n",
       "</g>\n",
       "<!-- C&#45;&gt;F -->\n",
       "<g id=\"edge5\" class=\"edge\">\n",
       "<title>C&#45;&gt;F</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M171,-71.7C171,-63.98 171,-54.71 171,-46.11\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"174.5,-46.1 171,-36.1 167.5,-46.1 174.5,-46.1\"/>\n",
       "</g>\n",
       "<!-- G -->\n",
       "<g id=\"node7\" class=\"node\">\n",
       "<title>G</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"243\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"243\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">G</text>\n",
       "</g>\n",
       "<!-- C&#45;&gt;G -->\n",
       "<g id=\"edge6\" class=\"edge\">\n",
       "<title>C&#45;&gt;G</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M185.57,-74.83C195.75,-64.94 209.52,-51.55 221.03,-40.36\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"223.47,-42.87 228.2,-33.38 218.59,-37.85 223.47,-42.87\"/>\n",
       "</g>\n",
       "</g>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "<__main__.mygraph at 0x7fd0794b5760>"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def backtrace(self, node):\n",
    "    nodes = []\n",
    "    while node != None:\n",
    "        nodes.append(node)\n",
    "        node = node.back\n",
    "    return tuple(reversed(nodes))\n",
    "\n",
    "def find_bfs_v2(self, dst):\n",
    "    # the first node to explore is the starting point\n",
    "    todo = [self]\n",
    "    self.back = None\n",
    "    self.graph.visited.add(self.name)\n",
    "\n",
    "    # keep looping while there are unexplored nodes\n",
    "    while len(todo) > 0:\n",
    "        print(\"TODO:\", todo)\n",
    "        curr = todo.pop(0) # pop from beginning\n",
    "\n",
    "        print(\"VISITING:\", curr)\n",
    "        if curr.name == dst:\n",
    "            return backtrace(self, curr)\n",
    "        else:\n",
    "            for child in curr.children:\n",
    "                if not child.name in self.graph.visited:\n",
    "                    todo.append(child)\n",
    "                    self.graph.visited.add(child.name)\n",
    "\n",
    "                    # remember we found child via curr\n",
    "                    # (will help us backtrack later!)\n",
    "                    child.back = curr\n",
    "    \n",
    "    # nothing left to check, and we haven't already returned True\n",
    "    return None\n",
    "\n",
    "Node.find = find_bfs_v2\n",
    "\n",
    "g = mygraph()\n",
    "g.edge(\"A\", \"B\")\n",
    "g.edge(\"A\", \"C\")\n",
    "g.edge(\"B\", \"D\")\n",
    "g.edge(\"B\", \"E\")\n",
    "g.edge(\"C\", \"F\")\n",
    "g.edge(\"C\", \"G\")\n",
    "g"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "TODO: [node A]\n",
      "VISITING: node A\n",
      "TODO: [node B, node C]\n",
      "VISITING: node B\n",
      "TODO: [node C, node D, node E]\n",
      "VISITING: node C\n",
      "TODO: [node D, node E, node F, node G]\n",
      "VISITING: node D\n",
      "TODO: [node E, node F, node G]\n",
      "VISITING: node E\n",
      "TODO: [node F, node G]\n",
      "VISITING: node F\n",
      "TODO: [node G]\n",
      "VISITING: node G\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "(node A, node C, node G)"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "g.find(\"A\", \"G\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's make a tougher test case, with the following:\n",
    "1. cycles\n",
    "2. short and long paths to the same target"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<!-- Generated by graphviz version 2.44.1 (20200629.0846)\n",
       " -->\n",
       "<!-- Pages: 1 -->\n",
       "<svg width=\"293pt\" height=\"260pt\"\n",
       " viewBox=\"0.00 0.00 292.61 260.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 256)\">\n",
       "<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-256 288.61,-256 288.61,4 -4,4\"/>\n",
       "<!-- A -->\n",
       "<g id=\"node1\" class=\"node\">\n",
       "<title>A</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"99\" cy=\"-234\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"99\" y=\"-230.3\" font-family=\"Times,serif\" font-size=\"14.00\">A</text>\n",
       "</g>\n",
       "<!-- B -->\n",
       "<g id=\"node2\" class=\"node\">\n",
       "<title>B</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"99\" cy=\"-162\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"99\" y=\"-158.3\" font-family=\"Times,serif\" font-size=\"14.00\">B</text>\n",
       "</g>\n",
       "<!-- A&#45;&gt;B -->\n",
       "<g id=\"edge1\" class=\"edge\">\n",
       "<title>A&#45;&gt;B</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M93.16,-216.41C92.3,-208.51 92.05,-198.85 92.41,-189.94\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"95.9,-190.18 93.12,-179.96 88.92,-189.68 95.9,-190.18\"/>\n",
       "</g>\n",
       "<!-- C -->\n",
       "<g id=\"node3\" class=\"node\">\n",
       "<title>C</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"207\" cy=\"-162\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"207\" y=\"-158.3\" font-family=\"Times,serif\" font-size=\"14.00\">C</text>\n",
       "</g>\n",
       "<!-- A&#45;&gt;C -->\n",
       "<g id=\"edge2\" class=\"edge\">\n",
       "<title>A&#45;&gt;C</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M117.81,-220.81C135,-209.67 160.62,-193.06 179.99,-180.5\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"181.92,-183.43 188.4,-175.05 178.11,-177.56 181.92,-183.43\"/>\n",
       "</g>\n",
       "<!-- B&#45;&gt;A -->\n",
       "<g id=\"edge5\" class=\"edge\">\n",
       "<title>B&#45;&gt;A</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M104.88,-179.96C105.71,-187.83 105.95,-197.37 105.58,-206.19\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"102.07,-206.18 104.84,-216.41 109.06,-206.69 102.07,-206.18\"/>\n",
       "</g>\n",
       "<!-- D -->\n",
       "<g id=\"node4\" class=\"node\">\n",
       "<title>D</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"27\" cy=\"-90\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"27\" y=\"-86.3\" font-family=\"Times,serif\" font-size=\"14.00\">D</text>\n",
       "</g>\n",
       "<!-- B&#45;&gt;D -->\n",
       "<g id=\"edge3\" class=\"edge\">\n",
       "<title>B&#45;&gt;D</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M84.43,-146.83C74.25,-136.94 60.48,-123.55 48.97,-112.36\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"51.41,-109.85 41.8,-105.38 46.53,-114.87 51.41,-109.85\"/>\n",
       "</g>\n",
       "<!-- E -->\n",
       "<g id=\"node5\" class=\"node\">\n",
       "<title>E</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"99\" cy=\"-90\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"99\" y=\"-86.3\" font-family=\"Times,serif\" font-size=\"14.00\">E</text>\n",
       "</g>\n",
       "<!-- B&#45;&gt;E -->\n",
       "<g id=\"edge4\" class=\"edge\">\n",
       "<title>B&#45;&gt;E</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M99,-143.7C99,-135.98 99,-126.71 99,-118.11\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"102.5,-118.1 99,-108.1 95.5,-118.1 102.5,-118.1\"/>\n",
       "</g>\n",
       "<!-- F -->\n",
       "<g id=\"node6\" class=\"node\">\n",
       "<title>F</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"171\" cy=\"-90\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"171\" y=\"-86.3\" font-family=\"Times,serif\" font-size=\"14.00\">F</text>\n",
       "</g>\n",
       "<!-- C&#45;&gt;F -->\n",
       "<g id=\"edge6\" class=\"edge\">\n",
       "<title>C&#45;&gt;F</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M198.65,-144.76C194.29,-136.28 188.85,-125.71 183.96,-116.2\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"186.99,-114.44 179.3,-107.15 180.77,-117.64 186.99,-114.44\"/>\n",
       "</g>\n",
       "<!-- G -->\n",
       "<g id=\"node7\" class=\"node\">\n",
       "<title>G</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"243\" cy=\"-90\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"243\" y=\"-86.3\" font-family=\"Times,serif\" font-size=\"14.00\">G</text>\n",
       "</g>\n",
       "<!-- C&#45;&gt;G -->\n",
       "<g id=\"edge7\" class=\"edge\">\n",
       "<title>C&#45;&gt;G</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M215.35,-144.76C219.71,-136.28 225.15,-125.71 230.04,-116.2\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"233.23,-117.64 234.7,-107.15 227.01,-114.44 233.23,-117.64\"/>\n",
       "</g>\n",
       "<!-- Z -->\n",
       "<g id=\"node8\" class=\"node\">\n",
       "<title>Z</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" cx=\"198\" cy=\"-18\" rx=\"27\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"198\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">Z</text>\n",
       "</g>\n",
       "<!-- C&#45;&gt;Z -->\n",
       "<g id=\"edge8\" class=\"edge\">\n",
       "<title>C&#45;&gt;Z</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M229.1,-151.61C246.19,-143.01 268.63,-128.5 279,-108 286.22,-93.72 286.61,-86.07 279,-72 268.82,-53.17 248.71,-39.95 231.07,-31.43\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"232.17,-28.08 221.61,-27.17 229.29,-34.46 232.17,-28.08\"/>\n",
       "</g>\n",
       "<!-- E&#45;&gt;Z -->\n",
       "<g id=\"edge9\" class=\"edge\">\n",
       "<title>E&#45;&gt;Z</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M117.16,-76.16C132.37,-65.41 154.29,-49.91 171.47,-37.76\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"173.81,-40.39 179.96,-31.76 169.77,-34.67 173.81,-40.39\"/>\n",
       "</g>\n",
       "</g>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "<__main__.mygraph at 0x7fd0794b5760>"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "g.edge(\"E\", \"Z\")\n",
    "g.edge(\"C\", \"Z\")\n",
    "g.edge(\"B\", \"A\")\n",
    "g"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now there are two A-to-Z paths:\n",
    "* A,B,E,Z\n",
    "* A,C,Z\n",
    "\n",
    "We ought to find the second one!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "TODO: [node A]\n",
      "VISITING: node A\n",
      "TODO: [node B, node C]\n",
      "VISITING: node B\n",
      "TODO: [node C, node D, node E]\n",
      "VISITING: node C\n",
      "TODO: [node D, node E, node F, node G, node Z]\n",
      "VISITING: node D\n",
      "TODO: [node E, node F, node G, node Z]\n",
      "VISITING: node E\n",
      "TODO: [node F, node G, node Z]\n",
      "VISITING: node F\n",
      "TODO: [node G, node Z]\n",
      "VISITING: node G\n",
      "TODO: [node Z]\n",
      "VISITING: node Z\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "(node A, node C, node Z)"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "g.find(\"A\", \"Z\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Just what we wanted."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Conclusion\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We have lots of experience using data structures like lists and dicts to keep track of data.  But data structures can also be used to keep track work that a program needs to do.  This strategy is used by BFS and many other systems.\n",
    "\n",
    "Although more complicated to implement, BFS guarantees the shortest path will be found (in contrast to DFS).  Of course, significant memory might be required to maintain the queue of nodes to visit if the graph is large.  Depending on the shape of the graph, this memory expense may be greater or less than the memory needed for the stack frames necessarly during a recursive depth-first search."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
