make DSFVector support preallocated memory

release/4.3a0
Kai Ni 2010-11-25 05:15:40 +00:00
parent 06c319f42c
commit 0625267187
3 changed files with 100 additions and 22 deletions

View File

@ -18,6 +18,8 @@
* As a result, the size of the forest is prefixed.
*/
#include <boost/make_shared.hpp>
#include <boost/foreach.hpp>
#include <gtsam/base/DSFVector.h>
using namespace std;
@ -26,23 +28,27 @@ namespace gtsam {
/* ************************************************************************* */
DSFVector::DSFVector (const size_t numNodes) {
resize(numNodes);
v_ = boost::make_shared<V>(numNodes);
int index = 0;
for(iterator it = begin(); it!=end(); it++, index++)
keys_.reserve(numNodes);
for(V::iterator it = v_->begin(); it!=v_->end(); it++, index++) {
*it = index;
keys_.push_back(index);
}
}
/* ************************************************************************* */
DSFVector::Label DSFVector::findSet(const size_t& key) const {
size_t parent = at(key);
return parent == key ? key : findSet(parent);
DSFVector::DSFVector(const boost::shared_ptr<V>& v_in, const std::vector<size_t>& keys) : keys_(keys) {
v_ = v_in;
BOOST_FOREACH(const size_t key, keys)
(*v_)[key] = key;
}
/* ************************************************************************* */
bool DSFVector::isSingleton(const Label& label) const {
bool result = false;
std::vector<size_t>::const_iterator it = begin();
for (; it != end(); ++it) {
V::const_iterator it = keys_.begin();
for (; it != keys_.end(); ++it) {
if(findSet(*it) == label) {
if (!result) // find the first occurrence
result = true;
@ -56,11 +62,10 @@ namespace gtsam {
/* ************************************************************************* */
std::set<size_t> DSFVector::set(const Label& label) const {
std::set<size_t> set;
size_t key = 0;
std::vector<size_t>::const_iterator it = begin();
for (; it != end(); it++, key++) {
V::const_iterator it = keys_.begin();
for (; it != keys_.end(); it++) {
if (findSet(*it) == label)
set.insert(key);
set.insert(*it);
}
return set;
}
@ -68,17 +73,26 @@ namespace gtsam {
/* ************************************************************************* */
std::map<DSFVector::Label, std::set<size_t> > DSFVector::sets() const {
std::map<Label, std::set<size_t> > sets;
size_t key = 0;
std::vector<size_t>::const_iterator it = begin();
for (; it != end(); it++, key++) {
sets[findSet(*it)].insert(key);
V::const_iterator it = keys_.begin();
for (; it != keys_.end(); it++) {
sets[findSet(*it)].insert(*it);
}
return sets;
}
/* ************************************************************************* */
std::map<DSFVector::Label, std::vector<size_t> > DSFVector::arrays() const {
std::map<Label, std::vector<size_t> > arrays;
V::const_iterator it = keys_.begin();
for (; it != keys_.end(); it++) {
arrays[findSet(*it)].push_back(*it);
}
return arrays;
}
/* ************************************************************************* */
void DSFVector::makeUnionInPlace(const size_t& i1, const size_t& i2) {
at(findSet(i2)) = findSet(i1);
(*v_)[findSet(i2)] = findSet(i1);
}
} // namespace

View File

@ -23,23 +23,41 @@
#include <vector>
#include <map>
#include <set>
#include <boost/shared_ptr.hpp>
namespace gtsam {
/**
* A fast impelementation of disjoint set forests that uses vector as underly data structure.
*/
class DSFVector : protected std::vector<std::size_t> {
private:
class DSFVector {
public:
typedef std::vector<size_t> V;
typedef size_t Label;
typedef std::vector<size_t>::const_iterator const_iterator;
typedef std::vector<size_t>::iterator iterator;
// constructor
DSFVector(const std::size_t numNodes);
private:
boost::shared_ptr<V> v_; // could use existing memory to improve the efficiency
std::vector<size_t> keys_;
public:
// constructor that allocate a new memory
DSFVector(const size_t numNodes);
// 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
Label findSet(const size_t& key) const;
inline Label findSet(size_t key) const {
size_t parent = (*v_)[key];
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 Label& label) const;
@ -49,9 +67,10 @@ namespace gtsam {
// return all sets, i.e. a partition of all elements
std::map<Label, std::set<size_t> > sets() const;
std::map<Label, std::vector<size_t> > arrays() const;
// the in-place version of makeUnion
void makeUnionInPlace(const std::size_t& i1, const std::size_t& i2);
void makeUnionInPlace(const size_t& i1, const size_t& i2);
};

View File

@ -18,8 +18,10 @@
*/
#include <iostream>
#include <boost/make_shared.hpp>
#include <boost/assign/std/list.hpp>
#include <boost/assign/std/set.hpp>
#include <boost/assign/std/vector.hpp>
using namespace boost::assign;
#include <CppUnitLite/TestHarness.h>
@ -41,6 +43,15 @@ TEST(DSFVectorVector, makeUnionInPlace) {
CHECK(dsf.findSet(0) == dsf.findSet(2));
}
/* ************************************************************************* */
TEST(DSFVectorVector, makeUnionInPlace2) {
boost::shared_ptr<DSFVector::V> v = boost::make_shared<DSFVector::V>(5);
std::vector<size_t> keys; keys += 1, 3;
DSFVector dsf(v, keys);
dsf.makeUnionInPlace(1,3);
CHECK(dsf.findSet(1) == dsf.findSet(3));
}
/* ************************************************************************* */
TEST(DSFVector, makeUnion2) {
DSFVector dsf(3);
@ -67,6 +78,17 @@ TEST(DSFVector, sets) {
CHECK(expected == sets[dsf.findSet(0)]);
}
/* ************************************************************************* */
TEST(DSFVector, arrays) {
DSFVector dsf(2);
dsf.makeUnionInPlace(0,1);
map<size_t, vector<size_t> > arrays = dsf.arrays();
LONGS_EQUAL(1, arrays.size());
vector<size_t> expected; expected += 0, 1;
CHECK(expected == arrays[dsf.findSet(0)]);
}
/* ************************************************************************* */
TEST(DSFVector, sets2) {
DSFVector dsf(3);
@ -79,6 +101,18 @@ TEST(DSFVector, sets2) {
CHECK(expected == sets[dsf.findSet(0)]);
}
/* ************************************************************************* */
TEST(DSFVector, arrays2) {
DSFVector dsf(3);
dsf.makeUnionInPlace(0,1);
dsf.makeUnionInPlace(1,2);
map<size_t, vector<size_t> > arrays = dsf.arrays();
LONGS_EQUAL(1, arrays.size());
vector<size_t> expected; expected += 0, 1, 2;
CHECK(expected == arrays[dsf.findSet(0)]);
}
/* ************************************************************************* */
TEST(DSFVector, sets3) {
DSFVector dsf(3);
@ -90,6 +124,17 @@ TEST(DSFVector, sets3) {
CHECK(expected == sets[dsf.findSet(0)]);
}
/* ************************************************************************* */
TEST(DSFVector, arrays3) {
DSFVector dsf(3);
dsf.makeUnionInPlace(0,1);
map<size_t, vector<size_t> > arrays = dsf.arrays();
LONGS_EQUAL(2, arrays.size());
vector<size_t> expected; expected += 0, 1;
CHECK(expected == arrays[dsf.findSet(0)]);
}
/* ************************************************************************* */
TEST(DSFVector, set) {
DSFVector dsf(3);