Split DSFVector into two classes
							parent
							
								
									0dbd016ca9
								
							
						
					
					
						commit
						ddd7c6663f
					
				|  | @ -26,33 +26,55 @@ using namespace std; | ||||||
| namespace gtsam { | namespace gtsam { | ||||||
| 
 | 
 | ||||||
| /* ************************************************************************* */ | /* ************************************************************************* */ | ||||||
| DSFVector::DSFVector(const size_t numNodes) { | DSFBase::DSFBase(const size_t numNodes) { | ||||||
|   v_ = boost::make_shared < V > (numNodes); |   v_ = boost::make_shared < V > (numNodes); | ||||||
|   int index = 0; |   int index = 0; | ||||||
|   keys_.reserve(numNodes); |   for (V::iterator it = v_->begin(); it != v_->end(); it++, index++) | ||||||
|   for (V::iterator it = v_->begin(); it != v_->end(); it++, index++) { |  | ||||||
|     *it = index; |     *it = index; | ||||||
|     keys_.push_back(index); | } | ||||||
|  | 
 | ||||||
|  | /* ************************************************************************* */ | ||||||
|  | DSFBase::DSFBase(const boost::shared_ptr<V>& v_in) { | ||||||
|  |   v_ = v_in; | ||||||
|  |   int index = 0; | ||||||
|  |   for (V::iterator it = v_->begin(); it != v_->end(); it++, index++) | ||||||
|  |     *it = index; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* ************************************************************************* */ | ||||||
|  | size_t DSFBase::findSet(size_t key) const { | ||||||
|  |   size_t parent = (*v_)[key]; | ||||||
|  |   // follow parent pointers until we reach set representative
 | ||||||
|  |   while (parent != key) { | ||||||
|  |     key = parent; | ||||||
|  |     parent = (*v_)[key]; | ||||||
|   } |   } | ||||||
|  |   return parent; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* ************************************************************************* */ | ||||||
|  | void DSFBase::makeUnionInPlace(const size_t& i1, const size_t& i2) { | ||||||
|  |   (*v_)[findSet(i2)] = findSet(i1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* ************************************************************************* */ | ||||||
|  | DSFVector::DSFVector(const size_t numNodes) : | ||||||
|  |     DSFBase(numNodes) { | ||||||
|  |   keys_.reserve(numNodes); | ||||||
|  |   for (size_t index = 0; index < numNodes; index++) | ||||||
|  |     keys_.push_back(index); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* ************************************************************************* */ | /* ************************************************************************* */ | ||||||
| DSFVector::DSFVector(const std::vector<size_t>& keys) : | DSFVector::DSFVector(const std::vector<size_t>& keys) : | ||||||
|     keys_(keys) { |     DSFBase(1 + *std::max_element(keys.begin(), keys.end())), keys_(keys) { | ||||||
|   size_t maxKey = *(std::max_element(keys.begin(), keys.end())); |  | ||||||
|   v_ = boost::make_shared < V > (maxKey + 1); |  | ||||||
|   BOOST_FOREACH(const size_t key, keys) |  | ||||||
|     (*v_)[key] = key; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* ************************************************************************* */ | /* ************************************************************************* */ | ||||||
| DSFVector::DSFVector(const boost::shared_ptr<V>& v_in, | DSFVector::DSFVector(const boost::shared_ptr<V>& v_in, | ||||||
|     const std::vector<size_t>& keys) : |     const std::vector<size_t>& keys) : | ||||||
|     keys_(keys) { |     DSFBase(v_in), keys_(keys) { | ||||||
|   assert(*(std::max_element(keys.begin(), keys.end()))<v_in->size()); |   assert(*(std::max_element(keys.begin(), keys.end()))<v_in->size()); | ||||||
|   v_ = v_in; |  | ||||||
|   BOOST_FOREACH(const size_t key, keys) |  | ||||||
|     (*v_)[key] = key; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* ************************************************************************* */ | /* ************************************************************************* */ | ||||||
|  | @ -94,10 +116,5 @@ std::map<size_t, std::vector<size_t> > DSFVector::arrays() const { | ||||||
|   return arrays; |   return arrays; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* ************************************************************************* */ |  | ||||||
| void DSFVector::makeUnionInPlace(const size_t& i1, const size_t& i2) { |  | ||||||
|   (*v_)[findSet(i2)] = findSet(i1); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| } // namespace  gtsam
 | } // namespace  gtsam
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -28,16 +28,39 @@ 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 | ||||||
|  * @addtogroup base |  * @addtogroup base | ||||||
|  */ |  */ | ||||||
| class GTSAM_EXPORT DSFVector { | class GTSAM_EXPORT DSFBase { | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
|   typedef std::vector<size_t> V; ///< Vector of ints
 |   typedef std::vector<size_t> V; ///< Vector of ints
 | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|   boost::shared_ptr<V> v_;///< Stores parent pointers, representative iff v[i]==i
 |   boost::shared_ptr<V> v_;///< Stores parent pointers, representative iff v[i]==i
 | ||||||
|   std::vector<size_t> keys_;///< stores keys
 | 
 | ||||||
|  | public: | ||||||
|  |   /// constructor that allocate new memory, allows for keys 0...numNodes-1
 | ||||||
|  |   DSFBase(const size_t numNodes); | ||||||
|  | 
 | ||||||
|  |   /// constructor that uses the existing memory
 | ||||||
|  |   DSFBase(const boost::shared_ptr<V>& v_in); | ||||||
|  | 
 | ||||||
|  |   /// find the label of the set in which {key} lives
 | ||||||
|  |   size_t findSet(size_t key) const; | ||||||
|  | 
 | ||||||
|  |   /// the in-place version of makeUnion
 | ||||||
|  |   void makeUnionInPlace(const size_t& i1, const size_t& i2); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * A fast implementation of disjoint set forests that uses vector as underly data structure. | ||||||
|  |  * @addtogroup base | ||||||
|  |  */ | ||||||
|  | class GTSAM_EXPORT DSFVector: public DSFBase { | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |   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
 | ||||||
|  | @ -49,17 +72,6 @@ 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); | ||||||
| 
 | 
 | ||||||
|   /// find the label of the set in which {key} lives
 |  | ||||||
|   inline size_t findSet(size_t key) const { |  | ||||||
|     size_t parent = (*v_)[key]; |  | ||||||
|     // follow parent pointers until we reach set representative
 |  | ||||||
|     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 size_t& label) const; |   bool isSingleton(const size_t& label) const; | ||||||
| 
 | 
 | ||||||
|  | @ -71,9 +83,6 @@ public: | ||||||
| 
 | 
 | ||||||
|   /// return all sets, i.e. a partition of all elements
 |   /// return all sets, i.e. a partition of all elements
 | ||||||
|   std::map<size_t, std::vector<size_t> > arrays() const; |   std::map<size_t, std::vector<size_t> > arrays() const; | ||||||
| 
 |  | ||||||
|   /// the in-place version of makeUnion
 |  | ||||||
|   void makeUnionInPlace(const size_t& i1, const size_t& i2); |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -186,9 +186,6 @@ TEST(DSFVector, mergePairwiseMatches) { | ||||||
|   BOOST_FOREACH(const Match& m, matches) |   BOOST_FOREACH(const Match& m, matches) | ||||||
|     dsf.makeUnionInPlace(m.first,m.second); |     dsf.makeUnionInPlace(m.first,m.second); | ||||||
| 
 | 
 | ||||||
|   cout << endl; |  | ||||||
|   map<size_t, set<size_t> > sets1 = dsf.sets(); |  | ||||||
| 
 |  | ||||||
|   // 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.findSet(1)); | ||||||
|  | @ -199,16 +196,13 @@ TEST(DSFVector, mergePairwiseMatches) { | ||||||
|   EXPECT_LONGS_EQUAL(rep2,dsf.findSet(6)); |   EXPECT_LONGS_EQUAL(rep2,dsf.findSet(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
 | ||||||
|   cout << endl; |  | ||||||
|   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> expected1; expected1 += 1,2,3; |   set<size_t> expected1; expected1 += 1,2,3; | ||||||
|   set<size_t> actual1 = sets[rep1]; |   set<size_t> actual1 = sets[rep1]; | ||||||
|   BOOST_FOREACH(size_t i, actual1) cout << i << " "; |  | ||||||
|   EXPECT(expected1 == actual1); |   EXPECT(expected1 == actual1); | ||||||
|   set<size_t> expected2; expected2 += 4,5,6; |   set<size_t> expected2; expected2 += 4,5,6; | ||||||
|   set<size_t> actual2 = sets[rep2]; |   set<size_t> actual2 = sets[rep2]; | ||||||
|   BOOST_FOREACH(size_t i, actual2) cout << i << " "; |  | ||||||
|   EXPECT(expected2 == actual2); |   EXPECT(expected2 == actual2); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue