在NetworkX中查找有向图中后继者的后继者

时间:2011-07-31 00:39:01

标签: python networkx directed-graph

我正在为NetworkX中的有向图制作一些代码,并且遇到了一个可能是我可疑编程经验的结果。我要做的是以下内容:

我有一个有向图G,顶部有两个“父节点”,所有其他节点都从这些节点流出。在绘制这个网络的图形时,我想将每个节点作为“父1”的后代绘制一种颜色,而所有其他节点绘制另一种颜色。这意味着我需要一个名单Parent 1的继承者。

现在,我可以轻松地使用它们获得第一层:

descend= G.successors(parent1)

问题是这只给了我第一代接班人。最好是,我想要继承者的继承者,继承者的继承者的继承者等等。任意地,因为能够运行分析并制作图表而不必确切知道其中有多少代是非常有用的

知道如何处理这个问题吗?

7 个答案:

答案 0 :(得分:5)

您不需要后代列表,只需要为它们着色。为此,您只需选择一个遍历图形并使用它为边缘着色的算法。

例如,您可以

from networkx.algorithms.traversal.depth_first_search import dfs_edges

G = DiGraph( ... )
for edge in dfs_edges(G, parent1):
    color(edge)

请参阅http://networkx.lanl.gov/reference/algorithms.traversal.html

答案 1 :(得分:1)

那么,继任者的继承者只是后代的继承者吗?

# First successors
descend = G.successors(parent1)
# 2nd level successors
def allDescendants(d1):
   d2 = []
   for d in d1:
       d2 += G.successors(d)
   return d2

descend2 = allDescendants(descend)

要获得3级后代,请调用allDescendants(d2)等。

编辑: 问题1: allDescend = descend + descend2为您提供两组合并,为更多级别的后代做同样的事情。

问题2:如果您的图表中有循环,那么您需要先修改代码以测试您之前是否访问过该后代,例如:

def allDescendants(d1, exclude):
   d2 = []
   for d in d1:
       d2 += filter(lambda s: s not in exclude, G.successors(d))
   return d2

这样,您将allDescend作为第二个参数传递给上面的函数,因此它不包含在将来的后代中。你一直这样做,直到allDescandants()返回一个空数组,在这种情况下你知道你已经探索了整个图,然后你就停止了。

由于这开始看起来像家庭作业,我会让你弄清楚如何将这一切拼凑在一起。 ;)

答案 2 :(得分:1)

因此,对于未来偶然发现的人来说,答案更清晰,更容易找到,这是我最终使用的代码:

G = DiGraph() # Creates an empty directed graph G
infile = open(sys.argv[1])
for edge in infile:
    edge1, edge2 = edge.split() #Splits data on the space
    node1 = int(edge1) #Creates integer version of the node names 
    node2 = int(edge2)
    G.add_edge(node1,node2) #Adds an edge between two nodes

parent1=int(sys.argv[2])   
parent2=int(sys.argv[3])

data_successors = dfs_successors(G,parent1)
successor_list = data_successors.values()
allsuccessors = [item for sublist in successor_list for item in sublist]

pos = graphviz_layout(G,prog='dot') 
plt.figure(dpi=300)
draw_networkx_nodes(G,pos,node_color="LightCoral")
draw_networkx_nodes(G,pos,nodelist=allsuccessors, node_color="SkyBlue")
draw_networkx_edges(G,pos,arrows=False) 
draw_networkx_labels(G,pos,font_size=6,font_family='sans-serif',labels=labels)

答案 3 :(得分:1)

我相信自几年前@Jochen Ritzel的回答以来,Networkx发生了变化。

现在以下内容成立,仅更改import语句。

import networkx
from networkx import dfs_edges

G = DiGraph( ... )
for edge in dfs_edges(G, parent1):
    color(edge)

答案 4 :(得分:0)

如果你想获得所有后继节点而不通过边缘,另一种方法可能是:

import networkx as nx
G = DiGraph( ... )
successors = nx.nodes(nx.dfs_tree(G, your_node))

我注意到,如果你打电话:

successors = list(nx.dfs_successors(G, your_node)

底层的节点不知何故不包括在内。

答案 5 :(得分:0)

Oneliner:

descendents = sum(nx.dfs_successors(G, parent).values(), [])

答案 6 :(得分:0)