Split DSFVector into two classes

release/4.3a0
Frank Dellaert 2013-10-26 15:16:41 +00:00
parent 0dbd016ca9
commit ddd7c6663f
3 changed files with 60 additions and 40 deletions

View File

@ -26,33 +26,55 @@ using namespace std;
namespace gtsam {
/* ************************************************************************* */
DSFVector::DSFVector(const size_t numNodes) {
DSFBase::DSFBase(const size_t numNodes) {
v_ = boost::make_shared < V > (numNodes);
int index = 0;
keys_.reserve(numNodes);
for (V::iterator it = v_->begin(); it != v_->end(); it++, index++) {
for (V::iterator it = v_->begin(); it != v_->end(); it++, index++)
*it = index;
keys_.push_back(index);
}
/* ************************************************************************* */
DSFBase::DSFBase(const boost::shared_ptr<V>& v_in) {
v_ = v_in;
int index = 0;
for (V::iterator it = v_->begin(); it != v_->end(); it++, index++)
*it = index;
}
/* ************************************************************************* */
size_t DSFBase::findSet(size_t key) const {
size_t parent = (*v_)[key];
// follow parent pointers until we reach set representative
while (parent != key) {
key = parent;
parent = (*v_)[key];
}
return parent;
}
/* ************************************************************************* */
void DSFBase::makeUnionInPlace(const size_t& i1, const size_t& i2) {
(*v_)[findSet(i2)] = findSet(i1);
}
/* ************************************************************************* */
DSFVector::DSFVector(const size_t numNodes) :
DSFBase(numNodes) {
keys_.reserve(numNodes);
for (size_t index = 0; index < numNodes; index++)
keys_.push_back(index);
}
/* ************************************************************************* */
DSFVector::DSFVector(const std::vector<size_t>& keys) :
keys_(keys) {
size_t maxKey = *(std::max_element(keys.begin(), keys.end()));
v_ = boost::make_shared < V > (maxKey + 1);
BOOST_FOREACH(const size_t key, keys)
(*v_)[key] = key;
DSFBase(1 + *std::max_element(keys.begin(), keys.end())), keys_(keys) {
}
/* ************************************************************************* */
DSFVector::DSFVector(const boost::shared_ptr<V>& v_in,
const std::vector<size_t>& keys) :
keys_(keys) {
DSFBase(v_in), keys_(keys) {
assert(*(std::max_element(keys.begin(), keys.end()))<v_in->size());
v_ = v_in;
BOOST_FOREACH(const size_t key, keys)
(*v_)[key] = key;
}
/* ************************************************************************* */
@ -94,10 +116,5 @@ std::map<size_t, std::vector<size_t> > DSFVector::arrays() const {
return arrays;
}
/* ************************************************************************* */
void DSFVector::makeUnionInPlace(const size_t& i1, const size_t& i2) {
(*v_)[findSet(i2)] = findSet(i1);
}
} // namespace gtsam

View File

@ -28,16 +28,39 @@ namespace gtsam {
/**
* A fast implementation of disjoint set forests that uses vector as underly data structure.
* This is the absolute minimal DSF data structure, and only allows size_t keys
* @addtogroup base
*/
class GTSAM_EXPORT DSFVector {
class GTSAM_EXPORT DSFBase {
public:
typedef std::vector<size_t> V; ///< Vector of ints
private:
boost::shared_ptr<V> v_;///< Stores parent pointers, representative iff v[i]==i
std::vector<size_t> keys_;///< stores keys
public:
/// constructor that allocate new memory, allows for keys 0...numNodes-1
DSFBase(const size_t numNodes);
/// constructor that uses the existing memory
DSFBase(const boost::shared_ptr<V>& v_in);
/// find the label of the set in which {key} lives
size_t findSet(size_t key) const;
/// the in-place version of makeUnion
void makeUnionInPlace(const size_t& i1, const size_t& i2);
};
/**
* A fast implementation of disjoint set forests that uses vector as underly data structure.
* @addtogroup base
*/
class GTSAM_EXPORT DSFVector: public DSFBase {
private:
std::vector<size_t> keys_;///< stores keys to support more expensive operations
public:
/// constructor that allocate new memory, uses sequential keys 0...numNodes-1
@ -49,17 +72,6 @@ public:
/// constructor that uses the existing memory
DSFVector(const boost::shared_ptr<V>& v_in, const std::vector<size_t>& keys);
/// find the label of the set in which {key} lives
inline size_t findSet(size_t key) const {
size_t parent = (*v_)[key];
// follow parent pointers until we reach set representative
while (parent != key) {
key = parent;
parent = (*v_)[key];
}
return parent;
}
/// find whether there is one and only one occurrence for the given {label}
bool isSingleton(const size_t& label) const;
@ -71,9 +83,6 @@ public:
/// return all sets, i.e. a partition of all elements
std::map<size_t, std::vector<size_t> > arrays() const;
/// the in-place version of makeUnion
void makeUnionInPlace(const size_t& i1, const size_t& i2);
};
}

View File

@ -186,9 +186,6 @@ TEST(DSFVector, mergePairwiseMatches) {
BOOST_FOREACH(const Match& m, matches)
dsf.makeUnionInPlace(m.first,m.second);
cout << endl;
map<size_t, set<size_t> > sets1 = dsf.sets();
// Each point is now associated with a set, represented by one of its members
size_t rep1 = 1, rep2 = 4;
EXPECT_LONGS_EQUAL(rep1,dsf.findSet(1));
@ -199,16 +196,13 @@ TEST(DSFVector, mergePairwiseMatches) {
EXPECT_LONGS_EQUAL(rep2,dsf.findSet(6));
// Check that we have two connected components, 1,2,3 and 4,5,6
cout << endl;
map<size_t, set<size_t> > sets = dsf.sets();
LONGS_EQUAL(2, sets.size());
set<size_t> expected1; expected1 += 1,2,3;
set<size_t> actual1 = sets[rep1];
BOOST_FOREACH(size_t i, actual1) cout << i << " ";
EXPECT(expected1 == actual1);
set<size_t> expected2; expected2 += 4,5,6;
set<size_t> actual2 = sets[rep2];
BOOST_FOREACH(size_t i, actual2) cout << i << " ";
EXPECT(expected2 == actual2);
}