// | |
//======================================================================= | |
// Copyright 1997-2001 University of Notre Dame. | |
// Authors: Jeremy G. Siek, Lie-Quan Lee, Andrew Lumsdaine | |
// | |
// Distributed under the Boost Software License, Version 1.0. (See | |
// accompanying file LICENSE_1_0.txt or copy at | |
// http://www.boost.org/LICENSE_1_0.txt) | |
//======================================================================= | |
// | |
/* | |
This file implements the following functions: | |
template <typename VertexListGraph, typename MutableGraph> | |
void copy_graph(const VertexListGraph& g_in, MutableGraph& g_out) | |
template <typename VertexListGraph, typename MutableGraph, | |
class P, class T, class R> | |
void copy_graph(const VertexListGraph& g_in, MutableGraph& g_out, | |
const bgl_named_params<P, T, R>& params) | |
template <typename IncidenceGraph, typename MutableGraph> | |
typename graph_traits<MutableGraph>::vertex_descriptor | |
copy_component(IncidenceGraph& g_in, | |
typename graph_traits<IncidenceGraph>::vertex_descriptor src, | |
MutableGraph& g_out) | |
template <typename IncidenceGraph, typename MutableGraph, | |
typename P, typename T, typename R> | |
typename graph_traits<MutableGraph>::vertex_descriptor | |
copy_component(IncidenceGraph& g_in, | |
typename graph_traits<IncidenceGraph>::vertex_descriptor src, | |
MutableGraph& g_out, | |
const bgl_named_params<P, T, R>& params) | |
*/ | |
#ifndef BOOST_GRAPH_COPY_HPP | |
#define BOOST_GRAPH_COPY_HPP | |
#include <boost/config.hpp> | |
#include <vector> | |
#include <boost/graph/graph_traits.hpp> | |
#include <boost/property_map/property_map.hpp> | |
#include <boost/graph/named_function_params.hpp> | |
#include <boost/graph/breadth_first_search.hpp> | |
#include <boost/type_traits/conversion_traits.hpp> | |
namespace boost { | |
namespace detail { | |
// Default edge and vertex property copiers | |
template <typename Graph1, typename Graph2> | |
struct edge_copier { | |
edge_copier(const Graph1& g1, Graph2& g2) | |
: edge_all_map1(get(edge_all, g1)), | |
edge_all_map2(get(edge_all, g2)) { } | |
template <typename Edge1, typename Edge2> | |
void operator()(const Edge1& e1, Edge2& e2) const { | |
put(edge_all_map2, e2, get(edge_all_map1, e1)); | |
} | |
typename property_map<Graph1, edge_all_t>::const_type edge_all_map1; | |
mutable typename property_map<Graph2, edge_all_t>::type edge_all_map2; | |
}; | |
template <typename Graph1, typename Graph2> | |
inline edge_copier<Graph1,Graph2> | |
make_edge_copier(const Graph1& g1, Graph2& g2) | |
{ | |
return edge_copier<Graph1,Graph2>(g1, g2); | |
} | |
template <typename Graph1, typename Graph2> | |
struct vertex_copier { | |
vertex_copier(const Graph1& g1, Graph2& g2) | |
: vertex_all_map1(get(vertex_all, g1)), | |
vertex_all_map2(get(vertex_all, g2)) { } | |
template <typename Vertex1, typename Vertex2> | |
void operator()(const Vertex1& v1, Vertex2& v2) const { | |
put(vertex_all_map2, v2, get(vertex_all_map1, v1)); | |
} | |
typename property_map<Graph1, vertex_all_t>::const_type vertex_all_map1; | |
mutable typename property_map<Graph2, vertex_all_t>::type | |
vertex_all_map2; | |
}; | |
template <typename Graph1, typename Graph2> | |
inline vertex_copier<Graph1,Graph2> | |
make_vertex_copier(const Graph1& g1, Graph2& g2) | |
{ | |
return vertex_copier<Graph1,Graph2>(g1, g2); | |
} | |
// Copy all the vertices and edges of graph g_in into graph g_out. | |
// The copy_vertex and copy_edge function objects control how vertex | |
// and edge properties are copied. | |
template <int Version> | |
struct copy_graph_impl { }; | |
template <> struct copy_graph_impl<0> | |
{ | |
template <typename Graph, typename MutableGraph, | |
typename CopyVertex, typename CopyEdge, typename IndexMap, | |
typename Orig2CopyVertexIndexMap> | |
static void apply(const Graph& g_in, MutableGraph& g_out, | |
CopyVertex copy_vertex, CopyEdge copy_edge, | |
Orig2CopyVertexIndexMap orig2copy, IndexMap) | |
{ | |
typename graph_traits<Graph>::vertex_iterator vi, vi_end; | |
for (boost::tie(vi, vi_end) = vertices(g_in); vi != vi_end; ++vi) { | |
typename graph_traits<MutableGraph>::vertex_descriptor | |
new_v = add_vertex(g_out); | |
put(orig2copy, *vi, new_v); | |
copy_vertex(*vi, new_v); | |
} | |
typename graph_traits<Graph>::edge_iterator ei, ei_end; | |
for (boost::tie(ei, ei_end) = edges(g_in); ei != ei_end; ++ei) { | |
typename graph_traits<MutableGraph>::edge_descriptor new_e; | |
bool inserted; | |
boost::tie(new_e, inserted) = add_edge(get(orig2copy, source(*ei, g_in)), | |
get(orig2copy, target(*ei, g_in)), | |
g_out); | |
copy_edge(*ei, new_e); | |
} | |
} | |
}; | |
// for directed graphs | |
template <> struct copy_graph_impl<1> | |
{ | |
template <typename Graph, typename MutableGraph, | |
typename CopyVertex, typename CopyEdge, typename IndexMap, | |
typename Orig2CopyVertexIndexMap> | |
static void apply(const Graph& g_in, MutableGraph& g_out, | |
CopyVertex copy_vertex, CopyEdge copy_edge, | |
Orig2CopyVertexIndexMap orig2copy, IndexMap) | |
{ | |
typename graph_traits<Graph>::vertex_iterator vi, vi_end; | |
for (boost::tie(vi, vi_end) = vertices(g_in); vi != vi_end; ++vi) { | |
typename graph_traits<MutableGraph>::vertex_descriptor | |
new_v = add_vertex(g_out); | |
put(orig2copy, *vi, new_v); | |
copy_vertex(*vi, new_v); | |
} | |
for (boost::tie(vi, vi_end) = vertices(g_in); vi != vi_end; ++vi) { | |
typename graph_traits<Graph>::out_edge_iterator ei, ei_end; | |
for (boost::tie(ei, ei_end) = out_edges(*vi, g_in); ei != ei_end; ++ei) { | |
typename graph_traits<MutableGraph>::edge_descriptor new_e; | |
bool inserted; | |
boost::tie(new_e, inserted) = add_edge(get(orig2copy, source(*ei, g_in)), | |
get(orig2copy, target(*ei, g_in)), | |
g_out); | |
copy_edge(*ei, new_e); | |
} | |
} | |
} | |
}; | |
// for undirected graphs | |
template <> struct copy_graph_impl<2> | |
{ | |
template <typename Graph, typename MutableGraph, | |
typename CopyVertex, typename CopyEdge, typename IndexMap, | |
typename Orig2CopyVertexIndexMap> | |
static void apply(const Graph& g_in, MutableGraph& g_out, | |
CopyVertex copy_vertex, CopyEdge copy_edge, | |
Orig2CopyVertexIndexMap orig2copy, | |
IndexMap index_map) | |
{ | |
typedef color_traits<default_color_type> Color; | |
std::vector<default_color_type> | |
color(num_vertices(g_in), Color::white()); | |
typename graph_traits<Graph>::vertex_iterator vi, vi_end; | |
for (boost::tie(vi, vi_end) = vertices(g_in); vi != vi_end; ++vi) { | |
typename graph_traits<MutableGraph>::vertex_descriptor | |
new_v = add_vertex(g_out); | |
put(orig2copy, *vi, new_v); | |
copy_vertex(*vi, new_v); | |
} | |
for (boost::tie(vi, vi_end) = vertices(g_in); vi != vi_end; ++vi) { | |
typename graph_traits<Graph>::out_edge_iterator ei, ei_end; | |
for (boost::tie(ei, ei_end) = out_edges(*vi, g_in); ei != ei_end; ++ei) { | |
typename graph_traits<MutableGraph>::edge_descriptor new_e; | |
bool inserted; | |
if (color[get(index_map, target(*ei, g_in))] == Color::white()) { | |
boost::tie(new_e, inserted) = add_edge(get(orig2copy, source(*ei,g_in)), | |
get(orig2copy, target(*ei,g_in)), | |
g_out); | |
copy_edge(*ei, new_e); | |
} | |
} | |
color[get(index_map, *vi)] = Color::black(); | |
} | |
} | |
}; | |
template <class Graph> | |
struct choose_graph_copy { | |
typedef typename Graph::traversal_category Trv; | |
typedef typename Graph::directed_category Dr; | |
enum { algo = | |
(is_convertible<Trv, vertex_list_graph_tag>::value | |
&& is_convertible<Trv, edge_list_graph_tag>::value) | |
? 0 : is_convertible<Dr, directed_tag>::value ? 1 : 2 }; | |
typedef copy_graph_impl<algo> type; | |
}; | |
//------------------------------------------------------------------------- | |
struct choose_copier_parameter { | |
template <class P, class G1, class G2> | |
struct bind_ { | |
typedef const P& result_type; | |
static result_type apply(const P& p, const G1&, G2&) | |
{ return p; } | |
}; | |
}; | |
struct choose_default_edge_copier { | |
template <class P, class G1, class G2> | |
struct bind_ { | |
typedef edge_copier<G1, G2> result_type; | |
static result_type apply(const P&, const G1& g1, G2& g2) { | |
return result_type(g1, g2); | |
} | |
}; | |
}; | |
template <class Param> | |
struct choose_edge_copy { | |
typedef choose_copier_parameter type; | |
}; | |
template <> | |
struct choose_edge_copy<detail::error_property_not_found> { | |
typedef choose_default_edge_copier type; | |
}; | |
template <class Param, class G1, class G2> | |
struct choose_edge_copier_helper { | |
typedef typename choose_edge_copy<Param>::type Selector; | |
typedef typename Selector:: template bind_<Param, G1, G2> Bind; | |
typedef Bind type; | |
typedef typename Bind::result_type result_type; | |
}; | |
template <typename Param, typename G1, typename G2> | |
typename detail::choose_edge_copier_helper<Param,G1,G2>::result_type | |
choose_edge_copier(const Param& params, const G1& g_in, G2& g_out) | |
{ | |
typedef typename | |
detail::choose_edge_copier_helper<Param,G1,G2>::type Choice; | |
return Choice::apply(params, g_in, g_out); | |
} | |
struct choose_default_vertex_copier { | |
template <class P, class G1, class G2> | |
struct bind_ { | |
typedef vertex_copier<G1, G2> result_type; | |
static result_type apply(const P&, const G1& g1, G2& g2) { | |
return result_type(g1, g2); | |
} | |
}; | |
}; | |
template <class Param> | |
struct choose_vertex_copy { | |
typedef choose_copier_parameter type; | |
}; | |
template <> | |
struct choose_vertex_copy<detail::error_property_not_found> { | |
typedef choose_default_vertex_copier type; | |
}; | |
template <class Param, class G1, class G2> | |
struct choose_vertex_copier_helper { | |
typedef typename choose_vertex_copy<Param>::type Selector; | |
typedef typename Selector:: template bind_<Param, G1, G2> Bind; | |
typedef Bind type; | |
typedef typename Bind::result_type result_type; | |
}; | |
template <typename Param, typename G1, typename G2> | |
typename detail::choose_vertex_copier_helper<Param,G1,G2>::result_type | |
choose_vertex_copier(const Param& params, const G1& g_in, G2& g_out) | |
{ | |
typedef typename | |
detail::choose_vertex_copier_helper<Param,G1,G2>::type Choice; | |
return Choice::apply(params, g_in, g_out); | |
} | |
} // namespace detail | |
template <typename VertexListGraph, typename MutableGraph> | |
void copy_graph(const VertexListGraph& g_in, MutableGraph& g_out) | |
{ | |
if (num_vertices(g_in) == 0) | |
return; | |
typedef typename graph_traits<MutableGraph>::vertex_descriptor vertex_t; | |
std::vector<vertex_t> orig2copy(num_vertices(g_in)); | |
typedef typename detail::choose_graph_copy<VertexListGraph>::type | |
copy_impl; | |
copy_impl::apply | |
(g_in, g_out, | |
detail::make_vertex_copier(g_in, g_out), | |
detail::make_edge_copier(g_in, g_out), | |
make_iterator_property_map(orig2copy.begin(), | |
get(vertex_index, g_in), orig2copy[0]), | |
get(vertex_index, g_in) | |
); | |
} | |
template <typename VertexListGraph, typename MutableGraph, | |
class P, class T, class R> | |
void copy_graph(const VertexListGraph& g_in, MutableGraph& g_out, | |
const bgl_named_params<P, T, R>& params) | |
{ | |
typename std::vector<T>::size_type n; | |
n = is_default_param(get_param(params, orig_to_copy_t())) | |
? num_vertices(g_in) : 1; | |
if (n == 0) | |
return; | |
std::vector<BOOST_DEDUCED_TYPENAME graph_traits<MutableGraph>::vertex_descriptor> | |
orig2copy(n); | |
typedef typename detail::choose_graph_copy<VertexListGraph>::type | |
copy_impl; | |
copy_impl::apply | |
(g_in, g_out, | |
detail::choose_vertex_copier(get_param(params, vertex_copy_t()), | |
g_in, g_out), | |
detail::choose_edge_copier(get_param(params, edge_copy_t()), | |
g_in, g_out), | |
choose_param(get_param(params, orig_to_copy_t()), | |
make_iterator_property_map | |
(orig2copy.begin(), | |
choose_const_pmap(get_param(params, vertex_index), | |
g_in, vertex_index), orig2copy[0])), | |
choose_const_pmap(get_param(params, vertex_index), g_in, vertex_index) | |
); | |
} | |
namespace detail { | |
template <class NewGraph, class Copy2OrigIndexMap, | |
class CopyVertex, class CopyEdge> | |
struct graph_copy_visitor : public bfs_visitor<> | |
{ | |
graph_copy_visitor(NewGraph& graph, Copy2OrigIndexMap c, | |
CopyVertex cv, CopyEdge ce) | |
: g_out(graph), orig2copy(c), copy_vertex(cv), copy_edge(ce) { } | |
template <class Vertex, class Graph> | |
typename graph_traits<NewGraph>::vertex_descriptor copy_one_vertex(Vertex u) const { | |
typename graph_traits<NewGraph>::vertex_descriptor | |
new_u = add_vertex(g_out); | |
put(orig2copy, u, new_u); | |
copy_vertex(u, new_u); | |
return new_u; | |
} | |
template <class Edge, class Graph> | |
void tree_edge(Edge e, const Graph& g_in) const { | |
// For a tree edge, the target vertex has not been copied yet. | |
typename graph_traits<NewGraph>::edge_descriptor new_e; | |
bool inserted; | |
boost::tie(new_e, inserted) = add_edge(get(orig2copy, source(e, g_in)), | |
this->copy_one_vertex(target(e, g_in)), | |
g_out); | |
copy_edge(e, new_e); | |
} | |
template <class Edge, class Graph> | |
void non_tree_edge(Edge e, const Graph& g_in) const { | |
// For a non-tree edge, the target vertex has already been copied. | |
typename graph_traits<NewGraph>::edge_descriptor new_e; | |
bool inserted; | |
boost::tie(new_e, inserted) = add_edge(get(orig2copy, source(e, g_in)), | |
get(orig2copy, target(e, g_in)), | |
g_out); | |
copy_edge(e, new_e); | |
} | |
private: | |
NewGraph& g_out; | |
Copy2OrigIndexMap orig2copy; | |
CopyVertex copy_vertex; | |
CopyEdge copy_edge; | |
}; | |
template <typename Graph, typename MutableGraph, | |
typename CopyVertex, typename CopyEdge, | |
typename Orig2CopyVertexIndexMap, typename Params> | |
typename graph_traits<MutableGraph>::vertex_descriptor | |
copy_component_impl | |
(const Graph& g_in, | |
typename graph_traits<Graph>::vertex_descriptor src, | |
MutableGraph& g_out, | |
CopyVertex copy_vertex, CopyEdge copy_edge, | |
Orig2CopyVertexIndexMap orig2copy, | |
const Params& params) | |
{ | |
graph_copy_visitor<MutableGraph, Orig2CopyVertexIndexMap, | |
CopyVertex, CopyEdge> vis(g_out, orig2copy, copy_vertex, copy_edge); | |
typename graph_traits<MutableGraph>::vertex_descriptor src_copy | |
= vis.copy_one_vertex(src); | |
breadth_first_search(g_in, src, params.visitor(vis)); | |
return src_copy; | |
} | |
} // namespace detail | |
// Copy all the vertices and edges of graph g_in that are reachable | |
// from the source vertex into graph g_out. Return the vertex | |
// in g_out that matches the source vertex of g_in. | |
template <typename IncidenceGraph, typename MutableGraph, | |
typename P, typename T, typename R> | |
typename graph_traits<MutableGraph>::vertex_descriptor | |
copy_component(IncidenceGraph& g_in, | |
typename graph_traits<IncidenceGraph>::vertex_descriptor src, | |
MutableGraph& g_out, | |
const bgl_named_params<P, T, R>& params) | |
{ | |
typename std::vector<T>::size_type n; | |
n = is_default_param(get_param(params, orig_to_copy_t())) | |
? num_vertices(g_in) : 1; | |
std::vector<typename graph_traits<IncidenceGraph>::vertex_descriptor> | |
orig2copy(n); | |
return detail::copy_component_impl | |
(g_in, src, g_out, | |
detail::choose_vertex_copier(get_param(params, vertex_copy_t()), | |
g_in, g_out), | |
detail::choose_edge_copier(get_param(params, edge_copy_t()), | |
g_in, g_out), | |
choose_param(get_param(params, orig_to_copy_t()), | |
make_iterator_property_map | |
(orig2copy.begin(), | |
choose_pmap(get_param(params, vertex_index), | |
g_in, vertex_index), orig2copy[0])), | |
params | |
); | |
} | |
template <typename IncidenceGraph, typename MutableGraph> | |
typename graph_traits<MutableGraph>::vertex_descriptor | |
copy_component(IncidenceGraph& g_in, | |
typename graph_traits<IncidenceGraph>::vertex_descriptor src, | |
MutableGraph& g_out) | |
{ | |
std::vector<typename graph_traits<IncidenceGraph>::vertex_descriptor> | |
orig2copy(num_vertices(g_in)); | |
return detail::copy_component_impl | |
(g_in, src, g_out, | |
make_vertex_copier(g_in, g_out), | |
make_edge_copier(g_in, g_out), | |
make_iterator_property_map(orig2copy.begin(), | |
get(vertex_index, g_in), orig2copy[0]), | |
bgl_named_params<char,char>('x') // dummy param object | |
); | |
} | |
} // namespace boost | |
#endif // BOOST_GRAPH_COPY_HPP |