Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/graph/compressed_sparse_row_graph.hpp @ 35

Last change on this file since 35 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

File size: 27.3 KB
Line 
1// Copyright 2005-2006 The Trustees of Indiana University.
2
3// Distributed under the Boost Software License, Version 1.0.
4// (See accompanying file LICENSE_1_0.txt or copy at
5// http://www.boost.org/LICENSE_1_0.txt)
6
7//  Authors: Jeremiah Willcock
8//           Douglas Gregor
9//           Andrew Lumsdaine
10
11// Compressed sparse row graph type
12
13#ifndef BOOST_GRAPH_COMPRESSED_SPARSE_ROW_GRAPH_HPP
14#define BOOST_GRAPH_COMPRESSED_SPARSE_ROW_GRAPH_HPP
15
16#include <vector>
17#include <utility>
18#include <algorithm>
19#include <climits>
20#include <iterator>
21#include <boost/graph/graph_traits.hpp>
22#include <boost/graph/properties.hpp>
23#include <boost/graph/detail/indexed_properties.hpp>
24#include <boost/iterator/counting_iterator.hpp>
25#include <boost/integer.hpp>
26#include <boost/iterator/iterator_facade.hpp>
27#include <boost/mpl/if.hpp>
28#include <boost/graph/graph_selectors.hpp>
29#include <boost/static_assert.hpp>
30
31#ifdef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
32#  error The Compressed Sparse Row graph only supports bundled properties.
33#  error You will need a compiler that conforms better to the C++ standard.
34#endif
35
36namespace boost {
37
38// A tag type indicating that the graph in question is a compressed
39// sparse row graph. This is an internal detail of the BGL.
40struct csr_graph_tag;
41
42/****************************************************************************
43 * Local helper macros to reduce typing and clutter later on.               *
44 ****************************************************************************/
45#define BOOST_CSR_GRAPH_TEMPLATE_PARMS                                  \
46  typename Directed, typename VertexProperty, typename EdgeProperty,    \
47  typename GraphProperty, typename Vertex, typename EdgeIndex
48#define BOOST_CSR_GRAPH_TYPE                                            \
49   compressed_sparse_row_graph<Directed, VertexProperty, EdgeProperty,  \
50                               GraphProperty, Vertex, EdgeIndex>
51
52// Forward declaration of CSR edge descriptor type, needed to pass to
53// indexed_edge_properties.
54template<typename Vertex, typename EdgeIndex>
55class csr_edge_descriptor;
56
57/** Compressed sparse row graph.
58 *
59 * Vertex and EdgeIndex should be unsigned integral types and should
60 * specialize numeric_limits.
61 */
62template<typename Directed = directedS, 
63         typename VertexProperty = void,
64         typename EdgeProperty = void,
65         typename GraphProperty = no_property,
66         typename Vertex = std::size_t,
67         typename EdgeIndex = Vertex>
68class compressed_sparse_row_graph
69   : public detail::indexed_vertex_properties<BOOST_CSR_GRAPH_TYPE, VertexProperty,
70                                              Vertex>,
71     public detail::indexed_edge_properties<BOOST_CSR_GRAPH_TYPE, EdgeProperty,
72                                            csr_edge_descriptor<Vertex,
73                                                                EdgeIndex> >
74
75{
76  typedef detail::indexed_vertex_properties<compressed_sparse_row_graph,
77                                            VertexProperty, Vertex>
78    inherited_vertex_properties;
79
80  typedef detail::indexed_edge_properties<BOOST_CSR_GRAPH_TYPE, EdgeProperty,
81                                          csr_edge_descriptor<Vertex, EdgeIndex> >
82    inherited_edge_properties;
83
84 public:
85  // For Property Graph
86  typedef GraphProperty graph_property_type;
87
88 protected:
89  template<typename InputIterator>
90  void
91  maybe_reserve_edge_list_storage(InputIterator, InputIterator,
92                                  std::input_iterator_tag)
93  {
94    // Do nothing: we have no idea how much storage to reserve.
95  }
96
97  template<typename InputIterator>
98  void
99  maybe_reserve_edge_list_storage(InputIterator first, InputIterator last,
100                                  std::forward_iterator_tag)
101  {
102    using std::distance;
103    typename std::iterator_traits<InputIterator>::difference_type n =
104      distance(first, last);
105    m_column.reserve(n);
106    inherited_edge_properties::reserve(n);
107  }
108
109 public:
110  /* At this time, the compressed sparse row graph can only be used to
111   * create a directed graph. In the future, bidirectional and
112   * undirected CSR graphs will also be supported.
113   */
114  BOOST_STATIC_ASSERT((is_same<Directed, directedS>::value));
115
116  // Concept requirements:
117  // For Graph
118  typedef Vertex vertex_descriptor;
119  typedef csr_edge_descriptor<Vertex, EdgeIndex> edge_descriptor;
120  typedef directed_tag directed_category;
121  typedef allow_parallel_edge_tag edge_parallel_category;
122
123  class traversal_category: public incidence_graph_tag,
124                            public adjacency_graph_tag,
125                            public vertex_list_graph_tag,
126                            public edge_list_graph_tag {};
127
128  static vertex_descriptor null_vertex() { return vertex_descriptor(-1); }
129
130  // For VertexListGraph
131  typedef counting_iterator<Vertex> vertex_iterator;
132  typedef Vertex vertices_size_type;
133
134  // For EdgeListGraph
135  typedef EdgeIndex edges_size_type;
136
137  // For IncidenceGraph
138  class out_edge_iterator;
139  typedef EdgeIndex degree_size_type;
140
141  // For AdjacencyGraph
142  typedef typename std::vector<Vertex>::const_iterator adjacency_iterator;
143
144  // For EdgeListGraph
145  class edge_iterator;
146
147  // For BidirectionalGraph (not implemented)
148  typedef void in_edge_iterator;
149
150  // For internal use
151  typedef csr_graph_tag graph_tag;
152
153  // Constructors
154
155  // Default constructor: an empty graph.
156  compressed_sparse_row_graph()
157    : m_rowstart(1, EdgeIndex(0)), m_column(0), m_property(),
158      m_last_source(0) {}
159
160  //  From number of vertices and sorted list of edges
161  template<typename InputIterator>
162  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
163                              vertices_size_type numverts,
164                              edges_size_type numedges = 0,
165                              const GraphProperty& prop = GraphProperty())
166    : inherited_vertex_properties(numverts), m_rowstart(numverts + 1),
167      m_column(0), m_property(prop), m_last_source(numverts)
168  {
169    // Reserving storage in advance can save us lots of time and
170    // memory, but it can only be done if we have forward iterators or
171    // the user has supplied the number of edges.
172    if (numedges == 0) {
173      typedef typename std::iterator_traits<InputIterator>::iterator_category
174        category;
175      maybe_reserve_edge_list_storage(edge_begin, edge_end, category());
176    } else {
177      m_column.reserve(numedges);
178    }
179
180    EdgeIndex current_edge = 0;
181    Vertex current_vertex_plus_one = 1;
182    m_rowstart[0] = 0;
183    for (InputIterator ei = edge_begin; ei != edge_end; ++ei) {
184      Vertex src = ei->first;
185      Vertex tgt = ei->second;
186      for (; current_vertex_plus_one != src + 1; ++current_vertex_plus_one)
187        m_rowstart[current_vertex_plus_one] = current_edge;
188      m_column.push_back(tgt);
189      ++current_edge;
190    }
191
192    // The remaining vertices have no edges
193    for (; current_vertex_plus_one != numverts + 1; ++current_vertex_plus_one)
194      m_rowstart[current_vertex_plus_one] = current_edge;
195
196    // Default-construct properties for edges
197    inherited_edge_properties::resize(m_column.size());
198  }
199
200  //  From number of vertices and sorted list of edges
201  template<typename InputIterator, typename EdgePropertyIterator>
202  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
203                              EdgePropertyIterator ep_iter,
204                              vertices_size_type numverts,
205                              edges_size_type numedges = 0,
206                              const GraphProperty& prop = GraphProperty())
207    : inherited_vertex_properties(numverts), m_rowstart(numverts + 1),
208      m_column(0), m_property(prop), m_last_source(numverts)
209  {
210    // Reserving storage in advance can save us lots of time and
211    // memory, but it can only be done if we have forward iterators or
212    // the user has supplied the number of edges.
213    if (numedges == 0) {
214      typedef typename std::iterator_traits<InputIterator>::iterator_category
215        category;
216      maybe_reserve_edge_list_storage(edge_begin, edge_end, category());
217    } else {
218      m_column.reserve(numedges);
219    }
220
221    EdgeIndex current_edge = 0;
222    Vertex current_vertex_plus_one = 1;
223    m_rowstart[0] = 0;
224    for (InputIterator ei = edge_begin; ei != edge_end; ++ei, ++ep_iter) {
225      Vertex src = ei->first;
226      Vertex tgt = ei->second;
227      for (; current_vertex_plus_one != src + 1; ++current_vertex_plus_one)
228        m_rowstart[current_vertex_plus_one] = current_edge;
229      m_column.push_back(tgt);
230      inherited_edge_properties::push_back(*ep_iter);
231      ++current_edge;
232    }
233
234    // The remaining vertices have no edges
235    for (; current_vertex_plus_one != numverts + 1; ++current_vertex_plus_one)
236      m_rowstart[current_vertex_plus_one] = current_edge;
237  }
238
239  //   Requires IncidenceGraph, a vertex index map, and a vertex(n, g) function
240  template<typename Graph, typename VertexIndexMap>
241  compressed_sparse_row_graph(const Graph& g, const VertexIndexMap& vi,
242                              vertices_size_type numverts,
243                              edges_size_type numedges)
244    : m_property(), m_last_source(0)
245  {
246    assign(g, vi, numverts, numedges);
247  }
248
249  //   Requires VertexListGraph and EdgeListGraph
250  template<typename Graph, typename VertexIndexMap>
251  compressed_sparse_row_graph(const Graph& g, const VertexIndexMap& vi)
252    : m_property(), m_last_source(0)
253  {
254    assign(g, vi, num_vertices(g), num_edges(g));
255  }
256
257  // Requires vertex index map plus requirements of previous constructor
258  template<typename Graph>
259  explicit compressed_sparse_row_graph(const Graph& g)
260    : m_property(), m_last_source(0)
261  {
262    assign(g, get(vertex_index, g), num_vertices(g), num_edges(g));
263  }
264
265  // From any graph (slow and uses a lot of memory)
266  //   Requires IncidenceGraph, a vertex index map, and a vertex(n, g) function
267  //   Internal helper function
268  template<typename Graph, typename VertexIndexMap>
269  void
270  assign(const Graph& g, const VertexIndexMap& vi,
271         vertices_size_type numverts, edges_size_type numedges)
272  {
273    inherited_vertex_properties::resize(numverts);
274    m_rowstart.resize(numverts + 1);
275    m_column.resize(numedges);
276    EdgeIndex current_edge = 0;
277    typedef typename boost::graph_traits<Graph>::vertex_descriptor g_vertex;
278    typedef typename boost::graph_traits<Graph>::edge_descriptor g_edge;
279    typedef typename boost::graph_traits<Graph>::out_edge_iterator
280      g_out_edge_iter;
281
282    for (Vertex i = 0; i != numverts; ++i) {
283      m_rowstart[i] = current_edge;
284      g_vertex v = vertex(i, g);
285      EdgeIndex num_edges_before_this_vertex = current_edge;
286      g_out_edge_iter ei, ei_end;
287      for (tie(ei, ei_end) = out_edges(v, g); ei != ei_end; ++ei) {
288        m_column[current_edge++] = get(vi, target(*ei, g));
289      }
290      std::sort(m_column.begin() + num_edges_before_this_vertex,
291                m_column.begin() + current_edge);
292    }
293    m_rowstart[numverts] = current_edge;
294    m_last_source = numverts;
295  }
296
297  // Requires the above, plus VertexListGraph and EdgeListGraph
298  template<typename Graph, typename VertexIndexMap>
299  void assign(const Graph& g, const VertexIndexMap& vi)
300  {
301    assign(g, vi, num_vertices(g), num_edges(g));
302  }
303
304  // Requires the above, plus a vertex_index map.
305  template<typename Graph>
306  void assign(const Graph& g)
307  {
308    assign(g, get(vertex_index, g), num_vertices(g), num_edges(g));
309  }
310
311  using inherited_vertex_properties::operator[];
312  using inherited_edge_properties::operator[];
313
314  // private: non-portable, requires friend templates
315  inherited_vertex_properties&       vertex_properties()       {return *this;}
316  const inherited_vertex_properties& vertex_properties() const {return *this;}
317  inherited_edge_properties&       edge_properties()       { return *this; }
318  const inherited_edge_properties& edge_properties() const { return *this; }
319
320  std::vector<EdgeIndex> m_rowstart;
321  std::vector<Vertex> m_column;
322  GraphProperty m_property;
323  Vertex m_last_source; // Last source of added edge, plus one
324};
325
326template<typename Vertex, typename EdgeIndex>
327class csr_edge_descriptor
328{
329 public:
330  Vertex src;
331  EdgeIndex idx;
332
333  csr_edge_descriptor(Vertex src, EdgeIndex idx): src(src), idx(idx) {}
334  csr_edge_descriptor(): src(0), idx(0) {}
335
336  bool operator==(const csr_edge_descriptor& e) const {return idx == e.idx;}
337  bool operator!=(const csr_edge_descriptor& e) const {return idx != e.idx;}
338  bool operator<(const csr_edge_descriptor& e) const {return idx < e.idx;}
339  bool operator>(const csr_edge_descriptor& e) const {return idx > e.idx;}
340  bool operator<=(const csr_edge_descriptor& e) const {return idx <= e.idx;}
341  bool operator>=(const csr_edge_descriptor& e) const {return idx >= e.idx;}
342};
343
344// Construction functions
345template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
346inline Vertex
347add_vertex(BOOST_CSR_GRAPH_TYPE& g) {
348  Vertex old_num_verts_plus_one = g.m_rowstart.size();
349  g.m_rowstart.push_back(EdgeIndex(0));
350  return old_num_verts_plus_one - 1;
351}
352
353template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
354inline Vertex
355add_vertices(typename BOOST_CSR_GRAPH_TYPE::vertices_size_type count, BOOST_CSR_GRAPH_TYPE& g) {
356  Vertex old_num_verts_plus_one = g.m_rowstart.size();
357  g.m_rowstart.resize(old_num_verts_plus_one + count, EdgeIndex(0));
358  return old_num_verts_plus_one - 1;
359}
360
361// This function requires that (src, tgt) be lexicographically at least as
362// large as the largest edge in the graph so far
363template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
364inline typename BOOST_CSR_GRAPH_TYPE::edge_descriptor
365add_edge(Vertex src, Vertex tgt, BOOST_CSR_GRAPH_TYPE& g) {
366  assert ((g.m_last_source == 0 || src >= g.m_last_source - 1) &&
367          src < num_vertices(g));
368  EdgeIndex num_edges_orig = g.m_column.size();
369  for (; g.m_last_source <= src; ++g.m_last_source)
370    g.m_rowstart[g.m_last_source] = num_edges_orig;
371  g.m_rowstart[src + 1] = num_edges_orig + 1;
372  g.m_column.push_back(tgt);
373  typedef typename BOOST_CSR_GRAPH_TYPE::edge_push_back_type push_back_type;
374  g.edge_properties().push_back(push_back_type());
375  return typename BOOST_CSR_GRAPH_TYPE::edge_descriptor(src, num_edges_orig);
376}
377
378// This function requires that (src, tgt) be lexicographically at least as
379// large as the largest edge in the graph so far
380template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
381inline typename BOOST_CSR_GRAPH_TYPE::edge_descriptor
382add_edge(Vertex src, Vertex tgt,
383         typename BOOST_CSR_GRAPH_TYPE::edge_bundled const& p,
384         BOOST_CSR_GRAPH_TYPE& g) {
385  assert ((g.m_last_source == 0 || src >= g.m_last_source - 1) &&
386          src < num_vertices(g));
387  EdgeIndex num_edges_orig = g.m_column.size();
388  for (; g.m_last_source <= src; ++g.m_last_source)
389    g.m_rowstart[g.m_last_source] = num_edges_orig;
390  g.m_rowstart[src + 1] = num_edges_orig + 1;
391  g.m_column.push_back(tgt);
392  g.edge_properties().push_back(p);
393  return typename BOOST_CSR_GRAPH_TYPE::edge_descriptor(src, num_edges_orig);
394}
395
396
397// From VertexListGraph
398template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
399inline Vertex
400num_vertices(const BOOST_CSR_GRAPH_TYPE& g) {
401  return g.m_rowstart.size() - 1;
402}
403
404template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
405std::pair<counting_iterator<Vertex>, counting_iterator<Vertex> >
406inline vertices(const BOOST_CSR_GRAPH_TYPE& g) {
407  return std::make_pair(counting_iterator<Vertex>(0),
408                        counting_iterator<Vertex>(num_vertices(g)));
409}
410
411// From IncidenceGraph
412template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
413class BOOST_CSR_GRAPH_TYPE::out_edge_iterator
414  : public iterator_facade<typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator,
415                           typename BOOST_CSR_GRAPH_TYPE::edge_descriptor,
416                           std::random_access_iterator_tag,
417                           const typename BOOST_CSR_GRAPH_TYPE::edge_descriptor&,
418                           typename int_t<CHAR_BIT * sizeof(EdgeIndex)>::fast>
419{
420 public:
421  typedef typename int_t<CHAR_BIT * sizeof(EdgeIndex)>::fast difference_type;
422
423  out_edge_iterator() {}
424  // Implicit copy constructor OK
425  explicit out_edge_iterator(edge_descriptor edge) : m_edge(edge) { }
426
427 private:
428  // iterator_facade requirements
429  const edge_descriptor& dereference() const { return m_edge; }
430
431  bool equal(const out_edge_iterator& other) const
432  { return m_edge == other.m_edge; }
433
434  void increment() { ++m_edge.idx; }
435  void decrement() { ++m_edge.idx; }
436  void advance(difference_type n) { m_edge.idx += n; }
437
438  difference_type distance_to(const out_edge_iterator& other) const
439  { return other.m_edge.idx - m_edge.idx; }
440
441  edge_descriptor m_edge;
442
443  friend class iterator_core_access;
444};
445
446template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
447inline Vertex
448source(typename BOOST_CSR_GRAPH_TYPE::edge_descriptor e,
449       const BOOST_CSR_GRAPH_TYPE&)
450{
451  return e.src;
452}
453
454template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
455inline Vertex
456target(typename BOOST_CSR_GRAPH_TYPE::edge_descriptor e,
457       const BOOST_CSR_GRAPH_TYPE& g)
458{
459  return g.m_column[e.idx];
460}
461
462template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
463inline std::pair<typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator,
464                 typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator>
465out_edges(Vertex v, const BOOST_CSR_GRAPH_TYPE& g)
466{
467  typedef typename BOOST_CSR_GRAPH_TYPE::edge_descriptor ed;
468  typedef typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator it;
469  EdgeIndex v_row_start = g.m_rowstart[v];
470  EdgeIndex next_row_start = g.m_rowstart[v + 1];
471  return std::make_pair(it(ed(v, v_row_start)),
472                        it(ed(v, (std::max)(v_row_start, next_row_start))));
473}
474
475template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
476inline EdgeIndex
477out_degree(Vertex v, const BOOST_CSR_GRAPH_TYPE& g)
478{
479  EdgeIndex v_row_start = g.m_rowstart[v];
480  EdgeIndex next_row_start = g.m_rowstart[v + 1];
481  return (std::max)(v_row_start, next_row_start) - v_row_start;
482}
483
484// From AdjacencyGraph
485template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
486inline std::pair<typename BOOST_CSR_GRAPH_TYPE::adjacency_iterator,
487                 typename BOOST_CSR_GRAPH_TYPE::adjacency_iterator>
488adjacent_vertices(Vertex v, const BOOST_CSR_GRAPH_TYPE& g)
489{
490  EdgeIndex v_row_start = g.m_rowstart[v];
491  EdgeIndex next_row_start = g.m_rowstart[v + 1];
492  return std::make_pair(g.m_column.begin() + v_row_start,
493                        g.m_column.begin() +
494                                (std::max)(v_row_start, next_row_start));
495}
496
497// Extra, common functions
498template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
499inline typename graph_traits<BOOST_CSR_GRAPH_TYPE>::vertex_descriptor
500vertex(typename graph_traits<BOOST_CSR_GRAPH_TYPE>::vertex_descriptor i, 
501       const BOOST_CSR_GRAPH_TYPE&)
502{
503  return i;
504}
505
506// Unlike for an adjacency_matrix, edge_range and edge take lg(out_degree(i))
507// time
508template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
509inline std::pair<typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator,
510                 typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator>
511edge_range(Vertex i, Vertex j, const BOOST_CSR_GRAPH_TYPE& g)
512{
513  typedef typename std::vector<Vertex>::const_iterator adj_iter;
514  typedef typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator out_edge_iter;
515  typedef typename BOOST_CSR_GRAPH_TYPE::edge_descriptor edge_desc;
516  std::pair<adj_iter, adj_iter> raw_adjacencies = adjacent_vertices(i, g);
517  std::pair<adj_iter, adj_iter> adjacencies =
518    std::equal_range(raw_adjacencies.first, raw_adjacencies.second, j);
519  EdgeIndex idx_begin = adjacencies.first - g.m_column.begin();
520  EdgeIndex idx_end = adjacencies.second - g.m_column.begin();
521  return std::make_pair(out_edge_iter(edge_desc(i, idx_begin)),
522                        out_edge_iter(edge_desc(i, idx_end)));
523}
524
525template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
526inline std::pair<typename BOOST_CSR_GRAPH_TYPE::edge_descriptor, bool>
527edge(Vertex i, Vertex j, const BOOST_CSR_GRAPH_TYPE& g)
528{
529  typedef typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator out_edge_iter;
530  std::pair<out_edge_iter, out_edge_iter> range = edge_range(i, j, g);
531  if (range.first == range.second)
532    return std::make_pair(typename BOOST_CSR_GRAPH_TYPE::edge_descriptor(),
533                          false);
534  else
535    return std::make_pair(*range.first, true);
536}
537
538// Find an edge given its index in the graph
539template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
540inline typename BOOST_CSR_GRAPH_TYPE::edge_descriptor
541edge_from_index(EdgeIndex idx, const BOOST_CSR_GRAPH_TYPE& g)
542{
543  typedef typename std::vector<EdgeIndex>::const_iterator row_start_iter;
544  assert (idx < num_edges(g));
545  row_start_iter src_plus_1 =
546    std::upper_bound(g.m_rowstart.begin(),
547                     g.m_rowstart.begin() + g.m_last_source + 1,
548                     idx);
549    // Get last source whose rowstart is at most idx
550    // upper_bound returns this position plus 1
551  Vertex src = (src_plus_1 - g.m_rowstart.begin()) - 1;
552  return typename BOOST_CSR_GRAPH_TYPE::edge_descriptor(src, idx);
553}
554
555// From EdgeListGraph
556template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
557class BOOST_CSR_GRAPH_TYPE::edge_iterator
558{
559 public:
560  typedef std::forward_iterator_tag iterator_category;
561  typedef edge_descriptor value_type;
562
563  typedef const edge_descriptor* pointer;
564
565  typedef edge_descriptor reference;
566  typedef typename int_t<CHAR_BIT * sizeof(EdgeIndex)>::fast difference_type;
567
568  edge_iterator() : rowstart_array(0), current_edge(), end_of_this_vertex(0) {}
569
570  edge_iterator(const compressed_sparse_row_graph& graph,
571                edge_descriptor current_edge,
572                EdgeIndex end_of_this_vertex)
573    : rowstart_array(&graph.m_rowstart[0]), current_edge(current_edge),
574      end_of_this_vertex(end_of_this_vertex) {}
575
576  // From InputIterator
577  reference operator*() const { return current_edge; }
578  pointer operator->() const { return &current_edge; }
579
580  bool operator==(const edge_iterator& o) const {
581    return current_edge == o.current_edge;
582  }
583  bool operator!=(const edge_iterator& o) const {
584    return current_edge != o.current_edge;
585  }
586
587  edge_iterator& operator++() {
588    ++current_edge.idx;
589    while (current_edge.idx == end_of_this_vertex) {
590      ++current_edge.src;
591      end_of_this_vertex = rowstart_array[current_edge.src + 1];
592    }
593    return *this;
594  }
595
596  edge_iterator operator++(int) {
597    edge_iterator temp = *this;
598    ++*this;
599    return temp;
600  }
601
602 private:
603  const EdgeIndex* rowstart_array;
604  edge_descriptor current_edge;
605  EdgeIndex end_of_this_vertex;
606};
607
608template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
609inline EdgeIndex
610num_edges(const BOOST_CSR_GRAPH_TYPE& g)
611{
612  return g.m_column.size();
613}
614
615template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
616std::pair<typename BOOST_CSR_GRAPH_TYPE::edge_iterator,
617          typename BOOST_CSR_GRAPH_TYPE::edge_iterator>
618edges(const BOOST_CSR_GRAPH_TYPE& g)
619{
620  typedef typename BOOST_CSR_GRAPH_TYPE::edge_iterator ei;
621  typedef typename BOOST_CSR_GRAPH_TYPE::edge_descriptor edgedesc;
622  if (g.m_rowstart.size() == 1 || g.m_column.empty()) {
623    return std::make_pair(ei(), ei());
624  } else {
625    // Find the first vertex that has outgoing edges
626    Vertex src = 0;
627    while (g.m_rowstart[src + 1] == 0) ++src;
628    return std::make_pair(ei(g, edgedesc(src, 0), g.m_rowstart[src + 1]),
629                          ei(g, edgedesc(num_vertices(g), g.m_column.size()), 0));
630  }
631}
632
633// For Property Graph
634
635// Graph properties
636template<BOOST_CSR_GRAPH_TEMPLATE_PARMS, class Tag, class Value>
637inline void
638set_property(BOOST_CSR_GRAPH_TYPE& g, Tag, const Value& value)
639{
640  get_property_value(g.m_property, Tag()) = value;
641}
642
643template<BOOST_CSR_GRAPH_TEMPLATE_PARMS, class Tag>
644inline
645typename graph_property<BOOST_CSR_GRAPH_TYPE, Tag>::type&
646get_property(BOOST_CSR_GRAPH_TYPE& g, Tag)
647{
648  return get_property_value(g.m_property, Tag());
649}
650
651template<BOOST_CSR_GRAPH_TEMPLATE_PARMS, class Tag>
652inline
653const
654typename graph_property<BOOST_CSR_GRAPH_TYPE, Tag>::type&
655get_property(const BOOST_CSR_GRAPH_TYPE& g, Tag)
656{
657  return get_property_value(g.m_property, Tag());
658}
659
660// Add edge_index property map
661template<typename Index, typename Descriptor>
662struct csr_edge_index_map
663{
664  typedef Index                     value_type;
665  typedef Index                     reference;
666  typedef Descriptor                key_type;
667  typedef readable_property_map_tag category;
668};
669
670template<typename Index, typename Descriptor>
671inline Index
672get(const csr_edge_index_map<Index, Descriptor>&,
673    const typename csr_edge_index_map<Index, Descriptor>::key_type& key)
674{
675  return key.idx;
676}
677
678// Doing the right thing here (by unifying with vertex_index_t and
679// edge_index_t) breaks GCC.
680template<BOOST_CSR_GRAPH_TEMPLATE_PARMS, typename Tag>
681struct property_map<BOOST_CSR_GRAPH_TYPE, Tag>
682{
683private:
684  typedef identity_property_map vertex_index_type;
685  typedef typename graph_traits<BOOST_CSR_GRAPH_TYPE>::edge_descriptor
686    edge_descriptor;
687  typedef csr_edge_index_map<EdgeIndex, edge_descriptor> edge_index_type;
688
689  typedef typename mpl::if_<is_same<Tag, edge_index_t>,
690                            edge_index_type,
691                            detail::error_property_not_found>::type
692    edge_or_none;
693
694public:
695  typedef typename mpl::if_<is_same<Tag, vertex_index_t>,
696                            vertex_index_type,
697                            edge_or_none>::type type;
698
699  typedef type const_type;
700};
701
702template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
703inline identity_property_map
704get(vertex_index_t, const BOOST_CSR_GRAPH_TYPE&)
705{
706  return identity_property_map();
707}
708
709template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
710inline Vertex
711get(vertex_index_t,
712    const BOOST_CSR_GRAPH_TYPE&, Vertex v)
713{
714  return v;
715}
716
717template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
718inline typename property_map<BOOST_CSR_GRAPH_TYPE, edge_index_t>::const_type
719get(edge_index_t, const BOOST_CSR_GRAPH_TYPE&)
720{
721  typedef typename property_map<BOOST_CSR_GRAPH_TYPE, edge_index_t>::const_type
722    result_type;
723  return result_type();
724}
725
726template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
727inline EdgeIndex
728get(edge_index_t, const BOOST_CSR_GRAPH_TYPE&,
729    typename BOOST_CSR_GRAPH_TYPE::edge_descriptor e)
730{
731  return e.idx;
732}
733
734// Support for bundled properties
735template<BOOST_CSR_GRAPH_TEMPLATE_PARMS, typename T, typename Bundle>
736struct property_map<BOOST_CSR_GRAPH_TYPE, T Bundle::*>
737{
738private:
739  typedef graph_traits<BOOST_CSR_GRAPH_TYPE> traits;
740  typedef VertexProperty vertex_bundled;
741  typedef EdgeProperty edge_bundled;
742  typedef typename ct_if<(detail::is_vertex_bundle<vertex_bundled, edge_bundled, Bundle>::value),
743                     typename traits::vertex_descriptor,
744                     typename traits::edge_descriptor>::type
745    descriptor;
746
747public:
748  typedef bundle_property_map<BOOST_CSR_GRAPH_TYPE, descriptor, Bundle, T>
749    type;
750  typedef bundle_property_map<const BOOST_CSR_GRAPH_TYPE, descriptor, Bundle,
751                              const T> const_type;
752};
753
754template<BOOST_CSR_GRAPH_TEMPLATE_PARMS, typename T, typename Bundle>
755inline
756typename property_map<BOOST_CSR_GRAPH_TYPE, T Bundle::*>::type
757get(T Bundle::* p, BOOST_CSR_GRAPH_TYPE& g)
758{
759  typedef typename property_map<BOOST_CSR_GRAPH_TYPE,
760                                T Bundle::*>::type
761    result_type;
762  return result_type(&g, p);
763}
764
765template<BOOST_CSR_GRAPH_TEMPLATE_PARMS, typename T, typename Bundle>
766inline
767typename property_map<BOOST_CSR_GRAPH_TYPE, T Bundle::*>::const_type
768get(T Bundle::* p, BOOST_CSR_GRAPH_TYPE const & g)
769{
770  typedef typename property_map<BOOST_CSR_GRAPH_TYPE,
771                                T Bundle::*>::const_type
772    result_type;
773  return result_type(&g, p);
774}
775
776template<BOOST_CSR_GRAPH_TEMPLATE_PARMS, typename T, typename Bundle,
777         typename Key>
778inline T
779get(T Bundle::* p, BOOST_CSR_GRAPH_TYPE const & g,
780    const Key& key)
781{
782  return get(get(p, g), key);
783}
784
785template<BOOST_CSR_GRAPH_TEMPLATE_PARMS, typename T, typename Bundle,
786         typename Key>
787inline void
788put(T Bundle::* p, BOOST_CSR_GRAPH_TYPE& g,
789    const Key& key, const T& value)
790{
791  put(get(p, g), key, value);
792}
793
794#undef BOOST_CSR_GRAPH_TYPE
795#undef BOOST_CSR_GRAPH_TEMPLATE_PARMS
796
797} // end namespace boost
798
799#endif // BOOST_GRAPH_COMPRESSED_SPARSE_ROW_GRAPH_HPP
Note: See TracBrowser for help on using the repository browser.