Search code examples
pythongraphnetworkxdirected-graph

Networkx : getting all possible paths in DAG


I am trying to split a directed (acyclic) graph into direction-connected path, relying on connectivity :

Example graph

When I test weak and strong connectivity subgraphs, here is what I get :

Weak connectivity :
['16', '17'], ['3', '41', '39', '42']
Strong connectivity :
['17'], ['16'], ['39'], ['41'], ['3'], ['42']

I understand the weak connectivity result, but not the strong-connectivity one, as I would expect 3 subgraphs : [16, 17], [42, 39] and [3, 41, 39].

What am I missing here, why those single node lists ? How to get the expected result ?

Here is the code :

import networkx as nx
import matplotlib.pyplot as plt

G = nx.DiGraph()
G.add_edges_from([('16', '17'), ('3', '41'), ('41', '39'), ('42', '39')])

print("Weak connectivity : ")
for subgraph in (G.subgraph(c).copy() for c in nx.weakly_connected_components(G)) :
    print(subgraph.nodes)
print("Strong connectivity : ")
for subgraph in (G.subgraph(c).copy() for c in nx.strongly_connected_components(G)) :
    print(subgraph.nodes)

nx.draw_networkx(G, pos=nx.circular_layout(G))
plt.show()

Solution

  • So, thanks to comments & answers, I realised that "connectivity" was a false lead for what I want to achieve. To be clear : I want to get every possible path between all starting nodes to their connected ending nodes, in a directed acyclic graph.

    So I ended up writing my own solution, which is quite simple to understand, but probably not the best, regarding performance or style (pythonic / networkx). Improvment suggestions are welcome :)

    import networkx as nx
    import matplotlib.pyplot as plt
    
    G = nx.DiGraph()
    G.add_edges_from([('16', '17'), ('3', '41'), ('41', '39'), ('42', '39')])
    
    roots = []
    leaves = []
    for node in G.nodes :
      if G.in_degree(node) == 0 : # it's a root
        roots.append(node)
      elif G.out_degree(node) == 0 : # it's a leaf
        leaves.append(node)
    
    for root in roots :
      for leaf in leaves :
        for path in nx.all_simple_paths(G, root, leaf) :
          print(path)
    
    nx.draw_networkx(G, pos=nx.circular_layout(G))
    plt.show()
    

    (If there is a built-in function in networkx, I clearly missed it)