annotate DEPENDENCIES/generic/include/boost/graph/incremental_components.hpp @ 125:34e428693f5d vext

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