| 
									
										
										
										
											2013-10-27 01:57:03 +08:00
										 |  |  | /* ----------------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  * 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>
 | 
					
						
							| 
									
										
										
										
											2013-10-27 06:22:31 +08:00
										 |  |  | #include <set>
 | 
					
						
							| 
									
										
										
										
											2013-10-29 02:07:19 +08:00
										 |  |  | #include <cstdlib>        // Provides size_t
 | 
					
						
							| 
									
										
										
										
											2013-10-27 01:57:03 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace gtsam { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * Disjoint set forest using an STL map data structure underneath | 
					
						
							| 
									
										
										
										
											2013-10-27 10:50:47 +08:00
										 |  |  |  * Uses rank compression and union by rank, iterator version | 
					
						
							| 
									
										
										
										
											2013-10-27 01:57:03 +08:00
										 |  |  |  * @addtogroup base | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | template<class KEY> | 
					
						
							|  |  |  | class DSFMap { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-27 10:18:42 +08:00
										 |  |  | protected: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/// We store the forest in an STL map, but parents are done with pointers
 | 
					
						
							|  |  |  | 	struct Entry { | 
					
						
							| 
									
										
										
										
											2013-10-30 20:15:43 +08:00
										 |  |  | 		typename std::map<KEY, Entry>::iterator parent_; | 
					
						
							| 
									
										
										
										
											2013-10-27 10:18:42 +08:00
										 |  |  | 		size_t rank_; | 
					
						
							| 
									
										
										
										
											2013-10-29 02:07:19 +08:00
										 |  |  | 		Entry() {} | 
					
						
							| 
									
										
										
										
											2013-10-27 10:18:42 +08:00
										 |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2013-10-27 10:50:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-30 20:15:43 +08:00
										 |  |  |     typedef typename std::map<KEY, Entry> Map; | 
					
						
							|  |  |  | 	typedef typename Map::iterator iterator; | 
					
						
							|  |  |  | 	mutable Map entries_; | 
					
						
							| 
									
										
										
										
											2013-10-27 10:18:42 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-27 10:50:47 +08:00
										 |  |  | 	/// Given key, find iterator to initial entry
 | 
					
						
							| 
									
										
										
										
											2013-10-27 11:45:12 +08:00
										 |  |  | 	iterator find__(const KEY& key) const { | 
					
						
							|  |  |  | 		static const Entry empty; | 
					
						
							|  |  |  | 		iterator it = entries_.find(key); | 
					
						
							| 
									
										
										
										
											2013-10-27 10:18:42 +08:00
										 |  |  | 		// if key does not exist, create and return itself
 | 
					
						
							|  |  |  | 		if (it == entries_.end()) { | 
					
						
							| 
									
										
										
										
											2013-10-27 11:45:12 +08:00
										 |  |  | 			it = entries_.insert(std::make_pair(key, empty)).first; | 
					
						
							|  |  |  | 			it->second.parent_ = it; | 
					
						
							|  |  |  | 			it->second.rank_ = 0; | 
					
						
							| 
									
										
										
										
											2013-10-27 10:18:42 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2013-10-27 10:50:47 +08:00
										 |  |  | 		return it; | 
					
						
							| 
									
										
										
										
											2013-10-27 10:18:42 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-27 10:50:47 +08:00
										 |  |  | 	/// Given iterator to initial entry, find the root Entry
 | 
					
						
							| 
									
										
										
										
											2013-10-27 11:45:12 +08:00
										 |  |  | 	iterator find_(const iterator& it) const { | 
					
						
							| 
									
										
										
										
											2013-10-27 10:18:42 +08:00
										 |  |  | 		// follow parent pointers until we reach set representative
 | 
					
						
							| 
									
										
										
										
											2013-10-27 11:45:12 +08:00
										 |  |  | 		iterator& parent = it->second.parent_; | 
					
						
							|  |  |  | 		if (parent != it) | 
					
						
							|  |  |  | 			parent = find_(parent); // not yet, recurse!
 | 
					
						
							| 
									
										
										
										
											2013-10-27 10:18:42 +08:00
										 |  |  | 		return parent; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-27 10:50:47 +08:00
										 |  |  | 	/// Given key, find the root Entry
 | 
					
						
							| 
									
										
										
										
											2013-10-27 11:45:12 +08:00
										 |  |  | 	inline iterator find_(const KEY& key) const { | 
					
						
							|  |  |  | 		iterator initial = find__(key); | 
					
						
							|  |  |  | 		return find_(initial); | 
					
						
							| 
									
										
										
										
											2013-10-27 10:50:47 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-27 10:18:42 +08:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2013-10-27 10:50:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	typedef std::set<KEY> Set; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-27 10:18:42 +08:00
										 |  |  | 	/// constructor
 | 
					
						
							| 
									
										
										
										
											2013-10-27 10:50:47 +08:00
										 |  |  | 	DSFMap() { | 
					
						
							| 
									
										
										
										
											2013-10-27 10:18:42 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-27 10:50:47 +08:00
										 |  |  | 	/// Given key, find the representative key for the set in which it lives
 | 
					
						
							| 
									
										
										
										
											2013-10-27 11:45:12 +08:00
										 |  |  | 	inline KEY find(const KEY& key) const { | 
					
						
							|  |  |  | 		iterator root = find_(key); | 
					
						
							|  |  |  | 		return root->first; | 
					
						
							| 
									
										
										
										
											2013-10-27 10:18:42 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/// Merge two sets
 | 
					
						
							|  |  |  | 	void merge(const KEY& x, const KEY& y) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// straight from http://en.wikipedia.org/wiki/Disjoint-set_data_structure
 | 
					
						
							| 
									
										
										
										
											2013-10-27 11:45:12 +08:00
										 |  |  | 		iterator xRoot = find_(x); | 
					
						
							|  |  |  | 		iterator yRoot = find_(y); | 
					
						
							| 
									
										
										
										
											2013-10-27 10:18:42 +08:00
										 |  |  | 		if (xRoot == yRoot) | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Merge sets
 | 
					
						
							| 
									
										
										
										
											2013-10-27 11:45:12 +08:00
										 |  |  | 		if (xRoot->second.rank_ < yRoot->second.rank_) | 
					
						
							|  |  |  | 			xRoot->second.parent_ = yRoot; | 
					
						
							|  |  |  | 		else if (xRoot->second.rank_ > yRoot->second.rank_) | 
					
						
							|  |  |  | 			yRoot->second.parent_ = xRoot; | 
					
						
							| 
									
										
										
										
											2013-10-27 10:18:42 +08:00
										 |  |  | 		else { | 
					
						
							| 
									
										
										
										
											2013-10-27 11:45:12 +08:00
										 |  |  | 			yRoot->second.parent_ = xRoot; | 
					
						
							|  |  |  | 			xRoot->second.rank_ = xRoot->second.rank_ + 1; | 
					
						
							| 
									
										
										
										
											2013-10-27 10:18:42 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-27 10:50:47 +08:00
										 |  |  | 	/// return all sets, i.e. a partition of all elements
 | 
					
						
							|  |  |  | 	std::map<KEY, Set> sets() const { | 
					
						
							|  |  |  | 		std::map<KEY, Set> sets; | 
					
						
							| 
									
										
										
										
											2013-10-27 11:45:12 +08:00
										 |  |  | 		iterator it = entries_.begin(); | 
					
						
							|  |  |  | 		for (; it != entries_.end(); it++) { | 
					
						
							|  |  |  | 			iterator root = find_(it); | 
					
						
							|  |  |  | 			sets[root->first].insert(it->first); | 
					
						
							| 
									
										
										
										
											2013-10-27 10:18:42 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2013-10-27 10:50:47 +08:00
										 |  |  | 		return sets; | 
					
						
							| 
									
										
										
										
											2013-10-27 10:18:42 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-10-27 06:22:31 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-27 01:57:03 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |