2
0
mirror of https://github.com/boostorg/graph.git synced 2026-02-03 09:12:14 +00:00

Full merge from trunk at revision 41356 of entire boost-root tree.

[SVN r41369]
This commit is contained in:
Beman Dawes
2007-11-25 18:07:19 +00:00
48 changed files with 8130 additions and 1526 deletions

View File

@@ -36,7 +36,10 @@
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/graph_selectors.hpp>
#include <boost/property_map.hpp>
#include <boost/pending/ct_if.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/graph/detail/edge.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/detail/workaround.hpp>
@@ -238,12 +241,12 @@ namespace boost {
namespace detail {
template <class Directed> struct is_random_access {
enum { value = false};
typedef false_type type;
typedef mpl::false_ type;
};
template <>
struct is_random_access<vecS> {
enum { value = true };
typedef true_type type;
typedef mpl::true_ type;
};
} // namespace detail
@@ -259,7 +262,8 @@ namespace boost {
template <class OutEdgeListS = vecS,
class VertexListS = vecS,
class DirectedS = directedS>
class DirectedS = directedS,
class EdgeListS = listS>
struct adjacency_list_traits
{
typedef typename detail::is_random_access<VertexListS>::type
@@ -267,9 +271,9 @@ namespace boost {
typedef typename DirectedS::is_bidir_t is_bidir;
typedef typename DirectedS::is_directed_t is_directed;
typedef typename boost::ct_if_t<is_bidir,
typedef typename mpl::if_<is_bidir,
bidirectional_tag,
typename boost::ct_if_t<is_directed,
typename mpl::if_<is_directed,
directed_tag, undirected_tag
>::type
>::type directed_category;
@@ -278,10 +282,26 @@ namespace boost {
edge_parallel_category;
typedef void* vertex_ptr;
typedef typename boost::ct_if_t<is_rand_access,
typedef typename mpl::if_<is_rand_access,
std::size_t, vertex_ptr>::type vertex_descriptor;
typedef detail::edge_desc_impl<directed_category, vertex_descriptor>
edge_descriptor;
typedef std::size_t vertices_size_type;
private:
// Logic to figure out the edges_size_type
struct dummy {};
typedef typename container_gen<EdgeListS, dummy>::type EdgeContainer;
typedef typename DirectedS::is_bidir_t BidirectionalT;
typedef typename DirectedS::is_directed_t DirectedT;
typedef typename mpl::and_<DirectedT,
typename mpl::not_<BidirectionalT>::type >::type on_edge_storage;
public:
typedef typename mpl::if_<on_edge_storage,
std::size_t, typename EdgeContainer::size_type
>::type edges_size_type;
};
} // namespace boost
@@ -335,10 +355,10 @@ namespace boost {
edge_property_type;
// The types that are actually bundled
typedef typename ct_if<(is_same<maybe_vertex_bundled, no_property>::value),
typedef typename mpl::if_c<(is_same<maybe_vertex_bundled, no_property>::value),
no_vertex_bundle,
maybe_vertex_bundled>::type vertex_bundled;
typedef typename ct_if<(is_same<maybe_edge_bundled, no_property>::value),
typedef typename mpl::if_c<(is_same<maybe_edge_bundled, no_property>::value),
no_edge_bundle,
maybe_edge_bundled>::type edge_bundled;
#else

View File

@@ -19,7 +19,7 @@
#include <boost/iterator.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/graph_selectors.hpp>
#include <boost/pending/ct_if.hpp>
#include <boost/mpl/if.hpp>
#include <boost/graph/adjacency_iterator.hpp>
#include <boost/graph/detail/edge.hpp>
#include <boost/iterator/iterator_adaptor.hpp>
@@ -441,7 +441,7 @@ namespace boost {
BOOST_STATIC_ASSERT(type_traits::ice_not<(is_same<Directed, bidirectionalS>::value)>::value);
#endif
typedef typename boost::ct_if_t<is_directed,
typedef typename mpl::if_<is_directed,
bidirectional_tag, undirected_tag>::type
directed_category;
@@ -497,10 +497,10 @@ namespace boost {
public:
// The types that are actually bundled
typedef typename ct_if<(is_same<maybe_vertex_bundled, no_property>::value),
typedef typename mpl::if_c<(is_same<maybe_vertex_bundled, no_property>::value),
no_vertex_bundle,
maybe_vertex_bundled>::type vertex_bundled;
typedef typename ct_if<(is_same<maybe_edge_bundled, no_property>::value),
typedef typename mpl::if_c<(is_same<maybe_edge_bundled, no_property>::value),
no_edge_bundle,
maybe_edge_bundled>::type edge_bundled;
#else
@@ -511,7 +511,7 @@ namespace boost {
#endif
public: // should be private
typedef typename ct_if_t<typename has_property<edge_property_type>::type,
typedef typename mpl::if_<typename has_property<edge_property_type>::type,
std::pair<bool, edge_property_type>, char>::type StoredEdge;
#if (defined(BOOST_MSVC) && BOOST_MSVC <= 1300) || defined(BOOST_NO_STD_ALLOCATOR)
typedef std::vector<StoredEdge> Matrix;
@@ -545,7 +545,7 @@ namespace boost {
vertex_descriptor, MatrixIter, size_type, edge_descriptor
> UnDirOutEdgeIter;
typedef typename ct_if_t<
typedef typename mpl::if_<
typename Directed::is_directed_t, DirOutEdgeIter, UnDirOutEdgeIter
>::type unfiltered_out_edge_iter;
@@ -557,7 +557,7 @@ namespace boost {
vertex_descriptor, MatrixIter, size_type, edge_descriptor
> UnDirInEdgeIter;
typedef typename ct_if_t<
typedef typename mpl::if_<
typename Directed::is_directed_t, DirInEdgeIter, UnDirInEdgeIter
>::type unfiltered_in_edge_iter;

View File

@@ -417,7 +417,6 @@ namespace detail { namespace graph {
WeightMap weight_map,
VertexIndexMap vertex_index)
{
typedef typename graph_traits<Graph>::degree_size_type degree_size_type;
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
typedef typename mpl::if_c<(is_same<CentralityMap,
@@ -432,7 +431,7 @@ namespace detail { namespace graph {
std::vector<std::vector<edge_descriptor> > incoming(V);
std::vector<centrality_type> distance(V);
std::vector<centrality_type> dependency(V);
std::vector<degree_size_type> path_count(V);
std::vector<unsigned long long> path_count(V);
brandes_betweenness_centrality(
g, centrality, edge_centrality_map,
@@ -453,7 +452,6 @@ namespace detail { namespace graph {
EdgeCentralityMap edge_centrality_map,
VertexIndexMap vertex_index)
{
typedef typename graph_traits<Graph>::degree_size_type degree_size_type;
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
typedef typename mpl::if_c<(is_same<CentralityMap,
@@ -468,7 +466,7 @@ namespace detail { namespace graph {
std::vector<std::vector<edge_descriptor> > incoming(V);
std::vector<centrality_type> distance(V);
std::vector<centrality_type> dependency(V);
std::vector<degree_size_type> path_count(V);
std::vector<unsigned long long> path_count(V);
brandes_betweenness_centrality(
g, centrality, edge_centrality_map,

View File

@@ -0,0 +1,322 @@
//=======================================================================
// Copyright 2007 Aaron Windsor
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
#ifndef __BOYER_MYRVOLD_PLANAR_TEST_HPP__
#define __BOYER_MYRVOLD_PLANAR_TEST_HPP__
#include <boost/graph/planar_detail/boyer_myrvold_impl.hpp>
#include <boost/parameter.hpp>
#include <boost/type_traits.hpp>
#include <boost/mpl/bool.hpp>
namespace boost
{
struct no_kuratowski_subgraph_isolation {};
struct no_planar_embedding {};
namespace boyer_myrvold_params
{
BOOST_PARAMETER_KEYWORD(tag, graph)
BOOST_PARAMETER_KEYWORD(tag, embedding)
BOOST_PARAMETER_KEYWORD(tag, kuratowski_subgraph)
BOOST_PARAMETER_KEYWORD(tag, vertex_index_map)
BOOST_PARAMETER_KEYWORD(tag, edge_index_map)
typedef parameter::parameters< parameter::required<tag::graph>,
tag::embedding,
tag::kuratowski_subgraph,
tag::vertex_index_map,
tag::edge_index_map
> boyer_myrvold_params_t;
namespace core
{
template <typename ArgumentPack>
bool dispatched_boyer_myrvold(ArgumentPack const& args,
mpl::true_,
mpl::true_
)
{
//Dispatch for no planar embedding, no kuratowski subgraph isolation
typedef typename remove_const
<
typename remove_reference
< typename parameter::binding
< ArgumentPack, tag::graph>::type
>::type
>::type graph_t;
typedef typename parameter::binding
< ArgumentPack,
tag::vertex_index_map,
typename property_map
< typename remove_reference<graph_t>::type,
vertex_index_t>::const_type
>::type vertex_index_map_t;
boyer_myrvold_impl
<graph_t,
vertex_index_map_t,
graph::detail::no_old_handles,
graph::detail::no_embedding
>
planarity_tester(args[graph],
args[vertex_index_map |
get(vertex_index, args[graph])
]
);
return planarity_tester.is_planar() ? true : false;
}
template <typename ArgumentPack>
bool dispatched_boyer_myrvold(ArgumentPack const& args,
mpl::true_,
mpl::false_
)
{
//Dispatch for no planar embedding, kuratowski subgraph isolation
typedef typename remove_const
<
typename remove_reference
< typename parameter::binding
< ArgumentPack, tag::graph>::type
>::type
>::type graph_t;
typedef typename parameter::binding
< ArgumentPack,
tag::vertex_index_map,
typename property_map<graph_t, vertex_index_t>::type
>::type vertex_index_map_t;
boyer_myrvold_impl
<graph_t,
vertex_index_map_t,
graph::detail::store_old_handles,
graph::detail::no_embedding
>
planarity_tester(args[graph],
args[vertex_index_map |
get(vertex_index, args[graph])
]
);
if (planarity_tester.is_planar())
return true;
else
{
planarity_tester.extract_kuratowski_subgraph
(args[kuratowski_subgraph],
args[edge_index_map|get(edge_index, args[graph])]
);
return false;
}
}
template <typename ArgumentPack>
bool dispatched_boyer_myrvold(ArgumentPack const& args,
mpl::false_,
mpl::true_
)
{
//Dispatch for planar embedding, no kuratowski subgraph isolation
typedef typename remove_const
<
typename remove_reference
< typename parameter::binding
< ArgumentPack, tag::graph>::type
>::type
>::type graph_t;
typedef typename parameter::binding
< ArgumentPack,
tag::vertex_index_map,
typename property_map<graph_t, vertex_index_t>::type
>::type vertex_index_map_t;
boyer_myrvold_impl
<graph_t,
vertex_index_map_t,
graph::detail::no_old_handles,
#ifdef BOOST_GRAPH_PREFER_STD_LIB
graph::detail::std_list
#else
graph::detail::recursive_lazy_list
#endif
>
planarity_tester(args[graph],
args[vertex_index_map |
get(vertex_index, args[graph])
]
);
if (planarity_tester.is_planar())
{
planarity_tester.make_edge_permutation(args[embedding]);
return true;
}
else
return false;
}
template <typename ArgumentPack>
bool dispatched_boyer_myrvold(ArgumentPack const& args,
mpl::false_,
mpl::false_
)
{
//Dispatch for planar embedding, kuratowski subgraph isolation
typedef typename remove_const
<
typename remove_reference
< typename parameter::binding
< ArgumentPack, tag::graph>::type
>::type
>::type graph_t;
typedef typename parameter::binding
< ArgumentPack,
tag::vertex_index_map,
typename property_map<graph_t, vertex_index_t>::type
>::type vertex_index_map_t;
boyer_myrvold_impl
<graph_t,
vertex_index_map_t,
graph::detail::store_old_handles,
#ifdef BOOST_BGL_PREFER_STD_LIB
graph::detail::std_list
#else
graph::detail::recursive_lazy_list
#endif
>
planarity_tester(args[graph],
args[vertex_index_map |
get(vertex_index, args[graph])
]
);
if (planarity_tester.is_planar())
{
planarity_tester.make_edge_permutation(args[embedding]);
return true;
}
else
{
planarity_tester.extract_kuratowski_subgraph
(args[kuratowski_subgraph],
args[edge_index_map | get(edge_index, args[graph])]
);
return false;
}
}
template <typename ArgumentPack>
bool boyer_myrvold_planarity_test(ArgumentPack const& args)
{
typedef typename parameter::binding
< ArgumentPack,
tag::kuratowski_subgraph,
const no_kuratowski_subgraph_isolation&
>::type
kuratowski_arg_t;
typedef typename parameter::binding
< ArgumentPack,
tag::embedding,
const no_planar_embedding&
>::type
embedding_arg_t;
return dispatched_boyer_myrvold
(args,
boost::is_same
<embedding_arg_t, const no_planar_embedding&>(),
boost::is_same
<kuratowski_arg_t, const no_kuratowski_subgraph_isolation&>()
);
}
} //namespace core
} //namespace boyer_myrvold_params
template <typename A0>
bool boyer_myrvold_planarity_test(A0 const& arg0)
{
return boyer_myrvold_params::core::boyer_myrvold_planarity_test
(boyer_myrvold_params::boyer_myrvold_params_t()(arg0));
}
template <typename A0, typename A1>
// bool boyer_myrvold_planarity_test(A0 const& arg0, A1 const& arg1)
bool boyer_myrvold_planarity_test(A0 const& arg0, A1 const& arg1)
{
return boyer_myrvold_params::core::boyer_myrvold_planarity_test
(boyer_myrvold_params::boyer_myrvold_params_t()(arg0,arg1));
}
template <typename A0, typename A1, typename A2>
bool boyer_myrvold_planarity_test(A0 const& arg0,
A1 const& arg1,
A2 const& arg2
)
{
return boyer_myrvold_params::core::boyer_myrvold_planarity_test
(boyer_myrvold_params::boyer_myrvold_params_t()(arg0,arg1,arg2));
}
template <typename A0, typename A1, typename A2, typename A3>
bool boyer_myrvold_planarity_test(A0 const& arg0,
A1 const& arg1,
A2 const& arg2,
A3 const& arg3
)
{
return boyer_myrvold_params::core::boyer_myrvold_planarity_test
(boyer_myrvold_params::boyer_myrvold_params_t()(arg0,arg1,arg2,arg3));
}
template <typename A0, typename A1, typename A2, typename A3, typename A4>
bool boyer_myrvold_planarity_test(A0 const& arg0,
A1 const& arg1,
A2 const& arg2,
A3 const& arg3,
A4 const& arg4
)
{
return boyer_myrvold_params::core::boyer_myrvold_planarity_test
(boyer_myrvold_params::boyer_myrvold_params_t()
(arg0,arg1,arg2,arg3,arg4)
);
}
}
#endif //__BOYER_MYRVOLD_PLANAR_TEST_HPP__

View File

@@ -0,0 +1,270 @@
//=======================================================================
// Copyright (c) Aaron Windsor 2007
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
#ifndef __CHROBAK_PAYNE_DRAWING_HPP__
#define __CHROBAK_PAYNE_DRAWING_HPP__
#include <vector>
#include <list>
#include <boost/config.hpp>
#include <boost/utility.hpp> //for next and prior
#include <boost/graph/graph_traits.hpp>
#include <boost/property_map.hpp>
namespace boost
{
namespace graph { namespace detail
{
template<typename Graph,
typename VertexToVertexMap,
typename VertexTo1DCoordMap>
void accumulate_offsets(typename graph_traits<Graph>::vertex_descriptor v,
std::size_t offset,
const Graph& g,
VertexTo1DCoordMap x,
VertexTo1DCoordMap delta_x,
VertexToVertexMap left,
VertexToVertexMap right)
{
if (v != graph_traits<Graph>::null_vertex())
{
x[v] += delta_x[v] + offset;
accumulate_offsets(left[v], x[v], g, x, delta_x, left, right);
accumulate_offsets(right[v], x[v], g, x, delta_x, left, right);
}
}
} /*namespace detail*/ } /*namespace graph*/
template<typename Graph,
typename PlanarEmbedding,
typename ForwardIterator,
typename GridPositionMap,
typename VertexIndexMap>
void chrobak_payne_straight_line_drawing(const Graph& g,
PlanarEmbedding embedding,
ForwardIterator ordering_begin,
ForwardIterator ordering_end,
GridPositionMap drawing,
VertexIndexMap vm
)
{
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
typedef typename PlanarEmbedding::value_type::const_iterator
edge_permutation_iterator_t;
typedef typename graph_traits<Graph>::vertices_size_type v_size_t;
typedef std::vector<vertex_t> vertex_vector_t;
typedef std::vector<v_size_t> vsize_vector_t;
typedef std::vector<bool> bool_vector_t;
typedef boost::iterator_property_map
<typename vertex_vector_t::iterator, VertexIndexMap>
vertex_to_vertex_map_t;
typedef boost::iterator_property_map
<typename vsize_vector_t::iterator, VertexIndexMap>
vertex_to_vsize_map_t;
typedef boost::iterator_property_map
<typename bool_vector_t::iterator, VertexIndexMap>
vertex_to_bool_map_t;
vertex_vector_t left_vector(num_vertices(g),
graph_traits<Graph>::null_vertex()
);
vertex_vector_t right_vector(num_vertices(g),
graph_traits<Graph>::null_vertex()
);
vsize_vector_t seen_as_right_vector(num_vertices(g), 0);
vsize_vector_t seen_vector(num_vertices(g), 0);
vsize_vector_t delta_x_vector(num_vertices(g),0);
vsize_vector_t y_vector(num_vertices(g));
vsize_vector_t x_vector(num_vertices(g),0);
bool_vector_t installed_vector(num_vertices(g),false);
vertex_to_vertex_map_t left(left_vector.begin(), vm);
vertex_to_vertex_map_t right(right_vector.begin(), vm);
vertex_to_vsize_map_t seen_as_right(seen_as_right_vector.begin(), vm);
vertex_to_vsize_map_t seen(seen_vector.begin(), vm);
vertex_to_vsize_map_t delta_x(delta_x_vector.begin(), vm);
vertex_to_vsize_map_t y(y_vector.begin(), vm);
vertex_to_vsize_map_t x(x_vector.begin(), vm);
vertex_to_bool_map_t installed(installed_vector.begin(), vm);
v_size_t timestamp = 1;
vertex_vector_t installed_neighbors;
ForwardIterator itr = ordering_begin;
vertex_t v1 = *itr; ++itr;
vertex_t v2 = *itr; ++itr;
vertex_t v3 = *itr; ++itr;
delta_x[v2] = 1;
delta_x[v3] = 1;
y[v1] = 0;
y[v2] = 0;
y[v3] = 1;
right[v1] = v3;
right[v3] = v2;
installed[v1] = installed[v2] = installed[v3] = true;
for(ForwardIterator itr_end = ordering_end; itr != itr_end; ++itr)
{
vertex_t v = *itr;
// First, find the leftmost and rightmost neighbor of v on the outer
// cycle of the embedding.
// Note: since we're moving clockwise through the edges adjacent to v,
// we're actually moving from right to left among v's neighbors on the
// outer face (since v will be installed above them all) looking for
// the leftmost and rightmost installed neigbhors
vertex_t leftmost = graph_traits<Graph>::null_vertex();
vertex_t rightmost = graph_traits<Graph>::null_vertex();
installed_neighbors.clear();
vertex_t prev_vertex = graph_traits<Graph>::null_vertex();
edge_permutation_iterator_t pi, pi_end;
pi_end = embedding[v].end();
for(pi = embedding[v].begin(); pi != pi_end; ++pi)
{
vertex_t curr_vertex = source(*pi,g) == v ?
target(*pi,g) : source(*pi,g);
// Skip any self-loops or parallel edges
if (curr_vertex == v || curr_vertex == prev_vertex)
continue;
if (installed[curr_vertex])
{
seen[curr_vertex] = timestamp;
if (right[curr_vertex] != graph_traits<Graph>::null_vertex())
{
seen_as_right[right[curr_vertex]] = timestamp;
}
installed_neighbors.push_back(curr_vertex);
}
prev_vertex = curr_vertex;
}
typename vertex_vector_t::iterator vi, vi_end;
vi_end = installed_neighbors.end();
for(vi = installed_neighbors.begin(); vi != vi_end; ++vi)
{
if (right[*vi] == graph_traits<Graph>::null_vertex() ||
seen[right[*vi]] != timestamp
)
rightmost = *vi;
if (seen_as_right[*vi] != timestamp)
leftmost = *vi;
}
++timestamp;
//stretch gaps
++delta_x[right[leftmost]];
++delta_x[rightmost];
//adjust offsets
std::size_t delta_p_q = 0;
vertex_t stopping_vertex = right[rightmost];
for(vertex_t temp = right[leftmost]; temp != stopping_vertex;
temp = right[temp]
)
{
delta_p_q += delta_x[temp];
}
delta_x[v] = (y[rightmost] - y[leftmost] + delta_p_q)/2;
y[v] = (y[rightmost] + y[leftmost] + delta_p_q)/2;
delta_x[rightmost] = delta_p_q - delta_x[v];
bool leftmost_and_rightmost_adjacent = right[leftmost] == rightmost;
if (!leftmost_and_rightmost_adjacent)
delta_x[right[leftmost]] -= delta_x[v];
//install v
if (!leftmost_and_rightmost_adjacent)
{
left[v] = right[leftmost];
vertex_t next_to_rightmost;
for(vertex_t temp = leftmost; temp != rightmost;
temp = right[temp]
)
{
next_to_rightmost = temp;
}
right[next_to_rightmost] = graph_traits<Graph>::null_vertex();
}
else
{
left[v] = graph_traits<Graph>::null_vertex();
}
right[leftmost] = v;
right[v] = rightmost;
installed[v] = true;
}
graph::detail::accumulate_offsets
(*ordering_begin,0,g,x,delta_x,left,right);
vertex_iterator_t vi, vi_end;
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
{
vertex_t v(*vi);
drawing[v].x = x[v];
drawing[v].y = y[v];
}
}
template<typename Graph,
typename PlanarEmbedding,
typename ForwardIterator,
typename GridPositionMap>
inline void chrobak_payne_straight_line_drawing(const Graph& g,
PlanarEmbedding embedding,
ForwardIterator ord_begin,
ForwardIterator ord_end,
GridPositionMap drawing
)
{
chrobak_payne_straight_line_drawing(g,
embedding,
ord_begin,
ord_end,
drawing,
get(vertex_index,g)
);
}
} // namespace boost
#endif //__CHROBAK_PAYNE_DRAWING_HPP__

View File

@@ -739,7 +739,7 @@ private:
typedef graph_traits<BOOST_CSR_GRAPH_TYPE> traits;
typedef VertexProperty vertex_bundled;
typedef EdgeProperty edge_bundled;
typedef typename ct_if<(detail::is_vertex_bundle<vertex_bundled, edge_bundled, Bundle>::value),
typedef typename mpl::if_c<(detail::is_vertex_bundle<vertex_bundled, edge_bundled, Bundle>::value),
typename traits::vertex_descriptor,
typename traits::edge_descriptor>::type
descriptor;

View File

@@ -24,7 +24,9 @@
#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/pending/ct_if.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/and.hpp>
#include <boost/graph/graph_concepts.hpp>
#include <boost/pending/container_traits.hpp>
#include <boost/graph/detail/adj_list_edge_iterator.hpp>
@@ -63,6 +65,11 @@
*/
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
// Stay out of the way of the concept checking class
# define Graph Graph_
#endif
namespace boost {
namespace detail {
@@ -2268,7 +2275,7 @@ namespace boost {
typedef typename container_gen<VertexListS,
vertex_ptr>::type SeqVertexList;
typedef boost::integer_range<std::size_t> RandVertexList;
typedef typename boost::ct_if_t<is_rand_access,
typedef typename mpl::if_<is_rand_access,
RandVertexList, SeqVertexList>::type VertexList;
typedef typename VertexList::iterator vertex_iterator;
@@ -2278,10 +2285,10 @@ namespace boost {
typedef typename container_gen<EdgeListS,
list_edge<vertex_descriptor, EdgeProperty> >::type EdgeContainer;
typedef typename ct_and<DirectedT,
typename ct_not<BidirectionalT>::type >::type on_edge_storage;
typedef typename mpl::and_<DirectedT,
typename mpl::not_<BidirectionalT>::type >::type on_edge_storage;
typedef typename boost::ct_if_t<on_edge_storage,
typedef typename mpl::if_<on_edge_storage,
std::size_t, typename EdgeContainer::size_type
>::type edges_size_type;
@@ -2289,9 +2296,9 @@ namespace boost {
typedef typename detail::is_random_access<EdgeListS>::type is_edge_ra;
typedef typename boost::ct_if_t<on_edge_storage,
typedef typename mpl::if_<on_edge_storage,
stored_edge_property<vertex_descriptor, EdgeProperty>,
typename boost::ct_if_t<is_edge_ra,
typename mpl::if_<is_edge_ra,
stored_ra_edge_iter<vertex_descriptor, EdgeContainer, EdgeProperty>,
stored_edge_iter<vertex_descriptor, EdgeIter, EdgeProperty>
>::type
@@ -2342,7 +2349,7 @@ namespace boost {
typedef adj_list_edge_iterator<vertex_iterator, out_edge_iterator,
graph_type> DirectedEdgeIter;
typedef typename boost::ct_if_t<on_edge_storage,
typedef typename mpl::if_<on_edge_storage,
DirectedEdgeIter, UndirectedEdgeIter>::type edge_iterator;
// stored_vertex and StoredVertexList
@@ -2376,10 +2383,10 @@ namespace boost {
InEdgeList m_in_edges;
VertexProperty m_property;
};
typedef typename boost::ct_if_t<is_rand_access,
typename boost::ct_if_t<BidirectionalT,
typedef typename mpl::if_<is_rand_access,
typename mpl::if_<BidirectionalT,
bidir_rand_stored_vertex, rand_stored_vertex>::type,
typename boost::ct_if_t<BidirectionalT,
typename mpl::if_<BidirectionalT,
bidir_seq_stored_vertex, seq_stored_vertex>::type
>::type StoredVertex;
struct stored_vertex : public StoredVertex {
@@ -2389,20 +2396,20 @@ namespace boost {
typedef typename container_gen<VertexListS, stored_vertex>::type
RandStoredVertexList;
typedef typename boost::ct_if_t< is_rand_access,
typedef typename mpl::if_< is_rand_access,
RandStoredVertexList, SeqStoredVertexList>::type StoredVertexList;
}; // end of config
typedef typename boost::ct_if_t<BidirectionalT,
typedef typename mpl::if_<BidirectionalT,
bidirectional_graph_helper_with_property<config>,
typename boost::ct_if_t<DirectedT,
typename mpl::if_<DirectedT,
directed_graph_helper<config>,
undirected_graph_helper<config>
>::type
>::type DirectedHelper;
typedef typename boost::ct_if_t<is_rand_access,
typedef typename mpl::if_<is_rand_access,
vec_adj_list_impl<Graph, config, DirectedHelper>,
adj_list_impl<Graph, config, DirectedHelper>
>::type type;
@@ -2807,6 +2814,11 @@ namespace BOOST_STD_EXTENSION_NAMESPACE {
#undef stored_edge_property
#undef stored_edge_iter
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
// Stay out of the way of the concept checking class
#undef Graph
#endif
#endif // BOOST_GRAPH_DETAIL_DETAIL_ADJACENCY_LIST_CCT
/*

View File

@@ -1,910 +0,0 @@
//=======================================================================
// Copyright 2001 Jeremy G. Siek
// Authors: Jeremy G. Siek
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
/*
* Copyright (c) 1998
* Silicon Graphics Computer Systems, Inc.
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Silicon Graphics makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*/
#include <boost/config.hpp>
#include <memory>
#include <stdexcept>
#include <algorithm>
#include <string>
#include <boost/config.hpp>
#include <boost/pending/ct_if.hpp>
#include <boost/graph/detail/bitset_adaptor.hpp>
// This provides versions of std::bitset with both static and dynamic size.
// UNDER CONSTRUCTION
// replace this later
#include <cassert>
#define BOOST_ASSERT_THROW(expr, except) assert(expr)
namespace boost {
namespace detail {
// structure to aid in counting bits
template<bool dummy = true>
struct bit_count {
static unsigned char value[256];
};
// Mapping from 8 bit unsigned integers to the index of the first bit
template<bool dummy = true>
struct first_bit_location {
static unsigned char value[256];
};
template <typename WordType> // this size is in bits
struct word_traits {
typedef WordType word_type;
static const std::size_t word_size = CHAR_BIT * sizeof(word_type);
};
//=========================================================================
template <class WordTraits, class SizeType, class Derived>
class bitset_base
: public bitset_adaptor< SizeType,
bitset_base<WordTraits, SizeType, Derived> >
{
// private:
public:
typedef SizeType size_type;
typedef typename WordTraits::word_type word_type;
static size_type s_which_word(size_type pos) {
return pos / WordTraits::word_size;
}
static size_type s_which_byte(size_type pos) {
return (pos % WordTraits::word_size) / CHAR_BIT;
}
static size_type s_which_bit(size_type pos) {
return pos % WordTraits::word_size;
}
static word_type s_mask_bit(size_type pos) {
return (static_cast<word_type>(1)) << s_which_bit(pos);
}
word_type& m_get_word(size_type pos) {
return data()[s_which_word(pos)];
}
word_type m_get_word(size_type pos) const {
return data()[s_which_word(pos)];
}
word_type& m_hi_word() { return data()[num_words() - 1]; }
word_type m_hi_word() const { return data()[num_words() - 1]; }
void m_sanitize_highest() {
size_type extra_bits = size() % WordTraits::word_size;
if (extra_bits)
m_hi_word() &= ~((~static_cast<word_type>(0)) << extra_bits);
}
public:
class reference {
friend class bitset_base;
word_type *m_word_ptr;
size_type m_bit_pos;
// left undefined
reference();
reference(bitset_base& b, size_type pos ) {
m_word_ptr = &b.m_get_word(pos);
m_bit_pos = s_which_bit(pos);
}
public:
~reference() {}
// for b[i] = x;
reference& operator=(bool x) {
if ( x )
*m_word_ptr |= s_mask_bit(m_bit_pos);
else
*m_word_ptr &= ~s_mask_bit(m_bit_pos);
return *this;
}
// for b[i] = b[j];
reference& operator=(const reference& j) {
if ( (*(j.m_word_ptr) & s_mask_bit(j.m_bit_pos)) )
*m_word_ptr |= s_mask_bit(m_bit_pos);
else
*m_word_ptr &= ~s_mask_bit(m_bit_pos);
return *this;
}
// flips the bit
bool operator~() const {
return (*(m_word_ptr) & s_mask_bit(m_bit_pos)) == 0;
}
// for x = b[i];
operator bool() const {
return (*(m_word_ptr) & s_mask_bit(m_bit_pos)) != 0;
}
// for b[i].flip();
reference& flip() {
*m_word_ptr ^= s_mask_bit(m_bit_pos);
return *this;
}
};
void init_from_ulong(unsigned long val) {
reset();
const size_type n = (std::min)(sizeof(unsigned long) * CHAR_BIT,
WordTraits::word_size * num_words());
for(size_type i = 0; i < n; ++i, val >>= 1)
if ( val & 0x1 )
m_get_word(i) |= s_mask_bit(i);
}
// intersection: this = this & x
Derived& operator&=(const Derived& x) {
for (size_type i = 0; i < num_words(); ++i)
data()[i] &= x.data()[i];
return static_cast<Derived&>(*this);
}
// union: this = this | x
Derived& operator|=(const Derived& x) {
for (size_type i = 0; i < num_words(); ++i)
data()[i] |= x.data()[i];
return static_cast<Derived&>(*this);
}
// exclusive or: this = this ^ x
Derived& operator^=(const Derived& x) {
for (size_type i = 0; i < num_words(); ++i)
data()[i] ^= x.data()[i];
return static_cast<Derived&>(*this);
}
// left shift
Derived& operator<<=(size_type pos);
// right shift
Derived& operator>>=(size_type pos);
Derived& set() {
for (size_type i = 0; i < num_words(); ++i)
data()[i] = ~static_cast<word_type>(0);
m_sanitize_highest();
return static_cast<Derived&>(*this);
}
Derived& set(size_type pos, int val = true)
{
BOOST_ASSERT_THROW(pos < size(), std::out_of_range("boost::bitset::set(pos,value)"));
if (val)
m_get_word(pos) |= s_mask_bit(pos);
else
m_get_word(pos) &= ~s_mask_bit(pos);
return static_cast<Derived&>(*this);
}
Derived& reset() {
for (size_type i = 0; i < num_words(); ++i)
data()[i] = 0;
return static_cast<Derived&>(*this);
}
Derived& reset(size_type pos) {
BOOST_ASSERT_THROW(pos < size(), std::out_of_range("boost::bitset::reset(pos)"));
m_get_word(pos) &= ~s_mask_bit(pos);
return static_cast<Derived&>(*this);
}
// compliment
Derived operator~() const {
return Derived(static_cast<const Derived&>(*this)).flip();
}
Derived& flip() {
for (size_type i = 0; i < num_words(); ++i)
data()[i] = ~data()[i];
m_sanitize_highest();
return static_cast<Derived&>(*this);
}
Derived& flip(size_type pos) {
BOOST_ASSERT_THROW(pos < size(), std::out_of_range("boost::bitset::flip(pos)"));
m_get_word(pos) ^= s_mask_bit(pos);
return static_cast<Derived&>(*this);
}
// element access
reference operator[](size_type pos) { return reference(*this, pos); }
bool operator[](size_type pos) const { return test(pos); }
unsigned long to_ulong() const;
// to_string
size_type count() const {
size_type result = 0;
const unsigned char* byte_ptr = (const unsigned char*)data();
const unsigned char* end_ptr =
(const unsigned char*)(data() + num_words());
while ( byte_ptr < end_ptr ) {
result += bit_count<>::value[*byte_ptr];
byte_ptr++;
}
return result;
}
// size() must be provided by Derived class
bool operator==(const Derived& x) const {
return std::equal(data(), data() + num_words(), x.data());
}
bool operator!=(const Derived& x) const {
return ! this->operator==(x);
}
bool test(size_type pos) const {
BOOST_ASSERT_THROW(pos < size(), std::out_of_range("boost::bitset::test(pos)"));
return (m_get_word(pos) & s_mask_bit(pos))
!= static_cast<word_type>(0);
}
bool any() const {
for (size_type i = 0; i < num_words(); ++i) {
if ( data()[i] != static_cast<word_type>(0) )
return true;
}
return false;
}
bool none() const {
return !any();
}
Derived operator<<(size_type pos) const
{ return Derived(static_cast<const Derived&>(*this)) <<= pos; }
Derived operator>>(size_type pos) const
{ return Derived(static_cast<const Derived&>(*this)) >>= pos; }
template <class CharT, class Traits, class Alloc>
void m_copy_from_string(const basic_string<CharT,Traits,Alloc>& s,
size_type pos, size_type n)
{
reset();
const size_type nbits = (std::min)(size(), (std::min)(n, s.size() - pos));
for (size_type i = 0; i < nbits; ++i) {
switch(s[pos + nbits - i - 1]) {
case '0':
break;
case '1':
this->set(i);
break;
default:
throw std::invalid_argument
("boost::bitset_base::m_copy_from_string(s, pos, n)");
}
}
}
template <class CharT, class Traits, class Alloc>
void m_copy_to_string(basic_string<CharT, Traits, Alloc>& s) const
{
s.assign(size(), '0');
for (size_type i = 0; i < size(); ++i)
if (test(i))
s[size() - 1 - i] = '1';
}
//-----------------------------------------------------------------------
// Stuff not in std::bitset
// difference: this = this - x
Derived& operator-=(const Derived& x) {
for (size_type i = 0; i < num_words(); ++i)
data()[i] &= ~x.data()[i];
return static_cast<Derived&>(*this);
}
// this wasn't working, why?
int compare_3way(const Derived& x) const {
return std::lexicographical_compare_3way
(data(), data() + num_words(), x.data(), x.data() + x.num_words());
}
// less-than compare
bool operator<(const Derived& x) const {
return std::lexicographical_compare
(data(), data() + num_words(), x.data(), x.data() + x.num_words());
}
// find the index of the first "on" bit
size_type find_first() const;
// find the index of the next "on" bit after prev
size_type find_next(size_type prev) const;
size_type _Find_first() const { return find_first(); }
// find the index of the next "on" bit after prev
size_type _Find_next(size_type prev) const { return find_next(prev); }
// private:
word_type* data()
{ return static_cast<Derived*>(this)->data(); }
const word_type* data() const
{ return static_cast<const Derived*>(this)->data(); }
size_type num_words() const
{ return static_cast<const Derived*>(this)->num_words(); }
size_type size() const
{ return static_cast<const Derived*>(this)->size(); }
};
// 23.3.5.3 bitset operations:
template <class W, class S, class D>
inline D operator&(const bitset_base<W,S,D>& x,
const bitset_base<W,S,D>& y) {
D result(static_cast<const D&>(x));
result &= static_cast<const D&>(y);
return result;
}
template <class W, class S, class D>
inline D operator|(const bitset_base<W,S,D>& x,
const bitset_base<W,S,D>& y) {
D result(static_cast<const D&>(x));
result |= static_cast<const D&>(y);
return result;
}
template <class W, class S, class D>
inline D operator^(const bitset_base<W,S,D>& x,
const bitset_base<W,S,D>& y) {
D result(static_cast<const D&>(x));
result ^= static_cast<const D&>(y);
return result;
}
// this one is an extension
template <class W, class S, class D>
inline D operator-(const bitset_base<W,S,D>& x,
const bitset_base<W,S,D>& y) {
D result(static_cast<const D&>(x));
result -= static_cast<const D&>(y);
return result;
}
template <class W, class S, class D>
inline int compare_3way(const bitset_base<W,S,D>& x,
const bitset_base<W,S,D>& y) {
return std::lexicographical_compare_3way
(x.data(), x.data() + x.num_words(),
y.data(), y.data() + y.num_words());
}
template <class W, class S, class D>
std::istream&
operator>>(std::istream& is, bitset_base<W,S,D>& x) {
std::string tmp;
tmp.reserve(x.size());
// In new templatized iostreams, use istream::sentry
if (is.flags() & ios::skipws) {
char c;
do
is.get(c);
while (is && isspace(c));
if (is)
is.putback(c);
}
for (S i = 0; i < x.size(); ++i) {
char c;
is.get(c);
if (!is)
break;
else if (c != '0' && c != '1') {
is.putback(c);
break;
}
else
// tmp.push_back(c);
tmp += c;
}
if (tmp.empty())
is.clear(is.rdstate() | ios::failbit);
else
x.m_copy_from_string(tmp, static_cast<S>(0), x.size());
return is;
}
template <class W, class S, class D>
std::ostream& operator<<(std::ostream& os,
const bitset_base<W,S,D>& x) {
std::string tmp;
x.m_copy_to_string(tmp);
return os << tmp;
}
//=========================================================================
template <typename WordType = unsigned long,
typename SizeType = std::size_t,
typename Allocator = std::allocator<WordType>
>
class dyn_size_bitset
: public bitset_base<word_traits<WordType>, SizeType,
dyn_size_bitset<WordType,SizeType,Allocator> >
{
typedef dyn_size_bitset self;
public:
typedef SizeType size_type;
private:
typedef word_traits<WordType> WordTraits;
static const size_type word_size = WordTraits::word_size;
public:
dyn_size_bitset(unsigned long val,
size_type n,
const Allocator& alloc = Allocator())
: m_data(alloc.allocate((n + word_size - 1) / word_size)),
m_size(n),
m_num_words((n + word_size - 1) / word_size),
m_alloc(alloc)
{
init_from_ulong(val);
}
dyn_size_bitset(size_type n, // size of the set's "universe"
const Allocator& alloc = Allocator())
: m_data(alloc.allocate((n + word_size - 1) / word_size)),
m_size(n), m_num_words((n + word_size - 1) / word_size),
m_alloc(alloc)
{ }
template<class CharT, class Traits, class Alloc>
explicit dyn_size_bitset
(const basic_string<CharT,Traits,Alloc>& s,
std::size_t pos = 0,
std::size_t n = std::size_t(basic_string<CharT,Traits,Alloc>::npos),
const Allocator& alloc = Allocator())
: m_data(alloc.allocate((n + word_size - 1) / word_size)),
m_size(n), m_num_words((n + word_size - 1) / word_size),
m_alloc(alloc)
{
BOOST_ASSERT_THROW(pos < s.size(), std::out_of_range("dyn_size_bitset::dyn_size_bitset(s,pos,n,alloc)"));
m_copy_from_string(s, pos, n);
}
template <typename InputIterator>
explicit dyn_size_bitset
(InputIterator first, InputIterator last,
size_type n, // size of the set's "universe"
const Allocator& alloc = Allocator())
: m_data(alloc.allocate((n + word_size - 1) / word_size)),
m_size(N), m_num_words((n + word_size - 1) / word_size),
m_alloc(alloc)
{
while (first != last)
this->set(*first++);
}
~dyn_size_bitset() {
m_alloc.deallocate(m_data, m_num_words);
}
size_type size() const { return m_size; }
// protected:
size_type num_words() const { return m_num_words; }
word_type* data() { return m_data; }
const word_type* data() const { return m_data; }
protected:
word_type* m_data;
SizeType m_size;
SizeType m_num_words;
Allocator m_alloc;
};
//=========================================================================
template <std::size_t N, typename WordType = unsigned long,
typename SizeType = std::size_t>
class bitset
: public bitset_base<word_traits<WordType>, SizeType,
bitset<N, WordType, SizeType> >
{
typedef bitset self;
static const std::size_t word_size = word_traits<WordType>::word_size;
public:
// 23.3.5.1 constructors:
bitset() {
#if defined(__GNUC__)
for (size_type i = 0; i < num_words(); ++i)
m_data[i] = static_cast<WordType>(0);
#endif
}
bitset(unsigned long val) {
init_from_ulong(val);
}
template<class CharT, class Traits, class Alloc>
explicit bitset
(const basic_string<CharT,Traits,Alloc>& s,
std::size_t pos = 0,
std::size_t n = std::size_t(basic_string<CharT,Traits,Alloc>::npos))
{
BOOST_ASSERT_THROW
(pos < s.size(), std::out_of_range("bitset::bitset(s,pos,n)"));
m_copy_from_string(s, pos, n);
}
size_type size() const { return N; }
// protected:
size_type num_words() const { return (N + word_size - 1) / word_size; }
word_type* data() { return m_data; }
const word_type* data() const { return m_data; }
protected:
word_type m_data[(N + word_size - 1) / word_size];
};
//=========================================================================
struct select_static_bitset {
template <std::size_t N, typename WordT, typename SizeT, typename Alloc>
struct bind_ {
typedef bitset<N, WordT, SizeT> type;
};
};
struct select_dyn_size_bitset {
template <std::size_t N, typename WordT, typename SizeT, typename Alloc>
struct bind_ {
typedef dyn_size_bitset<WordT, SizeT, Alloc> type;
};
};
template <std::size_t N = 0, // 0 means use dynamic
typename WordType = unsigned long,
typename Size_type = std::size_t,
typename Allocator = std::allocator<WordType>
>
class bitset_generator {
typedef typename ct_if<N, select_dyn_size_bitset,
select_static_bitset>::type selector;
public:
typedef typename selector
::template bind_<N, WordType, SizeType, Allocator>::type type;
};
//=========================================================================
// bitset_base non-inline member function implementations
template <class WordTraits, class SizeType, class Derived>
Derived&
bitset_base<WordTraits, SizeType, Derived>::
operator<<=(size_type shift)
{
typedef typename WordTraits::word_type word_type;
typedef SizeType size_type;
if (shift != 0) {
const size_type wshift = shift / WordTraits::word_size;
const size_type offset = shift % WordTraits::word_size;
const size_type sub_offset = WordTraits::word_size - offset;
size_type n = num_words() - 1;
for ( ; n > wshift; --n)
data()[n] = (data()[n - wshift] << offset) |
(data()[n - wshift - 1] >> sub_offset);
if (n == wshift)
data()[n] = data()[0] << offset;
for (size_type n1 = 0; n1 < n; ++n1)
data()[n1] = static_cast<word_type>(0);
}
m_sanitize_highest();
return static_cast<Derived&>(*this);
} // end operator<<=
template <class WordTraits, class SizeType, class Derived>
Derived&
bitset_base<WordTraits, SizeType, Derived>::
operator>>=(size_type shift)
{
typedef typename WordTraits::word_type word_type;
typedef SizeType size_type;
if (shift != 0) {
const size_type wshift = shift / WordTraits::word_size;
const size_type offset = shift % WordTraits::word_size;
const size_type sub_offset = WordTraits::word_size - offset;
const size_type limit = num_words() - wshift - 1;
size_type n = 0;
for ( ; n < limit; ++n)
data()[n] = (data()[n + wshift] >> offset) |
(data()[n + wshift + 1] << sub_offset);
data()[limit] = data()[num_words()-1] >> offset;
for (size_type n1 = limit + 1; n1 < num_words(); ++n1)
data()[n1] = static_cast<word_type>(0);
}
m_sanitize_highest();
return static_cast<Derived&>(*this);
} // end operator>>=
template <class WordTraits, class SizeType, class Derived>
unsigned long bitset_base<WordTraits, SizeType, Derived>::
to_ulong() const
{
typedef typename WordTraits::word_type word_type;
typedef SizeType size_type;
const std::overflow_error
overflow("boost::bit_set::operator unsigned long()");
if (sizeof(word_type) >= sizeof(unsigned long)) {
for (size_type i = 1; i < num_words(); ++i)
BOOST_ASSERT_THROW(! data()[i], overflow);
const word_type mask
= static_cast<word_type>(static_cast<unsigned long>(-1));
BOOST_ASSERT_THROW(! (data()[0] & ~mask), overflow);
return static_cast<unsigned long>(data()[0] & mask);
}
else { // sizeof(word_type) < sizeof(unsigned long).
const size_type nwords =
(sizeof(unsigned long) + sizeof(word_type) - 1) / sizeof(word_type);
size_type min_nwords = nwords;
if (num_words() > nwords) {
for (size_type i = nwords; i < num_words(); ++i)
BOOST_ASSERT_THROW(!data()[i], overflow);
}
else
min_nwords = num_words();
// If unsigned long is 8 bytes and word_type is 6 bytes, then
// an unsigned long consists of all of one word plus 2 bytes
// from another word.
const size_type part = sizeof(unsigned long) % sizeof(word_type);
#if 0
// bug in here?
// >> to far?
BOOST_ASSERT_THROW((part != 0
&& nwords <= num_words()
&& (data()[min_nwords - 1] >>
((sizeof(word_type) - part) * CHAR_BIT)) != 0),
overflow);
#endif
unsigned long result = 0;
for (size_type i = 0; i < min_nwords; ++i) {
result |= static_cast<unsigned long>(
data()[i]) << (i * sizeof(word_type) * CHAR_BIT);
}
return result;
}
}// end operator unsigned long()
template <class WordTraits, class SizeType, class Derived>
SizeType bitset_base<WordTraits,SizeType,Derived>::
find_first() const
{
SizeType not_found = size();
for (size_type i = 0; i < num_words(); i++ ) {
word_type thisword = data()[i];
if ( thisword != static_cast<word_type>(0) ) {
// find byte within word
for ( std::size_t j = 0; j < sizeof(word_type); j++ ) {
unsigned char this_byte
= static_cast<unsigned char>(thisword & (~(unsigned char)0));
if ( this_byte )
return i * WordTraits::word_size + j * CHAR_BIT +
first_bit_location<>::value[this_byte];
thisword >>= CHAR_BIT;
}
}
}
// not found, so return an indication of failure.
return not_found;
}
template <class WordTraits, class SizeType, class Derived>
SizeType bitset_base<WordTraits, SizeType, Derived>::
bitset_base<WordTraits,SizeType,Derived>::
find_next(size_type prev) const
{
SizeType not_found = size();
// make bound inclusive
++prev;
// check out of bounds
if ( prev >= num_words() * WordTraits::word_size )
return not_found;
// search first word
size_type i = s_which_word(prev);
word_type thisword = data()[i];
// mask off bits below bound
thisword &= (~static_cast<word_type>(0)) << s_which_bit(prev);
if ( thisword != static_cast<word_type>(0) ) {
// find byte within word
// get first byte into place
thisword >>= s_which_byte(prev) * CHAR_BIT;
for ( size_type j = s_which_byte(prev); j < sizeof(word_type); j++ ) {
unsigned char this_byte
= static_cast<unsigned char>(thisword & (~(unsigned char)0));
if ( this_byte )
return i * WordTraits::word_size + j * CHAR_BIT +
first_bit_location<>::value[this_byte];
thisword >>= CHAR_BIT;
}
}
// check subsequent words
i++;
for ( ; i < num_words(); i++ ) {
word_type thisword = data()[i];
if ( thisword != static_cast<word_type>(0) ) {
// find byte within word
for ( size_type j = 0; j < sizeof(word_type); j++ ) {
unsigned char this_byte
= static_cast<unsigned char>(thisword & (~(unsigned char)0));
if ( this_byte )
return i * WordTraits::word_size + j * CHAR_BIT +
first_bit_location<>::value[this_byte];
thisword >>= CHAR_BIT;
}
}
}
// not found, so return an indication of failure.
return not_found;
} // end find_next
template <bool dummy>
unsigned char bit_count<dummy>::value[] = {
0, /* 0 */ 1, /* 1 */ 1, /* 2 */ 2, /* 3 */ 1, /* 4 */
2, /* 5 */ 2, /* 6 */ 3, /* 7 */ 1, /* 8 */ 2, /* 9 */
2, /* 10 */ 3, /* 11 */ 2, /* 12 */ 3, /* 13 */ 3, /* 14 */
4, /* 15 */ 1, /* 16 */ 2, /* 17 */ 2, /* 18 */ 3, /* 19 */
2, /* 20 */ 3, /* 21 */ 3, /* 22 */ 4, /* 23 */ 2, /* 24 */
3, /* 25 */ 3, /* 26 */ 4, /* 27 */ 3, /* 28 */ 4, /* 29 */
4, /* 30 */ 5, /* 31 */ 1, /* 32 */ 2, /* 33 */ 2, /* 34 */
3, /* 35 */ 2, /* 36 */ 3, /* 37 */ 3, /* 38 */ 4, /* 39 */
2, /* 40 */ 3, /* 41 */ 3, /* 42 */ 4, /* 43 */ 3, /* 44 */
4, /* 45 */ 4, /* 46 */ 5, /* 47 */ 2, /* 48 */ 3, /* 49 */
3, /* 50 */ 4, /* 51 */ 3, /* 52 */ 4, /* 53 */ 4, /* 54 */
5, /* 55 */ 3, /* 56 */ 4, /* 57 */ 4, /* 58 */ 5, /* 59 */
4, /* 60 */ 5, /* 61 */ 5, /* 62 */ 6, /* 63 */ 1, /* 64 */
2, /* 65 */ 2, /* 66 */ 3, /* 67 */ 2, /* 68 */ 3, /* 69 */
3, /* 70 */ 4, /* 71 */ 2, /* 72 */ 3, /* 73 */ 3, /* 74 */
4, /* 75 */ 3, /* 76 */ 4, /* 77 */ 4, /* 78 */ 5, /* 79 */
2, /* 80 */ 3, /* 81 */ 3, /* 82 */ 4, /* 83 */ 3, /* 84 */
4, /* 85 */ 4, /* 86 */ 5, /* 87 */ 3, /* 88 */ 4, /* 89 */
4, /* 90 */ 5, /* 91 */ 4, /* 92 */ 5, /* 93 */ 5, /* 94 */
6, /* 95 */ 2, /* 96 */ 3, /* 97 */ 3, /* 98 */ 4, /* 99 */
3, /* 100 */ 4, /* 101 */ 4, /* 102 */ 5, /* 103 */ 3, /* 104 */
4, /* 105 */ 4, /* 106 */ 5, /* 107 */ 4, /* 108 */ 5, /* 109 */
5, /* 110 */ 6, /* 111 */ 3, /* 112 */ 4, /* 113 */ 4, /* 114 */
5, /* 115 */ 4, /* 116 */ 5, /* 117 */ 5, /* 118 */ 6, /* 119 */
4, /* 120 */ 5, /* 121 */ 5, /* 122 */ 6, /* 123 */ 5, /* 124 */
6, /* 125 */ 6, /* 126 */ 7, /* 127 */ 1, /* 128 */ 2, /* 129 */
2, /* 130 */ 3, /* 131 */ 2, /* 132 */ 3, /* 133 */ 3, /* 134 */
4, /* 135 */ 2, /* 136 */ 3, /* 137 */ 3, /* 138 */ 4, /* 139 */
3, /* 140 */ 4, /* 141 */ 4, /* 142 */ 5, /* 143 */ 2, /* 144 */
3, /* 145 */ 3, /* 146 */ 4, /* 147 */ 3, /* 148 */ 4, /* 149 */
4, /* 150 */ 5, /* 151 */ 3, /* 152 */ 4, /* 153 */ 4, /* 154 */
5, /* 155 */ 4, /* 156 */ 5, /* 157 */ 5, /* 158 */ 6, /* 159 */
2, /* 160 */ 3, /* 161 */ 3, /* 162 */ 4, /* 163 */ 3, /* 164 */
4, /* 165 */ 4, /* 166 */ 5, /* 167 */ 3, /* 168 */ 4, /* 169 */
4, /* 170 */ 5, /* 171 */ 4, /* 172 */ 5, /* 173 */ 5, /* 174 */
6, /* 175 */ 3, /* 176 */ 4, /* 177 */ 4, /* 178 */ 5, /* 179 */
4, /* 180 */ 5, /* 181 */ 5, /* 182 */ 6, /* 183 */ 4, /* 184 */
5, /* 185 */ 5, /* 186 */ 6, /* 187 */ 5, /* 188 */ 6, /* 189 */
6, /* 190 */ 7, /* 191 */ 2, /* 192 */ 3, /* 193 */ 3, /* 194 */
4, /* 195 */ 3, /* 196 */ 4, /* 197 */ 4, /* 198 */ 5, /* 199 */
3, /* 200 */ 4, /* 201 */ 4, /* 202 */ 5, /* 203 */ 4, /* 204 */
5, /* 205 */ 5, /* 206 */ 6, /* 207 */ 3, /* 208 */ 4, /* 209 */
4, /* 210 */ 5, /* 211 */ 4, /* 212 */ 5, /* 213 */ 5, /* 214 */
6, /* 215 */ 4, /* 216 */ 5, /* 217 */ 5, /* 218 */ 6, /* 219 */
5, /* 220 */ 6, /* 221 */ 6, /* 222 */ 7, /* 223 */ 3, /* 224 */
4, /* 225 */ 4, /* 226 */ 5, /* 227 */ 4, /* 228 */ 5, /* 229 */
5, /* 230 */ 6, /* 231 */ 4, /* 232 */ 5, /* 233 */ 5, /* 234 */
6, /* 235 */ 5, /* 236 */ 6, /* 237 */ 6, /* 238 */ 7, /* 239 */
4, /* 240 */ 5, /* 241 */ 5, /* 242 */ 6, /* 243 */ 5, /* 244 */
6, /* 245 */ 6, /* 246 */ 7, /* 247 */ 5, /* 248 */ 6, /* 249 */
6, /* 250 */ 7, /* 251 */ 6, /* 252 */ 7, /* 253 */ 7, /* 254 */
8 /* 255 */
}; // end _Bit_count
template <bool dummy>
unsigned char first_bit_location<dummy>::value[] = {
0, /* 0 */ 0, /* 1 */ 1, /* 2 */ 0, /* 3 */ 2, /* 4 */
0, /* 5 */ 1, /* 6 */ 0, /* 7 */ 3, /* 8 */ 0, /* 9 */
1, /* 10 */ 0, /* 11 */ 2, /* 12 */ 0, /* 13 */ 1, /* 14 */
0, /* 15 */ 4, /* 16 */ 0, /* 17 */ 1, /* 18 */ 0, /* 19 */
2, /* 20 */ 0, /* 21 */ 1, /* 22 */ 0, /* 23 */ 3, /* 24 */
0, /* 25 */ 1, /* 26 */ 0, /* 27 */ 2, /* 28 */ 0, /* 29 */
1, /* 30 */ 0, /* 31 */ 5, /* 32 */ 0, /* 33 */ 1, /* 34 */
0, /* 35 */ 2, /* 36 */ 0, /* 37 */ 1, /* 38 */ 0, /* 39 */
3, /* 40 */ 0, /* 41 */ 1, /* 42 */ 0, /* 43 */ 2, /* 44 */
0, /* 45 */ 1, /* 46 */ 0, /* 47 */ 4, /* 48 */ 0, /* 49 */
1, /* 50 */ 0, /* 51 */ 2, /* 52 */ 0, /* 53 */ 1, /* 54 */
0, /* 55 */ 3, /* 56 */ 0, /* 57 */ 1, /* 58 */ 0, /* 59 */
2, /* 60 */ 0, /* 61 */ 1, /* 62 */ 0, /* 63 */ 6, /* 64 */
0, /* 65 */ 1, /* 66 */ 0, /* 67 */ 2, /* 68 */ 0, /* 69 */
1, /* 70 */ 0, /* 71 */ 3, /* 72 */ 0, /* 73 */ 1, /* 74 */
0, /* 75 */ 2, /* 76 */ 0, /* 77 */ 1, /* 78 */ 0, /* 79 */
4, /* 80 */ 0, /* 81 */ 1, /* 82 */ 0, /* 83 */ 2, /* 84 */
0, /* 85 */ 1, /* 86 */ 0, /* 87 */ 3, /* 88 */ 0, /* 89 */
1, /* 90 */ 0, /* 91 */ 2, /* 92 */ 0, /* 93 */ 1, /* 94 */
0, /* 95 */ 5, /* 96 */ 0, /* 97 */ 1, /* 98 */ 0, /* 99 */
2, /* 100 */ 0, /* 101 */ 1, /* 102 */ 0, /* 103 */ 3, /* 104 */
0, /* 105 */ 1, /* 106 */ 0, /* 107 */ 2, /* 108 */ 0, /* 109 */
1, /* 110 */ 0, /* 111 */ 4, /* 112 */ 0, /* 113 */ 1, /* 114 */
0, /* 115 */ 2, /* 116 */ 0, /* 117 */ 1, /* 118 */ 0, /* 119 */
3, /* 120 */ 0, /* 121 */ 1, /* 122 */ 0, /* 123 */ 2, /* 124 */
0, /* 125 */ 1, /* 126 */ 0, /* 127 */ 7, /* 128 */ 0, /* 129 */
1, /* 130 */ 0, /* 131 */ 2, /* 132 */ 0, /* 133 */ 1, /* 134 */
0, /* 135 */ 3, /* 136 */ 0, /* 137 */ 1, /* 138 */ 0, /* 139 */
2, /* 140 */ 0, /* 141 */ 1, /* 142 */ 0, /* 143 */ 4, /* 144 */
0, /* 145 */ 1, /* 146 */ 0, /* 147 */ 2, /* 148 */ 0, /* 149 */
1, /* 150 */ 0, /* 151 */ 3, /* 152 */ 0, /* 153 */ 1, /* 154 */
0, /* 155 */ 2, /* 156 */ 0, /* 157 */ 1, /* 158 */ 0, /* 159 */
5, /* 160 */ 0, /* 161 */ 1, /* 162 */ 0, /* 163 */ 2, /* 164 */
0, /* 165 */ 1, /* 166 */ 0, /* 167 */ 3, /* 168 */ 0, /* 169 */
1, /* 170 */ 0, /* 171 */ 2, /* 172 */ 0, /* 173 */ 1, /* 174 */
0, /* 175 */ 4, /* 176 */ 0, /* 177 */ 1, /* 178 */ 0, /* 179 */
2, /* 180 */ 0, /* 181 */ 1, /* 182 */ 0, /* 183 */ 3, /* 184 */
0, /* 185 */ 1, /* 186 */ 0, /* 187 */ 2, /* 188 */ 0, /* 189 */
1, /* 190 */ 0, /* 191 */ 6, /* 192 */ 0, /* 193 */ 1, /* 194 */
0, /* 195 */ 2, /* 196 */ 0, /* 197 */ 1, /* 198 */ 0, /* 199 */
3, /* 200 */ 0, /* 201 */ 1, /* 202 */ 0, /* 203 */ 2, /* 204 */
0, /* 205 */ 1, /* 206 */ 0, /* 207 */ 4, /* 208 */ 0, /* 209 */
1, /* 210 */ 0, /* 211 */ 2, /* 212 */ 0, /* 213 */ 1, /* 214 */
0, /* 215 */ 3, /* 216 */ 0, /* 217 */ 1, /* 218 */ 0, /* 219 */
2, /* 220 */ 0, /* 221 */ 1, /* 222 */ 0, /* 223 */ 5, /* 224 */
0, /* 225 */ 1, /* 226 */ 0, /* 227 */ 2, /* 228 */ 0, /* 229 */
1, /* 230 */ 0, /* 231 */ 3, /* 232 */ 0, /* 233 */ 1, /* 234 */
0, /* 235 */ 2, /* 236 */ 0, /* 237 */ 1, /* 238 */ 0, /* 239 */
4, /* 240 */ 0, /* 241 */ 1, /* 242 */ 0, /* 243 */ 2, /* 244 */
0, /* 245 */ 1, /* 246 */ 0, /* 247 */ 3, /* 248 */ 0, /* 249 */
1, /* 250 */ 0, /* 251 */ 2, /* 252 */ 0, /* 253 */ 1, /* 254 */
0, /* 255 */
}; // end _First_one
} // namespace detail
} // namespace boost

View File

@@ -1,90 +0,0 @@
//=======================================================================
// Copyright 2002 Indiana University.
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
#ifndef BOOST_BITSET_ADAPTOR_HPP
#define BOOST_BITSET_ADAPTOR_HPP
template <class T, class Derived>
struct bitset_adaptor {
Derived& derived() { return static_cast<Derived&>(*this); }
const Derived& derived() const {
return static_cast<const Derived&>(*this);
}
};
template <class T, class D, class V>
bool set_contains(const bitset_adaptor<T,D>& s, const V& x) {
return s.derived().test(x);
}
template <class T, class D>
bool set_equal(const bitset_adaptor<T,D>& x,
const bitset_adaptor<T,D>& y) {
return x.derived() == y.derived();
}
template <class T, class D>
int set_lex_order(const bitset_adaptor<T,D>& x,
const bitset_adaptor<T,D>& y) {
return compare_3way(x.derived(), y.derived());
}
template <class T, class D>
void set_clear(bitset_adaptor<T,D>& x) {
x.derived().reset();
}
template <class T, class D>
bool set_empty(const bitset_adaptor<T,D>& x) {
return x.derived().none();
}
template <class T, class D, class V>
void set_insert(bitset_adaptor<T,D>& x, const V& a) {
x.derived().set(a);
}
template <class T, class D, class V>
void set_remove(bitset_adaptor<T,D>& x, const V& a) {
x.derived().set(a, false);
}
template <class T, class D>
void set_intersect(const bitset_adaptor<T,D>& x,
const bitset_adaptor<T,D>& y,
bitset_adaptor<T,D>& z)
{
z.derived() = x.derived() & y.derived();
}
template <class T, class D>
void set_union(const bitset_adaptor<T,D>& x,
const bitset_adaptor<T,D>& y,
bitset_adaptor<T,D>& z)
{
z.derived() = x.derived() | y.derived();
}
template <class T, class D>
void set_difference(const bitset_adaptor<T,D>& x,
const bitset_adaptor<T,D>& y,
bitset_adaptor<T,D>& z)
{
z.derived() = x.derived() - y.derived();
}
template <class T, class D>
void set_compliment(const bitset_adaptor<T,D>& x,
bitset_adaptor<T,D>& z)
{
z.derived() = x.derived();
z.derived().flip();
}
#endif // BOOST_BITSET_ADAPTOR_HPP

View File

@@ -49,7 +49,7 @@ namespace boost {
// protected:
property_type* m_eproperty;
};
template <class D, class V>
inline bool
operator==(const detail::edge_desc_impl<D,V>& a,
@@ -65,6 +65,36 @@ namespace boost {
return ! (a.get_property() == b.get_property());
}
// Order edges according to the address of their property object
template <class D, class V>
inline bool
operator<(const detail::edge_desc_impl<D,V>& a,
const detail::edge_desc_impl<D,V>& b)
{
return a.get_property() < b.get_property();
}
template <class D, class V>
inline bool
operator<=(const detail::edge_desc_impl<D,V>& a,
const detail::edge_desc_impl<D,V>& b)
{
return a.get_property() <= b.get_property();
}
template <class D, class V>
inline bool
operator>(const detail::edge_desc_impl<D,V>& a,
const detail::edge_desc_impl<D,V>& b)
{
return a.get_property() > b.get_property();
}
template <class D, class V>
inline bool
operator>=(const detail::edge_desc_impl<D,V>& a,
const detail::edge_desc_impl<D,V>& b)
{
return a.get_property() >= b.get_property();
}
} //namespace detail
} // namespace boost

View File

@@ -9,7 +9,7 @@
#ifndef BOOST_GRAPH_DETAIL_IS_SAME_HPP
#define BOOST_GRAPH_DETAIL_IS_SAME_HPP
#include <boost/pending/ct_if.hpp>
#include <boost/mpl/if.hpp>
namespace boost {
struct false_tag;
@@ -30,7 +30,7 @@ namespace boost {
template <class U, class V>
struct is_same {
enum { Unum = U::num, Vnum = V::num };
typedef typename boost::ct_if< (Unum == Vnum),
typedef typename mpl::if_c< (Unum == Vnum),
boost::true_tag, boost::false_tag>::type is_same_tag;
};
#endif

View File

@@ -149,7 +149,7 @@ struct dot_grammar : public boost::spirit::grammar<dot_grammar> {
ID
= ( lexeme_d[((alpha_p | ch_p('_')) >> *(alnum_p | ch_p('_')))]
| real_p
| confix_p('"', *c_escape_ch_p, '"')
| lexeme_d[confix_p('"', *c_escape_ch_p, '"')]
| comment_nest_p('<', '>')
)[ID.name = construct_<std::string>(arg1,arg2)]
;
@@ -161,7 +161,7 @@ struct dot_grammar : public boost::spirit::grammar<dot_grammar> {
>> !( ch_p('=')
>> ID[a_list.value = arg1])
[phoenix::bind(&definition::call_prop_actor)
(var(*this),a_list.key,a_list.value)],ch_p(','));
(var(*this),a_list.key,a_list.value)],!ch_p(','));
attr_list = +(ch_p('[') >> !a_list >> ch_p(']'));
@@ -182,6 +182,14 @@ struct dot_grammar : public boost::spirit::grammar<dot_grammar> {
= ( ID[node_id.name = arg1] >> (!port) )
[phoenix::bind(&definition::memoize_node)(var(*this))];
graph_stmt
= (ID[graph_stmt.key = arg1] >>
ch_p('=') >>
ID[graph_stmt.value = arg1])
[phoenix::bind(&definition::call_graph_prop)
(var(*this),graph_stmt.key,graph_stmt.value)]
; // Graph property.
attr_stmt
= (as_lower_d[keyword_p("graph")]
>> attr_list(actor_t(phoenix::bind(&definition::default_graph_prop)
@@ -236,7 +244,7 @@ struct dot_grammar : public boost::spirit::grammar<dot_grammar> {
stmt
= (ID >> ch_p('=') >> ID) // Graph property -- ignore.
= graph_stmt
| attr_stmt
| data_stmt
;
@@ -331,7 +339,7 @@ struct dot_grammar : public boost::spirit::grammar<dot_grammar> {
edge_stack_t& edge_stack = data_stmt.edge_stack();
for(nodes_t::iterator i = sources.begin(); i != sources.end(); ++i) {
for(nodes_t::iterator j = dests.begin(); j != dests.end(); ++j) {
// Create the edge and and push onto the edge stack.
// Create the edge and push onto the edge stack.
#ifdef BOOST_GRAPH_DEBUG
std::cout << "Edge " << *i << " to " << *j << std::endl;
#endif // BOOST_GRAPH_DEBUG
@@ -376,8 +384,13 @@ struct dot_grammar : public boost::spirit::grammar<dot_grammar> {
}
}
// default_graph_prop - Just ignore graph properties.
void default_graph_prop(id_t const&, id_t const&) { }
// default_graph_prop - Store as a graph property.
void default_graph_prop(id_t const& key, id_t const& value) {
#ifdef BOOST_GRAPH_DEBUG
std::cout << key << " = " << value << std::endl;
#endif // BOOST_GRAPH_DEBUG
self.graph_.set_graph_property(key, value);
}
// default_node_prop - declare default properties for any future new nodes
void default_node_prop(id_t const& key, id_t const& value) {
@@ -432,6 +445,15 @@ struct dot_grammar : public boost::spirit::grammar<dot_grammar> {
actor(lhs,rhs);
}
void call_graph_prop(std::string const& lhs, std::string const& rhs) {
// If first and last characters of the rhs are double-quotes,
// remove them.
if (!rhs.empty() && rhs[0] == '"' && rhs[rhs.size() - 1] == '"')
this->default_graph_prop(lhs, rhs.substr(1, rhs.size()-2));
else
this->default_graph_prop(lhs,rhs);
}
void set_node_property(node_t const& node, id_t const& key,
id_t const& value) {
@@ -454,7 +476,11 @@ struct dot_grammar : public boost::spirit::grammar<dot_grammar> {
self.graph_.set_edge_property(key, edge, value);
#ifdef BOOST_GRAPH_DEBUG
// Tell the world
std::cout << "(" << edge.first << "," << edge.second << "): "
#if 0 // RG - edge representation changed,
std::cout << "(" << edge.first << "," << edge.second << "): "
#else
std::cout << "an edge: "
#endif // 0
<< key << " = " << value << std::endl;
#endif // BOOST_GRAPH_DEBUG
}
@@ -476,6 +502,7 @@ struct dot_grammar : public boost::spirit::grammar<dot_grammar> {
rule_t port_angle;
rule_t port;
boost::spirit::rule<ScannerT,node_id_closure::context_t> node_id;
boost::spirit::rule<ScannerT,property_closure::context_t> graph_stmt;
rule_t attr_stmt;
boost::spirit::rule<ScannerT,data_stmt_closure::context_t> data_stmt;
boost::spirit::rule<ScannerT,subgraph_closure::context_t> subgraph;
@@ -527,9 +554,9 @@ struct dot_skipper : public boost::spirit::grammar<dot_skipper>
using namespace boost::spirit;
using namespace phoenix;
// comment forms
skip = space_p
skip = eol_p >> comment_p("#")
| space_p
| comment_p("//")
| comment_p("#")
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1400)
| confix_p(str_p("/*") ,*anychar_p, str_p("*/"))
#else

View File

@@ -13,7 +13,8 @@
#include <iterator>
#include <boost/config.hpp>
#include <boost/pending/ct_if.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/pending/integer_range.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/properties.hpp>
@@ -241,11 +242,11 @@ namespace boost {
template <class Cat>
struct is_random {
enum { RET = false };
typedef false_type type;
typedef mpl::false_ type;
};
template <>
struct is_random<std::random_access_iterator_tag> {
enum { RET = true }; typedef true_type type;
enum { RET = true }; typedef mpl::true_ type;
};
// The edge_list class conditionally inherits from one of the
@@ -262,7 +263,7 @@ namespace boost {
class Cat>
#endif
class edge_list
: public ct_if_t< typename is_random<Cat>::type,
: public mpl::if_< typename is_random<Cat>::type,
edge_list_impl_ra< edge_list<EdgeIter,T,D,Cat>, EdgeIter,T,D>,
edge_list_impl< edge_list<EdgeIter,T,D,Cat>, EdgeIter,T,D>
>::type

View File

@@ -18,125 +18,10 @@
#include <boost/concept_check.hpp>
#include <boost/detail/workaround.hpp>
namespace boost {
template <class T>
struct MultiPassInputIteratorConcept {
void constraints() {
function_requires< InputIteratorConcept<T> >();
}
};
template <class G>
struct GraphConcept
{
typedef typename graph_traits<G>::vertex_descriptor vertex_descriptor;
typedef typename graph_traits<G>::directed_category directed_category;
typedef typename graph_traits<G>::edge_parallel_category
edge_parallel_category;
typedef typename graph_traits<G>::traversal_category
traversal_category;
void constraints() {
function_requires< DefaultConstructibleConcept<vertex_descriptor> >();
function_requires< EqualityComparableConcept<vertex_descriptor> >();
function_requires< AssignableConcept<vertex_descriptor> >();
}
G g;
};
template <class G>
struct IncidenceGraphConcept
{
typedef typename graph_traits<G>::edge_descriptor edge_descriptor;
typedef typename graph_traits<G>::out_edge_iterator
out_edge_iterator;
typedef typename graph_traits<G>::traversal_category
traversal_category;
void constraints() {
function_requires< GraphConcept<G> >();
function_requires< MultiPassInputIteratorConcept<out_edge_iterator> >();
function_requires< DefaultConstructibleConcept<edge_descriptor> >();
function_requires< EqualityComparableConcept<edge_descriptor> >();
function_requires< AssignableConcept<edge_descriptor> >();
function_requires< ConvertibleConcept<traversal_category,
incidence_graph_tag> >();
p = out_edges(u, g);
n = out_degree(u, g);
e = *p.first;
u = source(e, g);
v = target(e, g);
const_constraints(g);
}
void const_constraints(const G& cg) {
p = out_edges(u, cg);
n = out_degree(u, cg);
e = *p.first;
u = source(e, cg);
v = target(e, cg);
}
std::pair<out_edge_iterator, out_edge_iterator> p;
typename graph_traits<G>::vertex_descriptor u, v;
typename graph_traits<G>::edge_descriptor e;
typename graph_traits<G>::degree_size_type n;
G g;
};
template <class G>
struct BidirectionalGraphConcept
{
typedef typename graph_traits<G>::in_edge_iterator
in_edge_iterator;
typedef typename graph_traits<G>::traversal_category
traversal_category;
void constraints() {
function_requires< IncidenceGraphConcept<G> >();
function_requires< MultiPassInputIteratorConcept<in_edge_iterator> >();
function_requires< ConvertibleConcept<traversal_category,
bidirectional_graph_tag> >();
p = in_edges(v, g);
n = in_degree(v, g);
e = *p.first;
const_constraints(g);
}
void const_constraints(const G& cg) {
p = in_edges(v, cg);
n = in_degree(v, cg);
e = *p.first;
}
std::pair<in_edge_iterator, in_edge_iterator> p;
typename graph_traits<G>::vertex_descriptor v;
typename graph_traits<G>::edge_descriptor e;
typename graph_traits<G>::degree_size_type n;
G g;
};
template <class G>
struct AdjacencyGraphConcept
{
typedef typename graph_traits<G>::adjacency_iterator
adjacency_iterator;
typedef typename graph_traits<G>::traversal_category
traversal_category;
void constraints() {
function_requires< GraphConcept<G> >();
function_requires< MultiPassInputIteratorConcept<adjacency_iterator> >();
function_requires< ConvertibleConcept<traversal_category,
adjacency_graph_tag> >();
p = adjacent_vertices(v, g);
v = *p.first;
const_constraints(g);
}
void const_constraints(const G& cg) {
p = adjacent_vertices(v, cg);
}
std::pair<adjacency_iterator,adjacency_iterator> p;
typename graph_traits<G>::vertex_descriptor v;
G g;
};
#include <boost/concept/detail/concept_def.hpp>
namespace boost
{
// dwa 2003/7/11 -- This clearly shouldn't be necessary, but if
// you want to use vector_as_graph, it is! I'm sure the graph
// library leaves these out all over the place. Probably a
@@ -156,18 +41,138 @@ template <class T>
typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
#endif
template <class G>
struct VertexListGraphConcept
namespace concepts {
BOOST_concept(MultiPassInputIterator,(T)) {
BOOST_CONCEPT_USAGE(MultiPassInputIterator) {
BOOST_CONCEPT_ASSERT((InputIterator<T>));
}
};
BOOST_concept(Graph,(G))
{
typedef typename graph_traits<G>::vertex_descriptor vertex_descriptor;
typedef typename graph_traits<G>::directed_category directed_category;
typedef typename graph_traits<G>::edge_parallel_category
edge_parallel_category;
typedef typename graph_traits<G>::traversal_category
traversal_category;
BOOST_CONCEPT_USAGE(Graph)
{
BOOST_CONCEPT_ASSERT((DefaultConstructible<vertex_descriptor>));
BOOST_CONCEPT_ASSERT((EqualityComparable<vertex_descriptor>));
BOOST_CONCEPT_ASSERT((Assignable<vertex_descriptor>));
}
G g;
};
BOOST_concept(IncidenceGraph,(G))
: Graph<G>
{
typedef typename graph_traits<G>::edge_descriptor edge_descriptor;
typedef typename graph_traits<G>::out_edge_iterator
out_edge_iterator;
typedef typename graph_traits<G>::traversal_category
traversal_category;
BOOST_CONCEPT_USAGE(IncidenceGraph) {
BOOST_CONCEPT_ASSERT((MultiPassInputIterator<out_edge_iterator>));
BOOST_CONCEPT_ASSERT((DefaultConstructible<edge_descriptor>));
BOOST_CONCEPT_ASSERT((EqualityComparable<edge_descriptor>));
BOOST_CONCEPT_ASSERT((Assignable<edge_descriptor>));
BOOST_CONCEPT_ASSERT((Convertible<traversal_category,
incidence_graph_tag>));
p = out_edges(u, g);
n = out_degree(u, g);
e = *p.first;
u = source(e, g);
v = target(e, g);
const_constraints(g);
}
void const_constraints(const G& cg) {
p = out_edges(u, cg);
n = out_degree(u, cg);
e = *p.first;
u = source(e, cg);
v = target(e, cg);
}
std::pair<out_edge_iterator, out_edge_iterator> p;
typename graph_traits<G>::vertex_descriptor u, v;
typename graph_traits<G>::edge_descriptor e;
typename graph_traits<G>::degree_size_type n;
G g;
};
BOOST_concept(BidirectionalGraph,(G))
: IncidenceGraph<G>
{
typedef typename graph_traits<G>::in_edge_iterator
in_edge_iterator;
typedef typename graph_traits<G>::traversal_category
traversal_category;
BOOST_CONCEPT_USAGE(BidirectionalGraph) {
BOOST_CONCEPT_ASSERT((MultiPassInputIterator<in_edge_iterator>));
BOOST_CONCEPT_ASSERT((Convertible<traversal_category,
bidirectional_graph_tag>));
p = in_edges(v, g);
n = in_degree(v, g);
e = *p.first;
const_constraints(g);
}
void const_constraints(const G& cg) {
p = in_edges(v, cg);
n = in_degree(v, cg);
e = *p.first;
}
std::pair<in_edge_iterator, in_edge_iterator> p;
typename graph_traits<G>::vertex_descriptor v;
typename graph_traits<G>::edge_descriptor e;
typename graph_traits<G>::degree_size_type n;
G g;
};
BOOST_concept(AdjacencyGraph,(G))
: Graph<G>
{
typedef typename graph_traits<G>::adjacency_iterator
adjacency_iterator;
typedef typename graph_traits<G>::traversal_category
traversal_category;
BOOST_CONCEPT_USAGE(AdjacencyGraph) {
BOOST_CONCEPT_ASSERT((MultiPassInputIterator<adjacency_iterator>));
BOOST_CONCEPT_ASSERT((Convertible<traversal_category,
adjacency_graph_tag>));
p = adjacent_vertices(v, g);
v = *p.first;
const_constraints(g);
}
void const_constraints(const G& cg) {
p = adjacent_vertices(v, cg);
}
std::pair<adjacency_iterator,adjacency_iterator> p;
typename graph_traits<G>::vertex_descriptor v;
G g;
};
BOOST_concept(VertexListGraph,(G))
: Graph<G>
{
typedef typename graph_traits<G>::vertex_iterator vertex_iterator;
typedef typename graph_traits<G>::vertices_size_type vertices_size_type;
typedef typename graph_traits<G>::traversal_category
traversal_category;
void constraints() {
function_requires< GraphConcept<G> >();
function_requires< MultiPassInputIteratorConcept<vertex_iterator> >();
function_requires< ConvertibleConcept<traversal_category,
vertex_list_graph_tag> >();
BOOST_CONCEPT_USAGE(VertexListGraph) {
BOOST_CONCEPT_ASSERT((MultiPassInputIterator<vertex_iterator>));
BOOST_CONCEPT_ASSERT((Convertible<traversal_category,
vertex_list_graph_tag>));
#ifdef BOOST_VECTOR_AS_GRAPH_GRAPH_ADL_HACK
// dwa 2003/7/11 -- This clearly shouldn't be necessary, but if
@@ -201,22 +206,22 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
vertices_size_type V;
};
template <class G>
struct EdgeListGraphConcept
BOOST_concept(EdgeListGraph,(G))
: Graph<G>
{
typedef typename graph_traits<G>::edge_descriptor edge_descriptor;
typedef typename graph_traits<G>::edge_iterator edge_iterator;
typedef typename graph_traits<G>::edges_size_type edges_size_type;
typedef typename graph_traits<G>::traversal_category
traversal_category;
void constraints() {
function_requires< GraphConcept<G> >();
function_requires< MultiPassInputIteratorConcept<edge_iterator> >();
function_requires< DefaultConstructibleConcept<edge_descriptor> >();
function_requires< EqualityComparableConcept<edge_descriptor> >();
function_requires< AssignableConcept<edge_descriptor> >();
function_requires< ConvertibleConcept<traversal_category,
edge_list_graph_tag> >();
BOOST_CONCEPT_USAGE(EdgeListGraph) {
BOOST_CONCEPT_ASSERT((MultiPassInputIterator<edge_iterator>));
BOOST_CONCEPT_ASSERT((DefaultConstructible<edge_descriptor>));
BOOST_CONCEPT_ASSERT((EqualityComparable<edge_descriptor>));
BOOST_CONCEPT_ASSERT((Assignable<edge_descriptor>));
BOOST_CONCEPT_ASSERT((Convertible<traversal_category,
edge_list_graph_tag>));
p = edges(g);
e = *p.first;
@@ -238,13 +243,10 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
G g;
};
template <class G>
struct VertexAndEdgeListGraphConcept
BOOST_concept(VertexAndEdgeListGraph,(G))
: VertexListGraph<G>
, EdgeListGraph<G>
{
void constraints() {
function_requires< VertexListGraphConcept<G> >();
function_requires< EdgeListGraphConcept<G> >();
}
};
// Where to put the requirement for this constructor?
@@ -252,11 +254,11 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
// Not in mutable graph, then LEDA graph's can't be models of
// MutableGraph.
template <class G>
struct EdgeMutableGraphConcept
BOOST_concept(EdgeMutableGraph,(G))
{
typedef typename graph_traits<G>::edge_descriptor edge_descriptor;
void constraints() {
BOOST_CONCEPT_USAGE(EdgeMutableGraph) {
p = add_edge(u, v, g);
remove_edge(u, v, g);
remove_edge(e, g);
@@ -268,10 +270,10 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
typename graph_traits<G>::vertex_descriptor u, v;
};
template <class G>
struct VertexMutableGraphConcept
BOOST_concept(VertexMutableGraph,(G))
{
void constraints() {
BOOST_CONCEPT_USAGE(VertexMutableGraph) {
v = add_vertex(g);
remove_vertex(v, g);
}
@@ -279,13 +281,10 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
typename graph_traits<G>::vertex_descriptor u, v;
};
template <class G>
struct MutableGraphConcept
BOOST_concept(MutableGraph,(G))
: EdgeMutableGraph<G>
, VertexMutableGraph<G>
{
void constraints() {
function_requires< EdgeMutableGraphConcept<G> >();
function_requires< VertexMutableGraphConcept<G> >();
}
};
template <class edge_descriptor>
@@ -295,11 +294,10 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
}
};
template <class G>
struct MutableIncidenceGraphConcept
BOOST_concept(MutableIncidenceGraph,(G))
: MutableGraph<G>
{
void constraints() {
function_requires< MutableGraphConcept<G> >();
BOOST_CONCEPT_USAGE(MutableIncidenceGraph) {
remove_edge(iter, g);
remove_out_edge_if(u, p, g);
}
@@ -310,24 +308,23 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
typename boost::graph_traits<G>::out_edge_iterator iter;
};
template <class G>
struct MutableBidirectionalGraphConcept
BOOST_concept(MutableBidirectionalGraph,(G))
: MutableIncidenceGraph<G>
{
void constraints() {
function_requires< MutableIncidenceGraphConcept<G> >();
remove_in_edge_if(u, p, g);
}
G g;
typedef typename graph_traits<G>::edge_descriptor edge_descriptor;
dummy_edge_predicate<edge_descriptor> p;
typename boost::graph_traits<G>::vertex_descriptor u;
BOOST_CONCEPT_USAGE(MutableBidirectionalGraph)
{
remove_in_edge_if(u, p, g);
}
G g;
typedef typename graph_traits<G>::edge_descriptor edge_descriptor;
dummy_edge_predicate<edge_descriptor> p;
typename boost::graph_traits<G>::vertex_descriptor u;
};
template <class G>
struct MutableEdgeListGraphConcept
BOOST_concept(MutableEdgeListGraph,(G))
: EdgeMutableGraph<G>
{
void constraints() {
function_requires< EdgeMutableGraphConcept<G> >();
BOOST_CONCEPT_USAGE(MutableEdgeListGraph) {
remove_edge_if(p, g);
}
G g;
@@ -335,11 +332,10 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
dummy_edge_predicate<edge_descriptor> p;
};
template <class G>
struct VertexMutablePropertyGraphConcept
BOOST_concept(VertexMutablePropertyGraph,(G))
: VertexMutableGraph<G>
{
void constraints() {
function_requires< VertexMutableGraphConcept<G> >();
BOOST_CONCEPT_USAGE(VertexMutablePropertyGraph) {
v = add_vertex(vp, g);
}
G g;
@@ -347,12 +343,12 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
typename vertex_property<G>::type vp;
};
template <class G>
struct EdgeMutablePropertyGraphConcept
BOOST_concept(EdgeMutablePropertyGraph,(G))
: EdgeMutableGraph<G>
{
typedef typename graph_traits<G>::edge_descriptor edge_descriptor;
void constraints() {
function_requires< EdgeMutableGraphConcept<G> >();
BOOST_CONCEPT_USAGE(EdgeMutablePropertyGraph) {
p = add_edge(u, v, ep, g);
}
G g;
@@ -361,13 +357,12 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
typename edge_property<G>::type ep;
};
template <class G>
struct AdjacencyMatrixConcept
BOOST_concept(AdjacencyMatrix,(G))
: Graph<G>
{
typedef typename graph_traits<G>::edge_descriptor edge_descriptor;
void constraints() {
function_requires< GraphConcept<G> >();
BOOST_CONCEPT_USAGE(AdjacencyMatrix) {
p = edge(u, v, g);
const_constraints(g);
}
@@ -379,13 +374,14 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
G g;
};
template <class G, class X, class Property>
struct ReadablePropertyGraphConcept
BOOST_concept(ReadablePropertyGraph,(G)(X)(Property))
: Graph<G>
{
typedef typename property_map<G, Property>::const_type const_Map;
void constraints() {
function_requires< GraphConcept<G> >();
function_requires< ReadablePropertyMapConcept<const_Map, X> >();
BOOST_CONCEPT_USAGE(ReadablePropertyGraph)
{
BOOST_CONCEPT_ASSERT((ReadablePropertyMapConcept<const_Map, X>));
const_constraints(g);
}
@@ -399,13 +395,12 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
typename property_traits<const_Map>::value_type pval;
};
template <class G, class X, class Property>
struct PropertyGraphConcept
BOOST_concept(PropertyGraph,(G)(X)(Property))
: ReadablePropertyGraph<G, X, Property>
{
typedef typename property_map<G, Property>::type Map;
void constraints() {
function_requires< ReadablePropertyGraphConcept<G, X, Property> >();
function_requires< ReadWritePropertyMapConcept<Map, X> >();
BOOST_CONCEPT_USAGE(PropertyGraph) {
BOOST_CONCEPT_ASSERT((ReadWritePropertyMapConcept<Map, X>));
Map pmap = get(Property(), g);
pval = get(Property(), g, x);
@@ -417,14 +412,14 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
typename property_traits<Map>::value_type pval;
};
template <class G, class X, class Property>
struct LvaluePropertyGraphConcept
BOOST_concept(LvaluePropertyGraph,(G)(X)(Property))
: ReadablePropertyGraph<G, X, Property>
{
typedef typename property_map<G, Property>::type Map;
typedef typename property_map<G, Property>::const_type const_Map;
void constraints() {
function_requires< ReadablePropertyGraphConcept<G, X, Property> >();
function_requires< LvaluePropertyMapConcept<const_Map, X> >();
BOOST_CONCEPT_USAGE(LvaluePropertyGraph) {
BOOST_CONCEPT_ASSERT((LvaluePropertyMapConcept<const_Map, X>));
pval = get(Property(), g, x);
put(Property(), g, x, pval);
@@ -435,10 +430,9 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
};
// This needs to move out of the graph library
template <class B>
struct BufferConcept
BOOST_concept(Buffer,(B))
{
void constraints() {
BOOST_CONCEPT_USAGE(Buffer) {
b.push(t);
b.pop();
typename B::value_type& v = b.top();
@@ -457,13 +451,11 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
B b;
};
template <class C>
struct ColorValueConcept
BOOST_concept(ColorValue,(C))
: EqualityComparable<C>
, DefaultConstructible<C>
{
void constraints() {
function_requires< EqualityComparableConcept<C> >();
function_requires< DefaultConstructibleConcept<C> >();
BOOST_CONCEPT_USAGE(ColorValue) {
c = color_traits<C>::white();
c = color_traits<C>::gray();
c = color_traits<C>::black();
@@ -471,10 +463,9 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
C c;
};
template <class M, class I, class V>
struct BasicMatrixConcept
BOOST_concept(BasicMatrix,(M)(I)(V))
{
void constraints() {
BOOST_CONCEPT_USAGE(BasicMatrix) {
V& elt = A[i][j];
const_constraints(A);
ignore_unused_variable_warning(elt);
@@ -487,6 +478,33 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
I i, j;
};
} // end namespace concepts
using boost::concepts::MultiPassInputIteratorConcept;
using boost::concepts::GraphConcept;
using boost::concepts::IncidenceGraphConcept;
using boost::concepts::BidirectionalGraphConcept;
using boost::concepts::AdjacencyGraphConcept;
using boost::concepts::VertexListGraphConcept;
using boost::concepts::EdgeListGraphConcept;
using boost::concepts::VertexAndEdgeListGraphConcept;
using boost::concepts::EdgeMutableGraphConcept;
using boost::concepts::VertexMutableGraphConcept;
using boost::concepts::MutableGraphConcept;
using boost::concepts::MutableIncidenceGraphConcept;
using boost::concepts::MutableBidirectionalGraphConcept;
using boost::concepts::MutableEdgeListGraphConcept;
using boost::concepts::VertexMutablePropertyGraphConcept;
using boost::concepts::EdgeMutablePropertyGraphConcept;
using boost::concepts::AdjacencyMatrixConcept;
using boost::concepts::ReadablePropertyGraphConcept;
using boost::concepts::PropertyGraphConcept;
using boost::concepts::LvaluePropertyGraphConcept;
using boost::concepts::BufferConcept;
using boost::concepts::ColorValueConcept;
using boost::concepts::BasicMatrixConcept;
} // namespace boost
#include <boost/concept/detail/concept_undef.hpp>
#endif /* BOOST_GRAPH_CONCEPTS_H */

View File

@@ -10,6 +10,8 @@
#ifndef BOOST_GRAPH_SELECTORS_HPP
#define BOOST_GRAPH_SELECTORS_HPP
#include <boost/mpl/bool.hpp>
namespace boost {
//===========================================================================
@@ -17,18 +19,18 @@ namespace boost {
// and adjacency_matrix.
struct directedS { enum { is_directed = true, is_bidir = false };
typedef true_type is_directed_t;
typedef false_type is_bidir_t;
typedef mpl::true_ is_directed_t;
typedef mpl::false_ is_bidir_t;
};
struct undirectedS {
enum { is_directed = false, is_bidir = false };
typedef false_type is_directed_t;
typedef false_type is_bidir_t;
typedef mpl::false_ is_directed_t;
typedef mpl::false_ is_bidir_t;
};
struct bidirectionalS {
enum { is_directed = true, is_bidir = true };
typedef true_type is_directed_t;
typedef true_type is_bidir_t;
typedef mpl::true_ is_directed_t;
typedef mpl::true_ is_bidir_t;
};
} // namespace boost

View File

@@ -85,7 +85,7 @@ namespace boost {
for (; p.first != p.second; ++p.first) {
edge_t e = *p.first;
BOOST_CHECK(source(e, g) == u);
BOOST_CHECK(contains(adj, target(e, g)) == true);
BOOST_CHECK(container_contains(adj, target(e, g)) == true);
}
}
}
@@ -114,7 +114,7 @@ namespace boost {
for (; p.first != p.second; ++p.first) {
edge_t e = *p.first;
BOOST_CHECK(target(e, g) == v);
BOOST_CHECK(contains(inv_adj, source(e, g)) == true);
BOOST_CHECK(container_contains(inv_adj, source(e, g)) == true);
}
}
}
@@ -140,7 +140,7 @@ namespace boost {
BOOST_CHECK(deg_size_t(std::distance(p.first, p.second)) == adj.size());
for (; p.first != p.second; ++p.first) {
vertex_t v = *p.first;
BOOST_CHECK(contains(adj, v) == true);
BOOST_CHECK(container_contains(adj, v) == true);
}
}
}
@@ -155,7 +155,7 @@ namespace boost {
BOOST_CHECK(n == num_vertices(g));
for (; p.first != p.second; ++p.first) {
vertex_t v = *p.first;
BOOST_CHECK(contains(vertex_set, v) == true);
BOOST_CHECK(container_contains(vertex_set, v) == true);
}
}
@@ -172,8 +172,8 @@ namespace boost {
for (; p.first != p.second; ++p.first) {
edge_t e = *p.first;
BOOST_CHECK(any_if(edge_set, connects(source(e, g), target(e, g), g)));
BOOST_CHECK(contains(vertex_set, source(e, g)) == true);
BOOST_CHECK(contains(vertex_set, target(e, g)) == true);
BOOST_CHECK(container_contains(vertex_set, source(e, g)) == true);
BOOST_CHECK(container_contains(vertex_set, target(e, g)) == true);
}
}
@@ -232,7 +232,7 @@ namespace boost {
IsoMap iso_map(iso_vec.begin(), get(vertex_index, g));
copy_graph(g, cpy, orig_to_copy(iso_map));
bool parallel_edge_exists = contains(adjacent_vertices(u, g), v);
bool parallel_edge_exists = container_contains(adjacent_vertices(u, g), v);
std::pair<edge_t, bool> p = add_edge(u, v, g);
edge_t e = p.first;
@@ -249,7 +249,7 @@ namespace boost {
if (p.second == true) { // edge added
BOOST_CHECK(num_edges(g) == num_edges(cpy) + 1);
BOOST_CHECK(contains(out_edges(u, g), e) == true);
BOOST_CHECK(container_contains(out_edges(u, g), e) == true);
BOOST_CHECK((verify_isomorphism
(make_filtered_graph(g, ignore_edge(e)), cpy, iso_map)));

View File

@@ -0,0 +1,332 @@
// Copyright (C) 2006 Tiago de Paula Peixoto <tiago@forked.de>
// Copyright (C) 2004 The Trustees of Indiana University.
//
// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Authors: Douglas Gregor
// Andrew Lumsdaine
// Tiago de Paula Peixoto
#ifndef BOOST_GRAPH_GRAPHML_HPP
#define BOOST_GRAPH_GRAPHML_HPP
#include <boost/config.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/any.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/graph/graphviz.hpp> // for exceptions
#include <typeinfo>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/find.hpp>
#include <boost/mpl/for_each.hpp>
#include <exception>
#include <sstream>
namespace boost
{
/////////////////////////////////////////////////////////////////////////////
// Graph reader exceptions
/////////////////////////////////////////////////////////////////////////////
struct parse_error: public graph_exception
{
parse_error(const std::string& error) {statement = "parse error: " + error;}
virtual ~parse_error() throw() {}
virtual const char* what() const throw() {return statement.c_str();}
std::string statement;
};
class mutate_graph
{
public:
virtual ~mutate_graph() {}
virtual bool is_directed() const = 0;
virtual boost::any do_add_vertex() = 0;
virtual std::pair<boost::any,bool> do_add_edge(boost::any source, boost::any target) = 0;
virtual void
set_graph_property(const std::string& name, const std::string& value, const std::string& value_type) = 0;
virtual void
set_vertex_property(const std::string& name, boost::any vertex, const std::string& value, const std::string& value_type) = 0;
virtual void
set_edge_property(const std::string& name, boost::any edge, const std::string& value, const std::string& value_type) = 0;
};
template<typename MutableGraph>
class mutate_graph_impl : public mutate_graph
{
typedef typename graph_traits<MutableGraph>::vertex_descriptor vertex_descriptor;
typedef typename graph_traits<MutableGraph>::edge_descriptor edge_descriptor;
public:
mutate_graph_impl(MutableGraph& g, dynamic_properties& dp)
: m_g(g), m_dp(dp) { }
bool is_directed() const
{
return is_convertible<typename graph_traits<MutableGraph>::directed_category,
directed_tag>::value;
}
virtual any do_add_vertex()
{
return any(add_vertex(m_g));
}
virtual std::pair<any,bool> do_add_edge(any source, any target)
{
std::pair<edge_descriptor,bool> retval = add_edge(any_cast<vertex_descriptor>(source),
any_cast<vertex_descriptor>(target), m_g);
return std::make_pair(any(retval.first), retval.second);
}
virtual void
set_graph_property(const std::string& name, const std::string& value, const std::string& value_type)
{
bool type_found = false;
try
{
mpl::for_each<value_types>(put_property<MutableGraph,value_types>
(name, m_dp, m_g, value, value_type, m_type_names, type_found));
}
catch (bad_lexical_cast)
{
throw parse_error("invalid value \"" + value + "\" for key " +
name + " of type " + value_type);
}
if (!type_found)
throw parse_error("unrecognized type \"" + value_type +
"\" for key " + name);
}
virtual void
set_vertex_property(const std::string& name, any vertex, const std::string& value, const std::string& value_type)
{
bool type_found = false;
try
{
mpl::for_each<value_types>(put_property<vertex_descriptor,value_types>
(name, m_dp, any_cast<vertex_descriptor>(vertex),
value, value_type, m_type_names, type_found));
}
catch (bad_lexical_cast)
{
throw parse_error("invalid value \"" + value + "\" for key " +
name + " of type " + value_type);
}
if (!type_found)
throw parse_error("unrecognized type \"" + value_type +
"\" for key " + name);
}
virtual void
set_edge_property(const std::string& name, any edge, const std::string& value, const std::string& value_type)
{
bool type_found = false;
try
{
mpl::for_each<value_types>(put_property<edge_descriptor,value_types>
(name, m_dp, any_cast<edge_descriptor>(edge),
value, value_type, m_type_names, type_found));
}
catch (bad_lexical_cast)
{
throw parse_error("invalid value \"" + value + "\" for key " +
name + " of type " + value_type);
}
if (!type_found)
throw parse_error("unrecognized type \"" + value_type +
"\" for key " + name);
}
template <typename Key, typename ValueVector>
class put_property
{
public:
put_property(const std::string& name, dynamic_properties& dp, const Key& key,
const std::string& value, const std::string& value_type,
char** type_names, bool& type_found)
: m_name(name), m_dp(dp), m_key(key), m_value(value),
m_value_type(value_type), m_type_names(type_names),
m_type_found(type_found) {}
template <class Value>
void operator()(Value)
{
if (m_value_type == m_type_names[mpl::find<ValueVector,Value>::type::pos::value])
{
put(m_name, m_dp, m_key, lexical_cast<Value>(m_value));
m_type_found = true;
}
}
private:
const std::string& m_name;
dynamic_properties& m_dp;
const Key& m_key;
const std::string& m_value;
const std::string& m_value_type;
char** m_type_names;
bool& m_type_found;
};
protected:
MutableGraph& m_g;
dynamic_properties& m_dp;
typedef mpl::vector<bool, int, long, float, double, std::string> value_types;
static char* m_type_names[];
};
template<typename MutableGraph>
char* mutate_graph_impl<MutableGraph>::m_type_names[] = {"boolean", "int", "long", "float", "double", "string"};
void
read_graphml(std::istream& in, mutate_graph& g);
template<typename MutableGraph>
void
read_graphml(std::istream& in, MutableGraph& g, dynamic_properties& dp)
{
mutate_graph_impl<MutableGraph> mg(g,dp);
read_graphml(in, mg);
}
template <typename Types>
class get_type_name
{
public:
get_type_name(const std::type_info& type, char** type_names, std::string& type_name)
: m_type(type), m_type_names(type_names), m_type_name(type_name) {}
template <typename Type>
void operator()(Type)
{
if (typeid(Type) == m_type)
m_type_name = m_type_names[mpl::find<Types,Type>::type::pos::value];
}
private:
const std::type_info &m_type;
char** m_type_names;
std::string &m_type_name;
};
template <typename Graph, typename VertexIndexMap>
void
write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index,
const dynamic_properties& dp, bool ordered_vertices=false)
{
typedef typename graph_traits<Graph>::directed_category directed_category;
typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
BOOST_STATIC_CONSTANT(bool,
graph_is_directed =
(is_convertible<directed_category*, directed_tag*>::value));
out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
<< "<graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd\">\n";
typedef mpl::vector<bool, short, unsigned short, int, unsigned int, long, unsigned long, long long, unsigned long long, float, double, long double, std::string> value_types;
char* type_names[] = {"boolean", "int", "int", "int", "int", "long", "long", "long", "long", "float", "double", "double", "string"};
std::map<std::string, std::string> graph_key_ids;
std::map<std::string, std::string> vertex_key_ids;
std::map<std::string, std::string> edge_key_ids;
int key_count = 0;
// Output keys
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
{
std::string key_id = "key" + lexical_cast<std::string>(key_count++);
if (i->second->key() == typeid(Graph))
vertex_key_ids[i->first] = key_id;
else if (i->second->key() == typeid(vertex_descriptor))
vertex_key_ids[i->first] = key_id;
else if (i->second->key() == typeid(edge_descriptor))
edge_key_ids[i->first] = key_id;
else
continue;
std::string type_name = "string";
mpl::for_each<value_types>(get_type_name<value_types>(i->second->value(), type_names, type_name));
out << " <key id=\"" << key_id << "\" for=\""
<< (i->second->key() == typeid(Graph) ? "graph" : (i->second->key() == typeid(vertex_descriptor) ? "node" : "edge")) << "\""
<< " attr.name=\"" << i->first << "\""
<< " attr.type=\"" << type_name << "\""
<< " />\n";
}
out << " <graph id=\"G\" edgedefault=\""
<< (graph_is_directed ? "directed" : "undirected") << "\""
<< " parse.nodeids=\"" << (ordered_vertices ? "canonical" : "free") << "\""
<< " parse.edgeids=\"canonical\" parse.order=\"nodesfirst\">\n";
// Output graph data
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
{
if (i->second->key() == typeid(Graph))
{
out << " <data key=\"" << graph_key_ids[i->first] << "\">"
<< i->second->get_string(g) << "</data>\n";
}
}
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
vertex_iterator v, v_end;
for (tie(v, v_end) = vertices(g); v != v_end; ++v)
{
out << " <node id=\"n" << get(vertex_index, *v) << "\">\n";
// Output data
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
{
if (i->second->key() == typeid(vertex_descriptor))
{
out << " <data key=\"" << vertex_key_ids[i->first] << "\">"
<< i->second->get_string(*v) << "</data>\n";
}
}
out << " </node>\n";
}
typedef typename graph_traits<Graph>::edge_iterator edge_iterator;
edge_iterator e, e_end;
typename graph_traits<Graph>::edges_size_type edge_count = 0;
for (tie(e, e_end) = edges(g); e != e_end; ++e)
{
out << " <edge id=\"e" << edge_count++ << "\" source=\"n"
<< get(vertex_index, source(*e, g)) << "\" target=\"n"
<< get(vertex_index, target(*e, g)) << "\">\n";
// Output data
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
{
if (i->second->key() == typeid(edge_descriptor))
{
out << " <data key=\"" << edge_key_ids[i->first] << "\">"
<< i->second->get_string(*e) << "</data>\n";
}
}
out << " </edge>\n";
}
out << " </graph>\n"
<< "</graphml>\n";
}
template <typename Graph>
void
write_graphml(std::ostream& out, const Graph& g, const dynamic_properties& dp,
bool ordered_vertices=false)
{
write_graphml(out, g, get(vertex_index, g), dp, ordered_vertices);
}
} // boost namespace
#endif // BOOST_GRAPH_GRAPHML_HPP

View File

@@ -679,6 +679,9 @@ class mutate_graph
virtual void
set_edge_property(const id_t& key, const edge_t& edge, const id_t& value) = 0;
virtual void // RG: need new second parameter to support BGL subgraphs
set_graph_property(const id_t& key, const id_t& value) = 0;
};
template<typename MutableGraph>
@@ -740,6 +743,14 @@ class mutate_graph_impl : public mutate_graph
put(key, dp_, bgl_edges[edge], value);
}
void
set_graph_property(const id_t& key, const id_t& value)
{
/* RG: pointer to graph prevents copying */
put(key, dp_, &graph_, value);
}
protected:
MutableGraph& graph_;
dynamic_properties& dp_;

View File

@@ -0,0 +1,611 @@
/*!
* Copyright 2007 Technical University of Catalonia
*
* Use, modification and distribution is subject to the Boost Software
* License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Authors: Dmitry Bufistov
* Andrey Parfenov
*/
#ifndef BOOST_GRAPH_HOWARD_CYCLE_RATIO_HOWARD_HPP
#define BOOST_GRAPH_HOWARD_CYCLE_RATIO_HOWARD_HPP
/*!
* \file Maximum cycle ratio algorithm (Jean Cochet-Terrasson, Guy
* Cochen and others)
*/
#include <exception>
#include <set>
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/is_signed.hpp>
#include <boost/concept_check.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/reverse_graph.hpp>
#include <boost/graph/breadth_first_search.hpp>
#include <boost/graph/iteration_macros.hpp>
namespace boost {
namespace detail {
/// To avoid round error.
static const double mcr_howard_ltolerance = 0.00001;
/*!
* Calculate maximum cycle ratio of "good" directed multigraph
* g. Use Howard's iteration policy algorithm ("Numerical
* Computation of Spectral Elements in MAX-PLUS algebra" by Jean
* Cochet-Terrasson, Guy Cochen and others).
*
* \param g = (V, E) - a "good" directed multigraph (out_degree of
* each vertex is greater then 0). If graph is strongly connected
* then it is "good".
*
* \param vim - Vertex Index, read property Map: V -> [0,
* num_vertices(g)).
*
* \param ewm - edge weight read property map: E -> R
*
* \param ewm2 - edge weight2 read property map: E -> R+
*
* \return maximum_{for all cycles C}CR(C), or
* -(std::numeric_limits<double>)::max() if g is not "good".
*/
template <typename TGraph, typename TVertexIndexMap,
typename TWeight1EdgeMap, typename TWeight2EdgeMap >
class Cmcr_Howard
{
public:
Cmcr_Howard(const TGraph& g, TVertexIndexMap vim, TWeight1EdgeMap ewm,
TWeight2EdgeMap ew2m)
: m_g(g), m_vim(vim), m_ew1m(ewm), m_ew2m(ew2m),
m_g2pi_g_vm(std::vector<pi_vertex_t>().end(), m_vim), /// Stupid dummy initialization
m_minus_infinity(-(std::numeric_limits<double>::max)())
{
typedef typename boost::graph_traits<TGraph>::directed_category DirCat;
BOOST_STATIC_ASSERT((boost::is_convertible<DirCat*, boost::directed_tag*>::value == true));
m_cr = m_minus_infinity;
}
double operator()()
{
return maximum_cycle_ratio_Howard();
}
virtual ~Cmcr_Howard() { }
protected:
typedef typename boost::graph_traits<TGraph>::vertex_descriptor
mcr_vertex_t;
typedef typename boost::graph_traits<TGraph>::edge_descriptor
mcr_edge_t;
const TGraph& m_g;
typedef std::vector<double> eigenmode_t;
eigenmode_t m_eigen_value;
eigenmode_t m_eigen_vector;
TVertexIndexMap m_vim;
TWeight1EdgeMap m_ew1m;
TWeight2EdgeMap m_ew2m;
typedef typename boost::remove_const<typename boost::property_traits<TWeight1EdgeMap>::value_type>::type mcr_edge_weight1_t;
typedef typename boost::remove_const<typename boost::property_traits<TWeight2EdgeMap>::value_type>::type mcr_edge_weight2_t;
typedef typename boost::adjacency_list<
boost::listS, boost::vecS, boost::bidirectionalS,
boost::no_property,
boost::property<boost::edge_weight_t,
mcr_edge_weight1_t,
boost::property<boost::edge_weight2_t,
mcr_edge_weight2_t> > >
pi_graph_t;
typedef typename boost::property_map<pi_graph_t, boost::vertex_index_t>::type TPiGraphVertexIndexMap;
typedef typename boost::property_map<pi_graph_t, boost::edge_weight_t>::type TPiGraphEdgeWeight1Map;
typedef typename boost::property_map<pi_graph_t, boost::edge_weight2_t>::type TPiGraphEdgeWeight2Map;
typedef typename boost::property_traits<TPiGraphVertexIndexMap>::value_type pigraph_vertex_index_t;
pi_graph_t m_pi_g;
typedef typename boost::graph_traits<pi_graph_t>::vertex_descriptor pi_vertex_t;
typedef typename boost::graph_traits<pi_graph_t>::edge_descriptor pi_edge_t;
typedef typename boost::iterator_property_map<typename std::vector<pi_vertex_t>::iterator, TVertexIndexMap> g2pi_g_vm_t;
g2pi_g_vm_t m_g2pi_g_vm; ///Graph to Pi graph vertex map
std::vector<pi_vertex_t> m_g2pig;
int m_step_number;
const double m_minus_infinity;
typedef typename std::vector<mcr_edge_t> critical_cycle_t;
double m_cr; ///Cycle ratio that already has been found
class bad_graph
{
public:
typedef typename boost::property_traits<TVertexIndexMap>::value_type
v_index_t;
bad_graph(v_index_t bvi) : bad_vertex_index(bvi) {}
v_index_t what() const throw()
{
return bad_vertex_index;
}
private:
v_index_t bad_vertex_index;
};
double maximum_cycle_ratio_Howard()
{
try
{
construct_pi_graph();
}
catch (const bad_graph& a)
{
return m_minus_infinity;
}
std::vector<double> max_eigen_val(boost::num_vertices(m_g));
m_eigen_value.resize(boost::num_vertices(m_g));
m_eigen_vector.resize(boost::num_vertices(m_g));
m_step_number = 0;
do
{
pi_eingen_value(get(vertex_index, m_pi_g), get(boost::edge_weight, m_pi_g), get(boost::edge_weight2, m_pi_g));
++m_step_number;
}
while (improve_policy_try1(max_eigen_val) || improve_policy_try2(max_eigen_val));
return *(std::max_element(m_eigen_value.begin(), m_eigen_value.end()));
}
/*!
* Construct an arbitrary policy m_pi_g.
*/
void construct_pi_graph()
{
m_g2pig.resize(boost::num_vertices(m_g));
m_g2pi_g_vm = boost::make_iterator_property_map(m_g2pig.begin(), m_vim);
BGL_FORALL_VERTICES_T(vd, m_g, TGraph)
{
m_g2pi_g_vm[vd] = boost::add_vertex(m_pi_g);
store_pivertex(m_g2pi_g_vm[vd], vd);
}
BGL_FORALL_VERTICES_T(vd1, m_g, TGraph)
{
if (boost::out_edges(vd1, m_g).first == boost::out_edges(vd1, m_g).second) throw bad_graph(m_vim[vd1]);
mcr_edge_t ed = *boost::out_edges(vd1, m_g).first;
pi_edge_t pied = boost::add_edge(m_g2pi_g_vm[source(ed, m_g)], m_g2pi_g_vm[target(ed, m_g)], m_pi_g).first;
boost::put(boost::edge_weight, m_pi_g, pied, m_ew1m[ed]);
boost::put(boost::edge_weight2, m_pi_g, pied, m_ew2m[ed]);
}
}
class bfs_eingmode_visitor : public boost::default_bfs_visitor
{
public:
bfs_eingmode_visitor(TPiGraphVertexIndexMap vi_m, TPiGraphEdgeWeight1Map w_m, TPiGraphEdgeWeight2Map& d_m,
eigenmode_t& e_val, eigenmode_t& e_vec, double ev) : m_index_map(vi_m), m_weight_map(w_m), m_delay_map(d_m),
m_eig_value(&e_val), m_eig_vec(&e_vec), m_eigen_value(ev) { }
template < typename Edge, typename g_t>
void examine_edge(Edge e, const g_t & g) const
{
typedef typename boost::graph_traits<g_t>::vertex_descriptor Vertex;
Vertex u = boost::target(e, g), v = boost::source(e, g);
pigraph_vertex_index_t ind = m_index_map[u];
(*m_eig_value)[ind] = m_eigen_value;
(*m_eig_vec)[ind] = m_weight_map[e] - m_eigen_value * m_delay_map[e] + (*m_eig_vec)[m_index_map[v]];
}
private:
TPiGraphVertexIndexMap m_index_map;
TPiGraphEdgeWeight1Map m_weight_map;
TPiGraphEdgeWeight2Map m_delay_map;
eigenmode_t* m_eig_value;
eigenmode_t* m_eig_vec;
double m_eigen_value;
};
/*!
* Find a vertex in the Pi Graph which belongs to cycle, just a DFV until back edge found
*/
pi_vertex_t find_good_source(const pi_vertex_t start_vertex)
{
pi_vertex_t good_vertex = start_vertex;
typename std::set<pi_vertex_t> s;
s.insert(start_vertex);
do
{
good_vertex = boost::target(*boost::out_edges(good_vertex, m_pi_g).first, m_pi_g);
}
while (s.insert(good_vertex).second);
return good_vertex;
}
virtual void store_pivertex(pi_vertex_t pivd, mcr_vertex_t vd) {}
virtual void store_critical_edge(pi_edge_t ed, critical_cycle_t& cc) {}
virtual void store_critical_cycle(critical_cycle_t& cc) {}
/*!
* \param startV - vertex that belongs to a cycle in policy graph m_pi_g
*/
double calculate_eigen_value(pi_vertex_t startV)
{
std::pair<double, double> accum_sums(0., 0.);
pi_vertex_t vd = startV;
critical_cycle_t cc;
do
{
pi_edge_t tmp_ed = *(boost::out_edges(vd, m_pi_g).first);
store_critical_edge(tmp_ed, cc);
accum_sums.first += boost::get(boost::edge_weight, m_pi_g, tmp_ed);
accum_sums.second += boost::get(boost::edge_weight2, m_pi_g, tmp_ed);
vd = boost::target(tmp_ed, m_pi_g);
}
while (vd != startV);
//assert((std::abs<double>(accum_sums.first) <= 0.00000001) && "Division by zerro!");
double cr = accum_sums.first / accum_sums.second;
if (cr > m_cr)
{
m_cr = cr;
store_critical_cycle(cc);
}
else
{
}
return cr;
}
/*!
* Value determination. Find a generalized eigenmode (n^{k+1}, x^{k+1}) of A^{Ï_{k+1}} of the pi graph (Algorithm IV.1).
*/
void pi_eingen_value(
TPiGraphVertexIndexMap index_map,
TPiGraphEdgeWeight1Map weight_map,
TPiGraphEdgeWeight2Map weigh2_map)
{
using namespace boost;
typedef std::vector<default_color_type> color_map_t;
color_map_t vcm(num_vertices(m_pi_g), white_color);//Vertex color map
color_map_t::iterator uv_itr = vcm.begin(); //Undiscovered vertex
reverse_graph<pi_graph_t> rev_g(m_pi_g); //For backward breadth visit
while ((uv_itr = std::find_if(uv_itr, vcm.end(),
boost::bind(std::equal_to<default_color_type>(), boost::white_color, _1))) != vcm.end())
///While there are undiscovered vertices
{
pi_vertex_t gv = find_good_source(pi_vertex_t(uv_itr - vcm.begin()));
pigraph_vertex_index_t gv_ind = index_map[gv];
m_eigen_value[gv_ind] = calculate_eigen_value(gv) ;
bfs_eingmode_visitor bfs_vis(index_map, weight_map, weigh2_map, m_eigen_value, m_eigen_vector, m_eigen_value[gv_ind]);
typename boost::queue<pi_vertex_t> Q;
breadth_first_visit(rev_g, gv, Q, bfs_vis, make_iterator_property_map(vcm.begin(), index_map));
}
}
void improve_policy(mcr_vertex_t vd, mcr_edge_t new_edge)
{
remove_edge(*(out_edges(m_g2pi_g_vm[vd], m_pi_g).first), m_pi_g);
pi_edge_t ned = add_edge(m_g2pi_g_vm[vd], m_g2pi_g_vm[target(new_edge, m_g)], m_pi_g).first;
put(edge_weight, m_pi_g, ned, m_ew1m[new_edge]);
put(edge_weight2, m_pi_g, ned, m_ew2m[new_edge]);
}
/*!
* Policy Improvement. Improve the policy graph. The new policy graph has greater cycle ratio.
* \return false if nothing can be improved.
*/
bool improve_policy_try1(std::vector<double>& max_eing_vals)
{
bool improved = false;
BGL_FORALL_VERTICES_T(vd, m_g, TGraph)
{
double max_ev = m_minus_infinity;/// Maximum eigen value for vertex
mcr_edge_t cr_ed;///Critical edge
BGL_FORALL_OUTEDGES_T(vd, outed, m_g, TGraph)
{
if (m_eigen_value[m_vim[target(outed, m_g)]] > max_ev)
{
max_ev = m_eigen_value[m_vim[boost::target(outed, m_g)]];
cr_ed = outed;
}
}
if (max_ev > m_eigen_value[get(m_vim,vd)])
{
improve_policy(vd, cr_ed);
improved = true;
}
max_eing_vals[get(m_vim,vd)] = max_ev;
}
return improved;
}
/*!
* \param max_eigen_values[u] = max_(for all adjacent vertices (u,v)) m_eigen_value[v]
*/
bool improve_policy_try2(const std::vector<double>& max_eigen_values)
{
bool improved = false;
BGL_FORALL_VERTICES_T(vd, m_g, TGraph)
{
mcr_edge_t impr_edge;
double max_val = m_minus_infinity;
BGL_FORALL_OUTEDGES_T(vd, outed, m_g, TGraph)
{
///If vertex vd is in the K(vd) set
if (max_eigen_values[get(m_vim, vd)] <= m_eigen_value[get(m_vim, target(outed, m_g))])
{
double c_val = m_ew1m[outed] - m_ew2m[outed] * m_eigen_value[m_vim[boost::target(outed, m_g)]] +
m_eigen_vector[m_vim[boost::target(outed, m_g)]];
if (c_val > max_val)
{
max_val = c_val;
impr_edge = outed;
}
}
}
if ((max_val - m_eigen_vector[get(m_vim, vd)]) > mcr_howard_ltolerance)
///If m_eigen_vector[vd] == max_val
{
improve_policy(vd, impr_edge);
improved = true;
}
}
return improved;
}
};///Cmcr_Howard
/*!
* \return maximum cycle ratio and one critical cycle.
*/
template <typename TGraph, typename TVertexIndexMap, typename TWeight1EdgeMap, typename TWeight2EdgeMap>
class Cmcr_Howard1 : public Cmcr_Howard<TGraph, TVertexIndexMap, TWeight1EdgeMap, TWeight2EdgeMap>
{
public:
typedef Cmcr_Howard<TGraph, TVertexIndexMap, TWeight1EdgeMap, TWeight2EdgeMap> inhr_t;
Cmcr_Howard1(const TGraph& g, TVertexIndexMap vim, TWeight1EdgeMap ewm, TWeight2EdgeMap ew2m) : inhr_t(g, vim, ewm, ew2m)
{
m_pi_g2g.resize(boost::num_vertices(g));
m_pi_g2g_vm = boost::make_iterator_property_map(m_pi_g2g.begin(), boost::get(boost::vertex_index, this->m_pi_g));
}
void get_critical_cycle(typename inhr_t::critical_cycle_t& cc) { return cc.swap(m_critical_cycle); }
protected:
void store_pivertex(typename inhr_t::pi_vertex_t pivd, typename inhr_t::mcr_vertex_t vd)
{
m_pi_g2g_vm[pivd] = vd;
}
void store_critical_edge(typename inhr_t::pi_edge_t ed, typename inhr_t::critical_cycle_t& cc)
{
typename inhr_t::pi_vertex_t s = boost::source(ed, this->m_pi_g);
typename inhr_t::pi_vertex_t t = boost::target(ed, this->m_pi_g);
assert(boost::edge(m_pi_g2g_vm[s], m_pi_g2g_vm[t], this->m_g).second);
cc.push_back(boost::edge(m_pi_g2g_vm[s], m_pi_g2g_vm[t], this->m_g).first); ///Store corresponding edge of the m_g
}
void store_critical_cycle(typename inhr_t::critical_cycle_t& cc)
{
m_critical_cycle.swap(cc);
}
private:
typename inhr_t::critical_cycle_t m_critical_cycle;
typedef typename boost::iterator_property_map<typename std::vector<typename inhr_t::mcr_vertex_t>::iterator, typename inhr_t::TPiGraphVertexIndexMap> pi_g2g_vm_t;
pi_g2g_vm_t m_pi_g2g_vm; ///Maps policy graph vertices to input graph vertices
typename std::vector<typename inhr_t::mcr_vertex_t> m_pi_g2g;
};
/*!
* Add sink vertex - this will make any graph good, the selfloop will have ratio equal to infinity
* Properties must be "self increasing"
*/
template <typename TGraph, typename TWeight1EdgeMap, typename TWeight2EdgeMap>
typename boost::graph_traits<TGraph>::vertex_descriptor
make_graph_good(TGraph& g, TWeight1EdgeMap ewm, TWeight2EdgeMap ew2m,
typename boost::property_traits<TWeight1EdgeMap>::value_type infinity)
{
typedef typename boost::graph_traits<TGraph>::edge_descriptor Edge;
typename boost::graph_traits<TGraph>::vertex_descriptor sink = boost::add_vertex(g);
BGL_FORALL_VERTICES_T(vd, g, TGraph)
{
Edge newed = boost::add_edge(vd, sink, g).first;
boost::put(ewm, newed, 0);
boost::put(ew2m, newed, 1);
}
Edge selfed = boost::edge(sink, sink, g).first;
boost::put(ewm, selfed, infinity);
return sink;
}
/*!
* Construct from input graph g "safe" (suitable for maximum_cycle_ratio1() call) version - safeg
*/
template <typename TG, typename TIndVertexMap, typename TW1EdgeMap, typename TW2EdgeMap, typename TSafeG, typename SafeG2GEdgeMap>
void construct_safe_graph(const TG& g, TIndVertexMap vim, TW1EdgeMap ew1m, TW2EdgeMap ew2m, TSafeG& safeg, SafeG2GEdgeMap& sg2gm)
{
assert(num_vertices(g) == num_vertices(safeg));
typedef typename graph_traits<TSafeG>::edge_descriptor tmp_edge_t;
typedef typename graph_traits<TG>::edge_descriptor edge_t;
typename graph_traits<TG>::edge_iterator ei, ei_end;
for (tie(ei, ei_end) = edges(g); ei != ei_end; ++ei)
{
tmp_edge_t tmped = add_edge(vim[source(*ei, g)], vim[target(*ei, g)], safeg).first;
sg2gm[tmped] = *ei;
put(edge_weight, safeg, tmped, get(ew1m, *ei));
put(edge_weight2, safeg, tmped, get(ew2m, *ei));
}
}
template <typename TGraph, typename TVertexIndexMap, typename TWeight1EdgeMap, typename TWeight2EdgeMap>
double maximum_cycle_ratio_good_graph(const TGraph& g, TVertexIndexMap vim, TWeight1EdgeMap ewm, TWeight2EdgeMap ew2m,
typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0)
{
if (pcc == 0)
{
return detail::Cmcr_Howard<TGraph, TVertexIndexMap, TWeight1EdgeMap, TWeight2EdgeMap>(g, vim, ewm, ew2m)();
}
else
{
detail::Cmcr_Howard1<TGraph, TVertexIndexMap, TWeight1EdgeMap, TWeight2EdgeMap> obj(g, vim, ewm, ew2m);
double maxcr = obj();
obj.get_critical_cycle(*pcc);
return maxcr;
}
}
template <typename TGraph, typename TVertexIndexMap, typename TWeight1EdgeMap, typename TWeight2EdgeMap, typename TEdgeIndexMap>
double minimum_cycle_ratio_good_graph(const TGraph& g, TVertexIndexMap vim, TWeight1EdgeMap ewm,
TWeight2EdgeMap ew2m, TEdgeIndexMap eim,
typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0)
{
typedef typename boost::remove_const<typename boost::property_traits<TWeight1EdgeMap>::value_type>::type weight_value_t;
BOOST_STATIC_ASSERT(!is_integral<weight_value_t>::value || is_signed<weight_value_t>::value);
typename std::vector<weight_value_t> ne_w(boost::num_edges(g));
BGL_FORALL_EDGES_T(ed, g, TGraph) ne_w[boost::get(eim, ed)] = -ewm[ed];
return -maximum_cycle_ratio_good_graph(g, vim, boost::make_iterator_property_map(ne_w.begin(), eim), ew2m, pcc);
}
/*!
* \param g directed multigraph.
* \param pcc - pointer to the critical edges list.
* \param minus_infinity must be small enough to garanty that g has at least one cycle with greater ratio.
* \return minus_infinity if there're no cycles in the graph
*/
template <typename TGraph, typename TWeight1EdgeMap, typename TWeight2EdgeMap>
double maximum_cycle_ratio1(const TGraph& g, TWeight1EdgeMap ewm, TWeight2EdgeMap ew2m,
typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0,
typename boost::property_traits<TWeight1EdgeMap>::value_type minus_infinity = -(std::numeric_limits<int>::max)())
{
typedef typename boost::graph_traits<TGraph>::vertex_descriptor Vertex;
typedef typename boost::graph_traits<TGraph>::edge_descriptor Edge;
boost::function_requires< boost::ReadWritePropertyMapConcept<TWeight1EdgeMap, Edge> >();
boost::function_requires< boost::ReadWritePropertyMapConcept<TWeight2EdgeMap, Edge> >();
TGraph& ncg = const_cast<TGraph&>(g);
Vertex sink = detail::make_graph_good(ncg, ewm, ew2m, minus_infinity );
double res = maximum_cycle_ratio_good_graph(ncg, boost::get(boost::vertex_index, g), ewm, ew2m, pcc);
boost::clear_vertex(sink, ncg); boost::remove_vertex(sink, ncg);
return res;
}
/*!
* Edge index MUST be in diapazon [0,..., num_edges(g)-1]
* \return plus_infinity if g has no cycles.
*/
template <typename TGraph, typename TWeight1EdgeMap, typename TWeight2EdgeMap, typename TEdgeIndexMap>
double minimum_cycle_ratio1(const TGraph& g, TWeight1EdgeMap ewm, TWeight2EdgeMap ew2m, TEdgeIndexMap eim,
typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0,
typename boost::property_traits<TWeight1EdgeMap>::value_type plus_infinity = (std::numeric_limits<int>::max)()
)
{
typedef typename boost::property_traits<TEdgeIndexMap>::value_type ei_t;
typedef typename boost::graph_traits<TGraph>::vertex_descriptor Vertex;
typedef typename boost::graph_traits<TGraph>::edge_descriptor Edge;
boost::function_requires< boost::ReadWritePropertyMapConcept<TWeight1EdgeMap, Edge> >();
boost::function_requires< boost::ReadWritePropertyMapConcept<TWeight2EdgeMap, Edge> >();
boost::function_requires< boost::ReadWritePropertyMapConcept<TEdgeIndexMap, Edge> >();
TGraph& ncg = const_cast<TGraph&>(g);
ei_t nei = ei_t(boost::num_edges(g));
Vertex sink = detail::make_graph_good(ncg, ewm, ew2m, plus_infinity );
///Maintain edge index invariant
BGL_FORALL_VERTICES_T(vd, ncg, TGraph)
{
typename boost::graph_traits<TGraph>::edge_descriptor ed = boost::edge(vd, sink, ncg).first;
boost::put(eim, ed, nei++);
}
double res = minimum_cycle_ratio_good_graph(ncg, boost::get(boost::vertex_index, ncg), ewm, ew2m, eim, pcc);
boost::clear_vertex(sink, ncg); boost::remove_vertex(sink, ncg);
return res;
}
struct edge_less_than
{
template <typename TEdgeDescriptor> bool operator()(const TEdgeDescriptor& x, const TEdgeDescriptor& y) const
{
return x.get_property() < y.get_property();
}
};
}///namespace detail
namespace
{
template <typename TW1, typename TW2> struct safe_graph
{
typedef typename boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, boost::no_property,
typename boost::property<boost::edge_weight_t, TW1, typename boost::property<boost::edge_weight2_t, TW2> > > type;
};
}
/*!
* Calculate the maximum cycle ratio (mcr) of the directed multigraph g.
* \param g directed multigraph
* \param pcc - If provided then a critical cycle will be written to corresponding vector.
* \param minus_infinity small enough value to garanty that g has at least one cycle with greater ratio.
* \return mcr or minus_infinity if g has no cycles.
*/
template <typename TGraph, typename TVertexIndexMap, typename TW1EdgeMap, typename TW2EdgeMap>
double maximum_cycle_ratio(const TGraph& g, TVertexIndexMap vim, TW1EdgeMap ew1m, TW2EdgeMap ew2m,
typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0,
typename boost::property_traits<TW1EdgeMap>::value_type minus_infinity =
-(std::numeric_limits<int>::max)())
{
typedef typename remove_const<typename property_traits<TW1EdgeMap>::value_type>::type w1_t;
typedef typename remove_const<typename property_traits<TW2EdgeMap>::value_type>::type w2_t;
typedef typename safe_graph<w1_t, w2_t>::type safe_graph_t;
typedef typename graph_traits<safe_graph_t>::edge_descriptor tmp_edge_t;
typedef typename graph_traits<TGraph>::edge_descriptor edge_t;
typename std::map<tmp_edge_t, edge_t, detail::edge_less_than> tmpg2g;
std::vector<tmp_edge_t> cc;
safe_graph_t sg(num_vertices(g));
detail::construct_safe_graph(g, vim, ew1m, ew2m, sg, tmpg2g);
double mcr = maximum_cycle_ratio1(sg, get(edge_weight, sg), get(edge_weight2, sg), pcc ? &cc : 0, minus_infinity);
if (pcc && (mcr > minus_infinity))
{
pcc->clear();
for (typename std::vector<tmp_edge_t>::iterator it = cc.begin(); it != cc.end(); ++it) pcc->push_back(tmpg2g[*it]);
}
return mcr;
}
template <typename TGraph, typename TVertexIndexMap, typename TW1EdgeMap, typename TW2EdgeMap, typename TIndEdgeMap>
double minimum_cycle_ratio(const TGraph& g, TVertexIndexMap vim, TW1EdgeMap ew1m, TW2EdgeMap ew2m, TIndEdgeMap eim,
typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0,
typename boost::property_traits<TW1EdgeMap>::value_type plus_infinity =
(std::numeric_limits<int>::max)())
{
typedef typename boost::remove_const<typename boost::property_traits<TW1EdgeMap>::value_type>::type weight_value_t;
BOOST_STATIC_ASSERT(!is_integral<weight_value_t>::value || is_signed<weight_value_t>::value);
typename std::vector<weight_value_t> ne_w(boost::num_edges(g));
BGL_FORALL_EDGES_T(ed, g, TGraph) ne_w[boost::get(eim, ed)] = -ew1m[ed];
return -maximum_cycle_ratio(g, vim, boost::make_iterator_property_map(ne_w.begin(), eim), ew2m, pcc, -plus_infinity);
}
/*!
* Calculate maximum mean cycle of directed weighted multigraph.
* \param g directed multigraph
* \return maximum mean cycle of g or minus_infinity if g has no cycles.
*/
template <typename TGraph, typename TVertexIndexMap, typename TWeightEdgeMap, typename TIndEdgeMap>
double maximum_mean_cycle(const TGraph& g, TVertexIndexMap vim, TWeightEdgeMap ewm, TIndEdgeMap eim,
typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0,
typename boost::property_traits<TWeightEdgeMap>::value_type minus_infinity =
-(std::numeric_limits<int>::max)())
{
typedef typename boost::remove_const<typename boost::property_traits<TWeightEdgeMap>::value_type>::type weight_value_t;
typedef typename boost::graph_traits<TGraph>::edge_descriptor Edge;
typename std::vector<weight_value_t> ed_w2(boost::num_edges(g), 1);
return maximum_cycle_ratio(g, vim, ewm, boost::make_iterator_property_map(ed_w2.begin(), eim), pcc, minus_infinity);
}
template <typename TGraph, typename TVertexIndexMap, typename TWeightEdgeMap, typename TIndEdgeMap>
double minimum_mean_cycle(const TGraph& g, TVertexIndexMap vim, TWeightEdgeMap ewm, TIndEdgeMap eim,
typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0,
typename boost::property_traits<TWeightEdgeMap>::value_type plus_infinity =
(std::numeric_limits<int>::max)())
{
typedef typename boost::remove_const<typename boost::property_traits<TWeightEdgeMap>::value_type>::type weight_value_t;
typedef typename boost::graph_traits<TGraph>::edge_descriptor Edge;
typename std::vector<weight_value_t> ed_w2(boost::num_edges(g), 1);
return minimum_cycle_ratio(g, vim, ewm, boost::make_iterator_property_map(ed_w2.begin(), eim), eim, pcc, plus_infinity);
}
} //namespace boost
#endif

View File

@@ -0,0 +1,332 @@
//=======================================================================
// Copyright 2007 Aaron Windsor
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
#ifndef __IS_KURATOWSKI_SUBGRAPH_HPP__
#define __IS_KURATOWSKI_SUBGRAPH_HPP__
#include <boost/config.hpp>
#include <boost/utility.hpp> //for next/prior
#include <boost/tuple/tuple.hpp> //for tie
#include <boost/property_map.hpp>
#include <boost/graph/properties.hpp>
#include <boost/graph/isomorphism.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <algorithm>
#include <vector>
#include <set>
namespace boost
{
namespace detail
{
template <typename Graph>
Graph make_K_5()
{
typename graph_traits<Graph>::vertex_iterator vi, vi_end, inner_vi;
Graph K_5(5);
for(tie(vi,vi_end) = vertices(K_5); vi != vi_end; ++vi)
for(inner_vi = next(vi); inner_vi != vi_end; ++inner_vi)
add_edge(*vi, *inner_vi, K_5);
return K_5;
}
template <typename Graph>
Graph make_K_3_3()
{
typename graph_traits<Graph>::vertex_iterator
vi, vi_end, bipartition_start, inner_vi;
Graph K_3_3(6);
bipartition_start = next(next(next(vertices(K_3_3).first)));
for(tie(vi, vi_end) = vertices(K_3_3); vi != bipartition_start; ++vi)
for(inner_vi= bipartition_start; inner_vi != vi_end; ++inner_vi)
add_edge(*vi, *inner_vi, K_3_3);
return K_3_3;
}
template <typename AdjacencyList, typename Vertex>
void contract_edge(AdjacencyList& neighbors, Vertex u, Vertex v)
{
// Remove u from v's neighbor list
neighbors[v].erase(std::remove(neighbors[v].begin(),
neighbors[v].end(), u
),
neighbors[v].end()
);
// Replace any references to u with references to v
typedef typename AdjacencyList::value_type::iterator
adjacency_iterator_t;
adjacency_iterator_t u_neighbor_end = neighbors[u].end();
for(adjacency_iterator_t u_neighbor_itr = neighbors[u].begin();
u_neighbor_itr != u_neighbor_end; ++u_neighbor_itr
)
{
Vertex u_neighbor(*u_neighbor_itr);
std::replace(neighbors[u_neighbor].begin(),
neighbors[u_neighbor].end(), u, v
);
}
// Remove v from u's neighbor list
neighbors[u].erase(std::remove(neighbors[u].begin(),
neighbors[u].end(), v
),
neighbors[u].end()
);
// Add everything in u's neighbor list to v's neighbor list
std::copy(neighbors[u].begin(),
neighbors[u].end(),
std::back_inserter(neighbors[v])
);
// Clear u's neighbor list
neighbors[u].clear();
}
} // namespace detail
template <typename Graph, typename ForwardIterator, typename VertexIndexMap>
bool is_kuratowski_subgraph(const Graph& g,
ForwardIterator begin,
ForwardIterator end,
VertexIndexMap vm
)
{
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
typedef typename graph_traits<Graph>::edges_size_type e_size_t;
typedef typename graph_traits<Graph>::vertices_size_type v_size_t;
typedef typename std::vector<vertex_t> v_list_t;
typedef typename v_list_t::iterator v_list_iterator_t;
typedef iterator_property_map
<typename std::vector<v_list_t>::iterator, VertexIndexMap>
vertex_to_v_list_map_t;
typedef adjacency_list<vecS, vecS, undirectedS> small_graph_t;
enum target_graph_t { k_3_3, k_5};
target_graph_t target_graph = k_3_3; //unless we decide otherwise later
static small_graph_t K_5(detail::make_K_5<small_graph_t>());
static small_graph_t K_3_3(detail::make_K_3_3<small_graph_t>());
v_size_t n_vertices(num_vertices(g));
v_size_t max_num_edges(3*n_vertices - 5);
std::vector<v_list_t> neighbors_vector(n_vertices);
vertex_to_v_list_map_t neighbors(neighbors_vector.begin(), vm);
e_size_t count = 0;
for(ForwardIterator itr = begin; itr != end; ++itr)
{
if (count++ > max_num_edges)
return false;
edge_t e(*itr);
vertex_t u(source(e,g));
vertex_t v(target(e,g));
neighbors[u].push_back(v);
neighbors[v].push_back(u);
}
for(v_size_t max_size = 2; max_size < 5; ++max_size)
{
vertex_iterator_t vi, vi_end;
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
{
vertex_t v(*vi);
//a hack to make sure we don't contract the middle edge of a path
//of four degree-3 vertices
if (max_size == 4 && neighbors[v].size() == 3)
{
if (neighbors[neighbors[v][0]].size() +
neighbors[neighbors[v][1]].size() +
neighbors[neighbors[v][2]].size()
< 11 // so, it has two degree-3 neighbors
)
continue;
}
while (neighbors[v].size() > 0 && neighbors[v].size() < max_size)
{
// Find one of v's neighbors u such that that v and u
// have no neighbors in common. We'll look for such a
// neighbor with a naive cubic-time algorithm since the
// max size of any of the neighbor sets we'll consider
// merging is 3
bool neighbor_sets_intersect = false;
vertex_t min_u = graph_traits<Graph>::null_vertex();
vertex_t u;
v_list_iterator_t v_neighbor_end = neighbors[v].end();
for(v_list_iterator_t v_neighbor_itr = neighbors[v].begin();
v_neighbor_itr != v_neighbor_end;
++v_neighbor_itr
)
{
neighbor_sets_intersect = false;
u = *v_neighbor_itr;
v_list_iterator_t u_neighbor_end = neighbors[u].end();
for(v_list_iterator_t u_neighbor_itr =
neighbors[u].begin();
u_neighbor_itr != u_neighbor_end &&
!neighbor_sets_intersect;
++u_neighbor_itr
)
{
for(v_list_iterator_t inner_v_neighbor_itr =
neighbors[v].begin();
inner_v_neighbor_itr != v_neighbor_end;
++inner_v_neighbor_itr
)
{
if (*u_neighbor_itr == *inner_v_neighbor_itr)
{
neighbor_sets_intersect = true;
break;
}
}
}
if (!neighbor_sets_intersect &&
(min_u == graph_traits<Graph>::null_vertex() ||
neighbors[u].size() < neighbors[min_u].size())
)
{
min_u = u;
}
}
if (min_u == graph_traits<Graph>::null_vertex())
// Exited the loop without finding an appropriate neighbor of
// v, so v must be a lost cause. Move on to other vertices.
break;
else
u = min_u;
detail::contract_edge(neighbors, u, v);
}//end iteration over v's neighbors
}//end iteration through vertices v
if (max_size == 3)
{
// check to see whether we should go on to find a K_5
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
if (neighbors[*vi].size() == 4)
{
target_graph = k_5;
break;
}
if (target_graph == k_3_3)
break;
}
}//end iteration through max degree 2,3, and 4
//Now, there should only be 5 or 6 vertices with any neighbors. Find them.
v_list_t main_vertices;
vertex_iterator_t vi, vi_end;
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
{
if (!neighbors[*vi].empty())
main_vertices.push_back(*vi);
}
// create a graph isomorphic to the contracted graph to test
// against K_5 and K_3_3
small_graph_t contracted_graph(main_vertices.size());
std::map<vertex_t,typename graph_traits<small_graph_t>::vertex_descriptor>
contracted_vertex_map;
typename v_list_t::iterator itr, itr_end;
itr_end = main_vertices.end();
typename graph_traits<small_graph_t>::vertex_iterator
si = vertices(contracted_graph).first;
for(itr = main_vertices.begin(); itr != itr_end; ++itr, ++si)
{
contracted_vertex_map[*itr] = *si;
}
typename v_list_t::iterator jtr, jtr_end;
for(itr = main_vertices.begin(); itr != itr_end; ++itr)
{
jtr_end = neighbors[*itr].end();
for(jtr = neighbors[*itr].begin(); jtr != jtr_end; ++jtr)
{
if (get(vm,*itr) < get(vm,*jtr))
{
add_edge(contracted_vertex_map[*itr],
contracted_vertex_map[*jtr],
contracted_graph
);
}
}
}
if (target_graph == k_5)
{
return isomorphism(K_5,contracted_graph);
}
else //target_graph == k_3_3
{
return isomorphism(K_3_3,contracted_graph);
}
}
template <typename Graph, typename ForwardIterator>
bool is_kuratowski_subgraph(const Graph& g,
ForwardIterator begin,
ForwardIterator end
)
{
return is_kuratowski_subgraph(g, begin, end, get(vertex_index,g));
}
}
#endif //__IS_KURATOWSKI_SUBGRAPH_HPP__

View File

@@ -0,0 +1,232 @@
//=======================================================================
// Copyright 2007 Aaron Windsor
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
#ifndef __IS_STRAIGHT_LINE_DRAWING_HPP__
#define __IS_STRAIGHT_LINE_DRAWING_HPP__
#include <boost/config.hpp>
#include <boost/utility.hpp> //for next and prior
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
#include <boost/property_map.hpp>
#include <boost/graph/properties.hpp>
#include <boost/graph/planar_detail/bucket_sort.hpp>
#include <algorithm>
#include <vector>
#include <set>
namespace boost
{
// Return true exactly when the line segments s1 = ((x1,y1), (x2,y2)) and
// s2 = ((a1,b1), (a2,b2)) intersect in a point other than the endpoints of
// the line segments. The one exception to this rule is when s1 = s2, in
// which case false is returned - this is to accomodate multiple edges
// between the same pair of vertices, which shouldn't invalidate the straight
// line embedding. A tolerance variable epsilon can also be used, which
// defines how far away from the endpoints of s1 and s2 we want to consider
// an intersection.
bool intersects(double x1, double y1,
double x2, double y2,
double a1, double b1,
double a2, double b2,
double epsilon = 0.000001
)
{
if (x1 - x2 == 0)
{
std::swap(x1,a1);
std::swap(y1,b1);
std::swap(x2,a2);
std::swap(y2,b2);
}
if (x1 - x2 == 0)
{
BOOST_USING_STD_MAX();
BOOST_USING_STD_MIN();
//two vertical line segments
double min_y = min BOOST_PREVENT_MACRO_SUBSTITUTION(y1,y2);
double max_y = max BOOST_PREVENT_MACRO_SUBSTITUTION(y1,y2);
double min_b = min BOOST_PREVENT_MACRO_SUBSTITUTION(b1,b2);
double max_b = max BOOST_PREVENT_MACRO_SUBSTITUTION(b1,b2);
if ((max_y > max_b && max_b > min_y) ||
(max_b > max_y && max_y > min_b)
)
return true;
else
return false;
}
double x_diff = x1 - x2;
double y_diff = y1 - y2;
double a_diff = a2 - a1;
double b_diff = b2 - b1;
double beta_denominator = b_diff - (y_diff/((double)x_diff)) * a_diff;
if (beta_denominator == 0)
{
//parallel lines
return false;
}
double beta = (b2 - y2 - (y_diff/((double)x_diff)) * (a2 - x2)) /
beta_denominator;
double alpha = (a2 - x2 - beta*(a_diff))/x_diff;
double upper_bound = 1 - epsilon;
double lower_bound = 0 + epsilon;
return (beta < upper_bound && beta > lower_bound &&
alpha < upper_bound && alpha > lower_bound);
}
template <typename Graph,
typename GridPositionMap,
typename VertexIndexMap
>
bool is_straight_line_drawing(const Graph& g,
GridPositionMap drawing,
VertexIndexMap vm
)
{
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
typedef typename graph_traits<Graph>::edge_iterator edge_iterator_t;
typedef typename graph_traits<Graph>::edges_size_type e_size_t;
typedef typename graph_traits<Graph>::vertices_size_type v_size_t;
typedef std::size_t x_coord_t;
typedef std::size_t y_coord_t;
typedef boost::tuple<edge_t, x_coord_t, y_coord_t> edge_event_t;
typedef typename std::vector< edge_event_t > edge_event_queue_t;
typedef tuple<y_coord_t, y_coord_t, x_coord_t, x_coord_t> active_map_key_t;
typedef edge_t active_map_value_t;
typedef std::map< active_map_key_t, active_map_value_t > active_map_t;
typedef typename active_map_t::iterator active_map_iterator_t;
edge_event_queue_t edge_event_queue;
active_map_t active_edges;
edge_iterator_t ei, ei_end;
for(tie(ei,ei_end) = edges(g); ei != ei_end; ++ei)
{
edge_t e(*ei);
vertex_t s(source(e,g));
vertex_t t(target(e,g));
edge_event_queue.push_back
(make_tuple(e,
static_cast<std::size_t>(drawing[s].x),
static_cast<std::size_t>(drawing[s].y)
)
);
edge_event_queue.push_back
(make_tuple(e,
static_cast<std::size_t>(drawing[t].x),
static_cast<std::size_t>(drawing[t].y)
)
);
}
// Order by edge_event_queue by first, then second coordinate
// (bucket_sort is a stable sort.)
bucket_sort(edge_event_queue.begin(), edge_event_queue.end(),
property_map_tuple_adaptor<edge_event_t, 2>()
);
bucket_sort(edge_event_queue.begin(), edge_event_queue.end(),
property_map_tuple_adaptor<edge_event_t, 1>()
);
typedef typename edge_event_queue_t::iterator event_queue_iterator_t;
event_queue_iterator_t itr_end = edge_event_queue.end();
for(event_queue_iterator_t itr = edge_event_queue.begin();
itr != itr_end; ++itr
)
{
edge_t e(get<0>(*itr));
vertex_t source_v(source(e,g));
vertex_t target_v(target(e,g));
if (drawing[source_v].x > drawing[target_v].x)
std::swap(source_v, target_v);
active_map_key_t key(get(drawing, source_v).y,
get(drawing, target_v).y,
get(drawing, source_v).x,
get(drawing, target_v).x
);
active_map_iterator_t a_itr = active_edges.find(key);
if (a_itr == active_edges.end())
{
active_edges[key] = e;
}
else
{
active_map_iterator_t before, after;
if (a_itr == active_edges.begin())
before = active_edges.end();
else
before = prior(a_itr);
after = next(a_itr);
if (after != active_edges.end() || before != active_edges.end())
{
edge_t f = after != active_edges.end() ?
after->second : before->second;
vertex_t e_source(source(e,g));
vertex_t e_target(target(e,g));
vertex_t f_source(source(f,g));
vertex_t f_target(target(f,g));
if (intersects(drawing[e_source].x,
drawing[e_source].y,
drawing[e_target].x,
drawing[e_target].y,
drawing[f_source].x,
drawing[f_source].y,
drawing[f_target].x,
drawing[f_target].y
)
)
return false;
}
active_edges.erase(a_itr);
}
}
return true;
}
template <typename Graph, typename GridPositionMap>
bool is_straight_line_drawing(const Graph& g, GridPositionMap drawing)
{
return is_straight_line_drawing(g, drawing, get(vertex_index,g));
}
}
#endif // __IS_STRAIGHT_LINE_DRAWING_HPP__

View File

@@ -245,7 +245,7 @@ namespace boost {
}
else {
if (contains(adjacent_vertices(f[i], G2), f[j])) {
if (container_contains(adjacent_vertices(f[i], G2), f[j])) {
++num_edges_on_k;
if (match(next(iter), dfs_num_k))
return true;

View File

@@ -27,7 +27,6 @@
#include <boost/graph/bellman_ford_shortest_paths.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/pending/ct_if.hpp>
#include <boost/type_traits/same_traits.hpp>
namespace boost {

View File

@@ -0,0 +1,807 @@
// Copyright (c) 2006, Stephan Diederich
//
// This code may be used under either of the following two licences:
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE. OF SUCH DAMAGE.
//
// Or:
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_KOLMOGOROV_MAX_FLOW_HPP
#define BOOST_KOLMOGOROV_MAX_FLOW_HPP
#include <boost/config.hpp>
#include <cassert>
#include <vector>
#include <list>
#include <utility>
#include <iosfwd>
#include <algorithm> // for std::min and std::max
#include <boost/pending/queue.hpp>
#include <boost/limits.hpp>
#include <boost/property_map.hpp>
#include <boost/none_t.hpp>
#include <boost/graph/graph_concepts.hpp>
#include <boost/graph/named_function_params.hpp>
namespace boost {
namespace detail {
template <class Graph,
class EdgeCapacityMap,
class ResidualCapacityEdgeMap,
class ReverseEdgeMap,
class PredecessorMap,
class ColorMap,
class DistanceMap,
class IndexMap>
class kolmogorov{
typedef typename property_traits<EdgeCapacityMap>::value_type tEdgeVal;
typedef graph_traits<Graph> tGraphTraits;
typedef typename tGraphTraits::vertex_iterator vertex_iterator;
typedef typename tGraphTraits::vertex_descriptor vertex_descriptor;
typedef typename tGraphTraits::edge_descriptor edge_descriptor;
typedef typename tGraphTraits::edge_iterator edge_iterator;
typedef typename tGraphTraits::out_edge_iterator out_edge_iterator;
typedef boost::queue<vertex_descriptor> tQueue; //queue of vertices, used in adoption-stage
typedef typename property_traits<ColorMap>::value_type tColorValue;
typedef color_traits<tColorValue> tColorTraits;
typedef typename property_traits<DistanceMap>::value_type tDistanceVal;
public:
kolmogorov(Graph& g,
EdgeCapacityMap cap,
ResidualCapacityEdgeMap res,
ReverseEdgeMap rev,
PredecessorMap pre,
ColorMap color,
DistanceMap dist,
IndexMap idx,
vertex_descriptor src,
vertex_descriptor sink):
m_g(g),
m_index_map(idx),
m_cap_map(cap),
m_res_cap_map(res),
m_rev_edge_map(rev),
m_pre_map(pre),
m_tree_map(color),
m_dist_map(dist),
m_source(src),
m_sink(sink),
m_active_nodes(),
m_in_active_list_vec(num_vertices(g), false),
m_in_active_list_map(make_iterator_property_map(m_in_active_list_vec.begin(), m_index_map)),
m_has_parent_vec(num_vertices(g), false),
m_has_parent_map(make_iterator_property_map(m_has_parent_vec.begin(), m_index_map)),
m_time_vec(num_vertices(g), 0),
m_time_map(make_iterator_property_map(m_time_vec.begin(), m_index_map)),
m_flow(0),
m_time(1),
m_last_grow_vertex(graph_traits<Graph>::null_vertex()){
// initialize the color-map with gray-values
vertex_iterator vi, v_end;
for(tie(vi, v_end) = vertices(m_g); vi != v_end; ++vi){
set_tree(*vi, tColorTraits::gray());
}
// Initialize flow to zero which means initializing
// the residual capacity equal to the capacity
edge_iterator ei, e_end;
for(tie(ei, e_end) = edges(m_g); ei != e_end; ++ei) {
m_res_cap_map[*ei] = m_cap_map[*ei];
assert(m_rev_edge_map[m_rev_edge_map[*ei]] == *ei); //check if the reverse edge map is build up properly
}
//init the search trees with the two terminals
set_tree(m_source, tColorTraits::black());
set_tree(m_sink, tColorTraits::white());
m_time_map[m_source] = 1;
m_time_map[m_sink] = 1;
}
~kolmogorov(){}
tEdgeVal max_flow(){
//augment direct paths from SOURCE->SINK and SOURCE->VERTEX->SINK
augment_direct_paths();
//start the main-loop
while(true){
bool path_found;
edge_descriptor connecting_edge;
tie(connecting_edge, path_found) = grow(); //find a path from source to sink
if(!path_found){
//we're finished, no more paths were found
break;
}
++m_time;
augment(connecting_edge); //augment that path
adopt(); //rebuild search tree structure
}
return m_flow;
}
//the complete class is protected, as we want access to members in derived test-class (see $(BOOST_ROOT)/libs/graph/test/kolmogorov_max_flow_test.cpp)
protected:
void augment_direct_paths(){
//in a first step, we augment all direct paths from source->NODE->sink
//and additionally paths from source->sink
//this improves especially graphcuts for segmentation, as most of the nodes have source/sink connects
//but shouldn't have an impact on other maxflow problems (this is done in grow() anyway)
out_edge_iterator ei, e_end;
for(tie(ei, e_end) = out_edges(m_source, m_g); ei != e_end; ++ei){
edge_descriptor from_source = *ei;
vertex_descriptor current_node = target(from_source, m_g);
if(current_node == m_sink){
tEdgeVal cap = m_res_cap_map[from_source];
m_res_cap_map[from_source] = 0;
m_flow += cap;
continue;
}
edge_descriptor to_sink;
bool is_there;
tie(to_sink, is_there) = edge(current_node, m_sink, m_g);
if(is_there){
tEdgeVal cap_from_source = m_res_cap_map[from_source];
tEdgeVal cap_to_sink = m_res_cap_map[to_sink];
if(cap_from_source > cap_to_sink){
set_tree(current_node, tColorTraits::black());
add_active_node(current_node);
set_edge_to_parent(current_node, from_source);
m_dist_map[current_node] = 1;
m_time_map[current_node] = 1;
//add stuff to flow and update residuals
//we dont need to update reverse_edges, as incoming/outgoing edges to/from source/sink don't count for max-flow
m_res_cap_map[from_source] -= cap_to_sink;
m_res_cap_map[to_sink] = 0;
m_flow += cap_to_sink;
} else if(cap_to_sink > 0){
set_tree(current_node, tColorTraits::white());
add_active_node(current_node);
set_edge_to_parent(current_node, to_sink);
m_dist_map[current_node] = 1;
m_time_map[current_node] = 1;
//add stuff to flow and update residuals
//we dont need to update reverse_edges, as incoming/outgoing edges to/from source/sink don't count for max-flow
m_res_cap_map[to_sink] -= cap_from_source;
m_res_cap_map[from_source] = 0;
m_flow += cap_from_source;
}
} else if(m_res_cap_map[from_source]){
//there is no sink connect, so we can't augment this path
//but to avoid adding m_source to the active nodes, we just activate this node and set the approciate things
set_tree(current_node, tColorTraits::black());
set_edge_to_parent(current_node, from_source);
m_dist_map[current_node] = 1;
m_time_map[current_node] = 1;
add_active_node(current_node);
}
}
for(tie(ei, e_end) = out_edges(m_sink, m_g); ei != e_end; ++ei){
edge_descriptor to_sink = m_rev_edge_map[*ei];
vertex_descriptor current_node = source(to_sink, m_g);
if(m_res_cap_map[to_sink]){
set_tree(current_node, tColorTraits::white());
set_edge_to_parent(current_node, to_sink);
m_dist_map[current_node] = 1;
m_time_map[current_node] = 1;
add_active_node(current_node);
}
}
}
/**
* returns a pair of an edge and a boolean. if the bool is true, the edge is a connection of a found path from s->t , read "the link" and
* source(returnVal, m_g) is the end of the path found in the source-tree
* target(returnVal, m_g) is the beginning of the path found in the sink-tree
*/
std::pair<edge_descriptor, bool> grow(){
assert(m_orphans.empty());
vertex_descriptor current_node;
while((current_node = get_next_active_node()) != graph_traits<Graph>::null_vertex()){ //if there is one
assert(get_tree(current_node) != tColorTraits::gray() && (has_parent(current_node) || current_node==m_source || current_node==m_sink));
if(get_tree(current_node) == tColorTraits::black()){
//source tree growing
out_edge_iterator ei, e_end;
if(current_node != m_last_grow_vertex){
m_last_grow_vertex = current_node;
tie(m_last_grow_edge_it, m_last_grow_edge_end) = out_edges(current_node, m_g);
}
for(; m_last_grow_edge_it != m_last_grow_edge_end; ++m_last_grow_edge_it){
edge_descriptor out_edge = *m_last_grow_edge_it;
if(m_res_cap_map[out_edge] > 0){ //check if we have capacity left on this edge
vertex_descriptor other_node = target(out_edge, m_g);
if(get_tree(other_node) == tColorTraits::gray()){ //it's a free node
set_tree(other_node, tColorTraits::black()); //aquire other node to our search tree
set_edge_to_parent(other_node, out_edge); //set us as parent
m_dist_map[other_node] = m_dist_map[current_node] + 1; //and update the distance-heuristic
m_time_map[other_node] = m_time_map[current_node];
add_active_node(other_node);
} else if(get_tree(other_node) == tColorTraits::black()){
if(is_closer_to_terminal(current_node, other_node)){ //we do this to get shorter paths. check if we are nearer to the source as its parent is
set_edge_to_parent(other_node, out_edge);
m_dist_map[other_node] = m_dist_map[current_node] + 1;
m_time_map[other_node] = m_time_map[current_node];
}
} else{
assert(get_tree(other_node)==tColorTraits::white());
//kewl, found a path from one to the other search tree, return the connecting edge in src->sink dir
return std::make_pair(out_edge, true);
}
}
} //for all out-edges
} //source-tree-growing
else{
assert(get_tree(current_node) == tColorTraits::white());
out_edge_iterator ei, e_end;
if(current_node != m_last_grow_vertex){
m_last_grow_vertex = current_node;
tie(m_last_grow_edge_it, m_last_grow_edge_end) = out_edges(current_node, m_g);
}
for(; m_last_grow_edge_it != m_last_grow_edge_end; ++m_last_grow_edge_it){
edge_descriptor in_edge = m_rev_edge_map[*m_last_grow_edge_it];
if(m_res_cap_map[in_edge] > 0){ //check if there is capacity left
vertex_descriptor other_node = source(in_edge, m_g);
if(get_tree(other_node) == tColorTraits::gray()){ //it's a free node
set_tree(other_node, tColorTraits::white()); //aquire that node to our search tree
set_edge_to_parent(other_node, in_edge); //set us as parent
add_active_node(other_node); //activate that node
m_dist_map[other_node] = m_dist_map[current_node] + 1; //set its distance
m_time_map[other_node] = m_time_map[current_node]; //and time
} else if(get_tree(other_node) == tColorTraits::white()){
if(is_closer_to_terminal(current_node, other_node)){
//we are closer to the sink than its parent is, so we "adopt" him
set_edge_to_parent(other_node, in_edge);
m_dist_map[other_node] = m_dist_map[current_node] + 1;
m_time_map[other_node] = m_time_map[current_node];
}
} else{
assert(get_tree(other_node)==tColorTraits::black());
//kewl, found a path from one to the other search tree, return the connecting edge in src->sink dir
return std::make_pair(in_edge, true);
}
}
} //for all out-edges
} //sink-tree growing
//all edges of that node are processed, and no more paths were found. so remove if from the front of the active queue
finish_node(current_node);
} //while active_nodes not empty
return std::make_pair(edge_descriptor(), false); //no active nodes anymore and no path found, we're done
}
/**
* augments path from s->t and updates residual graph
* source(e, m_g) is the end of the path found in the source-tree
* target(e, m_g) is the beginning of the path found in the sink-tree
* this phase generates orphans on satured edges, if the attached verts are from different search-trees
* orphans are ordered in distance to sink/source. first the farest from the source are front_inserted into the orphans list,
* and after that the sink-tree-orphans are front_inserted. when going to adoption stage the orphans are popped_front, and so we process the nearest
* verts to the terminals first
*/
void augment(edge_descriptor e){
assert(get_tree(target(e, m_g)) == tColorTraits::white());
assert(get_tree(source(e, m_g)) == tColorTraits::black());
assert(m_orphans.empty());
const tEdgeVal bottleneck = find_bottleneck(e);
//now we push the found flow through the path
//for each edge we saturate we have to look for the verts that belong to that edge, one of them becomes an orphans
//now process the connecting edge
m_res_cap_map[e] -= bottleneck;
assert(m_res_cap_map[e] >= 0);
m_res_cap_map[m_rev_edge_map[e]] += bottleneck;
//now we follow the path back to the source
vertex_descriptor current_node = source(e, m_g);
while(current_node != m_source){
edge_descriptor pred = get_edge_to_parent(current_node);
m_res_cap_map[pred] -= bottleneck;
assert(m_res_cap_map[pred] >= 0);
m_res_cap_map[m_rev_edge_map[pred]] += bottleneck;
if(m_res_cap_map[pred] == 0){
set_no_parent(current_node);
m_orphans.push_front(current_node);
}
current_node = source(pred, m_g);
}
//then go forward in the sink-tree
current_node = target(e, m_g);
while(current_node != m_sink){
edge_descriptor pred = get_edge_to_parent(current_node);
m_res_cap_map[pred] -= bottleneck;
assert(m_res_cap_map[pred] >= 0);
m_res_cap_map[m_rev_edge_map[pred]] += bottleneck;
if(m_res_cap_map[pred] == 0){
set_no_parent(current_node);
m_orphans.push_front(current_node);
}
current_node = target(pred, m_g);
}
//and add it to the max-flow
m_flow += bottleneck;
}
/**
* returns the bottleneck of a s->t path (end_of_path is last vertex in source-tree, begin_of_path is first vertex in sink-tree)
*/
inline tEdgeVal find_bottleneck(edge_descriptor e){
BOOST_USING_STD_MIN();
tEdgeVal minimum_cap = m_res_cap_map[e];
vertex_descriptor current_node = source(e, m_g);
//first go back in the source tree
while(current_node != m_source){
edge_descriptor pred = get_edge_to_parent(current_node);
minimum_cap = min BOOST_PREVENT_MACRO_SUBSTITUTION(minimum_cap, m_res_cap_map[pred]);
current_node = source(pred, m_g);
}
//then go forward in the sink-tree
current_node = target(e, m_g);
while(current_node != m_sink){
edge_descriptor pred = get_edge_to_parent(current_node);
minimum_cap = min BOOST_PREVENT_MACRO_SUBSTITUTION(minimum_cap, m_res_cap_map[pred]);
current_node = target(pred, m_g);
}
return minimum_cap;
}
/**
* rebuild search trees
* empty the queue of orphans, and find new parents for them or just drop them from the search trees
*/
void adopt(){
while(!m_orphans.empty() || !m_child_orphans.empty()){
vertex_descriptor current_node;
if(m_child_orphans.empty()){
//get the next orphan from the main-queue and remove it
current_node = m_orphans.front();
m_orphans.pop_front();
} else{
current_node = m_child_orphans.front();
m_child_orphans.pop();
}
if(get_tree(current_node) == tColorTraits::black()){
//we're in the source-tree
tDistanceVal min_distance = (std::numeric_limits<tDistanceVal>::max)();
edge_descriptor new_parent_edge;
out_edge_iterator ei, e_end;
for(tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){
const edge_descriptor in_edge = m_rev_edge_map[*ei];
assert(target(in_edge, m_g) == current_node); //we should be the target of this edge
if(m_res_cap_map[in_edge] > 0){
vertex_descriptor other_node = source(in_edge, m_g);
if(get_tree(other_node) == tColorTraits::black() && has_source_connect(other_node)){
if(m_dist_map[other_node] < min_distance){
min_distance = m_dist_map[other_node];
new_parent_edge = in_edge;
}
}
}
}
if(min_distance != (std::numeric_limits<tDistanceVal>::max)()){
set_edge_to_parent(current_node, new_parent_edge);
m_dist_map[current_node] = min_distance + 1;
m_time_map[current_node] = m_time;
} else{
m_time_map[current_node] = 0;
for(tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){
edge_descriptor in_edge = m_rev_edge_map[*ei];
vertex_descriptor other_node = source(in_edge, m_g);
if(get_tree(other_node) == tColorTraits::black() && has_parent(other_node)){
if(m_res_cap_map[in_edge] > 0){
add_active_node(other_node);
}
if(source(get_edge_to_parent(other_node), m_g) == current_node){
//we are the parent of that node
//it has to find a new parent, too
set_no_parent(other_node);
m_child_orphans.push(other_node);
}
}
}
set_tree(current_node, tColorTraits::gray());
} //no parent found
} //source-tree-adoption
else{
//now we should be in the sink-tree, check that...
assert(get_tree(current_node) == tColorTraits::white());
out_edge_iterator ei, e_end;
edge_descriptor new_parent_edge;
tDistanceVal min_distance = (std::numeric_limits<tDistanceVal>::max)();
for(tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){
const edge_descriptor out_edge = *ei;
if(m_res_cap_map[out_edge] > 0){
const vertex_descriptor other_node = target(out_edge, m_g);
if(get_tree(other_node) == tColorTraits::white() && has_sink_connect(other_node))
if(m_dist_map[other_node] < min_distance){
min_distance = m_dist_map[other_node];
new_parent_edge = out_edge;
}
}
}
if(min_distance != (std::numeric_limits<tDistanceVal>::max)()){
set_edge_to_parent(current_node, new_parent_edge);
m_dist_map[current_node] = min_distance + 1;
m_time_map[current_node] = m_time;
} else{
m_time_map[current_node] = 0;
for(tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){
const edge_descriptor out_edge = *ei;
const vertex_descriptor other_node = target(out_edge, m_g);
if(get_tree(other_node) == tColorTraits::white() && has_parent(other_node)){
if(m_res_cap_map[out_edge] > 0){
add_active_node(other_node);
}
if(target(get_edge_to_parent(other_node), m_g) == current_node){
//we were it's parent, so it has to find a new one, too
set_no_parent(other_node);
m_child_orphans.push(other_node);
}
}
}
set_tree(current_node, tColorTraits::gray());
} //no parent found
} //sink-tree adoption
} //while !orphans.empty()
} //adopt
/**
* return next active vertex if there is one, otherwise a null_vertex
*/
inline vertex_descriptor get_next_active_node(){
while(true){
if(m_active_nodes.empty())
return graph_traits<Graph>::null_vertex();
vertex_descriptor v = m_active_nodes.front();
if(!has_parent(v) && v != m_source && v != m_sink){ //if it has no parent, this node can't be active(if its not source or sink)
m_active_nodes.pop();
m_in_active_list_map[v] = false;
} else{
assert(get_tree(v) == tColorTraits::black() || get_tree(v) == tColorTraits::white());
return v;
}
}
}
/**
* adds v as an active vertex, but only if its not in the list already
*/
inline void add_active_node(vertex_descriptor v){
assert(get_tree(v) != tColorTraits::gray());
if(m_in_active_list_map[v]){
return;
} else{
m_in_active_list_map[v] = true;
m_active_nodes.push(v);
}
}
/**
* finish_node removes a node from the front of the active queue (its called in grow phase, if no more paths can be found using this node)
*/
inline void finish_node(vertex_descriptor v){
assert(m_active_nodes.front() == v);
m_active_nodes.pop();
m_in_active_list_map[v] = false;
m_last_grow_vertex = graph_traits<Graph>::null_vertex();
}
/**
* removes a vertex from the queue of active nodes (actually this does nothing,
* but checks if this node has no parent edge, as this is the criteria for beeing no more active)
*/
inline void remove_active_node(vertex_descriptor v){
assert(!has_parent(v));
}
/**
* returns the search tree of v; tColorValue::black() for source tree, white() for sink tree, gray() for no tree
*/
inline tColorValue get_tree(vertex_descriptor v) const {
return m_tree_map[v];
}
/**
* sets search tree of v; tColorValue::black() for source tree, white() for sink tree, gray() for no tree
*/
inline void set_tree(vertex_descriptor v, tColorValue t){
m_tree_map[v] = t;
}
/**
* returns edge to parent vertex of v;
*/
inline edge_descriptor get_edge_to_parent(vertex_descriptor v) const{
return m_pre_map[v];
}
/**
* returns true if the edge stored in m_pre_map[v] is a valid entry
*/
inline bool has_parent(vertex_descriptor v) const{
return m_has_parent_map[v];
}
/**
* sets edge to parent vertex of v;
*/
inline void set_edge_to_parent(vertex_descriptor v, edge_descriptor f_edge_to_parent){
assert(m_res_cap_map[f_edge_to_parent] > 0);
m_pre_map[v] = f_edge_to_parent;
m_has_parent_map[v] = true;
}
/**
* removes the edge to parent of v (this is done by invalidating the entry an additional map)
*/
inline void set_no_parent(vertex_descriptor v){
m_has_parent_map[v] = false;
}
/**
* checks if vertex v has a connect to the sink-vertex (@var m_sink)
* @param v the vertex which is checked
* @return true if a path to the sink was found, false if not
*/
inline bool has_sink_connect(vertex_descriptor v){
tDistanceVal current_distance = 0;
vertex_descriptor current_vertex = v;
while(true){
if(m_time_map[current_vertex] == m_time){
//we found a node which was already checked this round. use it for distance calculations
current_distance += m_dist_map[current_vertex];
break;
}
if(current_vertex == m_sink){
m_time_map[m_sink] = m_time;
break;
}
if(has_parent(current_vertex)){
//it has a parent, so get it
current_vertex = target(get_edge_to_parent(current_vertex), m_g);
++current_distance;
} else{
//no path found
return false;
}
}
current_vertex=v;
while(m_time_map[current_vertex] != m_time){
m_dist_map[current_vertex] = current_distance--;
m_time_map[current_vertex] = m_time;
current_vertex = target(get_edge_to_parent(current_vertex), m_g);
}
return true;
}
/**
* checks if vertex v has a connect to the source-vertex (@var m_source)
* @param v the vertex which is checked
* @return true if a path to the source was found, false if not
*/
inline bool has_source_connect(vertex_descriptor v){
tDistanceVal current_distance = 0;
vertex_descriptor current_vertex = v;
while(true){
if(m_time_map[current_vertex] == m_time){
//we found a node which was already checked this round. use it for distance calculations
current_distance += m_dist_map[current_vertex];
break;
}
if(current_vertex == m_source){
m_time_map[m_source] = m_time;
break;
}
if(has_parent(current_vertex)){
//it has a parent, so get it
current_vertex = source(get_edge_to_parent(current_vertex), m_g);
++current_distance;
} else{
//no path found
return false;
}
}
current_vertex=v;
while(m_time_map[current_vertex] != m_time){
m_dist_map[current_vertex] = current_distance-- ;
m_time_map[current_vertex] = m_time;
current_vertex = source(get_edge_to_parent(current_vertex), m_g);
}
return true;
}
/**
* returns true, if p is closer to a terminal than q
*/
inline bool is_closer_to_terminal(vertex_descriptor p, vertex_descriptor q){
//checks the timestamps first, to build no cycles, and after that the real distance
return (m_time_map[q] <= m_time_map[p] && m_dist_map[q] > m_dist_map[p]+1);
}
////////
// member vars
////////
Graph& m_g;
IndexMap m_index_map;
EdgeCapacityMap m_cap_map;
ResidualCapacityEdgeMap m_res_cap_map;
ReverseEdgeMap m_rev_edge_map;
PredecessorMap m_pre_map; //stores paths found in the growth stage
ColorMap m_tree_map; //maps each vertex into one of the two search tree or none (gray())
DistanceMap m_dist_map; //stores distance to source/sink nodes
vertex_descriptor m_source;
vertex_descriptor m_sink;
tQueue m_active_nodes;
std::vector<bool> m_in_active_list_vec;
iterator_property_map<std::vector<bool>::iterator, IndexMap> m_in_active_list_map;
std::list<vertex_descriptor> m_orphans;
tQueue m_child_orphans; // we use a second queuqe for child orphans, as they are FIFO processed
std::vector<bool> m_has_parent_vec;
iterator_property_map<std::vector<bool>::iterator, IndexMap> m_has_parent_map;
std::vector<long> m_time_vec; //timestamp of each node, used for sink/source-path calculations
iterator_property_map<std::vector<long>::iterator, IndexMap> m_time_map;
tEdgeVal m_flow;
long m_time;
vertex_descriptor m_last_grow_vertex;
out_edge_iterator m_last_grow_edge_it;
out_edge_iterator m_last_grow_edge_end;
};
} //namespace detail
/**
* non-named-parameter version, given everything
* this is the catch all version
*/
template <class Graph, class CapacityEdgeMap, class ResidualCapacityEdgeMap, class ReverseEdgeMap,
class PredecessorMap, class ColorMap, class DistanceMap, class IndexMap>
typename property_traits<CapacityEdgeMap>::value_type
kolmogorov_max_flow
(Graph& g,
CapacityEdgeMap cap,
ResidualCapacityEdgeMap res_cap,
ReverseEdgeMap rev_map,
PredecessorMap pre_map,
ColorMap color,
DistanceMap dist,
IndexMap idx,
typename graph_traits<Graph>::vertex_descriptor src,
typename graph_traits<Graph>::vertex_descriptor sink
)
{
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
//as this method is the last one before we instantiate the solver, we do the concept checks here
function_requires<VertexListGraphConcept<Graph> >(); //to have vertices(), num_vertices(),
function_requires<EdgeListGraphConcept<Graph> >(); //to have edges()
function_requires<IncidenceGraphConcept<Graph> >(); //to have source(), target() and out_edges()
function_requires<LvaluePropertyMapConcept<CapacityEdgeMap, edge_descriptor> >(); //read flow-values from edges
function_requires<Mutable_LvaluePropertyMapConcept<ResidualCapacityEdgeMap, edge_descriptor> >(); //write flow-values to residuals
function_requires<LvaluePropertyMapConcept<ReverseEdgeMap, edge_descriptor> >(); //read out reverse edges
function_requires<Mutable_LvaluePropertyMapConcept<PredecessorMap, vertex_descriptor> >(); //store predecessor there
function_requires<Mutable_LvaluePropertyMapConcept<ColorMap, vertex_descriptor> >(); //write corresponding tree
function_requires<Mutable_LvaluePropertyMapConcept<DistanceMap, vertex_descriptor> >(); //write distance to source/sink
function_requires<ReadablePropertyMapConcept<IndexMap, vertex_descriptor> >(); //get index 0...|V|-1
assert(num_vertices(g) >= 2 && src != sink);
detail::kolmogorov<Graph, CapacityEdgeMap, ResidualCapacityEdgeMap, ReverseEdgeMap, PredecessorMap, ColorMap, DistanceMap, IndexMap>
algo(g, cap, res_cap, rev_map, pre_map, color, dist, idx, src, sink);
return algo.max_flow();
}
/**
* non-named-parameter version, given: capacity, residucal_capacity, reverse_edges, and an index map.
*/
template <class Graph, class CapacityEdgeMap, class ResidualCapacityEdgeMap, class ReverseEdgeMap, class IndexMap>
typename property_traits<CapacityEdgeMap>::value_type
kolmogorov_max_flow
(Graph& g,
CapacityEdgeMap cap,
ResidualCapacityEdgeMap res_cap,
ReverseEdgeMap rev,
IndexMap idx,
typename graph_traits<Graph>::vertex_descriptor src,
typename graph_traits<Graph>::vertex_descriptor sink)
{
typename graph_traits<Graph>::vertices_size_type n_verts = num_vertices(g);
std::vector<typename graph_traits<Graph>::edge_descriptor> predecessor_vec(n_verts);
std::vector<default_color_type> color_vec(n_verts);
std::vector<typename graph_traits<Graph>::vertices_size_type> distance_vec(n_verts);
return kolmogorov_max_flow
(g, cap, res_cap, rev,
make_iterator_property_map(predecessor_vec.begin(), idx),
make_iterator_property_map(color_vec.begin(), idx),
make_iterator_property_map(distance_vec.begin(), idx),
idx, src, sink);
}
/**
* non-named-parameter version, some given: capacity, residual_capacity, reverse_edges, color_map and an index map.
* Use this if you are interested in the minimum cut, as the color map provides that info
*/
template <class Graph, class CapacityEdgeMap, class ResidualCapacityEdgeMap, class ReverseEdgeMap, class ColorMap, class IndexMap>
typename property_traits<CapacityEdgeMap>::value_type
kolmogorov_max_flow
(Graph& g,
CapacityEdgeMap cap,
ResidualCapacityEdgeMap res_cap,
ReverseEdgeMap rev,
ColorMap color,
IndexMap idx,
typename graph_traits<Graph>::vertex_descriptor src,
typename graph_traits<Graph>::vertex_descriptor sink)
{
typename graph_traits<Graph>::vertices_size_type n_verts = num_vertices(g);
std::vector<typename graph_traits<Graph>::edge_descriptor> predecessor_vec(n_verts);
std::vector<typename graph_traits<Graph>::vertices_size_type> distance_vec(n_verts);
return kolmogorov_max_flow
(g, cap, res_cap, rev,
make_iterator_property_map(predecessor_vec.begin(), idx),
color,
make_iterator_property_map(distance_vec.begin(), idx),
idx, src, sink);
}
/**
* named-parameter version, some given
*/
template <class Graph, class P, class T, class R>
typename property_traits<typename property_map<Graph, edge_capacity_t>::const_type>::value_type
kolmogorov_max_flow
(Graph& g,
typename graph_traits<Graph>::vertex_descriptor src,
typename graph_traits<Graph>::vertex_descriptor sink,
const bgl_named_params<P, T, R>& params)
{
return kolmogorov_max_flow(g,
choose_const_pmap(get_param(params, edge_capacity), g, edge_capacity),
choose_pmap(get_param(params, edge_residual_capacity), g, edge_residual_capacity),
choose_const_pmap(get_param(params, edge_reverse), g, edge_reverse),
choose_pmap(get_param(params, vertex_predecessor), g, vertex_predecessor),
choose_pmap(get_param(params, vertex_color), g, vertex_color),
choose_pmap(get_param(params, vertex_distance), g, vertex_distance),
choose_const_pmap(get_param(params, vertex_index), g, vertex_index),
src, sink);
}
/**
* named-parameter version, none given
*/
template <class Graph>
typename property_traits<typename property_map<Graph, edge_capacity_t>::const_type>::value_type
kolmogorov_max_flow
(Graph& g,
typename graph_traits<Graph>::vertex_descriptor src,
typename graph_traits<Graph>::vertex_descriptor sink)
{
bgl_named_params<int, buffer_param_t> params(0); // bogus empty param
return kolmogorov_max_flow(g, src, sink, params);
}
} // namespace boost
#endif // BOOST_KOLMOGOROV_MAX_FLOW_HPP

View File

@@ -1,7 +1,9 @@
//=======================================================================
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
// Copyright 2004 The Trustees of Indiana University.
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, Douglas Gregor
// Copyright 2007 University of Karlsruhe
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, Douglas Gregor,
// Jens Mueller
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -23,9 +25,6 @@
// treat a LEDA GRAPH object as a boost graph "as is". No
// wrapper is needed for the GRAPH object.
// Remember to define LEDA_PREFIX so that LEDA types such as
// leda_edge show up as "leda_edge" and not just "edge".
// Warning: this implementation relies on partial specialization
// for the graph_traits class (so it won't compile with Visual C++)
@@ -41,95 +40,103 @@ namespace boost {
template <class vtype, class etype>
struct graph_traits< leda::GRAPH<vtype,etype> > {
typedef leda_node vertex_descriptor;
typedef leda_edge edge_descriptor;
typedef leda::node vertex_descriptor;
typedef leda::edge edge_descriptor;
class adjacency_iterator
: public iterator_facade<adjacency_iterator,
leda_node,
leda::node,
bidirectional_traversal_tag,
leda_node,
const leda_node*>
leda::node,
const leda::node*>
{
public:
explicit adjacency_iterator(leda_edge edge = 0) : base(edge) {}
adjacency_iterator(leda::node node = 0,
const leda::GRAPH<vtype, etype>* g = 0)
: base(node), g(g) {}
private:
leda_node dereference() const { return leda::target(base); }
leda::node dereference() const { return leda::target(base); }
bool equal(const adjacency_iterator& other) const
{ return base == other.base; }
void increment() { base = Succ_Adj_Edge(base, 0); }
void decrement() { base = Pred_Adj_Edge(base, 0); }
void increment() { base = g->adj_succ(base); }
void decrement() { base = g->adj_pred(base); }
leda_edge base;
leda::edge base;
const leda::GRAPH<vtype, etype>* g;
friend class iterator_core_access;
};
class out_edge_iterator
: public iterator_facade<out_edge_iterator,
leda_edge,
leda::edge,
bidirectional_traversal_tag,
const leda_edge&,
const leda_edge*>
const leda::edge&,
const leda::edge*>
{
public:
explicit out_edge_iterator(leda_edge edge = 0) : base(edge) {}
out_edge_iterator(leda::node node = 0,
const leda::GRAPH<vtype, etype>* g = 0)
: base(node), g(g) {}
private:
const leda_edge& dereference() const { return base; }
const leda::edge& dereference() const { return base; }
bool equal(const out_edge_iterator& other) const
{ return base == other.base; }
void increment() { base = Succ_Adj_Edge(base, 0); }
void decrement() { base = Pred_Adj_Edge(base, 0); }
void increment() { base = g->adj_succ(base); }
void decrement() { base = g->adj_pred(base); }
leda_edge base;
leda::edge base;
const leda::GRAPH<vtype, etype>* g;
friend class iterator_core_access;
};
class in_edge_iterator
: public iterator_facade<in_edge_iterator,
leda_edge,
leda::edge,
bidirectional_traversal_tag,
const leda_edge&,
const leda_edge*>
const leda::edge&,
const leda::edge*>
{
public:
explicit in_edge_iterator(leda_edge edge = 0) : base(edge) {}
in_edge_iterator(leda::node node = 0,
const leda::GRAPH<vtype, etype>* g = 0)
: base(node), g(g) {}
private:
const leda_edge& dereference() const { return base; }
const leda::edge& dereference() const { return base; }
bool equal(const in_edge_iterator& other) const
{ return base == other.base; }
void increment() { base = Succ_Adj_Edge(base, 1); }
void decrement() { base = Pred_Adj_Edge(base, 1); }
void increment() { base = g->in_succ(base); }
void decrement() { base = g->in_pred(base); }
leda_edge base;
leda::edge base;
const leda::GRAPH<vtype, etype>* g;
friend class iterator_core_access;
};
class vertex_iterator
: public iterator_facade<vertex_iterator,
leda_node,
leda::node,
bidirectional_traversal_tag,
const leda_node&,
const leda_node*>
const leda::node&,
const leda::node*>
{
public:
vertex_iterator(leda_node node = 0,
vertex_iterator(leda::node node = 0,
const leda::GRAPH<vtype, etype>* g = 0)
: base(node), g(g) {}
private:
const leda_node& dereference() const { return base; }
const leda::node& dereference() const { return base; }
bool equal(const vertex_iterator& other) const
{ return base == other.base; }
@@ -137,7 +144,34 @@ namespace boost {
void increment() { base = g->succ_node(base); }
void decrement() { base = g->pred_node(base); }
leda_node base;
leda::node base;
const leda::GRAPH<vtype, etype>* g;
friend class iterator_core_access;
};
class edge_iterator
: public iterator_facade<edge_iterator,
leda::edge,
bidirectional_traversal_tag,
const leda::edge&,
const leda::edge*>
{
public:
edge_iterator(leda::edge edge = 0,
const leda::GRAPH<vtype, etype>* g = 0)
: base(edge), g(g) {}
private:
const leda::edge& dereference() const { return base; }
bool equal(const edge_iterator& other) const
{ return base == other.base; }
void increment() { base = g->succ_edge(base); }
void decrement() { base = g->pred_edge(base); }
leda::node base;
const leda::GRAPH<vtype, etype>* g;
friend class iterator_core_access;
@@ -151,14 +185,154 @@ namespace boost {
typedef int degree_size_type;
};
template <class vtype, class etype>
struct vertex_property< leda::GRAPH<vtype,etype> > {
typedef vtype type;
};
template <class vtype, class etype>
struct edge_property< leda::GRAPH<vtype,etype> > {
typedef etype type;
template<>
struct graph_traits<leda::graph> {
typedef leda::node vertex_descriptor;
typedef leda::edge edge_descriptor;
class adjacency_iterator
: public iterator_facade<adjacency_iterator,
leda::node,
bidirectional_traversal_tag,
leda::node,
const leda::node*>
{
public:
adjacency_iterator(leda::edge edge = 0,
const leda::graph* g = 0)
: base(edge), g(g) {}
private:
leda::node dereference() const { return leda::target(base); }
bool equal(const adjacency_iterator& other) const
{ return base == other.base; }
void increment() { base = g->adj_succ(base); }
void decrement() { base = g->adj_pred(base); }
leda::edge base;
const leda::graph* g;
friend class iterator_core_access;
};
class out_edge_iterator
: public iterator_facade<out_edge_iterator,
leda::edge,
bidirectional_traversal_tag,
const leda::edge&,
const leda::edge*>
{
public:
out_edge_iterator(leda::edge edge = 0,
const leda::graph* g = 0)
: base(edge), g(g) {}
private:
const leda::edge& dereference() const { return base; }
bool equal(const out_edge_iterator& other) const
{ return base == other.base; }
void increment() { base = g->adj_succ(base); }
void decrement() { base = g->adj_pred(base); }
leda::edge base;
const leda::graph* g;
friend class iterator_core_access;
};
class in_edge_iterator
: public iterator_facade<in_edge_iterator,
leda::edge,
bidirectional_traversal_tag,
const leda::edge&,
const leda::edge*>
{
public:
in_edge_iterator(leda::edge edge = 0,
const leda::graph* g = 0)
: base(edge), g(g) {}
private:
const leda::edge& dereference() const { return base; }
bool equal(const in_edge_iterator& other) const
{ return base == other.base; }
void increment() { base = g->in_succ(base); }
void decrement() { base = g->in_pred(base); }
leda::edge base;
const leda::graph* g;
friend class iterator_core_access;
};
class vertex_iterator
: public iterator_facade<vertex_iterator,
leda::node,
bidirectional_traversal_tag,
const leda::node&,
const leda::node*>
{
public:
vertex_iterator(leda::node node = 0,
const leda::graph* g = 0)
: base(node), g(g) {}
private:
const leda::node& dereference() const { return base; }
bool equal(const vertex_iterator& other) const
{ return base == other.base; }
void increment() { base = g->succ_node(base); }
void decrement() { base = g->pred_node(base); }
leda::node base;
const leda::graph* g;
friend class iterator_core_access;
};
class edge_iterator
: public iterator_facade<edge_iterator,
leda::edge,
bidirectional_traversal_tag,
const leda::edge&,
const leda::edge*>
{
public:
edge_iterator(leda::edge edge = 0,
const leda::graph* g = 0)
: base(edge), g(g) {}
private:
const leda::edge& dereference() const { return base; }
bool equal(const edge_iterator& other) const
{ return base == other.base; }
void increment() { base = g->succ_edge(base); }
void decrement() { base = g->pred_edge(base); }
leda::edge base;
const leda::graph* g;
friend class iterator_core_access;
};
typedef directed_tag directed_category;
typedef allow_parallel_edge_tag edge_parallel_category; // not sure here
typedef leda_graph_traversal_category traversal_category;
typedef int vertices_size_type;
typedef int edges_size_type;
typedef int degree_size_type;
};
} // namespace boost
@@ -166,6 +340,9 @@ namespace boost {
namespace boost {
//===========================================================================
// functions for GRAPH<vtype,etype>
template <class vtype, class etype>
typename graph_traits< leda::GRAPH<vtype,etype> >::vertex_descriptor
source(typename graph_traits< leda::GRAPH<vtype,etype> >::edge_descriptor e,
@@ -193,7 +370,16 @@ namespace boost {
return std::make_pair( Iter(g.first_node(),&g), Iter(0,&g) );
}
// no edges(g) function
template <class vtype, class etype>
inline std::pair<
typename graph_traits< leda::GRAPH<vtype,etype> >::edge_iterator,
typename graph_traits< leda::GRAPH<vtype,etype> >::edge_iterator >
edges(const leda::GRAPH<vtype,etype>& g)
{
typedef typename graph_traits< leda::GRAPH<vtype,etype> >::edge_iterator
Iter;
return std::make_pair( Iter(g.first_edge(),&g), Iter(0,&g) );
}
template <class vtype, class etype>
inline std::pair<
@@ -205,7 +391,7 @@ namespace boost {
{
typedef typename graph_traits< leda::GRAPH<vtype,etype> >
::out_edge_iterator Iter;
return std::make_pair( Iter(First_Adj_Edge(u,0)), Iter(0) );
return std::make_pair( Iter(g.first_adj_edge(u,0),&g), Iter(0,&g) );
}
template <class vtype, class etype>
@@ -218,7 +404,7 @@ namespace boost {
{
typedef typename graph_traits< leda::GRAPH<vtype,etype> >
::in_edge_iterator Iter;
return std::make_pair( Iter(First_Adj_Edge(u,1)), Iter(0) );
return std::make_pair( Iter(g.first_adj_edge(u,1),&g), Iter(0,&g) );
}
template <class vtype, class etype>
@@ -231,7 +417,7 @@ namespace boost {
{
typedef typename graph_traits< leda::GRAPH<vtype,etype> >
::adjacency_iterator Iter;
return std::make_pair( Iter(First_Adj_Edge(u,0)), Iter(0) );
return std::make_pair( Iter(g.first_adj_edge(u,0),&g), Iter(0,&g) );
}
template <class vtype, class etype>
@@ -252,29 +438,29 @@ namespace boost {
typename graph_traits< leda::GRAPH<vtype,etype> >::degree_size_type
out_degree(
typename graph_traits< leda::GRAPH<vtype,etype> >::vertex_descriptor u,
const leda::GRAPH<vtype,etype>&)
const leda::GRAPH<vtype,etype>& g)
{
return outdeg(u);
return g.outdeg(u);
}
template <class vtype, class etype>
typename graph_traits< leda::GRAPH<vtype,etype> >::degree_size_type
in_degree(
typename graph_traits< leda::GRAPH<vtype,etype> >::vertex_descriptor u,
const leda::GRAPH<vtype,etype>&)
const leda::GRAPH<vtype,etype>& g)
{
return indeg(u);
return g.indeg(u);
}
template <class vtype, class etype>
typename graph_traits< leda::GRAPH<vtype,etype> >::degree_size_type
degree(
typename graph_traits< leda::GRAPH<vtype,etype> >::vertex_descriptor u,
const leda::GRAPH<vtype,etype>&)
const leda::GRAPH<vtype,etype>& g)
{
return outdeg(u) + indeg(u);
return g.outdeg(u) + g.indeg(u);
}
template <class vtype, class etype>
typename graph_traits< leda::GRAPH<vtype,etype> >::vertex_descriptor
add_vertex(leda::GRAPH<vtype,etype>& g)
@@ -289,14 +475,18 @@ namespace boost {
return g.new_node(vp);
}
// Hmm, LEDA doesn't have the equivalent of clear_vertex() -JGS
// need to write an implementation
template <class vtype, class etype>
void clear_vertex(
typename graph_traits< leda::GRAPH<vtype,etype> >::vertex_descriptor u,
leda::GRAPH<vtype,etype>& g)
{
g.del_node(u);
typename graph_traits< leda::GRAPH<vtype,etype> >::out_edge_iterator ei, ei_end;
for (tie(ei, ei_end)=out_edges(u,g); ei!=ei_end; ei++)
remove_edge(*ei);
typename graph_traits< leda::GRAPH<vtype,etype> >::in_edge_iterator iei, iei_end;
for (tie(iei, iei_end)=in_edges(u,g); iei!=iei_end; iei++)
remove_edge(*iei);
}
template <class vtype, class etype>
@@ -356,8 +546,174 @@ namespace boost {
}
//===========================================================================
// property maps
// functions for graph (non-templated version)
graph_traits<leda::graph>::vertex_descriptor
source(graph_traits<leda::graph>::edge_descriptor e,
const leda::graph& g)
{
return source(e);
}
graph_traits<leda::graph>::vertex_descriptor
target(graph_traits<leda::graph>::edge_descriptor e,
const leda::graph& g)
{
return target(e);
}
inline std::pair<
graph_traits<leda::graph>::vertex_iterator,
graph_traits<leda::graph>::vertex_iterator >
vertices(const leda::graph& g)
{
typedef graph_traits<leda::graph>::vertex_iterator
Iter;
return std::make_pair( Iter(g.first_node(),&g), Iter(0,&g) );
}
inline std::pair<
graph_traits<leda::graph>::edge_iterator,
graph_traits<leda::graph>::edge_iterator >
edges(const leda::graph& g)
{
typedef graph_traits<leda::graph>::edge_iterator
Iter;
return std::make_pair( Iter(g.first_edge(),&g), Iter(0,&g) );
}
inline std::pair<
graph_traits<leda::graph>::out_edge_iterator,
graph_traits<leda::graph>::out_edge_iterator >
out_edges(
graph_traits<leda::graph>::vertex_descriptor u, const leda::graph& g)
{
typedef graph_traits<leda::graph>::out_edge_iterator Iter;
return std::make_pair( Iter(g.first_adj_edge(u),&g), Iter(0,&g) );
}
inline std::pair<
graph_traits<leda::graph>::in_edge_iterator,
graph_traits<leda::graph>::in_edge_iterator >
in_edges(
graph_traits<leda::graph>::vertex_descriptor u,
const leda::graph& g)
{
typedef graph_traits<leda::graph>
::in_edge_iterator Iter;
return std::make_pair( Iter(g.first_in_edge(u),&g), Iter(0,&g) );
}
inline std::pair<
graph_traits<leda::graph>::adjacency_iterator,
graph_traits<leda::graph>::adjacency_iterator >
adjacent_vertices(
graph_traits<leda::graph>::vertex_descriptor u,
const leda::graph& g)
{
typedef graph_traits<leda::graph>
::adjacency_iterator Iter;
return std::make_pair( Iter(g.first_adj_edge(u),&g), Iter(0,&g) );
}
graph_traits<leda::graph>::vertices_size_type
num_vertices(const leda::graph& g)
{
return g.number_of_nodes();
}
graph_traits<leda::graph>::edges_size_type
num_edges(const leda::graph& g)
{
return g.number_of_edges();
}
graph_traits<leda::graph>::degree_size_type
out_degree(
graph_traits<leda::graph>::vertex_descriptor u,
const leda::graph& g)
{
return g.outdeg(u);
}
graph_traits<leda::graph>::degree_size_type
in_degree(
graph_traits<leda::graph>::vertex_descriptor u,
const leda::graph& g)
{
return g.indeg(u);
}
graph_traits<leda::graph>::degree_size_type
degree(
graph_traits<leda::graph>::vertex_descriptor u,
const leda::graph& g)
{
return g.outdeg(u) + g.indeg(u);
}
graph_traits<leda::graph>::vertex_descriptor
add_vertex(leda::graph& g)
{
return g.new_node();
}
void
remove_edge(
graph_traits<leda::graph>::vertex_descriptor u,
graph_traits<leda::graph>::vertex_descriptor v,
leda::graph& g)
{
graph_traits<leda::graph>::out_edge_iterator
i,iend;
for (boost::tie(i,iend) = out_edges(u,g); i != iend; ++i)
if (target(*i,g) == v)
g.del_edge(*i);
}
void
remove_edge(
graph_traits<leda::graph>::edge_descriptor e,
leda::graph& g)
{
g.del_edge(e);
}
void clear_vertex(
graph_traits<leda::graph>::vertex_descriptor u,
leda::graph& g)
{
graph_traits<leda::graph>::out_edge_iterator ei, ei_end;
for (tie(ei, ei_end)=out_edges(u,g); ei!=ei_end; ei++)
remove_edge(*ei, g);
graph_traits<leda::graph>::in_edge_iterator iei, iei_end;
for (tie(iei, iei_end)=in_edges(u,g); iei!=iei_end; iei++)
remove_edge(*iei, g);
}
void remove_vertex(
graph_traits<leda::graph>::vertex_descriptor u,
leda::graph& g)
{
g.del_node(u);
}
std::pair<
graph_traits<leda::graph>::edge_descriptor,
bool>
add_edge(
graph_traits<leda::graph>::vertex_descriptor u,
graph_traits<leda::graph>::vertex_descriptor v,
leda::graph& g)
{
return std::make_pair(g.new_edge(u, v), true);
}
//===========================================================================
// property maps for GRAPH<vtype,etype>
class leda_graph_id_map
: public put_get_helper<int, leda_graph_id_map>
{
@@ -365,7 +721,7 @@ namespace boost {
typedef readable_property_map_tag category;
typedef int value_type;
typedef int reference;
typedef leda_node key_type;
typedef leda::node key_type;
leda_graph_id_map() { }
template <class T>
long operator[](T x) const { return x->id(); }
@@ -476,42 +832,42 @@ namespace boost {
public:
typedef E value_type;
typedef ERef reference;
typedef leda_node key_type;
typedef leda::node key_type;
typedef lvalue_property_map_tag category;
leda_node_property_map(NodeMapPtr a) : m_array(a) { }
ERef operator[](leda_node n) const { return (*m_array)[n]; }
ERef operator[](leda::node n) const { return (*m_array)[n]; }
protected:
NodeMapPtr m_array;
};
template <class E>
leda_node_property_map<E, const E&, const leda_node_array<E>*>
make_leda_node_property_map(const leda_node_array<E>& a)
leda_node_property_map<E, const E&, const leda::node_array<E>*>
make_leda_node_property_map(const leda::node_array<E>& a)
{
typedef leda_node_property_map<E, const E&, const leda_node_array<E>*>
typedef leda_node_property_map<E, const E&, const leda::node_array<E>*>
pmap_type;
return pmap_type(&a);
}
template <class E>
leda_node_property_map<E, E&, leda_node_array<E>*>
make_leda_node_property_map(leda_node_array<E>& a)
leda_node_property_map<E, E&, leda::node_array<E>*>
make_leda_node_property_map(leda::node_array<E>& a)
{
typedef leda_node_property_map<E, E&, leda_node_array<E>*> pmap_type;
typedef leda_node_property_map<E, E&, leda::node_array<E>*> pmap_type;
return pmap_type(&a);
}
template <class E>
leda_node_property_map<E, const E&, const leda_node_map<E>*>
make_leda_node_property_map(const leda_node_map<E>& a)
leda_node_property_map<E, const E&, const leda::node_map<E>*>
make_leda_node_property_map(const leda::node_map<E>& a)
{
typedef leda_node_property_map<E,const E&,const leda_node_map<E>*>
typedef leda_node_property_map<E,const E&,const leda::node_map<E>*>
pmap_type;
return pmap_type(&a);
}
template <class E>
leda_node_property_map<E, E&, leda_node_map<E>*>
make_leda_node_property_map(leda_node_map<E>& a)
leda_node_property_map<E, E&, leda::node_map<E>*>
make_leda_node_property_map(leda::node_map<E>& a)
{
typedef leda_node_property_map<E, E&, leda_node_map<E>*> pmap_type;
typedef leda_node_property_map<E, E&, leda::node_map<E>*> pmap_type;
return pmap_type(&a);
}
@@ -528,11 +884,11 @@ namespace boost {
inline
typename boost::property_traits<
typename boost::property_map<leda::GRAPH<vtype, etype>,PropertyTag>::const_type
>::value_type
::value_type
get(PropertyTag p, const leda::GRAPH<vtype, etype>& g, const Key& key) {
return get(get(p, g), key);
}
template <class vtype, class etype, class PropertyTag, class Key,class Value>
inline void
put(PropertyTag p, leda::GRAPH<vtype, etype>& g,
@@ -543,7 +899,54 @@ namespace boost {
put(pmap, key, value);
}
// property map interface to the LEDA edge_array class
template <class E, class ERef, class EdgeMapPtr>
class leda_edge_property_map
: public put_get_helper<ERef, leda_edge_property_map<E, ERef, EdgeMapPtr> >
{
public:
typedef E value_type;
typedef ERef reference;
typedef leda::edge key_type;
typedef lvalue_property_map_tag category;
leda_edge_property_map(EdgeMapPtr a) : m_array(a) { }
ERef operator[](leda::edge n) const { return (*m_array)[n]; }
protected:
EdgeMapPtr m_array;
};
template <class E>
leda_edge_property_map<E, const E&, const leda::edge_array<E>*>
make_leda_node_property_map(const leda::node_array<E>& a)
{
typedef leda_edge_property_map<E, const E&, const leda::node_array<E>*>
pmap_type;
return pmap_type(&a);
}
template <class E>
leda_edge_property_map<E, E&, leda::edge_array<E>*>
make_leda_edge_property_map(leda::edge_array<E>& a)
{
typedef leda_edge_property_map<E, E&, leda::edge_array<E>*> pmap_type;
return pmap_type(&a);
}
template <class E>
leda_edge_property_map<E, const E&, const leda::edge_map<E>*>
make_leda_edge_property_map(const leda::edge_map<E>& a)
{
typedef leda_edge_property_map<E,const E&,const leda::edge_map<E>*>
pmap_type;
return pmap_type(&a);
}
template <class E>
leda_edge_property_map<E, E&, leda::edge_map<E>*>
make_leda_edge_property_map(leda::edge_map<E>& a)
{
typedef leda_edge_property_map<E, E&, leda::edge_map<E>*> pmap_type;
return pmap_type(&a);
}
} // namespace boost
#endif // BOOST_GRAPH_LEDA_HPP

View File

@@ -0,0 +1,121 @@
//=======================================================================
// Copyright 2007 Aaron Windsor
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
#ifndef __MAKE_BICONNECTED_PLANAR_HPP__
#define __MAKE_BICONNECTED_PLANAR_HPP__
#include <boost/config.hpp>
#include <boost/tuple/tuple.hpp> //for tie
#include <boost/graph/biconnected_components.hpp>
#include <boost/property_map.hpp>
#include <vector>
#include <iterator>
#include <algorithm>
#include <boost/graph/planar_detail/add_edge_visitors.hpp>
namespace boost
{
template <typename Graph,
typename PlanarEmbedding,
typename EdgeIndexMap,
typename AddEdgeVisitor
>
void make_biconnected_planar(Graph& g,
PlanarEmbedding embedding,
EdgeIndexMap em,
AddEdgeVisitor& vis
)
{
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
typedef typename graph_traits<Graph>::edges_size_type edge_size_t;
typedef typename
property_traits<PlanarEmbedding>::value_type embedding_value_t;
typedef typename embedding_value_t::const_iterator embedding_iterator_t;
typedef iterator_property_map
<std::vector<std::size_t>::iterator, EdgeIndexMap> component_map_t;
edge_size_t n_edges(num_edges(g));
std::vector<vertex_t> articulation_points;
std::vector<edge_size_t> component_vector(n_edges);
component_map_t component_map(component_vector.begin(), em);
biconnected_components(g, component_map,
std::back_inserter(articulation_points));
typename std::vector<vertex_t>::iterator ap, ap_end;
ap_end = articulation_points.end();
for(ap = articulation_points.begin(); ap != ap_end; ++ap)
{
vertex_t v(*ap);
embedding_iterator_t pi = embedding[v].begin();
embedding_iterator_t pi_end = embedding[v].end();
edge_size_t previous_component(n_edges + 1);
vertex_t previous_vertex = graph_traits<Graph>::null_vertex();
for(; pi != pi_end; ++pi)
{
edge_t e(*pi);
vertex_t e_source(source(e,g));
vertex_t e_target(target(e,g));
//Skip self-loops and parallel edges
if (e_source == e_target || previous_vertex == e_target)
continue;
vertex_t current_vertex = e_source == v ? e_target : e_source;
edge_size_t current_component = component_map[e];
if (previous_vertex != graph_traits<Graph>::null_vertex() &&
current_component != previous_component)
{
vis.visit_vertex_pair(current_vertex, previous_vertex, g);
}
previous_vertex = current_vertex;
previous_component = current_component;
}
}
}
template <typename Graph,
typename PlanarEmbedding,
typename EdgeIndexMap
>
inline void make_biconnected_planar(Graph& g,
PlanarEmbedding embedding,
EdgeIndexMap em
)
{
default_add_edge_visitor vis;
make_biconnected_planar(g, embedding, em, vis);
}
template <typename Graph,
typename PlanarEmbedding
>
inline void make_biconnected_planar(Graph& g, PlanarEmbedding embedding)
{
make_biconnected_planar(g, embedding, get(edge_index,g));
}
} // namespace boost
#endif //__MAKE_BICONNECTED_PLANAR_HPP__

View File

@@ -0,0 +1,99 @@
//=======================================================================
// Copyright 2007 Aaron Windsor
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
#ifndef __MAKE_CONNECTED_HPP__
#define __MAKE_CONNECTED_HPP__
#include <boost/config.hpp>
#include <boost/utility.hpp> //for next
#include <boost/tuple/tuple.hpp> //for tie
#include <boost/graph/connected_components.hpp>
#include <boost/property_map.hpp>
#include <vector>
#include <boost/graph/planar_detail/add_edge_visitors.hpp>
#include <boost/graph/planar_detail/bucket_sort.hpp>
namespace boost
{
template <typename Graph,
typename VertexIndexMap,
typename AddEdgeVisitor
>
void make_connected(Graph& g, VertexIndexMap vm, AddEdgeVisitor& vis)
{
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
typedef typename graph_traits<Graph>::vertices_size_type v_size_t;
typedef iterator_property_map< typename std::vector<v_size_t>::iterator,
VertexIndexMap
> vertex_to_v_size_map_t;
std::vector<v_size_t> component_vector(num_vertices(g));
vertex_to_v_size_map_t component(component_vector.begin(), vm);
std::vector<vertex_t> vertices_by_component(num_vertices(g));
v_size_t num_components = connected_components(g, component);
if (num_components < 2)
return;
vertex_iterator_t vi, vi_end;
tie(vi,vi_end) = vertices(g);
std::copy(vi, vi_end, vertices_by_component.begin());
bucket_sort(vertices_by_component.begin(),
vertices_by_component.end(),
component,
num_components
);
typedef typename std::vector<vertex_t>::iterator vec_of_vertices_itr_t;
vec_of_vertices_itr_t ci_end = vertices_by_component.end();
vec_of_vertices_itr_t ci_prev = vertices_by_component.begin();
if (ci_prev == ci_end)
return;
for(vec_of_vertices_itr_t ci = next(ci_prev);
ci != ci_end; ci_prev = ci, ++ci
)
{
if (component[*ci_prev] != component[*ci])
vis.visit_vertex_pair(*ci_prev, *ci, g);
}
}
template <typename Graph, typename VertexIndexMap>
inline void make_connected(Graph& g, VertexIndexMap vm)
{
default_add_edge_visitor vis;
make_connected(g, vm, vis);
}
template <typename Graph>
inline void make_connected(Graph& g)
{
make_connected(g, get(vertex_index,g));
}
} // namespace boost
#endif //__MAKE_CONNECTED_HPP__

View File

@@ -0,0 +1,275 @@
//=======================================================================
// Copyright 2007 Aaron Windsor
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
#ifndef __MAKE_MAXIMAL_PLANAR_HPP__
#define __MAKE_MAXIMAL_PLANAR_HPP__
#include <boost/config.hpp>
#include <boost/tuple/tuple.hpp> //for tie
#include <boost/graph/biconnected_components.hpp>
#include <boost/property_map.hpp>
#include <vector>
#include <iterator>
#include <algorithm>
#include <boost/graph/planar_face_traversal.hpp>
#include <boost/graph/planar_detail/add_edge_visitors.hpp>
namespace boost
{
template <typename Graph, typename VertexIndexMap, typename AddEdgeVisitor>
struct triangulation_visitor : public planar_face_traversal_visitor
{
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
typedef typename graph_traits<Graph>::vertices_size_type v_size_t;
typedef typename graph_traits<Graph>::degree_size_type degree_size_t;
typedef typename graph_traits<Graph>::edge_iterator edge_iterator_t;
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
typedef typename graph_traits<Graph>::adjacency_iterator
adjacency_iterator_t;
typedef typename std::vector<vertex_t> vertex_vector_t;
typedef typename std::vector<v_size_t> v_size_vector_t;
typedef typename std::vector<degree_size_t> degree_size_vector_t;
typedef iterator_property_map
< typename v_size_vector_t::iterator, VertexIndexMap >
vertex_to_v_size_map_t;
typedef iterator_property_map
< typename degree_size_vector_t::iterator, VertexIndexMap >
vertex_to_degree_size_map_t;
typedef typename vertex_vector_t::iterator face_iterator;
triangulation_visitor(Graph& arg_g,
VertexIndexMap arg_vm,
AddEdgeVisitor arg_add_edge_visitor
) :
g(arg_g),
vm(arg_vm),
add_edge_visitor(arg_add_edge_visitor),
timestamp(0),
marked_vector(num_vertices(g), timestamp),
degree_vector(num_vertices(g), 0),
marked(marked_vector.begin(), vm),
degree(degree_vector.begin(), vm)
{
vertex_iterator_t vi, vi_end;
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
put(degree, *vi, out_degree(*vi, g));
}
template <typename Vertex>
void next_vertex(Vertex v)
{
// Self-loops will appear as consecutive vertices in the list of
// vertices on a face. We want to skip these.
if (!vertices_on_face.empty() &&
(vertices_on_face.back() == v || vertices_on_face.front() == v)
)
return;
vertices_on_face.push_back(v);
}
void end_face()
{
++timestamp;
if (vertices_on_face.size() <= 3)
{
// At most three vertices on this face - don't need to triangulate
vertices_on_face.clear();
return;
}
// Find vertex on face of minimum degree
degree_size_t min_degree = num_vertices(g);
typename vertex_vector_t::iterator min_degree_vertex_itr;
face_iterator fi_end = vertices_on_face.end();
for(face_iterator fi = vertices_on_face.begin(); fi != fi_end; ++fi)
{
degree_size_t deg = get(degree,*fi);
if (deg < min_degree)
{
min_degree_vertex_itr = fi;
min_degree = deg;
}
}
// To simplify some of the manipulations, we'll re-arrange
// vertices_on_face so that it still contains the same
// (counter-clockwise) order of the vertices on this face, but now the
// min_degree_vertex is the first element in vertices_on_face.
vertex_vector_t temp_vector;
std::copy(min_degree_vertex_itr, vertices_on_face.end(),
std::back_inserter(temp_vector));
std::copy(vertices_on_face.begin(), min_degree_vertex_itr,
std::back_inserter(temp_vector));
vertices_on_face.swap(temp_vector);
// Mark all of the min degree vertex's neighbors
adjacency_iterator_t ai, ai_end;
for(tie(ai,ai_end) = adjacent_vertices(vertices_on_face.front(),g);
ai != ai_end; ++ai
)
{
put(marked, *ai, timestamp);
}
typename vertex_vector_t::iterator marked_neighbor
= vertices_on_face.end();
// The iterator manipulations on the next two lines are safe because
// vertices_on_face.size() > 3 (from the first test in this function)
fi_end = prior(vertices_on_face.end());
for(face_iterator fi = next(next(vertices_on_face.begin()));
fi != fi_end; ++fi
)
{
if (get(marked, *fi) == timestamp)
{
marked_neighbor = fi;
break;
}
}
if (marked_neighbor == vertices_on_face.end())
{
add_edge_range(
vertices_on_face[0],
next(next(vertices_on_face.begin())),
prior(vertices_on_face.end())
);
}
else
{
add_edge_range(
vertices_on_face[1],
next(marked_neighbor),
vertices_on_face.end()
);
add_edge_range(
*next(marked_neighbor),
next(next(vertices_on_face.begin())),
marked_neighbor
);
}
//reset for the next face
vertices_on_face.clear();
}
private:
void add_edge_range(vertex_t anchor,
face_iterator fi,
face_iterator fi_end
)
{
for (; fi != fi_end; ++fi)
{
vertex_t v(*fi);
add_edge_visitor.visit_vertex_pair(anchor, v, g);
put(degree, anchor, get(degree, anchor) + 1);
put(degree, v, get(degree, v) + 1);
}
}
Graph& g;
VertexIndexMap vm;
AddEdgeVisitor add_edge_visitor;
v_size_t timestamp;
vertex_vector_t vertices_on_face;
v_size_vector_t marked_vector;
degree_size_vector_t degree_vector;
vertex_to_v_size_map_t marked;
vertex_to_degree_size_map_t degree;
};
template <typename Graph,
typename PlanarEmbedding,
typename VertexIndexMap,
typename EdgeIndexMap,
typename AddEdgeVisitor
>
void make_maximal_planar(Graph& g,
PlanarEmbedding embedding,
VertexIndexMap vm,
EdgeIndexMap em,
AddEdgeVisitor& vis)
{
triangulation_visitor<Graph,VertexIndexMap,AddEdgeVisitor>
visitor(g, vm, vis);
planar_face_traversal(g, embedding, visitor, em);
}
template <typename Graph,
typename PlanarEmbedding,
typename VertexIndexMap,
typename EdgeIndexMap
>
void make_maximal_planar(Graph& g,
PlanarEmbedding embedding,
VertexIndexMap vm,
EdgeIndexMap em
)
{
default_add_edge_visitor vis;
make_maximal_planar(g, embedding, vm, em, vis);
}
template <typename Graph,
typename PlanarEmbedding,
typename VertexIndexMap
>
void make_maximal_planar(Graph& g,
PlanarEmbedding embedding,
VertexIndexMap vm
)
{
make_maximal_planar(g, embedding, vm, get(edge_index,g));
}
template <typename Graph,
typename PlanarEmbedding
>
void make_maximal_planar(Graph& g,
PlanarEmbedding embedding
)
{
make_maximal_planar(g, embedding, get(vertex_index,g));
}
} // namespace boost
#endif //__MAKE_MAXIMAL_PLANAR_HPP__

View File

@@ -45,10 +45,10 @@ namespace boost
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
{
vertex_descriptor_t v = *vi;
if (get(mate,v) != graph_traits<Graph>::null_vertex()
vertex_descriptor_t v = *vi;
if (get(mate,v) != graph_traits<Graph>::null_vertex()
&& get(vm,v) < get(vm,get(mate,v)))
++size_of_matching;
++size_of_matching;
}
return size_of_matching;
}
@@ -76,10 +76,10 @@ namespace boost
vertex_iterator_t vi, vi_end;
for( tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
{
vertex_descriptor_t v = *vi;
if (get(mate,v) != graph_traits<Graph>::null_vertex()
vertex_descriptor_t v = *vi;
if (get(mate,v) != graph_traits<Graph>::null_vertex()
&& v != get(mate,get(mate,v)))
return false;
return false;
}
return true;
}
@@ -188,7 +188,7 @@ namespace boost
{
vertex_iterator_t vi, vi_end;
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
mate[*vi] = get(arg_mate, *vi);
mate[*vi] = get(arg_mate, *vi);
}
@@ -206,25 +206,25 @@ namespace boost
vertex_iterator_t vi, vi_end;
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
{
vertex_descriptor_t u = *vi;
{
vertex_descriptor_t u = *vi;
origin[u] = u;
pred[u] = u;
ancestor_of_v[u] = 0;
ancestor_of_w[u] = 0;
ds.make_set(u);
origin[u] = u;
pred[u] = u;
ancestor_of_v[u] = 0;
ancestor_of_w[u] = 0;
ds.make_set(u);
if (mate[u] == graph_traits<Graph>::null_vertex())
if (mate[u] == graph_traits<Graph>::null_vertex())
{
vertex_state[u] = graph::detail::V_EVEN;
out_edge_iterator_t ei, ei_end;
for(tie(ei,ei_end) = out_edges(u,g); ei != ei_end; ++ei)
even_edges.push_back( *ei );
even_edges.push_back( *ei );
}
else
vertex_state[u] = graph::detail::V_UNREACHED;
}
else
vertex_state[u] = graph::detail::V_UNREACHED;
}
//end initializations
@@ -234,40 +234,41 @@ namespace boost
bool found_alternating_path = false;
while(!even_edges.empty() && !found_alternating_path)
{
// since we push even edges onto the back of the list as
// they're discovered, taking them off the back will search
// for augmenting paths depth-first.
edge_descriptor_t current_edge = even_edges.back();
even_edges.pop_back();
{
// since we push even edges onto the back of the list as
// they're discovered, taking them off the back will search
// for augmenting paths depth-first.
edge_descriptor_t current_edge = even_edges.back();
even_edges.pop_back();
v = source(current_edge,g);
w = target(current_edge,g);
v = source(current_edge,g);
w = target(current_edge,g);
vertex_descriptor_t v_prime = origin[ds.find_set(v)];
vertex_descriptor_t w_prime = origin[ds.find_set(w)];
vertex_descriptor_t v_prime = origin[ds.find_set(v)];
vertex_descriptor_t w_prime = origin[ds.find_set(w)];
// because of the way we put all of the edges on the queue,
// v_prime should be labeled V_EVEN; the following is a
// little paranoid but it could happen...
if (vertex_state[v_prime] != graph::detail::V_EVEN)
// because of the way we put all of the edges on the queue,
// v_prime should be labeled V_EVEN; the following is a
// little paranoid but it could happen...
if (vertex_state[v_prime] != graph::detail::V_EVEN)
{
std::swap(v_prime,w_prime);
std::swap(v,w);
}
if (vertex_state[w_prime] == graph::detail::V_UNREACHED)
if (vertex_state[w_prime] == graph::detail::V_UNREACHED)
{
vertex_state[w_prime] = graph::detail::V_ODD;
vertex_state[mate[w_prime]] = graph::detail::V_EVEN;
out_edge_iterator_t ei, ei_end;
for( tie(ei,ei_end) = out_edges(mate[w_prime], g); ei != ei_end; ++ei)
even_edges.push_back(*ei);
even_edges.push_back(*ei);
pred[w_prime] = v;
}
//w_prime == v_prime can happen below if we get an edge that has been
//shrunk into a blossom
else if (vertex_state[w_prime] == graph::detail::V_EVEN && w_prime != v_prime)
//w_prime == v_prime can happen below if we get an edge that has been
//shrunk into a blossom
else if (vertex_state[w_prime] == graph::detail::V_EVEN && w_prime != v_prime)
{
vertex_descriptor_t w_up = w_prime;
vertex_descriptor_t v_up = v_prime;
@@ -291,42 +292,42 @@ namespace boost
w_free_ancestor == graph_traits<Graph>::null_vertex()
)
)
{
ancestor_of_w[w_up] = timestamp;
ancestor_of_v[v_up] = timestamp;
{
ancestor_of_w[w_up] = timestamp;
ancestor_of_v[v_up] = timestamp;
if (w_free_ancestor == graph_traits<Graph>::null_vertex())
w_up = parent(w_up);
if (v_free_ancestor == graph_traits<Graph>::null_vertex())
v_up = parent(v_up);
if (w_free_ancestor == graph_traits<Graph>::null_vertex())
w_up = parent(w_up);
if (v_free_ancestor == graph_traits<Graph>::null_vertex())
v_up = parent(v_up);
if (mate[v_up] == graph_traits<Graph>::null_vertex())
v_free_ancestor = v_up;
if (mate[w_up] == graph_traits<Graph>::null_vertex())
w_free_ancestor = w_up;
if (mate[v_up] == graph_traits<Graph>::null_vertex())
v_free_ancestor = v_up;
if (mate[w_up] == graph_traits<Graph>::null_vertex())
w_free_ancestor = w_up;
if (ancestor_of_w[v_up] == timestamp)
if (ancestor_of_w[v_up] == timestamp)
nearest_common_ancestor = v_up;
else if (ancestor_of_v[w_up] == timestamp)
nearest_common_ancestor = w_up;
else if (v_free_ancestor == w_free_ancestor &&
v_free_ancestor != graph_traits<Graph>::null_vertex())
nearest_common_ancestor = v_up;
else if (ancestor_of_v[w_up] == timestamp)
nearest_common_ancestor = w_up;
else if (v_free_ancestor == w_free_ancestor &&
v_free_ancestor != graph_traits<Graph>::null_vertex())
nearest_common_ancestor = v_up;
}
}
if (nearest_common_ancestor == graph_traits<Graph>::null_vertex())
found_alternating_path = true; //to break out of the loop
found_alternating_path = true; //to break out of the loop
else
{
//shrink the blossom
link_and_set_bridges(w_prime, nearest_common_ancestor, std::make_pair(w,v));
link_and_set_bridges(v_prime, nearest_common_ancestor, std::make_pair(v,w));
}
{
//shrink the blossom
link_and_set_bridges(w_prime, nearest_common_ancestor, std::make_pair(w,v));
link_and_set_bridges(v_prime, nearest_common_ancestor, std::make_pair(v,w));
}
}
}
}
if (!found_alternating_path)
return false;
return false;
// retrieve the augmenting path and put it in aug_path
reversed_retrieve_augmenting_path(v, v_free_ancestor);
@@ -335,14 +336,14 @@ namespace boost
// augment the matching along aug_path
vertex_descriptor_t a,b;
while (!aug_path.empty())
{
a = aug_path.front();
aug_path.pop_front();
b = aug_path.front();
aug_path.pop_front();
mate[a] = b;
mate[b] = a;
}
{
a = aug_path.front();
aug_path.pop_front();
b = aug_path.front();
aug_path.pop_front();
mate[a] = b;
mate[b] = a;
}
return true;
@@ -356,7 +357,7 @@ namespace boost
{
vertex_iterator_t vi,vi_end;
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
put(pm, *vi, mate[*vi]);
put(pm, *vi, mate[*vi]);
}
@@ -367,7 +368,7 @@ namespace boost
{
vertex_iterator_t vi,vi_end;
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
put(pm, *vi, vertex_state[origin[ds.find_set(*vi)]]);
put(pm, *vi, vertex_state[origin[ds.find_set(*vi)]]);
}
@@ -379,11 +380,11 @@ namespace boost
{
if (vertex_state[x] == graph::detail::V_EVEN
&& mate[x] != graph_traits<Graph>::null_vertex())
return mate[x];
return mate[x];
else if (vertex_state[x] == graph::detail::V_ODD)
return origin[ds.find_set(pred[x])];
return origin[ds.find_set(pred[x])];
else
return x;
return x;
}
@@ -394,18 +395,18 @@ namespace boost
vertex_pair_t the_bridge)
{
for(vertex_descriptor_t v = x; v != stop_vertex; v = parent(v))
{
ds.union_set(v, stop_vertex);
origin[ds.find_set(stop_vertex)] = stop_vertex;
{
ds.union_set(v, stop_vertex);
origin[ds.find_set(stop_vertex)] = stop_vertex;
if (vertex_state[v] == graph::detail::V_ODD)
if (vertex_state[v] == graph::detail::V_ODD)
{
bridge[v] = the_bridge;
out_edge_iterator_t oei, oei_end;
for(tie(oei, oei_end) = out_edges(v,g); oei != oei_end; ++oei)
even_edges.push_back(*oei);
even_edges.push_back(*oei);
}
}
}
}
@@ -426,19 +427,19 @@ namespace boost
void retrieve_augmenting_path(vertex_descriptor_t v, vertex_descriptor_t w)
{
if (v == w)
aug_path.push_back(v);
aug_path.push_back(v);
else if (vertex_state[v] == graph::detail::V_EVEN)
{
aug_path.push_back(v);
aug_path.push_back(mate[v]);
retrieve_augmenting_path(pred[mate[v]], w);
}
{
aug_path.push_back(v);
aug_path.push_back(mate[v]);
retrieve_augmenting_path(pred[mate[v]], w);
}
else //vertex_state[v] == graph::detail::V_ODD
{
aug_path.push_back(v);
reversed_retrieve_augmenting_path(bridge[v].first, mate[v]);
retrieve_augmenting_path(bridge[v].second, w);
}
{
aug_path.push_back(v);
reversed_retrieve_augmenting_path(bridge[v].first, mate[v]);
retrieve_augmenting_path(bridge[v].second, w);
}
}
@@ -447,19 +448,19 @@ namespace boost
{
if (v == w)
aug_path.push_back(v);
aug_path.push_back(v);
else if (vertex_state[v] == graph::detail::V_EVEN)
{
reversed_retrieve_augmenting_path(pred[mate[v]], w);
aug_path.push_back(mate[v]);
aug_path.push_back(v);
}
{
reversed_retrieve_augmenting_path(pred[mate[v]], w);
aug_path.push_back(mate[v]);
aug_path.push_back(v);
}
else //vertex_state[v] == graph::detail::V_ODD
{
reversed_retrieve_augmenting_path(bridge[v].second, w);
retrieve_augmenting_path(bridge[v].first, mate[v]);
aug_path.push_back(v);
}
{
reversed_retrieve_augmenting_path(bridge[v].second, w);
retrieve_augmenting_path(bridge[v].first, mate[v]);
aug_path.push_back(v);
}
}
@@ -520,23 +521,23 @@ namespace boost
{
vertex_iterator_t vi, vi_end;
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
put(mate, *vi, graph_traits<Graph>::null_vertex());
put(mate, *vi, graph_traits<Graph>::null_vertex());
edge_iterator_t ei, ei_end;
for( tie(ei, ei_end) = edges(g); ei != ei_end; ++ei)
{
edge_descriptor_t e = *ei;
vertex_descriptor_t u = source(e,g);
vertex_descriptor_t v = target(e,g);
{
edge_descriptor_t e = *ei;
vertex_descriptor_t u = source(e,g);
vertex_descriptor_t v = target(e,g);
if (get(mate,u) == get(mate,v))
if (get(mate,u) == get(mate,v))
//only way equality can hold is if
// mate[u] == mate[v] == null_vertex
// mate[u] == mate[v] == null_vertex
{
put(mate,u,v);
put(mate,v,u);
}
}
}
}
};
@@ -581,9 +582,9 @@ namespace boost
less_than_by_degree(const Graph& g): m_g(g) {}
bool operator() (const vertex_pair_t x, const vertex_pair_t y)
{
return
out_degree(PairSelector::select_vertex(x), m_g)
< out_degree(PairSelector::select_vertex(y), m_g);
return
out_degree(PairSelector::select_vertex(x), m_g)
< out_degree(PairSelector::select_vertex(y), m_g);
}
private:
const Graph& m_g;
@@ -598,17 +599,17 @@ namespace boost
directed_edges_vector_t edge_list;
vertex_iterator_t vi, vi_end;
for(tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
put(mate, *vi, graph_traits<Graph>::null_vertex());
put(mate, *vi, graph_traits<Graph>::null_vertex());
edge_iterator_t ei, ei_end;
for(tie(ei, ei_end) = edges(g); ei != ei_end; ++ei)
{
edge_descriptor_t e = *ei;
vertex_descriptor_t u = source(e,g);
vertex_descriptor_t v = target(e,g);
edge_list.push_back(std::make_pair(u,v));
edge_list.push_back(std::make_pair(v,u));
}
{
edge_descriptor_t e = *ei;
vertex_descriptor_t u = source(e,g);
vertex_descriptor_t v = target(e,g);
edge_list.push_back(std::make_pair(u,v));
edge_list.push_back(std::make_pair(v,u));
}
//sort the edges by the degree of the target, then (using a
//stable sort) by degree of the source
@@ -619,14 +620,14 @@ namespace boost
//construct the extra greedy matching
for(typename directed_edges_vector_t::const_iterator itr = edge_list.begin(); itr != edge_list.end(); ++itr)
{
if (get(mate,itr->first) == get(mate,itr->second))
{
if (get(mate,itr->first) == get(mate,itr->second))
//only way equality can hold is if mate[itr->first] == mate[itr->second] == null_vertex
{
put(mate, itr->first, itr->second);
put(mate, itr->second, itr->first);
}
}
}
}
};
@@ -642,7 +643,7 @@ namespace boost
{
vertex_iterator_t vi, vi_end;
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
put(mate, *vi, graph_traits<Graph>::null_vertex());
put(mate, *vi, graph_traits<Graph>::null_vertex());
}
};
@@ -666,29 +667,29 @@ namespace boost
{
public:
odd_components_counter(SizeType& c_count):
m_count(c_count)
m_count(c_count)
{
m_count = 0;
m_count = 0;
}
template <class Vertex, class Graph>
void start_vertex(Vertex v, Graph&)
{
addend = -1;
{
m_parity = false;
}
template <class Vertex, class Graph>
void discover_vertex(Vertex u, Graph&)
{
addend *= -1;
m_count += addend;
m_parity = !m_parity;
m_parity ? ++m_count : --m_count;
}
protected:
SizeType& m_count;
private:
SizeType addend;
bool m_parity;
};
@@ -728,21 +729,27 @@ namespace boost
typedef typename map_vertex_to_<vertex_descriptor_t>::type
vertex_to_vertex_map_t;
template <typename VertexStateMap>
struct non_odd_vertex {
//this predicate is used to create a filtered graph that
//excludes vertices labeled "graph::detail::V_ODD"
non_odd_vertex() : vertex_state(0) { }
non_odd_vertex(VertexStateMap* arg_vertex_state)
non_odd_vertex(VertexStateMap* arg_vertex_state)
: vertex_state(arg_vertex_state) { }
template <typename Vertex>
bool operator()(const Vertex& v) const {
BOOST_ASSERT(vertex_state);
return get(*vertex_state, v) != graph::detail::V_ODD;
template <typename Vertex>
bool operator()(const Vertex& v) const
{
BOOST_ASSERT(vertex_state);
return get(*vertex_state, v) != graph::detail::V_ODD;
}
VertexStateMap* vertex_state;
};
static bool verify_matching(const Graph& g, MateMap mate, VertexIndexMap vm)
{
//For any graph G, let o(G) be the number of connected
@@ -763,7 +770,7 @@ namespace boost
//first, make sure it's a valid matching
if (!is_a_matching(g,mate,vm))
return false;
return false;
//We'll try to augment the matching once. This serves two
//purposes: first, if we find some augmenting path, the matching
@@ -775,7 +782,7 @@ namespace boost
edmonds_augmenting_path_finder<Graph,MateMap,VertexIndexMap>
augmentor(g,mate,vm);
if (augmentor.augment_matching())
return false;
return false;
std::vector<int> vertex_state_vector(num_vertices(g));
vertex_to_int_map_t vertex_state(vertex_state_vector.begin(), vm);
@@ -785,8 +792,8 @@ namespace boost
v_size_t num_odd_vertices = 0;
vertex_iterator_t vi, vi_end;
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
if (vertex_state[*vi] == graph::detail::V_ODD)
++num_odd_vertices;
if (vertex_state[*vi] == graph::detail::V_ODD)
++num_odd_vertices;
//count the number of connected components with odd cardinality
//in the graph without graph::detail::V_ODD vertices
@@ -798,9 +805,9 @@ namespace boost
depth_first_search(fg, visitor(occ).vertex_index_map(vm));
if (2 * matching_size(g,mate,vm) == num_vertices(g) + num_odd_vertices - num_odd_components)
return true;
return true;
else
return false;
return false;
}
};
@@ -822,7 +829,7 @@ namespace boost
bool not_maximum_yet = true;
while(not_maximum_yet)
{
not_maximum_yet = augmentor.augment_matching();
not_maximum_yet = augmentor.augment_matching();
}
augmentor.get_current_matching(mate);

View File

@@ -284,6 +284,27 @@ namespace boost {
return Params(c, *this);
}
template <typename VertexInvar>
bgl_named_params<VertexInvar, vertex_invariant1_t, self>
vertex_invariant1(const VertexInvar& c) const {
typedef bgl_named_params<VertexInvar, vertex_invariant1_t, self> Params;
return Params(c, *this);
}
template <typename VertexInvar>
bgl_named_params<VertexInvar, vertex_invariant2_t, self>
vertex_invariant2(const VertexInvar& c) const {
typedef bgl_named_params<VertexInvar, vertex_invariant2_t, self> Params;
return Params(c, *this);
}
template <typename VertexMaxInvar>
bgl_named_params<VertexMaxInvar, vertex_max_invariant_t, self>
vertex_max_invariant(const VertexMaxInvar& c) const {
typedef bgl_named_params<VertexMaxInvar, vertex_max_invariant_t, self> Params;
return Params(c, *this);
}
template <typename VertexDisplacement>
bgl_named_params<VertexDisplacement, vertex_displacement_t, self>
displacement_map(const VertexDisplacement& c) const {
@@ -547,6 +568,27 @@ namespace boost {
return Params(c);
}
template <typename VertexInvar>
bgl_named_params<VertexInvar, vertex_invariant1_t>
vertex_invariant1(const VertexInvar& c) {
typedef bgl_named_params<VertexInvar, vertex_invariant1_t> Params;
return Params(c);
}
template <typename VertexInvar>
bgl_named_params<VertexInvar, vertex_invariant2_t>
vertex_invariant2(const VertexInvar& c) {
typedef bgl_named_params<VertexInvar, vertex_invariant2_t> Params;
return Params(c);
}
template <typename VertexMaxInvar>
bgl_named_params<VertexMaxInvar, vertex_max_invariant_t>
vertex_max_invariant(const VertexMaxInvar& c) {
typedef bgl_named_params<VertexMaxInvar, vertex_max_invariant_t> Params;
return Params(c);
}
template <typename VertexDisplacement>
bgl_named_params<VertexDisplacement, vertex_displacement_t>
displacement_map(const VertexDisplacement& c) {

View File

@@ -0,0 +1,211 @@
//=======================================================================
// Copyright (c) Aaron Windsor 2007
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
#ifndef __PLANAR_CANONICAL_ORDERING_HPP__
#define __PLANAR_CANONICAL_ORDERING_HPP__
#include <vector>
#include <list>
#include <boost/config.hpp>
#include <boost/utility.hpp> //for next and prior
#include <boost/graph/graph_traits.hpp>
#include <boost/property_map.hpp>
namespace boost
{
template<typename Graph,
typename PlanarEmbedding,
typename OutputIterator,
typename VertexIndexMap>
void planar_canonical_ordering(const Graph& g,
PlanarEmbedding embedding,
OutputIterator ordering,
VertexIndexMap vm)
{
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
typedef typename graph_traits<Graph>::adjacency_iterator
adjacency_iterator_t;
typedef typename std::pair<vertex_t, vertex_t> vertex_pair_t;
typedef typename property_traits<PlanarEmbedding>::value_type
embedding_value_t;
typedef typename embedding_value_t::const_iterator embedding_iterator_t;
typedef iterator_property_map
<typename std::vector<vertex_t>::iterator, VertexIndexMap>
vertex_to_vertex_map_t;
typedef iterator_property_map
<typename std::vector<std::size_t>::iterator, VertexIndexMap>
vertex_to_size_t_map_t;
enum {PROCESSED,
UNPROCESSED,
ONE_NEIGHBOR_PROCESSED,
READY_TO_BE_PROCESSED};
std::vector<vertex_t> processed_neighbor_vector(num_vertices(g));
vertex_to_vertex_map_t processed_neighbor
(processed_neighbor_vector.begin(), vm);
std::vector<std::size_t> status_vector(num_vertices(g), UNPROCESSED);
vertex_to_size_t_map_t status(status_vector.begin(), vm);
std::list<vertex_t> ready_to_be_processed;
vertex_t first_vertex = *vertices(g).first;
vertex_t second_vertex;
adjacency_iterator_t ai, ai_end;
for(tie(ai,ai_end) = adjacent_vertices(first_vertex,g); ai != ai_end; ++ai)
{
if (*ai == first_vertex)
continue;
second_vertex = *ai;
break;
}
ready_to_be_processed.push_back(first_vertex);
status[first_vertex] = READY_TO_BE_PROCESSED;
ready_to_be_processed.push_back(second_vertex);
status[second_vertex] = READY_TO_BE_PROCESSED;
while(!ready_to_be_processed.empty())
{
vertex_t u = ready_to_be_processed.front();
ready_to_be_processed.pop_front();
if (status[u] != READY_TO_BE_PROCESSED && u != second_vertex)
continue;
embedding_iterator_t ei, ei_start, ei_end;
embedding_iterator_t next_edge_itr, prior_edge_itr;
ei_start = embedding[u].begin();
ei_end = embedding[u].end();
prior_edge_itr = prior(ei_end);
while(source(*prior_edge_itr, g) == target(*prior_edge_itr,g))
prior_edge_itr = prior(prior_edge_itr);
for(ei = ei_start; ei != ei_end; ++ei)
{
edge_t e(*ei); // e = (u,v)
next_edge_itr = next(ei) == ei_end ? ei_start : next(ei);
vertex_t v = source(e,g) == u ? target(e,g) : source(e,g);
vertex_t prior_vertex = source(*prior_edge_itr, g) == u ?
target(*prior_edge_itr, g) : source(*prior_edge_itr, g);
vertex_t next_vertex = source(*next_edge_itr, g) == u ?
target(*next_edge_itr, g) : source(*next_edge_itr, g);
// Need prior_vertex, u, v, and next_vertex to all be
// distinct. This is possible, since the input graph is
// triangulated. It'll be true all the time in a simple
// graph, but loops and parallel edges cause some complications.
if (prior_vertex == v || prior_vertex == u)
{
prior_edge_itr = ei;
continue;
}
//Skip any self-loops
if (u == v)
continue;
// Move next_edge_itr (and next_vertex) forwards
// past any loops or parallel edges
while (next_vertex == v || next_vertex == u)
{
next_edge_itr = next(next_edge_itr) == ei_end ?
ei_start : next(next_edge_itr);
next_vertex = source(*next_edge_itr, g) == u ?
target(*next_edge_itr, g) : source(*next_edge_itr, g);
}
if (status[v] == UNPROCESSED)
{
status[v] = ONE_NEIGHBOR_PROCESSED;
processed_neighbor[v] = u;
}
else if (status[v] == ONE_NEIGHBOR_PROCESSED)
{
vertex_t x = processed_neighbor[v];
//are edges (v,u) and (v,x) adjacent in the planar
//embedding? if so, set status[v] = 1. otherwise, set
//status[v] = 2.
if ((next_vertex == x &&
!(first_vertex == u && second_vertex == x)
)
||
(prior_vertex == x &&
!(first_vertex == x && second_vertex == u)
)
)
{
status[v] = READY_TO_BE_PROCESSED;
}
else
{
status[v] = READY_TO_BE_PROCESSED + 1;
}
}
else if (status[v] > ONE_NEIGHBOR_PROCESSED)
{
//check the two edges before and after (v,u) in the planar
//embedding, and update status[v] accordingly
bool processed_before = false;
if (status[prior_vertex] == PROCESSED)
processed_before = true;
bool processed_after = false;
if (status[next_vertex] == PROCESSED)
processed_after = true;
if (!processed_before && !processed_after)
++status[v];
else if (processed_before && processed_after)
--status[v];
}
if (status[v] == READY_TO_BE_PROCESSED)
ready_to_be_processed.push_back(v);
prior_edge_itr = ei;
}
status[u] = PROCESSED;
*ordering = u;
++ordering;
}
}
template<typename Graph, typename PlanarEmbedding, typename OutputIterator>
void planar_canonical_ordering(const Graph& g,
PlanarEmbedding embedding,
OutputIterator ordering
)
{
planar_canonical_ordering(g, embedding, ordering, get(vertex_index,g));
}
} //namespace boost
#endif //__PLANAR_CANONICAL_ORDERING_HPP__

View File

@@ -0,0 +1,59 @@
//=======================================================================
// Copyright 2007 Aaron Windsor
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
#ifndef __ADD_EDGE_VISITORS_HPP__
#define __ADD_EDGE_VISITORS_HPP__
#include <boost/property_map.hpp>
namespace boost
{
struct default_add_edge_visitor
{
template <typename Graph, typename Vertex>
void visit_vertex_pair(Vertex u, Vertex v, Graph& g)
{
add_edge(u,v,g);
}
};
template<typename EdgeIndexMap>
struct edge_index_update_visitor
{
typedef typename
property_traits<EdgeIndexMap>::value_type edge_index_value_t;
edge_index_update_visitor(EdgeIndexMap em,
edge_index_value_t next_index_available
) :
m_em(em),
m_next_index(next_index_available)
{}
template <typename Graph, typename Vertex>
void visit_vertex_pair(Vertex u, Vertex v, Graph& g)
{
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
std::pair<edge_t, bool> return_value = add_edge(u,v,g);
if (return_value.second)
put( m_em, return_value.first, m_next_index++);
}
private:
EdgeIndexMap m_em;
edge_index_value_t m_next_index;
};
} // namespace boost
#endif //__ADD_EDGE_VISITORS_HPP__

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,144 @@
//=======================================================================
// Copyright 2007 Aaron Windsor
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
#ifndef __BUCKET_SORT_HPP__
#define __BUCKET_SORT_HPP__
#include <vector>
#include <algorithm>
#include <boost/property_map.hpp>
namespace boost
{
template <typename ItemToRankMap>
struct rank_comparison
{
rank_comparison(ItemToRankMap arg_itrm) : itrm(arg_itrm) {}
template <typename Item>
bool operator() (Item x, Item y) const
{
return get(itrm, x) < get(itrm, y);
}
private:
ItemToRankMap itrm;
};
template <typename TupleType,
int N,
typename PropertyMapWrapper = identity_property_map>
struct property_map_tuple_adaptor :
public put_get_helper< typename PropertyMapWrapper::value_type,
property_map_tuple_adaptor
<TupleType, N, PropertyMapWrapper>
>
{
typedef typename PropertyMapWrapper::reference reference;
typedef typename PropertyMapWrapper::value_type value_type;
typedef TupleType key_type;
typedef readable_property_map_tag category;
property_map_tuple_adaptor() {}
property_map_tuple_adaptor(PropertyMapWrapper wrapper_map) :
m_wrapper_map(wrapper_map)
{}
inline value_type operator[](const key_type& x) const
{
return get(m_wrapper_map, get<n>(x));
}
static const int n = N;
PropertyMapWrapper m_wrapper_map;
};
// This function sorts a sequence of n items by their ranks in linear time,
// given that all ranks are in the range [0, range). This sort is stable.
template <typename ForwardIterator,
typename ItemToRankMap,
typename SizeType>
void bucket_sort(ForwardIterator begin,
ForwardIterator end,
ItemToRankMap rank,
SizeType range = 0)
{
#ifdef BOOST_GRAPH_PREFER_STD_LIB
std::stable_sort(begin, end, rank_comparison<ItemToRankMap>(rank));
#else
typedef std::vector
< typename boost::property_traits<ItemToRankMap>::key_type >
vector_of_values_t;
typedef std::vector< vector_of_values_t > vector_of_vectors_t;
if (!range)
{
rank_comparison<ItemToRankMap> cmp(rank);
ForwardIterator max_by_rank = std::max_element(begin, end, cmp);
if (max_by_rank == end)
return;
range = get(rank, *max_by_rank) + 1;
}
vector_of_vectors_t temp_values(range);
for(ForwardIterator itr = begin; itr != end; ++itr)
{
temp_values[get(rank, *itr)].push_back(*itr);
}
ForwardIterator orig_seq_itr = begin;
typename vector_of_vectors_t::iterator itr_end = temp_values.end();
for(typename vector_of_vectors_t::iterator itr = temp_values.begin();
itr != itr_end; ++itr
)
{
typename vector_of_values_t::iterator jtr_end = itr->end();
for(typename vector_of_values_t::iterator jtr = itr->begin();
jtr != jtr_end; ++jtr
)
{
*orig_seq_itr = *jtr;
++orig_seq_itr;
}
}
#endif
}
template <typename ForwardIterator, typename ItemToRankMap>
void bucket_sort(ForwardIterator begin,
ForwardIterator end,
ItemToRankMap rank)
{
bucket_sort(begin, end, rank, 0);
}
template <typename ForwardIterator>
void bucket_sort(ForwardIterator begin,
ForwardIterator end
)
{
bucket_sort(begin, end, identity_property_map());
}
} //namespace boost
#endif //__BUCKET_SORT_HPP__

View File

@@ -0,0 +1,497 @@
//=======================================================================
// Copyright (c) Aaron Windsor 2007
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
#ifndef __FACE_HANDLES_HPP__
#define __FACE_HANDLES_HPP__
#include <list>
#include <boost/graph/graph_traits.hpp>
#include <boost/shared_ptr.hpp>
// A "face handle" is an optimization meant to serve two purposes in
// the implementation of the Boyer-Myrvold planarity test: (1) it holds
// the partial planar embedding of a particular vertex as it's being
// constructed, and (2) it allows for efficient traversal around the
// outer face of the partial embedding at that particular vertex. A face
// handle is lightweight, just a shared pointer to the actual implementation,
// since it is passed around/copied liberally in the algorithm. It consists
// of an "anchor" (the actual vertex it's associated with) as well as a
// sequence of edges. The functions first_vertex/second_vertex and
// first_edge/second_edge allow fast access to the beginning and end of the
// stored sequence, which allows one to traverse the outer face of the partial
// planar embedding as it's being created.
//
// There are some policies below that define the contents of the face handles:
// in the case no embedding is needed (for example, if one just wants to use
// the Boyer-Myrvold algorithm as a true/false test for planarity, the
// no_embedding class can be passed as the StoreEmbedding policy. Otherwise,
// either std_list (which uses as std::list) or recursive_lazy_list can be
// passed as this policy. recursive_lazy_list has the best theoretical
// performance (O(n) for a sequence of interleaved concatenations and reversals
// of the underlying list), but I've noticed little difference between std_list
// and recursive_lazy_list in my tests, even though using std_list changes
// the worst-case complexity of the planarity test to O(n^2)
//
// Another policy is StoreOldHandlesPolicy, which specifies whether or not
// to keep a record of the previous first/second vertex/edge - this is needed
// if a Kuratowski subgraph needs to be isolated.
namespace boost { namespace graph { namespace detail {
//face handle policies
//EmbeddingStorage policy
struct store_embedding {};
struct recursive_lazy_list : public store_embedding {};
struct std_list : public store_embedding {};
struct no_embedding {};
//StoreOldHandlesPolicy
struct store_old_handles {};
struct no_old_handles {};
template<typename DataType>
struct lazy_list_node
{
typedef shared_ptr< lazy_list_node<DataType> > ptr_t;
lazy_list_node(const DataType& data) :
m_reversed(false),
m_data(data),
m_has_data(true)
{}
lazy_list_node(ptr_t left_child, ptr_t right_child) :
m_reversed(false),
m_has_data(false),
m_left_child(left_child),
m_right_child(right_child)
{}
bool m_reversed;
DataType m_data;
bool m_has_data;
shared_ptr<lazy_list_node> m_left_child;
shared_ptr<lazy_list_node> m_right_child;
};
template <typename StoreOldHandlesPolicy, typename Vertex, typename Edge>
struct old_handles_storage;
template <typename Vertex, typename Edge>
struct old_handles_storage<store_old_handles, Vertex, Edge>
{
Vertex first_vertex;
Vertex second_vertex;
Edge first_edge;
Edge second_edge;
};
template <typename Vertex, typename Edge>
struct old_handles_storage<no_old_handles, Vertex, Edge>
{};
template <typename StoreEmbeddingPolicy, typename Edge>
struct edge_list_storage;
template <typename Edge>
struct edge_list_storage<no_embedding, Edge>
{
typedef void type;
void push_back(Edge) {}
void push_front(Edge) {}
void reverse() {}
void concat_front(edge_list_storage<no_embedding,Edge>) {}
void concat_back(edge_list_storage<no_embedding,Edge>) {}
template <typename OutputIterator>
void get_list(OutputIterator) {}
};
template <typename Edge>
struct edge_list_storage<recursive_lazy_list, Edge>
{
typedef lazy_list_node<Edge> node_type;
typedef shared_ptr< node_type > type;
type value;
void push_back(Edge e)
{
type new_node(new node_type(e));
value = type(new node_type(value, new_node));
}
void push_front(Edge e)
{
type new_node(new node_type(e));
value = type(new node_type(new_node, value));
}
void reverse()
{
value->m_reversed = !value->m_reversed;
}
void concat_front(edge_list_storage<recursive_lazy_list, Edge> other)
{
value = type(new node_type(other.value, value));
}
void concat_back(edge_list_storage<recursive_lazy_list, Edge> other)
{
value = type(new node_type(value, other.value));
}
template <typename OutputIterator>
void get_list(OutputIterator out)
{
get_list_helper(out, value);
}
private:
template <typename OutputIterator>
void get_list_helper(OutputIterator o_itr,
type root,
bool flipped = false
)
{
if (!root)
return;
if (root->m_has_data)
*o_itr = root->m_data;
if ((flipped && !root->m_reversed) ||
(!flipped && root->m_reversed)
)
{
get_list_helper(o_itr, root->m_right_child, true);
get_list_helper(o_itr, root->m_left_child, true);
}
else
{
get_list_helper(o_itr, root->m_left_child, false);
get_list_helper(o_itr, root->m_right_child, false);
}
}
};
template <typename Edge>
struct edge_list_storage<std_list, Edge>
{
typedef std::list<Edge> type;
type value;
void push_back(Edge e)
{
value.push_back(e);
}
void push_front(Edge e)
{
value.push_front(e);
}
void reverse()
{
value.reverse();
}
void concat_front(edge_list_storage<std_list,Edge> other)
{
value.splice(value.begin(), other.value);
}
void concat_back(edge_list_storage<std_list, Edge> other)
{
value.splice(value.end(), other.value);
}
template <typename OutputIterator>
void get_list(OutputIterator out)
{
std::copy(value.begin(), value.end(), out);
}
};
template<typename Graph,
typename StoreOldHandlesPolicy,
typename StoreEmbeddingPolicy
>
struct face_handle_impl
{
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
typedef typename edge_list_storage<StoreEmbeddingPolicy, edge_t>::type
edge_list_storage_t;
face_handle_impl() :
cached_first_vertex(graph_traits<Graph>::null_vertex()),
cached_second_vertex(graph_traits<Graph>::null_vertex()),
true_first_vertex(graph_traits<Graph>::null_vertex()),
true_second_vertex(graph_traits<Graph>::null_vertex()),
anchor(graph_traits<Graph>::null_vertex())
{
initialize_old_vertices_dispatch(StoreOldHandlesPolicy());
}
void initialize_old_vertices_dispatch(store_old_handles)
{
old_handles.first_vertex = graph_traits<Graph>::null_vertex();
old_handles.second_vertex = graph_traits<Graph>::null_vertex();
}
void initialize_old_vertices_dispatch(no_old_handles) {}
vertex_t cached_first_vertex;
vertex_t cached_second_vertex;
vertex_t true_first_vertex;
vertex_t true_second_vertex;
vertex_t anchor;
edge_t cached_first_edge;
edge_t cached_second_edge;
edge_list_storage<StoreEmbeddingPolicy, edge_t> edge_list;
old_handles_storage<StoreOldHandlesPolicy, vertex_t, edge_t> old_handles;
};
template <typename Graph,
typename StoreOldHandlesPolicy = store_old_handles,
typename StoreEmbeddingPolicy = recursive_lazy_list
>
class face_handle
{
public:
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
typedef face_handle_impl
<Graph, StoreOldHandlesPolicy, StoreEmbeddingPolicy> impl_t;
typedef face_handle
<Graph, StoreOldHandlesPolicy, StoreEmbeddingPolicy> self_t;
face_handle(vertex_t anchor = graph_traits<Graph>::null_vertex()) :
pimpl(new impl_t())
{
pimpl->anchor = anchor;
}
face_handle(vertex_t anchor, edge_t initial_edge, const Graph& g) :
pimpl(new impl_t())
{
vertex_t s(source(initial_edge,g));
vertex_t t(target(initial_edge,g));
vertex_t other_vertex = s == anchor ? t : s;
pimpl->anchor = anchor;
pimpl->cached_first_edge = initial_edge;
pimpl->cached_second_edge = initial_edge;
pimpl->cached_first_vertex = other_vertex;
pimpl->cached_second_vertex = other_vertex;
pimpl->true_first_vertex = other_vertex;
pimpl->true_second_vertex = other_vertex;
pimpl->edge_list.push_back(initial_edge);
store_old_face_handles_dispatch(StoreOldHandlesPolicy());
}
//default copy construction, assignment okay.
void push_first(edge_t e, const Graph& g)
{
pimpl->edge_list.push_front(e);
pimpl->cached_first_vertex = pimpl->true_first_vertex =
source(e, g) == pimpl->anchor ? target(e,g) : source(e,g);
pimpl->cached_first_edge = e;
}
void push_second(edge_t e, const Graph& g)
{
pimpl->edge_list.push_back(e);
pimpl->cached_second_vertex = pimpl->true_second_vertex =
source(e, g) == pimpl->anchor ? target(e,g) : source(e,g);
pimpl->cached_second_edge = e;
}
inline void store_old_face_handles()
{
store_old_face_handles_dispatch(StoreOldHandlesPolicy());
}
inline vertex_t first_vertex() const
{
return pimpl->cached_first_vertex;
}
inline vertex_t second_vertex() const
{
return pimpl->cached_second_vertex;
}
inline vertex_t true_first_vertex() const
{
return pimpl->true_first_vertex;
}
inline vertex_t true_second_vertex() const
{
return pimpl->true_second_vertex;
}
inline vertex_t old_first_vertex() const
{
return pimpl->old_handles.first_vertex;
}
inline vertex_t old_second_vertex() const
{
return pimpl->old_handles.second_vertex;
}
inline edge_t old_first_edge() const
{
return pimpl->old_handles.first_edge;
}
inline edge_t old_second_edge() const
{
return pimpl->old_handles.second_edge;
}
inline edge_t first_edge() const
{
return pimpl->cached_first_edge;
}
inline edge_t second_edge() const
{
return pimpl->cached_second_edge;
}
inline vertex_t get_anchor() const
{
return pimpl->anchor;
}
void glue_first_to_second
(face_handle<Graph,StoreOldHandlesPolicy,StoreEmbeddingPolicy>& bottom)
{
pimpl->edge_list.concat_front(bottom.pimpl->edge_list);
pimpl->true_first_vertex = bottom.pimpl->true_first_vertex;
pimpl->cached_first_vertex = bottom.pimpl->cached_first_vertex;
pimpl->cached_first_edge = bottom.pimpl->cached_first_edge;
}
void glue_second_to_first
(face_handle<Graph,StoreOldHandlesPolicy,StoreEmbeddingPolicy>& bottom)
{
pimpl->edge_list.concat_back(bottom.pimpl->edge_list);
pimpl->true_second_vertex = bottom.pimpl->true_second_vertex;
pimpl->cached_second_vertex = bottom.pimpl->cached_second_vertex;
pimpl->cached_second_edge = bottom.pimpl->cached_second_edge;
}
void flip()
{
pimpl->edge_list.reverse();
std::swap(pimpl->true_first_vertex, pimpl->true_second_vertex);
std::swap(pimpl->cached_first_vertex, pimpl->cached_second_vertex);
std::swap(pimpl->cached_first_edge, pimpl->cached_second_edge);
}
template <typename OutputIterator>
void get_list(OutputIterator o_itr)
{
pimpl->edge_list.get_list(o_itr);
}
void reset_vertex_cache()
{
pimpl->cached_first_vertex = pimpl->true_first_vertex;
pimpl->cached_second_vertex = pimpl->true_second_vertex;
}
inline void set_first_vertex(vertex_t v)
{
pimpl->cached_first_vertex = v;
}
inline void set_second_vertex(vertex_t v)
{
pimpl->cached_second_vertex = v;
}
private:
void store_old_face_handles_dispatch(store_old_handles)
{
pimpl->old_handles.first_vertex = pimpl->true_first_vertex;
pimpl->old_handles.second_vertex = pimpl->true_second_vertex;
pimpl->old_handles.first_edge = pimpl->cached_first_edge;
pimpl->old_handles.second_edge = pimpl->cached_second_edge;
}
void store_old_face_handles_dispatch(no_old_handles) {}
boost::shared_ptr<impl_t> pimpl;
};
} /* namespace detail */ } /* namespace graph */ } /* namespace boost */
#endif //__FACE_HANDLES_HPP__

View File

@@ -0,0 +1,375 @@
//=======================================================================
// Copyright (c) Aaron Windsor 2007
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
#ifndef __FACE_ITERATORS_HPP__
#define __FACE_ITERATORS_HPP__
#include <boost/iterator/iterator_facade.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/graph/graph_traits.hpp>
namespace boost
{
//tags for defining traversal properties
//VisitorType
struct lead_visitor {};
struct follow_visitor {};
//TraversalType
struct single_side {};
struct both_sides {};
//TraversalSubType
struct first_side {}; //for single_side
struct second_side {}; //for single_side
struct alternating {}; //for both_sides
//Time
struct current_iteration {};
struct previous_iteration {};
// Why TraversalType AND TraversalSubType? TraversalSubType is a function
// template parameter passed in to the constructor of the face iterator,
// whereas TraversalType is a class template parameter. This lets us decide
// at runtime whether to move along the first or second side of a bicomp (by
// assigning a face_iterator that has been constructed with TraversalSubType
// = first_side or second_side to a face_iterator variable) without any of
// the virtual function overhead that comes with implementing this
// functionality as a more structured form of type erasure. It also allows
// a single face_iterator to be the end iterator of two iterators traversing
// both sides of a bicomp.
//ValueType is either graph_traits<Graph>::vertex_descriptor
//or graph_traits<Graph>::edge_descriptor
//forward declaration (defining defaults)
template <typename Graph,
typename FaceHandlesMap,
typename ValueType,
typename BicompSideToTraverse = single_side,
typename VisitorType = lead_visitor,
typename Time = current_iteration
>
class face_iterator;
template <typename Graph, bool StoreEdge>
struct edge_storage
{};
template <typename Graph>
struct edge_storage <Graph, true>
{
typename graph_traits<Graph>::edge_descriptor value;
};
//specialization for TraversalType = traverse_vertices
template <typename Graph,
typename FaceHandlesMap,
typename ValueType,
typename TraversalType,
typename VisitorType,
typename Time
>
class face_iterator
: public boost::iterator_facade < face_iterator<Graph,
FaceHandlesMap,
ValueType,
TraversalType,
VisitorType,
Time
>,
ValueType,
boost::forward_traversal_tag,
ValueType
>
{
public:
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
typedef face_iterator
<Graph,FaceHandlesMap,ValueType,TraversalType,VisitorType,Time> self;
typedef typename FaceHandlesMap::value_type face_handle_t;
face_iterator() :
m_lead(graph_traits<Graph>::null_vertex()),
m_follow(graph_traits<Graph>::null_vertex())
{}
template <typename TraversalSubType>
face_iterator(face_handle_t anchor_handle,
FaceHandlesMap face_handles,
TraversalSubType traversal_type):
m_follow(anchor_handle.get_anchor()),
m_face_handles(face_handles)
{
set_lead_dispatch(anchor_handle, traversal_type);
}
template <typename TraversalSubType>
face_iterator(vertex_t anchor,
FaceHandlesMap face_handles,
TraversalSubType traversal_type):
m_follow(anchor),
m_face_handles(face_handles)
{
set_lead_dispatch(m_face_handles[anchor], traversal_type);
}
private:
friend class boost::iterator_core_access;
inline vertex_t get_first_vertex(face_handle_t anchor_handle,
current_iteration
)
{
return anchor_handle.first_vertex();
}
inline vertex_t get_second_vertex(face_handle_t anchor_handle,
current_iteration
)
{
return anchor_handle.second_vertex();
}
inline vertex_t get_first_vertex(face_handle_t anchor_handle,
previous_iteration
)
{
return anchor_handle.old_first_vertex();
}
inline vertex_t get_second_vertex(face_handle_t anchor_handle,
previous_iteration
)
{
return anchor_handle.old_second_vertex();
}
inline void set_lead_dispatch(face_handle_t anchor_handle, first_side)
{
m_lead = get_first_vertex(anchor_handle, Time());
set_edge_to_first_dispatch(anchor_handle, ValueType(), Time());
}
inline void set_lead_dispatch(face_handle_t anchor_handle, second_side)
{
m_lead = get_second_vertex(anchor_handle, Time());
set_edge_to_second_dispatch(anchor_handle, ValueType(), Time());
}
inline void set_edge_to_first_dispatch(face_handle_t anchor_handle,
edge_t,
current_iteration
)
{
m_edge.value = anchor_handle.first_edge();
}
inline void set_edge_to_second_dispatch(face_handle_t anchor_handle,
edge_t,
current_iteration
)
{
m_edge.value = anchor_handle.second_edge();
}
inline void set_edge_to_first_dispatch(face_handle_t anchor_handle,
edge_t,
previous_iteration
)
{
m_edge.value = anchor_handle.old_first_edge();
}
inline void set_edge_to_second_dispatch(face_handle_t anchor_handle,
edge_t,
previous_iteration
)
{
m_edge.value = anchor_handle.old_second_edge();
}
template<typename T>
inline void set_edge_to_first_dispatch(face_handle_t, vertex_t, T)
{}
template<typename T>
inline void set_edge_to_second_dispatch(face_handle_t, vertex_t, T)
{}
void increment()
{
face_handle_t curr_face_handle(m_face_handles[m_lead]);
vertex_t first = get_first_vertex(curr_face_handle, Time());
vertex_t second = get_second_vertex(curr_face_handle, Time());
if (first == m_follow)
{
m_follow = m_lead;
set_edge_to_second_dispatch(curr_face_handle, ValueType(), Time());
m_lead = second;
}
else if (second == m_follow)
{
m_follow = m_lead;
set_edge_to_first_dispatch(curr_face_handle, ValueType(), Time());
m_lead = first;
}
else
m_lead = m_follow = graph_traits<Graph>::null_vertex();
}
bool equal(self const& other) const
{
return m_lead == other.m_lead && m_follow == other.m_follow;
}
ValueType dereference() const
{
return dereference_dispatch(VisitorType(), ValueType());
}
inline ValueType dereference_dispatch(lead_visitor, vertex_t) const
{ return m_lead; }
inline ValueType dereference_dispatch(follow_visitor, vertex_t) const
{ return m_follow; }
inline ValueType dereference_dispatch(lead_visitor, edge_t) const
{ return m_edge.value; }
inline ValueType dereference_dispatch(follow_visitor, edge_t) const
{ return m_edge.value; }
vertex_t m_lead;
vertex_t m_follow;
edge_storage<Graph, boost::is_same<ValueType, edge_t>::value > m_edge;
FaceHandlesMap m_face_handles;
};
template <typename Graph,
typename FaceHandlesMap,
typename ValueType,
typename VisitorType,
typename Time
>
class face_iterator
<Graph, FaceHandlesMap, ValueType, both_sides, VisitorType, Time>
: public boost::iterator_facade< face_iterator<Graph,
FaceHandlesMap,
ValueType,
both_sides,
VisitorType,
Time>,
ValueType,
boost::forward_traversal_tag,
ValueType >
{
public:
typedef face_iterator
<Graph,FaceHandlesMap,ValueType,both_sides,VisitorType,Time> self;
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
typedef typename FaceHandlesMap::value_type face_handle_t;
face_iterator() {}
face_iterator(face_handle_t anchor_handle, FaceHandlesMap face_handles):
first_itr(anchor_handle, face_handles, first_side()),
second_itr(anchor_handle, face_handles, second_side()),
first_is_active(true),
first_increment(true)
{}
face_iterator(vertex_t anchor, FaceHandlesMap face_handles):
first_itr(face_handles[anchor], face_handles, first_side()),
second_itr(face_handles[anchor], face_handles, second_side()),
first_is_active(true),
first_increment(true)
{}
private:
friend class boost::iterator_core_access;
typedef face_iterator
<Graph, FaceHandlesMap, ValueType, single_side, follow_visitor, Time>
inner_itr_t;
void increment()
{
if (first_increment)
{
++first_itr;
++second_itr;
first_increment = false;
}
else if (first_is_active)
++first_itr;
else
++second_itr;
first_is_active = !first_is_active;
}
bool equal(self const& other) const
{
//Want this iterator to be equal to the "end" iterator when at least
//one of the iterators has reached the root of the current bicomp.
//This isn't ideal, but it works.
return (first_itr == other.first_itr || second_itr == other.second_itr);
}
ValueType dereference() const
{
return first_is_active ? *first_itr : *second_itr;
}
inner_itr_t first_itr;
inner_itr_t second_itr;
inner_itr_t face_end;
bool first_is_active;
bool first_increment;
};
} /* namespace boost */
#endif //__FACE_ITERATORS_HPP__

View File

@@ -0,0 +1,210 @@
//=======================================================================
// Copyright (c) Aaron Windsor 2007
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
#ifndef __PLANAR_FACE_TRAVERSAL_HPP__
#define __PLANAR_FACE_TRAVERSAL_HPP__
#include <vector>
#include <boost/utility.hpp> //for next and prior
#include <boost/graph/graph_traits.hpp>
namespace boost
{
struct planar_face_traversal_visitor
{
void begin_traversal()
{}
void begin_face()
{}
template <typename Edge>
void next_edge(Edge e)
{}
template <typename Vertex>
void next_vertex(Vertex v)
{}
void end_face()
{}
void end_traversal()
{}
};
template<typename Graph,
typename PlanarEmbedding,
typename Visitor,
typename EdgeIndexMap>
void planar_face_traversal(const Graph& g,
PlanarEmbedding embedding,
Visitor& visitor, EdgeIndexMap em
)
{
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
typedef typename graph_traits<Graph>::edge_iterator edge_iterator_t;
typedef typename
property_traits<PlanarEmbedding>::value_type embedding_value_t;
typedef typename embedding_value_t::const_iterator embedding_iterator_t;
typedef typename
std::vector< std::set<vertex_t> > distinguished_edge_storage_t;
typedef typename
std::vector< std::map<vertex_t, edge_t> >
distinguished_edge_to_edge_storage_t;
typedef typename
boost::iterator_property_map
<typename distinguished_edge_storage_t::iterator, EdgeIndexMap>
distinguished_edge_map_t;
typedef typename
boost::iterator_property_map
<typename distinguished_edge_to_edge_storage_t::iterator, EdgeIndexMap>
distinguished_edge_to_edge_map_t;
distinguished_edge_storage_t visited_vector(num_edges(g));
distinguished_edge_to_edge_storage_t next_edge_vector(num_edges(g));
distinguished_edge_map_t visited(visited_vector.begin(), em);
distinguished_edge_to_edge_map_t next_edge(next_edge_vector.begin(), em);
vertex_iterator_t vi, vi_end;
typename std::vector<edge_t>::iterator ei, ei_end;
edge_iterator_t fi, fi_end;
embedding_iterator_t pi, pi_begin, pi_end;
visitor.begin_traversal();
// Initialize the next_edge property map. This map is initialized from the
// PlanarEmbedding so that get(next_edge, e)[v] is the edge that comes
// after e in the clockwise embedding around vertex v.
for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
{
vertex_t v(*vi);
pi_begin = embedding[v].begin();
pi_end = embedding[v].end();
for(pi = pi_begin; pi != pi_end; ++pi)
{
edge_t e(*pi);
std::map<vertex_t, edge_t> m = get(next_edge, e);
m[v] = next(pi) == pi_end ? *pi_begin : *next(pi);
put(next_edge, e, m);
}
}
// Take a copy of the edges in the graph here, since we want to accomodate
// face traversals that add edges to the graph (for triangulation, in
// particular) and don't want to use invalidated edge iterators.
// Also, while iterating over all edges in the graph, we single out
// any self-loops, which need some special treatment in the face traversal.
std::vector<edge_t> self_loops;
std::vector<edge_t> edges_cache;
std::vector<vertex_t> vertices_in_edge;
for(tie(fi,fi_end) = edges(g); fi != fi_end; ++fi)
{
edge_t e(*fi);
edges_cache.push_back(e);
if (source(e,g) == target(e,g))
self_loops.push_back(e);
}
// Iterate over all edges in the graph
ei_end = edges_cache.end();
for(ei = edges_cache.begin(); ei != ei_end; ++ei)
{
edge_t e(*ei);
vertices_in_edge.clear();
vertices_in_edge.push_back(source(e,g));
vertices_in_edge.push_back(target(e,g));
typename std::vector<vertex_t>::iterator vi, vi_end;
vi_end = vertices_in_edge.end();
//Iterate over both vertices in the current edge
for(vi = vertices_in_edge.begin(); vi != vi_end; ++vi)
{
vertex_t v(*vi);
std::set<vertex_t> e_visited = get(visited, e);
typename std::set<vertex_t>::iterator e_visited_found
= e_visited.find(v);
if (e_visited_found == e_visited.end())
visitor.begin_face();
while (e_visited.find(v) == e_visited.end())
{
visitor.next_vertex(v);
visitor.next_edge(e);
e_visited.insert(v);
put(visited, e, e_visited);
v = source(e,g) == v ? target(e,g) : source(e,g);
e = get(next_edge, e)[v];
e_visited = get(visited, e);
}
if (e_visited_found == e_visited.end())
visitor.end_face();
}
}
// Iterate over all self-loops, visiting them once separately
// (they've already been visited once, this visitation is for
// the "inside" of the self-loop)
ei_end = self_loops.end();
for(ei = self_loops.begin(); ei != ei_end; ++ei)
{
visitor.begin_face();
visitor.next_edge(*ei);
visitor.next_vertex(source(*ei,g));
visitor.end_face();
}
visitor.end_traversal();
}
template<typename Graph, typename PlanarEmbedding, typename Visitor>
inline void planar_face_traversal(const Graph& g,
PlanarEmbedding embedding,
Visitor& visitor
)
{
planar_face_traversal(g, embedding, visitor, get(edge_index, g));
}
} //namespace boost
#endif //__PLANAR_FACE_TRAVERSAL_HPP__

View File

@@ -16,6 +16,13 @@
#include <boost/graph/graph_traits.hpp>
#include <boost/type_traits/is_convertible.hpp>
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
// Stay out of the way of the concept checking class
# define Graph Graph_
# define RandomAccessContainer RandomAccessContainer_
#endif
namespace boost {
enum default_color_type { white_color, gray_color, green_color, red_color, black_color };
@@ -322,7 +329,7 @@ namespace boost {
#if defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
# define BOOST_GRAPH_NO_BUNDLED_PROPERTIES
#endif
#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
template<typename Graph, typename Descriptor, typename Bundle, typename T>
struct bundle_property_map
@@ -354,11 +361,11 @@ namespace boost {
typedef graph_traits<Graph> traits;
typedef typename Graph::vertex_bundled vertex_bundled;
typedef typename Graph::edge_bundled edge_bundled;
typedef typename ct_if<(detail::is_vertex_bundle<vertex_bundled, edge_bundled, Bundle>::value),
typedef typename mpl::if_c<(detail::is_vertex_bundle<vertex_bundled, edge_bundled, Bundle>::value),
typename traits::vertex_descriptor,
typename traits::edge_descriptor>::type
descriptor;
typedef typename ct_if<(detail::is_vertex_bundle<vertex_bundled, edge_bundled, Bundle>::value),
typedef typename mpl::if_c<(detail::is_vertex_bundle<vertex_bundled, edge_bundled, Bundle>::value),
vertex_bundled,
edge_bundled>::type
actual_bundle;
@@ -372,4 +379,11 @@ namespace boost {
} // namespace boost
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
// Stay out of the way of the concept checking class
# undef Graph
# undef RandomAccessIterator
#endif
#endif /* BOOST_GRAPH_PROPERTIES_HPPA */

View File

@@ -20,7 +20,7 @@
#include <boost/property_map_iterator.hpp>
#include <boost/graph/properties.hpp>
#include <boost/pending/ct_if.hpp>
#include <boost/mpl/if.hpp>
#include <boost/type_traits/same_traits.hpp>
namespace boost {
@@ -34,7 +34,7 @@ namespace boost {
typedef typename property_map<Graph, PropertyTag>::const_type
const_map_type;
typedef typename property_kind<PropertyTag>::type Kind;
typedef typename ct_if<is_same<Kind, vertex_property_tag>::value,
typedef typename mpl::if_c<is_same<Kind, vertex_property_tag>::value,
typename graph_traits<Graph>::vertex_iterator,
typename graph_traits<Graph>::edge_iterator>::type iter;
public:

View File

@@ -9,15 +9,13 @@
/*
Reads maximal flow problem in extended DIMACS format.
Reads from stdin.
This works, but could use some polishing.
*/
/* ----------------------------------------------------------------- */
#include <vector>
#include <istream>
#include <stdio.h>
namespace boost {
@@ -27,7 +25,8 @@ int read_dimacs_max_flow(Graph& g,
CapacityMap capacity,
ReverseEdgeMap reverse_edge,
typename graph_traits<Graph>::vertex_descriptor& src,
typename graph_traits<Graph>::vertex_descriptor& sink)
typename graph_traits<Graph>::vertex_descriptor& sink,
std::istream& in=std::cin)
{
// const int MAXLINE = 100; /* max line length in the input file */
const int ARC_FIELDS = 3; /* no of fields in arc line */
@@ -114,7 +113,7 @@ int read_dimacs_max_flow(Graph& g,
- does service functions
*/
while (std::getline(std::cin, in_line)) {
while (std::getline(in, in_line)) {
++no_lines;
switch (in_line[0]) {

View File

@@ -24,11 +24,11 @@ namespace boost {
{
T operator()(const T& a, const T& b) const {
using namespace std;
T zero(0);
T result = a + b;
if (result < zero && a >= zero && b >= zero)
return (numeric_limits<T>::max)();
return result;
T zero(0);
T result = a + b;
if (result < zero && a >= zero && b >= zero)
return (numeric_limits<T>::max)();
return result;
}
};

View File

@@ -10,6 +10,11 @@
#include <boost/graph/properties.hpp>
#include <boost/tuple/tuple.hpp>
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
// Stay out of the way of the concept checking class
# define BidirectionalGraph BidirectionalGraph_
#endif
namespace boost {
struct reverse_graph_tag { };
@@ -311,4 +316,9 @@ get_property(const reverse_graph<BidirectionalGraph,GRef>& g, Tag tag)
} // namespace boost
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
// Stay out of the way of the concept checking class
# undef BidirectionalGraph
#endif
#endif

View File

@@ -20,6 +20,11 @@
#include <boost/limits.hpp>
#include <boost/graph/detail/is_same.hpp>
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
// Stay out of the way of the concept checking class
# define Graph Graph_
#endif
namespace boost {
// This is a bit more convenient than std::numeric_limits because
@@ -266,4 +271,9 @@ namespace boost {
} /* namespace boost */
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
// Stay out of the way of the concept checking class
# undef Graph
#endif
#endif

View File

@@ -0,0 +1,72 @@
// Copyright (c) 2006, Stephan Diederich
//
// This code may be used under either of the following two licences:
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE. OF SUCH DAMAGE.
//
// Or:
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
/*
Writes maximal flow problem in extended DIMACS format to an OutputIterator
Vertex indices are read from an IndexMap and shiftet by 1.
so their new range is [1..num_vertices(g)]
*/
/* ----------------------------------------------------------------- */
#include <vector>
#include <string>
#include <ostream>
namespace boost {
template <class Graph, class CapacityMap, class IndexMap>
void write_dimacs_max_flow(const Graph& g,
CapacityMap capacity,
IndexMap idx,
typename graph_traits<Graph>::vertex_descriptor src,
typename graph_traits<Graph>::vertex_descriptor sink,
std::ostream& out)
{
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
typedef typename graph_traits<Graph>::vertices_size_type vertices_size_type;
typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
typedef typename graph_traits<Graph>::edges_size_type edges_size_type;
typedef typename graph_traits<Graph>::edge_iterator edge_iterator;
out << "c DIMACS max-flow file generated from boost::write_dimacs_max_flow" << std::endl;
out << "p max " << num_vertices(g) << " " << num_edges(g) << std::endl; //print problem description "max" and number of verts and edges
out << "n " << get(idx, src) + 1 << " s" << std::endl;; //say which one is source
out << "n " << get(idx, sink) + 1 << " t" << std::endl; //say which one is sink
//output the edges
edge_iterator ei, e_end;
for(tie(ei,e_end) = edges(g); ei!=e_end; ++ei){
out << "a " << idx[ source(*ei, g) ] + 1 << " " << idx[ target(*ei, g) ] + 1 << " " << get(capacity,*ei) << std::endl;
}
}
} // namespace boost

View File

@@ -39,6 +39,12 @@
# endif
#endif
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
// Stay out of the way of concept checking class templates
# define Container Container_
# define AssociativeContainer AssociativeContainer_
#endif
// The content of this file is in 'graph_detail' because otherwise
// there will be name clashes with
// sandbox/boost/sequence_algo/container_traits.hpp
@@ -410,4 +416,10 @@ namespace boost { namespace graph_detail {
}} // namespace boost::graph_detail
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
// Stay out of the way of concept checking class templates
# undef Container
# undef AssociativeContainer
#endif
#endif // BOOST_GRAPH_DETAIL_CONTAINER_TRAITS_H

View File

@@ -120,12 +120,14 @@ public:
new_roots[r] = nil();
if (_compare(_key[u], _key[v])) {
_degree[v] = r;
_mark[v] = false;
std::swap(u, v);
}
make_child(u, v, r);
++r;
}
_degree[v] = r;
_mark[v] = false;
}
// 40
void make_child(size_type u, size_type v, size_type r) {
@@ -178,7 +180,7 @@ public:
if (p == nil()) {
if (_compare(d, _key[_root]))
_root = v;
} else if (_compare(d, _key[_root]))
} else if (_compare(d, _key[p]))
while (1) {
size_type r = _degree[p];
if (r >= 2)
@@ -191,6 +193,7 @@ public:
}
if (_mark[p] == false) {
_mark[p] = true;
--_degree[p];
break;
} else
--_degree[p];
@@ -237,7 +240,7 @@ protected:
void print_recur(size_type x, std::ostream& os) {
if (x != nil()) {
os << x;
if (_child[x] != nil()) {
if (_degree[x] > 0) {
os << "(";
size_type i = _child[x];
do {

View File

@@ -13,6 +13,8 @@
#include <boost/property_map.hpp>
#include <boost/optional.hpp>
#include <vector>
#include <climits> // for CHAR_BIT
#include <boost/none.hpp>
#ifdef BOOST_RELAXED_HEAP_DEBUG
# include <iostream>
@@ -172,14 +174,14 @@ public:
value_type& top()
{
find_smallest();
assert(smallest_value->value != 0);
assert(smallest_value->value != none);
return *smallest_value->value;
}
const value_type& top() const
{
find_smallest();
assert(smallest_value->value != 0);
assert(smallest_value->value != none);
return *smallest_value->value;
}
@@ -202,7 +204,7 @@ public:
rank_type r = x->rank;
group* p = x->parent;
{
assert(x->value != 0);
assert(x->value != none);
// Find x's group
size_type start = get(id, *x->value) - get(id, *x->value) % log_n;

View File

@@ -3,6 +3,9 @@
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_STRINGTOK_HPP
#define BOOST_STRINGTOK_HPP
/*
* stringtok.hpp -- Breaks a string into tokens. This is an example for lib3.
*
@@ -109,3 +112,5 @@ stringtok (Container &l, std::string const &s, char const * const ws = " \t\n")
} // namespace boost
#endif // BOOST_STRINGTOK_HPP