Remove all nodes in a networkx DiGraph with in-degree and out-degree equal to 1

穿精又带淫゛_ 提交于 2019-12-07 04:12:02

问题


Say I make a DiGraph in NetworkX:

import networkx as nx

G = nx.DiGraph()

n = ["A","B","C","D","E","F","H","I","J","K","L","X","Y","Z"]

e = [("A","Z"),("Z","B"),("B","Y"),("Y","C"),("C","G"),("G","H"),("G","I"),("I","J"),("K","J"),("J","L"),("F","E"),("E","D"),("D","X"),("X","C")]

G.add_nodes_from(n)

G.add_edges_from(e)

How would I remove all the nodes with a in-degree and an out-degree equal to 1, so that my graph would look like this?:

import networkx as nx

G = nx.DiGraph()

n = ["A","C","F","G","H","J","K","L"]

e = [("A","C"),("C","G"),("G","H"),("G","J"),("K","J"),("J","L")

G.add_nodes_from(n)

G.add_edges_from(e)

The idea is to remove the "flow-through" nodes and retain connectivity.


回答1:


The following code does what you want although I don't see where you would get edges from ("A", "C") and ("G", "J") in the final result.

import networkx as nx

def remove_edges(g, in_degree=1, out_degree=1):
    g2=g.copy()
    d_in=g2.in_degree(g2)
    d_out=g2.out_degree(g2)
    print(d_in)
    print(d_out)
    for n in g2.nodes():
        if d_in[n]==in_degree and d_out[n] == out_degree: 
            g2.remove_node(n)
    return g2

G_trimmed = remove_edges(G)
G_trimmed.edges()
#outputs [('C', 'G'), ('G', 'H'), ('K', 'J'), ('J', 'L')]
G_trimmed.nodes()
#outputs ['A', 'C', 'G', 'F', 'H', 'K', 'J', 'L']



回答2:


Essentially, just iterate through the nodes and check to see if they are "flow-through nodes", using remove_node and add_edge to rewire the graph. Define a function:

def remove_flow_through(graph):
    for n in graph.nodes():
        pred = graph.predecessors(n)
        succ = graph.successors(n)
        if len(pred) == len(succ) == 1:
            graph.remove_node(n)
            graph.add_edge(pred[0], succ[0])

The function modifies the graph in-place, so work on a copy of the graph if needed.

Now call remove_flow_through repeatedly until the number of nodes in the graph no longer decreases:

while True:
    prev_len = len(G)
    remove_flow_through(G)
    if len(G) == prev_len:
        break

The sample graph has all of the flow-through nodes with a single call of remove_flow_through. It is possible, however, to have the removal of a node reproduce an existing edge, which leads to a graph with remaining flow-through nodes. An example of this is:

dg = nx.DiGraph([(1,2), (2,3), (3,4), (2,5), (5,3)])


来源:https://stackoverflow.com/questions/17735252/remove-all-nodes-in-a-networkx-digraph-with-in-degree-and-out-degree-equal-to-1

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!