I'm not sure if specific terminology exists for this, but I'm looking to identify paths in a directed network in which case the directionality goes both ways. I'm building a network with a bunch of provided data and by accident stumbled on some artifacts where nodes A and B are both parents/children of each other.
In looking to identify these, I stumbled on the term "self loop". This is what I want, just for paths longer than a single edge.
import networkx as nx
g = nx.DiGraph()
g.add_edges_from([(0, 1), (0, 2), (0, 3), (1, 3), (3, 0), (3, 3), (2, 0), (1, 2), (2, 1)])
nx.draw_networkx(g, arrows=True, with_labels=True, width=0.2, edge_color='#AAAAAA', arrowsize=20,
node_size=2)
networkx
has a function to identify nodes with self loops, but I only get node 3 as a result.
list(nx.nodes_with_selfloops(g))
[3]
Only node 3
is identified, but in this case I'd be looking to identify that 1/2 and 0/1 have arrows going both ways. It's not a single edge self loop, but allows 2 > 0 > 1 > 2 and 1 > 3 > 0 > 2 > 1. I start and end at the same node, just with other nodes between.
Is there an efficient way to identify "what nodes that have bi-directional arrows to the same node"? I have not identified enough of these cases to know if the cause will always be a single double sided arrow or something like 2+ multi-edge paths that start/stop with the same node.
The real world data is like process flows, so there should not be cases where somehow A flows to B and B also flows into A, so these are the data inconsistencies I'm looking to quickly identify.
One easy way would be to compute a set intersection of the edges with their reversed counterpart (with reverse
and &
):
g.edges & nx.reverse(g).edges
Output:
{(0, 2), (0, 3), (1, 2), (2, 0), (2, 1), (3, 0), (3, 3)}
If you want a more compact version you could further combine the (a,b)/(b,a) pairs into a single (a,b) and (a,a) into (a,) with:
set(tuple(frozenset(e)) for e in g.edges & nx.reverse(g).edges)
Output:
{(0, 2), (0, 3), (1, 2), (3,)}
Graph: