Created
April 24, 2018 23:39
-
-
Save yrevar/47cea1c972db822db6c62fe9e51b335c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "code", | |
"execution_count": 78, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"import math\n", | |
"import numpy as np\n", | |
"import networkx as nx\n", | |
"import matplotlib.pyplot as plt\n", | |
"\n", | |
"%matplotlib inline\n", | |
"\n", | |
"\"\"\"\n", | |
"Author: Yagnesh Revar\n", | |
"Date created: 2/25/2018\n", | |
"\"\"\"" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Undirected Graph" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"G = nx.Graph()\n", | |
"V = range(1,11)\n", | |
"E = [(1,2,1), \n", | |
" (2,3,2), \n", | |
" (1,3,2), \n", | |
" (3,4,5), \n", | |
" (1,4,9), \n", | |
" (2,5,4), \n", | |
" (5,6,10), \n", | |
" (3,6,2), \n", | |
" (6,7,5), \n", | |
" (4,7,8), \n", | |
" (7,8,2), \n", | |
" (5,8,1),\n", | |
" (9,10,5)]\n", | |
"# for v in V:\n", | |
"G.add_nodes_from(V)\n", | |
"\n", | |
"for e in E:\n", | |
" G.add_edge(e[0], e[1], weight=e[2])" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 3, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"NodeView((1, 2, 3, 4, 5, 6, 7, 8, 9, 10))" | |
] | |
}, | |
"execution_count": 3, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"G.nodes()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 4, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"EdgeView([(1, 2), (1, 3), (1, 4), (2, 3), (2, 5), (3, 4), (3, 6), (4, 7), (5, 8), (5, 6), (6, 7), (7, 8), (9, 10)])" | |
] | |
}, | |
"execution_count": 4, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"G.edges()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 5, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"{(1, 2): Text(0.904509,0.293893,u'1'),\n", | |
" (1, 3): Text(0.654508,0.475528,u'2'),\n", | |
" (1, 4): Text(0.345491,0.475528,u'9'),\n", | |
" (2, 3): Text(0.559017,0.769421,u'2'),\n", | |
" (2, 5): Text(-2.98023e-08,0.587785,u'4'),\n", | |
" (3, 4): Text(-2.98023e-08,0.951057,u'5'),\n", | |
" (3, 6): Text(-0.345492,0.475528,u'2'),\n", | |
" (4, 7): Text(-0.559017,0.181636,u'8'),\n", | |
" (5, 6): Text(-0.904509,0.293893,u'10'),\n", | |
" (5, 8): Text(-0.559017,-0.181636,u'1'),\n", | |
" (6, 7): Text(-0.904508,-0.293893,u'5'),\n", | |
" (7, 8): Text(-0.559017,-0.769421,u'2'),\n", | |
" (9, 10): Text(0.559017,-0.769421,u'5')}" | |
] | |
}, | |
"execution_count": 5, | |
"metadata": {}, | |
"output_type": "execute_result" | |
}, | |
{ | |
"data": { | |
"image/png": "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RjFy5EhSUlJ48cUX7aFcUDn0b07HEGtJSDCMoCDDcHc3DA8Pw7BPh7C/PDzs7wcF2fcrxblz54y//e1vhre3t/HKK68YZ8+erYD/gPnS09MNb29vIyMjw+xSRKqkL774wujevbvh6+trrFmzxsjLyyvbB8uxf6vq9Gxtq7pwwf7IuqQk+w343t722wmGDbvnyRHnzp0jMjKSuLg4hg4dyrRp02jQoIFDyraKMWPGUKdOHWbPnm12KSJVxt69e4mIiOD7779n5syZvPTSS7i6ut77gcqxf6uqFM5OJD09ncjISNauXcvw4cOZOnUq9evXN7ssh0hLS6NDhw58//331KpV0nx3ESnNV199RXh4OGlpacyYMYOXXnpJC804mK45O5FHHnmExYsXk5ycTF5eHi1atGDKlCmcP3/e7NLKna+vL8888wzvvPOO2aWIVFr79u2jV69eDBkyhIEDB5KamsrLL7+sYK4ACmcn1LBhQ5YsWcKhQ4fIyckhICCAadOmceHCBbNLK1fTpk1j0aJFXL9+3exSRCqVb7/9lt69ezNw4ECCg4M5evQoI0aMUChXIIWzE2vUqBHLli3j4MGDXLt2jebNm/Pqq69y8eJFs0srF61btyYwMJB169aZXYpIpZCQkMBzzz1HSEgI/fv35+jRo4waNQo3NzezS3M6CmehcePGREdHc+DAAS5fvkyzZs2YPn06mZmZZpf2wF599VXmz5/PzZs3zS5FxLISExPp27cvQUFBPPfccxw7dozRo0dTo0YNs0tzWgpnue33v/89K1as4LvvviMzMxN/f39mzJjBTz/9ZHZp961r1648/PDDbN682exSRCznu+++o1+/fvTv359evXpx7Ngxxo4dq1C2AIWz3KVJkyasXLmSxMREMjIy8Pf35/XXX+dSJVxTteBykroxQcTu4MGDDBgwgL59+9KjRw+OHz/O+PHjcS9hBSmpWApnKdZjjz1GTEwM3377LWfOnMHPz4+IiAguX75sdmn3pG/fvmRlZbFr1y6zSxEx1aFDhwgKCqJPnz50796d48ePExoaqlC2IIWzlOoPf/gDq1ev5ptvvuHEiRP4+fnxxhtvcOXKFbNLKxMXFxemTZvGW2+9ZXYpIqZISkoiJCSEXr160aVLF44fP86ECRPwKGLBHbEGhbOUma+vL7GxsXz99dekpaXRtGlT3nzz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\n", | |
"text/plain": [ | |
"<matplotlib.figure.Figure at 0x114805c90>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"pos = nx.shell_layout(G)\n", | |
"nx.draw(G, pos, with_labels=True)\n", | |
"labels = nx.get_edge_attributes(G,'weight')\n", | |
"nx.draw_networkx_edge_labels(G, pos, edge_labels=labels)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Depth First Search (Recursive), Toplogical Sorting, and Connected Components" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 6, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"visited = {}\n", | |
"clock = 0\n", | |
"preorder, postorder = None, None\n", | |
"ccnum = {}\n", | |
"cc = 0\n", | |
"def DFS_recursive(G, V=None):\n", | |
" \n", | |
" global visited, clock, preorder, postorder, ccnum, cc\n", | |
" \n", | |
" clock = 0\n", | |
" cc = 0\n", | |
" if not V:\n", | |
" V = sorted(list(G.nodes()))\n", | |
" visited = {v: False for v in V}\n", | |
" preorder = {v: None for v in V}\n", | |
" postorder = {v: None for v in V}\n", | |
" ccnum = {v: None for v in V}\n", | |
"\n", | |
" for v in V:\n", | |
" if not visited[v]: \n", | |
" explore(G, v)\n", | |
" cc += 1\n", | |
" return visited, preorder, postorder, ccnum, cc\n", | |
"\n", | |
"def explore(G, v):\n", | |
" \n", | |
" global visited\n", | |
" visited[v] = True\n", | |
" \n", | |
" DFS_previsit(G, v)\n", | |
" for nbr in sorted(G.neighbors(v)):\n", | |
" if not visited[nbr]: explore(G, nbr)\n", | |
" DFS_postvisit(G, v)\n", | |
" \n", | |
"def DFS_previsit(pre,v):\n", | |
" global clock, preorder, ccnum, cc\n", | |
" preorder[v] = clock\n", | |
" ccnum[v] = cc\n", | |
" clock += 1\n", | |
" \n", | |
"def DFS_postvisit(post,v):\n", | |
" global clock, postorder\n", | |
" postorder[v] = clock\n", | |
" clock += 1" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 7, | |
"metadata": { | |
"scrolled": false | |
}, | |
"outputs": [], | |
"source": [ | |
"_ = DFS_recursive(G)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 8, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def summary(G):\n", | |
" \n", | |
" print \"Graph Nodes: \", G.nodes()\n", | |
" print \"Edges: \", G.edges()\n", | |
" visited, preorder, postorder, ccnum, cc = DFS_recursive(G)\n", | |
" print \"# Connected Components: \", cc\n", | |
" for v in G.nodes():\n", | |
" print \"node: {}, pre #: {}, post #: {}, CC#: {}\".format(v, preorder[v], postorder[v], ccnum[v]) " | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 9, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Graph Nodes: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n", | |
"Edges: [(1, 2), (1, 3), (1, 4), (2, 3), (2, 5), (3, 4), (3, 6), (4, 7), (5, 8), (5, 6), (6, 7), (7, 8), (9, 10)]\n", | |
"# Connected Components: 2\n", | |
"node: 1, pre #: 0, post #: 15, CC#: 0\n", | |
"node: 2, pre #: 1, post #: 14, CC#: 0\n", | |
"node: 3, pre #: 2, post #: 13, CC#: 0\n", | |
"node: 4, pre #: 3, post #: 12, CC#: 0\n", | |
"node: 5, pre #: 6, post #: 9, CC#: 0\n", | |
"node: 6, pre #: 5, post #: 10, CC#: 0\n", | |
"node: 7, pre #: 4, post #: 11, CC#: 0\n", | |
"node: 8, pre #: 7, post #: 8, CC#: 0\n", | |
"node: 9, pre #: 16, post #: 19, CC#: 1\n", | |
"node: 10, pre #: 17, post #: 18, CC#: 1\n" | |
] | |
} | |
], | |
"source": [ | |
"summary(G)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Directed Graph" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 10, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"G = nx.DiGraph()\n", | |
"V = range(1,11)\n", | |
"E = [(1,2,1), \n", | |
" (2,3,2), \n", | |
" (3,2,2), # 2,3 should be in same SCC\n", | |
" (1,3,2), \n", | |
" (3,4,5), \n", | |
" (1,4,9), \n", | |
" (2,5,4), \n", | |
" (5,6,10), \n", | |
" (3,6,2), \n", | |
" (6,7,5), \n", | |
" (4,7,8), \n", | |
" (7,8,2), \n", | |
" (5,8,1),\n", | |
" (9,10,5), # 9-10 should be in same SCC\n", | |
" (10,9,5)]\n", | |
"\n", | |
"# for v in V:\n", | |
"G.add_nodes_from(V)\n", | |
"\n", | |
"for e in E:\n", | |
" G.add_edge(e[0], e[1], weight=e[2])" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 11, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"{(1, 2): Text(0.904509,0.293893,u'1'),\n", | |
" (1, 3): Text(0.654508,0.475528,u'2'),\n", | |
" (1, 4): Text(0.345491,0.475528,u'9'),\n", | |
" (2, 3): Text(0.559017,0.769421,u'2'),\n", | |
" (2, 5): Text(-2.98023e-08,0.587785,u'4'),\n", | |
" (3, 2): Text(0.559017,0.769421,u'2'),\n", | |
" (3, 4): Text(-2.98023e-08,0.951057,u'5'),\n", | |
" (3, 6): Text(-0.345492,0.475528,u'2'),\n", | |
" (4, 7): Text(-0.559017,0.181636,u'8'),\n", | |
" (5, 6): Text(-0.904509,0.293893,u'10'),\n", | |
" (5, 8): Text(-0.559017,-0.181636,u'1'),\n", | |
" (6, 7): Text(-0.904508,-0.293893,u'5'),\n", | |
" (7, 8): Text(-0.559017,-0.769421,u'2'),\n", | |
" (9, 10): Text(0.559017,-0.769421,u'5'),\n", | |
" (10, 9): Text(0.559017,-0.769421,u'5')}" | |
] | |
}, | |
"execution_count": 11, | |
"metadata": {}, | |
"output_type": "execute_result" | |
}, | |
{ | |
"data": { | |
"image/png": "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\n", | |
"text/plain": [ | |
"<matplotlib.figure.Figure at 0x114814710>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"pos = nx.shell_layout(G)\n", | |
"nx.draw(G, pos, with_labels=True)\n", | |
"labels = nx.get_edge_attributes(G,'weight')\n", | |
"nx.draw_networkx_edge_labels(G, pos, edge_labels=labels)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Strongly Connected Components" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 12, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def SCC(G):\n", | |
" \"\"\"\n", | |
" Finds strongly connected components of Directed Graph\n", | |
" \"\"\"\n", | |
" \n", | |
" G_R = G.reverse()\n", | |
" visited, preorder, postorder, ccnum, cc = DFS_recursive(G_R)\n", | |
" # https://www.saltycrane.com/blog/2007/09/how-to-sort-python-dictionary-by-keys/\n", | |
" # https://stackoverflow.com/questions/8081545/convert-list-of-tuples-to-multiple-lists-in-python\n", | |
" V_po_rev_ordered = zip(*sorted(postorder.iteritems(), key=lambda (k,v): (v, k), reverse=True))[0]\n", | |
" return DFS_recursive(G, V_po_rev_ordered)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 13, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"visited, preorder, postorder, ccnum, cc = SCC(G)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 14, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"{1: 7, 2: 6, 3: 6, 4: 5, 5: 4, 6: 3, 7: 2, 8: 1, 9: 0, 10: 0}" | |
] | |
}, | |
"execution_count": 14, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"ccnum" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 15, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"SCC_LIST = []\n", | |
"tt = set()\n", | |
"for (k,v) in ccnum.iteritems():\n", | |
" if v not in tt:\n", | |
" SCC_LIST.append((k,))\n", | |
" tt.add(v)\n", | |
" else:\n", | |
" SCC_LIST[-1] = SCC_LIST[-1] + (k,)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 16, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"[(1,), (2, 3), (4,), (5,), (6,), (7,), (8,), (9, 10)]\n" | |
] | |
} | |
], | |
"source": [ | |
"print SCC_LIST" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 17, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"[{8}, {7}, {4}, {6}, {5}, {2, 3}, {1}, {9, 10}]" | |
] | |
}, | |
"execution_count": 17, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"list(nx.strongly_connected_components(G))" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Breadth First Search (Queue)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 18, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"G = nx.DiGraph()\n", | |
"V = range(1,11)\n", | |
"E = [(1,2,1), \n", | |
" (2,3,2), \n", | |
" (3,2,2), # 2,3 should be in same SCC\n", | |
" (1,3,2), \n", | |
" (3,4,5), \n", | |
" (1,4,9), \n", | |
" (2,5,4), \n", | |
" (5,6,10), \n", | |
" (3,6,2), \n", | |
" (6,7,5), \n", | |
" (4,7,8), \n", | |
" (7,8,2), \n", | |
" (5,8,1),\n", | |
" (9,10,5), # 9-10 should be in same SCC\n", | |
" (10,9,5),\n", | |
" (1,8,4)]\n", | |
"\n", | |
"# for v in V:\n", | |
"G.add_nodes_from(V)\n", | |
"\n", | |
"for e in E:\n", | |
" G.add_edge(e[0], e[1], weight=e[2])" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 19, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def BFS(G,s):\n", | |
" \n", | |
" V = list(G.nodes())\n", | |
" dist = {v: float(\"inf\") for v in V}\n", | |
" \n", | |
" dist[s] = 0\n", | |
" frontier_Q = [s] # Queue containing just s\n", | |
" explored = {v: False for v in V}\n", | |
" parent = {v: None for v in V}\n", | |
" \n", | |
" while len(frontier_Q):\n", | |
" \n", | |
" u = frontier_Q.pop(0) # First in first out\n", | |
" explored[u] = True\n", | |
" # print u\n", | |
" for v in sorted(G.neighbors(u)):\n", | |
" # print \"\\t->\", v\n", | |
" if not explored[v]: #if dist[v] == float(\"inf\"):\n", | |
" frontier_Q.append(v)\n", | |
" dist[v] = dist[u] + 1\n", | |
" parent[v] = u\n", | |
" \n", | |
" return dist" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 20, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"{1: 0, 2: 1, 3: 2, 4: 3, 5: 2, 6: 3, 7: 4, 8: 1, 9: inf, 10: inf}" | |
] | |
}, | |
"execution_count": 20, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"BFS(G, 1)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 21, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"{1: inf, 2: inf, 3: inf, 4: inf, 5: inf, 6: inf, 7: inf, 8: inf, 9: 0, 10: 1}" | |
] | |
}, | |
"execution_count": 21, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"BFS(G, 9)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Depth First Search (Stack)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 22, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def DFS(G,s):\n", | |
" \n", | |
" V = list(G.nodes())\n", | |
" dist = {v: float(\"inf\") for v in V}\n", | |
" \n", | |
" dist[s] = 0\n", | |
" frontier_stack = [s] # Stack containing just s\n", | |
" explored = {v: False for v in V}\n", | |
" parent = {v: None for v in V}\n", | |
" \n", | |
" while len(frontier_stack):\n", | |
" \n", | |
" u = frontier_stack.pop(0) # Last in first out\n", | |
" explored[u] = True\n", | |
" # print u\n", | |
" for v in sorted(G.neighbors(u))[::-1]:\n", | |
" # print \"\\t->\", v\n", | |
" if not explored[v]: #if dist[v] == float(\"inf\"):\n", | |
" frontier_stack.insert(0, v)\n", | |
" dist[v] = dist[u] + 1\n", | |
" parent[v] = u\n", | |
" \n", | |
" return dist, parent" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 23, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"dist, parent = DFS(G, 1)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 24, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def get_path(parent, node):\n", | |
" \n", | |
" path = [node]\n", | |
" while parent[node]:\n", | |
" \n", | |
" path.append(parent[node])\n", | |
" node = parent[node]\n", | |
" return path" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 25, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"[8, 7, 4, 3, 2, 1]" | |
] | |
}, | |
"execution_count": 25, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"get_path(parent, 8)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Dijkstra's Algorithm: Single Source All Shortest Paths" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 26, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"import heapq" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 27, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def Dijkstra(G, s):\n", | |
" \n", | |
" V = sorted(list(G.nodes()))\n", | |
" dist = {}\n", | |
" parent = {}\n", | |
" for v in V:\n", | |
" parent[v] = None\n", | |
" dist[v] = float(\"inf\")\n", | |
" \n", | |
" dist[s] = 0\n", | |
" # heapq will sort based on 1st element of the item in the list, and if there's tie it'll check 2nd element.\n", | |
" # So we use min distance found so far to any given target vertex as a first element in the list item\n", | |
" # Queue = [ (cost0, v0), (cost1, v1), ... ,(costm, vm) ]\n", | |
" frontier_priority_queue = [(dist[v], v) for v in V]\n", | |
" heapq.heapify(frontier_priority_queue)\n", | |
" \n", | |
" while len(frontier_priority_queue) != 0:\n", | |
" \n", | |
" _, u = heapq.heappop(frontier_priority_queue)\n", | |
" # print frontier_priority_queue, \"Pop: \", _, u\n", | |
" \n", | |
" for v in G.neighbors(u):\n", | |
" \n", | |
" if dist[v] > dist[u] + G.get_edge_data(u,v)['weight']:\n", | |
" dist[v] = dist[u] + G.get_edge_data(u,v)['weight']\n", | |
" parent[v] = u\n", | |
" heapq.heappush(frontier_priority_queue, (dist[v], v))\n", | |
" \n", | |
" return dist, parent" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 28, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"dist, parent = Dijkstra(G, 1)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 29, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def get_shortest_paths(G, parent):\n", | |
" \n", | |
" d = {}\n", | |
" for v in G.nodes():\n", | |
" path = get_path(parent, v)[::-1]\n", | |
" if len(path) > 1 or path[0] == v:\n", | |
" d[v] = path\n", | |
" else:\n", | |
" d[v] = []\n", | |
" return d" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 30, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"{1: [1],\n", | |
" 2: [1, 2],\n", | |
" 3: [1, 3],\n", | |
" 4: [1, 3, 4],\n", | |
" 5: [1, 2, 5],\n", | |
" 6: [1, 3, 6],\n", | |
" 7: [1, 3, 6, 7],\n", | |
" 8: [1, 8],\n", | |
" 9: [9],\n", | |
" 10: [10]}" | |
] | |
}, | |
"execution_count": 30, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"get_shortest_paths(G, parent)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 31, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"{1: [1],\n", | |
" 2: [1, 2],\n", | |
" 3: [1, 3],\n", | |
" 4: [1, 3, 4],\n", | |
" 5: [1, 2, 5],\n", | |
" 6: [1, 3, 6],\n", | |
" 7: [1, 3, 6, 7],\n", | |
" 8: [1, 8]}" | |
] | |
}, | |
"execution_count": 31, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"nx.shortest_path(G, 1, weight='weight')" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 32, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def swap(arr, i, j):\n", | |
" arr[i], arr[j] = arr[j], arr[i]\n", | |
" return arr" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Sorting\n", | |
"## Heap Sort (From Geeks for Geeks)\n", | |
"\n", | |
"Assume Array represents a binary tree: [root, left, right, left_left, left_right, right_left, right_right, ...] \n", | |
"\n", | |
"Properties: \n", | |
" \n", | |
"Child of ith element: A[2*i+1], A[2*i+1+2] \n", | |
"Parent of ith element: A[floor(i/2)] \n", | |
"\n", | |
"[n/2, ..., n] are all leaves of a nearly balanced binary tree" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 33, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"A = [np.random.randint(20) for i in range(10)]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 34, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"A = [8, 19, 6, 17, 0, 2, 18, 6, 13, 2]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 35, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def heapify(A, i, n):\n", | |
" # Bubble down the ith element so that heap is ordered/maintained\n", | |
" \n", | |
" left = 2*i + 1\n", | |
" right = 2*i + 2\n", | |
" max_idx = i\n", | |
" \n", | |
" if left < n and A[left] > A[i]:\n", | |
" max_idx = left\n", | |
" if right < n and A[right] > A[max_idx]:\n", | |
" max_idx = right\n", | |
" \n", | |
" if max_idx != i: #swap\n", | |
" A[i], A[max_idx] = A[max_idx], A[i]\n", | |
" heapify(A, max_idx, n)\n", | |
" return" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 36, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"heapify(A, 0, len(A))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 37, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"[19, 17, 6, 13, 0, 2, 18, 6, 8, 2]" | |
] | |
}, | |
"execution_count": 37, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"A" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 38, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def heapsort(A):\n", | |
" \n", | |
" n = len(A)\n", | |
" \n", | |
" # Build max-heap\n", | |
" # start from the parent of the last leaves, and keep bubbling down the nodes while going up\n", | |
" for i in range(n/2-1,-1,-1):\n", | |
" heapify(A, i, n)\n", | |
" \n", | |
" # To sort, start removing the max/top node and putting it at the back of the heap, keep heapifying so we always have max at the top.\n", | |
" for i in range(n-1, 0, -1): # iterate from the last element to the 2nd element of the heap\n", | |
" # At first iteration this will swap root (first/max element of the heap/list) with the last element of the heap.\n", | |
" # Next iteration it'll swap root (which would be 2nd to max element after heapyfying) with the 2nd to last element of the heap.\n", | |
" A[i], A[0] = A[0], A[i] # swap, violate heap at index 0 as well as ith, however we consider ith entry removed from the heap. \n", | |
" heapify(A, 0, i) # heapify at 0 on heap 0-i, i-end: sorted elements" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 39, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"heapsort(A)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 40, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"[0, 2, 2, 6, 6, 8, 13, 17, 18, 19]" | |
] | |
}, | |
"execution_count": 40, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"A" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 41, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def view_as_binary_tree(A, i, n):\n", | |
" \n", | |
" left = 2*i + 1\n", | |
" right = 2*i + 2\n", | |
" \n", | |
" if i < n:\n", | |
" if i >= n/2:\n", | |
" print A[i], \": leaf\"\n", | |
" else:\n", | |
" print A[i], \":\",\n", | |
" if left < n:\n", | |
" print A[left],\n", | |
" if right < n:\n", | |
" print A[right],\n", | |
" print \"\"\n", | |
" \n", | |
" if left < n:\n", | |
" view_as_binary_tree(A, left, n)\n", | |
" if right < n:\n", | |
" view_as_binary_tree(A, right, n)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 42, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"0 : 2 2 \n", | |
"2 : 6 6 \n", | |
"6 : 17 18 \n", | |
"17 : leaf\n", | |
"\n", | |
"18 : leaf\n", | |
"\n", | |
"6 : 19 \n", | |
"19 : leaf\n", | |
"\n", | |
"2 : 8 13 \n", | |
"8 : leaf\n", | |
"\n", | |
"13 : leaf\n", | |
"\n" | |
] | |
} | |
], | |
"source": [ | |
"view_as_binary_tree(A, 0, len(A))" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Merge Sort" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 44, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def merge(A):\n", | |
" n = len(A)\n", | |
" if n == 1:\n", | |
" return A\n", | |
" left = merge(A[:n//2])\n", | |
" right = merge(A[n//2:])\n", | |
" return combine(left, right)\n", | |
"\n", | |
"def combine(left, right):\n", | |
" \n", | |
" if len(left) == 0:\n", | |
" return right\n", | |
" \n", | |
" if len(right) == 0:\n", | |
" return left\n", | |
" \n", | |
" if left[0] < right[0]:\n", | |
" return [left[0]] + combine(left[1:], right)\n", | |
" else:\n", | |
" return [right[0]] + combine(left, right[1:])" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 45, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"[0, 2, 2, 6, 6, 8, 13, 17, 18, 19]" | |
] | |
}, | |
"execution_count": 45, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"A" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 46, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"[0, 2, 2, 6, 6, 8, 13, 17, 18, 19]" | |
] | |
}, | |
"execution_count": 46, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"merge(A)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Quick Sort" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 47, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def partition(A, left, right, pivot_idx):\n", | |
" \n", | |
" pivot = A[pivot_idx]\n", | |
" A[pivot_idx], A[right-1] = A[right-1], A[pivot_idx]\n", | |
" store_idx = left\n", | |
" \n", | |
" for i in range(left, right-1):\n", | |
" \n", | |
" if A[i] <= pivot:\n", | |
" A[store_idx], A[i] = A[i], A[store_idx]\n", | |
" store_idx += 1\n", | |
" \n", | |
" A[store_idx], A[right-1] = A[right-1], A[store_idx]\n", | |
" return store_idx\n", | |
"\n", | |
"def q_sort(A, left, right):\n", | |
" \n", | |
" if left < right:\n", | |
" pivot_idx = np.random.randint(left, right)\n", | |
" pivot_idx_new = partition(A, left, right, pivot_idx)\n", | |
" q_sort(A, left, pivot_idx_new)\n", | |
" q_sort(A, pivot_idx_new+1, right)\n", | |
" return A" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 48, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"A = [8, 19, 6, 17, 0, 2, 18, 6, 13, 2]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 49, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"[0, 2, 2, 6, 6, 8, 13, 17, 18, 19]" | |
] | |
}, | |
"execution_count": 49, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"q_sort(A, 0, len(A))\n", | |
"A" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Binary Search Tree\n", | |
"(from geeksforgeeks)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 50, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"class Node:\n", | |
" \n", | |
" def __init__(self, key):\n", | |
" \n", | |
" self.key = key\n", | |
" self.left = None\n", | |
" self.right = None\n", | |
" \n", | |
"\n", | |
"def insert_BST_node(node, key):\n", | |
" \n", | |
" # If a node is empty, two possibilities: 1) It's a root, 2) It's a leaf\n", | |
" # in both cases we create a new node with key=key and return it. \n", | |
" # If this is root node, we'll create a new tree rooted at tree, otherwise it'll return leaf node (tree) rooted at key which could be stored to parent pointers.\n", | |
" if node is None:\n", | |
" return Node(key)\n", | |
" \n", | |
" if key < node.key:\n", | |
" node.left = insert_BST_node(node.left, key)\n", | |
" else:\n", | |
" node.right = insert_BST_node(node.right, key)\n", | |
" \n", | |
" return node" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 51, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"root = insert_BST_node(None, 10)\n", | |
"root = insert_BST_node(root, 15)\n", | |
"root = insert_BST_node(root, 4)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 52, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def traverse_BST_inorder(root):\n", | |
" \n", | |
" if root is not None:\n", | |
" traverse_BST_inorder(root.left)\n", | |
" print root.key,\n", | |
" traverse_BST_inorder(root.right)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 53, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"4 10 15\n" | |
] | |
} | |
], | |
"source": [ | |
"traverse_BST_inorder(root)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 54, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def get_BST_minval(root):\n", | |
" \n", | |
" curr = root\n", | |
" \n", | |
" while curr.left is not None:\n", | |
" curr = curr.left\n", | |
" \n", | |
" return curr" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 55, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"4" | |
] | |
}, | |
"execution_count": 55, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"get_BST_minval(root).key" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 56, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def del_BST_node(root, key):\n", | |
" \n", | |
" if root is None:\n", | |
" return root\n", | |
" \n", | |
" if key < root.key:\n", | |
" root.left = del_BST_node(root.left, key)\n", | |
" elif key > root.key:\n", | |
" root.right = del_BST_node(root.right, key)\n", | |
" \n", | |
" if root.left is None:\n", | |
" onlychild = root.right\n", | |
" root = None # to delete the object\n", | |
" return onlychild\n", | |
" elif root.right is None:\n", | |
" onlychild = root.left\n", | |
" root = None\n", | |
" return onlychild\n", | |
" else:\n", | |
" \n", | |
" # The easiest way to remove root node in BST is to replace with the next inorder node so that least shuffling is required\n", | |
" # The next inorder node is the left most node of the tree rooted at right branch\n", | |
" \n", | |
" in_next = get_BST_minval(root.right) # get inorder successor node\n", | |
" root.key = in_next.key # read its value and assign to current node\n", | |
" root.right = del_BST_node(root.right, in_next.key) # delete inorder successor node\n", | |
" \n", | |
" return root" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 57, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"root = del_BST_node(root, 10)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 58, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"4 15\n" | |
] | |
} | |
], | |
"source": [ | |
"traverse_BST_inorder(root)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Kruskal's MST" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 59, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def create_undirected_graph(vertices, edges):\n", | |
" G = nx.Graph()\n", | |
" G.add_nodes_from(vertices)\n", | |
" for e in edges:\n", | |
" G.add_edge(e[0], e[1], weight=e[2])\n", | |
" return G" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 60, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def draw_G(G, layout= lambda g: nx.shell_layout(*g)):\n", | |
" \"\"\"\n", | |
" circular_layout(G[, dim, scale, center])\tPosition nodes on a circle.\n", | |
" random_layout(G[, dim, center])\tPosition nodes uniformly at random in the unit square.\n", | |
" shell_layout(G[, nlist, dim, scale, center])\tPosition nodes in concentric circles.\n", | |
" spring_layout(G[, dim, k, pos, fixed, ...])\tPosition nodes using Fruchterman-Reingold force-directed algorithm.\n", | |
" spectral_layout(G[, dim, weight, scale, center])\tPosition nodes using the eigenvectors of the graph Laplacian.\n", | |
" \"\"\"\n", | |
" pos = layout(G)\n", | |
" nx.draw(G, pos, with_labels=True)\n", | |
" labels = nx.get_edge_attributes(G,'weight')\n", | |
" nx.draw_networkx_edge_labels(G, pos, edge_labels=labels)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 61, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"Vs = list(\"ABCDEF\")\n", | |
"Es = [(x[0], x[1], float(x[2])) for x in \"AB4 AC1 BD4 BC4 AD3 CD2 CF4 DF6 FE5\".split(\" \")]\n", | |
"G = create_undirected_graph(Vs, Es)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 62, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"image/png": "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\n", | |
"text/plain": [ | |
"<matplotlib.figure.Figure at 0x11484cfd0>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"draw_G(G, lambda g: nx.spring_layout(g, k=100, iterations=1000))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 63, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"EdgeDataView([('A', 'C', {'weight': 1.0}), ('A', 'B', {'weight': 4.0}), ('A', 'D', {'weight': 3.0}), ('C', 'B', {'weight': 4.0}), ('C', 'D', {'weight': 2.0}), ('C', 'F', {'weight': 4.0}), ('B', 'D', {'weight': 4.0}), ('E', 'F', {'weight': 5.0}), ('D', 'F', {'weight': 6.0})])" | |
] | |
}, | |
"execution_count": 63, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"G.edges(data=True)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"### Union Find Data Structure (as described in DPV Ch. 5)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 64, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"class UnionFindDS:\n", | |
" \n", | |
" def __init__(self):\n", | |
" self.P = {}\n", | |
" self.rank = {}\n", | |
" \n", | |
" def makeset(self, x):\n", | |
" self.P[x] = x\n", | |
" self.rank[x] = 0\n", | |
" \n", | |
" def find(self, x):\n", | |
" while self.P[x] != x:\n", | |
" x = self.P[x]\n", | |
" return x\n", | |
" \n", | |
" def union(self, x, y):\n", | |
" \n", | |
" rx = self.find(x)\n", | |
" ry = self.find(y)\n", | |
" \n", | |
" if rx == ry: return\n", | |
" \n", | |
" if self.rank[x] > self.rank[y]:\n", | |
" self.P[ry] = rx\n", | |
" else:\n", | |
" self.P[rx] = ry\n", | |
" # acts like elif\n", | |
" if self.rank[rx] == self.rank[ry]: self.rank[ry] = self.rank[ry] + 1\n", | |
" \n", | |
"class UnionFindDS_Awesome:\n", | |
" \n", | |
" def __init__(self):\n", | |
" self.P = {}\n", | |
" self.rank = {}\n", | |
" \n", | |
" def makeset(self, x):\n", | |
" self.P[x] = x\n", | |
" self.rank[x] = 0\n", | |
" \n", | |
" def find(self, x):\n", | |
" if self.P[x] != x:\n", | |
" self.P[x] = self.find(self.P[x])\n", | |
" return self.P[x]\n", | |
" \n", | |
" def union(self, x, y):\n", | |
" \n", | |
" rx = self.find(x)\n", | |
" ry = self.find(y)\n", | |
" \n", | |
" if rx == ry: return\n", | |
" \n", | |
" if self.rank[x] > self.rank[y]:\n", | |
" self.P[ry] = rx\n", | |
" else:\n", | |
" self.P[rx] = ry\n", | |
" # acts like elif\n", | |
" if self.rank[rx] == self.rank[ry]: self.rank[ry] = self.rank[ry] + 1" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 65, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def Kruskal(G):\n", | |
" \n", | |
" union_find = UnionFindDS_Awesome()\n", | |
" for u in G.nodes:\n", | |
" union_find.makeset(u)\n", | |
" \n", | |
" X = []\n", | |
" for u, v, data in sorted(G.edges(data=True), key=lambda x: x[2]['weight']):\n", | |
" #print('{a} {b} {w}'.format(a=a, b=b, w=data['weight']))\n", | |
" if union_find.find(u) != union_find.find(v):\n", | |
" X.append((u,v,data['weight']))\n", | |
" union_find.union(u,v)\n", | |
" return X, union_find" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 66, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"[('A', 'C', 1.0),\n", | |
" ('C', 'D', 2.0),\n", | |
" ('A', 'B', 4.0),\n", | |
" ('C', 'F', 4.0),\n", | |
" ('E', 'F', 5.0)]" | |
] | |
}, | |
"execution_count": 66, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"mst_edges, components = Kruskal(G)\n", | |
"mst_edges" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 67, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"{'A': 'C', 'B': 'B', 'C': 'B', 'D': 'B', 'E': 'B', 'F': 'B'}" | |
] | |
}, | |
"execution_count": 67, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"components.P" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 68, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"{'A': 0, 'B': 1, 'C': 1, 'D': 0, 'E': 0, 'F': 0}" | |
] | |
}, | |
"execution_count": 68, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"components.rank" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 69, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"G_MST = create_undirected_graph(G.nodes, Kruskal(G)[0])" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 70, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"EdgeDataView([('A', 'C', {'weight': 1.0}), ('A', 'B', {'weight': 4.0}), ('C', 'D', {'weight': 2.0}), ('C', 'F', {'weight': 4.0}), ('E', 'F', {'weight': 5.0})])" | |
] | |
}, | |
"execution_count": 70, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"G_MST.edges(data=True)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 71, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAecAAAFCCAYAAADL3BUJAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMS4wLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvpW3flQAAIABJREFUeJzt3XlclWXi/vEPiAuYW4q75b6AYKK44AIuaJpZlq0/K21MTbQ0zdJy2tPKyha1pvqOtk3Z5DiNuaSgqImKKyhomihiKrghyg7P748TJ1FQ0APPWa7368VrgvOcw0WTXN73uZ/7djMMw0BERETshrvZAURERKQwlbOIiIidUTmLiIjYGZWziIiInVE5i4iI2BmVs4iIiJ1ROYuIiNgZlbOIiIidUTmLiIjYGZWziIiInVE5i4iI2BmVs4iIiJ1ROYuIiNgZlbOIiIidUTmLiIjYGZWziIiInVE5i4iI2BkPswOIiJSr5GRYuBBiYiA1FWrUAH9/GDUKvL3NTicCgJthGIbZIUREylx0NMyaBStWWD7PzPzrMU9PMAwYNAimT4fAQHMyivxJ5Swizm/BApg6FTIyLCVcHDc3S1HPmQNPPll++UQuo2ltEXFuBcWcnn7taw3Dct3UqZbPVdBiEo2cRcR5RUdDSEihYm4KnAQqXHLZSODjy5/r5QWRkdC5c9lmFCmCVmuLiPOaNcsylX2Z/wEXLvm4opjB8rxZs8o0nkhxVM4i4pySky2Lv653ctAwYPlySEmxbS6RElA5i4hzWrjwxl/Dzc02ryNSSipnEXFOMTGFb5e6xN1AzUs+PivuNTIyIDa2TOKJXI1Wa4uIc0pNLfahpUD/kr7O2bO2SCNSKho5i4hzqlHDNq9Tq5ZtXkekFFTOIuKc/P2hSpUbew1PT/Dzs00ekVLQfc4i4pySk8lr3JgKOTmFvtyUK+9zDgX+U9RrVKkCiYnac1vKnUbOIuJ0kpKSuC8sjDUVK5Lv5lboscNABoXvcy6ymN3cYPBgFbOYQuUsIk4jOzubt99+m9tuuw1fX1+CV67E3dPz+l7M09NyCIaICbRaW0ScQkREBBMmTKBZs2Zs2bKFFi1aWB6YM6fke2sX8PKyPE9bd4pJVM4i4tD++OMPpkyZQlRUFB988AFDhw7F7dKp7ILDK3QqlTgQTWuLiEPKycnhvffew9/fn+bNmxMXF8ddd91VuJgLPPmk5RCLYcMsi7wun+r29LR8fdgwy3UqZjGZVmuLiMNZv349YWFhNGjQgI8//pjWrVuX/MkpKZYtOWNjLRuM1KpluV1q5Egt/hK7oXIWEYdx8uRJnn32WdauXcv777/PvffeW/RIWcTBaVpbROxebm4uH330Ee3bt6dBgwbEx8czfPhwFbM4LS0IExG7FhUVxfjx46lZsyaRkZH4+PiYHUmkzKmcRcQupaSk8Pzzz7Ny5UrmzJnDgw8+qJGyuAxNa4uIXcnLy+OTTz7B19eXGjVqEB8fz0MPPaRiFpeikbOI2I3o6GjGjx9PlSpVWLNmDf7+/mZHEjGFRs4iYrrTp08zbtw4hg4dysSJE1m/fr2KWVyayllETJOfn88XX3yBr68vFStWJD4+nkcffVRT2OLyNK3typKTLZsxxMRAaqrlcHp/fxg1SpsxSJnbuXMn48ePB2D58uUEBASYnEjEfmgTElcUHQ2zZsGKFZbPMzP/eszT07L38KBBlhN5AgPNyShO69y5c8ycOZPFixfz5ptvMmrUKNzdNYkncin9iXA1CxZASAgsXWop5UuLGSwHA2RmWh4PCbFcL2IDhmHw5Zdf0q5dO3JycoiPj+dvf/ubilmkCJrWdiULFpT86DzDsFw3darlcx0EIDcgNjaW8ePHk5mZyU8//USgZmRErkrT2q4iOtoyEi7NmbYFvLwsJ/XobFsppfPnz/PSSy/xzTff8Oqrr/LEE09QoUIFs2OJ2D3NJ7mKWbMsU9aXaAp4AjcBtYA7gKNFPTcjw/J8kRIyDINvv/2Wdu3acf78efbu3cu4ceNUzCIlpJGzK0hOhltvveL95abA50B/IBMYD5wBlhb1GlWqQGKiVnHLNcXFxTFhwgTOnj3L/Pnz6d69u9mRRByORs6uYOHCa15SBRgOxBV3gZtbiV5HXNeFCxeYNm0awcHB3HPPPURHR6uYRa6TytkVxMRcuSr7MunA90C34i7IyLAcTi9yGcMw+OGHH2jXrh0nT55kz549TJgwAQ8PrTcVuV760+MKUlOLfehuLP8RXAS8gVVXe52zZ20aSxzf/v37mThxIsePH+fbb7+lV69eZkcScQoaObuCGjWKfWgpcA7Le84fA8HAieIurlXL1snEQaWnp/PCCy/Qo0cPBg0axI4dO1TMIjakcnYF/v6WBV1XUQG458//3VjUBZ6e4Odn+2ziUAzDYOnSpfj4+JCQkEBMTAyTJ0+mYsWKZkcTcSpare0KSrBa2wB+Au4FdgO+l7+GVmu7vN9//52nnnqKhIQE5s2bR58+fcyOJOK0NHJ2BXXrWvbKLuKknzux3OdcHXgBWEQRxezmBoMHq5hdVEZGBi+//DJdu3YlODiYXbt2qZhFypgWhLmK6dNh1apCO4QdLulzPT0tzxeX8/PPP/PUU08REBDAzp07adKkidmRRFyCprVdSWn21i7g5QVz5mhvbRdz+PBhJk2aRFxcHB9//DEDBgwwO5KIS9G0tit58klL0Xp5FTnFXYibm4rZBWVlZfHGG2/QuXNnunTpQmxsrIpZxAQqZ1fz5JOWQyyGDbMs8vL0LPRwVoUKlq8PG2a5TsXsMlatWoWfnx/btm1j27ZtzJgxg8qVK5sdS8QlaVrblaWkWLbkjI2Fs2dJ8/Dg/fBwZh48iFvdumank3Jy9OhRJk+ezM6dO/nwww+54447zI4k4vJUzlJI8+bN+emnn2jfvr3ZUaSMZWdn8/777/POO+8wceJEpk2bhudlMykiYg6t1pZCQkNDWbNmjcrZyUVERBAWFkbz5s3ZsmULLVq0MDuSiFxC7zlLIaGhoaxevdrsGFJGjh07xkMPPcTjjz/O7NmzWbZsmYpZxA6pnKWQPn36sGHDBrKzs82OIjaUk5PDe++9R4cOHWjRogVxcXHcdddduF1r1b6ImELT2lJI7dq1adOmDVFRUQQHB5sdR2xg/fr1hIWF0aBBAzZt2kTr1q3NjiQi16CRs1xBU9vO4cSJEzzyyCOMGDGCl156iVWrVqmYRRyEylmuoHJ2bLm5uXz00Uf4+fnRsGFD4uLiGD58uKawRRyIbqWSK2RlZeHt7c2RI0eopTOcHcqmTZsICwujVq1azJs3j3bt2pkdSUSug0bOcoXKlSvTo0cP1q5da3YUKaGUlBQef/xx7rvvPqZNm0Z4eLiKWcSBqZylSJradgx5eXksWLAAX19fatasSXx8PA899JCmsEUcnFZrS5FCQ0OZP3++2THkKqKjoxk/fjyenp6Eh4fj5+dndiQRsRGNnKVI7du358KFCyQkJJgdRS5z+vRpxo4dy9ChQ3nqqaeIjIxUMYs4GZWzFMnNzY3+/ftratuO5Ofn8/nnn+Pj40OlSpWIj4/nkUce0RS2iBPStLYUKzQ0lGXLljFmzBizo7i8HTt2MH78eNzc3Fi5ciUdO3Y0O5KIlCHdSiXFOnbsGP7+/iQnJ1OhQgWz47iks2fPMnPmTP7973/z5ptvMnLkSNzdNeEl4uz0p1yK1ahRI+rXr8/OnTvNjuJyDMNg0aJF+Pj4kJeXR1xcHI8//riKWcRFaFpbrqrglqrOnTubHcVlxMTEEBYWRmZmJj/99BOBgYFmRxKRcqa/hstV6X7n8nP+/HkmT55M//79GTFiBJs3b1Yxi7golbNcVe/evYmOjiY9Pd3sKE7LMAy+/fZb2rVrR1paGnFxcYwdO1bv84u4ME1ry1VVq1aNjh07sn79em6//Xaz4ziduLg4wsLCSE1N5ccff6Rbt25mRxIRO6CRs1yTprZt78KFC0ybNo2QkBCGDx9OdHS0illErFTOck0qZ9sxDIMffviBdu3akZycTGxsLGFhYZrCFpFCdJ+zXFNubi7e3t7Ex8dTv359s+M4rP379zNx4kROnDjBvHnz6NWrl9mRRMROaeQs1+Th4UGfPn0IDw83O4pDunjxIjNmzKBnz54MHjyYHTt2qJhF5KpUzlIimtouPcMwWLp0Kb6+vhw5coTdu3czadIkPDy0DlNErk7T2lIiBw4cICQkhKSkJB20UAK///47EydO5PDhw8ybN48+ffqYHUlEHIhGzlIiLVu2pGLFisTHx5sdxa5lZGTw0ksv0bVrV/r06cOuXbtUzCJSaipnKRE3NzdNbV/DsmXL8PX1JT4+nl27dvHss89SqVIls2OJiANSOUuJqZyLlpCQwNChQ5kyZQqffPIJixcvpnHjxmbHEhEHpnKWEuvXrx8bNmwgOzvb7Ch2ITMzk9dee43AwEC6detGTEwMAwYMMDuWiDgBlbOUWO3atWnVqhVbtmwxO4rpVq1ahZ+fHzt27GD79u3MmDGDypUrmx1LRJyE7umQUimY2nbV+3QTExOZPHkyu3fv5sMPP2Tw4MFmRxIRJ6SRs5RK//79nfp95927d5ORkQFY7lMuYBgGO3fuJCAgAH9/f/bs2aNiFpEyo/ucpVQyMzPx9vbm6NGj1KxZ0+w4NrNnzx5GjBhB7dq1qVSpEjNmzLhidiArK4uUlBQt9hKRMqeRs5RKlSpVCAoKYu3atWZHsal//etf3HvvvYSHh3PXXXcxY8YMDh8+XOiaSpUqqZhFpFyonKXUnOmWqvz8fMBybnXBPcnjxo2jXbt2LFy40DrFDWhnNBEpNypnKTVHL+djx44BlmJ2d7f8EahQoQKGYXDmzBkApk6dyqpVq6yjZ737IyLlSeUspebn58f58+evmPa1d2lpaYwbN47hw4eTnp6Ou7u7tXQHDRrEhg0biIuLIysri9atW9OpUyfmzp0LaNQsIuVL5Syl5u7uTv/+/VmzZo3ZUUpsyZIlBAQEULduXdatW4eXlxdgKV3DMGjfvj09evTghx9+YOvWrQCEhITQsmVLM2OLiItSOct1cbSp7fT0dPLz83n11VepXLkyv/32G2lpacBfo+LJkyfTpEkTZs2axdixYwkLC6NNmzZmxhYRF6VbqeS6JCUlcdttt5GcnGx939beDRw4kDZt2nDq1CnOnDlDXl4eEydOpF+/flStWtV63c6dO4mMjOTuu++madOm5gUWEZflGL9Vxe40btwYb29vdu7caXaUEpszZw5Lly4lMDCQlStXcs8997BmzRr27dtHeno6P//8M9nZ2XTs2JFJkyapmEXENNq+U65bwdR2p06dzI5SIn5+fmzatMl6r/KTTz5JSEgIeXl5REdHYxiGjngUEbugkbNcN0d437ngPuYCl24ism3bNtzd3alZsybBwcEMGTKkvOOJiBRJ5SzXLSQkhK1bt5Kenm52lCvk5+fzz3/+k9OnTxf6umEYJCcnc9999zFx4kTCwsJo3bq1SSlFRIqmcpbrVq1aNW677TY2btxodpRCduzYQVBQEJ999pl1RXYBNzc3KleuzIABA4iKiuLee+81KaWISPFUznJD7Glq++zZs4SFhTF48GDGjBnDxo0bad68+RXX1ahRgyeeeMKEhCIiJaNylhtiD0dI5ufns3DhQnx8fDAMg7i4OB5//HGHucVLRORyus9Zbkhubi516tRh//791KtXr9y/f0xMDOPHjyc7O5v58+fTuXPncs8gImJrGlrIDfHw8CAkJITw8PBy/b6pqalMmjSJ0NBQHn30UTZv3qxiFhGnoXKWG1ae7zsbhsE333yDj48PFy9eZO/evYwZM0ZT2CLiVDStLTfst99+o1+/fiQmJpbp6U179+4lLCyM8+fPM3/+fLp161Zm30tExEwabsgNa9WqFe7u7uzfv79MXj8tLY1nn32WkJAQ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mTJlCqGhobz11lvUrVvX7FhWGRkZ1K1bl2PHjlG9enWz44iICzl79ixt27ZlzZo1+JXDcY+2oGltJ7Bv3z4mTJhASkoK3333HT17XnECqek8PT3p2rUr69atY+jQoWbHEREX8vrrr3P33Xc7TDGDprUd2sWLF5k+fTq9evXizjvvZPv27XZZzAU0tS0i5e3gwYMsWrSIV1991ewopaJydkCGYbBkyRJ8fHw4evQoMTExPP3003h42PdEiI6QFJHy9txzzzFlyhTq1atndpRS0XvODubAgQNMnDiRo0ePMm/ePEJCQsyOVGL5+fnUq1ePnTt30rhxY7PjiIiTi4yM5LHHHmPfvn1UqVLF7DilopGzg0hPT2fmzJl0796d/v37s2vXLocqZgB3d3f69u2rqW0RKXP5+fk888wzzJ492+GKGVTODuF///sfvr6+/Pbbb+zatYupU6c6xH16RdH7ziJSHr766isqVarEAw88YHaU62Lfb1K6uISEBJ566ikOHDjAZ599Rv/+/c2OdMMGDx7MsWPHdISkiJSZixcv8sILL/Dvf//bYX/PaORshzIzM3n11VcJDAwkKCiI3bt3O0UxAzRs2JDnnnvOYf/AiIj9mzNnDr169aJbt25mR7luGjnbmRUrVjBx4kT8/f3ZsWMHt9xyi9mRbM4R3/8REcdw7NgxPvzwQ3bs2GF2lBui1dp2IjExkUmTJhETE8NHH33EoEGDzI4kIuJwRo4cScOGDXnzzTfNjnJDNK1tsuzsbGbNmkVAQAAdO3Zkz549KmYRkeuwfft2Vq1axfPPP292lBumaW0TrVmzhgkTJtCqVSu2bt1K8+bNzY5kmvz8fNzd3bVQTESui2EYPPPMM7z66qtOsX+/ytkESUlJTJkyha1bt/Lhhx9y5513mh2p3BmGwbvvvkv16tW56aabuOuuu6hataqKWUSuy9KlSzl79iyPP/642VFsQu85l6OcnBw++OADZs+ezfjx43n++efx8vIyO1a5KxglDxkyhGrVqtGpUyd+//13srOzuf/++2nRogUtW7Y0O6aIOIisrCx8fX355JNPnObOFo2cy8m6desICwujSZMmREVF0apVK7MjmS4wMJDz588zdepUNm3axIEDB5g8eTKtW7dm6dKlZscTEQcxb9482rZt6zTFDCrnMnf8+HGeffZZNmzYwPvvv8+w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\n", | |
"text/plain": [ | |
"<matplotlib.figure.Figure at 0x114a71990>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"draw_G(G_MST, lambda g: nx.spring_layout(g, k=100, iterations=1000))" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Prim's MST (basically Dijkstra's algorithm)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 72, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def prim(G):\n", | |
" \n", | |
" #use alphabetical ordering of nodes (unlike tie breaking in Kruskal's)\n", | |
" V = sorted(list(G.nodes()))\n", | |
" dist = {}\n", | |
" parent = {}\n", | |
" for v in V:\n", | |
" parent[v] = None\n", | |
" dist[v] = float(\"inf\")\n", | |
" \n", | |
" ## DIFF1 from Dijaktra's, pick random source node\n", | |
" s = V[0] # use alphabetical ordering of nodes (unlike tie breaking in Kruskal's)\n", | |
" dist[s] = 0\n", | |
" # heapq will sort based on 1st element of the item in the list, and if there's tie it'll check 2nd element.\n", | |
" # So we use min distance found so far to any given target vertex as a first element in the list item\n", | |
" # Queue = [ (cost0, v0), (cost1, v1), ... ,(costm, vm) ]\n", | |
" frontier_priority_queue = [(dist[v], v) for v in V]\n", | |
" heapq.heapify(frontier_priority_queue)\n", | |
" \n", | |
" while len(frontier_priority_queue) != 0:\n", | |
" \n", | |
" _, u = heapq.heappop(frontier_priority_queue)\n", | |
" # print frontier_priority_queue, \"Pop: \", _, u\n", | |
" \n", | |
" for v in G.neighbors(u):\n", | |
" \n", | |
" if dist[v] > G.get_edge_data(u,v)['weight']: # DIFF2 from Dijaktra's, dist/cost = dist[u] + G.get_edge_data(u,v)['weight']\n", | |
" dist[v] = G.get_edge_data(u,v)['weight']\n", | |
" parent[v] = u\n", | |
" heapq.heappush(frontier_priority_queue, (dist[v], v))\n", | |
" \n", | |
" return dist, parent\n", | |
"\n", | |
"def printMST(G, parent):\n", | |
" for v in G.nodes:\n", | |
" if parent[v] != None and v != None:\n", | |
" print parent[v],\"-\", v, \"\\t\", G[parent[v]][v]\n", | |
" \n", | |
"def get_edges(G, parent):\n", | |
" X = []\n", | |
" for v in G.nodes:\n", | |
" if parent[v] != None and v != None:\n", | |
" X.append((parent[v], v, G[parent[v]][v]['weight']))\n", | |
" return X" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 73, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"dist, parent = prim(G)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 74, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"X = get_edges(G, parent)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 75, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"G_MST = create_undirected_graph(G.nodes, get_edges(G, prim(G)[1]))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 76, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"image/png": "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5pCamkqTJk0ctl93ndpWOVdBI2cRcbSePXuyceNGRowYwYYNG4yOYyq7du1i7NixbNq0ibZt2zp03yrnOkIjZxFxlu7du5OamsrEiRPJzs42Oo4pfPHFFyQmJrJixQpuueUWh+8/ODjYLctZq7Ur0aVUIuJMnTt35vPPP8fX17fabco/h+r659HRo0eJiYlh9uzZREVFOeUYGjnXIXX5L4OIGK9BgwYXXfBU/hl07NgxV0VyuZ9//pm4uDgeeOABhg8f7rTjuGs5a+Rciaa1RcQINpuNL774goKCAt577z0sFgvLli1j+fLlREZGGh3PoYqKikhMTKRbt2786U9/cuqxVM51iEbOIuJKX331FUuXLuXkyZN07tyZevXqUa9ePYKDg+vcgMFms/HAAw/g7+/PwoULnf55667lrGntSuraXwQRMb8zZ86wZs0abr/9dsaPH09ISAhZWVk89thjTjsXa5QZM2bw5ZdfsmrVKnx8nD8+bNWqFUeOHHG7z3aNnKugkbOIuIrNZuPWW2/lrbfeYsyYMXzzzTccOHCAfv36MXDgQABKS0sr7pblzovE3njjDdasWUNWVhb16tVzyTHr1atHQEAAJ0+epGnTpi45piNo5FyJu327EhH3Vl60vXv35oEHHmDevHkEBwczbNgwAIqLi/H29qa0tBSbzcahQ4eMjFtrGzdu5OmnnyY1NZWrr77apcd2x6ltjZwrcedvpSLinmw2Gzt27GDHjh1MnjwZf39/ysrKKC4uxs/PjzNnzjBr1ixOnDjBZ599Rnx8PI8//rjRsWvsk08+4f7772fz5s3ccMMNLj9+eTnffPPNLj92bamcq6ByFhFXslgsdOrUiXHjxtG/f/+Kn/v5+ZGfn8+AAQMICQlh6NChPPXUU4SHh9OtWze3WMV94MAB+vfvz1//+le6detmSAaNnOsATWuLiBGaNGlC//79ee2117j++uuJiYmhpKSEIUOG0L59e1544QUAfH19iYmJcfnUcG1kZ2cTExPDM888Q9++fQ3L4Y7lrHPOVdDIWUSMct999xEUFATAqlWraNGiBS+++CK+vr74+vqybt06NmzYQMOGDQ1OenFnz56lb9++3HPPPYwePdrQLCrnOkAjZxExUmBgIDfddBMAx48fp3379tSvXx+AtLQ0Hn30URYuXMi1115r2s+rkpISBg8ezO9+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\n", | |
"text/plain": [ | |
"<matplotlib.figure.Figure at 0x114a8ccd0>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"draw_G(G_MST, lambda g: nx.spring_layout(g, k=100, iterations=1000))" | |
] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "py3", | |
"language": "python", | |
"name": "py3" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 2 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython2", | |
"version": "2.7.3" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 2 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment