有没有一种有效的方法可以将节点添加到Digraph而不引起networkx中的循环?

时间:2019-04-30 19:29:58

标签: python python-3.x networkx

我正在考虑使用networkx创建和维护Directed Acyclic Graph(DAG)

检查添加边缘是否会导致DiGraph不再是DAG的首选方法是什么?

示例图:

import networkx as nx


G = nx.DiGraph()
G.add_edges_from([(1,2), (1,3), (2,4)]) # no cycles so far

我们得到:

>>> G
1 2 3
2 4
3
4


>>> nx.is_directed_acyclic_graph(G)
True

当我们向图中添加一个循环时:

G.add_edge(4,1) # now we have a cycle

我们得到:

>>> G
1 2 3
2 4
3
4 1


>>> nx.is_directed_acyclic_graph(G)
False

如何检查新边是否会引起循环?到目前为止,我想出的最好的方法是:

def add_dependency(G, n1, n2):
    if n2 in nx.ancestors(G, n1):
        print('this will create a cycle')
    else:
        print(f"add {n2} as edge of {n1}")
        G.add_edge(n1, n2)

有更好的方法吗?

1 个答案:

答案 0 :(得分:1)

在可读性和内存消耗的情况下,您的代码最适合networkx。请注意,许多问题(尤其是图论)在时间和内存消耗之间权衡。

在您的情况下,您不知道新边是否会创建一个循环,因此您必须重新计算节点内祖先并检查它们(因此,我建议您使用代码)。但是,如果您有密集的图并且大多数新边都不正确,则必须重复重新计算祖先。但是您可以预先计算每个节点的祖先并将它们存储在集合的字典中:d = {n: nx.ancestors(DAG, n) for n in DAG}搜索复杂度为O(1),但是每个边的加法会导致许多节点祖先的重新计算。