DSF with Map, allows more general types
parent
af0de393ea
commit
48dd3cb769
|
@ -487,6 +487,14 @@
|
||||||
<useDefaultCommand>true</useDefaultCommand>
|
<useDefaultCommand>true</useDefaultCommand>
|
||||||
<runAllBuilders>true</runAllBuilders>
|
<runAllBuilders>true</runAllBuilders>
|
||||||
</target>
|
</target>
|
||||||
|
<target name="testDSFMap.run" path="build/gtsam_unstable/base" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||||
|
<buildCommand>make</buildCommand>
|
||||||
|
<buildArguments>-j5</buildArguments>
|
||||||
|
<buildTarget>testDSFMap.run</buildTarget>
|
||||||
|
<stopOnError>true</stopOnError>
|
||||||
|
<useDefaultCommand>true</useDefaultCommand>
|
||||||
|
<runAllBuilders>true</runAllBuilders>
|
||||||
|
</target>
|
||||||
<target name="all" path="release" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
<target name="all" path="release" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||||
<buildCommand>make</buildCommand>
|
<buildCommand>make</buildCommand>
|
||||||
<buildArguments>-j2</buildArguments>
|
<buildArguments>-j2</buildArguments>
|
||||||
|
|
|
@ -33,13 +33,13 @@ using namespace std;
|
||||||
using namespace gtsam;
|
using namespace gtsam;
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
TEST(DSFVectorVector, find) {
|
TEST(DSFBase, find) {
|
||||||
DSFBase dsf(3);
|
DSFBase dsf(3);
|
||||||
EXPECT(dsf.find(0) != dsf.find(2));
|
EXPECT(dsf.find(0) != dsf.find(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
TEST(DSFVectorVector, merge) {
|
TEST(DSFBase, merge) {
|
||||||
DSFBase dsf(3);
|
DSFBase dsf(3);
|
||||||
dsf.merge(0,2);
|
dsf.merge(0,2);
|
||||||
EXPECT(dsf.find(0) == dsf.find(2));
|
EXPECT(dsf.find(0) == dsf.find(2));
|
||||||
|
|
|
@ -18,12 +18,12 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <gtsam_unstable/base/BTree.h>
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
#include <gtsam_unstable/base/BTree.h>
|
|
||||||
|
|
||||||
namespace gtsam {
|
namespace gtsam {
|
||||||
|
|
||||||
|
@ -40,11 +40,10 @@ namespace gtsam {
|
||||||
class DSF : protected BTree<KEY, KEY> {
|
class DSF : protected BTree<KEY, KEY> {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef KEY Label; // label can be different from key, but for now they are same
|
|
||||||
typedef DSF<KEY> Self;
|
typedef DSF<KEY> Self;
|
||||||
typedef std::set<KEY> Set;
|
typedef std::set<KEY> Set;
|
||||||
typedef BTree<KEY, Label> Tree;
|
typedef BTree<KEY, KEY> Tree;
|
||||||
typedef std::pair<KEY, Label> KeyLabel;
|
typedef std::pair<KEY, KEY> KeyLabel;
|
||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
DSF() : Tree() { }
|
DSF() : Tree() { }
|
||||||
|
@ -62,7 +61,7 @@ namespace gtsam {
|
||||||
Self makeSet(const KEY& key) const { if (this->mem(key)) return *this; else return this->add(key, key); }
|
Self makeSet(const KEY& key) const { if (this->mem(key)) return *this; else return this->add(key, key); }
|
||||||
|
|
||||||
// find the label of the set in which {key} lives
|
// find the label of the set in which {key} lives
|
||||||
Label findSet(const KEY& key) const {
|
KEY findSet(const KEY& key) const {
|
||||||
KEY parent = this->find(key);
|
KEY parent = this->find(key);
|
||||||
return parent == key ? key : findSet(parent); }
|
return parent == key ? key : findSet(parent); }
|
||||||
|
|
||||||
|
@ -111,23 +110,23 @@ namespace gtsam {
|
||||||
size_t size() const { return Tree::size(); }
|
size_t size() const { return Tree::size(); }
|
||||||
|
|
||||||
// return all sets, i.e. a partition of all elements
|
// return all sets, i.e. a partition of all elements
|
||||||
std::map<Label, Set> sets() const {
|
std::map<KEY, Set> sets() const {
|
||||||
std::map<Label, Set> sets;
|
std::map<KEY, Set> sets;
|
||||||
BOOST_FOREACH(const KeyLabel& pair, (Tree)*this)
|
BOOST_FOREACH(const KeyLabel& pair, (Tree)*this)
|
||||||
sets[findSet(pair.second)].insert(pair.first);
|
sets[findSet(pair.second)].insert(pair.first);
|
||||||
return sets;
|
return sets;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return a partition of the given elements {keys}
|
// return a partition of the given elements {keys}
|
||||||
std::map<Label, Set> partition(const std::list<KEY>& keys) const {
|
std::map<KEY, Set> partition(const std::list<KEY>& keys) const {
|
||||||
std::map<Label, Set> partitions;
|
std::map<KEY, Set> partitions;
|
||||||
BOOST_FOREACH(const KEY& key, keys)
|
BOOST_FOREACH(const KEY& key, keys)
|
||||||
partitions[findSet(key)].insert(key);
|
partitions[findSet(key)].insert(key);
|
||||||
return partitions;
|
return partitions;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the nodes in the tree with the given label
|
// get the nodes in the tree with the given label
|
||||||
Set set(const Label& label) const {
|
Set set(const KEY& label) const {
|
||||||
Set set;
|
Set set;
|
||||||
BOOST_FOREACH(const KeyLabel& pair, (Tree)*this) {
|
BOOST_FOREACH(const KeyLabel& pair, (Tree)*this) {
|
||||||
if (pair.second == label || findSet(pair.second) == label)
|
if (pair.second == label || findSet(pair.second) == label)
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
|
||||||
|
* Atlanta, Georgia 30332-0415
|
||||||
|
* All Rights Reserved
|
||||||
|
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
|
||||||
|
|
||||||
|
* See LICENSE for the license information
|
||||||
|
|
||||||
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file DSFMap.h
|
||||||
|
* @date Oct 26, 2013
|
||||||
|
* @author Frank Dellaert
|
||||||
|
* @brief Allow for arbitrary type in DSF
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace gtsam {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disjoint set forest using an STL map data structure underneath
|
||||||
|
* Uses rank compression but not union by rank :-(
|
||||||
|
* @addtogroup base
|
||||||
|
*/
|
||||||
|
template<class KEY>
|
||||||
|
class DSFMap {
|
||||||
|
|
||||||
|
/// We store the forest in an STL map
|
||||||
|
typedef std::map<KEY, KEY> Map;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,122 @@
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
|
||||||
|
* Atlanta, Georgia 30332-0415
|
||||||
|
* All Rights Reserved
|
||||||
|
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
|
||||||
|
|
||||||
|
* See LICENSE for the license information
|
||||||
|
|
||||||
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file testDSFMap.cpp
|
||||||
|
* @date Oct 26, 2013
|
||||||
|
* @author Frank Dellaert
|
||||||
|
* @brief unit tests for DSFMap
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gtsam_unstable/base/DSFMap.h>
|
||||||
|
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
#include <boost/assign/std/list.hpp>
|
||||||
|
//#include <boost/assign/std/set.hpp>
|
||||||
|
using namespace boost::assign;
|
||||||
|
//
|
||||||
|
#include <CppUnitLite/TestHarness.h>
|
||||||
|
//
|
||||||
|
//#include <iostream>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace gtsam;
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
TEST(DSFMap, find) {
|
||||||
|
DSFMap<size_t> dsf;
|
||||||
|
EXPECT(dsf.find(0)==0);
|
||||||
|
EXPECT(dsf.find(2)==2);
|
||||||
|
EXPECT(dsf.find(0)==0);
|
||||||
|
EXPECT(dsf.find(2)==2);
|
||||||
|
EXPECT(dsf.find(0) != dsf.find(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
TEST(DSFMap, merge) {
|
||||||
|
DSFMap<size_t> dsf;
|
||||||
|
dsf.merge(0,2);
|
||||||
|
EXPECT(dsf.find(0) == dsf.find(2));
|
||||||
|
}
|
||||||
|
/* ************************************************************************* */
|
||||||
|
TEST(DSFMap, merge2) {
|
||||||
|
DSFMap<size_t> dsf;
|
||||||
|
dsf.merge(2,0);
|
||||||
|
EXPECT(dsf.find(0) == dsf.find(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
TEST(DSFMap, merge3) {
|
||||||
|
DSFMap<size_t> dsf;
|
||||||
|
dsf.merge(0,1);
|
||||||
|
dsf.merge(1,2);
|
||||||
|
EXPECT(dsf.find(0) == dsf.find(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
TEST(DSFMap, mergePairwiseMatches) {
|
||||||
|
|
||||||
|
// Create some "matches"
|
||||||
|
typedef pair<size_t,size_t> Match;
|
||||||
|
list<Match> matches;
|
||||||
|
matches += Match(1,2), Match(2,3), Match(4,5), Match(4,6);
|
||||||
|
|
||||||
|
// Merge matches
|
||||||
|
DSFMap<size_t> dsf;
|
||||||
|
BOOST_FOREACH(const Match& m, matches)
|
||||||
|
dsf.merge(m.first,m.second);
|
||||||
|
|
||||||
|
// 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.find(1));
|
||||||
|
EXPECT_LONGS_EQUAL(rep1,dsf.find(2));
|
||||||
|
EXPECT_LONGS_EQUAL(rep1,dsf.find(3));
|
||||||
|
EXPECT_LONGS_EQUAL(rep2,dsf.find(4));
|
||||||
|
EXPECT_LONGS_EQUAL(rep2,dsf.find(5));
|
||||||
|
EXPECT_LONGS_EQUAL(rep2,dsf.find(6));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
TEST(DSFMap, mergePairwiseMatches2) {
|
||||||
|
|
||||||
|
// Create some measurements with image index and feature index
|
||||||
|
typedef pair<size_t,size_t> Measurement;
|
||||||
|
Measurement m11(1,1),m12(1,2),m14(1,4); // in image 1
|
||||||
|
Measurement m22(2,2),m23(2,3),m25(2,5),m26(2,6); // in image 2
|
||||||
|
|
||||||
|
// Add them all
|
||||||
|
list<Measurement> measurements;
|
||||||
|
measurements += m11,m12,m14, m22,m23,m25,m26;
|
||||||
|
|
||||||
|
// Create some "matches"
|
||||||
|
typedef pair<Measurement,Measurement> Match;
|
||||||
|
list<Match> matches;
|
||||||
|
matches += Match(m11,m22), Match(m12,m23), Match(m14,m25), Match(m14,m26);
|
||||||
|
|
||||||
|
// Merge matches
|
||||||
|
DSFMap<Measurement> dsf;
|
||||||
|
BOOST_FOREACH(const Match& m, matches)
|
||||||
|
dsf.merge(m.first,m.second);
|
||||||
|
|
||||||
|
// Check that sets are merged correctly
|
||||||
|
EXPECT(dsf.find(m11)==m11);
|
||||||
|
EXPECT(dsf.find(m12)==m12);
|
||||||
|
EXPECT(dsf.find(m14)==m14);
|
||||||
|
EXPECT(dsf.find(m22)==m11);
|
||||||
|
EXPECT(dsf.find(m23)==m12);
|
||||||
|
EXPECT(dsf.find(m25)==m14);
|
||||||
|
EXPECT(dsf.find(m26)==m14);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
int main() { TestResult tr; return TestRegistry::runAllTests(tr);}
|
||||||
|
/* ************************************************************************* */
|
||||||
|
|
Loading…
Reference in New Issue