diff -r 666f914201fb -r 2fe1408b6811 epoc32/include/stdapis/boost/graph/compressed_sparse_row_graph.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/epoc32/include/stdapis/boost/graph/compressed_sparse_row_graph.hpp Tue Mar 16 16:12:26 2010 +0000 @@ -0,0 +1,799 @@ +// Copyright 2005-2006 The Trustees of Indiana University. + +// 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) + +// Authors: Jeremiah Willcock +// Douglas Gregor +// Andrew Lumsdaine + +// Compressed sparse row graph type + +#ifndef BOOST_GRAPH_COMPRESSED_SPARSE_ROW_GRAPH_HPP +#define BOOST_GRAPH_COMPRESSED_SPARSE_ROW_GRAPH_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_GRAPH_NO_BUNDLED_PROPERTIES +# error The Compressed Sparse Row graph only supports bundled properties. +# error You will need a compiler that conforms better to the C++ standard. +#endif + +namespace boost { + +// A tag type indicating that the graph in question is a compressed +// sparse row graph. This is an internal detail of the BGL. +struct csr_graph_tag; + +/**************************************************************************** + * Local helper macros to reduce typing and clutter later on. * + ****************************************************************************/ +#define BOOST_CSR_GRAPH_TEMPLATE_PARMS \ + typename Directed, typename VertexProperty, typename EdgeProperty, \ + typename GraphProperty, typename Vertex, typename EdgeIndex +#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; + +/** Compressed sparse row graph. + * + * Vertex and EdgeIndex should be unsigned integral types and should + * specialize numeric_limits. + */ +template +class compressed_sparse_row_graph + : public detail::indexed_vertex_properties, + public detail::indexed_edge_properties > + +{ + 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); + } + + public: + /* At this time, the compressed sparse row graph can only be used to + * create a directed graph. In the future, bidirectional and + * undirected CSR graphs will also be supported. + */ + BOOST_STATIC_ASSERT((is_same::value)); + + // Concept requirements: + // For Graph + typedef Vertex vertex_descriptor; + typedef csr_edge_descriptor edge_descriptor; + typedef directed_tag directed_category; + typedef allow_parallel_edge_tag edge_parallel_category; + + class traversal_category: public incidence_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 + class out_edge_iterator; + typedef EdgeIndex degree_size_type; + + // For AdjacencyGraph + typedef typename std::vector::const_iterator adjacency_iterator; + + // For EdgeListGraph + class edge_iterator; + + // For BidirectionalGraph (not implemented) + typedef void in_edge_iterator; + + // For internal use + typedef csr_graph_tag graph_tag; + + // Constructors + + // Default constructor: an empty graph. + compressed_sparse_row_graph() + : m_rowstart(1, EdgeIndex(0)), m_column(0), m_property(), + m_last_source(0) {} + + // From number of vertices and sorted list of edges + template + compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end, + vertices_size_type numverts, + edges_size_type numedges = 0, + const GraphProperty& prop = GraphProperty()) + : inherited_vertex_properties(numverts), m_rowstart(numverts + 1), + m_column(0), m_property(prop), m_last_source(numverts) + { + // 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; + maybe_reserve_edge_list_storage(edge_begin, edge_end, category()); + } else { + m_column.reserve(numedges); + } + + EdgeIndex current_edge = 0; + Vertex current_vertex_plus_one = 1; + m_rowstart[0] = 0; + for (InputIterator ei = edge_begin; ei != edge_end; ++ei) { + Vertex src = 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 != numverts + 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()); + } + + // From number of vertices and sorted list of edges + template + compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end, + EdgePropertyIterator ep_iter, + vertices_size_type numverts, + edges_size_type numedges = 0, + const GraphProperty& prop = GraphProperty()) + : inherited_vertex_properties(numverts), m_rowstart(numverts + 1), + m_column(0), m_property(prop), m_last_source(numverts) + { + // 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; + maybe_reserve_edge_list_storage(edge_begin, edge_end, category()); + } else { + m_column.reserve(numedges); + } + + 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) { + Vertex src = 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 != numverts + 1; ++current_vertex_plus_one) + m_rowstart[current_vertex_plus_one] = current_edge; + } + + // Requires IncidenceGraph, a vertex index map, and a vertex(n, g) function + template + compressed_sparse_row_graph(const Graph& g, const VertexIndexMap& vi, + vertices_size_type numverts, + edges_size_type numedges) + : m_property(), m_last_source(0) + { + assign(g, vi, numverts, numedges); + } + + // Requires VertexListGraph and EdgeListGraph + template + compressed_sparse_row_graph(const Graph& g, const VertexIndexMap& vi) + : m_property(), m_last_source(0) + { + assign(g, vi, num_vertices(g), num_edges(g)); + } + + // Requires vertex index map plus requirements of previous constructor + template + explicit compressed_sparse_row_graph(const Graph& g) + : m_property(), m_last_source(0) + { + assign(g, get(vertex_index, g), num_vertices(g), num_edges(g)); + } + + // From any graph (slow and uses a lot of memory) + // Requires IncidenceGraph, a vertex index map, and a vertex(n, g) function + // Internal helper function + template + void + assign(const Graph& g, const VertexIndexMap& vi, + vertices_size_type numverts, edges_size_type 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); + EdgeIndex num_edges_before_this_vertex = current_edge; + 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)); + } + std::sort(m_column.begin() + num_edges_before_this_vertex, + m_column.begin() + current_edge); + } + m_rowstart[numverts] = current_edge; + m_last_source = numverts; + } + + // 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)); + } + + // 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)); + } + + using inherited_vertex_properties::operator[]; + using inherited_edge_properties::operator[]; + + // 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; } + + std::vector m_rowstart; + std::vector m_column; + GraphProperty m_property; + Vertex m_last_source; // Last source of added edge, plus one +}; + +template +class csr_edge_descriptor +{ + public: + Vertex src; + EdgeIndex idx; + + csr_edge_descriptor(Vertex src, EdgeIndex idx): src(src), idx(idx) {} + csr_edge_descriptor(): src(0), idx(0) {} + + 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;} +}; + +// Construction functions +template +inline Vertex +add_vertex(BOOST_CSR_GRAPH_TYPE& g) { + Vertex old_num_verts_plus_one = g.m_rowstart.size(); + g.m_rowstart.push_back(EdgeIndex(0)); + return old_num_verts_plus_one - 1; +} + +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(); + g.m_rowstart.resize(old_num_verts_plus_one + count, EdgeIndex(0)); + return old_num_verts_plus_one - 1; +} + +// This function requires that (src, tgt) be lexicographically at least as +// large as the largest edge in the graph so far +template +inline typename BOOST_CSR_GRAPH_TYPE::edge_descriptor +add_edge(Vertex src, Vertex tgt, BOOST_CSR_GRAPH_TYPE& g) { + assert ((g.m_last_source == 0 || src >= g.m_last_source - 1) && + src < num_vertices(g)); + EdgeIndex num_edges_orig = g.m_column.size(); + for (; g.m_last_source <= src; ++g.m_last_source) + g.m_rowstart[g.m_last_source] = num_edges_orig; + g.m_rowstart[src + 1] = num_edges_orig + 1; + g.m_column.push_back(tgt); + typedef typename BOOST_CSR_GRAPH_TYPE::edge_push_back_type push_back_type; + g.edge_properties().push_back(push_back_type()); + return typename BOOST_CSR_GRAPH_TYPE::edge_descriptor(src, num_edges_orig); +} + +// This function requires that (src, tgt) be lexicographically at least as +// large as the largest edge in the graph so far +template +inline typename BOOST_CSR_GRAPH_TYPE::edge_descriptor +add_edge(Vertex src, Vertex tgt, + typename BOOST_CSR_GRAPH_TYPE::edge_bundled const& p, + BOOST_CSR_GRAPH_TYPE& g) { + assert ((g.m_last_source == 0 || src >= g.m_last_source - 1) && + src < num_vertices(g)); + EdgeIndex num_edges_orig = g.m_column.size(); + for (; g.m_last_source <= src; ++g.m_last_source) + g.m_rowstart[g.m_last_source] = num_edges_orig; + g.m_rowstart[src + 1] = num_edges_orig + 1; + g.m_column.push_back(tgt); + g.edge_properties().push_back(p); + return typename BOOST_CSR_GRAPH_TYPE::edge_descriptor(src, num_edges_orig); +} + + +// From VertexListGraph +template +inline Vertex +num_vertices(const BOOST_CSR_GRAPH_TYPE& g) { + return g.m_rowstart.size() - 1; +} + +template +std::pair, counting_iterator > +inline vertices(const BOOST_CSR_GRAPH_TYPE& g) { + return std::make_pair(counting_iterator(0), + counting_iterator(num_vertices(g))); +} + +// From IncidenceGraph +template +class BOOST_CSR_GRAPH_TYPE::out_edge_iterator + : public iterator_facade::fast> +{ + public: + typedef typename int_t::fast difference_type; + + out_edge_iterator() {} + // Implicit copy constructor OK + explicit out_edge_iterator(edge_descriptor edge) : m_edge(edge) { } + + private: + // iterator_facade requirements + const edge_descriptor& dereference() const { return m_edge; } + + bool equal(const out_edge_iterator& other) const + { return m_edge == other.m_edge; } + + void increment() { ++m_edge.idx; } + void decrement() { ++m_edge.idx; } + void advance(difference_type n) { m_edge.idx += n; } + + difference_type distance_to(const out_edge_iterator& other) const + { return other.m_edge.idx - m_edge.idx; } + + edge_descriptor m_edge; + + friend class iterator_core_access; +}; + +template +inline Vertex +source(typename BOOST_CSR_GRAPH_TYPE::edge_descriptor e, + const BOOST_CSR_GRAPH_TYPE&) +{ + return e.src; +} + +template +inline Vertex +target(typename BOOST_CSR_GRAPH_TYPE::edge_descriptor e, + const BOOST_CSR_GRAPH_TYPE& g) +{ + return g.m_column[e.idx]; +} + +template +inline std::pair +out_edges(Vertex v, const BOOST_CSR_GRAPH_TYPE& g) +{ + typedef typename BOOST_CSR_GRAPH_TYPE::edge_descriptor ed; + typedef typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator it; + EdgeIndex v_row_start = g.m_rowstart[v]; + EdgeIndex next_row_start = g.m_rowstart[v + 1]; + return std::make_pair(it(ed(v, v_row_start)), + it(ed(v, (std::max)(v_row_start, next_row_start)))); +} + +template +inline EdgeIndex +out_degree(Vertex v, const BOOST_CSR_GRAPH_TYPE& g) +{ + EdgeIndex v_row_start = g.m_rowstart[v]; + EdgeIndex next_row_start = g.m_rowstart[v + 1]; + return (std::max)(v_row_start, next_row_start) - v_row_start; +} + +// From AdjacencyGraph +template +inline std::pair +adjacent_vertices(Vertex v, const BOOST_CSR_GRAPH_TYPE& g) +{ + EdgeIndex v_row_start = g.m_rowstart[v]; + EdgeIndex next_row_start = g.m_rowstart[v + 1]; + return std::make_pair(g.m_column.begin() + v_row_start, + g.m_column.begin() + + (std::max)(v_row_start, next_row_start)); +} + +// Extra, common functions +template +inline typename graph_traits::vertex_descriptor +vertex(typename graph_traits::vertex_descriptor i, + const BOOST_CSR_GRAPH_TYPE&) +{ + return i; +} + +// Unlike for an adjacency_matrix, edge_range and edge take lg(out_degree(i)) +// time +template +inline std::pair +edge_range(Vertex i, Vertex j, const BOOST_CSR_GRAPH_TYPE& g) +{ + typedef typename std::vector::const_iterator adj_iter; + typedef typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator out_edge_iter; + typedef typename BOOST_CSR_GRAPH_TYPE::edge_descriptor edge_desc; + std::pair raw_adjacencies = adjacent_vertices(i, g); + std::pair adjacencies = + std::equal_range(raw_adjacencies.first, raw_adjacencies.second, j); + EdgeIndex idx_begin = adjacencies.first - g.m_column.begin(); + EdgeIndex idx_end = adjacencies.second - g.m_column.begin(); + return std::make_pair(out_edge_iter(edge_desc(i, idx_begin)), + out_edge_iter(edge_desc(i, idx_end))); +} + +template +inline std::pair +edge(Vertex i, Vertex j, const BOOST_CSR_GRAPH_TYPE& g) +{ + typedef typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator out_edge_iter; + std::pair range = edge_range(i, j, g); + if (range.first == range.second) + return std::make_pair(typename BOOST_CSR_GRAPH_TYPE::edge_descriptor(), + false); + else + return std::make_pair(*range.first, true); +} + +// Find an edge given its index in the graph +template +inline typename BOOST_CSR_GRAPH_TYPE::edge_descriptor +edge_from_index(EdgeIndex idx, const BOOST_CSR_GRAPH_TYPE& g) +{ + typedef typename std::vector::const_iterator row_start_iter; + assert (idx < num_edges(g)); + row_start_iter src_plus_1 = + std::upper_bound(g.m_rowstart.begin(), + g.m_rowstart.begin() + g.m_last_source + 1, + idx); + // Get last source whose rowstart is at most idx + // upper_bound returns this position plus 1 + Vertex src = (src_plus_1 - g.m_rowstart.begin()) - 1; + return typename BOOST_CSR_GRAPH_TYPE::edge_descriptor(src, idx); +} + +// From EdgeListGraph +template +class BOOST_CSR_GRAPH_TYPE::edge_iterator +{ + public: + typedef std::forward_iterator_tag iterator_category; + typedef edge_descriptor value_type; + + typedef const edge_descriptor* pointer; + + typedef edge_descriptor reference; + typedef typename int_t::fast difference_type; + + edge_iterator() : rowstart_array(0), current_edge(), end_of_this_vertex(0) {} + + edge_iterator(const compressed_sparse_row_graph& graph, + edge_descriptor current_edge, + EdgeIndex end_of_this_vertex) + : rowstart_array(&graph.m_rowstart[0]), current_edge(current_edge), + end_of_this_vertex(end_of_this_vertex) {} + + // From InputIterator + reference operator*() const { return current_edge; } + pointer operator->() const { return ¤t_edge; } + + bool operator==(const edge_iterator& o) const { + return current_edge == o.current_edge; + } + bool operator!=(const edge_iterator& o) const { + return current_edge != o.current_edge; + } + + edge_iterator& operator++() { + ++current_edge.idx; + while (current_edge.idx == end_of_this_vertex) { + ++current_edge.src; + end_of_this_vertex = rowstart_array[current_edge.src + 1]; + } + return *this; + } + + edge_iterator operator++(int) { + edge_iterator temp = *this; + ++*this; + return temp; + } + + private: + const EdgeIndex* rowstart_array; + edge_descriptor current_edge; + EdgeIndex end_of_this_vertex; +}; + +template +inline EdgeIndex +num_edges(const BOOST_CSR_GRAPH_TYPE& g) +{ + return g.m_column.size(); +} + +template +std::pair +edges(const BOOST_CSR_GRAPH_TYPE& g) +{ + typedef typename BOOST_CSR_GRAPH_TYPE::edge_iterator ei; + typedef typename BOOST_CSR_GRAPH_TYPE::edge_descriptor edgedesc; + if (g.m_rowstart.size() == 1 || g.m_column.empty()) { + return std::make_pair(ei(), ei()); + } else { + // Find the first vertex that has outgoing edges + Vertex src = 0; + while (g.m_rowstart[src + 1] == 0) ++src; + return std::make_pair(ei(g, edgedesc(src, 0), g.m_rowstart[src + 1]), + ei(g, edgedesc(num_vertices(g), g.m_column.size()), 0)); + } +} + +// For Property Graph + +// Graph properties +template +inline void +set_property(BOOST_CSR_GRAPH_TYPE& g, Tag, const Value& value) +{ + get_property_value(g.m_property, Tag()) = value; +} + +template +inline +typename graph_property::type& +get_property(BOOST_CSR_GRAPH_TYPE& g, Tag) +{ + return get_property_value(g.m_property, Tag()); +} + +template +inline +const +typename graph_property::type& +get_property(const BOOST_CSR_GRAPH_TYPE& g, Tag) +{ + return get_property_value(g.m_property, Tag()); +} + +// Add edge_index property map +template +struct csr_edge_index_map +{ + typedef Index value_type; + typedef Index reference; + typedef Descriptor key_type; + typedef readable_property_map_tag category; +}; + +template +inline Index +get(const csr_edge_index_map&, + const typename csr_edge_index_map::key_type& key) +{ + return key.idx; +} + +// Doing the right thing here (by unifying with vertex_index_t and +// edge_index_t) breaks GCC. +template +struct property_map +{ +private: + typedef identity_property_map vertex_index_type; + typedef typename graph_traits::edge_descriptor + edge_descriptor; + typedef csr_edge_index_map edge_index_type; + + typedef typename mpl::if_, + edge_index_type, + detail::error_property_not_found>::type + edge_or_none; + +public: + typedef typename mpl::if_, + vertex_index_type, + edge_or_none>::type type; + + typedef type const_type; +}; + +template +inline identity_property_map +get(vertex_index_t, const BOOST_CSR_GRAPH_TYPE&) +{ + return identity_property_map(); +} + +template +inline Vertex +get(vertex_index_t, + const BOOST_CSR_GRAPH_TYPE&, Vertex v) +{ + return v; +} + +template +inline typename property_map::const_type +get(edge_index_t, const BOOST_CSR_GRAPH_TYPE&) +{ + typedef typename property_map::const_type + result_type; + return result_type(); +} + +template +inline EdgeIndex +get(edge_index_t, const BOOST_CSR_GRAPH_TYPE&, + typename BOOST_CSR_GRAPH_TYPE::edge_descriptor e) +{ + return e.idx; +} + +// Support for bundled properties +template +struct property_map +{ +private: + typedef graph_traits traits; + typedef VertexProperty vertex_bundled; + typedef EdgeProperty edge_bundled; + typedef typename ct_if<(detail::is_vertex_bundle::value), + typename traits::vertex_descriptor, + typename traits::edge_descriptor>::type + descriptor; + +public: + typedef bundle_property_map + type; + typedef bundle_property_map const_type; +}; + +template +inline +typename property_map::type +get(T Bundle::* p, BOOST_CSR_GRAPH_TYPE& g) +{ + typedef typename property_map::type + result_type; + return result_type(&g, p); +} + +template +inline +typename property_map::const_type +get(T Bundle::* p, BOOST_CSR_GRAPH_TYPE const & g) +{ + typedef typename property_map::const_type + result_type; + return result_type(&g, p); +} + +template +inline T +get(T Bundle::* p, BOOST_CSR_GRAPH_TYPE const & g, + const Key& key) +{ + return get(get(p, g), key); +} + +template +inline void +put(T Bundle::* p, BOOST_CSR_GRAPH_TYPE& g, + const Key& key, const T& value) +{ + put(get(p, g), key, value); +} + +#undef BOOST_CSR_GRAPH_TYPE +#undef BOOST_CSR_GRAPH_TEMPLATE_PARMS + +} // end namespace boost + +#endif // BOOST_GRAPH_COMPRESSED_SPARSE_ROW_GRAPH_HPP