More sophisticated markdown

release/4.3a0
Frank Dellaert 2021-12-24 11:00:28 -05:00
parent 791e04e9f3
commit 839679eb7d
2 changed files with 86 additions and 47 deletions

View File

@ -227,41 +227,66 @@ std::string DiscreteConditional::_repr_markdown_(
const KeyFormatter& keyFormatter) const { const KeyFormatter& keyFormatter) const {
std::stringstream ss; std::stringstream ss;
// Print out signature.
ss << " $P(";
for(Key key: frontals())
ss << keyFormatter(key);
if (nrParents() > 0)
ss << "|";
bool first = true;
for (Key parent : parents()) {
if (!first) ss << ",";
ss << keyFormatter(parent);
first = false;
}
ss << ")$:" << std::endl;
// Print out header and construct argument for `cartesianProduct`. // Print out header and construct argument for `cartesianProduct`.
// TODO(dellaert): examine why we can't use "for (auto key: frontals())"
std::vector<std::pair<Key, size_t>> pairs; std::vector<std::pair<Key, size_t>> pairs;
ss << "|"; ss << "|";
const_iterator it; const_iterator it;
for (it = beginParents(); it != endParents(); ++it) { for(Key parent: parents()) {
auto key = *it; ss << keyFormatter(parent) << "|";
ss << keyFormatter(key) << "|"; pairs.emplace_back(parent, cardinalities_.at(parent));
pairs.emplace_back(key, cardinalities_.at(key));
} }
for (it = beginFrontals(); it != endFrontals(); ++it) {
auto key = *it; size_t n = 1;
ss << keyFormatter(key) << "|"; for(Key key: frontals()) {
pairs.emplace_back(key, cardinalities_.at(key)); size_t k = cardinalities_.at(key);
pairs.emplace_back(key, k);
n *= k;
} }
ss << "value|\n"; size_t nrParents = size() - nrFrontals_;
std::vector<std::pair<Key, size_t>> slatnorf(pairs.rbegin(),
pairs.rend() - nrParents);
const auto frontal_assignments = cartesianProduct(slatnorf);
for (const auto& a : frontal_assignments) {
for (it = beginFrontals(); it != endFrontals(); ++it) ss << a.at(*it);
ss << "|";
}
ss << "\n";
// Print out separator with alignment hints. // Print out separator with alignment hints.
ss << "|"; ss << "|";
for (size_t j = 0; j < size(); j++) ss << ":-:|"; for (size_t j = 0; j < nrParents + n; j++) ss << ":-:|";
ss << ":-:|\n"; ss << "\n";
// Print out all rows. // Print out all rows.
std::vector<std::pair<Key, size_t>> rpairs(pairs.rbegin(), pairs.rend()); std::vector<std::pair<Key, size_t>> rpairs(pairs.rbegin(), pairs.rend());
const auto assignments = cartesianProduct(rpairs); const auto assignments = cartesianProduct(rpairs);
size_t count = 0;
for (const auto& a : assignments) { for (const auto& a : assignments) {
if (count == 0) {
ss << "|"; ss << "|";
for (it = beginParents(); it != endParents(); ++it) ss << a.at(*it) << "|"; for (it = beginParents(); it != endParents(); ++it)
for (it = beginFrontals(); it != endFrontals(); ++it) ss << a.at(*it) << "|";
ss << "*" << a.at(*it) << "*|"; }
ss << operator()(a) << "|\n"; ss << operator()(a) << "|";
count = (count + 1) % n;
if (count == 0) ss << "\n";
} }
return ss.str(); return ss.str();
} }
/* ******************************************************************************** /* ************************************************************************* */
*/
}// namespace } // namespace gtsam

View File

@ -24,6 +24,7 @@ using namespace boost::assign;
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
#include <gtsam/discrete/DecisionTreeFactor.h> #include <gtsam/discrete/DecisionTreeFactor.h>
#include <gtsam/discrete/DiscreteConditional.h> #include <gtsam/discrete/DiscreteConditional.h>
#include <gtsam/inference/Symbol.h>
using namespace std; using namespace std;
using namespace gtsam; using namespace gtsam;
@ -107,40 +108,53 @@ TEST(DiscreteConditional, Combine) {
} }
/* ************************************************************************* */ /* ************************************************************************* */
// TEST(DiscreteConditional, Combine2) { // Check markdown representation looks as expected, no parents.
// DiscreteKey A(0, 3), B(1, 2), C(2, 2); TEST(DiscreteConditional, markdown_prior) {
// vector<DiscreteConditional::shared_ptr> c; DiscreteKey A(Symbol('x', 1), 2);
// auto P = {B, C}; DiscreteConditional conditional(A % "1/3");
// c.push_back(boost::make_shared<DiscreteConditional>(A, P, "1/2 2/1 1/2 2/1")); string expected =
// c.push_back(boost::make_shared<DiscreteConditional>(B | C = "1/2")); " $P(x1)$:\n"
// auto actual = DiscreteConditional::Combine(c.begin(), c.end()); "|0|1|\n"
// GTSAM_PRINT(*actual); "|:-:|:-:|\n"
// } "|0.25|0.75|\n";
string actual = conditional._repr_markdown_();
EXPECT(actual == expected);
}
/* ************************************************************************* */ /* ************************************************************************* */
// Check markdown representation looks as expected. // Check markdown representation looks as expected, multivalued.
TEST(DiscreteConditional, markdown_multivalued) {
DiscreteKey A(Symbol('a', 1), 3), B(Symbol('b', 1), 5);
DiscreteConditional conditional(
A | B = "2/88/10 2/20/78 33/33/34 33/33/34 95/2/3");
string expected =
" $P(a1|b1)$:\n"
"|b1|0|1|2|\n"
"|:-:|:-:|:-:|:-:|\n"
"|0|0.02|0.88|0.1|\n"
"|1|0.02|0.2|0.78|\n"
"|2|0.33|0.33|0.34|\n"
"|3|0.33|0.33|0.34|\n"
"|4|0.95|0.02|0.03|\n";
string actual = conditional._repr_markdown_();
EXPECT(actual == expected);
}
/* ************************************************************************* */
// Check markdown representation looks as expected, two parents.
TEST(DiscreteConditional, markdown) { TEST(DiscreteConditional, markdown) {
DiscreteKey A(2, 2), B(1, 2), C(0, 3); DiscreteKey A(2, 2), B(1, 2), C(0, 3);
DiscreteConditional conditional(A, {B, C}, "0/1 1/3 1/1 3/1 0/1 1/0"); DiscreteConditional conditional(A, {B, C}, "0/1 1/3 1/1 3/1 0/1 1/0");
EXPECT_LONGS_EQUAL(A.first, *(conditional.beginFrontals()));
EXPECT_LONGS_EQUAL(B.first, *(conditional.beginParents()));
EXPECT(conditional.endParents() == conditional.end());
EXPECT(conditional.endFrontals() == conditional.beginParents());
string expected = string expected =
"|B|C|A|value|\n" " $P(A|B,C)$:\n"
"|B|C|0|1|\n"
"|:-:|:-:|:-:|:-:|\n" "|:-:|:-:|:-:|:-:|\n"
"|0|0|*0*|0|\n" "|0|0|0|1|\n"
"|0|0|*1*|1|\n" "|0|1|0.25|0.75|\n"
"|0|1|*0*|0.25|\n" "|0|2|0.5|0.5|\n"
"|0|1|*1*|0.75|\n" "|1|0|0.75|0.25|\n"
"|0|2|*0*|0.5|\n" "|1|1|0|1|\n"
"|0|2|*1*|0.5|\n" "|1|2|1|0|\n";
"|1|0|*0*|0.75|\n"
"|1|0|*1*|0.25|\n"
"|1|1|*0*|0|\n"
"|1|1|*1*|1|\n"
"|1|2|*0*|1|\n"
"|1|2|*1*|0|\n";
vector<string> names{"C", "B", "A"}; vector<string> names{"C", "B", "A"};
auto formatter = [names](Key key) { return names[key]; }; auto formatter = [names](Key key) { return names[key]; };
string actual = conditional._repr_markdown_(formatter); string actual = conditional._repr_markdown_(formatter);