| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * @file    VariableIndex.h | 
					
						
							|  |  |  |  * @brief    | 
					
						
							|  |  |  |  * @author  Richard Roberts | 
					
						
							|  |  |  |  * @created Sep 12, 2010 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #pragma once
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <gtsam/base/types.h>
 | 
					
						
							|  |  |  | #include <gtsam/inference/Permutation.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <vector>
 | 
					
						
							|  |  |  | #include <deque>
 | 
					
						
							|  |  |  | #include <iostream>
 | 
					
						
							|  |  |  | #include <boost/shared_ptr.hpp>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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<typename T> struct type_factory { typedef std::vector<T> type; }; }; | 
					
						
							|  |  |  | struct VariableIndexStorage_deque { template<typename T> struct type_factory { typedef std::deque<T> 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<size_t,size_t>, | 
					
						
							|  |  |  |  * 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 VariableIndexStorage=VariableIndexStorage_vector> | 
					
						
							|  |  |  | class VariableIndex { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   typedef _mapped_factor_type mapped_factor_type; | 
					
						
							|  |  |  |   typedef boost::shared_ptr<VariableIndex> shared_ptr; | 
					
						
							|  |  |  |   typedef std::deque<mapped_factor_type> 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<mapped_type>::type storage_type; | 
					
						
							|  |  |  |   storage_type indexUnpermuted_; | 
					
						
							|  |  |  |   Permuted<storage_type, typename storage_type::value_type&> index_; | 
					
						
							|  |  |  |   size_t nFactors_; | 
					
						
							|  |  |  |   size_t nEntries_; // Sum of involved variable counts of each factor
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |   VariableIndex() : index_(indexUnpermuted_), nFactors_(0), nEntries_(0) {} | 
					
						
							|  |  |  |   template<class FactorGraph> VariableIndex(const FactorGraph& factorGraph); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  |   Index size() const { return index_.size(); } | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  |   size_t nFactors() const { return nFactors_; } | 
					
						
							|  |  |  |   size_t nEntries() const { return nEntries_; } | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  |   const mapped_type& operator[](Index variable) const { checkVar(variable); return index_[variable]; } | 
					
						
							|  |  |  |   mapped_type& operator[](Index variable) { checkVar(variable); return index_[variable]; } | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  |   void permute(const Permutation& permutation); | 
					
						
							|  |  |  | //  template<class Derived> void augment(const Derived& varIndex);
 | 
					
						
							|  |  |  |   template<class FactorGraph> void augment(const FactorGraph& factorGraph); | 
					
						
							|  |  |  |   void rebaseFactors(ptrdiff_t baseIndexChange); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   template<class Derived> 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) {} | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  |   void checkVar(Index variable) const { assert(variable < index_.size()); } | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  |   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(); } | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   friend class Inference; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | template<class Storage> | 
					
						
							|  |  |  | void VariableIndex<Storage>::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.
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  |   for(Index j=0; j<this->index_.size(); ++j) | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  |     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);
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | //  for(Index j=0; j<permutation.size(); ++j)
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //    this->index_[j].swap(original[permutation[j]]);
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | template<class Storage> | 
					
						
							|  |  |  | template<class FactorGraph> | 
					
						
							|  |  |  | VariableIndex<Storage>::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
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  |     Index maxVar = 0; | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  |     BOOST_FOREACH(const typename FactorGraph::sharedFactor& factor, factorGraph) { | 
					
						
							|  |  |  |       if(factor) { | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  |         BOOST_FOREACH(const Index key, factor->keys()) { | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  |           if(key > maxVar) | 
					
						
							|  |  |  |             maxVar = key; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Allocate index
 | 
					
						
							|  |  |  |     index_.container().resize(maxVar+1); | 
					
						
							|  |  |  |     index_.permutation() = Permutation::Identity(maxVar+1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Build index mapping from variable id to factor index
 | 
					
						
							|  |  |  |     for(size_t fi=0; fi<factorGraph.size(); ++fi) | 
					
						
							|  |  |  |       if(factorGraph[fi]) { | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  |         Index fvari = 0; | 
					
						
							|  |  |  |         BOOST_FOREACH(const Index key, factorGraph[fi]->keys()) { | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  |           index_[key].push_back(mapped_factor_type(fi, fvari)); | 
					
						
							|  |  |  |           ++ fvari; | 
					
						
							|  |  |  |           ++ nEntries_; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         ++ nFactors_; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ///* ************************************************************************* */
 | 
					
						
							|  |  |  | //template<class Storage>
 | 
					
						
							|  |  |  | //template<class Derived>
 | 
					
						
							|  |  |  | //void VariableIndex<Storage>::augment(const Derived& varIndex) {
 | 
					
						
							|  |  |  | //  nFactors_ = std::max(nFactors_, varIndex.nFactors());
 | 
					
						
							|  |  |  | //  nEntries_ = nEntries_ + varIndex.nEntries();
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | //  Index originalSize = index_.size();
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //  index_.container().resize(std::max(index_.size(), varIndex.size()));
 | 
					
						
							|  |  |  | //  index_.permutation().resize(index_.container().size());
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | //  for(Index var=originalSize; var<index_.permutation().size(); ++var)
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //    index_.permutation()[var] = var;
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  | //  for(Index var=0; var<varIndex.size(); ++var)
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | //    index_[var].insert(index_[var].begin(), varIndex[var].begin(), varIndex[var].end());
 | 
					
						
							|  |  |  | //}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | template<class Storage> | 
					
						
							|  |  |  | template<class FactorGraph> | 
					
						
							|  |  |  | void VariableIndex<Storage>::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
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  |     Index maxVar = 0; | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  |     BOOST_FOREACH(const typename FactorGraph::sharedFactor& factor, factorGraph) { | 
					
						
							|  |  |  |       if(factor) { | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  |         BOOST_FOREACH(const Index key, factor->keys()) { | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  |           if(key > maxVar) | 
					
						
							|  |  |  |             maxVar = key; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Allocate index
 | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  |     Index originalSize = index_.size(); | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  |     index_.container().resize(std::max(index_.size(), maxVar+1)); | 
					
						
							|  |  |  |     index_.permutation().resize(index_.container().size()); | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  |     for(Index var=originalSize; var<index_.permutation().size(); ++var) | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  |       index_.permutation()[var] = var; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Augment index mapping from variable id to factor index
 | 
					
						
							|  |  |  |     size_t orignFactors = nFactors_; | 
					
						
							|  |  |  |     for(size_t fi=0; fi<factorGraph.size(); ++fi) | 
					
						
							|  |  |  |       if(factorGraph[fi]) { | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  |         Index fvari = 0; | 
					
						
							|  |  |  |         BOOST_FOREACH(const Index key, factorGraph[fi]->keys()) { | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  |           index_[key].push_back(mapped_factor_type(orignFactors + fi, fvari)); | 
					
						
							|  |  |  |           ++ fvari; | 
					
						
							|  |  |  |           ++ nEntries_; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         ++ nFactors_; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | template<class Storage> | 
					
						
							|  |  |  | void VariableIndex<Storage>::rebaseFactors(ptrdiff_t baseIndexChange) { | 
					
						
							|  |  |  |   BOOST_FOREACH(mapped_type& factors, index_.container()) { | 
					
						
							|  |  |  |     BOOST_FOREACH(mapped_factor_type& factor, factors) { | 
					
						
							|  |  |  |       factor.factorIndex += baseIndexChange; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | template<class Storage> | 
					
						
							|  |  |  | template<class Derived> | 
					
						
							|  |  |  | bool VariableIndex<Storage>::equals(const Derived& other, double tol) const { | 
					
						
							| 
									
										
										
										
											2010-10-14 04:43:58 +08:00
										 |  |  |   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]) | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  |         return false; | 
					
						
							|  |  |  |   } else | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | template<class Storage> | 
					
						
							|  |  |  | void VariableIndex<Storage>::print(const std::string& str) const { | 
					
						
							|  |  |  |   std::cout << str; | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  |   Index var = 0; | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  |   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()); | 
					
						
							| 
									
										
										
										
											2010-10-14 04:43:58 +08:00
										 |  |  |     std::cout << "var " << (rvar-index_.permutation().begin()) << ":"; | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  |     BOOST_FOREACH(const mapped_factor_type& factor, variable) { | 
					
						
							|  |  |  |       std::cout << " " << factor.factorIndex << "-" << factor.variablePosition; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     std::cout << "\n"; | 
					
						
							|  |  |  |     ++ var; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   std::cout << std::flush; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |