3

I have a networkx.Graph object representing a graph whose nodes represent English words, and whose edges between two wnodes imply that the two words that those nodes represent have at least one shared cognitive synonym between their synsets (i.e. a non-empty intersection). I hope that is interesting or useful background to someone, but my problem is a more widely applicable one relating to graphs, networkx, and Python.

Many induced subgraphs (edge-induced, or vertex-induced) of this graph are both edge disjoint and vertex disjoint, and I'd like to separate these subgraphs into their own networkx.Graph objects such that they're connected and mutually disjoint. It is possible that I'm just using the wrong search terms for the networkx documentation, but I didn't see anything promising related to "disjoint". Here are some examples from a tiny portion of the graph.

enter image description here

I looked through the search results for [networkx] disjoint on Stack Overflow and didn't see what I was looking for. For example, one result talked about getting the induced subgraph when there's already have an edge set to induce from. Or another post talked about trying to draw two disjoint graphs, but that's assuming you already have them. Related to the graph theory aspect of my question, but not the networkx aspect, is that apparently there's such a thing as a flood fill algorithm that might address the part of my question.

Now, for a minimum working example, let's create a small random graph but ensure that it is disconnected.

import networkx as nx

g = nx.fast_gnp_random_graph(10, 0.3)

while nx.is_connected(g):
    g = nx.fast_gnp_random_graph(10, 0.3)

At this point, we have a graph g. What I'm thinking of is somethine like below, where I occupy a list of the graphs that are to be mutually disjoint. I need to not only add more graphs as I loop over the nodes, but also update the graphs as I go. I thought maybe unions of induced graphs might work, but the nx.disjoint_union_all and nx.union are either going to force the graphs to be disjoint by relabelling (I don't want this) or expect the graphs to already be disjoint.

graphs = []

for node in g.nodes(): # same 'g' we made above
    if graphs:
        pass
    else:
        graphs.append(g.subgraph([i for i in g.neighbors(node)] +\
                                 [node]).copy())

How can I separate an unconnected networkx graph into multiple mutually disjoint graphs that are connected?

Galen
  • 1,128
  • 1
  • 14
  • 31
  • Is your graph directed? The graphs you're showing in your examples are undirected, but you're also using the term "weakly connected", which implies directed. If undirected, use `nx.connected_components`. If directed, use `nx.connected_components(nx.Graph(G))` [first converts it to undirected] – Joel May 01 '20 at 04:43
  • Oops, that's a mistake in language on my part. I am working with undirected graphs. I'll fix the wording. Thanks for the feedback. It looks like you have a potential answer; please post it as one so I can accept it if it works! :P – Galen May 01 '20 at 04:44
  • I'm busy now, so I'm more than happy for anyone else to fill in the details. I may not get back to it for a few days. – Joel May 01 '20 at 04:49

1 Answers1

10

It seems that you are looking for connected components.
Consider the following graph.

enter image description here

components = [g.subgraph(c).copy() for c in nx.connected_components(g)]
for idx,g in enumerate(components,start=1):
    print(f"Component {idx}: Nodes: {g.nodes()} Edges: {g.edges()}")

Output:

Component 1: Nodes: [0, 1, 2, 5, 6, 7, 8, 9] Edges: [(0, 2), (0, 6), (1, 2), (1, 5), (1, 7), (1, 8), (2, 5), (5, 7), (6, 8), (7, 9), (8, 9)]
Component 2: Nodes: [3, 4] Edges: [(3, 4)]
abc
  • 11,579
  • 2
  • 26
  • 51