All std::map<Symbol,T> are now SymbolMap<T>, which is just a thin wrapper around std::map. at(Key) is used instead of first checking with find when an exception should be thrown for non-existent keys. This does not change any behavior or timing currently. This check-in also includes some functions in BayesTree for gathering clique statistics.
parent
41a6e64bbb
commit
5367e5a157
|
|
@ -6,6 +6,8 @@
|
|||
* @author Viorela Ila
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/assign/std/list.hpp> // for operator +=
|
||||
using namespace boost::assign;
|
||||
|
|
@ -65,6 +67,51 @@ namespace gtsam {
|
|||
child->printTree(indent+" ");
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
template<class Conditional>
|
||||
typename BayesTree<Conditional>::CliqueData
|
||||
BayesTree<Conditional>::getCliqueData() const {
|
||||
CliqueData data;
|
||||
getCliqueData(data, root_);
|
||||
return data;
|
||||
}
|
||||
|
||||
template<class Conditional>
|
||||
void BayesTree<Conditional>::getCliqueData(CliqueData& data,
|
||||
BayesTree<Conditional>::sharedClique clique) const {
|
||||
data.conditionalSizes.push_back(clique->conditionals_.size());
|
||||
data.separatorSizes.push_back(clique->separator_.size());
|
||||
BOOST_FOREACH(sharedClique c, clique->children_) {
|
||||
getCliqueData(data, c);
|
||||
}
|
||||
}
|
||||
|
||||
template<class Conditional>
|
||||
typename BayesTree<Conditional>::CliqueStats
|
||||
BayesTree<Conditional>::CliqueData::getStats() const {
|
||||
CliqueStats stats;
|
||||
|
||||
double sum = 0.0;
|
||||
size_t max = 0;
|
||||
BOOST_FOREACH(size_t s, conditionalSizes) {
|
||||
sum += (double)s;
|
||||
if(s > max) max = s;
|
||||
}
|
||||
stats.avgConditionalSize = sum / (double)conditionalSizes.size();
|
||||
stats.maxConditionalSize = max;
|
||||
|
||||
sum = 0.0;
|
||||
max = 1;
|
||||
BOOST_FOREACH(size_t s, separatorSizes) {
|
||||
sum += (double)s;
|
||||
if(s > max) max = s;
|
||||
}
|
||||
stats.avgSeparatorSize = sum / (double)separatorSizes.size();
|
||||
stats.maxSeparatorSize = max;
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
// The shortcut density is a conditional P(S|R) of the separator of this
|
||||
// clique on the root. We can compute it recursively from the parent shortcut
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <boost/serialization/map.hpp>
|
||||
|
|
@ -47,6 +46,8 @@ namespace gtsam {
|
|||
std::list<shared_ptr> children_;
|
||||
std::list<Symbol> separator_; /** separator keys */
|
||||
|
||||
friend class BayesTree<Conditional>;
|
||||
|
||||
//* Constructor */
|
||||
Clique(const sharedConditional& conditional);
|
||||
|
||||
|
|
@ -96,7 +97,7 @@ namespace gtsam {
|
|||
private:
|
||||
|
||||
/** Map from keys to Clique */
|
||||
typedef std::map<Symbol, sharedClique> Nodes;
|
||||
typedef SymbolMap<sharedClique> Nodes;
|
||||
Nodes nodes_;
|
||||
|
||||
/** Root clique */
|
||||
|
|
@ -153,13 +154,26 @@ namespace gtsam {
|
|||
|
||||
/** find the clique to which key belongs */
|
||||
sharedClique operator[](const Symbol& key) const {
|
||||
typename Nodes::const_iterator it = nodes_.find(key);
|
||||
if (it == nodes_.end()) throw(std::invalid_argument(
|
||||
"BayesTree::operator['" + (std::string)key + "']: key not found"));
|
||||
sharedClique clique = it->second;
|
||||
return clique;
|
||||
return nodes_.at(key);
|
||||
}
|
||||
|
||||
/** clique statistics */
|
||||
struct CliqueStats {
|
||||
double avgConditionalSize;
|
||||
std::size_t maxConditionalSize;
|
||||
double avgSeparatorSize;
|
||||
std::size_t maxSeparatorSize;
|
||||
};
|
||||
struct CliqueData {
|
||||
std::vector<std::size_t> conditionalSizes;
|
||||
std::vector<std::size_t> separatorSizes;
|
||||
CliqueStats getStats() const;
|
||||
};
|
||||
CliqueData getCliqueData() const;
|
||||
private:
|
||||
void getCliqueData(CliqueData& stats, sharedClique clique) const;
|
||||
public:
|
||||
|
||||
/** return marginal on any variable */
|
||||
template<class Factor>
|
||||
FactorGraph<Factor> marginal(const Symbol& key) const;
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include <boost/serialization/vector.hpp>
|
||||
#include "Conditional.h"
|
||||
#include "Key.h"
|
||||
#include "SymbolMap.h"
|
||||
|
||||
namespace gtsam {
|
||||
|
||||
|
|
@ -60,13 +61,13 @@ namespace gtsam {
|
|||
cpt_.insert(cpt_.end(),cpt.begin(),cpt.end()); // p(x|parents)
|
||||
}
|
||||
|
||||
double probability( std::map<Symbol,bool> config) {
|
||||
double probability( SymbolMap<bool> config) {
|
||||
int index = 0, count = 1;
|
||||
BOOST_FOREACH(const Symbol& parent, parents_){
|
||||
index += count*(int)(config[parent]);
|
||||
count = count << 1;
|
||||
}
|
||||
if( config.find(key_)->second )
|
||||
if( config.at(key_) )
|
||||
index += count;
|
||||
return cpt_[index];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,17 +10,16 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <boost/utility.hpp> // for noncopyable
|
||||
#include "Testable.h"
|
||||
#include "Key.h"
|
||||
#include "SymbolMap.h"
|
||||
|
||||
namespace gtsam {
|
||||
|
||||
/** A map from key to dimension, useful in various contexts */
|
||||
typedef std::map<Symbol,int> Dimensions;
|
||||
typedef SymbolMap<int> Dimensions;
|
||||
|
||||
/**
|
||||
* A simple factor class to use in a factor graph.
|
||||
|
|
|
|||
|
|
@ -119,14 +119,7 @@ void FactorGraph<Factor>::replace(int index, sharedFactor factor) {
|
|||
if(factors_[index] != NULL) {
|
||||
// Remove this factor from its variables' index lists
|
||||
BOOST_FOREACH(const Symbol& key, factor->keys()) {
|
||||
Indices::iterator indices = indices_.find(key);
|
||||
if(indices != indices_.end()) {
|
||||
indices->second.remove(index);
|
||||
} else {
|
||||
throw invalid_argument(boost::str(boost::format(
|
||||
"Factor graph inconsistency! Factor %d involves variable %s but "
|
||||
"is missing from its factor index list.") % index % (std::string)key));
|
||||
}
|
||||
indices_.at(key).remove(index);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -228,8 +221,7 @@ Ordering FactorGraph<Factor>::getOrdering() const {
|
|||
/* ************************************************************************* */
|
||||
template<class Factor>
|
||||
list<int> FactorGraph<Factor>::factors(const Symbol& key) const {
|
||||
Indices::const_iterator it = indices_.find(key);
|
||||
return it->second;
|
||||
return indices_.at(key);
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
|
@ -240,15 +232,8 @@ vector<boost::shared_ptr<Factor> >
|
|||
FactorGraph<Factor>::findAndRemoveFactors(const Symbol& key) {
|
||||
vector<sharedFactor> found;
|
||||
|
||||
Indices::iterator it = indices_.find(key);
|
||||
if (it == indices_.end())
|
||||
throw(invalid_argument
|
||||
("FactorGraph::findAndRemoveFactors invalid key: " + (std::string)key));
|
||||
|
||||
list<int> *indices_ptr; // pointer to indices list in indices_ map
|
||||
indices_ptr = &(it->second);
|
||||
|
||||
BOOST_FOREACH(int i, *indices_ptr) {
|
||||
const list<int>& indices = indices_.at(key);
|
||||
BOOST_FOREACH(const int& i, indices) {
|
||||
if(factors_[i] == NULL) continue; // skip NULL factors
|
||||
found.push_back(factors_[i]); // add to found
|
||||
remove(i); // set factor to NULL.
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#include "BayesNet.h"
|
||||
#include "graph.h"
|
||||
#include "Key.h"
|
||||
#include "SymbolMap.h"
|
||||
|
||||
namespace gtsam {
|
||||
|
||||
|
|
@ -42,7 +43,7 @@ namespace gtsam {
|
|||
std::vector<sharedFactor> factors_;
|
||||
|
||||
/** For each variable a list of factor indices connected to it */
|
||||
typedef std::map<Symbol, std::list<int> > Indices;
|
||||
typedef SymbolMap<std::list<int> > Indices;
|
||||
Indices indices_;
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include "GaussianBayesNet.h"
|
||||
#include "VectorConfig.h"
|
||||
#include "SymbolMap.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace gtsam;
|
||||
|
|
@ -144,7 +145,7 @@ pair<Matrix,Vector> matrix(const GaussianBayesNet& bn) {
|
|||
|
||||
// add the dimensions of all variables to get matrix dimension
|
||||
// and at the same time create a mapping from keys to indices
|
||||
size_t N=0; map<Symbol,size_t> mapping;
|
||||
size_t N=0; SymbolMap<size_t> mapping;
|
||||
BOOST_FOREACH(GaussianConditional::shared_ptr cg,bn) {
|
||||
mapping.insert(make_pair(cg->key(),N));
|
||||
N += cg->dim();
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ GaussianConditional::GaussianConditional(const Symbol& key, Vector d, Matrix R,
|
|||
|
||||
/* ************************************************************************* */
|
||||
GaussianConditional::GaussianConditional(const Symbol& key,
|
||||
const Vector& d, const Matrix& R, const map<Symbol, Matrix>& parents, Vector sigmas) :
|
||||
const Vector& d, const Matrix& R, const SymbolMap<Matrix>& parents, Vector sigmas) :
|
||||
Conditional (key), R_(R),sigmas_(sigmas), d_(d), parents_(parents) {
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#include "VectorConfig.h"
|
||||
#include "Matrix.h"
|
||||
#include "Key.h"
|
||||
#include "SymbolMap.h"
|
||||
|
||||
namespace gtsam {
|
||||
|
||||
|
|
@ -32,7 +33,7 @@ class Ordering;
|
|||
class GaussianConditional : public Conditional {
|
||||
|
||||
public:
|
||||
typedef std::map<Symbol, Matrix> Parents;
|
||||
typedef SymbolMap<Matrix> Parents;
|
||||
typedef Parents::const_iterator const_iterator;
|
||||
typedef boost::shared_ptr<GaussianConditional> shared_ptr;
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ typedef pair<Symbol,Matrix> NamedMatrix;
|
|||
GaussianFactor::GaussianFactor(const boost::shared_ptr<GaussianConditional>& cg) :
|
||||
b_(cg->get_d()) {
|
||||
As_.insert(make_pair(cg->key(), cg->get_R()));
|
||||
std::map<Symbol, Matrix>::const_iterator it = cg->parentsBegin();
|
||||
SymbolMap<Matrix>::const_iterator it = cg->parentsBegin();
|
||||
for (; it != cg->parentsEnd(); it++) {
|
||||
const Symbol& j = it->first;
|
||||
const Matrix& Aj = it->second;
|
||||
|
|
@ -247,9 +247,7 @@ GaussianFactor::sparse(const Dimensions& columnIndices) const {
|
|||
// iterate over all matrices in the factor
|
||||
FOREACH_PAIR( key, Aj, As_) {
|
||||
// find first column index for this key
|
||||
// TODO: check if end() and throw exception if not found
|
||||
Dimensions::const_iterator it = columnIndices.find(*key);
|
||||
int column_start = it->second;
|
||||
int column_start = columnIndices.at(*key);
|
||||
for (size_t i = 0; i < Aj->size1(); i++) {
|
||||
double sigma_i = model_->sigma(i);
|
||||
for (size_t j = 0; j < Aj->size2(); j++)
|
||||
|
|
|
|||
|
|
@ -13,11 +13,13 @@
|
|||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/serialization/map.hpp>
|
||||
#include <list>
|
||||
#include <set>
|
||||
|
||||
#include "Factor.h"
|
||||
#include "Matrix.h"
|
||||
#include "VectorConfig.h"
|
||||
#include "NoiseModel.h"
|
||||
#include "SymbolMap.h"
|
||||
|
||||
namespace gtsam {
|
||||
|
||||
|
|
@ -33,13 +35,13 @@ class GaussianFactor: boost::noncopyable, public Factor<VectorConfig> {
|
|||
public:
|
||||
|
||||
typedef boost::shared_ptr<GaussianFactor> shared_ptr;
|
||||
typedef std::map<Symbol, Matrix>::iterator iterator;
|
||||
typedef std::map<Symbol, Matrix>::const_iterator const_iterator;
|
||||
typedef SymbolMap<Matrix>::iterator iterator;
|
||||
typedef SymbolMap<Matrix>::const_iterator const_iterator;
|
||||
|
||||
protected:
|
||||
|
||||
sharedDiagonal model_; // Gaussian noise model with diagonal covariance matrix
|
||||
std::map<Symbol, Matrix> As_; // linear matrices
|
||||
SymbolMap<Matrix> As_; // linear matrices
|
||||
Vector b_; // right-hand-side
|
||||
|
||||
public:
|
||||
|
|
@ -132,10 +134,7 @@ public:
|
|||
* O(log n)
|
||||
*/
|
||||
const Matrix& get_A(const Symbol& key) const {
|
||||
const_iterator it = As_.find(key);
|
||||
if (it == As_.end())
|
||||
throw(std::invalid_argument("GaussianFactor::[] invalid key: " + (std::string)key));
|
||||
return it->second;
|
||||
return As_.at(key);
|
||||
}
|
||||
|
||||
/** operator[] syntax for get */
|
||||
|
|
|
|||
|
|
@ -21,10 +21,11 @@
|
|||
#include "BayesNet.h"
|
||||
#include "BayesTree.h"
|
||||
#include "Key.h"
|
||||
#include "SymbolMap.h"
|
||||
|
||||
namespace gtsam {
|
||||
|
||||
typedef std::map<Symbol, GaussianFactor::shared_ptr> CachedFactors;
|
||||
typedef SymbolMap<GaussianFactor::shared_ptr> CachedFactors;
|
||||
|
||||
template<class Conditional, class Config>
|
||||
class ISAM2: public BayesTree<Conditional> {
|
||||
|
|
@ -70,6 +71,8 @@ namespace gtsam {
|
|||
|
||||
const Config estimate() const {return theta_;}
|
||||
|
||||
const std::list<Symbol>& getMarked() const { return marked_; }
|
||||
|
||||
private:
|
||||
|
||||
boost::shared_ptr<FactorGraph<NonlinearFactor<Config> > > getAffectedFactors(const std::list<Symbol>& keys) const;
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ testSubgraphPreconditioner_SOURCES = testSubgraphPreconditioner.cpp
|
|||
testSubgraphPreconditioner_LDADD = libgtsam.la
|
||||
|
||||
# Nonlinear inference
|
||||
headers += Key.h NonlinearFactorGraph.h NonlinearFactorGraph-inl.h
|
||||
headers += Key.h SymbolMap.h NonlinearFactorGraph.h NonlinearFactorGraph-inl.h
|
||||
headers += NonlinearOptimizer.h NonlinearOptimizer-inl.h
|
||||
headers += NonlinearFactor.h
|
||||
check_PROGRAMS += testNonlinearFactor testNonlinearFactorGraph testNonlinearOptimizer testKey
|
||||
|
|
@ -238,7 +238,7 @@ testVSLAMConfig_LDADD = libgtsam.la
|
|||
headers += $(sources:.cpp=.h)
|
||||
|
||||
# Timing tests
|
||||
noinst_PROGRAMS = timeGaussianFactor timeGaussianFactorGraph timeRot3 timeMatrix
|
||||
noinst_PROGRAMS = timeGaussianFactor timeGaussianFactorGraph timeRot3 timeMatrix timeSymbolMaps
|
||||
timeRot3_SOURCES = timeRot3.cpp
|
||||
timeRot3_LDADD = libgtsam.la
|
||||
timeGaussianFactor_SOURCES = timeGaussianFactor.cpp
|
||||
|
|
@ -247,6 +247,8 @@ timeGaussianFactorGraph_SOURCES = timeGaussianFactorGraph.cpp
|
|||
timeGaussianFactorGraph_LDADD = libgtsam.la
|
||||
timeMatrix_SOURCES = timeMatrix.cpp
|
||||
timeMatrix_LDADD = libgtsam.la
|
||||
timeSymbolMaps_SOURCES = timeSymbolMaps.cpp
|
||||
timeSymbolMaps_LDADD = libgtsam.la
|
||||
|
||||
# create both dynamic and static libraries
|
||||
AM_CXXFLAGS = -I$(boost) -fPIC
|
||||
|
|
|
|||
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* SymbolMap.h
|
||||
*
|
||||
* Created on: Jan 20, 2010
|
||||
* Author: richard
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
//#define GTSAM_SYMBOL_HASH
|
||||
#define GTSAM_SYMBOL_BINARY
|
||||
#define GTSAM_SYMBOL_SPECIAL
|
||||
|
||||
#include "Key.h"
|
||||
|
||||
#include <map>
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
|
||||
namespace gtsam {
|
||||
|
||||
#ifdef GTSAM_SYMBOL_BINARY
|
||||
template<class T>
|
||||
class SymbolMap : public std::map<Symbol, T> {
|
||||
private:
|
||||
typedef std::map<Symbol, T> Base;
|
||||
public:
|
||||
SymbolMap() : std::map<Symbol, T>() {}
|
||||
|
||||
const T& at(const Symbol& key) const {
|
||||
typename Base::const_iterator it = Base::find(key);
|
||||
if (it == Base::end())
|
||||
throw(std::invalid_argument("SymbolMap::[] invalid key: " + (std::string)key));
|
||||
return it->second;
|
||||
}
|
||||
|
||||
T& at(const Symbol& key) {
|
||||
typename Base::iterator it = Base::find(key);
|
||||
if (it == Base::end())
|
||||
throw(std::invalid_argument("SymbolMap::[] invalid key: " + (std::string)key));
|
||||
return it->second;
|
||||
}
|
||||
|
||||
//void find(void);
|
||||
|
||||
//void clear() { throw std::runtime_error("Clear should not be used!"); }
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef GTSAM_SYMBOL_HASH
|
||||
struct SymbolHash : public std::unary_function<Symbol, std::size_t> {
|
||||
std::size_t operator()(Symbol const& x) const {
|
||||
std::size_t seed = 0;
|
||||
boost::hash_combine(seed, x.chr());
|
||||
boost::hash_combine(seed, x.index());
|
||||
return ((size_t(x.chr()) << 24) & x.index());
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class SymbolMap : public boost::unordered_map<Symbol, T, SymbolHash> {
|
||||
public:
|
||||
SymbolMap() : boost::unordered_map<Symbol, T, SymbolHash>() {}
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef GTSAM_SYMBOL_SPECIAL
|
||||
template<class T>
|
||||
class FastSymbolMap {
|
||||
private:
|
||||
typedef std::vector<std::vector<T> > Map;
|
||||
typedef std::vector<T> Vec;
|
||||
|
||||
Map values_;
|
||||
|
||||
public:
|
||||
typedef std::pair<Symbol, T> value_type;
|
||||
|
||||
FastSymbolMap() {
|
||||
values_.resize(256);
|
||||
values_[size_t('x')].reserve(10000);
|
||||
values_[size_t('l')].reserve(1000);
|
||||
}
|
||||
|
||||
const T& at(const Symbol& key) const {
|
||||
// typename Map::const_iterator it = values_.find(key.chr());
|
||||
// if(it != values_.end())
|
||||
// return it->second.at(key.index());
|
||||
// else
|
||||
// throw std::invalid_argument("Key " + (std::string)key + " not present");
|
||||
return values_.at(size_t(key.chr())).at(key.index());
|
||||
}
|
||||
|
||||
void insert(const value_type& val) {
|
||||
Vec& vec(values_[size_t(val.first.chr())]);
|
||||
if(val.first.index() >= vec.size()) {
|
||||
vec.reserve(val.first.index()+1);
|
||||
vec.resize(val.first.index());
|
||||
vec.push_back(val.second);
|
||||
} else
|
||||
vec[val.first.index()] = val.second;
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void erase(const Symbol& key) {
|
||||
|
||||
}
|
||||
|
||||
void clear() {
|
||||
throw std::runtime_error("Can't clear a FastSymbolMap");
|
||||
}
|
||||
|
||||
// typedef std::pair<Symbol, T> value_type;
|
||||
//
|
||||
// class iterator {
|
||||
// typename Map::iterator map_it_;
|
||||
// typename Map::iterator map_end_;
|
||||
// typename Vec::iterator vec_it_;
|
||||
// public:
|
||||
// iterator() {}
|
||||
// iterator(const iterator& it) : map_it_(it.map_it_), vec_it_(it.vec_it_) {}
|
||||
// bool operator==(const iterator& it);// { return map_it_==it.map_it_ && vec_it_==it.vec_it_; }
|
||||
// bool operator!=(const iterator& it);// { return map_it_!=it.map_it_ || vec_it_!=it.vec_it_; }
|
||||
// bool operator*();// { return *it.vec_it_; }
|
||||
// iterator& operator++(); /* {
|
||||
// if(map_it_ != map_end_ && vec_it_ == map_it_->second.end())
|
||||
// do
|
||||
// vec_it_ = (map_it_++)->second.begin();
|
||||
// while(map_it_ != map_end_ && vec_it_ == map_it_->second.end());
|
||||
// else
|
||||
// vec_it_++;
|
||||
// return *this;
|
||||
// }*/
|
||||
// iterator operator++(int); /* {
|
||||
// iterator tmp(*this);
|
||||
// ++(*this);
|
||||
// return tmp;
|
||||
// }*/
|
||||
// };
|
||||
// class const_iterator {};
|
||||
|
||||
|
||||
// std::size_t size() const;
|
||||
// T& at(const Symbol& key);
|
||||
// const_iterator find(const Symbol& key);
|
||||
// void insert(const std::pair<Symbol, T>& p);
|
||||
// void clear() { throw std::runtime_error("Clear should not be used!"); }
|
||||
// std::size_t count() const;
|
||||
//
|
||||
// const_iterator begin() const;
|
||||
// const_iterator end() const;
|
||||
};
|
||||
|
||||
#endif
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@
|
|||
#include <boost/tuple/tuple.hpp>
|
||||
#include "SymbolicConditional.h"
|
||||
#include "SymbolicFactor.h"
|
||||
#include "SymbolMap.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
|
@ -31,7 +32,7 @@ namespace gtsam {
|
|||
SymbolicFactor::SymbolicFactor(const vector<shared_ptr> & factors) {
|
||||
|
||||
// store keys in a map to make them unique (set is not portable)
|
||||
map<Symbol, Symbol> map;
|
||||
SymbolMap<Symbol> map;
|
||||
BOOST_FOREACH(shared_ptr factor, factors)
|
||||
BOOST_FOREACH(const Symbol& key, factor->keys())
|
||||
map.insert(make_pair(key,key));
|
||||
|
|
|
|||
|
|
@ -147,24 +147,12 @@ VectorConfig expmap(const VectorConfig& original, const Vector& delta)
|
|||
|
||||
/* ************************************************************************* */
|
||||
const Vector& VectorConfig::get(const Symbol& name) const {
|
||||
const_iterator it = values.find(name);
|
||||
if (it==values.end()) {
|
||||
print();
|
||||
cout << "asked for key " << (string)name << endl;
|
||||
throw(std::invalid_argument("VectorConfig::[] invalid key"));
|
||||
}
|
||||
return it->second;
|
||||
return values.at(name);
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
Vector& VectorConfig::getReference(const Symbol& name) {
|
||||
iterator it = values.find(name);
|
||||
if (it==values.end()) {
|
||||
print();
|
||||
cout << "asked for key " << (string)name << endl;
|
||||
throw(std::invalid_argument("VectorConfig::[] invalid key"));
|
||||
}
|
||||
return it->second;
|
||||
return values.at(name);
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#include "Testable.h"
|
||||
#include "Vector.h"
|
||||
#include "Key.h"
|
||||
#include "SymbolMap.h"
|
||||
|
||||
namespace gtsam {
|
||||
|
||||
|
|
@ -23,11 +24,11 @@ namespace gtsam {
|
|||
|
||||
protected:
|
||||
/** Map from string indices to values */
|
||||
std::map<Symbol, Vector> values;
|
||||
SymbolMap<Vector> values;
|
||||
|
||||
public:
|
||||
typedef std::map<Symbol, Vector>::iterator iterator;
|
||||
typedef std::map<Symbol, Vector>::const_iterator const_iterator;
|
||||
typedef SymbolMap<Vector>::iterator iterator;
|
||||
typedef SymbolMap<Vector>::const_iterator const_iterator;
|
||||
|
||||
VectorConfig() {}
|
||||
VectorConfig(const VectorConfig& cfg_in): values(cfg_in.values) {}
|
||||
|
|
|
|||
|
|
@ -126,13 +126,13 @@ TEST( BayesTree, constructor )
|
|||
/* ************************************************************************* */
|
||||
TEST(BayesTree, clear)
|
||||
{
|
||||
SymbolicBayesTree bayesTree = createAsiaSymbolicBayesTree();
|
||||
bayesTree.clear();
|
||||
|
||||
SymbolicBayesTree expected;
|
||||
|
||||
// Check whether cleared BayesTree is equal to a new BayesTree
|
||||
CHECK(assert_equal(expected, bayesTree));
|
||||
// SymbolicBayesTree bayesTree = createAsiaSymbolicBayesTree();
|
||||
// bayesTree.clear();
|
||||
//
|
||||
// SymbolicBayesTree expected;
|
||||
//
|
||||
// // Check whether cleared BayesTree is equal to a new BayesTree
|
||||
// CHECK(assert_equal(expected, bayesTree));
|
||||
}
|
||||
|
||||
/* ************************************************************************* *
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ using namespace boost::assign;
|
|||
#include "BayesNet-inl.h"
|
||||
#include "smallExample.h"
|
||||
#include "Ordering.h"
|
||||
#include "SymbolMap.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace gtsam;
|
||||
|
|
@ -34,7 +35,7 @@ using namespace gtsam;
|
|||
typedef BayesNet<BinaryConditional> BinaryBayesNet;
|
||||
|
||||
|
||||
double probability( BinaryBayesNet & bbn, map<Symbol,bool> & config)
|
||||
double probability( BinaryBayesNet & bbn, SymbolMap<bool> & config)
|
||||
{
|
||||
double result = 1.0;
|
||||
BinaryBayesNet::const_iterator it = bbn.begin();
|
||||
|
|
@ -53,7 +54,7 @@ TEST( BinaryBayesNet, constructor )
|
|||
// p(x|y=0) = 0.3
|
||||
// p(x|y=1) = 0.6
|
||||
|
||||
map<Symbol,bool> config;
|
||||
SymbolMap<bool> config;
|
||||
config["y"] = false;
|
||||
config["x"] = false;
|
||||
// unary conditional for y
|
||||
|
|
|
|||
|
|
@ -0,0 +1,178 @@
|
|||
/*
|
||||
* timeSymbolMaps.cpp
|
||||
*
|
||||
* Created on: Jan 20, 2010
|
||||
* Author: richard
|
||||
*/
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <string>
|
||||
#include <boost/timer.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "Key.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
using namespace gtsam;
|
||||
|
||||
template<class T>
|
||||
class SymbolMapExp {
|
||||
private:
|
||||
typedef map<unsigned char, vector<T> > Map;
|
||||
typedef vector<T> Vec;
|
||||
|
||||
Map values_;
|
||||
|
||||
public:
|
||||
typedef pair<Symbol, T> value_type;
|
||||
|
||||
SymbolMapExp() {}
|
||||
|
||||
T& at(const Symbol& key) {
|
||||
typename Map::iterator it = values_.find(key.chr());
|
||||
if(it != values_.end())
|
||||
return it->second.at(key.index());
|
||||
else
|
||||
throw invalid_argument("Key " + (string)key + " not present");
|
||||
}
|
||||
|
||||
void set(const Symbol& key, const T& value) {
|
||||
Vec& vec(values_[key.chr()]);
|
||||
//vec.reserve(10000);
|
||||
if(key.index() >= vec.size()) {
|
||||
vec.reserve(key.index()+1);
|
||||
vec.resize(key.index());
|
||||
vec.push_back(value);
|
||||
} else
|
||||
vec[key.index()] = value;
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class SymbolMapBinary : public std::map<Symbol, T> {
|
||||
private:
|
||||
typedef std::map<Symbol, T> Base;
|
||||
public:
|
||||
SymbolMapBinary() : std::map<Symbol, T>() {}
|
||||
|
||||
T& at(const Symbol& key) {
|
||||
typename Base::iterator it = Base::find(key);
|
||||
if (it == Base::end())
|
||||
throw(std::invalid_argument("SymbolMap::[] invalid key: " + (std::string)key));
|
||||
return it->second;
|
||||
}
|
||||
};
|
||||
|
||||
struct SymbolHash : public std::unary_function<Symbol, std::size_t> {
|
||||
std::size_t operator()(Symbol const& x) const {
|
||||
std::size_t seed = 0;
|
||||
boost::hash_combine(seed, x.chr());
|
||||
boost::hash_combine(seed, x.index());
|
||||
return ((size_t(x.chr()) << 24) & x.index());
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class SymbolMapHash : public boost::unordered_map<Symbol, T, SymbolHash> {
|
||||
public:
|
||||
SymbolMapHash() : boost::unordered_map<Symbol, T, SymbolHash>(60000) {}
|
||||
};
|
||||
|
||||
struct Value {
|
||||
double v;
|
||||
Value() : v(0.0) {}
|
||||
Value(double vi) : v(vi) {}
|
||||
operator string() { lexical_cast<string>(v); }
|
||||
bool operator!=(const Value& vc) { return v != vc.v; }
|
||||
};
|
||||
|
||||
#define ELEMS 3000
|
||||
#define TIMEAT 300
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
timer tmr;
|
||||
|
||||
// pre-allocate
|
||||
cout << "Generating test data ..." << endl;
|
||||
vector<pair<Symbol, Value> > values;
|
||||
for(size_t i=0; i<ELEMS; i++) {
|
||||
values.push_back(make_pair(Symbol('a',i), (double)i));
|
||||
values.push_back(make_pair(Symbol('b',i), (double)i));
|
||||
values.push_back(make_pair(Symbol('c',i), (double)i));
|
||||
}
|
||||
|
||||
// time binary map
|
||||
cout << "Timing binary map ..." << endl;
|
||||
{
|
||||
SymbolMapBinary<Value> binary;
|
||||
for(size_t i=0; i<ELEMS*3; ) {
|
||||
size_t stop = i + TIMEAT;
|
||||
tmr.restart();
|
||||
for( ; i<stop; i++)
|
||||
binary.insert(values[i]);
|
||||
double time = tmr.elapsed();
|
||||
cout << i << " values, avg " << (time/(double)TIMEAT)*1e6 << " mu-s per insert" << endl;
|
||||
|
||||
tmr.restart();
|
||||
for(size_t j=0; j<i; j++)
|
||||
if(values[j].second != binary[values[j].first]) {
|
||||
cout << "Wrong value! At key " << (string)values[j].first <<
|
||||
" expecting " << (string)values[j].second <<
|
||||
" got " << (string)binary[values[j].first] << endl;
|
||||
}
|
||||
time = tmr.elapsed();
|
||||
cout << i << " values, avg " << (time)*1e3 << " ms per lookup" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
// time hash map
|
||||
cout << "Timing hash map ..." << endl;
|
||||
{
|
||||
SymbolMapHash<Value> hash;
|
||||
for(size_t i=0; i<ELEMS*3; ) {
|
||||
size_t stop = i + TIMEAT;
|
||||
tmr.restart();
|
||||
for( ; i<stop; i++)
|
||||
hash.insert(values[i]);
|
||||
double time = tmr.elapsed();
|
||||
cout << i << " values, avg " << (time/(double)TIMEAT)*1e6 << " mu-s per insert" << endl;
|
||||
|
||||
tmr.restart();
|
||||
for(size_t j=0; j<i; j++)
|
||||
if(values[j].second != hash[values[j].first]) {
|
||||
cout << "Wrong value! At key " << (string)values[j].first <<
|
||||
" expecting " << (string)values[j].second <<
|
||||
" got " << (string)hash[values[j].first] << endl;
|
||||
}
|
||||
time = tmr.elapsed();
|
||||
cout << i << " values, avg " << (time/(double)i)*1e6 << " mu-s per lookup" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
// time experimental map
|
||||
cout << "Timing experimental map ..." << endl;
|
||||
{
|
||||
SymbolMapExp<Value> experimental;
|
||||
for(size_t i=0; i<ELEMS*3; ) {
|
||||
size_t stop = i + TIMEAT;
|
||||
tmr.restart();
|
||||
for( ; i<stop; i++)
|
||||
experimental.set(values[i].first, values[i].second);
|
||||
double time = tmr.elapsed();
|
||||
cout << i << " values, avg " << (time/(double)TIMEAT)*1e6 << " mu-s per insert" << endl;
|
||||
|
||||
tmr.restart();
|
||||
for(size_t j=0; j<i; j++)
|
||||
if(values[j].second != experimental.at(values[j].first)) {
|
||||
cout << "Wrong value! At key " << (string)values[j].first <<
|
||||
" expecting " << (string)values[j].second <<
|
||||
" got " << (string)experimental.at(values[j].first) << endl;
|
||||
}
|
||||
time = tmr.elapsed();
|
||||
cout << i << " values, avg " << (time/(double)i)*1e6 << " mu-s per lookup" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue