feat():initial version

This commit is contained in:
2026-06-09 20:16:47 +08:00
commit 85fbb3188c
14809 changed files with 3044607 additions and 0 deletions

View File

@@ -0,0 +1,135 @@
//
//=======================================================================
// 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,239 @@
//
//=======================================================================
// 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
{ // replace with iterator_adaptor implementation -JGS
typedef std::bidirectional_iterator_tag iterator_category;
typedef ArrayBinaryTreeNode value_type;
typedef size_type difference_type;
typedef array_binary_tree_node* pointer;
typedef ArrayBinaryTreeNode& reference;
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 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,66 @@
//=======================================================================
// Copyright 2013 University of Warsaw.
// Authors: Piotr Wygocki
//
// 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_AUGMENT_HPP
#define BOOST_GRAPH_AUGMENT_HPP
#include <boost/graph/filtered_graph.hpp>
namespace boost
{
namespace detail
{
template < class Graph, class ResCapMap >
filtered_graph< const Graph, is_residual_edge< ResCapMap > > residual_graph(
const Graph& g, ResCapMap residual_capacity)
{
return filtered_graph< const Graph, is_residual_edge< ResCapMap > >(
g, is_residual_edge< ResCapMap >(residual_capacity));
}
template < class Graph, class PredEdgeMap, class ResCapMap,
class RevEdgeMap >
inline void augment(const Graph& g,
typename graph_traits< Graph >::vertex_descriptor src,
typename graph_traits< Graph >::vertex_descriptor sink, PredEdgeMap p,
ResCapMap residual_capacity, RevEdgeMap reverse_edge)
{
typename graph_traits< Graph >::edge_descriptor e;
typename graph_traits< Graph >::vertex_descriptor u;
typedef typename property_traits< ResCapMap >::value_type FlowValue;
// find minimum residual capacity along the augmenting path
FlowValue delta = (std::numeric_limits< FlowValue >::max)();
e = get(p, sink);
do
{
BOOST_USING_STD_MIN();
delta = min BOOST_PREVENT_MACRO_SUBSTITUTION(
delta, get(residual_capacity, e));
u = source(e, g);
e = get(p, u);
} while (u != src);
// push delta units of flow along the augmenting path
e = get(p, sink);
do
{
put(residual_capacity, e, get(residual_capacity, e) - delta);
put(residual_capacity, get(reverse_edge, e),
get(residual_capacity, get(reverse_edge, e)) + delta);
u = source(e, g);
e = get(p, u);
} while (u != src);
}
} // namespace detail
} // namespace boost
#endif /* BOOST_GRAPH_AUGMENT_HPP */

View File

@@ -0,0 +1,740 @@
// 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>
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)
{
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 >::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_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 boost::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 boost::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,206 @@
//=======================================================================
// 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,358 @@
//
//=======================================================================
// 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>
// WARNING: it is not safe to copy a d_ary_heap_indirect and then modify one of
// the copies. The class is required to be copyable so it can be passed around
// (without move support from C++11), but it deep-copies the heap contents yet
// shallow-copies the index_in_heap_map.
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()
{
BOOST_ASSERT(!this->empty());
return data[0];
}
const Value& top() const
{
BOOST_ASSERT(!this->empty());
return data[0];
}
void pop()
{
BOOST_ASSERT(!this->empty());
put(index_in_heap, data[0], (size_type)(-1));
if (data.size() != 1)
{
data[0] = data.back();
put(index_in_heap, data[0], (size_type)(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,122 @@
//
//=======================================================================
// 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
#include <iosfwd>
#include <boost/functional/hash.hpp>
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
{
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 << ")";
}
}
// Boost's functional/hash
namespace boost
{
template < typename D, typename V >
struct hash< boost::detail::edge_desc_impl< D, V > >
{
std::size_t operator()(const boost::detail::edge_desc_impl< D, V >& x) const
{
return hash_value(x.get_property());
}
};
}
#endif // BOOST_GRAPH_DETAIL_DETAIL_EDGE_HPP

View File

@@ -0,0 +1,10 @@
#ifndef BOOST_GRAPH_DETAIL_EMPTY_HEADER_HPP_INCLUDED
#define BOOST_GRAPH_DETAIL_EMPTY_HEADER_HPP_INCLUDED
// Copyright 2018 Peter Dimov
//
// 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)
#endif // #ifndef BOOST_GRAPH_DETAIL_EMPTY_HEADER_HPP_INCLUDED

View File

@@ -0,0 +1,137 @@
// (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>
#include <boost/concept/assert.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 = {https://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)
{
BOOST_CONCEPT_ASSERT((VertexListGraphConcept< Graph >));
typedef typename graph_traits< Graph >::vertex_descriptor Vertex;
typedef typename graph_traits< Graph >::vertex_iterator VertexIterator;
BOOST_CONCEPT_ASSERT(
(ReadablePropertyMapConcept< DistanceMap, Vertex >));
BOOST_CONCEPT_ASSERT((NumericValueConcept< Distance >));
typedef numeric_values< Distance > DistanceNumbers;
BOOST_CONCEPT_ASSERT((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
{
typedef T result_type;
typedef T first_argument_type;
typedef T second_argument_type;
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
{
typedef T result_type;
typedef T 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,319 @@
// 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
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))
{
BOOST_ASSERT(key_transform(*i) < numkeys);
++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 (VerticesSize i = 1; i < numkeys + 1; ++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
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))
{
NumKeys source = key_transform(*i);
BOOST_ASSERT(source < numkeys);
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
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))
{
NumKeys source = key_transform(*i);
BOOST_ASSERT(source < numkeys);
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
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)
{
BOOST_ASSERT(key_transform(key_begin[i]) < numkeys);
// 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
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)
{
BOOST_ASSERT(key_transform(key_begin[i]) < numkeys);
// 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;
}
}
// The versions of operator()() here can't return by reference because
// the actual type passed in may not match Pair, in which case the
// reference parameter is bound to a temporary that could end up
// dangling after the operator returns.
template < typename Pair > struct project1st
{
typedef typename Pair::first_type result_type;
result_type operator()(const Pair& p) const { return p.first; }
};
template < typename Pair > struct project2nd
{
typedef typename Pair::second_type result_type;
result_type operator()(const Pair& p) const { return p.second; }
};
}
}
}
#endif // BOOST_GRAPH_DETAIL_HISTOGRAM_SORT_HPP

View File

@@ -0,0 +1,98 @@
//
//=======================================================================
// 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,92 @@
//=======================================================================
// 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,77 @@
// (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,298 @@
// 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,30 @@
// Copyright 2012 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
// Selector to determine whether a selector is distributedS (can only be true
// if <boost/graph/distributed/selector.hpp> has been included) so that we can
// disable various sequential-graph-only traits specializations for distributed
// graphs.
#ifndef BOOST_GRAPH_DETAIL_IS_DISTRIBUTED_SELECTOR_HPP
#define BOOST_GRAPH_DETAIL_IS_DISTRIBUTED_SELECTOR_HPP
#include <boost/mpl/bool.hpp>
namespace boost
{
namespace detail
{
template < typename > struct is_distributed_selector : boost::mpl::false_
{
};
}
}
#endif // BOOST_GRAPH_DETAIL_IS_DISTRIBUTED_SELECTOR_HPP

View File

@@ -0,0 +1,232 @@
// 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 the labeled graph.
// This specialization depends on the mutability of the underlying graph type.
// If the underlying graph is fully mutable, 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,206 @@
//=======================================================================
// 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 empty, Next next)
{
while (head != empty && 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 empty, Next next)
{
Node result = node;
node = next(node);
next(result) = empty;
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 empty, Next next)
{
std::size_t s = 0;
for (; head != empty; 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,16 @@
#ifndef BOOST_GRAPH_DETAIL_MPI_INCLUDE_HPP_INCLUDED
#define BOOST_GRAPH_DETAIL_MPI_INCLUDE_HPP_INCLUDED
// Copyright 2018 Peter Dimov
//
// 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)
#if defined BOOST_GRAPH_USE_MPI
#define BOOST_GRAPH_MPI_INCLUDE(x) x
#else
#define BOOST_GRAPH_MPI_INCLUDE(x) <boost/graph/detail/empty_header.hpp>
#endif
#endif // #ifndef BOOST_GRAPH_DETAIL_MPI_INCLUDE_HPP_INCLUDED

View File

@@ -0,0 +1,211 @@
// (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,124 @@
// 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:
// https://web.archive.org/web/20041213234742/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,673 @@
// 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:
// https://web.archive.org/web/20041213234742/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);
bool ok = p.parse(scan);
m_graph.finish_building_graph();
return ok;
}
} // namespace boost
#endif // BOOST_READ_GRAPHVIZ_SPIRIT_HPP

View File

@@ -0,0 +1,483 @@
//=======================================================================
// 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,118 @@
// (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,183 @@
// (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,211 @@
//=======================================================================
// 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