1 // Copyright 2005-2009 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 <boost/assert.hpp>
21 #include <iterator>
22 #if 0
23 #include <iostream> // For some debugging code below
24 #endif
25 #include <boost/graph/graph_traits.hpp>
26 #include <boost/graph/properties.hpp>
27 #include <boost/graph/filtered_graph.hpp> // For keep_all
28 #include <boost/graph/detail/indexed_properties.hpp>
29 #include <boost/graph/detail/compressed_sparse_row_struct.hpp>
30 #include <boost/graph/iteration_macros.hpp>
31 #include <boost/iterator/counting_iterator.hpp>
32 #include <boost/iterator/reverse_iterator.hpp>
33 #include <boost/iterator/zip_iterator.hpp>
34 #include <boost/iterator/transform_iterator.hpp>
35 #include <boost/tuple/tuple.hpp>
36 #include <boost/property_map/property_map.hpp>
37 #include <boost/integer.hpp>
38 #include <boost/iterator/iterator_facade.hpp>
39 #include <boost/mpl/if.hpp>
40 #include <boost/utility/enable_if.hpp>
41 #include <boost/graph/graph_selectors.hpp>
42 #include <boost/graph/detail/is_distributed_selector.hpp>
43 #include <boost/graph/properties.hpp>
44 #include <boost/static_assert.hpp>
45 #include <boost/functional/hash.hpp>
46 #include <boost/next_prior.hpp>
47 #include <boost/property_map/transform_value_property_map.hpp>
48 #include <boost/mpl/print.hpp>
49 
50 namespace boost
51 {
52 
53 // A tag type indicating that the graph in question is a compressed
54 // sparse row graph. This is an internal detail of the BGL.
55 struct csr_graph_tag;
56 
57 // A type (edges_are_sorted_t) and a value (edges_are_sorted) used to indicate
58 // that the edge list passed into the CSR graph is already sorted by source
59 // vertex.
60 enum edges_are_sorted_t
61 {
62     edges_are_sorted
63 };
64 
65 // A type (edges_are_sorted_global_t) and a value (edges_are_sorted_global)
66 // used to indicate that the edge list passed into the CSR graph is already
67 // sorted by source vertex.
68 enum edges_are_sorted_global_t
69 {
70     edges_are_sorted_global
71 };
72 
73 // A type (edges_are_unsorted_t) and a value (edges_are_unsorted) used to
74 // indicate that the edge list passed into the CSR graph is not sorted by
75 // source vertex.  This version caches the edge information in memory, and thus
76 // requires only a single pass over the input data.
77 enum edges_are_unsorted_t
78 {
79     edges_are_unsorted
80 };
81 
82 // A type (edges_are_unsorted_multi_pass_t) and a value
83 // (edges_are_unsorted_multi_pass) used to indicate that the edge list passed
84 // into the CSR graph is not sorted by source vertex.  This version uses less
85 // memory but requires multi-pass capability on the iterators.
86 enum edges_are_unsorted_multi_pass_t
87 {
88     edges_are_unsorted_multi_pass
89 };
90 
91 // A type (edges_are_unsorted_multi_pass_global_t) and a value
92 // (edges_are_unsorted_multi_pass_global) used to indicate that the edge list
93 // passed into the CSR graph is not sorted by source vertex.  This version uses
94 // less memory but requires multi-pass capability on the iterators.  The
95 // global mapping and filtering is done here because it is often faster and it
96 // greatly simplifies handling of edge properties.
97 enum edges_are_unsorted_multi_pass_global_t
98 {
99     edges_are_unsorted_multi_pass_global
100 };
101 
102 // A type (construct_inplace_from_sources_and_targets_t) and a value
103 // (construct_inplace_from_sources_and_targets) used to indicate that mutable
104 // vectors of sources and targets (and possibly edge properties) are being used
105 // to construct the CSR graph.  These vectors are sorted in-place and then the
106 // targets and properties are swapped into the graph data structure.
107 enum construct_inplace_from_sources_and_targets_t
108 {
109     construct_inplace_from_sources_and_targets
110 };
111 
112 // A type (construct_inplace_from_sources_and_targets_global_t) and a value
113 // (construct_inplace_from_sources_and_targets_global) used to indicate that
114 // mutable vectors of sources and targets (and possibly edge properties) are
115 // being used to construct the CSR graph.  These vectors are sorted in-place
116 // and then the targets and properties are swapped into the graph data
117 // structure.  It is assumed that global indices (for distributed CSR) are
118 // used, and a map is required to convert those to local indices.  This
119 // constructor is intended for internal use by the various CSR graphs
120 // (sequential and distributed).
121 enum construct_inplace_from_sources_and_targets_global_t
122 {
123     construct_inplace_from_sources_and_targets_global
124 };
125 
126 // A type (edges_are_unsorted_global_t) and a value (edges_are_unsorted_global)
127 // used to indicate that the edge list passed into the CSR graph is not sorted
128 // by source vertex.  The data is also stored using global vertex indices, and
129 // must be filtered to choose only local vertices.  This constructor caches the
130 // edge information in memory, and thus requires only a single pass over the
131 // input data.  This constructor is intended for internal use by the
132 // distributed CSR constructors.
133 enum edges_are_unsorted_global_t
134 {
135     edges_are_unsorted_global
136 };
137 
138 /****************************************************************************
139  * Local helper macros to reduce typing and clutter later on.               *
140  ****************************************************************************/
141 #define BOOST_CSR_GRAPH_TEMPLATE_PARMS                                 \
142     typename Directed, typename VertexProperty, typename EdgeProperty, \
143         typename GraphProperty, typename Vertex, typename EdgeIndex
144 #define BOOST_CSR_GRAPH_TYPE                                             \
145     compressed_sparse_row_graph< Directed, VertexProperty, EdgeProperty, \
146         GraphProperty, Vertex, EdgeIndex >
147 #define BOOST_DIR_CSR_GRAPH_TEMPLATE_PARMS                                  \
148     typename VertexProperty, typename EdgeProperty, typename GraphProperty, \
149         typename Vertex, typename EdgeIndex
150 #define BOOST_DIR_CSR_GRAPH_TYPE                                          \
151     compressed_sparse_row_graph< directedS, VertexProperty, EdgeProperty, \
152         GraphProperty, Vertex, EdgeIndex >
153 #define BOOST_BIDIR_CSR_GRAPH_TEMPLATE_PARMS                                \
154     typename VertexProperty, typename EdgeProperty, typename GraphProperty, \
155         typename Vertex, typename EdgeIndex
156 #define BOOST_BIDIR_CSR_GRAPH_TYPE                                             \
157     compressed_sparse_row_graph< bidirectionalS, VertexProperty, EdgeProperty, \
158         GraphProperty, Vertex, EdgeIndex >
159 
160 namespace detail
161 {
162     template < typename T >
163     struct default_construct_iterator
164     : public boost::iterator_facade< default_construct_iterator< T >, T,
165           boost::random_access_traversal_tag, const T& >
166     {
167         typedef boost::iterator_facade< default_construct_iterator< T >, T,
168             std::random_access_iterator_tag, const T& >
169             base_type;
170         T saved_value;
dereferenceboost::detail::default_construct_iterator171         const T& dereference() const { return saved_value; }
equalboost::detail::default_construct_iterator172         bool equal(default_construct_iterator /*i*/) const { return true; }
incrementboost::detail::default_construct_iterator173         void increment() {}
decrementboost::detail::default_construct_iterator174         void decrement() {}
advanceboost::detail::default_construct_iterator175         void advance(typename base_type::difference_type) {}
distance_toboost::detail::default_construct_iterator176         typename base_type::difference_type distance_to(
177             default_construct_iterator) const
178         {
179             return 0;
180         }
181     };
182 
183     template < typename Less > struct compare_first
184     {
185         Less less;
compare_firstboost::detail::compare_first186         compare_first(Less less = Less()) : less(less) {}
187         template < typename Tuple >
operator ()boost::detail::compare_first188         bool operator()(const Tuple& a, const Tuple& b) const
189         {
190             return less(a.template get< 0 >(), b.template get< 0 >());
191         }
192     };
193 
194     template < int N, typename Result > struct my_tuple_get_class
195     {
196         typedef const Result& result_type;
operator ()boost::detail::my_tuple_get_class197         template < typename Tuple > result_type operator()(const Tuple& t) const
198         {
199             return t.template get< N >();
200         }
201     };
202 }
203 
204 /** Compressed sparse row graph.
205  *
206  * Vertex and EdgeIndex should be unsigned integral types and should
207  * specialize numeric_limits.
208  */
209 template < typename Directed = directedS, typename VertexProperty = no_property,
210     typename EdgeProperty = no_property, typename GraphProperty = no_property,
211     typename Vertex = std::size_t,
212     typename EdgeIndex = Vertex >
213 class compressed_sparse_row_graph; // Not defined
214 
215 template < typename VertexProperty, typename EdgeProperty,
216     typename GraphProperty, typename Vertex, typename EdgeIndex >
217 class compressed_sparse_row_graph< directedS, VertexProperty, EdgeProperty,
218     GraphProperty, Vertex, EdgeIndex >
219 : public detail::indexed_vertex_properties< BOOST_DIR_CSR_GRAPH_TYPE,
220       VertexProperty, Vertex, typed_identity_property_map< Vertex > >
221 {
222 public:
223     typedef detail::indexed_vertex_properties< compressed_sparse_row_graph,
224         VertexProperty, Vertex, typed_identity_property_map< Vertex > >
225         inherited_vertex_properties;
226 
227     // Some tests to prevent use of "void" is a property type (as was done in
228     // some test cases):
229     BOOST_STATIC_ASSERT((!is_same< VertexProperty, void >::value));
230     BOOST_STATIC_ASSERT((!is_same< EdgeProperty, void >::value));
231     BOOST_STATIC_ASSERT((!is_same< GraphProperty, void >::value));
232 
233 public:
234     // For Property Graph
235     typedef GraphProperty graph_property_type;
236     typedef typename lookup_one_property< GraphProperty, graph_bundle_t >::type
237         graph_bundled;
238 
239     typedef detail::compressed_sparse_row_structure< EdgeProperty, Vertex,
240         EdgeIndex >
241         forward_type;
242 
243 public:
244     /* At this time, the compressed sparse row graph can only be used to
245      * create directed and bidirectional graphs. In the future,
246      * undirected CSR graphs will also be supported.
247      */
248     // BOOST_STATIC_ASSERT((is_same<Directed, directedS>::value));
249 
250     // Concept requirements:
251     // For Graph
252     typedef Vertex vertex_descriptor;
253     typedef detail::csr_edge_descriptor< Vertex, EdgeIndex > edge_descriptor;
254     typedef directed_tag directed_category;
255     typedef allow_parallel_edge_tag edge_parallel_category;
256 
257     class traversal_category : public incidence_graph_tag,
258                                public adjacency_graph_tag,
259                                public vertex_list_graph_tag,
260                                public edge_list_graph_tag
261     {
262     };
263 
null_vertex()264     static vertex_descriptor null_vertex() { return vertex_descriptor(-1); }
265 
266     // For VertexListGraph
267     typedef counting_iterator< Vertex > vertex_iterator;
268     typedef Vertex vertices_size_type;
269 
270     // For EdgeListGraph
271     typedef EdgeIndex edges_size_type;
272 
273     // For IncidenceGraph
274     typedef detail::csr_out_edge_iterator< compressed_sparse_row_graph >
275         out_edge_iterator;
276     typedef EdgeIndex degree_size_type;
277 
278     // For AdjacencyGraph
279     typedef typename std::vector< Vertex >::const_iterator adjacency_iterator;
280 
281     // For EdgeListGraph
282     typedef detail::csr_edge_iterator< compressed_sparse_row_graph >
283         edge_iterator;
284 
285     // For BidirectionalGraph (not implemented)
286     typedef void in_edge_iterator;
287 
288     // For internal use
289     typedef csr_graph_tag graph_tag;
290 
291     typedef typename forward_type::inherited_edge_properties::edge_bundled
292         edge_bundled;
293     typedef
294         typename forward_type::inherited_edge_properties::edge_push_back_type
295             edge_push_back_type;
296     typedef typename forward_type::inherited_edge_properties::edge_property_type
297         edge_property_type;
298 
299     // Constructors
300 
301     // Default constructor: an empty graph.
compressed_sparse_row_graph()302     compressed_sparse_row_graph() : m_property() {}
303 
304     //  With numverts vertices
compressed_sparse_row_graph(vertices_size_type numverts)305     compressed_sparse_row_graph(vertices_size_type numverts)
306     : inherited_vertex_properties(numverts), m_forward(numverts)
307     {
308     }
309 
310     //  From number of vertices and unsorted list of edges
311     template < typename MultiPassInputIterator >
compressed_sparse_row_graph(edges_are_unsorted_multi_pass_t,MultiPassInputIterator edge_begin,MultiPassInputIterator edge_end,vertices_size_type numverts,const GraphProperty & prop=GraphProperty ())312     compressed_sparse_row_graph(edges_are_unsorted_multi_pass_t,
313         MultiPassInputIterator edge_begin, MultiPassInputIterator edge_end,
314         vertices_size_type numverts,
315         const GraphProperty& prop = GraphProperty())
316     : inherited_vertex_properties(numverts), m_property(prop)
317     {
318         m_forward.assign_unsorted_multi_pass_edges(edge_begin, edge_end,
319             numverts, typed_identity_property_map< vertices_size_type >(),
320             keep_all());
321     }
322 
323     //  From number of vertices and unsorted list of edges, plus edge properties
324     template < typename MultiPassInputIterator, typename EdgePropertyIterator >
compressed_sparse_row_graph(edges_are_unsorted_multi_pass_t,MultiPassInputIterator edge_begin,MultiPassInputIterator edge_end,EdgePropertyIterator ep_iter,vertices_size_type numverts,const GraphProperty & prop=GraphProperty ())325     compressed_sparse_row_graph(edges_are_unsorted_multi_pass_t,
326         MultiPassInputIterator edge_begin, MultiPassInputIterator edge_end,
327         EdgePropertyIterator ep_iter, vertices_size_type numverts,
328         const GraphProperty& prop = GraphProperty())
329     : inherited_vertex_properties(numverts), m_forward(), m_property(prop)
330     {
331         m_forward.assign_unsorted_multi_pass_edges(edge_begin, edge_end,
332             ep_iter, numverts,
333             typed_identity_property_map< vertices_size_type >(), keep_all());
334     }
335 
336     //  From number of vertices and unsorted list of edges, with filter and
337     //  global-to-local map
338     template < typename MultiPassInputIterator, typename GlobalToLocal,
339         typename SourcePred >
compressed_sparse_row_graph(edges_are_unsorted_multi_pass_global_t,MultiPassInputIterator edge_begin,MultiPassInputIterator edge_end,vertices_size_type numlocalverts,const GlobalToLocal & global_to_local,const SourcePred & source_pred,const GraphProperty & prop=GraphProperty ())340     compressed_sparse_row_graph(edges_are_unsorted_multi_pass_global_t,
341         MultiPassInputIterator edge_begin, MultiPassInputIterator edge_end,
342         vertices_size_type numlocalverts, const GlobalToLocal& global_to_local,
343         const SourcePred& source_pred,
344         const GraphProperty& prop = GraphProperty())
345     : inherited_vertex_properties(numlocalverts), m_forward(), m_property(prop)
346     {
347         m_forward.assign_unsorted_multi_pass_edges(
348             edge_begin, edge_end, numlocalverts, global_to_local, source_pred);
349     }
350 
351     //  From number of vertices and unsorted list of edges, plus edge
352     //  properties, with filter and global-to-local map
353     template < typename MultiPassInputIterator, typename EdgePropertyIterator,
354         typename GlobalToLocal, typename SourcePred >
compressed_sparse_row_graph(edges_are_unsorted_multi_pass_global_t,MultiPassInputIterator edge_begin,MultiPassInputIterator edge_end,EdgePropertyIterator ep_iter,vertices_size_type numlocalverts,const GlobalToLocal & global_to_local,const SourcePred & source_pred,const GraphProperty & prop=GraphProperty ())355     compressed_sparse_row_graph(edges_are_unsorted_multi_pass_global_t,
356         MultiPassInputIterator edge_begin, MultiPassInputIterator edge_end,
357         EdgePropertyIterator ep_iter, vertices_size_type numlocalverts,
358         const GlobalToLocal& global_to_local, const SourcePred& source_pred,
359         const GraphProperty& prop = GraphProperty())
360     : inherited_vertex_properties(numlocalverts), m_forward(), m_property(prop)
361     {
362         m_forward.assign_unsorted_multi_pass_edges(edge_begin, edge_end,
363             ep_iter, numlocalverts, global_to_local, source_pred);
364     }
365 
366     //  From number of vertices and sorted list of edges (new interface)
367     template < typename InputIterator >
compressed_sparse_row_graph(edges_are_sorted_t,InputIterator edge_begin,InputIterator edge_end,vertices_size_type numverts,edges_size_type numedges=0,const GraphProperty & prop=GraphProperty ())368     compressed_sparse_row_graph(edges_are_sorted_t, InputIterator edge_begin,
369         InputIterator edge_end, vertices_size_type numverts,
370         edges_size_type numedges = 0,
371         const GraphProperty& prop = GraphProperty())
372     : m_property(prop)
373     {
374         m_forward.assign_from_sorted_edges(edge_begin, edge_end,
375             typed_identity_property_map< vertices_size_type >(), keep_all(),
376             numverts, numedges);
377         inherited_vertex_properties::resize(numverts);
378     }
379 
380     //  From number of vertices and sorted list of edges (new interface)
381     template < typename InputIterator, typename EdgePropertyIterator >
compressed_sparse_row_graph(edges_are_sorted_t,InputIterator edge_begin,InputIterator edge_end,EdgePropertyIterator ep_iter,vertices_size_type numverts,edges_size_type numedges=0,const GraphProperty & prop=GraphProperty ())382     compressed_sparse_row_graph(edges_are_sorted_t, InputIterator edge_begin,
383         InputIterator edge_end, EdgePropertyIterator ep_iter,
384         vertices_size_type numverts, edges_size_type numedges = 0,
385         const GraphProperty& prop = GraphProperty())
386     : m_property(prop)
387     {
388         m_forward.assign_from_sorted_edges(edge_begin, edge_end, ep_iter,
389             typed_identity_property_map< vertices_size_type >(), keep_all(),
390             numverts, numedges);
391         inherited_vertex_properties::resize(numverts);
392     }
393 
394     //  From number of vertices and sorted list of edges, filtered and global
395     //  (new interface)
396     template < typename InputIterator, typename GlobalToLocal,
397         typename SourcePred >
compressed_sparse_row_graph(edges_are_sorted_global_t,InputIterator edge_begin,InputIterator edge_end,const GlobalToLocal & global_to_local,const SourcePred & source_pred,vertices_size_type numverts,const GraphProperty & prop=GraphProperty ())398     compressed_sparse_row_graph(edges_are_sorted_global_t,
399         InputIterator edge_begin, InputIterator edge_end,
400         const GlobalToLocal& global_to_local, const SourcePred& source_pred,
401         vertices_size_type numverts,
402         const GraphProperty& prop = GraphProperty())
403     : m_property(prop)
404     {
405         m_forward.assign_from_sorted_edges(
406             edge_begin, edge_end, global_to_local, source_pred, numverts, 0);
407         inherited_vertex_properties::resize(numverts);
408     }
409 
410     //  From number of vertices and sorted list of edges (new interface)
411     template < typename InputIterator, typename EdgePropertyIterator,
412         typename GlobalToLocal, typename SourcePred >
compressed_sparse_row_graph(edges_are_sorted_global_t,InputIterator edge_begin,InputIterator edge_end,EdgePropertyIterator ep_iter,const GlobalToLocal & global_to_local,const SourcePred & source_pred,vertices_size_type numverts,const GraphProperty & prop=GraphProperty ())413     compressed_sparse_row_graph(edges_are_sorted_global_t,
414         InputIterator edge_begin, InputIterator edge_end,
415         EdgePropertyIterator ep_iter, const GlobalToLocal& global_to_local,
416         const SourcePred& source_pred, vertices_size_type numverts,
417         const GraphProperty& prop = GraphProperty())
418     : m_property(prop)
419     {
420         m_forward.assign_from_sorted_edges(edge_begin, edge_end, ep_iter,
421             global_to_local, source_pred, numverts, 0);
422         inherited_vertex_properties::resize(numverts);
423     }
424 
425     //  From number of vertices and mutable vectors of sources and targets;
426     //  vectors are returned with unspecified contents but are guaranteed not to
427     //  share storage with the constructed graph.
compressed_sparse_row_graph(construct_inplace_from_sources_and_targets_t,std::vector<vertex_descriptor> & sources,std::vector<vertex_descriptor> & targets,vertices_size_type numverts,const GraphProperty & prop=GraphProperty ())428     compressed_sparse_row_graph(construct_inplace_from_sources_and_targets_t,
429         std::vector< vertex_descriptor >& sources,
430         std::vector< vertex_descriptor >& targets, vertices_size_type numverts,
431         const GraphProperty& prop = GraphProperty())
432     : inherited_vertex_properties(numverts), m_property(prop)
433     {
434         m_forward.assign_sources_and_targets_global(sources, targets, numverts,
435             boost::typed_identity_property_map< vertices_size_type >());
436     }
437 
438     //  From number of vertices and mutable vectors of sources and targets,
439     //  expressed with global vertex indices; vectors are returned with
440     //  unspecified contents but are guaranteed not to share storage with the
441     //  constructed graph.  This constructor should only be used by the
442     //  distributed CSR graph.
443     template < typename GlobalToLocal >
compressed_sparse_row_graph(construct_inplace_from_sources_and_targets_global_t,std::vector<vertex_descriptor> & sources,std::vector<vertex_descriptor> & targets,vertices_size_type numlocalverts,GlobalToLocal global_to_local,const GraphProperty & prop=GraphProperty ())444     compressed_sparse_row_graph(
445         construct_inplace_from_sources_and_targets_global_t,
446         std::vector< vertex_descriptor >& sources,
447         std::vector< vertex_descriptor >& targets,
448         vertices_size_type numlocalverts, GlobalToLocal global_to_local,
449         const GraphProperty& prop = GraphProperty())
450     : inherited_vertex_properties(numlocalverts), m_property(prop)
451     {
452         m_forward.assign_sources_and_targets_global(
453             sources, targets, numlocalverts, global_to_local);
454     }
455 
456     //  From number of vertices and mutable vectors of sources, targets, and
457     //  edge properties; vectors are returned with unspecified contents but are
458     //  guaranteed not to share storage with the constructed graph.
compressed_sparse_row_graph(construct_inplace_from_sources_and_targets_t,std::vector<vertex_descriptor> & sources,std::vector<vertex_descriptor> & targets,std::vector<typename forward_type::inherited_edge_properties::edge_bundled> & edge_props,vertices_size_type numverts,const GraphProperty & prop=GraphProperty ())459     compressed_sparse_row_graph(construct_inplace_from_sources_and_targets_t,
460         std::vector< vertex_descriptor >& sources,
461         std::vector< vertex_descriptor >& targets,
462         std::vector<
463             typename forward_type::inherited_edge_properties::edge_bundled >&
464             edge_props,
465         vertices_size_type numverts,
466         const GraphProperty& prop = GraphProperty())
467     : inherited_vertex_properties(numverts), m_property(prop)
468     {
469         m_forward.assign_sources_and_targets_global(sources, targets,
470             edge_props, numverts,
471             boost::typed_identity_property_map< vertices_size_type >());
472     }
473 
474     //  From number of vertices and mutable vectors of sources and targets and
475     //  edge properties, expressed with global vertex indices; vectors are
476     //  returned with unspecified contents but are guaranteed not to share
477     //  storage with the constructed graph.  This constructor should only be
478     //  used by the distributed CSR graph.
479     template < typename GlobalToLocal >
compressed_sparse_row_graph(construct_inplace_from_sources_and_targets_global_t,std::vector<vertex_descriptor> & sources,std::vector<vertex_descriptor> & targets,std::vector<typename forward_type::inherited_edge_properties::edge_bundled> & edge_props,vertices_size_type numlocalverts,GlobalToLocal global_to_local,const GraphProperty & prop=GraphProperty ())480     compressed_sparse_row_graph(
481         construct_inplace_from_sources_and_targets_global_t,
482         std::vector< vertex_descriptor >& sources,
483         std::vector< vertex_descriptor >& targets,
484         std::vector<
485             typename forward_type::inherited_edge_properties::edge_bundled >&
486             edge_props,
487         vertices_size_type numlocalverts, GlobalToLocal global_to_local,
488         const GraphProperty& prop = GraphProperty())
489     : inherited_vertex_properties(numlocalverts), m_property(prop)
490     {
491         m_forward.assign_sources_and_targets_global(
492             sources, targets, edge_props, numlocalverts, global_to_local);
493     }
494 
495     //  From number of vertices and single-pass range of unsorted edges.  Data
496     //  is cached in coordinate form before creating the actual graph.
497     template < typename InputIterator >
compressed_sparse_row_graph(edges_are_unsorted_t,InputIterator edge_begin,InputIterator edge_end,vertices_size_type numverts,const GraphProperty & prop=GraphProperty ())498     compressed_sparse_row_graph(edges_are_unsorted_t, InputIterator edge_begin,
499         InputIterator edge_end, vertices_size_type numverts,
500         const GraphProperty& prop = GraphProperty())
501     : inherited_vertex_properties(numverts), m_property(prop)
502     {
503         std::vector< vertex_descriptor > sources, targets;
504         boost::graph::detail::split_into_separate_coords(
505             edge_begin, edge_end, sources, targets);
506         m_forward.assign_sources_and_targets_global(sources, targets, numverts,
507             boost::typed_identity_property_map< vertices_size_type >());
508     }
509 
510     //  From number of vertices and single-pass range of unsorted edges and
511     //  single-pass range of edge properties.  Data is cached in coordinate form
512     //  before creating the actual graph.
513     template < typename InputIterator, typename EdgePropertyIterator >
compressed_sparse_row_graph(edges_are_unsorted_t,InputIterator edge_begin,InputIterator edge_end,EdgePropertyIterator ep_iter,vertices_size_type numverts,const GraphProperty & prop=GraphProperty ())514     compressed_sparse_row_graph(edges_are_unsorted_t, InputIterator edge_begin,
515         InputIterator edge_end, EdgePropertyIterator ep_iter,
516         vertices_size_type numverts,
517         const GraphProperty& prop = GraphProperty())
518     : inherited_vertex_properties(numverts), m_property(prop)
519     {
520         std::vector< vertex_descriptor > sources, targets;
521         boost::graph::detail::split_into_separate_coords(
522             edge_begin, edge_end, sources, targets);
523         size_t numedges = sources.size();
524         std::vector<
525             typename forward_type::inherited_edge_properties::edge_bundled >
526             edge_props(numedges);
527         for (size_t i = 0; i < numedges; ++i)
528         {
529             edge_props[i] = *ep_iter++;
530         }
531         m_forward.assign_sources_and_targets_global(sources, targets,
532             edge_props, numverts,
533             boost::typed_identity_property_map< vertices_size_type >());
534     }
535 
536     //  From number of vertices and single-pass range of unsorted edges.  Data
537     //  is cached in coordinate form before creating the actual graph.  Edges
538     //  are filtered and transformed for use in a distributed graph.
539     template < typename InputIterator, typename GlobalToLocal,
540         typename SourcePred >
compressed_sparse_row_graph(edges_are_unsorted_global_t,InputIterator edge_begin,InputIterator edge_end,vertices_size_type numlocalverts,GlobalToLocal global_to_local,const SourcePred & source_pred,const GraphProperty & prop=GraphProperty ())541     compressed_sparse_row_graph(edges_are_unsorted_global_t,
542         InputIterator edge_begin, InputIterator edge_end,
543         vertices_size_type numlocalverts, GlobalToLocal global_to_local,
544         const SourcePred& source_pred,
545         const GraphProperty& prop = GraphProperty())
546     : inherited_vertex_properties(numlocalverts), m_property(prop)
547     {
548         std::vector< vertex_descriptor > sources, targets;
549         boost::graph::detail::split_into_separate_coords_filtered(
550             edge_begin, edge_end, sources, targets, source_pred);
551         m_forward.assign_sources_and_targets_global(
552             sources, targets, numlocalverts, global_to_local);
553     }
554 
555     //  From number of vertices and single-pass range of unsorted edges and
556     //  single-pass range of edge properties.  Data is cached in coordinate form
557     //  before creating the actual graph.  Edges are filtered and transformed
558     //  for use in a distributed graph.
559     template < typename InputIterator, typename EdgePropertyIterator,
560         typename GlobalToLocal, typename SourcePred >
compressed_sparse_row_graph(edges_are_unsorted_global_t,InputIterator edge_begin,InputIterator edge_end,EdgePropertyIterator ep_iter,vertices_size_type numlocalverts,GlobalToLocal global_to_local,const SourcePred & source_pred,const GraphProperty & prop=GraphProperty ())561     compressed_sparse_row_graph(edges_are_unsorted_global_t,
562         InputIterator edge_begin, InputIterator edge_end,
563         EdgePropertyIterator ep_iter, vertices_size_type numlocalverts,
564         GlobalToLocal global_to_local, const SourcePred& source_pred,
565         const GraphProperty& prop = GraphProperty())
566     : inherited_vertex_properties(numlocalverts), m_property(prop)
567     {
568         std::vector< vertex_descriptor > sources, targets;
569         std::vector< edge_bundled > edge_props;
570         boost::graph::detail::split_into_separate_coords_filtered(edge_begin,
571             edge_end, ep_iter, sources, targets, edge_props, source_pred);
572         m_forward.assign_sources_and_targets_global(
573             sources, targets, edge_props, numlocalverts, global_to_local);
574     }
575 
576     //   Requires IncidenceGraph and a vertex index map
577     template < typename Graph, typename VertexIndexMap >
compressed_sparse_row_graph(const Graph & g,const VertexIndexMap & vi,vertices_size_type numverts,edges_size_type numedges)578     compressed_sparse_row_graph(const Graph& g, const VertexIndexMap& vi,
579         vertices_size_type numverts, edges_size_type numedges)
580     : m_property()
581     {
582         assign(g, vi, numverts, numedges);
583         inherited_vertex_properties::resize(numverts);
584     }
585 
586     //   Requires VertexListGraph and EdgeListGraph
587     template < typename Graph, typename VertexIndexMap >
compressed_sparse_row_graph(const Graph & g,const VertexIndexMap & vi)588     compressed_sparse_row_graph(const Graph& g, const VertexIndexMap& vi)
589     : m_property()
590     {
591         typename graph_traits< Graph >::edges_size_type numedges = num_edges(g);
592         if (is_same< typename graph_traits< Graph >::directed_category,
593                 undirectedS >::value)
594         {
595             numedges *= 2; // Double each edge (actual doubling done by
596                            // out_edges function)
597         }
598         vertices_size_type numverts = num_vertices(g);
599         assign(g, vi, numverts, numedges);
600         inherited_vertex_properties::resize(numverts);
601     }
602 
603     // Requires vertex index map plus requirements of previous constructor
604     template < typename Graph >
compressed_sparse_row_graph(const Graph & g)605     explicit compressed_sparse_row_graph(const Graph& g) : m_property()
606     {
607         typename graph_traits< Graph >::edges_size_type numedges = num_edges(g);
608         if (is_same< typename graph_traits< Graph >::directed_category,
609                 undirectedS >::value)
610         {
611             numedges *= 2; // Double each edge (actual doubling done by
612                            // out_edges function)
613         }
614         assign(g, get(vertex_index, g), num_vertices(g), numedges);
615     }
616 
617     // From any graph (slow and uses a lot of memory)
618     //   Requires IncidenceGraph and a vertex index map
619     //   Internal helper function
620     //   Note that numedges must be doubled for undirected source graphs
621     template < typename Graph, typename VertexIndexMap >
assign(const Graph & g,const VertexIndexMap & vi,vertices_size_type numverts,edges_size_type numedges)622     void assign(const Graph& g, const VertexIndexMap& vi,
623         vertices_size_type numverts, edges_size_type numedges)
624     {
625         m_forward.assign(g, vi, numverts, numedges);
626         inherited_vertex_properties::resize(numverts);
627     }
628 
629     // Requires the above, plus VertexListGraph and EdgeListGraph
630     template < typename Graph, typename VertexIndexMap >
assign(const Graph & g,const VertexIndexMap & vi)631     void assign(const Graph& g, const VertexIndexMap& vi)
632     {
633         typename graph_traits< Graph >::edges_size_type numedges = num_edges(g);
634         if (is_same< typename graph_traits< Graph >::directed_category,
635                 undirectedS >::value)
636         {
637             numedges *= 2; // Double each edge (actual doubling done by
638                            // out_edges function)
639         }
640         vertices_size_type numverts = num_vertices(g);
641         m_forward.assign(g, vi, numverts, numedges);
642         inherited_vertex_properties::resize(numverts);
643     }
644 
645     // Requires the above, plus a vertex_index map.
assign(const Graph & g)646     template < typename Graph > void assign(const Graph& g)
647     {
648         typename graph_traits< Graph >::edges_size_type numedges = num_edges(g);
649         if (is_same< typename graph_traits< Graph >::directed_category,
650                 undirectedS >::value)
651         {
652             numedges *= 2; // Double each edge (actual doubling done by
653                            // out_edges function)
654         }
655         vertices_size_type numverts = num_vertices(g);
656         m_forward.assign(g, get(vertex_index, g), numverts, numedges);
657         inherited_vertex_properties::resize(numverts);
658     }
659 
660     // Add edges from a sorted (smallest sources first) range of pairs and edge
661     // properties
662     template < typename BidirectionalIteratorOrig, typename EPIterOrig,
663         typename GlobalToLocal >
add_edges_sorted_internal(BidirectionalIteratorOrig first_sorted,BidirectionalIteratorOrig last_sorted,EPIterOrig ep_iter_sorted,const GlobalToLocal & global_to_local)664     void add_edges_sorted_internal(BidirectionalIteratorOrig first_sorted,
665         BidirectionalIteratorOrig last_sorted, EPIterOrig ep_iter_sorted,
666         const GlobalToLocal& global_to_local)
667     {
668         m_forward.add_edges_sorted_internal(
669             first_sorted, last_sorted, ep_iter_sorted, global_to_local);
670     }
671 
672     template < typename BidirectionalIteratorOrig, typename EPIterOrig >
add_edges_sorted_internal(BidirectionalIteratorOrig first_sorted,BidirectionalIteratorOrig last_sorted,EPIterOrig ep_iter_sorted)673     void add_edges_sorted_internal(BidirectionalIteratorOrig first_sorted,
674         BidirectionalIteratorOrig last_sorted, EPIterOrig ep_iter_sorted)
675     {
676         m_forward.add_edges_sorted_internal(first_sorted, last_sorted,
677             ep_iter_sorted,
678             typed_identity_property_map< vertices_size_type >());
679     }
680 
681     // Add edges from a sorted (smallest sources first) range of pairs
682     template < typename BidirectionalIteratorOrig >
add_edges_sorted_internal(BidirectionalIteratorOrig first_sorted,BidirectionalIteratorOrig last_sorted)683     void add_edges_sorted_internal(BidirectionalIteratorOrig first_sorted,
684         BidirectionalIteratorOrig last_sorted)
685     {
686         m_forward.add_edges_sorted_internal(first_sorted, last_sorted,
687             detail::default_construct_iterator< edge_bundled >());
688     }
689 
690     template < typename BidirectionalIteratorOrig, typename GlobalToLocal >
add_edges_sorted_internal_global(BidirectionalIteratorOrig first_sorted,BidirectionalIteratorOrig last_sorted,const GlobalToLocal & global_to_local)691     void add_edges_sorted_internal_global(
692         BidirectionalIteratorOrig first_sorted,
693         BidirectionalIteratorOrig last_sorted,
694         const GlobalToLocal& global_to_local)
695     {
696         m_forward.add_edges_sorted_internal(first_sorted, last_sorted,
697             detail::default_construct_iterator< edge_bundled >(),
698             global_to_local);
699     }
700 
701     template < typename BidirectionalIteratorOrig, typename EPIterOrig,
702         typename GlobalToLocal >
add_edges_sorted_internal_global(BidirectionalIteratorOrig first_sorted,BidirectionalIteratorOrig last_sorted,EPIterOrig ep_iter_sorted,const GlobalToLocal & global_to_local)703     void add_edges_sorted_internal_global(
704         BidirectionalIteratorOrig first_sorted,
705         BidirectionalIteratorOrig last_sorted, EPIterOrig ep_iter_sorted,
706         const GlobalToLocal& global_to_local)
707     {
708         m_forward.add_edges_sorted_internal(
709             first_sorted, last_sorted, ep_iter_sorted, global_to_local);
710     }
711 
712     // Add edges from a range of (source, target) pairs that are unsorted
713     template < typename InputIterator, typename GlobalToLocal >
add_edges_internal(InputIterator first,InputIterator last,const GlobalToLocal & global_to_local)714     inline void add_edges_internal(InputIterator first, InputIterator last,
715         const GlobalToLocal& global_to_local)
716     {
717         typedef compressed_sparse_row_graph Graph;
718         typedef
719             typename boost::graph_traits< Graph >::vertex_descriptor vertex_t;
720         typedef std::vector< std::pair< vertex_t, vertex_t > > edge_vector_t;
721         edge_vector_t new_edges(first, last);
722         if (new_edges.empty())
723             return;
724         std::sort(new_edges.begin(), new_edges.end());
725         this->add_edges_sorted_internal_global(
726             new_edges.begin(), new_edges.end(), global_to_local);
727     }
728 
729     template < typename InputIterator >
add_edges_internal(InputIterator first,InputIterator last)730     inline void add_edges_internal(InputIterator first, InputIterator last)
731     {
732         this->add_edges_internal(
733             first, last, typed_identity_property_map< vertices_size_type >());
734     }
735 
736     // Add edges from a range of (source, target) pairs and edge properties that
737     // are unsorted
738     template < typename InputIterator, typename EPIterator,
739         typename GlobalToLocal >
add_edges_internal(InputIterator first,InputIterator last,EPIterator ep_iter,EPIterator ep_iter_end,const GlobalToLocal & global_to_local)740     inline void add_edges_internal(InputIterator first, InputIterator last,
741         EPIterator ep_iter, EPIterator ep_iter_end,
742         const GlobalToLocal& global_to_local)
743     {
744         typedef compressed_sparse_row_graph Graph;
745         typedef
746             typename boost::graph_traits< Graph >::vertex_descriptor vertex_t;
747         typedef std::pair< vertex_t, vertex_t > vertex_pair;
748         typedef std::vector< boost::tuple< vertex_pair, edge_bundled > >
749             edge_vector_t;
750         edge_vector_t new_edges(
751             boost::make_zip_iterator(boost::make_tuple(first, ep_iter)),
752             boost::make_zip_iterator(boost::make_tuple(last, ep_iter_end)));
753         if (new_edges.empty())
754             return;
755         std::sort(new_edges.begin(), new_edges.end(),
756             boost::detail::compare_first< std::less< vertex_pair > >());
757         m_forward.add_edges_sorted_internal(
758             boost::make_transform_iterator(new_edges.begin(),
759                 boost::detail::my_tuple_get_class< 0, vertex_pair >()),
760             boost::make_transform_iterator(new_edges.end(),
761                 boost::detail::my_tuple_get_class< 0, vertex_pair >()),
762             boost::make_transform_iterator(new_edges.begin(),
763                 boost::detail::my_tuple_get_class< 1, edge_bundled >()),
764             global_to_local);
765     }
766 
767     // Add edges from a range of (source, target) pairs and edge properties that
768     // are unsorted
769     template < typename InputIterator, typename EPIterator >
add_edges_internal(InputIterator first,InputIterator last,EPIterator ep_iter,EPIterator ep_iter_end)770     inline void add_edges_internal(InputIterator first, InputIterator last,
771         EPIterator ep_iter, EPIterator ep_iter_end)
772     {
773         this->add_edges_internal(first, last, ep_iter, ep_iter_end,
774             typed_identity_property_map< vertices_size_type >());
775     }
776 
777     using inherited_vertex_properties::operator[];
778 
779     // Directly access a edge or edge bundle
operator [](const edge_descriptor & v)780     edge_push_back_type& operator[](const edge_descriptor& v)
781     {
782         return m_forward.m_edge_properties[get(edge_index, *this, v)];
783     }
784 
operator [](const edge_descriptor & v) const785     const edge_push_back_type& operator[](const edge_descriptor& v) const
786     {
787         return m_forward.m_edge_properties[get(edge_index, *this, v)];
788     }
789 
790     // Directly access a graph bundle
operator [](graph_bundle_t)791     graph_bundled& operator[](graph_bundle_t) { return get_property(*this); }
792 
operator [](graph_bundle_t) const793     const graph_bundled& operator[](graph_bundle_t) const
794     {
795         return get_property(*this);
796     }
797 
798     // private: non-portable, requires friend templates
vertex_properties()799     inherited_vertex_properties& vertex_properties() { return *this; }
vertex_properties() const800     const inherited_vertex_properties& vertex_properties() const
801     {
802         return *this;
803     }
edge_properties()804     typename forward_type::inherited_edge_properties& edge_properties()
805     {
806         return m_forward;
807     }
808     const typename forward_type::inherited_edge_properties&
edge_properties() const809     edge_properties() const
810     {
811         return m_forward;
812     }
813 
814     forward_type m_forward;
815     GraphProperty m_property;
816 };
817 
818 template < typename VertexProperty, typename EdgeProperty,
819     typename GraphProperty, typename Vertex, typename EdgeIndex >
820 class compressed_sparse_row_graph< bidirectionalS, VertexProperty, EdgeProperty,
821     GraphProperty, Vertex, EdgeIndex >
822 : public detail::indexed_vertex_properties< BOOST_BIDIR_CSR_GRAPH_TYPE,
823       VertexProperty, Vertex, typed_identity_property_map< Vertex > >
824 {
825 public:
826     typedef detail::indexed_vertex_properties< compressed_sparse_row_graph,
827         VertexProperty, Vertex, typed_identity_property_map< Vertex > >
828         inherited_vertex_properties;
829 
830 public:
831     // For Property Graph
832     typedef GraphProperty graph_property_type;
833     typedef typename lookup_one_property< GraphProperty, graph_bundle_t >::type
834         graph_bundled;
835     // typedef GraphProperty graph_property_type;
836 
837     typedef detail::compressed_sparse_row_structure< EdgeProperty, Vertex,
838         EdgeIndex >
839         forward_type;
840     typedef EdgeIndex /* typename boost::mpl::if_c<boost::is_same<EdgeProperty,
841                          boost::no_property>, boost::no_property, EdgeIndex> */
842         backward_edge_property;
843     typedef detail::compressed_sparse_row_structure< backward_edge_property,
844         Vertex, EdgeIndex >
845         backward_type;
846 
847 public:
848     // Concept requirements:
849     // For Graph
850     typedef Vertex vertex_descriptor;
851     typedef detail::csr_edge_descriptor< Vertex, EdgeIndex > edge_descriptor;
852     typedef bidirectional_tag directed_category;
853     typedef allow_parallel_edge_tag edge_parallel_category;
854 
855     class traversal_category : public bidirectional_graph_tag,
856                                public adjacency_graph_tag,
857                                public vertex_list_graph_tag,
858                                public edge_list_graph_tag
859     {
860     };
861 
null_vertex()862     static vertex_descriptor null_vertex() { return vertex_descriptor(-1); }
863 
864     // For VertexListGraph
865     typedef counting_iterator< Vertex > vertex_iterator;
866     typedef Vertex vertices_size_type;
867 
868     // For EdgeListGraph
869     typedef EdgeIndex edges_size_type;
870 
871     // For IncidenceGraph
872     typedef detail::csr_out_edge_iterator< compressed_sparse_row_graph >
873         out_edge_iterator;
874     typedef EdgeIndex degree_size_type;
875 
876     // For AdjacencyGraph
877     typedef typename std::vector< Vertex >::const_iterator adjacency_iterator;
878 
879     // For EdgeListGraph
880     typedef detail::csr_edge_iterator< compressed_sparse_row_graph >
881         edge_iterator;
882 
883     // For BidirectionalGraph (not implemented)
884     typedef detail::csr_in_edge_iterator< compressed_sparse_row_graph >
885         in_edge_iterator;
886 
887     // For internal use
888     typedef csr_graph_tag graph_tag;
889 
890     typedef typename forward_type::inherited_edge_properties::edge_bundled
891         edge_bundled;
892     typedef
893         typename forward_type::inherited_edge_properties::edge_push_back_type
894             edge_push_back_type;
895     typedef typename forward_type::inherited_edge_properties::edge_property_type
896         edge_property_type;
897 
898     // Constructors
899 
900     // Default constructor: an empty graph.
compressed_sparse_row_graph()901     compressed_sparse_row_graph() : m_property() {}
902 
903     //  With numverts vertices
compressed_sparse_row_graph(vertices_size_type numverts)904     compressed_sparse_row_graph(vertices_size_type numverts)
905     : inherited_vertex_properties(numverts)
906     , m_forward(numverts)
907     , m_backward(numverts)
908     {
909     }
910 
911 private:
set_up_backward_property_links()912     void set_up_backward_property_links()
913     {
914         std::pair< edge_iterator, edge_iterator > e = edges(*this);
915         m_backward.assign_unsorted_multi_pass_edges(
916             detail::transpose_edges(detail::make_edge_to_index_pair_iter(
917                 *this, get(vertex_index, *this), e.first)),
918             detail::transpose_edges(detail::make_edge_to_index_pair_iter(
919                 *this, get(vertex_index, *this), e.second)),
920             boost::counting_iterator< EdgeIndex >(0),
921             m_forward.m_rowstart.size() - 1,
922             typed_identity_property_map< Vertex >(), keep_all());
923     }
924 
925 public:
926     //  From number of vertices and unsorted list of edges
927     template < typename MultiPassInputIterator >
compressed_sparse_row_graph(edges_are_unsorted_multi_pass_t,MultiPassInputIterator edge_begin,MultiPassInputIterator edge_end,vertices_size_type numverts,const GraphProperty & prop=GraphProperty ())928     compressed_sparse_row_graph(edges_are_unsorted_multi_pass_t,
929         MultiPassInputIterator edge_begin, MultiPassInputIterator edge_end,
930         vertices_size_type numverts,
931         const GraphProperty& prop = GraphProperty())
932     : inherited_vertex_properties(numverts), m_property(prop)
933     {
934         m_forward.assign_unsorted_multi_pass_edges(edge_begin, edge_end,
935             numverts, typed_identity_property_map< Vertex >(), keep_all());
936         set_up_backward_property_links();
937     }
938 
939     //  From number of vertices and unsorted list of edges, plus edge properties
940     template < typename MultiPassInputIterator, typename EdgePropertyIterator >
compressed_sparse_row_graph(edges_are_unsorted_multi_pass_t,MultiPassInputIterator edge_begin,MultiPassInputIterator edge_end,EdgePropertyIterator ep_iter,vertices_size_type numverts,const GraphProperty & prop=GraphProperty ())941     compressed_sparse_row_graph(edges_are_unsorted_multi_pass_t,
942         MultiPassInputIterator edge_begin, MultiPassInputIterator edge_end,
943         EdgePropertyIterator ep_iter, vertices_size_type numverts,
944         const GraphProperty& prop = GraphProperty())
945     : inherited_vertex_properties(numverts), m_forward(), m_property(prop)
946     {
947         m_forward.assign_unsorted_multi_pass_edges(edge_begin, edge_end,
948             ep_iter, numverts, typed_identity_property_map< Vertex >(),
949             keep_all());
950         set_up_backward_property_links();
951     }
952 
953     //  From number of vertices and unsorted list of edges, with filter and
954     //  global-to-local map
955     template < typename MultiPassInputIterator, typename GlobalToLocal,
956         typename SourcePred >
compressed_sparse_row_graph(edges_are_unsorted_multi_pass_global_t,MultiPassInputIterator edge_begin,MultiPassInputIterator edge_end,vertices_size_type numlocalverts,const GlobalToLocal & global_to_local,const SourcePred & source_pred,const GraphProperty & prop=GraphProperty ())957     compressed_sparse_row_graph(edges_are_unsorted_multi_pass_global_t,
958         MultiPassInputIterator edge_begin, MultiPassInputIterator edge_end,
959         vertices_size_type numlocalverts, const GlobalToLocal& global_to_local,
960         const SourcePred& source_pred,
961         const GraphProperty& prop = GraphProperty())
962     : inherited_vertex_properties(numlocalverts), m_forward(), m_property(prop)
963     {
964         m_forward.assign_unsorted_multi_pass_edges(
965             edge_begin, edge_end, numlocalverts, global_to_local, source_pred);
966         set_up_backward_property_links();
967     }
968 
969     //  From number of vertices and unsorted list of edges, plus edge
970     //  properties, with filter and global-to-local map
971     template < typename MultiPassInputIterator, typename EdgePropertyIterator,
972         typename GlobalToLocal, typename SourcePred >
compressed_sparse_row_graph(edges_are_unsorted_multi_pass_global_t,MultiPassInputIterator edge_begin,MultiPassInputIterator edge_end,EdgePropertyIterator ep_iter,vertices_size_type numlocalverts,const GlobalToLocal & global_to_local,const SourcePred & source_pred,const GraphProperty & prop=GraphProperty ())973     compressed_sparse_row_graph(edges_are_unsorted_multi_pass_global_t,
974         MultiPassInputIterator edge_begin, MultiPassInputIterator edge_end,
975         EdgePropertyIterator ep_iter, vertices_size_type numlocalverts,
976         const GlobalToLocal& global_to_local, const SourcePred& source_pred,
977         const GraphProperty& prop = GraphProperty())
978     : inherited_vertex_properties(numlocalverts), m_forward(), m_property(prop)
979     {
980         m_forward.assign_unsorted_multi_pass_edges(edge_begin, edge_end,
981             ep_iter, numlocalverts, global_to_local, source_pred);
982         set_up_backward_property_links();
983     }
984 
985     //   Requires IncidenceGraph and a vertex index map
986     template < typename Graph, typename VertexIndexMap >
compressed_sparse_row_graph(const Graph & g,const VertexIndexMap & vi,vertices_size_type numverts,edges_size_type numedges)987     compressed_sparse_row_graph(const Graph& g, const VertexIndexMap& vi,
988         vertices_size_type numverts, edges_size_type numedges)
989     : m_property()
990     {
991         assign(g, vi, numverts, numedges);
992         inherited_vertex_properties::resize(numverts);
993     }
994 
995     //   Requires VertexListGraph and EdgeListGraph
996     template < typename Graph, typename VertexIndexMap >
compressed_sparse_row_graph(const Graph & g,const VertexIndexMap & vi)997     compressed_sparse_row_graph(const Graph& g, const VertexIndexMap& vi)
998     : m_property()
999     {
1000         typename graph_traits< Graph >::edges_size_type numedges = num_edges(g);
1001         if (is_same< typename graph_traits< Graph >::directed_category,
1002                 undirectedS >::value)
1003         {
1004             numedges *= 2; // Double each edge (actual doubling done by
1005                            // out_edges function)
1006         }
1007         vertices_size_type numverts = num_vertices(g);
1008         assign(g, vi, numverts, numedges);
1009         inherited_vertex_properties::resize(numverts);
1010     }
1011 
1012     // Requires vertex index map plus requirements of previous constructor
1013     template < typename Graph >
compressed_sparse_row_graph(const Graph & g)1014     explicit compressed_sparse_row_graph(const Graph& g) : m_property()
1015     {
1016         typename graph_traits< Graph >::edges_size_type numedges = num_edges(g);
1017         if (is_same< typename graph_traits< Graph >::directed_category,
1018                 undirectedS >::value)
1019         {
1020             numedges *= 2; // Double each edge (actual doubling done by
1021                            // out_edges function)
1022         }
1023         assign(g, get(vertex_index, g), num_vertices(g), numedges);
1024     }
1025 
1026     // From any graph (slow and uses a lot of memory)
1027     //   Requires IncidenceGraph and a vertex index map
1028     //   Internal helper function
1029     //   Note that numedges must be doubled for undirected source graphs
1030     template < typename Graph, typename VertexIndexMap >
assign(const Graph & g,const VertexIndexMap & vi,vertices_size_type numverts,edges_size_type numedges)1031     void assign(const Graph& g, const VertexIndexMap& vi,
1032         vertices_size_type numverts, edges_size_type numedges)
1033     {
1034         m_forward.assign(g, vi, numverts, numedges);
1035         inherited_vertex_properties::resize(numverts);
1036         set_up_backward_property_links();
1037     }
1038 
1039     // Requires the above, plus VertexListGraph and EdgeListGraph
1040     template < typename Graph, typename VertexIndexMap >
assign(const Graph & g,const VertexIndexMap & vi)1041     void assign(const Graph& g, const VertexIndexMap& vi)
1042     {
1043         typename graph_traits< Graph >::edges_size_type numedges = num_edges(g);
1044         if (is_same< typename graph_traits< Graph >::directed_category,
1045                 undirectedS >::value)
1046         {
1047             numedges *= 2; // Double each edge (actual doubling done by
1048                            // out_edges function)
1049         }
1050         vertices_size_type numverts = num_vertices(g);
1051         m_forward.assign(g, vi, numverts, numedges);
1052         inherited_vertex_properties::resize(numverts);
1053         set_up_backward_property_links();
1054     }
1055 
1056     // Requires the above, plus a vertex_index map.
assign(const Graph & g)1057     template < typename Graph > void assign(const Graph& g)
1058     {
1059         typename graph_traits< Graph >::edges_size_type numedges = num_edges(g);
1060         if (is_same< typename graph_traits< Graph >::directed_category,
1061                 undirectedS >::value)
1062         {
1063             numedges *= 2; // Double each edge (actual doubling done by
1064                            // out_edges function)
1065         }
1066         vertices_size_type numverts = num_vertices(g);
1067         m_forward.assign(g, get(vertex_index, g), numverts, numedges);
1068         inherited_vertex_properties::resize(numverts);
1069         set_up_backward_property_links();
1070     }
1071 
1072     using inherited_vertex_properties::operator[];
1073 
1074     // Directly access a edge or edge bundle
operator [](const edge_descriptor & v)1075     edge_push_back_type& operator[](const edge_descriptor& v)
1076     {
1077         return m_forward.m_edge_properties[get(edge_index, *this, v)];
1078     }
1079 
operator [](const edge_descriptor & v) const1080     const edge_push_back_type& operator[](const edge_descriptor& v) const
1081     {
1082         return m_forward.m_edge_properties[get(edge_index, *this, v)];
1083     }
1084 
1085     // private: non-portable, requires friend templates
vertex_properties()1086     inherited_vertex_properties& vertex_properties() { return *this; }
vertex_properties() const1087     const inherited_vertex_properties& vertex_properties() const
1088     {
1089         return *this;
1090     }
edge_properties()1091     typename forward_type::inherited_edge_properties& edge_properties()
1092     {
1093         return m_forward;
1094     }
1095     const typename forward_type::inherited_edge_properties&
edge_properties() const1096     edge_properties() const
1097     {
1098         return m_forward;
1099     }
1100 
1101     forward_type m_forward;
1102     backward_type m_backward;
1103     GraphProperty m_property;
1104 };
1105 
1106 // Construction functions
1107 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
add_vertex(BOOST_CSR_GRAPH_TYPE & g)1108 inline Vertex add_vertex(BOOST_CSR_GRAPH_TYPE& g)
1109 {
1110     add_vertex(g, typename BOOST_CSR_GRAPH_TYPE::vertex_bundled());
1111 }
1112 
1113 template < BOOST_DIR_CSR_GRAPH_TEMPLATE_PARMS >
add_vertex(BOOST_DIR_CSR_GRAPH_TYPE & g,typename BOOST_DIR_CSR_GRAPH_TYPE::vertex_bundled const & p)1114 inline Vertex add_vertex(BOOST_DIR_CSR_GRAPH_TYPE& g,
1115     typename BOOST_DIR_CSR_GRAPH_TYPE::vertex_bundled const& p)
1116 {
1117     Vertex old_num_verts_plus_one = g.m_forward.m_rowstart.size();
1118     g.m_forward.m_rowstart.push_back(g.m_forward.m_rowstart.back());
1119     g.vertex_properties().push_back(p);
1120     return old_num_verts_plus_one - 1;
1121 }
1122 
1123 template < BOOST_BIDIR_CSR_GRAPH_TEMPLATE_PARMS >
add_vertex(BOOST_BIDIR_CSR_GRAPH_TYPE & g,typename BOOST_BIDIR_CSR_GRAPH_TYPE::vertex_bundled const & p)1124 inline Vertex add_vertex(BOOST_BIDIR_CSR_GRAPH_TYPE& g,
1125     typename BOOST_BIDIR_CSR_GRAPH_TYPE::vertex_bundled const& p)
1126 {
1127     Vertex old_num_verts_plus_one = g.m_forward.m_rowstart.size();
1128     g.m_forward.m_rowstart.push_back(g.m_forward.m_rowstart.back());
1129     g.m_backward.m_rowstart.push_back(g.m_backward.m_rowstart.back());
1130     g.vertex_properties().push_back(p);
1131     return old_num_verts_plus_one - 1;
1132 }
1133 
1134 template < BOOST_DIR_CSR_GRAPH_TEMPLATE_PARMS >
add_vertices(typename BOOST_DIR_CSR_GRAPH_TYPE::vertices_size_type count,BOOST_DIR_CSR_GRAPH_TYPE & g)1135 inline Vertex add_vertices(
1136     typename BOOST_DIR_CSR_GRAPH_TYPE::vertices_size_type count,
1137     BOOST_DIR_CSR_GRAPH_TYPE& g)
1138 {
1139     Vertex old_num_verts_plus_one = g.m_forward.m_rowstart.size();
1140     EdgeIndex numedges = g.m_forward.m_rowstart.back();
1141     g.m_forward.m_rowstart.resize(old_num_verts_plus_one + count, numedges);
1142     g.vertex_properties().resize(num_vertices(g));
1143     return old_num_verts_plus_one - 1;
1144 }
1145 
1146 // Add edges from a sorted (smallest sources first) range of pairs and edge
1147 // properties
1148 template < BOOST_DIR_CSR_GRAPH_TEMPLATE_PARMS,
1149     typename BidirectionalIteratorOrig, typename EPIterOrig >
add_edges_sorted(BidirectionalIteratorOrig first_sorted,BidirectionalIteratorOrig last_sorted,EPIterOrig ep_iter_sorted,BOOST_DIR_CSR_GRAPH_TYPE & g)1150 void add_edges_sorted(BidirectionalIteratorOrig first_sorted,
1151     BidirectionalIteratorOrig last_sorted, EPIterOrig ep_iter_sorted,
1152     BOOST_DIR_CSR_GRAPH_TYPE& g)
1153 {
1154     g.add_edges_sorted_internal(first_sorted, last_sorted, ep_iter_sorted);
1155 }
1156 
1157 // Add edges from a sorted (smallest sources first) range of pairs
1158 template < BOOST_DIR_CSR_GRAPH_TEMPLATE_PARMS,
1159     typename BidirectionalIteratorOrig >
add_edges_sorted(BidirectionalIteratorOrig first_sorted,BidirectionalIteratorOrig last_sorted,BOOST_DIR_CSR_GRAPH_TYPE & g)1160 void add_edges_sorted(BidirectionalIteratorOrig first_sorted,
1161     BidirectionalIteratorOrig last_sorted, BOOST_DIR_CSR_GRAPH_TYPE& g)
1162 {
1163     g.add_edges_sorted_internal(first_sorted, last_sorted);
1164 }
1165 
1166 template < BOOST_DIR_CSR_GRAPH_TEMPLATE_PARMS,
1167     typename BidirectionalIteratorOrig, typename EPIterOrig,
1168     typename GlobalToLocal >
add_edges_sorted_global(BidirectionalIteratorOrig first_sorted,BidirectionalIteratorOrig last_sorted,EPIterOrig ep_iter_sorted,const GlobalToLocal & global_to_local,BOOST_DIR_CSR_GRAPH_TYPE & g)1169 void add_edges_sorted_global(BidirectionalIteratorOrig first_sorted,
1170     BidirectionalIteratorOrig last_sorted, EPIterOrig ep_iter_sorted,
1171     const GlobalToLocal& global_to_local, BOOST_DIR_CSR_GRAPH_TYPE& g)
1172 {
1173     g.add_edges_sorted_internal_global(
1174         first_sorted, last_sorted, ep_iter_sorted, global_to_local);
1175 }
1176 
1177 // Add edges from a sorted (smallest sources first) range of pairs
1178 template < BOOST_DIR_CSR_GRAPH_TEMPLATE_PARMS,
1179     typename BidirectionalIteratorOrig, typename GlobalToLocal >
add_edges_sorted_global(BidirectionalIteratorOrig first_sorted,BidirectionalIteratorOrig last_sorted,const GlobalToLocal & global_to_local,BOOST_DIR_CSR_GRAPH_TYPE & g)1180 void add_edges_sorted_global(BidirectionalIteratorOrig first_sorted,
1181     BidirectionalIteratorOrig last_sorted, const GlobalToLocal& global_to_local,
1182     BOOST_DIR_CSR_GRAPH_TYPE& g)
1183 {
1184     g.add_edges_sorted_internal_global(
1185         first_sorted, last_sorted, global_to_local);
1186 }
1187 
1188 // Add edges from a range of (source, target) pairs that are unsorted
1189 template < BOOST_DIR_CSR_GRAPH_TEMPLATE_PARMS, typename InputIterator,
1190     typename GlobalToLocal >
add_edges_global(InputIterator first,InputIterator last,const GlobalToLocal & global_to_local,BOOST_DIR_CSR_GRAPH_TYPE & g)1191 inline void add_edges_global(InputIterator first, InputIterator last,
1192     const GlobalToLocal& global_to_local, BOOST_DIR_CSR_GRAPH_TYPE& g)
1193 {
1194     g.add_edges_internal(first, last, global_to_local);
1195 }
1196 
1197 // Add edges from a range of (source, target) pairs that are unsorted
1198 template < BOOST_DIR_CSR_GRAPH_TEMPLATE_PARMS, typename InputIterator >
add_edges(InputIterator first,InputIterator last,BOOST_DIR_CSR_GRAPH_TYPE & g)1199 inline void add_edges(
1200     InputIterator first, InputIterator last, BOOST_DIR_CSR_GRAPH_TYPE& g)
1201 {
1202     g.add_edges_internal(first, last);
1203 }
1204 
1205 // Add edges from a range of (source, target) pairs and edge properties that
1206 // are unsorted
1207 template < BOOST_DIR_CSR_GRAPH_TEMPLATE_PARMS, typename InputIterator,
1208     typename EPIterator >
add_edges(InputIterator first,InputIterator last,EPIterator ep_iter,EPIterator ep_iter_end,BOOST_DIR_CSR_GRAPH_TYPE & g)1209 inline void add_edges(InputIterator first, InputIterator last,
1210     EPIterator ep_iter, EPIterator ep_iter_end, BOOST_DIR_CSR_GRAPH_TYPE& g)
1211 {
1212     g.add_edges_internal(first, last, ep_iter, ep_iter_end);
1213 }
1214 
1215 template < BOOST_DIR_CSR_GRAPH_TEMPLATE_PARMS, typename InputIterator,
1216     typename EPIterator, typename GlobalToLocal >
add_edges_global(InputIterator first,InputIterator last,EPIterator ep_iter,EPIterator ep_iter_end,const GlobalToLocal & global_to_local,BOOST_DIR_CSR_GRAPH_TYPE & g)1217 inline void add_edges_global(InputIterator first, InputIterator last,
1218     EPIterator ep_iter, EPIterator ep_iter_end,
1219     const GlobalToLocal& global_to_local, BOOST_DIR_CSR_GRAPH_TYPE& g)
1220 {
1221     g.add_edges_internal(first, last, ep_iter, ep_iter_end, global_to_local);
1222 }
1223 
1224 // From VertexListGraph
1225 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
num_vertices(const BOOST_CSR_GRAPH_TYPE & g)1226 inline Vertex num_vertices(const BOOST_CSR_GRAPH_TYPE& g)
1227 {
1228     return g.m_forward.m_rowstart.size() - 1;
1229 }
1230 
1231 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
1232 std::pair< counting_iterator< Vertex >,
vertices(const BOOST_CSR_GRAPH_TYPE & g)1233     counting_iterator< Vertex > > inline vertices(const BOOST_CSR_GRAPH_TYPE& g)
1234 {
1235     return std::make_pair(counting_iterator< Vertex >(0),
1236         counting_iterator< Vertex >(num_vertices(g)));
1237 }
1238 
1239 // From IncidenceGraph
1240 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
source(typename BOOST_CSR_GRAPH_TYPE::edge_descriptor e,const BOOST_CSR_GRAPH_TYPE &)1241 inline Vertex source(typename BOOST_CSR_GRAPH_TYPE::edge_descriptor e,
1242     const BOOST_CSR_GRAPH_TYPE&)
1243 {
1244     return e.src;
1245 }
1246 
1247 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
target(typename BOOST_CSR_GRAPH_TYPE::edge_descriptor e,const BOOST_CSR_GRAPH_TYPE & g)1248 inline Vertex target(typename BOOST_CSR_GRAPH_TYPE::edge_descriptor e,
1249     const BOOST_CSR_GRAPH_TYPE& g)
1250 {
1251     return g.m_forward.m_column[e.idx];
1252 }
1253 
1254 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
1255 inline std::pair< typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator,
1256     typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator >
out_edges(Vertex v,const BOOST_CSR_GRAPH_TYPE & g)1257 out_edges(Vertex v, const BOOST_CSR_GRAPH_TYPE& g)
1258 {
1259     typedef typename BOOST_CSR_GRAPH_TYPE::edge_descriptor ed;
1260     typedef typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator it;
1261     EdgeIndex v_row_start = g.m_forward.m_rowstart[v];
1262     EdgeIndex next_row_start = g.m_forward.m_rowstart[v + 1];
1263     return std::make_pair(it(ed(v, v_row_start)), it(ed(v, next_row_start)));
1264 }
1265 
1266 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
out_degree(Vertex v,const BOOST_CSR_GRAPH_TYPE & g)1267 inline EdgeIndex out_degree(Vertex v, const BOOST_CSR_GRAPH_TYPE& g)
1268 {
1269     EdgeIndex v_row_start = g.m_forward.m_rowstart[v];
1270     EdgeIndex next_row_start = g.m_forward.m_rowstart[v + 1];
1271     return next_row_start - v_row_start;
1272 }
1273 
1274 template < BOOST_BIDIR_CSR_GRAPH_TEMPLATE_PARMS >
1275 inline std::pair< typename BOOST_BIDIR_CSR_GRAPH_TYPE::in_edge_iterator,
1276     typename BOOST_BIDIR_CSR_GRAPH_TYPE::in_edge_iterator >
in_edges(Vertex v,const BOOST_BIDIR_CSR_GRAPH_TYPE & g)1277 in_edges(Vertex v, const BOOST_BIDIR_CSR_GRAPH_TYPE& g)
1278 {
1279     typedef typename BOOST_BIDIR_CSR_GRAPH_TYPE::in_edge_iterator it;
1280     EdgeIndex v_row_start = g.m_backward.m_rowstart[v];
1281     EdgeIndex next_row_start = g.m_backward.m_rowstart[v + 1];
1282     return std::make_pair(it(g, v_row_start), it(g, next_row_start));
1283 }
1284 
1285 template < BOOST_BIDIR_CSR_GRAPH_TEMPLATE_PARMS >
in_degree(Vertex v,const BOOST_BIDIR_CSR_GRAPH_TYPE & g)1286 inline EdgeIndex in_degree(Vertex v, const BOOST_BIDIR_CSR_GRAPH_TYPE& g)
1287 {
1288     EdgeIndex v_row_start = g.m_backward.m_rowstart[v];
1289     EdgeIndex next_row_start = g.m_backward.m_rowstart[v + 1];
1290     return next_row_start - v_row_start;
1291 }
1292 
1293 // From AdjacencyGraph
1294 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
1295 inline std::pair< typename BOOST_CSR_GRAPH_TYPE::adjacency_iterator,
1296     typename BOOST_CSR_GRAPH_TYPE::adjacency_iterator >
adjacent_vertices(Vertex v,const BOOST_CSR_GRAPH_TYPE & g)1297 adjacent_vertices(Vertex v, const BOOST_CSR_GRAPH_TYPE& g)
1298 {
1299     EdgeIndex v_row_start = g.m_forward.m_rowstart[v];
1300     EdgeIndex next_row_start = g.m_forward.m_rowstart[v + 1];
1301     return std::make_pair(g.m_forward.m_column.begin() + v_row_start,
1302         g.m_forward.m_column.begin() + next_row_start);
1303 }
1304 
1305 // Extra, common functions
1306 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
vertex(typename graph_traits<BOOST_CSR_GRAPH_TYPE>::vertex_descriptor i,const BOOST_CSR_GRAPH_TYPE &)1307 inline typename graph_traits< BOOST_CSR_GRAPH_TYPE >::vertex_descriptor vertex(
1308     typename graph_traits< BOOST_CSR_GRAPH_TYPE >::vertex_descriptor i,
1309     const BOOST_CSR_GRAPH_TYPE&)
1310 {
1311     return i;
1312 }
1313 
1314 // edge() can be provided in linear time for the new interface
1315 
1316 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
edge(Vertex i,Vertex j,const BOOST_CSR_GRAPH_TYPE & g)1317 inline std::pair< typename BOOST_CSR_GRAPH_TYPE::edge_descriptor, bool > edge(
1318     Vertex i, Vertex j, const BOOST_CSR_GRAPH_TYPE& g)
1319 {
1320     typedef typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator out_edge_iter;
1321     std::pair< out_edge_iter, out_edge_iter > range = out_edges(i, g);
1322     for (; range.first != range.second; ++range.first)
1323     {
1324         if (target(*range.first, g) == j)
1325             return std::make_pair(*range.first, true);
1326     }
1327     return std::make_pair(
1328         typename BOOST_CSR_GRAPH_TYPE::edge_descriptor(), false);
1329 }
1330 
1331 // Find an edge given its index in the graph
1332 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
edge_from_index(EdgeIndex idx,const BOOST_CSR_GRAPH_TYPE & g)1333 inline typename BOOST_CSR_GRAPH_TYPE::edge_descriptor edge_from_index(
1334     EdgeIndex idx, const BOOST_CSR_GRAPH_TYPE& g)
1335 {
1336     typedef typename std::vector< EdgeIndex >::const_iterator row_start_iter;
1337     BOOST_ASSERT(idx < num_edges(g));
1338     row_start_iter src_plus_1 = std::upper_bound(
1339         g.m_forward.m_rowstart.begin(), g.m_forward.m_rowstart.end(), idx);
1340     // Get last source whose rowstart is at most idx
1341     // upper_bound returns this position plus 1
1342     Vertex src = (src_plus_1 - g.m_forward.m_rowstart.begin()) - 1;
1343     return typename BOOST_CSR_GRAPH_TYPE::edge_descriptor(src, idx);
1344 }
1345 
1346 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
num_edges(const BOOST_CSR_GRAPH_TYPE & g)1347 inline EdgeIndex num_edges(const BOOST_CSR_GRAPH_TYPE& g)
1348 {
1349     return g.m_forward.m_column.size();
1350 }
1351 
1352 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
1353 std::pair< typename BOOST_CSR_GRAPH_TYPE::edge_iterator,
1354     typename BOOST_CSR_GRAPH_TYPE::edge_iterator >
edges(const BOOST_CSR_GRAPH_TYPE & g)1355 edges(const BOOST_CSR_GRAPH_TYPE& g)
1356 {
1357     typedef typename BOOST_CSR_GRAPH_TYPE::edge_iterator ei;
1358     typedef typename BOOST_CSR_GRAPH_TYPE::edge_descriptor edgedesc;
1359     if (g.m_forward.m_rowstart.size() == 1 || g.m_forward.m_column.empty())
1360     {
1361         return std::make_pair(ei(), ei());
1362     }
1363     else
1364     {
1365         // Find the first vertex that has outgoing edges
1366         Vertex src = 0;
1367         while (g.m_forward.m_rowstart[src + 1] == 0)
1368             ++src;
1369         return std::make_pair(
1370             ei(g, edgedesc(src, 0), g.m_forward.m_rowstart[src + 1]),
1371             ei(g, edgedesc(num_vertices(g), g.m_forward.m_column.size()), 0));
1372     }
1373 }
1374 
1375 // For Property Graph
1376 
1377 // Graph properties
1378 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS, class Tag, class Value >
set_property(BOOST_CSR_GRAPH_TYPE & g,Tag tag,const Value & value)1379 inline void set_property(BOOST_CSR_GRAPH_TYPE& g, Tag tag, const Value& value)
1380 {
1381     get_property_value(g.m_property, tag) = value;
1382 }
1383 
1384 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS, class Tag >
get_property(BOOST_CSR_GRAPH_TYPE & g,Tag tag)1385 inline typename graph_property< BOOST_CSR_GRAPH_TYPE, Tag >::type& get_property(
1386     BOOST_CSR_GRAPH_TYPE& g, Tag tag)
1387 {
1388     return get_property_value(g.m_property, tag);
1389 }
1390 
1391 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS, class Tag >
1392 inline const typename graph_property< BOOST_CSR_GRAPH_TYPE, Tag >::type&
get_property(const BOOST_CSR_GRAPH_TYPE & g,Tag tag)1393 get_property(const BOOST_CSR_GRAPH_TYPE& g, Tag tag)
1394 {
1395     return get_property_value(g.m_property, tag);
1396 }
1397 
1398 template < typename G, typename Tag, typename Kind >
1399 struct csr_property_map_helper
1400 {
1401 };
1402 // Kind == void for invalid property tags, so we can use that to SFINAE out
1403 
1404 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS, typename Tag >
1405 struct csr_property_map_helper< BOOST_CSR_GRAPH_TYPE, Tag, vertex_property_tag >
1406 {
1407     typedef vertex_all_t all_tag;
1408     typedef
1409         typename property_traits< typename property_map< BOOST_CSR_GRAPH_TYPE,
1410             vertex_all_t >::type >::key_type key_type;
1411     typedef VertexProperty plist_type;
1412     typedef typename property_map< BOOST_CSR_GRAPH_TYPE, vertex_all_t >::type
1413         all_type;
1414     typedef
1415         typename property_map< BOOST_CSR_GRAPH_TYPE, vertex_all_t >::const_type
1416             all_const_type;
1417     typedef transform_value_property_map<
1418         detail::lookup_one_property_f< plist_type, Tag >, all_type >
1419         type;
1420     typedef transform_value_property_map<
1421         detail::lookup_one_property_f< const plist_type, Tag >, all_const_type >
1422         const_type;
1423 };
1424 
1425 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS, typename Tag >
1426 struct csr_property_map_helper< BOOST_CSR_GRAPH_TYPE, Tag, edge_property_tag >
1427 {
1428     typedef edge_all_t all_tag;
1429     typedef
1430         typename property_traits< typename property_map< BOOST_CSR_GRAPH_TYPE,
1431             edge_all_t >::type >::key_type key_type;
1432     typedef EdgeProperty plist_type;
1433     typedef typename property_map< BOOST_CSR_GRAPH_TYPE, edge_all_t >::type
1434         all_type;
1435     typedef
1436         typename property_map< BOOST_CSR_GRAPH_TYPE, edge_all_t >::const_type
1437             all_const_type;
1438     typedef transform_value_property_map<
1439         detail::lookup_one_property_f< plist_type, Tag >, all_type >
1440         type;
1441     typedef transform_value_property_map<
1442         detail::lookup_one_property_f< const plist_type, Tag >, all_const_type >
1443         const_type;
1444 };
1445 
1446 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS, typename Tag >
1447 struct csr_property_map_helper< BOOST_CSR_GRAPH_TYPE, Tag, graph_property_tag >
1448 {
1449     typedef graph_all_t all_tag;
1450     typedef BOOST_CSR_GRAPH_TYPE* key_type;
1451     typedef GraphProperty plist_type;
1452     typedef typename property_map< BOOST_CSR_GRAPH_TYPE, graph_all_t >::type
1453         all_type;
1454     typedef
1455         typename property_map< BOOST_CSR_GRAPH_TYPE, graph_all_t >::const_type
1456             all_const_type;
1457     typedef transform_value_property_map<
1458         detail::lookup_one_property_f< plist_type, Tag >, all_type >
1459         type;
1460     typedef transform_value_property_map<
1461         detail::lookup_one_property_f< const plist_type, Tag >, all_const_type >
1462         const_type;
1463 };
1464 
1465 // disable_if isn't truly necessary but required to avoid ambiguity with
1466 // specializations below
1467 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS, typename Tag >
1468 struct property_map< BOOST_CSR_GRAPH_TYPE, Tag,
1469     typename disable_if< detail::is_distributed_selector< Vertex > >::type >
1470 : csr_property_map_helper< BOOST_CSR_GRAPH_TYPE, Tag,
1471       typename detail::property_kind_from_graph< BOOST_CSR_GRAPH_TYPE,
1472           Tag >::type >
1473 {
1474 };
1475 
1476 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS, typename Tag >
get(Tag tag,BOOST_CSR_GRAPH_TYPE & g)1477 typename property_map< BOOST_CSR_GRAPH_TYPE, Tag >::type get(
1478     Tag tag, BOOST_CSR_GRAPH_TYPE& g)
1479 {
1480     return typename property_map< BOOST_CSR_GRAPH_TYPE, Tag >::type(tag,
1481         get(typename property_map< BOOST_CSR_GRAPH_TYPE, Tag >::all_tag(), g));
1482 }
1483 
1484 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS, typename Tag >
get(Tag tag,const BOOST_CSR_GRAPH_TYPE & g)1485 typename property_map< BOOST_CSR_GRAPH_TYPE, Tag >::const_type get(
1486     Tag tag, const BOOST_CSR_GRAPH_TYPE& g)
1487 {
1488     return typename property_map< BOOST_CSR_GRAPH_TYPE, Tag >::const_type(tag,
1489         get(typename property_map< BOOST_CSR_GRAPH_TYPE, Tag >::all_tag(), g));
1490 }
1491 
1492 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS, typename Tag >
1493 typename property_traits<
1494     typename property_map< BOOST_CSR_GRAPH_TYPE, Tag >::type >::reference
get(Tag tag,BOOST_CSR_GRAPH_TYPE & g,typename property_map<BOOST_CSR_GRAPH_TYPE,Tag>::key_type k)1495 get(Tag tag, BOOST_CSR_GRAPH_TYPE& g,
1496     typename property_map< BOOST_CSR_GRAPH_TYPE, Tag >::key_type k)
1497 {
1498     typedef typename property_map< BOOST_CSR_GRAPH_TYPE, Tag >::all_tag all_tag;
1499     typedef
1500         typename property_map< BOOST_CSR_GRAPH_TYPE, all_tag >::type outer_pm;
1501     return lookup_one_property<
1502         typename property_traits< outer_pm >::value_type,
1503         Tag >::lookup(get(all_tag(), g, k), tag);
1504 }
1505 
1506 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS, typename Tag >
1507 typename property_traits<
1508     typename property_map< BOOST_CSR_GRAPH_TYPE, Tag >::const_type >::reference
get(Tag tag,const BOOST_CSR_GRAPH_TYPE & g,typename property_map<BOOST_CSR_GRAPH_TYPE,Tag>::key_type k)1509 get(Tag tag, const BOOST_CSR_GRAPH_TYPE& g,
1510     typename property_map< BOOST_CSR_GRAPH_TYPE, Tag >::key_type k)
1511 {
1512     typedef typename property_map< BOOST_CSR_GRAPH_TYPE, Tag >::all_tag all_tag;
1513     typedef typename property_map< BOOST_CSR_GRAPH_TYPE, all_tag >::const_type
1514         outer_pm;
1515     return lookup_one_property<
1516         const typename property_traits< outer_pm >::value_type,
1517         Tag >::lookup(get(all_tag(), g, k), tag);
1518 }
1519 
1520 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS, typename Tag >
put(Tag tag,BOOST_CSR_GRAPH_TYPE & g,typename property_map<BOOST_CSR_GRAPH_TYPE,Tag>::key_type k,typename lookup_one_property<typename property_map<BOOST_CSR_GRAPH_TYPE,Tag>::plist_type,Tag>::type val)1521 void put(Tag tag, BOOST_CSR_GRAPH_TYPE& g,
1522     typename property_map< BOOST_CSR_GRAPH_TYPE, Tag >::key_type k,
1523     typename lookup_one_property<
1524         typename property_map< BOOST_CSR_GRAPH_TYPE, Tag >::plist_type,
1525         Tag >::type val)
1526 {
1527     typedef typename property_map< BOOST_CSR_GRAPH_TYPE, Tag >::all_tag all_tag;
1528     lookup_one_property<
1529         typename property_map< BOOST_CSR_GRAPH_TYPE, Tag >::plist_type,
1530         Tag >::lookup(get(all_tag(), g, k), tag)
1531         = val;
1532 }
1533 
1534 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
1535 struct property_map< BOOST_CSR_GRAPH_TYPE, vertex_index_t,
1536     typename disable_if< detail::is_distributed_selector< Vertex > >::type >
1537 {
1538     typedef typed_identity_property_map< Vertex > type;
1539     typedef type const_type;
1540 };
1541 
1542 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
1543 struct property_map< BOOST_CSR_GRAPH_TYPE, edge_index_t,
1544     typename disable_if< detail::is_distributed_selector< Vertex > >::type >
1545 {
1546     typedef detail::csr_edge_index_map< Vertex, EdgeIndex > type;
1547     typedef type const_type;
1548 };
1549 
1550 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
1551 struct property_map< BOOST_CSR_GRAPH_TYPE, vertex_all_t,
1552     typename disable_if< detail::is_distributed_selector< Vertex > >::type >
1553 {
1554     typedef typename BOOST_CSR_GRAPH_TYPE::inherited_vertex_properties::
1555         vertex_map_type type;
1556     typedef typename BOOST_CSR_GRAPH_TYPE::inherited_vertex_properties::
1557         const_vertex_map_type const_type;
1558 };
1559 
1560 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
1561 struct property_map< BOOST_CSR_GRAPH_TYPE, edge_all_t,
1562     typename disable_if< detail::is_distributed_selector< Vertex > >::type >
1563 {
1564     typedef typename BOOST_CSR_GRAPH_TYPE::forward_type::
1565         inherited_edge_properties::edge_map_type type;
1566     typedef typename BOOST_CSR_GRAPH_TYPE::forward_type::
1567         inherited_edge_properties::const_edge_map_type const_type;
1568 };
1569 
1570 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
1571 struct property_map< BOOST_CSR_GRAPH_TYPE, graph_all_t,
1572     typename disable_if< detail::is_distributed_selector< Vertex > >::type >
1573 {
1574     typedef boost::ref_property_map< BOOST_CSR_GRAPH_TYPE*,
1575         typename BOOST_CSR_GRAPH_TYPE::graph_property_type >
1576         type;
1577     typedef boost::ref_property_map< BOOST_CSR_GRAPH_TYPE*,
1578         const typename BOOST_CSR_GRAPH_TYPE::graph_property_type >
1579         const_type;
1580 };
1581 
1582 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
get(vertex_index_t,const BOOST_CSR_GRAPH_TYPE &)1583 inline typed_identity_property_map< Vertex > get(
1584     vertex_index_t, const BOOST_CSR_GRAPH_TYPE&)
1585 {
1586     return typed_identity_property_map< Vertex >();
1587 }
1588 
1589 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
get(vertex_index_t,const BOOST_CSR_GRAPH_TYPE &,Vertex v)1590 inline Vertex get(vertex_index_t, const BOOST_CSR_GRAPH_TYPE&, Vertex v)
1591 {
1592     return v;
1593 }
1594 
1595 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
get(vertex_index_t,BOOST_CSR_GRAPH_TYPE &)1596 inline typed_identity_property_map< Vertex > get(
1597     vertex_index_t, BOOST_CSR_GRAPH_TYPE&)
1598 {
1599     return typed_identity_property_map< Vertex >();
1600 }
1601 
1602 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
get(vertex_index_t,BOOST_CSR_GRAPH_TYPE &,Vertex v)1603 inline Vertex get(vertex_index_t, BOOST_CSR_GRAPH_TYPE&, Vertex v)
1604 {
1605     return v;
1606 }
1607 
1608 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
1609 inline typename property_map< BOOST_CSR_GRAPH_TYPE, edge_index_t >::const_type
get(edge_index_t,const BOOST_CSR_GRAPH_TYPE &)1610 get(edge_index_t, const BOOST_CSR_GRAPH_TYPE&)
1611 {
1612     typedef
1613         typename property_map< BOOST_CSR_GRAPH_TYPE, edge_index_t >::const_type
1614             result_type;
1615     return result_type();
1616 }
1617 
1618 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
get(edge_index_t,const BOOST_CSR_GRAPH_TYPE &,typename BOOST_CSR_GRAPH_TYPE::edge_descriptor e)1619 inline EdgeIndex get(edge_index_t, const BOOST_CSR_GRAPH_TYPE&,
1620     typename BOOST_CSR_GRAPH_TYPE::edge_descriptor e)
1621 {
1622     return e.idx;
1623 }
1624 
1625 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
1626 inline typename property_map< BOOST_CSR_GRAPH_TYPE, edge_index_t >::const_type
get(edge_index_t,BOOST_CSR_GRAPH_TYPE &)1627 get(edge_index_t, BOOST_CSR_GRAPH_TYPE&)
1628 {
1629     typedef
1630         typename property_map< BOOST_CSR_GRAPH_TYPE, edge_index_t >::const_type
1631             result_type;
1632     return result_type();
1633 }
1634 
1635 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
get(edge_index_t,BOOST_CSR_GRAPH_TYPE &,typename BOOST_CSR_GRAPH_TYPE::edge_descriptor e)1636 inline EdgeIndex get(edge_index_t, BOOST_CSR_GRAPH_TYPE&,
1637     typename BOOST_CSR_GRAPH_TYPE::edge_descriptor e)
1638 {
1639     return e.idx;
1640 }
1641 
1642 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
get(vertex_all_t,BOOST_CSR_GRAPH_TYPE & g)1643 inline typename property_map< BOOST_CSR_GRAPH_TYPE, vertex_all_t >::type get(
1644     vertex_all_t, BOOST_CSR_GRAPH_TYPE& g)
1645 {
1646     return g.get_vertex_bundle(get(vertex_index, g));
1647 }
1648 
1649 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
1650 inline typename property_map< BOOST_CSR_GRAPH_TYPE, vertex_all_t >::const_type
get(vertex_all_t,const BOOST_CSR_GRAPH_TYPE & g)1651 get(vertex_all_t, const BOOST_CSR_GRAPH_TYPE& g)
1652 {
1653     return g.get_vertex_bundle(get(vertex_index, g));
1654 }
1655 
1656 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
get(vertex_all_t,BOOST_CSR_GRAPH_TYPE & g,Vertex v)1657 inline VertexProperty& get(vertex_all_t, BOOST_CSR_GRAPH_TYPE& g, Vertex v)
1658 {
1659     return get(vertex_all, g)[v];
1660 }
1661 
1662 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
get(vertex_all_t,const BOOST_CSR_GRAPH_TYPE & g,Vertex v)1663 inline const VertexProperty& get(
1664     vertex_all_t, const BOOST_CSR_GRAPH_TYPE& g, Vertex v)
1665 {
1666     return get(vertex_all, g)[v];
1667 }
1668 
1669 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
put(vertex_all_t,BOOST_CSR_GRAPH_TYPE & g,Vertex v,const VertexProperty & val)1670 inline void put(
1671     vertex_all_t, BOOST_CSR_GRAPH_TYPE& g, Vertex v, const VertexProperty& val)
1672 {
1673     put(get(vertex_all, g), v, val);
1674 }
1675 
1676 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
get(edge_all_t,BOOST_CSR_GRAPH_TYPE & g)1677 inline typename property_map< BOOST_CSR_GRAPH_TYPE, edge_all_t >::type get(
1678     edge_all_t, BOOST_CSR_GRAPH_TYPE& g)
1679 {
1680     return g.m_forward.get_edge_bundle(get(edge_index, g));
1681 }
1682 
1683 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
1684 inline typename property_map< BOOST_CSR_GRAPH_TYPE, edge_all_t >::const_type
get(edge_all_t,const BOOST_CSR_GRAPH_TYPE & g)1685 get(edge_all_t, const BOOST_CSR_GRAPH_TYPE& g)
1686 {
1687     return g.m_forward.get_edge_bundle(get(edge_index, g));
1688 }
1689 
1690 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
get(edge_all_t,BOOST_CSR_GRAPH_TYPE & g,const typename BOOST_CSR_GRAPH_TYPE::edge_descriptor & e)1691 inline EdgeProperty& get(edge_all_t, BOOST_CSR_GRAPH_TYPE& g,
1692     const typename BOOST_CSR_GRAPH_TYPE::edge_descriptor& e)
1693 {
1694     return get(edge_all, g)[e];
1695 }
1696 
1697 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
get(edge_all_t,const BOOST_CSR_GRAPH_TYPE & g,const typename BOOST_CSR_GRAPH_TYPE::edge_descriptor & e)1698 inline const EdgeProperty& get(edge_all_t, const BOOST_CSR_GRAPH_TYPE& g,
1699     const typename BOOST_CSR_GRAPH_TYPE::edge_descriptor& e)
1700 {
1701     return get(edge_all, g)[e];
1702 }
1703 
1704 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
put(edge_all_t,BOOST_CSR_GRAPH_TYPE & g,const typename BOOST_CSR_GRAPH_TYPE::edge_descriptor & e,const EdgeProperty & val)1705 inline void put(edge_all_t, BOOST_CSR_GRAPH_TYPE& g,
1706     const typename BOOST_CSR_GRAPH_TYPE::edge_descriptor& e,
1707     const EdgeProperty& val)
1708 {
1709     put(get(edge_all, g), e, val);
1710 }
1711 
1712 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
get(graph_all_t,BOOST_CSR_GRAPH_TYPE & g)1713 inline typename property_map< BOOST_CSR_GRAPH_TYPE, graph_all_t >::type get(
1714     graph_all_t, BOOST_CSR_GRAPH_TYPE& g)
1715 {
1716     return typename property_map< BOOST_CSR_GRAPH_TYPE, graph_all_t >::type(
1717         g.m_property);
1718 }
1719 
1720 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
1721 inline typename property_map< BOOST_CSR_GRAPH_TYPE, graph_all_t >::const_type
get(graph_all_t,const BOOST_CSR_GRAPH_TYPE & g)1722 get(graph_all_t, const BOOST_CSR_GRAPH_TYPE& g)
1723 {
1724     return
1725         typename property_map< BOOST_CSR_GRAPH_TYPE, graph_all_t >::const_type(
1726             g.m_property);
1727 }
1728 
1729 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
get(graph_all_t,BOOST_CSR_GRAPH_TYPE & g,BOOST_CSR_GRAPH_TYPE *)1730 inline GraphProperty& get(
1731     graph_all_t, BOOST_CSR_GRAPH_TYPE& g, BOOST_CSR_GRAPH_TYPE*)
1732 {
1733     return g.m_property;
1734 }
1735 
1736 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
get(graph_all_t,const BOOST_CSR_GRAPH_TYPE & g,BOOST_CSR_GRAPH_TYPE *)1737 inline const GraphProperty& get(
1738     graph_all_t, const BOOST_CSR_GRAPH_TYPE& g, BOOST_CSR_GRAPH_TYPE*)
1739 {
1740     return g.m_property;
1741 }
1742 
1743 template < BOOST_CSR_GRAPH_TEMPLATE_PARMS >
put(graph_all_t,BOOST_CSR_GRAPH_TYPE & g,BOOST_CSR_GRAPH_TYPE *,const GraphProperty & val)1744 inline void put(graph_all_t, BOOST_CSR_GRAPH_TYPE& g, BOOST_CSR_GRAPH_TYPE*,
1745     const GraphProperty& val)
1746 {
1747     g.m_property = val;
1748 }
1749 
1750 #undef BOOST_CSR_GRAPH_TYPE
1751 #undef BOOST_CSR_GRAPH_TEMPLATE_PARMS
1752 #undef BOOST_DIR_CSR_GRAPH_TYPE
1753 #undef BOOST_DIR_CSR_GRAPH_TEMPLATE_PARMS
1754 #undef BOOST_BIDIR_CSR_GRAPH_TYPE
1755 #undef BOOST_BIDIR_CSR_GRAPH_TEMPLATE_PARMS
1756 
1757 } // end namespace boost
1758 
1759 #endif // BOOST_GRAPH_COMPRESSED_SPARSE_ROW_GRAPH_HPP
1760