gtsam/gtsam/discrete/Signature.cpp

194 lines
5.0 KiB
C++

/* ----------------------------------------------------------------------------
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
* Atlanta, Georgia 30332-0415
* All Rights Reserved
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
* See LICENSE for the license information
* -------------------------------------------------------------------------- */
/**
* @file Signature.cpp
* @brief signatures for conditional densities
* @author Frank Dellaert
* @date Feb 27, 2011
*/
#include <sstream>
#include "Signature.h"
#include <boost/spirit/include/qi.hpp> // for parsing
#include <boost/spirit/include/phoenix.hpp> // for qi::_val
namespace gtsam {
using namespace std;
namespace qi = boost::spirit::qi;
namespace ph = boost::phoenix;
// parser for strings of form "99/1 80/20" etc...
namespace parser {
typedef string::const_iterator It;
using boost::phoenix::val;
using boost::phoenix::ref;
using boost::phoenix::push_back;
// Special rows, true and false
Signature::Row F{1, 0}, T{0, 1};
// Special tables (inefficient, but do we care for user input?)
Signature::Table logic(bool ff, bool ft, bool tf, bool tt) {
Signature::Table t(4);
t[0] = ff ? T : F;
t[1] = ft ? T : F;
t[2] = tf ? T : F;
t[3] = tt ? T : F;
return t;
}
struct Grammar {
qi::rule<It, qi::space_type, Signature::Table()> table, or_, and_, rows;
qi::rule<It, Signature::Row()> true_, false_, row;
Grammar() {
table = or_ | and_ | rows;
or_ = qi::lit("OR")[qi::_val = logic(false, true, true, true)];
and_ = qi::lit("AND")[qi::_val = logic(false, false, false, true)];
rows = +(row | true_ | false_);
row = qi::double_ >> +("/" >> qi::double_);
true_ = qi::lit("T")[qi::_val = T];
false_ = qi::lit("F")[qi::_val = F];
}
} grammar;
} // \namespace parser
ostream& operator <<(ostream &os, const Signature::Row &row) {
os << row[0];
for (size_t i = 1; i < row.size(); i++)
os << " " << row[i];
return os;
}
ostream& operator <<(ostream &os, const Signature::Table &table) {
for (size_t i = 0; i < table.size(); i++)
os << table[i] << endl;
return os;
}
Signature::Signature(const DiscreteKey& key, const DiscreteKeys& parents,
const Table& table)
: key_(key), parents_(parents) {
operator=(table);
}
Signature::Signature(const DiscreteKey& key, const DiscreteKeys& parents,
const std::string& spec)
: key_(key), parents_(parents) {
operator=(spec);
}
Signature::Signature(const DiscreteKey& key) :
key_(key) {
}
DiscreteKeys Signature::discreteKeys() const {
DiscreteKeys keys;
keys.push_back(key_);
for (const DiscreteKey& key : parents_) keys.push_back(key);
return keys;
}
KeyVector Signature::indices() const {
KeyVector js;
js.push_back(key_.first);
for (const DiscreteKey& key : parents_) js.push_back(key.first);
return js;
}
vector<double> Signature::cpt() const {
vector<double> cpt;
if (table_) {
const size_t nrStates = table_->at(0).size();
for (size_t j = 0; j < nrStates; j++) {
for (const Row& row : *table_) {
assert(row.size() == nrStates);
cpt.push_back(row[j]);
}
}
}
return cpt;
}
Signature& Signature::operator,(const DiscreteKey& parent) {
parents_.push_back(parent);
return *this;
}
static void normalize(Signature::Row& row) {
double sum = 0;
for (size_t i = 0; i < row.size(); i++)
sum += row[i];
for (size_t i = 0; i < row.size(); i++)
row[i] /= sum;
}
Signature& Signature::operator=(const string& spec) {
spec_.reset(spec);
Table table;
parser::It f = spec.begin(), l = spec.end();
bool success =
qi::phrase_parse(f, l, parser::grammar.table, qi::space, table);
if (success) {
for (Row& row : table) normalize(row);
table_.reset(table);
}
return *this;
}
Signature& Signature::operator=(const Table& t) {
Table table = t;
for(Row& row: table)
normalize(row);
table_.reset(table);
return *this;
}
ostream& operator <<(ostream &os, const Signature &s) {
os << s.key_.first;
if (s.parents_.empty()) {
os << " % ";
} else {
os << " | " << s.parents_[0].first;
for (size_t i = 1; i < s.parents_.size(); i++)
os << " && " << s.parents_[i].first;
os << " = ";
}
os << (s.spec_ ? *s.spec_ : "no spec") << endl;
if (s.table_)
os << (*s.table_);
else
os << "spec could not be parsed" << endl;
return os;
}
Signature operator|(const DiscreteKey& key, const DiscreteKey& parent) {
Signature s(key);
return s, parent;
}
Signature operator%(const DiscreteKey& key, const string& parent) {
Signature s(key);
return s = parent;
}
Signature operator%(const DiscreteKey& key, const Signature::Table& parent) {
Signature s(key);
return s = parent;
}
} // namespace gtsam