Reputation: 1290
I've a MultiDiGraph
in which there are some edges that I need remove.
import networkx as ntx
import matplotlib.pyplot as plt
edges = [
(6, 7), (7, 6), (7, 11), (11, 7), (11, 8), (8, 11), (8, 9), (9, 8), (9, 5), (5, 9),
(5, 10), (10, 5), (10, 2), (2, 10),
(2, 1), (1, 2), (1, 0), (0, 1),
(0, 12), (12, 0),
(11, 14), (14, 11),
(5, 3),
(3, 4),
(4, 13), (13, 4),
]
G = ntx.MultiDiGraph()
G.add_edges_from(edges)
fig, ax = plt.subplots(figsize=(10, 10))
ntx.draw_networkx(G, with_labels=True)
plt.show()
Above an example of my graph, I will remove the edges between nodes 5 and 12 and I will the same with all situation in which an edge is linked with only one edge. There are some situation in which a bidirectional edge is linked to a one way edge, in this case I don't wont to merge the edges.
So, my aim is to obtain the graph below:
new_edges = [
(6, 11), (11, 6),
(11, 14), (14, 11),
(11, 5), (5, 11),
(5, 12), (12, 5),
(5, 4),
(4, 13), (13, 4),
]
new_G = ntx.MultiDiGraph()
new_G.add_edges_from(new_edges)
fig, ax = plt.subplots(figsize=(10, 10))
ntx.draw_networkx(new_G, with_labels=True)
plt.show()
I found this question but is useful for a Graph
not for a MultiDiGraph
.
Upvotes: 0
Views: 94
Reputation: 926
Firstly, for the bidirectional edges, it's pretty much the same as the one for Graph
but we add another edge in the opposite direction to make it bidirectional:
# Select all nodes with only 2 neighbors
nodes_to_remove_bidirectional = [n for n in G.nodes if len(list(G.neighbors(n))) == 2]
# For each of those nodes
for node in nodes_to_remove_bidirectional:
# We add an edge between neighbors (len == 2 so it is correct)
neighbors = list(G.neighbors(node))
G.add_edge(*neighbors)
neighbors.reverse() # add the edge with opposite direction
G.add_edge(*neighbors)
# And delete the node
G.remove_node(node)
Now for the unidirectional edges, we select nodes with one incoming edge (predecessor
) and one outgoing edge (successor
) to different nodes:
nodes_to_remove_unidirectional = [n for n in G.nodes if
len(list(G.neighbors(n))) == 1 and
len(list(G.predecessors(n))) == 1 and
next(G.neighbors(n)) != next(G.predecessors(n))
]
# For each of those nodes
for node in nodes_to_remove_unidirectional:
# We add an edge between neighbors (len == 2 so it is correct)
neighbors = list(G.neighbors(node))
G.add_edge(next(G.predecessors(node)), next(G.neighbors(node)))
# And delete the node
G.remove_node(node)
Upvotes: 1