A HybridJunctionTree is the hybrid equivalent of gtsam.GaussianJunctionTree. It represents an intermediate stage in multifrontal variable elimination on a HybridGaussianFactorGraph.
It is a tree structure where each node (a “cluster” or “clique”) contains:
A set of frontal variables (those being eliminated at this node).
A set of separator variables (those shared with the parent clique).
The original factors from the
HybridGaussianFactorGraphthat involve only the frontal and separator variables of this clique and its descendants in the elimination tree.
Key differences:
vs. HybridEliminationTree: A junction tree node can eliminate multiple variables (frontals) at once, whereas an elimination tree node corresponds to a single variable elimination.
vs. HybridBayesTree: A junction tree node stores the original factors before elimination, while a Bayes tree node stores the result of eliminating those factors (a
HybridConditional).
Like HybridEliminationTree, the HybridJunctionTree is primarily an internal data structure used by the eliminateMultifrontal process. Its structure directly informs the structure of the resulting HybridBayesTree. Direct manipulation in Python is uncommon.
import gtsam
import numpy as np
from gtsam import (
HybridGaussianFactorGraph,
Ordering,
HybridEliminationTree,
HybridJunctionTree,
JacobianFactor,
DecisionTreeFactor,
HybridGaussianFactor,
)
from gtsam.symbol_shorthand import X, DCreating a HybridJunctionTree¶
It is constructed from a HybridEliminationTree. The process typically involves:
Create
HybridGaussianFactorGraph.Determine an
Ordering.Build the
HybridEliminationTree.Build the
HybridJunctionTreefrom theHybridEliminationTree.
This process is encapsulated within HybridGaussianFactorGraph.eliminateMultifrontal.
# --- Create a HybridGaussianFactorGraph (same as HBT/HET examples) ---
hgfg = HybridGaussianFactorGraph()
dk0 = (D(0), 2)
prior_d0 = DecisionTreeFactor([dk0], "0.6 0.4"); hgfg.add(prior_d0) # F0
prior_x0 = JacobianFactor(X(0), np.eye(1), np.zeros(1), gtsam.noiseModel.Isotropic.Sigma(1, 1.0)); hgfg.add(prior_x0) # F1
gf0 = JacobianFactor(X(1), np.eye(1), np.array([1.0]), gtsam.noiseModel.Isotropic.Sigma(1, 0.5))
gf1 = JacobianFactor(X(1), np.eye(1), np.array([5.0]), gtsam.noiseModel.Isotropic.Sigma(1, 1.0))
meas_x1_d0 = HybridGaussianFactor(dk0, [gf0, gf1]); hgfg.add(meas_x1_d0) # F2
odom_x0_x1 = JacobianFactor(X(0), -np.eye(1), X(1), np.eye(1), np.array([1.0]), gtsam.noiseModel.Isotropic.Sigma(1, np.sqrt(0.1))); hgfg.add(odom_x0_x1) # F3
print("Original HybridGaussianFactorGraph:")
hgfg.print()
# --- Ordering and Elimination Tree ---
ordering = gtsam.Ordering([X(0), X(1), D(0)])
print(f"\nElimination Ordering: {ordering}")
het = HybridEliminationTree(hgfg, ordering)
print("\nHybridEliminationTree:")
het.print()
# --- Construct the Junction Tree ---
hjt = HybridJunctionTree(het)
print("\nResulting HybridJunctionTree:")
# Printing shows cliques, separators, and the *original factor indices* stored within each clique.
hjt.print()Original HybridGaussianFactorGraph:
size: 4
Factor 0
DiscreteFactor:
f[ (d0,2), ]
Choice(d0)
0 Leaf 0.6
1 Leaf 0.4
Factor 1
GaussianFactor:
A[x0] = [
1
]
b = [ 0 ]
Noise model: unit (1)
Factor 2
HybridGaussianFactor:
Hybrid [x1; d0]{
Choice(d0)
0 Leaf :
A[x1] = [
1
]
b = [ 1 ]
isotropic dim=1 sigma=0.5
scalar: 0
1 Leaf :
A[x1] = [
1
]
b = [ 5 ]
Noise model: unit (1)
scalar: 0
}
Factor 3
GaussianFactor:
A[x0] = [
-1
]
A[x1] = [
1
]
b = [ 1 ]
isotropic dim=1 sigma=0.316228
Elimination Ordering: Position 0: x0, x1, d0
HybridEliminationTree:
-(d0)
- f[ (d0,2), ]
Choice(d0)
0 Leaf 0.6
1 Leaf 0.4
| -(x1)
| -
Hybrid [x1; d0]{
Choice(d0)
0 Leaf :
A[x1] = [
1
]
b = [ 1 ]
isotropic dim=1 sigma=0.5
scalar: 0
1 Leaf :
A[x1] = [
1
]
b = [ 5 ]
Noise model: unit (1)
scalar: 0
}
| | -(x0)
| | -
A[x0] = [
1
]
b = [ 0 ]
Noise model: unit (1)
| | -
A[x0] = [
-1
]
A[x1] = [
1
]
b = [ 1 ]
isotropic dim=1 sigma=0.316228
Resulting HybridJunctionTree:
- (4) d0
| - (4) x1
| | - (4) x0
Elimination¶
The primary purpose of the junction tree is to structure the multifrontal elimination process, which ultimately yields a HybridBayesTree. The eliminate method of the junction tree performs this step, but it’s usually accessed via HybridGaussianFactorGraph.eliminateMultifrontal.