Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/networkx/algorithms/tree/decomposition.py: 30%
27 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-10-20 07:00 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-10-20 07:00 +0000
1r"""Function for computing a junction tree of a graph."""
3from itertools import combinations
5import networkx as nx
6from networkx.algorithms import chordal_graph_cliques, complete_to_chordal_graph, moral
7from networkx.utils import not_implemented_for
9__all__ = ["junction_tree"]
12@not_implemented_for("multigraph")
13@nx._dispatch
14def junction_tree(G):
15 r"""Returns a junction tree of a given graph.
17 A junction tree (or clique tree) is constructed from a (un)directed graph G.
18 The tree is constructed based on a moralized and triangulated version of G.
19 The tree's nodes consist of maximal cliques and sepsets of the revised graph.
20 The sepset of two cliques is the intersection of the nodes of these cliques,
21 e.g. the sepset of (A,B,C) and (A,C,E,F) is (A,C). These nodes are often called
22 "variables" in this literature. The tree is bipartite with each sepset
23 connected to its two cliques.
25 Junction Trees are not unique as the order of clique consideration determines
26 which sepsets are included.
28 The junction tree algorithm consists of five steps [1]_:
30 1. Moralize the graph
31 2. Triangulate the graph
32 3. Find maximal cliques
33 4. Build the tree from cliques, connecting cliques with shared
34 nodes, set edge-weight to number of shared variables
35 5. Find maximum spanning tree
38 Parameters
39 ----------
40 G : networkx.Graph
41 Directed or undirected graph.
43 Returns
44 -------
45 junction_tree : networkx.Graph
46 The corresponding junction tree of `G`.
48 Raises
49 ------
50 NetworkXNotImplemented
51 Raised if `G` is an instance of `MultiGraph` or `MultiDiGraph`.
53 References
54 ----------
55 .. [1] Junction tree algorithm:
56 https://en.wikipedia.org/wiki/Junction_tree_algorithm
58 .. [2] Finn V. Jensen and Frank Jensen. 1994. Optimal
59 junction trees. In Proceedings of the Tenth international
60 conference on Uncertainty in artificial intelligence (UAI’94).
61 Morgan Kaufmann Publishers Inc., San Francisco, CA, USA, 360–366.
62 """
64 clique_graph = nx.Graph()
66 if G.is_directed():
67 G = moral.moral_graph(G)
68 chordal_graph, _ = complete_to_chordal_graph(G)
70 cliques = [tuple(sorted(i)) for i in chordal_graph_cliques(chordal_graph)]
71 clique_graph.add_nodes_from(cliques, type="clique")
73 for edge in combinations(cliques, 2):
74 set_edge_0 = set(edge[0])
75 set_edge_1 = set(edge[1])
76 if not set_edge_0.isdisjoint(set_edge_1):
77 sepset = tuple(sorted(set_edge_0.intersection(set_edge_1)))
78 clique_graph.add_edge(edge[0], edge[1], weight=len(sepset), sepset=sepset)
80 junction_tree = nx.maximum_spanning_tree(clique_graph)
82 for edge in list(junction_tree.edges(data=True)):
83 junction_tree.add_node(edge[2]["sepset"], type="sepset")
84 junction_tree.add_edge(edge[0], edge[2]["sepset"])
85 junction_tree.add_edge(edge[1], edge[2]["sepset"])
86 junction_tree.remove_edge(edge[0], edge[1])
88 return junction_tree