/* ---------------------------------------------------------------------------- * 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 VariableIndex.h * @brief * @author Richard Roberts * @created Sep 12, 2010 */ #pragma once #include #include #include #include #include #include #include namespace gtsam { class Inference; /** * The VariableIndex can internally use either a vector or a deque to store * variables. For one-shot elimination, using a vector will give the best * performance, and this is the default. For incremental updates, such as in * ISAM and ISAM2, deque storage is used to prevent frequent reallocation. */ struct VariableIndexStorage_vector { template struct type_factory { typedef std::vector type; }; }; struct VariableIndexStorage_deque { template struct type_factory { typedef std::deque type; }; }; /** * The VariableIndex class stores the information necessary to perform * elimination, including an index of factors involving each variable and * the structure of the intermediate joint factors that develop during * elimination. This maps variables to deque's of pair, * which is pairs the factor index with the position of the variable within * the factor. */ struct _mapped_factor_type { size_t factorIndex; size_t variablePosition; _mapped_factor_type(size_t _factorIndex, size_t _variablePosition) : factorIndex(_factorIndex), variablePosition(_variablePosition) {} bool operator==(const _mapped_factor_type& o) const { return factorIndex == o.factorIndex && variablePosition == o.variablePosition; } }; template class VariableIndex { public: typedef _mapped_factor_type mapped_factor_type; typedef boost::shared_ptr shared_ptr; typedef std::deque mapped_type; typedef typename mapped_type::iterator factor_iterator; typedef typename mapped_type::const_iterator const_factor_iterator; protected: typedef typename VARIABLEINDEXSTORAGE::template type_factory::type storage_type; storage_type indexUnpermuted_; Permuted index_; size_t nFactors_; size_t nEntries_; // Sum of involved variable counts of each factor public: VariableIndex() : index_(indexUnpermuted_), nFactors_(0), nEntries_(0) {} template VariableIndex(const FactorGraph& factorGraph, Index nVariables); template VariableIndex(const FactorGraph& factorGraph); Index size() const { return index_.size(); } size_t nFactors() const { return nFactors_; } size_t nEntries() const { return nEntries_; } const mapped_type& operator[](Index variable) const { checkVar(variable); return index_[variable]; } mapped_type& operator[](Index variable) { checkVar(variable); return index_[variable]; } void permute(const Permutation& permutation); template void augment(const FactorGraph& factorGraph); void rebaseFactors(ptrdiff_t baseIndexChange); template bool equals(const Derived& other, double tol=0.0) const; void print(const std::string& str = "VariableIndex: ") const; protected: VariableIndex(size_t nVars) : indexUnpermuted_(nVars), index_(indexUnpermuted_), nFactors_(0), nEntries_(0) {} void checkVar(Index variable) const { assert(variable < index_.size()); } template void fill(const FactorGraph& factorGraph); factor_iterator factorsBegin(Index variable) { checkVar(variable); return index_[variable].begin(); } const_factor_iterator factorsBegin(Index variable) const { checkVar(variable); return index_[variable].begin(); } factor_iterator factorsEnd(Index variable) { checkVar(variable); return index_[variable].end(); } const_factor_iterator factorsEnd(Index variable) const { checkVar(variable); return index_[variable].end(); } friend class Inference; }; /* ************************************************************************* */ template void VariableIndex::permute(const Permutation& permutation) { #ifndef NDEBUG // Assert that the permutation does not leave behind any non-empty variables, // otherwise the nFactors and nEntries counts would be incorrect. for(Index j=0; jindex_.size(); ++j) if(find(permutation.begin(), permutation.end(), j) == permutation.end()) assert(this->operator[](j).empty()); #endif index_.permute(permutation); // storage_type original(this->index_.size()); // this->index_.swap(original); // for(Index j=0; jindex_[j].swap(original[permutation[j]]); } /* ************************************************************************* */ template template void VariableIndex::fill(const FactorGraph& factorGraph) { // Build index mapping from variable id to factor index for(size_t fi=0; fikeys()) { if(key < index_.size()) { index_[key].push_back(mapped_factor_type(fi, fvari)); ++ fvari; ++ nEntries_; } } ++ nFactors_; } } /* ************************************************************************* */ template template VariableIndex::VariableIndex(const FactorGraph& factorGraph) : index_(indexUnpermuted_), nFactors_(0), nEntries_(0) { // If the factor graph is empty, return an empty index because inside this // if block we assume at least one factor. if(factorGraph.size() > 0) { // Find highest-numbered variable Index maxVar = 0; BOOST_FOREACH(const typename FactorGraph::sharedFactor& factor, factorGraph) { if(factor) { BOOST_FOREACH(const Index key, factor->keys()) { if(key > maxVar) maxVar = key; } } } // Allocate array index_.container().resize(maxVar+1); index_.permutation() = Permutation::Identity(maxVar+1); fill(factorGraph); } } /* ************************************************************************* */ template template VariableIndex::VariableIndex(const FactorGraph& factorGraph, Index nVariables) : indexUnpermuted_(nVariables), index_(indexUnpermuted_), nFactors_(0), nEntries_(0) { fill(factorGraph); } /* ************************************************************************* */ template template void VariableIndex::augment(const FactorGraph& factorGraph) { // If the factor graph is empty, return an empty index because inside this // if block we assume at least one factor. if(factorGraph.size() > 0) { // Find highest-numbered variable Index maxVar = 0; BOOST_FOREACH(const typename FactorGraph::sharedFactor& factor, factorGraph) { if(factor) { BOOST_FOREACH(const Index key, factor->keys()) { if(key > maxVar) maxVar = key; } } } // Allocate index Index originalSize = index_.size(); index_.container().resize(std::max(index_.size(), maxVar+1)); index_.permutation().resize(index_.container().size()); for(Index var=originalSize; varkeys()) { index_[key].push_back(mapped_factor_type(orignFactors + fi, fvari)); ++ fvari; ++ nEntries_; } ++ nFactors_; } } } /* ************************************************************************* */ template void VariableIndex::rebaseFactors(ptrdiff_t baseIndexChange) { BOOST_FOREACH(mapped_type& factors, index_.container()) { BOOST_FOREACH(mapped_factor_type& factor, factors) { factor.factorIndex += baseIndexChange; } } } /* ************************************************************************* */ template template bool VariableIndex::equals(const Derived& other, double tol) const { if(this->nEntries_ == other.nEntries_ && this->nFactors_ == other.nFactors_) { for(size_t var=0; var < std::max(this->index_.size(), other.index_.size()); ++var) if(var >= this->index_.size() || var >= other.index_.size()) { if(!((var >= this->index_.size() && other.index_[var].empty()) || (var >= other.index_.size() && this->index_[var].empty()))) return false; } else if(this->index_[var] != other.index_[var]) return false; } else return false; return true; } /* ************************************************************************* */ template void VariableIndex::print(const std::string& str) const { std::cout << str; Index var = 0; BOOST_FOREACH(const mapped_type& variable, index_.container()) { Permutation::const_iterator rvar = find(index_.permutation().begin(), index_.permutation().end(), var); assert(rvar != index_.permutation().end()); std::cout << "var " << (rvar-index_.permutation().begin()) << ":"; BOOST_FOREACH(const mapped_factor_type& factor, variable) { std::cout << " " << factor.factorIndex << "-" << factor.variablePosition; } std::cout << "\n"; ++ var; } std::cout << std::flush; } }