update boost
This commit is contained in:
@@ -15,100 +15,118 @@
|
||||
#include <utility>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
|
||||
# define BOOST_GRAPH_NO_OPTIONAL
|
||||
#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>
|
||||
#define BOOST_GRAPH_MEMBER .
|
||||
#else
|
||||
#define BOOST_GRAPH_MEMBER ->
|
||||
#include <boost/optional.hpp>
|
||||
#endif // ndef BOOST_GRAPH_NO_OPTIONAL
|
||||
|
||||
namespace boost {
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail {
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template < class VertexIterator, class OutEdgeIterator, class Graph >
|
||||
class adj_list_edge_iterator
|
||||
{
|
||||
typedef adj_list_edge_iterator self;
|
||||
|
||||
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;
|
||||
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() {}
|
||||
|
||||
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)
|
||||
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)
|
||||
{
|
||||
++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);
|
||||
}
|
||||
|
||||
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;
|
||||
VertexIterator vBegin;
|
||||
VertexIterator vCurr;
|
||||
VertexIterator vEnd;
|
||||
|
||||
#ifdef BOOST_GRAPH_NO_OPTIONAL
|
||||
std::pair<OutEdgeIterator, OutEdgeIterator> edges;
|
||||
std::pair< OutEdgeIterator, OutEdgeIterator > edges;
|
||||
#else
|
||||
boost::optional<std::pair<OutEdgeIterator, OutEdgeIterator> >
|
||||
edges;
|
||||
boost::optional< std::pair< OutEdgeIterator, OutEdgeIterator > > edges;
|
||||
#endif // ndef BOOST_GRAPH_NO_OPTIONAL
|
||||
const Graph* m_g;
|
||||
const Graph* m_g;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace detail
|
||||
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -14,170 +14,224 @@
|
||||
#include <iterator>
|
||||
#include <functional>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/iterator.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace boost
|
||||
{
|
||||
|
||||
/*
|
||||
* Note: array_binary_tree is a completey balanced binary tree.
|
||||
*/
|
||||
#if !defined BOOST_NO_STD_ITERATOR_TRAITS
|
||||
template <class RandomAccessIterator, class ID>
|
||||
template < class RandomAccessIterator, class ID >
|
||||
#else
|
||||
template <class RandomAccessIterator, class ValueType, class ID>
|
||||
template < class RandomAccessIterator, class ValueType, class ID >
|
||||
#endif
|
||||
class array_binary_tree_node {
|
||||
class array_binary_tree_node
|
||||
{
|
||||
public:
|
||||
typedef array_binary_tree_node ArrayBinaryTreeNode;
|
||||
typedef RandomAccessIterator rep_iterator;
|
||||
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;
|
||||
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;
|
||||
typedef int difference_type;
|
||||
typedef ValueType value_type;
|
||||
#endif
|
||||
typedef difference_type size_type;
|
||||
typedef difference_type size_type;
|
||||
|
||||
struct children_type {
|
||||
struct iterator
|
||||
: boost::iterator<std::bidirectional_iterator_tag, ArrayBinaryTreeNode,
|
||||
difference_type, array_binary_tree_node*, ArrayBinaryTreeNode&>
|
||||
{ // replace with iterator_adaptor implementation -JGS
|
||||
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;
|
||||
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 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;
|
||||
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;
|
||||
};
|
||||
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 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)
|
||||
{
|
||||
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;
|
||||
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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//=======================================================================
|
||||
// Copyright 2013 University of Warsaw.
|
||||
// Authors: Piotr Wygocki
|
||||
// Authors: Piotr Wygocki
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -12,52 +12,55 @@
|
||||
|
||||
#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)
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
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);
|
||||
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));
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
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
|
||||
} // namespace boost
|
||||
|
||||
#endif /* BOOST_GRAPH_AUGMENT_HPP */
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,9 +15,11 @@
|
||||
|
||||
#include <boost/operators.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail {
|
||||
namespace detail
|
||||
{
|
||||
|
||||
//=========================================================================
|
||||
// Implementation details of connected_components
|
||||
@@ -25,184 +27,180 @@ namespace boost {
|
||||
// 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>
|
||||
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) {}
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
ComponentsPA m_component;
|
||||
comp_type& m_count;
|
||||
};
|
||||
|
||||
template <class DiscoverTimeMap, class FinishTimeMap, class TimeT,
|
||||
class DFSVisitor>
|
||||
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) {}
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
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>
|
||||
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);
|
||||
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)
|
||||
|
||||
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++;
|
||||
}
|
||||
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>
|
||||
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;
|
||||
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)
|
||||
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);
|
||||
}
|
||||
|
||||
// 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]];
|
||||
|
||||
|
||||
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());
|
||||
// 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 IndexIterator, class Integer, class Distance>
|
||||
class component_iterator
|
||||
: boost::forward_iterator_helper<
|
||||
component_iterator<IndexIterator,Integer,Distance>,
|
||||
Integer, Distance,Integer*, Integer&>
|
||||
|
||||
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;
|
||||
}
|
||||
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)
|
||||
|
||||
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;
|
||||
return x.node == y.node;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace detail
|
||||
|
||||
#if defined(__sgi) && !defined(__GNUC__)
|
||||
#pragma reset woff 1234
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -25,160 +25,172 @@
|
||||
// (without move support from C++11), but it deep-copies the heap contents yet
|
||||
// shallow-copies the index_in_heap_map.
|
||||
|
||||
namespace boost {
|
||||
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);
|
||||
// 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);
|
||||
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 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) {}
|
||||
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();
|
||||
}
|
||||
size_type size() const { return data.size(); }
|
||||
|
||||
bool empty() const {
|
||||
return data.empty();
|
||||
}
|
||||
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();
|
||||
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();
|
||||
} else {
|
||||
data.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
// 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));
|
||||
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();
|
||||
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;
|
||||
}
|
||||
DistanceMap keys() const { return distance; }
|
||||
|
||||
private:
|
||||
private:
|
||||
Compare compare;
|
||||
Container data;
|
||||
DistanceMap distance;
|
||||
@@ -186,38 +198,41 @@ namespace boost {
|
||||
|
||||
// The distances being compared using compare and that are stored in the
|
||||
// distance map
|
||||
typedef typename boost::property_traits<DistanceMap>::value_type distance_type;
|
||||
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;
|
||||
}
|
||||
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;
|
||||
// Get the first child of a given node
|
||||
static size_type first_child(size_type index)
|
||||
{
|
||||
return index * Arity + 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);
|
||||
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));
|
||||
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
|
||||
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)])) {
|
||||
@@ -229,90 +244,114 @@ namespace boost {
|
||||
|
||||
// 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
|
||||
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();
|
||||
// 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;
|
||||
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 = first_child(index);
|
||||
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;
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
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();
|
||||
verify_heap();
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
@@ -15,107 +15,108 @@
|
||||
|
||||
#include <boost/functional/hash.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail {
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename Directed, typename Vertex>
|
||||
struct edge_base
|
||||
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;
|
||||
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 < 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)
|
||||
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();
|
||||
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)
|
||||
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());
|
||||
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)
|
||||
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();
|
||||
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)
|
||||
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();
|
||||
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)
|
||||
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();
|
||||
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)
|
||||
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();
|
||||
return a.get_property() >= b.get_property();
|
||||
}
|
||||
|
||||
} //namespace detail
|
||||
|
||||
} // 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)
|
||||
{
|
||||
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()); }
|
||||
};
|
||||
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
|
||||
|
||||
10
linx64/include/boost/graph/detail/empty_header.hpp
Normal file
10
linx64/include/boost/graph/detail/empty_header.hpp
Normal 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
|
||||
@@ -33,32 +33,31 @@ namespace boost
|
||||
// pages = {466--484},
|
||||
// priority = {0},
|
||||
// title = {A Graph-theoretic perspective on centrality},
|
||||
// url = {http://dx.doi.org/10.1016/j.socnet.2005.11.005},
|
||||
// url = {https://doi.org/10.1016/j.socnet.2005.11.005},
|
||||
// volume = {28},
|
||||
// year = {2006}
|
||||
// }
|
||||
// }
|
||||
|
||||
namespace detail {
|
||||
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)
|
||||
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> ));
|
||||
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;
|
||||
// NOTE: Disabled until this concept assert is fixed in Boost.ConceptCheck.
|
||||
// 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
|
||||
@@ -66,12 +65,15 @@ namespace detail {
|
||||
// zero, so it shouldn't be too problematic.
|
||||
Distance ret = init;
|
||||
VertexIterator i, end;
|
||||
for(boost::tie(i, end) = vertices(g); i != end; ++i) {
|
||||
for (boost::tie(i, end) = vertices(g); i != end; ++i)
|
||||
{
|
||||
Vertex v = *i;
|
||||
if(get(dist, v) != DistanceNumbers::infinity()) {
|
||||
if (get(dist, v) != DistanceNumbers::infinity())
|
||||
{
|
||||
ret = combine(ret, get(dist, v));
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
ret = DistanceNumbers::infinity();
|
||||
break;
|
||||
}
|
||||
@@ -81,51 +83,54 @@ namespace detail {
|
||||
|
||||
// Similar to std::plus<T>, but maximizes parameters
|
||||
// rather than adding them.
|
||||
template <typename T>
|
||||
struct maximize
|
||||
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); }
|
||||
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
|
||||
template < typename T > struct reciprocal
|
||||
{
|
||||
typedef T result_type;
|
||||
typedef T argument_type;
|
||||
T operator ()(T t)
|
||||
{ return T(1) / t; }
|
||||
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>
|
||||
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 typename graph_traits< Graph >::vertices_size_type size_type;
|
||||
|
||||
typedef numeric_values<distance_type> distance_values;
|
||||
typedef numeric_values<result_type> result_values;
|
||||
typedef numeric_values< distance_type > distance_values;
|
||||
typedef numeric_values< result_type > result_values;
|
||||
|
||||
static inline distance_type infinite_distance()
|
||||
{ return distance_values::infinity(); }
|
||||
{
|
||||
return distance_values::infinity();
|
||||
}
|
||||
|
||||
static inline result_type infinite_result()
|
||||
{ return result_values::infinity(); }
|
||||
{
|
||||
return result_values::infinity();
|
||||
}
|
||||
|
||||
static inline result_type zero_result()
|
||||
{ return result_values::zero(); }
|
||||
static inline result_type zero_result() { return result_values::zero(); }
|
||||
};
|
||||
|
||||
} /* namespace boost */
|
||||
|
||||
@@ -12,282 +12,308 @@
|
||||
|
||||
#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)
|
||||
namespace boost
|
||||
{
|
||||
// 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)
|
||||
namespace graph
|
||||
{
|
||||
using std::distance;
|
||||
typename std::iterator_traits<InputIterator>::difference_type n =
|
||||
distance(first, last);
|
||||
return (size_t)n;
|
||||
}
|
||||
namespace detail
|
||||
{
|
||||
|
||||
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 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 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) {
|
||||
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;
|
||||
}
|
||||
|
||||
typedef typename std::iterator_traits<RowstartIterator>::value_type EdgeIndex;
|
||||
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());
|
||||
}
|
||||
|
||||
// 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];
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
typedef
|
||||
typename std::iterator_traits< RowstartIterator >::value_type
|
||||
EdgeIndex;
|
||||
|
||||
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) {
|
||||
// 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];
|
||||
}
|
||||
}
|
||||
|
||||
typedef typename std::iterator_traits<RowstartIterator>::value_type EdgeIndex;
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
// 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 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)
|
||||
{
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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 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)
|
||||
{
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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 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)
|
||||
{
|
||||
|
||||
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;
|
||||
|
||||
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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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 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)
|
||||
{
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
typedef
|
||||
typename std::iterator_traits< RowstartIterator >::value_type
|
||||
EdgeIndex;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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 PropInputIterator,
|
||||
typename VerticesSize, typename PropType, typename SourceFilter>
|
||||
void split_into_separate_coords_filtered
|
||||
(InputIterator begin, InputIterator end,
|
||||
PropInputIterator props,
|
||||
std::vector<VerticesSize>& firsts,
|
||||
std::vector<VerticesSize>& seconds,
|
||||
std::vector<PropType>& props_out,
|
||||
const SourceFilter& filter) {
|
||||
firsts.clear();
|
||||
seconds.clear();
|
||||
props_out.clear();
|
||||
for (; begin != end; ++begin) {
|
||||
std::pair<VerticesSize, VerticesSize> edge = *begin;
|
||||
if (filter(edge.first)) {
|
||||
firsts.push_back(edge.first);
|
||||
seconds.push_back(edge.second);
|
||||
props_out.push_back(*props);
|
||||
}
|
||||
++props;
|
||||
}
|
||||
}
|
||||
template < typename 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);
|
||||
}
|
||||
}
|
||||
|
||||
// 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 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 Pair>
|
||||
struct project1st {
|
||||
typedef typename Pair::first_type result_type;
|
||||
result_type operator()(const Pair& p) const {return p.first;}
|
||||
};
|
||||
template < typename InputIterator, typename PropInputIterator,
|
||||
typename VerticesSize, typename PropType, typename SourceFilter >
|
||||
void split_into_separate_coords_filtered(InputIterator begin,
|
||||
InputIterator end, PropInputIterator props,
|
||||
std::vector< VerticesSize >& firsts,
|
||||
std::vector< VerticesSize >& seconds,
|
||||
std::vector< PropType >& props_out, const SourceFilter& filter)
|
||||
{
|
||||
firsts.clear();
|
||||
seconds.clear();
|
||||
props_out.clear();
|
||||
for (; begin != end; ++begin)
|
||||
{
|
||||
std::pair< VerticesSize, VerticesSize > edge = *begin;
|
||||
if (filter(edge.first))
|
||||
{
|
||||
firsts.push_back(edge.first);
|
||||
seconds.push_back(edge.second);
|
||||
props_out.push_back(*props);
|
||||
}
|
||||
++props;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Pair>
|
||||
struct project2nd {
|
||||
typedef typename Pair::second_type result_type;
|
||||
result_type operator()(const Pair& p) const {return p.second;}
|
||||
};
|
||||
// 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
|
||||
|
||||
@@ -16,64 +16,83 @@
|
||||
|
||||
// OBSOLETE
|
||||
|
||||
namespace boost {
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail {
|
||||
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() );
|
||||
}
|
||||
struct in_edge_tag
|
||||
{
|
||||
};
|
||||
struct out_edge_tag
|
||||
{
|
||||
};
|
||||
|
||||
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)
|
||||
template < class Vertex, class Edge, class Iterator1D, class EdgeDir >
|
||||
struct bidir_incidence_iterator
|
||||
{
|
||||
return x.i == y.i;
|
||||
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)
|
||||
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;
|
||||
return x.i != y.i;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -13,65 +13,80 @@
|
||||
|
||||
#include <boost/operators.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail {
|
||||
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> {
|
||||
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;
|
||||
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;
|
||||
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 "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) { }
|
||||
// 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);
|
||||
}
|
||||
inline value_type operator*() const { return (m_current_index); }
|
||||
|
||||
bool operator==(const self& other_iterator) const {
|
||||
return (m_current_index == *other_iterator);
|
||||
}
|
||||
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;
|
||||
IndexRandomAccessIterator m_index_iterator;
|
||||
value_type m_current_index;
|
||||
|
||||
}; // class component_index_iterator
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace detail
|
||||
|
||||
#endif // BOOST_GRAPH_DETAIL_INCREMENTAL_COMPONENTS_HPP
|
||||
|
||||
@@ -16,59 +16,62 @@
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
namespace detail
|
||||
{
|
||||
template < typename Graph > struct vertex_indexer
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
return get(vertex_index, g);
|
||||
}
|
||||
|
||||
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 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
|
||||
static value_type index(key_type k, const Graph& g)
|
||||
{
|
||||
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;
|
||||
return get(vertex_index, g, k);
|
||||
}
|
||||
};
|
||||
|
||||
static const_map_type index_map(const Graph& g)
|
||||
{ return get(edge_index, g); }
|
||||
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 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
|
||||
static const_map_type index_map(const Graph& g)
|
||||
{
|
||||
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;
|
||||
};
|
||||
}
|
||||
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
|
||||
|
||||
@@ -26,257 +26,271 @@
|
||||
#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
|
||||
namespace boost
|
||||
{
|
||||
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>
|
||||
namespace detail
|
||||
{
|
||||
struct secret {};
|
||||
|
||||
public:
|
||||
typedef no_property vertex_property_type;
|
||||
typedef void vertex_bundled;
|
||||
typedef secret vertex_map_type;
|
||||
typedef secret const_vertex_map_type;
|
||||
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;
|
||||
|
||||
secret operator[](secret) { return secret(); }
|
||||
// Directly access a vertex or edge bundle
|
||||
Property& operator[](Descriptor v)
|
||||
{
|
||||
return m_vertex_properties[get(vertex_index, derived(), v)];
|
||||
}
|
||||
|
||||
vertex_map_type get_vertex_bundle() const {
|
||||
return vertex_map_type();
|
||||
}
|
||||
const Property& operator[](Descriptor v) const
|
||||
{
|
||||
return m_vertex_properties[get(vertex_index, derived(), v)];
|
||||
}
|
||||
|
||||
protected:
|
||||
// All operations do nothing.
|
||||
indexed_vertex_properties() { }
|
||||
indexed_vertex_properties(std::size_t) { }
|
||||
vertex_map_type get_vertex_bundle(
|
||||
const IndexMap& index_map = IndexMap())
|
||||
{
|
||||
return vertex_map_type(m_vertex_properties.begin(), index_map);
|
||||
}
|
||||
|
||||
public:
|
||||
void clear() { }
|
||||
void resize(std::size_t) { }
|
||||
void reserve(std::size_t) { }
|
||||
};
|
||||
const_vertex_map_type get_vertex_bundle(
|
||||
const IndexMap& index_map = IndexMap()) const
|
||||
{
|
||||
return const_vertex_map_type(
|
||||
m_vertex_properties.begin(), index_map);
|
||||
}
|
||||
|
||||
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;
|
||||
protected:
|
||||
// Default-construct with no property values
|
||||
indexed_vertex_properties() {}
|
||||
|
||||
// Directly access a edge or edge bundle
|
||||
Property& operator[](Descriptor v)
|
||||
{ return m_edge_properties[get(edge_index, derived(), v)]; }
|
||||
// Initialize with n default-constructed property values
|
||||
indexed_vertex_properties(std::size_t n) : m_vertex_properties(n) {}
|
||||
|
||||
const Property& operator[](Descriptor v) const
|
||||
{ return m_edge_properties[get(edge_index, derived(), v)]; }
|
||||
public:
|
||||
// Clear the properties vector
|
||||
void clear() { m_vertex_properties.clear(); }
|
||||
|
||||
edge_map_type get_edge_bundle(const IndexMap& index_map = IndexMap()) {
|
||||
return edge_map_type(m_edge_properties.begin(), index_map);
|
||||
}
|
||||
// Resize the properties vector
|
||||
void resize(std::size_t n) { m_vertex_properties.resize(n); }
|
||||
|
||||
const_edge_map_type get_edge_bundle(const IndexMap& index_map = IndexMap()) const {
|
||||
return const_edge_map_type(m_edge_properties.begin(), index_map);
|
||||
}
|
||||
// Reserve space in the vector of properties
|
||||
void reserve(std::size_t n) { m_vertex_properties.reserve(n); }
|
||||
|
||||
protected:
|
||||
// Default-construct with no property values
|
||||
indexed_edge_properties() {}
|
||||
// Add a new property value to the back
|
||||
void push_back(const Property& prop)
|
||||
{
|
||||
m_vertex_properties.push_back(prop);
|
||||
}
|
||||
|
||||
// Initialize with n default-constructed property values
|
||||
indexed_edge_properties(std::size_t n) : m_edge_properties(n) { }
|
||||
// Write an element by raw index
|
||||
void write_by_index(std::size_t idx, const Property& prop)
|
||||
{
|
||||
m_vertex_properties[idx] = prop;
|
||||
}
|
||||
|
||||
// Get the size of the properties vector
|
||||
std::size_t size() const
|
||||
{
|
||||
return m_edge_properties.size();
|
||||
}
|
||||
// Access to the derived object
|
||||
Derived& derived() { return *static_cast< Derived* >(this); }
|
||||
|
||||
// Clear the properties vector
|
||||
void clear()
|
||||
{
|
||||
m_edge_properties.clear();
|
||||
}
|
||||
const Derived& derived() const
|
||||
{
|
||||
return *static_cast< const Derived* >(this);
|
||||
}
|
||||
|
||||
// Resize the properties vector
|
||||
void resize(std::size_t n)
|
||||
{
|
||||
m_edge_properties.resize(n);
|
||||
}
|
||||
public: // should be private, but friend templates not portable
|
||||
std::vector< Property > m_vertex_properties;
|
||||
};
|
||||
|
||||
// Reserve space in the vector of properties
|
||||
void reserve(std::size_t n)
|
||||
{
|
||||
m_edge_properties.reserve(n);
|
||||
}
|
||||
template < typename Derived, typename Descriptor, typename IndexMap >
|
||||
class indexed_vertex_properties< Derived, void, Descriptor, IndexMap >
|
||||
{
|
||||
struct secret
|
||||
{
|
||||
};
|
||||
|
||||
// Write an element by raw index
|
||||
void write_by_index(std::size_t idx, const Property& prop)
|
||||
{
|
||||
m_edge_properties[idx] = prop;
|
||||
}
|
||||
public:
|
||||
typedef no_property vertex_property_type;
|
||||
typedef void vertex_bundled;
|
||||
typedef secret vertex_map_type;
|
||||
typedef secret const_vertex_map_type;
|
||||
|
||||
public:
|
||||
// Add a new property value to the back
|
||||
void push_back(const Property& prop)
|
||||
{
|
||||
m_edge_properties.push_back(prop);
|
||||
}
|
||||
secret operator[](secret) { return secret(); }
|
||||
|
||||
// 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));
|
||||
}
|
||||
vertex_map_type get_vertex_bundle() const { return vertex_map_type(); }
|
||||
|
||||
typedef typename std::vector<Property>::iterator iterator;
|
||||
iterator begin() {return m_edge_properties.begin();}
|
||||
iterator end() {return m_edge_properties.end();}
|
||||
protected:
|
||||
// All operations do nothing.
|
||||
indexed_vertex_properties() {}
|
||||
indexed_vertex_properties(std::size_t) {}
|
||||
|
||||
private:
|
||||
// Access to the derived object
|
||||
Derived& derived() { return *static_cast<Derived*>(this); }
|
||||
public:
|
||||
void clear() {}
|
||||
void resize(std::size_t) {}
|
||||
void reserve(std::size_t) {}
|
||||
};
|
||||
|
||||
const Derived& derived() const
|
||||
{ return *static_cast<const Derived*>(this); }
|
||||
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;
|
||||
|
||||
public: // should be private, but friend templates not portable
|
||||
std::vector<Property> m_edge_properties;
|
||||
};
|
||||
// Directly access a edge or edge bundle
|
||||
Property& operator[](Descriptor v)
|
||||
{
|
||||
return m_edge_properties[get(edge_index, derived(), v)];
|
||||
}
|
||||
|
||||
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;}
|
||||
};
|
||||
const Property& operator[](Descriptor v) const
|
||||
{
|
||||
return m_edge_properties[get(edge_index, derived(), v)];
|
||||
}
|
||||
|
||||
template<typename Derived, typename Descriptor, typename IndexMap>
|
||||
class indexed_edge_properties<Derived, void, Descriptor, IndexMap>
|
||||
{
|
||||
struct secret {};
|
||||
edge_map_type get_edge_bundle(const IndexMap& index_map = IndexMap())
|
||||
{
|
||||
return edge_map_type(m_edge_properties.begin(), index_map);
|
||||
}
|
||||
|
||||
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;
|
||||
const_edge_map_type get_edge_bundle(
|
||||
const IndexMap& index_map = IndexMap()) const
|
||||
{
|
||||
return const_edge_map_type(m_edge_properties.begin(), index_map);
|
||||
}
|
||||
|
||||
secret operator[](secret) { return secret(); }
|
||||
void write_by_index(std::size_t /*idx*/, const no_property& /*prop*/) {}
|
||||
protected:
|
||||
// Default-construct with no property values
|
||||
indexed_edge_properties() {}
|
||||
|
||||
edge_map_type get_edge_bundle(const IndexMap& = IndexMap()) const {
|
||||
return edge_map_type();
|
||||
}
|
||||
// Initialize with n default-constructed property values
|
||||
indexed_edge_properties(std::size_t n) : m_edge_properties(n) {}
|
||||
|
||||
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) { }
|
||||
// Get the size of the properties vector
|
||||
std::size_t size() const { return m_edge_properties.size(); }
|
||||
|
||||
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*/) {}
|
||||
// Clear the properties vector
|
||||
void clear() { m_edge_properties.clear(); }
|
||||
|
||||
typedef dummy_no_property_iterator iterator;
|
||||
iterator begin() {return dummy_no_property_iterator();}
|
||||
iterator end() {return dummy_no_property_iterator();}
|
||||
// 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(); }
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,10 +17,14 @@
|
||||
|
||||
#include <boost/mpl/bool.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace detail {
|
||||
template <typename> struct is_distributed_selector: boost::mpl::false_ {};
|
||||
}
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template < typename > struct is_distributed_selector : boost::mpl::false_
|
||||
{
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // BOOST_GRAPH_DETAIL_IS_DISTRIBUTED_SELECTOR_HPP
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
|
||||
#include <boost/graph/graph_mutability_traits.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace boost
|
||||
{
|
||||
|
||||
// Extend the graph mutability traits (and metafunctions) to include options
|
||||
// for labeled graphs.
|
||||
@@ -20,213 +21,207 @@ namespace boost {
|
||||
// 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 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_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
|
||||
{ };
|
||||
: 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
|
||||
{ };
|
||||
: 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_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
|
||||
{ };
|
||||
: 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
|
||||
{ };
|
||||
: virtual labeled_add_vertex_property_tag,
|
||||
virtual labeled_mutable_edge_property_graph_tag
|
||||
{
|
||||
};
|
||||
|
||||
// Metafunctions
|
||||
|
||||
template <typename Graph>
|
||||
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
|
||||
>
|
||||
{ };
|
||||
: mpl::bool_<
|
||||
is_convertible< typename graph_mutability_traits< Graph >::category,
|
||||
labeled_add_vertex_tag >::value >
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Graph>
|
||||
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
|
||||
>
|
||||
{ };
|
||||
: mpl::bool_<
|
||||
is_convertible< typename graph_mutability_traits< Graph >::category,
|
||||
labeled_add_vertex_property_tag >::value >
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Graph>
|
||||
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
|
||||
>
|
||||
{ };
|
||||
: mpl::bool_<
|
||||
is_convertible< typename graph_mutability_traits< Graph >::category,
|
||||
labeled_remove_vertex_tag >::value >
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Graph>
|
||||
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
|
||||
>
|
||||
{ };
|
||||
: mpl::bool_<
|
||||
is_convertible< typename graph_mutability_traits< Graph >::category,
|
||||
labeled_add_edge_tag >::value >
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Graph>
|
||||
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
|
||||
>
|
||||
{ };
|
||||
: mpl::bool_<
|
||||
is_convertible< typename graph_mutability_traits< Graph >::category,
|
||||
labeled_add_edge_property_tag >::value >
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Graph>
|
||||
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
|
||||
>
|
||||
{ };
|
||||
: mpl::bool_<
|
||||
is_convertible< typename graph_mutability_traits< Graph >::category,
|
||||
labeled_remove_edge_tag >::value >
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Graph>
|
||||
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>
|
||||
>
|
||||
{ };
|
||||
: mpl::and_< graph_has_add_vertex_by_label< Graph >,
|
||||
graph_has_remove_vertex_by_label< Graph > >
|
||||
{
|
||||
};
|
||||
|
||||
template <typename 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>
|
||||
>
|
||||
{ };
|
||||
: mpl::and_< graph_has_add_vertex_by_label< Graph >,
|
||||
graph_has_remove_vertex_by_label< Graph > >
|
||||
{
|
||||
};
|
||||
|
||||
template <typename 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>
|
||||
>
|
||||
{ };
|
||||
: mpl::and_< graph_has_add_edge_by_label< Graph >,
|
||||
graph_has_remove_edge_by_label< Graph > >
|
||||
{
|
||||
};
|
||||
|
||||
template <typename 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>
|
||||
>
|
||||
{ };
|
||||
: mpl::and_< graph_has_add_edge_by_label< Graph >,
|
||||
graph_has_remove_edge_by_label< Graph > >
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Graph>
|
||||
template < typename Graph >
|
||||
struct is_labeled_mutable_graph
|
||||
: mpl::and_<
|
||||
is_labeled_mutable_vertex_graph<Graph>,
|
||||
is_labeled_mutable_edge_graph<Graph>
|
||||
>
|
||||
{ };
|
||||
: mpl::and_< is_labeled_mutable_vertex_graph< Graph >,
|
||||
is_labeled_mutable_edge_graph< Graph > >
|
||||
{
|
||||
};
|
||||
|
||||
template <typename 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>
|
||||
>
|
||||
{ };
|
||||
: mpl::and_< is_labeled_mutable_vertex_property_graph< Graph >,
|
||||
is_labeled_mutable_edge_property_graph< Graph > >
|
||||
{
|
||||
};
|
||||
|
||||
template <typename 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
|
||||
>
|
||||
{ };
|
||||
: mpl::bool_<
|
||||
is_convertible< typename graph_mutability_traits< Graph >::category,
|
||||
labeled_add_only_property_graph_tag >::value >
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Graph>
|
||||
template < typename Graph >
|
||||
struct is_labeled_graph
|
||||
: mpl::bool_<
|
||||
is_convertible<
|
||||
typename graph_mutability_traits<Graph>::category,
|
||||
label_vertex_tag
|
||||
>::value
|
||||
>
|
||||
{ };
|
||||
: mpl::bool_<
|
||||
is_convertible< typename graph_mutability_traits< Graph >::category,
|
||||
label_vertex_tag >::value >
|
||||
{
|
||||
};
|
||||
|
||||
template <typename> struct graph_mutability_traits;
|
||||
template < typename > struct graph_mutability_traits;
|
||||
|
||||
namespace graph_detail {
|
||||
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>,
|
||||
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>,
|
||||
typename mpl::if_< is_mutable_property_graph< Graph >,
|
||||
labeled_mutable_property_graph_tag,
|
||||
typename mpl::if_<
|
||||
is_mutable_graph<Graph>,
|
||||
typename mpl::if_< is_mutable_graph< Graph >,
|
||||
labeled_mutable_graph_tag,
|
||||
typename mpl::if_<
|
||||
is_mutable_edge_graph<Graph>,
|
||||
typename mpl::if_< is_mutable_edge_graph< Graph >,
|
||||
labeled_graph_tag,
|
||||
typename graph_mutability_traits<Graph>::category
|
||||
>::type
|
||||
>::type
|
||||
>::type
|
||||
>::type type;
|
||||
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>
|
||||
#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 > {
|
||||
template < LABELED_GRAPH_PARAMS >
|
||||
struct graph_mutability_traits< LABELED_GRAPH >
|
||||
{
|
||||
typedef typename graph_detail::determine_mutability<
|
||||
typename LABELED_GRAPH::graph_type
|
||||
>::type category;
|
||||
typename LABELED_GRAPH::graph_type >::type category;
|
||||
};
|
||||
|
||||
#undef LABELED_GRAPH_PARAMS
|
||||
|
||||
@@ -20,201 +20,187 @@
|
||||
functions that do not require the container object!
|
||||
*/
|
||||
|
||||
namespace boost {
|
||||
namespace detail {
|
||||
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)
|
||||
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;
|
||||
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)
|
||||
template < class Node, class Next >
|
||||
inline Node slist_remove_after(Node pos, Next next)
|
||||
{
|
||||
Node n = next(pos);
|
||||
next(pos) = next(n);
|
||||
return n;
|
||||
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)
|
||||
template < class Node, class Next >
|
||||
inline Node slist_remove_range(Node before_first, Node last, Next next)
|
||||
{
|
||||
next(before_first) = last;
|
||||
return last;
|
||||
next(before_first) = last;
|
||||
return last;
|
||||
}
|
||||
|
||||
template <class Node, class Next>
|
||||
inline Node
|
||||
slist_previous(Node head, Node x, Node empty,
|
||||
Next next)
|
||||
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;
|
||||
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)
|
||||
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;
|
||||
}
|
||||
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)
|
||||
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;
|
||||
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)
|
||||
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;
|
||||
std::size_t s = 0;
|
||||
for (; head != empty; head = next(head))
|
||||
++s;
|
||||
return s;
|
||||
}
|
||||
|
||||
template <class Next, class Data>
|
||||
class slist_iterator_policies
|
||||
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) { }
|
||||
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 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 > void increment(Node& x) const { x = m_next(x); }
|
||||
|
||||
template <class Node>
|
||||
bool equal(Node& x, Node& y) const
|
||||
{ return x == y; }
|
||||
template < class Node > bool equal(Node& x, Node& y) const
|
||||
{
|
||||
return x == y;
|
||||
}
|
||||
|
||||
protected:
|
||||
Next m_next;
|
||||
Data m_data;
|
||||
Next m_next;
|
||||
Data m_data;
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
// Doubly-Linked List Generic Implementation Functions
|
||||
//===========================================================================
|
||||
// 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)
|
||||
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;
|
||||
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)
|
||||
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;
|
||||
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)
|
||||
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;
|
||||
Node i, tmp;
|
||||
i = next(sentinel);
|
||||
while (i != sentinel)
|
||||
{
|
||||
tmp = i;
|
||||
i = next(i);
|
||||
del(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Node, class Next, class Prev>
|
||||
void
|
||||
dlist_transfer(Node pos, Node first, Node last,
|
||||
Next next, Prev prev)
|
||||
template < class Node > inline bool dlist_empty(Node dummy)
|
||||
{
|
||||
if (pos != last) {
|
||||
// Remove [first,last) from its old position
|
||||
next(prev(last)) = pos;
|
||||
next(prev(first)) = last;
|
||||
next(prev(pos)) = first;
|
||||
return next(dummy) == dummy;
|
||||
}
|
||||
|
||||
// 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>
|
||||
template < class Node, class Next, class Prev >
|
||||
void dlist_transfer(Node pos, Node first, Node last, Next next, Prev prev)
|
||||
{
|
||||
typedef slist_iterator_policies<Next, Data> Base;
|
||||
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); }
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
dlist_iterator_policies(Next n, Prev p, Data d)
|
||||
: Base(n,d), m_prev(p) { }
|
||||
protected:
|
||||
Prev m_prev;
|
||||
Prev m_prev;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace detail
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_LIST_BASE_HPP
|
||||
|
||||
16
linx64/include/boost/graph/detail/mpi_include.hpp
Normal file
16
linx64/include/boost/graph/detail/mpi_include.hpp
Normal 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
|
||||
@@ -12,194 +12,200 @@
|
||||
#include <algorithm>
|
||||
#include <boost/graph/detail/shadow_iterator.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace boost
|
||||
{
|
||||
|
||||
template <class Iter1, class Iter2>
|
||||
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:
|
||||
typedef std::ptrdiff_t D :
|
||||
#else
|
||||
typedef typename std::iterator_traits<Iter1>::difference_type D;
|
||||
typedef typename std::iterator_traits< Iter1 >::difference_type D;
|
||||
#endif
|
||||
|
||||
D n = 0;
|
||||
while (permuter != last) {
|
||||
std::swap(result[n], result[*permuter]);
|
||||
++n;
|
||||
++permuter;
|
||||
}
|
||||
D n
|
||||
= 0;
|
||||
while (permuter != last)
|
||||
{
|
||||
std::swap(result[n], result[*permuter]);
|
||||
++n;
|
||||
++permuter;
|
||||
}
|
||||
}
|
||||
|
||||
template <class InIter, class RandIterP, class RandIterR>
|
||||
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;
|
||||
typedef std::ptrdiff_t i = 0;
|
||||
#else
|
||||
typename std::iterator_traits<RandIterP>::difference_type i = 0;
|
||||
typename std::iterator_traits< RandIterP >::difference_type i = 0;
|
||||
#endif
|
||||
for (; first != last; ++first, ++i)
|
||||
result[p[i]] = *first;
|
||||
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)
|
||||
namespace detail
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
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>
|
||||
template < class RandIter, class RandIterPerm >
|
||||
void permute(RandIter first, RandIter last, RandIterPerm p)
|
||||
{
|
||||
detail::permute_helper(first, last, p, last - first, *first);
|
||||
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)
|
||||
template < class PermIter > void invert_permutation(PermIter X, PermIter Xend)
|
||||
{
|
||||
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
|
||||
typedef std::ptrdiff_t T:
|
||||
typedef std::ptrdiff_t T :
|
||||
#else
|
||||
typedef typename std::iterator_traits<PermIter>::value_type T;
|
||||
typedef typename std::iterator_traits< PermIter >::value_type T;
|
||||
#endif
|
||||
T n = Xend - X;
|
||||
T m = n;
|
||||
T j = -1;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
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>
|
||||
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;
|
||||
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;
|
||||
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]);
|
||||
}
|
||||
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>
|
||||
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);
|
||||
}
|
||||
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>
|
||||
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);
|
||||
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>
|
||||
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>());
|
||||
typedef typename std::iterator_traits< IterP >::value_type P;
|
||||
sortp(first, last, p, cmp, std::allocator< P >());
|
||||
}
|
||||
|
||||
template <class Iter, class IterP>
|
||||
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>());
|
||||
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>
|
||||
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);
|
||||
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
|
||||
|
||||
@@ -5,19 +5,19 @@
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
//
|
||||
// read_graphviz_new.hpp -
|
||||
// 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.
|
||||
// DOT Language.
|
||||
//
|
||||
// Based on the grammar found at:
|
||||
// http://www.graphviz.org/cvs/doc/info/lang.html
|
||||
// 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:
|
||||
// See documentation for this code at:
|
||||
// http://www.boost.org/libs/graph/doc/read_graphviz.html
|
||||
//
|
||||
|
||||
@@ -41,66 +41,82 @@
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace boost {
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace read_graphviz_detail {
|
||||
typedef std::string node_name;
|
||||
typedef std::string subgraph_name;
|
||||
namespace read_graphviz_detail
|
||||
{
|
||||
typedef std::string node_name;
|
||||
typedef std::string subgraph_name;
|
||||
|
||||
typedef std::map<std::string, std::string> properties;
|
||||
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
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
};
|
||||
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 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
|
||||
};
|
||||
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);
|
||||
// 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);
|
||||
// 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
|
||||
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);
|
||||
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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -10,19 +10,19 @@
|
||||
#define BOOST_SELF_AVOIDING_WALK_HPP
|
||||
|
||||
/*
|
||||
This file defines necessary components for SAW.
|
||||
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.
|
||||
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
|
||||
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.
|
||||
therefore it is a traingle in mesh.
|
||||
|
||||
*/
|
||||
|
||||
@@ -33,135 +33,161 @@
|
||||
|
||||
#define SAW_SENTINAL -1
|
||||
|
||||
namespace boost {
|
||||
namespace boost
|
||||
{
|
||||
|
||||
template <class T1, class T2, class T3>
|
||||
struct triple {
|
||||
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(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;
|
||||
typedef triple< int, int, int > Triple;
|
||||
|
||||
/* 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> > { };
|
||||
/* 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;
|
||||
|
||||
/*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)
|
||||
{
|
||||
/* 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;
|
||||
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;
|
||||
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;
|
||||
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 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 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;
|
||||
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:
|
||||
};
|
||||
|
||||
/* 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) {}
|
||||
: 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();
|
||||
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:
|
||||
@@ -171,248 +197,287 @@ namespace boost {
|
||||
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);
|
||||
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();
|
||||
get_vertex_sharing< TriangleDecorator, Vertex, Line > get_sharing_line(
|
||||
td);
|
||||
|
||||
iter w_i = iter_d[i];
|
||||
Line tau_i = get_sharing_line(tau, i);
|
||||
|
||||
iter w_i_m_1 = w_i;
|
||||
iter w_i_p_1 = w_i;
|
||||
iter w_end = hlist->end();
|
||||
|
||||
/*----------------------------------------------------------
|
||||
* 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;
|
||||
iter w_i = iter_d[i];
|
||||
|
||||
--w_i_m_1;
|
||||
++w_i_p_1;
|
||||
b = ( w_i->second.first != SAW_SENTINAL );
|
||||
iter w_i_m_1 = w_i;
|
||||
iter w_i_p_1 = w_i;
|
||||
|
||||
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);
|
||||
/*----------------------------------------------------------
|
||||
* 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
|
||||
*----------------------------------------------------------
|
||||
*/
|
||||
|
||||
iter w_i_m_2 = w_i_m_1;
|
||||
--w_i_m_2;
|
||||
bool a = false, b = false;
|
||||
|
||||
bool c = true;
|
||||
|
||||
if ( w_i_m_2 != w_end ) {
|
||||
c = w_i_m_2->second != l1;
|
||||
}
|
||||
--w_i_m_1;
|
||||
++w_i_p_1;
|
||||
b = (w_i->second.first != SAW_SENTINAL);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (w_i_m_1 != w_end)
|
||||
{
|
||||
a = (w_i_m_1->second.first != SAW_SENTINAL);
|
||||
}
|
||||
|
||||
} 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;
|
||||
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:
|
||||
|
||||
protected:
|
||||
TriangleDecorator td; /*a decorator for vertex*/
|
||||
HList hlist;
|
||||
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;
|
||||
|
||||
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
|
||||
*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 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);
|
||||
}
|
||||
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 :(
|
||||
|
||||
// should also have combo's of pointers, and also const :(
|
||||
|
||||
}
|
||||
|
||||
#endif /*BOOST_SAW_H*/
|
||||
|
||||
@@ -9,115 +9,110 @@
|
||||
#include <set>
|
||||
#include <boost/unordered_set.hpp>
|
||||
|
||||
namespace boost {
|
||||
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;
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
// 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)
|
||||
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)
|
||||
{
|
||||
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;
|
||||
return 1;
|
||||
else if (*yi < *xi)
|
||||
return -1;
|
||||
}
|
||||
if (xi == xend)
|
||||
return -1;
|
||||
}
|
||||
if (xi == xend)
|
||||
return (yi == yend) ? 0 : -1;
|
||||
else
|
||||
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 > 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 >
|
||||
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_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, 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_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_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_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 >
|
||||
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>
|
||||
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());
|
||||
}
|
||||
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()));
|
||||
}
|
||||
|
||||
// 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
|
||||
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
|
||||
|
||||
@@ -9,131 +9,175 @@
|
||||
#include <boost/iterator_adaptors.hpp>
|
||||
#include <boost/operators.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail {
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <class A, class B, class D>
|
||||
class shadow_proxy
|
||||
: boost::operators< shadow_proxy<A,B,D> >
|
||||
template < class A, class B, class D >
|
||||
class shadow_proxy : boost::operators< shadow_proxy< A, B, D > >
|
||||
{
|
||||
typedef shadow_proxy self;
|
||||
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;
|
||||
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_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 >
|
||||
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 > 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; }
|
||||
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
|
||||
} // namespace detail
|
||||
|
||||
template < typename IterA, typename IterB > struct shadow_iterator_generator
|
||||
{
|
||||
|
||||
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();
|
||||
};
|
||||
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;
|
||||
};
|
||||
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));
|
||||
}
|
||||
// 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>
|
||||
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);
|
||||
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)
|
||||
{
|
||||
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
|
||||
|
||||
@@ -21,13 +21,14 @@
|
||||
#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 boost
|
||||
{
|
||||
|
||||
namespace sparse {
|
||||
namespace sparse
|
||||
{
|
||||
|
||||
// rcm_queue
|
||||
//
|
||||
@@ -35,164 +36,175 @@ namespace boost {
|
||||
// *_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;
|
||||
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;
|
||||
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) { }
|
||||
/* 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();
|
||||
inline void pop()
|
||||
{
|
||||
if (!_size)
|
||||
Qsize = base::size();
|
||||
|
||||
base::pop();
|
||||
if ( _size == Qsize-1 ) {
|
||||
_size = 0;
|
||||
++eccen;
|
||||
} else
|
||||
++_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 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 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 value_type& top() { return front(); }
|
||||
inline const value_type& top() const { return front(); }
|
||||
inline size_type size() const { return base::size(); }
|
||||
|
||||
inline size_type size() const { return base::size(); }
|
||||
|
||||
inline size_type eccentricity() const { return eccen; }
|
||||
inline value_type spouse() const { return w; }
|
||||
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;
|
||||
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;
|
||||
|
||||
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(); }
|
||||
|
||||
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
|
||||
// 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);
|
||||
} // namespace sparse
|
||||
|
||||
typename boost::graph_traits<Graph>::vertex_iterator ui, ui_end;
|
||||
// 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());
|
||||
if (get(color, *ui) != Color::red())
|
||||
put(color, *ui, Color::white());
|
||||
breadth_first_visit(G, u, buffer(Q).color_map(color));
|
||||
|
||||
ecc = Q.eccentricity();
|
||||
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)
|
||||
{
|
||||
// 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);
|
||||
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> >
|
||||
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);
|
||||
}
|
||||
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;
|
||||
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);
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user