Moved sorted-key invariant out of Factor and into IndexFactor, also out of Conditional and into IndexConditional

release/4.3a0
Richard Roberts 2011-03-01 21:47:08 +00:00
parent 86ac4d5374
commit 07ad9ac957
8 changed files with 118 additions and 36 deletions

View File

@ -54,15 +54,14 @@ protected:
/** The first nFrontal variables are frontal and the rest are parents. */ /** The first nFrontal variables are frontal and the rest are parents. */
size_t nrFrontals_; size_t nrFrontals_;
/** Debugging invariant that the keys should be in order, including that the // Calls the base class assertInvariants, which checks for unique keys
* conditioned variable is numbered lower than the parents. void assertInvariants() const { Factor<KEY>::assertInvariants(); }
*/
void assertInvariants() const;
public: public:
typedef KEY Key; typedef KEY Key;
typedef Conditional<Key> This; typedef Conditional<Key> This;
typedef Factor<Key> Base;
/** /**
* Typedef to the factor type that produces this conditional and that this * Typedef to the factor type that produces this conditional and that this
@ -87,25 +86,26 @@ public:
typedef boost::iterator_range<const_iterator> Parents; typedef boost::iterator_range<const_iterator> Parents;
/** Empty Constructor to make serialization possible */ /** Empty Constructor to make serialization possible */
Conditional() : nrFrontals_(0) {} Conditional() : nrFrontals_(0) { assertInvariants(); }
/** No parents */ /** No parents */
Conditional(Key key) : FactorType(key), nrFrontals_(1) {} Conditional(Key key) : FactorType(key), nrFrontals_(1) { assertInvariants(); }
/** Single parent */ /** Single parent */
Conditional(Key key, Key parent) : FactorType(key, parent), nrFrontals_(1) {} Conditional(Key key, Key parent) : FactorType(key, parent), nrFrontals_(1) { assertInvariants(); }
/** Two parents */ /** Two parents */
Conditional(Key key, Key parent1, Key parent2) : FactorType(key, parent1, parent2), nrFrontals_(1) {} Conditional(Key key, Key parent1, Key parent2) : FactorType(key, parent1, parent2), nrFrontals_(1) { assertInvariants(); }
/** Three parents */ /** Three parents */
Conditional(Key key, Key parent1, Key parent2, Key parent3) : FactorType(key, parent1, parent2, parent3), nrFrontals_(1) {} Conditional(Key key, Key parent1, Key parent2, Key parent3) : FactorType(key, parent1, parent2, parent3), nrFrontals_(1) { assertInvariants(); }
/** Constructor from a frontal variable and a vector of parents */ /** Constructor from a frontal variable and a vector of parents */
Conditional(Key key, const std::vector<Key>& parents) : nrFrontals_(1) { Conditional(Key key, const std::vector<Key>& parents) : nrFrontals_(1) {
FactorType::keys_.resize(1 + parents.size()); FactorType::keys_.resize(1 + parents.size());
*(beginFrontals()) = key; *(beginFrontals()) = key;
std::copy(parents.begin(), parents.end(), beginParents()); std::copy(parents.begin(), parents.end(), beginParents());
assertInvariants();
} }
/** Constructor from a frontal variable and an iterator range of parents */ /** Constructor from a frontal variable and an iterator range of parents */
@ -115,6 +115,7 @@ public:
conditional->nrFrontals_ = 1; conditional->nrFrontals_ = 1;
conditional->keys_.push_back(key); conditional->keys_.push_back(key);
std::copy(firstParent, lastParent, back_inserter(conditional->keys_)); std::copy(firstParent, lastParent, back_inserter(conditional->keys_));
conditional->This::assertInvariants();
return conditional; return conditional;
} }
@ -124,6 +125,7 @@ public:
typename DERIVED::shared_ptr conditional(new DERIVED); typename DERIVED::shared_ptr conditional(new DERIVED);
conditional->nrFrontals_ = nrFrontals; conditional->nrFrontals_ = nrFrontals;
std::copy(firstKey, lastKey, back_inserter(conditional->keys_)); std::copy(firstKey, lastKey, back_inserter(conditional->keys_));
conditional->This::assertInvariants();
return conditional; return conditional;
} }
@ -212,6 +214,7 @@ bool Conditional<KEY>::permuteSeparatorWithInverse(const Permutation& inversePer
parent = newParent; parent = newParent;
} }
} }
assertInvariants();
return parentChanged; return parentChanged;
} }
@ -227,6 +230,7 @@ void Conditional<KEY>::permuteWithInverse(const Permutation& inversePermutation)
} }
#endif #endif
FactorType::permuteWithInverse(inversePermutation); FactorType::permuteWithInverse(inversePermutation);
assertInvariants();
} }
} }

View File

@ -31,19 +31,20 @@ namespace gtsam {
/* ************************************************************************* */ /* ************************************************************************* */
template<typename KEY> template<typename KEY>
Factor<KEY>::Factor(const Factor<KEY>& f) : keys_(f.keys_) {} Factor<KEY>::Factor(const Factor<KEY>& f) : keys_(f.keys_) { assertInvariants(); }
/* ************************************************************************* */ /* ************************************************************************* */
template<typename KEY> template<typename KEY>
Factor<KEY>::Factor(const ConditionalType& c) : keys_(c.keys()) {} Factor<KEY>::Factor(const ConditionalType& c) : keys_(c.keys()) { assertInvariants(); }
/* ************************************************************************* */ /* ************************************************************************* */
template<typename KEY> template<typename KEY>
void Factor<KEY>::assertInvariants() const { void Factor<KEY>::assertInvariants() const {
#ifndef NDEBUG #ifndef NDEBUG
std::set<Index> uniqueSorted(keys_.begin(), keys_.end()); // Check that keys are all unique
assert(uniqueSorted.size() == keys_.size()); std::multiset<Key> nonunique(keys_.begin(), keys_.end());
assert(std::equal(uniqueSorted.begin(), uniqueSorted.end(), keys_.begin())); std::set<Key> unique(keys_.begin(), keys_.end());
assert(nonunique.size() == unique.size() && std::equal(nonunique.begin(), nonunique.end(), unique.begin()));
#endif #endif
} }
@ -84,6 +85,7 @@ typename CONDITIONAL::shared_ptr Factor<KEY>::eliminateFirst() {
assertInvariants(); assertInvariants();
KEY eliminated = keys_.front(); KEY eliminated = keys_.front();
keys_.erase(keys_.begin()); keys_.erase(keys_.begin());
assertInvariants();
return typename CONDITIONAL::shared_ptr(new CONDITIONAL(eliminated, keys_)); return typename CONDITIONAL::shared_ptr(new CONDITIONAL(eliminated, keys_));
} }
@ -100,6 +102,7 @@ typename BayesNet<CONDITIONAL>::shared_ptr Factor<KEY>::eliminate(size_t nrFront
nextFrontal, const_iterator(this->end()), 1)); nextFrontal, const_iterator(this->end()), 1));
if(nrFrontals > 0) if(nrFrontals > 0)
keys_.assign(fragment->back()->beginParents(), fragment->back()->endParents()); keys_.assign(fragment->back()->beginParents(), fragment->back()->endParents());
assertInvariants();
return fragment; return fragment;
} }
@ -107,6 +110,7 @@ typename BayesNet<CONDITIONAL>::shared_ptr Factor<KEY>::eliminate(size_t nrFront
template<typename KEY> template<typename KEY>
void Factor<KEY>::permuteWithInverse(const Permutation& inversePermutation) { void Factor<KEY>::permuteWithInverse(const Permutation& inversePermutation) {
BOOST_FOREACH(KEY& key, keys_) { key = inversePermutation[key]; } BOOST_FOREACH(KEY& key, keys_) { key = inversePermutation[key]; }
assertInvariants();
} }
} }

View File

@ -76,7 +76,7 @@ protected:
// The keys involved in this factor // The keys involved in this factor
std::vector<Key> keys_; std::vector<Key> keys_;
// Internal check to make sure keys are sorted. If NDEBUG is defined, this // Internal check to make sure keys are unique. If NDEBUG is defined, this
// is empty and optimized out. // is empty and optimized out.
void assertInvariants() const; void assertInvariants() const;

View File

@ -16,10 +16,29 @@
* @created Oct 17, 2010 * @created Oct 17, 2010
*/ */
#include <gtsam/base/FastSet.h>
#include <gtsam/inference/IndexConditional.h> #include <gtsam/inference/IndexConditional.h>
#include <boost/lambda/lambda.hpp>
namespace gtsam { namespace gtsam {
using namespace std;
using namespace boost::lambda;
template class Conditional<Index>; template class Conditional<Index>;
/* ************************************************************************* */
void IndexConditional::assertInvariants() const {
// Checks for uniqueness of keys
Base::assertInvariants();
#ifndef NDEBUG
// Check that separator keys are sorted
FastSet<Index> uniquesorted(beginFrontals(), endFrontals());
assert(uniquesorted.size() == nrFrontals() && std::equal(uniquesorted.begin(), uniquesorted.end(), beginFrontals()));
// Check that separator keys are less than parent keys
BOOST_FOREACH(Index j, frontals()) {
assert(find_if(beginParents(), endParents(), _1 < j) == endParents()); }
#endif
}
} }

View File

@ -33,6 +33,11 @@ namespace gtsam {
*/ */
class IndexConditional : public Conditional<Index> { class IndexConditional : public Conditional<Index> {
protected:
// Checks that frontal indices are sorted and lower than parent indices
void assertInvariants() const;
public: public:
typedef IndexConditional This; typedef IndexConditional This;
@ -41,32 +46,36 @@ namespace gtsam {
typedef boost::shared_ptr<IndexConditional> shared_ptr; typedef boost::shared_ptr<IndexConditional> shared_ptr;
/** Empty Constructor to make serialization possible */ /** Empty Constructor to make serialization possible */
IndexConditional() {} IndexConditional() { assertInvariants(); }
/** No parents */ /** No parents */
IndexConditional(Index j) : Base(j) {} IndexConditional(Index j) : Base(j) { assertInvariants(); }
/** Single parent */ /** Single parent */
IndexConditional(Index j, Index parent) : Base(j, parent) {} IndexConditional(Index j, Index parent) : Base(j, parent) { assertInvariants(); }
/** Two parents */ /** Two parents */
IndexConditional(Index j, Index parent1, Index parent2) : Base(j, parent1, parent2) {} IndexConditional(Index j, Index parent1, Index parent2) : Base(j, parent1, parent2) { assertInvariants(); }
/** Three parents */ /** Three parents */
IndexConditional(Index j, Index parent1, Index parent2, Index parent3) : Base(j, parent1, parent2, parent3) {} IndexConditional(Index j, Index parent1, Index parent2, Index parent3) : Base(j, parent1, parent2, parent3) { assertInvariants(); }
/** Constructor from a frontal variable and a vector of parents */ /** Constructor from a frontal variable and a vector of parents */
IndexConditional(Index j, const std::vector<Index>& parents) : Base(j, parents) {} IndexConditional(Index j, const std::vector<Index>& parents) : Base(j, parents) { assertInvariants(); }
/** Constructor from a frontal variable and an iterator range of parents */ /** Constructor from a frontal variable and an iterator range of parents */
template<typename ITERATOR> template<typename ITERATOR>
static shared_ptr FromRange(Index j, ITERATOR firstParent, ITERATOR lastParent) { static shared_ptr FromRange(Index j, ITERATOR firstParent, ITERATOR lastParent) {
return Base::FromRange<This>(j, firstParent, lastParent); } shared_ptr result(Base::FromRange<This>(j, firstParent, lastParent));
result->assertInvariants();
return result; }
/** Named constructor from any number of frontal variables and parents */ /** Named constructor from any number of frontal variables and parents */
template<typename ITERATOR> template<typename ITERATOR>
static shared_ptr FromRange(ITERATOR firstKey, ITERATOR lastKey, size_t nrFrontals) { static shared_ptr FromRange(ITERATOR firstKey, ITERATOR lastKey, size_t nrFrontals) {
return Base::FromRange<This>(firstKey, lastKey, nrFrontals); } shared_ptr result(Base::FromRange<This>(firstKey, lastKey, nrFrontals));
result->assertInvariants();
return result; }
/** Convert to a factor */ /** Convert to a factor */
IndexFactor::shared_ptr toFactor() const { return IndexFactor::shared_ptr(new IndexFactor(*this)); } IndexFactor::shared_ptr toFactor() const { return IndexFactor::shared_ptr(new IndexFactor(*this)); }

View File

@ -28,8 +28,21 @@ namespace gtsam {
template class Factor<Index>; template class Factor<Index>;
IndexFactor::IndexFactor(const IndexConditional& c) : Base(c) {} /* ************************************************************************* */
void IndexFactor::assertInvariants() const {
Base::assertInvariants();
#ifndef NDEBUG
std::set<Index> uniqueSorted(keys_.begin(), keys_.end());
assert(uniqueSorted.size() == keys_.size() && std::equal(uniqueSorted.begin(), uniqueSorted.end(), keys_.begin()));
#endif
}
/* ************************************************************************* */
IndexFactor::IndexFactor(const IndexConditional& c): Base(c) {
assertInvariants();
}
/* ************************************************************************* */
pair<BayesNet<IndexConditional>::shared_ptr, IndexFactor::shared_ptr> IndexFactor::CombineAndEliminate( pair<BayesNet<IndexConditional>::shared_ptr, IndexFactor::shared_ptr> IndexFactor::CombineAndEliminate(
const FactorGraph<This>& factors, size_t nrFrontals) { const FactorGraph<This>& factors, size_t nrFrontals) {
@ -51,14 +64,26 @@ pair<BayesNet<IndexConditional>::shared_ptr, IndexFactor::shared_ptr> IndexFacto
return result; return result;
} }
/* ************************************************************************* */
IndexFactor::shared_ptr IndexFactor::Combine( IndexFactor::shared_ptr IndexFactor::Combine(
const FactorGraph<This>& factors, const FastMap<Index, std::vector<Index> >& variableSlots) { const FactorGraph<This>& factors, const FastMap<Index, std::vector<Index> >& variableSlots) {
return Base::Combine<This>(factors, variableSlots); } IndexFactor::shared_ptr combined(Base::Combine<This>(factors, variableSlots));
combined->assertInvariants();
return combined;
}
/* ************************************************************************* */
boost::shared_ptr<IndexConditional> IndexFactor::eliminateFirst() { boost::shared_ptr<IndexConditional> IndexFactor::eliminateFirst() {
return Base::eliminateFirst<IndexConditional>(); } boost::shared_ptr<IndexConditional> result(Base::eliminateFirst<IndexConditional>());
assertInvariants();
return result;
}
/* ************************************************************************* */
boost::shared_ptr<BayesNet<IndexConditional> > IndexFactor::eliminate(size_t nrFrontals) { boost::shared_ptr<BayesNet<IndexConditional> > IndexFactor::eliminate(size_t nrFrontals) {
return Base::eliminate<IndexConditional>(nrFrontals); } boost::shared_ptr<BayesNet<IndexConditional> > result(Base::eliminate<IndexConditional>(nrFrontals));
assertInvariants();
return result;
}
} }

View File

@ -41,6 +41,11 @@ namespace gtsam {
*/ */
class IndexFactor : public Factor<Index> { class IndexFactor : public Factor<Index> {
protected:
// Internal function for checking class invariants (sorted keys for this factor)
void assertInvariants() const;
public: public:
typedef IndexFactor This; typedef IndexFactor This;
@ -53,32 +58,32 @@ namespace gtsam {
typedef boost::shared_ptr<IndexFactor> shared_ptr; typedef boost::shared_ptr<IndexFactor> shared_ptr;
/** Copy constructor */ /** Copy constructor */
IndexFactor(const This& f) : Base(f) {} IndexFactor(const This& f) : Base(f) { assertInvariants(); }
/** Construct from derived type */ /** Construct from derived type */
IndexFactor(const IndexConditional& c); IndexFactor(const IndexConditional& c);
/** Constructor from a collection of keys */ /** Constructor from a collection of keys */
template<class KeyIterator> IndexFactor(KeyIterator beginKey, KeyIterator endKey) : template<class KeyIterator> IndexFactor(KeyIterator beginKey, KeyIterator endKey) :
Base(beginKey, endKey) {} Base(beginKey, endKey) { assertInvariants(); }
/** Default constructor for I/O */ /** Default constructor for I/O */
IndexFactor() {} IndexFactor() { assertInvariants(); }
/** Construct unary factor */ /** Construct unary factor */
IndexFactor(Index j) : Base(j) {} IndexFactor(Index j) : Base(j) { assertInvariants(); }
/** Construct binary factor */ /** Construct binary factor */
IndexFactor(Index j1, Index j2) : Base(j1, j2) {} IndexFactor(Index j1, Index j2) : Base(j1, j2) { assertInvariants(); }
/** Construct ternary factor */ /** Construct ternary factor */
IndexFactor(Index j1, Index j2, Index j3) : Base(j1, j2, j3) {} IndexFactor(Index j1, Index j2, Index j3) : Base(j1, j2, j3) { assertInvariants(); }
/** Construct 4-way factor */ /** Construct 4-way factor */
IndexFactor(Index j1, Index j2, Index j3, Index j4) : Base(j1, j2, j3, j4) {} IndexFactor(Index j1, Index j2, Index j3, Index j4) : Base(j1, j2, j3, j4) { assertInvariants(); }
/** Construct n-way factor */ /** Construct n-way factor */
IndexFactor(const std::set<Index>& js) : Base(js) {} IndexFactor(const std::set<Index>& js) : Base(js) { assertInvariants(); }
/** /**
* Combine and eliminate several factors. * Combine and eliminate several factors.

View File

@ -28,6 +28,22 @@ using namespace std;
using namespace gtsam; using namespace gtsam;
using namespace boost::assign; using namespace boost::assign;
/* ************************************************************************* */
TEST(SymbolicFactor, constructor) {
// Frontals sorted, parents not sorted
vector<Index> keys1; keys1 += 3, 4, 5, 9, 7, 8;
(void)IndexConditional::FromRange(keys1.begin(), keys1.end(), 3);
// // Frontals not sorted
// vector<Index> keys2; keys2 += 3, 5, 4, 9, 7, 8;
// (void)IndexConditional::FromRange(keys2.begin(), keys2.end(), 3);
// // Frontals not before parents
// vector<Index> keys3; keys3 += 3, 4, 5, 1, 7, 8;
// (void)IndexConditional::FromRange(keys3.begin(), keys3.end(), 3);
}
/* ************************************************************************* */ /* ************************************************************************* */
TEST(SymbolicFactor, eliminate) { TEST(SymbolicFactor, eliminate) {
vector<Index> keys; keys += 2, 3, 4, 6, 7, 9, 10, 11; vector<Index> keys; keys += 2, 3, 4, 6, 7, 9, 10, 11;