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