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