A discrete Bayes tree represents the discrete probability distribution produced by multifrontal elimination of a discrete factor graph. Its DiscreteBayesTreeClique nodes group one conditional with its child cliques, making repeated marginal and joint queries efficient.
import gtsam
import numpy as np
from gtsam.symbol_shorthand import M, X
from IPython.display import Markdown, displayBuilding a Bayes tree¶
The usual construction path is DiscreteFactorGraph.eliminateMultifrontal(). Here a two-variable model specifies a prior on A0 and a pairwise potential over B0 and A0; the ordering controls which variables are eliminated first.
A = (gtsam.symbol("A", 0), 2)
B = (gtsam.symbol("B", 0), 2)
graph = gtsam.DiscreteFactorGraph()
graph.add(A, "0.6 0.4")
graph.add([B, A], "0.8 0.2 0.3 0.7")
ordering = gtsam.Ordering()
ordering.push_back(A[0])
ordering.push_back(B[0])
tree = graph.eliminateMultifrontal(ordering)
print("cliques:", tree.size(), "empty:", tree.empty())DiscreteBayesTree¶
size() and empty() describe the tree, while clique(key) finds the clique containing a frontal variable. marginalFactor(key), joint(key1, key2), and jointBayesNet(key1, key2) perform inference without rebuilding the entire elimination. evaluate(values) evaluates the factored distribution, and dot() or saveGraph() expose its structure.
dot_source = tree.dot()
print(dot_source.splitlines()[0])
assignment = gtsam.DiscreteValues()
assignment[A[0]] = 0
assignment[B[0]] = 0
print("unnormalized value:", tree.evaluate(assignment))DiscreteBayesTreeClique¶
A clique is generally obtained from a tree rather than constructed manually. conditional() returns its discrete conditional, isRoot() identifies the root, and nrChildren() reports the local branching. The clique can also evaluate the part of the Bayes tree rooted at that node.
clique = tree.clique(B[0])
print("is root:", clique.isRoot())
print("children:", clique.nrChildren())
print("frontals:", clique.conditional().nrFrontals())