| 1 | /* ---------------------------------------------------------------------------- |
| 2 | |
| 3 | * GTSAM Copyright 2010, Georgia Tech Research Corporation, |
| 4 | * Atlanta, Georgia 30332-0415 |
| 5 | * All Rights Reserved |
| 6 | * Authors: Frank Dellaert, et al. (see THANKS for the full author list) |
| 7 | |
| 8 | * See LICENSE for the license information |
| 9 | |
| 10 | * -------------------------------------------------------------------------- */ |
| 11 | |
| 12 | /** |
| 13 | * @file UGM_small.cpp |
| 14 | * @brief UGM (undirected graphical model) examples: small |
| 15 | * @author Frank Dellaert |
| 16 | * |
| 17 | * See http://www.di.ens.fr/~mschmidt/Software/UGM/small.html |
| 18 | */ |
| 19 | |
| 20 | #include <gtsam/base/Vector.h> |
| 21 | #include <gtsam/discrete/DiscreteFactorGraph.h> |
| 22 | #include <gtsam/discrete/DiscreteMarginals.h> |
| 23 | |
| 24 | using namespace std; |
| 25 | using namespace gtsam; |
| 26 | |
| 27 | int main(int argc, char** argv) { |
| 28 | |
| 29 | // We will assume 2-state variables, where, to conform to the "small" example |
| 30 | // we have 0 == "right answer" and 1 == "wrong answer" |
| 31 | size_t nrStates = 2; |
| 32 | |
| 33 | // define variables |
| 34 | DiscreteKey Cathy(1, nrStates), Heather(2, nrStates), Mark(3, nrStates), |
| 35 | Allison(4, nrStates); |
| 36 | |
| 37 | // create graph |
| 38 | DiscreteFactorGraph graph; |
| 39 | |
| 40 | // add node potentials |
| 41 | graph.add(args&: Cathy, args: "1 3" ); |
| 42 | graph.add(args&: Heather, args: "9 1" ); |
| 43 | graph.add(args&: Mark, args: "1 3" ); |
| 44 | graph.add(args&: Allison, args: "9 1" ); |
| 45 | |
| 46 | // add edge potentials |
| 47 | graph.add(args: Cathy & Heather, args: "2 1 1 2" ); |
| 48 | graph.add(args: Heather & Mark, args: "2 1 1 2" ); |
| 49 | graph.add(args: Mark & Allison, args: "2 1 1 2" ); |
| 50 | |
| 51 | // Print the UGM distribution |
| 52 | cout << "\nUGM distribution:" << endl; |
| 53 | auto allPosbValues = |
| 54 | DiscreteValues::CartesianProduct(keys: Cathy & Heather & Mark & Allison); |
| 55 | for (size_t i = 0; i < allPosbValues.size(); ++i) { |
| 56 | DiscreteFactor::Values values = allPosbValues[i]; |
| 57 | double prodPot = graph(values); |
| 58 | cout << values[Cathy.first] << " " << values[Heather.first] << " " |
| 59 | << values[Mark.first] << " " << values[Allison.first] << " :\t" |
| 60 | << prodPot << "\t" << prodPot / 3790 << endl; |
| 61 | } |
| 62 | |
| 63 | // "Decoding", i.e., configuration with largest value (MPE) |
| 64 | // Uses max-product |
| 65 | auto optimalDecoding = graph.optimize(); |
| 66 | GTSAM_PRINT(optimalDecoding); |
| 67 | |
| 68 | // "Inference" Computing marginals |
| 69 | cout << "\nComputing Node Marginals .." << endl; |
| 70 | DiscreteMarginals marginals(graph); |
| 71 | |
| 72 | Vector margProbs = marginals.marginalProbabilities(key: Cathy); |
| 73 | print(v: margProbs, s: "Cathy's Node Marginal:" ); |
| 74 | |
| 75 | margProbs = marginals.marginalProbabilities(key: Heather); |
| 76 | print(v: margProbs, s: "Heather's Node Marginal" ); |
| 77 | |
| 78 | margProbs = marginals.marginalProbabilities(key: Mark); |
| 79 | print(v: margProbs, s: "Mark's Node Marginal" ); |
| 80 | |
| 81 | margProbs = marginals.marginalProbabilities(key: Allison); |
| 82 | print(v: margProbs, s: "Allison's Node Marginal" ); |
| 83 | |
| 84 | return 0; |
| 85 | } |
| 86 | |
| 87 | |