copy.hpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  1. //
  2. //=======================================================================
  3. // Copyright 1997-2001 University of Notre Dame.
  4. // Authors: Jeremy G. Siek, Lie-Quan Lee, Andrew Lumsdaine
  5. //
  6. // Distributed under the Boost Software License, Version 1.0. (See
  7. // accompanying file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt)
  9. //=======================================================================
  10. //
  11. /*
  12. This file implements the following functions:
  13. template <typename VertexListGraph, typename MutableGraph>
  14. void copy_graph(const VertexListGraph& g_in, MutableGraph& g_out)
  15. template <typename VertexListGraph, typename MutableGraph,
  16. class P, class T, class R>
  17. void copy_graph(const VertexListGraph& g_in, MutableGraph& g_out,
  18. const bgl_named_params<P, T, R>& params)
  19. template <typename IncidenceGraph, typename MutableGraph>
  20. typename graph_traits<MutableGraph>::vertex_descriptor
  21. copy_component(IncidenceGraph& g_in,
  22. typename graph_traits<IncidenceGraph>::vertex_descriptor src,
  23. MutableGraph& g_out)
  24. template <typename IncidenceGraph, typename MutableGraph,
  25. typename P, typename T, typename R>
  26. typename graph_traits<MutableGraph>::vertex_descriptor
  27. copy_component(IncidenceGraph& g_in,
  28. typename graph_traits<IncidenceGraph>::vertex_descriptor src,
  29. MutableGraph& g_out,
  30. const bgl_named_params<P, T, R>& params)
  31. */
  32. #ifndef BOOST_GRAPH_COPY_HPP
  33. #define BOOST_GRAPH_COPY_HPP
  34. #include <boost/config.hpp>
  35. #include <vector>
  36. #include <boost/graph/graph_traits.hpp>
  37. #include <boost/graph/reverse_graph.hpp>
  38. #include <boost/property_map/property_map.hpp>
  39. #include <boost/graph/named_function_params.hpp>
  40. #include <boost/graph/breadth_first_search.hpp>
  41. #include <boost/type_traits/conversion_traits.hpp>
  42. namespace boost {
  43. namespace detail {
  44. // Hack to make transpose_graph work with the same interface as before
  45. template <typename Graph, typename Desc>
  46. struct remove_reverse_edge_descriptor {
  47. typedef Desc type;
  48. static Desc convert(const Desc& d, const Graph&) {return d;}
  49. };
  50. template <typename Graph, typename Desc>
  51. struct remove_reverse_edge_descriptor<Graph, reverse_graph_edge_descriptor<Desc> > {
  52. typedef Desc type;
  53. static Desc convert(const reverse_graph_edge_descriptor<Desc>& d, const Graph& g) {
  54. return get(edge_underlying, g, d);
  55. }
  56. };
  57. // Add a reverse_graph_edge_descriptor wrapper if the Graph is a
  58. // reverse_graph but the edge descriptor is from the original graph (this
  59. // case comes from the fact that transpose_graph uses reverse_graph
  60. // internally but doesn't expose the different edge descriptor type to the
  61. // user).
  62. template <typename Desc, typename Graph>
  63. struct add_reverse_edge_descriptor {
  64. typedef Desc type;
  65. static Desc convert(const Desc& d) {return d;}
  66. };
  67. template <typename Desc, typename G, typename GR>
  68. struct add_reverse_edge_descriptor<Desc, boost::reverse_graph<G, GR> > {
  69. typedef reverse_graph_edge_descriptor<Desc> type;
  70. static reverse_graph_edge_descriptor<Desc> convert(const Desc& d) {
  71. return reverse_graph_edge_descriptor<Desc>(d);
  72. }
  73. };
  74. template <typename Desc, typename G, typename GR>
  75. struct add_reverse_edge_descriptor<reverse_graph_edge_descriptor<Desc>, boost::reverse_graph<G, GR> > {
  76. typedef reverse_graph_edge_descriptor<Desc> type;
  77. static reverse_graph_edge_descriptor<Desc> convert(const reverse_graph_edge_descriptor<Desc>& d) {
  78. return d;
  79. }
  80. };
  81. // Default edge and vertex property copiers
  82. template <typename Graph1, typename Graph2>
  83. struct edge_copier {
  84. edge_copier(const Graph1& g1, Graph2& g2)
  85. : edge_all_map1(get(edge_all, g1)),
  86. edge_all_map2(get(edge_all, g2)) { }
  87. template <typename Edge1, typename Edge2>
  88. void operator()(const Edge1& e1, Edge2& e2) const {
  89. put(edge_all_map2, e2, get(edge_all_map1, add_reverse_edge_descriptor<Edge1, Graph1>::convert(e1)));
  90. }
  91. typename property_map<Graph1, edge_all_t>::const_type edge_all_map1;
  92. mutable typename property_map<Graph2, edge_all_t>::type edge_all_map2;
  93. };
  94. template <typename Graph1, typename Graph2>
  95. inline edge_copier<Graph1,Graph2>
  96. make_edge_copier(const Graph1& g1, Graph2& g2)
  97. {
  98. return edge_copier<Graph1,Graph2>(g1, g2);
  99. }
  100. template <typename Graph1, typename Graph2>
  101. struct vertex_copier {
  102. vertex_copier(const Graph1& g1, Graph2& g2)
  103. : vertex_all_map1(get(vertex_all, g1)),
  104. vertex_all_map2(get(vertex_all, g2)) { }
  105. template <typename Vertex1, typename Vertex2>
  106. void operator()(const Vertex1& v1, Vertex2& v2) const {
  107. put(vertex_all_map2, v2, get(vertex_all_map1, v1));
  108. }
  109. typename property_map<Graph1, vertex_all_t>::const_type vertex_all_map1;
  110. mutable typename property_map<Graph2, vertex_all_t>::type
  111. vertex_all_map2;
  112. };
  113. template <typename Graph1, typename Graph2>
  114. inline vertex_copier<Graph1,Graph2>
  115. make_vertex_copier(const Graph1& g1, Graph2& g2)
  116. {
  117. return vertex_copier<Graph1,Graph2>(g1, g2);
  118. }
  119. // Copy all the vertices and edges of graph g_in into graph g_out.
  120. // The copy_vertex and copy_edge function objects control how vertex
  121. // and edge properties are copied.
  122. template <int Version>
  123. struct copy_graph_impl { };
  124. template <> struct copy_graph_impl<0>
  125. {
  126. template <typename Graph, typename MutableGraph,
  127. typename CopyVertex, typename CopyEdge, typename IndexMap,
  128. typename Orig2CopyVertexIndexMap>
  129. static void apply(const Graph& g_in, MutableGraph& g_out,
  130. CopyVertex copy_vertex, CopyEdge copy_edge,
  131. Orig2CopyVertexIndexMap orig2copy, IndexMap)
  132. {
  133. typedef remove_reverse_edge_descriptor<Graph, typename graph_traits<Graph>::edge_descriptor> cvt;
  134. typename graph_traits<Graph>::vertex_iterator vi, vi_end;
  135. for (boost::tie(vi, vi_end) = vertices(g_in); vi != vi_end; ++vi) {
  136. typename graph_traits<MutableGraph>::vertex_descriptor
  137. new_v = add_vertex(g_out);
  138. put(orig2copy, *vi, new_v);
  139. copy_vertex(*vi, new_v);
  140. }
  141. typename graph_traits<Graph>::edge_iterator ei, ei_end;
  142. for (boost::tie(ei, ei_end) = edges(g_in); ei != ei_end; ++ei) {
  143. typename graph_traits<MutableGraph>::edge_descriptor new_e;
  144. bool inserted;
  145. boost::tie(new_e, inserted) = add_edge(get(orig2copy, source(*ei, g_in)),
  146. get(orig2copy, target(*ei, g_in)),
  147. g_out);
  148. copy_edge(cvt::convert(*ei, g_in), new_e);
  149. }
  150. }
  151. };
  152. // for directed graphs
  153. template <> struct copy_graph_impl<1>
  154. {
  155. template <typename Graph, typename MutableGraph,
  156. typename CopyVertex, typename CopyEdge, typename IndexMap,
  157. typename Orig2CopyVertexIndexMap>
  158. static void apply(const Graph& g_in, MutableGraph& g_out,
  159. CopyVertex copy_vertex, CopyEdge copy_edge,
  160. Orig2CopyVertexIndexMap orig2copy, IndexMap)
  161. {
  162. typedef remove_reverse_edge_descriptor<Graph, typename graph_traits<Graph>::edge_descriptor> cvt;
  163. typename graph_traits<Graph>::vertex_iterator vi, vi_end;
  164. for (boost::tie(vi, vi_end) = vertices(g_in); vi != vi_end; ++vi) {
  165. typename graph_traits<MutableGraph>::vertex_descriptor
  166. new_v = add_vertex(g_out);
  167. put(orig2copy, *vi, new_v);
  168. copy_vertex(*vi, new_v);
  169. }
  170. for (boost::tie(vi, vi_end) = vertices(g_in); vi != vi_end; ++vi) {
  171. typename graph_traits<Graph>::out_edge_iterator ei, ei_end;
  172. for (boost::tie(ei, ei_end) = out_edges(*vi, g_in); ei != ei_end; ++ei) {
  173. typename graph_traits<MutableGraph>::edge_descriptor new_e;
  174. bool inserted;
  175. boost::tie(new_e, inserted) = add_edge(get(orig2copy, source(*ei, g_in)),
  176. get(orig2copy, target(*ei, g_in)),
  177. g_out);
  178. copy_edge(cvt::convert(*ei, g_in), new_e);
  179. }
  180. }
  181. }
  182. };
  183. // for undirected graphs
  184. template <> struct copy_graph_impl<2>
  185. {
  186. template <typename Graph, typename MutableGraph,
  187. typename CopyVertex, typename CopyEdge, typename IndexMap,
  188. typename Orig2CopyVertexIndexMap>
  189. static void apply(const Graph& g_in, MutableGraph& g_out,
  190. CopyVertex copy_vertex, CopyEdge copy_edge,
  191. Orig2CopyVertexIndexMap orig2copy,
  192. IndexMap index_map)
  193. {
  194. typedef remove_reverse_edge_descriptor<Graph, typename graph_traits<Graph>::edge_descriptor> cvt;
  195. typedef color_traits<default_color_type> Color;
  196. std::vector<default_color_type>
  197. color(num_vertices(g_in), Color::white());
  198. typename graph_traits<Graph>::vertex_iterator vi, vi_end;
  199. for (boost::tie(vi, vi_end) = vertices(g_in); vi != vi_end; ++vi) {
  200. typename graph_traits<MutableGraph>::vertex_descriptor
  201. new_v = add_vertex(g_out);
  202. put(orig2copy, *vi, new_v);
  203. copy_vertex(*vi, new_v);
  204. }
  205. for (boost::tie(vi, vi_end) = vertices(g_in); vi != vi_end; ++vi) {
  206. typename graph_traits<Graph>::out_edge_iterator ei, ei_end;
  207. for (boost::tie(ei, ei_end) = out_edges(*vi, g_in); ei != ei_end; ++ei) {
  208. typename graph_traits<MutableGraph>::edge_descriptor new_e;
  209. bool inserted;
  210. if (color[get(index_map, target(*ei, g_in))] == Color::white()) {
  211. boost::tie(new_e, inserted) = add_edge(get(orig2copy, source(*ei,g_in)),
  212. get(orig2copy, target(*ei,g_in)),
  213. g_out);
  214. copy_edge(cvt::convert(*ei, g_in), new_e);
  215. }
  216. }
  217. color[get(index_map, *vi)] = Color::black();
  218. }
  219. }
  220. };
  221. template <class Graph>
  222. struct choose_graph_copy {
  223. typedef typename graph_traits<Graph>::traversal_category Trv;
  224. typedef typename graph_traits<Graph>::directed_category Dr;
  225. enum { algo =
  226. (is_convertible<Trv, vertex_list_graph_tag>::value
  227. && is_convertible<Trv, edge_list_graph_tag>::value)
  228. ? 0 : is_convertible<Dr, directed_tag>::value ? 1 : 2 };
  229. typedef copy_graph_impl<algo> type;
  230. };
  231. //-------------------------------------------------------------------------
  232. struct choose_copier_parameter {
  233. template <class P, class G1, class G2>
  234. struct bind_ {
  235. typedef const P& result_type;
  236. static result_type apply(const P& p, const G1&, G2&)
  237. { return p; }
  238. };
  239. };
  240. struct choose_default_edge_copier {
  241. template <class P, class G1, class G2>
  242. struct bind_ {
  243. typedef edge_copier<G1, G2> result_type;
  244. static result_type apply(const P&, const G1& g1, G2& g2) {
  245. return result_type(g1, g2);
  246. }
  247. };
  248. };
  249. template <class Param>
  250. struct choose_edge_copy {
  251. typedef choose_copier_parameter type;
  252. };
  253. template <>
  254. struct choose_edge_copy<param_not_found> {
  255. typedef choose_default_edge_copier type;
  256. };
  257. template <class Param, class G1, class G2>
  258. struct choose_edge_copier_helper {
  259. typedef typename choose_edge_copy<Param>::type Selector;
  260. typedef typename Selector:: template bind_<Param, G1, G2> Bind;
  261. typedef Bind type;
  262. typedef typename Bind::result_type result_type;
  263. };
  264. template <typename Param, typename G1, typename G2>
  265. typename detail::choose_edge_copier_helper<Param,G1,G2>::result_type
  266. choose_edge_copier(const Param& params, const G1& g_in, G2& g_out)
  267. {
  268. typedef typename
  269. detail::choose_edge_copier_helper<Param,G1,G2>::type Choice;
  270. return Choice::apply(params, g_in, g_out);
  271. }
  272. struct choose_default_vertex_copier {
  273. template <class P, class G1, class G2>
  274. struct bind_ {
  275. typedef vertex_copier<G1, G2> result_type;
  276. static result_type apply(const P&, const G1& g1, G2& g2) {
  277. return result_type(g1, g2);
  278. }
  279. };
  280. };
  281. template <class Param>
  282. struct choose_vertex_copy {
  283. typedef choose_copier_parameter type;
  284. };
  285. template <>
  286. struct choose_vertex_copy<param_not_found> {
  287. typedef choose_default_vertex_copier type;
  288. };
  289. template <class Param, class G1, class G2>
  290. struct choose_vertex_copier_helper {
  291. typedef typename choose_vertex_copy<Param>::type Selector;
  292. typedef typename Selector:: template bind_<Param, G1, G2> Bind;
  293. typedef Bind type;
  294. typedef typename Bind::result_type result_type;
  295. };
  296. template <typename Param, typename G1, typename G2>
  297. typename detail::choose_vertex_copier_helper<Param,G1,G2>::result_type
  298. choose_vertex_copier(const Param& params, const G1& g_in, G2& g_out)
  299. {
  300. typedef typename
  301. detail::choose_vertex_copier_helper<Param,G1,G2>::type Choice;
  302. return Choice::apply(params, g_in, g_out);
  303. }
  304. } // namespace detail
  305. template <typename VertexListGraph, typename MutableGraph>
  306. void copy_graph(const VertexListGraph& g_in, MutableGraph& g_out)
  307. {
  308. if (num_vertices(g_in) == 0)
  309. return;
  310. typedef typename graph_traits<MutableGraph>::vertex_descriptor vertex_t;
  311. std::vector<vertex_t> orig2copy(num_vertices(g_in));
  312. typedef typename detail::choose_graph_copy<VertexListGraph>::type
  313. copy_impl;
  314. copy_impl::apply
  315. (g_in, g_out,
  316. detail::make_vertex_copier(g_in, g_out),
  317. detail::make_edge_copier(g_in, g_out),
  318. make_iterator_property_map(orig2copy.begin(),
  319. get(vertex_index, g_in), orig2copy[0]),
  320. get(vertex_index, g_in)
  321. );
  322. }
  323. template <typename VertexListGraph, typename MutableGraph,
  324. class P, class T, class R>
  325. void copy_graph(const VertexListGraph& g_in, MutableGraph& g_out,
  326. const bgl_named_params<P, T, R>& params)
  327. {
  328. typename std::vector<T>::size_type n;
  329. n = is_default_param(get_param(params, orig_to_copy_t()))
  330. ? num_vertices(g_in) : 1;
  331. if (n == 0)
  332. return;
  333. std::vector<BOOST_DEDUCED_TYPENAME graph_traits<MutableGraph>::vertex_descriptor>
  334. orig2copy(n);
  335. typedef typename detail::choose_graph_copy<VertexListGraph>::type
  336. copy_impl;
  337. copy_impl::apply
  338. (g_in, g_out,
  339. detail::choose_vertex_copier(get_param(params, vertex_copy_t()),
  340. g_in, g_out),
  341. detail::choose_edge_copier(get_param(params, edge_copy_t()),
  342. g_in, g_out),
  343. choose_param(get_param(params, orig_to_copy_t()),
  344. make_iterator_property_map
  345. (orig2copy.begin(),
  346. choose_const_pmap(get_param(params, vertex_index),
  347. g_in, vertex_index), orig2copy[0])),
  348. choose_const_pmap(get_param(params, vertex_index), g_in, vertex_index)
  349. );
  350. }
  351. namespace detail {
  352. template <class NewGraph, class Copy2OrigIndexMap,
  353. class CopyVertex, class CopyEdge>
  354. struct graph_copy_visitor : public bfs_visitor<>
  355. {
  356. graph_copy_visitor(NewGraph& graph, Copy2OrigIndexMap c,
  357. CopyVertex cv, CopyEdge ce)
  358. : g_out(graph), orig2copy(c), copy_vertex(cv), copy_edge(ce) { }
  359. template <class Vertex>
  360. typename graph_traits<NewGraph>::vertex_descriptor copy_one_vertex(Vertex u) const {
  361. typename graph_traits<NewGraph>::vertex_descriptor
  362. new_u = add_vertex(g_out);
  363. put(orig2copy, u, new_u);
  364. copy_vertex(u, new_u);
  365. return new_u;
  366. }
  367. template <class Edge, class Graph>
  368. void tree_edge(Edge e, const Graph& g_in) const {
  369. // For a tree edge, the target vertex has not been copied yet.
  370. typename graph_traits<NewGraph>::edge_descriptor new_e;
  371. bool inserted;
  372. boost::tie(new_e, inserted) = add_edge(get(orig2copy, source(e, g_in)),
  373. this->copy_one_vertex(target(e, g_in)),
  374. g_out);
  375. copy_edge(e, new_e);
  376. }
  377. template <class Edge, class Graph>
  378. void non_tree_edge(Edge e, const Graph& g_in) const {
  379. // For a non-tree edge, the target vertex has already been copied.
  380. typename graph_traits<NewGraph>::edge_descriptor new_e;
  381. bool inserted;
  382. boost::tie(new_e, inserted) = add_edge(get(orig2copy, source(e, g_in)),
  383. get(orig2copy, target(e, g_in)),
  384. g_out);
  385. copy_edge(e, new_e);
  386. }
  387. private:
  388. NewGraph& g_out;
  389. Copy2OrigIndexMap orig2copy;
  390. CopyVertex copy_vertex;
  391. CopyEdge copy_edge;
  392. };
  393. template <typename Graph, typename MutableGraph,
  394. typename CopyVertex, typename CopyEdge,
  395. typename Orig2CopyVertexIndexMap, typename Params>
  396. typename graph_traits<MutableGraph>::vertex_descriptor
  397. copy_component_impl
  398. (const Graph& g_in,
  399. typename graph_traits<Graph>::vertex_descriptor src,
  400. MutableGraph& g_out,
  401. CopyVertex copy_vertex, CopyEdge copy_edge,
  402. Orig2CopyVertexIndexMap orig2copy,
  403. const Params& params)
  404. {
  405. graph_copy_visitor<MutableGraph, Orig2CopyVertexIndexMap,
  406. CopyVertex, CopyEdge> vis(g_out, orig2copy, copy_vertex, copy_edge);
  407. typename graph_traits<MutableGraph>::vertex_descriptor src_copy
  408. = vis.copy_one_vertex(src);
  409. breadth_first_search(g_in, src, params.visitor(vis));
  410. return src_copy;
  411. }
  412. } // namespace detail
  413. // Copy all the vertices and edges of graph g_in that are reachable
  414. // from the source vertex into graph g_out. Return the vertex
  415. // in g_out that matches the source vertex of g_in.
  416. template <typename IncidenceGraph, typename MutableGraph,
  417. typename P, typename T, typename R>
  418. typename graph_traits<MutableGraph>::vertex_descriptor
  419. copy_component(IncidenceGraph& g_in,
  420. typename graph_traits<IncidenceGraph>::vertex_descriptor src,
  421. MutableGraph& g_out,
  422. const bgl_named_params<P, T, R>& params)
  423. {
  424. typename std::vector<T>::size_type n;
  425. n = is_default_param(get_param(params, orig_to_copy_t()))
  426. ? num_vertices(g_in) : 1;
  427. std::vector<typename graph_traits<IncidenceGraph>::vertex_descriptor>
  428. orig2copy(n);
  429. return detail::copy_component_impl
  430. (g_in, src, g_out,
  431. detail::choose_vertex_copier(get_param(params, vertex_copy_t()),
  432. g_in, g_out),
  433. detail::choose_edge_copier(get_param(params, edge_copy_t()),
  434. g_in, g_out),
  435. choose_param(get_param(params, orig_to_copy_t()),
  436. make_iterator_property_map
  437. (orig2copy.begin(),
  438. choose_pmap(get_param(params, vertex_index),
  439. g_in, vertex_index), orig2copy[0])),
  440. params
  441. );
  442. }
  443. template <typename IncidenceGraph, typename MutableGraph>
  444. typename graph_traits<MutableGraph>::vertex_descriptor
  445. copy_component(IncidenceGraph& g_in,
  446. typename graph_traits<IncidenceGraph>::vertex_descriptor src,
  447. MutableGraph& g_out)
  448. {
  449. std::vector<typename graph_traits<IncidenceGraph>::vertex_descriptor>
  450. orig2copy(num_vertices(g_in));
  451. return detail::copy_component_impl
  452. (g_in, src, g_out,
  453. make_vertex_copier(g_in, g_out),
  454. make_edge_copier(g_in, g_out),
  455. make_iterator_property_map(orig2copy.begin(),
  456. get(vertex_index, g_in), orig2copy[0]),
  457. bgl_named_params<char,char>('x') // dummy param object
  458. );
  459. }
  460. } // namespace boost
  461. #endif // BOOST_GRAPH_COPY_HPP