summaryrefslogtreecommitdiff
path: root/boost/graph/undirected_graph.hpp
blob: 3178b42afd8ed35eb63c4fd632ae4c65cb49330d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
// (C) Copyright 2007-2009 Andrew Sutton
//
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0 (See accompanying file
// LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)

#ifndef BOOST_GRAPH_UNDIRECTED_GRAPH_HPP
#define BOOST_GRAPH_UNDIRECTED_GRAPH_HPP

#include <boost/utility.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/properties.hpp>

// NOTE: The retag_property_list is used to "normalize" a proeprty such that
// any non-property conforming parameter is wrapped in a vertex_bundle
// property. For example (with bad syntax) retag<property<X>> -> property<X>,
// but retag<foo> -> property<vertex_bundle_t, foo>.

namespace boost
{
struct undirected_graph_tag { };

/**
 * The undirected_graph class template is a simplified version of the BGL
 * adjacency list. This class is provided for ease of use, but may not
 * perform as well as custom-defined adjacency list classes. Instances of
 * this template model the VertexIndexGraph, and EdgeIndexGraph concepts. The
 * graph is also fully mutable, supporting both insertions and removals of
 * vertices and edges.
 *
 * @note Special care must be taken when removing vertices or edges since
 * those operations can invalidate the numbering of vertices.
 */
template <
    typename VertexProp = no_property,
    typename EdgeProp = no_property,
    typename GraphProp = no_property>
class undirected_graph
{
public:
    typedef typename graph_detail::graph_prop<GraphProp>::property graph_property_type;
    typedef typename graph_detail::graph_prop<GraphProp>::bundle graph_bundled;

    typedef typename graph_detail::vertex_prop<VertexProp>::property vertex_property_type;
    typedef typename graph_detail::vertex_prop<VertexProp>::bundle vertex_bundled;

    typedef typename graph_detail::edge_prop<EdgeProp>::property edge_property_type;
    typedef typename graph_detail::edge_prop<EdgeProp>::bundle edge_bundled;

private:
    // Embed indices into the vertex type.
    typedef property<vertex_index_t, unsigned, vertex_property_type> vertex_property;
    typedef property<edge_index_t, unsigned, edge_property_type> edge_property;
public:
    typedef adjacency_list<listS,
                listS,
                undirectedS,
                vertex_property,
                edge_property,
                GraphProp,
                listS> graph_type;
private:
    // storage selectors
    typedef typename graph_type::vertex_list_selector vertex_list_selector;
    typedef typename graph_type::edge_list_selector edge_list_selector;
    typedef typename graph_type::out_edge_list_selector out_edge_list_selector;
    typedef typename graph_type::directed_selector directed_selector;

public:
    // more commonly used graph types
    typedef typename graph_type::stored_vertex stored_vertex;
    typedef typename graph_type::vertices_size_type vertices_size_type;
    typedef typename graph_type::edges_size_type edges_size_type;
    typedef typename graph_type::degree_size_type degree_size_type;
    typedef typename graph_type::vertex_descriptor vertex_descriptor;
    typedef typename graph_type::edge_descriptor edge_descriptor;

    // iterator types
    typedef typename graph_type::vertex_iterator vertex_iterator;
    typedef typename graph_type::edge_iterator edge_iterator;
    typedef typename graph_type::out_edge_iterator out_edge_iterator;
    typedef typename graph_type::in_edge_iterator in_edge_iterator;
    typedef typename graph_type::adjacency_iterator adjacency_iterator;

    // miscellaneous types
    typedef undirected_graph_tag graph_tag;
    typedef typename graph_type::directed_category directed_category;
    typedef typename graph_type::edge_parallel_category edge_parallel_category;
    typedef typename graph_type::traversal_category traversal_category;

    typedef std::size_t vertex_index_type;
    typedef std::size_t edge_index_type;

    inline undirected_graph(GraphProp const& p = GraphProp())
        : m_graph(p), m_num_vertices(0), m_num_edges(0), m_max_vertex_index(0)
        , m_max_edge_index(0)
    { }

    inline undirected_graph(undirected_graph const& x)
        : m_graph(x.m_graph), m_num_vertices(x.m_num_vertices), m_num_edges(x.m_num_edges)
        , m_max_vertex_index(x.m_max_vertex_index), m_max_edge_index(x.m_max_edge_index)
    { }

    inline undirected_graph(vertices_size_type n,
                            GraphProp const& p = GraphProp())
        : m_graph(n, p), m_num_vertices(n), m_num_edges(0), m_max_vertex_index(n)
        , m_max_edge_index(0)
    { renumber_vertex_indices(); }

    template <typename EdgeIterator>
    inline undirected_graph(EdgeIterator f,
                            EdgeIterator l,
                            vertices_size_type n,
                            edges_size_type m = 0,
                            GraphProp const& p = GraphProp())
        : m_graph(f, l, n, m, p), m_num_vertices(n), m_num_edges(0)
        , m_max_vertex_index(n), m_max_edge_index(0)
    {
        // Unfortunately, we have to renumber to ensure correct indexing.
        renumber_indices();

        // Can't always guarantee that the number of edges is actually
        // m if distance(f, l) != m (or is undefined).
        m_num_edges = m_max_edge_index = boost::num_edges(m_graph);
    }

    undirected_graph& operator =(undirected_graph const& g) {
        if(&g != this) {
            m_graph = g.m_graph;
            m_num_vertices = g.m_num_vertices;
            m_num_edges = g.m_num_edges;
            m_max_vertex_index = g.m_max_vertex_index;
        }
        return *this;
    }

    // The impl_() methods are not part of the public interface.
    graph_type& impl()
    { return m_graph; }

    graph_type const& impl() const
    { return m_graph; }

    // The following methods are not part of the public interface
    vertices_size_type num_vertices() const
    { return m_num_vertices; }


private:
    // This helper function manages the attribution of vertex indices.
    vertex_descriptor make_index(vertex_descriptor v) {
        boost::put(vertex_index, m_graph, v, m_max_vertex_index);
        m_num_vertices++;
        m_max_vertex_index++;
        return v;
    }
public:
    vertex_descriptor add_vertex()
    { return make_index(boost::add_vertex(m_graph)); }

    vertex_descriptor add_vertex(vertex_property_type const& p)
    { return make_index(boost::add_vertex(vertex_property(0u, p), m_graph)); }

    void clear_vertex(vertex_descriptor v) {
        std::pair<out_edge_iterator, out_edge_iterator>
        p = boost::out_edges(v, m_graph);
        m_num_edges -= std::distance(p.first, p.second);
        boost::clear_vertex(v, m_graph);
    }

    void remove_vertex(vertex_descriptor v) {
        boost::remove_vertex(v, m_graph);
        --m_num_vertices;
    }

    edges_size_type num_edges() const
    { return m_num_edges; }

private:
    // A helper fucntion for managing edge index attributes.
    std::pair<edge_descriptor, bool> const&
    make_index(std::pair<edge_descriptor, bool> const& x)
    {
        if(x.second) {
            boost::put(edge_index, m_graph, x.first, m_max_edge_index);
            ++m_num_edges;
            ++m_max_edge_index;
        }
        return x;
    }
public:
    std::pair<edge_descriptor, bool>
    add_edge(vertex_descriptor u, vertex_descriptor v)
    { return make_index(boost::add_edge(u, v, m_graph)); }

    std::pair<edge_descriptor, bool>
    add_edge(vertex_descriptor u, vertex_descriptor v,
             edge_property_type const& p)
    { return make_index(boost::add_edge(u, v, edge_property(0u, p), m_graph)); }

    void remove_edge(vertex_descriptor u, vertex_descriptor v) {
        // find all edges, (u, v)
        std::vector<edge_descriptor> edges;
        out_edge_iterator i, i_end;
        for(boost::tie(i, i_end) = boost::out_edges(u, m_graph); i != i_end; ++i) {
            if(boost::target(*i, m_graph) == v) {
                edges.push_back(*i);
            }
        }
        // remove all edges, (u, v)
        typename std::vector<edge_descriptor>::iterator
        j = edges.begin(), j_end = edges.end();
        for( ; j != j_end; ++j) {
            remove_edge(*j);
        }
    }

    void remove_edge(edge_iterator i) {
        remove_edge(*i);
    }

    void remove_edge(edge_descriptor e) {
        boost::remove_edge(e, m_graph);
        --m_num_edges;
    }

    vertex_index_type max_vertex_index() const
    { return m_max_vertex_index; }

    void renumber_vertex_indices() {
        vertex_iterator i, i_end;
        boost::tie(i, i_end) = vertices(m_graph);
        m_max_vertex_index = renumber_vertex_indices(i, i_end, 0);
    }

    void remove_vertex_and_renumber_indices(vertex_iterator i) {
        vertex_iterator j = next(i), end = vertices(m_graph).second;
        vertex_index_type n = get(vertex_index, m_graph, *i);

        // remove the offending vertex and renumber everything after
        remove_vertex(*i);
        m_max_vertex_index = renumber_vertex_indices(j, end, n);
    }


    edge_index_type max_edge_index() const
    { return m_max_edge_index; }

    void renumber_edge_indices() {
        edge_iterator i, end;
        boost::tie(i, end) = edges(m_graph);
        m_max_edge_index = renumber_edge_indices(i, end, 0);
    }

    void remove_edge_and_renumber_indices(edge_iterator i) {
        edge_iterator j = next(i), end = edges(m_graph.second);
        edge_index_type n = get(edge_index, m_graph, *i);

        // remove the edge and renumber everything after it
        remove_edge(*i);
        m_max_edge_index = renumber_edge_indices(j, end, n);
    }

    void renumber_indices() {
        renumber_vertex_indices();
        renumber_edge_indices();
    }

    // bundled property support
#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
    vertex_bundled& operator[](vertex_descriptor v)
    { return m_graph[v]; }

    vertex_bundled const& operator[](vertex_descriptor v) const
    { return m_graph[v]; }

    edge_bundled& operator[](edge_descriptor e)
    { return m_graph[e]; }

    edge_bundled const& operator[](edge_descriptor e) const
    { return m_graph[e]; }

    graph_bundled& operator[](graph_bundle_t)
    { return get_property(*this); }

    graph_bundled const& operator[](graph_bundle_t) const
    { return get_property(*this); }
#endif

    // Graph concepts
    static vertex_descriptor null_vertex()
    { return graph_type::null_vertex(); }

    void clear() {
        m_graph.clear();
        m_num_vertices = m_max_vertex_index = 0;
        m_num_edges = m_max_edge_index = 0;
    }

    void swap(undirected_graph& g) {
        m_graph.swap(g);
        std::swap(m_num_vertices, g.m_num_vertices);
        std::swap(m_max_vertex_index, g.m_max_vertex_index);
        std::swap(m_num_edges, g.m_num_edges);
        std::swap(m_max_edge_index, g.m_max_edge_index);
    }

private:
    vertices_size_type renumber_vertex_indices(vertex_iterator i,
                                               vertex_iterator end,
                                               vertices_size_type n)
    {
        typedef typename property_map<graph_type, vertex_index_t>::type IndexMap;
        IndexMap indices = get(vertex_index, m_graph);
        for( ; i != end; ++i) {
            indices[*i] = n++;
        }
        return n;
    }

    edges_size_type renumber_edge_indices(edge_iterator i,
                                          edge_iterator end,
                                          edges_size_type n)
    {
        typedef typename property_map<graph_type, edge_index_t>::type IndexMap;
        IndexMap indices = get(edge_index, m_graph);
        for( ; i != end; ++i) {
            indices[*i] = n++;
        }
        return n;
    }

    graph_type m_graph;
    vertices_size_type m_num_vertices;
    edges_size_type m_num_edges;
    vertex_index_type m_max_vertex_index;
    edge_index_type m_max_edge_index;
};

#define UNDIRECTED_GRAPH_PARAMS typename VP, typename EP, typename GP
#define UNDIRECTED_GRAPH undirected_graph<VP,EP,GP>

// IncidenceGraph concepts
template <UNDIRECTED_GRAPH_PARAMS>
inline typename UNDIRECTED_GRAPH::vertex_descriptor
source(typename UNDIRECTED_GRAPH::edge_descriptor e,
       UNDIRECTED_GRAPH const& g)
{ return source(e, g.impl()); }

template <UNDIRECTED_GRAPH_PARAMS>
inline typename UNDIRECTED_GRAPH::vertex_descriptor
target(typename UNDIRECTED_GRAPH::edge_descriptor e,
       UNDIRECTED_GRAPH const& g)
{ return target(e, g.impl()); }

template <UNDIRECTED_GRAPH_PARAMS>
inline typename UNDIRECTED_GRAPH::degree_size_type
out_degree(typename UNDIRECTED_GRAPH::vertex_descriptor v,
           UNDIRECTED_GRAPH const& g)
{ return out_degree(v, g.impl()); }

template <UNDIRECTED_GRAPH_PARAMS>
inline std::pair<
    typename UNDIRECTED_GRAPH::out_edge_iterator,
    typename UNDIRECTED_GRAPH::out_edge_iterator
>
out_edges(typename UNDIRECTED_GRAPH::vertex_descriptor v,
          UNDIRECTED_GRAPH const& g)
{ return out_edges(v, g.impl()); }

// BidirectionalGraph concepts
template <UNDIRECTED_GRAPH_PARAMS>
inline typename UNDIRECTED_GRAPH::degree_size_type
in_degree(typename UNDIRECTED_GRAPH::vertex_descriptor v,
          UNDIRECTED_GRAPH const& g)
{ return in_degree(v, g.impl()); }

template <UNDIRECTED_GRAPH_PARAMS>
inline std::pair<
    typename UNDIRECTED_GRAPH::in_edge_iterator,
    typename UNDIRECTED_GRAPH::in_edge_iterator
>
in_edges(typename UNDIRECTED_GRAPH::vertex_descriptor v,
         UNDIRECTED_GRAPH const& g)
{ return in_edges(v, g.impl()); }

template <UNDIRECTED_GRAPH_PARAMS>
inline std::pair<
    typename UNDIRECTED_GRAPH::out_edge_iterator,
    typename UNDIRECTED_GRAPH::out_edge_iterator
>
incident_edges(typename UNDIRECTED_GRAPH::vertex_descriptor v,
               UNDIRECTED_GRAPH const& g)
{ return out_edges(v, g.impl()); }

template <UNDIRECTED_GRAPH_PARAMS>
inline typename UNDIRECTED_GRAPH::degree_size_type
degree(typename UNDIRECTED_GRAPH::vertex_descriptor v,
       UNDIRECTED_GRAPH const& g)
{ return degree(v, g.impl()); }

// AdjacencyGraph concepts
template <UNDIRECTED_GRAPH_PARAMS>
inline std::pair<
    typename UNDIRECTED_GRAPH::adjacency_iterator,
    typename UNDIRECTED_GRAPH::adjacency_iterator
    >
adjacent_vertices(typename UNDIRECTED_GRAPH::vertex_descriptor v,
                  UNDIRECTED_GRAPH const& g)
{ return adjacent_vertices(v, g.impl()); }

template <UNDIRECTED_GRAPH_PARAMS>
typename UNDIRECTED_GRAPH::vertex_descriptor
vertex(typename UNDIRECTED_GRAPH::vertices_size_type n,
       UNDIRECTED_GRAPH const& g)
{ return vertex(n, g.impl()); }

template <UNDIRECTED_GRAPH_PARAMS>
std::pair<typename UNDIRECTED_GRAPH::edge_descriptor, bool>
edge(typename UNDIRECTED_GRAPH::vertex_descriptor u,
    typename UNDIRECTED_GRAPH::vertex_descriptor v,
    UNDIRECTED_GRAPH const& g)
{ return edge(u, v, g.impl()); }

// VertexListGraph concepts
template <UNDIRECTED_GRAPH_PARAMS>
inline typename UNDIRECTED_GRAPH::vertices_size_type
num_vertices(UNDIRECTED_GRAPH const& g)
{ return g.num_vertices(); }

template <UNDIRECTED_GRAPH_PARAMS>
inline std::pair<
    typename UNDIRECTED_GRAPH::vertex_iterator,
    typename UNDIRECTED_GRAPH::vertex_iterator
>
vertices(UNDIRECTED_GRAPH const& g)
{ return vertices(g.impl()); }

// EdgeListGraph concepts
template <UNDIRECTED_GRAPH_PARAMS>
inline typename UNDIRECTED_GRAPH::edges_size_type
num_edges(UNDIRECTED_GRAPH const& g)
{ return g.num_edges(); }

template <UNDIRECTED_GRAPH_PARAMS>
inline std::pair<
    typename UNDIRECTED_GRAPH::edge_iterator,
    typename UNDIRECTED_GRAPH::edge_iterator
>
edges(UNDIRECTED_GRAPH const& g)
{ return edges(g.impl()); }

// MutableGraph concepts
template <UNDIRECTED_GRAPH_PARAMS>
inline typename UNDIRECTED_GRAPH::vertex_descriptor
add_vertex(UNDIRECTED_GRAPH& g)
{ return g.add_vertex(); }

template <UNDIRECTED_GRAPH_PARAMS>
inline typename UNDIRECTED_GRAPH::vertex_descriptor
add_vertex(typename UNDIRECTED_GRAPH::vertex_property_type const& p,
           UNDIRECTED_GRAPH& g)
{ return g.add_vertex(p); }

template <UNDIRECTED_GRAPH_PARAMS>
inline void
clear_vertex(typename UNDIRECTED_GRAPH::vertex_descriptor v,
             UNDIRECTED_GRAPH& g)
{ return g.clear_vertex(v); }

template <UNDIRECTED_GRAPH_PARAMS>
inline void
remove_vertex(typename UNDIRECTED_GRAPH::vertex_descriptor v, UNDIRECTED_GRAPH& g)
{ return g.remove_vertex(v); }

template <UNDIRECTED_GRAPH_PARAMS>
inline std::pair<typename UNDIRECTED_GRAPH::edge_descriptor, bool>
add_edge(typename UNDIRECTED_GRAPH::vertex_descriptor u,
         typename UNDIRECTED_GRAPH::vertex_descriptor v,
         UNDIRECTED_GRAPH& g)
{ return g.add_edge(u, v); }

template <UNDIRECTED_GRAPH_PARAMS>
inline std::pair<typename UNDIRECTED_GRAPH::edge_descriptor, bool>
add_edge(typename UNDIRECTED_GRAPH::vertex_descriptor u,
         typename UNDIRECTED_GRAPH::vertex_descriptor v,
         typename UNDIRECTED_GRAPH::edge_property_type const& p,
         UNDIRECTED_GRAPH& g)
{ return g.add_edge(u, v, p); }

template <UNDIRECTED_GRAPH_PARAMS>
inline void
remove_edge(typename UNDIRECTED_GRAPH::vertex_descriptor u,
            typename UNDIRECTED_GRAPH::vertex_descriptor v,
            UNDIRECTED_GRAPH& g)
{ return g.remove_edge(u, v); }

template <UNDIRECTED_GRAPH_PARAMS>
inline void
remove_edge(typename UNDIRECTED_GRAPH::edge_descriptor e, UNDIRECTED_GRAPH& g)
{ return g.remove_edge(e); }

template <UNDIRECTED_GRAPH_PARAMS>
inline void
remove_edge(typename UNDIRECTED_GRAPH::edge_iterator i, UNDIRECTED_GRAPH& g)
{ return g.remove_edge(i); }

template <UNDIRECTED_GRAPH_PARAMS, class Predicate>
inline void remove_edge_if(Predicate pred, UNDIRECTED_GRAPH& g)
{ return remove_edge_if(pred, g.impl()); }

template <UNDIRECTED_GRAPH_PARAMS, class Predicate>
inline void
remove_incident_edge_if(typename UNDIRECTED_GRAPH::vertex_descriptor v,
                        Predicate pred,
                        UNDIRECTED_GRAPH& g)
{ return remove_out_edge_if(v, pred, g.impl()); }

template <UNDIRECTED_GRAPH_PARAMS, class Predicate>
inline void
remove_out_edge_if(typename UNDIRECTED_GRAPH::vertex_descriptor v,
                   Predicate pred,
                   UNDIRECTED_GRAPH& g)
{ return remove_out_edge_if(v, pred, g.impl()); }

template <UNDIRECTED_GRAPH_PARAMS, class Predicate>
inline void
remove_in_edge_if(typename UNDIRECTED_GRAPH::vertex_descriptor v,
                  Predicate pred,
                  UNDIRECTED_GRAPH& g)
{ return remove_in_edge_if(v, pred, g.impl()); }

// Helper code for working with property maps
namespace detail {
    struct undirected_graph_vertex_property_selector {
        template <class UndirectedGraph, class Property, class Tag>
        struct bind_ {
            typedef typename UndirectedGraph::graph_type Graph;
            typedef property_map<Graph, Tag> PropertyMap;
            typedef typename PropertyMap::type type;
            typedef typename PropertyMap::const_type const_type;
        };
    };

    struct undirected_graph_edge_property_selector {
        template <class UndirectedGraph, class Property, class Tag>
        struct bind_ {
            typedef typename UndirectedGraph::graph_type Graph;
            typedef property_map<Graph, Tag> PropertyMap;
            typedef typename PropertyMap::type type;
            typedef typename PropertyMap::const_type const_type;
        };
    };
} // namespace detail

template <>
struct vertex_property_selector<undirected_graph_tag>
{ typedef detail::undirected_graph_vertex_property_selector type; };

template <>
struct edge_property_selector<undirected_graph_tag>
{ typedef detail::undirected_graph_edge_property_selector type; };

// PropertyGraph concepts
template <UNDIRECTED_GRAPH_PARAMS, typename Property>
inline typename property_map<UNDIRECTED_GRAPH, Property>::type
get(Property p, UNDIRECTED_GRAPH& g)
{ return get(p, g.impl()); }

template <UNDIRECTED_GRAPH_PARAMS, typename Property>
inline typename property_map<UNDIRECTED_GRAPH, Property>::const_type
get(Property p, UNDIRECTED_GRAPH const& g)
{ return get(p, g.impl()); }

template <UNDIRECTED_GRAPH_PARAMS, typename Property, typename Key>
inline typename property_traits<
    typename property_map<
        typename UNDIRECTED_GRAPH::graph_type, Property
    >::const_type
>::value_type
get(Property p, UNDIRECTED_GRAPH const& g, Key const& k)
{ return get(p, g.impl(), k); }

template <UNDIRECTED_GRAPH_PARAMS, typename Property, typename Key, typename Value>
inline void put(Property p, UNDIRECTED_GRAPH& g, Key const& k, Value const& v)
{ put(p, g.impl(), k, v); }

template <UNDIRECTED_GRAPH_PARAMS, class Property>
inline typename graph_property<UNDIRECTED_GRAPH, Property>::type&
get_property(UNDIRECTED_GRAPH& g, Property p)
{ return get_property(g.impl(), p); }

template <UNDIRECTED_GRAPH_PARAMS, class Property>
inline typename graph_property<UNDIRECTED_GRAPH, Property>::type const&
get_property(UNDIRECTED_GRAPH const& g, Property p)
{ return get_property(g.impl(), p); }

template <UNDIRECTED_GRAPH_PARAMS, class Property, class Value>
inline void set_property(UNDIRECTED_GRAPH& g, Property p, Value v)
{ return set_property(g.impl(), p, v); }

#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
template <UNDIRECTED_GRAPH_PARAMS, typename Type, typename Bundle>
inline typename property_map<UNDIRECTED_GRAPH, Type Bundle::*>::type
get(Type Bundle::* p, UNDIRECTED_GRAPH& g) {
    typedef typename property_map<
        UNDIRECTED_GRAPH, Type Bundle::*
    >::type return_type;
    return return_type(&g, p);
}

template <UNDIRECTED_GRAPH_PARAMS, typename Type, typename Bundle>
inline typename property_map<UNDIRECTED_GRAPH, Type Bundle::*>::const_type
get(Type Bundle::* p, UNDIRECTED_GRAPH const& g) {
    typedef typename property_map<
        UNDIRECTED_GRAPH, Type Bundle::*
    >::const_type return_type;
    return return_type(&g, p);
}

template <UNDIRECTED_GRAPH_PARAMS, typename Type, typename Bundle, typename Key>
inline Type
get(Type Bundle::* p, UNDIRECTED_GRAPH const& g, Key const& k)
{ return get(p, g.impl(), k); }

template <UNDIRECTED_GRAPH_PARAMS, typename Type, typename Bundle, typename Key, typename Value>
inline void
put(Type Bundle::* p, UNDIRECTED_GRAPH& g, Key const& k, Value const& v)
{ put(p, g.impl(), k, v); }
#endif

// Indexed Vertex graph

template <UNDIRECTED_GRAPH_PARAMS>
inline typename UNDIRECTED_GRAPH::vertex_index_type
get_vertex_index(typename UNDIRECTED_GRAPH::vertex_descriptor v,
                 UNDIRECTED_GRAPH const& g)
{ return get(vertex_index, g, v); }

template <UNDIRECTED_GRAPH_PARAMS>
typename UNDIRECTED_GRAPH::vertex_index_type
max_vertex_index(UNDIRECTED_GRAPH const& g)
{ return g.max_vertex_index(); }

template <UNDIRECTED_GRAPH_PARAMS>
inline void
renumber_vertex_indices(UNDIRECTED_GRAPH& g)
{ g.renumber_vertex_indices(); }

template <UNDIRECTED_GRAPH_PARAMS>
inline void
remove_vertex_and_renumber_indices(typename UNDIRECTED_GRAPH::vertex_iterator i,
                                   UNDIRECTED_GRAPH& g)
{ g.remove_vertex_and_renumber_indices(i); }


// Edge index management

template <UNDIRECTED_GRAPH_PARAMS>
inline typename UNDIRECTED_GRAPH::edge_index_type
get_edge_index(typename UNDIRECTED_GRAPH::edge_descriptor v,
               UNDIRECTED_GRAPH const& g)
{ return get(edge_index, g, v); }

template <UNDIRECTED_GRAPH_PARAMS>
typename UNDIRECTED_GRAPH::edge_index_type
max_edge_index(UNDIRECTED_GRAPH const& g)
{ return g.max_edge_index(); }

template <UNDIRECTED_GRAPH_PARAMS>
inline void
renumber_edge_indices(UNDIRECTED_GRAPH& g)
{ g.renumber_edge_indices(); }

template <UNDIRECTED_GRAPH_PARAMS>
inline void
remove_edge_and_renumber_indices(typename UNDIRECTED_GRAPH::edge_iterator i,
                                 UNDIRECTED_GRAPH& g)
{ g.remove_edge_and_renumber_indices(i); }

// Index management
template <UNDIRECTED_GRAPH_PARAMS>
inline void
renumber_indices(UNDIRECTED_GRAPH& g)
{ g.renumber_indices(); }

// Mutability Traits
template <UNDIRECTED_GRAPH_PARAMS>
struct graph_mutability_traits<UNDIRECTED_GRAPH> {
    typedef mutable_property_graph_tag category;
};

#undef UNDIRECTED_GRAPH_PARAMS
#undef UNDIRECTED_GRAPH

} /* namespace boost */

#endif