NetworkX Tutorial¶
In this tutorial we will take a look at ways of combining the analysis tools provided by NetworkX with the visualization capailities of AlgorithmX.
Simple Graph¶
Let’s start by creating a simple NetworkX graph. We will use add_path
to quickly add both nodes and edges.
import networkx as nx
G = nx.Graph()
nx.add_path(G, [1, 2, 3])
nx.add_path(G, [4, 2, 5])
print('Nodes:', G.nodes)
print('Edges:', G.edges)
Nodes: [1, 2, 3, 4, 5]
Edges: [(1, 2), (2, 3), (2, 4), (2, 5)]
Now that we have all the data we need, we can create an AlgorithmX canvas to display our nodes and edges.
from algorithmx import jupyter_canvas
canvas = jupyter_canvas()
canvas.nodes(G.nodes).add()
canvas.edges(G.edges).add()
canvas
Finally, let’s make it look a little more interesting.
canvas = jupyter_canvas()
node_colors = {1: 'red', 2: 'green', 3: 'blue', 4: 'orange', 5: 'purple'}
canvas.nodes(G.nodes).add(
shape='rect',
size=(20, 12),
color=lambda n: node_colors[n]
)
canvas.edges(G.edges).add()
canvas
Weighted and Directed Graphs¶
To create a directed graph, all we need to do is use a NetworkX DiGraph, and tell AlgrithmX that the edges should be rendered with an arrow.
G = nx.DiGraph()
G.add_nodes_from([1, 2, 3])
G.add_edges_from([(1, 2), (2, 3), (3, 1)])
canvas = jupyter_canvas()
canvas.nodes(G.nodes).add()
canvas.edges(G.edges).add(directed=True)
canvas
To create wighted graph, we will first ensure that our NetworkX edges have a ‘weight’ attribute. Then, we will add a label to each edge displaying the attribute.
G = nx.Graph()
G.add_nodes_from([1, 2, 3])
G.add_weighted_edges_from([(1, 2, 0.4), (2, 3, 0.2), (3, 1, 0.3)])
canvas = jupyter_canvas()
canvas.nodes(G.nodes).add()
canvas.edges(G.edges).add(
labels=lambda e: {0: {'text': G.edges[e]['weight']}}
)
canvas
Finally, AlgorithmX provides a uility to simplify this process.
from algorithmx.networkx import add_graph
canvas = jupyter_canvas()
add_graph(canvas, G)
Random Graph¶
NetworkX provides a range of functions for generating graphs. For generating a random
graph, we will use the basic gnp_random_graph
function. By providing a seed, we can
ensure that we get the same graph every time (otherwise there is no guarantee of it
being connected!).
G = nx.gnp_random_graph(10, 0.3, 138)
canvas = jupyter_canvas()
canvas.nodes(G.nodes).add()
canvas.edges(G.edges).add()
canvas
To make the graph directed, we will simply use G.to_directed
. To make the graph
weighted, we will need to configure a weight attribute for each edge. Since our graph is
random, we’ll make our edge weights random as well.
from random import randint
G = G.to_directed()
nx.set_edge_attributes(G, {e: {'weight': randint(1, 10)} for e in G.edges})
Finally, we display the graph.
canvas = jupyter_canvas()
add_graph(canvas, G)
Detailed Graph¶
Now we are going to create a graph that displays a range of interesting properties. Let’s begin by generating a random weighted graph, as before.
G = nx.gnp_random_graph(10, 0.3, 201)
nx.set_edge_attributes(G, {e: {'weight': randint(1, 10)} for e in G.edges})
Next, we will use NetworkX to calculate the graph’s coloring and edge centrality.
coloring = nx.greedy_color(G)
centrality = nx.edge_betweenness_centrality(G, weight='weight', normalized=True)
We can now begin displaying the graph. First, we will add the nodes and assign them a color based on their calculated priority. We happen to know that any planar graph requires at most 4 different colors, and so we prepare these beforehand.
canvas = jupyter_canvas()
color_priority = {0: 'red', 1: 'orange', 2: 'yellow', 3: 'green'}
canvas.nodes(G.nodes).add() \
.color(lambda n: color_priority[coloring[n]])
print(coloring)
{4: 0, 2: 1, 3: 2, 0: 1, 1: 2, 6: 0, 8: 1, 7: 2, 9: 2, 5: 0}
Afterwards, we will add the edges. Each one will have two labels; one to display it’s weight, and another to display it’s calculated centrality.
formatted_centrality = {k: '{0:.2f}'.format(v) for k, v in centrality.items()}
init_edges = canvas.edges(G.edges).add()
init_edges.label().add(
text=lambda e: G.edges[e]['weight']
)
init_edges.label('centrality').add(
color='blue',
text=lambda e: formatted_centrality[e]
)
print(formatted_centrality)
{(0, 1): '0.02', (0, 3): '0.07', (0, 4): '0.11', (1, 4): '0.18', (1, 8): '0.00', (2, 3): '0.04', (2, 4): '0.40', (2, 5): '0.20', (2, 6): '0.20', (2, 7): '0.07', (3, 4): '0.09', (3, 6): '0.09', (4, 8): '0.00', (4, 9): '0.36', (6, 7): '0.13', (8, 9): '0.20'}
Finally, we display the whole graph.
canvas