| 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_chain.cpp |
| 14 | * @brief UGM (undirected graphical model) examples: chain |
| 15 | * @author Frank Dellaert |
| 16 | * @author Abhijit Kundu |
| 17 | * |
| 18 | * See http://www.di.ens.fr/~mschmidt/Software/UGM/chain.html |
| 19 | * for more explanation. This code demos the same example using GTSAM. |
| 20 | */ |
| 21 | |
| 22 | #include <gtsam/base/timing.h> |
| 23 | #include <gtsam/discrete/DiscreteFactorGraph.h> |
| 24 | #include <gtsam/discrete/DiscreteMarginals.h> |
| 25 | |
| 26 | #include <iomanip> |
| 27 | |
| 28 | using namespace std; |
| 29 | using namespace gtsam; |
| 30 | |
| 31 | int main(int argc, char** argv) { |
| 32 | // Set Number of Nodes in the Graph |
| 33 | const int nrNodes = 60; |
| 34 | |
| 35 | // Each node takes 1 of 7 possible states denoted by 0-6 in following order: |
| 36 | // ["VideoGames" "Industry" "GradSchool" "VideoGames(with PhD)" |
| 37 | // "Industry(with PhD)" "Academia" "Deceased"] |
| 38 | const size_t nrStates = 7; |
| 39 | |
| 40 | // define variables |
| 41 | vector<DiscreteKey> nodes; |
| 42 | for (int i = 0; i < nrNodes; i++) { |
| 43 | DiscreteKey dk(i, nrStates); |
| 44 | nodes.push_back(x: dk); |
| 45 | } |
| 46 | |
| 47 | // create graph |
| 48 | DiscreteFactorGraph graph; |
| 49 | |
| 50 | // add node potentials |
| 51 | graph.add(args&: nodes[0], args: ".3 .6 .1 0 0 0 0" ); |
| 52 | for (int i = 1; i < nrNodes; i++) graph.add(args&: nodes[i], args: "1 1 1 1 1 1 1" ); |
| 53 | |
| 54 | const std::string edgePotential = |
| 55 | ".08 .9 .01 0 0 0 .01 " |
| 56 | ".03 .95 .01 0 0 0 .01 " |
| 57 | ".06 .06 .75 .05 .05 .02 .01 " |
| 58 | "0 0 0 .3 .6 .09 .01 " |
| 59 | "0 0 0 .02 .95 .02 .01 " |
| 60 | "0 0 0 .01 .01 .97 .01 " |
| 61 | "0 0 0 0 0 0 1" ; |
| 62 | |
| 63 | // add edge potentials |
| 64 | for (int i = 0; i < nrNodes - 1; i++) |
| 65 | graph.add(args: nodes[i] & nodes[i + 1], args: edgePotential); |
| 66 | |
| 67 | cout << "Created Factor Graph with " << nrNodes << " variable nodes and " |
| 68 | << graph.size() << " factors (Unary+Edge)." ; |
| 69 | |
| 70 | // "Decoding", i.e., configuration with largest value |
| 71 | // Uses max-product. |
| 72 | auto optimalDecoding = graph.optimize(); |
| 73 | optimalDecoding.print(s: "\nMost Probable Explanation (optimalDecoding)\n" ); |
| 74 | |
| 75 | // "Inference" Computing marginals for each node |
| 76 | // Here we'll make use of DiscreteMarginals class, which makes use of |
| 77 | // bayes-tree based shortcut evaluation of marginals |
| 78 | DiscreteMarginals marginals(graph); |
| 79 | |
| 80 | cout << "\nComputing Node Marginals ..(BayesTree based)" << endl; |
| 81 | gttic_(Multifrontal); |
| 82 | for (vector<DiscreteKey>::iterator it = nodes.begin(); it != nodes.end(); |
| 83 | ++it) { |
| 84 | // Compute the marginal |
| 85 | Vector margProbs = marginals.marginalProbabilities(key: *it); |
| 86 | |
| 87 | // Print the marginals |
| 88 | cout << "Node#" << setw(4) << it->first << " : " ; |
| 89 | print(v: margProbs); |
| 90 | } |
| 91 | gttoc_(Multifrontal); |
| 92 | |
| 93 | tictoc_print_(); |
| 94 | return 0; |
| 95 | } |
| 96 | |