Added boost header
This commit is contained in:
231
test/external/boost/graph/incremental_components.hpp
vendored
Normal file
231
test/external/boost/graph/incremental_components.hpp
vendored
Normal file
@@ -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
|
||||
Reference in New Issue
Block a user