Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/graph/named_graph.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children | c530137014c0 |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
1 // Copyright (C) 2007 Douglas Gregor | |
2 | |
3 // Use, modification and distribution is subject to the Boost Software | |
4 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | |
5 // http://www.boost.org/LICENSE_1_0.txt) | |
6 | |
7 // Provides support for named vertices in graphs, allowing one to more | |
8 // easily associate unique external names (URLs, city names, employee | |
9 // ID numbers, etc.) with the vertices of a graph. | |
10 #ifndef BOOST_GRAPH_NAMED_GRAPH_HPP | |
11 #define BOOST_GRAPH_NAMED_GRAPH_HPP | |
12 | |
13 #include <boost/config.hpp> | |
14 #include <boost/static_assert.hpp> | |
15 #include <boost/functional/hash.hpp> | |
16 #include <boost/graph/graph_traits.hpp> | |
17 #include <boost/graph/properties.hpp> | |
18 #include <boost/multi_index/hashed_index.hpp> | |
19 #include <boost/multi_index/member.hpp> | |
20 #include <boost/multi_index_container.hpp> | |
21 #include <boost/optional.hpp> | |
22 #include <boost/pending/property.hpp> // for boost::lookup_one_property | |
23 #include <boost/pending/container_traits.hpp> | |
24 #include <boost/throw_exception.hpp> | |
25 #include <boost/tuple/tuple.hpp> // for boost::make_tuple | |
26 #include <boost/type_traits/is_same.hpp> | |
27 #include <boost/type_traits/is_base_of.hpp> | |
28 #include <boost/type_traits/remove_cv.hpp> | |
29 #include <boost/type_traits/remove_reference.hpp> | |
30 #include <boost/utility/enable_if.hpp> | |
31 #include <functional> // for std::equal_to | |
32 #include <stdexcept> // for std::runtime_error | |
33 #include <utility> // for std::pair | |
34 | |
35 namespace boost { namespace graph { | |
36 | |
37 /******************************************************************* | |
38 * User-customized traits * | |
39 *******************************************************************/ | |
40 | |
41 /** | |
42 * @brief Trait used to extract the internal vertex name from a vertex | |
43 * property. | |
44 * | |
45 * To enable the use of internal vertex names in a graph type, | |
46 * specialize the @c internal_vertex_name trait for your graph | |
47 * property (e.g., @c a City class, which stores information about the | |
48 * vertices in a road map). | |
49 */ | |
50 template<typename VertexProperty> | |
51 struct internal_vertex_name | |
52 { | |
53 /** | |
54 * The @c type field provides a function object that extracts a key | |
55 * from the @c VertexProperty. The function object type must have a | |
56 * nested @c result_type that provides the type of the key. For | |
57 * more information, see the @c KeyExtractor concept in the | |
58 * Boost.MultiIndex documentation: @c type must either be @c void | |
59 * (if @c VertexProperty does not have an internal vertex name) or | |
60 * a model of @c KeyExtractor. | |
61 */ | |
62 typedef void type; | |
63 }; | |
64 | |
65 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | |
66 /** | |
67 * Extract the internal vertex name from a @c property structure by | |
68 * looking at its base. | |
69 */ | |
70 template<typename Tag, typename T, typename Base> | |
71 struct internal_vertex_name<property<Tag, T, Base> > | |
72 : internal_vertex_name<Base> { }; | |
73 #endif | |
74 | |
75 /** | |
76 * Construct an instance of @c VertexProperty directly from its | |
77 * name. This function object should be used within the @c | |
78 * internal_vertex_constructor trait. | |
79 */ | |
80 template<typename VertexProperty> | |
81 struct vertex_from_name | |
82 { | |
83 private: | |
84 typedef typename internal_vertex_name<VertexProperty>::type extract_name_type; | |
85 | |
86 typedef typename remove_cv< | |
87 typename remove_reference< | |
88 typename extract_name_type::result_type>::type>::type | |
89 vertex_name_type; | |
90 | |
91 public: | |
92 typedef vertex_name_type argument_type; | |
93 typedef VertexProperty result_type; | |
94 | |
95 VertexProperty operator()(const vertex_name_type& name) | |
96 { | |
97 return VertexProperty(name); | |
98 } | |
99 }; | |
100 | |
101 /** | |
102 * Throw an exception whenever one tries to construct a @c | |
103 * VertexProperty instance from its name. | |
104 */ | |
105 template<typename VertexProperty> | |
106 struct cannot_add_vertex | |
107 { | |
108 private: | |
109 typedef typename internal_vertex_name<VertexProperty>::type extract_name_type; | |
110 | |
111 typedef typename remove_cv< | |
112 typename remove_reference< | |
113 typename extract_name_type::result_type>::type>::type | |
114 vertex_name_type; | |
115 | |
116 public: | |
117 typedef vertex_name_type argument_type; | |
118 typedef VertexProperty result_type; | |
119 | |
120 VertexProperty operator()(const vertex_name_type&) | |
121 { | |
122 boost::throw_exception(std::runtime_error("add_vertex: " | |
123 "unable to create a vertex from its name")); | |
124 } | |
125 }; | |
126 | |
127 /** | |
128 * @brief Trait used to construct an instance of a @c VertexProperty, | |
129 * which is a class type that stores the properties associated with a | |
130 * vertex in a graph, from just the name of that vertex property. This | |
131 * operation is used when an operation is required to map from a | |
132 * vertex name to a vertex descriptor (e.g., to add an edge outgoing | |
133 * from that vertex), but no vertex by the name exists. The function | |
134 * object provided by this trait will be used to add new vertices | |
135 * based only on their names. Since this cannot be done for arbitrary | |
136 * types, the default behavior is to throw an exception when this | |
137 * routine is called, which requires that all named vertices be added | |
138 * before adding any edges by name. | |
139 */ | |
140 template<typename VertexProperty> | |
141 struct internal_vertex_constructor | |
142 { | |
143 /** | |
144 * The @c type field provides a function object that constructs a | |
145 * new instance of @c VertexProperty from the name of the vertex (as | |
146 * determined by @c internal_vertex_name). The function object shall | |
147 * accept a vertex name and return a @c VertexProperty. Predefined | |
148 * options include: | |
149 * | |
150 * @c vertex_from_name<VertexProperty>: construct an instance of | |
151 * @c VertexProperty directly from the name. | |
152 * | |
153 * @c cannot_add_vertex<VertexProperty>: the default value, which | |
154 * throws an @c std::runtime_error if one attempts to add a vertex | |
155 * given just the name. | |
156 */ | |
157 typedef cannot_add_vertex<VertexProperty> type; | |
158 }; | |
159 | |
160 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | |
161 /** | |
162 * Extract the internal vertex constructor from a @c property structure by | |
163 * looking at its base. | |
164 */ | |
165 template<typename Tag, typename T, typename Base> | |
166 struct internal_vertex_constructor<property<Tag, T, Base> > | |
167 : internal_vertex_constructor<Base> { }; | |
168 #endif | |
169 | |
170 /******************************************************************* | |
171 * Named graph mixin * | |
172 *******************************************************************/ | |
173 | |
174 /** | |
175 * named_graph is a mixin that provides names for the vertices of a | |
176 * graph, including a mapping from names to vertices. Graph types that | |
177 * may or may not be have vertex names (depending on the properties | |
178 * supplied by the user) should use maybe_named_graph. | |
179 * | |
180 * Template parameters: | |
181 * | |
182 * Graph: the graph type that derives from named_graph | |
183 * | |
184 * Vertex: the type of a vertex descriptor in Graph. Note: we cannot | |
185 * use graph_traits here, because the Graph is not yet defined. | |
186 * | |
187 * VertexProperty: the type stored with each vertex in the Graph. | |
188 */ | |
189 template<typename Graph, typename Vertex, typename VertexProperty> | |
190 class named_graph | |
191 { | |
192 public: | |
193 /// The type of the function object that extracts names from vertex | |
194 /// properties. | |
195 typedef typename internal_vertex_name<VertexProperty>::type extract_name_type; | |
196 /// The type of the "bundled" property, from which the name can be | |
197 /// extracted. | |
198 typedef typename lookup_one_property<VertexProperty, vertex_bundle_t>::type | |
199 bundled_vertex_property_type; | |
200 | |
201 /// The type of the function object that generates vertex properties | |
202 /// from names, for the implicit addition of vertices. | |
203 typedef typename internal_vertex_constructor<VertexProperty>::type | |
204 vertex_constructor_type; | |
205 | |
206 /// The type used to name vertices in the graph | |
207 typedef typename remove_cv< | |
208 typename remove_reference< | |
209 typename extract_name_type::result_type>::type>::type | |
210 vertex_name_type; | |
211 | |
212 /// The type of vertex descriptors in the graph | |
213 typedef Vertex vertex_descriptor; | |
214 | |
215 private: | |
216 /// Key extractor for use with the multi_index_container | |
217 struct extract_name_from_vertex | |
218 { | |
219 typedef vertex_name_type result_type; | |
220 | |
221 extract_name_from_vertex(Graph& graph, const extract_name_type& extract) | |
222 : graph(graph), extract(extract) { } | |
223 | |
224 const result_type& operator()(Vertex vertex) const | |
225 { | |
226 return extract(graph[vertex]); | |
227 } | |
228 | |
229 Graph& graph; | |
230 extract_name_type extract; | |
231 }; | |
232 | |
233 public: | |
234 /// The type that maps names to vertices | |
235 typedef multi_index::multi_index_container< | |
236 Vertex, | |
237 multi_index::indexed_by< | |
238 multi_index::hashed_unique<multi_index::tag<vertex_name_t>, | |
239 extract_name_from_vertex> > | |
240 > named_vertices_type; | |
241 | |
242 /// The set of vertices, indexed by name | |
243 typedef typename named_vertices_type::template index<vertex_name_t>::type | |
244 vertices_by_name_type; | |
245 | |
246 /// Construct an instance of the named graph mixin, using the given | |
247 /// function object to extract a name from the bundled property | |
248 /// associated with a vertex. | |
249 named_graph(const extract_name_type& extract = extract_name_type(), | |
250 const vertex_constructor_type& vertex_constructor | |
251 = vertex_constructor_type()); | |
252 | |
253 /// Notify the named_graph that we have added the given vertex. The | |
254 /// name of the vertex will be added to the mapping. | |
255 void added_vertex(Vertex vertex); | |
256 | |
257 /// Notify the named_graph that we are removing the given | |
258 /// vertex. The name of the vertex will be removed from the mapping. | |
259 template <typename VertexIterStability> | |
260 void removing_vertex(Vertex vertex, VertexIterStability); | |
261 | |
262 /// Notify the named_graph that we are clearing the graph. | |
263 /// This will clear out all of the name->vertex mappings | |
264 void clearing_graph(); | |
265 | |
266 /// Retrieve the derived instance | |
267 Graph& derived() { return static_cast<Graph&>(*this); } | |
268 const Graph& derived() const { return static_cast<const Graph&>(*this); } | |
269 | |
270 /// Extract the name from a vertex property instance | |
271 typename extract_name_type::result_type | |
272 extract_name(const bundled_vertex_property_type& property); | |
273 | |
274 /// Search for a vertex that has the given property (based on its | |
275 /// name) | |
276 optional<vertex_descriptor> | |
277 vertex_by_property(const bundled_vertex_property_type& property); | |
278 | |
279 /// Mapping from names to vertices | |
280 named_vertices_type named_vertices; | |
281 | |
282 /// Constructs a vertex from the name of that vertex | |
283 vertex_constructor_type vertex_constructor; | |
284 }; | |
285 | |
286 /// Helper macro containing the template parameters of named_graph | |
287 #define BGL_NAMED_GRAPH_PARAMS \ | |
288 typename Graph, typename Vertex, typename VertexProperty | |
289 /// Helper macro containing the named_graph<...> instantiation | |
290 #define BGL_NAMED_GRAPH \ | |
291 named_graph<Graph, Vertex, VertexProperty> | |
292 | |
293 template<BGL_NAMED_GRAPH_PARAMS> | |
294 BGL_NAMED_GRAPH::named_graph(const extract_name_type& extract, | |
295 const vertex_constructor_type& vertex_constructor) | |
296 : named_vertices( | |
297 typename named_vertices_type::ctor_args_list( | |
298 boost::make_tuple( | |
299 boost::make_tuple( | |
300 0, // initial number of buckets | |
301 extract_name_from_vertex(derived(), extract), | |
302 boost::hash<vertex_name_type>(), | |
303 std::equal_to<vertex_name_type>())))), | |
304 vertex_constructor(vertex_constructor) | |
305 { | |
306 } | |
307 | |
308 template<BGL_NAMED_GRAPH_PARAMS> | |
309 inline void BGL_NAMED_GRAPH::added_vertex(Vertex vertex) | |
310 { | |
311 named_vertices.insert(vertex); | |
312 } | |
313 | |
314 template<BGL_NAMED_GRAPH_PARAMS> | |
315 template<typename VertexIterStability> | |
316 inline void BGL_NAMED_GRAPH::removing_vertex(Vertex vertex, VertexIterStability) | |
317 { | |
318 BOOST_STATIC_ASSERT_MSG ((boost::is_base_of<boost::graph_detail::stable_tag, VertexIterStability>::value), "Named graphs cannot use vecS as vertex container and remove vertices; the lack of vertex descriptor stability (which iterator stability is a proxy for) means that the name -> vertex mapping would need to be completely rebuilt after each deletion. See https://svn.boost.org/trac/boost/ticket/7863 for more information and a test case."); | |
319 typedef typename BGL_NAMED_GRAPH::vertex_name_type vertex_name_type; | |
320 const vertex_name_type& vertex_name = extract_name(derived()[vertex]); | |
321 named_vertices.erase(vertex_name); | |
322 } | |
323 | |
324 template<BGL_NAMED_GRAPH_PARAMS> | |
325 inline void BGL_NAMED_GRAPH::clearing_graph() | |
326 { | |
327 named_vertices.clear(); | |
328 } | |
329 | |
330 template<BGL_NAMED_GRAPH_PARAMS> | |
331 typename BGL_NAMED_GRAPH::extract_name_type::result_type | |
332 BGL_NAMED_GRAPH::extract_name(const bundled_vertex_property_type& property) | |
333 { | |
334 return named_vertices.key_extractor().extract(property); | |
335 } | |
336 | |
337 template<BGL_NAMED_GRAPH_PARAMS> | |
338 optional<typename BGL_NAMED_GRAPH::vertex_descriptor> | |
339 BGL_NAMED_GRAPH:: | |
340 vertex_by_property(const bundled_vertex_property_type& property) | |
341 { | |
342 return find_vertex(extract_name(property), *this); | |
343 } | |
344 | |
345 /// Retrieve the vertex associated with the given name | |
346 template<BGL_NAMED_GRAPH_PARAMS> | |
347 optional<Vertex> | |
348 find_vertex(typename BGL_NAMED_GRAPH::vertex_name_type const& name, | |
349 const BGL_NAMED_GRAPH& g) | |
350 { | |
351 typedef typename BGL_NAMED_GRAPH::vertices_by_name_type | |
352 vertices_by_name_type; | |
353 | |
354 // Retrieve the set of vertices indexed by name | |
355 vertices_by_name_type const& vertices_by_name | |
356 = g.named_vertices.template get<vertex_name_t>(); | |
357 | |
358 /// Look for a vertex with the given name | |
359 typename vertices_by_name_type::const_iterator iter | |
360 = vertices_by_name.find(name); | |
361 | |
362 if (iter == vertices_by_name.end()) | |
363 return optional<Vertex>(); // vertex not found | |
364 else | |
365 return *iter; | |
366 } | |
367 | |
368 /// Retrieve the vertex associated with the given name, or add a new | |
369 /// vertex with that name if no such vertex is available. | |
370 /// Note: This is enabled only when the vertex property type is different | |
371 /// from the vertex name to avoid ambiguous overload problems with | |
372 /// the add_vertex() function that takes a vertex property. | |
373 template<BGL_NAMED_GRAPH_PARAMS> | |
374 typename disable_if<is_same< | |
375 typename BGL_NAMED_GRAPH::vertex_name_type, | |
376 VertexProperty | |
377 >, | |
378 Vertex>::type | |
379 add_vertex(typename BGL_NAMED_GRAPH::vertex_name_type const& name, | |
380 BGL_NAMED_GRAPH& g) | |
381 { | |
382 if (optional<Vertex> vertex = find_vertex(name, g)) | |
383 /// We found the vertex, so return it | |
384 return *vertex; | |
385 else | |
386 /// There is no vertex with the given name, so create one | |
387 return add_vertex(g.vertex_constructor(name), g.derived()); | |
388 } | |
389 | |
390 /// Add an edge using vertex names to refer to the vertices | |
391 template<BGL_NAMED_GRAPH_PARAMS> | |
392 std::pair<typename graph_traits<Graph>::edge_descriptor, bool> | |
393 add_edge(typename BGL_NAMED_GRAPH::vertex_name_type const& u_name, | |
394 typename BGL_NAMED_GRAPH::vertex_name_type const& v_name, | |
395 BGL_NAMED_GRAPH& g) | |
396 { | |
397 return add_edge(add_vertex(u_name, g.derived()), | |
398 add_vertex(v_name, g.derived()), | |
399 g.derived()); | |
400 } | |
401 | |
402 /// Add an edge using vertex descriptors or names to refer to the vertices | |
403 template<BGL_NAMED_GRAPH_PARAMS> | |
404 std::pair<typename graph_traits<Graph>::edge_descriptor, bool> | |
405 add_edge(typename BGL_NAMED_GRAPH::vertex_descriptor const& u, | |
406 typename BGL_NAMED_GRAPH::vertex_name_type const& v_name, | |
407 BGL_NAMED_GRAPH& g) | |
408 { | |
409 return add_edge(u, | |
410 add_vertex(v_name, g.derived()), | |
411 g.derived()); | |
412 } | |
413 | |
414 /// Add an edge using vertex descriptors or names to refer to the vertices | |
415 template<BGL_NAMED_GRAPH_PARAMS> | |
416 std::pair<typename graph_traits<Graph>::edge_descriptor, bool> | |
417 add_edge(typename BGL_NAMED_GRAPH::vertex_name_type const& u_name, | |
418 typename BGL_NAMED_GRAPH::vertex_descriptor const& v, | |
419 BGL_NAMED_GRAPH& g) | |
420 { | |
421 return add_edge(add_vertex(u_name, g.derived()), | |
422 v, | |
423 g.derived()); | |
424 } | |
425 | |
426 // Overloads to support EdgeMutablePropertyGraph graphs | |
427 template <BGL_NAMED_GRAPH_PARAMS> | |
428 std::pair<typename graph_traits<Graph>::edge_descriptor, bool> | |
429 add_edge(typename BGL_NAMED_GRAPH::vertex_descriptor const& u, | |
430 typename BGL_NAMED_GRAPH::vertex_name_type const& v_name, | |
431 typename edge_property_type<Graph>::type const& p, | |
432 BGL_NAMED_GRAPH& g) { | |
433 return add_edge(u, add_vertex(v_name, g.derived()), p, g.derived()); | |
434 } | |
435 | |
436 template <BGL_NAMED_GRAPH_PARAMS> | |
437 std::pair<typename graph_traits<Graph>::edge_descriptor, bool> | |
438 add_edge(typename BGL_NAMED_GRAPH::vertex_name_type const& u_name, | |
439 typename BGL_NAMED_GRAPH::vertex_descriptor const& v, | |
440 typename edge_property_type<Graph>::type const& p, | |
441 BGL_NAMED_GRAPH& g) { | |
442 return add_edge(add_vertex(u_name, g.derived()), v, p, g.derived()); | |
443 } | |
444 | |
445 template <BGL_NAMED_GRAPH_PARAMS> | |
446 std::pair<typename graph_traits<Graph>::edge_descriptor, bool> | |
447 add_edge(typename BGL_NAMED_GRAPH::vertex_name_type const& u_name, | |
448 typename BGL_NAMED_GRAPH::vertex_name_type const& v_name, | |
449 typename edge_property_type<Graph>::type const& p, | |
450 BGL_NAMED_GRAPH& g) { | |
451 return add_edge(add_vertex(u_name, g.derived()), | |
452 add_vertex(v_name, g.derived()), p, g.derived()); | |
453 } | |
454 | |
455 #undef BGL_NAMED_GRAPH | |
456 #undef BGL_NAMED_GRAPH_PARAMS | |
457 | |
458 /******************************************************************* | |
459 * Maybe named graph mixin * | |
460 *******************************************************************/ | |
461 | |
462 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | |
463 /** | |
464 * A graph mixin that can provide a mapping from names to vertices, | |
465 * and use that mapping to simplify creation and manipulation of | |
466 * graphs. | |
467 */ | |
468 template<typename Graph, typename Vertex, typename VertexProperty, | |
469 typename ExtractName | |
470 = typename internal_vertex_name<VertexProperty>::type> | |
471 struct maybe_named_graph : public named_graph<Graph, Vertex, VertexProperty> | |
472 { | |
473 }; | |
474 | |
475 /** | |
476 * A graph mixin that can provide a mapping from names to vertices, | |
477 * and use that mapping to simplify creation and manipulation of | |
478 * graphs. This partial specialization turns off this functionality | |
479 * when the @c VertexProperty does not have an internal vertex name. | |
480 */ | |
481 template<typename Graph, typename Vertex, typename VertexProperty> | |
482 struct maybe_named_graph<Graph, Vertex, VertexProperty, void> | |
483 { | |
484 /// The type of the "bundled" property, from which the name can be | |
485 /// extracted. | |
486 typedef typename lookup_one_property<VertexProperty, vertex_bundle_t>::type | |
487 bundled_vertex_property_type; | |
488 | |
489 /// Notify the named_graph that we have added the given vertex. This | |
490 /// is a no-op. | |
491 void added_vertex(Vertex) { } | |
492 | |
493 /// Notify the named_graph that we are removing the given | |
494 /// vertex. This is a no-op. | |
495 template <typename VertexIterStability> | |
496 void removing_vertex(Vertex, VertexIterStability) { } | |
497 | |
498 /// Notify the named_graph that we are clearing the graph. This is a | |
499 /// no-op. | |
500 void clearing_graph() { } | |
501 | |
502 /// Search for a vertex that has the given property (based on its | |
503 /// name). This always returns an empty optional<> | |
504 optional<Vertex> | |
505 vertex_by_property(const bundled_vertex_property_type&) | |
506 { | |
507 return optional<Vertex>(); | |
508 } | |
509 }; | |
510 #else | |
511 template<typename Graph, typename Vertex, typename VertexProperty, | |
512 typename ExtractName | |
513 = typename internal_vertex_name<VertexProperty>::type> | |
514 struct maybe_named_graph | |
515 { | |
516 /// The type of the "bundled" property, from which the name can be | |
517 /// extracted. | |
518 typedef typename detail::extract_bundled_vertex<VertexProperty>::type | |
519 bundled_vertex_property_type; | |
520 | |
521 /// Notify the named_graph that we have added the given vertex. This | |
522 /// is a no-op. | |
523 void added_vertex(Vertex) { } | |
524 | |
525 /// Notify the named_graph that we are removing the given | |
526 /// vertex. This is a no-op. | |
527 template <typename VertexIterStability> | |
528 void removing_vertex(Vertex, VertexIterStability) { } | |
529 | |
530 /// Notify the named_graph that we are clearing the graph. This is a | |
531 /// no-op. | |
532 void clearing_graph() { } | |
533 | |
534 /// Search for a vertex that has the given property (based on its | |
535 /// name). This always returns an empty optional<> | |
536 template<typename Property> | |
537 optional<Vertex> | |
538 vertex_by_property(const bundled_vertex_property_type&) | |
539 { | |
540 return optional<Vertex>(); | |
541 } | |
542 }; | |
543 #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | |
544 | |
545 } } // end namespace boost::graph | |
546 | |
547 #endif // BOOST_GRAPH_NAMED_GRAPH_HPP |