incremental_components.hpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. //
  2. //=======================================================================
  3. // Copyright 1997-2001 University of Notre Dame.
  4. // Copyright 2009 Trustees of Indiana University.
  5. // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, Michael Hansen
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See
  8. // accompanying file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. //=======================================================================
  11. //
  12. #ifndef BOOST_INCREMENTAL_COMPONENTS_HPP
  13. #define BOOST_INCREMENTAL_COMPONENTS_HPP
  14. #include <boost/detail/iterator.hpp>
  15. #include <boost/graph/detail/incremental_components.hpp>
  16. #include <boost/iterator/counting_iterator.hpp>
  17. #include <boost/make_shared.hpp>
  18. #include <boost/pending/disjoint_sets.hpp>
  19. #include <iterator>
  20. namespace boost {
  21. // A connected component algorithm for the case when dynamically
  22. // adding (but not removing) edges is common. The
  23. // incremental_components() function is a preparing operation. Call
  24. // same_component to check whether two vertices are in the same
  25. // component, or use disjoint_set::find_set to determine the
  26. // representative for a vertex.
  27. // This version of connected components does not require a full
  28. // Graph. Instead, it just needs an edge list, where the vertices of
  29. // each edge need to be of integer type. The edges are assumed to
  30. // be undirected. The other difference is that the result is stored in
  31. // a container, instead of just a decorator. The container should be
  32. // empty before the algorithm is called. It will grow during the
  33. // course of the algorithm. The container must be a model of
  34. // BackInsertionSequence and RandomAccessContainer
  35. // (std::vector is a good choice). After running the algorithm the
  36. // index container will map each vertex to the representative
  37. // vertex of the component to which it belongs.
  38. //
  39. // Adapted from an implementation by Alex Stepanov. The disjoint
  40. // sets data structure is from Tarjan's "Data Structures and Network
  41. // Algorithms", and the application to connected components is
  42. // similar to the algorithm described in Ch. 22 of "Intro to
  43. // Algorithms" by Cormen, et. all.
  44. //
  45. // An implementation of disjoint sets can be found in
  46. // boost/pending/disjoint_sets.hpp
  47. template <class EdgeListGraph, class DisjointSets>
  48. void incremental_components(EdgeListGraph& g, DisjointSets& ds)
  49. {
  50. typename graph_traits<EdgeListGraph>::edge_iterator e, end;
  51. for (boost::tie(e,end) = edges(g); e != end; ++e)
  52. ds.union_set(source(*e,g),target(*e,g));
  53. }
  54. template <class ParentIterator>
  55. void compress_components(ParentIterator first, ParentIterator last)
  56. {
  57. for (ParentIterator current = first; current != last; ++current)
  58. detail::find_representative_with_full_compression(first, current-first);
  59. }
  60. template <class ParentIterator>
  61. typename boost::detail::iterator_traits<ParentIterator>::difference_type
  62. component_count(ParentIterator first, ParentIterator last)
  63. {
  64. std::ptrdiff_t count = 0;
  65. for (ParentIterator current = first; current != last; ++current)
  66. if (*current == current - first) ++count;
  67. return count;
  68. }
  69. // This algorithm can be applied to the result container of the
  70. // connected_components algorithm to normalize
  71. // the components.
  72. template <class ParentIterator>
  73. void normalize_components(ParentIterator first, ParentIterator last)
  74. {
  75. for (ParentIterator current = first; current != last; ++current)
  76. detail::normalize_node(first, current - first);
  77. }
  78. template <class VertexListGraph, class DisjointSets>
  79. void initialize_incremental_components(VertexListGraph& G, DisjointSets& ds)
  80. {
  81. typename graph_traits<VertexListGraph>
  82. ::vertex_iterator v, vend;
  83. for (boost::tie(v, vend) = vertices(G); v != vend; ++v)
  84. ds.make_set(*v);
  85. }
  86. template <class Vertex, class DisjointSet>
  87. inline bool same_component(Vertex u, Vertex v, DisjointSet& ds)
  88. {
  89. return ds.find_set(u) == ds.find_set(v);
  90. }
  91. // Class that builds a quick-access indexed linked list that allows
  92. // for fast iterating through a parent component's children.
  93. template <typename IndexType>
  94. class component_index {
  95. private:
  96. typedef std::vector<IndexType> IndexContainer;
  97. public:
  98. typedef counting_iterator<IndexType> iterator;
  99. typedef iterator const_iterator;
  100. typedef IndexType value_type;
  101. typedef IndexType size_type;
  102. typedef detail::component_index_iterator<typename IndexContainer::iterator>
  103. component_iterator;
  104. public:
  105. template <typename ParentIterator,
  106. typename ElementIndexMap>
  107. component_index(ParentIterator parent_start,
  108. ParentIterator parent_end,
  109. const ElementIndexMap& index_map) :
  110. m_num_elements(std::distance(parent_start, parent_end)),
  111. m_components(make_shared<IndexContainer>()),
  112. m_index_list(make_shared<IndexContainer>(m_num_elements)) {
  113. build_index_lists(parent_start, index_map);
  114. } // component_index
  115. template <typename ParentIterator>
  116. component_index(ParentIterator parent_start,
  117. ParentIterator parent_end) :
  118. m_num_elements(std::distance(parent_start, parent_end)),
  119. m_components(make_shared<IndexContainer>()),
  120. m_index_list(make_shared<IndexContainer>(m_num_elements)) {
  121. build_index_lists(parent_start, boost::identity_property_map());
  122. } // component_index
  123. // Returns the number of components
  124. inline std::size_t size() const {
  125. return (m_components->size());
  126. }
  127. // Beginning iterator for component indices
  128. iterator begin() const {
  129. return (iterator(0));
  130. }
  131. // End iterator for component indices
  132. iterator end() const {
  133. return (iterator(this->size()));
  134. }
  135. // Returns a pair of begin and end iterators for the child
  136. // elements of component [component_index].
  137. std::pair<component_iterator, component_iterator>
  138. operator[](IndexType component_index) const {
  139. IndexType first_index = (*m_components)[component_index];
  140. return (std::make_pair
  141. (component_iterator(m_index_list->begin(), first_index),
  142. component_iterator(m_num_elements)));
  143. }
  144. private:
  145. template <typename ParentIterator,
  146. typename ElementIndexMap>
  147. void build_index_lists(ParentIterator parent_start,
  148. const ElementIndexMap& index_map) {
  149. typedef typename std::iterator_traits<ParentIterator>::value_type Element;
  150. typename IndexContainer::iterator index_list =
  151. m_index_list->begin();
  152. // First pass - find root elements, construct index list
  153. for (IndexType element_index = 0; element_index < m_num_elements;
  154. ++element_index) {
  155. Element parent_element = parent_start[element_index];
  156. IndexType parent_index = get(index_map, parent_element);
  157. if (element_index != parent_index) {
  158. index_list[element_index] = parent_index;
  159. }
  160. else {
  161. m_components->push_back(element_index);
  162. // m_num_elements is the linked list terminator
  163. index_list[element_index] = m_num_elements;
  164. }
  165. }
  166. // Second pass - build linked list
  167. for (IndexType element_index = 0; element_index < m_num_elements;
  168. ++element_index) {
  169. Element parent_element = parent_start[element_index];
  170. IndexType parent_index = get(index_map, parent_element);
  171. if (element_index != parent_index) {
  172. // Follow list until a component parent is found
  173. while (index_list[parent_index] != m_num_elements) {
  174. parent_index = index_list[parent_index];
  175. }
  176. // Push element to the front of the linked list
  177. index_list[element_index] = index_list[parent_index];
  178. index_list[parent_index] = element_index;
  179. }
  180. }
  181. } // build_index_lists
  182. protected:
  183. IndexType m_num_elements;
  184. shared_ptr<IndexContainer> m_components, m_index_list;
  185. }; // class component_index
  186. } // namespace boost
  187. #endif // BOOST_INCREMENTAL_COMPONENTS_HPP