Source code for networkx.algorithms.tree.decomposition

r"""用于计算图的连接树的函数。"""

from itertools import combinations

import networkx as nx
from networkx.algorithms import chordal_graph_cliques, complete_to_chordal_graph, moral
from networkx.utils import not_implemented_for

__all__ = ["junction_tree"]


[docs] @not_implemented_for("multigraph") @nx._dispatchable(returns_graph=True) def junction_tree(G): r"""返回给定图的连接树。 连接树(或团树)是从一个(无)向图 G 构建的。该树基于 G 的道德化和三角化版本构建。树的节点由修正图的最大团和分离集组成。两个团的分离集是这些团节点的交集,例如,(A,B,C) 和 (A,C,E,F) 的分离集是 (A,C)。这些节点在此文献中通常称为“变量”。该树是二分的,每个分离集与其两个团相连。 连接树不是唯一的,因为团的考虑顺序决定了包含哪些分离集。 连接树算法包括五个步骤 [1]_: 1. 道德化图 2. 三角化图 3. 找到最大团 4. 从团构建树,连接共享节点的团,设置边权重为共享变量的数量 5. 找到最大生成树 Parameters ---------- G : networkx.Graph 有向或无向图。 Returns ------- junction_tree : networkx.Graph `G` 对应的连接树。 Raises ------ NetworkXNotImplemented 如果 `G` 是 `MultiGraph` 或 `MultiDiGraph` 的实例,则引发此异常。 References ---------- .. [1] 连接树算法: https://en.wikipedia.org/wiki/Junction_tree_algorithm .. [2] Finn V. Jensen 和 Frank Jensen。1994。最优连接树。在第十届国际人工智能不确定性会议(UAI’94)的会议记录中。Morgan Kaufmann Publishers Inc., San Francisco, CA, USA, 360–366. """ clique_graph = nx.Graph() if G.is_directed(): G = moral.moral_graph(G) chordal_graph, _ = complete_to_chordal_graph(G) cliques = [tuple(sorted(i)) for i in chordal_graph_cliques(chordal_graph)] clique_graph.add_nodes_from(cliques, type="clique") for edge in combinations(cliques, 2): set_edge_0 = set(edge[0]) set_edge_1 = set(edge[1]) if not set_edge_0.isdisjoint(set_edge_1): sepset = tuple(sorted(set_edge_0.intersection(set_edge_1))) clique_graph.add_edge(edge[0], edge[1], weight=len(sepset), sepset=sepset) junction_tree = nx.maximum_spanning_tree(clique_graph) for edge in list(junction_tree.edges(data=True)): junction_tree.add_node(edge[2]["sepset"], type="sepset") junction_tree.add_edge(edge[0], edge[2]["sepset"]) junction_tree.add_edge(edge[1], edge[2]["sepset"]) junction_tree.remove_edge(edge[0], edge[1]) return junction_tree