{"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"name":"2022-01-20-site-rank.ipynb","provenance":[{"file_id":"https://github.com/recohut/nbs/blob/main/raw/T063204%20%7C%20Using%20Basic%20Graph%20Theory%20to%20Rank%20Websites%20by%20Popularity.ipynb","timestamp":1644652991001}],"collapsed_sections":[],"mount_file_id":"1rT_QuvN41cRuqmg-Er4oCRGGnV1ChTLQ","authorship_tag":"ABX9TyNzSca3h+CrAOcdlx7se1up"},"kernelspec":{"name":"python3","display_name":"Python 3"},"language_info":{"name":"python"}},"cells":[{"cell_type":"markdown","metadata":{"id":"tRtTnlRZ_ejE"},"source":["# Using Basic Graph Theory to Rank Websites by Popularity"]},{"cell_type":"markdown","metadata":{"id":"TPyxgmcQBKnM"},"source":["There are many data science websites on the internet. Some sites are more popular than others. Suppose you wish to estimate the most popular data science website using data that is publicly available. This precludes privately tracked traffic data. What should you do? Network theory offers us a simple way of ranking websites based on their public links. To see how, let’s build a simple network composed of two data science websites: a NumPy tutorial and a SciPy tutorial. In graph theory, these websites are referred to as the nodes in the graph. Nodes are network points that can form connections with each other; these connections are called edges. Our two website nodes will form an edge if one site links to the other or vice versa.\n","\n","**Listing 18. 1. Defining a node list**"]},{"cell_type":"code","metadata":{"id":"43hz_afuAb08"},"source":["nodes = ['NumPy', 'SciPy']"],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"6j21ze4bAb0-"},"source":["Suppose the _SciPy_ website is discussing NumPy dependencies. This discussion includes a web-link to the _NumPy_ page. We'll treat this connection as an edge that goes from index 1 to index 0. The edge can be expressed as the tuple `(1, 0)`. \n","\n","**Listing 18. 2. Defining an edge list**"]},{"cell_type":"code","metadata":{"id":"gzDMPI20Ab0_"},"source":["edges = [(1, 0)]"],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"hb2-hU2AAb1A"},"source":["Given our directed `edges` list, we can easily check if a webpage at index `i` links a webpage at index `j`. That connection exists if `(i, j) in edges` equals `True`.\n","\n","**Listing 18. 3. Checking for the existence of an edge**"]},{"cell_type":"code","metadata":{"id":"E3QcoSHPAb1A"},"source":["def edge_exists(i, j): return (i, j) in edges\n","\n","assert edge_exists(1, 0)\n","assert not edge_exists(0, 1)"],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"hvH-iElIAb1B"},"source":["Our `edge_exists` function works, but it's not efficient. The function must traverse a list to check the presence of an edge. One alternative approach is to store the presence or absence of each edge `(i, j)` within the ith row and jth column of a matrix. This matrix representation of a network is known as an **adjacency matrix**. \n","\n","\n","**Listing 18. 4. Tracking nodes and edges using a matrix**"]},{"cell_type":"code","metadata":{"id":"tHy0kBHbAb1D","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637507053254,"user_tz":-330,"elapsed":12,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"32fdcdb9-625a-4808-fc5d-9d28fc8b5daf"},"source":["import numpy as np\n","adjacency_matrix = np.zeros((len(nodes), len(nodes)))\n","for i, j in edges:\n"," adjacency_matrix[i][j] = 1\n"," \n","assert adjacency_matrix[1][0]\n","assert not adjacency_matrix[0][1]\n","\n","print(adjacency_matrix)"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["[[0. 0.]\n"," [1. 0.]]\n"]}]},{"cell_type":"markdown","metadata":{"id":"4R5gEKryAb1F"},"source":["Our matrix print-out permits us to view those edges that are present in the network. Additionally, we can observe potential edges that are missing from the network. Lets turn our attention to the missing edge going from _Node 0_ to _Node 1_. We'll add that edge to our adjacency matrix. This will imply that the _NumPy_ page now links to the _SciPy_ page.\n","\n","**Listing 18. 5. Adding an edge to the adjacency matrix**"]},{"cell_type":"code","metadata":{"id":"XHK_RPm0Ab1G","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637507055471,"user_tz":-330,"elapsed":7,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"3fd0ec66-b51b-460e-cd41-85618a8f4368"},"source":["adjacency_matrix[0][1] = 1\n","print(adjacency_matrix)"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["[[0. 1.]\n"," [1. 0.]]\n"]}]},{"cell_type":"markdown","metadata":{"id":"jzGNOr-tAb1H"},"source":["Suppose we wish to expand our website network by adding two more data science sites. We'll need to expand the adjacency matrix dimensions from 2-by-2 to 4-by-4. Unfortunately, in NumPy, it's quite hard to resize a matrix while maintaining all existing matrix values. We need to switch to a different Python library; NextworkX.\n","\n","### Analyzing Web Networks Using NetworkX\n","\n","We'll begin by installing NetworkX. Afterwords, we'll import `networkx` as `nx`, per the common NetworkX usage convention.\n","\n","**Listing 18. 6. Importing the NetworkX library**"]},{"cell_type":"code","metadata":{"id":"pHYencVKAb1I"},"source":["import networkx as nx"],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"x9DsODcuAb1J"},"source":["Now, we will utilize `nx` to generate a directed graph. In NetworkX, directed graphs are tracked using the `nx.DiGraph` class.\n","\n","**Listing 18. 7. Initializing a directed graph object**"]},{"cell_type":"code","metadata":{"id":"9dhAfNJOAb1K"},"source":["G = nx.DiGraph()"],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"-hBVP2vXAb1K"},"source":["Lets slowly expand the directed graph. To start, we'll add a single node.\n","\n","**Listing 18. 8. Adding a single node to a graph object**"]},{"cell_type":"code","metadata":{"id":"-4p7CgwcAb1L","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637507075592,"user_tz":-330,"elapsed":6,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"8b17dacf-3ce3-43c6-f5a8-c243d9ac2df7"},"source":["G.add_node(0)\n","print(nx.to_numpy_array(G))"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["[[0.]]\n"]}]},{"cell_type":"markdown","metadata":{"id":"E6oOXRP7Ab1N"},"source":["Our single node is associated with a _NumPy_ webpage. We can explicitly record this association by executing `G.nodes[0]['webpage'] = 'NumPy'`. \n","\n","\n","**Listing 18. 9. Adding an attribute to an existing node**"]},{"cell_type":"code","metadata":{"id":"5kcdmousAb1N","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637507076369,"user_tz":-330,"elapsed":10,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"fd65d884-27b1-4910-ec4b-683dbb6af7b4"},"source":["def print_node_attributes():\n"," for i in G.nodes:\n"," print(f\"The attribute dictionary at node {i} is {G.nodes[i]}\")\n","\n","print_node_attributes()\n","G.nodes[0]['webpage'] = 'NumPy'\n","print(\"\\nWe've added a webpage to node 0\")\n","print_node_attributes()"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["The attribute dictionary at node 0 is {}\n","\n","We've added a webpage to node 0\n","The attribute dictionary at node 0 is {'webpage': 'NumPy'}\n"]}]},{"cell_type":"markdown","metadata":{"id":"ptz1T6LlAb1O"},"source":["We've added a node attribute after first inserting the node into the graph. However, we can also assign attributes directly while inserting a node into the graph.\n","\n","**Listing 18. 10. Adding a node with an attribute**"]},{"cell_type":"code","metadata":{"id":"zD9nmhSlAb1P","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637507077030,"user_tz":-330,"elapsed":7,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"ba2cf30b-50b8-4d12-bca5-b902b0d4a2c7"},"source":["G.add_node(1, webpage='SciPy')\n","print_node_attributes()"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["The attribute dictionary at node 0 is {'webpage': 'NumPy'}\n","The attribute dictionary at node 1 is {'webpage': 'SciPy'}\n"]}]},{"cell_type":"markdown","metadata":{"id":"qgwgqHR0Ab1Q"},"source":["\n","Please note that we can output all the nodes and together with their attributes simply by running `G.nodes(data=True)`.\n","\n","**Listing 18. 11. Outputting nodes together with their attributes**"]},{"cell_type":"code","metadata":{"id":"kiEl8fPzAb1Q","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637507077790,"user_tz":-330,"elapsed":8,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"6d92fc6b-8484-44dd-b601-9998fc78a7f6"},"source":["print(G.nodes(data=True))"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["[(0, {'webpage': 'NumPy'}), (1, {'webpage': 'SciPy'})]\n"]}]},{"cell_type":"markdown","metadata":{"id":"J7HB9nMvAb1R"},"source":["Now, lets add a web-link from _Node 1_ (SciPy) to _Node 0_ (NumPy). \n","\n","**Listing 18. 12. Adding a single edge to a graph object**"]},{"cell_type":"code","metadata":{"id":"eWtisfLCAb1R","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637507079905,"user_tz":-330,"elapsed":6,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"0ad7d554-91fb-434e-c1f8-7a7f6a143702"},"source":["G.add_edge(1, 0)\n","print(nx.to_numpy_array(G))"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["[[0. 0.]\n"," [1. 0.]]\n"]}]},{"cell_type":"markdown","metadata":{"id":"kyDenZOMAb1S"},"source":["Printing the adjacency matrix has given us a visual representation of the network. Unfortunately, our matrix visualization will grow cumbersome as other nodes are added. What if instead, we plotted the network directly? Our two nodes could be plotted as two points in 2D space. Meanwhile, our single edge could be plotted as a line segment that connects these points. \n","\n","**Listing 18. 13. Plotting a graph object**"]},{"cell_type":"code","metadata":{"id":"MJHMMxlqAb1S","colab":{"base_uri":"https://localhost:8080/","height":319},"executionInfo":{"status":"ok","timestamp":1637507081410,"user_tz":-330,"elapsed":10,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"2142d5db-a20c-4312-fda7-367ce0345968"},"source":["import matplotlib.pyplot as plt \n","np.random.seed(0)\n","nx.draw(G)\n","plt.show()"],"execution_count":null,"outputs":[{"output_type":"display_data","data":{"image/png":"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\n","text/plain":["
"]},"metadata":{}}]},{"cell_type":"markdown","metadata":{"id":"ZJVikYlwAb1T"},"source":["Our plotted graph could clearly use some improvement. First of all, we need to make our arrow bigger. Also, we will benefit by adding labels to the nodes. \n","\n","**Listing 18. 14. Tweaking the graph visulization**"]},{"cell_type":"code","metadata":{"id":"0sDu3FPdAb1T","colab":{"base_uri":"https://localhost:8080/","height":319},"executionInfo":{"status":"ok","timestamp":1637507082214,"user_tz":-330,"elapsed":8,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"36a92840-7932-49bc-b44a-7f24766dd18b"},"source":["np.random.seed(0)\n","labels = {i: G.nodes[i]['webpage'] for i in G.nodes}\n","nx.draw(G, labels=labels, arrowsize=20)\n","plt.show()"],"execution_count":null,"outputs":[{"output_type":"display_data","data":{"image/png":"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\n","text/plain":["
"]},"metadata":{}}]},{"cell_type":"markdown","metadata":{"id":"Nc2h5xA3Ab1U"},"source":["The arrow is now bigger, and the node labels now partially visible. Unfortunately, these labels are obscured by the dark node color. However, we can make the labels more visible by changing the node color to something lighter, like cyan.\n","\n","**Listing 18. 15. Altering the node color**"]},{"cell_type":"code","metadata":{"id":"KzPpmnLzAb1U","colab":{"base_uri":"https://localhost:8080/","height":319},"executionInfo":{"status":"ok","timestamp":1637507083678,"user_tz":-330,"elapsed":832,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"4d8bd2ed-feaa-4531-8112-5407ed3d1197"},"source":["np.random.seed(0)\n","nx.draw(G, labels=labels, node_color=\"cyan\", arrowsize=20)\n","plt.show()"],"execution_count":null,"outputs":[{"output_type":"display_data","data":{"image/png":"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\n","text/plain":["
"]},"metadata":{}}]},{"cell_type":"markdown","metadata":{"id":"d_VyLGlbAb1V"},"source":["Within our latest plot, the labels are much more clearly visible. We see the directed link from _SciPy_ to _NumPy_. Now, lets add a reverse web-link from _NumPy_ to _SciPy_ in order to stay consistent with our earlier discussion.\n","\n","**Listing 18. 16. Adding a back-link between webpages**"]},{"cell_type":"code","metadata":{"id":"bK8coJ4jAb1V","colab":{"base_uri":"https://localhost:8080/","height":319},"executionInfo":{"status":"ok","timestamp":1637507083679,"user_tz":-330,"elapsed":10,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"5771341c-7b16-4897-d10f-ad425df007fa"},"source":["np.random.seed(0)\n","G.add_edge(0, 1)\n","nx.draw(G, labels=labels, node_color=\"cyan\", arrowsize=20)\n","plt.show()"],"execution_count":null,"outputs":[{"output_type":"display_data","data":{"image/png":"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\n","text/plain":["
"]},"metadata":{}}]},{"cell_type":"markdown","metadata":{"id":"pXpbVlInAb1W"},"source":["We are now ready to expand our network by adding two more webpages; _Pandas_ and _Matplotlib_. These webpages will correspond to nodes containing ids 2 and 3, respectively.\n","\n","**Listing 18. 17. Adding multiple nodes to a graph object** "]},{"cell_type":"code","metadata":{"id":"mfCRs5nnAb1W","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637507084316,"user_tz":-330,"elapsed":6,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"328dc485-37c7-4b80-b6d8-cb100465a63e"},"source":["webpages = ['Pandas', 'Matplotlib']\n","new_nodes = [(i, {'webpage': webpage})\n"," for i, webpage in enumerate(webpages, 2)]\n","G.add_nodes_from(new_nodes)\n","\n","print(f\"We've added these nodes to our graph:\\n{new_nodes}\")\n","print('\\nOur updated list of nodes is:')\n","print(G.nodes(data=True))"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["We've added these nodes to our graph:\n","[(2, {'webpage': 'Pandas'}), (3, {'webpage': 'Matplotlib'})]\n","\n","Our updated list of nodes is:\n","[(0, {'webpage': 'NumPy'}), (1, {'webpage': 'SciPy'}), (2, {'webpage': 'Pandas'}), (3, {'webpage': 'Matplotlib'})]\n"]}]},{"cell_type":"markdown","metadata":{"id":"4StXQ_v8Ab1W"},"source":["We've added the two more nodes. Lets visualize the updated graph.\n","\n","**Listing 18. 18. Plotting the updated 4-node graph**"]},{"cell_type":"code","metadata":{"id":"xZwhu3rIAb1X","colab":{"base_uri":"https://localhost:8080/","height":319},"executionInfo":{"status":"ok","timestamp":1637507085621,"user_tz":-330,"elapsed":754,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"54e822a5-33d9-4e89-ba9c-b1536b36bcd6"},"source":["np.random.seed(0)\n","labels = {i: G.nodes[i]['webpage'] for i in G.nodes}\n","nx.draw(G, labels=labels, node_color=\"cyan\", arrowsize=20)\n","plt.show()"],"execution_count":null,"outputs":[{"output_type":"display_data","data":{"image/png":"iVBORw0KGgoAAAANSUhEUgAAAb4AAAEuCAYAAADx63eqAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAYT0lEQVR4nO3de3AV9aHA8e9JAiQhgZAICEh51gsXQUEsKAgZq95qGauooKm8bBnLmHZ8duq1qPSidCr2IVOZqVSjoDjWVkov6NQqQumlMZpWA4gQ5Snl/QhpgEDI/eMkIUgIBJJzwN/3M+OYs3t295eMM193z9nfRiorKyuRJCkQCfEegCRJsWT4JElBMXySpKAYPklSUAyfJCkohk+SFBTDJ0kKiuGTJAXF8EmSgmL4JElBSYr3AHR22QbkAR8Be4HWQD9gAtA2fsOSpEYTca5OARQA04A3ql4fqLUuBagErgMeAi6L7dAkqVEZPjETeADYTzRwJxIhGsHpwKQYjEuSmoKf8QWuOnpl1BG97GyYNavmZWXV+x6o2q4+eXl5DB06tOZ1Wloan332GQDjx4/nxz/+8RmOXJJOj+E7R3Tt2pXmzZuzY8eOY5b379+fSCTCunXr6t1+3bp1RCIRDh8+XLOsgKPRa4jq+L1fz76/qLS0lO7duzfwSJLU+AzfOaRbt27MnTu35nVRURFlZQ3N1lHTiF7ePB37q7aXpHON4TuHjBkzhhdffLHm9QsvvMDYsWNrXi9YsID+/fvTqlUrOnfuzGOPPVazbtiwYQBkZGSQlpbGgmXL+FNeHpVDhkBuLrRuDb16wdtv133wI0dg6lTo0gXataNy7FgW7N3L9jr2vWzZsuM2j0QiFBcX17zesWMH11xzDenp6QwfPpz169efwV9Gkk6d4TuHDB48mJKSEj7++GMqKip45ZVXuOOOO2rWt2zZkhdffJE9e/awYMECZs6cybx58wBYsmQJAHv27KG0tJQVl18e3Sg/H3r0gB07YMoUGDkSdu06/uB5edF/Fi2Czz6D0lIO5+aSV8e+L6/edz1eeuklJk+ezI4dO7jkkkv49re/fQZ/GUk6dYbvHFN91vfWW2/Ru3dvOnXqVLMuOzubvn37kpCQQL9+/bj99ttZvHhxnfv5CDgM0K4d3HMPNGsGo0fDf/wHLFhw/AYvvQT33Qfdu0NaGkybRsUrr/BhPZ/r1eeb3/wmw4YNo0WLFjz++OMsW7aMjRs3nta+JKkhvIH9HDNmzBiGDRvG2rVrj7nMCZCfn8+PfvQjli9fTnl5OQcPHuTWW2+tcz97q3/o1AkikaMrunSBzZuP32Dz5ui62u87fJgtW7ee1u/RuXPnmp/T0tLIzMxk8+bNxyyXpKbgGd85pkuXLnTr1o2FCxcycuTIY9bl5ORwww03sHHjRvbu3cv3vvc9qm/TjNSOG9EZWQD4/HOofSvnhg3QsePxB+7YEWp/DrdhAyQlcX779sft+1TUPrsrLS1l165ddKzruJLUyAzfOei3v/0t77zzDi1btjxm+b59+8jMzCQ5OZn33nuPl19+uWZd27ZtSUhIqLmXrh9Vp/vbtsHTT8OhQ/C738HHH8P11x9/0Ntvh1/8AtauhdJS+O//JnH0aC5OSjpu36di4cKFLF26lPLyciZPnszgwYM925MUE17qPAf16NGjzuXPPPMM999/P7m5uQwfPpxRo0axZ88eAFJTU3n44YcZMmQIhw4d4uU334xuNGgQrFkD550H7dvDa69BVtbxO7/zzujlzmHD4MAB+K//ImnGDMbXse83q/ddj5ycHKZMmcKyZcsYMGAAc+bMOc2/hiQ1jFOWBezSvDwKZ82CpUsbvG0EuAn4faOPSpKalpc6AzaC0/8PIIXohNWSdK4xfAHrVvVPagO3SyU6UfXARh+RJDU9L3XKpzNICorhExCdcHoasJBo4GrP4Vn9PL7riV7e9ExP0rnM8OkY24k+gb0I2A20AfoC4/EJ7JK+HAyfJCkofrlFkhQUwydJCorhkyQFxfBJkoJi+CRJQTF8kqSgGD5JUlAMnyQpKIZPkhQUwydJCorhkyQFxfBJkoJi+CRJQTF8kqSgGD5JUlAMnyQpKIZPkhQUwydJCorhkyQFxfBJkoJi+CRJQTF8kqSgGD5JUlAMnyQpKIZPkhQUwydJCorhkyQFxfBJkoJi+CRJQTF8kqSgGD5JUlAMnyQpKIZPkhQUwydJCorhkyQFxfBJkoJi+CRJQTF8kqSgGD5JUlAMnyQpKIZPkhQUwydJCorhkyQFxfBJkoJi+CRJQTF8kqSgGD5JUlAMnyQpKIZPkhQUwydJCorhkyQFxfBJkoJi+CRJQTF8kqSgGD5JUlAMnyQpKIZPkhQUwydJCorhkyQFxfBJkoJi+CRJQTF8kqSgGD5JUlAMnyQpKIZPkhQUwydJCorhkyQFxfBJkoJi+CRJQTF8kqSgGD5JUlAMnyQpKIZPkhQUwydJCorhkyQFxfBJkoJi+CRJQTF8kqSgGD5JUlAMnyQpKIZPkhQUwydJCorhkyQFxfBJkoJi+CRJQTF8kqSgGD5JUlAMnyQpKIZPkhQUwydJCorhkyQFxfBJkoJi+CRJQTF8kqSgGD5JUlAMnyQpKIZPkhQUwydJCorhkyQFxfBJkoJi+CRJQTF8kqSgGD5JUlAMnyQpKIZPkhQUwydJCorhkyQFxfBJkoJi+CRJQTF8kqSgGD5JUlAMnyQpKIZPkhQUwydJCorhkyQFxfBJkoJi+CRJQTF8kqSgGD5JUlAMnyQpKIZPkhQUwydJCorhkyQFxfBJkoJi+CRJQTF8kqSgGD5JUlAMnyQpKIZPkhQUwydJCorhkyQFxfBJkoJi+CRJQTF8kqSgGD5JUlAMnyQpKIZPkhQUwydJCorhkyQFxfBJkoJi+CRJQTF8kqSgGD5JUlAMnyQpKIZPkhQUwydJCorhkyQFxfBJkoJi+CRJQTF8kqSgGD5JUlAMnyQpKIZPkhQUwydJCorhkyQFxfBJkoJi+CRJQTF8kqSgGD5JUlCS4j0ASVKYtgF5wEfAXqA10A+YALRtwuNGKisrK5tw/5IkHaMAmAa8UfX6QK11KUAlcB3wEHBZExzf8EmSYmYm8ACwn2jgTiRCNILTgUmNPAY/45MkNVjXrl1p164d//73v2uWzZo1i+zs7BNuUx29MuqPHlXry6ref/n48TRv3py0tDQyMzO55pprWLVq1WmP3fBJkk5LRUUFv/rVr07pvQUcjV5DlFVtO+aHP6S0tJRNmzbRrl07xo8f38A9HWX4JEmn5cEHH2T69Ons2bPnmOXr1q0jEolw+PDhmmXXZ2dTNmtW9EVeHgwZAvfeCxkZ0L07/N//RZd37gzt2sELL9RsWwH8rern1NRUcnJyWL58OVu2bCE1NZWdO3fWvLewsJC2bev/aozhkySdloEDB5Kdnc306dPrfd82YOcXF+bnQ79+sHMn5OTAbbdBQQEUF8OcOZCbC6WlNW8vBrYDpaWlvPTSS/Tv35/zzz+f7OxsXn311Zr3zZ49m9tuu63e8Rg+SdJp+8lPfsKMGTPYvn37Cd+TV9fCbt1gwgRITITRo2HjRnjkEWjRAq69Fpo3j0awSsX06XwlI4OePXtSWlpKXl50r+PGjWPOnDnR91RUMHfuXMaMGVPvmA2fJOm0XXTRRYwYMYKf/vSnJ3zPR9TxZZb27Y/+nJJS97JaZ3w88AC37tnDli1bmD9/Pj169ADgW9/6FitXrmTt2rW89dZbtG7dmq997Wv1jtkb2CVJZ2TKlCkMGDCA+++/H4CWLVsCUFZWRqtWrdgLsGXLGR9ndx3LkpOTGTVqFHPmzGHVqlUnPdsDz/gkSWeoZ8+ejB49mqeffhqAtm3b0qlTJ+bMmUNFRQU7nnsOPv30jI/T5gTLx44dS15eHvPnzzd8kqTYeOSRR465p+/ZZ5/lySefJCsri2YrVhC54ooz2n8S0PcE64YMGUJCQgIDBgygS5cuJ92XM7dIkprUNqALx05N1lDJwAZOPIfnVVddRU5ODt/97ndPui/P+CRJTaod0bk3I6e5fQS4nhNHr6CggMLCQkaPHn1K+zN8kqQm9xDRuTdPR0rV9nUZN24cV199Nb/85S9JT08/pf15qVOSFBO15+o8Vak0/kTV3s4gSYqJ6nj5dAZJUjAmAYuBm4h+YYWyY8//UqqW31T1vsaOHnipU5IUJz+fPZv7P/yQm6dM4WDLlrQhesvCeHwCuyTpS2br1q1069aN/fv3M2PGDHJzc2N2bC91SpJiqrKykpycHA4ciN7Z9/zzz8f0+IZPkhRTv/nNb8jPz6f6guOKFSvYunVrzI5v+CRJMVNcXMx99913zPRmiYmJ/OEPf4jZGAyfJCkmDh8+zM0331xzibNaWVkZzz33XMzGYfgkSTExdepUiouLOXLkyHHrioqK6n2YbWMyfJKkJldWVsYTTzxBJBIhJeX4ycsSExN5/fXXYzIWwydJanKpqamsW7eOP/7xj/z85z9n2LBhJCQk0LFjR5KSkigvL4/Z53zexydJirnvfOc7LFq0iM8++4zDhw+zfv16kpKSTul5emfKuTolSTH38ccf061bNwCSkpLo0aNHzI7tpU5JUsxt2LCBPn36xOXYhk+SFHM7d+5k0KBBcTm2n/FJkmLqyJEjJCYmsmnTJjp16hTz43vGJ0mKqcLCQhISEuISPTB8kqQYW7JkCWlpaXE7vuGTJMVUYWEh7du3j9vxDZ8kKaY++eSTmN6+8EWGT5IUU5s2baJv375xO77hkyTF1K5du+J2KwN4O4MkKYbKy8tp0aIFO3fuJDMzMy5j8IxPkhQzf//730lMTIxb9MDwSZJi6G9/+xutWrWK6xgMnyQpZgoLC+nQoUNcx2D4JEkxs2bNGnr27BnXMRg+SVLMfP7551x88cVxHYPhkyTFzJ49e7j88svjOgZvZ5AkxURpaSnp6ens27fPuTolSV9+f/3rX0lKSopr9MDwSZJiZNmyZWRkZMR7GIZPkhQbH374YdyewVeb4ZMkxURxcTFf/epX4z0MwydJio1//etfXHLJJfEehuGTJMVGSUkJV155ZbyH0fS3M2wD8oCPgL1Aa6AfMAFo25QHliSdNXbt2kVWVhYHDx6kefPmcR1LUlPtuACYBrxR9fpArXV/AB4FrgMeAi5rqkFIks4KixYtonnz5nGPHjTRpc6ZQDYwj2jwDnxh/f6qZfOq3jezKQYhSTpr5Ofnx/VRRLU1evhmAg8AZcDJrqFWdu1K2V/+wgMYP0n6MisqKjorbmWAk4QvJSWFtLQ02rdvz/jx4yktLa13ZwUcjV5DlFVt934Dt5MknRs+/fRTevXqFe9hACcJ35/+9CdKS0spLCzk/fffZ+rUqfXubBrRy5inY3/V9pKkL5+tW7cyYMCAeA8DOMVLnZ06deK6666jqKiIESNG0LZtW9q0acOIESPYtGkTEP325rzsbConT4YhQyA9Ha69FnbsOLqj2bOhSxfIyoLHHz/mGJXvvcfrl19O64wMOnToQG5uLuXl5dF1lZXce++9tGvXjlatWtG3b1+WL1/eOH8BSVKTKy0tPStuZYBTDN/GjRtZuHAh3bt3Z8KECaxfv54NGzaQkpJCbm4uEL1lAYCXX4bnn4dt26C8HKZPjy5fuRImTYrGb/Nm2LkTqqIJQGIizX/xCx7asYNly5bx9ttv88wzzwDw5z//mSVLlrB69Wr27t3Lq6++SlZWViP9CSRJTWnTpk0cOXLk3Djju/HGG8nIyGDo0KEMHz6cn/3sZ9x8882kpqaSnp7Oww8/zOLFi4HofXqVABMmwIUXQkoKjBoF//xndGevvQYjRsCwYdCiBfzP/0BCrcNfeikHBw9mZVISXbt25a677qrZd7Nmzdi3bx+rVq2isrKS3r17x/3R9ZKkU7N48WKSk5NJTEyM91CAk9zHN2/ePK6++uqa12VlZdx11128+eab7N69G4B9+/ZRUVHB3upf6Pzzj+4gNRWqvxCzeTN07nx0XcuW0Uue1Vavhvvu49X332deWRmHDx/m0ksvBeCqq64iNzeXu+++m/Xr1zNy5EimT59Oq1atzuBXlyTFQn5+/ll1la5BtzM89dRTfPLJJ+Tn51NSUsKSJUuA6GdwrU+2cYcOsHHj0ddlZdHLndUmTYJevbhpzRpKSkp44oknqD2pzA9+8AM++OADVq5cyerVq3nyyScbMnRJUpysWLGCr3zlK/EeRo0GhW/fvn2kpKSQkZHBrl27mDJlSs26fkCkvo1vuQX+939h6dLoZ3+PPAJHjtTeOUmtWtE/LY1Vq1Yxc+bRO/sKCgrIz8/n0KFDtGzZkuTkZBISnGZUks4Fa9eupXfv3vEeRo0G1eOee+5h//79nHfeeQwePJhvfOMbNevGn2zjPn3g17+GnJzo2V+bNnDBBUfXT59OxcsvMyU9nYkTJzJ69OiaVSUlJUycOJE2bdrQpUsXsrKyePDBBxsydElSnGzbto2BAwfGexg1GnWS6pFEpyE7nR1GgJuA3zfWYCRJZ4WEhASKioro06dPvIcCNHL4CojOvdnQmVsAUoHFwNnz/wSSpDO1Zs0aLrzwQioqKs6aj6gadRSXAdOJRqwhUqu2M3qS9OWyePFiUlNTz5roQRM8lmhS1b8fIDoNWX2nkxEghWj0JtXzPknSuem9996jbduz6+mrTZLgSUQvW94EJBONW20pVctvqnqf0ZOkL4eZM2fSsWNHrrzySu6++27eeecdWrduzfr16zlS+5v8cdTkT2DfTnQ6syJgN9AG6Ev0W6Bn1/8DSJLO1JtvvsnIkSPZvz/6yIJIJEJSUhLNmjWjvLycCy64gPnz59O3b9+4jbHJwydJCkd5eTlt2rShrKzurzmed955FBcX07r1Sac9aTJnz6eNkqRzXvPmzRkxYkSd61JSUnjttdfiGj0wfJKkRjZ27Njj5lJOSUlh4sSJDB8+PE6jOspLnZKkRnXw4EEyMzOPudzZvXt3Vq5cSYsWLeI4sijP+CRJjapFixbHTGmZkpLCvHnzzorogeGTJDWBcePGkZCQQEJCAo8++mhcv8X5RV7qlCQ1ugMHDpCSkkL79u3ZvHnzWTVzy9kzEknSl0ZycjJZWVnMmDHjrIoeNMGUZZKkMG0jOmHJR8BeoNOiRazp1YvtnF0TlnipU5J0RgqAacAbVa8P1FqXQnTO5uuAh4g+zCDeDJ8k6bTN5Nx7KMHZdeFVknTOqI5eGV+IXp8+8O67x7y3sup9D1RtF0+GT5J0QkuXLuWKK66gdevWZGZmMmTIEAoKCijgaPSOs2IFZGdHf37sMWjWDNLSICODsiuu4N5ly3g/Vr9AHQyfJKlOJSUljBgxgu9///vs2rWLzz//nEcffZQWLVowjejlzVMyejSUlsL27TB0KAdHjuSJOH7KZvgkSXVavXo1ALfffjuJiYmkpKRw7bXXcn6/frwBVD77LPTuDenp8J//CYWF0Q27doW//OX4HTZrBuPGwZYtLNy+nTaZmRQVFdWs3rZtG6mpqWzfvr1Jfy/DJ0mq04UXXkhiYiLjxo3jjTfeYPfu3UD0loWK3/0uehnzxRehpATmz4esrPp3ePAg5OVB584ktGtH79tuY86cOTWr586dy9e//vUmf2K74ZMk1alVq1YsXbqUSCTCxIkTadu2LTfccAP5W7dyaNYs+OEP4bLLIBKBnj2hS5e6d/Tqq5CRAZ07wwcfwOuvsx9oPW4cc+fOpfrmgtmzZzNmzJgm/728gV2SdEK9e/cmLy8PgFWrVnHHHXfwr3vugY0boUePU9vJqFFQ68yuWtKgQaSmpvLuu+/SoUMHiouLueGGGxpx9HXzjE+SdEp69erF+PHj+ffy5dGzt08/PaP9tSE6mfWcOXOYPXs2t9xyC8nJyY0z2Hp4xidJqtOqVatYsGABo0eP5oILLmDjxo3MnTuXCwcP5p/XXsuh++6DoUNhwIBoBJs1O/Hlzi9IAfoCt91xBxdffDHp6enMnj27SX+fap7xSZLqlJ6eTn5+PoMGDaJly5YMHjyYiy66iLlPPUXirbfCww9DTk70W5033gi7dp3yviuB8UDnzp0ZMGAAkUiEK6+8sql+lWM4ZZkkqcFGAvOof5qyE4kANwG/r3p955130rFjR6ZOndpYw6v/+IZPktRQBUA2J5i55SRSgcXAQGDdunVccskl/OMf/6Bbt26NOMIT81KnJKnBLiM64XRqA7dLrdpuIDB58mQuuugiHnzwwZhFDzzjkySdgXPx6QyGT5J0Rt4n+jy+hUQDV3sOz+rn8V1P9Hl8A2M+uuMZPklSo9hOdDqzImA30fv0+hL99qZPYJckKU78coskKSiGT5IUFMMnSQqK4ZMkBcXwSZKCYvgkSUExfJKkoBg+SVJQDJ8kKSiGT5IUFMMnSQqK4ZMkBcXwSZKC8v/pIVKqDktDlwAAAABJRU5ErkJggg==\n","text/plain":["
"]},"metadata":{}}]},{"cell_type":"markdown","metadata":{"id":"eTeq16ifAb1X"},"source":["Our current web-link network is disconnected. We'll proceed to add two more web-links.\n","\n","**Listing 18. 19. Adding multiple edges to a graph object** "]},{"cell_type":"code","metadata":{"id":"sq7KH7viAb1Y","colab":{"base_uri":"https://localhost:8080/","height":319},"executionInfo":{"status":"ok","timestamp":1637507087015,"user_tz":-330,"elapsed":9,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"45e6d029-4177-4cba-c9b9-fed3f5139a0f"},"source":["np.random.seed(1)\n","G.add_edges_from([(0, 2), (3, 0)])\n","nx.draw(G, labels=labels, node_color=\"cyan\", arrowsize=20)\n","plt.show()"],"execution_count":null,"outputs":[{"output_type":"display_data","data":{"image/png":"iVBORw0KGgoAAAANSUhEUgAAAb4AAAEuCAYAAADx63eqAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAgAElEQVR4nO3deXxM9+L/8ddkkT0iaEWorZvbUrSuXVJ7IrbE0FLF7e23S9JbtfReVXqp8i2K760K1d5GuZaGJkQSqqqUakT7c2spQtGQEluCWiKZ+f0RppRYIsmZybyfj0cfNXPOzLwnVW/nc875fExWq9WKiIiIk3AxOoCIiEhZUvGJiIhTUfGJiIhTUfGJiIhTUfGJiIhTUfGJiIhTUfGJiIhTUfGJiIhTUfGJiIhTUfGJiIhTUfGJiIhTUfGJiIhTUfGJiIhTUfGJiIhTUfGJiIhTUfGJiIhTUfGJiIhTUfGJiIhTUfGJiIhTUfGJiIhTUfGJiIhTUfGJiIhTcTM6wO3KBuKAH4FcoCLQEBgMVDUuloiIOBiT1Wq1Gh3iZtKBiUDq5ccXrtrmBViBMGAk0LRso4mIiAOy6+KLBYYD5yksuKKYKCzBKcBLZZBLREQcl92e47tSeuf4Q+k98gh8/fU1+1ov7zf88utERESKYmjxbdiwgZYtW1KxYkUCAwNp1aoV6enppPN76V1nxw4IDS389T//Ce7u4OsLAQGca9mS1zZtYktZfQEREXE4hhXf6dOniYiI4JVXXuHkyZMcPnyYt956Cw8PDyZSOLx5W/r2hbNn4dgxaN2ai5GRTLDf0VsRETGYYcW3Z88eAJ5++mlcXV3x8vKiU6dOVGvYkFTAOmcO1K8Pfn7wpz/BDz8UvrB2bfjyy+vf0N0dBg6EI0dIOXaMSoGBbNu2zbY5Ozsbb29vjh07VvpfTkRE7JZhxffggw/i6urKwIEDSU1N5dSpU0DhLQsF8fGFw5iffgqnT8Py5VC58s3f8OJFiIuDmjVxuece6j/1FPPnz7dtXrhwIe3bt6dqVd38ICLizAwrPn9/fzZs2IDJZOL555+natWqdO/enbSjR7n00Ufw+uvQtCmYTHD//VCr1o3f6LPPICAAataE77+HhATOAxUHDmThwoVcuWh13rx5DBgwoOy+oIiI2CVDb2CvX78+cXFxAOzatYtnnnmGX4cMgcxMqFfv9t6kTx+46sjuCrdmzfD29ubrr78mKCiIvXv30r179xJMLyIijshubmd4+OGHGTRoEL9t31549LZv3129XyVg4MCBzJ8/n3nz5tG7d288PT1LJqyIiDgsw474du3aRXJyMn379qVGjRpkZmaycOFCHmzenK2dOnFp6FBo3RqaNCksQXf3ooc7/8DLaqWBycRTzzzDY489hp+fH/PmzbNtv3TpEgUFBSpCEREnZFjx+fn5kZaWxtSpU8nJySEgIICIiAhenzyZR/39uXTiBPTrB4cPF17JOW/ebRff+YsXebdxYz62Wjl//jy5ubl069aNvLw88vLysFgs+Pv7k5ubW7pfUkRE7I5dTlkWCSRy82nKimKyWqn8zTccDwkpch9XV1f69OnDggULihtRREQclN2c47vaSArn3iwOL5OJlDZtiIiIwNXV9Yb7VKhQgVGjRhU7n4iIOC67LL6mFE447X2Hr/O+/LqmJhN/+tOfsFgsmEym6/a77777eOSRR+4+qIiIOBy7HOq84m5XZzh48CCPPfbYNefyXF1dsVqt+Pv78+qrr/Lmm2/i5uYwyxKKiMhdsssjviteAtYBvQBPrh/+9Lr8fK/L+/1xSaJatWqRlJSEl9fvr6xduzY5OTn07duXd999Fx8fHwYOHEhOTk6pfQ8RkfImG5gEPAN0u/zvSYAjTApp10d8VztG4XRm24BTFN6n1wAYxK1XYJ85cyYjRowAYNasWbYZXCwWC++99x6TJ0/mxIkThISEEBsby0MPPVQ6X0JExMGVh8XBHab47tbgwYNZsWIFWVlZuLu7X7d92bJlvP7662RkZFC/fn2mTp1K586dDUgqImKfysvi4HY91FmS5syZw7Zt225YegA9evRg9+7dbN26lcDAQMLCwggKCmLGjBlYLJYyTisiYl+KXBwcCtdI/egj28M7WRw8Li6O1q1b2x77+vry888/AzBo0CDefPPNu0x+PacpPjc3N6pVq3bL/Ro2bMg333zD0aNHCQkJYejQofj7+zNkyBAuXLhwy9eLiBipdu3aVKhQgePHj1/zfOPGjTGZTBw4cOCmrz9w4AAmk4n8/HzbczddHPwmrpTflcXBb/Tef3T27Fnq1q17h590Z5ym+O5U1apVWbRoEWfPnuWVV17hk08+wdfXl169epGVlWV0PBGRItWpU4eFCxfaHm/bto1z5+60tn53R4uD/8H5y6+3Jyq+W6hQoQITJ04kNzeX2bNns2XLFmrUqEGzZs1IT083Op6IyHUGDBjAp59+ans8d+5cnn32Wdvj5ORkGjdujL+/PzVr1uSf//ynbVvbtm0BCAgIwNfXl+RNm0iKi8PaqhXExEDFivDww7BmzY0/3GKB8eMLp5i85x6szz5Lcm4ux27w3ps2bbru5SaTib1799oeHz9+nI4dO+Ln50dISAgHDx68i59MIRXfHXjuuefIzMzk66+/Ji8vj2bNmlG3bl0WL15sdDQREZvmzZtz+vRpfvrpJwoKCli0aBHPPPOMbbuPjw+ffvopOTk5JCcnExsbS2JiIgDr168HICcnh7Nnz7KjRYvCF6WlFS4Xd/w4jB0LkZFw8uT1Hx4XV/jP2rXw889w9iz5MTHE3eC9W1x575v4z3/+w+jRozl+/DiNGjWif//+d/GTKaTiK4a2bdvy//7f/2Pfvn089NBD9OvXj8DAQMaNG6cLYUTELlw56lu9ejX169cnODjYti00NJQGDRrg4uJCw4YNefrpp1m3bt0N3+dHIB/gnntgyJDClXL69oWHHoLk5Otf8J//wNChULcu+PrCxIkULFrEf29yXu9munbtStu2bfHw8OCdd95h06ZNZGZmFuu9rlDx3YU6deqQmppKbm4uffr0YeLEiXh7ezNo0CDdEC8ihhowYAALFiwgLi7ummFOgLS0NJ588kmqVq1KxYoVmTVr1nUXw1xhm/cqOBiungKyVi240fUOWVnXrqRTqxbk53Pk6NFifY+aNWvafu3r60tgYOBdX2eh4isBvr6+zJo1i99++41x48aRnJxM5cqVad++PXv27DE6nog4oVq1alGnTh1SUlKIjIy8Zlu/fv3o3r07mZmZ5Obm8uKLL3Lllu4/zm9c8covDh+Gq2/7/uUXqF79+g+uXh2uPg/3yy/g5ka1e++94dzJt3L10d3Zs2c5efIk1W/0uXdAxVeCXFxceP311zl27BhLliwhMzOThx9+mEcffZQvv/zS6Hgi4mQ+/vhjvvrqK3x8fK55/syZMwQGBuLp6cnmzZuvWaKtatWquLi48P777xMVFcU3H3xQuHBrdjb8619w6RLEx8NPP0F4+PUf+vTTMG0a7N8PZ8/CG2/g2rcvj7m52d77yn16tyMlJYUNGzaQl5fH6NGjad68+TVHgcWh4islvXr1Ys+ePWzdupWAgAA6depE9erVmTlzps4DikiZqFevHk888cR1z8+cOZMxY8bg5+fHuHHj6NOnD5cuXWLBggX0798fNzc3/v73v5OamsqkBx4ofFGzZpCRAVWqwKhRsGQJVK58/Yf+5S8wYAC0bQt16oCnJ27vv88gwNvbm1GjRtGqVSsCAgL47rvvbvkd+vXrx9ixYwkMDOT7779n/vz5d/dDwYmmLDNadnY2MTExJCQk4OHhwfPPP8/EiRPx9PQ0OpqIOKnTp0+TlJREfHw8X331FW3atMFsNtOjRw8qVapk2+/xuDh++Ogj2LDhjj/DROFCAktLLvZd0xFfGbnnnnv47LPP+O2334iOjubjjz/Gz8+PyMhI3RAvImUmNzeXefPm0b17d2rUqMGiRYuIjIzkl19+ITk5mUGDBl1TegARFL8svCicsNqeqPjKWIUKFXj33Xc5ffo0sbGxbN68mRo1atC8eXO2bNly6zcQEblDOTk5fPrpp3Tr1o2aNWsSHx+P2WwmMzOTpKQknn32WQICAop8fZ3L/xR3cfDrB1uNpaFOO/D1118zZMgQfvzxR+rUqcPEiRPp06eP0bFExIGdOnWK5cuXEx8fz/r163nyyScxm81069aNihUr3voNbqC8rM6g4rMj+/fv56WXXmL16tUEBATw2muv8cYbb+DiogNzEbm1U6dOkZiYSHx8PBs3bqRdu3aYzWYiIiLw9/cvkc/YQuHcmykUFtzVc3heWY8vnMLhTXs70rtCxWeHzp49y9ChQ5k3bx5Wq5V+/foxffr0EvuNKyLlx8mTJ21l9+2339K+fXtb2fn5+ZXa597N4uBGU/HZMYvFwqRJk5gyZQqnTp2iXbt2zJw5kweuXF4sIk7pxIkTJCQkEB8fz3fffUfHjh0xm8107doVX19fo+PZPRWfg1i6dCn/+Mc/2LdvH4888gjTp0+nffv2RscSkTJy/PhxW9mlpaXRqVMnzGYz4eHhKrs7pOJzMFu3biU6OppNmzZRrVo1xowZwwsvvFCsqYBExL4dO3bMVnabN2+mc+fOtrL742wscvtUfA4qOzub6OhoEhMT8fT05H/+53+YMGECHh4eRkcTkbuQnZ3N559/Tnx8PN9//z1dunTBbDYTFhaGt/ed3lAgN6Lic3B5eXm8+eabzJo1i/Pnz9OjRw9mzJhBtWrVjI4mIrfp6NGjtrL74YcfCAsLw2w206VLF5VdKVDxlSMffvgh48aNIysri2bNmjFjxgwef/xxo2OJyA0cOXLEVnZbt24lPDyc3r1706VLF7y8vIyOV66p+Mqhr776iiFDhrB9+3bq1KnDu+++S+/evY2OJeL0fv31V5YuXUp8fDw//vgjXbt2xWw207lzZ83bW4ZUfOXYvn37ePnll/nyyy8JCAhg6NChjBw5UjfEi5ShrKwsW9lt27aNiIgIzGYznTp1UtkZRMXnBE6fPs3QoUNty3n079+fadOm6YZ4kVJy+PBhlixZQnx8PDt37qRbt26YzWY6duyoC9DsgIrPiVgsFt59913ee+89Tp06Rfv27YmNjaVevXpGRxNxeIcOHbKV3U8//UT37t0xm8106NBBZWdnVHxOasmSJfzjH//g559/5tFHH2X69Om0a9fO6FgiDiUzM9NWdrt376ZHjx707t2bDh06UKFCBaPjSRFUfE7uhx9+ICYmhu+++46goCDbDfEicmMHDx60ld3evXvp0aMHZrOZdu3aqewchIpPgMJLq2NiYli2bBmenp68+OKLvPPOO/ofWQQ4cOCArez27dtHz549bWXn7u5udDy5Qyo+uUZeXh6jRo1i1qxZXLhwgZ49ezJjxgzuvfdeo6OJlKn9+/cTHx9PfHw8Bw4coFevXpjNZkJDQ1V2Dk7FJ0WaPXs248aN49dff6V58+Z88MEHNG7c2OhYIqXm559/tpXdL7/8ck3Zubm5GR1PSoiKT27p6hvi69aty7vvvktUVJTRsURKxL59+2xld+jQISIjI+nduzchISEqu3JKxSe3bd++fbz00kusWbOGSpUqMWzYMP7+97/rhnhxOBkZGbay+/XXX4mMjMRsNtO2bVtcXV2NjielTMUnd+z06dMMGTKEBQsWYDKZeOaZZ5g2bZrWBBO7tmfPHlvZHTlyhKioKMxmM23atFHZORkVnxSbxWJh4sSJTJ06lZycHDp06EBsbCx169Y1OpoIALt27bJdjXns2DFb2bVq1Upl58RUfFIiPvvsM0aOHMn+/ftp0KAB//d//0doaKjRscQJ/fTTT7Yju5MnT15TdhqWF1DxSQnbsmULr7zyCmlpaVSvXp233nqL559/3uhYUs7t3LnTVnY5OTm2smvZsqXKTq6j4pNSceTIEaKjo1m+fDleXl68+OKLjB8/XjfES4mwWq3s2LHDVnZnzpyhd+/emM1mmjdvrrKTm1LxSam6cOECo0aNYvbs2Vy8eJFevXoxY8YM7rnnHqOjiYOxWq1s377dVna//fabreyaNWumspPbpuKTMmGxWJg9ezZvv/02R44coUWLFnzwwQc0atTI6Ghix6xWK9u2bbOV3fnz521l9+c//1llJ8Wi4pMyt2bNGoYMGcKOHTuoV68ekyZNolevXkbHEjthtVr573//S3x8PEuWLOHixYuYzWbMZjNNmzbFZDIZHVEcnIpPDJORkcHLL7/MV199RaVKlRgxYgQjRozQ3+KdkNVqZevWrbYju/z8fFvZPfHEEyo7KVEqPjHc6dOnefXVV1m4cCEmk4kBAwYwdepU3RBfzlmtVn744QfbkZ3VarWVXZMmTVR2UmpUfGI3LBYLEyZMYNq0aeTk5NCpUydmzpxJnTp1jI4mJcRqtfL999/bys5kMtnKrnHjxio7KRMqPrFLixcv5o033mD//v00bNiQf/3rX7Rt29boWFIMVquVLVu22MrO1dXVVnaNGjVS2UmZU/GJXduyZQsxMTFs3ryZ6tWrM3bsWJ577jmjY8ktWK1WNm/ebCs7Dw8PW9k1bNhQZSeGUvGJQ8jKyiImJoakpCS8vLx46aWXePvtt3VDvB2xWq2kpaXZys7Ly8tWdg0aNFDZid1Q8YlDuXDhAm+88QYffvgheXl5REZGMmPGDKpUqWJ0NKdksVj47rvviI+PZ+nSpfj6+mI2m+nduzePPvqoyk7skopPHJLFYmHWrFmMHz+eI0eO0LJlS2bOnEnDhg2NjlbuWSwWNm3aZCs7f39/25HdI488YnQ8kVtS8YnDW716Na+99ho7d+7k/vvvZ/LkyfTo0cPoWOWKxWLh22+/tZVdQECArez+9Kc/GR1P5I6o+KTc2L17N9HR0axdu5bAwEBGjBjB8OHDdUN8MRUUFLBx40Zb2VWpUsU2jFm/fn2j44kUm4pPyp2cnByGDBnCokWLMJlMDBw4kClTpuiG+NtQUFDAhg0biI+P5/PPP6dq1aq2I7uHHnrI6HgiJULFJ+VWfn4+EyZMYPr06eTm5tK5c2diY2OpVauW0dHsSkFBAevXr7eVXbVq1Wxl9+CDDxodT6TEqfjEKSxevJiRI0dy4MABHnvsMd5//31at25tdCzD5OfnX1N2wcHBtmHMBx54wOh4IqVKxSdOJT09nZiYGNLT06lRowZjx45l8ODBRscqE/n5+axbt474+HgSEhKoUaOGrezuv/9+o+OJlBkVnzilrKwsoqOjSUpKwsfHh5dffpmxY8cWeUP8L7/8YltP0JEulsnPz2ft2rUsWbKEhIQEatWqZSu7unXrGh1PxBAqPnFqFy5cYOTIkcyZM4e8vDyioqJ4//33r7sh/q9//SuffPIJI0eOZPz48WWa8dy5c3h7e9/2/pcuXWLt2rXEx8eTmJhInTp1bGWnCb9FVHwiQOF9ajNnzuSdd97h6NGjtGrVitjYWB599FFOnDhBzZo1OX/+PF5eXsyfP5/IyMgyyfXhhx/y6quvkpWVRaVKlYrc79KlS6xZs4YlS5aQmJhIvXr1bGVXu3btMskq4ihUfCJ/sGrVKoYOHcpPP/3EAw88wOOPP05CQgIXLlwAwNvbm++++44GDRrc9H2ygTjgRyAXqAg0BAYDVW8jx+zZs3nttdewWq3MnDnzunOReXl5rFmzhvj4eJYtW8aDDz6I2WwmKipKV66K3ISKT6QIu3fv5sUXX+Trr7++btu9997L9u3bbzhHaDowEUi9/PjCVdu8ACsQBowEmhbx2bNmzWLo0KGcP38egLZt27Ju3Try8vL48ssviY+PZ/ny5Tz00EO2srvvvvuK+U1FnIuKT+Qm/v3vf/O3v/2N33777Zrn3d3dady4MRs2bMDd3d32fCwwHDhPYcEVxURhCU4BXvrDttjYWIYNG2YrvSuf17t3b1auXEn9+vVtZVezZs27+n4izsjN6AAi9spqtfL2229fV3pQeE5ty5YtDBw4kAULFgC/l96523nvy/sNv/z4SvndqPSg8CZzk8nEtm3bCA4OLt4XEhFAR3wiN1S7dm1ycnI4c+YMFosFABcXF6xWK97e3lgsFi5cuIDVaqVNmzaMXr6cngEBt1V6f+Q6aBCmBQtwMZnIy8srcr+QkJAbDruKyJ3REZ9IEaxWK40aNaJt27b4+/uzY8cO/vvf//LGG2/g4+ODt7c3hw4d4qeffmJ8QQHnb/2WN1QABL3wAr/OmHHT/TZt2kRubi4VK1Ys5ieJCKj4RIo0cuRIJk2axJo1awgICOCjjz7i+PHjPPnkk9SpU4dLly7h5uZGNlAtNBTrM8/AX/8KcXEwZw78+c/wyScQGAjz58OePTB6NFy8CJMnw8CBts/K9vdnwerVXMjMZMWKFSxbtoygoCAOHTqEh4cHHh4enDt3jhkzZjB9+nSysrKuObcoIrfPcaagECljTzzxBKGhoUyZMuWm+8Xd6Mm0NGjYEE6cgH794KmnID0d9u4tLMGYGDh71ra7yWTiUIcOmM1mPDw8aNGiBZmZmYSFhfHWW2+xfPlyYmNj2bt3L0899ZRKT+QuqPhEbmLcuHG8//77HDt2rMh9fuQGV3DWqQODB4OrK/TtC5mZMGYMeHhAp05QoUJhCV6WP2UKowICuP/++zl79ixxcXEADBw4kBUrVhASEsLgwYNJTU1lwIABJf49RZyJik/kJh599FEiIiL43//93yL3yb3Rk/fe+/uvvbxu/NxVR3wMH07nnByOHDnC8uXLqVevHgA9evRg586d7N+/n9WrV1OxYkX+/Oc/F/8LiYjO8YncytixY2nSpAnDhg0DwMfHByicQ9Pf35+KAEeO3PXn3GhCMk9PT/r06cP8+fPZtWuXjvZESoCO+ERu4f7776dv377861//AqBq1aoEBwczf/58CgoKuPjvf8O+fXf1GW5AUROgPfvss8TFxbF8+XIVn0gJUPGJ3IYxY8ZccyP7nDlzmDx5MpUrV6bKjh2YWra8q/e3AoOK2NaqVStcXFxo0qSJ5uAUKQG6gV2kBEQCidx8mrKimIBewNKb7NOuXTv69evHX//61+LEE5GrqPhESkA6EMrtTVf2R97AOuCJot47PZ2OHTuSmZmJn59fMROKyBUa6hQpAU0pnHD69peLLeSel8cUii69gQMH0qFDB6ZPn67SEykhOuITKUF3sjqDp8WC1+jRTLn//uvW2hOR0qPiEylhWyhcjy+FwoK7eg7PK+vxhVO4Hp/vrl2EhITw6aef0rlz5zLPKuKMVHwipeQYhdOZbQNOUXifXgMKr968egX2jRs30rNnT1atWkWTJk3KOqaI01HxidiBzz//nFdeeYWNGzdSu3Zto+OIlGuauUXEDkRGRnL48GG6dOnCt99+S2BgoNGRRMotHfGJ2JERI0awadMmVq9ejdeVOT5FpESp+ETsiMVioX///uTl5fHZZ5/h6upqdCSRckf38YnYERcXF+Li4jh58iRDhw5Ffy8VKXkqPhE74+HhQUJCAmvWrGHq1KlGxxEpd3Rxi4gdCggIIDU1lZYtWxIcHMxTTz1ldCSRckPFJ2KnatasSXJyMh06dKBatWqEhoYaHUmkXNBQp4gda9iwIYsWLaJPnz5s377d6Dgi5YKKT8TOtWvXjmnTphEeHs7hw4eNjiPi8DTUKeIA+vfvz6FDhwgPD2f9+vVUrFjR6EgiDkv38Yk4CKvVSkxMDLt37yYlJYUKFSoYHUnEIan4RBxIQUEBUVFR+Pr6Mm/ePEwmk9GRRByOzvGJOBBXV1cWLFjAvn37eOONN4yOI+KQVHwiDsbb25ukpCSWLl3KzJkzjY4j4nB0cYuIA6pSpQorV66kdevWBAcH06NHD6MjiTgMneMTcWDp6emEh4ezfPlyWrRoYXQcEYegoU4RB9a0aVPmzp1Lr1692LNnj9FxRByCik/EwYWHhzN+/HjCwsI4evSo0XFE7J6GOkXKibfeeouUlBS+/vprfHx8jI4jYrdUfCLlhNVq5bnnnuPo0aMsW7YMNzdduyZyIxrqFCknTCYTs2fPpqCggJdfflmL2IoUQcUnUo64u7sTHx/P999/z/jx442OI2KXNBYiUs74+fmRnJxMixYtqFmzJoMGDTI6kohdUfGJlEPVqlUjNTWVkJAQgoKC6Ny5s9GRROyGLm4RKcc2btxIr169WLlyJU2aNDE6johd0Dk+kXKsVatWxMbG0q1bNw4cOGB0HBG7oKFOkXIuKiqKw4cPExYWxsaNGwkMDDQ6koihNNQp4iRGjBjBpk2b+PLLL/H09DQ6johhVHwiTsJisdC/f38uXbrE4sWLcXV1NTqSiCF0jk/ESbi4uBAXF8fx48cZOnSobnAXp6XiE3EiHh4eJCYmsmbNGqZOnWp0HBFD6OIWEScTEBBAamoqLVu2JDg4mKeeesroSCJlSsUn4oRq1qxJcnIyHTp0ICgoiJCQEKMjiZQZDXWKOKmGDRuycOFC+vTpw44dO4yOI1JmVHwiTqx9+/ZMnTqV8PBwDh8+bHQckTKhoU4RJ9e/f38yMzMJDw9n/fr1VKxY0ehIIqVK9/GJCFarlZiYGHbv3k1KSgoVKlQwOpJIqVHxiQgABQUFREVF4efnx6efforJZDI6kkip0Dk+EQHA1dWVBQsWsHfvXkaNGmV0HJFSo+ITERtvb2+SkpJYsmQJsbGxRscRKRW6uEVErlGlShVWrlxJ69atqV69Oj169DA6kkiJ0jk+Ebmh9PR0unbtyvLly2nevLnRcURKjIY6ReSGmjZtSlxcHL169SIjI8PoOCIlRsUnIkUKDw9n3LhxdOnShezsbKPjiJQIDXWKyC2NGTOGlStXsnbtWnx8fIyOI3JXVHwicktWq5W//OUvHDt2jMTERNzcdF2cOC4NdYrILZlMJj788EPy8/N5+eWXtYitODQVn4jcFnd3d+Lj49myZQvvvPOO0XFEik3jFSJy2/z8/EhOTqZly5bUqFGDQYMGGR1J5I6p+ETkjgQFBZGamkpoaCjVq1enU6dORkcSuSO6uEVEigNP7kQAAA3iSURBVGXjxo306tWLVatW0bhxY6PjiNw2neMTkWJp1aoVsbGxREREcODAAaPjiNw2DXWKSLFFRUVx+PBhwsLC2LhxI4GBgUZHErklDXWKyF0bPnw4aWlprF69Gk9PT6PjiNyUik9E7prFYqFfv37k5+fz2Wef4eKisyhiv/S7U0TumouLC3PnzuX48eMMGzbM6DgiN6XiE5ES4eHhQWJiIqtXr2bq1KlGxxEpki5uEZESExAQQGpqKi1btiQ4OJi+ffsaHUnkOio+ESlRNWvWJDk5mQ4dOlCtWjVCQkKMjiRyDQ11ikiJa9iwIQsXLqRPnz7s2LHD6Dgi11DxiUipaN++PVOnTiU8PJzDhw8bHUfERkOdIlJq+vfvT2ZmJuHh4XzzzTf4+/sbHUlE9/GJSOmyWq1ER0eTkZFBcnIyFSpUMDqSODkVn4iUuoKCAqKiovD392fu3LmYTCajI4kT0zk+ESl1rq6uLFiwgIyMDN58802j44iTU/GJSJnw9vYmKSmJ+Ph4Zs2aZXQccWK6uEVEykyVKlVITU2lTZs2VK9ene7duxsdSZyQzvGJSJlLT08nPDycpKQkmjdvbnQccTIa6hSRMte0aVPi4uLo1asXGRkZRscRJ6PiExFDdO3alXHjxhEWFkZ2drbRccSJaKhTRAw1ZswYVq5cydq1a/Hx8TE6jjgBFZ+IGMpqtfKXv/yF48ePk5CQgJubrrmT0qWhThExlMlk4sMPPyQvL4/o6Gj0d3EpbSo+ETGcu7s7S5YsIT09nQkTJhgdR8o5jSmIiF3w8/MjOTmZli1bUqNGDQYOHGh0JCmnVHwiYjeCgoJISUkhNDSUoKAgOnXqZHQkKYd0cYuI2J0NGzYQGRnJqlWraNy4sdFxpJzROT4RsTutW7cmNjaWbt26cfDgQaPjSDmjoU4RsUtRUVEcPnyYLl26sHHjRgIDA42OJOWEhjpFxK4NHz6ctLQ0Vq9ejaenp9FxpBxQ8YmIXbNYLPTr14+CggIWL16Mi4vO0Mjd0e8gEbFrLi4uzJ07l2PHjjFs2DCj40g5oOITEbvn4eFBQkICq1evZtq0aUbHEQeni1tExCFUqlSJlJQUWrVqRXBwMH369DE6kjgoFZ+IOIz77ruPFStW0LFjR6pVq0bbtm2NjiQOSEOdIuJQHnvsMRYuXIjZbGbHjh1GxxEHpOITEYfTvn173nvvPcLDw8nKyjI6jjgYDXWKiEN65plnOHToEGFhYXzzzTf4+/sbHUkchO7jExGHZbVaiY6OJiMjg+TkZCpUqGB0JHEAKj4RcWgFBQVERkZSsWJF5s6di8lkMjqS2Dmd4xMRh+bq6srChQvZs2cPb775ptFxxAGo+ETE4Xl7e5OUlER8fDyzZs0yOo7YOV3cIiLlQtWqVUlNTaVNmzZUr16d7t27Gx1J7JTO8YlIuZKenk7Xrl1JSkqiWbNmRscRO6ShThEpV5o2bconn3xCz549ycjIMDqO2CEVn4iUO127dmXcuHGEhYWRnZ1tdByxMxrqFJFya8yYMaxcuZK1a9fi4+NjdByxEyo+ESm3rFYrgwcP5sSJEyQkJODmpuv5REOdIlKOmUwm5syZQ15eHtHR0ejv+QIqPhEp59zd3VmyZAmbN29mwoQJRscRO6DjfhEp9/z8/EhJSaFly5bUqFGDgQMHGh1JDKTiExGnEBQUREpKCqGhoQQFBdGpUyejI4lBdHGLiDiVDRs2EBkZyRdffEGjRo2MjiMG0Dk+EXEqrVu3JjY2loiICA4ePGh0HDGAhjpFxOlERUXZFrHdsGEDgYGBRkeSMqShThFxWsOHD2fz5s188cUXeHp6Gh1HyoiKT0SclsVi4emnn8ZqtbJo0SJcXHT2xxnov7KIOC0XFxfmzp3L0aNHGT58uNFxpIyo+ETEqXl6epKYmMiqVauYNm2a0XGkDOjiFhFxepUqVSI1NZVWrVoRHBxMnz59jI4kpUjFJyIC3HfffaxYsYKOHTtSrVo12rZta3QkKSUa6hQRueyxxx5jwYIFmM1mdu7caXQcKSUqPhGRq3To0IEpU6YQHh5OVlaW0XGkFGioU0TkDwYMGMChQ4cIDw9n/fr1+Pv7Gx1JSpDu4xMRuQGr1Up0dDQZGRkkJydToUIFoyNJCVHxiYgUoaCggMjISAICAoiLi8NkMhkdSUqAzvGJiBTB1dWVhQsXsnv3bkaPHm10HCkhKj4RkZvw9vYmKSmJxYsXM3v2bKPjSAnQxS0iIrdQtWpVVq5cSZs2bahevTrdunUzOpLcBZ3jExG5Tenp6YSHh7NixQqaNWtmdBwpJg11iojcpqZNm/LJJ5/Qs2dP9u7da3QcKSYVn4jIHYiIiGDs2LF06dKF7Oxso+NIMWioU0SkGEaPHs2qVatYu3YtPj4+RseRO6DiExEpBqvVyuDBgzlx4gQJCQm4uelaQUehoU4RkWIwmUzMmTOHixcvEhMTg44hHIeKT0SkmNzd3Vm6dClpaWlMnDjR6Dhym3RsLiJyF/z8/EhJSaFFixbUqFGDZ5991uhIcgsqPhGRuxQUFERqaiqhoaEEBQXRsWNHoyPJTejiFhGRErJhwwYiIyP54osvaNSokdFxpAg6xyciUkJat27NzJkziYiI4ODBg0bHkSJoqFNEpAT17t2bw4cPExYWxoYNGwgMDDQ6kvyBhjpFRErBsGHDSE9P54svvsDT09PoOHIVDXWKiJSCyZMnExQUxLPPPovFYrE9f+7cOUaOHElubq6B6Zybik9EpBS4uLgwd+5cjh49yvDhwwE4duwYzZo1Y9KkSaxatcrghM5LxSciUko8PT1JTExk1apVjBo1ikaNGrF7924sFgvLli0zOp7T0jk+EZFStnz5cnr27Algm9qsSpUqZGdnYzKZjIzmlHTEJyJSipKSknj66aexWq3XzOf522+/8fPPPxuYzHmp+ERESsnHH39M3759OXfu3HXbTCYTq1evNiCVqPhEREpJRkYGVqsVb2/v67adO3eOhIQEA1KJzvGJiJSinJwc5s6dy7Rp0zh+/Djnzp2zDXl6eXlx5swZXF1dDU7pXFR8IiJlwGq18u233zJt2jRWrFhBfn4+FouFjRs30qJFCwCygTjgRyAXqAg0BAYDVQ3KXR6p+EREytjJkyf597//zT//+U9eeeUVIidOZCKQenn7hav29QKsQBgwEmhaxlnLIxWfiIiBYoHhwHkKC64oJgpLcArwUhnkKs90cYuIiEGulN45bl56XN5+rnZtXvvyS2JLPVn5puITESkBtWvXxsvLC19fX+69914GDRrE2bNni9w/nd9L705cvPy6LcWP6vRUfCIiJSQpKYmzZ8/yww8/sGXLFsaPH1/kvhMpHN4sjvOXXy/Fo+ITESlhwcHBhIWFsW3bNiIiIqhatSqVKlUiIiKCQ4cOkU3hhSzW0FAYPRpatQI/P+jUCY4f//2N5s2DWrWgcmV45x3b01ZgxebNPNGiBQEBAQQFBRETE0NeXl7hdquV1157jXvuuQd/f38aNGjA9u3by/JHYNdUfCIiJSwzM5OUlBTq1q3L4MGDOXjwIL/88gteXl7ExMQQd/XOCxbAJ59Adjbk5cGUKYXP79wJL71UWH5ZWXDiBBw6ZHuZydWV5pfvDdy0aRNr1qxh5syZAHzxxResX7+ePXv2kJuby2effUblypXL7PvbOxWfiEgJ6dmzJwEBAbRu3ZqQkBAmTZpEVFQU3t7e+Pn5MWrUKNatW8ePXHXLwuDB8OCD4OUFffrA1q2Fzy9ZAhER0LYteHjA22+Dy+9/ZF98/HFON2+Om5sbtWvX5oUXXmDdunUAuLu7c+bMGXbt2oXVaqV+/foEBQWV6c/CnrkZHUBEpLxITEykQ4cOtsfnzp3jhRdeYOXKlZw6dQqAM2fOkFNQAFdma6lW7fc38PaGKxfEZGVBzZq/b/PxKRzyvGLPHlYNHUq1LVs4d+4c+fn5PP744wC0a9eOmJgYoqOjOXjwIJGRkUyZMgV/f/9S+d6ORkd8IiKl5L333mP37t2kpaVx+vRp1q9fD4D/7dw+HRQEmZm/Pz53rnC484qXXqLKww+TkZHB6dOnmTBhwjWrP/ztb3/j+++/Z+fOnezZs4fJkyeX1NdyeCo+EZFScubMGby8vAgICODkyZOMHTsWgAaA561e3Ls3rFgBGzYUnvsbMwYsFttm05kzBPv74+vry65du4iN/f3uvvT0dNLS0rh06RI+Pj54enri4qI/7q/QT0JEpJQMGTKE8+fPU6VKFZo3b06XLl0AGHg7L37kEfjgA+jXr/Dor1IlqFHDttl9yhT2L1iAn58fzz//PH379rVtO336NM8//zyVKlWiVq1aVK5cmREjRpTwt3NcmrJMRMQAkUAit56x5UZMQC9gaYkmch4qPhERA6QDodz5zC0A3sA64ImSDORENNQpImKAphROOH39ErU35335dSq94tPtDCIiBrmyyoJWZyhbGuoUETHYFgrn3kyhsOCunsPzynp84RSux6cjvbun4hMRsRPHKFyBfRtwCqhE4a0Pg9AK7CVJxSciIk5FF7eIiIhTUfGJiIhTUfGJiIhTUfGJiIhTUfGJiIhTUfGJiIhTUfGJiIhTUfGJiIhTUfGJiIhTUfGJiIhTUfGJiIhTUfGJiIhTUfGJiIhTUfGJiIhTUfGJiIhTUfGJiIhTUfGJiIhTUfGJiIhTUfGJiIhTUfGJiIhTUfGJiIhT+f9g3QQw29nnYQAAAABJRU5ErkJggg==\n","text/plain":["
"]},"metadata":{}}]},{"cell_type":"markdown","metadata":{"id":"XKVBOttbAb1Y"},"source":["We can infer that _NumPy_ is our most popular site, since it has more inbound links than any other page. We've basically developed a simple metric for ranking websites on the internet. That metric equals the number of inbound edges pointing towards the site, also known as the **in-degree**. We can also compute the in-degree directly from the graph's adjacency matrix. In order to demonstrate how, we'll first print-out our updated adjacency matrix.\n","\n","**Listing 18. 20. Printing the updated adjacency matrix**"]},{"cell_type":"code","metadata":{"id":"cpbLDJRTAb1Y","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637507087581,"user_tz":-330,"elapsed":5,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"9768b925-abe9-4170-f3d4-b780a5f33750"},"source":["adjacency_matrix = nx.to_numpy_array(G)\n","print(adjacency_matrix)"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["[[0. 1. 1. 0.]\n"," [1. 0. 0. 0.]\n"," [0. 0. 0. 0.]\n"," [1. 0. 0. 0.]]\n"]}]},{"cell_type":"markdown","metadata":{"id":"B906o3xBAb1a"},"source":["The ith column in the matrix tracks the inbound edges of node `i`. The total number of inbound edges equals the number of non-zero ones within that column. Therefore, the sum of values in the column is equal to the node's in-degree. In general, executing `adjacency_matrix.sum(axis=0)` will return a vector of in-degrees. That vector's largest element will correspond to the most popular page in our Internet graph.\n","\n","**Listing 18. 21. Computing in-degrees using the adjacency matrix** "]},{"cell_type":"code","metadata":{"id":"cfZJKTDrAb1b","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1637507089324,"user_tz":-330,"elapsed":7,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"74a296f8-61fc-468f-e009-97c1938f4126"},"source":["in_degrees = adjacency_matrix.sum(axis=0)\n","for i, in_degree in enumerate(in_degrees):\n"," page = G.nodes[i]['webpage']\n"," print(f\"{page} has an in-degree of {in_degree}\")\n","\n","top_page = G.nodes[in_degrees.argmax()]['webpage']\n","print(f\"\\n{top_page} is the most popular page.\")"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["NumPy has an in-degree of 2.0\n","SciPy has an in-degree of 1.0\n","Pandas has an in-degree of 1.0\n","Matplotlib has an in-degree of 0.0\n","\n","NumPy is the most popular page.\n"]}]},{"cell_type":"markdown","metadata":{"id":"o5dVYXocAb1b"},"source":["Alternatively, we can compute all in-degrees using the NetworkX `in_degree` method.\n","\n","**Listing 18. 22. Computing in-degrees using NetworkX**"]},{"cell_type":"code","metadata":{"id":"MgBQdzE0Ab1c"},"source":["assert G.in_degree(0) == 2"],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"M_jFGiROAb1c"},"source":["Tracking the mapping between node ids and page-names can be slightly inconvenient. However, we can bypass that inconvenience by assigning string ids to individual nodes.\n","\n","**Listing 18. 23. Using strings as node-ids within a graph**"]},{"cell_type":"code","metadata":{"id":"9sRm_pVOAb1c"},"source":["G2 = nx.DiGraph()\n","G2.add_nodes_from(['NumPy', 'SciPy', 'Matplotlib', 'Pandas'])\n","G2.add_edges_from([('SciPy', 'NumPy'), ('SciPy', 'NumPy'),\n"," ('NumPy', 'Pandas'), ('Matplotlib', 'NumPy')])\n","assert G2.in_degree('NumPy') == 2"],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"d1wlKMi0CKMX"},"source":["---"]},{"cell_type":"code","metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"lHkwc2S2B_kh","executionInfo":{"status":"ok","timestamp":1637507153786,"user_tz":-330,"elapsed":3188,"user":{"displayName":"Sparsh Agarwal","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"13037694610922482904"}},"outputId":"35c5c7f9-b263-417b-9c86-fd956f898791"},"source":["!pip install -q watermark\n","%reload_ext watermark\n","%watermark -a \"Sparsh A.\" -m -iv -u -t -d"],"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Author: Sparsh A.\n","\n","Last updated: 2021-11-21 15:05:52\n","\n","Compiler : GCC 7.5.0\n","OS : Linux\n","Release : 5.4.104+\n","Machine : x86_64\n","Processor : x86_64\n","CPU cores : 2\n","Architecture: 64bit\n","\n","matplotlib: 3.2.2\n","numpy : 1.19.5\n","IPython : 5.5.0\n","networkx : 2.6.3\n","\n"]}]},{"cell_type":"markdown","metadata":{"id":"8imjytiuCLfp"},"source":["---"]}]}