new names find/merge, made it clear DFSVector operations are expensive
							parent
							
								
									42fda7913f
								
							
						
					
					
						commit
						482777a938
					
				|  | @ -42,18 +42,18 @@ DSFBase::DSFBase(const boost::shared_ptr<V>& v_in) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* ************************************************************************* */ | /* ************************************************************************* */ | ||||||
| size_t DSFBase::findSet(size_t key) const { | size_t DSFBase::find(size_t key) const { | ||||||
|   // follow parent pointers until we reach set representative
 |   // follow parent pointers until we reach set representative
 | ||||||
|   size_t parent = (*v_)[key]; |   size_t parent = (*v_)[key]; | ||||||
|   if (parent != key) |   if (parent != key) | ||||||
|     parent = findSet(parent); // recursive call
 |     parent = find(parent); // recursive call
 | ||||||
|   (*v_)[key] = parent; // path compression
 |   (*v_)[key] = parent; // path compression
 | ||||||
|   return parent; |   return parent; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* ************************************************************************* */ | /* ************************************************************************* */ | ||||||
| void DSFBase::makeUnionInPlace(const size_t& i1, const size_t& i2) { | void DSFBase::merge(const size_t& i1, const size_t& i2) { | ||||||
|   (*v_)[findSet(i2)] = findSet(i1); |   (*v_)[find(i2)] = find(i1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* ************************************************************************* */ | /* ************************************************************************* */ | ||||||
|  | @ -80,7 +80,7 @@ DSFVector::DSFVector(const boost::shared_ptr<V>& v_in, | ||||||
| bool DSFVector::isSingleton(const size_t& label) const { | bool DSFVector::isSingleton(const size_t& label) const { | ||||||
|   bool result = false; |   bool result = false; | ||||||
|   BOOST_FOREACH(size_t key,keys_) { |   BOOST_FOREACH(size_t key,keys_) { | ||||||
|     if (findSet(key) == label) { |     if (find(key) == label) { | ||||||
|       if (!result) // find the first occurrence
 |       if (!result) // find the first occurrence
 | ||||||
|         result = true; |         result = true; | ||||||
|       else |       else | ||||||
|  | @ -94,7 +94,7 @@ bool DSFVector::isSingleton(const size_t& label) const { | ||||||
| std::set<size_t> DSFVector::set(const size_t& label) const { | std::set<size_t> DSFVector::set(const size_t& label) const { | ||||||
|   std::set < size_t > set; |   std::set < size_t > set; | ||||||
|   BOOST_FOREACH(size_t key,keys_) |   BOOST_FOREACH(size_t key,keys_) | ||||||
|     if (findSet(key) == label) |     if (find(key) == label) | ||||||
|       set.insert(key); |       set.insert(key); | ||||||
|   return set; |   return set; | ||||||
| } | } | ||||||
|  | @ -103,7 +103,7 @@ std::set<size_t> DSFVector::set(const size_t& label) const { | ||||||
| std::map<size_t, std::set<size_t> > DSFVector::sets() const { | std::map<size_t, std::set<size_t> > DSFVector::sets() const { | ||||||
|   std::map<size_t, std::set<size_t> > sets; |   std::map<size_t, std::set<size_t> > sets; | ||||||
|   BOOST_FOREACH(size_t key,keys_) |   BOOST_FOREACH(size_t key,keys_) | ||||||
|     sets[findSet(key)].insert(key); |     sets[find(key)].insert(key); | ||||||
|   return sets; |   return sets; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -111,7 +111,7 @@ std::map<size_t, std::set<size_t> > DSFVector::sets() const { | ||||||
| std::map<size_t, std::vector<size_t> > DSFVector::arrays() const { | std::map<size_t, std::vector<size_t> > DSFVector::arrays() const { | ||||||
|   std::map<size_t, std::vector<size_t> > arrays; |   std::map<size_t, std::vector<size_t> > arrays; | ||||||
|   BOOST_FOREACH(size_t key,keys_) |   BOOST_FOREACH(size_t key,keys_) | ||||||
|     arrays[findSet(key)].push_back(key); |     arrays[find(key)].push_back(key); | ||||||
|   return arrays; |   return arrays; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -29,6 +29,7 @@ namespace gtsam { | ||||||
| /**
 | /**
 | ||||||
|  * A fast implementation of disjoint set forests that uses vector as underly data structure. |  * A fast implementation of disjoint set forests that uses vector as underly data structure. | ||||||
|  * This is the absolute minimal DSF data structure, and only allows size_t keys |  * This is the absolute minimal DSF data structure, and only allows size_t keys | ||||||
|  |  * Uses rank compression but not union by rank :-( | ||||||
|  * @addtogroup base |  * @addtogroup base | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT DSFBase { | class GTSAM_EXPORT DSFBase { | ||||||
|  | @ -47,20 +48,26 @@ public: | ||||||
|   DSFBase(const boost::shared_ptr<V>& v_in); |   DSFBase(const boost::shared_ptr<V>& v_in); | ||||||
| 
 | 
 | ||||||
|   /// find the label of the set in which {key} lives
 |   /// find the label of the set in which {key} lives
 | ||||||
|   size_t findSet(size_t key) const; |   size_t find(size_t key) const; | ||||||
| 
 | 
 | ||||||
|   /// the in-place version of makeUnion
 |   /// Merge two sets
 | ||||||
|   void makeUnionInPlace(const size_t& i1, const size_t& i2); |   void merge(const size_t& i1, const size_t& i2); | ||||||
|  | 
 | ||||||
|  |   /// @deprecated old name
 | ||||||
|  |   inline size_t findSet(size_t key) const {return find(key);} | ||||||
|  | 
 | ||||||
|  |   /// @deprecated old name
 | ||||||
|  |   inline void makeUnionInPlace(const size_t& i1, const size_t& i2) {return merge(i1,i2);} | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * A fast implementation of disjoint set forests that uses vector as underly data structure. |  * DSFVector additionaly keeps a vector of keys to support more expensive operations | ||||||
|  * @addtogroup base |  * @addtogroup base | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT DSFVector: public DSFBase { | class GTSAM_EXPORT DSFVector: public DSFBase { | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|   std::vector<size_t> keys_;///< stores keys to support more expensive operations
 |   std::vector<size_t> keys_; ///< stores keys to support more expensive operations
 | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
|   /// constructor that allocate new memory, uses sequential keys 0...numNodes-1
 |   /// constructor that allocate new memory, uses sequential keys 0...numNodes-1
 | ||||||
|  | @ -72,6 +79,8 @@ public: | ||||||
|   /// constructor that uses the existing memory
 |   /// constructor that uses the existing memory
 | ||||||
|   DSFVector(const boost::shared_ptr<V>& v_in, const std::vector<size_t>& keys); |   DSFVector(const boost::shared_ptr<V>& v_in, const std::vector<size_t>& keys); | ||||||
| 
 | 
 | ||||||
|  |   // all operations below loop over all keys and hence are *at least* O(n)
 | ||||||
|  | 
 | ||||||
|   /// 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 size_t& label) const; |   bool isSingleton(const size_t& label) const; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -33,114 +33,114 @@ using namespace std; | ||||||
| using namespace gtsam; | using namespace gtsam; | ||||||
| 
 | 
 | ||||||
| /* ************************************************************************* */ | /* ************************************************************************* */ | ||||||
| TEST(DSFVectorVector, findSet) { | TEST(DSFVectorVector, find) { | ||||||
|   DSFVector dsf(3); |   DSFBase dsf(3); | ||||||
|   EXPECT(dsf.findSet(0) != dsf.findSet(2)); |   EXPECT(dsf.find(0) != dsf.find(2)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* ************************************************************************* */ | /* ************************************************************************* */ | ||||||
| TEST(DSFVectorVector, makeUnionInPlace) { | TEST(DSFVectorVector, merge) { | ||||||
|   DSFVector dsf(3); |   DSFBase dsf(3); | ||||||
|   dsf.makeUnionInPlace(0,2); |   dsf.merge(0,2); | ||||||
|   EXPECT(dsf.findSet(0) == dsf.findSet(2)); |   EXPECT(dsf.find(0) == dsf.find(2)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* ************************************************************************* */ | /* ************************************************************************* */ | ||||||
| TEST(DSFVectorVector, makeUnionInPlace2) { | TEST(DSFBase, makeUnion2) { | ||||||
|   boost::shared_ptr<DSFVector::V> v = boost::make_shared<DSFVector::V>(5); |   DSFBase dsf(3); | ||||||
|  |   dsf.merge(2,0); | ||||||
|  |   EXPECT(dsf.find(0) == dsf.find(2)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* ************************************************************************* */ | ||||||
|  | TEST(DSFBase, makeUnion3) { | ||||||
|  |   DSFBase dsf(3); | ||||||
|  |   dsf.merge(0,1); | ||||||
|  |   dsf.merge(1,2); | ||||||
|  |   EXPECT(dsf.find(0) == dsf.find(2)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* ************************************************************************* */ | ||||||
|  | TEST(DSFVector, merge2) { | ||||||
|  |   boost::shared_ptr<DSFBase::V> v = boost::make_shared<DSFBase::V>(5); | ||||||
|   std::vector<size_t> keys; keys += 1, 3; |   std::vector<size_t> keys; keys += 1, 3; | ||||||
|   DSFVector dsf(v, keys); |   DSFVector dsf(v, keys); | ||||||
|   dsf.makeUnionInPlace(1,3); |   dsf.merge(1,3); | ||||||
|   EXPECT(dsf.findSet(1) == dsf.findSet(3)); |   EXPECT(dsf.find(1) == dsf.find(3)); | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* ************************************************************************* */ |  | ||||||
| TEST(DSFVector, makeUnion2) { |  | ||||||
|   DSFVector dsf(3); |  | ||||||
|   dsf.makeUnionInPlace(2,0); |  | ||||||
|   EXPECT(dsf.findSet(0) == dsf.findSet(2)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* ************************************************************************* */ |  | ||||||
| TEST(DSFVector, makeUnion3) { |  | ||||||
|   DSFVector dsf(3); |  | ||||||
|   dsf.makeUnionInPlace(0,1); |  | ||||||
|   dsf.makeUnionInPlace(1,2); |  | ||||||
|   EXPECT(dsf.findSet(0) == dsf.findSet(2)); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* ************************************************************************* */ | /* ************************************************************************* */ | ||||||
| TEST(DSFVector, sets) { | TEST(DSFVector, sets) { | ||||||
|   DSFVector dsf(2); |   DSFVector dsf(2); | ||||||
|   dsf.makeUnionInPlace(0,1); |   dsf.merge(0,1); | ||||||
|   map<size_t, set<size_t> > sets = dsf.sets(); |   map<size_t, set<size_t> > sets = dsf.sets(); | ||||||
|   LONGS_EQUAL(1, sets.size()); |   LONGS_EQUAL(1, sets.size()); | ||||||
| 
 | 
 | ||||||
|   set<size_t> expected; expected += 0, 1; |   set<size_t> expected; expected += 0, 1; | ||||||
|   EXPECT(expected == sets[dsf.findSet(0)]); |   EXPECT(expected == sets[dsf.find(0)]); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* ************************************************************************* */ | /* ************************************************************************* */ | ||||||
| TEST(DSFVector, arrays) { | TEST(DSFVector, arrays) { | ||||||
|   DSFVector dsf(2); |   DSFVector dsf(2); | ||||||
|   dsf.makeUnionInPlace(0,1); |   dsf.merge(0,1); | ||||||
|   map<size_t, vector<size_t> > arrays = dsf.arrays(); |   map<size_t, vector<size_t> > arrays = dsf.arrays(); | ||||||
|   LONGS_EQUAL(1, arrays.size()); |   LONGS_EQUAL(1, arrays.size()); | ||||||
| 
 | 
 | ||||||
|   vector<size_t> expected; expected += 0, 1; |   vector<size_t> expected; expected += 0, 1; | ||||||
|   EXPECT(expected == arrays[dsf.findSet(0)]); |   EXPECT(expected == arrays[dsf.find(0)]); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* ************************************************************************* */ | /* ************************************************************************* */ | ||||||
| TEST(DSFVector, sets2) { | TEST(DSFVector, sets2) { | ||||||
|   DSFVector dsf(3); |   DSFVector dsf(3); | ||||||
|   dsf.makeUnionInPlace(0,1); |   dsf.merge(0,1); | ||||||
|   dsf.makeUnionInPlace(1,2); |   dsf.merge(1,2); | ||||||
|   map<size_t, set<size_t> > sets = dsf.sets(); |   map<size_t, set<size_t> > sets = dsf.sets(); | ||||||
|   LONGS_EQUAL(1, sets.size()); |   LONGS_EQUAL(1, sets.size()); | ||||||
| 
 | 
 | ||||||
|   set<size_t> expected; expected += 0, 1, 2; |   set<size_t> expected; expected += 0, 1, 2; | ||||||
|   EXPECT(expected == sets[dsf.findSet(0)]); |   EXPECT(expected == sets[dsf.find(0)]); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* ************************************************************************* */ | /* ************************************************************************* */ | ||||||
| TEST(DSFVector, arrays2) { | TEST(DSFVector, arrays2) { | ||||||
|   DSFVector dsf(3); |   DSFVector dsf(3); | ||||||
|   dsf.makeUnionInPlace(0,1); |   dsf.merge(0,1); | ||||||
|   dsf.makeUnionInPlace(1,2); |   dsf.merge(1,2); | ||||||
|   map<size_t, vector<size_t> > arrays = dsf.arrays(); |   map<size_t, vector<size_t> > arrays = dsf.arrays(); | ||||||
|   LONGS_EQUAL(1, arrays.size()); |   LONGS_EQUAL(1, arrays.size()); | ||||||
| 
 | 
 | ||||||
|   vector<size_t> expected; expected += 0, 1, 2; |   vector<size_t> expected; expected += 0, 1, 2; | ||||||
|   EXPECT(expected == arrays[dsf.findSet(0)]); |   EXPECT(expected == arrays[dsf.find(0)]); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* ************************************************************************* */ | /* ************************************************************************* */ | ||||||
| TEST(DSFVector, sets3) { | TEST(DSFVector, sets3) { | ||||||
|   DSFVector dsf(3); |   DSFVector dsf(3); | ||||||
|   dsf.makeUnionInPlace(0,1); |   dsf.merge(0,1); | ||||||
|   map<size_t, set<size_t> > sets = dsf.sets(); |   map<size_t, set<size_t> > sets = dsf.sets(); | ||||||
|   LONGS_EQUAL(2, sets.size()); |   LONGS_EQUAL(2, sets.size()); | ||||||
| 
 | 
 | ||||||
|   set<size_t> expected; expected += 0, 1; |   set<size_t> expected; expected += 0, 1; | ||||||
|   EXPECT(expected == sets[dsf.findSet(0)]); |   EXPECT(expected == sets[dsf.find(0)]); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* ************************************************************************* */ | /* ************************************************************************* */ | ||||||
| TEST(DSFVector, arrays3) { | TEST(DSFVector, arrays3) { | ||||||
|   DSFVector dsf(3); |   DSFVector dsf(3); | ||||||
|   dsf.makeUnionInPlace(0,1); |   dsf.merge(0,1); | ||||||
|   map<size_t, vector<size_t> > arrays = dsf.arrays(); |   map<size_t, vector<size_t> > arrays = dsf.arrays(); | ||||||
|   LONGS_EQUAL(2, arrays.size()); |   LONGS_EQUAL(2, arrays.size()); | ||||||
| 
 | 
 | ||||||
|   vector<size_t> expected; expected += 0, 1; |   vector<size_t> expected; expected += 0, 1; | ||||||
|   EXPECT(expected == arrays[dsf.findSet(0)]); |   EXPECT(expected == arrays[dsf.find(0)]); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* ************************************************************************* */ | /* ************************************************************************* */ | ||||||
| TEST(DSFVector, set) { | TEST(DSFVector, set) { | ||||||
|   DSFVector dsf(3); |   DSFVector dsf(3); | ||||||
|   dsf.makeUnionInPlace(0,1); |   dsf.merge(0,1); | ||||||
|   set<size_t> set = dsf.set(0); |   set<size_t> set = dsf.set(0); | ||||||
|   LONGS_EQUAL(2, set.size()); |   LONGS_EQUAL(2, set.size()); | ||||||
| 
 | 
 | ||||||
|  | @ -151,8 +151,8 @@ TEST(DSFVector, set) { | ||||||
| /* ************************************************************************* */ | /* ************************************************************************* */ | ||||||
| TEST(DSFVector, set2) { | TEST(DSFVector, set2) { | ||||||
|   DSFVector dsf(3); |   DSFVector dsf(3); | ||||||
|   dsf.makeUnionInPlace(0,1); |   dsf.merge(0,1); | ||||||
|   dsf.makeUnionInPlace(1,2); |   dsf.merge(1,2); | ||||||
|   set<size_t> set = dsf.set(0); |   set<size_t> set = dsf.set(0); | ||||||
|   LONGS_EQUAL(3, set.size()); |   LONGS_EQUAL(3, set.size()); | ||||||
| 
 | 
 | ||||||
|  | @ -163,7 +163,7 @@ TEST(DSFVector, set2) { | ||||||
| /* ************************************************************************* */ | /* ************************************************************************* */ | ||||||
| TEST(DSFVector, isSingleton) { | TEST(DSFVector, isSingleton) { | ||||||
|   DSFVector dsf(3); |   DSFVector dsf(3); | ||||||
|   dsf.makeUnionInPlace(0,1); |   dsf.merge(0,1); | ||||||
|   EXPECT(!dsf.isSingleton(0)); |   EXPECT(!dsf.isSingleton(0)); | ||||||
|   EXPECT(!dsf.isSingleton(1)); |   EXPECT(!dsf.isSingleton(1)); | ||||||
|   EXPECT( dsf.isSingleton(2)); |   EXPECT( dsf.isSingleton(2)); | ||||||
|  | @ -184,16 +184,16 @@ TEST(DSFVector, mergePairwiseMatches) { | ||||||
|   // Merge matches
 |   // Merge matches
 | ||||||
|   DSFVector dsf(keys); |   DSFVector dsf(keys); | ||||||
|   BOOST_FOREACH(const Match& m, matches) |   BOOST_FOREACH(const Match& m, matches) | ||||||
|     dsf.makeUnionInPlace(m.first,m.second); |     dsf.merge(m.first,m.second); | ||||||
| 
 | 
 | ||||||
|   // Each point is now associated with a set, represented by one of its members
 |   // Each point is now associated with a set, represented by one of its members
 | ||||||
|   size_t rep1 = 1, rep2 = 4; |   size_t rep1 = 1, rep2 = 4; | ||||||
|   EXPECT_LONGS_EQUAL(rep1,dsf.findSet(1)); |   EXPECT_LONGS_EQUAL(rep1,dsf.find(1)); | ||||||
|   EXPECT_LONGS_EQUAL(rep1,dsf.findSet(2)); |   EXPECT_LONGS_EQUAL(rep1,dsf.find(2)); | ||||||
|   EXPECT_LONGS_EQUAL(rep1,dsf.findSet(3)); |   EXPECT_LONGS_EQUAL(rep1,dsf.find(3)); | ||||||
|   EXPECT_LONGS_EQUAL(rep2,dsf.findSet(4)); |   EXPECT_LONGS_EQUAL(rep2,dsf.find(4)); | ||||||
|   EXPECT_LONGS_EQUAL(rep2,dsf.findSet(5)); |   EXPECT_LONGS_EQUAL(rep2,dsf.find(5)); | ||||||
|   EXPECT_LONGS_EQUAL(rep2,dsf.findSet(6)); |   EXPECT_LONGS_EQUAL(rep2,dsf.find(6)); | ||||||
| 
 | 
 | ||||||
|   // Check that we have two connected components, 1,2,3 and 4,5,6
 |   // Check that we have two connected components, 1,2,3 and 4,5,6
 | ||||||
|   map<size_t, set<size_t> > sets = dsf.sets(); |   map<size_t, set<size_t> > sets = dsf.sets(); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue