Skip to content

Commit cd5517c

Browse files
authored
Merge pull request borglab#2259 from borglab/doc/discrete3
Add some more examples
2 parents 52e00fa + 451effc commit cd5517c

4 files changed

Lines changed: 912 additions & 135 deletions

File tree

gtsam/discrete/discrete.md

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# Discrete Inference in GTSAM
2+
3+
The discrete module in GTSAM provides a comprehensive framework for probabilistic inference over discrete random variables. This module implements Bayesian networks, factor graphs, and efficient inference algorithms using decision trees and elimination methods.
4+
5+
## Overview
6+
7+
The discrete inference workflow in GTSAM typically follows this pattern:
8+
9+
1. **Model Definition**: Start with Bayesian networks using `DiscreteBayesNet` and `DiscreteConditional`
10+
2. **Likelihood Integration**: Transform to factor graphs with `DiscreteFactorGraph` and various factor types
11+
3. **Inference**: Eliminate variables to obtain `DiscreteBayesTree` for efficient marginalization
12+
4. **Specialized Operations**: Use advanced classes for specific inference tasks
13+
14+
## Bayesian Networks for Modeling
15+
16+
### DiscreteBayesNet
17+
The foundational class for representing Bayesian networks over discrete variables. A Bayes net defines a joint probability distribution as a product of conditional probability distributions.
18+
19+
```cpp
20+
DiscreteBayesNet bayesNet;
21+
bayesNet.add(conditional1);
22+
bayesNet.add(conditional2);
23+
```
24+
25+
**Notebook**: [DiscreteBayesNet.ipynb](doc/DiscreteBayesNet.ipynb)
26+
27+
### DiscreteConditional
28+
Represents conditional probability tables P(X|Y1, Y2, ...) in the Bayesian network. These form the building blocks of Bayes nets and encode the conditional dependencies between variables.
29+
30+
```cpp
31+
DiscreteConditional conditional(key, parents, signature);
32+
```
33+
34+
**Notebook**: [DiscreteConditional.ipynb](doc/DiscreteConditional.ipynb)
35+
36+
### DiscreteDistribution
37+
Represents marginal probability distributions P(X) for discrete variables. Used for priors.
38+
39+
**Notebook**: [DiscreteDistribution.ipynb](doc/DiscreteDistribution.ipynb)
40+
41+
### Signature
42+
Handy class to define the conditional probability structure for discrete variables, specifying parent-child relationships and cardinalities.
43+
44+
**Notebook**: [Signature.ipynb](doc/Signature.ipynb)
45+
46+
## Discrete Factor Graphs
47+
48+
### DiscreteFactorGraph
49+
The central class for factor graph representation. Bayes nets can be transformed into factor graphs by converting conditionals to factors, allowing for the integration of likelihood factors from observations.
50+
51+
```cpp
52+
DiscreteFactorGraph graph = bayesNet.toFactorGraph();
53+
graph.add(likelihoodFactor);
54+
```
55+
56+
**Notebook**: [DiscreteFactorGraph.ipynb](doc/DiscreteFactorGraph.ipynb)
57+
58+
### DiscreteFactor
59+
Abstract base class for all discrete factors. Factors represent arbitrary functions over discrete variables and can encode both prior knowledge and likelihood information.
60+
61+
### DecisionTreeFactor
62+
A concrete implementation of discrete factors using decision trees for efficient storage and computation. Particularly effective for factors with conditional independence structure.
63+
64+
**Notebook**: [DecisionTreeFactor.ipynb](doc/DecisionTreeFactor.ipynb)
65+
66+
### TableFactor
67+
Represents factors as explicit probability tables. Useful for small factors or when the full joint distribution needs to be stored explicitly.
68+
69+
## Inference: Bayes Trees
70+
71+
### DiscreteBayesTree
72+
The result of variable elimination on a factor graph. Bayes trees enable efficient exact inference through their clique tree structure, supporting fast marginalization and conditioning operations.
73+
74+
```cpp
75+
DiscreteBayesTree bayesTree = graph.eliminateMultifrontal(ordering);
76+
DiscreteValues result = bayesTree.optimize();
77+
```
78+
79+
### DiscreteEliminationTree
80+
Intermediate structure used during the elimination process. Represents the computational tree for variable elimination before conversion to a Bayes tree.
81+
82+
### DiscreteJunctionTree
83+
Alternative tree structure for inference, particularly useful for repeated marginal queries over the same model.
84+
85+
## Specialized and Exotic Classes
86+
87+
### DiscreteMarginals
88+
Provides efficient computation of marginal probabilities for all variables in a factor graph or Bayes tree. Essential for uncertainty quantification.
89+
90+
### DiscreteLookupDAG
91+
Specialized data structure for fast lookup operations in discrete probabilistic models. Optimized for scenarios with repeated queries.
92+
93+
### DiscreteSearch
94+
Implements search algorithms over discrete probability spaces, including optimization and sampling methods.
95+
96+
### AlgebraicDecisionTree
97+
Implements decision trees with algebraic operations (addition, multiplication) for efficient factor operations. The computational backbone for many discrete operations.
98+
99+
### Assignment and DiscreteValues
100+
Core data structures for representing variable assignments and probability values in discrete models.
101+
102+
### DiscreteKey
103+
Represents discrete random variables with their cardinalities, fundamental for defining the variable space.
104+
105+
## Decision Trees and Computational Primitives
106+
107+
### DecisionTree
108+
Template-based decision tree implementation supporting arbitrary value types. Provides the foundation for efficient discrete computations.
109+
110+
### Ring
111+
Mathematical abstraction for algebraic operations on decision tree values, enabling generic algorithms over different semirings.
112+
113+
## Parser and Utilities
114+
115+
### SignatureParser
116+
Parses string representations of conditional probability signatures, enabling convenient model specification from text.
117+
118+
### TableDistribution
119+
Utility class for working with probability distributions represented as tables.
120+
121+
## Example Workflows
122+
123+
### Basic Bayesian Network
124+
1. Define variables with `DiscreteKey`
125+
2. Create conditionals with `DiscreteConditional`
126+
3. Build network with `DiscreteBayesNet`
127+
4. Query marginals or sample
128+
129+
### Factor Graph Inference
130+
1. Start with `DiscreteBayesNet` or build `DiscreteFactorGraph` directly
131+
2. Add likelihood factors using `DecisionTreeFactor` or `TableFactor`
132+
3. Eliminate variables to get `DiscreteBayesTree`
133+
4. Query results using `DiscreteMarginals`
134+
135+
### Advanced Operations
136+
1. Use `AlgebraicDecisionTree` for custom factor operations
137+
2. Employ `DiscreteLookupDAG` for repeated queries
138+
3. Apply `DiscreteSearch` for optimization problems

gtsam/discrete/doc/DecisionTreeFactor.ipynb

Lines changed: 75 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@
120120
},
121121
{
122122
"cell_type": "code",
123-
"execution_count": 7,
123+
"execution_count": 4,
124124
"metadata": {},
125125
"outputs": [
126126
{
@@ -129,17 +129,49 @@
129129
"text": [
130130
"Value of f1 at A=1, B=0: 3.0\n",
131131
"\n",
132-
"--- Product Factor f3 = f1 * f2 ---\n",
133-
"DecisionTreeFactor\n",
134-
" f[ (a0,2), (b0,2), ]\n",
135-
" Choice(b0) \n",
136-
" 0 Choice(a0) \n",
137-
" 0 0 Leaf 0.8\n",
138-
" 0 1 Leaf 0.6\n",
139-
" 1 Choice(a0) \n",
140-
" 1 0 Leaf 1.6\n",
141-
" 1 1 Leaf 0.8\n"
132+
"--- Product Factor f3 = f1 * f2 ---\n"
142133
]
134+
},
135+
{
136+
"data": {
137+
"text/html": [
138+
"<div>\n",
139+
"<table class='DecisionTreeFactor'>\n",
140+
" <thead>\n",
141+
" <tr><th>a0</th><th>b0</th><th>value</th></tr>\n",
142+
" </thead>\n",
143+
" <tbody>\n",
144+
" <tr><th>0</th><th>0</th><td>0.8</td></tr>\n",
145+
" <tr><th>0</th><th>1</th><td>1.6</td></tr>\n",
146+
" <tr><th>1</th><th>0</th><td>0.6</td></tr>\n",
147+
" <tr><th>1</th><th>1</th><td>0.8</td></tr>\n",
148+
" </tbody>\n",
149+
"</table>\n",
150+
"</div>"
151+
],
152+
"text/markdown": [
153+
"|a0|b0|value|\n",
154+
"|:-:|:-:|:-:|\n",
155+
"|0|0|0.8|\n",
156+
"|0|1|1.6|\n",
157+
"|1|0|0.6|\n",
158+
"|1|1|0.8|\n"
159+
],
160+
"text/plain": [
161+
"DecisionTreeFactor\n",
162+
" f[ (a0,2), (b0,2), ]\n",
163+
" Choice(b0) \n",
164+
" 0 Choice(a0) \n",
165+
" 0 0 Leaf 0.8\n",
166+
" 0 1 Leaf 0.6\n",
167+
" 1 Choice(a0) \n",
168+
" 1 0 Leaf 1.6\n",
169+
" 1 1 Leaf 0.8"
170+
]
171+
},
172+
"execution_count": 4,
173+
"metadata": {},
174+
"output_type": "execute_result"
143175
}
144176
],
145177
"source": [
@@ -158,7 +190,7 @@
158190
"# f3(A,B) = f1(A,B) * f2(A)\n",
159191
"f3_product = f1_string * f2_vector\n",
160192
"print(\"\\n--- Product Factor f3 = f1 * f2 ---\")\n",
161-
"f3_product.print()"
193+
"f3_product"
162194
]
163195
},
164196
{
@@ -172,7 +204,7 @@
172204
},
173205
{
174206
"cell_type": "code",
175-
"execution_count": 9,
207+
"execution_count": 5,
176208
"metadata": {},
177209
"outputs": [
178210
{
@@ -189,92 +221,92 @@
189221
"<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 180.7)\">\n",
190222
"<title>G</title>\n",
191223
"<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-180.7 274,-180.7 274,4 -4,4\"/>\n",
192-
"<!-- 0x11743f4a8 -->\n",
224+
"<!-- 0x135734e58 -->\n",
193225
"<g id=\"node1\" class=\"node\">\n",
194-
"<title>0x11743f4a8</title>\n",
226+
"<title>0x135734e58</title>\n",
195227
"<ellipse fill=\"none\" stroke=\"black\" cx=\"135\" cy=\"-156.57\" rx=\"20.13\" ry=\"20.13\"/>\n",
196228
"<text text-anchor=\"middle\" x=\"135\" y=\"-151.52\" font-family=\"Times,serif\" font-size=\"14.00\">b0</text>\n",
197229
"</g>\n",
198-
"<!-- 0x1174343c8 -->\n",
230+
"<!-- 0x135734f08 -->\n",
199231
"<g id=\"node2\" class=\"node\">\n",
200-
"<title>0x1174343c8</title>\n",
232+
"<title>0x135734f08</title>\n",
201233
"<ellipse fill=\"none\" stroke=\"black\" cx=\"99\" cy=\"-80.82\" rx=\"19.62\" ry=\"19.62\"/>\n",
202234
"<text text-anchor=\"middle\" x=\"99\" y=\"-75.77\" font-family=\"Times,serif\" font-size=\"14.00\">a0</text>\n",
203235
"</g>\n",
204-
"<!-- 0x11743f4a8&#45;&gt;0x1174343c8 -->\n",
236+
"<!-- 0x135734e58&#45;&gt;0x135734f08 -->\n",
205237
"<g id=\"edge1\" class=\"edge\">\n",
206-
"<title>0x11743f4a8&#45;&gt;0x1174343c8</title>\n",
238+
"<title>0x135734e58&#45;&gt;0x135734f08</title>\n",
207239
"<path fill=\"none\" stroke=\"black\" stroke-dasharray=\"5,2\" d=\"M126.47,-138.09C122.22,-129.4 117,-118.69 112.25,-108.95\"/>\n",
208240
"<polygon fill=\"black\" stroke=\"black\" points=\"115.54,-107.73 108.01,-100.28 109.25,-110.8 115.54,-107.73\"/>\n",
209241
"</g>\n",
210-
"<!-- 0x117434058 -->\n",
242+
"<!-- 0x1357353a8 -->\n",
211243
"<g id=\"node5\" class=\"node\">\n",
212-
"<title>0x117434058</title>\n",
244+
"<title>0x1357353a8</title>\n",
213245
"<ellipse fill=\"none\" stroke=\"black\" cx=\"171\" cy=\"-80.82\" rx=\"19.62\" ry=\"19.62\"/>\n",
214246
"<text text-anchor=\"middle\" x=\"171\" y=\"-75.77\" font-family=\"Times,serif\" font-size=\"14.00\">a0</text>\n",
215247
"</g>\n",
216-
"<!-- 0x11743f4a8&#45;&gt;0x117434058 -->\n",
248+
"<!-- 0x135734e58&#45;&gt;0x1357353a8 -->\n",
217249
"<g id=\"edge4\" class=\"edge\">\n",
218-
"<title>0x11743f4a8&#45;&gt;0x117434058</title>\n",
250+
"<title>0x135734e58&#45;&gt;0x1357353a8</title>\n",
219251
"<path fill=\"none\" stroke=\"black\" d=\"M143.53,-138.09C147.78,-129.4 153,-118.69 157.75,-108.95\"/>\n",
220252
"<polygon fill=\"black\" stroke=\"black\" points=\"160.75,-110.8 161.99,-100.28 154.46,-107.73 160.75,-110.8\"/>\n",
221253
"</g>\n",
222-
"<!-- 0x117443d80 -->\n",
254+
"<!-- 0x147a5f210 -->\n",
223255
"<g id=\"node3\" class=\"node\">\n",
224-
"<title>0x117443d80</title>\n",
256+
"<title>0x147a5f210</title>\n",
225257
"<polygon fill=\"none\" stroke=\"black\" points=\"54,-25.2 0,-25.2 0,0 54,0 54,-25.2\"/>\n",
226258
"<text text-anchor=\"middle\" x=\"27\" y=\"-7.55\" font-family=\"Times,serif\" font-size=\"14.00\">1.00</text>\n",
227259
"</g>\n",
228-
"<!-- 0x1174343c8&#45;&gt;0x117443d80 -->\n",
260+
"<!-- 0x135734f08&#45;&gt;0x147a5f210 -->\n",
229261
"<g id=\"edge2\" class=\"edge\">\n",
230-
"<title>0x1174343c8&#45;&gt;0x117443d80</title>\n",
262+
"<title>0x135734f08&#45;&gt;0x147a5f210</title>\n",
231263
"<path fill=\"none\" stroke=\"black\" stroke-dasharray=\"5,2\" d=\"M84.78,-66.74C74.32,-57.13 59.95,-43.91 48.16,-33.06\"/>\n",
232264
"<polygon fill=\"black\" stroke=\"black\" points=\"50.59,-30.54 40.86,-26.35 45.85,-35.69 50.59,-30.54\"/>\n",
233265
"</g>\n",
234-
"<!-- 0x117434400 -->\n",
266+
"<!-- 0x135734f60 -->\n",
235267
"<g id=\"node4\" class=\"node\">\n",
236-
"<title>0x117434400</title>\n",
268+
"<title>0x135734f60</title>\n",
237269
"<polygon fill=\"none\" stroke=\"black\" points=\"126,-25.2 72,-25.2 72,0 126,0 126,-25.2\"/>\n",
238270
"<text text-anchor=\"middle\" x=\"99\" y=\"-7.55\" font-family=\"Times,serif\" font-size=\"14.00\">3.00</text>\n",
239271
"</g>\n",
240-
"<!-- 0x1174343c8&#45;&gt;0x117434400 -->\n",
272+
"<!-- 0x135734f08&#45;&gt;0x135734f60 -->\n",
241273
"<g id=\"edge3\" class=\"edge\">\n",
242-
"<title>0x1174343c8&#45;&gt;0x117434400</title>\n",
274+
"<title>0x135734f08&#45;&gt;0x135734f60</title>\n",
243275
"<path fill=\"none\" stroke=\"black\" d=\"M99,-61.02C99,-53.49 99,-44.74 99,-36.82\"/>\n",
244276
"<polygon fill=\"black\" stroke=\"black\" points=\"102.5,-36.87 99,-26.87 95.5,-36.87 102.5,-36.87\"/>\n",
245277
"</g>\n",
246-
"<!-- 0x117446c20 -->\n",
278+
"<!-- 0x135734520 -->\n",
247279
"<g id=\"node6\" class=\"node\">\n",
248-
"<title>0x117446c20</title>\n",
280+
"<title>0x135734520</title>\n",
249281
"<polygon fill=\"none\" stroke=\"black\" points=\"198,-25.2 144,-25.2 144,0 198,0 198,-25.2\"/>\n",
250282
"<text text-anchor=\"middle\" x=\"171\" y=\"-7.55\" font-family=\"Times,serif\" font-size=\"14.00\">2.00</text>\n",
251283
"</g>\n",
252-
"<!-- 0x117434058&#45;&gt;0x117446c20 -->\n",
284+
"<!-- 0x1357353a8&#45;&gt;0x135734520 -->\n",
253285
"<g id=\"edge5\" class=\"edge\">\n",
254-
"<title>0x117434058&#45;&gt;0x117446c20</title>\n",
286+
"<title>0x1357353a8&#45;&gt;0x135734520</title>\n",
255287
"<path fill=\"none\" stroke=\"black\" stroke-dasharray=\"5,2\" d=\"M171,-61.02C171,-53.49 171,-44.74 171,-36.82\"/>\n",
256288
"<polygon fill=\"black\" stroke=\"black\" points=\"174.5,-36.87 171,-26.87 167.5,-36.87 174.5,-36.87\"/>\n",
257289
"</g>\n",
258-
"<!-- 0x11743f4e0 -->\n",
290+
"<!-- 0x135734f90 -->\n",
259291
"<g id=\"node7\" class=\"node\">\n",
260-
"<title>0x11743f4e0</title>\n",
292+
"<title>0x135734f90</title>\n",
261293
"<polygon fill=\"none\" stroke=\"black\" points=\"270,-25.2 216,-25.2 216,0 270,0 270,-25.2\"/>\n",
262294
"<text text-anchor=\"middle\" x=\"243\" y=\"-7.55\" font-family=\"Times,serif\" font-size=\"14.00\">4.00</text>\n",
263295
"</g>\n",
264-
"<!-- 0x117434058&#45;&gt;0x11743f4e0 -->\n",
296+
"<!-- 0x1357353a8&#45;&gt;0x135734f90 -->\n",
265297
"<g id=\"edge6\" class=\"edge\">\n",
266-
"<title>0x117434058&#45;&gt;0x11743f4e0</title>\n",
298+
"<title>0x1357353a8&#45;&gt;0x135734f90</title>\n",
267299
"<path fill=\"none\" stroke=\"black\" d=\"M185.22,-66.74C195.68,-57.13 210.05,-43.91 221.84,-33.06\"/>\n",
268300
"<polygon fill=\"black\" stroke=\"black\" points=\"224.15,-35.69 229.14,-26.35 219.41,-30.54 224.15,-35.69\"/>\n",
269301
"</g>\n",
270302
"</g>\n",
271303
"</svg>\n"
272304
],
273305
"text/plain": [
274-
"<graphviz.sources.Source at 0x117fb2c00>"
306+
"<graphviz.sources.Source at 0x136ccbc80>"
275307
]
276308
},
277-
"execution_count": 9,
309+
"execution_count": 5,
278310
"metadata": {},
279311
"output_type": "execute_result"
280312
}
@@ -293,7 +325,7 @@
293325
},
294326
{
295327
"cell_type": "code",
296-
"execution_count": 10,
328+
"execution_count": 6,
297329
"metadata": {},
298330
"outputs": [
299331
{
@@ -333,7 +365,7 @@
333365
" 1 1 Leaf 4"
334366
]
335367
},
336-
"execution_count": 10,
368+
"execution_count": 6,
337369
"metadata": {},
338370
"output_type": "execute_result"
339371
}

0 commit comments

Comments
 (0)