Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

html renderers in discrete #1022

Merged
merged 10 commits into from
Jan 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion examples/UGM_small.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ int main(int argc, char** argv) {

// Print the UGM distribution
cout << "\nUGM distribution:" << endl;
auto allPosbValues = cartesianProduct(Cathy & Heather & Mark & Allison);
auto allPosbValues =
DiscreteValues::CartesianProduct(Cathy & Heather & Mark & Allison);
for (size_t i = 0; i < allPosbValues.size(); ++i) {
DiscreteFactor::Values values = allPosbValues[i];
double prodPot = graph(values);
Expand Down
65 changes: 31 additions & 34 deletions gtsam/discrete/Assignment.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,32 +19,30 @@
#pragma once

#include <iostream>
#include <vector>
#include <map>

#include <utility>
#include <vector>

namespace gtsam {

/**
* An assignment from labels to value index (size_t).
* Assigns to each label a value. Implemented as a simple map.
* A discrete factor takes an Assignment and returns a value.
*/
template<class L>
class Assignment: public std::map<L, size_t> {
public:
void print(const std::string& s = "Assignment: ") const {
std::cout << s << ": ";
for(const typename Assignment::value_type& keyValue: *this)
std::cout << "(" << keyValue.first << ", " << keyValue.second << ")";
std::cout << std::endl;
}

bool equals(const Assignment& other, double tol = 1e-9) const {
return (*this == other);
}
}; //Assignment
/**
* An assignment from labels to value index (size_t).
* Assigns to each label a value. Implemented as a simple map.
* A discrete factor takes an Assignment and returns a value.
*/
template <class L>
class Assignment : public std::map<L, size_t> {
public:
void print(const std::string& s = "Assignment: ") const {
std::cout << s << ": ";
for (const typename Assignment::value_type& keyValue : *this)
std::cout << "(" << keyValue.first << ", " << keyValue.second << ")";
std::cout << std::endl;
}

bool equals(const Assignment& other, double tol = 1e-9) const {
return (*this == other);
}

/**
* @brief Get Cartesian product consisting all possible configurations
Expand All @@ -58,29 +56,28 @@ namespace gtsam {
* variables with each having cardinalities 4, we get 4096 possible
* configurations!!
*/
template<typename L>
std::vector<Assignment<L> > cartesianProduct(
const std::vector<std::pair<L, size_t> >& keys) {
std::vector<Assignment<L> > allPossValues;
Assignment<L> values;
template <typename Derived = Assignment<L>>
static std::vector<Derived> CartesianProduct(
const std::vector<std::pair<L, size_t>>& keys) {
std::vector<Derived> allPossValues;
Derived values;
typedef std::pair<L, size_t> DiscreteKey;
for(const DiscreteKey& key: keys)
values[key.first] = 0; //Initialize from 0
for (const DiscreteKey& key : keys)
values[key.first] = 0; // Initialize from 0
while (1) {
allPossValues.push_back(values);
size_t j = 0;
for (j = 0; j < keys.size(); j++) {
L idx = keys[j].first;
values[idx]++;
if (values[idx] < keys[j].second)
break;
//Wrap condition
if (values[idx] < keys[j].second) break;
// Wrap condition
values[idx] = 0;
}
if (j == keys.size())
break;
if (j == keys.size()) break;
}
return allPossValues;
}
}; // Assignment

} // namespace gtsam
} // namespace gtsam
46 changes: 42 additions & 4 deletions gtsam/discrete/DecisionTreeFactor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <gtsam/base/FastSet.h>

#include <boost/make_shared.hpp>
#include <utility>

using namespace std;

Expand Down Expand Up @@ -150,9 +151,9 @@ namespace gtsam {
for (auto& key : keys()) {
pairs.emplace_back(key, cardinalities_.at(key));
}
// Reverse to make cartesianProduct output a more natural ordering.
// Reverse to make cartesian product output a more natural ordering.
std::vector<std::pair<Key, size_t>> rpairs(pairs.rbegin(), pairs.rend());
const auto assignments = cartesianProduct(rpairs);
const auto assignments = DiscreteValues::CartesianProduct(rpairs);

// Construct unordered_map with values
std::vector<std::pair<DiscreteValues, double>> result;
Expand Down Expand Up @@ -187,12 +188,13 @@ namespace gtsam {
return ADT::dot(keyFormatter, valueFormatter, showZero);
}

// Print out header.
/* ************************************************************************* */
string DecisionTreeFactor::markdown(const KeyFormatter& keyFormatter,
const Names& names) const {
stringstream ss;

// Print out header and construct argument for `cartesianProduct`.
// Print out header.
ss << "|";
for (auto& key : keys()) {
ss << keyFormatter(key) << "|";
Expand All @@ -211,18 +213,54 @@ namespace gtsam {
auto assignment = kv.first;
for (auto& key : keys()) {
size_t index = assignment.at(key);
ss << Translate(names, key, index) << "|";
ss << DiscreteValues::Translate(names, key, index) << "|";
}
ss << kv.second << "|\n";
}
return ss.str();
}

/* ************************************************************************ */
string DecisionTreeFactor::html(const KeyFormatter& keyFormatter,
const Names& names) const {
stringstream ss;

// Print out preamble.
ss << "<div>\n<table class='DecisionTreeFactor'>\n <thead>\n";

// Print out header row.
ss << " <tr>";
for (auto& key : keys()) {
ss << "<th>" << keyFormatter(key) << "</th>";
}
ss << "<th>value</th></tr>\n";

// Finish header and start body.
ss << " </thead>\n <tbody>\n";

// Print out all rows.
auto rows = enumerate();
for (const auto& kv : rows) {
ss << " <tr>";
auto assignment = kv.first;
for (auto& key : keys()) {
size_t index = assignment.at(key);
ss << "<th>" << DiscreteValues::Translate(names, key, index) << "</th>";
}
ss << "<td>" << kv.second << "</td>"; // value
ss << "</tr>\n";
}
ss << " </tbody>\n</table>\n</div>";
return ss.str();
}

/* ************************************************************************* */
DecisionTreeFactor::DecisionTreeFactor(const DiscreteKeys &keys, const vector<double> &table) :
DiscreteFactor(keys.indices()), AlgebraicDecisionTree<Key>(keys, table),
cardinalities_(keys.cardinalities()) {
}

/* ************************************************************************* */
DecisionTreeFactor::DecisionTreeFactor(const DiscreteKeys &keys, const string &table) :
DiscreteFactor(keys.indices()), AlgebraicDecisionTree<Key>(keys, table),
cardinalities_(keys.cardinalities()) {
Expand Down
10 changes: 10 additions & 0 deletions gtsam/discrete/DecisionTreeFactor.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,16 @@ namespace gtsam {
std::string markdown(const KeyFormatter& keyFormatter = DefaultKeyFormatter,
const Names& names = {}) const override;

/**
* @brief Render as html table
*
* @param keyFormatter GTSAM-style Key formatter.
* @param names optional, category names corresponding to choices.
* @return std::string a html string.
*/
std::string html(const KeyFormatter& keyFormatter = DefaultKeyFormatter,
const Names& names = {}) const override;

/// @}

};
Expand Down
17 changes: 15 additions & 2 deletions gtsam/discrete/DiscreteBayesNet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,29 @@ namespace gtsam {
return result;
}

/* ************************************************************************* */
/* *********************************************************************** */
std::string DiscreteBayesNet::markdown(
const KeyFormatter& keyFormatter,
const DiscreteFactor::Names& names) const {
using std::endl;
std::stringstream ss;
ss << "`DiscreteBayesNet` of size " << size() << endl << endl;
for(const DiscreteConditional::shared_ptr& conditional: *this)
for (const DiscreteConditional::shared_ptr& conditional : *this)
ss << conditional->markdown(keyFormatter, names) << endl;
return ss.str();
}

/* *********************************************************************** */
std::string DiscreteBayesNet::html(
const KeyFormatter& keyFormatter,
const DiscreteFactor::Names& names) const {
using std::endl;
std::stringstream ss;
ss << "<div><p><tt>DiscreteBayesNet</tt> of size " << size() << "</p>";
for (const DiscreteConditional::shared_ptr& conditional : *this)
ss << conditional->html(keyFormatter, names) << endl;
return ss.str();
}

/* ************************************************************************* */
} // namespace
21 changes: 14 additions & 7 deletions gtsam/discrete/DiscreteBayesNet.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,16 @@

#pragma once

#include <vector>
#include <map>
#include <boost/shared_ptr.hpp>
#include <gtsam/discrete/DiscreteConditional.h>
#include <gtsam/discrete/DiscretePrior.h>
#include <gtsam/inference/BayesNet.h>
#include <gtsam/inference/FactorGraph.h>
#include <gtsam/discrete/DiscretePrior.h>
#include <gtsam/discrete/DiscreteConditional.h>

#include <boost/shared_ptr.hpp>
#include <map>
#include <string>
#include <utility>
#include <vector>

namespace gtsam {

Expand Down Expand Up @@ -107,13 +110,17 @@ namespace gtsam {
/// @name Wrapper support
/// @{

/// Render as markdown table.
/// Render as markdown tables.
std::string markdown(const KeyFormatter& keyFormatter = DefaultKeyFormatter,
const DiscreteFactor::Names& names = {}) const;

/// Render as html tables.
std::string html(const KeyFormatter& keyFormatter = DefaultKeyFormatter,
const DiscreteFactor::Names& names = {}) const;

/// @}

private:
private:
/** Serialization function */
friend class boost::serialization::access;
template<class ARCHIVE>
Expand Down
18 changes: 18 additions & 0 deletions gtsam/discrete/DiscreteBayesTree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,23 @@ namespace gtsam {
return ss.str();
}

/* **************************************************************************/
std::string DiscreteBayesTree::html(
dellaert marked this conversation as resolved.
Show resolved Hide resolved
const KeyFormatter& keyFormatter,
const DiscreteFactor::Names& names) const {
using std::endl;
std::stringstream ss;
ss << "<div><p><tt>DiscreteBayesTree</tt> of size " << nodes_.size()
<< "</p>";
auto visitor = [&](const DiscreteBayesTreeClique::shared_ptr& clique,
size_t& indent) {
ss << clique->conditional()->html(keyFormatter, names);
return indent + 1;
};
size_t indent;
treeTraversal::DepthFirstForest(*this, indent, visitor);
return ss.str();
}

/* **************************************************************************/
} // namespace gtsam
6 changes: 5 additions & 1 deletion gtsam/discrete/DiscreteBayesTree.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,14 @@ class GTSAM_EXPORT DiscreteBayesTree
/// @name Wrapper support
/// @{

/// Render as markdown table.
/// Render as markdown tables.
std::string markdown(const KeyFormatter& keyFormatter = DefaultKeyFormatter,
const DiscreteFactor::Names& names = {}) const;

/// Render as html tables.
std::string html(const KeyFormatter& keyFormatter = DefaultKeyFormatter,
const DiscreteFactor::Names& names = {}) const;

/// @}
};

Expand Down
Loading