使用Networkx(Python)进行图形遍历

使用Networkx(Python)进行图形遍历,python,networkx,Python,Networkx,我正在使用Networkx来管理依赖关系图。 假设我有一个图表,每个字母代表一个服务器 >>> G = nx.Graph() >>> G.add_edge("A","B") >>> G.add_edge("A","H") >>> G.add_edge("H","C") >>> G.add_edge("B","C") >>> G.add_edge("B","D") A

我正在使用Networkx来管理依赖关系图。 假设我有一个图表,每个字母代表一个服务器

>>> G = nx.Graph()
>>> G.add_edge("A","B")
>>> G.add_edge("A","H")
>>> G.add_edge("H","C")
>>> G.add_edge("B","C")
>>> G.add_edge("B","D")

           A
         /   \
       H       B
     /        /  \
   C         C     D 
在这里我们可以看到,在开始A之前,我们需要开始H和B,开始H,我们需要开始C,然后开始B,我们需要开始C和D

通过稍微摆弄一下Networkx,我发现我可以通过进行dfs遍历来实现这一点

print nx.dfs_successors(G,"A")
{A:[H,B], H:[C], B:[D] }
但我对这种方法有一个问题。正如您所看到的,当树中有两个相同的字母时,Networkx只选择将其中一个放入最终结构中(这是正确的),但我需要完整的结构 如何强制Networkx添加到结构B:[D,C]

我想通过这样做来精确说明这一点

>>> nx.dfs_successors(G,"B")
{'B': ['C', 'D']}
所以一切都是“内部”正确的,只是dfs_的继任者没有以我希望的方式显示它


谢谢你

接受了你的代码,你的图表并没有像你期望的那样出来。如果您这样做:

import pylab as p
import networkx as nx

G = nx.Graph()
G.add_edge("A","B")
G.add_edge("A","H")
G.add_edge("H","C")
G.add_edge("B","C")
G.add_edge("B","D")

nx.draw(G)
p.show()
您将看到以下图形:

这是由于
G的逻辑造成的。添加边缘(“A”、“B”)

  • 如果
    G
    没有id为“A”的节点,则添加它
  • 如果
    G
    没有id为“B”的节点,则添加它
  • 用新边将“A”连接到“B”
  • 因此,您只创建了五个节点,而不是图片中的六个节点

    编辑 Networkx可以将任何哈希值作为节点的值,在图形中它使用str(节点)标记每个圆。因此,我们可以简单地定义自己的节点类(您可能想将其称为服务器?),并为其提供所需的行为

    import pylab as p
    import networkx as nx
    
    
    class Node(object):
        nodes = []
    
        def __init__(self, label):
            self._label = label
    
        def __str__(self):
            return self._label
    
    nodes = [Node(l) for l in ["A","B","C","C","D","H"]]
    edges = [(0,1),(0,5),(5,2),(1,3),(1,4)]
    
    G = nx.Graph()
    for i,j in edges:
        G.add_edge(nodes[i], nodes[j])
    
    nx.draw(G)
    p.show()
    
    给我们
    这就是你想要的。

    我想你想要的是拓扑排序

    这仅在具有DAG(有向无环图)时有效。 如果是这样,您也可以绘制所需的树-如下所示:

    import uuid
    import networkx as nx
    import matplotlib.pyplot as plt
    G = nx.DiGraph()
    G.add_edge("A","B")
    G.add_edge("A","H")
    G.add_edge("H","C")
    G.add_edge("B","C")
    G.add_edge("B","D")
    
    order =  nx.topological_sort(G)
    print "topological sort"
    print order
    
    # build tree
    start = order[0]
    nodes = [order[0]] # start with first node in topological order
    labels = {}
    print "edges"
    tree = nx.Graph()
    while nodes:
        source = nodes.pop()
        labels[source] = source
        for target in G.neighbors(source):
            if target in tree:
                t = uuid.uuid1() # new unique id
            else:
                t = target
            labels[t] = target
            tree.add_edge(source,t)
            print source,target,source,t
            nodes.append(target)
    
    nx.draw(tree,labels=labels)
    plt.show()
    
    图形使用标签映射将节点的ID映射到原始标签


    感谢您绘制图表。这就是我“认为”Networkx在我背后所做的。因此,我的问题是:如何使用Networkx创建我的示例中的树?典型的理想情况是,当我创建G.add_边(“B”,“C”)时,创建一个新节点“C”是为了重用连接到H的on。然后,您需要将该新节点称为其他节点。可能是C1和C2。据我所知,NetworkX不允许多个节点具有相同的标签。但我需要节点具有相同的标签。就像我在主线中说的。我的节点是servername,我不能更改名称,否则我不知道哪个是哪个。。。但实际上,托尔斯滕·克兰兹不是“错”的,而是正确的,B取决于“C和D”。只是算法“dfs_successivers()”的输出B只依赖于D,如果我的树不能用于Networkx,那么这是错误的,是否可以用于其他库?感谢第二个例子,希望这符合你的需要。