2

I am working with networks undergoing a number of disrupting events. So, a number of nodes fail because of a given event. Therefore there is a transition between the image to the left to that to the right:

enter image description here

My question: how can I find the disconnected subgraphs, even if they contain only 1 node? My purpose is to count them and render as failed, as in my study this is what applies to them. By semi-isolated nodes, I mean groups of isolated nodes, but connected to each other.

I know I can find isolated nodes like this:

def find_isolated_nodes(graph):
    """ returns a list of isolated nodes. """
    isolated = []
    for node in graph:
        if not graph[node]:
            isolated += node
    return isolated

but how would you amend these lines to make them find groups of isolated nodes as well, like those highlighted in the right hand side picture?

MY THEORETICAL ATTEMPT

It looks like this problem is addressed by the Flood Fill algorithm, which is explained here. However, I wonder how it could be possible to simply count the number of nodes in the giant component(s) and then subtract it from the number of nodes that appear still active at stage 2. How would you implement this?

mdml
  • 22,442
  • 8
  • 58
  • 66
FaCoffee
  • 7,609
  • 28
  • 99
  • 174
  • Hello, can you suggest the way for counting the isolated networks (the dotted red circle. i.e., the number of isolated network = 5)? – Ssong Mar 29 '22 at 14:05

1 Answers1

5

If I understand correctly, you are looking for "isolated" nodes, meaning the nodes not in the largest component of the graph. As you mentioned, one method to identify the "isolated" nodes is to find all the nodes NOT in the largest component. To do so, you can just use networkx.connected_components, to get a list of the components and sort them by size:

components = list(nx.connected_components(G)) # list because it returns a generator
components.sort(key=len, reverse=True)

Then you can find the largest component, and get a count of the "isolated" nodes:

largest = components.pop(0)
num_isolated = G.order() - len(largest)

I put this all together in an example where I draw a Erdos-Renyi random graph, coloring isolated nodes blue:

# Load modules and create a random graph
import networkx as nx, matplotlib.pyplot as plt
G = nx.gnp_random_graph(10, 0.15)

# Identify the largest component and the "isolated" nodes
components = list(nx.connected_components(G)) # list because it returns a generator
components.sort(key=len, reverse=True)
largest = components.pop(0)
isolated = set( g for cc in components for g in cc )

# Draw the graph
pos = nx.spring_layout(G)
nx.draw_networkx_nodes(G, pos=pos, nodelist=largest, node_color='r')
nx.draw_networkx_nodes(G, pos=pos, nodelist=isolated, node_color='b')
nx.draw_networkx_edges(G, pos=pos)
plt.show()

graph with isolated nodes colored blue

mdml
  • 22,442
  • 8
  • 58
  • 66
  • In my understanding the line `components.pop(0)` does exactly what `max(nx.connected_component_subgraphs(G), key=len)` would do. Am I wrong? Also, why did you use `set( g for cc in components for g in cc )` rather than `len(G.nodes()) - len(largest)` when computing the isolated nodes? – FaCoffee Nov 04 '15 at 14:24
  • 1
    @FrancescoCastellani: you're understanding is correct. And I used a `set()` to get a list of the isolated nodes, so that I could plot them. For your application, it sounds like you could just do `len(G.nodes())-len(largest)`. – mdml Nov 04 '15 at 14:25
  • 1
    `components.sort(key=lambda cc: len(cc), reverse=True)` should be simplified to `components.sort(key= len, reverse=True)`. and `len(G.nodes())` should be simplified to `G.order()` – Joel Nov 04 '15 at 20:39