diff --git a/doc/BUILD_DOCS.sh b/doc/BUILD_DOCS.sh
index ac11f274..e18de3b3 100755
--- a/doc/BUILD_DOCS.sh
+++ b/doc/BUILD_DOCS.sh
@@ -10,3 +10,4 @@
for i in read_graphml read_graphviz write_graphml; do
rst2html.py -gdt --link-stylesheet --traceback --trim-footnote-reference-space --footnote-references=superscript --stylesheet=../../../rst.css $i.rst > $i.html
done
+# Also see grid_graph_export_png.sh for figure conversions
diff --git a/doc/Graph.html b/doc/Graph.html
index 2c74f367..08423b10 100644
--- a/doc/Graph.html
+++ b/doc/Graph.html
@@ -62,9 +62,8 @@ href="http://www.sgi.com/tech/stl/DefaultConstructible.html">Default Constructib
An edge descriptor corresponds to a unique edge (u,v) in a
graph. An edge descriptor must be Default Constructible,
- Assignable ,
-and Equality Comparable .
+Assignable , and
+Equality Comparable .
diff --git a/doc/IncidenceGraph.html b/doc/IncidenceGraph.html
index cbdc60b1..29db1946 100644
--- a/doc/IncidenceGraph.html
+++ b/doc/IncidenceGraph.html
@@ -76,7 +76,7 @@ href="../../utility/MultiPassInputIterator.html">MultiPassInputIterator.
boost::graph_traits<G>::degree_size_type
-The unsigned intergral type used for representing the number
+The unsigned integral type used for representing the number
out-edges or incident edges of a vertex.
@@ -108,7 +108,7 @@ directed graphs) or incident edges (for undirected graphs) of vertex
u in graph g . The source vertex of an edge obtained
via an out edge iterator is guaranteed (for both directed and
undirected graphs) to be the vertex u used in the call to
-out_edges(u, g) and the target vertex must the a vertex
+out_edges(u, g) and the target vertex must be a vertex
adjacent to u .[1]
Return type: std::pair<out_edge_iterator, out_edge_iterator>
diff --git a/doc/compressed_sparse_row.html b/doc/compressed_sparse_row.html
index d7cefa17..5086ac68 100644
--- a/doc/compressed_sparse_row.html
+++ b/doc/compressed_sparse_row.html
@@ -40,7 +40,8 @@ function address(host, user) {
The class template compressed_sparse_row_graph is
a graph class that uses the compact Compressed Sparse Row (CSR)
- format to store directed graphs. While CSR graphs have much less
+ format to store directed (and bidirectional) graphs. While CSR graphs have
+ much less
overhead than many other graph formats (e.g., adjacency_list ), they
do not provide any mutability: one cannot add or remove vertices
@@ -67,14 +68,20 @@ function address(host, user) {
providing the offset of the first edge outgoing from each
vertex. Iteration over the out-edges for the i th
vertex in the graph is achieved by
- visiting edge_array[vertex_array[i]] , edge_array[vertex_array[i]+1] ,
+ visiting edge_array[vertex_array[i]] ,
+ edge_array[vertex_array[i]+1] ,
..., edge_array[vertex_array[i+1]] . This format minimizes
memory use to O(n + m) , where n and m are the
number of vertices and edges, respectively. The constants
multiplied by n and m are based on the size of the
integers needed to represent indices into the edge and vertex
arrays, respectively, which can be controlled using
- the template parameters .
+ the template parameters . The
+ Directed template parameter controls whether one edge direction
+ (the default) or both directions are stored. A directed CSR graph has
+ Directed = directedS and a bidirectional CSR graph (only
+ supported with the new interface and with a limited set of constructors)
+ has Directed = bidirectionalS .
Synopsis
@@ -155,7 +162,7 @@ public:
edges_size_type numedges = 0,
const GraphProperty& prop = GraphProperty());
- // New sorted edge list constructors (both interfaces)
+ // New sorted edge list constructors (both interfaces, directed only)
template<typename InputIterator>
compressed_sparse_row_graph (edges_are_sorted_t,
InputIterator edge_begin, InputIterator edge_end,
@@ -171,7 +178,7 @@ public:
edges_size_type numedges = 0,
const GraphProperty& prop = GraphProperty());
- // In-place unsorted edge list constructors (new interface only)
+ // In-place unsorted edge list constructors (new interface and directed only)
template<typename InputIterator>
compressed_sparse_row_graph (construct_inplace_from_sources_and_targets_t,
std::vector<vertex_descriptor>& sources,
@@ -187,7 +194,7 @@ public:
vertices_size_type numverts,
const GraphProperty& prop = GraphProperty());
- // Miscellaneous constructors (both interfaces)
+ // Miscellaneous constructors (both interfaces, directed only)
template<typename Graph, typename VertexIndexMap>
compressed_sparse_row_graph (const Graph& g, const VertexIndexMap& vi,
vertices_size_type numverts,
@@ -199,7 +206,7 @@ public:
template<typename Graph>
explicit compressed_sparse_row_graph (const Graph& g);
- // Graph mutators (both interfaces)
+ // Graph mutators (both interfaces, directed only)
template<typename Graph, typename VertexIndexMap>
void assign (const Graph& g, const VertexIndexMap& vi,
vertices_size_type numverts, edges_size_type numedges);
@@ -224,6 +231,11 @@ std::pair<out_edge_iterator, out_edge_iterator>
out_edges(vertex_descriptor, const compressed_sparse_row_graph&);
degree_size_type out_degree(vertex_descriptor v, const compressed_sparse_row_graph&);
+// Bidirectional Graph requirements (new interface and bidirectional only)
+std::pair<in_edge_iterator, in_edge_iterator>
+ in_edges(vertex_descriptor, const compressed_sparse_row_graph&);
+degree_size_type in_degree(vertex_descriptor v, const compressed_sparse_row_graph&);
+
// Adjacency Graph requirements (both interfaces)
std::pair<adjacency_iterator, adjacency_iterator>
adjacent_vertices(vertex_descriptor, const compressed_sparse_row_graph&);
@@ -243,7 +255,7 @@ vertex_descriptor vertex (vertices_size_type i, const compr
(old interface only)
std::pair<out_edge_iterator, out_edge_iterator>
edge_range (vertex_descriptor u, vertex_descriptor v, const compressed_sparse_row_graph&);
-(old interface only)
+(both interfaces)
std::pair<edge_descriptor, bool>
edge (vertex_descriptor u, vertex_descriptor v, const compressed_sparse_row_graph&);
(both interfaces)
@@ -259,7 +271,7 @@ property_map<compressed_sparse_row_graph, Tag>::const_type
get (PropertyTag, const compressed_sparse_row_graph& g)
template<typename PropertyTag , class X>
-typename property_traits<property_map<compressed_sparse_row_graph, PropertyTag>::const_type>::value_type
+typename property_traits<property_map<compressed_sparse_row_graph, PropertyTag>::const_type>::value_type
get (PropertyTag, const compressed_sparse_row_graph& g, X x)
template<typename PropertyTag , class X, class Value>
@@ -290,19 +302,19 @@ vertex_descriptor add_vertices (vertices_size_type co
template<typename Graph>
edge_descriptor add_edge (vertex_descriptor src, vertex_descriptor tgt, compressed_sparse_row_graph& g);
-(new interface only)
+(new interface and directed only)
template<typename InputIterator, typename Graph>
void add_edges (InputIterator first, InputIterator last, compressed_sparse_row_graph& g);
-(new interface only)
+(new interface and directed only)
template<typename InputIterator, typename EPIter, typename Graph>
void add_edges (InputIterator first, InputIterator last, EPIter ep_first, EPIter ep_last, compressed_sparse_row_graph& g);
-(new interface only)
+(new interface and directed only)
template<typename BidirectionalIterator, typename Graph>
void add_edges_sorted (BidirectionalIterator first, BidirectionalIterator last, compressed_sparse_row_graph& g);
-(new interface only)
+(new interface and directed only)
template<typename BidirectionalIterator, typename EPIter, typename Graph>
void add_edges_sorted (BidirectionalIterator first, BidirectionalIterator last, EPIter ep_iter, compressed_sparse_row_graph& g);
@@ -699,9 +711,7 @@ void add_edges_sorted (BidirectionalIterator
Clears the CSR graph and builds a CSR graph in place from the
structure of another graph. The graph type Graph must
- be a model of IncidenceGraph
- and have a vertex(i, g) function that retrieves the
- i th vertex in the graph.
+ be a model of IncidenceGraph .
Parameters
@@ -772,7 +782,7 @@ void add_edges_sorted (BidirectionalIterator
Returns all edges from u to v . Requires time
- linear in the number of edges outgoing from u .
+ logarithmic in the number of edges outgoing from u .
(This function is only provided by the old interface.)
@@ -789,8 +799,9 @@ void add_edges_sorted (BidirectionalIterator
second value in the pair will be false . If multiple
edges exist from u to v , the first edge will
be returned; use edge_range
- to retrieve all edges.
- (This function is only provided by the old interface.)
+ to retrieve all edges. This function requires time logarithmic in the
+ number of edges outgoing from u for the old interface, and
+ linear time for the new interface.
diff --git a/doc/figs/grid_graph_indexed.png b/doc/figs/grid_graph_indexed.png
new file mode 100644
index 00000000..0636c16e
Binary files /dev/null and b/doc/figs/grid_graph_indexed.png differ
diff --git a/doc/figs/grid_graph_indexed.svg b/doc/figs/grid_graph_indexed.svg
new file mode 100644
index 00000000..246f368c
--- /dev/null
+++ b/doc/figs/grid_graph_indexed.svg
@@ -0,0 +1,1128 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ image/svg+xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+
+
+
+
+ 1
+ 2
+ 5
+ 4
+
+ 3
+
+
+ 8
+ 7
+
+ 6
+
+
+
+
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 2
+ 3
+ 4
+ 5
+ 11
+ 10
+ 8
+ 9
+ 7
+ 6
+ 18
+ 15
+ 21
+ 16
+ 22
+ 19
+ 13
+ 14
+ 20
+ 23
+ 17
+ 12
+
+
diff --git a/doc/figs/grid_graph_unindexed.svg b/doc/figs/grid_graph_unindexed.svg
new file mode 100644
index 00000000..6dd95ec7
--- /dev/null
+++ b/doc/figs/grid_graph_unindexed.svg
@@ -0,0 +1,412 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ image/svg+xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/figs/grid_graph_unwrapped.png b/doc/figs/grid_graph_unwrapped.png
new file mode 100644
index 00000000..ddd4f376
Binary files /dev/null and b/doc/figs/grid_graph_unwrapped.png differ
diff --git a/doc/figs/grid_graph_wrapped.png b/doc/figs/grid_graph_wrapped.png
new file mode 100644
index 00000000..9e9eea8d
Binary files /dev/null and b/doc/figs/grid_graph_wrapped.png differ
diff --git a/doc/grid_graph.html b/doc/grid_graph.html
new file mode 100644
index 00000000..2ca9b71d
--- /dev/null
+++ b/doc/grid_graph.html
@@ -0,0 +1,304 @@
+
+
+
+
+ Boost Graph Library: Grid Graph
+
+
+
+
+
+
+ grid_graph
+
+
+
+
+ Overview
+
+ A grid_graph represents a multi-dimensional,
+ rectangular grid of vertices with user-defined dimension lengths
+ and wrapping.
+
+
+
+ grid_graph models:
+
+
+
+ Defined in
+ boost/graph/grid_graph.hpp
+ with all functions in the boost namespace. All examples are available in a single program file in libs/graph/example/grid_graph_example.cpp
+
+
+ Template Parameters
+
+template <typename std ::size_t Dimensions ,
+ typename VertexIndex = std ::size_t ,
+ typename EdgeIndex = VertexIndex >
+ class grid_graph;
+
+
+
+ Dimensions - Number of dimensions in the graph, must be greater than 2
+
+
+ VertexIndex - Type used for vertex indices, defaults to std::size_t
+
+
+ EdgeIndex - Type used for edge indices, defaults to the same type as VertexIndex
+
+
+
+ Creating a Grid Graph
+
+ The constructor to grid_graph has several overloads to aid in configuring each dimension:
+
+
+
+grid_graph <...>(boost :array <VertexIndex , Dimensions > dimension_lengths);
+
+
+grid_graph <...>(boost :array <VertexIndex , Dimensions > dimension_lengths,
+ bool wrap_all_dimensions);
+
+
+grid_graph <...>(boost :array <VertexIndex , Dimensions > dimension_lengths,
+ boost :array <bool , Dimensions > wrap_dimension);
+
+
+ Example
+
+
+boost ::array <int , 2 > lengths = { { 3 , 3 } };
+
+
+grid_graph <2 > graph(lengths);
+
+
+grid_graph <2 > graph(lengths, true );
+
+
+
+
+
+ Figure 1: A 3x3 two-dimensional, unwrapped grid graph
+
+
+
+
+
+ Figure 2: A 3x3 two-dimensional, wrapped grid graph
+
+
+
+ Indexing
+
+ The grid_graph supports addressing vertices and edges
+ by index. The following functions allow you to convert between
+ vertices, edges, and their associated indices:
+
+
+
+typedef grid_graph <...> Graph ;
+typedef graph_traits <Graph > Traits ;
+
+
+Traits ::vertex_descriptor
+vertex(Traits ::vertices_size_type vertex_index,
+ const Graph& graph);
+
+
+Traits ::vertices_size_type
+get(boost ::vertex_index_t ,
+ Traits ::vertex_descriptor vertex,
+ const Graph& graph);
+
+
+Traits ::edge_descriptor
+edge_at(Traits ::edges_size_type edge_index,
+ const Graph& graph);
+
+
+Traits ::edges_size_type
+get(boost ::edge_index_t ,
+ Traits ::edge_descriptor edge,
+ const Graph& graph);
+
+
+Traits ::edge_descriptor
+out_edge_at(Traits ::vertex_descriptor vertex,
+ Traits ::degree_size_type out_edge_index,
+ const Graph& graph);
+
+
+Traits ::edge_descriptor
+in_edge_at(Traits ::vertex_descriptor vertex,
+ Traits ::degree_size_type in_edge_index,
+ const Graph& graph);
+
+
+ Example
+
+typedef grid_graph <2> Graph ;
+typedef graph_traits <Graph > Traits ;
+
+
+boost ::array <int , 2 > lengths = { { 3 , 3 } };
+Graph graph(lengths);
+
+
+for (Traits ::vertices_size_type v_index = 0 ;
+ v_index < num_vertices(graph); ++v_index) {
+
+
+ std ::cout << "Index of vertex " << v_index << " is " <<
+ get(boost ::vertex_index, graph, vertex(v_index, graph)) << std ::endl;
+
+}
+
+
+for (Traits ::edges_size_type e_index = 0 ;
+ e_index < num_edges(graph); ++e_index) {
+
+
+ std ::cout << "Index of edge " << e_index << " is " <<
+ get(boost ::edge_index, graph, edge_at(e_index, graph)) << std ::endl;
+
+}
+
+
+
+
+
+ Figure 3: 3x3 unwrapped grid_graph with vertex and edge indices shown.
+
+
+
+ Member Functions
+
+ There are several grid_graph specific member functions available:
+
+
+typedef grid_graph <...> Graph ;
+typedef graph_traits <Graph > Traits ;
+
+
+std ::size_t dimensions();
+
+
+Traits ::vertices_size_type length(std ::size_t dimension);
+
+
+bool wrapped(std ::size_t dimension);
+
+Traits ::vertex_descriptor next(Traits ::vertex_descriptor vertex,
+ std ::size_t dimension,
+ Traits ::vertices_size_type distance = 1 );
+
+Traits ::vertex_descriptor previous(Traits ::vertex_descriptor vertex,
+ std ::size_t dimension,
+ Traits ::vertices_size_type distance = 1 );
+
+
+ Example
+
+typedef grid_graph <3 > Graph ;
+typedef graph_traits <Graph > Traits ;
+
+
+boost ::array <std ::size_t , 3 > lengths = { { 3 , 5 , 7 } };
+boost ::array <bool , 3 > wrapped = { { true , false , true } };
+Graph graph(lengths, wrapped);
+
+
+std ::cout << graph.dimensions() << std ::endl;
+
+
+std ::cout << graph.length(0 ) << "x" << graph.length(1 ) <<
+ "x" << graph.length(2 ) << std ::endl;
+
+
+std ::cout << graph.wrapped(0 ) ? "W" : "U" << ", " <<
+ graph.wrapped(1 ) ? "W" : "U" << ", " <<
+ graph.wrapped(2 ) ? "W" : "U" << std ::endl;
+
+
+void print_vertex(Traits ::vertex_descriptor vertex_to_print) {
+ std ::cout << "(" << vertex_to_print[0 ] << ", " << vertex_to_print[1 ] <<
+ ", " << vertex_to_print[2 ] << ")" << std ::endl;
+}
+
+
+Traits ::vertex_descriptor first_vertex = vertex(0 , graph);
+print_vertex(first_vertex);
+
+
+print_vertex(graph.next(first_vertex, 0 ));
+
+
+print_vertex(graph.next(first_vertex, 1 ));
+
+
+print_vertex(graph.next(first_vertex, 2 , 5 ));
+
+
+print_vertex(graph.previous(first_vertex, 0 ));
+
+
+print_vertex(graph.previous(first_vertex, 1 ));
+
+
+print_vertex(graph.previous(first_vertex, 2 , 20 ));
+
+
+
+ Copyright © 2009 Trustees of Indiana University
+
+
+
diff --git a/doc/grid_graph_export_svg.sh b/doc/grid_graph_export_svg.sh
new file mode 100755
index 00000000..03e7cb9c
--- /dev/null
+++ b/doc/grid_graph_export_svg.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+#=======================================================================
+# Copyright 2009 Trustees of Indiana University.
+# Authors: Michael Hansen, Andrew Lumsdaine
+#
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http:#www.boost.org/LICENSE_1_0.txt)
+#=======================================================================
+
+# Unindexed, unwrapped
+inkscape --export-png grid_graph_unwrapped.png --export-id g3150 --export-id-only grid_graph_unindexed.svg
+
+# Unindexed, wrapped
+inkscape --export-png grid_graph_wrapped.png grid_graph_unindexed.svg
+
+# Indexed, unwrapped
+inkscape --export-png grid_graph_indexed.png grid_graph_indexed.svg
\ No newline at end of file
diff --git a/doc/incremental_components.html b/doc/incremental_components.html
index 87765147..ef3ba9b7 100644
--- a/doc/incremental_components.html
+++ b/doc/incremental_components.html
@@ -8,6 +8,18 @@
-->
Boost Graph Library: Incremental Connected Components
+
+
examples/incremental_components.cpp .
-
-typedef adjacency_list <vecS, vecS, undirectedS> Graph;
-typedef graph_traits<Graph>::vertex_descriptor Vertex;
-typedef graph_traits<Graph>::vertices_size_type size_type;
+
+using namespace boost;
-const int N = 6;
-Graph G(N);
+int main(int argc, char* argv[])
+{
+ typedef adjacency_list Graph;
+ typedef graph_traits::vertex_descriptor Vertex;
+ typedef graph_traits::vertices_size_type VertexIndex;
-std::vector<size_type> rank(num_vertices(G));
-std::vector<Vertex> parent(num_vertices(G));
-typedef size_type* Rank;
-typedef Vertex* Parent;
-disjoint_sets<Rank, Parent> ds(&rank[0], &parent[0]);
+ const int VERTEX_COUNT = 6;
+ Graph graph(VERTEX_COUNT);
-initialize_incremental_components(G, ds);
-incremental_components(G, ds);
+ std::vector rank(num_vertices(graph));
+ std::vector parent(num_vertices(graph));
-graph_traits<Graph>::edge_descriptor e;
-bool flag;
-boost::tie(e,flag) = add_edge(0, 1, G);
-ds.union_set(0,1);
+ typedef VertexIndex* Rank;
+ typedef Vertex* Parent;
-boost::tie(e,flag) = add_edge(1, 4, G);
-ds.union_set(1,4);
+ disjoint_sets ds(&rank[0], &parent[0]);
-boost::tie(e,flag) = add_edge(4, 0, G);
-ds.union_set(4,0);
+ initialize_incremental_components(graph, ds);
+ incremental_components(graph, ds);
-boost::tie(e,flag) = add_edge(2, 5, G);
-ds.union_set(2,5);
+ graph_traits::edge_descriptor edge;
+ bool flag;
-cout << "An undirected graph:" << endl;
-print_graph(G, get(vertex_index, G));
-cout << endl;
+ boost::tie(edge, flag) = add_edge(0, 1, graph);
+ ds.union_set(0,1);
-graph_traits<Graph>::vertex_iterator i,end;
-for (boost::tie(i, end) = vertices(G); i != end; ++i)
- cout << "representative[" << *i << "] = " <<
- ds.find_set(*i) << endl;;
-cout << endl;
+ boost::tie(edge, flag) = add_edge(1, 4, graph);
+ ds.union_set(1,4);
-typedef component_index<unsigned int> Components;
-Components components(&parent[0], &parent[0] + parent.size());
+ boost::tie(edge, flag) = add_edge(4, 0, graph);
+ ds.union_set(4,0);
-for (Components::size_type c = 0; c < components.size(); ++c) {
- cout << "component " << c << " contains: ";
- Components::value_type::iterator
- j = components[c].begin(),
- jend = components[c].end();
- for ( ; j != jend; ++j)
- cout << *j << " ";
- cout << endl;
+ boost::tie(edge, flag) = add_edge(2, 5, graph);
+ ds.union_set(2,5);
+
+ std::cout << "An undirected graph:" << std::endl;
+ print_graph(graph, get(boost::vertex_index, graph));
+ std::cout << std::endl;
+
+ BOOST_FOREACH(Vertex current_vertex, vertices(graph)) {
+ std::cout << "representative[" << current_vertex << "] = " <<
+ ds.find_set(current_vertex) << std::endl;
+ }
+
+ std::cout << std::endl;
+
+ typedef component_index Components;
+
+ // NOTE: Because we're using vecS for the graph type, we're
+ // effectively using identity_property_map for a vertex index map.
+ // If we were to use listS instead, the index map would need to be
+ // explicity passed to the component_index constructor.
+ Components components(parent.begin(), parent.end());
+
+ // Iterate through the component indices
+ BOOST_FOREACH(VertexIndex current_index, components) {
+ std::cout << "component " << current_index << " contains: ";
+
+ // Iterate through the child vertex indices for [current_index]
+ BOOST_FOREACH(VertexIndex child_index,
+ components[current_index]) {
+ std::cout << child_index << " ";
+ }
+
+ std::cout << std::endl;
+ }
+
+ return (0);
}
@@ -298,19 +329,14 @@ component_index<Index>
-The component_index functionality is broken in Boost 1.40 and
-earlier versions (see bug 3250 for more
-information).
-
-
-
-The is a class that provides an STL container-like view for the
-components of the graph. Each component is a container-like object,
-and the component_index object provides access to the
-component objects via operator[] . A component_index
-object is initialized with the parents property in the disjoint-sets
-calculated from the incremental_components() function.
+The component_index class provides an STL
+container-like view for the components of the graph. Each component is
+a container-like object, and access is provided via
+the operator[] . A component_index object is
+initialized with the parents property in the disjoint-sets calculated
+from the incremental_components() function. Optionally, a
+vertex -> index property map is passed in
+(identity_property_map is used by default).
@@ -332,82 +358,48 @@ calculated from the incremental_components() function.
-size_type
-The type used for representing the number of components.
+value_type/size_type
+
+The type for a component index (same as Index ).
+
+
+
+
+size_type size()
+
+Returns the number of components in the graph.
+
-value_type
+iterator/const_iterator
-The type for a component object. The component type has the following members.
+Iterators used to traverse the available component indices [0 to size() ).
+
+
+
+
+iterator begin() const
+
+Returns an iterator at the start of the component indices (0).
+
+
+
+
+iterator end() const
+
+Returns an iterator past the end of the component indices (size() ).
-value_type::value_type
+std::pair<component_iterator, component_iterator> operator[size_type index] const
-The value type of a component object is a vertex ID.
+Returns a pair of iterators for the component at index where index is in [0, size() ).
-
-value_type::iterator
-
-This iterator can be used to traverse all of the vertices
-in the component. This iterator dereferences to give a vertex ID.
-
-
-
-
-value_type::const_iterator
-
-The const iterator.
-
-
-
-
-value_type::iterator value_type::begin() const
-
-Return an iterator pointing to the first vertex in the component.
-
-
-
-
-value_type::iterator value_type::end() const
-
-Return an iterator pointing past the end of the last vertex in the
-component.
-
-
-
-
-
-
-template <class ComponentsContainer>
-component_index(const ComponentsContainer& c)
-
-
-
-Construct the component_index using the information
-from the components container c which was the result
-of executing connected_components_on_edgelist .
-
-
-
-
-value_type operator[](size_type i)
-
-Returns the i th component in the graph.
-
-
-
-
-size_type component_index::size()
-
-Returns the number of components in the graph.
-
-
diff --git a/doc/quick_tour.html b/doc/quick_tour.html
index dc300d62..c95fae84 100644
--- a/doc/quick_tour.html
+++ b/doc/quick_tour.html
@@ -210,8 +210,7 @@ choice for the BGL.
The output is:
- edges(g) = (0,1) (0,2) (0,3) (0,4) (2,0) (2,4) (3,0)
- (3,1) (3,4) (4,0) (4,1)
+ edges(g) = (0,1) (0,3) (2,0) (3,2) (2,4) (1,3) (3,4)
The Adjacency Structure
@@ -558,14 +557,14 @@ equipped to handle the use of multiple visitors in the same algorithm
using std::vector;
using std::cout;
using std::endl;
- vector<Vertex> p(num_vertices(G)); //the predecessor array
+ vector<Vertex> p(num_vertices(G), graph_traits<G>::null_vertex()); //the predecessor array
dijkstra_shortest_paths(G, s, distance_map(&d[0]).
visitor(make_predecessor_recorder(&p[0])));
cout << "parents in the tree of shortest paths:" << endl;
for(vi = vertices(G).first; vi != vertices(G).second; ++vi) {
cout << "parent(" << *vi;
- if (p[*vi] == Vertex())
+ if (p[*vi] == graph_traits<G>::null_vertex())
cout << ") = no parent" << endl;
else
cout << ") = " << p[*vi] << endl;
diff --git a/doc/table_of_contents.html b/doc/table_of_contents.html
index 9b7cc51c..b277a077 100644
--- a/doc/table_of_contents.html
+++ b/doc/table_of_contents.html
@@ -110,6 +110,9 @@
Matrix as Graph *
Leda Graph *
Stanford GraphBase
+ Implicit Graphs
+
+ Multi-dimensional grid graph
Iterator Adaptors
diff --git a/example/Jamfile.v2 b/example/Jamfile.v2
index e157a2a4..b57f8ef3 100644
--- a/example/Jamfile.v2
+++ b/example/Jamfile.v2
@@ -19,3 +19,4 @@ exe tiernan_girth_circumference : tiernan_girth_circumference.cpp ;
exe bron_kerbosch_print_cliques : bron_kerbosch_print_cliques.cpp ;
exe bron_kerbosch_clique_number : bron_kerbosch_clique_number.cpp ;
exe mcgregor_subgraphs_example : mcgregor_subgraphs_example.cpp ;
+exe grid_graph_example : grid_graph_example.cpp ;
diff --git a/example/grid_graph_example.cpp b/example/grid_graph_example.cpp
new file mode 100644
index 00000000..1406f2ef
--- /dev/null
+++ b/example/grid_graph_example.cpp
@@ -0,0 +1,86 @@
+//=======================================================================
+// Copyright 2009 Trustees of Indiana University.
+// Authors: Michael Hansen, Andrew Lumsdaine
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//=======================================================================
+
+#include
+#include
+#include
+
+#define DIMENSIONS 3
+using namespace boost;
+
+typedef grid_graph Graph;
+typedef graph_traits Traits;
+
+// Define a simple function to print vertices
+void print_vertex(Traits::vertex_descriptor vertex_to_print) {
+ std::cout << "(" << vertex_to_print[0] << ", " << vertex_to_print[1] <<
+ ", " << vertex_to_print[2] << ")" << std::endl;
+}
+
+int main(int argc, char* argv[]) {
+
+ // Define a 3x5x7 grid_graph where the second dimension doesn't wrap
+ boost::array lengths = { { 3, 5, 7 } };
+ boost::array wrapped = { { true, false, true } };
+ Graph graph(lengths, wrapped);
+
+ // Do a round-trip test of the vertex index functions
+ for (Traits::vertices_size_type v_index = 0;
+ v_index < num_vertices(graph); ++v_index) {
+
+ // The two indicies should always be equal
+ std::cout << "Index of vertex " << v_index << " is " <<
+ get(boost::vertex_index, graph, vertex(v_index, graph)) << std::endl;
+
+ }
+
+ // Do a round-trip test of the edge index functions
+ for (Traits::edges_size_type e_index = 0;
+ e_index < num_edges(graph); ++e_index) {
+
+ // The two indicies should always be equal
+ std::cout << "Index of edge " << e_index << " is " <<
+ get(boost::edge_index, graph, edge_at(e_index, graph)) << std::endl;
+
+ }
+
+ // Print number of dimensions
+ std::cout << graph.dimensions() << std::endl; // prints "3"
+
+ // Print dimension lengths (same order as in the lengths array)
+ std::cout << graph.length(0) << "x" << graph.length(1) <<
+ "x" << graph.length(2) << std::endl; // prints "3x5x7"
+
+ // Print dimension wrapping (W = wrapped, U = unwrapped)
+ std::cout << (graph.wrapped(0) ? "W" : "U") << ", " <<
+ (graph.wrapped(1) ? "W" : "U") << ", " <<
+ (graph.wrapped(2) ? "W" : "U") << std::endl; // prints "W, U, W"
+
+ // Start with the first vertex in the graph
+ Traits::vertex_descriptor first_vertex = vertex(0, graph);
+ print_vertex(first_vertex); // prints "(0, 0, 0)"
+
+ // Print the next vertex in dimension 0
+ print_vertex(graph.next(first_vertex, 0)); // prints "(1, 0, 0)"
+
+ // Print the next vertex in dimension 1
+ print_vertex(graph.next(first_vertex, 1)); // prints "(0, 1, 0)"
+
+ // Print the 5th next vertex in dimension 2
+ print_vertex(graph.next(first_vertex, 2, 5)); // prints "(0, 0, 4)"
+
+ // Print the previous vertex in dimension 0 (wraps)
+ print_vertex(graph.previous(first_vertex, 0)); // prints "(2, 0, 0)"
+
+ // Print the previous vertex in dimension 1 (doesn't wrap, so it's the same)
+ print_vertex(graph.previous(first_vertex, 1)); // prints "(0, 0, 0)"
+
+ // Print the 20th previous vertex in dimension 2 (wraps around twice)
+ print_vertex(graph.previous(first_vertex, 2, 20)); // prints "(0, 0, ?)"
+}
diff --git a/example/incremental-components-eg.cpp b/example/incremental-components-eg.cpp
index 521963ff..2ee63e4d 100644
--- a/example/incremental-components-eg.cpp
+++ b/example/incremental-components-eg.cpp
@@ -1,64 +1,84 @@
//=======================================================================
// Copyright 2001 Jeremy G. Siek, Andrew Lumsdaine, Lie-Quan Lee,
+// Copyright 2009 Trustees of Indiana University.
+// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, Michael Hansen
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
-#include
+
#include
#include
-#include
-#include
+
+#include
#include
-#include
#include
+#include
-int
-main(int, char *[])
+using namespace boost;
+
+int main(int argc, char* argv[])
{
- using namespace boost;
+ typedef adjacency_list Graph;
+ typedef graph_traits::vertex_descriptor Vertex;
+ typedef graph_traits::edge_descriptor Edge;
+ typedef graph_traits::vertices_size_type VertexIndex;
+
// Create a graph
- typedef adjacency_list < vecS, vecS, undirectedS > Graph;
- typedef graph_traits < Graph >::vertex_descriptor Vertex;
- const int N = 6;
- Graph G(N);
- add_edge(0, 1, G);
- add_edge(1, 4, G);
- // create the disjoint-sets object, which requires rank and parent vertex properties
- std::vector < Vertex > rank(num_vertices(G));
- std::vector < Vertex > parent(num_vertices(G));
- typedef graph_traits::vertices_size_type* Rank;
- typedef Vertex* Parent;
- disjoint_sets < Rank, Parent > ds(&rank[0], &parent[0]);
+ const int VERTEX_COUNT = 6;
+ Graph graph(VERTEX_COUNT);
- // determine the connected components, storing the results in the disjoint-sets object
- initialize_incremental_components(G, ds);
- incremental_components(G, ds);
+ add_edge(0, 1, graph);
+ add_edge(1, 4, graph);
+
+ // reate the disjoint-sets object, which requires rank and parent
+ // vertex properties.
+ std::vector rank(num_vertices(graph));
+ std::vector parent(num_vertices(graph));
+
+ typedef VertexIndex* Rank;
+ typedef Vertex* Parent;
+ disjoint_sets ds(&rank[0], &parent[0]);
+
+ // Determine the connected components, storing the results in the
+ // disjoint-sets object.
+ initialize_incremental_components(graph, ds);
+ incremental_components(graph, ds);
// Add a couple more edges and update the disjoint-sets
- graph_traits < Graph >::edge_descriptor e;
- bool flag;
- tie(e, flag) = add_edge(4, 0, G);
+ add_edge(4, 0, graph);
+ add_edge(2, 5, graph);
+
ds.union_set(4, 0);
- tie(e, flag) = add_edge(2, 5, G);
ds.union_set(2, 5);
- graph_traits < Graph >::vertex_iterator iter, end;
- for (tie(iter, end) = vertices(G); iter != end; ++iter)
- std::cout << "representative[" << *iter << "] = " <<
- ds.find_set(*iter) << std::endl;;
+ BOOST_FOREACH(Vertex current_vertex, vertices(graph)) {
+ std::cout << "representative[" << current_vertex << "] = " <<
+ ds.find_set(current_vertex) << std::endl;
+ }
+
std::cout << std::endl;
- typedef component_index < unsigned int >Components;
+ // Generate component index. NOTE: We would need to pass in a vertex
+ // index map into the component_index constructor if our graph type
+ // used listS instead of vecS (identity_property_map is used by
+ // default).
+ typedef component_index Components;
Components components(parent.begin(), parent.end());
- for (Components::size_type i = 0; i < components.size(); ++i) {
- std::cout << "component " << i << " contains: ";
- for (Components::value_type::iterator j = components[i].begin();
- j != components[i].end(); ++j)
- std::cout << *j << " ";
+
+ // Iterate through the component indices
+ BOOST_FOREACH(VertexIndex component_index, components) {
+ std::cout << "component " << component_index << " contains: ";
+
+ // Iterate through the child vertex indices for [component_index]
+ BOOST_FOREACH(VertexIndex child_index,
+ components[component_index]) {
+ std::cout << child_index << " ";
+ }
+
std::cout << std::endl;
}
- return EXIT_SUCCESS;
+ return (0);
}
diff --git a/example/incremental_components.cpp b/example/incremental_components.cpp
index 9e235d2c..f8f156ef 100644
--- a/example/incremental_components.cpp
+++ b/example/incremental_components.cpp
@@ -1,20 +1,20 @@
//=======================================================================
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
-// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
+// Copyright 2009 Trustees of Indiana University.
+// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, Michael Hansen
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
-#include
#include
#include
-#include
-#include
-#include
+
+#include
#include
-#include
+#include
#include
+#include
/*
@@ -45,64 +45,75 @@
*/
-using namespace std;
+using namespace boost;
-int main(int , char* [])
+int main(int argc, char* argv[])
{
- using namespace boost;
typedef adjacency_list Graph;
typedef graph_traits::vertex_descriptor Vertex;
- typedef graph_traits::vertices_size_type size_type;
+ typedef graph_traits::vertices_size_type VertexIndex;
- const int N = 6;
- Graph G(N);
+ const int VERTEX_COUNT = 6;
+ Graph graph(VERTEX_COUNT);
- std::vector rank(num_vertices(G));
- std::vector parent(num_vertices(G));
- typedef size_type* Rank;
+ std::vector rank(num_vertices(graph));
+ std::vector parent(num_vertices(graph));
+
+ typedef VertexIndex* Rank;
typedef Vertex* Parent;
- disjoint_sets ds(&rank[0], &parent[0]);
- initialize_incremental_components(G, ds);
- incremental_components(G, ds);
+ disjoint_sets ds(&rank[0], &parent[0]);
- graph_traits::edge_descriptor e;
+ initialize_incremental_components(graph, ds);
+ incremental_components(graph, ds);
+
+ graph_traits::edge_descriptor edge;
bool flag;
- boost::tie(e,flag) = add_edge(0, 1, G);
+
+ boost::tie(edge, flag) = add_edge(0, 1, graph);
ds.union_set(0,1);
- boost::tie(e,flag) = add_edge(1, 4, G);
+ boost::tie(edge, flag) = add_edge(1, 4, graph);
ds.union_set(1,4);
- boost::tie(e,flag) = add_edge(4, 0, G);
+ boost::tie(edge, flag) = add_edge(4, 0, graph);
ds.union_set(4,0);
- boost::tie(e,flag) = add_edge(2, 5, G);
+ boost::tie(edge, flag) = add_edge(2, 5, graph);
ds.union_set(2,5);
- cout << "An undirected graph:" << endl;
- print_graph(G, get(vertex_index, G));
- cout << endl;
+ std::cout << "An undirected graph:" << std::endl;
+ print_graph(graph, get(boost::vertex_index, graph));
+ std::cout << std::endl;
- graph_traits::vertex_iterator i,end;
- for (boost::tie(i, end) = vertices(G); i != end; ++i)
- cout << "representative[" << *i << "] = " <<
- ds.find_set(*i) << endl;;
- cout << endl;
-
- typedef component_index Components;
- Components components(&parent[0], &parent[0] + parent.size());
-
- for (Components::size_type c = 0; c < components.size(); ++c) {
- cout << "component " << c << " contains: ";
- Components::value_type::iterator
- j = components[c].begin(),
- jend = components[c].end();
- for ( ; j != jend; ++j)
- cout << *j << " ";
- cout << endl;
+ BOOST_FOREACH(Vertex current_vertex, vertices(graph)) {
+ std::cout << "representative[" << current_vertex << "] = " <<
+ ds.find_set(current_vertex) << std::endl;
}
- return 0;
+ std::cout << std::endl;
+
+ typedef component_index Components;
+
+ // NOTE: Because we're using vecS for the graph type, we're
+ // effectively using identity_property_map for a vertex index map.
+ // If we were to use listS instead, the index map would need to be
+ // explicitly passed to the component_index constructor.
+ Components components(parent.begin(), parent.end());
+
+ // Iterate through the component indices
+ BOOST_FOREACH(VertexIndex current_index, components) {
+ std::cout << "component " << current_index << " contains: ";
+
+ // Iterate through the child vertex indices for [current_index]
+ BOOST_FOREACH(VertexIndex child_index,
+ components[current_index]) {
+ std::cout << child_index << " ";
+ }
+
+ std::cout << std::endl;
+ }
+
+ return (0);
}
diff --git a/example/incremental_components.expected b/example/incremental_components.expected
index c1e0b510..e5cdd4a6 100644
--- a/example/incremental_components.expected
+++ b/example/incremental_components.expected
@@ -13,6 +13,6 @@ representative[3] = 3
representative[4] = 1
representative[5] = 5
-component 0 contains: 4 1 0
+component 0 contains: 1 4 0
component 1 contains: 3
component 2 contains: 5 2
diff --git a/example/quick_tour.cpp b/example/quick_tour.cpp
index ecabb4c9..ffb08488 100644
--- a/example/quick_tour.cpp
+++ b/example/quick_tour.cpp
@@ -18,14 +18,14 @@
using namespace boost;
template struct exercise_vertex {
- exercise_vertex(Graph& g_) : g(g_) { }
+ exercise_vertex(Graph& g_, const char name_[]) : g(g_),name(name_) { }
typedef typename graph_traits::vertex_descriptor Vertex;
void operator()(const Vertex& v) const
{
using namespace boost;
typename property_map::type
vertex_id = get(vertex_index, g);
- std::cout << "vertex: " << get(vertex_id, v) << std::endl;
+ std::cout << "vertex: " << name[get(vertex_id, v)] << std::endl;
// Write out the outgoing edges
std::cout << "\tout-edges: ";
@@ -36,8 +36,8 @@ template struct exercise_vertex {
{
e = *out_i;
Vertex src = source(e, g), targ = target(e, g);
- std::cout << "(" << get(vertex_id, src)
- << "," << get(vertex_id, targ) << ") ";
+ std::cout << "(" << name[get(vertex_id, src)]
+ << "," << name[get(vertex_id, targ)] << ") ";
}
std::cout << std::endl;
@@ -48,8 +48,8 @@ template struct exercise_vertex {
{
e = *in_i;
Vertex src = source(e, g), targ = target(e, g);
- std::cout << "(" << get(vertex_id, src)
- << "," << get(vertex_id, targ) << ") ";
+ std::cout << "(" << name[get(vertex_id, src)]
+ << "," << name[get(vertex_id, targ)] << ") ";
}
std::cout << std::endl;
@@ -57,10 +57,11 @@ template struct exercise_vertex {
std::cout << "\tadjacent vertices: ";
typename graph_traits::adjacency_iterator ai, ai_end;
for (tie(ai,ai_end) = adjacent_vertices(v, g); ai != ai_end; ++ai)
- std::cout << get(vertex_id, *ai) << " ";
+ std::cout << name[get(vertex_id, *ai)] << " ";
std::cout << std::endl;
}
Graph& g;
+ const char *name;
};
@@ -73,7 +74,7 @@ int main(int,char*[])
// Make convenient labels for the vertices
enum { A, B, C, D, E, N };
const int num_vertices = N;
- const char* name = "ABCDE";
+ const char name[] = "ABCDE";
// writing out the edges in the graph
typedef std::pair Edge;
@@ -120,7 +121,7 @@ int main(int,char*[])
std::cout << std::endl;
std::for_each(vertices(g).first, vertices(g).second,
- exercise_vertex(g));
+ exercise_vertex(g, name));
std::map graph_attr, vertex_attr, edge_attr;
graph_attr["size"] = "3,3";
diff --git a/include/boost/graph/compressed_sparse_row_graph.hpp b/include/boost/graph/compressed_sparse_row_graph.hpp
index e5144f7e..b4f01352 100644
--- a/include/boost/graph/compressed_sparse_row_graph.hpp
+++ b/include/boost/graph/compressed_sparse_row_graph.hpp
@@ -26,6 +26,8 @@
#include
#include // For keep_all
#include
+#include
+#include
#include
#include
#include
@@ -131,42 +133,21 @@ enum edges_are_unsorted_global_t {edges_are_unsorted_global};
#define BOOST_CSR_GRAPH_TYPE \
compressed_sparse_row_graph
-
-// Forward declaration of CSR edge descriptor type, needed to pass to
-// indexed_edge_properties.
-template
-class csr_edge_descriptor;
-
-namespace detail {
- template
- size_t
- reserve_count_for_single_pass_helper(InputIterator, InputIterator,
- std::input_iterator_tag)
- {
- // Do nothing: we have no idea how much storage to reserve.
- return 0;
- }
-
- template
- size_t
- reserve_count_for_single_pass_helper(InputIterator first, InputIterator last,
- std::random_access_iterator_tag)
- {
- using std::distance;
- typename std::iterator_traits::difference_type n =
- distance(first, last);
- return (size_t)n;
- }
-
- template
- size_t
- reserve_count_for_single_pass(InputIterator first, InputIterator last) {
- typedef typename std::iterator_traits::iterator_category
- category;
- return reserve_count_for_single_pass_helper(first, last, category());
- }
+#define BOOST_DIR_CSR_GRAPH_TEMPLATE_PARMS \
+ typename VertexProperty, typename EdgeProperty, \
+ typename GraphProperty, typename Vertex, typename EdgeIndex
+#define BOOST_DIR_CSR_GRAPH_TYPE \
+ compressed_sparse_row_graph
+#define BOOST_BIDIR_CSR_GRAPH_TEMPLATE_PARMS \
+ typename VertexProperty, typename EdgeProperty, \
+ typename GraphProperty, typename Vertex, typename EdgeIndex
+#define BOOST_BIDIR_CSR_GRAPH_TYPE \
+ compressed_sparse_row_graph
#ifdef BOOST_GRAPH_USE_NEW_CSR_INTERFACE
+namespace detail {
template
struct default_construct_iterator: public boost::iterator_facade, T, boost::random_access_traversal_tag, const T&> {
typedef boost::iterator_facade, T, std::random_access_iterator_tag, const T&> base_type;
@@ -197,8 +178,8 @@ namespace detail {
return t.template get();
}
};
-#endif // BOOST_GRAPH_USE_NEW_CSR_INTERFACE
}
+#endif // BOOST_GRAPH_USE_NEW_CSR_INTERFACE
/** Compressed sparse row graph.
*
@@ -211,59 +192,39 @@ template
-class compressed_sparse_row_graph
- : public detail::indexed_vertex_properties,
- public detail::indexed_edge_properties >
+class compressed_sparse_row_graph; // Not defined
+template
+class compressed_sparse_row_graph
+ : public detail::indexed_vertex_properties
{
public:
typedef detail::indexed_vertex_properties
inherited_vertex_properties;
- typedef detail::indexed_edge_properties >
- inherited_edge_properties;
-
public:
// For Property Graph
typedef GraphProperty graph_property_type;
- protected:
- template
- void
- maybe_reserve_edge_list_storage(InputIterator, InputIterator,
- std::input_iterator_tag)
- {
- // Do nothing: we have no idea how much storage to reserve.
- }
-
- template
- void
- maybe_reserve_edge_list_storage(InputIterator first, InputIterator last,
- std::forward_iterator_tag)
- {
- using std::distance;
- typename std::iterator_traits::difference_type n =
- distance(first, last);
- m_column.reserve(n);
- inherited_edge_properties::reserve(n);
- }
+ typedef detail::compressed_sparse_row_structure forward_type;
public:
/* At this time, the compressed sparse row graph can only be used to
- * create a directed graph. In the future, bidirectional and
+ * create directed and bidirectional graphs. In the future,
* undirected CSR graphs will also be supported.
*/
- BOOST_STATIC_ASSERT((is_same::value));
+ // BOOST_STATIC_ASSERT((is_same::value));
// Concept requirements:
// For Graph
typedef Vertex vertex_descriptor;
- typedef csr_edge_descriptor edge_descriptor;
+ typedef detail::csr_edge_descriptor edge_descriptor;
typedef directed_tag directed_category;
typedef allow_parallel_edge_tag edge_parallel_category;
@@ -282,14 +243,14 @@ class compressed_sparse_row_graph
typedef EdgeIndex edges_size_type;
// For IncidenceGraph
- class out_edge_iterator;
+ typedef detail::csr_out_edge_iterator out_edge_iterator;
typedef EdgeIndex degree_size_type;
// For AdjacencyGraph
typedef typename std::vector::const_iterator adjacency_iterator;
// For EdgeListGraph
- class edge_iterator;
+ typedef detail::csr_edge_iterator edge_iterator;
// For BidirectionalGraph (not implemented)
typedef void in_edge_iterator;
@@ -297,110 +258,20 @@ class compressed_sparse_row_graph
// For internal use
typedef csr_graph_tag graph_tag;
+ typedef typename forward_type::inherited_edge_properties::edge_bundled edge_bundled;
+ typedef typename forward_type::inherited_edge_properties::edge_push_back_type edge_push_back_type;
+ typedef typename forward_type::inherited_edge_properties::edge_property_type edge_property_type;
+
// Constructors
// Default constructor: an empty graph.
- compressed_sparse_row_graph()
- : m_rowstart(1, EdgeIndex(0)), m_column(0), m_property()
-#ifdef BOOST_GRAPH_USE_OLD_CSR_INTERFACE
- , m_last_source(0)
-#endif // BOOST_GRAPH_USE_OLD_CSR_INTERFACE
- {}
+ compressed_sparse_row_graph(): m_property() {}
// With numverts vertices
compressed_sparse_row_graph(vertices_size_type numverts)
- : inherited_vertex_properties(numverts), m_rowstart(numverts + 1),
- m_column(0)
-#ifdef BOOST_GRAPH_USE_OLD_CSR_INTERFACE
- , m_last_source(numverts)
-#endif // BOOST_GRAPH_USE_OLD_CSR_INTERFACE
- {
- for (Vertex v = 0; v < numverts + 1; ++v)
- m_rowstart[v] = 0;
- }
+ : inherited_vertex_properties(numverts), m_forward(numverts) {}
#ifdef BOOST_GRAPH_USE_NEW_CSR_INTERFACE
- // Rebuild graph from number of vertices and multi-pass unsorted list of
- // edges (filtered using edge_pred and mapped using global_to_local)
- template
- void
- assign_unsorted_multi_pass_edges(MultiPassInputIterator edge_begin,
- MultiPassInputIterator edge_end,
- vertices_size_type numlocalverts,
- const GlobalToLocal& global_to_local,
- const EdgePred& edge_pred) {
- m_rowstart.clear();
- m_rowstart.resize(numlocalverts + 1, 0);
- // Put the degree of each vertex v into m_rowstart[v + 1]
- for (MultiPassInputIterator i = edge_begin; i != edge_end; ++i)
- if (edge_pred(*i))
- ++m_rowstart[get(global_to_local, i->first) + 1];
-
- // Compute the partial sum of the degrees to get the actual values of
- // m_rowstart
- EdgeIndex start_of_this_row = 0;
- m_rowstart[0] = start_of_this_row;
- for (vertices_size_type i = 1; i <= numlocalverts; ++i) {
- start_of_this_row += m_rowstart[i];
- m_rowstart[i] = start_of_this_row;
- }
- m_column.resize(m_rowstart.back());
-
- // Histogram sort the edges by their source vertices, putting the targets
- // into m_column. The index current_insert_positions[v] contains the next
- // location to insert out edges for vertex v.
- std::vector
- current_insert_positions(m_rowstart.begin(), m_rowstart.begin() + numlocalverts);
- for (; edge_begin != edge_end; ++edge_begin)
- if (edge_pred(*edge_begin))
- m_column[current_insert_positions[get(global_to_local, edge_begin->first)]++] = edge_begin->second;
- }
-
- // Rebuild graph from number of vertices and multi-pass unsorted list of
- // edges and their properties (filtered using edge_pred and mapped using
- // global_to_local)
- template
- void
- assign_unsorted_multi_pass_edges(MultiPassInputIterator edge_begin,
- MultiPassInputIterator edge_end,
- EdgePropertyIterator ep_iter,
- vertices_size_type numlocalverts,
- const GlobalToLocal& global_to_local,
- const EdgePred& edge_pred) {
- m_rowstart.clear();
- m_rowstart.resize(numlocalverts + 1, 0);
- // Put the degree of each vertex v into m_rowstart[v + 1]
- for (MultiPassInputIterator i = edge_begin; i != edge_end; ++i)
- if (edge_pred(*i))
- ++m_rowstart[get(global_to_local, i->first) + 1];
-
- // Compute the partial sum of the degrees to get the actual values of
- // m_rowstart
- EdgeIndex start_of_this_row = 0;
- m_rowstart[0] = start_of_this_row;
- for (vertices_size_type i = 1; i <= numlocalverts; ++i) {
- start_of_this_row += m_rowstart[i];
- m_rowstart[i] = start_of_this_row;
- }
- m_column.resize(m_rowstart.back());
- inherited_edge_properties::resize(m_rowstart.back());
-
- // Histogram sort the edges by their source vertices, putting the targets
- // into m_column. The index current_insert_positions[v] contains the next
- // location to insert out edges for vertex v.
- std::vector
- current_insert_positions(m_rowstart.begin(), m_rowstart.begin() + numlocalverts);
- for (; edge_begin != edge_end; ++edge_begin, ++ep_iter) {
- if (edge_pred(*edge_begin)) {
- vertices_size_type source = get(global_to_local, edge_begin->first);
- EdgeIndex insert_pos = current_insert_positions[source];
- ++current_insert_positions[source];
- m_column[insert_pos] = edge_begin->second;
- inherited_edge_properties::write_by_index(insert_pos, *ep_iter);
- }
- }
- }
-
// From number of vertices and unsorted list of edges
template
compressed_sparse_row_graph(edges_are_unsorted_multi_pass_t,
@@ -408,13 +279,9 @@ class compressed_sparse_row_graph
MultiPassInputIterator edge_end,
vertices_size_type numverts,
const GraphProperty& prop = GraphProperty())
- : inherited_vertex_properties(numverts), m_rowstart(),
- m_column(0), m_property(prop)
+ : inherited_vertex_properties(numverts), m_property(prop)
{
- assign_unsorted_multi_pass_edges(edge_begin, edge_end, numverts, identity_property_map(), keep_all());
-
- // Default-construct properties for edges
- inherited_edge_properties::resize(m_column.size());
+ m_forward.assign_unsorted_multi_pass_edges(edge_begin, edge_end, numverts, identity_property_map(), keep_all());
}
// From number of vertices and unsorted list of edges, plus edge properties
@@ -425,116 +292,43 @@ class compressed_sparse_row_graph
EdgePropertyIterator ep_iter,
vertices_size_type numverts,
const GraphProperty& prop = GraphProperty())
- : inherited_vertex_properties(numverts), m_rowstart(),
- m_column(0), m_property(prop)
+ : inherited_vertex_properties(numverts), m_forward(), m_property(prop)
{
- assign_unsorted_multi_pass_edges(edge_begin, edge_end, ep_iter, numverts, identity_property_map(), keep_all());
+ m_forward.assign_unsorted_multi_pass_edges(edge_begin, edge_end, ep_iter, numverts, identity_property_map(), keep_all());
}
// From number of vertices and unsorted list of edges, with filter and
// global-to-local map
- template
+ template
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 EdgePred& edge_pred,
+ const SourcePred& source_pred,
const GraphProperty& prop = GraphProperty())
- : inherited_vertex_properties(numlocalverts), m_rowstart(),
- m_column(0), m_property(prop)
+ : inherited_vertex_properties(numlocalverts), m_forward(), m_property(prop)
{
- assign_unsorted_multi_pass_edges(edge_begin, edge_end, numlocalverts, global_to_local, edge_pred);
-
- // Default-construct properties for edges
- inherited_edge_properties::resize(m_column.size());
+ m_forward.assign_unsorted_multi_pass_edges(edge_begin, edge_end, numlocalverts, global_to_local, source_pred);
}
// From number of vertices and unsorted list of edges, plus edge properties,
// with filter and global-to-local map
- template
+ template
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 EdgePred& edge_pred,
+ const SourcePred& source_pred,
const GraphProperty& prop = GraphProperty())
- : inherited_vertex_properties(numlocalverts), m_rowstart(),
- m_column(0), m_property(prop)
+ : inherited_vertex_properties(numlocalverts), m_forward(), m_property(prop)
{
- assign_unsorted_multi_pass_edges(edge_begin, edge_end, ep_iter, numlocalverts, global_to_local, edge_pred);
+ m_forward.assign_unsorted_multi_pass_edges(edge_begin, edge_end, ep_iter, numlocalverts, global_to_local, source_pred);
}
#endif // BOOST_GRAPH_USE_NEW_CSR_INTERFACE
- // Assign from number of vertices and sorted list of edges
- template
- void assign_from_sorted_edges(
- InputIterator edge_begin, InputIterator edge_end,
- const GlobalToLocal& global_to_local,
- const EdgePred& edge_pred,
- vertices_size_type numlocalverts,
- edges_size_type numedges_or_zero) {
- m_column.clear();
- m_column.reserve(numedges_or_zero);
- inherited_vertex_properties::resize(numlocalverts);
- m_rowstart.resize(numlocalverts + 1);
- EdgeIndex current_edge = 0;
- Vertex current_vertex_plus_one = 1;
- m_rowstart[0] = 0;
- for (InputIterator ei = edge_begin; ei != edge_end; ++ei) {
- if (!edge_pred(*ei)) continue;
- Vertex src = get(global_to_local, ei->first);
- Vertex tgt = ei->second;
- for (; current_vertex_plus_one != src + 1; ++current_vertex_plus_one)
- m_rowstart[current_vertex_plus_one] = current_edge;
- m_column.push_back(tgt);
- ++current_edge;
- }
-
- // The remaining vertices have no edges
- for (; current_vertex_plus_one != numlocalverts + 1; ++current_vertex_plus_one)
- m_rowstart[current_vertex_plus_one] = current_edge;
-
- // Default-construct properties for edges
- inherited_edge_properties::resize(m_column.size());
- }
-
- // Assign from number of vertices and sorted list of edges
- template
- void assign_from_sorted_edges(
- InputIterator edge_begin, InputIterator edge_end,
- EdgePropertyIterator ep_iter,
- const GlobalToLocal& global_to_local,
- const EdgePred& edge_pred,
- vertices_size_type numlocalverts,
- edges_size_type numedges_or_zero) {
- m_column.clear();
- m_column.reserve(numedges_or_zero);
- inherited_edge_properties::clear();
- inherited_edge_properties::reserve(numedges_or_zero);
- inherited_vertex_properties::resize(numlocalverts);
- m_rowstart.resize(numlocalverts + 1);
- EdgeIndex current_edge = 0;
- Vertex current_vertex_plus_one = 1;
- m_rowstart[0] = 0;
- for (InputIterator ei = edge_begin; ei != edge_end; ++ei, ++ep_iter) {
- if (!edge_pred(*ei)) continue;
- Vertex src = get(global_to_local, ei->first);
- Vertex tgt = ei->second;
- for (; current_vertex_plus_one != src + 1; ++current_vertex_plus_one)
- m_rowstart[current_vertex_plus_one] = current_edge;
- m_column.push_back(tgt);
- inherited_edge_properties::push_back(*ep_iter);
- ++current_edge;
- }
-
- // The remaining vertices have no edges
- for (; current_vertex_plus_one != numlocalverts + 1; ++current_vertex_plus_one)
- m_rowstart[current_vertex_plus_one] = current_edge;
- }
-
#ifdef BOOST_GRAPH_USE_OLD_CSR_INTERFACE
// From number of vertices and sorted list of edges (deprecated
@@ -544,17 +338,10 @@ class compressed_sparse_row_graph
vertices_size_type numverts,
edges_size_type numedges = 0,
const GraphProperty& prop = GraphProperty())
- : m_property(prop), m_last_source(numverts)
+ : m_property(prop)
{
- // Reserving storage in advance can save us lots of time and
- // memory, but it can only be done if we have forward iterators or
- // the user has supplied the number of edges.
- if (numedges == 0) {
- typedef typename std::iterator_traits::iterator_category
- category;
- numedges = detail::reserve_count_for_single_pass(edge_begin, edge_end);
- }
- assign_from_sorted_edges(edge_begin, edge_end, identity_property_map(), keep_all(), numverts, numedges);
+ m_forward.assign_from_sorted_edges(edge_begin, edge_end, identity_property_map(), keep_all(), numverts, numedges);
+ inherited_vertex_properties::resize(numverts);
}
// From number of vertices and sorted list of edges (deprecated
@@ -565,17 +352,10 @@ class compressed_sparse_row_graph
vertices_size_type numverts,
edges_size_type numedges = 0,
const GraphProperty& prop = GraphProperty())
- : m_property(prop), m_last_source(numverts)
+ : m_property(prop)
{
- // Reserving storage in advance can save us lots of time and
- // memory, but it can only be done if we have forward iterators or
- // the user has supplied the number of edges.
- if (numedges == 0) {
- typedef typename std::iterator_traits::iterator_category
- category;
- numedges = detail::reserve_count_for_single_pass(edge_begin, edge_end);
- }
- assign_from_sorted_edges(edge_begin, edge_end, ep_iter, identity_property_map(), keep_all(), numverts, numedges);
+ m_forward.assign_from_sorted_edges(edge_begin, edge_end, ep_iter, identity_property_map(), keep_all(), numverts, numedges);
+ inherited_vertex_properties::resize(numverts);
}
#endif // BOOST_GRAPH_USE_OLD_CSR_INTERFACE
@@ -588,19 +368,9 @@ class compressed_sparse_row_graph
edges_size_type numedges = 0,
const GraphProperty& prop = GraphProperty())
: m_property(prop)
-#ifdef BOOST_GRAPH_USE_OLD_CSR_INTERFACE
- , m_last_source(numverts)
-#endif // BOOST_GRAPH_USE_OLD_CSR_INTERFACE
{
- // Reserving storage in advance can save us lots of time and
- // memory, but it can only be done if we have forward iterators or
- // the user has supplied the number of edges.
- if (numedges == 0) {
- typedef typename std::iterator_traits::iterator_category
- category;
- numedges = detail::reserve_count_for_single_pass(edge_begin, edge_end);
- }
- assign_from_sorted_edges(edge_begin, edge_end, identity_property_map(), keep_all(), numverts, numedges);
+ m_forward.assign_from_sorted_edges(edge_begin, edge_end, identity_property_map(), keep_all(), numverts, numedges);
+ inherited_vertex_properties::resize(numverts);
}
// From number of vertices and sorted list of edges (new interface)
@@ -612,53 +382,39 @@ class compressed_sparse_row_graph
edges_size_type numedges = 0,
const GraphProperty& prop = GraphProperty())
: m_property(prop)
-#ifdef BOOST_GRAPH_USE_OLD_CSR_INTERFACE
- , m_last_source(numverts)
-#endif // BOOST_GRAPH_USE_OLD_CSR_INTERFACE
{
- // Reserving storage in advance can save us lots of time and
- // memory, but it can only be done if we have forward iterators or
- // the user has supplied the number of edges.
- if (numedges == 0) {
- typedef typename std::iterator_traits::iterator_category
- category;
- numedges = detail::reserve_count_for_single_pass(edge_begin, edge_end);
- }
- assign_from_sorted_edges(edge_begin, edge_end, ep_iter, identity_property_map(), keep_all(), numverts, numedges);
+ m_forward.assign_from_sorted_edges(edge_begin, edge_end, ep_iter, identity_property_map(), keep_all(), numverts, numedges);
+ inherited_vertex_properties::resize(numverts);
}
#ifdef BOOST_GRAPH_USE_NEW_CSR_INTERFACE
// From number of vertices and sorted list of edges, filtered and global (new interface)
- template
+ template
compressed_sparse_row_graph(edges_are_sorted_global_t,
InputIterator edge_begin, InputIterator edge_end,
const GlobalToLocal& global_to_local,
- const EdgePred& edge_pred,
+ const SourcePred& source_pred,
vertices_size_type numverts,
const GraphProperty& prop = GraphProperty())
: m_property(prop)
-#ifdef BOOST_GRAPH_USE_OLD_CSR_INTERFACE
- , m_last_source(numverts)
-#endif // BOOST_GRAPH_USE_OLD_CSR_INTERFACE
{
- assign_from_sorted_edges(edge_begin, edge_end, global_to_local, edge_pred, numverts, 0);
+ m_forward.assign_from_sorted_edges(edge_begin, edge_end, global_to_local, source_pred, numverts, 0);
+ inherited_vertex_properties::resize(numverts);
}
// From number of vertices and sorted list of edges (new interface)
- template
+ template
compressed_sparse_row_graph(edges_are_sorted_global_t,
InputIterator edge_begin, InputIterator edge_end,
EdgePropertyIterator ep_iter,
const GlobalToLocal& global_to_local,
- const EdgePred& edge_pred,
+ const SourcePred& source_pred,
vertices_size_type numverts,
const GraphProperty& prop = GraphProperty())
: m_property(prop)
-#ifdef BOOST_GRAPH_USE_OLD_CSR_INTERFACE
- , m_last_source(numverts)
-#endif // BOOST_GRAPH_USE_OLD_CSR_INTERFACE
{
- assign_from_sorted_edges(edge_begin, edge_end, ep_iter, global_to_local, edge_pred, numverts, 0);
+ m_forward.assign_from_sorted_edges(edge_begin, edge_end, ep_iter, global_to_local, source_pred, numverts, 0);
+ inherited_vertex_properties::resize(numverts);
}
// From number of vertices and mutable vectors of sources and targets;
@@ -669,10 +425,9 @@ class compressed_sparse_row_graph
std::vector& targets,
vertices_size_type numverts,
const GraphProperty& prop = GraphProperty())
- : inherited_vertex_properties(numverts), m_rowstart(),
- m_column(), m_property(prop)
+ : inherited_vertex_properties(numverts), m_property(prop)
{
- assign_sources_and_targets_global(sources, targets, numverts, boost::identity_property_map());
+ m_forward.assign_sources_and_targets_global(sources, targets, numverts, boost::identity_property_map());
}
// From number of vertices and mutable vectors of sources and targets,
@@ -687,10 +442,9 @@ class compressed_sparse_row_graph
vertices_size_type numlocalverts,
GlobalToLocal global_to_local,
const GraphProperty& prop = GraphProperty())
- : inherited_vertex_properties(numlocalverts), m_rowstart(),
- m_column(), m_property(prop)
+ : inherited_vertex_properties(numlocalverts), m_property(prop)
{
- assign_sources_and_targets_global(sources, targets, numlocalverts, global_to_local);
+ m_forward.assign_sources_and_targets_global(sources, targets, numlocalverts, global_to_local);
}
// From number of vertices and mutable vectors of sources, targets, and edge
@@ -699,13 +453,12 @@ class compressed_sparse_row_graph
compressed_sparse_row_graph(construct_inplace_from_sources_and_targets_t,
std::vector& sources,
std::vector& targets,
- std::vector& edge_props,
+ std::vector& edge_props,
vertices_size_type numverts,
const GraphProperty& prop = GraphProperty())
- : inherited_vertex_properties(numverts), m_rowstart(),
- m_column(), m_property(prop)
+ : inherited_vertex_properties(numverts), m_property(prop)
{
- assign_sources_and_targets_global(sources, targets, edge_props, numverts, boost::identity_property_map());
+ m_forward.assign_sources_and_targets_global(sources, targets, edge_props, numverts, boost::identity_property_map());
}
// From number of vertices and mutable vectors of sources and targets and
@@ -717,14 +470,13 @@ class compressed_sparse_row_graph
compressed_sparse_row_graph(construct_inplace_from_sources_and_targets_global_t,
std::vector& sources,
std::vector& targets,
- std::vector& edge_props,
+ std::vector& edge_props,
vertices_size_type numlocalverts,
GlobalToLocal global_to_local,
const GraphProperty& prop = GraphProperty())
- : inherited_vertex_properties(numlocalverts), m_rowstart(),
- m_column(), m_property(prop)
+ : inherited_vertex_properties(numlocalverts), m_property(prop)
{
- assign_sources_and_targets_global(sources, targets, edge_props, numlocalverts, global_to_local);
+ m_forward.assign_sources_and_targets_global(sources, targets, edge_props, numlocalverts, global_to_local);
}
// From number of vertices and single-pass range of unsorted edges. Data is
@@ -734,19 +486,12 @@ class compressed_sparse_row_graph
InputIterator edge_begin, InputIterator edge_end,
vertices_size_type numverts,
const GraphProperty& prop = GraphProperty())
- : inherited_vertex_properties(numverts), m_rowstart(),
- m_column(), m_property(prop)
+ : inherited_vertex_properties(numverts), m_property(prop)
{
std::vector sources, targets;
- size_t reserve_size
- = detail::reserve_count_for_single_pass(edge_begin, edge_end);
- sources.reserve(reserve_size);
- targets.reserve(reserve_size);
- for (; edge_begin != edge_end; ++edge_begin) {
- sources.push_back(edge_begin->first);
- targets.push_back(edge_begin->second);
- }
- assign_sources_and_targets_global(sources, targets, numverts, boost::identity_property_map());
+ boost::graph::detail::split_into_separate_coords
+ (edge_begin, edge_end, sources, targets);
+ m_forward.assign_sources_and_targets_global(sources, targets, numverts, boost::identity_property_map());
}
// From number of vertices and single-pass range of unsorted edges and
@@ -758,45 +503,35 @@ class compressed_sparse_row_graph
EdgePropertyIterator ep_iter,
vertices_size_type numverts,
const GraphProperty& prop = GraphProperty())
- : inherited_vertex_properties(numverts), m_rowstart(),
- m_column(), m_property(prop)
+ : inherited_vertex_properties(numverts), m_property(prop)
{
std::vector sources, targets;
- std::vector edge_props;
- size_t reserve_size
- = detail::reserve_count_for_single_pass(edge_begin, edge_end);
- sources.reserve(reserve_size);
- targets.reserve(reserve_size);
- edge_props.reserve(reserve_size);
- for (; edge_begin != edge_end; ++edge_begin, ++ep_iter) {
- sources.push_back(edge_begin->first);
- targets.push_back(edge_begin->second);
- edge_props.push_back(*ep_iter);
+ boost::graph::detail::split_into_separate_coords
+ (edge_begin, edge_end, sources, targets);
+ size_t numedges = sources.size();
+ std::vector edge_props(numedges);
+ for (size_t i = 0; i < numedges; ++i) {
+ edge_props[i] = *ep_iter++;
}
- assign_sources_and_targets_global(sources, targets, edge_props, numverts, boost::identity_property_map());
+ m_forward.assign_sources_and_targets_global(sources, targets, edge_props, numverts, boost::identity_property_map());
}
// From number of vertices and single-pass range of unsorted edges. Data is
// cached in coordinate form before creating the actual graph. Edges are
// filtered and transformed for use in a distributed graph.
- template
+ template
compressed_sparse_row_graph(edges_are_unsorted_global_t,
InputIterator edge_begin, InputIterator edge_end,
vertices_size_type numlocalverts,
GlobalToLocal global_to_local,
- const EdgePred& edge_pred,
+ const SourcePred& source_pred,
const GraphProperty& prop = GraphProperty())
- : inherited_vertex_properties(numlocalverts), m_rowstart(),
- m_column(), m_property(prop)
+ : inherited_vertex_properties(numlocalverts), m_property(prop)
{
std::vector sources, targets;
- for (; edge_begin != edge_end; ++edge_begin) {
- if (edge_pred(*edge_begin)) {
- sources.push_back(edge_begin->first);
- targets.push_back(edge_begin->second);
- }
- }
- assign_sources_and_targets_global(sources, targets, numlocalverts, global_to_local);
+ boost::graph::detail::split_into_separate_coords_filtered
+ (edge_begin, edge_end, sources, targets, source_pred);
+ m_forward.assign_sources_and_targets_global(sources, targets, numlocalverts, global_to_local);
}
// From number of vertices and single-pass range of unsorted edges and
@@ -804,125 +539,27 @@ class compressed_sparse_row_graph
// before creating the actual graph. Edges are filtered and transformed for
// use in a distributed graph.
template
+ 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 EdgePred& edge_pred,
+ const SourcePred& source_pred,
const GraphProperty& prop = GraphProperty())
- : inherited_vertex_properties(numlocalverts), m_rowstart(),
- m_column(), m_property(prop)
+ : inherited_vertex_properties(numlocalverts), m_property(prop)
{
std::vector sources, targets;
- std::vector edge_props;
- for (; edge_begin != edge_end; ++edge_begin, ++ep_iter) {
- if (edge_pred(*edge_begin)) {
- sources.push_back(edge_begin->first);
- targets.push_back(edge_begin->second);
- edge_props.push_back(*ep_iter);
- }
- }
- assign_sources_and_targets_global(sources, targets, edge_props, numlocalverts, global_to_local);
- }
-
- // Replace graph with sources and targets given, sorting them in-place, and
- // using the given global-to-local property map to get local indices from
- // global ones in the two arrays.
- template
- void assign_sources_and_targets_global(std::vector& sources,
- std::vector& targets,
- vertices_size_type numverts,
- GlobalToLocal global_to_local) {
- assert (sources.size() == targets.size());
- typedef typename std::vector::iterator vertex_vec_iter;
- EdgeIndex numedges = sources.size();
- // Do an in-place histogram sort (at least that's what I think it is) to
- // sort sources and targets
- // 1. Count degrees; degree of vertex v is in m_rowstart[v + 1]
- m_rowstart.clear();
- m_rowstart.resize(numverts + 1);
- for (size_t i = 0; i < numedges; ++i) {
- assert(get(global_to_local, sources[i]) < numverts);
- ++m_rowstart[get(global_to_local, sources[i]) + 1];
- }
- // 2. Do a prefix sum on those to get starting positions of each row
- for (size_t i = 0; i < numverts; ++i) {
- m_rowstart[i + 1] += m_rowstart[i];
- }
- // 3. Copy m_rowstart (except last element) to get insert positions
- std::vector insert_positions(m_rowstart.begin(), boost::prior(m_rowstart.end()));
- // 4. Swap the sources and targets into place
- for (size_t i = 0; i < numedges; ++i) {
- // While edge i is not in the right bucket:
- while (!(i >= m_rowstart[get(global_to_local, sources[i])] && i < insert_positions[get(global_to_local, sources[i])])) {
- // Add a slot in the right bucket
- size_t target_pos = insert_positions[get(global_to_local, sources[i])]++;
- assert (target_pos < m_rowstart[get(global_to_local, sources[i]) + 1]);
- if (target_pos == i) continue;
- // Swap this edge into place
- using std::swap;
- swap(sources[i], sources[target_pos]);
- swap(targets[i], targets[target_pos]);
- }
- }
- // Now targets is the correct vector (properly sorted by source) for
- // m_column
- m_column.swap(targets);
- }
-
- // Replace graph with sources and targets and edge properties given, sorting
- // them in-place, and using the given global-to-local property map to get
- // local indices from global ones in the two arrays.
- template
- void assign_sources_and_targets_global(std::vector& sources,
- std::vector& targets,
- std::vector& edge_props,
- vertices_size_type numverts,
- GlobalToLocal global_to_local) {
- assert (sources.size() == targets.size());
- assert (sources.size() == edge_props.size());
- EdgeIndex numedges = sources.size();
- // Do an in-place histogram sort (at least that's what I think it is) to
- // sort sources and targets
- // 1. Count degrees; degree of vertex v is in m_rowstart[v + 1]
- m_rowstart.clear();
- m_rowstart.resize(numverts + 1);
- for (size_t i = 0; i < numedges; ++i) {
- ++m_rowstart[get(global_to_local, sources[i]) + 1];
- }
- // 2. Do a prefix sum on those to get starting positions of each row
- for (size_t i = 0; i < numverts; ++i) {
- m_rowstart[i + 1] += m_rowstart[i];
- }
- // 3. Copy m_rowstart (except last element) to get insert positions
- std::vector insert_positions(m_rowstart.begin(), boost::prior(m_rowstart.end()));
- // 4. Swap the sources and targets into place
- for (size_t i = 0; i < numedges; ++i) {
- // While edge i is not in the right bucket:
- while (!(i >= m_rowstart[get(global_to_local, sources[i])] && i < insert_positions[get(global_to_local, sources[i])])) {
- // Add a slot in the right bucket
- size_t target_pos = insert_positions[get(global_to_local, sources[i])]++;
- assert (target_pos < m_rowstart[get(global_to_local, sources[i]) + 1]);
- if (target_pos == i) continue;
- // Swap this edge into place
- using std::swap;
- swap(sources[i], sources[target_pos]);
- swap(targets[i], targets[target_pos]);
- swap(edge_props[i], edge_props[target_pos]);
- }
- }
- // Now targets is the correct vector (properly sorted by source) for
- // m_column, and edge_props for m_edge_properties
- m_column.swap(targets);
- this->m_edge_properties.swap(edge_props);
+ std::vector edge_props;
+ boost::graph::detail::split_into_separate_coords_filtered
+ (edge_begin, edge_end, ep_iter, sources, targets, edge_props, source_pred);
+ m_forward.assign_sources_and_targets_global(sources, targets, edge_props, numlocalverts, global_to_local);
}
#endif // BOOST_GRAPH_USE_NEW_CSR_INTERFACE
- // Requires IncidenceGraph, a vertex index map, and a vertex(n, g) function
+ // Requires IncidenceGraph and a vertex index map
template
compressed_sparse_row_graph(const Graph& g, const VertexIndexMap& vi,
vertices_size_type numverts,
@@ -930,6 +567,7 @@ class compressed_sparse_row_graph
: m_property()
{
assign(g, vi, numverts, numedges);
+ inherited_vertex_properties::resize(numverts);
}
// Requires VertexListGraph and EdgeListGraph
@@ -937,7 +575,13 @@ class compressed_sparse_row_graph
compressed_sparse_row_graph(const Graph& g, const VertexIndexMap& vi)
: m_property()
{
- assign(g, vi, num_vertices(g), num_edges(g));
+ typename graph_traits::edges_size_type numedges = num_edges(g);
+ if (is_same::directed_category, undirectedS>::value) {
+ numedges *= 2; // Double each edge (actual doubling done by out_edges function)
+ }
+ vertices_size_type numverts = num_vertices(g);
+ assign(g, vi, numverts, numedges);
+ inherited_vertex_properties::resize(numverts);
}
// Requires vertex index map plus requirements of previous constructor
@@ -945,61 +589,50 @@ class compressed_sparse_row_graph
explicit compressed_sparse_row_graph(const Graph& g)
: m_property()
{
- assign(g, get(vertex_index, g), num_vertices(g), num_edges(g));
+ typename graph_traits::edges_size_type numedges = num_edges(g);
+ if (is_same::directed_category, undirectedS>::value) {
+ numedges *= 2; // Double each edge (actual doubling done by out_edges function)
+ }
+ assign(g, get(vertex_index, g), num_vertices(g), numedges);
}
// From any graph (slow and uses a lot of memory)
- // Requires IncidenceGraph, a vertex index map, and a vertex(n, g) function
+ // Requires IncidenceGraph and a vertex index map
// Internal helper function
+ // Note that numedges must be doubled for undirected source graphs
template
void
assign(const Graph& g, const VertexIndexMap& vi,
vertices_size_type numverts, edges_size_type numedges)
{
+ m_forward.assign(g, vi, numverts, numedges);
inherited_vertex_properties::resize(numverts);
- m_rowstart.resize(numverts + 1);
- m_column.resize(numedges);
- EdgeIndex current_edge = 0;
- typedef typename boost::graph_traits::vertex_descriptor g_vertex;
- typedef typename boost::graph_traits::edge_descriptor g_edge;
- typedef typename boost::graph_traits::out_edge_iterator
- g_out_edge_iter;
-
- for (Vertex i = 0; i != numverts; ++i) {
- m_rowstart[i] = current_edge;
- g_vertex v = vertex(i, g);
-#ifdef BOOST_GRAPH_USE_OLD_CSR_INTERFACE
- // Out edges in a single vertex are only sorted for the old interface
- EdgeIndex num_edges_before_this_vertex = current_edge;
-#endif // BOOST_GRAPH_USE_OLD_CSR_INTERFACE
- g_out_edge_iter ei, ei_end;
- for (tie(ei, ei_end) = out_edges(v, g); ei != ei_end; ++ei) {
- m_column[current_edge++] = get(vi, target(*ei, g));
- }
-#ifdef BOOST_GRAPH_USE_OLD_CSR_INTERFACE
- // Out edges in a single vertex are only sorted for the old interface
- std::sort(m_column.begin() + num_edges_before_this_vertex,
- m_column.begin() + current_edge);
-#endif // BOOST_GRAPH_USE_OLD_CSR_INTERFACE
- }
- m_rowstart[numverts] = current_edge;
-#ifdef BOOST_GRAPH_USE_OLD_CSR_INTERFACE
- m_last_source = numverts;
-#endif // BOOST_GRAPH_USE_OLD_CSR_INTERFACE
}
// Requires the above, plus VertexListGraph and EdgeListGraph
template
void assign(const Graph& g, const VertexIndexMap& vi)
{
- assign(g, vi, num_vertices(g), num_edges(g));
+ typename graph_traits::edges_size_type numedges = num_edges(g);
+ if (is_same::directed_category, undirectedS>::value) {
+ numedges *= 2; // Double each edge (actual doubling done by out_edges function)
+ }
+ vertices_size_type numverts = num_vertices(g);
+ m_forward.assign(g, vi, numverts, numedges);
+ inherited_vertex_properties::resize(numverts);
}
// Requires the above, plus a vertex_index map.
template
void assign(const Graph& g)
{
- assign(g, get(vertex_index, g), num_vertices(g), num_edges(g));
+ typename graph_traits::edges_size_type numedges = num_edges(g);
+ if (is_same::directed_category, undirectedS>::value) {
+ numedges *= 2; // Double each edge (actual doubling done by out_edges function)
+ }
+ vertices_size_type numverts = num_vertices(g);
+ m_forward.assign(g, get(vertex_index, g), numverts, numedges);
+ inherited_vertex_properties::resize(numverts);
}
#ifdef BOOST_GRAPH_USE_NEW_CSR_INTERFACE
@@ -1013,66 +646,7 @@ class compressed_sparse_row_graph
BidirectionalIteratorOrig last_sorted,
EPIterOrig ep_iter_sorted,
const GlobalToLocal& global_to_local) {
- typedef boost::reverse_iterator BidirectionalIterator;
- typedef boost::reverse_iterator EPIter;
- // Flip sequence
- BidirectionalIterator first(last_sorted);
- BidirectionalIterator last(first_sorted);
- typedef compressed_sparse_row_graph Graph;
- typedef typename boost::graph_traits::vertex_descriptor vertex_t;
- typedef typename boost::graph_traits::vertices_size_type vertex_num;
- typedef typename boost::graph_traits::edges_size_type edge_num;
- edge_num new_edge_count = std::distance(first, last);
-
- EPIter ep_iter(ep_iter_sorted);
- std::advance(ep_iter, -(std::ptrdiff_t)new_edge_count);
- edge_num edges_added_before_i = new_edge_count; // Count increment to add to rowstarts
- m_column.resize(m_column.size() + new_edge_count);
- inherited_edge_properties::resize(inherited_edge_properties::size() + new_edge_count);
- BidirectionalIterator current_new_edge = first, prev_new_edge = first;
- EPIter current_new_edge_prop = ep_iter;
- for (vertex_num i_plus_1 = num_vertices(*this); i_plus_1 > 0; --i_plus_1) {
- vertex_num i = i_plus_1 - 1;
- prev_new_edge = current_new_edge;
- // edges_added_to_this_vertex = #mbrs of new_edges with first == i
- edge_num edges_added_to_this_vertex = 0;
- while (current_new_edge != last) {
- if (get(global_to_local, current_new_edge->first) != i) break;
- ++current_new_edge;
- ++current_new_edge_prop;
- ++edges_added_to_this_vertex;
- }
- edges_added_before_i -= edges_added_to_this_vertex;
- // Invariant: edges_added_before_i = #mbrs of new_edges with first < i
- edge_num old_rowstart = m_rowstart[i];
- edge_num new_rowstart = m_rowstart[i] + edges_added_before_i;
- edge_num old_degree = m_rowstart[i + 1] - m_rowstart[i];
- edge_num new_degree = old_degree + edges_added_to_this_vertex;
- // Move old edges forward (by #new_edges before this i) to make room
- // new_rowstart > old_rowstart, so use copy_backwards
- if (old_rowstart != new_rowstart) {
- std::copy_backward(m_column.begin() + old_rowstart,
- m_column.begin() + old_rowstart + old_degree,
- m_column.begin() + new_rowstart + old_degree);
- inherited_edge_properties::move_range(old_rowstart, old_rowstart + old_degree, new_rowstart);
- }
- // Add new edges (reversed because current_new_edge is a
- // const_reverse_iterator)
- BidirectionalIterator temp = current_new_edge;
- EPIter temp_prop = current_new_edge_prop;
- for (; temp != prev_new_edge; ++old_degree) {
- --temp;
- --temp_prop;
- m_column[new_rowstart + old_degree] = temp->second;
- inherited_edge_properties::write_by_index(new_rowstart + old_degree, *temp_prop);
- }
- m_rowstart[i + 1] = new_rowstart + new_degree;
- if (edges_added_before_i == 0) break; // No more edges inserted before this point
- // m_rowstart[i] will be fixed up on the next iteration (to avoid
- // changing the degree of vertex i - 1); the last iteration never changes
- // it (either because of the condition of the break or because
- // m_rowstart[0] is always 0)
- }
+ m_forward.add_edges_sorted_internal(first_sorted, last_sorted, ep_iter_sorted, global_to_local);
}
template
@@ -1081,8 +655,7 @@ class compressed_sparse_row_graph
BidirectionalIteratorOrig first_sorted,
BidirectionalIteratorOrig last_sorted,
EPIterOrig ep_iter_sorted) {
- add_edges_sorted_internal(first_sorted, last_sorted, ep_iter_sorted,
- identity_property_map());
+ m_forward.add_edges_sorted_internal(first_sorted, last_sorted, ep_iter_sorted, identity_property_map());
}
// Add edges from a sorted (smallest sources first) range of pairs
@@ -1091,7 +664,7 @@ class compressed_sparse_row_graph
add_edges_sorted_internal(
BidirectionalIteratorOrig first_sorted,
BidirectionalIteratorOrig last_sorted) {
- add_edges_sorted_internal(first_sorted, last_sorted, detail::default_construct_iterator());
+ m_forward.add_edges_sorted_internal(first_sorted, last_sorted, detail::default_construct_iterator());
}
template
@@ -1100,8 +673,7 @@ class compressed_sparse_row_graph
BidirectionalIteratorOrig first_sorted,
BidirectionalIteratorOrig last_sorted,
const GlobalToLocal& global_to_local) {
- add_edges_sorted_internal(first_sorted, last_sorted, detail::default_construct_iterator(),
- global_to_local);
+ m_forward.add_edges_sorted_internal(first_sorted, last_sorted, detail::default_construct_iterator(), global_to_local);
}
template add_edges_sorted_internal_global(new_edges.begin(), new_edges.end(), global_to_local);
}
template
inline void
add_edges_internal(InputIterator first, InputIterator last) {
- add_edges_internal(first, last, identity_property_map());
+ this->add_edges_internal(first, last, identity_property_map());
}
// Add edges from a range of (source, target) pairs and edge properties that
@@ -1152,7 +723,7 @@ class compressed_sparse_row_graph
typedef std::pair vertex_pair;
typedef std::vector<
boost::tuple >
+ edge_bundled> >
edge_vector_t;
edge_vector_t new_edges
(boost::make_zip_iterator(boost::make_tuple(first, ep_iter)),
@@ -1161,7 +732,7 @@ class compressed_sparse_row_graph
std::sort(new_edges.begin(), new_edges.end(),
boost::detail::compare_first<
std::less >());
- add_edges_sorted_internal
+ m_forward.add_edges_sorted_internal
(boost::make_transform_iterator(
new_edges.begin(),
boost::detail::my_tuple_get_class<0, vertex_pair>()),
@@ -1171,7 +742,7 @@ class compressed_sparse_row_graph
boost::make_transform_iterator(
new_edges.begin(),
boost::detail::my_tuple_get_class
- <1, typename inherited_edge_properties::edge_bundled>()),
+ <1, edge_bundled>()),
global_to_local);
}
@@ -1181,91 +752,435 @@ class compressed_sparse_row_graph
inline void
add_edges_internal(InputIterator first, InputIterator last,
EPIterator ep_iter, EPIterator ep_iter_end) {
- add_edges_internal(first, last, ep_iter, ep_iter_end, identity_property_map());
+ this->add_edges_internal(first, last, ep_iter, ep_iter_end, identity_property_map());
}
#endif // BOOST_GRAPH_USE_NEW_CSR_INTERFACE
using inherited_vertex_properties::operator[];
- using inherited_edge_properties::operator[];
+
+ // Directly access a edge or edge bundle
+ edge_push_back_type& operator[](const edge_descriptor& v)
+ { return m_forward.m_edge_properties[get(edge_index, *this, v)]; }
+
+ const edge_push_back_type& operator[](const edge_descriptor& v) const
+ { return m_forward.m_edge_properties[get(edge_index, *this, v)]; }
// private: non-portable, requires friend templates
inherited_vertex_properties& vertex_properties() {return *this;}
const inherited_vertex_properties& vertex_properties() const {return *this;}
- inherited_edge_properties& edge_properties() { return *this; }
- const inherited_edge_properties& edge_properties() const { return *this; }
+ typename forward_type::inherited_edge_properties& edge_properties() { return m_forward; }
+ const typename forward_type::inherited_edge_properties& edge_properties() const { return m_forward; }
- std::vector m_rowstart;
- std::vector m_column;
+ forward_type m_forward;
GraphProperty m_property;
-#ifdef BOOST_GRAPH_USE_OLD_CSR_INTERFACE
- // This member is only needed to support add_edge(), which is not provided by
- // the new interface
- Vertex m_last_source; // Last source of added edge, plus one
-#endif // BOOST_GRAPH_USE_OLD_CSR_INTERFACE
};
-template
-class csr_edge_descriptor
+#ifdef BOOST_GRAPH_USE_NEW_CSR_INTERFACE
+// Bidir is only supported in this mode
+template
+class compressed_sparse_row_graph
+ : public detail::indexed_vertex_properties
{
public:
- Vertex src;
- EdgeIndex idx;
+ typedef detail::indexed_vertex_properties
+ inherited_vertex_properties;
- csr_edge_descriptor(Vertex src, EdgeIndex idx): src(src), idx(idx) {}
- csr_edge_descriptor(): src(0), idx(0) {}
+ public:
+ // For Property Graph
+ typedef GraphProperty graph_property_type;
- bool operator==(const csr_edge_descriptor& e) const {return idx == e.idx;}
- bool operator!=(const csr_edge_descriptor& e) const {return idx != e.idx;}
- bool operator<(const csr_edge_descriptor& e) const {return idx < e.idx;}
- bool operator>(const csr_edge_descriptor& e) const {return idx > e.idx;}
- bool operator<=(const csr_edge_descriptor& e) const {return idx <= e.idx;}
- bool operator>=(const csr_edge_descriptor& e) const {return idx >= e.idx;}
+ typedef detail::compressed_sparse_row_structure forward_type;
+ typedef EdgeIndex /* typename boost::mpl::if_c, boost::no_property, EdgeIndex> */ backward_edge_property;
+ typedef detail::compressed_sparse_row_structure backward_type;
- template
- void serialize(Archiver& ar, const unsigned int /*version*/)
- {
- ar & src & idx;
+ public:
+ // Concept requirements:
+ // For Graph
+ typedef Vertex vertex_descriptor;
+ typedef detail::csr_edge_descriptor edge_descriptor;
+ typedef bidirectional_tag directed_category;
+ typedef allow_parallel_edge_tag edge_parallel_category;
+
+ class traversal_category: public bidirectional_graph_tag,
+ public adjacency_graph_tag,
+ public vertex_list_graph_tag,
+ public edge_list_graph_tag {};
+
+ static vertex_descriptor null_vertex() { return vertex_descriptor(-1); }
+
+ // For VertexListGraph
+ typedef counting_iterator vertex_iterator;
+ typedef Vertex vertices_size_type;
+
+ // For EdgeListGraph
+ typedef EdgeIndex edges_size_type;
+
+ // For IncidenceGraph
+ typedef detail::csr_out_edge_iterator out_edge_iterator;
+ typedef EdgeIndex degree_size_type;
+
+ // For AdjacencyGraph
+ typedef typename std::vector::const_iterator adjacency_iterator;
+
+ // For EdgeListGraph
+ typedef detail::csr_edge_iterator edge_iterator;
+
+ // For BidirectionalGraph (not implemented)
+ typedef detail::csr_in_edge_iterator in_edge_iterator;
+
+ // For internal use
+ typedef csr_graph_tag graph_tag;
+
+ typedef typename forward_type::inherited_edge_properties::edge_bundled edge_bundled;
+ typedef typename forward_type::inherited_edge_properties::edge_push_back_type edge_push_back_type;
+ typedef typename forward_type::inherited_edge_properties::edge_property_type edge_property_type;
+
+ // Constructors
+
+ // Default constructor: an empty graph.
+ compressed_sparse_row_graph(): m_property() {}
+
+ // With numverts vertices
+ compressed_sparse_row_graph(vertices_size_type numverts)
+ : inherited_vertex_properties(numverts),
+ m_forward(numverts), m_backward(numverts) {}
+
+ private:
+
+ void set_up_backward_property_links() {
+ std::pair e = edges(*this);
+ m_backward.assign_unsorted_multi_pass_edges
+ (detail::transpose_edges(
+ detail::make_edge_to_index_pair_iter
+ (*this, get(vertex_index, *this), e.first)),
+ detail::transpose_edges(
+ detail::make_edge_to_index_pair_iter
+ (*this, get(vertex_index, *this), e.second)),
+ boost::counting_iterator(0),
+ m_forward.m_rowstart.size() - 1,
+ identity_property_map(),
+ keep_all());
}
-};
-template
-struct hash >
-{
- std::size_t operator()(csr_edge_descriptor const& x) const
+ public:
+
+ // From number of vertices and unsorted list of edges
+ template
+ compressed_sparse_row_graph(edges_are_unsorted_multi_pass_t,
+ MultiPassInputIterator edge_begin,
+ MultiPassInputIterator edge_end,
+ vertices_size_type numverts,
+ const GraphProperty& prop = GraphProperty())
+ : inherited_vertex_properties(numverts), m_property(prop)
{
- std::size_t hash = hash_value(x.src);
- hash_combine(hash, x.idx);
- return hash;
+ m_forward.assign_unsorted_multi_pass_edges(edge_begin, edge_end, numverts, identity_property_map(), keep_all());
+ set_up_backward_property_links();
}
+
+ // From number of vertices and unsorted list of edges, plus edge properties
+ template
+ 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())
+ : inherited_vertex_properties(numverts), m_forward(), m_property(prop)
+ {
+ m_forward.assign_unsorted_multi_pass_edges(edge_begin, edge_end, ep_iter, numverts, identity_property_map(), keep_all());
+ set_up_backward_property_links();
+ }
+
+ // From number of vertices and unsorted list of edges, with filter and
+ // global-to-local map
+ template
+ 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())
+ : inherited_vertex_properties(numlocalverts), m_forward(), m_property(prop)
+ {
+ m_forward.assign_unsorted_multi_pass_edges(edge_begin, edge_end, numlocalverts, global_to_local, source_pred);
+ set_up_backward_property_links();
+ }
+
+ // From number of vertices and unsorted list of edges, plus edge properties,
+ // with filter and global-to-local map
+ template
+ 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())
+ : inherited_vertex_properties(numlocalverts), m_forward(), m_property(prop)
+ {
+ m_forward.assign_unsorted_multi_pass_edges(edge_begin, edge_end, ep_iter, numlocalverts, global_to_local, source_pred);
+ set_up_backward_property_links();
+ }
+
+ // Requires IncidenceGraph and a vertex index map
+ template
+ compressed_sparse_row_graph(const Graph& g, const VertexIndexMap& vi,
+ vertices_size_type numverts,
+ edges_size_type numedges)
+ : m_property()
+ {
+ assign(g, vi, numverts, numedges);
+ inherited_vertex_properties::resize(numverts);
+ }
+
+ // Requires VertexListGraph and EdgeListGraph
+ template
+ compressed_sparse_row_graph(const Graph& g, const VertexIndexMap& vi)
+ : m_property()
+ {
+ typename graph_traits::edges_size_type numedges = num_edges(g);
+ if (is_same::directed_category, undirectedS>::value) {
+ numedges *= 2; // Double each edge (actual doubling done by out_edges function)
+ }
+ vertices_size_type numverts = num_vertices(g);
+ assign(g, vi, numverts, numedges);
+ inherited_vertex_properties::resize(numverts);
+ }
+
+ // Requires vertex index map plus requirements of previous constructor
+ template
+ explicit compressed_sparse_row_graph(const Graph& g)
+ : m_property()
+ {
+ typename graph_traits::edges_size_type numedges = num_edges(g);
+ if (is_same::directed_category, undirectedS>::value) {
+ numedges *= 2; // Double each edge (actual doubling done by out_edges function)
+ }
+ assign(g, get(vertex_index, g), num_vertices(g), numedges);
+ }
+
+ // From any graph (slow and uses a lot of memory)
+ // Requires IncidenceGraph and a vertex index map
+ // Internal helper function
+ // Note that numedges must be doubled for undirected source graphs
+ template
+ void
+ assign(const Graph& g, const VertexIndexMap& vi,
+ vertices_size_type numverts, edges_size_type numedges)
+ {
+ m_forward.assign(g, vi, numverts, numedges);
+ inherited_vertex_properties::resize(numverts);
+ }
+
+ // Requires the above, plus VertexListGraph and EdgeListGraph
+ template
+ void assign(const Graph& g, const VertexIndexMap& vi)
+ {
+ typename graph_traits::edges_size_type numedges = num_edges(g);
+ if (is_same::directed_category, undirectedS>::value) {
+ numedges *= 2; // Double each edge (actual doubling done by out_edges function)
+ }
+ vertices_size_type numverts = num_vertices(g);
+ m_forward.assign(g, vi, numverts, numedges);
+ inherited_vertex_properties::resize(numverts);
+ }
+
+ // Requires the above, plus a vertex_index map.
+ template
+ void assign(const Graph& g)
+ {
+ typename graph_traits::edges_size_type numedges = num_edges(g);
+ if (is_same::directed_category, undirectedS>::value) {
+ numedges *= 2; // Double each edge (actual doubling done by out_edges function)
+ }
+ vertices_size_type numverts = num_vertices(g);
+ m_forward.assign(g, get(vertex_index, g), numverts, numedges);
+ inherited_vertex_properties::resize(numverts);
+ }
+
+ // Add edges from a sorted (smallest sources first) range of pairs and edge
+ // properties
+ template
+ void
+ add_edges_sorted_internal(
+ BidirectionalIteratorOrig first_sorted,
+ BidirectionalIteratorOrig last_sorted,
+ EPIterOrig ep_iter_sorted,
+ const GlobalToLocal& global_to_local) {
+ m_forward.add_edges_sorted_internal(first_sorted, last_sorted, ep_iter_sorted, global_to_local);
+ }
+
+ template
+ void
+ add_edges_sorted_internal(
+ BidirectionalIteratorOrig first_sorted,
+ BidirectionalIteratorOrig last_sorted,
+ EPIterOrig ep_iter_sorted) {
+ m_forward.add_edges_sorted_internal(first_sorted, last_sorted, ep_iter_sorted, identity_property_map());
+ }
+
+ // Add edges from a sorted (smallest sources first) range of pairs
+ template
+ void
+ add_edges_sorted_internal(
+ BidirectionalIteratorOrig first_sorted,
+ BidirectionalIteratorOrig last_sorted) {
+ m_forward.add_edges_sorted_internal(first_sorted, last_sorted, detail::default_construct_iterator());
+ }
+
+ template
+ void
+ add_edges_sorted_internal_global(
+ BidirectionalIteratorOrig first_sorted,
+ BidirectionalIteratorOrig last_sorted,
+ const GlobalToLocal& global_to_local) {
+ m_forward.add_edges_sorted_internal(first_sorted, last_sorted, detail::default_construct_iterator(), global_to_local);
+ }
+
+ template
+ void
+ add_edges_sorted_internal_global(
+ BidirectionalIteratorOrig first_sorted,
+ BidirectionalIteratorOrig last_sorted,
+ EPIterOrig ep_iter_sorted,
+ const GlobalToLocal& global_to_local) {
+ m_forward.add_edges_sorted_internal(first_sorted, last_sorted, ep_iter_sorted, global_to_local);
+ }
+
+ // Add edges from a range of (source, target) pairs that are unsorted
+ template
+ inline void
+ add_edges_internal(InputIterator first, InputIterator last,
+ const GlobalToLocal& global_to_local) {
+ typedef compressed_sparse_row_graph Graph;
+ typedef typename boost::graph_traits::vertex_descriptor vertex_t;
+ typedef typename boost::graph_traits::vertices_size_type vertex_num;
+ typedef typename boost::graph_traits::edges_size_type edge_num;
+ typedef std::vector > edge_vector_t;
+ edge_vector_t new_edges(first, last);
+ if (new_edges.empty()) return;
+ std::sort(new_edges.begin(), new_edges.end());
+ this->add_edges_sorted_internal_global(new_edges.begin(), new_edges.end(), global_to_local);
+ }
+
+ template
+ inline void
+ add_edges_internal(InputIterator first, InputIterator last) {
+ this->add_edges_internal(first, last, identity_property_map());
+ }
+
+ // Add edges from a range of (source, target) pairs and edge properties that
+ // are unsorted
+ template
+ inline void
+ add_edges_internal(InputIterator first, InputIterator last,
+ EPIterator ep_iter, EPIterator ep_iter_end,
+ const GlobalToLocal& global_to_local) {
+ typedef compressed_sparse_row_graph Graph;
+ typedef typename boost::graph_traits::vertex_descriptor vertex_t;
+ typedef typename boost::graph_traits::vertices_size_type vertex_num;
+ typedef typename boost::graph_traits::edges_size_type edge_num;
+ typedef std::pair vertex_pair;
+ typedef std::vector<
+ boost::tuple >
+ edge_vector_t;
+ edge_vector_t new_edges
+ (boost::make_zip_iterator(boost::make_tuple(first, ep_iter)),
+ boost::make_zip_iterator(boost::make_tuple(last, ep_iter_end)));
+ if (new_edges.empty()) return;
+ std::sort(new_edges.begin(), new_edges.end(),
+ boost::detail::compare_first<
+ std::less >());
+ m_forward.add_edges_sorted_internal
+ (boost::make_transform_iterator(
+ new_edges.begin(),
+ boost::detail::my_tuple_get_class<0, vertex_pair>()),
+ boost::make_transform_iterator(
+ new_edges.end(),
+ boost::detail::my_tuple_get_class<0, vertex_pair>()),
+ boost::make_transform_iterator(
+ new_edges.begin(),
+ boost::detail::my_tuple_get_class
+ <1, edge_bundled>()),
+ global_to_local);
+ }
+
+ // Add edges from a range of (source, target) pairs and edge properties that
+ // are unsorted
+ template
+ inline void
+ add_edges_internal(InputIterator first, InputIterator last,
+ EPIterator ep_iter, EPIterator ep_iter_end) {
+ this->add_edges_internal(first, last, ep_iter, ep_iter_end, identity_property_map());
+ }
+
+ using inherited_vertex_properties::operator[];
+
+ // Directly access a edge or edge bundle
+ edge_push_back_type& operator[](const edge_descriptor& v)
+ { return m_forward.m_edge_properties[get(edge_index, *this, v)]; }
+
+ const edge_push_back_type& operator[](const edge_descriptor& v) const
+ { return m_forward.m_edge_properties[get(edge_index, *this, v)]; }
+
+ // private: non-portable, requires friend templates
+ inherited_vertex_properties& vertex_properties() {return *this;}
+ const inherited_vertex_properties& vertex_properties() const {return *this;}
+ typename forward_type::inherited_edge_properties& edge_properties() { return m_forward; }
+ const typename forward_type::inherited_edge_properties& edge_properties() const { return m_forward; }
+
+ forward_type m_forward;
+ backward_type m_backward;
+ GraphProperty m_property;
};
+#endif // BOOST_GRAPH_USE_NEW_CSR_INTERFACE
// Construction functions
template
inline Vertex
add_vertex(BOOST_CSR_GRAPH_TYPE& g) {
- Vertex old_num_verts_plus_one = g.m_rowstart.size();
- EdgeIndex numedges = g.m_rowstart.back();
- g.m_rowstart.push_back(numedges);
- g.vertex_properties().resize(num_vertices(g));
- return old_num_verts_plus_one - 1;
+ add_vertex(g, typename BOOST_CSR_GRAPH_TYPE::vertex_bundled());
}
-template
+template
inline Vertex
-add_vertex(BOOST_CSR_GRAPH_TYPE& g,
- typename BOOST_CSR_GRAPH_TYPE::vertex_bundled const& p) {
- Vertex old_num_verts_plus_one = g.m_rowstart.size();
- g.m_rowstart.push_back(EdgeIndex(0));
+add_vertex(BOOST_DIR_CSR_GRAPH_TYPE& g,
+ typename BOOST_DIR_CSR_GRAPH_TYPE::vertex_bundled const& p) {
+ Vertex old_num_verts_plus_one = g.m_forward.m_rowstart.size();
+ g.m_forward.m_rowstart.push_back(g.m_forward.m_rowstart.back());
g.vertex_properties().push_back(p);
return old_num_verts_plus_one - 1;
}
-template
+template
inline Vertex
-add_vertices(typename BOOST_CSR_GRAPH_TYPE::vertices_size_type count, BOOST_CSR_GRAPH_TYPE& g) {
- Vertex old_num_verts_plus_one = g.m_rowstart.size();
- EdgeIndex numedges = g.m_rowstart.back();
- g.m_rowstart.resize(old_num_verts_plus_one + count, numedges);
+add_vertex(BOOST_BIDIR_CSR_GRAPH_TYPE& g,
+ typename BOOST_BIDIR_CSR_GRAPH_TYPE::vertex_bundled const& p) {
+ Vertex old_num_verts_plus_one = g.m_forward.m_rowstart.size();
+ g.m_forward.m_rowstart.push_back(g.m_forward.m_rowstart.back());
+ g.m_backward.m_rowstart.push_back(g.m_backward.m_rowstart.back());
+ g.vertex_properties().push_back(p);
+ return old_num_verts_plus_one - 1;
+}
+
+template