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