gpt4 book ai didi

python - 使用 networkX 查找节点前辈的最优雅方式

转载 作者:太空狗 更新时间:2023-10-29 17:38:23 29 4
gpt4 key购买 nike

我正在使用 python 开发图形模型项目 NetworkX .NetworkX 使用字典提供简单而良好的功能:

import networkx as nx
G = nx.DiGraph() # a directed graph
G.add_edge('a', 'b')
print G['a'] # prints {'b': {}}
print G['b'] # prints {}

我想使用有向图,因为我正在编写具有方向的依赖项(在上面的示例中,我有条件为“a”的“b”的封闭形式,而不是相反)。

对于给定的节点,我想找到该节点的前任。对于上面的例子,par('b') 应该返回 ['a']。 NetworkX 确实有一个后继函数,它可以找到任何节点的子节点。显然,通过遍历所有节点并找到那些子节点为“b”的节点是可行的,但节点数量将是 Ω(n)(这对我的应用程序来说太昂贵了)。

我无法想象这么简单的东西会被排除在这个制作精良的包裹之外,但找不到任何东西。

一个有效的选择是存储图的有向和无向版本;所有无向边基本上都是通过添加两个有向边来实现的,因此可以采用相邻节点和子节点(这将是前身)之间的集合差异。

问题是我不确定包装现有 networkx DiGraph 和 Graph 类来完成此任务的最 pythonic 方法。真的,我只想得到一个 PGraph 类,它的行为与 networkx DiGraph 类完全一样,但除了 successors(node) 函数外,还有一个 predecessors(node) 函数.

PGraph是否应该继承DiGraph并封装Graph(以供前辈功能使用)?那么我应该如何强制将所有节点和边添加到它包含的有向图和无向图中呢?我是否应该重新实现在 PGraph 中添加和删除节点和边的功能(以便在有向和无向版本中添加和删除它们)?我担心如果我错过了一些晦涩难懂的东西,我以后会头疼,这可能并不意味着好的设计。

或者(请让它成为True)是否有一种简单的方法来获取网络中节点的前辈 x.DiGraph 而我完全错过了它?

非常感谢您的帮助。


编辑:

我认为这可以完成工作。 PGraph继承自DiGraph,封装了另一个DiGraph(这个倒过来)。我已经覆盖了添加和删除节点和边缘的方法。

import networkx as nx

class PGraph(nx.DiGraph):
def __init__(self):
nx.DiGraph.__init__(self)
self.reversed_graph = nx.DiGraph()
def add_node(self, n, attr_dict=None, **attr):
nx.DiGraph.add_node(self, n, attr_dict, **attr)
self.reversed_graph.add_node(n, attr_dict, **attr)
def add_nodes_from(self, ns, attr_dict=None, **attr):
nx.DiGraph.add_nodes_from(self, ns, attr_dict, **attr)
self.reversed_graph.add_nodes_from(ns, attr_dict, **attr)
def add_edge(self, a, b, attr_dict=None, **attr):
nx.DiGraph.add_edge(self, a, b, attr_dict, **attr)
self.reversed_graph.add_edge(b, a, attr_dict, **attr)
def add_edges_from(self, es, attr_dict=None, **attr):
nx.DiGraph.add_edges_from(self, es, attr_dict, **attr)
self.reversed_graph.add_edges_from(es, attr_dict, **attr)
def remove_node(self, n):
nx.DiGraph.remove_node(self, n)
self.reversed_graph.remove_node(n)
def remove_nodes_from(self, ns):
nx.DiGraph.remove_nodes_from(self, ns)
self.reversed_graph.remove_nodes_from(ns)
def remove_edge(self, a, b):
nx.DiGraph.remove_edge(self, b, a)
self.reversed_graph.remove_edge(a, b)
def remove_edges_from(self, es):
nx.DiGraph.remove_edges_from(self, es)
self.reversed_graph.remove_edges_from([ (b,a) for a,b in es])
# the predecessors function I wanted
def predecessors(self, n):
return self.reversed_graph.successors(n)

您如何看待这个解决方案?它可能会使内存使用量增加一倍,但我认为这是可以接受的。是不是太复杂了?这是好的设计吗?

最佳答案

有一个前驱(和前驱_iter)方法: http://networkx.lanl.gov/reference/generated/networkx.DiGraph.predecessors.html#networkx.DiGraph.predecessors

也没有什么可以阻止您直接访问数据结构作为 G.pred

 In [1]: import networkx as nx
In [2]: G = nx.DiGraph() # a directed graph
In [3]: G.add_edge('a', 'b')
In [4]: G.predecessors('b')
Out[4]: ['a']
In [5]: G.pred['b']
Out[5]: {'a': {}}

关于python - 使用 networkX 查找节点前辈的最优雅方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3810782/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com