242 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			C++
		
	
	
			
		
		
	
	
			242 lines
		
	
	
		
			9.1 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    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);
 | 
						|
 | 
						|
  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<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) {}
 | 
						|
  void checkVar(Index variable) const { assert(variable < index_.size()); }
 | 
						|
 | 
						|
  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<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.
 | 
						|
  for(Index j=0; j<this->index_.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; j<permutation.size(); ++j)
 | 
						|
//    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
 | 
						|
    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_.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]) {
 | 
						|
        Index fvari = 0;
 | 
						|
        BOOST_FOREACH(const Index key, factorGraph[fi]->keys()) {
 | 
						|
          index_[key].push_back(mapped_factor_type(fi, fvari));
 | 
						|
          ++ fvari;
 | 
						|
          ++ nEntries_;
 | 
						|
        }
 | 
						|
        ++ nFactors_;
 | 
						|
      }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/* ************************************************************************* */
 | 
						|
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
 | 
						|
    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; var<index_.permutation().size(); ++var)
 | 
						|
      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]) {
 | 
						|
        Index fvari = 0;
 | 
						|
        BOOST_FOREACH(const Index key, factorGraph[fi]->keys()) {
 | 
						|
          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 {
 | 
						|
  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<class Storage>
 | 
						|
void VariableIndex<Storage>::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;
 | 
						|
}
 | 
						|
 | 
						|
}
 |