鉴于混合非循环图由有向和无向边组成,我想将此图分解为链组件的有向图(链组件中的每个节点将仅与无向边连接)及其排序。
我很困惑我是否应该首先拓扑排序所有有向边,然后将无向边作为链组件捕获,或者首先应该遍历所有无向边并给它们组ID,然后找到一些有向边连接这些组件。
由于图表是非循环的,我认为可以从低编号组件到高编号组件进行排序,但无法得出可靠答案。
答案 0 :(得分:1)
定义链组件的等价关系如下由Drton 2009:
定义链图 G 中的两个顶点 v_0
和 v_k
等价,如果存在路径 (v_0,..., v_k)
使得 G 中的 v_i − v_{i+1}
对于所有 0 ≤ i ≤ k − 1 .
这个等价关系下的等价类是 G 的链分量。粗略地说,这意味着由链图的无向边构成的图的所有连通分量,加上所有只与有向边相交的节点,加上所有根本没有邻居的节点,相当于 Peter's answer
这是正确分解 Cowell 2005,Probabilistic Networks and ..., p. 中给出的链图 CH-Asia 的函数。 110 图 6.1。 它是我作为业余爱好项目开发的 graphical models library 的一部分。
虽然它使用自定义数据结构,但适应其他涉及图形模型的代码库应该不会太难。
def get_chain_components(self) -> Set[Set[Node]]:
"""!
"""
# filter out undirected edges
edges = set()
for e in self.edges():
if e.type() == EdgeType.UNDIRECTED:
edges.add(e)
# make a graph from undirected edges
undi = UndiGraph.from_graph(Graph.from_edge_node_set(edges, self.nodes()))
return undi.get_components_as_node_set()
答案 1 :(得分:0)
我认为你的两种方法都可以正常工作。
在我看来,第二种方法似乎更自然。
如果我在networkx中这样做,我会通过以下方式实现你的第二种方法:
创建一个仅包含无向边的新图H.
在H上调用connected_components以提取链组件并为每个组件分配不同的组ID。
为每个组ID创建一个包含1个节点的新图表F.根据原始图中的有向边,将F中的组与有向边连接。
在F上调用topological_sort以计算组ID的顺序。
答案 2 :(得分:0)
您描述的混合图也是有向图。只需用指向相反方向的两个定向边缘替换每个无向边缘即可。
此外,您不能拥有具有无向边的非循环图。至少有一个长度为2的循环,所以我不确定你的意思是什么。
您似乎在寻找此图中强关联的组件,因此我建议您使用Tarjan's algorith来查找它们。