【问题标题】:pygraphviz: finding the max rank node using successorspygraphviz:使用后继查找最大等级节点
【发布时间】:2020-02-23 22:44:12
【问题描述】:

我正在尝试查找最大等级节点和深度。这是我的代码。

import pygraphviz as pgv


class Test:
    def __init__(self):
        self.G = pgv.AGraph(directed=True)

        self.G.add_node('a')
        self.G.add_node('b')
        self.G.add_node('c')
        self.G.add_node('d')
        self.G.add_node('e')
        self.G.add_node('f')

        self.G.add_edge('a', 'b')
        self.G.add_edge('b', 'c')
        self.G.add_edge('b', 'd')
        self.G.add_edge('d', 'e')
        self.G.add_edge('e', 'f')
        print(self.G.string())
        self.find_max_rank_node()

    def find_max_rank_node(self):
        nodes = self.G.nodes()
        depth = 0
        for n in nodes:
            layer1 = self.G.successors(n)
            if layer1:
                depth = depth + 1
                for layer_one in layer1:
                    layer2 = self.G.successors(layer_one)
                    print(n, layer2)


if __name__ == '__main__': Test()

输出应该是f4。我开始编写代码,但意识到我不知道分支的深度......而且我不确定如何编写循环。

【问题讨论】:

  • 一个澄清问题,如果根是“a”,“f”的深度是 4。是在搜索函数中定义根还是先找到根/源,再计算深度?
  • @pastaleg 是的。那是正确的。假设您从a 开始。遇到树枝时需要一个通用的解决方案。

标签: python loops search binary-search-tree pygraphviz


【解决方案1】:

使用来自NetworkX Python 库的算法进行图形处理。

使用pip install networkx 安装 NetworkX。那么:

import networkx as nx
from networkx.drawing.nx_agraph import from_agraph
import pygraphviz as pgv

# constructing graph with pygraphviz
G = pgv.AGraph(directed=True)

G.add_node('a')
G.add_node('b')
G.add_node('c')
G.add_node('d')
G.add_node('e')
G.add_node('f')

G.add_edge('a', 'b')
G.add_edge('b', 'c')
G.add_edge('b', 'd')
G.add_edge('d', 'e')
G.add_edge('e', 'f')

# converting pygraphviz graph to networkx graph
X = from_agraph(G)

# dictionary {node: length}
lengths = nx.shortest_path_length(X, 'a')

result = max(lengths.items(), key=lambda p: p[1])

结果是('f', 4)


旁注

因为问题是关于pygraphviz,所以我提供了将pygraphviz 对象转换为networkx 的解决方案。

您也可以在软件及更高版本中仅使用 networkx 图表 然后使用networkx.drawing.nx_agraph.to_agraph 转换为pygraphviz 图形。

【讨论】:

    【解决方案2】:

    使用递归可以最简单地解决您的问题。创建以下find_max_rank_node 函数来获取我们要开始搜索的节点,并返回最深的节点和深度:

    import pygraphviz as pgv
    
    class Test:
        def __init__(self):
            self.G = pgv.AGraph(directed=True)
    
            self.G.add_node('a')
            self.G.add_node('b')
            self.G.add_node('c')
            self.G.add_node('d')
            self.G.add_node('e')
            self.G.add_node('f')
    
            self.G.add_edge('a', 'b')
            self.G.add_edge('b', 'c')
            self.G.add_edge('b', 'd')
            self.G.add_edge('d', 'e')
            self.G.add_edge('e', 'f')
            print(self.G.string())
            # try it out
            self.find_max_rank_node('a')    # ('f', 4)
            self.find_max_rank_node('b')    # ('f', 3)
            self.find_max_rank_node('c')    # ('c', 0)
            self.find_max_rank_node('d')    # ('f', 2)
            self.find_max_rank_node('e')    # ('f', 1)
            self.find_max_rank_node('f')    # ('f', 0)
            # visualize the graph
            self.viz()
    
        def find_max_rank_node(self, start_node):
            succ = self.G.successors(start_node)
            if len(succ) == 0:
                return (start_node, 0)
            else:
                deepest_node = None
                depth = 0
                for node in succ:
                    n, d = self.find_max_rank_node(node)
                    if d >= depth:
                        deepest_node = n
                        depth = d
                return (deepest_node, 1+depth)
    
        def viz(self):
            self.G.layout()
            self.G.draw('file.png')
    
    
    if __name__ == '__main__': Test()
    

    此外,我还创建了一种名为 viz 的方法来可视化图形并将其写入名为 file.png 的图像中,如下所示:

    希望这能回答你的问题!!

    【讨论】:

    • 如果添加循环,算法会引发递归错误。例如,添加边self.G.add_edge('e', 'b')
    • @MichałSłapek.. 这是真的 :)
    猜你喜欢
    • 2014-04-08
    • 2020-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多