make DSFVector support preallocated memory
parent
06c319f42c
commit
0625267187
|
|
@ -18,6 +18,8 @@
|
||||||
* As a result, the size of the forest is prefixed.
|
* As a result, the size of the forest is prefixed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <boost/make_shared.hpp>
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
#include <gtsam/base/DSFVector.h>
|
#include <gtsam/base/DSFVector.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
@ -26,23 +28,27 @@ namespace gtsam {
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
DSFVector::DSFVector (const size_t numNodes) {
|
DSFVector::DSFVector (const size_t numNodes) {
|
||||||
resize(numNodes);
|
v_ = boost::make_shared<V>(numNodes);
|
||||||
int index = 0;
|
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;
|
*it = index;
|
||||||
|
keys_.push_back(index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
DSFVector::Label DSFVector::findSet(const size_t& key) const {
|
DSFVector::DSFVector(const boost::shared_ptr<V>& v_in, const std::vector<size_t>& keys) : keys_(keys) {
|
||||||
size_t parent = at(key);
|
v_ = v_in;
|
||||||
return parent == key ? key : findSet(parent);
|
BOOST_FOREACH(const size_t key, keys)
|
||||||
|
(*v_)[key] = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
bool DSFVector::isSingleton(const Label& label) const {
|
bool DSFVector::isSingleton(const Label& label) const {
|
||||||
bool result = false;
|
bool result = false;
|
||||||
std::vector<size_t>::const_iterator it = begin();
|
V::const_iterator it = keys_.begin();
|
||||||
for (; it != end(); ++it) {
|
for (; it != keys_.end(); ++it) {
|
||||||
if(findSet(*it) == label) {
|
if(findSet(*it) == label) {
|
||||||
if (!result) // find the first occurrence
|
if (!result) // find the first occurrence
|
||||||
result = true;
|
result = true;
|
||||||
|
|
@ -56,11 +62,10 @@ namespace gtsam {
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
std::set<size_t> DSFVector::set(const Label& label) const {
|
std::set<size_t> DSFVector::set(const Label& label) const {
|
||||||
std::set<size_t> set;
|
std::set<size_t> set;
|
||||||
size_t key = 0;
|
V::const_iterator it = keys_.begin();
|
||||||
std::vector<size_t>::const_iterator it = begin();
|
for (; it != keys_.end(); it++) {
|
||||||
for (; it != end(); it++, key++) {
|
|
||||||
if (findSet(*it) == label)
|
if (findSet(*it) == label)
|
||||||
set.insert(key);
|
set.insert(*it);
|
||||||
}
|
}
|
||||||
return set;
|
return set;
|
||||||
}
|
}
|
||||||
|
|
@ -68,17 +73,26 @@ namespace gtsam {
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
std::map<DSFVector::Label, std::set<size_t> > DSFVector::sets() const {
|
std::map<DSFVector::Label, std::set<size_t> > DSFVector::sets() const {
|
||||||
std::map<Label, std::set<size_t> > sets;
|
std::map<Label, std::set<size_t> > sets;
|
||||||
size_t key = 0;
|
V::const_iterator it = keys_.begin();
|
||||||
std::vector<size_t>::const_iterator it = begin();
|
for (; it != keys_.end(); it++) {
|
||||||
for (; it != end(); it++, key++) {
|
sets[findSet(*it)].insert(*it);
|
||||||
sets[findSet(*it)].insert(key);
|
|
||||||
}
|
}
|
||||||
return sets;
|
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) {
|
void DSFVector::makeUnionInPlace(const size_t& i1, const size_t& i2) {
|
||||||
at(findSet(i2)) = findSet(i1);
|
(*v_)[findSet(i2)] = findSet(i1);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
||||||
|
|
@ -23,23 +23,41 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
namespace gtsam {
|
namespace gtsam {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A fast impelementation of disjoint set forests that uses vector as underly data structure.
|
* A fast impelementation of disjoint set forests that uses vector as underly data structure.
|
||||||
*/
|
*/
|
||||||
class DSFVector : protected std::vector<std::size_t> {
|
class DSFVector {
|
||||||
private:
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
typedef std::vector<size_t> V;
|
||||||
typedef size_t Label;
|
typedef size_t Label;
|
||||||
|
typedef std::vector<size_t>::const_iterator const_iterator;
|
||||||
|
typedef std::vector<size_t>::iterator iterator;
|
||||||
|
|
||||||
// constructor
|
private:
|
||||||
DSFVector(const std::size_t numNodes);
|
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
|
// 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}
|
// find whether there is one and only one occurrence for the given {label}
|
||||||
bool isSingleton(const Label& label) const;
|
bool isSingleton(const Label& label) const;
|
||||||
|
|
@ -49,9 +67,10 @@ namespace gtsam {
|
||||||
|
|
||||||
// return all sets, i.e. a partition of all elements
|
// return all sets, i.e. a partition of all elements
|
||||||
std::map<Label, std::set<size_t> > sets() const;
|
std::map<Label, std::set<size_t> > sets() const;
|
||||||
|
std::map<Label, std::vector<size_t> > arrays() const;
|
||||||
|
|
||||||
// the in-place version of makeUnion
|
// 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);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <boost/make_shared.hpp>
|
||||||
#include <boost/assign/std/list.hpp>
|
#include <boost/assign/std/list.hpp>
|
||||||
#include <boost/assign/std/set.hpp>
|
#include <boost/assign/std/set.hpp>
|
||||||
|
#include <boost/assign/std/vector.hpp>
|
||||||
using namespace boost::assign;
|
using namespace boost::assign;
|
||||||
#include <CppUnitLite/TestHarness.h>
|
#include <CppUnitLite/TestHarness.h>
|
||||||
|
|
||||||
|
|
@ -41,6 +43,15 @@ TEST(DSFVectorVector, makeUnionInPlace) {
|
||||||
CHECK(dsf.findSet(0) == dsf.findSet(2));
|
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) {
|
TEST(DSFVector, makeUnion2) {
|
||||||
DSFVector dsf(3);
|
DSFVector dsf(3);
|
||||||
|
|
@ -67,6 +78,17 @@ TEST(DSFVector, sets) {
|
||||||
CHECK(expected == sets[dsf.findSet(0)]);
|
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) {
|
TEST(DSFVector, sets2) {
|
||||||
DSFVector dsf(3);
|
DSFVector dsf(3);
|
||||||
|
|
@ -79,6 +101,18 @@ TEST(DSFVector, sets2) {
|
||||||
CHECK(expected == sets[dsf.findSet(0)]);
|
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) {
|
TEST(DSFVector, sets3) {
|
||||||
DSFVector dsf(3);
|
DSFVector dsf(3);
|
||||||
|
|
@ -90,6 +124,17 @@ TEST(DSFVector, sets3) {
|
||||||
CHECK(expected == sets[dsf.findSet(0)]);
|
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) {
|
TEST(DSFVector, set) {
|
||||||
DSFVector dsf(3);
|
DSFVector dsf(3);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue