summaryrefslogtreecommitdiff
path: root/boost/graph/vector_as_graph.hpp
blob: 7bc8ac3802d66d5401d95d637ae824756d775cfa (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
//=======================================================================
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
// Copyright 2006 The Trustees of Indiana University.
// Copyright (C) 2001 Vladimir Prus <ghost@cs.msu.su>
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, Douglas Gregor
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

// The mutating functions (add_edge, etc.) were added by Vladimir Prus.

#ifndef BOOST_VECTOR_AS_GRAPH_HPP
#define BOOST_VECTOR_AS_GRAPH_HPP

#include <cassert>
#include <utility>
#include <vector>
#include <cstddef>
#include <boost/iterator.hpp>
#include <boost/iterator/counting_iterator.hpp>
#include <boost/range/irange.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/graph/properties.hpp>
#include <algorithm>

/*
  This module implements the VertexListGraph concept using a
  std::vector as the "back-bone" of the graph (the vector *is* the
  graph object). The edge-lists type of the graph is templated, so the
  user can choose any STL container, so long as the value_type of the
  container is convertible to the size_type of the vector. For now any
  graph properties must be stored seperately.

  This module requires the C++ compiler to support partial
  specialization for the graph_traits class, so this is not portable
  to VC++.

*/

#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
#error The vector-as-graph module requires a compiler that supports partial specialization
#endif


namespace boost {
  namespace detail {
    template <class EdgeList> struct val_out_edge_ret;
    template <class EdgeList> struct val_out_edge_iter;
    template <class EdgeList> struct val_edge;
  }
}

#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
namespace boost {

  struct vector_as_graph_traversal_tag
    : public vertex_list_graph_tag,
      public adjacency_graph_tag,
      public incidence_graph_tag { };

  template <class EdgeList>
  struct graph_traits< std::vector<EdgeList> >
  {
    typedef typename EdgeList::value_type V;
    typedef V vertex_descriptor;
    typedef typename detail::val_edge<EdgeList>::type edge_descriptor;
    typedef typename EdgeList::const_iterator adjacency_iterator;
    typedef typename detail::val_out_edge_iter<EdgeList>::type
      out_edge_iterator;
    typedef void in_edge_iterator;
    typedef void edge_iterator;
    typedef counting_iterator<V> vertex_iterator;
    typedef directed_tag directed_category;
    typedef allow_parallel_edge_tag edge_parallel_category;
    typedef vector_as_graph_traversal_tag traversal_category;
    typedef typename std::vector<EdgeList>::size_type vertices_size_type;
    typedef void edges_size_type;
    typedef typename EdgeList::size_type degree_size_type;
    static V null_vertex() {return V(-1);}
  };
  template <class EdgeList>
  struct edge_property_type< std::vector<EdgeList> >
  {
    typedef void type;
  };
  template <class EdgeList>
  struct vertex_property_type< std::vector<EdgeList> >
  {
    typedef void type;
  };
  template <class EdgeList>
  struct graph_property_type< std::vector<EdgeList> >
  {
    typedef void type;
  };
}
#endif

namespace boost {

  namespace detail {

    // "val" is short for Vector Adjacency List

    template <class EdgeList>
    struct val_edge
    {
      typedef typename EdgeList::value_type V;
      typedef std::pair<V,V> type;
    };

    // need rewrite this using boost::iterator_adaptor
    template <class V, class Iter>
    class val_out_edge_iterator
      : public boost::iterator<std::input_iterator_tag, std::pair<V,V>,
         std::ptrdiff_t, std::pair<V,V>*, const std::pair<V,V> >
    {
      typedef val_out_edge_iterator self;
      typedef std::pair<V,V> Edge;
    public:
      val_out_edge_iterator() { }
      val_out_edge_iterator(V s, Iter i) : _source(s), _iter(i) { }
      Edge operator*() const { return Edge(_source, *_iter); }
      self& operator++() { ++_iter; return *this; }
      self operator++(int) { self t = *this; ++_iter; return t; }
      bool operator==(const self& x) const { return _iter == x._iter; }
      bool operator!=(const self& x) const { return _iter != x._iter; }
    protected:
      V _source;
      Iter _iter;
    };

    template <class EdgeList>
    struct val_out_edge_iter
    {
      typedef typename EdgeList::value_type V;
      typedef typename EdgeList::const_iterator Iter;
      typedef val_out_edge_iterator<V,Iter> type;
    };

    template <class EdgeList>
    struct val_out_edge_ret
    {
      typedef typename val_out_edge_iter<EdgeList>::type IncIter;
      typedef std::pair<IncIter,IncIter> type;
    };

  } // namesapce detail

  template <class EdgeList, class Alloc>
  typename detail::val_out_edge_ret<EdgeList>::type
  out_edges(typename EdgeList::value_type v,
            const std::vector<EdgeList, Alloc>& g)
  {
    typedef typename detail::val_out_edge_iter<EdgeList>::type Iter;
    typedef typename detail::val_out_edge_ret<EdgeList>::type return_type;
    return return_type(Iter(v, g[v].begin()), Iter(v, g[v].end()));
  }

  template <class EdgeList, class Alloc>
  typename EdgeList::size_type
  out_degree(typename EdgeList::value_type v,
             const std::vector<EdgeList, Alloc>& g)
  {
    return g[v].size();
  }

  template <class EdgeList, class Alloc>
  std::pair<typename EdgeList::const_iterator,
            typename EdgeList::const_iterator>
  adjacent_vertices(typename EdgeList::value_type v,
                    const std::vector<EdgeList, Alloc>& g)
  {
    return std::make_pair(g[v].begin(), g[v].end());
  }

  // source() and target() already provided for pairs in graph_traits.hpp

  template <class EdgeList, class Alloc>
  std::pair<boost::counting_iterator<typename EdgeList::value_type>,
            boost::counting_iterator<typename EdgeList::value_type> >
  vertices(const std::vector<EdgeList, Alloc>& v)
  {
    typedef boost::counting_iterator<typename EdgeList::value_type> Iter;
    return std::make_pair(Iter(0), Iter(v.size()));
  }

  template <class EdgeList, class Alloc>
  typename std::vector<EdgeList, Alloc>::size_type
  num_vertices(const std::vector<EdgeList, Alloc>& v)
  {
    return v.size();
  }

  template<class EdgeList, class Allocator>
  typename std::pair<typename detail::val_edge<EdgeList>::type, bool>
  add_edge(typename EdgeList::value_type u, typename EdgeList::value_type v,
           std::vector<EdgeList, Allocator>& g)
  {
    typedef typename detail::val_edge<EdgeList>::type edge_type;
    g[u].insert(g[u].end(), v);
    return std::make_pair(edge_type(u, v), true);
  }

  template<class EdgeList, class Allocator>
  typename std::pair<typename detail::val_edge<EdgeList>::type, bool>
  edge(typename EdgeList::value_type u, typename EdgeList::value_type v,
       std::vector<EdgeList, Allocator>& g)
  {
    typedef typename detail::val_edge<EdgeList>::type edge_type;
    typename EdgeList::iterator i = g[u].begin(), end = g[u].end();
    for (; i != end; ++i)
      if (*i == v)
        return std::make_pair(edge_type(u, v), true);
    return std::make_pair(edge_type(), false);
  }

  template<class EdgeList, class Allocator>
  void
  remove_edge(typename EdgeList::value_type u, typename EdgeList::value_type v,
              std::vector<EdgeList, Allocator>& g)
  {
    typename EdgeList::iterator i = std::remove(g[u].begin(), g[u].end(), v);
    if (i != g[u].end())
      g[u].erase(i, g[u].end());
  }

  template<class EdgeList, class Allocator>
  void
  remove_edge(typename detail::val_edge<EdgeList>::type e,
              std::vector<EdgeList, Allocator>& g)
  {
    typename EdgeList::value_type u, v;
    u = e.first;
    v = e.second;
    // FIXME: edge type does not fully specify the edge to be deleted
    typename EdgeList::iterator i = std::remove(g[u].begin(), g[u].end(), v);
    if (i != g[u].end())
      g[u].erase(i, g[u].end());
  }

  template<class EdgeList, class Allocator, class Predicate>
  void
  remove_edge_if(Predicate p,
                 std::vector<EdgeList, Allocator>& g)
  {
      for (std::size_t u = 0; u < g.size(); ++u) {
          // Oops! gcc gets internal compiler error on compose_.......

          typedef typename EdgeList::iterator iterator;
          iterator b = g[u].begin(), e = g[u].end();

          if (!g[u].empty()) {

              for(; b != e;) {
                  if (p(std::make_pair(u, *b))) {
                      --e;
                      if (b == e)
                          break;
                      else
                          iter_swap(b, e);
                  } else {
                      ++b;
                  }
              }
          }

          if (e != g[u].end())
              g[u].erase(e, g[u].end());
      }
  }

  template<class EdgeList, class Allocator>
  typename EdgeList::value_type
  add_vertex(std::vector<EdgeList, Allocator>& g)
  {
    g.resize(g.size()+1);
    return g.size()-1;
  }

  template<class EdgeList, class Allocator>
  void
  clear_vertex(typename EdgeList::value_type u,
               std::vector<EdgeList, Allocator>& g)
  {
    g[u].clear();
    for (std::size_t i = 0; i < g.size(); ++i)
      remove_edge(i, u, g);
  }

  template<class EdgeList, class Allocator>
  void
  remove_vertex(typename EdgeList::value_type u,
                std::vector<EdgeList, Allocator>& g)
  {
    typedef typename EdgeList::iterator iterator;
    clear_vertex(u, g);
    g.erase(g.begin() + u);
    for (std::size_t i = 0; i < g.size(); ++i)
      for ( iterator it = g[i].begin(); it != g[i].end(); ++it )
        // after clear_vertex *it is never equal to u
        if ( *it > u )
          --*it;
  }

  template<typename EdgeList, typename Allocator>
  struct property_map<std::vector<EdgeList, Allocator>, vertex_index_t>
  {
    typedef identity_property_map type;
    typedef type const_type;
  };

  template<typename EdgeList, typename Allocator>
  identity_property_map
  get(vertex_index_t, const std::vector<EdgeList, Allocator>&)
  {
    return identity_property_map();
  }

  template<typename EdgeList, typename Allocator>
  identity_property_map
  get(vertex_index_t, std::vector<EdgeList, Allocator>&)
  {
    return identity_property_map();
  }
} // namespace boost

#endif // BOOST_VECTOR_AS_GRAPH_HPP