{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [
],
"source": [
"from sys import stderr\n",
"\n",
"from queue import LifoQueue as stack\n",
"from queue import PriorityQueue as p_queue\n",
"from queue import SimpleQueue as queue\n",
"\n",
"# It seems like these structures can keep \"garbage\" fro\n",
"# previous runs, so we must clean them out before using:\n",
"def gc(queue):\n",
" if not queue.empty():\n",
" while not queue.empty():\n",
" queue.get()"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"# The adjacency list graph\n",
"The following indicates the simple structure used for our graphs. The following shows a graph with nodes 0,1,2,3,4,5,6 and directed edges: $0\\to 1$ with weight 1, $0\\to 2$ with weight 2, etc. "
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {
"collapsed": false
},
"outputs": [
],
"source": [
"ToyGraph = {0 : {1:1, 2:1},\n",
" 1 : {3:8},\n",
" 2 : {4:2},\n",
" 3 : {4:1, 6:2},\n",
" 4 : {5:2, 3:5},\n",
" 5 : {3:1, 4:2},\n",
" 6 : {}}"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"# Visualizing graphs: `showGraph`\n",
"We can visualize our graphs using the networkx module. We need to load a few modules and convert our adjacency list graph to a networkx graph. This is done below in the following code which may be ignored. Things are set up to indicate the DFS ('blue'), the BFS solution ('red'), and the UCS solution ('green') some basic attempt has been made to indicte when the path overlay each other. "
]
},
{
"cell_type": "code",
"execution_count": 86,
"metadata": {
"collapsed": false
},
"outputs": [
],
"source": [
"import networkx as nx\n",
"import pylab as plt\n",
"import pydot as pdot\n",
"\n",
"from IPython.core.display import HTML, display, Image\n",
"\n",
"#import pygraphviz\n",
"#from networkx.drawing.nx_agraph import graphviz_layout\n",
"\n",
"def adjToNxGraph(G, digraph=True):\n",
" \"\"\"\n",
" Converts one of our adjacency \"list\" representations for a graph into\n",
" a networkx graph.\n",
" \"\"\"\n",
" if digraph:\n",
" Gr = nx.DiGraph()\n",
" else:\n",
" Gr = nx.Graph()\n",
"\n",
" for node in G:\n",
" Gr.add_node(node)\n",
" if G[node]:\n",
" for adj in G[node]:\n",
" Gr.add_edge(node, adj)\n",
" Gr[node][adj]['weight'] = G[node][adj]\n",
" return Gr\n",
"\n",
"def showGraph(G, start, goal, paths = [], node_labels = 'default', \n",
" node_pos = 'neato', gsize = (14,14), save_file=None, digraph=True):\n",
" \"\"\"\n",
" paths should be an array of which paths to show: paths = ['bfs', 'dfs', 'ucs']\n",
" node_labels must be one of: 'default', 'none', or a list of labels to use.\n",
" save_file must be an image file name with extension, i.e., save_file='my_graph.png'\n",
" \"\"\"\n",
" \n",
" fig, ax = plt.subplots(figsize=gsize)\n",
"\n",
" # Conver G into structure used in networkx\n",
" Gr = adjToNxGraph(G, digraph=digraph)\n",
"\n",
" if node_pos is 'project_layout':\n",
" # The project graphs have a particular structure.\n",
" node_pos = dict(zip(Gr.nodes(),[(b, 9 - a) for a,b in Gr.nodes()]))\n",
" else:\n",
" node_pos = nx.nx_pydot.graphviz_layout(Gr, prog=node_pos, root=start)\n",
" \n",
"\n",
" edge_weight=nx.get_edge_attributes(Gr,'weight')\n",
" \n",
" \n",
" def path_edges(path):\n",
" edges = list(zip(path[:-1], path[1:]))\n",
" cost = sum([Gr[z[0]][z[1]]['weight'] for z in edges])\n",
" if not digraph:\n",
" edges += list(zip(path[1:], path[:-1]))\n",
" return edges, cost\n",
" \n",
" # Process Paths:\n",
" if 'bfs' in paths:\n",
" bpath = getPath(bdfs(G, start, goal, search ='bfs'), start, goal)\n",
" bedges, bcost = path_edges(bpath)\n",
" else:\n",
" bpath = []\n",
" bedges = []\n",
" \n",
" if 'dfs' in paths:\n",
" dpath = getPath(bdfs(G, start, goal, search = 'dfs'), start, goal)\n",
" dedges, dcost = path_edges(dpath)\n",
" else:\n",
" dpath = []\n",
" dedges = []\n",
" \n",
" if 'ucs' in paths:\n",
" ucost, back = ucs(G, start, goal)\n",
" upath = getPath(back, start, goal)\n",
" uedges, ucost = path_edges(upath)\n",
" else:\n",
" upath = []\n",
" uedges = []\n",
" \n",
"\n",
" node_col = ['orange' if node in upath\n",
" else 'purple' if node in bpath and node in dpath\n",
" else 'blue' if node in dpath\n",
" else 'red' if node in bpath\n",
" else 'lightgray' for node in Gr.nodes()]\n",
"\n",
" if node_labels == 'default': \n",
" nodes = nx.draw_networkx_nodes(Gr, node_pos, ax = ax, node_color=node_col, node_size=400)\n",
" nodes.set_edgecolor('k')\n",
" nx.draw_networkx_labels(Gr, node_pos, ax = ax, font_size = 8)\n",
" elif node_labels == 'none':\n",
" nodes = nx.draw_networkx_nodes(Gr, node_pos, ax = ax, node_color=node_col, node_size=50)\n",
" else:\n",
" # labels must be a list\n",
" nodes = nx.draw_networkx_nodes(Gr, node_pos, ax = ax, node_color=node_col, node_size=400)\n",
" nodes.set_edgecolor('k')\n",
" mapping = dict(zip(Gr.nodes, node_labels))\n",
" nx.draw_networkx_labels(Gr, node_pos, labels=mapping, ax = ax, font_size = 8)\n",
" \n",
"\n",
" edge_col = ['purple' if edge in bedges and edge in dedges\n",
" else 'blue' if edge in dedges \n",
" else 'red' if edge in bedges \n",
" else 'orange' if edge in uedges else 'gray' for edge in Gr.edges()]\n",
" \n",
" edge_width = [3 if edge in dedges or edge in bedges or edge in uedges else 1 for edge in Gr.edges()]\n",
"\n",
" if digraph:\n",
" nx.draw_networkx_edge_labels(Gr, node_pos, ax = ax, edge_color=edge_col, label_pos=0.3, edge_labels=edge_weight)\n",
" else:\n",
" nx.draw_networkx_edge_labels(Gr, node_pos, ax = ax, edge_color=edge_col, edge_labels=edge_weight)\n",
" nx.draw_networkx_edges(Gr, node_pos, ax = ax, edge_color=edge_col, width=edge_width, alpha=.3)\n",
" \n",
" if save_file:\n",
" plt.savefig(save_file)\n",
" \n",
" plt.show()\n",
" \n",
" result = \"DFS gives a path of length {} with cost {}
\".format(len(dpath) - 1, dcost) if 'dfs' in paths else \"\" \n",
" result += \"BFS gives a path of length {} with cost {}. BFS always returns a minimal length path.
\".format(len(bpath) - 1, bcost) if 'bfs' in paths else \"\" \n",
" result += \"UCS gives a path of length {} with cost {}. UCS alway returns a minimal cost path.\".format(len(upath) - 1, ucost) if 'ucs' in paths else \"\"\n",
"\n",
" display(HTML(result)) # Need display in Jupyter"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"# Display initial toy graph"
]
},
{
"cell_type": "code",
"execution_count": 39,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/png": "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",
"text/plain": [
"