DSF with Map, allows more general types
							parent
							
								
									af0de393ea
								
							
						
					
					
						commit
						48dd3cb769
					
				|  | @ -487,6 +487,14 @@ | |||
| 				<useDefaultCommand>true</useDefaultCommand> | ||||
| 				<runAllBuilders>true</runAllBuilders> | ||||
| 			</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"> | ||||
| 				<buildCommand>make</buildCommand> | ||||
| 				<buildArguments>-j2</buildArguments> | ||||
|  |  | |||
|  | @ -33,13 +33,13 @@ using namespace std; | |||
| using namespace gtsam; | ||||
| 
 | ||||
| /* ************************************************************************* */ | ||||
| TEST(DSFVectorVector, find) { | ||||
| TEST(DSFBase, find) { | ||||
|   DSFBase dsf(3); | ||||
|   EXPECT(dsf.find(0) != dsf.find(2)); | ||||
| } | ||||
| 
 | ||||
| /* ************************************************************************* */ | ||||
| TEST(DSFVectorVector, merge) { | ||||
| TEST(DSFBase, merge) { | ||||
|   DSFBase dsf(3); | ||||
|   dsf.merge(0,2); | ||||
|   EXPECT(dsf.find(0) == dsf.find(2)); | ||||
|  |  | |||
|  | @ -18,12 +18,12 @@ | |||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <gtsam_unstable/base/BTree.h> | ||||
| #include <boost/foreach.hpp> | ||||
| #include <iostream> | ||||
| #include <list> | ||||
| #include <set> | ||||
| #include <map> | ||||
| #include <boost/foreach.hpp> | ||||
| #include <gtsam_unstable/base/BTree.h> | ||||
| 
 | ||||
| namespace gtsam { | ||||
| 
 | ||||
|  | @ -40,11 +40,10 @@ namespace gtsam { | |||
|   class DSF : protected BTree<KEY, KEY> { | ||||
| 
 | ||||
|   public: | ||||
|     typedef KEY Label; // label can be different from key, but for now they are same
 | ||||
|     typedef DSF<KEY> Self; | ||||
|     typedef std::set<KEY> Set; | ||||
|     typedef BTree<KEY, Label> Tree; | ||||
|     typedef std::pair<KEY, Label> KeyLabel; | ||||
|     typedef BTree<KEY, KEY> Tree; | ||||
|     typedef std::pair<KEY, KEY> KeyLabel; | ||||
| 
 | ||||
|     // constructor
 | ||||
|     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); } | ||||
| 
 | ||||
|     // 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); | ||||
|       return parent == key ? key : findSet(parent); } | ||||
| 
 | ||||
|  | @ -111,23 +110,23 @@ namespace gtsam { | |||
|     size_t size() const { return Tree::size(); } | ||||
| 
 | ||||
|     // return all sets, i.e. a partition of all elements
 | ||||
|     std::map<Label, Set> sets() const { | ||||
|       std::map<Label, Set> sets; | ||||
|     std::map<KEY, Set> sets() const { | ||||
|       std::map<KEY, Set> sets; | ||||
|       BOOST_FOREACH(const KeyLabel& pair, (Tree)*this) | ||||
|         sets[findSet(pair.second)].insert(pair.first); | ||||
|       return sets; | ||||
|     } | ||||
| 
 | ||||
|     // return a partition of the given elements {keys}
 | ||||
|     std::map<Label, Set> partition(const std::list<KEY>& keys) const { | ||||
|       std::map<Label, Set> partitions; | ||||
|     std::map<KEY, Set> partition(const std::list<KEY>& keys) const { | ||||
|       std::map<KEY, Set> partitions; | ||||
|       BOOST_FOREACH(const KEY& key, keys) | ||||
|         partitions[findSet(key)].insert(key); | ||||
|       return partitions; | ||||
|     } | ||||
| 
 | ||||
|     // get the nodes in the tree with the given label
 | ||||
|     Set set(const Label& label) const { | ||||
|     Set set(const KEY& label) const { | ||||
|       Set set; | ||||
|       BOOST_FOREACH(const KeyLabel& pair, (Tree)*this) { | ||||
|         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