compressed_sparse_row_struct.hpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740
  1. // Copyright 2005-2009 The Trustees of Indiana University.
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. // Authors: Jeremiah Willcock
  6. // Douglas Gregor
  7. // Andrew Lumsdaine
  8. // Compressed sparse row graph type internal structure
  9. #ifndef BOOST_GRAPH_COMPRESSED_SPARSE_ROW_STRUCT_HPP
  10. #define BOOST_GRAPH_COMPRESSED_SPARSE_ROW_STRUCT_HPP
  11. #ifndef BOOST_GRAPH_COMPRESSED_SPARSE_ROW_GRAPH_HPP
  12. #error This file should only be included from boost/graph/compressed_sparse_row_graph.hpp
  13. #endif
  14. #include <vector>
  15. #include <utility>
  16. #include <algorithm>
  17. #include <climits>
  18. #include <boost/assert.hpp>
  19. #include <iterator>
  20. #if 0
  21. #include <iostream> // For some debugging code below
  22. #endif
  23. #include <boost/graph/graph_traits.hpp>
  24. #include <boost/graph/properties.hpp>
  25. #include <boost/graph/filtered_graph.hpp> // For keep_all
  26. #include <boost/graph/detail/indexed_properties.hpp>
  27. #include <boost/graph/detail/histogram_sort.hpp>
  28. #include <boost/graph/iteration_macros.hpp>
  29. #include <boost/iterator/counting_iterator.hpp>
  30. #include <boost/iterator/reverse_iterator.hpp>
  31. #include <boost/iterator/zip_iterator.hpp>
  32. #include <boost/iterator/transform_iterator.hpp>
  33. #include <boost/tuple/tuple.hpp>
  34. #include <boost/property_map/property_map.hpp>
  35. #include <boost/integer.hpp>
  36. #include <boost/iterator/iterator_facade.hpp>
  37. #include <boost/mpl/if.hpp>
  38. #include <boost/graph/graph_selectors.hpp>
  39. #include <boost/static_assert.hpp>
  40. #include <boost/functional/hash.hpp>
  41. namespace boost
  42. {
  43. namespace detail
  44. {
  45. // Forward declaration of CSR edge descriptor type, needed to pass to
  46. // indexed_edge_properties.
  47. template < typename Vertex, typename EdgeIndex > class csr_edge_descriptor;
  48. // Add edge_index property map
  49. template < typename Vertex, typename EdgeIndex > struct csr_edge_index_map
  50. {
  51. typedef EdgeIndex value_type;
  52. typedef EdgeIndex reference;
  53. typedef csr_edge_descriptor< Vertex, EdgeIndex > key_type;
  54. typedef readable_property_map_tag category;
  55. };
  56. template < typename Vertex, typename EdgeIndex >
  57. inline EdgeIndex get(const csr_edge_index_map< Vertex, EdgeIndex >&,
  58. const csr_edge_descriptor< Vertex, EdgeIndex >& key)
  59. {
  60. return key.idx;
  61. }
  62. /** Compressed sparse row graph internal structure.
  63. *
  64. * Vertex and EdgeIndex should be unsigned integral types and should
  65. * specialize numeric_limits.
  66. */
  67. template < typename EdgeProperty, typename Vertex = std::size_t,
  68. typename EdgeIndex = Vertex >
  69. class compressed_sparse_row_structure
  70. : public detail::indexed_edge_properties<
  71. compressed_sparse_row_structure< EdgeProperty, Vertex, EdgeIndex >,
  72. EdgeProperty, csr_edge_descriptor< Vertex, EdgeIndex >,
  73. csr_edge_index_map< Vertex, EdgeIndex > >
  74. {
  75. public:
  76. typedef detail::indexed_edge_properties<
  77. compressed_sparse_row_structure< EdgeProperty, Vertex, EdgeIndex >,
  78. EdgeProperty, csr_edge_descriptor< Vertex, EdgeIndex >,
  79. csr_edge_index_map< Vertex, EdgeIndex > >
  80. inherited_edge_properties;
  81. typedef Vertex vertices_size_type;
  82. typedef Vertex vertex_descriptor;
  83. typedef EdgeIndex edges_size_type;
  84. static vertex_descriptor null_vertex() { return vertex_descriptor(-1); }
  85. std::vector< EdgeIndex > m_rowstart;
  86. std::vector< Vertex > m_column;
  87. compressed_sparse_row_structure(Vertex numverts = 0)
  88. : m_rowstart(numverts + 1, EdgeIndex(0)), m_column()
  89. {
  90. }
  91. // Rebuild graph from number of vertices and multi-pass unsorted list
  92. // of edges (filtered using source_pred and mapped using
  93. // global_to_local)
  94. template < typename MultiPassInputIterator, typename GlobalToLocal,
  95. typename SourcePred >
  96. void assign_unsorted_multi_pass_edges(MultiPassInputIterator edge_begin,
  97. MultiPassInputIterator edge_end, vertices_size_type numlocalverts,
  98. const GlobalToLocal& global_to_local, const SourcePred& source_pred)
  99. {
  100. m_rowstart.clear();
  101. m_rowstart.resize(numlocalverts + 1, 0);
  102. typedef std::pair< vertices_size_type, vertices_size_type >
  103. edge_type;
  104. typedef boost::transform_iterator<
  105. boost::graph::detail::project1st< edge_type >,
  106. MultiPassInputIterator >
  107. source_iterator;
  108. typedef boost::transform_iterator<
  109. boost::graph::detail::project2nd< edge_type >,
  110. MultiPassInputIterator >
  111. target_iterator;
  112. source_iterator sources_begin(
  113. edge_begin, boost::graph::detail::project1st< edge_type >());
  114. source_iterator sources_end(
  115. edge_end, boost::graph::detail::project1st< edge_type >());
  116. target_iterator targets_begin(
  117. edge_begin, boost::graph::detail::project2nd< edge_type >());
  118. target_iterator targets_end(
  119. edge_end, boost::graph::detail::project2nd< edge_type >());
  120. boost::graph::detail::count_starts(sources_begin, sources_end,
  121. m_rowstart.begin(), numlocalverts, source_pred,
  122. boost::make_property_map_function(global_to_local));
  123. m_column.resize(m_rowstart.back());
  124. inherited_edge_properties::resize(m_rowstart.back());
  125. boost::graph::detail::histogram_sort(sources_begin, sources_end,
  126. m_rowstart.begin(), numlocalverts, targets_begin,
  127. m_column.begin(), source_pred,
  128. boost::make_property_map_function(global_to_local));
  129. }
  130. // Rebuild graph from number of vertices and multi-pass unsorted list
  131. // of edges and their properties (filtered using source_pred and mapped
  132. // using global_to_local)
  133. template < typename MultiPassInputIterator,
  134. typename EdgePropertyIterator, typename GlobalToLocal,
  135. typename SourcePred >
  136. void assign_unsorted_multi_pass_edges(MultiPassInputIterator edge_begin,
  137. MultiPassInputIterator edge_end, EdgePropertyIterator ep_iter,
  138. vertices_size_type numlocalverts,
  139. const GlobalToLocal& global_to_local, const SourcePred& source_pred)
  140. {
  141. m_rowstart.clear();
  142. m_rowstart.resize(numlocalverts + 1, 0);
  143. typedef std::pair< vertices_size_type, vertices_size_type >
  144. edge_type;
  145. typedef boost::transform_iterator<
  146. boost::graph::detail::project1st< edge_type >,
  147. MultiPassInputIterator >
  148. source_iterator;
  149. typedef boost::transform_iterator<
  150. boost::graph::detail::project2nd< edge_type >,
  151. MultiPassInputIterator >
  152. target_iterator;
  153. source_iterator sources_begin(
  154. edge_begin, boost::graph::detail::project1st< edge_type >());
  155. source_iterator sources_end(
  156. edge_end, boost::graph::detail::project1st< edge_type >());
  157. target_iterator targets_begin(
  158. edge_begin, boost::graph::detail::project2nd< edge_type >());
  159. target_iterator targets_end(
  160. edge_end, boost::graph::detail::project2nd< edge_type >());
  161. boost::graph::detail::count_starts(sources_begin, sources_end,
  162. m_rowstart.begin(), numlocalverts, source_pred,
  163. boost::make_property_map_function(global_to_local));
  164. m_column.resize(m_rowstart.back());
  165. inherited_edge_properties::resize(m_rowstart.back());
  166. boost::graph::detail::histogram_sort(sources_begin, sources_end,
  167. m_rowstart.begin(), numlocalverts, targets_begin,
  168. m_column.begin(), ep_iter, inherited_edge_properties::begin(),
  169. source_pred,
  170. boost::make_property_map_function(global_to_local));
  171. }
  172. // Assign from number of vertices and sorted list of edges
  173. template < typename InputIterator, typename GlobalToLocal,
  174. typename SourcePred >
  175. void assign_from_sorted_edges(InputIterator edge_begin,
  176. InputIterator edge_end, const GlobalToLocal& global_to_local,
  177. const SourcePred& source_pred, vertices_size_type numlocalverts,
  178. edges_size_type numedges_or_zero)
  179. {
  180. m_column.clear();
  181. m_column.reserve(numedges_or_zero);
  182. m_rowstart.resize(numlocalverts + 1);
  183. EdgeIndex current_edge = 0;
  184. Vertex current_vertex_plus_one = 1;
  185. m_rowstart[0] = 0;
  186. for (InputIterator ei = edge_begin; ei != edge_end; ++ei)
  187. {
  188. if (!source_pred(ei->first))
  189. continue;
  190. Vertex src = get(global_to_local, ei->first);
  191. Vertex tgt = ei->second;
  192. for (; current_vertex_plus_one != src + 1;
  193. ++current_vertex_plus_one)
  194. m_rowstart[current_vertex_plus_one] = current_edge;
  195. m_column.push_back(tgt);
  196. ++current_edge;
  197. }
  198. // The remaining vertices have no edges
  199. for (; current_vertex_plus_one != numlocalverts + 1;
  200. ++current_vertex_plus_one)
  201. m_rowstart[current_vertex_plus_one] = current_edge;
  202. // Default-construct properties for edges
  203. inherited_edge_properties::resize(m_column.size());
  204. }
  205. // Assign from number of vertices and sorted list of edges
  206. template < typename InputIterator, typename EdgePropertyIterator,
  207. typename GlobalToLocal, typename SourcePred >
  208. void assign_from_sorted_edges(InputIterator edge_begin,
  209. InputIterator edge_end, EdgePropertyIterator ep_iter,
  210. const GlobalToLocal& global_to_local, const SourcePred& source_pred,
  211. vertices_size_type numlocalverts, edges_size_type numedges_or_zero)
  212. {
  213. // Reserving storage in advance can save us lots of time and
  214. // memory, but it can only be done if we have forward iterators or
  215. // the user has supplied the number of edges.
  216. edges_size_type numedges = numedges_or_zero;
  217. if (numedges == 0)
  218. {
  219. numedges = boost::graph::detail::reserve_count_for_single_pass(
  220. edge_begin, edge_end);
  221. }
  222. m_column.clear();
  223. m_column.reserve(numedges_or_zero);
  224. inherited_edge_properties::clear();
  225. inherited_edge_properties::reserve(numedges_or_zero);
  226. m_rowstart.resize(numlocalverts + 1);
  227. EdgeIndex current_edge = 0;
  228. Vertex current_vertex_plus_one = 1;
  229. m_rowstart[0] = 0;
  230. for (InputIterator ei = edge_begin; ei != edge_end; ++ei, ++ep_iter)
  231. {
  232. if (!source_pred(ei->first))
  233. continue;
  234. Vertex src = get(global_to_local, ei->first);
  235. Vertex tgt = ei->second;
  236. for (; current_vertex_plus_one != src + 1;
  237. ++current_vertex_plus_one)
  238. m_rowstart[current_vertex_plus_one] = current_edge;
  239. m_column.push_back(tgt);
  240. inherited_edge_properties::push_back(*ep_iter);
  241. ++current_edge;
  242. }
  243. // The remaining vertices have no edges
  244. for (; current_vertex_plus_one != numlocalverts + 1;
  245. ++current_vertex_plus_one)
  246. m_rowstart[current_vertex_plus_one] = current_edge;
  247. }
  248. // Replace graph with sources and targets given, sorting them in-place,
  249. // and using the given global-to-local property map to get local indices
  250. // from global ones in the two arrays.
  251. template < typename GlobalToLocal >
  252. void assign_sources_and_targets_global(
  253. std::vector< vertex_descriptor >& sources,
  254. std::vector< vertex_descriptor >& targets,
  255. vertices_size_type numverts, GlobalToLocal global_to_local)
  256. {
  257. BOOST_ASSERT(sources.size() == targets.size());
  258. // Do an in-place histogram sort (at least that's what I think it
  259. // is) to sort sources and targets
  260. m_rowstart.clear();
  261. m_rowstart.resize(numverts + 1);
  262. boost::graph::detail::count_starts(sources.begin(), sources.end(),
  263. m_rowstart.begin(), numverts, keep_all(),
  264. boost::make_property_map_function(global_to_local));
  265. boost::graph::detail::histogram_sort_inplace(sources.begin(),
  266. m_rowstart.begin(), numverts, targets.begin(),
  267. boost::make_property_map_function(global_to_local));
  268. // Now targets is the correct vector (properly sorted by source) for
  269. // m_column
  270. m_column.swap(targets);
  271. inherited_edge_properties::resize(m_rowstart.back());
  272. }
  273. // Replace graph with sources and targets and edge properties given,
  274. // sorting them in-place, and using the given global-to-local property
  275. // map to get local indices from global ones in the two arrays.
  276. template < typename GlobalToLocal >
  277. void assign_sources_and_targets_global(
  278. std::vector< vertex_descriptor >& sources,
  279. std::vector< vertex_descriptor >& targets,
  280. std::vector< typename inherited_edge_properties::edge_bundled >&
  281. edge_props,
  282. vertices_size_type numverts, GlobalToLocal global_to_local)
  283. {
  284. BOOST_ASSERT(sources.size() == targets.size());
  285. BOOST_ASSERT(sources.size() == edge_props.size());
  286. // Do an in-place histogram sort (at least that's what I think it
  287. // is) to sort sources and targets
  288. m_rowstart.clear();
  289. m_rowstart.resize(numverts + 1);
  290. boost::graph::detail::count_starts(sources.begin(), sources.end(),
  291. m_rowstart.begin(), numverts, keep_all(),
  292. boost::make_property_map_function(global_to_local));
  293. boost::graph::detail::histogram_sort_inplace(sources.begin(),
  294. m_rowstart.begin(), numverts, targets.begin(),
  295. edge_props.begin(),
  296. boost::make_property_map_function(global_to_local));
  297. // Now targets is the correct vector (properly sorted by source) for
  298. // m_column, and edge_props for m_edge_properties
  299. m_column.swap(targets);
  300. this->m_edge_properties.swap(edge_props);
  301. }
  302. // From any graph (slow and uses a lot of memory)
  303. // Requires IncidenceGraph and a vertex index map
  304. // Internal helper function
  305. // Note that numedges must be doubled for undirected source graphs
  306. template < typename Graph, typename VertexIndexMap >
  307. void assign(const Graph& g, const VertexIndexMap& vi,
  308. vertices_size_type numverts, edges_size_type numedges)
  309. {
  310. m_rowstart.resize(numverts + 1);
  311. m_column.resize(numedges);
  312. inherited_edge_properties::resize(numedges);
  313. EdgeIndex current_edge = 0;
  314. typedef typename boost::graph_traits< Graph >::vertex_descriptor
  315. g_vertex;
  316. typedef typename boost::graph_traits< Graph >::out_edge_iterator
  317. g_out_edge_iter;
  318. std::vector< g_vertex > ordered_verts_of_g(numverts);
  319. BGL_FORALL_VERTICES_T(v, g, Graph)
  320. {
  321. ordered_verts_of_g[get(vertex_index, g, v)] = v;
  322. }
  323. for (Vertex i = 0; i != numverts; ++i)
  324. {
  325. m_rowstart[i] = current_edge;
  326. g_vertex v = ordered_verts_of_g[i];
  327. g_out_edge_iter ei, ei_end;
  328. for (boost::tie(ei, ei_end) = out_edges(v, g); ei != ei_end;
  329. ++ei)
  330. {
  331. m_column[current_edge++] = get(vi, target(*ei, g));
  332. }
  333. }
  334. m_rowstart[numverts] = current_edge;
  335. }
  336. // Add edges from a sorted (smallest sources first) range of pairs and
  337. // edge properties
  338. template < typename BidirectionalIteratorOrig, typename EPIterOrig,
  339. typename GlobalToLocal >
  340. void add_edges_sorted_internal(BidirectionalIteratorOrig first_sorted,
  341. BidirectionalIteratorOrig last_sorted, EPIterOrig ep_iter_sorted,
  342. const GlobalToLocal& global_to_local)
  343. {
  344. typedef boost::reverse_iterator< BidirectionalIteratorOrig >
  345. BidirectionalIterator;
  346. typedef boost::reverse_iterator< EPIterOrig > EPIter;
  347. // Flip sequence
  348. BidirectionalIterator first(last_sorted);
  349. BidirectionalIterator last(first_sorted);
  350. typedef Vertex vertex_num;
  351. typedef EdgeIndex edge_num;
  352. edge_num new_edge_count = std::distance(first, last);
  353. EPIter ep_iter(ep_iter_sorted);
  354. std::advance(ep_iter, -(std::ptrdiff_t)new_edge_count);
  355. edge_num edges_added_before_i
  356. = new_edge_count; // Count increment to add to rowstarts
  357. m_column.resize(m_column.size() + new_edge_count);
  358. inherited_edge_properties::resize(
  359. inherited_edge_properties::size() + new_edge_count);
  360. BidirectionalIterator current_new_edge = first,
  361. prev_new_edge = first;
  362. EPIter current_new_edge_prop = ep_iter;
  363. for (vertex_num i_plus_1 = m_rowstart.size() - 1; i_plus_1 > 0;
  364. --i_plus_1)
  365. {
  366. vertex_num i = i_plus_1 - 1;
  367. prev_new_edge = current_new_edge;
  368. // edges_added_to_this_vertex = #mbrs of new_edges with first ==
  369. // i
  370. edge_num edges_added_to_this_vertex = 0;
  371. while (current_new_edge != last)
  372. {
  373. if (get(global_to_local, current_new_edge->first) != i)
  374. break;
  375. ++current_new_edge;
  376. ++current_new_edge_prop;
  377. ++edges_added_to_this_vertex;
  378. }
  379. edges_added_before_i -= edges_added_to_this_vertex;
  380. // Invariant: edges_added_before_i = #mbrs of new_edges with
  381. // first < i
  382. edge_num old_rowstart = m_rowstart[i];
  383. edge_num new_rowstart = m_rowstart[i] + edges_added_before_i;
  384. edge_num old_degree = m_rowstart[i + 1] - m_rowstart[i];
  385. edge_num new_degree = old_degree + edges_added_to_this_vertex;
  386. // Move old edges forward (by #new_edges before this i) to make
  387. // room new_rowstart > old_rowstart, so use copy_backwards
  388. if (old_rowstart != new_rowstart)
  389. {
  390. std::copy_backward(m_column.begin() + old_rowstart,
  391. m_column.begin() + old_rowstart + old_degree,
  392. m_column.begin() + new_rowstart + old_degree);
  393. inherited_edge_properties::move_range(
  394. old_rowstart, old_rowstart + old_degree, new_rowstart);
  395. }
  396. // Add new edges (reversed because current_new_edge is a
  397. // const_reverse_iterator)
  398. BidirectionalIterator temp = current_new_edge;
  399. EPIter temp_prop = current_new_edge_prop;
  400. for (; temp != prev_new_edge; ++old_degree)
  401. {
  402. --temp;
  403. --temp_prop;
  404. m_column[new_rowstart + old_degree] = temp->second;
  405. inherited_edge_properties::write_by_index(
  406. new_rowstart + old_degree, *temp_prop);
  407. }
  408. m_rowstart[i + 1] = new_rowstart + new_degree;
  409. if (edges_added_before_i == 0)
  410. break; // No more edges inserted before this point
  411. // m_rowstart[i] will be fixed up on the next iteration (to
  412. // avoid changing the degree of vertex i - 1); the last
  413. // iteration never changes it (either because of the condition
  414. // of the break or because m_rowstart[0] is always 0)
  415. }
  416. }
  417. };
  418. template < typename Vertex, typename EdgeIndex > class csr_edge_descriptor
  419. {
  420. public:
  421. Vertex src;
  422. EdgeIndex idx;
  423. csr_edge_descriptor(Vertex src, EdgeIndex idx) : src(src), idx(idx) {}
  424. csr_edge_descriptor() : src(0), idx(0) {}
  425. bool operator==(const csr_edge_descriptor& e) const
  426. {
  427. return idx == e.idx;
  428. }
  429. bool operator!=(const csr_edge_descriptor& e) const
  430. {
  431. return idx != e.idx;
  432. }
  433. bool operator<(const csr_edge_descriptor& e) const
  434. {
  435. return idx < e.idx;
  436. }
  437. bool operator>(const csr_edge_descriptor& e) const
  438. {
  439. return idx > e.idx;
  440. }
  441. bool operator<=(const csr_edge_descriptor& e) const
  442. {
  443. return idx <= e.idx;
  444. }
  445. bool operator>=(const csr_edge_descriptor& e) const
  446. {
  447. return idx >= e.idx;
  448. }
  449. template < typename Archiver >
  450. void serialize(Archiver& ar, const unsigned int /*version*/)
  451. {
  452. ar& src& idx;
  453. }
  454. };
  455. // Common out edge and edge iterators
  456. template < typename CSRGraph >
  457. class csr_out_edge_iterator
  458. : public iterator_facade< csr_out_edge_iterator< CSRGraph >,
  459. typename CSRGraph::edge_descriptor, std::random_access_iterator_tag,
  460. const typename CSRGraph::edge_descriptor&,
  461. typename int_t< CHAR_BIT
  462. * sizeof(typename CSRGraph::edges_size_type) >::fast >
  463. {
  464. public:
  465. typedef typename CSRGraph::edges_size_type EdgeIndex;
  466. typedef typename CSRGraph::edge_descriptor edge_descriptor;
  467. typedef typename int_t< CHAR_BIT * sizeof(EdgeIndex) >::fast
  468. difference_type;
  469. csr_out_edge_iterator() {}
  470. // Implicit copy constructor OK
  471. explicit csr_out_edge_iterator(edge_descriptor edge) : m_edge(edge) {}
  472. public: // GCC 4.2.1 doesn't like the private-and-friend thing
  473. // iterator_facade requirements
  474. const edge_descriptor& dereference() const { return m_edge; }
  475. bool equal(const csr_out_edge_iterator& other) const
  476. {
  477. return m_edge == other.m_edge;
  478. }
  479. void increment() { ++m_edge.idx; }
  480. void decrement() { --m_edge.idx; }
  481. void advance(difference_type n) { m_edge.idx += n; }
  482. difference_type distance_to(const csr_out_edge_iterator& other) const
  483. {
  484. return other.m_edge.idx - m_edge.idx;
  485. }
  486. edge_descriptor m_edge;
  487. friend class boost::iterator_core_access;
  488. };
  489. template < typename CSRGraph >
  490. class csr_edge_iterator
  491. : public iterator_facade< csr_edge_iterator< CSRGraph >,
  492. typename CSRGraph::edge_descriptor, boost::forward_traversal_tag,
  493. typename CSRGraph::edge_descriptor >
  494. {
  495. private:
  496. typedef typename CSRGraph::edge_descriptor edge_descriptor;
  497. typedef typename CSRGraph::edges_size_type EdgeIndex;
  498. public:
  499. csr_edge_iterator()
  500. : rowstart_array(0)
  501. , current_edge()
  502. , end_of_this_vertex(0)
  503. , total_num_edges(0)
  504. {
  505. }
  506. csr_edge_iterator(const CSRGraph& graph, edge_descriptor current_edge,
  507. EdgeIndex end_of_this_vertex)
  508. : rowstart_array(&graph.m_forward.m_rowstart[0])
  509. , current_edge(current_edge)
  510. , end_of_this_vertex(end_of_this_vertex)
  511. , total_num_edges(num_edges(graph))
  512. {
  513. }
  514. public: // See above
  515. friend class boost::iterator_core_access;
  516. edge_descriptor dereference() const { return current_edge; }
  517. bool equal(const csr_edge_iterator& o) const
  518. {
  519. return current_edge == o.current_edge;
  520. }
  521. void increment()
  522. {
  523. ++current_edge.idx;
  524. if (current_edge.idx == total_num_edges)
  525. return;
  526. while (current_edge.idx == end_of_this_vertex)
  527. {
  528. ++current_edge.src;
  529. end_of_this_vertex = rowstart_array[current_edge.src + 1];
  530. }
  531. }
  532. const EdgeIndex* rowstart_array;
  533. edge_descriptor current_edge;
  534. EdgeIndex end_of_this_vertex;
  535. EdgeIndex total_num_edges;
  536. };
  537. // Only for bidirectional graphs
  538. template < typename CSRGraph >
  539. class csr_in_edge_iterator
  540. : public iterator_facade< csr_in_edge_iterator< CSRGraph >,
  541. typename CSRGraph::edge_descriptor, boost::forward_traversal_tag,
  542. typename CSRGraph::edge_descriptor >
  543. {
  544. public:
  545. typedef typename CSRGraph::edges_size_type EdgeIndex;
  546. typedef typename CSRGraph::edge_descriptor edge_descriptor;
  547. csr_in_edge_iterator() : m_graph(0) {}
  548. // Implicit copy constructor OK
  549. csr_in_edge_iterator(
  550. const CSRGraph& graph, EdgeIndex index_in_backward_graph)
  551. : m_index_in_backward_graph(index_in_backward_graph), m_graph(&graph)
  552. {
  553. }
  554. public: // See above
  555. // iterator_facade requirements
  556. edge_descriptor dereference() const
  557. {
  558. return edge_descriptor(
  559. m_graph->m_backward.m_column[m_index_in_backward_graph],
  560. m_graph->m_backward
  561. .m_edge_properties[m_index_in_backward_graph]);
  562. }
  563. bool equal(const csr_in_edge_iterator& other) const
  564. {
  565. return m_index_in_backward_graph == other.m_index_in_backward_graph;
  566. }
  567. void increment() { ++m_index_in_backward_graph; }
  568. void decrement() { --m_index_in_backward_graph; }
  569. void advance(std::ptrdiff_t n) { m_index_in_backward_graph += n; }
  570. std::ptrdiff_t distance_to(const csr_in_edge_iterator& other) const
  571. {
  572. return other.m_index_in_backward_graph - m_index_in_backward_graph;
  573. }
  574. EdgeIndex m_index_in_backward_graph;
  575. const CSRGraph* m_graph;
  576. friend class boost::iterator_core_access;
  577. };
  578. template < typename A, typename B > struct transpose_pair
  579. {
  580. typedef std::pair< B, A > result_type;
  581. result_type operator()(const std::pair< A, B >& p) const
  582. {
  583. return result_type(p.second, p.first);
  584. }
  585. };
  586. template < typename Iter > struct transpose_iterator_gen
  587. {
  588. typedef typename std::iterator_traits< Iter >::value_type vt;
  589. typedef typename vt::first_type first_type;
  590. typedef typename vt::second_type second_type;
  591. typedef transpose_pair< first_type, second_type > transpose;
  592. typedef boost::transform_iterator< transpose, Iter > type;
  593. static type make(Iter it) { return type(it, transpose()); }
  594. };
  595. template < typename Iter >
  596. typename transpose_iterator_gen< Iter >::type transpose_edges(Iter i)
  597. {
  598. return transpose_iterator_gen< Iter >::make(i);
  599. }
  600. template < typename GraphT, typename VertexIndexMap >
  601. class edge_to_index_pair
  602. {
  603. typedef typename boost::graph_traits< GraphT >::vertices_size_type
  604. vertices_size_type;
  605. typedef typename boost::graph_traits< GraphT >::edge_descriptor
  606. edge_descriptor;
  607. public:
  608. typedef std::pair< vertices_size_type, vertices_size_type > result_type;
  609. edge_to_index_pair() : g(0), index() {}
  610. edge_to_index_pair(const GraphT& g, const VertexIndexMap& index)
  611. : g(&g), index(index)
  612. {
  613. }
  614. result_type operator()(edge_descriptor e) const
  615. {
  616. return result_type(
  617. get(index, source(e, *g)), get(index, target(e, *g)));
  618. }
  619. private:
  620. const GraphT* g;
  621. VertexIndexMap index;
  622. };
  623. template < typename GraphT, typename VertexIndexMap >
  624. edge_to_index_pair< GraphT, VertexIndexMap > make_edge_to_index_pair(
  625. const GraphT& g, const VertexIndexMap& index)
  626. {
  627. return edge_to_index_pair< GraphT, VertexIndexMap >(g, index);
  628. }
  629. template < typename GraphT >
  630. edge_to_index_pair< GraphT,
  631. typename boost::property_map< GraphT,
  632. boost::vertex_index_t >::const_type >
  633. make_edge_to_index_pair(const GraphT& g)
  634. {
  635. typedef typename boost::property_map< GraphT,
  636. boost::vertex_index_t >::const_type VertexIndexMap;
  637. return edge_to_index_pair< GraphT, VertexIndexMap >(
  638. g, get(boost::vertex_index, g));
  639. }
  640. template < typename GraphT, typename VertexIndexMap, typename Iter >
  641. boost::transform_iterator< edge_to_index_pair< GraphT, VertexIndexMap >,
  642. Iter >
  643. make_edge_to_index_pair_iter(
  644. const GraphT& g, const VertexIndexMap& index, Iter it)
  645. {
  646. return boost::transform_iterator<
  647. edge_to_index_pair< GraphT, VertexIndexMap >, Iter >(
  648. it, edge_to_index_pair< GraphT, VertexIndexMap >(g, index));
  649. }
  650. } // namespace detail
  651. template < typename Vertex, typename EdgeIndex >
  652. struct hash< detail::csr_edge_descriptor< Vertex, EdgeIndex > >
  653. {
  654. std::size_t operator()(
  655. detail::csr_edge_descriptor< Vertex, EdgeIndex > const& x) const
  656. {
  657. std::size_t hash = hash_value(x.src);
  658. hash_combine(hash, x.idx);
  659. return hash;
  660. }
  661. };
  662. } // namespace boost
  663. #endif // BOOST_GRAPH_COMPRESSED_SPARSE_ROW_STRUCT_HPP