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