Killed other variants
parent
f4b7ab54b0
commit
d1a62b0cc1
|
@ -18,154 +18,19 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
namespace gtsam {
|
namespace gtsam {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disjoint set forest using an STL map data structure underneath
|
* Disjoint set forest using an STL map data structure underneath
|
||||||
* Uses rank compression but not union by rank :-(
|
* Uses rank compression and union by rank, iterator version
|
||||||
* @addtogroup base
|
* @addtogroup base
|
||||||
*/
|
*/
|
||||||
template<class KEY>
|
template<class KEY>
|
||||||
class DSFMap {
|
class DSFMap {
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
/// We store the forest in an STL map
|
|
||||||
typedef std::map<KEY, KEY> Map;
|
|
||||||
typedef std::set<KEY> Set;
|
|
||||||
typedef std::pair<KEY, KEY> key_pair;
|
|
||||||
mutable Map parent_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// constructor
|
|
||||||
DSFMap() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/// find the label of the set in which {key} lives
|
|
||||||
KEY find(const KEY& key) const {
|
|
||||||
typename Map::const_iterator it = parent_.find(key);
|
|
||||||
// if key does not exist, create and return itself
|
|
||||||
if (it == parent_.end()) {
|
|
||||||
parent_[key] = key;
|
|
||||||
return key;
|
|
||||||
} else {
|
|
||||||
// follow parent pointers until we reach set representative
|
|
||||||
KEY parent = it->second;
|
|
||||||
if (parent != key)
|
|
||||||
parent = find(parent); // not yet, recurse!
|
|
||||||
parent_[key] = parent; // path compression
|
|
||||||
return parent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Merge two sets
|
|
||||||
void merge(const KEY& i1, const KEY& i2) {
|
|
||||||
parent_[find(i2)] = find(i1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// return all sets, i.e. a partition of all elements
|
|
||||||
std::map<KEY, Set> sets() const {
|
|
||||||
std::map<KEY, Set> sets;
|
|
||||||
BOOST_FOREACH(const key_pair& pair, parent_)
|
|
||||||
sets[find(pair.second)].insert(pair.first);
|
|
||||||
return sets;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disjoint set forest using an STL map data structure underneath
|
|
||||||
* Uses rank compression but not union by rank :-(
|
|
||||||
* @addtogroup base
|
|
||||||
*/
|
|
||||||
template<class KEY>
|
|
||||||
class DSFMapIt {
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
/// We store the forest in an STL map, but parents are done with pointers
|
|
||||||
struct Entry {
|
|
||||||
typedef std::map<KEY, Entry> Map;
|
|
||||||
typename Map::iterator parent_;
|
|
||||||
size_t rank_;
|
|
||||||
Entry() :
|
|
||||||
rank_(0) {
|
|
||||||
}
|
|
||||||
void makeRoot(const typename Map::iterator& it) {
|
|
||||||
parent_ = it;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
mutable typename Entry::Map entries_;
|
|
||||||
|
|
||||||
/// find the initial Entry
|
|
||||||
typename Entry::Map::iterator find__(const KEY& key) const {
|
|
||||||
typename Entry::Map::iterator it = entries_.find(key);
|
|
||||||
// if key does not exist, create and return itself
|
|
||||||
if (it == entries_.end()) {
|
|
||||||
it = entries_.insert(it, std::make_pair(key, Entry()));
|
|
||||||
it->second.makeRoot(it);
|
|
||||||
}
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// find the root Entry
|
|
||||||
typename Entry::Map::iterator find_(const KEY& key) const {
|
|
||||||
typename Entry::Map::iterator initial = find__(key);
|
|
||||||
// follow parent pointers until we reach set representative
|
|
||||||
typename Entry::Map::iterator parent = initial->second.parent_;
|
|
||||||
while (parent->second.parent_ != parent)
|
|
||||||
parent = parent->second.parent_; // not yet, recurse!
|
|
||||||
//initial.parent_ = parent; // path compression
|
|
||||||
return parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// constructor
|
|
||||||
DSFMapIt() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/// find the representative KEY for the set in which key lives
|
|
||||||
KEY find(const KEY& key) const {
|
|
||||||
typename Entry::Map::iterator root = find_(key);
|
|
||||||
return root->first;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Merge two sets
|
|
||||||
void merge(const KEY& x, const KEY& y) {
|
|
||||||
|
|
||||||
// straight from http://en.wikipedia.org/wiki/Disjoint-set_data_structure
|
|
||||||
typename Entry::Map::iterator xRoot = find_(x);
|
|
||||||
typename Entry::Map::iterator yRoot = find_(y);
|
|
||||||
if (xRoot == yRoot)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Merge sets
|
|
||||||
size_t xRootRank = xRoot->second.rank_, yRootRank = yRoot->second.rank_;
|
|
||||||
if (xRootRank < yRootRank)
|
|
||||||
xRoot->second.parent_ = yRoot;
|
|
||||||
else if (xRootRank > yRootRank)
|
|
||||||
yRoot->second.parent_ = xRoot;
|
|
||||||
else {
|
|
||||||
yRoot->second.parent_ = xRoot;
|
|
||||||
xRoot->second.rank_ = xRootRank + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disjoint set forest using an STL map data structure underneath
|
|
||||||
* Uses rank compression but not union by rank :-(
|
|
||||||
* @addtogroup base
|
|
||||||
*/
|
|
||||||
template<class KEY>
|
|
||||||
class DSFMap2 {
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/// We store the forest in an STL map, but parents are done with pointers
|
/// We store the forest in an STL map, but parents are done with pointers
|
||||||
|
@ -180,37 +45,46 @@ protected:
|
||||||
parent_ = this;
|
parent_ = this;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::map<KEY, Entry> Map;
|
typedef std::map<KEY, Entry> Map;
|
||||||
mutable Map entries_;
|
mutable Map entries_;
|
||||||
|
|
||||||
/// find the initial Entry
|
/// Given key, find iterator to initial entry
|
||||||
Entry& find__(const KEY& key) const {
|
typename Map::iterator find__(const KEY& key) const {
|
||||||
typename Map::iterator it = entries_.find(key);
|
typename Map::iterator it = entries_.find(key);
|
||||||
// if key does not exist, create and return itself
|
// if key does not exist, create and return itself
|
||||||
if (it == entries_.end()) {
|
if (it == entries_.end()) {
|
||||||
it = entries_.insert(it, std::make_pair(key, Entry(key)));
|
it = entries_.insert(it, std::make_pair(key, Entry(key)));
|
||||||
it->second.makeRoot();
|
it->second.makeRoot();
|
||||||
}
|
}
|
||||||
return it->second;
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// find the root Entry
|
/// Given iterator to initial entry, find the root Entry
|
||||||
Entry* find_(const KEY& key) const {
|
Entry* find_(const typename Map::iterator& it) const {
|
||||||
Entry& initial = find__(key);
|
|
||||||
// follow parent pointers until we reach set representative
|
// follow parent pointers until we reach set representative
|
||||||
Entry* parent = initial.parent_;
|
Entry* parent = it->second.parent_;
|
||||||
while (parent->parent_ != parent)
|
while (parent->parent_ != parent)
|
||||||
parent = parent->parent_; // not yet, recurse!
|
parent = parent->parent_; // not yet, recurse!
|
||||||
initial.parent_ = parent; // path compression
|
it->second.parent_ = parent; // path compression
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
/// Given key, find the root Entry
|
||||||
/// constructor
|
Entry* find_(const KEY& key) const {
|
||||||
DSFMap2() {
|
typename Map::iterator it = find__(key);
|
||||||
|
return find_(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// find the representative KEY for the set in which key lives
|
public:
|
||||||
|
|
||||||
|
typedef std::set<KEY> Set;
|
||||||
|
|
||||||
|
/// constructor
|
||||||
|
DSFMap() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Given key, find the representative key for the set in which it lives
|
||||||
KEY find(const KEY& key) const {
|
KEY find(const KEY& key) const {
|
||||||
Entry* root = find_(key);
|
Entry* root = find_(key);
|
||||||
return root->key_;
|
return root->key_;
|
||||||
|
@ -236,48 +110,15 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
/// return all sets, i.e. a partition of all elements
|
||||||
|
std::map<KEY, Set> sets() const {
|
||||||
/**
|
std::map<KEY, Set> sets;
|
||||||
* DSFMap version that uses union by rank :-)
|
typename Map::iterator it = entries_.begin();
|
||||||
* @addtogroup base
|
for(;it!=entries_.end();it++) {
|
||||||
*/
|
Entry* root = find_(it);
|
||||||
template<class KEY>
|
sets[root->key_].insert(it->first);
|
||||||
class DSFMap3: public DSFMap<KEY> {
|
|
||||||
|
|
||||||
/// We store rank in an STL map as well
|
|
||||||
typedef std::map<KEY, size_t> Ranks;
|
|
||||||
mutable Ranks rank_;
|
|
||||||
|
|
||||||
size_t rank(const KEY& i) const {
|
|
||||||
typename Ranks::const_iterator it = rank_.find(i);
|
|
||||||
return it == rank_.end() ? 0 : it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// constructor
|
|
||||||
DSFMap3() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Merge two sets
|
|
||||||
void merge(const KEY& x, const KEY& y) {
|
|
||||||
|
|
||||||
// straight from http://en.wikipedia.org/wiki/Disjoint-set_data_structure
|
|
||||||
KEY xRoot = this->find(x);
|
|
||||||
KEY yRoot = this->find(y);
|
|
||||||
if (xRoot == yRoot)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Merge sets
|
|
||||||
size_t xRootRank = rank(xRoot), yRootRank = rank(yRoot);
|
|
||||||
if (xRootRank < yRootRank)
|
|
||||||
this->parent_[xRoot] = yRoot;
|
|
||||||
else if (xRootRank > yRootRank)
|
|
||||||
this->parent_[yRoot] = xRoot;
|
|
||||||
else {
|
|
||||||
this->parent_[yRoot] = xRoot;
|
|
||||||
this->rank_[xRoot] = xRootRank + 1;
|
|
||||||
}
|
}
|
||||||
|
return sets;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -32,7 +32,7 @@ using namespace gtsam;
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
TEST(DSFMap, find) {
|
TEST(DSFMap, find) {
|
||||||
DSFMapIt<size_t> dsf;
|
DSFMap<size_t> dsf;
|
||||||
EXPECT(dsf.find(0)==0);
|
EXPECT(dsf.find(0)==0);
|
||||||
EXPECT(dsf.find(2)==2);
|
EXPECT(dsf.find(2)==2);
|
||||||
EXPECT(dsf.find(0)==0);
|
EXPECT(dsf.find(0)==0);
|
||||||
|
@ -42,21 +42,21 @@ TEST(DSFMap, find) {
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
TEST(DSFMap, merge) {
|
TEST(DSFMap, merge) {
|
||||||
DSFMapIt<size_t> dsf;
|
DSFMap<size_t> dsf;
|
||||||
dsf.merge(0,2);
|
dsf.merge(0,2);
|
||||||
EXPECT(dsf.find(0) == dsf.find(2));
|
EXPECT(dsf.find(0) == dsf.find(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
TEST(DSFMap, merge2) {
|
TEST(DSFMap, merge2) {
|
||||||
DSFMapIt<size_t> dsf;
|
DSFMap<size_t> dsf;
|
||||||
dsf.merge(2,0);
|
dsf.merge(2,0);
|
||||||
EXPECT(dsf.find(0) == dsf.find(2));
|
EXPECT(dsf.find(0) == dsf.find(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
TEST(DSFMap, merge3) {
|
TEST(DSFMap, merge3) {
|
||||||
DSFMapIt<size_t> dsf;
|
DSFMap<size_t> dsf;
|
||||||
dsf.merge(0,1);
|
dsf.merge(0,1);
|
||||||
dsf.merge(1,2);
|
dsf.merge(1,2);
|
||||||
EXPECT(dsf.find(0) == dsf.find(2));
|
EXPECT(dsf.find(0) == dsf.find(2));
|
||||||
|
@ -71,7 +71,7 @@ TEST(DSFMap, mergePairwiseMatches) {
|
||||||
matches += Match(1,2), Match(2,3), Match(4,5), Match(4,6);
|
matches += Match(1,2), Match(2,3), Match(4,5), Match(4,6);
|
||||||
|
|
||||||
// Merge matches
|
// Merge matches
|
||||||
DSFMapIt<size_t> dsf;
|
DSFMap<size_t> dsf;
|
||||||
BOOST_FOREACH(const Match& m, matches)
|
BOOST_FOREACH(const Match& m, matches)
|
||||||
dsf.merge(m.first,m.second);
|
dsf.merge(m.first,m.second);
|
||||||
|
|
||||||
|
@ -101,7 +101,7 @@ TEST(DSFMap, mergePairwiseMatches2) {
|
||||||
matches += Match(m11,m22), Match(m12,m23), Match(m14,m25), Match(m14,m26);
|
matches += Match(m11,m22), Match(m12,m23), Match(m14,m25), Match(m14,m26);
|
||||||
|
|
||||||
// Merge matches
|
// Merge matches
|
||||||
DSFMapIt<Measurement> dsf;
|
DSFMap<Measurement> dsf;
|
||||||
BOOST_FOREACH(const Match& m, matches)
|
BOOST_FOREACH(const Match& m, matches)
|
||||||
dsf.merge(m.first,m.second);
|
dsf.merge(m.first,m.second);
|
||||||
|
|
||||||
|
|
|
@ -82,17 +82,7 @@ int main(int argc, char* argv[]) {
|
||||||
{
|
{
|
||||||
// DSFMap version
|
// DSFMap version
|
||||||
timer tim;
|
timer tim;
|
||||||
DSFMapIt<size_t> dsf;
|
DSFMap<size_t> dsf;
|
||||||
BOOST_FOREACH(const Match& m, matches)
|
|
||||||
dsf.merge(m.first, m.second);
|
|
||||||
os << tim.elapsed() << ",";
|
|
||||||
cout << format("DSFMap: %1% s") % tim.elapsed() << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// DSFMap2 version
|
|
||||||
timer tim;
|
|
||||||
DSFMap2<size_t> dsf;
|
|
||||||
BOOST_FOREACH(const Match& m, matches)
|
BOOST_FOREACH(const Match& m, matches)
|
||||||
dsf.merge(m.first, m.second);
|
dsf.merge(m.first, m.second);
|
||||||
os << tim.elapsed() << endl;
|
os << tim.elapsed() << endl;
|
||||||
|
|
Loading…
Reference in New Issue