A JunctionTree
is an intermediate data structure used in GTSAM’s multifrontal variable elimination. It is a ClusterTree
where each node (cluster) corresponds to a clique in the chordal graph formed during elimination.
Key differences from related structures:
- vs. EliminationTree: Junction tree nodes can represent the elimination of multiple variables simultaneously (a ‘frontal’ set), whereas elimination tree nodes typically represent single variable eliminations.
- vs. BayesTree: A JunctionTree node contains the original factors associated with the variables being eliminated in that clique. A BayesTree node contains the result of eliminating those factors (i.e., a conditional density ).
Like EliminationTree
, direct manipulation of JunctionTree
objects in Python is uncommon. It’s primarily an internal structure used by eliminateMultifrontal
when producing a BayesTree
.
import gtsam
import numpy as np
# JunctionTree is templated, need concrete types
from gtsam import GaussianFactorGraph, Ordering, VariableIndex
from gtsam import symbol_shorthand
X = symbol_shorthand.X
L = symbol_shorthand.L
Creating a JunctionTree¶
A JunctionTree
is typically constructed from an EliminationTree
as part of the multifrontal elimination process. The direct constructor might not be exposed in Python, as it’s usually created internally.
# Create a graph (same as BayesTree example)
graph = GaussianFactorGraph()
model = gtsam.noiseModel.Isotropic.Sigma(1, 1.0)
graph.add(X(0), -np.eye(1), np.zeros(1), model)
graph.add(X(0), -np.eye(1), X(1), np.eye(1), np.zeros(1), model)
graph.add(X(1), -np.eye(1), X(2), np.eye(1), np.zeros(1), model)
graph.add(L(1), -np.eye(1), X(0), np.eye(1), np.zeros(1), model)
graph.add(L(1), -np.eye(1), X(1), np.eye(1), np.zeros(1), model)
graph.add(L(2), -np.eye(1), X(1), np.eye(1), np.zeros(1), model)
graph.add(L(2), -np.eye(1), X(2), np.eye(1), np.zeros(1), model)
ordering = Ordering.ColamdGaussianFactorGraph(graph)
# Perform multifrontal elimination, which uses a JunctionTree internally
bayes_tree, remaining_graph = graph.eliminatePartialMultifrontal(ordering)
# The resulting BayesTree reflects the structure of the intermediate JunctionTree
print("Resulting BayesTree (structure mirrors JunctionTree):")
bayes_tree.print()
# Accessing the JunctionTree directly isn't typical in Python workflows.
# Its structure is implicitly captured by the BayesTree cliques.
Resulting BayesTree (structure mirrors JunctionTree):
: cliques: 2, variables: 5
- p(x1 l2 x2 )
R = [ 1.61245 -0.620174 -0.620174 ]
[ 0 1.27098 -1.08941 ]
[ 0 0 0.654654 ]
d = [ 0 0 0 ]
mean: 3 elements
l2: 0
x1: 0
x2: 0
logNormalizationConstant: -2.46292
No noise model
| - p(l1 x0 | x1)
R = [ 1.41421 -0.707107 ]
[ 0 1.58114 ]
S[x1] = [ -0.707107 ]
[ -0.948683 ]
d = [ 0 0 ]
logNormalizationConstant: -1.03316
No noise model