incremental_components.hpp 8.0 KB

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