Added boost header

This commit is contained in:
Christophe Riccio
2012-01-08 01:26:07 +00:00
parent 9c3faaca40
commit c7d752cdf8
8946 changed files with 1732316 additions and 0 deletions

View File

@@ -0,0 +1,117 @@
//
//=======================================================================
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
//
// 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_GRAPH_DETAIL_ADJ_LIST_EDGE_ITERATOR_HPP
#define BOOST_GRAPH_DETAIL_ADJ_LIST_EDGE_ITERATOR_HPP
#include <iterator>
#include <utility>
#include <boost/detail/workaround.hpp>
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
# define BOOST_GRAPH_NO_OPTIONAL
#endif
#ifdef BOOST_GRAPH_NO_OPTIONAL
# define BOOST_GRAPH_MEMBER .
#else
# define BOOST_GRAPH_MEMBER ->
# include <boost/optional.hpp>
#endif // ndef BOOST_GRAPH_NO_OPTIONAL
namespace boost {
namespace detail {
template <class VertexIterator, class OutEdgeIterator, class Graph>
class adj_list_edge_iterator {
typedef adj_list_edge_iterator self;
public:
typedef std::forward_iterator_tag iterator_category;
typedef typename OutEdgeIterator::value_type value_type;
typedef typename OutEdgeIterator::reference reference;
typedef typename OutEdgeIterator::pointer pointer;
typedef typename OutEdgeIterator::difference_type difference_type;
typedef difference_type distance_type;
inline adj_list_edge_iterator() {}
inline adj_list_edge_iterator(const self& x)
: vBegin(x.vBegin), vCurr(x.vCurr), vEnd(x.vEnd),
edges(x.edges), m_g(x.m_g) { }
template <class G>
inline adj_list_edge_iterator(VertexIterator b,
VertexIterator c,
VertexIterator e,
const G& g)
: vBegin(b), vCurr(c), vEnd(e), m_g(&g) {
if ( vCurr != vEnd ) {
while ( vCurr != vEnd && out_degree(*vCurr, *m_g) == 0 )
++vCurr;
if ( vCurr != vEnd )
edges = out_edges(*vCurr, *m_g);
}
}
/*Note:
In the directed graph cases, it is fine.
For undirected graphs, one edge go through twice.
*/
inline self& operator++() {
++edges BOOST_GRAPH_MEMBER first;
if (edges BOOST_GRAPH_MEMBER first == edges BOOST_GRAPH_MEMBER second)
{
++vCurr;
while ( vCurr != vEnd && out_degree(*vCurr, *m_g) == 0 )
++vCurr;
if ( vCurr != vEnd )
edges = out_edges(*vCurr, *m_g);
}
return *this;
}
inline self operator++(int) {
self tmp = *this;
++(*this);
return tmp;
}
inline value_type operator*() const
{ return *edges BOOST_GRAPH_MEMBER first; }
inline bool operator==(const self& x) const {
return vCurr == x.vCurr
&& (vCurr == vEnd
|| edges BOOST_GRAPH_MEMBER first == x.edges BOOST_GRAPH_MEMBER first);
}
inline bool operator!=(const self& x) const {
return vCurr != x.vCurr
|| (vCurr != vEnd
&& edges BOOST_GRAPH_MEMBER first != x.edges BOOST_GRAPH_MEMBER first);
}
protected:
VertexIterator vBegin;
VertexIterator vCurr;
VertexIterator vEnd;
#ifdef BOOST_GRAPH_NO_OPTIONAL
std::pair<OutEdgeIterator, OutEdgeIterator> edges;
#else
boost::optional<std::pair<OutEdgeIterator, OutEdgeIterator> >
edges;
#endif // ndef BOOST_GRAPH_NO_OPTIONAL
const Graph* m_g;
};
} // namespace detail
}
#undef BOOST_GRAPH_MEMBER
#endif // BOOST_GRAPH_DETAIL_ADJ_LIST_EDGE_ITERATOR_HPP

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,181 @@
//
//=======================================================================
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
//
// 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_ARRAY_BINARY_TREE_HPP
#define BOOST_ARRAY_BINARY_TREE_HPP
#include <iterator>
#include <functional>
#include <boost/config.hpp>
namespace boost {
/*
* Note: array_binary_tree is a completey balanced binary tree.
*/
#if !defined BOOST_NO_STD_ITERATOR_TRAITS
template <class RandomAccessIterator, class ID>
#else
template <class RandomAccessIterator, class ValueType, class ID>
#endif
class array_binary_tree_node {
public:
typedef array_binary_tree_node ArrayBinaryTreeNode;
typedef RandomAccessIterator rep_iterator;
#if !defined BOOST_NO_STD_ITERATOR_TRAITS
typedef typename std::iterator_traits<RandomAccessIterator>::difference_type
difference_type;
typedef typename std::iterator_traits<RandomAccessIterator>::value_type
value_type;
#else
typedef int difference_type;
typedef ValueType value_type;
#endif
typedef difference_type size_type;
struct children_type {
struct iterator
: boost::iterator<std::bidirectional_iterator_tag, ArrayBinaryTreeNode,
difference_type, array_binary_tree_node*, ArrayBinaryTreeNode&>
{ // replace with iterator_adaptor implementation -JGS
inline iterator() : i(0), n(0) { }
inline iterator(const iterator& x) : r(x.r), i(x.i), n(x.n), id(x.id) { }
inline iterator& operator=(const iterator& x) {
r = x.r; i = x.i; n = x.n;
/*egcs generate a warning*/
id = x.id;
return *this;
}
inline iterator(rep_iterator rr,
size_type ii,
size_type nn,
const ID& _id) : r(rr), i(ii), n(nn), id(_id) { }
inline array_binary_tree_node operator*() {
return ArrayBinaryTreeNode(r, i, n, id); }
inline iterator& operator++() { ++i; return *this; }
inline iterator operator++(int)
{ iterator t = *this; ++(*this); return t; }
inline bool operator==(const iterator& x) const { return i == x.i; }
inline bool operator!=(const iterator& x) const
{ return !(*this == x); }
rep_iterator r;
size_type i;
size_type n;
ID id;
};
inline children_type() : i(0), n(0) { }
inline children_type(const children_type& x)
: r(x.r), i(x.i), n(x.n), id(x.id) { }
inline children_type& operator=(const children_type& x) {
r = x.r; i = x.i; n = x.n;
/*egcs generate a warning*/
id = x.id;
return *this;
}
inline children_type(rep_iterator rr,
size_type ii,
size_type nn,
const ID& _id) : r(rr), i(ii), n(nn), id(_id) { }
inline iterator begin() { return iterator(r, 2 * i + 1, n, id); }
inline iterator end() { return iterator(r, 2 * i + 1 + size(), n, id); }
inline size_type size() const {
size_type c = 2 * i + 1;
size_type s;
if (c + 1 < n) s = 2;
else if (c < n) s = 1;
else s = 0;
return s;
}
rep_iterator r;
size_type i;
size_type n;
ID id;
};
inline array_binary_tree_node() : i(0), n(0) { }
inline array_binary_tree_node(const array_binary_tree_node& x)
: r(x.r), i(x.i), n(x.n), id(x.id) { }
inline ArrayBinaryTreeNode& operator=(const ArrayBinaryTreeNode& x) {
r = x.r;
i = x.i;
n = x.n;
/*egcs generate a warning*/
id = x.id;
return *this;
}
inline array_binary_tree_node(rep_iterator start,
rep_iterator end,
rep_iterator pos, const ID& _id)
: r(start), i(pos - start), n(end - start), id(_id) { }
inline array_binary_tree_node(rep_iterator rr,
size_type ii,
size_type nn, const ID& _id)
: r(rr), i(ii), n(nn), id(_id) { }
inline value_type& value() { return *(r + i); }
inline const value_type& value() const { return *(r + i); }
inline ArrayBinaryTreeNode parent() const {
return ArrayBinaryTreeNode(r, (i - 1) / 2, n, id);
}
inline bool has_parent() const { return i != 0; }
inline children_type children() { return children_type(r, i, n, id); }
/*
inline void swap(array_binary_tree_node x) {
value_type tmp = x.value();
x.value() = value();
value() = tmp;
i = x.i;
}
*/
template <class ExternalData>
inline void swap(ArrayBinaryTreeNode x, ExternalData& edata ) {
using boost::get;
value_type tmp = x.value();
/*swap external data*/
edata[ get(id, tmp) ] = i;
edata[ get(id, value()) ] = x.i;
x.value() = value();
value() = tmp;
i = x.i;
}
inline const children_type children() const {
return children_type(r, i, n);
}
inline size_type index() const { return i; }
rep_iterator r;
size_type i;
size_type n;
ID id;
};
template <class RandomAccessContainer,
class Compare = std::less<typename RandomAccessContainer::value_type> >
struct compare_array_node {
typedef typename RandomAccessContainer::value_type value_type;
compare_array_node(const Compare& x) : comp(x) {}
compare_array_node(const compare_array_node& x) : comp(x.comp) {}
template< class node_type >
inline bool operator()(const node_type& x, const node_type& y) {
return comp(x.value(), y.value());
}
template< class node_type >
inline bool operator()(const node_type& x, const node_type& y) const {
return comp(x.value(), y.value());
}
Compare comp;
};
} // namespace boost
#endif /* BOOST_ARRAY_BINARY_TREE_HPP */

View File

@@ -0,0 +1,652 @@
// Copyright 2005-2009 The Trustees of Indiana University.
// 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)
// Authors: Jeremiah Willcock
// Douglas Gregor
// Andrew Lumsdaine
// Compressed sparse row graph type internal structure
#ifndef BOOST_GRAPH_COMPRESSED_SPARSE_ROW_STRUCT_HPP
#define BOOST_GRAPH_COMPRESSED_SPARSE_ROW_STRUCT_HPP
#ifndef BOOST_GRAPH_COMPRESSED_SPARSE_ROW_GRAPH_HPP
#error This file should only be included from boost/graph/compressed_sparse_row_graph.hpp
#endif
#include <vector>
#include <utility>
#include <algorithm>
#include <climits>
#include <boost/assert.hpp>
#include <iterator>
#if 0
#include <iostream> // For some debugging code below
#endif
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/properties.hpp>
#include <boost/graph/filtered_graph.hpp> // For keep_all
#include <boost/graph/detail/indexed_properties.hpp>
#include <boost/graph/detail/histogram_sort.hpp>
#include <boost/graph/iteration_macros.hpp>
#include <boost/iterator/counting_iterator.hpp>
#include <boost/iterator/reverse_iterator.hpp>
#include <boost/iterator/zip_iterator.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/integer.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/mpl/if.hpp>
#include <boost/graph/graph_selectors.hpp>
#include <boost/static_assert.hpp>
#include <boost/functional/hash.hpp>
#include <boost/utility.hpp>
namespace boost {
namespace detail {
// Forward declaration of CSR edge descriptor type, needed to pass to
// indexed_edge_properties.
template<typename Vertex, typename EdgeIndex>
class csr_edge_descriptor;
// Add edge_index property map
template<typename Vertex, typename EdgeIndex>
struct csr_edge_index_map
{
typedef EdgeIndex value_type;
typedef EdgeIndex reference;
typedef csr_edge_descriptor<Vertex, EdgeIndex> key_type;
typedef readable_property_map_tag category;
};
template<typename Vertex, typename EdgeIndex>
inline EdgeIndex
get(const csr_edge_index_map<Vertex, EdgeIndex>&,
const csr_edge_descriptor<Vertex, EdgeIndex>& key)
{
return key.idx;
}
/** Compressed sparse row graph internal structure.
*
* Vertex and EdgeIndex should be unsigned integral types and should
* specialize numeric_limits.
*/
template <typename EdgeProperty,
typename Vertex = std::size_t, typename EdgeIndex = Vertex>
class compressed_sparse_row_structure :
public detail::indexed_edge_properties<
compressed_sparse_row_structure<EdgeProperty, Vertex, EdgeIndex>,
EdgeProperty,
csr_edge_descriptor<Vertex, EdgeIndex>,
csr_edge_index_map<Vertex, EdgeIndex> > {
public:
typedef detail::indexed_edge_properties<
compressed_sparse_row_structure<EdgeProperty, Vertex, EdgeIndex>,
EdgeProperty,
csr_edge_descriptor<Vertex, EdgeIndex>,
csr_edge_index_map<Vertex, EdgeIndex> >
inherited_edge_properties;
typedef Vertex vertices_size_type;
typedef Vertex vertex_descriptor;
typedef EdgeIndex edges_size_type;
static vertex_descriptor null_vertex() { return vertex_descriptor(-1); }
std::vector<EdgeIndex> m_rowstart;
std::vector<Vertex> m_column;
compressed_sparse_row_structure(Vertex numverts = 0)
: m_rowstart(numverts + 1, EdgeIndex(0)), m_column()
{}
// Rebuild graph from number of vertices and multi-pass unsorted list of
// edges (filtered using source_pred and mapped using global_to_local)
template <typename MultiPassInputIterator, typename GlobalToLocal, typename SourcePred>
void
assign_unsorted_multi_pass_edges(MultiPassInputIterator edge_begin,
MultiPassInputIterator edge_end,
vertices_size_type numlocalverts,
const GlobalToLocal& global_to_local,
const SourcePred& source_pred) {
m_rowstart.clear();
m_rowstart.resize(numlocalverts + 1, 0);
typedef std::pair<vertices_size_type, vertices_size_type> edge_type;
typedef boost::transform_iterator<boost::graph::detail::project1st<edge_type>, MultiPassInputIterator> source_iterator;
typedef boost::transform_iterator<boost::graph::detail::project2nd<edge_type>, MultiPassInputIterator> target_iterator;
source_iterator sources_begin(edge_begin, boost::graph::detail::project1st<edge_type>());
source_iterator sources_end(edge_end, boost::graph::detail::project1st<edge_type>());
target_iterator targets_begin(edge_begin, boost::graph::detail::project2nd<edge_type>());
target_iterator targets_end(edge_end, boost::graph::detail::project2nd<edge_type>());
boost::graph::detail::count_starts
(sources_begin, sources_end, m_rowstart.begin(), numlocalverts,
source_pred, boost::make_property_map_function(global_to_local));
m_column.resize(m_rowstart.back());
inherited_edge_properties::resize(m_rowstart.back());
boost::graph::detail::histogram_sort
(sources_begin, sources_end, m_rowstart.begin(), numlocalverts,
targets_begin, m_column.begin(),
source_pred, boost::make_property_map_function(global_to_local));
}
// Rebuild graph from number of vertices and multi-pass unsorted list of
// edges and their properties (filtered using source_pred and mapped using
// global_to_local)
template <typename MultiPassInputIterator, typename EdgePropertyIterator, typename GlobalToLocal, typename SourcePred>
void
assign_unsorted_multi_pass_edges(MultiPassInputIterator edge_begin,
MultiPassInputIterator edge_end,
EdgePropertyIterator ep_iter,
vertices_size_type numlocalverts,
const GlobalToLocal& global_to_local,
const SourcePred& source_pred) {
m_rowstart.clear();
m_rowstart.resize(numlocalverts + 1, 0);
typedef std::pair<vertices_size_type, vertices_size_type> edge_type;
typedef boost::transform_iterator<boost::graph::detail::project1st<edge_type>, MultiPassInputIterator> source_iterator;
typedef boost::transform_iterator<boost::graph::detail::project2nd<edge_type>, MultiPassInputIterator> target_iterator;
source_iterator sources_begin(edge_begin, boost::graph::detail::project1st<edge_type>());
source_iterator sources_end(edge_end, boost::graph::detail::project1st<edge_type>());
target_iterator targets_begin(edge_begin, boost::graph::detail::project2nd<edge_type>());
target_iterator targets_end(edge_end, boost::graph::detail::project2nd<edge_type>());
boost::graph::detail::count_starts
(sources_begin, sources_end, m_rowstart.begin(), numlocalverts,
source_pred, boost::make_property_map_function(global_to_local));
m_column.resize(m_rowstart.back());
inherited_edge_properties::resize(m_rowstart.back());
boost::graph::detail::histogram_sort
(sources_begin, sources_end, m_rowstart.begin(), numlocalverts,
targets_begin, m_column.begin(),
ep_iter, inherited_edge_properties::begin(),
source_pred, boost::make_property_map_function(global_to_local));
}
// Assign from number of vertices and sorted list of edges
template<typename InputIterator, typename GlobalToLocal, typename SourcePred>
void assign_from_sorted_edges(
InputIterator edge_begin, InputIterator edge_end,
const GlobalToLocal& global_to_local,
const SourcePred& source_pred,
vertices_size_type numlocalverts,
edges_size_type numedges_or_zero) {
m_column.clear();
m_column.reserve(numedges_or_zero);
m_rowstart.resize(numlocalverts + 1);
EdgeIndex current_edge = 0;
Vertex current_vertex_plus_one = 1;
m_rowstart[0] = 0;
for (InputIterator ei = edge_begin; ei != edge_end; ++ei) {
if (!source_pred(ei->first)) continue;
Vertex src = get(global_to_local, ei->first);
Vertex tgt = ei->second;
for (; current_vertex_plus_one != src + 1; ++current_vertex_plus_one)
m_rowstart[current_vertex_plus_one] = current_edge;
m_column.push_back(tgt);
++current_edge;
}
// The remaining vertices have no edges
for (; current_vertex_plus_one != numlocalverts + 1; ++current_vertex_plus_one)
m_rowstart[current_vertex_plus_one] = current_edge;
// Default-construct properties for edges
inherited_edge_properties::resize(m_column.size());
}
// Assign from number of vertices and sorted list of edges
template<typename InputIterator, typename EdgePropertyIterator, typename GlobalToLocal, typename SourcePred>
void assign_from_sorted_edges(
InputIterator edge_begin, InputIterator edge_end,
EdgePropertyIterator ep_iter,
const GlobalToLocal& global_to_local,
const SourcePred& source_pred,
vertices_size_type numlocalverts,
edges_size_type numedges_or_zero) {
// Reserving storage in advance can save us lots of time and
// memory, but it can only be done if we have forward iterators or
// the user has supplied the number of edges.
edges_size_type numedges = numedges_or_zero;
if (numedges == 0) {
typedef typename std::iterator_traits<InputIterator>::iterator_category
category;
numedges = boost::graph::detail::reserve_count_for_single_pass(edge_begin, edge_end);
}
m_column.clear();
m_column.reserve(numedges_or_zero);
inherited_edge_properties::clear();
inherited_edge_properties::reserve(numedges_or_zero);
m_rowstart.resize(numlocalverts + 1);
EdgeIndex current_edge = 0;
Vertex current_vertex_plus_one = 1;
m_rowstart[0] = 0;
for (InputIterator ei = edge_begin; ei != edge_end; ++ei, ++ep_iter) {
if (!source_pred(ei->first)) continue;
Vertex src = get(global_to_local, ei->first);
Vertex tgt = ei->second;
for (; current_vertex_plus_one != src + 1; ++current_vertex_plus_one)
m_rowstart[current_vertex_plus_one] = current_edge;
m_column.push_back(tgt);
inherited_edge_properties::push_back(*ep_iter);
++current_edge;
}
// The remaining vertices have no edges
for (; current_vertex_plus_one != numlocalverts + 1; ++current_vertex_plus_one)
m_rowstart[current_vertex_plus_one] = current_edge;
}
// Replace graph with sources and targets given, sorting them in-place, and
// using the given global-to-local property map to get local indices from
// global ones in the two arrays.
template <typename GlobalToLocal>
void assign_sources_and_targets_global(std::vector<vertex_descriptor>& sources,
std::vector<vertex_descriptor>& targets,
vertices_size_type numverts,
GlobalToLocal global_to_local) {
BOOST_ASSERT (sources.size() == targets.size());
// Do an in-place histogram sort (at least that's what I think it is) to
// sort sources and targets
m_rowstart.clear();
m_rowstart.resize(numverts + 1);
boost::graph::detail::count_starts
(sources.begin(), sources.end(), m_rowstart.begin(), numverts,
keep_all(), boost::make_property_map_function(global_to_local));
boost::graph::detail::histogram_sort_inplace
(sources.begin(), m_rowstart.begin(), numverts,
targets.begin(), boost::make_property_map_function(global_to_local));
// Now targets is the correct vector (properly sorted by source) for
// m_column
m_column.swap(targets);
inherited_edge_properties::resize(m_rowstart.back());
}
// Replace graph with sources and targets and edge properties given, sorting
// them in-place, and using the given global-to-local property map to get
// local indices from global ones in the two arrays.
template <typename GlobalToLocal>
void assign_sources_and_targets_global(std::vector<vertex_descriptor>& sources,
std::vector<vertex_descriptor>& targets,
std::vector<typename inherited_edge_properties::edge_bundled>& edge_props,
vertices_size_type numverts,
GlobalToLocal global_to_local) {
BOOST_ASSERT (sources.size() == targets.size());
BOOST_ASSERT (sources.size() == edge_props.size());
// Do an in-place histogram sort (at least that's what I think it is) to
// sort sources and targets
m_rowstart.clear();
m_rowstart.resize(numverts + 1);
boost::graph::detail::count_starts
(sources.begin(), sources.end(), m_rowstart.begin(), numverts,
keep_all(), boost::make_property_map_function(global_to_local));
boost::graph::detail::histogram_sort_inplace
(sources.begin(), m_rowstart.begin(), numverts,
targets.begin(), edge_props.begin(),
boost::make_property_map_function(global_to_local));
// Now targets is the correct vector (properly sorted by source) for
// m_column, and edge_props for m_edge_properties
m_column.swap(targets);
this->m_edge_properties.swap(edge_props);
}
// From any graph (slow and uses a lot of memory)
// Requires IncidenceGraph and a vertex index map
// Internal helper function
// Note that numedges must be doubled for undirected source graphs
template<typename Graph, typename VertexIndexMap>
void
assign(const Graph& g, const VertexIndexMap& vi,
vertices_size_type numverts, edges_size_type numedges)
{
m_rowstart.resize(numverts + 1);
m_column.resize(numedges);
inherited_edge_properties::resize(numedges);
EdgeIndex current_edge = 0;
typedef typename boost::graph_traits<Graph>::vertex_descriptor g_vertex;
typedef typename boost::graph_traits<Graph>::edge_descriptor g_edge;
typedef typename boost::graph_traits<Graph>::out_edge_iterator
g_out_edge_iter;
std::vector<g_vertex> ordered_verts_of_g(numverts);
BGL_FORALL_VERTICES_T(v, g, Graph) {
ordered_verts_of_g[get(vertex_index, g, v)] = v;
}
for (Vertex i = 0; i != numverts; ++i) {
m_rowstart[i] = current_edge;
g_vertex v = ordered_verts_of_g[i];
g_out_edge_iter ei, ei_end;
for (boost::tie(ei, ei_end) = out_edges(v, g); ei != ei_end; ++ei) {
m_column[current_edge++] = get(vi, target(*ei, g));
}
}
m_rowstart[numverts] = current_edge;
}
// Add edges from a sorted (smallest sources first) range of pairs and edge
// properties
template <typename BidirectionalIteratorOrig, typename EPIterOrig,
typename GlobalToLocal>
void
add_edges_sorted_internal(
BidirectionalIteratorOrig first_sorted,
BidirectionalIteratorOrig last_sorted,
EPIterOrig ep_iter_sorted,
const GlobalToLocal& global_to_local) {
typedef boost::reverse_iterator<BidirectionalIteratorOrig> BidirectionalIterator;
typedef boost::reverse_iterator<EPIterOrig> EPIter;
// Flip sequence
BidirectionalIterator first(last_sorted);
BidirectionalIterator last(first_sorted);
typedef Vertex vertex_t;
typedef Vertex vertex_num;
typedef EdgeIndex edge_num;
edge_num new_edge_count = std::distance(first, last);
EPIter ep_iter(ep_iter_sorted);
std::advance(ep_iter, -(std::ptrdiff_t)new_edge_count);
edge_num edges_added_before_i = new_edge_count; // Count increment to add to rowstarts
m_column.resize(m_column.size() + new_edge_count);
inherited_edge_properties::resize(inherited_edge_properties::size() + new_edge_count);
BidirectionalIterator current_new_edge = first, prev_new_edge = first;
EPIter current_new_edge_prop = ep_iter;
for (vertex_num i_plus_1 = m_rowstart.size() - 1; i_plus_1 > 0; --i_plus_1) {
vertex_num i = i_plus_1 - 1;
prev_new_edge = current_new_edge;
// edges_added_to_this_vertex = #mbrs of new_edges with first == i
edge_num edges_added_to_this_vertex = 0;
while (current_new_edge != last) {
if (get(global_to_local, current_new_edge->first) != i) break;
++current_new_edge;
++current_new_edge_prop;
++edges_added_to_this_vertex;
}
edges_added_before_i -= edges_added_to_this_vertex;
// Invariant: edges_added_before_i = #mbrs of new_edges with first < i
edge_num old_rowstart = m_rowstart[i];
edge_num new_rowstart = m_rowstart[i] + edges_added_before_i;
edge_num old_degree = m_rowstart[i + 1] - m_rowstart[i];
edge_num new_degree = old_degree + edges_added_to_this_vertex;
// Move old edges forward (by #new_edges before this i) to make room
// new_rowstart > old_rowstart, so use copy_backwards
if (old_rowstart != new_rowstart) {
std::copy_backward(m_column.begin() + old_rowstart,
m_column.begin() + old_rowstart + old_degree,
m_column.begin() + new_rowstart + old_degree);
inherited_edge_properties::move_range(old_rowstart, old_rowstart + old_degree, new_rowstart);
}
// Add new edges (reversed because current_new_edge is a
// const_reverse_iterator)
BidirectionalIterator temp = current_new_edge;
EPIter temp_prop = current_new_edge_prop;
for (; temp != prev_new_edge; ++old_degree) {
--temp;
--temp_prop;
m_column[new_rowstart + old_degree] = temp->second;
inherited_edge_properties::write_by_index(new_rowstart + old_degree, *temp_prop);
}
m_rowstart[i + 1] = new_rowstart + new_degree;
if (edges_added_before_i == 0) break; // No more edges inserted before this point
// m_rowstart[i] will be fixed up on the next iteration (to avoid
// changing the degree of vertex i - 1); the last iteration never changes
// it (either because of the condition of the break or because
// m_rowstart[0] is always 0)
}
}
};
template<typename Vertex, typename EdgeIndex>
class csr_edge_descriptor
{
public:
Vertex src;
EdgeIndex idx;
csr_edge_descriptor(Vertex src, EdgeIndex idx): src(src), idx(idx) {}
csr_edge_descriptor(): src(0), idx(0) {}
bool operator==(const csr_edge_descriptor& e) const {return idx == e.idx;}
bool operator!=(const csr_edge_descriptor& e) const {return idx != e.idx;}
bool operator<(const csr_edge_descriptor& e) const {return idx < e.idx;}
bool operator>(const csr_edge_descriptor& e) const {return idx > e.idx;}
bool operator<=(const csr_edge_descriptor& e) const {return idx <= e.idx;}
bool operator>=(const csr_edge_descriptor& e) const {return idx >= e.idx;}
template<typename Archiver>
void serialize(Archiver& ar, const unsigned int /*version*/)
{
ar & src & idx;
}
};
// Common out edge and edge iterators
template<typename CSRGraph>
class csr_out_edge_iterator
: public iterator_facade<csr_out_edge_iterator<CSRGraph>,
typename CSRGraph::edge_descriptor,
std::random_access_iterator_tag,
const typename CSRGraph::edge_descriptor&,
typename int_t<CHAR_BIT * sizeof(typename CSRGraph::edges_size_type)>::fast>
{
public:
typedef typename CSRGraph::edges_size_type EdgeIndex;
typedef typename CSRGraph::edge_descriptor edge_descriptor;
typedef typename int_t<CHAR_BIT * sizeof(EdgeIndex)>::fast difference_type;
csr_out_edge_iterator() {}
// Implicit copy constructor OK
explicit csr_out_edge_iterator(edge_descriptor edge) : m_edge(edge) { }
public: // GCC 4.2.1 doesn't like the private-and-friend thing
// iterator_facade requirements
const edge_descriptor& dereference() const { return m_edge; }
bool equal(const csr_out_edge_iterator& other) const
{ return m_edge == other.m_edge; }
void increment() { ++m_edge.idx; }
void decrement() { --m_edge.idx; }
void advance(difference_type n) { m_edge.idx += n; }
difference_type distance_to(const csr_out_edge_iterator& other) const
{ return other.m_edge.idx - m_edge.idx; }
edge_descriptor m_edge;
friend class iterator_core_access;
};
template<typename CSRGraph>
class csr_edge_iterator
: public iterator_facade<csr_edge_iterator<CSRGraph>,
typename CSRGraph::edge_descriptor,
boost::forward_traversal_tag,
typename CSRGraph::edge_descriptor>
{
private:
typedef typename CSRGraph::edge_descriptor edge_descriptor;
typedef typename CSRGraph::edges_size_type EdgeIndex;
public:
csr_edge_iterator() : rowstart_array(0), current_edge(), end_of_this_vertex(0), total_num_edges(0) {}
csr_edge_iterator(const CSRGraph& graph,
edge_descriptor current_edge,
EdgeIndex end_of_this_vertex)
: rowstart_array(&graph.m_forward.m_rowstart[0]),
current_edge(current_edge),
end_of_this_vertex(end_of_this_vertex),
total_num_edges(num_edges(graph)) {}
public: // See above
friend class boost::iterator_core_access;
edge_descriptor dereference() const {return current_edge;}
bool equal(const csr_edge_iterator& o) const {
return current_edge == o.current_edge;
}
void increment() {
++current_edge.idx;
if (current_edge.idx == total_num_edges) return;
while (current_edge.idx == end_of_this_vertex) {
++current_edge.src;
end_of_this_vertex = rowstart_array[current_edge.src + 1];
}
}
const EdgeIndex* rowstart_array;
edge_descriptor current_edge;
EdgeIndex end_of_this_vertex;
EdgeIndex total_num_edges;
};
// Only for bidirectional graphs
template<typename CSRGraph>
class csr_in_edge_iterator
: public iterator_facade<csr_in_edge_iterator<CSRGraph>,
typename CSRGraph::edge_descriptor,
boost::forward_traversal_tag,
typename CSRGraph::edge_descriptor>
{
public:
typedef typename CSRGraph::edges_size_type EdgeIndex;
typedef typename CSRGraph::edge_descriptor edge_descriptor;
csr_in_edge_iterator(): m_graph(0) {}
// Implicit copy constructor OK
csr_in_edge_iterator(const CSRGraph& graph,
EdgeIndex index_in_backward_graph)
: m_index_in_backward_graph(index_in_backward_graph), m_graph(&graph) {}
public: // See above
// iterator_facade requirements
edge_descriptor dereference() const {
return edge_descriptor(
m_graph->m_backward.m_column[m_index_in_backward_graph],
m_graph->m_backward.m_edge_properties[m_index_in_backward_graph]);
}
bool equal(const csr_in_edge_iterator& other) const
{ return m_index_in_backward_graph == other.m_index_in_backward_graph; }
void increment() { ++m_index_in_backward_graph; }
void decrement() { --m_index_in_backward_graph; }
void advance(std::ptrdiff_t n) { m_index_in_backward_graph += n; }
std::ptrdiff_t distance_to(const csr_in_edge_iterator& other) const
{ return other.m_index_in_backward_graph - m_index_in_backward_graph; }
EdgeIndex m_index_in_backward_graph;
const CSRGraph* m_graph;
friend class iterator_core_access;
};
template <typename A, typename B>
struct transpose_pair {
typedef std::pair<B, A> result_type;
result_type operator()(const std::pair<A, B>& p) const {
return result_type(p.second, p.first);
}
};
template <typename Iter>
struct transpose_iterator_gen {
typedef typename std::iterator_traits<Iter>::value_type vt;
typedef typename vt::first_type first_type;
typedef typename vt::second_type second_type;
typedef transpose_pair<first_type, second_type> transpose;
typedef boost::transform_iterator<transpose, Iter> type;
static type make(Iter it) {
return type(it, transpose());
}
};
template <typename Iter>
typename transpose_iterator_gen<Iter>::type transpose_edges(Iter i) {
return transpose_iterator_gen<Iter>::make(i);
}
template<typename GraphT, typename VertexIndexMap>
class edge_to_index_pair
{
typedef typename boost::graph_traits<GraphT>::vertices_size_type
vertices_size_type;
typedef typename boost::graph_traits<GraphT>::edge_descriptor edge_descriptor;
public:
typedef std::pair<vertices_size_type, vertices_size_type> result_type;
edge_to_index_pair() : g(0), index() { }
edge_to_index_pair(const GraphT& g, const VertexIndexMap& index)
: g(&g), index(index)
{ }
result_type operator()(edge_descriptor e) const
{
return result_type(get(index, source(e, *g)), get(index, target(e, *g)));
}
private:
const GraphT* g;
VertexIndexMap index;
};
template<typename GraphT, typename VertexIndexMap>
edge_to_index_pair<GraphT, VertexIndexMap>
make_edge_to_index_pair(const GraphT& g, const VertexIndexMap& index)
{
return edge_to_index_pair<GraphT, VertexIndexMap>(g, index);
}
template<typename GraphT>
edge_to_index_pair
<GraphT,
typename boost::property_map<GraphT,boost::vertex_index_t>::const_type>
make_edge_to_index_pair(const GraphT& g)
{
typedef typename boost::property_map<GraphT,
boost::vertex_index_t>::const_type
VertexIndexMap;
return edge_to_index_pair<GraphT, VertexIndexMap>(g,
get(boost::vertex_index,
g));
}
template<typename GraphT, typename VertexIndexMap, typename Iter>
boost::transform_iterator<edge_to_index_pair<GraphT, VertexIndexMap>, Iter>
make_edge_to_index_pair_iter(const GraphT& g, const VertexIndexMap& index,
Iter it) {
return boost::transform_iterator<edge_to_index_pair<GraphT, VertexIndexMap>, Iter>(it, edge_to_index_pair<GraphT, VertexIndexMap>(g, index));
}
} // namespace detail
template<typename Vertex, typename EdgeIndex>
struct hash<detail::csr_edge_descriptor<Vertex, EdgeIndex> >
{
std::size_t operator()
(detail::csr_edge_descriptor<Vertex, EdgeIndex> const& x) const
{
std::size_t hash = hash_value(x.src);
hash_combine(hash, x.idx);
return hash;
}
};
} // namespace boost
#endif // BOOST_GRAPH_COMPRESSED_SPARSE_ROW_STRUCT_HPP

View File

@@ -0,0 +1,208 @@
//=======================================================================
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
//
// 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_GRAPH_DETAIL_CONNECTED_COMPONENTS_HPP
#define BOOST_GRAPH_DETAIL_CONNECTED_COMPONENTS_HPP
#if defined(__sgi) && !defined(__GNUC__)
#pragma set woff 1234
#endif
#include <boost/operators.hpp>
namespace boost {
namespace detail {
//=========================================================================
// Implementation details of connected_components
// This is used both in the connected_components algorithm and in
// the kosaraju strong components algorithm during the second DFS
// traversal.
template <class ComponentsPA, class DFSVisitor>
class components_recorder : public DFSVisitor
{
typedef typename property_traits<ComponentsPA>::value_type comp_type;
public:
components_recorder(ComponentsPA c,
comp_type& c_count,
DFSVisitor v)
: DFSVisitor(v), m_component(c), m_count(c_count) {}
template <class Vertex, class Graph>
void start_vertex(Vertex u, Graph& g) {
++m_count;
DFSVisitor::start_vertex(u, g);
}
template <class Vertex, class Graph>
void discover_vertex(Vertex u, Graph& g) {
put(m_component, u, m_count);
DFSVisitor::discover_vertex(u, g);
}
protected:
ComponentsPA m_component;
comp_type& m_count;
};
template <class DiscoverTimeMap, class FinishTimeMap, class TimeT,
class DFSVisitor>
class time_recorder : public DFSVisitor
{
public:
time_recorder(DiscoverTimeMap d, FinishTimeMap f, TimeT& t, DFSVisitor v)
: DFSVisitor(v), m_discover_time(d), m_finish_time(f), m_t(t) {}
template <class Vertex, class Graph>
void discover_vertex(Vertex u, Graph& g) {
put(m_discover_time, u, ++m_t);
DFSVisitor::discover_vertex(u, g);
}
template <class Vertex, class Graph>
void finish_vertex(Vertex u, Graph& g) {
put(m_finish_time, u, ++m_t);
DFSVisitor::discover_vertex(u, g);
}
protected:
DiscoverTimeMap m_discover_time;
FinishTimeMap m_finish_time;
TimeT m_t;
};
template <class DiscoverTimeMap, class FinishTimeMap, class TimeT,
class DFSVisitor>
time_recorder<DiscoverTimeMap, FinishTimeMap, TimeT, DFSVisitor>
record_times(DiscoverTimeMap d, FinishTimeMap f, TimeT& t, DFSVisitor vis)
{
return time_recorder<DiscoverTimeMap, FinishTimeMap, TimeT, DFSVisitor>
(d, f, t, vis);
}
//=========================================================================
// Implementation detail of dynamic_components
//-------------------------------------------------------------------------
// Helper functions for the component_index class
// Record the representative vertices in the header array.
// Representative vertices now point to the component number.
template <class Parent, class OutputIterator, class Integer>
inline void
build_components_header(Parent p,
OutputIterator header,
Integer num_nodes)
{
Parent component = p;
Integer component_num = 0;
for (Integer v = 0; v != num_nodes; ++v)
if (p[v] == v) {
*header++ = v;
component[v] = component_num++;
}
}
// Pushes x onto the front of the list. The list is represented in
// an array.
template <class Next, class T, class V>
inline void push_front(Next next, T& head, V x)
{
T tmp = head;
head = x;
next[x] = tmp;
}
// Create a linked list of the vertices in each component
// by reusing the representative array.
template <class Parent1, class Parent2,
class Integer>
void
link_components(Parent1 component, Parent2 header,
Integer num_nodes, Integer num_components)
{
// Make the non-representative vertices point to their component
Parent1 representative = component;
for (Integer v = 0; v != num_nodes; ++v)
if (component[v] >= num_components || header[component[v]] != v)
component[v] = component[representative[v]];
// initialize the "head" of the lists to "NULL"
std::fill_n(header, num_components, num_nodes);
// Add each vertex to the linked list for its component
Parent1 next = component;
for (Integer k = 0; k != num_nodes; ++k)
push_front(next, header[component[k]], k);
}
template <class IndexContainer, class HeaderContainer>
void
construct_component_index(IndexContainer& index, HeaderContainer& header)
{
build_components_header(index.begin(),
std::back_inserter(header),
index.end() - index.begin());
link_components(index.begin(), header.begin(),
index.end() - index.begin(),
header.end() - header.begin());
}
template <class IndexIterator, class Integer, class Distance>
class component_iterator
: boost::forward_iterator_helper<
component_iterator<IndexIterator,Integer,Distance>,
Integer, Distance,Integer*, Integer&>
{
public:
typedef component_iterator self;
IndexIterator next;
Integer node;
typedef std::forward_iterator_tag iterator_category;
typedef Integer value_type;
typedef Integer& reference;
typedef Integer* pointer;
typedef Distance difference_type;
component_iterator() {}
component_iterator(IndexIterator x, Integer i)
: next(x), node(i) {}
Integer operator*() const {
return node;
}
self& operator++() {
node = next[node];
return *this;
}
};
template <class IndexIterator, class Integer, class Distance>
inline bool
operator==(const component_iterator<IndexIterator, Integer, Distance>& x,
const component_iterator<IndexIterator, Integer, Distance>& y)
{
return x.node == y.node;
}
} // namespace detail
} // namespace detail
#if defined(__sgi) && !defined(__GNUC__)
#pragma reset woff 1234
#endif
#endif

View File

@@ -0,0 +1,311 @@
//
//=======================================================================
// Copyright 2009 Trustees of Indiana University
// Authors: Jeremiah J. Willcock, Andrew Lumsdaine
//
// 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_D_ARY_HEAP_HPP
#define BOOST_D_ARY_HEAP_HPP
#include <vector>
#include <cstddef>
#include <algorithm>
#include <utility>
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/shared_array.hpp>
#include <boost/property_map/property_map.hpp>
namespace boost {
// Swap two elements in a property map without assuming they model
// LvaluePropertyMap -- currently not used
template <typename PropMap>
inline void property_map_swap(
PropMap prop_map,
const typename boost::property_traits<PropMap>::key_type& ka,
const typename boost::property_traits<PropMap>::key_type& kb) {
typename boost::property_traits<PropMap>::value_type va = get(prop_map, ka);
put(prop_map, ka, get(prop_map, kb));
put(prop_map, kb, va);
}
namespace detail {
template <typename Value>
class fixed_max_size_vector {
boost::shared_array<Value> m_data;
std::size_t m_size;
public:
typedef std::size_t size_type;
fixed_max_size_vector(std::size_t max_size)
: m_data(new Value[max_size]), m_size(0) {}
std::size_t size() const {return m_size;}
bool empty() const {return m_size == 0;}
Value& operator[](std::size_t i) {return m_data[i];}
const Value& operator[](std::size_t i) const {return m_data[i];}
void push_back(Value v) {m_data[m_size++] = v;}
void pop_back() {--m_size;}
Value& back() {return m_data[m_size - 1];}
const Value& back() const {return m_data[m_size - 1];}
};
}
// D-ary heap using an indirect compare operator (use identity_property_map
// as DistanceMap to get a direct compare operator). This heap appears to be
// commonly used for Dijkstra's algorithm for its good practical performance
// on some platforms; asymptotically, it has an O(lg N) decrease-key
// operation while that can be done in constant time on a relaxed heap. The
// implementation is mostly based on the binary heap page on Wikipedia and
// online sources that state that the operations are the same for d-ary
// heaps. This code is not based on the old Boost d-ary heap code.
//
// - d_ary_heap_indirect is a model of UpdatableQueue as is needed for
// dijkstra_shortest_paths.
//
// - Value must model Assignable.
// - Arity must be at least 2 (optimal value appears to be 4, both in my and
// third-party experiments).
// - IndexInHeapMap must be a ReadWritePropertyMap from Value to
// Container::size_type (to store the index of each stored value within the
// heap for decrease-key aka update).
// - DistanceMap must be a ReadablePropertyMap from Value to something
// (typedef'ed as distance_type).
// - Compare must be a BinaryPredicate used as a less-than operator on
// distance_type.
// - Container must be a random-access, contiguous container (in practice,
// the operations used probably require that it is std::vector<Value>).
//
template <typename Value,
std::size_t Arity,
typename IndexInHeapPropertyMap,
typename DistanceMap,
typename Compare = std::less<Value>,
typename Container = std::vector<Value> >
class d_ary_heap_indirect {
BOOST_STATIC_ASSERT (Arity >= 2);
public:
typedef typename Container::size_type size_type;
typedef Value value_type;
typedef typename boost::property_traits<DistanceMap>::value_type key_type;
typedef DistanceMap key_map;
d_ary_heap_indirect(DistanceMap distance,
IndexInHeapPropertyMap index_in_heap,
const Compare& compare = Compare(),
const Container& data = Container())
: compare(compare), data(data), distance(distance),
index_in_heap(index_in_heap) {}
/* Implicit copy constructor */
/* Implicit assignment operator */
size_type size() const {
return data.size();
}
bool empty() const {
return data.empty();
}
void push(const Value& v) {
size_type index = data.size();
data.push_back(v);
put(index_in_heap, v, index);
preserve_heap_property_up(index);
verify_heap();
}
Value& top() {
return data[0];
}
const Value& top() const {
return data[0];
}
void pop() {
put(index_in_heap, data[0], (size_type)(-1));
if (data.size() != 1) {
data[0] = data.back();
put(index_in_heap, data[0], 0);
data.pop_back();
preserve_heap_property_down();
verify_heap();
} else {
data.pop_back();
}
}
// This function assumes the key has been updated (using an external write
// to the distance map or such)
// See http://coding.derkeiler.com/Archive/General/comp.theory/2007-05/msg00043.html
void update(const Value& v) { /* decrease-key */
size_type index = get(index_in_heap, v);
preserve_heap_property_up(index);
verify_heap();
}
bool contains(const Value& v) const {
size_type index = get(index_in_heap, v);
return (index != (size_type)(-1));
}
void push_or_update(const Value& v) { /* insert if not present, else update */
size_type index = get(index_in_heap, v);
if (index == (size_type)(-1)) {
index = data.size();
data.push_back(v);
put(index_in_heap, v, index);
}
preserve_heap_property_up(index);
verify_heap();
}
DistanceMap keys() const {
return distance;
}
private:
Compare compare;
Container data;
DistanceMap distance;
IndexInHeapPropertyMap index_in_heap;
// The distances being compared using compare and that are stored in the
// distance map
typedef typename boost::property_traits<DistanceMap>::value_type distance_type;
// Get the parent of a given node in the heap
static size_type parent(size_type index) {
return (index - 1) / Arity;
}
// Get the child_idx'th child of a given node; 0 <= child_idx < Arity
static size_type child(size_type index, std::size_t child_idx) {
return index * Arity + child_idx + 1;
}
// Swap two elements in the heap by index, updating index_in_heap
void swap_heap_elements(size_type index_a, size_type index_b) {
using std::swap;
Value value_a = data[index_a];
Value value_b = data[index_b];
data[index_a] = value_b;
data[index_b] = value_a;
put(index_in_heap, value_a, index_b);
put(index_in_heap, value_b, index_a);
}
// Emulate the indirect_cmp that is now folded into this heap class
bool compare_indirect(const Value& a, const Value& b) const {
return compare(get(distance, a), get(distance, b));
}
// Verify that the array forms a heap; commented out by default
void verify_heap() const {
// This is a very expensive test so it should be disabled even when
// NDEBUG is not defined
#if 0
for (size_t i = 1; i < data.size(); ++i) {
if (compare_indirect(data[i], data[parent(i)])) {
BOOST_ASSERT (!"Element is smaller than its parent");
}
}
#endif
}
// Starting at a node, move up the tree swapping elements to preserve the
// heap property
void preserve_heap_property_up(size_type index) {
size_type orig_index = index;
size_type num_levels_moved = 0;
// The first loop just saves swaps that need to be done in order to avoid
// aliasing issues in its search; there is a second loop that does the
// necessary swap operations
if (index == 0) return; // Do nothing on root
Value currently_being_moved = data[index];
distance_type currently_being_moved_dist =
get(distance, currently_being_moved);
for (;;) {
if (index == 0) break; // Stop at root
size_type parent_index = parent(index);
Value parent_value = data[parent_index];
if (compare(currently_being_moved_dist, get(distance, parent_value))) {
++num_levels_moved;
index = parent_index;
continue;
} else {
break; // Heap property satisfied
}
}
// Actually do the moves -- move num_levels_moved elements down in the
// tree, then put currently_being_moved at the top
index = orig_index;
for (size_type i = 0; i < num_levels_moved; ++i) {
size_type parent_index = parent(index);
Value parent_value = data[parent_index];
put(index_in_heap, parent_value, index);
data[index] = parent_value;
index = parent_index;
}
data[index] = currently_being_moved;
put(index_in_heap, currently_being_moved, index);
verify_heap();
}
// From the root, swap elements (each one with its smallest child) if there
// are any parent-child pairs that violate the heap property
void preserve_heap_property_down() {
if (data.empty()) return;
size_type index = 0;
Value currently_being_moved = data[0];
distance_type currently_being_moved_dist =
get(distance, currently_being_moved);
size_type heap_size = data.size();
Value* data_ptr = &data[0];
for (;;) {
size_type first_child_index = child(index, 0);
if (first_child_index >= heap_size) break; /* No children */
Value* child_base_ptr = data_ptr + first_child_index;
size_type smallest_child_index = 0;
distance_type smallest_child_dist = get(distance, child_base_ptr[smallest_child_index]);
if (first_child_index + Arity <= heap_size) {
// Special case for a statically known loop count (common case)
for (size_t i = 1; i < Arity; ++i) {
Value i_value = child_base_ptr[i];
distance_type i_dist = get(distance, i_value);
if (compare(i_dist, smallest_child_dist)) {
smallest_child_index = i;
smallest_child_dist = i_dist;
}
}
} else {
for (size_t i = 1; i < heap_size - first_child_index; ++i) {
distance_type i_dist = get(distance, child_base_ptr[i]);
if (compare(i_dist, smallest_child_dist)) {
smallest_child_index = i;
smallest_child_dist = i_dist;
}
}
}
if (compare(smallest_child_dist, currently_being_moved_dist)) {
swap_heap_elements(smallest_child_index + first_child_index, index);
index = smallest_child_index + first_child_index;
continue;
} else {
break; // Heap property satisfied
}
}
verify_heap();
}
};
} // namespace boost
#endif // BOOST_D_ARY_HEAP_HPP

View File

@@ -0,0 +1,124 @@
//
//=======================================================================
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
//
// 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_GRAPH_DETAIL_EDGE_HPP
#define BOOST_GRAPH_DETAIL_EDGE_HPP
#if __GNUC__ < 3
#include <iostream>
#else
#include <iosfwd>
#endif
namespace boost {
namespace detail {
template <typename Directed, typename Vertex>
struct edge_base
{
inline edge_base() {}
inline edge_base(Vertex s, Vertex d)
: m_source(s), m_target(d) { }
Vertex m_source;
Vertex m_target;
};
template <typename Directed, typename Vertex>
class edge_desc_impl : public edge_base<Directed,Vertex> {
typedef edge_desc_impl self;
typedef edge_base<Directed,Vertex> Base;
public:
typedef void property_type;
inline edge_desc_impl() : m_eproperty(0) {}
inline edge_desc_impl(Vertex s, Vertex d, const property_type* eplug)
: Base(s,d), m_eproperty(const_cast<property_type*>(eplug)) { }
property_type* get_property() { return m_eproperty; }
const property_type* get_property() const { return m_eproperty; }
// protected:
property_type* m_eproperty;
};
template <class D, class V>
inline bool
operator==(const detail::edge_desc_impl<D,V>& a,
const detail::edge_desc_impl<D,V>& b)
{
return a.get_property() == b.get_property();
}
template <class D, class V>
inline bool
operator!=(const detail::edge_desc_impl<D,V>& a,
const detail::edge_desc_impl<D,V>& b)
{
return ! (a.get_property() == b.get_property());
}
// Order edges according to the address of their property object
template <class D, class V>
inline bool
operator<(const detail::edge_desc_impl<D,V>& a,
const detail::edge_desc_impl<D,V>& b)
{
return a.get_property() < b.get_property();
}
template <class D, class V>
inline bool
operator<=(const detail::edge_desc_impl<D,V>& a,
const detail::edge_desc_impl<D,V>& b)
{
return a.get_property() <= b.get_property();
}
template <class D, class V>
inline bool
operator>(const detail::edge_desc_impl<D,V>& a,
const detail::edge_desc_impl<D,V>& b)
{
return a.get_property() > b.get_property();
}
template <class D, class V>
inline bool
operator>=(const detail::edge_desc_impl<D,V>& a,
const detail::edge_desc_impl<D,V>& b)
{
return a.get_property() >= b.get_property();
}
} //namespace detail
} // namespace boost
namespace std {
#if __GNUC__ < 3
template <class D, class V>
std::ostream&
operator<<(std::ostream& os, const boost::detail::edge_desc_impl<D,V>& e)
{
return os << "(" << e.m_source << "," << e.m_target << ")";
}
#else
template <class Char, class Traits, class D, class V>
std::basic_ostream<Char, Traits>&
operator<<(std::basic_ostream<Char, Traits>& os,
const boost::detail::edge_desc_impl<D,V>& e)
{
return os << "(" << e.m_source << "," << e.m_target << ")";
}
#endif
}
#endif // BOOST_GRAPH_DETAIL_DETAIL_EDGE_HPP

View File

@@ -0,0 +1,130 @@
// (C) Copyright 2007 Andrew Sutton
//
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0 (See accompanying file
// LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GRAPH_DETAIL_GEODESIC_HPP
#define BOOST_GRAPH_DETAIL_GEODESIC_HPP
#include <functional>
#include <boost/config.hpp>
#include <boost/graph/graph_concepts.hpp>
#include <boost/graph/numeric_values.hpp>
// TODO: Should this really be in detail?
namespace boost
{
// This is a very good discussion on centrality measures. While I can't
// say that this has been the motivating factor for the design and
// implementation of ths centrality framework, it does provide a single
// point of reference for defining things like degree and closeness
// centrality. Plus, the bibliography seems fairly complete.
//
// @article{citeulike:1144245,
// author = {Borgatti, Stephen P. and Everett, Martin G.},
// citeulike-article-id = {1144245},
// doi = {10.1016/j.socnet.2005.11.005},
// journal = {Social Networks},
// month = {October},
// number = {4},
// pages = {466--484},
// priority = {0},
// title = {A Graph-theoretic perspective on centrality},
// url = {http://dx.doi.org/10.1016/j.socnet.2005.11.005},
// volume = {28},
// year = {2006}
// }
// }
namespace detail {
// Note that this assumes T == property_traits<DistanceMap>::value_type
// and that the args and return of combine are also T.
template <typename Graph,
typename DistanceMap,
typename Combinator,
typename Distance>
inline Distance
combine_distances(const Graph& g,
DistanceMap dist,
Combinator combine,
Distance init)
{
function_requires< VertexListGraphConcept<Graph> >();
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
typedef typename graph_traits<Graph>::vertex_iterator VertexIterator;
function_requires< ReadablePropertyMapConcept<DistanceMap,Vertex> >();
function_requires< NumericValueConcept<Distance> >();
typedef numeric_values<Distance> DistanceNumbers;
function_requires< AdaptableBinaryFunction<Combinator,Distance,Distance,Distance> >();
// If there's ever an infinite distance, then we simply return
// infinity. Note that this /will/ include the a non-zero
// distance-to-self in the combined values. However, this is usually
// zero, so it shouldn't be too problematic.
Distance ret = init;
VertexIterator i, end;
for(boost::tie(i, end) = vertices(g); i != end; ++i) {
Vertex v = *i;
if(get(dist, v) != DistanceNumbers::infinity()) {
ret = combine(ret, get(dist, v));
}
else {
ret = DistanceNumbers::infinity();
break;
}
}
return ret;
}
// Similar to std::plus<T>, but maximizes parameters
// rather than adding them.
template <typename T>
struct maximize : public std::binary_function<T, T, T>
{
T operator ()(T x, T y) const
{ BOOST_USING_STD_MAX(); return max BOOST_PREVENT_MACRO_SUBSTITUTION (x, y); }
};
// Another helper, like maximize() to help abstract functional
// concepts. This is trivially instantiated for builtin numeric
// types, but should be specialized for those types that have
// discrete notions of reciprocals.
template <typename T>
struct reciprocal : public std::unary_function<T, T>
{
typedef std::unary_function<T, T> function_type;
typedef typename function_type::result_type result_type;
typedef typename function_type::argument_type argument_type;
T operator ()(T t)
{ return T(1) / t; }
};
} /* namespace detail */
// This type defines the basic facilities used for computing values
// based on the geodesic distances between vertices. Examples include
// closeness centrality and mean geodesic distance.
template <typename Graph, typename DistanceType, typename ResultType>
struct geodesic_measure
{
typedef DistanceType distance_type;
typedef ResultType result_type;
typedef typename graph_traits<Graph>::vertices_size_type size_type;
typedef numeric_values<distance_type> distance_values;
typedef numeric_values<result_type> result_values;
static inline distance_type infinite_distance()
{ return distance_values::infinity(); }
static inline result_type infinite_result()
{ return result_values::infinity(); }
static inline result_type zero_result()
{ return result_values::zero(); }
};
} /* namespace boost */
#endif

View File

@@ -0,0 +1,288 @@
// Copyright 2009 The Trustees of Indiana University.
// 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)
// Authors: Jeremiah Willcock
// Andrew Lumsdaine
#ifndef BOOST_GRAPH_DETAIL_HISTOGRAM_SORT_HPP
#define BOOST_GRAPH_DETAIL_HISTOGRAM_SORT_HPP
#include <boost/assert.hpp>
namespace boost {
namespace graph {
namespace detail {
template<typename InputIterator>
size_t
reserve_count_for_single_pass_helper(InputIterator, InputIterator,
std::input_iterator_tag)
{
// Do nothing: we have no idea how much storage to reserve.
return 0;
}
template<typename InputIterator>
size_t
reserve_count_for_single_pass_helper(InputIterator first, InputIterator last,
std::random_access_iterator_tag)
{
using std::distance;
typename std::iterator_traits<InputIterator>::difference_type n =
distance(first, last);
return (size_t)n;
}
template<typename InputIterator>
size_t
reserve_count_for_single_pass(InputIterator first, InputIterator last) {
typedef typename std::iterator_traits<InputIterator>::iterator_category
category;
return reserve_count_for_single_pass_helper(first, last, category());
}
template <typename KeyIterator, typename RowstartIterator,
typename VerticesSize, typename KeyFilter, typename KeyTransform>
void
count_starts
(KeyIterator begin, KeyIterator end,
RowstartIterator starts, // Must support numverts + 1 elements
VerticesSize numkeys,
KeyFilter key_filter,
KeyTransform key_transform) {
typedef VerticesSize vertices_size_type;
typedef typename std::iterator_traits<RowstartIterator>::value_type EdgeIndex;
// Put the degree of each vertex v into m_rowstart[v + 1]
for (KeyIterator i = begin; i != end; ++i) {
if (key_filter(*i)) {
++starts[key_transform(*i) + 1];
}
}
// Compute the partial sum of the degrees to get the actual values of
// m_rowstart
EdgeIndex start_of_this_row = 0;
starts[0] = start_of_this_row;
for (vertices_size_type i = 1; i <= numkeys; ++i) {
start_of_this_row += starts[i];
starts[i] = start_of_this_row;
}
}
template <typename KeyIterator, typename RowstartIterator,
typename NumKeys,
typename Value1InputIter,
typename Value1OutputIter, typename KeyFilter, typename KeyTransform>
void
histogram_sort(KeyIterator key_begin, KeyIterator key_end,
RowstartIterator rowstart, // Must support numkeys + 1 elements and be precomputed
NumKeys numkeys,
Value1InputIter values1_begin,
Value1OutputIter values1_out,
KeyFilter key_filter,
KeyTransform key_transform) {
typedef NumKeys vertices_size_type;
typedef typename std::iterator_traits<RowstartIterator>::value_type EdgeIndex;
// Histogram sort the edges by their source vertices, putting the targets
// into m_column. The index current_insert_positions[v] contains the next
// location to insert out edges for vertex v.
std::vector<EdgeIndex>
current_insert_positions(rowstart, rowstart + numkeys);
Value1InputIter v1i = values1_begin;
for (KeyIterator i = key_begin; i != key_end; ++i, ++v1i) {
if (key_filter(*i)) {
vertices_size_type source = key_transform(*i);
EdgeIndex insert_pos = current_insert_positions[source];
++current_insert_positions[source];
values1_out[insert_pos] = *v1i;
}
}
}
template <typename KeyIterator, typename RowstartIterator,
typename NumKeys,
typename Value1InputIter,
typename Value1OutputIter,
typename Value2InputIter,
typename Value2OutputIter,
typename KeyFilter, typename KeyTransform>
void
histogram_sort(KeyIterator key_begin, KeyIterator key_end,
RowstartIterator rowstart, // Must support numkeys + 1 elements and be precomputed
NumKeys numkeys,
Value1InputIter values1_begin,
Value1OutputIter values1_out,
Value2InputIter values2_begin,
Value2OutputIter values2_out,
KeyFilter key_filter,
KeyTransform key_transform) {
typedef NumKeys vertices_size_type;
typedef typename std::iterator_traits<RowstartIterator>::value_type EdgeIndex;
// Histogram sort the edges by their source vertices, putting the targets
// into m_column. The index current_insert_positions[v] contains the next
// location to insert out edges for vertex v.
std::vector<EdgeIndex>
current_insert_positions(rowstart, rowstart + numkeys);
Value1InputIter v1i = values1_begin;
Value2InputIter v2i = values2_begin;
for (KeyIterator i = key_begin; i != key_end; ++i, ++v1i, ++v2i) {
if (key_filter(*i)) {
vertices_size_type source = key_transform(*i);
EdgeIndex insert_pos = current_insert_positions[source];
++current_insert_positions[source];
values1_out[insert_pos] = *v1i;
values2_out[insert_pos] = *v2i;
}
}
}
template <typename KeyIterator, typename RowstartIterator,
typename NumKeys,
typename Value1Iter,
typename KeyTransform>
void
histogram_sort_inplace(KeyIterator key_begin,
RowstartIterator rowstart, // Must support numkeys + 1 elements and be precomputed
NumKeys numkeys,
Value1Iter values1,
KeyTransform key_transform) {
typedef NumKeys vertices_size_type;
typedef typename std::iterator_traits<RowstartIterator>::value_type EdgeIndex;
// 1. Copy m_rowstart (except last element) to get insert positions
std::vector<EdgeIndex> insert_positions(rowstart, rowstart + numkeys);
// 2. Swap the sources and targets into place
for (size_t i = 0; i < rowstart[numkeys]; ++i) {
// While edge i is not in the right bucket:
while (!(i >= rowstart[key_transform(key_begin[i])] && i < insert_positions[key_transform(key_begin[i])])) {
// Add a slot in the right bucket
size_t target_pos = insert_positions[key_transform(key_begin[i])]++;
BOOST_ASSERT (target_pos < rowstart[key_transform(key_begin[i]) + 1]);
if (target_pos == i) continue;
// Swap this edge into place
using std::swap;
swap(key_begin[i], key_begin[target_pos]);
swap(values1[i], values1[target_pos]);
}
}
}
template <typename KeyIterator, typename RowstartIterator,
typename NumKeys,
typename Value1Iter,
typename Value2Iter,
typename KeyTransform>
void
histogram_sort_inplace(KeyIterator key_begin,
RowstartIterator rowstart, // Must support numkeys + 1 elements and be precomputed
NumKeys numkeys,
Value1Iter values1,
Value2Iter values2,
KeyTransform key_transform) {
typedef NumKeys vertices_size_type;
typedef typename std::iterator_traits<RowstartIterator>::value_type EdgeIndex;
// 1. Copy m_rowstart (except last element) to get insert positions
std::vector<EdgeIndex> insert_positions(rowstart, rowstart + numkeys);
// 2. Swap the sources and targets into place
for (size_t i = 0; i < rowstart[numkeys]; ++i) {
// While edge i is not in the right bucket:
while (!(i >= rowstart[key_transform(key_begin[i])] && i < insert_positions[key_transform(key_begin[i])])) {
// Add a slot in the right bucket
size_t target_pos = insert_positions[key_transform(key_begin[i])]++;
BOOST_ASSERT (target_pos < rowstart[key_transform(key_begin[i]) + 1]);
if (target_pos == i) continue;
// Swap this edge into place
using std::swap;
swap(key_begin[i], key_begin[target_pos]);
swap(values1[i], values1[target_pos]);
swap(values2[i], values2[target_pos]);
}
}
}
template <typename InputIterator, typename VerticesSize>
void split_into_separate_coords(InputIterator begin, InputIterator end,
std::vector<VerticesSize>& firsts,
std::vector<VerticesSize>& seconds) {
firsts.clear();
seconds.clear();
size_t reserve_size
= detail::reserve_count_for_single_pass(begin, end);
firsts.reserve(reserve_size);
seconds.reserve(reserve_size);
for (; begin != end; ++begin) {
std::pair<VerticesSize, VerticesSize> edge = *begin;
firsts.push_back(edge.first);
seconds.push_back(edge.second);
}
}
template <typename InputIterator, typename VerticesSize, typename SourceFilter>
void split_into_separate_coords_filtered
(InputIterator begin, InputIterator end,
std::vector<VerticesSize>& firsts,
std::vector<VerticesSize>& seconds,
const SourceFilter& filter) {
firsts.clear();
seconds.clear();
for (; begin != end; ++begin) {
std::pair<VerticesSize, VerticesSize> edge = *begin;
if (filter(edge.first)) {
firsts.push_back(edge.first);
seconds.push_back(edge.second);
}
}
}
template <typename InputIterator, typename PropInputIterator,
typename VerticesSize, typename PropType, typename SourceFilter>
void split_into_separate_coords_filtered
(InputIterator begin, InputIterator end,
PropInputIterator props,
std::vector<VerticesSize>& firsts,
std::vector<VerticesSize>& seconds,
std::vector<PropType>& props_out,
const SourceFilter& filter) {
firsts.clear();
seconds.clear();
props_out.clear();
for (; begin != end; ++begin) {
std::pair<VerticesSize, VerticesSize> edge = *begin;
if (filter(edge.first)) {
firsts.push_back(edge.first);
seconds.push_back(edge.second);
props_out.push_back(*props);
}
++props;
}
}
template <typename Pair>
struct project1st {
typedef typename Pair::first_type result_type;
const result_type& operator()(const Pair& p) const {return p.first;}
};
template <typename Pair>
struct project2nd {
typedef typename Pair::second_type result_type;
const result_type& operator()(const Pair& p) const {return p.second;}
};
}
}
}
#endif // BOOST_GRAPH_DETAIL_HISTOGRAM_SORT_HPP

View File

@@ -0,0 +1,79 @@
//
//=======================================================================
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
//
// 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_GRAPH_DETAIL_INCIDENCE_ITERATOR_HPP
#define BOOST_GRAPH_DETAIL_INCIDENCE_ITERATOR_HPP
#include <utility>
#include <iterator>
// OBSOLETE
namespace boost {
namespace detail {
// EdgeDir tags
struct in_edge_tag { };
struct out_edge_tag { };
template <class Vertex, class Edge, class Iterator1D, class EdgeDir>
struct bidir_incidence_iterator {
typedef bidir_incidence_iterator self;
typedef Edge edge_type;
typedef typename Edge::property_type EdgeProperty;
public:
typedef int difference_type;
typedef std::forward_iterator_tag iterator_category;
typedef edge_type reference;
typedef edge_type value_type;
typedef value_type* pointer;
inline bidir_incidence_iterator() {}
inline bidir_incidence_iterator(Iterator1D ii, Vertex src)
: i(ii), _src(src) { }
inline self& operator++() { ++i; return *this; }
inline self operator++(int) { self tmp = *this; ++(*this); return tmp; }
inline reference operator*() const {
return deref_helper(EdgeDir());
}
inline self* operator->() { return this; }
Iterator1D& iter() { return i; }
const Iterator1D& iter() const { return i; }
Iterator1D i;
Vertex _src;
protected:
inline reference deref_helper(out_edge_tag) const {
return edge_type( _src, (*i).get_target(), &(*i).get_property() );
}
inline reference deref_helper(in_edge_tag) const {
return edge_type((*i).get_target(), _src, &(*i).get_property() );
}
};
template <class V, class E, class Iter, class Dir>
inline bool operator==(const bidir_incidence_iterator<V,E,Iter,Dir>& x,
const bidir_incidence_iterator<V,E,Iter,Dir>& y)
{
return x.i == y.i;
}
template <class V, class E, class Iter, class Dir>
inline bool operator!=(const bidir_incidence_iterator<V,E,Iter,Dir>& x,
const bidir_incidence_iterator<V,E,Iter,Dir>& y)
{
return x.i != y.i;
}
}
}
#endif

View File

@@ -0,0 +1,77 @@
//=======================================================================
// Copyright 2002 Indiana University.
// 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_GRAPH_DETAIL_INCREMENTAL_COMPONENTS_HPP
#define BOOST_GRAPH_DETAIL_INCREMENTAL_COMPONENTS_HPP
#include <boost/operators.hpp>
namespace boost {
namespace detail {
// Iterator for a component index linked list. The contents of
// each array element represent the next index in the list. A
// special value (the maximum index + 1) is used to terminate a
// list.
template <typename IndexRandomAccessIterator>
class component_index_iterator :
boost::forward_iterator_helper<component_index_iterator<IndexRandomAccessIterator>,
typename std::iterator_traits<IndexRandomAccessIterator>::value_type,
typename std::iterator_traits<IndexRandomAccessIterator>::difference_type,
typename std::iterator_traits<IndexRandomAccessIterator>::pointer,
typename std::iterator_traits<IndexRandomAccessIterator>::reference> {
private:
typedef component_index_iterator<IndexRandomAccessIterator> self;
public:
typedef std::forward_iterator_tag iterator_category;
typedef typename std::iterator_traits<IndexRandomAccessIterator>::value_type value_type;
typedef typename std::iterator_traits<IndexRandomAccessIterator>::difference_type reference;
typedef typename std::iterator_traits<IndexRandomAccessIterator>::pointer pointer;
typedef typename std::iterator_traits<IndexRandomAccessIterator>::reference difference_type;
// Constructor for "begin" iterator
component_index_iterator(IndexRandomAccessIterator index_iterator,
value_type begin_index) :
m_index_iterator(index_iterator),
m_current_index(begin_index) { }
// Constructor for "end" iterator (end_index should be the linked
// list terminator).
component_index_iterator(value_type end_index) :
m_current_index(end_index) { }
inline value_type operator*() const {
return (m_current_index);
}
self& operator++() {
// Move to the next element in the linked list
m_current_index = m_index_iterator[m_current_index];
return (*this);
}
bool operator==(const self& other_iterator) const {
return (m_current_index == *other_iterator);
}
protected:
IndexRandomAccessIterator m_index_iterator;
value_type m_current_index;
}; // class component_index_iterator
} // namespace detail
} // namespace detail
#endif // BOOST_GRAPH_DETAIL_INCREMENTAL_COMPONENTS_HPP

View File

@@ -0,0 +1,74 @@
// (C) Copyright 2007-2009 Andrew Sutton
//
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0 (See accompanying file
// LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GRAPH_DETAIL_INDEX_HPP
#define BOOST_GRAPH_DETAIL_INDEX_HPP
#include <boost/graph/graph_traits.hpp>
// The structures in this module are responsible for selecting and defining
// types for accessing a builting index map. Note that the selection of these
// types requires the Graph parameter to model either VertexIndexGraph or
// EdgeIndexGraph.
namespace boost
{
namespace detail
{
template <typename Graph>
struct vertex_indexer
{
typedef vertex_index_t index_type;
typedef typename property_map<Graph, vertex_index_t>::type map_type;
typedef typename property_map<Graph, vertex_index_t>::const_type const_map_type;
typedef typename property_traits<map_type>::value_type value_type;
typedef typename graph_traits<Graph>::vertex_descriptor key_type;
static const_map_type index_map(const Graph& g)
{ return get(vertex_index, g); }
static map_type index_map(Graph& g)
{ return get(vertex_index, g); }
static value_type index(key_type k, const Graph& g)
{ return get(vertex_index, g, k); }
};
template <typename Graph>
struct edge_indexer
{
typedef edge_index_t index_type;
typedef typename property_map<Graph, edge_index_t>::type map_type;
typedef typename property_map<Graph, edge_index_t>::const_type const_map_type;
typedef typename property_traits<map_type>::value_type value_type;
typedef typename graph_traits<Graph>::edge_descriptor key_type;
static const_map_type index_map(const Graph& g)
{ return get(edge_index, g); }
static map_type index_map(Graph& g)
{ return get(edge_index, g); }
static value_type index(key_type k, const Graph& g)
{ return get(edge_index, g, k); }
};
// NOTE: The Graph parameter MUST be a model of VertexIndexGraph or
// VertexEdgeGraph - whichever type Key is selecting.
template <typename Graph, typename Key>
struct choose_indexer
{
typedef typename mpl::if_<
is_same<Key, typename graph_traits<Graph>::vertex_descriptor>,
vertex_indexer<Graph>,
edge_indexer<Graph>
>::type indexer_type;
typedef typename indexer_type::index_type index_type;
};
}
}
#endif

View File

@@ -0,0 +1,284 @@
// Copyright 2005 The Trustees of Indiana University.
// 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)
// Authors: Jeremiah Willcock
// Douglas Gregor
// Andrew Lumsdaine
// Indexed properties -- used for CSR and CSR-like graphs
#ifndef BOOST_GRAPH_INDEXED_PROPERTIES_HPP
#define BOOST_GRAPH_INDEXED_PROPERTIES_HPP
#include <vector>
#include <utility>
#include <algorithm>
#include <climits>
#include <iterator>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/properties.hpp>
#include <boost/iterator/counting_iterator.hpp>
#include <boost/integer.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/mpl/if.hpp>
namespace boost {
namespace detail {
template<typename Derived, typename Property, typename Descriptor, typename IndexMap>
class indexed_vertex_properties
{
public:
typedef no_property vertex_property_type;
typedef Property vertex_bundled;
typedef iterator_property_map<
typename std::vector<Property>::iterator,
IndexMap> vertex_map_type;
typedef iterator_property_map<
typename std::vector<Property>::const_iterator,
IndexMap> const_vertex_map_type;
// Directly access a vertex or edge bundle
Property& operator[](Descriptor v)
{ return m_vertex_properties[get(vertex_index, derived(), v)]; }
const Property& operator[](Descriptor v) const
{ return m_vertex_properties[get(vertex_index, derived(), v)]; }
vertex_map_type get_vertex_bundle(const IndexMap& index_map = IndexMap()) {
return vertex_map_type(m_vertex_properties.begin(), index_map);
}
const_vertex_map_type get_vertex_bundle(const IndexMap& index_map = IndexMap()) const {
return const_vertex_map_type(m_vertex_properties.begin(), index_map);
}
protected:
// Default-construct with no property values
indexed_vertex_properties() {}
// Initialize with n default-constructed property values
indexed_vertex_properties(std::size_t n) : m_vertex_properties(n) { }
public:
// Clear the properties vector
void clear()
{
m_vertex_properties.clear();
}
// Resize the properties vector
void resize(std::size_t n)
{
m_vertex_properties.resize(n);
}
// Reserve space in the vector of properties
void reserve(std::size_t n)
{
m_vertex_properties.reserve(n);
}
// Add a new property value to the back
void push_back(const Property& prop)
{
m_vertex_properties.push_back(prop);
}
// Write an element by raw index
void write_by_index(std::size_t idx, const Property& prop)
{
m_vertex_properties[idx] = prop;
}
// Access to the derived object
Derived& derived() { return *static_cast<Derived*>(this); }
const Derived& derived() const
{ return *static_cast<const Derived*>(this); }
public: // should be private, but friend templates not portable
std::vector<Property> m_vertex_properties;
};
template<typename Derived, typename Descriptor, typename IndexMap>
class indexed_vertex_properties<Derived, void, Descriptor, IndexMap>
{
struct secret {};
public:
typedef no_property vertex_property_type;
typedef void vertex_bundled;
typedef secret vertex_map_type;
typedef secret const_vertex_map_type;
secret operator[](secret) { return secret(); }
vertex_map_type get_vertex_bundle() const {
return vertex_map_type();
}
protected:
// All operations do nothing.
indexed_vertex_properties() { }
indexed_vertex_properties(std::size_t) { }
public:
void clear() { }
void resize(std::size_t) { }
void reserve(std::size_t) { }
};
template<typename Derived, typename Property, typename Descriptor, typename IndexMap>
class indexed_edge_properties
{
public:
typedef no_property edge_property_type;
typedef Property edge_bundled;
typedef Property edge_push_back_type;
typedef iterator_property_map<
typename std::vector<Property>::iterator,
IndexMap> edge_map_type;
typedef iterator_property_map<
typename std::vector<Property>::const_iterator,
IndexMap> const_edge_map_type;
// Directly access a edge or edge bundle
Property& operator[](Descriptor v)
{ return m_edge_properties[get(edge_index, derived(), v)]; }
const Property& operator[](Descriptor v) const
{ return m_edge_properties[get(edge_index, derived(), v)]; }
edge_map_type get_edge_bundle(const IndexMap& index_map = IndexMap()) {
return edge_map_type(m_edge_properties.begin(), index_map);
}
const_edge_map_type get_edge_bundle(const IndexMap& index_map = IndexMap()) const {
return const_edge_map_type(m_edge_properties.begin(), index_map);
}
protected:
// Default-construct with no property values
indexed_edge_properties() {}
// Initialize with n default-constructed property values
indexed_edge_properties(std::size_t n) : m_edge_properties(n) { }
// Get the size of the properties vector
std::size_t size() const
{
return m_edge_properties.size();
}
// Clear the properties vector
void clear()
{
m_edge_properties.clear();
}
// Resize the properties vector
void resize(std::size_t n)
{
m_edge_properties.resize(n);
}
// Reserve space in the vector of properties
void reserve(std::size_t n)
{
m_edge_properties.reserve(n);
}
// Write an element by raw index
void write_by_index(std::size_t idx, const Property& prop)
{
m_edge_properties[idx] = prop;
}
public:
// Add a new property value to the back
void push_back(const Property& prop)
{
m_edge_properties.push_back(prop);
}
// Move range of properties backwards
void move_range(std::size_t src_begin, std::size_t src_end, std::size_t dest_begin) {
std::copy_backward(
m_edge_properties.begin() + src_begin,
m_edge_properties.begin() + src_end,
m_edge_properties.begin() + dest_begin + (src_end - src_begin));
}
typedef typename std::vector<Property>::iterator iterator;
iterator begin() {return m_edge_properties.begin();}
iterator end() {return m_edge_properties.end();}
private:
// Access to the derived object
Derived& derived() { return *static_cast<Derived*>(this); }
const Derived& derived() const
{ return *static_cast<const Derived*>(this); }
public: // should be private, but friend templates not portable
std::vector<Property> m_edge_properties;
};
struct dummy_no_property_iterator
: public boost::iterator_facade<dummy_no_property_iterator, no_property, std::random_access_iterator_tag> {
mutable no_property prop;
no_property& dereference() const {return prop;}
bool equal(const dummy_no_property_iterator&) const {return true;}
void increment() {}
void decrement() {}
void advance(std::ptrdiff_t) {}
std::ptrdiff_t distance_to(const dummy_no_property_iterator) const {return 0;}
};
template<typename Derived, typename Descriptor, typename IndexMap>
class indexed_edge_properties<Derived, void, Descriptor, IndexMap>
{
struct secret {};
public:
typedef no_property edge_property_type;
typedef void edge_bundled;
typedef void* edge_push_back_type;
typedef secret edge_map_type;
typedef secret const_edge_map_type;
secret operator[](secret) { return secret(); }
void write_by_index(std::size_t idx, const no_property& prop) {}
edge_map_type get_edge_bundle(const IndexMap& = IndexMap()) const {
return edge_map_type();
}
protected:
// All operations do nothing.
indexed_edge_properties() { }
indexed_edge_properties(std::size_t) { }
std::size_t size() const {return 0;}
void clear() { }
void resize(std::size_t) { }
void reserve(std::size_t) { }
public:
void push_back(const edge_push_back_type&) { }
void move_range(std::size_t src_begin, std::size_t src_end, std::size_t dest_begin) {}
typedef dummy_no_property_iterator iterator;
iterator begin() {return dummy_no_property_iterator();}
iterator end() {return dummy_no_property_iterator();}
};
}
}
#endif // BOOST_GRAPH_INDEXED_PROPERTIES_HPP

View File

@@ -0,0 +1,237 @@
// Copyright (C) 2009 Andrew Sutton
// Use, modification and distribution is subject to 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_GRAPH_LABELED_GRAPH_TRAITS_HPP
#define BOOST_GRAPH_LABELED_GRAPH_TRAITS_HPP
#include <boost/graph/graph_mutability_traits.hpp>
namespace boost {
// Extend the graph mutability traits (and metafunctions) to include options
// for labeled graphs.
// NOTE: the label_vertex tag denotes the fact that you can basically assign
// arbitrary labels to vertices without modifying the actual graph.
// TODO: We might also overlay the uniqueness/multiplicity of labels in this
// hierarchy also. For now, we just assumed that labels are unique.
struct label_vertex_tag { };
struct labeled_add_vertex_tag : virtual label_vertex_tag { };
struct labeled_add_vertex_property_tag : virtual labeled_add_vertex_tag { };
struct labeled_remove_vertex_tag { };
struct labeled_add_edge_tag : virtual label_vertex_tag { };
struct labeled_add_edge_property_tag : virtual labeled_add_edge_tag{ };
struct labeled_remove_edge_tag { };
struct labeled_mutable_vertex_graph_tag
: virtual labeled_add_vertex_tag, virtual labeled_remove_vertex_tag
{ };
struct labeled_mutable_vertex_property_graph_tag
: virtual labeled_add_vertex_property_tag, virtual labeled_remove_vertex_tag
{ };
struct labeled_mutable_edge_graph_tag
: virtual labeled_add_edge_tag, virtual labeled_remove_edge_tag
{ };
struct labeled_mutable_edge_property_graph_tag
: virtual labeled_add_edge_property_tag, virtual labeled_remove_edge_tag
{ };
struct labeled_graph_tag
: virtual label_vertex_tag
{ };
struct labeled_mutable_graph_tag
: virtual labeled_mutable_vertex_graph_tag
, virtual labeled_mutable_edge_graph_tag
{ };
struct labeled_mutable_property_graph_tag
: virtual labeled_mutable_vertex_property_graph_tag
, virtual labeled_mutable_edge_property_graph_tag
{ };
struct labeled_add_only_property_graph_tag
: virtual labeled_add_vertex_property_tag
, virtual labeled_mutable_edge_property_graph_tag
{ };
// Metafunctions
template <typename Graph>
struct graph_has_add_vertex_by_label
: mpl::bool_<
is_convertible<
typename graph_mutability_traits<Graph>::category,
labeled_add_vertex_tag
>::value
>
{ };
template <typename Graph>
struct graph_has_add_vertex_by_label_with_property
: mpl::bool_<
is_convertible<
typename graph_mutability_traits<Graph>::category,
labeled_add_vertex_property_tag
>::value
>
{ };
template <typename Graph>
struct graph_has_remove_vertex_by_label
: mpl::bool_<
is_convertible<
typename graph_mutability_traits<Graph>::category,
labeled_remove_vertex_tag
>::value
>
{ };
template <typename Graph>
struct graph_has_add_edge_by_label
: mpl::bool_<
is_convertible<
typename graph_mutability_traits<Graph>::category,
labeled_add_edge_tag
>::value
>
{ };
template <typename Graph>
struct graph_has_add_edge_by_label_with_property
: mpl::bool_<
is_convertible<
typename graph_mutability_traits<Graph>::category,
labeled_add_edge_property_tag
>::value
>
{ };
template <typename Graph>
struct graph_has_remove_edge_by_label
: mpl::bool_<
is_convertible<
typename graph_mutability_traits<Graph>::category,
labeled_remove_edge_tag
>::value
>
{ };
template <typename Graph>
struct is_labeled_mutable_vertex_graph
: mpl::and_<
graph_has_add_vertex_by_label<Graph>,
graph_has_remove_vertex_by_label<Graph>
>
{ };
template <typename Graph>
struct is_labeled_mutable_vertex_property_graph
: mpl::and_<
graph_has_add_vertex_by_label<Graph>,
graph_has_remove_vertex_by_label<Graph>
>
{ };
template <typename Graph>
struct is_labeled_mutable_edge_graph
: mpl::and_<
graph_has_add_edge_by_label<Graph>,
graph_has_remove_edge_by_label<Graph>
>
{ };
template <typename Graph>
struct is_labeled_mutable_edge_property_graph
: mpl::and_<
graph_has_add_edge_by_label<Graph>,
graph_has_remove_edge_by_label<Graph>
>
{ };
template <typename Graph>
struct is_labeled_mutable_graph
: mpl::and_<
is_labeled_mutable_vertex_graph<Graph>,
is_labeled_mutable_edge_graph<Graph>
>
{ };
template <typename Graph>
struct is_labeled_mutable_property_graph
: mpl::and_<
is_labeled_mutable_vertex_property_graph<Graph>,
is_labeled_mutable_edge_property_graph<Graph>
>
{ };
template <typename Graph>
struct is_labeled_add_only_property_graph
: mpl::bool_<
is_convertible<
typename graph_mutability_traits<Graph>::category,
labeled_add_only_property_graph_tag
>::value
>
{ };
template <typename Graph>
struct is_labeled_graph
: mpl::bool_<
is_convertible<
typename graph_mutability_traits<Graph>::category,
label_vertex_tag
>::value
>
{ };
template <typename> struct graph_mutability_traits;
namespace graph_detail {
// The determine mutability metafunction computes a labeled mutability tag
// based on the mutability of the given graph type. This is used by the
// graph_mutability_traits specialization below.
template <typename Graph>
struct determine_mutability {
typedef typename mpl::if_<
is_add_only_property_graph<Graph>,
labeled_add_only_property_graph_tag,
typename mpl::if_<
is_mutable_property_graph<Graph>,
labeled_mutable_property_graph_tag,
typename mpl::if_<
is_mutable_graph<Graph>,
labeled_mutable_graph_tag,
typename mpl::if_<
is_mutable_edge_graph<Graph>,
labeled_graph_tag,
typename graph_mutability_traits<Graph>::category
>::type
>::type
>::type
>::type type;
};
} // namespace graph_detail
#define LABELED_GRAPH_PARAMS typename G, typename L, typename S
#define LABELED_GRAPH labeled_graph<G,L,S>
// Specialize mutability traits for for the labeled graph.
// This specialization depends on the mutability of the underlying graph type.
// If the underlying graph is fully mutable, this this is also fully mutable.
// Otherwise, it's different.
template <LABELED_GRAPH_PARAMS>
struct graph_mutability_traits< LABELED_GRAPH > {
typedef typename graph_detail::determine_mutability<
typename LABELED_GRAPH::graph_type
>::type category;
};
#undef LABELED_GRAPH_PARAMS
#undef LABELED_GRAPH
} // namespace boost
#endif

View File

@@ -0,0 +1,220 @@
//=======================================================================
// Copyright 2002 Indiana University.
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
//
// 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_LIST_BASE_HPP
#define BOOST_LIST_BASE_HPP
#include <boost/iterator_adaptors.hpp>
// Perhaps this should go through formal review, and move to <boost/>.
/*
An alternate interface idea:
Extend the std::list functionality by creating remove/insert
functions that do not require the container object!
*/
namespace boost {
namespace detail {
//=========================================================================
// Linked-List Generic Implementation Functions
template <class Node, class Next>
inline Node
slist_insert_after(Node pos, Node x,
Next next)
{
next(x) = next(pos);
next(pos) = x;
return x;
}
// return next(pos) or next(next(pos)) ?
template <class Node, class Next>
inline Node
slist_remove_after(Node pos,
Next next)
{
Node n = next(pos);
next(pos) = next(n);
return n;
}
template <class Node, class Next>
inline Node
slist_remove_range(Node before_first, Node last,
Next next)
{
next(before_first) = last;
return last;
}
template <class Node, class Next>
inline Node
slist_previous(Node head, Node x, Node nil,
Next next)
{
while (head != nil && next(head) != x)
head = next(head);
return head;
}
template<class Node, class Next>
inline void
slist_splice_after(Node pos, Node before_first, Node before_last,
Next next)
{
if (pos != before_first && pos != before_last) {
Node first = next(before_first);
Node after = next(pos);
next(before_first) = next(before_last);
next(pos) = first;
next(before_last) = after;
}
}
template <class Node, class Next>
inline Node
slist_reverse(Node node, Node nil,
Next next)
{
Node result = node;
node = next(node);
next(result) = nil;
while(node) {
Node next = next(node);
next(node) = result;
result = node;
node = next;
}
return result;
}
template <class Node, class Next>
inline std::size_t
slist_size(Node head, Node nil,
Next next)
{
std::size_t s = 0;
for ( ; head != nil; head = next(head))
++s;
return s;
}
template <class Next, class Data>
class slist_iterator_policies
{
public:
explicit slist_iterator_policies(const Next& n, const Data& d)
: m_next(n), m_data(d) { }
template <class Reference, class Node>
Reference dereference(type<Reference>, const Node& x) const
{ return m_data(x); }
template <class Node>
void increment(Node& x) const
{ x = m_next(x); }
template <class Node>
bool equal(Node& x, Node& y) const
{ return x == y; }
protected:
Next m_next;
Data m_data;
};
//===========================================================================
// Doubly-Linked List Generic Implementation Functions
template <class Node, class Next, class Prev>
inline void
dlist_insert_before(Node pos, Node x,
Next next, Prev prev)
{
next(x) = pos;
prev(x) = prev(pos);
next(prev(pos)) = x;
prev(pos) = x;
}
template <class Node, class Next, class Prev>
void
dlist_remove(Node pos,
Next next, Prev prev)
{
Node next_node = next(pos);
Node prev_node = prev(pos);
next(prev_node) = next_node;
prev(next_node) = prev_node;
}
// This deletes every node in the list except the
// sentinel node.
template <class Node, class Delete>
inline void
dlist_clear(Node sentinel, Delete del)
{
Node i, tmp;
i = next(sentinel);
while (i != sentinel) {
tmp = i;
i = next(i);
del(tmp);
}
}
template <class Node>
inline bool
dlist_empty(Node dummy)
{
return next(dummy) == dummy;
}
template <class Node, class Next, class Prev>
void
dlist_transfer(Node pos, Node first, Node last,
Next next, Prev prev)
{
if (pos != last) {
// Remove [first,last) from its old position
next(prev(last)) = pos;
next(prev(first)) = last;
next(prev(pos)) = first;
// Splice [first,last) into its new position
Node tmp = prev(pos);
prev(pos) = prev(last);
prev(last) = prev(first);
prev(first) = tmp;
}
}
template <class Next, class Prev, class Data>
class dlist_iterator_policies
: public slist_iterator_policies<Next, Data>
{
typedef slist_iterator_policies<Next, Data> Base;
public:
template <class Node>
void decrement(Node& x) const
{ x = m_prev(x); }
dlist_iterator_policies(Next n, Prev p, Data d)
: Base(n,d), m_prev(p) { }
protected:
Prev m_prev;
};
} // namespace detail
} // namespace boost
#endif // BOOST_LIST_BASE_HPP

View File

@@ -0,0 +1,205 @@
// (C) Copyright Jeremy Siek 2001.
// 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_PERMUTATION_HPP
#define BOOST_PERMUTATION_HPP
#include <vector>
#include <memory>
#include <functional>
#include <algorithm>
#include <boost/graph/detail/shadow_iterator.hpp>
namespace boost {
template <class Iter1, class Iter2>
void permute_serial(Iter1 permuter, Iter1 last, Iter2 result)
{
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
typedef std::ptrdiff_t D:
#else
typedef typename std::iterator_traits<Iter1>::difference_type D;
#endif
D n = 0;
while (permuter != last) {
std::swap(result[n], result[*permuter]);
++n;
++permuter;
}
}
template <class InIter, class RandIterP, class RandIterR>
void permute_copy(InIter first, InIter last, RandIterP p, RandIterR result)
{
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
typedef std::ptrdiff_t i = 0;
#else
typename std::iterator_traits<RandIterP>::difference_type i = 0;
#endif
for (; first != last; ++first, ++i)
result[p[i]] = *first;
}
namespace detail {
template <class RandIter, class RandIterPerm, class D, class T>
void permute_helper(RandIter first, RandIter last, RandIterPerm p, D, T)
{
D i = 0, pi, n = last - first, cycle_start;
T tmp;
std::vector<int> visited(n, false);
while (i != n) { // continue until all elements have been processed
cycle_start = i;
tmp = first[i];
do { // walk around a cycle
pi = p[i];
visited[pi] = true;
std::swap(tmp, first[pi]);
i = pi;
} while (i != cycle_start);
// find the next cycle
for (i = 0; i < n; ++i)
if (visited[i] == false)
break;
}
}
} // namespace detail
template <class RandIter, class RandIterPerm>
void permute(RandIter first, RandIter last, RandIterPerm p)
{
detail::permute_helper(first, last, p, last - first, *first);
}
// Knuth 1.3.3, Vol. 1 p 176
// modified for zero-based arrays
// time complexity?
//
// WARNING: T must be a signed integer!
template <class PermIter>
void invert_permutation(PermIter X, PermIter Xend)
{
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
typedef std::ptrdiff_t T:
#else
typedef typename std::iterator_traits<PermIter>::value_type T;
#endif
T n = Xend - X;
T m = n;
T j = -1;
while (m > 0) {
T i = X[m-1] + 1;
if (i > 0) {
do {
X[m-1] = j - 1;
j = -m;
m = i;
i = X[m-1] + 1;
} while (i > 0);
i = j;
}
X[m-1] = -i - 1;
--m;
}
}
// Takes a "normal" permutation array (and its inverse), and turns it
// into a BLAS-style permutation array (which can be thought of as a
// serialized permutation).
template <class Iter1, class Iter2, class Iter3>
inline void serialize_permutation(Iter1 q, Iter1 q_end, Iter2 q_inv, Iter3 p)
{
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
typedef std::ptrdiff_t P1;
typedef std::ptrdiff_t P2;
typedef std::ptrdiff_t D;
#else
typedef typename std::iterator_traits<Iter1>::value_type P1;
typedef typename std::iterator_traits<Iter2>::value_type P2;
typedef typename std::iterator_traits<Iter1>::difference_type D;
#endif
D n = q_end - q;
for (D i = 0; i < n; ++i) {
P1 qi = q[i];
P2 qii = q_inv[i];
*p++ = qii;
std::swap(q[i], q[qii]);
std::swap(q_inv[i], q_inv[qi]);
}
}
// Not used anymore, leaving it here for future reference.
template <typename Iter, typename Compare>
void merge_sort(Iter first, Iter last, Compare cmp)
{
if (first + 1 < last) {
Iter mid = first + (last - first)/2;
merge_sort(first, mid, cmp);
merge_sort(mid, last, cmp);
std::inplace_merge(first, mid, last, cmp);
}
}
// time: N log N + 3N + ?
// space: 2N
template <class Iter, class IterP, class Cmp, class Alloc>
inline void sortp(Iter first, Iter last, IterP p, Cmp cmp, Alloc alloc)
{
typedef typename std::iterator_traits<IterP>::value_type P;
typedef typename std::iterator_traits<IterP>::difference_type D;
D n = last - first;
std::vector<P, Alloc> q(n);
for (D i = 0; i < n; ++i)
q[i] = i;
std::sort(make_shadow_iter(first, q.begin()),
make_shadow_iter(last, q.end()),
shadow_cmp<Cmp>(cmp));
invert_permutation(q.begin(), q.end());
std::copy(q.begin(), q.end(), p);
}
template <class Iter, class IterP, class Cmp>
inline void sortp(Iter first, Iter last, IterP p, Cmp cmp)
{
typedef typename std::iterator_traits<IterP>::value_type P;
sortp(first, last, p, cmp, std::allocator<P>());
}
template <class Iter, class IterP>
inline void sortp(Iter first, Iter last, IterP p)
{
typedef typename std::iterator_traits<Iter>::value_type T;
typedef typename std::iterator_traits<IterP>::value_type P;
sortp(first, last, p, std::less<T>(), std::allocator<P>());
}
template <class Iter, class IterP, class Cmp, class Alloc>
inline void sortv(Iter first, Iter last, IterP p, Cmp cmp, Alloc alloc)
{
typedef typename std::iterator_traits<IterP>::value_type P;
typedef typename std::iterator_traits<IterP>::difference_type D;
D n = last - first;
std::vector<P, Alloc> q(n), q_inv(n);
for (D i = 0; i < n; ++i)
q_inv[i] = i;
std::sort(make_shadow_iter(first, q_inv.begin()),
make_shadow_iter(last, q_inv.end()),
shadow_cmp<Cmp>(cmp));
std::copy(q_inv, q_inv.end(), q.begin());
invert_permutation(q.begin(), q.end());
serialize_permutation(q.begin(), q.end(), q_inv.end(), p);
}
} // namespace boost
#endif // BOOST_PERMUTATION_HPP

View File

@@ -0,0 +1,108 @@
// Copyright 2004-9 Trustees of Indiana University
// 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)
//
// read_graphviz_new.hpp -
// Initialize a model of the BGL's MutableGraph concept and an associated
// collection of property maps using a graph expressed in the GraphViz
// DOT Language.
//
// Based on the grammar found at:
// http://www.graphviz.org/cvs/doc/info/lang.html
//
// Jeremiah rewrite used grammar found at:
// http://www.graphviz.org/doc/info/lang.html
// and page 34 or http://www.graphviz.org/pdf/dotguide.pdf
//
// See documentation for this code at:
// http://www.boost.org/libs/graph/doc/read-graphviz.html
//
// Author: Jeremiah Willcock
// Ronald Garcia
//
#ifndef BOOST_READ_GRAPHVIZ_NEW_HPP
#define BOOST_READ_GRAPHVIZ_NEW_HPP
#include <boost/ref.hpp>
#include <boost/property_map/dynamic_property_map.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/detail/workaround.hpp>
#include <algorithm>
#include <string>
#include <vector>
#include <set>
#include <utility>
#include <map>
#include <iostream>
#include <cstdlib>
namespace boost {
namespace read_graphviz_detail {
typedef std::string node_name;
typedef std::string subgraph_name;
typedef std::map<std::string, std::string> properties;
struct node_and_port {
node_name name;
std::string angle; // Or empty if no angle
std::vector<std::string> location; // Up to two identifiers
friend inline bool operator==(const node_and_port& a, const node_and_port& b) {
return a.name == b.name &&
a.angle == b.angle &&
a.location == b.location;
}
friend inline bool operator<(const node_and_port& a, const node_and_port& b) {
if (a.name != b.name) return a.name < b.name;
if (a.angle != b.angle) return a.angle < b.angle;
return a.location < b.location;
}
};
struct edge_info {
node_and_port source;
node_and_port target;
properties props;
};
struct parser_result {
bool graph_is_directed;
bool graph_is_strict;
std::map<node_name, properties> nodes; // Global set
std::vector<edge_info> edges;
std::map<subgraph_name, properties> graph_props; // Root and subgraphs
};
// The actual parser, from libs/graph/src/read_graphviz_new.cpp
void parse_graphviz_from_string(const std::string& str, parser_result& result, bool want_directed);
// Translate from those results to a graph
void translate_results_to_graph(const parser_result& r, ::boost::detail::graph::mutate_graph* mg);
} // namespace read_graphviz_detail
namespace detail {
namespace graph {
BOOST_GRAPH_DECL bool read_graphviz_new(const std::string& str, boost::detail::graph::mutate_graph* mg);
} // end namespace graph
} // end namespace detail
template <typename MutableGraph>
bool read_graphviz_new(const std::string& str,
MutableGraph& graph, boost::dynamic_properties& dp,
std::string const& node_id = "node_id") {
boost::detail::graph::mutate_graph_impl<MutableGraph> mg(graph, dp, node_id);
return detail::graph::read_graphviz_new(str, &mg);
}
} // namespace boost
#endif // BOOST_READ_GRAPHVIZ_NEW_HPP

View File

@@ -0,0 +1,612 @@
// Copyright 2004-9 Trustees of Indiana University
// 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)
//
// read_graphviz_spirit.hpp -
// Initialize a model of the BGL's MutableGraph concept and an associated
// collection of property maps using a graph expressed in the GraphViz
// DOT Language.
//
// Based on the grammar found at:
// http://www.graphviz.org/cvs/doc/info/lang.html
//
// See documentation for this code at:
// http://www.boost.org/libs/graph/doc/read-graphviz.html
//
// Author: Ronald Garcia
//
#ifndef BOOST_READ_GRAPHVIZ_SPIRIT_HPP
#define BOOST_READ_GRAPHVIZ_SPIRIT_HPP
// Phoenix/Spirit set these limits to 3, but I need more.
#define PHOENIX_LIMIT 6
#define BOOST_SPIRIT_CLOSURE_LIMIT 6
#include <boost/spirit/include/classic_multi_pass.hpp>
#include <boost/spirit/include/classic_core.hpp>
#include <boost/spirit/include/classic_confix.hpp>
#include <boost/spirit/include/classic_distinct.hpp>
#include <boost/spirit/include/classic_lists.hpp>
#include <boost/spirit/include/classic_escape_char.hpp>
#include <boost/spirit/include/classic_attribute.hpp>
#include <boost/spirit/include/classic_dynamic.hpp>
#include <boost/spirit/include/classic_actor.hpp>
#include <boost/spirit/include/classic_closure.hpp>
#include <boost/spirit/include/phoenix1.hpp>
#include <boost/spirit/include/phoenix1_binders.hpp>
#include <boost/ref.hpp>
#include <boost/function/function2.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/property_map/dynamic_property_map.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/detail/workaround.hpp>
#include <algorithm>
#include <exception> // for std::exception
#include <string>
#include <vector>
#include <set>
#include <utility>
#include <map>
#include <boost/graph/graphviz.hpp>
#include <boost/throw_exception.hpp>
namespace phoenix {
// Workaround: std::map::operator[] uses a different return type than all
// other standard containers. Phoenix doesn't account for that.
template <typename TK, typename T0, typename T1>
struct binary_operator<index_op, std::map<TK,T0>, T1>
{
typedef typename std::map<TK,T0>::mapped_type& result_type;
static result_type eval(std::map<TK,T0>& container, T1 const& index)
{ return container[index]; }
};
} // namespace phoenix
namespace boost {
namespace detail {
namespace graph {
/////////////////////////////////////////////////////////////////////////////
// Application-specific type definitions
/////////////////////////////////////////////////////////////////////////////
typedef std::set<edge_t> edges_t;
typedef std::set<node_t> nodes_t;
typedef std::set<id_t> ids_t;
typedef std::map<edge_t,ids_t> edge_map_t;
typedef std::map<node_t,ids_t> node_map_t;
typedef std::map<id_t,id_t> props_t;
typedef std::map<id_t,props_t> subgraph_props_t;
typedef boost::function2<void, id_t const&, id_t const&> actor_t;
typedef std::vector<edge_t> edge_stack_t;
typedef std::map<id_t,nodes_t> subgraph_nodes_t;
typedef std::map<id_t,edges_t> subgraph_edges_t;
/////////////////////////////////////////////////////////////////////////////
// Stack frames used by semantic actions
/////////////////////////////////////////////////////////////////////////////
struct id_closure : boost::spirit::classic::closure<id_closure, node_t> {
member1 name;
};
struct node_id_closure : boost::spirit::classic::closure<node_id_closure, node_t> {
member1 name;
};
struct attr_list_closure : boost::spirit::classic::closure<attr_list_closure, actor_t> {
member1 prop_actor;
};
struct property_closure : boost::spirit::classic::closure<property_closure, id_t, id_t> {
member1 key;
member2 value;
};
struct data_stmt_closure : boost::spirit::classic::closure<data_stmt_closure,
nodes_t,nodes_t,edge_stack_t,bool,node_t> {
member1 sources;
member2 dests;
member3 edge_stack;
member4 saw_node;
member5 active_node;
};
struct subgraph_closure : boost::spirit::classic::closure<subgraph_closure,
nodes_t, edges_t, node_t> {
member1 nodes;
member2 edges;
member3 name;
};
/////////////////////////////////////////////////////////////////////////////
// Grammar and Actions for the DOT Language
/////////////////////////////////////////////////////////////////////////////
// Grammar for a dot file.
struct dot_grammar : public boost::spirit::classic::grammar<dot_grammar> {
mutate_graph& graph_;
explicit dot_grammar(mutate_graph& graph) : graph_(graph) { }
template <class ScannerT>
struct definition {
definition(dot_grammar const& self) : self(self), subgraph_depth(0),
keyword_p("0-9a-zA-Z_") {
using namespace boost::spirit::classic;
using namespace phoenix;
// RG - Future Work
// - Handle multi-line strings using \ line continuation
// - Make keywords case insensitive
ID
= ( lexeme_d[((alpha_p | ch_p('_')) >> *(alnum_p | ch_p('_')))]
| real_p
| lexeme_d[confix_p('"', *c_escape_ch_p, '"')]
| comment_nest_p('<', '>')
)[ID.name = construct_<std::string>(arg1,arg2)]
;
a_list
= list_p( ID[(a_list.key = arg1),
(a_list.value = "true")
]
>> !( ch_p('=')
>> ID[a_list.value = arg1])
[phoenix::bind(&definition::call_prop_actor)
(var(*this),a_list.key,a_list.value)],!ch_p(','));
attr_list = +(ch_p('[') >> !a_list >> ch_p(']'));
// RG - disregard port id's for now.
port_location
= (ch_p(':') >> ID)
| (ch_p(':') >> ch_p('(') >> ID >> ch_p(',') >> ID >> ch_p(')'))
;
port_angle = ch_p('@') >> ID;
port
= port_location >> (!port_angle)
| port_angle >> (!port_location);
node_id
= ( ID[node_id.name = arg1] >> (!port) )
[phoenix::bind(&definition::memoize_node)(var(*this))];
graph_stmt
= (ID[graph_stmt.key = arg1] >>
ch_p('=') >>
ID[graph_stmt.value = arg1])
[phoenix::bind(&definition::call_graph_prop)
(var(*this),graph_stmt.key,graph_stmt.value)]
; // Graph property.
attr_stmt
= (as_lower_d[keyword_p("graph")]
>> attr_list(actor_t(phoenix::bind(&definition::default_graph_prop)
(var(*this),arg1,arg2))))
| (as_lower_d[keyword_p("node")]
>> attr_list(actor_t(phoenix::bind(&definition::default_node_prop)
(var(*this),arg1,arg2))))
| (as_lower_d[keyword_p("edge")]
>> attr_list(actor_t(phoenix::bind(&definition::default_edge_prop)
(var(*this),arg1,arg2))))
;
// edge_head is set depending on the graph type (directed/undirected)
edgeop = ch_p('-') >> ch_p(boost::ref(edge_head));
edgeRHS
= +( edgeop[(data_stmt.sources = data_stmt.dests),
(data_stmt.dests = construct_<nodes_t>())]
>> ( subgraph[data_stmt.dests = arg1]
| node_id[phoenix::bind(&definition::insert_node)
(var(*this),data_stmt.dests,arg1)]
)
[phoenix::bind(&definition::activate_edge)
(var(*this),data_stmt.sources,data_stmt.dests,
var(edges), var(default_edge_props))]
);
// To avoid backtracking, edge, node, and subgraph statements are
// processed as one nonterminal.
data_stmt
= ( subgraph[(data_stmt.dests = arg1),// will get moved in rhs
(data_stmt.saw_node = false)]
| node_id[(phoenix::bind(&definition::insert_node)
(var(*this),data_stmt.dests,arg1)),
(data_stmt.saw_node = true),
#ifdef BOOST_GRAPH_DEBUG
(std::cout << val("AcTive Node: ") << arg1 << "\n"),
#endif // BOOST_GRAPH_DEBUG
(data_stmt.active_node = arg1)]
) >> if_p(edgeRHS)[
!attr_list(
actor_t(phoenix::bind(&definition::edge_prop)
(var(*this),arg1,arg2)))
].else_p[
if_p(data_stmt.saw_node)[
!attr_list(
actor_t(phoenix::bind(&definition::node_prop)
(var(*this),arg1,arg2)))
] // otherwise it's a subgraph, nothing more to do.
];
stmt
= graph_stmt
| attr_stmt
| data_stmt
;
stmt_list = *( stmt >> !ch_p(';') );
subgraph
= !( as_lower_d[keyword_p("subgraph")]
>> (!ID[(subgraph.name = arg1),
(subgraph.nodes = (var(subgraph_nodes))[arg1]),
(subgraph.edges = (var(subgraph_edges))[arg1])])
)
>> ch_p('{')[++var(subgraph_depth)]
>> stmt_list
>> ch_p('}')[--var(subgraph_depth)]
[(var(subgraph_nodes))[subgraph.name] = subgraph.nodes]
[(var(subgraph_edges))[subgraph.name] = subgraph.edges]
| as_lower_d[keyword_p("subgraph")]
>> ID[(subgraph.nodes = (var(subgraph_nodes))[arg1]),
(subgraph.edges = (var(subgraph_edges))[arg1])]
;
the_grammar
= (!as_lower_d[keyword_p("strict")])
>> ( as_lower_d[keyword_p("graph")][
(var(edge_head) = '-'),
(phoenix::bind(&definition::check_undirected)(var(*this)))]
| as_lower_d[keyword_p("digraph")][
(var(edge_head) = '>'),
(phoenix::bind(&definition::check_directed)(var(*this)))]
)
>> (!ID) >> ch_p('{') >> stmt_list >> ch_p('}');
} // definition()
typedef boost::spirit::classic::rule<ScannerT> rule_t;
rule_t const& start() const { return the_grammar; }
//
// Semantic actions
//
void check_undirected() {
if(self.graph_.is_directed())
boost::throw_exception(boost::undirected_graph_error());
}
void check_directed() {
if(!self.graph_.is_directed())
boost::throw_exception(boost::directed_graph_error());
}
void memoize_node() {
id_t const& node = node_id.name();
props_t& node_props = default_node_props;
if(nodes.find(node) == nodes.end()) {
nodes.insert(node);
self.graph_.do_add_vertex(node);
node_map.insert(std::make_pair(node,ids_t()));
#ifdef BOOST_GRAPH_DEBUG
std::cout << "Add new node " << node << std::endl;
#endif // BOOST_GRAPH_DEBUG
// Set the default properties for this edge
// RG: Here I would actually set the properties
for(props_t::iterator i = node_props.begin();
i != node_props.end(); ++i) {
set_node_property(node,i->first,i->second);
}
if(subgraph_depth > 0) {
subgraph.nodes().insert(node);
// Set the subgraph's default properties as well
props_t& props = subgraph_node_props[subgraph.name()];
for(props_t::iterator i = props.begin(); i != props.end(); ++i) {
set_node_property(node,i->first,i->second);
}
}
} else {
#ifdef BOOST_GRAPH_DEBUG
std::cout << "See node " << node << std::endl;
#endif // BOOST_GRAPH_DEBUG
}
}
void activate_edge(nodes_t& sources, nodes_t& dests, edges_t& edges,
props_t& edge_props) {
edge_stack_t& edge_stack = data_stmt.edge_stack();
for(nodes_t::iterator i = sources.begin(); i != sources.end(); ++i) {
for(nodes_t::iterator j = dests.begin(); j != dests.end(); ++j) {
// Create the edge and push onto the edge stack.
#ifdef BOOST_GRAPH_DEBUG
std::cout << "Edge " << *i << " to " << *j << std::endl;
#endif // BOOST_GRAPH_DEBUG
edge_t edge = edge_t::new_edge();
edge_stack.push_back(edge);
edges.insert(edge);
edge_map.insert(std::make_pair(edge,ids_t()));
// Add the real edge.
self.graph_.do_add_edge(edge, *i, *j);
// Set the default properties for this edge
for(props_t::iterator k = edge_props.begin();
k != edge_props.end(); ++k) {
set_edge_property(edge,k->first,k->second);
}
if(subgraph_depth > 0) {
subgraph.edges().insert(edge);
// Set the subgraph's default properties as well
props_t& props = subgraph_edge_props[subgraph.name()];
for(props_t::iterator k = props.begin(); k != props.end(); ++k) {
set_edge_property(edge,k->first,k->second);
}
}
}
}
}
// node_prop - Assign the property for the current active node.
void node_prop(id_t const& key, id_t const& value) {
node_t& active_object = data_stmt.active_node();
set_node_property(active_object, key, value);
}
// edge_prop - Assign the property for the current active edges.
void edge_prop(id_t const& key, id_t const& value) {
edge_stack_t const& active_edges_ = data_stmt.edge_stack();
for (edge_stack_t::const_iterator i = active_edges_.begin();
i != active_edges_.end(); ++i) {
set_edge_property(*i,key,value);
}
}
// default_graph_prop - Store as a graph property.
void default_graph_prop(id_t const& key, id_t const& value) {
#ifdef BOOST_GRAPH_DEBUG
std::cout << key << " = " << value << std::endl;
#endif // BOOST_GRAPH_DEBUG
self.graph_.set_graph_property(key, value);
}
// default_node_prop - declare default properties for any future new nodes
void default_node_prop(id_t const& key, id_t const& value) {
nodes_t& nodes_ =
subgraph_depth == 0 ? nodes : subgraph.nodes();
props_t& node_props_ =
subgraph_depth == 0 ?
default_node_props :
subgraph_node_props[subgraph.name()];
// add this to the selected list of default node properties.
node_props_[key] = value;
// for each node, set its property to default-constructed value
// if it hasn't been set already.
// set the dynamic property map value
for(nodes_t::iterator i = nodes_.begin(); i != nodes_.end(); ++i)
if(node_map[*i].find(key) == node_map[*i].end()) {
set_node_property(*i,key,id_t());
}
}
// default_edge_prop - declare default properties for any future new edges
void default_edge_prop(id_t const& key, id_t const& value) {
edges_t& edges_ =
subgraph_depth == 0 ? edges : subgraph.edges();
props_t& edge_props_ =
subgraph_depth == 0 ?
default_edge_props :
subgraph_edge_props[subgraph.name()];
// add this to the list of default edge properties.
edge_props_[key] = value;
// for each edge, set its property to be empty string
// set the dynamic property map value
for(edges_t::iterator i = edges_.begin(); i != edges_.end(); ++i)
if(edge_map[*i].find(key) == edge_map[*i].end())
set_edge_property(*i,key,id_t());
}
// helper function
void insert_node(nodes_t& nodes, id_t const& name) {
nodes.insert(name);
}
void call_prop_actor(std::string const& lhs, std::string const& rhs) {
actor_t& actor = attr_list.prop_actor();
// If first and last characters of the rhs are double-quotes,
// remove them.
if (!rhs.empty() && rhs[0] == '"' && rhs[rhs.size() - 1] == '"')
actor(lhs, rhs.substr(1, rhs.size()-2));
else
actor(lhs,rhs);
}
void call_graph_prop(std::string const& lhs, std::string const& rhs) {
// If first and last characters of the rhs are double-quotes,
// remove them.
if (!rhs.empty() && rhs[0] == '"' && rhs[rhs.size() - 1] == '"')
this->default_graph_prop(lhs, rhs.substr(1, rhs.size()-2));
else
this->default_graph_prop(lhs,rhs);
}
void set_node_property(node_t const& node, id_t const& key,
id_t const& value) {
// Add the property key to the "set" table to avoid default overwrite
node_map[node].insert(key);
// Set the user's property map
self.graph_.set_node_property(key, node, value);
#ifdef BOOST_GRAPH_DEBUG
// Tell the world
std::cout << node << ": " << key << " = " << value << std::endl;
#endif // BOOST_GRAPH_DEBUG
}
void set_edge_property(edge_t const& edge, id_t const& key,
id_t const& value) {
// Add the property key to the "set" table to avoid default overwrite
edge_map[edge].insert(key);
// Set the user's property map
self.graph_.set_edge_property(key, edge, value);
#ifdef BOOST_GRAPH_DEBUG
// Tell the world
#if 0 // RG - edge representation changed,
std::cout << "(" << edge.first << "," << edge.second << "): "
#else
std::cout << "an edge: "
#endif // 0
<< key << " = " << value << std::endl;
#endif // BOOST_GRAPH_DEBUG
}
// Variables explicitly initialized
dot_grammar const& self;
// if subgraph_depth > 0, then we're processing a subgraph.
int subgraph_depth;
// Keywords;
const boost::spirit::classic::distinct_parser<> keyword_p;
//
// rules that make up the grammar
//
boost::spirit::classic::rule<ScannerT,id_closure::context_t> ID;
boost::spirit::classic::rule<ScannerT,property_closure::context_t> a_list;
boost::spirit::classic::rule<ScannerT,attr_list_closure::context_t> attr_list;
rule_t port_location;
rule_t port_angle;
rule_t port;
boost::spirit::classic::rule<ScannerT,node_id_closure::context_t> node_id;
boost::spirit::classic::rule<ScannerT,property_closure::context_t> graph_stmt;
rule_t attr_stmt;
boost::spirit::classic::rule<ScannerT,data_stmt_closure::context_t> data_stmt;
boost::spirit::classic::rule<ScannerT,subgraph_closure::context_t> subgraph;
rule_t edgeop;
rule_t edgeRHS;
rule_t stmt;
rule_t stmt_list;
rule_t the_grammar;
// The grammar uses edge_head to dynamically set the syntax for edges
// directed graphs: edge_head = '>', and so edgeop = "->"
// undirected graphs: edge_head = '-', and so edgeop = "--"
char edge_head;
//
// Support data structures
//
nodes_t nodes; // list of node names seen
edges_t edges; // list of edges seen
node_map_t node_map; // remember the properties set for each node
edge_map_t edge_map; // remember the properties set for each edge
subgraph_nodes_t subgraph_nodes; // per-subgraph lists of nodes
subgraph_edges_t subgraph_edges; // per-subgraph lists of edges
props_t default_node_props; // global default node properties
props_t default_edge_props; // global default edge properties
subgraph_props_t subgraph_node_props; // per-subgraph default node properties
subgraph_props_t subgraph_edge_props; // per-subgraph default edge properties
}; // struct definition
}; // struct dot_grammar
//
// dot_skipper - GraphViz whitespace and comment skipper
//
struct dot_skipper : public boost::spirit::classic::grammar<dot_skipper>
{
dot_skipper() {}
template <typename ScannerT>
struct definition
{
definition(dot_skipper const& /*self*/) {
using namespace boost::spirit::classic;
using namespace phoenix;
// comment forms
skip = eol_p >> comment_p("#")
| space_p
| comment_p("//")
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1400)
| confix_p(str_p("/*") ,*anychar_p, str_p("*/"))
#else
| confix_p("/*" ,*anychar_p, "*/")
#endif
;
#ifdef BOOST_SPIRIT_DEBUG
BOOST_SPIRIT_DEBUG_RULE(skip);
#endif
}
boost::spirit::classic::rule<ScannerT> skip;
boost::spirit::classic::rule<ScannerT> const&
start() const { return skip; }
}; // definition
}; // dot_skipper
} // namespace graph
} // namespace detail
template <typename MultiPassIterator, typename MutableGraph>
bool read_graphviz_spirit(MultiPassIterator begin, MultiPassIterator end,
MutableGraph& graph, dynamic_properties& dp,
std::string const& node_id = "node_id") {
using namespace boost;
using namespace boost::spirit::classic;
typedef MultiPassIterator iterator_t;
typedef skip_parser_iteration_policy< boost::detail::graph::dot_skipper>
iter_policy_t;
typedef scanner_policies<iter_policy_t> scanner_policies_t;
typedef scanner<iterator_t, scanner_policies_t> scanner_t;
::boost::detail::graph::mutate_graph_impl<MutableGraph>
m_graph(graph, dp, node_id);
::boost::detail::graph::dot_grammar p(m_graph);
::boost::detail::graph::dot_skipper skip_p;
iter_policy_t iter_policy(skip_p);
scanner_policies_t policies(iter_policy);
scanner_t scan(begin, end, policies);
return p.parse(scan);
}
} // namespace boost
#endif // BOOST_READ_GRAPHVIZ_SPIRIT_HPP

View File

@@ -0,0 +1,418 @@
//=======================================================================
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
//
// 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_SELF_AVOIDING_WALK_HPP
#define BOOST_SELF_AVOIDING_WALK_HPP
/*
This file defines necessary components for SAW.
mesh language: (defined by myself to clearify what is what)
A triangle in mesh is called an triangle.
An edge in mesh is called an line.
A vertex in mesh is called a point.
A triangular mesh corresponds to a graph in which a vertex is a
triangle and an edge(u, v) stands for triangle u and triangle v
share an line.
After this point, a vertex always refers to vertex in graph,
therefore it is a traingle in mesh.
*/
#include <utility>
#include <boost/config.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/property_map/property_map.hpp>
#define SAW_SENTINAL -1
namespace boost {
template <class T1, class T2, class T3>
struct triple {
T1 first;
T2 second;
T3 third;
triple(const T1& a, const T2& b, const T3& c) : first(a), second(b), third(c) {}
triple() : first(SAW_SENTINAL), second(SAW_SENTINAL), third(SAW_SENTINAL) {}
};
typedef triple<int, int, int> Triple;
/* Define a vertex property which has a triangle inside. Triangle is
represented by a triple. */
struct triangle_tag { enum { num = 100 }; };
typedef property<triangle_tag,Triple> triangle_property;
/* Define an edge property with a line. A line is represented by a
pair. This is not required for SAW though.
*/
struct line_tag { enum { num = 101 }; };
template <class T> struct line_property
: public property<line_tag, std::pair<T,T> > { };
/*Precondition: Points in a Triangle are in order */
template <class Triangle, class Line>
inline void get_sharing(const Triangle& a, const Triangle& b, Line& l)
{
l.first = SAW_SENTINAL;
l.second = SAW_SENTINAL;
if ( a.first == b.first ) {
l.first = a.first;
if ( a.second == b.second || a.second == b.third )
l.second = a.second;
else if ( a.third == b.second || a.third == b.third )
l.second = a.third;
} else if ( a.first == b.second ) {
l.first = a.first;
if ( a.second == b.third )
l.second = a.second;
else if ( a.third == b.third )
l.second = a.third;
} else if ( a.first == b.third ) {
l.first = a.first;
} else if ( a.second == b.first ) {
l.first = a.second;
if ( a.third == b.second || a.third == b.third )
l.second = a.third;
} else if ( a.second == b.second ) {
l.first = a.second;
if ( a.third == b.third )
l.second = a.third;
} else if ( a.second == b.third ) {
l.first = a.second;
} else if ( a.third == b.first
|| a.third == b.second
|| a.third == b.third )
l.first = a.third;
/*Make it in order*/
if ( l.first > l.second ) {
typename Line::first_type i = l.first;
l.first = l.second;
l.second = i;
}
}
template <class TriangleDecorator, class Vertex, class Line>
struct get_vertex_sharing {
typedef std::pair<Vertex, Line> Pair;
get_vertex_sharing(const TriangleDecorator& _td) : td(_td) {}
inline Line operator()(const Vertex& u, const Vertex& v) const {
Line l;
get_sharing(td[u], td[v], l);
return l;
}
inline Line operator()(const Pair& u, const Vertex& v) const {
Line l;
get_sharing(td[u.first], td[v], l);
return l;
}
inline Line operator()(const Pair& u, const Pair& v) const {
Line l;
get_sharing(td[u.first], td[v.first], l);
return l;
}
TriangleDecorator td;
};
/* HList has to be a handle of data holder so that pass-by-value is
* in right logic.
*
* The element of HList is a pair of vertex and line. (remember a
* line is a pair of two ints.). That indicates the walk w from
* current vertex is across line. (If the first of line is -1, it is
* a point though.
*/
template < class TriangleDecorator, class HList, class IteratorD>
class SAW_visitor
: public bfs_visitor<>, public dfs_visitor<>
{
typedef typename boost::property_traits<IteratorD>::value_type iter;
/*use boost shared_ptr*/
typedef typename HList::element_type::value_type::second_type Line;
public:
typedef tree_edge_tag category;
inline SAW_visitor(TriangleDecorator _td, HList _hlist, IteratorD ia)
: td(_td), hlist(_hlist), iter_d(ia) {}
template <class Vertex, class Graph>
inline void start_vertex(Vertex v, Graph&) {
Line l1;
l1.first = SAW_SENTINAL;
l1.second = SAW_SENTINAL;
hlist->push_front(std::make_pair(v, l1));
iter_d[v] = hlist->begin();
}
/*Several symbols:
w(i): i-th triangle in walk w
w(i) |- w(i+1): w enter w(i+1) from w(i) over a line
w(i) ~> w(i+1): w enter w(i+1) from w(i) over a point
w(i) -> w(i+1): w enter w(i+1) from w(i)
w(i) ^ w(i+1): the line or point w go over from w(i) to w(i+1)
*/
template <class Edge, class Graph>
bool tree_edge(Edge e, Graph& G) {
using std::make_pair;
typedef typename boost::graph_traits<Graph>::vertex_descriptor Vertex;
Vertex tau = target(e, G);
Vertex i = source(e, G);
get_vertex_sharing<TriangleDecorator, Vertex, Line> get_sharing_line(td);
Line tau_i = get_sharing_line(tau, i);
iter w_end = hlist->end();
iter w_i = iter_d[i];
iter w_i_m_1 = w_i;
iter w_i_p_1 = w_i;
/*----------------------------------------------------------
* true false
*==========================================================
*a w(i-1) |- w(i) w(i-1) ~> w(i) or w(i-1) is null
*----------------------------------------------------------
*b w(i) |- w(i+1) w(i) ~> w(i+1) or no w(i+1) yet
*----------------------------------------------------------
*/
bool a = false, b = false;
--w_i_m_1;
++w_i_p_1;
b = ( w_i->second.first != SAW_SENTINAL );
if ( w_i_m_1 != w_end ) {
a = ( w_i_m_1->second.first != SAW_SENTINAL );
}
if ( a ) {
if ( b ) {
/*Case 1:
w(i-1) |- w(i) |- w(i+1)
*/
Line l1 = get_sharing_line(*w_i_m_1, tau);
iter w_i_m_2 = w_i_m_1;
--w_i_m_2;
bool c = true;
if ( w_i_m_2 != w_end ) {
c = w_i_m_2->second != l1;
}
if ( c ) { /* w(i-1) ^ tau != w(i-2) ^ w(i-1) */
/*extension: w(i-1) -> tau |- w(i) */
w_i_m_1->second = l1;
/*insert(pos, const T&) is to insert before pos*/
iter_d[tau] = hlist->insert(w_i, make_pair(tau, tau_i));
} else { /* w(i-1) ^ tau == w(i-2) ^ w(i-1) */
/*must be w(i-2) ~> w(i-1) */
bool d = true;
//need to handle the case when w_i_p_1 is null
Line l3 = get_sharing_line(*w_i_p_1, tau);
if ( w_i_p_1 != w_end )
d = w_i_p_1->second != l3;
if ( d ) { /* w(i+1) ^ tau != w(i+1) ^ w(i+2) */
/*extension: w(i) |- tau -> w(i+1) */
w_i->second = tau_i;
iter_d[tau] = hlist->insert(w_i_p_1, make_pair(tau, l3));
} else { /* w(i+1) ^ tau == w(i+1) ^ w(i+2) */
/*must be w(1+1) ~> w(i+2) */
Line l5 = get_sharing_line(*w_i_m_1, *w_i_p_1);
if ( l5 != w_i_p_1->second ) { /* w(i-1) ^ w(i+1) != w(i+1) ^ w(i+2) */
/*extension: w(i-2) -> tau |- w(i) |- w(i-1) -> w(i+1) */
w_i_m_2->second = get_sharing_line(*w_i_m_2, tau);
iter_d[tau] = hlist->insert(w_i, make_pair(tau, tau_i));
w_i->second = w_i_m_1->second;
w_i_m_1->second = l5;
iter_d[w_i_m_1->first] = hlist->insert(w_i_p_1, *w_i_m_1);
hlist->erase(w_i_m_1);
} else {
/*mesh is tetrahedral*/
// dont know what that means.
;
}
}
}
} else {
/*Case 2:
w(i-1) |- w(i) ~> w(1+1)
*/
if ( w_i->second.second == tau_i.first
|| w_i->second.second == tau_i.second ) { /*w(i) ^ w(i+1) < w(i) ^ tau*/
/*extension: w(i) |- tau -> w(i+1) */
w_i->second = tau_i;
Line l1 = get_sharing_line(*w_i_p_1, tau);
iter_d[tau] = hlist->insert(w_i_p_1, make_pair(tau, l1));
} else { /*w(i) ^ w(i+1) !< w(i) ^ tau*/
Line l1 = get_sharing_line(*w_i_m_1, tau);
bool c = true;
iter w_i_m_2 = w_i_m_1;
--w_i_m_2;
if ( w_i_m_2 != w_end )
c = l1 != w_i_m_2->second;
if (c) { /*w(i-1) ^ tau != w(i-2) ^ w(i-1)*/
/*extension: w(i-1) -> tau |- w(i)*/
w_i_m_1->second = l1;
iter_d[tau] = hlist->insert(w_i, make_pair(tau, tau_i));
} else { /*w(i-1) ^ tau == w(i-2) ^ w(i-1)*/
/*must be w(i-2)~>w(i-1)*/
/*extension: w(i-2) -> tau |- w(i) |- w(i-1) -> w(i+1)*/
w_i_m_2->second = get_sharing_line(*w_i_m_2, tau);
iter_d[tau] = hlist->insert(w_i, make_pair(tau, tau_i));
w_i->second = w_i_m_1->second;
w_i_m_1->second = get_sharing_line(*w_i_m_1, *w_i_p_1);
iter_d[w_i_m_1->first] = hlist->insert(w_i_p_1, *w_i_m_1);
hlist->erase(w_i_m_1);
}
}
}
} else {
if ( b ) {
/*Case 3:
w(i-1) ~> w(i) |- w(i+1)
*/
bool c = false;
if ( w_i_m_1 != w_end )
c = ( w_i_m_1->second.second == tau_i.first)
|| ( w_i_m_1->second.second == tau_i.second);
if ( c ) { /*w(i-1) ^ w(i) < w(i) ^ tau*/
/* extension: w(i-1) -> tau |- w(i) */
if ( w_i_m_1 != w_end )
w_i_m_1->second = get_sharing_line(*w_i_m_1, tau);
iter_d[tau] = hlist->insert(w_i, make_pair(tau, tau_i));
} else {
bool d = true;
Line l1;
l1.first = SAW_SENTINAL;
l1.second = SAW_SENTINAL;
if ( w_i_p_1 != w_end ) {
l1 = get_sharing_line(*w_i_p_1, tau);
d = l1 != w_i_p_1->second;
}
if (d) { /*w(i+1) ^ tau != w(i+1) ^ w(i+2)*/
/*extension: w(i) |- tau -> w(i+1) */
w_i->second = tau_i;
iter_d[tau] = hlist->insert(w_i_p_1, make_pair(tau, l1));
} else {
/*must be w(i+1) ~> w(i+2)*/
/*extension: w(i-1) -> w(i+1) |- w(i) |- tau -> w(i+2) */
iter w_i_p_2 = w_i_p_1;
++w_i_p_2;
w_i_p_1->second = w_i->second;
iter_d[i] = hlist->insert(w_i_p_2, make_pair(i, tau_i));
hlist->erase(w_i);
Line l2 = get_sharing_line(*w_i_p_2, tau);
iter_d[tau] = hlist->insert(w_i_p_2, make_pair(tau, l2));
}
}
} else {
/*Case 4:
w(i-1) ~> w(i) ~> w(i+1)
*/
bool c = false;
if ( w_i_m_1 != w_end ) {
c = (w_i_m_1->second.second == tau_i.first)
|| (w_i_m_1->second.second == tau_i.second);
}
if ( c ) { /*w(i-1) ^ w(i) < w(i) ^ tau */
/*extension: w(i-1) -> tau |- w(i) */
if ( w_i_m_1 != w_end )
w_i_m_1->second = get_sharing_line(*w_i_m_1, tau);
iter_d[tau] = hlist->insert(w_i, make_pair(tau, tau_i));
} else {
/*extension: w(i) |- tau -> w(i+1) */
w_i->second = tau_i;
Line l1;
l1.first = SAW_SENTINAL;
l1.second = SAW_SENTINAL;
if ( w_i_p_1 != w_end )
l1 = get_sharing_line(*w_i_p_1, tau);
iter_d[tau] = hlist->insert(w_i_p_1, make_pair(tau, l1));
}
}
}
return true;
}
protected:
TriangleDecorator td; /*a decorator for vertex*/
HList hlist;
/*This must be a handle of list to record the SAW
The element type of the list is pair<Vertex, Line>
*/
IteratorD iter_d;
/*Problem statement: Need a fast access to w for triangle i.
*Possible solution: mantain an array to record.
iter_d[i] will return an iterator
which points to w(i), where i is a vertex
representing triangle i.
*/
};
template <class Triangle, class HList, class Iterator>
inline
SAW_visitor<Triangle, HList, Iterator>
visit_SAW(Triangle t, HList hl, Iterator i) {
return SAW_visitor<Triangle, HList, Iterator>(t, hl, i);
}
template <class Tri, class HList, class Iter>
inline
SAW_visitor< random_access_iterator_property_map<Tri*,Tri,Tri&>,
HList, random_access_iterator_property_map<Iter*,Iter,Iter&> >
visit_SAW_ptr(Tri* t, HList hl, Iter* i) {
typedef random_access_iterator_property_map<Tri*,Tri,Tri&> TriD;
typedef random_access_iterator_property_map<Iter*,Iter,Iter&> IterD;
return SAW_visitor<TriD, HList, IterD>(t, hl, i);
}
// should also have combo's of pointers, and also const :(
}
#endif /*BOOST_SAW_H*/

View File

@@ -0,0 +1,123 @@
// (C) Copyright Jeremy Siek 2001.
// 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_SET_ADAPTOR_HPP
#define BOOST_SET_ADAPTOR_HPP
#include <set>
#include <boost/unordered_set.hpp>
namespace boost {
template <class K, class C, class A, class T>
bool set_contains(const std::set<K,C,A>& s, const T& x) {
return s.find(x) != s.end();
}
template <class K, class H, class C, class A, class T>
bool set_contains(const boost::unordered_set<K,H,C,A>& s, const T& x) {
return s.find(x) != s.end();
}
template <class K, class C, class A>
bool set_equal(const std::set<K,C,A>& x,
const std::set<K,C,A>& y)
{
return x == y;
}
// Not the same as lexicographical_compare_3way applied to std::set.
// this is equivalent semantically to bitset::operator<()
template <class K, class C, class A>
int set_lex_order(const std::set<K,C,A>& x,
const std::set<K,C,A>& y)
{
typename std::set<K,C,A>::iterator
xi = x.begin(), yi = y.begin(), xend = x.end(), yend = y.end();
for (; xi != xend && yi != yend; ++xi, ++yi) {
if (*xi < *yi)
return 1;
else if (*yi < *xi)
return -1;
}
if (xi == xend)
return (yi == yend) ? 0 : -1;
else
return 1;
}
template <class K, class C, class A>
void set_clear(std::set<K,C,A>& x) {
x.clear();
}
template <class K, class C, class A>
bool set_empty(const std::set<K,C,A>& x) {
return x.empty();
}
template <class K, class C, class A, class T>
void set_insert(std::set<K,C,A>& x, const T& a) {
x.insert(a);
}
template <class K, class C, class A, class T>
void set_remove(std::set<K,C,A>& x, const T& a) {
x.erase(a);
}
template <class K, class C, class A>
void set_intersect(const std::set<K,C,A>& x,
const std::set<K,C,A>& y,
std::set<K,C,A>& z)
{
z.clear();
std::set_intersection(x.begin(), x.end(),
y.begin(), y.end(),
std::inserter(z));
}
template <class K, class C, class A>
void set_union(const std::set<K,C,A>& x,
const std::set<K,C,A>& y,
std::set<K,C,A>& z)
{
z.clear();
std::set_union(x.begin(), x.end(),
y.begin(), y.end(),
std::inserter(z));
}
template <class K, class C, class A>
void set_difference(const std::set<K,C,A>& x,
const std::set<K,C,A>& y,
std::set<K,C,A>& z)
{
z.clear();
std::set_difference(x.begin(), x.end(),
y.begin(), y.end(),
std::inserter(z, z.begin()));
}
template <class K, class C, class A>
bool set_subset(const std::set<K,C,A>& x,
const std::set<K,C,A>& y)
{
return std::includes(x.begin(), x.end(), y.begin(), y.end());
}
// Shit, can't implement this without knowing the size of the
// universe.
template <class K, class C, class A>
void set_compliment(const std::set<K,C,A>& x,
std::set<K,C,A>& z)
{
z.clear();
}
} // namespace boost
#endif // BOOST_SET_ADAPTOR_HPP

View File

@@ -0,0 +1,139 @@
// (C) Copyright Jeremy Siek 2001.
// 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_SHADOW_ITERATOR_HPP
#define BOOST_SHADOW_ITERATOR_HPP
#include <boost/iterator_adaptors.hpp>
#include <boost/operators.hpp>
namespace boost {
namespace detail {
template <class A, class B, class D>
class shadow_proxy
: boost::operators< shadow_proxy<A,B,D> >
{
typedef shadow_proxy self;
public:
inline shadow_proxy(A aa, B bb) : a(aa), b(bb) { }
inline shadow_proxy(const self& x) : a(x.a), b(x.b) { }
template <class Self>
inline shadow_proxy(Self x) : a(x.a), b(x.b) { }
inline self& operator=(const self& x) { a = x.a; b = x.b; return *this; }
inline self& operator++() { ++a; return *this; }
inline self& operator--() { --a; return *this; }
inline self& operator+=(const self& x) { a += x.a; return *this; }
inline self& operator-=(const self& x) { a -= x.a; return *this; }
inline self& operator*=(const self& x) { a *= x.a; return *this; }
inline self& operator/=(const self& x) { a /= x.a; return *this; }
inline self& operator%=(const self& x) { return *this; } // JGS
inline self& operator&=(const self& x) { return *this; } // JGS
inline self& operator|=(const self& x) { return *this; } // JGS
inline self& operator^=(const self& x) { return *this; } // JGS
inline friend D operator-(const self& x, const self& y) {
return x.a - y.a;
}
inline bool operator==(const self& x) const { return a == x.a; }
inline bool operator<(const self& x) const { return a < x.a; }
// protected:
A a;
B b;
};
struct shadow_iterator_policies
{
template <typename iter_pair>
void initialize(const iter_pair&) { }
template <typename Iter>
typename Iter::reference dereference(const Iter& i) const {
typedef typename Iter::reference R;
return R(*i.base().first, *i.base().second);
}
template <typename Iter>
bool equal(const Iter& p1, const Iter& p2) const {
return p1.base().first == p2.base().first;
}
template <typename Iter>
void increment(Iter& i) { ++i.base().first; ++i.base().second; }
template <typename Iter>
void decrement(Iter& i) { --i.base().first; --i.base().second; }
template <typename Iter>
bool less(const Iter& x, const Iter& y) const {
return x.base().first < y.base().first;
}
template <typename Iter>
typename Iter::difference_type
distance(const Iter& x, const Iter& y) const {
return y.base().first - x.base().first;
}
template <typename D, typename Iter>
void advance(Iter& p, D n) { p.base().first += n; p.base().second += n; }
};
} // namespace detail
template <typename IterA, typename IterB>
struct shadow_iterator_generator {
// To use the iterator_adaptor we can't derive from
// random_access_iterator because we don't have a real reference.
// However, we want the STL algorithms to treat the shadow
// iterator like a random access iterator.
struct shadow_iterator_tag : public std::input_iterator_tag {
operator std::random_access_iterator_tag() {
return std::random_access_iterator_tag();
};
};
typedef typename std::iterator_traits<IterA>::value_type Aval;
typedef typename std::iterator_traits<IterB>::value_type Bval;
typedef typename std::iterator_traits<IterA>::reference Aref;
typedef typename std::iterator_traits<IterB>::reference Bref;
typedef typename std::iterator_traits<IterA>::difference_type D;
typedef detail::shadow_proxy<Aval,Bval,Aval> V;
typedef detail::shadow_proxy<Aref,Bref,Aval> R;
typedef iterator_adaptor< std::pair<IterA, IterB>,
detail::shadow_iterator_policies,
V, R, V*, shadow_iterator_tag,
D> type;
};
// short cut for creating a shadow iterator
template <class IterA, class IterB>
inline typename shadow_iterator_generator<IterA,IterB>::type
make_shadow_iter(IterA a, IterB b) {
typedef typename shadow_iterator_generator<IterA,IterB>::type Iter;
return Iter(std::make_pair(a,b));
}
template <class Cmp>
struct shadow_cmp {
inline shadow_cmp(const Cmp& c) : cmp(c) { }
template <class ShadowProxy1, class ShadowProxy2>
inline bool operator()(const ShadowProxy1& x, const ShadowProxy2& y) const
{
return cmp(x.a, y.a);
}
Cmp cmp;
};
} // namespace boost
namespace std {
template <class A1, class B1, class D1,
class A2, class B2, class D2>
void swap(boost::detail::shadow_proxy<A1&,B1&,D1> x,
boost::detail::shadow_proxy<A2&,B2&,D2> y)
{
std::swap(x.a, y.a);
std::swap(x.b, y.b);
}
}
#endif // BOOST_SHADOW_ITERATOR_HPP

View File

@@ -0,0 +1,198 @@
//=======================================================================
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
// Copyright 2004, 2005 Trustees of Indiana University
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek,
// Doug Gregor, D. Kevin McGrath
//
// 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_GRAPH_DETAIL_SPARSE_ORDERING_HPP
#define BOOST_GRAPH_DETAIL_SPARSE_ORDERING_HPP
#include <boost/config.hpp>
#include <vector>
#include <queue>
#include <boost/pending/queue.hpp>
#include <boost/pending/mutable_queue.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/breadth_first_search.hpp>
#include <boost/graph/properties.hpp>
#include <boost/pending/indirect_cmp.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/bind.hpp>
#include <boost/graph/iteration_macros.hpp>
#include <boost/graph/depth_first_search.hpp>
namespace boost {
namespace sparse {
// rcm_queue
//
// This is a custom queue type used in the
// *_ordering algorithms.
// In addition to the normal queue operations, the
// rcm_queue provides:
//
// int eccentricity() const;
// value_type spouse() const;
//
// yes, it's a bad name...but it works, so use it
template < class Vertex, class DegreeMap,
class Container = std::deque<Vertex> >
class rcm_queue : public std::queue<Vertex, Container> {
typedef std::queue<Vertex> base;
public:
typedef typename base::value_type value_type;
typedef typename base::size_type size_type;
/* SGI queue has not had a contructor queue(const Container&) */
inline rcm_queue(DegreeMap deg)
: _size(0), Qsize(1), eccen(-1), degree(deg) { }
inline void pop() {
if ( !_size )
Qsize = base::size();
base::pop();
if ( _size == Qsize-1 ) {
_size = 0;
++eccen;
} else
++_size;
}
inline value_type& front() {
value_type& u = base::front();
if ( _size == 0 )
w = u;
else if (get(degree,u) < get(degree,w) )
w = u;
return u;
}
inline const value_type& front() const {
const value_type& u = base::front();
if ( _size == 0 )
w = u;
else if (get(degree,u) < get(degree,w) )
w = u;
return u;
}
inline value_type& top() { return front(); }
inline const value_type& top() const { return front(); }
inline size_type size() const { return base::size(); }
inline size_type eccentricity() const { return eccen; }
inline value_type spouse() const { return w; }
protected:
size_type _size;
size_type Qsize;
int eccen;
mutable value_type w;
DegreeMap degree;
};
template <typename Tp, typename Sequence = std::deque<Tp> >
class sparse_ordering_queue : public boost::queue<Tp, Sequence>{
public:
typedef typename Sequence::iterator iterator;
typedef typename Sequence::reverse_iterator reverse_iterator;
typedef queue<Tp,Sequence> base;
typedef typename Sequence::size_type size_type;
inline iterator begin() { return this->c.begin(); }
inline reverse_iterator rbegin() { return this->c.rbegin(); }
inline iterator end() { return this->c.end(); }
inline reverse_iterator rend() { return this->c.rend(); }
inline Tp &operator[](int n) { return this->c[n]; }
inline size_type size() {return this->c.size(); }
protected:
//nothing
};
} // namespace sparse
// Compute Pseudo peripheral
//
// To compute an approximated peripheral for a given vertex.
// Used in <tt>king_ordering</tt> algorithm.
//
template <class Graph, class Vertex, class ColorMap, class DegreeMap>
Vertex
pseudo_peripheral_pair(Graph const& G, const Vertex& u, int& ecc,
ColorMap color, DegreeMap degree)
{
typedef typename property_traits<ColorMap>::value_type ColorValue;
typedef color_traits<ColorValue> Color;
sparse::rcm_queue<Vertex, DegreeMap> Q(degree);
typename boost::graph_traits<Graph>::vertex_iterator ui, ui_end;
for (boost::tie(ui, ui_end) = vertices(G); ui != ui_end; ++ui)
if (get(color, *ui) != Color::red()) put(color, *ui, Color::white());
breadth_first_visit(G, u, buffer(Q).color_map(color));
ecc = Q.eccentricity();
return Q.spouse();
}
// Find a good starting node
//
// This is to find a good starting node for the
// king_ordering algorithm. "good" is in the sense
// of the ordering generated by RCM.
//
template <class Graph, class Vertex, class Color, class Degree>
Vertex find_starting_node(Graph const& G, Vertex r, Color color, Degree degree)
{
Vertex x, y;
int eccen_r, eccen_x;
x = pseudo_peripheral_pair(G, r, eccen_r, color, degree);
y = pseudo_peripheral_pair(G, x, eccen_x, color, degree);
while (eccen_x > eccen_r) {
r = x;
eccen_r = eccen_x;
x = y;
y = pseudo_peripheral_pair(G, x, eccen_x, color, degree);
}
return x;
}
template <typename Graph>
class out_degree_property_map
: public put_get_helper<typename graph_traits<Graph>::degree_size_type,
out_degree_property_map<Graph> >
{
public:
typedef typename graph_traits<Graph>::vertex_descriptor key_type;
typedef typename graph_traits<Graph>::degree_size_type value_type;
typedef value_type reference;
typedef readable_property_map_tag category;
out_degree_property_map(const Graph& g) : m_g(g) { }
value_type operator[](const key_type& v) const {
return out_degree(v, m_g);
}
private:
const Graph& m_g;
};
template <typename Graph>
inline out_degree_property_map<Graph>
make_out_degree_map(const Graph& g) {
return out_degree_property_map<Graph>(g);
}
} // namespace boost
#endif // BOOST_GRAPH_KING_HPP