2010-03-27 14:05:06 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								/*
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								 * DSF.h
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								 *
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								 *  Created on: Mar 26, 2010
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								 *  Author: nikai
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								 *  Description: An implementation of Disjoint set forests (see CLR page 446 and up)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								 *  						 Quoting from CLR: A disjoint-set data structure maintains a collection
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								 * 							 S = {S_1,S_2,...} of disjoint dynamic sets. Each set is identified by
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								 * 							 a representative, which is some member of the set.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								 */
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								#pragma once
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2010-04-21 11:47:20 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								#include <iostream>
							 | 
						
					
						
							
								
									
										
										
										
											2010-03-27 14:05:06 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								#include <list>
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								#include <set>
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								#include <map>
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								#include <boost/foreach.hpp>
							 | 
						
					
						
							
								
									
										
										
										
											2010-08-20 01:23:19 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								#include <gtsam/base/BTree.h>
							 | 
						
					
						
							
								
									
										
										
										
											2010-03-27 14:05:06 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								namespace gtsam {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									template <class Key>
							 | 
						
					
						
							
								
									
										
										
										
											2010-04-21 11:47:20 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
									class DSF : protected BTree<Key, Key> {
							 | 
						
					
						
							
								
									
										
										
										
											2010-03-27 14:05:06 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									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;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										// constructor
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										DSF() : Tree() { }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										// constructor
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										DSF(const Tree& tree) : Tree(tree) {}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2010-03-30 15:27:10 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
										// constructor with a list of unconnected keys
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										DSF(const std::list<Key>& keys) : Tree() { BOOST_FOREACH(const Key& key, keys) *this = this->add(key, key); }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2010-03-27 14:05:06 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
										// create a new singleton, does nothing if already exists
							 | 
						
					
						
							
								
									
										
										
										
											2010-03-30 15:27:10 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
										Self makeSet(const Key& key) const { if (mem(key)) return *this; else return this->add(key, key); }
							 | 
						
					
						
							
								
									
										
										
										
											2010-03-27 14:05:06 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										// find the label of the set in which {key} lives
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										Label findSet(const Key& key) const {
							 | 
						
					
						
							
								
									
										
										
										
											2010-03-30 15:27:10 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
											Key parent = this->find(key);
							 | 
						
					
						
							
								
									
										
										
										
											2010-03-27 14:05:06 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
											return parent == key ? key : findSet(parent); }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										// return a new DSF where x and y are in the same set. Kai: the caml implementation is not const, and I followed
							 | 
						
					
						
							
								
									
										
										
										
											2010-03-30 15:27:10 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
										Self makeUnion(const Key& key1, const Key& key2) { return this->add(findSet_(key2), findSet_(key1));	}
							 | 
						
					
						
							
								
									
										
										
										
											2010-03-27 14:05:06 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2010-05-09 04:11:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
										// the in-place version of makeUnion
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										void makeUnionInPlace(const Key& key1, const Key& key2) { *this = this->add(findSet_(key2), findSet_(key1)); }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2010-03-27 14:05:06 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
										// create a new singleton with two connected keys
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										Self makePair(const Key& key1, const Key& key2) const { return makeSet(key1).makeSet(key2).makeUnion(key1, key2); }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										// create a new singleton with a list of fully connected keys
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										Self makeList(const std::list<Key>& keys) const {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											Self t = *this;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											BOOST_FOREACH(const Key& key, keys)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
												t = t.makePair(key, keys.front());
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											return t;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										// return a dsf in which all find_set operations will be O(1) due to path compression.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										DSF flatten() const {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											DSF t = *this;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											BOOST_FOREACH(const KeyLabel& pair, (Tree)t)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
												t.findSet_(pair.first);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											return t;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										// maps f over all keys, must be invertible
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										DSF map(boost::function<Key(const Key&)> func) const {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											DSF t;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											BOOST_FOREACH(const KeyLabel& pair, (Tree)*this)
							 | 
						
					
						
							
								
									
										
										
										
											2010-03-30 15:27:10 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
												t = t.add(func(pair.first), func(pair.second));
							 | 
						
					
						
							
								
									
										
										
										
											2010-03-27 14:05:06 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
											return t;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										// return the number of sets
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										size_t numSets() const {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											size_t num = 0;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											BOOST_FOREACH(const KeyLabel& pair, (Tree)*this)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
												if (pair.first == pair.second) num++;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											return num;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										// return the numer of keys
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										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;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											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;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											BOOST_FOREACH(const Key& key, keys)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
												partitions[findSet(key)].insert(key);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											return partitions;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2010-06-23 11:09:26 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
										// get the nodes in the tree with the given label
							 | 
						
					
						
							
								
									
										
										
										
											2010-06-25 14:35:44 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
										Set set(const Label& label) const {
							 | 
						
					
						
							
								
									
										
										
										
											2010-04-10 07:36:13 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
											Set set;
							 | 
						
					
						
							
								
									
										
										
										
											2010-06-23 11:09:26 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
											BOOST_FOREACH(const KeyLabel& pair, (Tree)*this) {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
												if (pair.second == label || findSet(pair.second) == label)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
													set.insert(pair.first);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											}
							 | 
						
					
						
							
								
									
										
										
										
											2010-04-10 07:36:13 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
											return set;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2010-03-27 14:05:06 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
										/** equality */
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										bool operator==(const Self& t) const { return (Tree)*this == (Tree)t;	}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2010-03-30 15:27:10 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
										/** inequality */
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										bool operator!=(const Self& t) const { return (Tree)*this != (Tree)t;	}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2010-03-27 14:05:06 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
										// print the object
							 | 
						
					
						
							
								
									
										
										
										
											2010-03-30 15:27:10 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
										void print(const std::string& name = "DSF") const {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											std::cout << name << std::endl;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											BOOST_FOREACH(const KeyLabel& pair, (Tree)*this)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
												std::cout << (std::string)pair.first << " " << (std::string)pair.second << std::endl;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										}
							 | 
						
					
						
							
								
									
										
										
										
											2010-03-27 14:05:06 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2010-04-21 11:47:20 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
									protected:
							 | 
						
					
						
							
								
									
										
										
										
											2010-03-27 14:05:06 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										/**
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										 * same as findSet except with path compression: After we have traversed the path to
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										 * the root, each parent pointer is made to directly point to it
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										 */
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										Key findSet_(const Key& key) {
							 | 
						
					
						
							
								
									
										
										
										
											2010-03-30 15:27:10 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
											Key parent = this->find(key);
							 | 
						
					
						
							
								
									
										
										
										
											2010-03-27 14:05:06 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
											if (parent == key)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
												return parent;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											else {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
												Key label = findSet_(parent);
							 | 
						
					
						
							
								
									
										
										
										
											2010-03-30 15:27:10 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
												*this = this->add(key, label);
							 | 
						
					
						
							
								
									
										
										
										
											2010-03-27 14:05:06 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
												return label;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									};
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									// shortcuts
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									typedef DSF<int> DSFInt;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								} // namespace gtsam
							 |