1 //
2 //=======================================================================
3 // Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
4 // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
5 //
6 // Copyright 2009, Andrew Sutton
7 //
8 // Distributed under the Boost Software License, Version 1.0. (See
9 // accompanying file LICENSE_1_0.txt or copy at
10 // http://www.boost.org/LICENSE_1_0.txt)
11 //=======================================================================
12 //
13 #ifndef BOOST_GRAPH_CONCEPTS_HPP
14 #define BOOST_GRAPH_CONCEPTS_HPP
15 
16 #include <boost/config.hpp>
17 #include <boost/property_map/property_map.hpp>
18 #include <boost/graph/graph_traits.hpp>
19 #include <boost/graph/properties.hpp>
20 #include <boost/graph/numeric_values.hpp>
21 #include <boost/graph/buffer_concepts.hpp>
22 #include <boost/concept_check.hpp>
23 #include <boost/type_traits/is_same.hpp>
24 #include <boost/mpl/not.hpp>
25 #include <boost/static_assert.hpp>
26 #include <boost/detail/workaround.hpp>
27 #include <boost/concept/assert.hpp>
28 
29 #include <boost/concept/detail/concept_def.hpp>
30 namespace boost
31 {
32 // dwa 2003/7/11 -- This clearly shouldn't be necessary, but if
33 // you want to use vector_as_graph, it is!  I'm sure the graph
34 // library leaves these out all over the place.  Probably a
35 // redesign involving specializing a template with a static
36 // member function is in order :(
37 //
38 // It is needed in order to allow us to write using boost::vertices as
39 // needed for ADL when using vector_as_graph below.
40 #if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) \
41     && !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564))
42 #define BOOST_VECTOR_AS_GRAPH_GRAPH_ADL_HACK
43 #endif
44 
45 #ifdef BOOST_VECTOR_AS_GRAPH_GRAPH_ADL_HACK
46 template < class T >
47 typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
48 #endif
49 
50 namespace concepts
51 {
BOOST_CONCEPT_USAGE(MultiPassInputIterator)52     BOOST_concept(MultiPassInputIterator, (T)) { BOOST_CONCEPT_USAGE(
53         MultiPassInputIterator) { BOOST_CONCEPT_ASSERT((InputIterator< T >));
54 }
55 };
56 
57 BOOST_concept(Graph, (G))
58 {
59     typedef typename graph_traits< G >::vertex_descriptor vertex_descriptor;
60     typedef typename graph_traits< G >::edge_descriptor edge_descriptor;
61     typedef typename graph_traits< G >::directed_category directed_category;
62     typedef typename graph_traits< G >::edge_parallel_category
63         edge_parallel_category;
64     typedef typename graph_traits< G >::traversal_category traversal_category;
65 
BOOST_CONCEPT_USAGE(Graph)66     BOOST_CONCEPT_USAGE(Graph)
67     {
68         BOOST_CONCEPT_ASSERT((DefaultConstructible< vertex_descriptor >));
69         BOOST_CONCEPT_ASSERT((EqualityComparable< vertex_descriptor >));
70         BOOST_CONCEPT_ASSERT((Assignable< vertex_descriptor >));
71     }
72     G g;
73 };
74 
75 BOOST_concept(IncidenceGraph, (G)) : Graph< G >
76 {
77     typedef typename graph_traits< G >::edge_descriptor edge_descriptor;
78     typedef typename graph_traits< G >::out_edge_iterator out_edge_iterator;
79     typedef typename graph_traits< G >::degree_size_type degree_size_type;
80     typedef typename graph_traits< G >::traversal_category traversal_category;
81 
82     BOOST_STATIC_ASSERT(
83         (boost::mpl::not_< boost::is_same< out_edge_iterator, void > >::value));
84     BOOST_STATIC_ASSERT(
85         (boost::mpl::not_< boost::is_same< degree_size_type, void > >::value));
86 
BOOST_CONCEPT_USAGE(IncidenceGraph)87     BOOST_CONCEPT_USAGE(IncidenceGraph)
88     {
89         BOOST_CONCEPT_ASSERT((MultiPassInputIterator< out_edge_iterator >));
90         BOOST_CONCEPT_ASSERT((DefaultConstructible< edge_descriptor >));
91         BOOST_CONCEPT_ASSERT((EqualityComparable< edge_descriptor >));
92         BOOST_CONCEPT_ASSERT((Assignable< edge_descriptor >));
93         BOOST_CONCEPT_ASSERT(
94             (Convertible< traversal_category, incidence_graph_tag >));
95 
96         p = out_edges(u, g);
97         n = out_degree(u, g);
98         e = *p.first;
99         u = source(e, g);
100         v = target(e, g);
101         const_constraints(g);
102     }
const_constraints(const G & cg)103     void const_constraints(const G& cg)
104     {
105         p = out_edges(u, cg);
106         n = out_degree(u, cg);
107         e = *p.first;
108         u = source(e, cg);
109         v = target(e, cg);
110     }
111     std::pair< out_edge_iterator, out_edge_iterator > p;
112     typename graph_traits< G >::vertex_descriptor u, v;
113     typename graph_traits< G >::edge_descriptor e;
114     typename graph_traits< G >::degree_size_type n;
115     G g;
116 };
117 
118 BOOST_concept(BidirectionalGraph, (G)) : IncidenceGraph< G >
119 {
120     typedef typename graph_traits< G >::in_edge_iterator in_edge_iterator;
121     typedef typename graph_traits< G >::traversal_category traversal_category;
122 
BOOST_CONCEPT_USAGE(BidirectionalGraph)123     BOOST_CONCEPT_USAGE(BidirectionalGraph)
124     {
125         BOOST_CONCEPT_ASSERT((MultiPassInputIterator< in_edge_iterator >));
126         BOOST_CONCEPT_ASSERT(
127             (Convertible< traversal_category, bidirectional_graph_tag >));
128 
129         BOOST_STATIC_ASSERT((boost::mpl::not_<
130             boost::is_same< in_edge_iterator, void > >::value));
131 
132         p = in_edges(v, g);
133         n = in_degree(v, g);
134         n = degree(v, g);
135         e = *p.first;
136         const_constraints(g);
137     }
const_constraints(const G & cg)138     void const_constraints(const G& cg)
139     {
140         p = in_edges(v, cg);
141         n = in_degree(v, cg);
142         n = degree(v, cg);
143         e = *p.first;
144     }
145     std::pair< in_edge_iterator, in_edge_iterator > p;
146     typename graph_traits< G >::vertex_descriptor v;
147     typename graph_traits< G >::edge_descriptor e;
148     typename graph_traits< G >::degree_size_type n;
149     G g;
150 };
151 
152 BOOST_concept(AdjacencyGraph, (G)) : Graph< G >
153 {
154     typedef typename graph_traits< G >::adjacency_iterator adjacency_iterator;
155     typedef typename graph_traits< G >::traversal_category traversal_category;
156 
BOOST_CONCEPT_USAGE(AdjacencyGraph)157     BOOST_CONCEPT_USAGE(AdjacencyGraph)
158     {
159         BOOST_CONCEPT_ASSERT((MultiPassInputIterator< adjacency_iterator >));
160         BOOST_CONCEPT_ASSERT(
161             (Convertible< traversal_category, adjacency_graph_tag >));
162 
163         BOOST_STATIC_ASSERT((boost::mpl::not_<
164             boost::is_same< adjacency_iterator, void > >::value));
165 
166         p = adjacent_vertices(v, g);
167         v = *p.first;
168         const_constraints(g);
169     }
const_constraints(const G & cg)170     void const_constraints(const G& cg) { p = adjacent_vertices(v, cg); }
171     std::pair< adjacency_iterator, adjacency_iterator > p;
172     typename graph_traits< G >::vertex_descriptor v;
173     G g;
174 };
175 
176 BOOST_concept(VertexListGraph, (G)) : Graph< G >
177 {
178     typedef typename graph_traits< G >::vertex_iterator vertex_iterator;
179     typedef typename graph_traits< G >::vertices_size_type vertices_size_type;
180     typedef typename graph_traits< G >::traversal_category traversal_category;
181 
BOOST_CONCEPT_USAGE(VertexListGraph)182     BOOST_CONCEPT_USAGE(VertexListGraph)
183     {
184         BOOST_CONCEPT_ASSERT((MultiPassInputIterator< vertex_iterator >));
185         BOOST_CONCEPT_ASSERT(
186             (Convertible< traversal_category, vertex_list_graph_tag >));
187 
188         BOOST_STATIC_ASSERT((boost::mpl::not_<
189             boost::is_same< vertex_iterator, void > >::value));
190         BOOST_STATIC_ASSERT((boost::mpl::not_<
191             boost::is_same< vertices_size_type, void > >::value));
192 
193 #ifdef BOOST_VECTOR_AS_GRAPH_GRAPH_ADL_HACK
194         // dwa 2003/7/11 -- This clearly shouldn't be necessary, but if
195         // you want to use vector_as_graph, it is!  I'm sure the graph
196         // library leaves these out all over the place.  Probably a
197         // redesign involving specializing a template with a static
198         // member function is in order :(
199         using boost::vertices;
200 #endif
201         p = vertices(g);
202         v = *p.first;
203         const_constraints(g);
204     }
const_constraints(const G & cg)205     void const_constraints(const G& cg)
206     {
207 #ifdef BOOST_VECTOR_AS_GRAPH_GRAPH_ADL_HACK
208         // dwa 2003/7/11 -- This clearly shouldn't be necessary, but if
209         // you want to use vector_as_graph, it is!  I'm sure the graph
210         // library leaves these out all over the place.  Probably a
211         // redesign involving specializing a template with a static
212         // member function is in order :(
213         using boost::vertices;
214 #endif
215 
216         p = vertices(cg);
217         v = *p.first;
218         V = num_vertices(cg);
219     }
220     std::pair< vertex_iterator, vertex_iterator > p;
221     typename graph_traits< G >::vertex_descriptor v;
222     G g;
223     vertices_size_type V;
224 };
225 
226 BOOST_concept(EdgeListGraph, (G)) : Graph< G >
227 {
228     typedef typename graph_traits< G >::edge_descriptor edge_descriptor;
229     typedef typename graph_traits< G >::edge_iterator edge_iterator;
230     typedef typename graph_traits< G >::edges_size_type edges_size_type;
231     typedef typename graph_traits< G >::traversal_category traversal_category;
232 
BOOST_CONCEPT_USAGE(EdgeListGraph)233     BOOST_CONCEPT_USAGE(EdgeListGraph)
234     {
235         BOOST_CONCEPT_ASSERT((MultiPassInputIterator< edge_iterator >));
236         BOOST_CONCEPT_ASSERT((DefaultConstructible< edge_descriptor >));
237         BOOST_CONCEPT_ASSERT((EqualityComparable< edge_descriptor >));
238         BOOST_CONCEPT_ASSERT((Assignable< edge_descriptor >));
239         BOOST_CONCEPT_ASSERT(
240             (Convertible< traversal_category, edge_list_graph_tag >));
241 
242         BOOST_STATIC_ASSERT(
243             (boost::mpl::not_< boost::is_same< edge_iterator, void > >::value));
244         BOOST_STATIC_ASSERT((boost::mpl::not_<
245             boost::is_same< edges_size_type, void > >::value));
246 
247         p = edges(g);
248         e = *p.first;
249         u = source(e, g);
250         v = target(e, g);
251         const_constraints(g);
252     }
const_constraints(const G & cg)253     void const_constraints(const G& cg)
254     {
255         p = edges(cg);
256         E = num_edges(cg);
257         e = *p.first;
258         u = source(e, cg);
259         v = target(e, cg);
260     }
261     std::pair< edge_iterator, edge_iterator > p;
262     typename graph_traits< G >::vertex_descriptor u, v;
263     typename graph_traits< G >::edge_descriptor e;
264     edges_size_type E;
265     G g;
266 };
267 
268 BOOST_concept(VertexAndEdgeListGraph, (G))
269 : VertexListGraph< G >, EdgeListGraph< G > {};
270 
271 // Where to put the requirement for this constructor?
272 //      G g(n_vertices);
273 // Not in mutable graph, then LEDA graph's can't be models of
274 // MutableGraph.
275 BOOST_concept(EdgeMutableGraph, (G))
276 {
277     typedef typename graph_traits< G >::edge_descriptor edge_descriptor;
278 
BOOST_CONCEPT_USAGE(EdgeMutableGraph)279     BOOST_CONCEPT_USAGE(EdgeMutableGraph)
280     {
281         p = add_edge(u, v, g);
282         remove_edge(u, v, g);
283         remove_edge(e, g);
284         clear_vertex(v, g);
285     }
286     G g;
287     edge_descriptor e;
288     std::pair< edge_descriptor, bool > p;
289     typename graph_traits< G >::vertex_descriptor u, v;
290 };
291 
292 BOOST_concept(VertexMutableGraph, (G))
293 {
294 
BOOST_CONCEPT_USAGE(VertexMutableGraph)295     BOOST_CONCEPT_USAGE(VertexMutableGraph)
296     {
297         v = add_vertex(g);
298         remove_vertex(v, g);
299     }
300     G g;
301     typename graph_traits< G >::vertex_descriptor u, v;
302 };
303 
304 BOOST_concept(MutableGraph, (G))
305 : EdgeMutableGraph< G >, VertexMutableGraph< G > {};
306 
307 template < class edge_descriptor > struct dummy_edge_predicate
308 {
operator ()boost::concepts::dummy_edge_predicate309     bool operator()(const edge_descriptor&) const { return false; }
310 };
311 
312 BOOST_concept(MutableIncidenceGraph, (G)) : MutableGraph< G >
313 {
BOOST_CONCEPT_USAGE(MutableIncidenceGraph)314     BOOST_CONCEPT_USAGE(MutableIncidenceGraph)
315     {
316         remove_edge(iter, g);
317         remove_out_edge_if(u, p, g);
318     }
319     G g;
320     typedef typename graph_traits< G >::edge_descriptor edge_descriptor;
321     dummy_edge_predicate< edge_descriptor > p;
322     typename boost::graph_traits< G >::vertex_descriptor u;
323     typename boost::graph_traits< G >::out_edge_iterator iter;
324 };
325 
326 BOOST_concept(MutableBidirectionalGraph, (G)) : MutableIncidenceGraph< G >
327 {
BOOST_CONCEPT_USAGE(MutableBidirectionalGraph)328     BOOST_CONCEPT_USAGE(MutableBidirectionalGraph)
329     {
330         remove_in_edge_if(u, p, g);
331     }
332     G g;
333     typedef typename graph_traits< G >::edge_descriptor edge_descriptor;
334     dummy_edge_predicate< edge_descriptor > p;
335     typename boost::graph_traits< G >::vertex_descriptor u;
336 };
337 
338 BOOST_concept(MutableEdgeListGraph, (G)) : EdgeMutableGraph< G >
339 {
BOOST_CONCEPT_USAGE(MutableEdgeListGraph)340     BOOST_CONCEPT_USAGE(MutableEdgeListGraph) { remove_edge_if(p, g); }
341     G g;
342     typedef typename graph_traits< G >::edge_descriptor edge_descriptor;
343     dummy_edge_predicate< edge_descriptor > p;
344 };
345 
346 BOOST_concept(VertexMutablePropertyGraph, (G)) : VertexMutableGraph< G >
347 {
BOOST_CONCEPT_USAGE(VertexMutablePropertyGraph)348     BOOST_CONCEPT_USAGE(VertexMutablePropertyGraph) { v = add_vertex(vp, g); }
349     G g;
350     typename graph_traits< G >::vertex_descriptor v;
351     typename vertex_property_type< G >::type vp;
352 };
353 
354 BOOST_concept(EdgeMutablePropertyGraph, (G)) : EdgeMutableGraph< G >
355 {
356     typedef typename graph_traits< G >::edge_descriptor edge_descriptor;
357 
BOOST_CONCEPT_USAGE(EdgeMutablePropertyGraph)358     BOOST_CONCEPT_USAGE(EdgeMutablePropertyGraph) { p = add_edge(u, v, ep, g); }
359     G g;
360     std::pair< edge_descriptor, bool > p;
361     typename graph_traits< G >::vertex_descriptor u, v;
362     typename edge_property_type< G >::type ep;
363 };
364 
365 BOOST_concept(AdjacencyMatrix, (G)) : Graph< G >
366 {
367     typedef typename graph_traits< G >::edge_descriptor edge_descriptor;
368 
BOOST_CONCEPT_USAGE(AdjacencyMatrix)369     BOOST_CONCEPT_USAGE(AdjacencyMatrix)
370     {
371         p = edge(u, v, g);
372         const_constraints(g);
373     }
const_constraints(const G & cg)374     void const_constraints(const G& cg) { p = edge(u, v, cg); }
375     typename graph_traits< G >::vertex_descriptor u, v;
376     std::pair< edge_descriptor, bool > p;
377     G g;
378 };
379 
380 BOOST_concept(ReadablePropertyGraph, (G)(X)(Property)) : Graph< G >
381 {
382     typedef typename property_map< G, Property >::const_type const_Map;
383 
BOOST_CONCEPT_USAGE(ReadablePropertyGraph)384     BOOST_CONCEPT_USAGE(ReadablePropertyGraph)
385     {
386         BOOST_CONCEPT_ASSERT((ReadablePropertyMapConcept< const_Map, X >));
387 
388         const_constraints(g);
389     }
const_constraints(const G & cg)390     void const_constraints(const G& cg)
391     {
392         const_Map pmap = get(Property(), cg);
393         pval = get(Property(), cg, x);
394         ignore_unused_variable_warning(pmap);
395     }
396     G g;
397     X x;
398     typename property_traits< const_Map >::value_type pval;
399 };
400 
401 BOOST_concept(PropertyGraph, (G)(X)(Property))
402 : ReadablePropertyGraph< G, X, Property >
403 {
404     typedef typename property_map< G, Property >::type Map;
BOOST_CONCEPT_USAGE(PropertyGraph)405     BOOST_CONCEPT_USAGE(PropertyGraph)
406     {
407         BOOST_CONCEPT_ASSERT((ReadWritePropertyMapConcept< Map, X >));
408 
409         Map pmap = get(Property(), g);
410         pval = get(Property(), g, x);
411         put(Property(), g, x, pval);
412         ignore_unused_variable_warning(pmap);
413     }
414     G g;
415     X x;
416     typename property_traits< Map >::value_type pval;
417 };
418 
419 BOOST_concept(LvaluePropertyGraph, (G)(X)(Property))
420 : ReadablePropertyGraph< G, X, Property >
421 {
422     typedef typename property_map< G, Property >::type Map;
423     typedef typename property_map< G, Property >::const_type const_Map;
424 
BOOST_CONCEPT_USAGE(LvaluePropertyGraph)425     BOOST_CONCEPT_USAGE(LvaluePropertyGraph)
426     {
427         BOOST_CONCEPT_ASSERT((LvaluePropertyMapConcept< const_Map, X >));
428 
429         pval = get(Property(), g, x);
430         put(Property(), g, x, pval);
431     }
432     G g;
433     X x;
434     typename property_traits< Map >::value_type pval;
435 };
436 
437 // The *IndexGraph concepts are "semantic" graph concpepts. These can be
438 // applied to describe any graph that has an index map that can be accessed
439 // using the get(*_index, g) method. For example, adjacency lists with
440 // VertexSet == vecS are implicitly models of this concept.
441 //
442 // NOTE: We could require an associated type vertex_index_type, but that
443 // would mean propagating that type name into graph_traits and all of the
444 // other graph implementations. Much easier to simply call it unsigned.
445 
446 BOOST_concept(VertexIndexGraph, (Graph))
447 {
BOOST_CONCEPT_USAGE(VertexIndexGraph)448     BOOST_CONCEPT_USAGE(VertexIndexGraph)
449     {
450         typedef typename graph_traits< Graph >::vertex_descriptor Vertex;
451         typedef typename property_map< Graph, vertex_index_t >::type Map;
452         typedef unsigned Index; // This could be Graph::vertex_index_type
453         Map m = get(vertex_index, g);
454         Index x = get(vertex_index, g, Vertex());
455         ignore_unused_variable_warning(m);
456         ignore_unused_variable_warning(x);
457 
458         // This is relaxed
459         renumber_vertex_indices(g);
460 
461         const_constraints(g);
462     }
const_constraints(const Graph & g_)463     void const_constraints(const Graph& g_)
464     {
465         typedef typename property_map< Graph, vertex_index_t >::const_type Map;
466         Map m = get(vertex_index, g_);
467         ignore_unused_variable_warning(m);
468     }
469 
470 private:
471     Graph g;
472 };
473 
474 BOOST_concept(EdgeIndexGraph, (Graph))
475 {
476     BOOST_CONCEPT_USAGE(EdgeIndexGraph)
477     {
478         typedef typename graph_traits< Graph >::edge_descriptor Edge;
479         typedef typename property_map< Graph, edge_index_t >::type Map;
480         typedef unsigned Index; // This could be Graph::vertex_index_type
481         Map m = get(edge_index, g);
482         Index x = get(edge_index, g, Edge());
483         ignore_unused_variable_warning(m);
484         ignore_unused_variable_warning(x);
485 
486         // This is relaxed
487         renumber_edge_indices(g);
488 
489         const_constraints(g);
490     }
491     void const_constraints(const Graph& g_)
492     {
493         typedef typename property_map< Graph, edge_index_t >::const_type Map;
494         Map m = get(edge_index, g_);
495         ignore_unused_variable_warning(m);
496     }
497 
498 private:
499     Graph g;
500 };
501 
502 BOOST_concept(ColorValue, (C))
503 : EqualityComparable< C >, DefaultConstructible< C >
504 {
505     BOOST_CONCEPT_USAGE(ColorValue)
506     {
507         c = color_traits< C >::white();
508         c = color_traits< C >::gray();
509         c = color_traits< C >::black();
510     }
511     C c;
512 };
513 
514 BOOST_concept(BasicMatrix, (M)(I)(V))
515 {
516     BOOST_CONCEPT_USAGE(BasicMatrix)
517     {
518         V& elt = A[i][j];
519         const_constraints(A);
520         ignore_unused_variable_warning(elt);
521     }
522     void const_constraints(const M& cA)
523     {
524         const V& elt = cA[i][j];
525         ignore_unused_variable_warning(elt);
526     }
527     M A;
528     I i, j;
529 };
530 
531 // The following concepts describe aspects of numberic values and measure
532 // functions. We're extending the notion of numeric values to include
533 // emulation for zero and infinity.
534 
535 BOOST_concept(NumericValue, (Numeric)) { BOOST_CONCEPT_USAGE(NumericValue) {
536     BOOST_CONCEPT_ASSERT((DefaultConstructible< Numeric >));
537 BOOST_CONCEPT_ASSERT((CopyConstructible< Numeric >));
538 numeric_values< Numeric >::zero();
539 numeric_values< Numeric >::infinity();
540 }
541 }
542 ;
543 
544 BOOST_concept(DegreeMeasure, (Measure)(Graph))
545 {
546     BOOST_CONCEPT_USAGE(DegreeMeasure)
547     {
548         typedef typename Measure::degree_type Degree;
549         typedef typename Measure::vertex_type Vertex;
550 
551         Degree d = m(Vertex(), g);
552         ignore_unused_variable_warning(d);
553     }
554 
555 private:
556     Measure m;
557     Graph g;
558 };
559 
560 BOOST_concept(DistanceMeasure, (Measure)(Graph))
561 {
562     BOOST_CONCEPT_USAGE(DistanceMeasure)
563     {
564         typedef typename Measure::distance_type Distance;
565         typedef typename Measure::result_type Result;
566         Result r = m(Distance(), g);
567         ignore_unused_variable_warning(r);
568     }
569 
570 private:
571     Measure m;
572     Graph g;
573 };
574 
575 } /* namespace concepts */
576 
577 using boost::concepts::MultiPassInputIteratorConcept;
578 
579 // Graph concepts
580 using boost::concepts::AdjacencyGraphConcept;
581 using boost::concepts::AdjacencyMatrixConcept;
582 using boost::concepts::BidirectionalGraphConcept;
583 using boost::concepts::EdgeIndexGraphConcept;
584 using boost::concepts::EdgeListGraphConcept;
585 using boost::concepts::EdgeMutableGraphConcept;
586 using boost::concepts::EdgeMutablePropertyGraphConcept;
587 using boost::concepts::GraphConcept;
588 using boost::concepts::IncidenceGraphConcept;
589 using boost::concepts::LvaluePropertyGraphConcept;
590 using boost::concepts::MutableBidirectionalGraphConcept;
591 using boost::concepts::MutableEdgeListGraphConcept;
592 using boost::concepts::MutableGraphConcept;
593 using boost::concepts::MutableIncidenceGraphConcept;
594 using boost::concepts::PropertyGraphConcept;
595 using boost::concepts::ReadablePropertyGraphConcept;
596 using boost::concepts::VertexAndEdgeListGraphConcept;
597 using boost::concepts::VertexIndexGraphConcept;
598 using boost::concepts::VertexListGraphConcept;
599 using boost::concepts::VertexMutableGraphConcept;
600 using boost::concepts::VertexMutablePropertyGraphConcept;
601 
602 // Utility concepts
603 using boost::concepts::BasicMatrixConcept;
604 using boost::concepts::ColorValueConcept;
605 using boost::concepts::DegreeMeasureConcept;
606 using boost::concepts::DistanceMeasureConcept;
607 using boost::concepts::NumericValueConcept;
608 
609 } /* namespace boost */
610 #include <boost/concept/detail/concept_undef.hpp>
611 
612 #endif /* BOOST_GRAPH_CONCEPTS_H */
613