=================================== Working with Betweenness Centrality =================================== The betweenness centrality of a graph is a measure of centrality based on shortest paths. For every pair of nodes in a connected graph, there is at least a single shortest path between the nodes such that the number of edges the path passes through is minimized. The betweenness centrality for a given graph node is the number of these shortest paths that pass through the node. This is defined as: .. math:: c_B(v) =\sum_{s,t \in V} \frac{\sigma(s, t|v)}{\sigma(s, t)} where :math:`V` is the set of nodes, :math:`\sigma(s, t)` is the number of shortest :math:`(s, t)` paths, and :math:`\sigma(s, t|v)` is the number of those paths passing through some node :math:`v` other than :math:`s, t`. If :math:`s = t`, :math:`\sigma(s, t) = 1`, and if :math:`v \in {s, t}`, :math:`\sigma(s, t|v) = 0` This tutorial will take you through the process of calculating the betweenness centrality of a graph and visualizing it. Generate a Graph ---------------- To start we need to generate a graph: .. jupyter-execute:: import rustworkx as rx from rustworkx.visualization import mpl_draw graph = rx.generators.hexagonal_lattice_graph(4, 4) mpl_draw(graph) Calculate the Betweenness Centrality ------------------------------------ The :func:`~rustworkx.betweenness_centrality` function can be used to calculate the betweenness centrality for each node in the graph. .. jupyter-execute:: import pprint centrality = rx.betweenness_centrality(graph) # Print the centrality value for the first 5 nodes in the graph pprint.pprint({x: centrality[x] for x in range(5)}) The output of :func:`~rustworkx.betweenness_centrality` is a :class:`.CentralityMapping` which is a custom `mapping `__ type that maps the node index to the centrality value as a float. This is a mapping and not a sequence because node indices (and edge indices too, which is not relevant here) are not guaranteed to be a contiguous sequence if there are removals. Visualize the Betweenness Centrality ------------------------------------ Now that we've found the betweenness centrality for ``graph`` lets visualize it. We'll color each node in the output visualization using its calculated centrality: .. jupyter-execute:: import matplotlib.pyplot as plt # Generate a color list colors = [] for node in graph.node_indices(): colors.append(centrality[node]) # Generate a visualization with a colorbar plt.rcParams['figure.figsize'] = [15, 10] ax = plt.gca() sm = plt.cm.ScalarMappable(norm=plt.Normalize( vmin=min(centrality.values()), vmax=max(centrality.values()) )) plt.colorbar(sm, ax=ax) plt.title("Betweenness Centrality of a 4 x 4 Hexagonal Lattice Graph") mpl_draw(graph, node_color=colors, ax=ax) Alternatively, you can use :func:`~rustworkx.visualization.graphviz_draw`: .. jupyter-execute:: from rustworkx.visualization import graphviz_draw import matplotlib # For graphviz visualization we need to assign the data payload for each # node to its centrality value so that we can color based on this for node, btw in centrality.items(): graph[node] = btw # Leverage matplotlib for color map colormap = matplotlib.colormaps["magma"] norm = matplotlib.colors.Normalize( vmin=min(centrality.values()), vmax=max(centrality.values()) ) def color_node(node): rgba = matplotlib.colors.to_hex(colormap(norm(node)), keep_alpha=True) return { "color": f"\"{rgba}\"", "fillcolor": f"\"{rgba}\"", "style": "filled", "shape": "circle", "label": "%.2f" % node, } graphviz_draw(graph, node_attr_fn=color_node, method="neato")