A factor graph has round variable nodes and square factor nodes, and p(x) ∝ ∏s fs(xs). On a tree, every marginal follows from two sweeps of local messages: from the leaves to a root and back. A factor multiplies its table by the messages from its other variables and sums them out (8.66); a variable multiplies the messages from its other factors (8.69). Max-sum replaces the sum by a maximum (in logarithms) and finds the most probable configuration by back-tracking. Press Next message to send one message at a time; the lower panel compares the result with brute-force enumeration of every configuration. Click a variable to observe it.
A click on a variable cycles it through its observed states (0, 1 for binary variables; 1, 2, 3 on the chain, as in the book) and back to unobserved; observed variables are shaded and clamped by an indicator function. Chain: five variables with three states and the potentials ψn,n+1 of Figure 8.53 in the Python code. Tree: the graph of Figure 8.51 with binary variables and integer tables, so the messages are whole numbers. Cycle: five binary variables with pairwise factors exp(J ck sk sk+1) and unary factors exp(hk sk), s = ±1 (states 0, 1).
code/ch08_graphical_models.py (functions chain_sum_product, sum_product, max_sum, chain_max_sum, loopy_bp; Figures 8.51 to 8.53) and the checks in code/checks_ch08.py (marginals, evidence and arg max against brute-force enumeration).