Max-product produces an MPE (maximum probability explanation), which GTSAM represents with a DiscreteLookupDAG. Its DiscreteLookupTable conditionals record the maximizing frontal value for every parent assignment, allowing the MPE assignment to be recovered with argmax().
import gtsam
import numpy as np
from gtsam.symbol_shorthand import M, X
from IPython.display import Markdown, displayCreating a lookup DAG¶
Users normally obtain the DAG from DiscreteFactorGraph.maxProduct(). Constructing DiscreteLookupTable directly requires the internal algebraic decision tree, which is intentionally not part of the high-level Python API.
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])
dag = graph.maxProduct(ordering)
print("lookup tables:", dag.size())DiscreteLookupDAG.argmax()¶
With no arguments, argmax() back-substitutes through every table and returns the global maximum-product assignment. Its optional given argument supplies values for parent variables outside the DAG; variables solved by the DAG are written during back-substitution.
mpe = dag.argmax()
readable_mpe = {gtsam.DefaultKeyFormatter(k): v for k, v in mpe.items()}
print("MPE assignment:", readable_mpe)DiscreteLookupTable¶
at(i) returns an individual table. It is a DiscreteConditional, so nrFrontals(), nrParents(), keys(), and argmax(parent_values) describe the local decision rule. The DAG owns these tables; retain the DAG while inspecting them.
table = dag.at(0)
print("frontals:", table.nrFrontals(), "parents:", table.nrParents())
print("local maximizing value at the MPE parents:", table.argmax(mpe))