Mercurial > hg > vamp-build-and-test
diff DEPENDENCIES/generic/include/boost/graph/incremental_components.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DEPENDENCIES/generic/include/boost/graph/incremental_components.hpp Tue Aug 05 11:11:38 2014 +0100 @@ -0,0 +1,231 @@ +// +//======================================================================= +// Copyright 1997-2001 University of Notre Dame. +// Copyright 2009 Trustees of Indiana University. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, Michael Hansen +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// + +#ifndef BOOST_INCREMENTAL_COMPONENTS_HPP +#define BOOST_INCREMENTAL_COMPONENTS_HPP + +#include <boost/detail/iterator.hpp> +#include <boost/graph/detail/incremental_components.hpp> +#include <boost/iterator/counting_iterator.hpp> +#include <boost/make_shared.hpp> +#include <boost/pending/disjoint_sets.hpp> +#include <iterator> + +namespace boost { + + // A connected component algorithm for the case when dynamically + // adding (but not removing) edges is common. The + // incremental_components() function is a preparing operation. Call + // same_component to check whether two vertices are in the same + // component, or use disjoint_set::find_set to determine the + // representative for a vertex. + + // This version of connected components does not require a full + // Graph. Instead, it just needs an edge list, where the vertices of + // each edge need to be of integer type. The edges are assumed to + // be undirected. The other difference is that the result is stored in + // a container, instead of just a decorator. The container should be + // empty before the algorithm is called. It will grow during the + // course of the algorithm. The container must be a model of + // BackInsertionSequence and RandomAccessContainer + // (std::vector is a good choice). After running the algorithm the + // index container will map each vertex to the representative + // vertex of the component to which it belongs. + // + // Adapted from an implementation by Alex Stepanov. The disjoint + // sets data structure is from Tarjan's "Data Structures and Network + // Algorithms", and the application to connected components is + // similar to the algorithm described in Ch. 22 of "Intro to + // Algorithms" by Cormen, et. all. + // + + // An implementation of disjoint sets can be found in + // boost/pending/disjoint_sets.hpp + + template <class EdgeListGraph, class DisjointSets> + void incremental_components(EdgeListGraph& g, DisjointSets& ds) + { + typename graph_traits<EdgeListGraph>::edge_iterator e, end; + for (boost::tie(e,end) = edges(g); e != end; ++e) + ds.union_set(source(*e,g),target(*e,g)); + } + + template <class ParentIterator> + void compress_components(ParentIterator first, ParentIterator last) + { + for (ParentIterator current = first; current != last; ++current) + detail::find_representative_with_full_compression(first, current-first); + } + + template <class ParentIterator> + typename boost::detail::iterator_traits<ParentIterator>::difference_type + component_count(ParentIterator first, ParentIterator last) + { + std::ptrdiff_t count = 0; + for (ParentIterator current = first; current != last; ++current) + if (*current == current - first) ++count; + return count; + } + + // This algorithm can be applied to the result container of the + // connected_components algorithm to normalize + // the components. + template <class ParentIterator> + void normalize_components(ParentIterator first, ParentIterator last) + { + for (ParentIterator current = first; current != last; ++current) + detail::normalize_node(first, current - first); + } + + template <class VertexListGraph, class DisjointSets> + void initialize_incremental_components(VertexListGraph& G, DisjointSets& ds) + { + typename graph_traits<VertexListGraph> + ::vertex_iterator v, vend; + for (boost::tie(v, vend) = vertices(G); v != vend; ++v) + ds.make_set(*v); + } + + template <class Vertex, class DisjointSet> + inline bool same_component(Vertex u, Vertex v, DisjointSet& ds) + { + return ds.find_set(u) == ds.find_set(v); + } + + // Class that builds a quick-access indexed linked list that allows + // for fast iterating through a parent component's children. + template <typename IndexType> + class component_index { + + private: + typedef std::vector<IndexType> IndexContainer; + + public: + typedef counting_iterator<IndexType> iterator; + typedef iterator const_iterator; + typedef IndexType value_type; + typedef IndexType size_type; + + typedef detail::component_index_iterator<typename IndexContainer::iterator> + component_iterator; + + public: + template <typename ParentIterator, + typename ElementIndexMap> + component_index(ParentIterator parent_start, + ParentIterator parent_end, + const ElementIndexMap& index_map) : + m_num_elements(std::distance(parent_start, parent_end)), + m_components(make_shared<IndexContainer>()), + m_index_list(make_shared<IndexContainer>(m_num_elements)) { + + build_index_lists(parent_start, index_map); + + } // component_index + + template <typename ParentIterator> + component_index(ParentIterator parent_start, + ParentIterator parent_end) : + m_num_elements(std::distance(parent_start, parent_end)), + m_components(make_shared<IndexContainer>()), + m_index_list(make_shared<IndexContainer>(m_num_elements)) { + + build_index_lists(parent_start, boost::identity_property_map()); + + } // component_index + + // Returns the number of components + inline std::size_t size() const { + return (m_components->size()); + } + + // Beginning iterator for component indices + iterator begin() const { + return (iterator(0)); + } + + // End iterator for component indices + iterator end() const { + return (iterator(this->size())); + } + + // Returns a pair of begin and end iterators for the child + // elements of component [component_index]. + std::pair<component_iterator, component_iterator> + operator[](IndexType component_index) const { + + IndexType first_index = (*m_components)[component_index]; + + return (std::make_pair + (component_iterator(m_index_list->begin(), first_index), + component_iterator(m_num_elements))); + } + + private: + template <typename ParentIterator, + typename ElementIndexMap> + void build_index_lists(ParentIterator parent_start, + const ElementIndexMap& index_map) { + + typedef typename std::iterator_traits<ParentIterator>::value_type Element; + typename IndexContainer::iterator index_list = + m_index_list->begin(); + + // First pass - find root elements, construct index list + for (IndexType element_index = 0; element_index < m_num_elements; + ++element_index) { + + Element parent_element = parent_start[element_index]; + IndexType parent_index = get(index_map, parent_element); + + if (element_index != parent_index) { + index_list[element_index] = parent_index; + } + else { + m_components->push_back(element_index); + + // m_num_elements is the linked list terminator + index_list[element_index] = m_num_elements; + } + } + + // Second pass - build linked list + for (IndexType element_index = 0; element_index < m_num_elements; + ++element_index) { + + Element parent_element = parent_start[element_index]; + IndexType parent_index = get(index_map, parent_element); + + if (element_index != parent_index) { + + // Follow list until a component parent is found + while (index_list[parent_index] != m_num_elements) { + parent_index = index_list[parent_index]; + } + + // Push element to the front of the linked list + index_list[element_index] = index_list[parent_index]; + index_list[parent_index] = element_index; + } + } + + } // build_index_lists + + protected: + IndexType m_num_elements; + shared_ptr<IndexContainer> m_components, m_index_list; + + }; // class component_index + +} // namespace boost + +#endif // BOOST_INCREMENTAL_COMPONENTS_HPP