From 18ae1c65bb8738ae254bf6c8fd538645715cc496 Mon Sep 17 00:00:00 2001 From: Andrew Lumsdaine Date: Sun, 27 Dec 2020 16:34:24 -0800 Subject: [PATCH 001/385] update --- include/containers/edge_list.hpp | 25 +++++++------------------ include/containers/soa.hpp | 32 ++++++++++++++++++++++++-------- include/graph_base.hpp | 6 +++--- 3 files changed, 34 insertions(+), 29 deletions(-) mode change 100644 => 100755 include/containers/soa.hpp diff --git a/include/containers/edge_list.hpp b/include/containers/edge_list.hpp index 91480885..423831bf 100644 --- a/include/containers/edge_list.hpp +++ b/include/containers/edge_list.hpp @@ -11,12 +11,10 @@ #ifndef NW_GRAPH_EDGE_LIST_HPP #define NW_GRAPH_EDGE_LIST_HPP -#include "containers/aos.hpp" #include "containers/soa.hpp" #include "containers/compressed.hpp" #include "graph_base.hpp" -#include "adaptors/plain_range.hpp" #include "util/provenance.hpp" #if defined(CL_SYCL_LANGUAGE_VERSION) @@ -65,17 +63,8 @@ class adj_list; template -// #define EDGELIST_AOS - -#if defined(EDGELIST_AOS) -class edge_list : public graph_base, public array_of_structs { - using base = array_of_structs; -#else class edge_list : public graph_base, public struct_of_arrays { using base = struct_of_arrays; - -#endif - using element = std::tuple; public: @@ -115,7 +104,7 @@ class edge_list : public graph_base, public struct_of_arrays x(*this); - edge_list x(graph_base::lim[0]); + edge_list x(graph_base::vertex_cardinality[0]); x.resize(base::size()); x.open_for_push_back(); @@ -152,7 +141,7 @@ class edge_list : public graph_base, public struct_of_arrays x(2 * graph_base::lim[0]); + edge_list x(2 * graph_base::vertex_cardinality[0]); x.open_for_push_back(); #if 1 @@ -207,8 +196,8 @@ class edge_list : public graph_base, public struct_of_arrays(magic), sizeof(magic)); size_t d = edge_directedness; outfile.write(reinterpret_cast(&d), sizeof(d)); - outfile.write(reinterpret_cast(lim), sizeof(lim)); + outfile.write(reinterpret_cast(vertex_cardinality), sizeof(vertex_cardinality)); outfile.write(reinterpret_cast(&min_), sizeof(min_)); outfile.write(reinterpret_cast(&max_), sizeof(max_)); base::serialize(outfile); @@ -725,7 +714,7 @@ class edge_list : public graph_base, public struct_of_arrays(lim), sizeof(lim)); + infile.read(reinterpret_cast(vertex_cardinality), sizeof(vertex_cardinality)); infile.read(reinterpret_cast(&min_), sizeof(min_)); infile.read(reinterpret_cast(&max_), sizeof(max_)); base::deserialize(infile); @@ -746,7 +735,7 @@ class edge_list : public graph_base, public struct_of_arrays @@ -43,9 +42,6 @@ struct struct_of_arrays : std::tuple...> { using storage_type = std::tuple...>; using base = std::tuple...>; - struct_of_arrays() = default; - struct_of_arrays(size_t M) : base(std::vector(M)...) {} - template class It { std::tuple start; @@ -55,9 +51,9 @@ struct struct_of_arrays : std::tuple...> { public: using value_type = typename std::tuple::value_type...>; + using difference_type = std::ptrdiff_t; using reference = typename std::tuple::reference...>; using pointer = typename std::tuple::pointer...>; - using difference_type = std::ptrdiff_t; using iterator_category = std::random_access_iterator_tag; It() = default; @@ -134,7 +130,27 @@ struct struct_of_arrays : std::tuple...> { bool operator<=(const It& x) const { return cursor <= x.cursor; } }; - using iterator = It::iterator...>; + using iterator = It::iterator...>; + + using value_type = iterator::value_type; + using reference = iterator::reference; + using size_type = std::size_t; + using difference_type = iterator::difference_type; + using pointer = iterator::pointer; + + using const_iterator = It::iterator...>; + using const_reference = const_iterator::reference; + using const_pointer = const_iterator::pointer; + + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + struct_of_arrays() = default; + struct_of_arrays(size_t M) : base(std::vector(M)...) {} + + struct_of_arrays(std::initializer_list l) { + for_each(l.begin(), l.end(), [&](value_type x) { push_back(x); }); + } iterator begin() { return std::apply([](auto&... vs) { return iterator(vs.begin()...); }, *this); diff --git a/include/graph_base.hpp b/include/graph_base.hpp index cec44d2c..5cad4bbb 100644 --- a/include/graph_base.hpp +++ b/include/graph_base.hpp @@ -51,11 +51,11 @@ class other_direction { class graph_base { public: - graph_base(size_t d0) : lim{d0, d0}, is_open(false) {} - graph_base(size_t d0, size_t d1) : lim{d0, d1}, is_open(false) {} + graph_base(size_t d0) : vertex_cardinality{d0, d0}, is_open(false) {} + graph_base(size_t d0, size_t d1) : vertex_cardinality{d0, d1}, is_open(false) {} protected: - size_t lim[2]; // ordinal limits + size_t vertex_cardinality[2]; // ordinal limits bool is_open; // can we mutate graph }; From 7d6a6968ca02859745b5a7162702d00f8ddcab58 Mon Sep 17 00:00:00 2001 From: Andrew Lumsdaine Date: Sun, 27 Dec 2020 16:38:24 -0800 Subject: [PATCH 002/385] cleanup --- CMakeLists.txt | 4 +- test/CMakeLists.txt | 1 + test/ranges_test.cpp | 226 +++++++++++++++++++++++++++++++++++++++++++ test/soa_test.cpp | 106 ++++++++++++++++++++ 4 files changed, 335 insertions(+), 2 deletions(-) create mode 100644 test/ranges_test.cpp create mode 100644 test/soa_test.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 93f1700e..40e387b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -62,8 +62,8 @@ if (NW_GRAPH_SANITIZE) set(CMAKE_LINKER_FLAGS "${CMAKE_LINKER_FLAGS} -fsanitize=${NW_GRAPH_SANITIZE}") endif (NW_GRAPH_SANITIZE) -option(NW_GRAPH_BUILD_TESTS "Determines whether to build tests." OFF) -option(NW_GRAPH_BUILD_APBS "Determines whether to build abstraction penalty benchmarks." ON) +option(NW_GRAPH_BUILD_TESTS "Determines whether to build tests." ON) +option(NW_GRAPH_BUILD_APBS "Determines whether to build abstraction penalty benchmarks." OFF) option(NW_GRAPH_BUILD_BENCH "Determines whether to build performance benchmarks." OFF) option(NW_GRAPH_BUILD_EXAMPLES "Determines whether to build examples." OFF) option(NW_GRAPH_USE_TBBMALLOC "Link to tbbmalloc" OFF) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 74854ad8..55f473cb 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -19,6 +19,7 @@ endmacro (nw_graph_add_test) # Add Catch2 tests nw_graph_add_test(mmio_test) nw_graph_add_test(aos_test) +nw_graph_add_test(soa_test) nw_graph_add_test(aolos_test) nw_graph_add_test(vov_test) nw_graph_add_test(bfs_test_0) diff --git a/test/ranges_test.cpp b/test/ranges_test.cpp new file mode 100644 index 00000000..2ecebbe7 --- /dev/null +++ b/test/ranges_test.cpp @@ -0,0 +1,226 @@ + +#if 0 +template +concept AdjacencyGraphAA = + requires(G g, size_t i) { + typename G::iterator; + { g.begin() } -> std::convertible_to; + { g.end() } -> std::convertible_to; + { g[i] } -> std::convertible_to; + { g.size() } -> std::convertible_to; +}; + +#include + + +template +concept AdjacencyGraph = std::ranges::random_access_range; + + +template< class T > +concept _range = requires(T& t) { + t.begin(); + t.end(); +}; + +template< class T > +concept _sized_range = _range && + requires(T& t) { + t.size(); + }; + +template +concept _input_range = + _range ; // && std::input_iterator; + +template +concept _forward_range = + _input_range ; // && std::forward_iterator; + +template +concept _bidirectional_range = + _forward_range ; // && std::bidirectional_iterator; + +template +concept _random_access_range = + _bidirectional_range ; // && std::random_access_iterator; + + // outer_iterator ... failing is_constructible<> + + +template +concept AdjacencyGraph = ranges::random_access_range && + ranges::forward_range && + std::is_convertible_v; + // value_type of inner_range is a tuple + // edge? -- tuple is source, target, edge properties + // vertex? -- tuple is target, vertex properties -- or are vertex properties always indexable (random_access_range)? + + + // In original Boost.Graph + // AdjacencyGraph => inner container is vertices (rarely used) + // IncidenceGraph => inner container is edges + // with Incidence Graph -- one can get neighbor vertices and vertex properties if vertex properties are indexable + +template +concept IncidenceGraph = ranges::random_access_range && + ranges::forward_range && + std::is_same_v>; + // Still need to be able store this as CSR + // Adapt to edge_range + + +template +concept TopologyGraph = ranges::random_access_range && + ranges::forward_range && + std::is_same_v>; + + // I. Conceptify interfaces -> IncidenceGraph + // A. const + // II. Refactor algorithms to use IncidenceGraph + // III. Maybe not use std::get<0> and std::get<1> for accessing edge information (source/target?) + // IV. Maybe rather than begin()/end() -> neighbors()? or out_edges()? +#endif + +#include +#include +#include "vovos.hpp" +#include "aolos.hpp" +#include "compressed.hpp" +#include "util/intersection_size.hpp" + + + +template +using inner_range = std::ranges::range_value_t; + +template +using inner_value = std::ranges::range_value_t>; + +template +using vertex_id_t = nw::graph::vertex_id_t; + +template +using index_t = nw::graph::vertex_id_t; + +template +concept Adjacence = + requires (T graph, inner_value vertex) { + { target (vertex) } -> std::convertible_to>; + }; + +template +concept Incidence = + requires (T graph, inner_value edge) { + { source (edge) } -> std::convertible_to>; + { target (edge) } -> std::convertible_to>; + }; + +template +concept Graph = + std::ranges::random_access_range && + std::ranges::forward_range> && + std::convertible_to, index_t>; + +template +concept IncidenceGraph = Graph && Incidence; + +template +concept AdjacenceGraph = Graph && Adjacence; + + +template +size_t triangle_count(const GraphT& A) { + size_t triangles = 0; + auto first = A.begin(); + auto last = A.end(); + + for (auto G = first; first != last; ++first) { + for (auto v = (*first).begin(); v != (*first).end(); ++v) { + triangles += nw::graph::intersection_size(*first, G[std::get<0>(*v)]); + } + } + + return triangles; +} + + +template +auto bfs(const Graph_t& graph, vertex_id_t root) requires Graph { + + std::deque> q1, q2; + std::vector> level(graph.size(), std::numeric_limits>::max()); + std::vector> parents(graph.size(), std::numeric_limits>::max()); + size_t lvl = 0; + + q1.push_back(root); + level[root] = lvl++; + parents[root] = root; + + auto g = graph.begin(); + + while (!q1.empty()) { + + std::for_each(q1.begin(), q1.end(), [&](vertex_id_t u) { + std::for_each(g[u].begin(), g[u].end(), [&](auto&& x) { + vertex_id_t v = std::get<0>(x); + if (level[v] == std::numeric_limits>::max()) { + q2.push_back(v); + level[v] = lvl; + parents[v] = u; + } + }); + }); + std::swap(q1, q2); + q2.clear(); + ++lvl; + } + return parents; +} + + +template +auto foo(const T& A) requires Graph { + + auto _b = std::ranges::begin(A); + auto _e = std::ranges::end(A); + auto _f = A[0]; + + auto _b_b = std::ranges::begin(*_b); + auto _b_e = std::ranges::end(*_b); + + for (auto& j : A) { + for (auto& k : j) { + + } + } + + for (auto& j : A[0]) { + + } + +} + + +int main() { + + triangle_count(nw::graph::vov<>(5)); + triangle_count(nw::graph::adj_list<>(5)); + + bfs(nw::graph::vov<>(5), 0); + bfs(nw::graph::adj_list<>(5), 0); + + foo(nw::graph::vector_of_vector_of_structs(5)); + foo(nw::graph::vov<>(5)); + + + foo(nw::graph::array_of_list_of_structs(5)); + foo(nw::graph::adj_list(5)); + + + + // foo>(); + + + return 0; +} diff --git a/test/soa_test.cpp b/test/soa_test.cpp new file mode 100644 index 00000000..07dd87ca --- /dev/null +++ b/test/soa_test.cpp @@ -0,0 +1,106 @@ +// +// This file is part of BGL17 (aka NWGraph aka GraphPack aka the Graph Standard Library) +// (c) Pacific Northwest National Laboratory 2018 +// +// Licensed under Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License +// https://creativecommons.org/licenses/by-nc-sa/4.0/ +// +// Author: Andrew Lumsdaine +// + +#include + +#include "containers/soa.hpp" + +#include "common/test_header.hpp" + +using namespace nw::graph; +using namespace nw::util; + +template +void test_assignment(Iterator iter, size_t index = 0) { + typename std::iterator_traits::reference tuple = index ? *iter : iter[index]; + std::get(tuple) = 0; + typename std::iterator_traits::reference tuple1 = index ? *iter : iter[index]; + REQUIRE(std::get(tuple1) == 0); + std::get(tuple1) = 1; + typename std::iterator_traits::reference tuple2 = index ? *iter : iter[index]; + REQUIRE(std::get(tuple2) == 1); +} + + +TEST_CASE("struct of arrays", "[soa]") { + SECTION("push back") { + struct_of_arrays E; + struct_of_arrays F; + struct_of_arrays G; + struct_of_arrays H; + + E.push_back(8675309); + F.push_back(867, 5309); + G.push_back(867, 5309, 3.14159); + H.push_back(95141.3, 867, 5309, 3.14159); + H.push_back(195141.3, 1867, 15309, 13.14159); + H.push_back(295141.3, 2867, 25309, 23.14159); + H.push_back(395141.3, 3867, 35309, 33.14159); + + auto e = E.begin(); + REQUIRE(std::get<0>(*e) == 8675309); + auto f = F.begin(); + REQUIRE(std::get<0>(*f) == 867); + REQUIRE(std::get<1>(*f) == 5309); + auto h = H.begin(); + REQUIRE(std::get<0>(*h) == 95141.3); + REQUIRE(std::get<1>(*h) == 867); + REQUIRE(std::get<2>(*h) == 5309); + REQUIRE(std::get<3>(*h) == 3.14159); + REQUIRE(std::get<0>(h[3]) == 395141.3); + REQUIRE(std::get<1>(h[3]) == 3867); + REQUIRE(std::get<2>(h[3]) == 35309); + REQUIRE(std::get<3>(h[3]) == 33.14159); + } + + SECTION("initializer list") { + struct_of_arrays E ({ 1, 2, 3 }); + + struct_of_arrays F { 1, 2, 3 }; + + struct_of_arrays G { {1}, {2}, {3} }; + } + + SECTION("assignment through iterator") { + struct_of_arrays E; + struct_of_arrays F; + struct_of_arrays G; + struct_of_arrays H; + + E.push_back(8675309); + F.push_back(867, 5309); + G.push_back(867, 5309, 3.14159); + H.push_back(95141.3, 867, 5309, 3.14159); + H.push_back(195141.3, 1867, 15309, 13.14159); + H.push_back(295141.3, 2867, 25309, 23.14159); + H.push_back(395141.3, 3867, 35309, 33.14159); + + auto e = E.begin(); + test_assignment<0>(e); + auto f = F.begin(); + test_assignment<0>(f); + test_assignment<1>(f); + auto h = H.begin(); + test_assignment<0>(h); + test_assignment<1>(h); + test_assignment<3>(h); + test_assignment<0>(h, 3); + test_assignment<1>(h, 3); + test_assignment<2>(h, 3); + test_assignment<3>(h, 3); + } + + SECTION("assignment through iterator") { + + } +} + + + From 206b15d7f9105bd2c50c19b755ab5eb54089473d Mon Sep 17 00:00:00 2001 From: Andrew Lumsdaine Date: Sun, 27 Dec 2020 21:51:26 -0800 Subject: [PATCH 003/385] soa refactor mildly --- include/containers/soa.hpp | 44 +++++++++++++++++++++------------- test/soa_test.cpp | 49 ++++++++++++++++++++++++++++++++------ 2 files changed, 70 insertions(+), 23 deletions(-) diff --git a/include/containers/soa.hpp b/include/containers/soa.hpp index ae1b3879..0fd0593d 100755 --- a/include/containers/soa.hpp +++ b/include/containers/soa.hpp @@ -23,7 +23,8 @@ #include #include -#include "util.hpp" +#include "util/print_types.hpp" +#include "util/util.hpp" #if defined(CL_SYCL_LANGUAGE_VERSION) #include @@ -47,8 +48,6 @@ struct struct_of_arrays : std::tuple...> { std::tuple start; std::size_t cursor = 0; - It(const std::tuple& iters, std::size_t init) : start(iters), cursor(init) {} - public: using value_type = typename std::tuple::value_type...>; using difference_type = std::ptrdiff_t; @@ -58,11 +57,14 @@ struct struct_of_arrays : std::tuple...> { It() = default; It(const It&) = default; + It& operator=(const It&) = default; + It(It&&) = default; It& operator=(It&&) = default; - explicit It(const RandomAccessIterators... iters) : start(iters...) {} + It(const std::tuple& iters, std::size_t init = 0) : start(iters), cursor(init) {} + It(const RandomAccessIterators... iters, std::size_t init = 0) : start(iters...), cursor(init) {} friend void swap(It a, It b) { std::apply([&](auto&&... is) { (std::swap(*a.start[is], *b.start[is]), ...); }, @@ -130,17 +132,17 @@ struct struct_of_arrays : std::tuple...> { bool operator<=(const It& x) const { return cursor <= x.cursor; } }; - using iterator = It::iterator...>; + using iterator = It::iterator...>; - using value_type = iterator::value_type; - using reference = iterator::reference; - using size_type = std::size_t; - using difference_type = iterator::difference_type; - using pointer = iterator::pointer; + using value_type = typename iterator::value_type; + using reference = typename iterator::reference; + using size_type = std::size_t; + using difference_type = typename iterator::difference_type; + using pointer = typename iterator::pointer; - using const_iterator = It::iterator...>; - using const_reference = const_iterator::reference; - using const_pointer = const_iterator::pointer; + using const_iterator = It::const_iterator...>; + using const_reference = typename const_iterator::reference; + using const_pointer = typename const_iterator::pointer; using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; @@ -156,13 +158,23 @@ struct struct_of_arrays : std::tuple...> { return std::apply([](auto&... vs) { return iterator(vs.begin()...); }, *this); } - iterator begin() const { - return std::apply([](auto&... vs) { return iterator(vs.begin()...); }, *this); + const_iterator begin() const { + return std::apply([](auto&... vs) { return const_iterator(vs.begin()...); }, *this); } iterator end() { return begin() + size(); } - iterator end() const { return begin() + size(); } + const_iterator end() const { return begin() + size(); } + + reference operator[](std::size_t i) { + return begin()[i]; + // return std::apply([&](auto&&... r) { return std::forward_as_tuple(std::forward(r)[i]...); }, *this); + } + + const_reference operator[](std::size_t i) const { + return begin()[i]; + // return std::apply([&](auto&&... r) { return std::forward_as_tuple(std::forward(r)[i]...); }, *this); + } void push_back(Attributes... attrs) { std::apply([&](auto&... vs) { (vs.push_back(attrs), ...); }, *this); diff --git a/test/soa_test.cpp b/test/soa_test.cpp index 07dd87ca..2ef5e127 100644 --- a/test/soa_test.cpp +++ b/test/soa_test.cpp @@ -14,6 +14,9 @@ #include "common/test_header.hpp" +#include "util/print_types.hpp" + + using namespace nw::graph; using namespace nw::util; @@ -61,11 +64,21 @@ TEST_CASE("struct of arrays", "[soa]") { } SECTION("initializer list") { - struct_of_arrays E ({ 1, 2, 3 }); - - struct_of_arrays F { 1, 2, 3 }; - - struct_of_arrays G { {1}, {2}, {3} }; + struct_of_arrays E { 8, 6, 7, 5, 3, 0, 9}; + struct_of_arrays F { {0, 8}, {1, 6}, {2, 7} }; + struct_of_arrays G { {0, 8, 6.7}, {5,3, 0.9}, {8, 6, 7.5309} }; + struct_of_arrays H { {3, 0, 8, 6.7}, {.1, 5, 3, 0.9}, {4.159, 8, 6, 7.5309} }; + + REQUIRE(std::get<0>(E[3]) == 5); + REQUIRE(std::get<0>(F[2]) == 2); + REQUIRE(std::get<1>(F[2]) == 7); + REQUIRE(std::get<0>(G[2]) == 8); + REQUIRE(std::get<1>(G[2]) == 6); + REQUIRE(std::get<2>(G[2]) == 7.5309); + REQUIRE(std::get<0>(H[2]) == 4.159); + REQUIRE(std::get<1>(H[2]) == 8); + REQUIRE(std::get<2>(H[2]) == 6); + REQUIRE(std::get<3>(H[2]) == 7.5309); } SECTION("assignment through iterator") { @@ -96,9 +109,31 @@ TEST_CASE("struct of arrays", "[soa]") { test_assignment<2>(h, 3); test_assignment<3>(h, 3); } +} + + +template +void foo(SOA& s) { + SOA t(s); + REQUIRE(std::get<0>(s[0]) == std::get<0>(t[0])); +} + +template +void bar(const SOA& s) { + SOA t(s); + REQUIRE(std::get<0>(s[0]) == std::get<0>(t[0])); +} + + +TEST_CASE("struct of arrays const", "[c_soa]") { + SECTION("const iterator") { + struct_of_arrays E { 8, 6, 7, 5, 3, 0, 9}; + struct_of_arrays F { {0, 8}, {1, 6}, {2, 7} }; + struct_of_arrays G { {0, 8, 6.7}, {5,3, 0.9}, {8, 6, 7.5309} }; + struct_of_arrays H { {3, 0, 8, 6.7}, {.1, 5, 3, 0.9}, {4.159, 8, 6, 7.5309} }; + foo(E); + bar(E); - SECTION("assignment through iterator") { - } } From 842f77074cd694ce3b48b1bd2802f9c68f45c97f Mon Sep 17 00:00:00 2001 From: Andrew Lumsdaine Date: Sun, 27 Dec 2020 21:52:46 -0800 Subject: [PATCH 004/385] soa refactor mildly --- include/containers/soa.hpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/include/containers/soa.hpp b/include/containers/soa.hpp index 0fd0593d..adc71265 100755 --- a/include/containers/soa.hpp +++ b/include/containers/soa.hpp @@ -167,13 +167,11 @@ struct struct_of_arrays : std::tuple...> { const_iterator end() const { return begin() + size(); } reference operator[](std::size_t i) { - return begin()[i]; - // return std::apply([&](auto&&... r) { return std::forward_as_tuple(std::forward(r)[i]...); }, *this); + return std::apply([&](auto&&... r) { return std::forward_as_tuple(std::forward(r)[i]...); }, *this); } const_reference operator[](std::size_t i) const { - return begin()[i]; - // return std::apply([&](auto&&... r) { return std::forward_as_tuple(std::forward(r)[i]...); }, *this); + return std::apply([&](auto&&... r) { return std::forward_as_tuple(std::forward(r)[i]...); }, *this); } void push_back(Attributes... attrs) { From e087de38944db18e91d10f4350fb1165d90e0075 Mon Sep 17 00:00:00 2001 From: Andrew Lumsdaine Date: Mon, 28 Dec 2020 16:30:00 -0800 Subject: [PATCH 005/385] refactor, add const_iterators to edge_list and compressed --- CMakeLists.txt | 2 +- include/adaptors/splittable_range_adapter.hpp | 2 +- include/algorithms/bfs.hpp | 6 +- include/containers/aolos.hpp | 8 +- include/containers/aos.hpp | 106 +++--- include/containers/compressed.hpp | 335 +++++++++--------- include/containers/edge_list.hpp | 242 ++++++------- include/containers/soa.hpp | 6 +- include/graph_base.hpp | 9 +- include/io/mmio.hpp | 6 +- include/util/types.hpp | 4 +- include/util/util.hpp | 15 +- test/compressed_test.cpp | 170 ++++++++- test/idxsoa_1.cpp | 2 +- 14 files changed, 531 insertions(+), 382 deletions(-) mode change 100755 => 100644 include/containers/soa.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 40e387b2..a7557d36 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,7 +49,7 @@ include(CompilerFlags) # ----------------------------------------------------------------------------- # Select a C++ standard # ----------------------------------------------------------------------------- -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) diff --git a/include/adaptors/splittable_range_adapter.hpp b/include/adaptors/splittable_range_adapter.hpp index faed6717..dd1fcde4 100644 --- a/include/adaptors/splittable_range_adapter.hpp +++ b/include/adaptors/splittable_range_adapter.hpp @@ -4,7 +4,7 @@ #define NW_GRAPH_SPLITTABLE_RANGE_ADAPTER_HPP #include -#include +#include namespace nw { namespace graph { diff --git a/include/algorithms/bfs.hpp b/include/algorithms/bfs.hpp index fec8e50c..9878da46 100644 --- a/include/algorithms/bfs.hpp +++ b/include/algorithms/bfs.hpp @@ -280,13 +280,17 @@ auto bfs_v9(Graph& graph, vertex_id_t root) { } template -[[gnu::noinline]] auto bfs_top_down(Graph&& graph, vertex_id_t root) { +[[gnu::noinline]] auto bfs_top_down(Graph&& graph, Graph::vertex_id_t root) { + using vertex_id_t = Graph::vertex_id_t; + constexpr const std::size_t num_bins = 32; const std::size_t N = graph.max() + 1; std::vector> q1(num_bins); std::vector> q2(num_bins); std::vector parents(N); + constexpr const auto null_vertex = null_vertex_v(); + std::fill(std::execution::par_unseq, parents.begin(), parents.end(), null_vertex); q1[0].push_back(root); diff --git a/include/containers/aolos.hpp b/include/containers/aolos.hpp index d9c015c4..02893c05 100644 --- a/include/containers/aolos.hpp +++ b/include/containers/aolos.hpp @@ -8,8 +8,8 @@ #ifndef NW_GRAPH_AOLOS_HPP #define NW_GRAPH_AOLOS_HPP -#include "graph_base.hpp" #include "edge_list.hpp" +#include "graph_base.hpp" #include #include #include @@ -49,10 +49,12 @@ template class adj_list : public array_of_list_of_structs { public: adj_list(size_t N) : array_of_list_of_structs(N) {} - adj_list(edge_list& A) : array_of_list_of_structs(std::max(A.max()[0], A.max()[1]) + 1) { + adj_list(edge_list& A) + : array_of_list_of_structs(std::max(A.max()[0], A.max()[1]) + 1) { A.fill(*this); } - adj_list(edge_list& A) : array_of_list_of_structs(std::max(A.max()[0], A.max()[1]) + 1) { + adj_list(edge_list& A) + : array_of_list_of_structs(std::max(A.max()[0], A.max()[1]) + 1) { A.fill(*this); } diff --git a/include/containers/aos.hpp b/include/containers/aos.hpp index 28621256..e727c514 100644 --- a/include/containers/aos.hpp +++ b/include/containers/aos.hpp @@ -43,18 +43,18 @@ namespace nw { namespace graph { - // Bare bones array of structs (vector of tuples) - template - class array_of_structs : public std::vector> { +// Bare bones array of structs (vector of tuples) +template +class array_of_structs : public std::vector> { - public: - using storage_type = std::vector>; - using base = std::vector>; - using reference = typename std::iterator_traits::reference; +public: + using storage_type = std::vector>; + using base = std::vector>; + using reference = typename std::iterator_traits::reference; - // storage_type storage_; + // storage_type storage_; - public: +public: #if 0 void clear() { storage_.clear(); } @@ -70,54 +70,52 @@ namespace graph { #endif - void push_back(const std::tuple& attrs) { base::push_back(attrs); } - void push_back(const std::tuple& attrs) { base::push_back(attrs); } - void push_back(const Attributes&... attrs) { base::push_back({attrs...}); } + void push_back(const std::tuple& attrs) { base::push_back(attrs); } + void push_back(const std::tuple& attrs) { base::push_back(attrs); } + void push_back(const Attributes&... attrs) { base::push_back({attrs...}); } - bool operator==(array_of_structs& a) { - return std::equal(std::execution::par, base::begin(), base::end(), a.begin()); - } - bool operator!=(const storage_type& a) { return !operator==(a); } - - template - void print_helper(std::ostream& output_stream, std::tuple attrs, std::index_sequence) { - output_stream << "( "; - (..., (output_stream << (0 == Is ? "" : ", ") << std::get(attrs))); - output_stream << " )" << std::endl; - } - - void stream(std::ostream& output_stream, const std::string& msg = "") { - output_stream << msg; - for (auto& element : *this) { - print_helper(output_stream, element, std::make_index_sequence()); - } - } - - void stream(const std::string& msg = "") { stream(std::cout, msg); } - - // size (number of elements) - // sizeof data elements - // data elements - - void serialize(std::ostream& outfile) const { - size_t st_size = base::size(); - size_t el_size = sizeof(dynamic_cast(*this)[0]); - - outfile.write(reinterpret_cast(&st_size), sizeof(size_t)); - outfile.write(reinterpret_cast(&el_size), sizeof(size_t)); - outfile.write(reinterpret_cast(base::data()), st_size * el_size); - } + bool operator==(array_of_structs& a) { return std::equal(std::execution::par, base::begin(), base::end(), a.begin()); } + bool operator!=(const storage_type& a) { return !operator==(a); } - void deserialize(std::istream& infile) { - size_t st_size = -1; - size_t el_size = -1; + template + void print_helper(std::ostream& output_stream, std::tuple attrs, std::index_sequence) { + output_stream << "( "; + (..., (output_stream << (0 == Is ? "" : ", ") << std::get(attrs))); + output_stream << " )" << std::endl; + } - infile.read(reinterpret_cast(&st_size), sizeof(size_t)); - infile.read(reinterpret_cast(&el_size), sizeof(size_t)); - base::resize(st_size); - infile.read(reinterpret_cast(base::data()), st_size * el_size); + void stream(std::ostream& output_stream, const std::string& msg = "") { + output_stream << msg; + for (auto& element : *this) { + print_helper(output_stream, element, std::make_index_sequence()); } - }; -} + } + + void stream(const std::string& msg = "") { stream(std::cout, msg); } + + // size (number of elements) + // sizeof data elements + // data elements + + void serialize(std::ostream& outfile) const { + size_t st_size = base::size(); + size_t el_size = sizeof(dynamic_cast(*this)[0]); + + outfile.write(reinterpret_cast(&st_size), sizeof(size_t)); + outfile.write(reinterpret_cast(&el_size), sizeof(size_t)); + outfile.write(reinterpret_cast(base::data()), st_size * el_size); + } + + void deserialize(std::istream& infile) { + size_t st_size = -1; + size_t el_size = -1; + + infile.read(reinterpret_cast(&st_size), sizeof(size_t)); + infile.read(reinterpret_cast(&el_size), sizeof(size_t)); + base::resize(st_size); + infile.read(reinterpret_cast(base::data()), st_size * el_size); + } +}; +} // namespace graph } // namespace nw #endif // NW_GRAPH_AOS_HPP diff --git a/include/containers/compressed.hpp b/include/containers/compressed.hpp index c0812fbe..feff93c5 100644 --- a/include/containers/compressed.hpp +++ b/include/containers/compressed.hpp @@ -3,16 +3,17 @@ #ifndef NW_GRAPH_COMPRESSED_HPP #define NW_GRAPH_COMPRESSED_HPP +#include "adaptors/splittable_range_adapter.hpp" #include "containers/aos.hpp" #include "containers/edge_list.hpp" +#include "containers/soa.hpp" #include "graph_base.hpp" +#include "util/defaults.hpp" #include "util/proxysort.hpp" -#include "containers/soa.hpp" -#include "adaptors/splittable_range_adapter.hpp" #include "util/util.hpp" -#include "util/types.hpp" #include +#include #include #include #include @@ -33,9 +34,9 @@ #include #include +#include "util/defaults.hpp" #include "util/demangle.hpp" #include "util/timer.hpp" -#include "util/types.hpp" namespace nw { namespace graph { @@ -47,128 +48,123 @@ void debug_compressed(bool flag = true) { g_debug_compressed = flag; } void time_compressed(bool flag = true) { g_time_compressed = flag; } -template +template class indexed_struct_of_arrays { - constexpr static const char magic_[24] = "BGL17 compressed_sparse"; + constexpr static const char magic_[34] = "NW GRAPH indexed_struct_of_arrays"; - bool is_open_ = false; - vertex_id_t N_; + bool is_open_ = false; + index_t N_; public: // fixme - std::vector indices_; + std::vector indices_; struct_of_arrays to_be_indexed_; - using edge_id_t = std::ptrdiff_t; - using inner_iterator = typename struct_of_arrays::iterator; - using sub_view = nw::graph::splittable_range_adapter; + using inner_iterator = typename struct_of_arrays::iterator; + using const_inner_iterator = typename struct_of_arrays::const_iterator; + using sub_view = nw::graph::splittable_range_adapter; + using const_sub_view = nw::graph::splittable_range_adapter; static constexpr std::size_t getNAttr() { return sizeof...(Attributes); } indexed_struct_of_arrays(size_t N) : N_(N), indices_(N + 1) {} indexed_struct_of_arrays(size_t N, size_t M) : N_(N), indices_(N + 1), to_be_indexed_(M) {} - /// A linear edge iterator that supports random-access operations. - /// - /// This edge iterator currently only iterates edges as u,v - /// pairs. Bidirectional iterator operations are very efficient, while random - /// access operations like `+=` require a log2 search of the index array. - /// - /// @tparam Attrs... The 0-based indices of the edge attributes to access. template - class edge_iterator { + class flat_iterator { public: - using difference_type = edge_id_t; - using value_type = nw::graph::select_t, 0, 1, (Attrs + 2)...>; - using reference = nw::graph::select_t, 0, 1, (Attrs + 2)...>; - using pointer = nw::graph::select_t, 0, 1, (Attrs + 2)...>; + using difference_type = std::ptrdiff_t; + using value_type = nw::graph::select_t, 0, 1, (Attrs + 2)...>; + using reference = nw::graph::select_t, 0, 1, (Attrs + 2)...>; + using pointer = nw::graph::select_t, 0, 1, (Attrs + 2)...>; using iterator_category = std::random_access_iterator_tag; private: indexed_struct_of_arrays& graph_; // the underlying indexed data - vertex_id_t u_; // the current source vertex id - edge_id_t j_; // the current edge + index_t u_; // the current source vertex id + difference_type j_; // the current edge public: - edge_iterator(indexed_struct_of_arrays& graph, vertex_id_t i, edge_id_t j) : graph_(graph), u_(i), j_(j) {} + flat_iterator(indexed_struct_of_arrays& graph, index_t i, difference_type j) : graph_(graph), u_(i), j_(j) {} reference operator*() { return {u_, std::get<0>(graph_.to_be_indexed_)[j_], std::get(graph_.to_be_indexed_)[j_]...}; } - reference operator[](edge_id_t n) { + reference operator[](difference_type n) { return {graph_.source(j_ + n), std::get<0>(graph_.to_be_indexed_)[j_ + n], std::get(graph_.to_be_indexed_)[j_]...}; } - edge_iterator& operator++() { + flat_iterator& operator++() { for (++j_; j_ >= graph_.indices_[u_ + 1] && u_ < graph_.indices_.size() - 1; ++u_) ; return *this; } - edge_iterator& operator--() { + flat_iterator& operator--() { for (--j_; j_ < graph_.indices_[u_] && u_ > 0; --u_) ; return *this; } - edge_iterator operator++(int) { - edge_iterator i = *this; + flat_iterator operator++(int) { + flat_iterator i = *this; ++(*this); return i; } - edge_iterator operator--(int) { - edge_iterator i = *this; + flat_iterator operator--(int) { + flat_iterator i = *this; ++(*this); return i; } - edge_iterator& operator+=(edge_id_t n) { + flat_iterator& operator+=(difference_type n) { j_ += n; u_ = graph_.source(j_); return *this; } - edge_iterator& operator-=(edge_id_t n) { + flat_iterator& operator-=(difference_type n) { j_ -= n; u_ = graph_.source(j_); return *this; } - edge_iterator operator+(edge_id_t n) const { return {graph_, graph_.source(j_ + n), j_ + n}; } + flat_iterator operator+(difference_type n) const { return {graph_, graph_.source(j_ + n), j_ + n}; } - edge_iterator operator-(edge_id_t n) const { return {graph_, graph_.source(j_ - n), j_ - n}; } + flat_iterator operator-(difference_type n) const { return {graph_, graph_.source(j_ - n), j_ - n}; } - edge_id_t operator-(const edge_iterator& b) const { return j_ - b.j_; } + difference_type operator-(const flat_iterator& b) const { return j_ - b.j_; } - bool operator==(const edge_iterator& b) const { return j_ == b.j_; } + bool operator==(const flat_iterator& b) const { return j_ == b.j_; } - bool operator!=(const edge_iterator& b) const { return j_ != b.j_; } + bool operator!=(const flat_iterator& b) const { return j_ != b.j_; } - bool operator<(const edge_iterator& b) const { return j_ < b.j_; } + bool operator<(const flat_iterator& b) const { return j_ < b.j_; } - bool operator>(const edge_iterator& b) const { return j_ > b.j_; } + bool operator>(const flat_iterator& b) const { return j_ > b.j_; } - bool operator<=(const edge_iterator& b) const { return j_ <= b.j_; } + bool operator<=(const flat_iterator& b) const { return j_ <= b.j_; } - bool operator>=(const edge_iterator& b) const { return j_ >= b.j_; } + bool operator>=(const flat_iterator& b) const { return j_ >= b.j_; } }; + /// Provide a tbb split-able range interface to the edge iterators. template - class edge_range { - edge_iterator begin_; - edge_iterator end_; + class flat_range { + flat_iterator begin_; + flat_iterator end_; std::ptrdiff_t cutoff_; public: - edge_range(edge_iterator begin, edge_iterator end, std::ptrdiff_t cutoff) + flat_range(flat_iterator begin, flat_iterator end, std::ptrdiff_t cutoff) : begin_(begin), end_(end), cutoff_(cutoff) {} - edge_range(edge_range& rhs, tbb::split) : begin_(rhs.begin_), end_(rhs.begin_ += rhs.size() / 2), cutoff_(rhs.cutoff_) {} + flat_range(flat_range& rhs, tbb::split) : begin_(rhs.begin_), end_(rhs.begin_ += rhs.size() / 2), cutoff_(rhs.cutoff_) {} - edge_iterator begin() { return begin_; } - edge_iterator end() { return end_; } + flat_iterator begin() { return begin_; } + flat_iterator end() { return end_; } std::ptrdiff_t size() const { return end_ - begin_; } bool empty() const { return begin_ == end_; } @@ -177,28 +173,28 @@ class indexed_struct_of_arrays { /// Get a tbb split-able edge range with the passed cutoff. template - edge_range edges(std::ptrdiff_t cutoff = std::numeric_limits::max()) { - edge_iterator begin = {*this, 0, 0}; - edge_iterator end = {*this, vertex_id_t(indices_.size() - 1), vertex_id_t(to_be_indexed_.size())}; + flat_range edges(std::ptrdiff_t cutoff = std::numeric_limits::max()) { + flat_iterator begin = {*this, 0, 0}; + flat_iterator end = {*this, index_t(indices_.size() - 1), index_t(to_be_indexed_.size())}; return {begin, end, cutoff}; } + /// This iterator provides a 2D vertex-neighbor tbb split-able interface to /// the graph. class outer_iterator { - std::vector::iterator indices_; + std::vector::iterator indices_; typename struct_of_arrays::iterator indexed_; - vertex_id_t i_; + index_t i_; public: - using difference_type = vertex_id_t; + using difference_type = index_t; using value_type = sub_view; using reference = value_type&; using pointer = value_type*; using iterator_category = std::random_access_iterator_tag; - outer_iterator(std::vector::iterator indices, typename struct_of_arrays::iterator indexed, - vertex_id_t i) + outer_iterator(std::vector::iterator indices, typename struct_of_arrays::iterator indexed, index_t i) : indices_(indices), indexed_(indexed), i_(i) {} outer_iterator& operator++() { @@ -223,30 +219,86 @@ class indexed_struct_of_arrays { value_type operator*() { return {indexed_ + indices_[i_], indexed_ + indices_[i_ + 1]}; } value_type operator*() const { return {indexed_ + indices_[i_], indexed_ + indices_[i_ + 1]}; } - value_type operator[](vertex_id_t n) { return {indexed_ + indices_[i_ + n], indexed_ + indices_[i_ + n + 1]}; } + value_type operator[](index_t n) { return {indexed_ + indices_[i_ + n], indexed_ + indices_[i_ + n + 1]}; } - value_type operator[](vertex_id_t n) const { return {indexed_ + indices_[i_ + n], indexed_ + indices_[i_ + n + 1]}; } + value_type operator[](index_t n) const { return {indexed_ + indices_[i_ + n], indexed_ + indices_[i_ + n + 1]}; } }; + + class const_outer_iterator { + std::vector::const_iterator indices_; + typename struct_of_arrays::const_iterator indexed_; + index_t i_; + + public: + using difference_type = index_t; + using value_type = const_sub_view; + using reference = const value_type&; + using pointer = const value_type*; + using iterator_category = std::random_access_iterator_tag; + + const_outer_iterator(std::vector::const_iterator indices, typename struct_of_arrays::const_iterator indexed, index_t i) + : indices_(indices), indexed_(indexed), i_(i) {} + + const_outer_iterator& operator++() { + ++i_; + return *this; + } + + const_outer_iterator& operator+=(difference_type n) { + i_ += n; + return *this; + } + + const_outer_iterator operator+(difference_type n) const { return {indices_, indexed_, i_ + n}; } + const_outer_iterator operator-(difference_type n) const { return {indices_, indexed_, i_ - n}; } + + difference_type operator-(const const_outer_iterator& b) const { return i_ - b.i_; } + + bool operator==(const const_outer_iterator& b) const { return i_ == b.i_; } + bool operator!=(const const_outer_iterator& b) const { return i_ != b.i_; } + bool operator<(const const_outer_iterator& b) const { return i_ < b.i_; } + + value_type operator*() { return {indexed_ + indices_[i_], indexed_ + indices_[i_ + 1]}; } + value_type operator*() const { return {indexed_ + indices_[i_], indexed_ + indices_[i_ + 1]}; } + + value_type operator[](index_t n) { return {indexed_ + indices_[i_ + n], indexed_ + indices_[i_ + n + 1]}; } + + value_type operator[](index_t n) const { return {indexed_ + indices_[i_ + n], indexed_ + indices_[i_ + n + 1]}; } + }; + using iterator = outer_iterator; - iterator begin() { return {indices_.begin(), to_be_indexed_.begin(), 0}; } - iterator begin() const { return {indices_.begin(), to_be_indexed_.begin(), 0}; } - iterator end() { return {indices_.begin(), to_be_indexed_.begin(), N_}; } - iterator end() const { return {indices_.begin(), to_be_indexed_.begin(), N_}; } + using value_type = typename iterator::value_type; + using reference = typename iterator::reference; + using size_type = std::size_t; + using difference_type = typename iterator::difference_type; + using pointer = typename iterator::pointer; + + using const_iterator = const_outer_iterator; + using const_reference = typename const_iterator::reference; + using const_pointer = typename const_iterator::pointer; + + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + iterator begin() { return {indices_.begin(), to_be_indexed_.begin(), 0}; } + const_iterator begin() const { return {indices_.begin(), to_be_indexed_.begin(), 0}; } + iterator end() { return {indices_.begin(), to_be_indexed_.begin(), N_}; } + const_iterator end() const { return {indices_.begin(), to_be_indexed_.begin(), N_}; } /// Random access to the outer range. - sub_view operator[](vertex_id_t i) { return begin()[i]; } - sub_view operator[](vertex_id_t i) const { return begin()[i]; } + sub_view operator[](index_t i) { return begin()[i]; } + const_sub_view operator[](index_t i) const { return begin()[i]; } - vertex_id_t size() const { return indices_.size() - 1; } - vertex_id_t max() const { return indices_.size() - 2; } + index_t size() const { return indices_.size() - 1; } + index_t max() const { return indices_.size() - 2; } - vertex_id_t source(edge_id_t edge) const { + index_t source(difference_type edge) const { auto i = std::upper_bound(indices_.begin(), indices_.end(), edge); return i - indices_.begin() - 1; } - vertex_id_t source(edge_id_t edge) { + index_t source(difference_type edge) { auto i = std::upper_bound(indices_.begin(), indices_.end(), edge); return i - indices_.begin() - 1; } @@ -263,19 +315,21 @@ class indexed_struct_of_arrays { void close_for_push_back() { if (to_be_indexed_.size() == 0) return; - //std::exclusive_scan(std::execution::par, indices_.begin(), indices_.end(), indices_.begin(), 0); + + // std::exclusive_scan(std::execution::par, indices_.begin(), indices_.end(), indices_.begin(), 0); + std::exclusive_scan(indices_.begin(), indices_.end(), indices_.begin(), 0); assert(indices_.back() == to_be_indexed_.size()); is_open_ = false; } - void push_back(vertex_id_t i, const Attributes&... attrs) { + void push_back(index_t i, const Attributes&... attrs) { ++indices_[i]; to_be_indexed_.push_back(attrs...); } - void push_at(vertex_id_t i, const Attributes&... attrs) { - vertex_id_t j = indices_[i]++; + void push_at(index_t i, const Attributes&... attrs) { + index_t j = indices_[i]++; to_be_indexed_.push_at(j, attrs...); } @@ -329,9 +383,9 @@ class indexed_struct_of_arrays { deserialize(infile); } - template {})> - void triangularize_(Comparator comp = std::less{}) { - std::vector new_indices_(indices_.size()); + template {})> + void triangularize_(Comparator comp = std::less{}) { + std::vector new_indices_(indices_.size()); struct_of_arrays new_to_be_indexed_(0); new_to_be_indexed_.reserve(to_be_indexed_.size()); @@ -356,9 +410,9 @@ class indexed_struct_of_arrays { template void triangularize() { if constexpr (cessor == predecessor) { - triangularize_(std::less{}); + triangularize_(std::less{}); } else if constexpr (cessor == successor) { - triangularize_(std::greater{}); + triangularize_(std::greater{}); } else { } if (g_debug_compressed) { @@ -366,16 +420,16 @@ class indexed_struct_of_arrays { } } - std::vector degrees() const { - std::vector degrees_(indices_); + std::vector degrees() const { + std::vector degrees_(indices_); std::adjacent_difference(indices_.begin(), indices_.end(), degrees_.begin()); return degrees_; } template void sort_by_degree(std::string direction = "descending", ExecutionPolicy&& ex_policy = {}) { - std::vector degrees_ = degrees(); - std::vector perm(indices_.size() - 1); + std::vector degrees_ = degrees(); + std::vector perm(indices_.size() - 1); std::iota(perm.begin(), perm.end(), 0); auto d = degrees_.begin() + 1; @@ -387,9 +441,9 @@ class indexed_struct_of_arrays { std::cout << "Unknown direction: " << direction << std::endl; } - std::vector new_indices_(indices_); - auto n = new_indices_.begin() + 1; - std::vector iperm(perm.size()); + std::vector new_indices_(indices_); + auto n = new_indices_.begin() + 1; + std::vector iperm(perm.size()); for (size_t j = 0; j < perm.size(); ++j) { n[j] = d[perm[j]]; @@ -443,103 +497,52 @@ class indexed_struct_of_arrays { } }; -/** - * @brief - * - * @todo compressed_sparse should be deprecated -- there is no such thing as directedness - * - * @file compressed.hpp - * @author Andrew Lumsdaine - * @date 2018-08-22 - */ - -template -class edge_list; - -template -class compressed_sparse : public indexed_struct_of_arrays { + + +template +class index_compressed : public graph_base, public indexed_struct_of_arrays { + using base = indexed_struct_of_arrays; public: - // The first vertex_id_t isn't considered an attribute. - using attributes_t = std::tuple; - static constexpr std::size_t getNAttr() { return sizeof...(Attributes); } + index_compressed(size_t N) : graph_base(N), base(N) {} - compressed_sparse(size_t N) : indexed_struct_of_arrays(N) {} - compressed_sparse(edge_list& A) : indexed_struct_of_arrays(A.max()[idx] + 1) { - A.fill(*this); + void close_for_push_back() { + base::close_for_push_back(); + }; + + auto num_edges() { + return base::to_be_indexed_.size(); } - // size_t size() const { return indexed_struct_of_arrays::size(); } }; + +template +using compressed = index_compressed; + + +#if 0 template -class adjacency : public indexed_struct_of_arrays { +class adjacency : public indexed_struct_of_arrays { public: - // The first vertex_id_t isn't considered an attribute. + // The first index_t isn't considered an attribute. using attributes_t = std::tuple; static constexpr std::size_t getNAttr() { return sizeof...(Attributes); } - using vertex_id_t = nw::graph::vertex_id_t; + using index_t = nw::graph::index_t; + + adjacency(size_t N = 0, size_t M = 0) : indexed_struct_of_arrays(N, M) {} - adjacency(size_t N = 0, size_t M = 0) : indexed_struct_of_arrays(N, M) {} template - adjacency(edge_list& A, ExecutionPolicy&& policy = {}) : indexed_struct_of_arrays(std::max(A.max()[0], A.max()[1]) + 1) { + adjacency(edge_list& A, ExecutionPolicy&& policy = {}) : indexed_struct_of_arrays(std::max(A.max()[0], A.max()[1]) + 1) { A.fill(*this, policy); } + template adjacency(edge_list& A, ExecutionPolicy&& policy = {}) - : indexed_struct_of_arrays(std::max(A.max()[0], A.max()[1]) + 1) { + : indexed_struct_of_arrays(std::max(A.max()[0], A.max()[1]) + 1) { A.fill(*this, policy); } - - // size_t size() const { return indexed_struct_of_arrays::size(); } - -#if 0 - auto transpose() { - if ((idx != 0) || (idx != 1)) { - throw; - } - size_t t_idx = (idx+1) % 2; - adjacency A_transpose(N); - auto A_column_nos = std::get<0>(to_be_indexed_); - auto A_row_indices = indices_; - - auto A_t_col_indices = A_transpose.indices_; - - for (size_t i = 0; size_t < A_columns.size(); ++i) { - auto col = A_column_nos[i]; - A_t_col_indices[col]++; - } - A_transpose.close_for_push_back(); - A_transpose.resize(to_be_indexed_.size()); - - auto A_t_row_nos = std::get<0>(A_transpose.to_be_indexed_); - - for (size_t i = 0; i < N_; ++i) { - for (size_t j = indices_[i]; j < indices_[i+1]; ++j) { - auto_col = A_column_nos[j]; - auto A_tra = A_t_col_indices_[A_col]++; - A_transpose.to_be_indexed_[A_tra] = to_be_indexed_[j]; - A_t_row_nos[A_tra] = i; - } - } - return A_transpose; - } -#endif -}; - -template -class packed : public indexed_struct_of_arrays { -public: - // The first vertex_id_t isn't considered an attribute. - using attributes_t = std::tuple; - static constexpr std::size_t getNAttr() { return sizeof...(Attributes); } - - packed(size_t N) : indexed_struct_of_arrays(N) {} - packed(edge_list& A) : indexed_struct_of_arrays(A.size()) { - A.fill(*this); - } - - // size_t size() const { return indexed_struct_of_arrays::size(); } }; +#endif } // namespace graph } // namespace nw diff --git a/include/containers/edge_list.hpp b/include/containers/edge_list.hpp index 423831bf..a5fd8593 100644 --- a/include/containers/edge_list.hpp +++ b/include/containers/edge_list.hpp @@ -30,11 +30,12 @@ #include "detail/numeric.hpp" #endif +#include "util/defaults.hpp" #include "util/demangle.hpp" #include "util/print_types.hpp" #include "util/timer.hpp" -#include "util/types.hpp" #include +#include #include #include #include @@ -61,57 +62,48 @@ class packed; template class adj_list; -template +template +class index_edge_list : public graph_base, public struct_of_arrays { +public: + using vertex_id_t = vertex_id_type; -class edge_list : public graph_base, public struct_of_arrays { - using base = struct_of_arrays; +private: + using base = struct_of_arrays; using element = std::tuple; public: - edge_list(size_t N) - : graph_base(N), min_({std::numeric_limits::max(), std::numeric_limits::max()}), max_({0, 0}) {} + index_edge_list(size_t N) : graph_base(N){}; + + index_edge_list() : graph_base(0) { open_for_push_back(); } - edge_list(std::initializer_list l) - : graph_base(l.size()), min_({std::numeric_limits::max(), std::numeric_limits::max()}), - max_({0, 0}) { + index_edge_list(std::initializer_list l) : graph_base(0) { open_for_push_back(); for_each(l.begin(), l.end(), [&](element x) { push_back(x); }); - std::cout << "min " << min_[0] << " " << min_[1] << " " - << " max " << max_[0] << " " << max_[1] << std::endl; + if (g_debug_edge_list) { + std::cout << " max " << vertex_cardinality[0] << " " << vertex_cardinality[1] << std::endl; + } close_for_push_back(); - std::cout << "min " << min_[0] << " " << min_[1] << " " - << " max " << max_[0] << " " << max_[1] << std::endl; - } - - edge_list() - : graph_base(0), min_({std::numeric_limits::max(), std::numeric_limits::max()}), max_({0, 0}) { - open_for_push_back(); + if (g_debug_edge_list) { + std::cout << " max " << vertex_cardinality[0] << " " << vertex_cardinality[1] << std::endl; + } } - //edge_list(const edge_list&) = default; - - //edge_list convert (const edge_list&) ; - //edge_list convert(const edge_list&); template auto convert_directedness(ExecutionPolicy&& policy = {}) { if constexpr (edge_directedness == to_dir) { - return edge_list(*this); + return index_edge_list(*this); } else if constexpr (edge_directedness == directed && to_dir == undirected) { - // edge_list x(*this); - - edge_list x(graph_base::vertex_cardinality[0]); + index_edge_list x(graph_base::vertex_cardinality[0]); x.resize(base::size()); x.open_for_push_back(); - x.max_[0] = max_[1]; - x.max_[1] = max_[0]; - x.min_[0] = min_[1]; - x.min_[1] = min_[0]; + x.vertex_cardinality[0] = vertex_cardinality[1]; + x.vertex_cardinality[1] = vertex_cardinality[0]; std::copy(policy, base::begin(), base::end(), x.begin()); const int jdx = (kdx + 1) % 2; @@ -136,12 +128,7 @@ class edge_list : public graph_base, public struct_of_arrays x(2*graph_base::lim[0]); - x.open_for_push_back(); - -#else - edge_list x(2 * graph_base::vertex_cardinality[0]); + index_edge_list x(2 * graph_base::vertex_cardinality[0]); x.open_for_push_back(); #if 1 @@ -166,7 +153,7 @@ class edge_list : public graph_base, public struct_of_arrays(0); + return index_edge_list(0); } - void open_for_push_back() {} + void open_for_push_back() { is_open = true; } void close_for_push_back() { + vertex_cardinality[0] = vertex_cardinality[0] + 1; + vertex_cardinality[1] = vertex_cardinality[1] + 1; - if (min_[0] != 0 || min_[1] != 0) { - vertex_id_t the_min = std::min(min_[0], min_[1]); - - std::for_each(std::execution::par, base::begin(), base::end(), [&](auto&& x) { - - std::get<0>(x) -= the_min; - std::get<1>(x) -= the_min; - }); - max_[0] -= the_min; - min_[0] -= the_min; - max_[1] -= the_min; - min_[1] -= the_min; - } - - vertex_cardinality[0] = max_[0] + 1; - vertex_cardinality[1] = max_[1] + 1; + is_open = false; } void push_back(vertex_id_t i, vertex_id_t j, Attributes... attrs) { - min_[0] = std::min(i, min_[0]); - min_[1] = std::min(j, min_[1]); + assert(is_open == true); - max_[0] = std::max(i, max_[0]); - max_[1] = std::max(j, max_[1]); + vertex_cardinality[0] = std::max(i, vertex_cardinality[0]); + vertex_cardinality[1] = std::max(j, vertex_cardinality[1]); base::push_back(i, j, attrs...); } @@ -214,11 +187,8 @@ class edge_list : public graph_base, public struct_of_arrays(elem); vertex_id_t j = std::get<1>(elem); - min_[0] = std::min(i, min_[0]); - min_[1] = std::min(j, min_[1]); - - max_[0] = std::max(i, max_[0]); - max_[1] = std::max(j, max_[1]); + vertex_cardinality[0] = std::max(i, vertex_cardinality[0]); + vertex_cardinality[1] = std::max(j, vertex_cardinality[1]); base::push_back(elem); } @@ -262,11 +232,10 @@ class edge_list : public graph_base, public struct_of_arrays bool { return a < b; } ); } else { - std::sort(policy, base::begin(), base::end(), - [](const element& a, const element& b) -> bool { - // print_types(a, b); - return std::tie(std::get<1>(a), std::get<0>(a)) < std::tie(std::get<1>(b), std::get<0>(b)); - }); + std::sort(policy, base::begin(), base::end(), [](const element& a, const element& b) -> bool { + // print_types(a, b); + return std::tie(std::get<1>(a), std::get<0>(a)) < std::tie(std::get<1>(b), std::get<0>(b)); + }); } } @@ -278,10 +247,9 @@ class edge_list : public graph_base, public struct_of_arrays bool { - return std::tie(std::get(a), std::get(a)) < std::tie(std::get(b), std::get(b)); - }); + std::stable_sort(policy, base::begin(), base::end(), [](const element& a, const element& b) -> bool { + return std::tie(std::get(a), std::get(a)) < std::tie(std::get(b), std::get(b)); + }); } template @@ -329,18 +297,19 @@ class edge_list : public graph_base, public struct_of_arrays{}), class ExecutionPolicy = std::execution::parallel_unsequenced_policy> + template {}), + class ExecutionPolicy = std::execution::parallel_unsequenced_policy> void fill_if(adjacency& cs, Comparator comp, ExecutionPolicy&& policy = {}) { const kdx = (idx + 1) % 2; if constexpr (edge_directedness == directed) { - std::vector degrees(max_ + 1 + 1); + std::vector degrees(vertex_cardinality + 1 + 1); std::for_each(base::begin(), base::end(), [&](auto&& elt) { if (comp((std::get(elt), std::get(elt))) { ++degrees[std::get(elt)]; } }); exclusive_scan(/* std::execution::par, */ degrees.begin(), degrees.end(), degrees.begin(), (vertex_id_t)0); - cs.indices_.resize(max_ + 1 + 1); + cs.indices_.resize(vertex_cardinality + 1 + 1); std::copy(policy, degrees.begin(), degrees.end(), cs.indices_.begin()); cs.to_be_indexed_.resize(size()); @@ -353,16 +322,14 @@ class edge_list : public graph_base, public struct_of_arrays void fill_helper(adjacency& cs, std::index_sequence is, ExecutionPolicy&& policy = {}) { - (..., ( - std::copy(policy, - std::get(dynamic_cast(*this)).begin(), std::get(dynamic_cast(*this)).end(), - std::get(cs.to_be_indexed_).begin()))); + (..., (std::copy(policy, std::get(dynamic_cast(*this)).begin(), + std::get(dynamic_cast(*this)).end(), std::get(cs.to_be_indexed_).begin()))); } template void fill_helper(adjacency& cs, std::index_sequence is, T& Tmp, ExecutionPolicy&& policy = {}) { - (..., (std::copy(policy, std::get(dynamic_cast(Tmp)).begin(), - std::get(dynamic_cast(Tmp)).end(), std::get(cs.to_be_indexed_).begin()))); + (..., (std::copy(policy, std::get(dynamic_cast(Tmp)).begin(), std::get(dynamic_cast(Tmp)).end(), + std::get(cs.to_be_indexed_).begin()))); } template @@ -372,17 +339,17 @@ class edge_list : public graph_base, public struct_of_arrays(policy); auto degree = degrees(); - + const int kdx = (idx + 1) % 2; - cs.indices_.resize(std::max(max_[idx], max_[kdx]) + 1 + 1); - //cs.indices_.resize(max_[idx] + 1 + 1); + cs.indices_.resize(std::max(vertex_cardinality[idx], vertex_cardinality[kdx]) + 1 + 1); + //cs.indices_.resize(vertex_cardinality[idx] + 1 + 1); std::inclusive_scan(std::execution::par, degree.begin(), degree.end(), cs.indices_.begin() + 1); - cs.to_be_indexed_.resize(size()); + cs.to_be_indexed_.resize(base::to_be_indexed.size()); //const int kdx = (idx + 1) % 2; - std::copy(policy, std::get(dynamic_cast(*this)).begin(), - std::get(dynamic_cast(*this)).end(), std::get<0>(cs.to_be_indexed_).begin()); + std::copy(policy, std::get(dynamic_cast(*this)).begin(), std::get(dynamic_cast(*this)).end(), + std::get<0>(cs.to_be_indexed_).begin()); if constexpr (sizeof...(Attributes) > 0) { fill_helper(cs, std::make_integer_sequence()); @@ -391,7 +358,7 @@ class edge_list : public graph_base, public struct_of_arrays(policy); cs.open_for_push_back(); - + std::for_each(base::begin(), base::end(), [&](auto&& elt) { std::apply([&](vertex_id_t i, vertex_id_t j, Attributes... attrs) { cs.push_back(i, j, attrs...); }, elt); }); @@ -400,9 +367,10 @@ class edge_list : public graph_base, public struct_of_arrays Tmp(0); // BUG!!!! + // index_edge_list Tmp(0); // BUG!!!! - edge_list Tmp(0); // undirected == directed with doubled (and swapped) edges + index_edge_list Tmp( + 0); // undirected == directed with doubled (and swapped) edges Tmp.resize(2 * base::size()); { @@ -415,8 +383,7 @@ class edge_list : public graph_base, public struct_of_arrays(); auto degree = Tmp.template degrees(); // Can have a fast version if we know it is sorted -- using equal_range - cs.indices_.resize(Tmp.max_[idx] + 1 + 1); + cs.indices_.resize(Tmp.vertex_cardinality[idx] + 1 + 1); std::inclusive_scan(std::execution::par, degree.begin(), degree.end(), cs.indices_.begin() + 1); cs.to_be_indexed_.resize(Tmp.size()); @@ -436,8 +403,8 @@ class edge_list : public graph_base, public struct_of_arrays(dynamic_cast(Tmp)).begin(), - std::get(dynamic_cast(Tmp)).end(), std::get<0>(cs.to_be_indexed_).begin()); + std::copy(policy, std::get(dynamic_cast(Tmp)).begin(), std::get(dynamic_cast(Tmp)).end(), + std::get<0>(cs.to_be_indexed_).begin()); if constexpr (sizeof...(Attributes) > 0) { fill_helper(cs, std::make_integer_sequence(), Tmp); @@ -458,7 +425,7 @@ class edge_list : public graph_base, public struct_of_arrays Tmp(0); + index_edge_list Tmp(0); Tmp.reserve(2 * base::size()); Tmp.open_for_push_back(); std::for_each(base::begin(), base::end(), [&](auto&& elt) { @@ -477,10 +444,13 @@ class edge_list : public graph_base, public struct_of_arrays(f) < std::get<1>(f)) { - std::swap(std::get<0>(f), std::get<1>(f)); - } - }); + std::for_each(policy, base::begin(), base::end(), [](auto&& f) { + if (std::get<0>(f) < std::get<1>(f)) { + std::swap(std::get<0>(f), std::get<1>(f)); + } + }); } else if constexpr ((idx == 0 && cessor == successor) || (idx == 1 && cessor == predecessor)) { - std::for_each(policy, base::begin(), base::end(), - [](auto&& f) { - if (std::get<1>(f) < std::get<0>(f)) { - std::swap(std::get<1>(f), std::get<0>(f)); - } - }); + std::for_each(policy, base::begin(), base::end(), [](auto&& f) { + if (std::get<1>(f) < std::get<0>(f)) { + std::swap(std::get<1>(f), std::get<0>(f)); + } + }); } } @@ -570,13 +538,13 @@ class edge_list : public graph_base, public struct_of_arrays(x) < std::get<1>(x); }); + auto past_the_end = + std::remove_if(policy, base::begin(), base::end(), [](auto&& x) { return std::get<0>(x) < std::get<1>(x); }); base::erase(past_the_end, base::end()); } else if constexpr ((idx == 0 && cessor == successor) || (idx == 1 && cessor == predecessor)) { - auto past_the_end = std::remove_if(policy, base::begin(), base::end(), - [](auto&& x) { return std::get<1>(x) < std::get<0>(x); }); + auto past_the_end = + std::remove_if(policy, base::begin(), base::end(), [](auto&& x) { return std::get<1>(x) < std::get<0>(x); }); base::erase(past_the_end, base::end()); } } @@ -588,9 +556,9 @@ class edge_list : public graph_base, public struct_of_arrays(x) == std::get<0>(y) && std::get<1>(x) == std::get<1>(y); }); + auto past_the_end = std::unique(policy, base::begin(), base::end(), [](auto&& x, auto&& y) { + return std::get<0>(x) == std::get<0>(y) && std::get<1>(x) == std::get<1>(y); + }); // base::erase(past_the_end, base::end()); base::resize(past_the_end - base::begin()); @@ -608,7 +576,7 @@ class edge_list : public graph_base, public struct_of_arrays auto degrees(ExecutionPolicy&& policy = {}) { - std::vector degree(max_[d_idx] + 1); + std::vector degree(vertex_cardinality[d_idx] + 1); if constexpr (edge_directedness == directed) { std::vector> tmp(degree.size()); @@ -652,8 +620,7 @@ class edge_list : public graph_base, public struct_of_arrays d[b]; }); } else if (direction == "ascending") { std::sort(policy, perm.begin(), perm.end(), [&](auto a, auto b) { return d[a] < d[b]; }); - } - else { + } else { std::cout << "Unknown direction: " << direction << std::endl; } @@ -670,11 +637,10 @@ class edge_list : public graph_base, public struct_of_arrays(x) = iperm[std::get<0>(x)]; - std::get<1>(x) = iperm[std::get<1>(x)]; - }); + std::for_each(policy, base::begin(), base::end(), [&](auto&& x) { + std::get<0>(x) = iperm[std::get<0>(x)]; + std::get<1>(x) = iperm[std::get<1>(x)]; + }); } template > @@ -687,15 +653,13 @@ class edge_list : public graph_base, public struct_of_arrays(magic), sizeof(magic)); size_t d = edge_directedness; outfile.write(reinterpret_cast(&d), sizeof(d)); outfile.write(reinterpret_cast(vertex_cardinality), sizeof(vertex_cardinality)); - outfile.write(reinterpret_cast(&min_), sizeof(min_)); - outfile.write(reinterpret_cast(&max_), sizeof(max_)); base::serialize(outfile); } @@ -715,8 +679,6 @@ class edge_list : public graph_base, public struct_of_arrays(vertex_cardinality), sizeof(vertex_cardinality)); - infile.read(reinterpret_cast(&min_), sizeof(min_)); - infile.read(reinterpret_cast(&max_), sizeof(max_)); base::deserialize(infile); close_for_push_back(); } @@ -735,9 +697,7 @@ class edge_list : public graph_base, public struct_of_arrays construct", "[construct]") { + SECTION("construct") { + compressed A(N); + } + SECTION("push_back diagonal") { + compressed A(N); + A.open_for_push_back(); + for (size_t i = 0; i < A.size(); ++i) { + A.push_back(i, i, i*3.14159); + } + A.close_for_push_back(); + } + + SECTION("push_back diagonal less 0") { + compressed A(N); + A.open_for_push_back(); + for (size_t i = 1; i < A.size(); ++i) { + A.push_back(i, i, i*3.14159); + } + A.close_for_push_back(); + } + + SECTION("push_back diagonal less N-1") { + compressed A(N); + A.open_for_push_back(); + for (size_t i = 0; i < A.size()-1; ++i) { + A.push_back(i, i, i*3.14159); + } + A.close_for_push_back(); + } +} + + +TEST_CASE("indexed_struct_of_arrays outer iteration", "[outer]") { + SECTION("") { + compressed A(N); + A.open_for_push_back(); + for (size_t i = 0; i < A.size(); ++i) { + A.push_back(i, i, i*3.14159); + if (i > 0) { + A.push_back(i, i-1, i*3.14159); + } + } + A.close_for_push_back(); + size_t i = 0; + for (auto && j : A) { + if (i++ > 0) { + REQUIRE(j.size() == 2); + } else { + REQUIRE(j.size() == 1); + } + } + } +} + + +TEST_CASE("indexed_struct_of_arrays inner iteration", "[inner]") { + SECTION("") { + compressed A(N); + A.open_for_push_back(); + for (size_t i = 0; i < A.size(); ++i) { + A.push_back(i, i, i*3.14159); + if (i > 0) { + A.push_back(i, i-1, i*3.14159); + } + } + A.close_for_push_back(); + size_t i = 0; + for (auto && j : A) { + for (auto && k : j) { + std::cout << std::get<0>(k) << " " << std::get<1>(k) << std::endl; + } + } + } +} + + + + +TEST_CASE("indexed_struct_of_arrays flat iteration", "[flat]") { + SECTION("") { + } +} + + +template +void foo(SOA& s) { + + size_t i = 0; + for (auto && j : s) { + for (auto && k : j) { + std::cout << std::get<0>(k) << " " << std::get<1>(k) << std::endl; + } + } +} + +template +void bar(const SOA& s) { + + size_t i = 0; + for (auto && j : s) { + for (auto && k : j) { + std::cout << std::get<0>(k) << " " << std::get<1>(k) << std::endl; + } + } + +} + + +TEST_CASE("indexed_struct_of_arrays const iteration", "[const]") { + SECTION("") { + compressed A(N); + A.open_for_push_back(); + for (size_t i = 0; i < A.size(); ++i) { + A.push_back(i, i, i*3.14159); + if (i > 0) { + A.push_back(i, i-1, i*3.14159); + } + } + A.close_for_push_back(); + foo(A); + bar(A); + } +} + + + +#if 0 + // data/karate.mtx:%%MatrixMarket matrix coordinate pattern symmetric // data/karate.mtx:%%MatrixMarket matrix coordinate pattern symmetric @@ -46,7 +210,7 @@ TEST_CASE("compressed class I/O", "[compressed_io]") { SECTION("I/O (read to edge_list and convert to compressed matrix)") {} } -#if 0 + TEST_CASE("compressed class iteration", "[compressed]") { SECTION("push_back") { diff --git a/test/idxsoa_1.cpp b/test/idxsoa_1.cpp index 79a5bf67..a3cfcc29 100644 --- a/test/idxsoa_1.cpp +++ b/test/idxsoa_1.cpp @@ -20,7 +20,7 @@ using namespace nw::util; int main(int argc, char* argv[]) { - indexed_struct_of_arrays pre_A(7); + indexed_struct_of_arrays pre_A(7); { std::cout << "Nu" << std::endl; From 5f77782396aafa8f0dac72d021c737c301f3e08e Mon Sep 17 00:00:00 2001 From: Andrew Lumsdaine Date: Mon, 28 Dec 2020 16:32:53 -0800 Subject: [PATCH 006/385] clang-format --- include/adaptors/back_edge_range.hpp | 2 +- include/adaptors/bfs_edge_range.hpp | 418 +++++++++--------- include/adaptors/bfs_range.hpp | 2 +- include/adaptors/cyclic_range_adapter.hpp | 4 +- include/adaptors/dag_range.hpp | 2 +- include/adaptors/dfs_range.hpp | 2 +- include/adaptors/edge_range.hpp | 2 +- include/adaptors/filtered_bfs_range.hpp | 2 +- include/adaptors/neighbor_range.hpp | 2 +- include/adaptors/new_dfs_range.hpp | 4 +- include/adaptors/plain_range.hpp | 7 +- include/adaptors/random_range.hpp | 2 +- include/adaptors/reverse.hpp | 2 +- include/algorithms/betweenness_centrality.hpp | 34 +- include/algorithms/bfs.hpp | 12 +- include/algorithms/boykov_kolmogorov.hpp | 2 +- include/algorithms/connected_components.hpp | 270 +++++------ include/algorithms/delta_stepping.hpp | 2 +- include/algorithms/k_core.hpp | 4 +- include/algorithms/max_flow.hpp | 2 +- include/algorithms/page_rank.hpp | 76 ++-- include/algorithms/spMatspMat.hpp | 2 +- include/algorithms/spanning_tree.hpp | 2 +- include/algorithms/triangle_count.hpp | 12 +- include/containers/compressed.hpp | 37 +- include/containers/edge_list.hpp | 4 +- include/detail/numeric.hpp | 19 +- include/graph_base.hpp | 6 +- include/io/MatrixMarketFile.hpp | 117 ++--- include/io/mmio.hpp | 5 +- include/util/disjoint_set.hpp | 10 +- include/util/types.hpp | 4 +- include/util/util.hpp | 3 - 33 files changed, 500 insertions(+), 574 deletions(-) diff --git a/include/adaptors/back_edge_range.hpp b/include/adaptors/back_edge_range.hpp index 02fbba45..7f3ff5a8 100644 --- a/include/adaptors/back_edge_range.hpp +++ b/include/adaptors/back_edge_range.hpp @@ -7,8 +7,8 @@ // // Author: Kevin Deweese // -#include "util/util.hpp" #include "util/types.hpp" +#include "util/util.hpp" #include #include diff --git a/include/adaptors/bfs_edge_range.hpp b/include/adaptors/bfs_edge_range.hpp index 4226cd65..4cdbc6a4 100644 --- a/include/adaptors/bfs_edge_range.hpp +++ b/include/adaptors/bfs_edge_range.hpp @@ -27,277 +27,277 @@ namespace nw { namespace graph { - enum three_colors { black, white, grey }; +enum three_colors { black, white, grey }; - template > - class bfs_edge_range { +template > +class bfs_edge_range { - public: - bfs_edge_range(Graph& graph, vertex_id_t seed = 0) : the_graph_(graph), colors_(graph.size(), white) { - Q_.push(seed); - colors_[seed] = grey; - } +public: + bfs_edge_range(Graph& graph, vertex_id_t seed = 0) : the_graph_(graph), colors_(graph.size(), white) { + Q_.push(seed); + colors_[seed] = grey; + } - bfs_edge_range(const bfs_edge_range&) = delete; - bfs_edge_range(const bfs_edge_range&&) = delete; + bfs_edge_range(const bfs_edge_range&) = delete; + bfs_edge_range(const bfs_edge_range&&) = delete; - bool empty() { - bool b = Q_.empty(); - return b; - } + bool empty() { + bool b = Q_.empty(); + return b; + } - class bfs_edge_range_iterator { - private: - bfs_edge_range& the_range_; - typename Graph::outer_iterator G; - vertex_id_t v_; - typename Graph::inner_iterator u_begin, u_end; + class bfs_edge_range_iterator { + private: + bfs_edge_range& the_range_; + typename Graph::outer_iterator G; + vertex_id_t v_; + typename Graph::inner_iterator u_begin, u_end; - public: - bfs_edge_range_iterator(bfs_edge_range& range) - : the_range_(range), G(the_range_.the_graph_.begin()), v_(the_range_.Q_.front()), u_begin(G[v_].begin()), - u_end(G[v_].end()) {} + public: + bfs_edge_range_iterator(bfs_edge_range& range) + : the_range_(range), G(the_range_.the_graph_.begin()), v_(the_range_.Q_.front()), u_begin(G[v_].begin()), + u_end(G[v_].end()) {} - bfs_edge_range_iterator(const bfs_edge_range_iterator& ite) - : the_range_(ite.the_range_), G(ite.G), v_(ite.v_), u_begin(u_begin), u_end(u_end) {} + bfs_edge_range_iterator(const bfs_edge_range_iterator& ite) + : the_range_(ite.the_range_), G(ite.G), v_(ite.v_), u_begin(u_begin), u_end(u_end) {} - bfs_edge_range_iterator& operator++() { - auto& Q = the_range_.Q_; - auto& colors = the_range_.colors_; + bfs_edge_range_iterator& operator++() { + auto& Q = the_range_.Q_; + auto& colors = the_range_.colors_; - Q.push(std::get<0>(*u_begin)); - colors[std::get<0>(*u_begin)] = grey; + Q.push(std::get<0>(*u_begin)); + colors[std::get<0>(*u_begin)] = grey; + ++u_begin; + while (u_begin != u_end && colors[std::get<0>(*u_begin)] != white) { ++u_begin; - while (u_begin != u_end && colors[std::get<0>(*u_begin)] != white) { - ++u_begin; - } + } - while (u_begin == u_end) { - colors[v_] = black; - Q.pop(); - if (Q.empty()) break; + while (u_begin == u_end) { + colors[v_] = black; + Q.pop(); + if (Q.empty()) break; - v_ = Q.front(); - assert(colors[v_] == grey); - u_begin = G[v_].begin(); - u_end = G[v_].end(); + v_ = Q.front(); + assert(colors[v_] == grey); + u_begin = G[v_].begin(); + u_end = G[v_].end(); - while (u_begin != u_end && colors[std::get<0>(*u_begin)] != white) { - ++u_begin; - } + while (u_begin != u_end && colors[std::get<0>(*u_begin)] != white) { + ++u_begin; } - - return *this; } - auto operator*() { return std::tuple_cat(std::make_tuple(v_), *u_begin); } + return *this; + } - class end_sentinel_type { - public: - end_sentinel_type() {} - }; + auto operator*() { return std::tuple_cat(std::make_tuple(v_), *u_begin); } - auto operator==(const end_sentinel_type&) const { return the_range_.empty(); } - bool operator!=(const end_sentinel_type&) const { return !the_range_.empty(); } + class end_sentinel_type { + public: + end_sentinel_type() {} }; - typedef bfs_edge_range_iterator iterator; + auto operator==(const end_sentinel_type&) const { return the_range_.empty(); } + bool operator!=(const end_sentinel_type&) const { return !the_range_.empty(); } + }; - auto begin() { return bfs_edge_range_iterator(*this); } - auto end() { return typename bfs_edge_range_iterator::end_sentinel_type(); } + typedef bfs_edge_range_iterator iterator; - private: - Graph& the_graph_; - Queue Q_; - std::vector colors_; - }; + auto begin() { return bfs_edge_range_iterator(*this); } + auto end() { return typename bfs_edge_range_iterator::end_sentinel_type(); } - //**************************************************************************** - // This range used by dijkstra - template - class bfs_edge_range2 { - private: - public: - bfs_edge_range2(Graph& graph, PriorityQueue& Q, std::tuple seed = {0, 0}) - : the_graph_(graph), Q_(Q), colors_(graph.end() - graph.begin(), white) { - Q_.push(seed); - colors_[std::get<0>(seed)] = grey; - } +private: + Graph& the_graph_; + Queue Q_; + std::vector colors_; +}; - bfs_edge_range2(const bfs_edge_range2&) = delete; - bfs_edge_range2(const bfs_edge_range2&&) = delete; +//**************************************************************************** +// This range used by dijkstra +template +class bfs_edge_range2 { +private: +public: + bfs_edge_range2(Graph& graph, PriorityQueue& Q, std::tuple seed = {0, 0}) + : the_graph_(graph), Q_(Q), colors_(graph.end() - graph.begin(), white) { + Q_.push(seed); + colors_[std::get<0>(seed)] = grey; + } - bool empty() { return Q_.empty(); } + bfs_edge_range2(const bfs_edge_range2&) = delete; + bfs_edge_range2(const bfs_edge_range2&&) = delete; - class bfs_edge_range2_iterator { - private: - bfs_edge_range2& the_range_; - typename Graph::outer_iterator G; - vertex_id_t v_; - typename Graph::inner_iterator u_begin, u_end; + bool empty() { return Q_.empty(); } - // Graph -> v, u, w - // Q -> v, d + class bfs_edge_range2_iterator { + private: + bfs_edge_range2& the_range_; + typename Graph::outer_iterator G; + vertex_id_t v_; + typename Graph::inner_iterator u_begin, u_end; - public: - bfs_edge_range2_iterator(bfs_edge_range2& range) - : the_range_(range), G(the_range_.the_graph_.begin()), v_(std::get<0>(the_range_.Q_.top())), u_begin(G[v_].begin()), - u_end(G[v_].end()) {} + // Graph -> v, u, w + // Q -> v, d - bfs_edge_range2_iterator& operator++() { - auto& Q = the_range_.Q_; - auto& colors = the_range_.colors_; + public: + bfs_edge_range2_iterator(bfs_edge_range2& range) + : the_range_(range), G(the_range_.the_graph_.begin()), v_(std::get<0>(the_range_.Q_.top())), u_begin(G[v_].begin()), + u_end(G[v_].end()) {} - Q.push({std::get<0>(*u_begin), size_t(0xffffffffffffffffULL)}); - colors[std::get<0>(*u_begin)] = grey; + bfs_edge_range2_iterator& operator++() { + auto& Q = the_range_.Q_; + auto& colors = the_range_.colors_; + Q.push({std::get<0>(*u_begin), size_t(0xffffffffffffffffULL)}); + colors[std::get<0>(*u_begin)] = grey; + + ++u_begin; + while (u_begin != u_end && colors[std::get<0>(*u_begin)] != white) { ++u_begin; - while (u_begin != u_end && colors[std::get<0>(*u_begin)] != white) { - ++u_begin; - } + } - while (u_begin == u_end) { - colors[v_] = black; + while (u_begin == u_end) { + colors[v_] = black; - while (colors[std::get<0>(Q.top())] == black && !Q.empty()) - Q.pop(); + while (colors[std::get<0>(Q.top())] == black && !Q.empty()) + Q.pop(); - if (Q.empty()) break; + if (Q.empty()) break; - v_ = std::get<0>(Q.top()); - u_begin = G[v_].begin(); - u_end = G[v_].end(); + v_ = std::get<0>(Q.top()); + u_begin = G[v_].begin(); + u_end = G[v_].end(); - while (u_begin != u_end && colors[std::get<0>(*u_begin)] != white) { - ++u_begin; - } + while (u_begin != u_end && colors[std::get<0>(*u_begin)] != white) { + ++u_begin; } - - return *this; } - auto operator*() { return std::tuple(v_, std::get<0>(*u_begin), std::get<1>(*u_begin)); } + return *this; + } - class end_sentinel_type { - public: - end_sentinel_type() {} - }; + auto operator*() { return std::tuple(v_, std::get<0>(*u_begin), std::get<1>(*u_begin)); } - auto operator==(const end_sentinel_type&) const { return the_range_.empty(); } - bool operator!=(const end_sentinel_type&) const { return !the_range_.empty(); } + class end_sentinel_type { + public: + end_sentinel_type() {} }; - typedef bfs_edge_range2_iterator iterator; - - auto begin() { return bfs_edge_range2_iterator(*this); } - auto end() { return typename bfs_edge_range2_iterator::end_sentinel_type(); } - - private: - Graph& the_graph_; - PriorityQueue& Q_; - std::vector colors_; + auto operator==(const end_sentinel_type&) const { return the_range_.empty(); } + bool operator!=(const end_sentinel_type&) const { return !the_range_.empty(); } }; - template > - class bfs_edge_range3 { - public: - bfs_edge_range3(Graph& graph, vertex_id_t seed = 0) : the_graph_(graph), colors_(graph.end() - graph.begin(), white) { - Q_[0].push(seed); - colors_[seed] = grey; - //After adding seed, add the neighbors of seed to next queue - for (auto ite = the_graph_.begin()[seed].begin(); ite != the_graph_.begin()[seed].end(); ++ite) { // Explore neighbors - auto u = std::get<0>(*ite); - if (colors_[u] == white) { - colors_[u] = grey; - Q_[1].push(u); - } + typedef bfs_edge_range2_iterator iterator; + + auto begin() { return bfs_edge_range2_iterator(*this); } + auto end() { return typename bfs_edge_range2_iterator::end_sentinel_type(); } + +private: + Graph& the_graph_; + PriorityQueue& Q_; + std::vector colors_; +}; + +template > +class bfs_edge_range3 { +public: + bfs_edge_range3(Graph& graph, vertex_id_t seed = 0) : the_graph_(graph), colors_(graph.end() - graph.begin(), white) { + Q_[0].push(seed); + colors_[seed] = grey; + //After adding seed, add the neighbors of seed to next queue + for (auto ite = the_graph_.begin()[seed].begin(); ite != the_graph_.begin()[seed].end(); ++ite) { // Explore neighbors + auto u = std::get<0>(*ite); + if (colors_[u] == white) { + colors_[u] = grey; + Q_[1].push(u); } } + } - bfs_edge_range3(const bfs_edge_range3&) = delete; - bfs_edge_range3(const bfs_edge_range3&&) = delete; + bfs_edge_range3(const bfs_edge_range3&) = delete; + bfs_edge_range3(const bfs_edge_range3&&) = delete; - bool empty() { return Q_[0].empty(); } + bool empty() { return Q_[0].empty(); } - class bfs_edge_range3_iterator { - public: - bfs_edge_range3_iterator(bfs_edge_range3& range) : the_range_(range) {} - - bfs_edge_range3_iterator& operator++() { - auto G = the_range_.the_graph_.begin(); - Queue(&Q)[2] = the_range_.Q_; - auto& colors = the_range_.colors_; - - if (!Q[1].empty()) { // if the neighbor queue is not empty - // we proceed all the neighbors - auto u = Q[1].front(); - Q[1].pop(); // pop the child which has been visited - colors[u] = black; // mark the child as black (visited) - Q[0].push(u); // put the visited child to current frontier (it becomes parent) - while (Q[1].empty()) { // keep filling neighbors until the - // neighboring queue is not empty - if (Q[0].empty()) break; // break if both queue are empty - - auto v = Q[0].front(); // get parent vertex v - - for (auto ite = G[v].begin(); ite != G[v].end(); ++ite) { // Explore neighbors - u = std::get<0>(*ite); - if (colors[u] == white) { - colors[u] = grey; - Q[1].push(u); //add all the white neighbors of v - } - } //for - if (Q[1].empty()) { //if parent vertex v has no white neighbors, then v has done all traverse - Q[0].pop(); //pop it out - colors[v] = black; //be done with parent vertex v + class bfs_edge_range3_iterator { + public: + bfs_edge_range3_iterator(bfs_edge_range3& range) : the_range_(range) {} + + bfs_edge_range3_iterator& operator++() { + auto G = the_range_.the_graph_.begin(); + Queue(&Q)[2] = the_range_.Q_; + auto& colors = the_range_.colors_; + + if (!Q[1].empty()) { // if the neighbor queue is not empty + // we proceed all the neighbors + auto u = Q[1].front(); + Q[1].pop(); // pop the child which has been visited + colors[u] = black; // mark the child as black (visited) + Q[0].push(u); // put the visited child to current frontier (it becomes parent) + while (Q[1].empty()) { // keep filling neighbors until the + // neighboring queue is not empty + if (Q[0].empty()) break; // break if both queue are empty + + auto v = Q[0].front(); // get parent vertex v + + for (auto ite = G[v].begin(); ite != G[v].end(); ++ite) { // Explore neighbors + u = std::get<0>(*ite); + if (colors[u] == white) { + colors[u] = grey; + Q[1].push(u); //add all the white neighbors of v } - // but we still need to populate the child queue, so we continue populate with the next parent vertex - } // while - } else { - auto v = Q[0].front(); - Q[0].pop(); //if v has no neighbor, pop it - colors[v] = black; - } - - return *this; - } - - auto operator*() { - Queue(&Q)[2] = the_range_.Q_; - //if v has no neighbor, return a self loop - if (!Q[1].empty()) - return std::make_tuple(Q[0].front(), Q[1].front()); - else - return std::make_tuple(Q[0].front(), Q[0].front()); + } //for + if (Q[1].empty()) { //if parent vertex v has no white neighbors, then v has done all traverse + Q[0].pop(); //pop it out + colors[v] = black; //be done with parent vertex v + } + // but we still need to populate the child queue, so we continue populate with the next parent vertex + } // while + } else { + auto v = Q[0].front(); + Q[0].pop(); //if v has no neighbor, pop it + colors[v] = black; } - class end_sentinel_type { - public: - end_sentinel_type() {} - }; + return *this; + } - auto operator==(const end_sentinel_type&) const { return the_range_.empty(); } - bool operator!=(const end_sentinel_type&) const { return !the_range_.empty(); } + auto operator*() { + Queue(&Q)[2] = the_range_.Q_; + //if v has no neighbor, return a self loop + if (!Q[1].empty()) + return std::make_tuple(Q[0].front(), Q[1].front()); + else + return std::make_tuple(Q[0].front(), Q[0].front()); + } - private: - bfs_edge_range3& the_range_; + class end_sentinel_type { + public: + end_sentinel_type() {} }; - typedef bfs_edge_range3_iterator iterator; - - auto begin() { return bfs_edge_range3_iterator(*this); } - auto end() { return typename bfs_edge_range3_iterator::end_sentinel_type(); } + auto operator==(const end_sentinel_type&) const { return the_range_.empty(); } + bool operator!=(const end_sentinel_type&) const { return !the_range_.empty(); } private: - Graph& the_graph_; - std::vector colors_; // Every node in Q_[0] and those who has been processed is black. - // Every nobe in Q_[1] is grey. - // Every unprocessed node is white. - Queue Q_[2]; //Q_[0] is processing queue, Q_[1] is neighbor queue - //the reason to use two queues instead of one: we need to return tuple at the front of each queue respectively. + bfs_edge_range3& the_range_; }; -} + + typedef bfs_edge_range3_iterator iterator; + + auto begin() { return bfs_edge_range3_iterator(*this); } + auto end() { return typename bfs_edge_range3_iterator::end_sentinel_type(); } + +private: + Graph& the_graph_; + std::vector colors_; // Every node in Q_[0] and those who has been processed is black. + // Every nobe in Q_[1] is grey. + // Every unprocessed node is white. + Queue Q_[2]; //Q_[0] is processing queue, Q_[1] is neighbor queue + //the reason to use two queues instead of one: we need to return tuple at the front of each queue respectively. +}; +} // namespace graph } // namespace nw #endif // BFS_EDGE_RANGE_HPP diff --git a/include/adaptors/bfs_range.hpp b/include/adaptors/bfs_range.hpp index 7a3020a1..16310e40 100644 --- a/include/adaptors/bfs_range.hpp +++ b/include/adaptors/bfs_range.hpp @@ -11,8 +11,8 @@ #ifndef NW_GRAPH_BFS_RANGE_HPP #define NW_GRAPH_BFS_RANGE_HPP -#include "util/util.hpp" #include "util/types.hpp" +#include "util/util.hpp" #include #include #include diff --git a/include/adaptors/cyclic_range_adapter.hpp b/include/adaptors/cyclic_range_adapter.hpp index fc5aa8bc..a0d85b2f 100644 --- a/include/adaptors/cyclic_range_adapter.hpp +++ b/include/adaptors/cyclic_range_adapter.hpp @@ -1,8 +1,8 @@ #ifndef NW_GRAPH_CYCLIC_RANGE_ADAPTER_HPP #define NW_GRAPH_CYCLIC_RANGE_ADAPTER_HPP -#include "util/util.hpp" #include "util/types.hpp" +#include "util/util.hpp" #include #include @@ -106,4 +106,4 @@ constexpr decltype(auto) cyclic(Range&& range, Cutoff cutoff) { } } // namespace graph } // namespace nw -#endif // NW_GRAPH_CYCLIC_RANGE_ADAPTER_HPP +#endif // NW_GRAPH_CYCLIC_RANGE_ADAPTER_HPP diff --git a/include/adaptors/dag_range.hpp b/include/adaptors/dag_range.hpp index bc08b416..85b9bf01 100644 --- a/include/adaptors/dag_range.hpp +++ b/include/adaptors/dag_range.hpp @@ -116,4 +116,4 @@ class dag_range { } // namespace graph } // namespace nw -#endif // NW_GRAPH_DAG_RANGE_HPP +#endif // NW_GRAPH_DAG_RANGE_HPP diff --git a/include/adaptors/dfs_range.hpp b/include/adaptors/dfs_range.hpp index 39016317..0ba0c580 100644 --- a/include/adaptors/dfs_range.hpp +++ b/include/adaptors/dfs_range.hpp @@ -11,8 +11,8 @@ #ifndef NW_GRAPH_DFS_RANGE_HPP #define NW_GRAPH_DFS_RANGE_HPP -#include "util/util.hpp" #include "util/types.hpp" +#include "util/util.hpp" #include #include #include diff --git a/include/adaptors/edge_range.hpp b/include/adaptors/edge_range.hpp index 58d3a278..62fc2d48 100644 --- a/include/adaptors/edge_range.hpp +++ b/include/adaptors/edge_range.hpp @@ -11,9 +11,9 @@ #ifndef NW_GRAPH_EDGE_RANGE_HPP #define NW_GRAPH_EDGE_RANGE_HPP -#include "util/util.hpp" #include "util/print_types.hpp" #include "util/types.hpp" +#include "util/util.hpp" #include #include diff --git a/include/adaptors/filtered_bfs_range.hpp b/include/adaptors/filtered_bfs_range.hpp index 566c56c6..84c5d973 100644 --- a/include/adaptors/filtered_bfs_range.hpp +++ b/include/adaptors/filtered_bfs_range.hpp @@ -10,8 +10,8 @@ #ifndef NW_GRAPH_FILTERED_BFS_RANGE_HPP #define NW_GRAPH_FILTERED_BFS_RANGE_HPP -#include "util/util.hpp" #include "util/types.hpp" +#include "util/util.hpp" #include #include #include diff --git a/include/adaptors/neighbor_range.hpp b/include/adaptors/neighbor_range.hpp index f83bbcc4..2833938e 100644 --- a/include/adaptors/neighbor_range.hpp +++ b/include/adaptors/neighbor_range.hpp @@ -11,8 +11,8 @@ #ifndef NW_GRAPH_NEIGHBOR_RANGE_HPP #define NW_GRAPH_NEIGHBOR_RANGE_HPP -#include "util/util.hpp" #include "util/types.hpp" +#include "util/util.hpp" #include #include diff --git a/include/adaptors/new_dfs_range.hpp b/include/adaptors/new_dfs_range.hpp index e3a39b2e..aaaccd3d 100644 --- a/include/adaptors/new_dfs_range.hpp +++ b/include/adaptors/new_dfs_range.hpp @@ -11,8 +11,8 @@ #ifndef NW_GRAPH_NEW_DFS_RANGE_HPP #define NW_GRAPH_NEW_DFS_RANGE_HPP -#include "util/util.hpp" #include "util/types.hpp" +#include "util/util.hpp" #include #include #include @@ -247,4 +247,4 @@ class dfs_edge_range { } // namespace graph } // namespace nw -#endif // NW_GRAPH_NEW_DFS_RANGE_HPP +#endif // NW_GRAPH_NEW_DFS_RANGE_HPP diff --git a/include/adaptors/plain_range.hpp b/include/adaptors/plain_range.hpp index a5063f00..858b082a 100644 --- a/include/adaptors/plain_range.hpp +++ b/include/adaptors/plain_range.hpp @@ -11,9 +11,9 @@ #ifndef NW_GRAPH_PLAIN_RANGE_HPP #define NW_GRAPH_PLAIN_RANGE_HPP -#include "util/util.hpp" #include "util/print_types.hpp" #include "util/types.hpp" +#include "util/util.hpp" #include #include #include @@ -27,7 +27,7 @@ namespace graph { template using counting_iterator = dpstd::counting_iterator; } -} +} // namespace nw #else #include #include @@ -36,13 +36,12 @@ namespace graph { template using counting_iterator = tbb::counting_iterator; } -} +} // namespace nw #endif namespace nw { namespace graph { - template class plain_range { public: diff --git a/include/adaptors/random_range.hpp b/include/adaptors/random_range.hpp index 81e0caad..b3e0efa7 100644 --- a/include/adaptors/random_range.hpp +++ b/include/adaptors/random_range.hpp @@ -11,8 +11,8 @@ #ifndef NW_GRAPH_RANDOM_RANGE_HPP #define NW_GRAPH_RANDOM_RANGE_HPP -#include "util/util.hpp" #include "util/types.hpp" +#include "util/util.hpp" #include #include #include diff --git a/include/adaptors/reverse.hpp b/include/adaptors/reverse.hpp index 685a2baf..f0fe8bb3 100644 --- a/include/adaptors/reverse.hpp +++ b/include/adaptors/reverse.hpp @@ -11,8 +11,8 @@ #ifndef NW_GRAPH_REVERSE_HPP #define NW_GRAPH_REVERSE_HPP -#include "util/util.hpp" #include "util/types.hpp" +#include "util/util.hpp" #include namespace nw { diff --git a/include/algorithms/betweenness_centrality.hpp b/include/algorithms/betweenness_centrality.hpp index 43739ea7..29fc1417 100644 --- a/include/algorithms/betweenness_centrality.hpp +++ b/include/algorithms/betweenness_centrality.hpp @@ -11,12 +11,12 @@ #ifndef BETWEENNESS_CENTRALITY_HPP #define BETWEENNESS_CENTRALITY_HPP -#include "util/util.hpp" -#include "util/types.hpp" +#include "adaptors/worklist.hpp" #include "util/AtomicBitVector.hpp" #include "util/atomic.hpp" #include "util/parallel_for.hpp" -#include "adaptors/worklist.hpp" +#include "util/types.hpp" +#include "util/util.hpp" #include @@ -1412,7 +1412,8 @@ auto bc2_v1(Graph& graph, const std::vector sources) { return bc; } -template +template auto bc2_v2(Graph& graph, const std::vector& sources, ExecutionPolicy&& policy = {}) { auto g = graph.begin(); @@ -1484,8 +1485,11 @@ auto bc2_v2(Graph& graph, const std::vector& sources, ExecutionPoli return bc; } -template -auto bc2_v3(Graph& graph, const std::vector& sources, OuterExecutionPolicy&& outer_policy = {}, InnerExecutionPolicy&& inner_policy = {}) { +template +auto bc2_v3(Graph& graph, const std::vector& sources, OuterExecutionPolicy&& outer_policy = {}, + InnerExecutionPolicy&& inner_policy = {}) { auto g = graph.begin(); vertex_id_t N = graph.max() + 1; @@ -1582,8 +1586,10 @@ auto bc2_v3(Graph& graph, const std::vector& sources, OuterExecutio return bc; } -template -auto bc2_v4(Graph&& graph, const std::vector& sources, int threads, OuterExecutionPolicy&& outer_policy={}, InnerExecutionPolicy&& inner_policy={}) { +template +auto bc2_v4(Graph&& graph, const std::vector& sources, int threads, OuterExecutionPolicy&& outer_policy = {}, + InnerExecutionPolicy&& inner_policy = {}) { auto g = graph.begin(); vertex_id_t N = graph.max() + 1; size_t M = graph.to_be_indexed_.size(); @@ -1595,7 +1601,7 @@ auto bc2_v4(Graph&& graph, const std::vector& sources, int threads, for (vertex_id_t root : sources) { std::vector> levels(N); - nw::graph::AtomicBitVector succ(M); + nw::graph::AtomicBitVector succ(M); std::fill(outer_policy, levels.begin(), levels.end(), std::numeric_limits::max()); @@ -1669,8 +1675,10 @@ auto bc2_v4(Graph&& graph, const std::vector& sources, int threads, return bc; } -template -auto bc2_v5(Graph&& graph, const std::vector& sources, int threads, OuterExecutionPolicy&& outer_policy = {}, InnerExecutionPolicy&& inner_policy = {}) { +template +auto bc2_v5(Graph&& graph, const std::vector& sources, int threads, OuterExecutionPolicy&& outer_policy = {}, + InnerExecutionPolicy&& inner_policy = {}) { vertex_id_t N = graph.max() + 1; size_t M = graph.to_be_indexed_.size(); auto&& edges = std::get<0>(*(graph[0]).begin()); @@ -1684,8 +1692,8 @@ auto bc2_v5(Graph&& graph, const std::vector& sources, int threads, futures[s_idx] = std::async( std::launch::async, [&](vertex_id_t root) { - std::vector levels(N); - nw::graph::AtomicBitVector succ(M); + std::vector levels(N); + nw::graph::AtomicBitVector succ(M); // Initialize the levels to infinity. std::fill(outer_policy, levels.begin(), levels.end(), std::numeric_limits::max()); diff --git a/include/algorithms/bfs.hpp b/include/algorithms/bfs.hpp index 9878da46..31d783f8 100644 --- a/include/algorithms/bfs.hpp +++ b/include/algorithms/bfs.hpp @@ -11,11 +11,11 @@ #ifndef NW_GRAPH_BFS_HPP #define NW_GRAPH_BFS_HPP -#include "util/types.hpp" #include "containers/compressed.hpp" #include "util/AtomicBitVector.hpp" #include "util/atomic.hpp" #include "util/parallel_for.hpp" +#include "util/types.hpp" #include #include @@ -333,7 +333,7 @@ template std::vector> q1(num_bins); std::vector> q2(num_bins); std::vector parents(N); - nw::graph::AtomicBitVector visited(N); + nw::graph::AtomicBitVector visited(N); std::fill(std::execution::par_unseq, parents.begin(), parents.end(), null_vertex); @@ -373,7 +373,7 @@ template template [[gnu::noinline]] auto bfs_bottom_up(Graph&& g, Transpose&& gx, vertex_id_t root) { - const std::size_t N = gx.max() + 1; + const std::size_t N = gx.max() + 1; nw::graph::AtomicBitVector frontier(N); nw::graph::AtomicBitVector next(N); @@ -414,8 +414,8 @@ template const std::size_t M = out_graph.to_be_indexed_.size(); std::vector> q1(n), q2(n); - nw::graph::AtomicBitVector visited(N); - std::vector parents(N); + nw::graph::AtomicBitVector visited(N); + std::vector parents(N); std::fill(std::execution::par_unseq, parents.begin(), parents.end(), null_vertex); @@ -431,7 +431,7 @@ template if (scout_count > edges_to_check / alpha) { nw::graph::AtomicBitVector front(N, false); nw::graph::AtomicBitVector curr(N); - std::size_t awake_count = 0; + std::size_t awake_count = 0; // Initialize the frontier bitmap from the frontier queues, and count the // number of non-zeros. diff --git a/include/algorithms/boykov_kolmogorov.hpp b/include/algorithms/boykov_kolmogorov.hpp index d024651a..d8695948 100644 --- a/include/algorithms/boykov_kolmogorov.hpp +++ b/include/algorithms/boykov_kolmogorov.hpp @@ -18,8 +18,8 @@ #include #include -#include "util/util.hpp" #include "util/types.hpp" +#include "util/util.hpp" namespace nw { namespace graph { diff --git a/include/algorithms/connected_components.hpp b/include/algorithms/connected_components.hpp index a2dd7cc5..caaa20c4 100644 --- a/include/algorithms/connected_components.hpp +++ b/include/algorithms/connected_components.hpp @@ -11,10 +11,10 @@ #ifndef CONNECTED_COMPONENT_HPP #define CONNECTED_COMPONENT_HPP -#include "util/types.hpp" #include "adaptors/bfs_edge_range.hpp" -#include "util/disjoint_set.hpp" #include "adaptors/edge_range.hpp" +#include "util/disjoint_set.hpp" +#include "util/types.hpp" #include #include #include @@ -61,28 +61,25 @@ struct atomwrapper { } }; - // BFS-based connected component algorithm template void compute_connected_components(Graph A, std::vector& component_ids) { size_t N = A.size(); std::atomic global_component_counter = -1; - std::for_each( - std::execution::par_unseq, - counting_iterator(0), counting_iterator(N), [&](auto vtx) { - if (std::numeric_limits::max() == component_ids[vtx]) { - global_component_counter++; - component_ids[vtx] = global_component_counter.load(); - // std::cout << "--------vertex--------------" << vtx << " - // component_ids[vtx]: " << component_ids[vtx] << std::endl; - bfs_edge_range3 ranges(A, vtx); - for (auto ite = ranges.begin(); ite != ranges.end(); ++ite) { - // auto u = std::get<0>(*ite); - auto v = std::get<1>(*ite); - component_ids[v] = global_component_counter.load(); - } - } - }); + std::for_each(std::execution::par_unseq, counting_iterator(0), counting_iterator(N), [&](auto vtx) { + if (std::numeric_limits::max() == component_ids[vtx]) { + global_component_counter++; + component_ids[vtx] = global_component_counter.load(); + // std::cout << "--------vertex--------------" << vtx << " + // component_ids[vtx]: " << component_ids[vtx] << std::endl; + bfs_edge_range3 ranges(A, vtx); + for (auto ite = ranges.begin(); ite != ranges.end(); ++ite) { + // auto u = std::get<0>(*ite); + auto v = std::get<1>(*ite); + component_ids[v] = global_component_counter.load(); + } + } + }); } template @@ -102,12 +99,10 @@ void hook(T u, T v, std::vector& comp) { template void compress(std::vector& comp) { - std::for_each( - std::execution::par_unseq, - counting_iterator(0), counting_iterator(comp.size()), [&](auto n) { - while (comp[n] != comp[comp[n]]) - comp[n] = comp[comp[n]]; - }); + std::for_each(std::execution::par_unseq, counting_iterator(0), counting_iterator(comp.size()), [&](auto n) { + while (comp[n] != comp[comp[n]]) + comp[n] = comp[comp[n]]; + }); } template @@ -185,9 +180,8 @@ std::vector compute_connected_components_v1(Graph& g) { // atomwrapper(-1)); std::vector> comp(N); - std::for_each( - std::execution::par_unseq, - counting_iterator(0), counting_iterator(N), [&](auto n) { comp[n]._a.store(n); }); + std::for_each(std::execution::par_unseq, counting_iterator(0), counting_iterator(N), + [&](auto n) { comp[n]._a.store(n); }); bool change = true; for (size_t num_iter = 0; num_iter < 2; ++num_iter) { @@ -223,50 +217,46 @@ std::vector compute_connected_components_v1(Graph& g) { } }); */ - std::for_each( - std::execution::par_unseq, - counting_iterator(0), counting_iterator(N), [&](auto u) { - vertex_id_t v; - for (auto j = g.begin()[u].begin(); j != g.begin()[u].end(); ++j) { - v = std::get<0>(*j); - // if (v != comp[v]._a.load()) continue; - auto p1 = comp[u]._a.load(); - auto p2 = comp[v]._a.load(); - while (p1 != p2) { - auto high = std::max(p1, p2); - auto low = p1 + p2 - high; - auto p_high = comp[high]._a.load(); - if (p_high == low || comp[high]._a.compare_exchange_weak(p_high, comp[low]._a)) { - change = true; - break; - } - high = comp[high]._a.load(); - p1 = comp[high]._a.load(); - p2 = comp[low]._a.load(); - } // while + std::for_each(std::execution::par_unseq, counting_iterator(0), counting_iterator(N), [&](auto u) { + vertex_id_t v; + for (auto j = g.begin()[u].begin(); j != g.begin()[u].end(); ++j) { + v = std::get<0>(*j); + // if (v != comp[v]._a.load()) continue; + auto p1 = comp[u]._a.load(); + auto p2 = comp[v]._a.load(); + while (p1 != p2) { + auto high = std::max(p1, p2); + auto low = p1 + p2 - high; + auto p_high = comp[high]._a.load(); + if (p_high == low || comp[high]._a.compare_exchange_weak(p_high, comp[low]._a)) { + change = true; + break; } - }); + high = comp[high]._a.load(); + p1 = comp[high]._a.load(); + p2 = comp[low]._a.load(); + } // while + } + }); } std::vector res(N); - std::for_each( - std::execution::par_unseq, - counting_iterator(0), counting_iterator(N), [&](auto n) { - auto m = n; - // while (comp[m]._a.load() != m) m = comp[m]._a.load(); - while (comp[m]._a.load() != comp[comp[m]._a.load()]._a.load()) { - comp[m]._a.store(comp[comp[m]._a.load()]._a.load()); - m = comp[m]._a.load(); - } - res[n] = comp[n]._a.load(); - // std::cout << n <<":" << res[n] << std::endl; - /* + std::for_each(std::execution::par_unseq, counting_iterator(0), counting_iterator(N), [&](auto n) { + auto m = n; + // while (comp[m]._a.load() != m) m = comp[m]._a.load(); + while (comp[m]._a.load() != comp[comp[m]._a.load()]._a.load()) { + comp[m]._a.store(comp[comp[m]._a.load()]._a.load()); + m = comp[m]._a.load(); + } + res[n] = comp[n]._a.load(); + // std::cout << n <<":" << res[n] << std::endl; + /* atomwrapper m(std::atomic(n)); while ( comp[m._a.load()] != comp[comp[m._a.load()]._a.load()]) { m._a.store(comp[m._a.load()]); } res[n] = comp[m._a.load()].a_.load(); */ - }); + }); // compress(comp); return res; } // compute_connected_components_v1 @@ -275,9 +265,8 @@ template std::vector compute_connected_components_v2(Graph& g) { size_t N = g.size(); std::vector comp(g.size()); - std::for_each( - std::execution::par_unseq, - counting_iterator(0), counting_iterator(g.size()), [&](auto n) { comp[n] = n; }); + std::for_each(std::execution::par_unseq, counting_iterator(0), counting_iterator(g.size()), + [&](auto n) { comp[n] = n; }); bool change = true; @@ -288,12 +277,10 @@ std::vector compute_connected_components_v2(Graph& g) { } change = false; - std::for_each( - std::execution::par_unseq, - counting_iterator(0), counting_iterator(N), [&](auto u) { change = pull(g, u, comp); }); - std::for_each( - std::execution::par_unseq, - counting_iterator(0), counting_iterator(N), [&](auto u) { push(g, u, comp); }); + std::for_each(std::execution::par_unseq, counting_iterator(0), counting_iterator(N), + [&](auto u) { change = pull(g, u, comp); }); + std::for_each(std::execution::par_unseq, counting_iterator(0), counting_iterator(N), + [&](auto u) { push(g, u, comp); }); compress(comp); } @@ -303,13 +290,11 @@ std::vector compute_connected_components_v2(Graph& g) { template std::vector ccv1(Graph& g) { std::vector comp(g.size()); - std::for_each( - std::execution::par_unseq, - counting_iterator(0), counting_iterator(g.size()), [&](auto n) { comp[n] = n; }); + std::for_each(std::execution::par_unseq, counting_iterator(0), counting_iterator(g.size()), + [&](auto n) { comp[n] = n; }); - std::for_each( - std::execution::par_unseq, - counting_iterator(0), counting_iterator(g.size()), [&](auto u) { push(g, u, comp); }); + std::for_each(std::execution::par_unseq, counting_iterator(0), counting_iterator(g.size()), + [&](auto u) { push(g, u, comp); }); compress(comp); return comp; } @@ -318,29 +303,25 @@ template std::vector Afforest(Graph& g, Graph2& t_graph, size_t neighbor_bound = 2) { std::vector comp(g.size()); // set component id of vertex v to v - std::for_each( - std::execution::par_unseq, - counting_iterator(0), counting_iterator(g.size()), [&](auto n) { comp[n] = n; }); + std::for_each(std::execution::par_unseq, counting_iterator(0), counting_iterator(g.size()), + [&](auto n) { comp[n] = n; }); // approximate the dominant component by linking certain neighbors of each // vertex v (a sparse subgraph) - std::for_each( - std::execution::par_unseq, - counting_iterator(0), counting_iterator(g.size()), - [&](auto u) { link(g, u, comp, neighbor_bound); }); + std::for_each(std::execution::par_unseq, counting_iterator(0), counting_iterator(g.size()), + [&](auto u) { link(g, u, comp, neighbor_bound); }); compress(comp); // Sample certain vertices to find dominant component id vertex_id_t dominant_c = findDominantComponentID(comp); // link the rest vertices outside of dominant component - std::for_each( - std::execution::par_unseq, - counting_iterator(0), counting_iterator(g.size()), [&](auto u) { - if (dominant_c != comp[u]) { - push(g, u, comp); - if (t_graph.size() != 0) { - push(t_graph, u, comp); - } - } - }); + std::for_each(std::execution::par_unseq, counting_iterator(0), counting_iterator(g.size()), + [&](auto u) { + if (dominant_c != comp[u]) { + push(g, u, comp); + if (t_graph.size() != 0) { + push(t_graph, u, comp); + } + } + }); compress(comp); return comp; @@ -350,19 +331,15 @@ template std::vector ccv5(Graph& g) { size_t N = g.size(); std::vector comp(g.size()); - std::for_each( - std::execution::par_unseq, - counting_iterator(0), counting_iterator(g.size()), [&](auto n) { comp[n] = n; }); + std::for_each(std::execution::par_unseq, counting_iterator(0), counting_iterator(g.size()), + [&](auto n) { comp[n] = n; }); - std::for_each( - std::execution::par_unseq, - counting_iterator(0), counting_iterator(N), [&](auto u) { pull(g, u, comp); }); + std::for_each(std::execution::par_unseq, counting_iterator(0), counting_iterator(N), + [&](auto u) { pull(g, u, comp); }); vertex_id_t dominant_c = findDominantComponentID(comp); - std::for_each( - std::execution::par_unseq, - counting_iterator(0), counting_iterator(N), [&](auto u) { - if (dominant_c != comp[u]) push(g, u, comp); - }); + std::for_each(std::execution::par_unseq, counting_iterator(0), counting_iterator(N), [&](auto u) { + if (dominant_c != comp[u]) push(g, u, comp); + }); compress(comp); return comp; @@ -372,9 +349,8 @@ template auto sv_v6(/* const */ Graph& g) { std::vector comp(g.size()); - std::for_each( - std::execution::par_unseq, - counting_iterator(0), counting_iterator(g.size()), [&](auto n) { comp[n] = n; }); + std::for_each(std::execution::par_unseq, counting_iterator(0), counting_iterator(g.size()), + [&](auto n) { comp[n] = n; }); bool change = true; @@ -388,21 +364,20 @@ auto sv_v6(/* const */ Graph& g) { } change = false; - std::for_each( - std::execution::par_unseq, - counting_iterator(0), counting_iterator(g.size()), [&](auto u) { - for (auto&& [v] : G[u]) { - vertex_id_t comp_u = comp[u]; - vertex_id_t comp_v = comp[v]; - if (comp_u == comp_v) continue; - vertex_id_t high_comp = comp_u > comp_v ? comp_u : comp_v; - vertex_id_t low_comp = comp_u + (comp_v - high_comp); - if (high_comp == comp[high_comp]) { - change = true; - comp[high_comp] = low_comp; - } - } - }); + std::for_each(std::execution::par_unseq, counting_iterator(0), counting_iterator(g.size()), + [&](auto u) { + for (auto&& [v] : G[u]) { + vertex_id_t comp_u = comp[u]; + vertex_id_t comp_v = comp[v]; + if (comp_u == comp_v) continue; + vertex_id_t high_comp = comp_u > comp_v ? comp_u : comp_v; + vertex_id_t low_comp = comp_u + (comp_v - high_comp); + if (high_comp == comp[high_comp]) { + change = true; + comp[high_comp] = low_comp; + } + } + }); for (vertex_id_t n = 0; n < g.size(); n++) { while (comp[n] != comp[comp[n]]) { @@ -418,9 +393,8 @@ template auto sv_v8(/* const */ Graph& g) { std::vector comp(g.size()); - std::for_each( - std::execution::par_unseq, - counting_iterator(0), counting_iterator(g.size()), [&](auto n) { comp[n] = n; }); + std::for_each(std::execution::par_unseq, counting_iterator(0), counting_iterator(g.size()), + [&](auto n) { comp[n] = n; }); bool change = true; @@ -433,25 +407,24 @@ auto sv_v8(/* const */ Graph& g) { } change = false; - std::for_each( - std::execution::par_unseq, - counting_iterator(0), counting_iterator(g.size()), [&](auto u) { - auto Gu = G[u]; - // tbb::parallel_for(G[u], [&] (auto& Gu) { - for (auto&& [v] : Gu) { - vertex_id_t comp_u = comp[u]; - vertex_id_t comp_v = comp[v]; - if (comp_u == comp_v) continue; - vertex_id_t high_comp = std::max(comp_u, comp_v); - - vertex_id_t low_comp = comp_u + (comp_v - high_comp); - if (high_comp == comp[high_comp]) { - change = true; - comp[high_comp] = low_comp; - } - } - // }); - }); + std::for_each(std::execution::par_unseq, counting_iterator(0), counting_iterator(g.size()), + [&](auto u) { + auto Gu = G[u]; + // tbb::parallel_for(G[u], [&] (auto& Gu) { + for (auto&& [v] : Gu) { + vertex_id_t comp_u = comp[u]; + vertex_id_t comp_v = comp[v]; + if (comp_u == comp_v) continue; + vertex_id_t high_comp = std::max(comp_u, comp_v); + + vertex_id_t low_comp = comp_u + (comp_v - high_comp); + if (high_comp == comp[high_comp]) { + change = true; + comp[high_comp] = low_comp; + } + } + // }); + }); for (vertex_id_t n = 0; n < g.size(); n++) { while (comp[n] != comp[comp[n]]) { @@ -467,9 +440,8 @@ template auto sv_v9(/* const */ Graph& g) { std::vector comp(g.size()); - std::for_each( - std::execution::par_unseq, - counting_iterator(0), counting_iterator(g.size()), [&](auto n) { comp[n] = n; }); + std::for_each(std::execution::par_unseq, counting_iterator(0), counting_iterator(g.size()), + [&](auto n) { comp[n] = n; }); bool change = true; diff --git a/include/algorithms/delta_stepping.hpp b/include/algorithms/delta_stepping.hpp index f57f44b8..020b7049 100644 --- a/include/algorithms/delta_stepping.hpp +++ b/include/algorithms/delta_stepping.hpp @@ -22,10 +22,10 @@ #include "util/atomic.hpp" #include "util/types.hpp" -#include "util/util.hpp" #include "util/parallel_for.hpp" #include "util/timer.hpp" #include "util/types.hpp" +#include "util/util.hpp" #include "tbb/concurrent_vector.h" #include "tbb/parallel_for_each.h" diff --git a/include/algorithms/k_core.hpp b/include/algorithms/k_core.hpp index cea1c43b..98745282 100644 --- a/include/algorithms/k_core.hpp +++ b/include/algorithms/k_core.hpp @@ -11,10 +11,10 @@ #ifndef NW_GRAPH_K_CORE_HPP #define NW_GRAPH_K_CORE_HPP -#include "util/types.hpp" -#include "util/util.hpp" #include "adaptors/edge_range.hpp" #include "adaptors/new_dfs_range.hpp" +#include "util/types.hpp" +#include "util/util.hpp" #include #include #include diff --git a/include/algorithms/max_flow.hpp b/include/algorithms/max_flow.hpp index d35ebe1d..00ca7e0e 100644 --- a/include/algorithms/max_flow.hpp +++ b/include/algorithms/max_flow.hpp @@ -11,10 +11,10 @@ #ifndef NW_GRAPH_MAX_FLOW_HPP #define NW_GRAPH_MAX_FLOW_HPP -#include "util/types.hpp" #include "adaptors/back_edge_range.hpp" #include "adaptors/filtered_bfs_range.hpp" #include "adaptors/reverse.hpp" +#include "util/types.hpp" #include "util/util.hpp" #include #include diff --git a/include/algorithms/page_rank.hpp b/include/algorithms/page_rank.hpp index 679af0c5..fc93dd19 100644 --- a/include/algorithms/page_rank.hpp +++ b/include/algorithms/page_rank.hpp @@ -19,11 +19,11 @@ #include #include -#include "util/types.hpp" +#include "adaptors/edge_range.hpp" #include "containers/compressed.hpp" #include "containers/edge_list.hpp" -#include "adaptors/edge_range.hpp" #include "util/parallel_for.hpp" +#include "util/types.hpp" #if defined(CL_SYCL_LANGUAGE_VERSION) #include @@ -247,21 +247,18 @@ void page_rank_v4(Graph& graph, const std::vector& degrees, std::ve const Real init_score = 1.0 / page_rank.size(); const Real base_score = (1.0 - damping_factor) / page_rank.size(); - std::fill( - std::execution::par_unseq, - page_rank.begin(), page_rank.end(), init_score); + std::fill(std::execution::par_unseq, page_rank.begin(), page_rank.end(), init_score); std::vector outgoing_contrib(page_rank.size()); std::vector> futures(num_threads); for (size_t iter = 0; iter < max_iters; ++iter) { - std::transform( - std::execution::par_unseq, - page_rank.begin(), page_rank.end(), degrees.begin(), outgoing_contrib.begin(), [&](auto&& x, auto&& y) { - ; - return x / (y + 0); - }); + std::transform(std::execution::par_unseq, page_rank.begin(), page_rank.end(), degrees.begin(), outgoing_contrib.begin(), + [&](auto&& x, auto&& y) { + ; + return x / (y + 0); + }); auto G = graph.begin(); @@ -364,9 +361,7 @@ void page_rank_v7(Graph& graph, const std::vector& degrees, std::ve { nw::util::life_timer _("fill"); - std::fill( - std::execution::par_unseq, - page_rank.begin(), page_rank.end(), init_score); + std::fill(std::execution::par_unseq, page_rank.begin(), page_rank.end(), init_score); } std::vector outgoing_contrib(page_rank.size()); @@ -374,18 +369,17 @@ void page_rank_v7(Graph& graph, const std::vector& degrees, std::ve nw::util::life_timer _("iters"); for (size_t iter = 0; iter < max_iters; ++iter) { - std::transform( - std::execution::par, - page_rank.begin(), page_rank.end(), degrees.begin(), outgoing_contrib.begin(), [&](auto&& x, auto&& y) { - ; - return x / (y + 0); - }); + std::transform(std::execution::par, page_rank.begin(), page_rank.end(), degrees.begin(), outgoing_contrib.begin(), + [&](auto&& x, auto&& y) { + ; + return x / (y + 0); + }); auto G = graph.begin(); double error = std::transform_reduce( - std::execution::par_unseq, - counting_iterator(0), counting_iterator(page_rank.size()), Real(0.0), std::plus(), + std::execution::par_unseq, counting_iterator(0), counting_iterator(page_rank.size()), Real(0.0), + std::plus(), [&](auto i) { Real z = tbb::parallel_reduce( @@ -412,34 +406,31 @@ void page_rank_v8(Graph& graph, const std::vector& degrees, std::ve const Real init_score = 1.0 / page_rank.size(); const Real base_score = (1.0 - damping_factor) / page_rank.size(); - std::fill( - std::execution::par_unseq, - page_rank.begin(), page_rank.end(), init_score); + std::fill(std::execution::par_unseq, page_rank.begin(), page_rank.end(), init_score); std::vector outgoing_contrib(page_rank.size()); for (size_t iter = 0; iter < max_iters; ++iter) { - std::transform( - std::execution::par_unseq, - page_rank.begin(), page_rank.end(), degrees.begin(), outgoing_contrib.begin(), [&](auto&& x, auto&& y) { - ; - return x / (y + 0); - }); + std::transform(std::execution::par_unseq, page_rank.begin(), page_rank.end(), degrees.begin(), outgoing_contrib.begin(), + [&](auto&& x, auto&& y) { + ; + return x / (y + 0); + }); auto G = graph.begin(); - double error = std::transform_reduce( - std::execution::par_unseq, - counting_iterator(0), counting_iterator(page_rank.size()), Real(0.0), std::plus(), - - [&](auto i) { - Real z = std::transform_reduce(std::execution::par_unseq, G[i].begin(), G[i].end(), Real(0.0), std::plus(), - [&](auto&& j) { return outgoing_contrib[std::get<0>(j)]; }); - auto old_rank = page_rank[i]; - page_rank[i] = base_score + damping_factor * z; - return fabs(page_rank[i] - old_rank); - }); + double error = std::transform_reduce(std::execution::par_unseq, counting_iterator(0), + counting_iterator(page_rank.size()), Real(0.0), std::plus(), + + [&](auto i) { + Real z = std::transform_reduce( + std::execution::par_unseq, G[i].begin(), G[i].end(), Real(0.0), std::plus(), + [&](auto&& j) { return outgoing_contrib[std::get<0>(j)]; }); + auto old_rank = page_rank[i]; + page_rank[i] = base_score + damping_factor * z; + return fabs(page_rank[i] - old_rank); + }); std::cout << iter << " " << error << std::endl; if (error < threshold) break; } @@ -803,7 +794,6 @@ template } } - template [[gnu::noinline]] std::size_t page_rank_v14(Graph&& graph, const std::vector& degrees, std::vector& page_rank, Real damping_factor, Real threshold, size_t max_iters) { diff --git a/include/algorithms/spMatspMat.hpp b/include/algorithms/spMatspMat.hpp index 8c720173..12707580 100644 --- a/include/algorithms/spMatspMat.hpp +++ b/include/algorithms/spMatspMat.hpp @@ -16,8 +16,8 @@ #include #include -#include "containers/edge_list.hpp" #include "adaptors/plain_range.hpp" +#include "containers/edge_list.hpp" #include "util/util.hpp" namespace nw { diff --git a/include/algorithms/spanning_tree.hpp b/include/algorithms/spanning_tree.hpp index eeebe43f..ff2077c2 100644 --- a/include/algorithms/spanning_tree.hpp +++ b/include/algorithms/spanning_tree.hpp @@ -15,8 +15,8 @@ #include #include "util/disjoint_set.hpp" -#include "util/util.hpp" #include "util/types.hpp" +#include "util/util.hpp" namespace nw { namespace graph { diff --git a/include/algorithms/triangle_count.hpp b/include/algorithms/triangle_count.hpp index b5a0b083..604239a2 100644 --- a/include/algorithms/triangle_count.hpp +++ b/include/algorithms/triangle_count.hpp @@ -13,11 +13,11 @@ #include "adaptors/cyclic_range_adapter.hpp" #include "adaptors/edge_range.hpp" -#include "util/util.hpp" #include "util/intersection_size.hpp" #include "util/parallel_for.hpp" #include "util/timer.hpp" #include "util/types.hpp" +#include "util/util.hpp" #include #include @@ -300,7 +300,8 @@ template total_triangles = 0; std::for_each(outer, A.begin(), A.end(), [&](auto&& x) { std::atomic triangles = 0; - std::for_each(inner, x.begin(), x.end(), [&](auto&& v) { triangles += nw::graph::intersection_size(x, A[std::get<0>(v)], set); }); + std::for_each(inner, x.begin(), x.end(), + [&](auto&& v) { triangles += nw::graph::intersection_size(x, A[std::get<0>(v)], set); }); total_triangles += triangles; }); return total_triangles; @@ -393,7 +394,8 @@ template [[gnu::noinline]] std::size_t triangle_count_v14(Graph&& graph, SetExecutionPolicy&& set = {}) { return nw::graph::parallel_for( - edge_range(graph), [&](auto&& u, auto&& v) { return nw::graph::intersection_size(graph[u], graph[v], set); }, std::plus{}, 0ul); + edge_range(graph), [&](auto&& u, auto&& v) { return nw::graph::intersection_size(graph[u], graph[v], set); }, std::plus{}, + 0ul); } /// One dimensional triangle counting with an edge range. @@ -434,8 +436,8 @@ template [[gnu::noinline]] std::size_t triangle_count_edgerange_cyclic(Graph&& graph, int stride, SetExecutionPolicy&& set = {}) { return nw::graph::parallel_for( - nw::graph::cyclic(graph.edges(), stride), [&](auto&& u, auto&& v) { return nw::graph::intersection_size(graph[u], graph[v], set); }, - std::plus{}, 0ul); + nw::graph::cyclic(graph.edges(), stride), + [&](auto&& u, auto&& v) { return nw::graph::intersection_size(graph[u], graph[v], set); }, std::plus{}, 0ul); } /// Two-dimensional triangle counting. diff --git a/include/containers/compressed.hpp b/include/containers/compressed.hpp index feff93c5..8c1a8029 100644 --- a/include/containers/compressed.hpp +++ b/include/containers/compressed.hpp @@ -81,7 +81,7 @@ class indexed_struct_of_arrays { private: indexed_struct_of_arrays& graph_; // the underlying indexed data index_t u_; // the current source vertex id - difference_type j_; // the current edge + difference_type j_; // the current edge public: flat_iterator(indexed_struct_of_arrays& graph, index_t i, difference_type j) : graph_(graph), u_(i), j_(j) {} @@ -149,7 +149,6 @@ class indexed_struct_of_arrays { bool operator>=(const flat_iterator& b) const { return j_ >= b.j_; } }; - /// Provide a tbb split-able range interface to the edge iterators. template class flat_range { @@ -179,9 +178,6 @@ class indexed_struct_of_arrays { return {begin, end, cutoff}; } - - /// This iterator provides a 2D vertex-neighbor tbb split-able interface to - /// the graph. class outer_iterator { std::vector::iterator indices_; typename struct_of_arrays::iterator indexed_; @@ -225,9 +221,9 @@ class indexed_struct_of_arrays { }; class const_outer_iterator { - std::vector::const_iterator indices_; + std::vector::const_iterator indices_; typename struct_of_arrays::const_iterator indexed_; - index_t i_; + index_t i_; public: using difference_type = index_t; @@ -236,7 +232,8 @@ class indexed_struct_of_arrays { using pointer = const value_type*; using iterator_category = std::random_access_iterator_tag; - const_outer_iterator(std::vector::const_iterator indices, typename struct_of_arrays::const_iterator indexed, index_t i) + const_outer_iterator(std::vector::const_iterator indices, + typename struct_of_arrays::const_iterator indexed, index_t i) : indices_(indices), indexed_(indexed), i_(i) {} const_outer_iterator& operator++() { @@ -281,17 +278,17 @@ class indexed_struct_of_arrays { using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; - iterator begin() { return {indices_.begin(), to_be_indexed_.begin(), 0}; } + iterator begin() { return {indices_.begin(), to_be_indexed_.begin(), 0}; } const_iterator begin() const { return {indices_.begin(), to_be_indexed_.begin(), 0}; } - iterator end() { return {indices_.begin(), to_be_indexed_.begin(), N_}; } - const_iterator end() const { return {indices_.begin(), to_be_indexed_.begin(), N_}; } + iterator end() { return {indices_.begin(), to_be_indexed_.begin(), N_}; } + const_iterator end() const { return {indices_.begin(), to_be_indexed_.begin(), N_}; } /// Random access to the outer range. - sub_view operator[](index_t i) { return begin()[i]; } + sub_view operator[](index_t i) { return begin()[i]; } const_sub_view operator[](index_t i) const { return begin()[i]; } index_t size() const { return indices_.size() - 1; } - index_t max() const { return indices_.size() - 2; } + index_t max() const { return indices_.size() - 2; } index_t source(difference_type edge) const { auto i = std::upper_bound(indices_.begin(), indices_.end(), edge); @@ -497,29 +494,21 @@ class indexed_struct_of_arrays { } }; - - template class index_compressed : public graph_base, public indexed_struct_of_arrays { using base = indexed_struct_of_arrays; + public: index_compressed(size_t N) : graph_base(N), base(N) {} - void close_for_push_back() { - base::close_for_push_back(); - }; - - auto num_edges() { - return base::to_be_indexed_.size(); - } + void close_for_push_back() { base::close_for_push_back(); }; + auto num_edges() { return base::to_be_indexed_.size(); } }; - template using compressed = index_compressed; - #if 0 template class adjacency : public indexed_struct_of_arrays { diff --git a/include/containers/edge_list.hpp b/include/containers/edge_list.hpp index a5fd8593..abe6648a 100644 --- a/include/containers/edge_list.hpp +++ b/include/containers/edge_list.hpp @@ -369,8 +369,7 @@ class index_edge_list : public graph_base, public struct_of_arrays Tmp(0); // BUG!!!! - index_edge_list Tmp( - 0); // undirected == directed with doubled (and swapped) edges + index_edge_list Tmp(0); // undirected == directed with doubled (and swapped) edges Tmp.resize(2 * base::size()); { @@ -449,7 +448,6 @@ class index_edge_list : public graph_base, public struct_of_arrays -_OutputIterator exclusive_scan(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _Tp __init, - _BinaryOp __b) { +template +_OutputIterator exclusive_scan(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _Tp __init, _BinaryOp __b) { if (__first != __last) { _Tp __saved = __init; do { @@ -23,7 +22,7 @@ _OutputIterator exclusive_scan(_InputIterator __first, _InputIterator __last, _O return __result; } -template +template _OutputIterator exclusive_scan(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _Tp __init) { return exclusive_scan(__first, __last, __result, __init, std::plus<>()); } @@ -31,7 +30,7 @@ _OutputIterator exclusive_scan(_InputIterator __first, _InputIterator __last, _O #endif #if defined(BGL17_NEED_INCLUSIVE_SCAN) -template +template _OutputIterator inclusive_scan(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _BinaryOperation __binary_op, _Tp __init) { for (; __first != __last; ++__first) @@ -39,7 +38,7 @@ _OutputIterator inclusive_scan(_InputIterator __first, _InputIterator __last, _O return __result; } -template +template _OutputIterator inclusive_scan(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _BinaryOperation __binary_op) { if (__first != __last) { @@ -51,14 +50,14 @@ _OutputIterator inclusive_scan(_InputIterator __first, _InputIterator __last, _O return __result; } -template +template _OutputIterator inclusive_scan(_InputIterator __first, _InputIterator __last, _OutputIterator __result) { return std::inclusive_scan(__first, __last, __result, std::plus<>()); } #endif #if defined(BGL17_NEED_REDUCE) -template +template _Tp reduce(_InputIterator __first, _InputIterator __last, _Tp __init, _BinaryOperation __binary_op) { using value_type = typename iterator_traits<_InputIterator>::value_type; static_assert(is_invocable_r_v<_Tp, _BinaryOperation&, _Tp&, _Tp&>); @@ -78,12 +77,12 @@ _Tp reduce(_InputIterator __first, _InputIterator __last, _Tp __init, _BinaryOpe return __init; } -template +template _Tp reduce(_InputIterator __first, _InputIterator __last, _Tp __init) { return std::reduce(__first, __last, std::move(__init), std::plus<>()); } -template +template typename iterator_traits<_InputIterator>::value_type reduce(_InputIterator __first, _InputIterator __last) { using value_type = typename iterator_traits<_InputIterator>::value_type; return std::reduce(__first, __last, value_type{}, std::plus<>()); diff --git a/include/graph_base.hpp b/include/graph_base.hpp index 7f59e4b0..4d75b167 100644 --- a/include/graph_base.hpp +++ b/include/graph_base.hpp @@ -57,9 +57,9 @@ class graph_base { auto num_edges() { return num_edges_; } protected: - std::array vertex_cardinality; // ordinal limits - std::size_t num_edges_; - bool is_open; // can we mutate graph + std::array vertex_cardinality; // ordinal limits + std::size_t num_edges_; + bool is_open; // can we mutate graph }; template diff --git a/include/io/MatrixMarketFile.hpp b/include/io/MatrixMarketFile.hpp index 66c26a05..4f42fdc0 100644 --- a/include/io/MatrixMarketFile.hpp +++ b/include/io/MatrixMarketFile.hpp @@ -12,13 +12,12 @@ #include #include +#include #include -#include -#include #include -#include #include -#include +#include +#include #include extern "C" { @@ -27,34 +26,30 @@ extern "C" { namespace mmio { template -class Range -{ +class Range { It begin_; It end_; - public: +public: Range(It begin, It end) : begin_(begin), end_(end) {} It begin() const { return begin_; } - It end() const { return end_; } + It end() const { return end_; } }; -class MatrixMarketFile final -{ - int fd_ = -1; // .mtx file descriptor - int n_ = 0; // number of rows - int m_ = 0; // number of columns - int nnz_ = 0; // number of edges - - char* base_ = nullptr; // base pointer to mmap-ed file - long i_ = 0; // byte offset of the first edge - long e_ = 0; // bytes in the mmap-ed file - +class MatrixMarketFile final { + int fd_ = -1; // .mtx file descriptor + int n_ = 0; // number of rows + int m_ = 0; // number of columns + int nnz_ = 0; // number of edges + + char* base_ = nullptr; // base pointer to mmap-ed file + long i_ = 0; // byte offset of the first edge + long e_ = 0; // bytes in the mmap-ed file + MM_typecode type_; - public: - MatrixMarketFile(std::filesystem::path path) - : fd_(open(path.c_str(), O_RDONLY)) - { +public: + MatrixMarketFile(std::filesystem::path path) : fd_(open(path.c_str(), O_RDONLY)) { if (fd_ < 0) { fprintf(stderr, "open failed, %d: %s\n", errno, strerror(errno)); std::terminate(); @@ -67,10 +62,10 @@ class MatrixMarketFile final } switch (mm_read_banner(f, &type_)) { - case MM_PREMATURE_EOF: // if all items are not present on first line of file. - case MM_NO_HEADER: // if the file does not begin with "%%MatrixMarket". - case MM_UNSUPPORTED_TYPE: // if not recongizable description. - goto error; + case MM_PREMATURE_EOF: // if all items are not present on first line of file. + case MM_NO_HEADER: // if the file does not begin with "%%MatrixMarket". + case MM_UNSUPPORTED_TYPE: // if not recongizable description. + goto error; } if (!mm_is_coordinate(type_)) { @@ -78,8 +73,8 @@ class MatrixMarketFile final } switch (mm_read_mtx_crd_size(f, &n_, &m_, &nnz_)) { - case MM_PREMATURE_EOF: // if an end-of-file is encountered before processing these three values. - goto error; + case MM_PREMATURE_EOF: // if an end-of-file is encountered before processing these three values. + goto error; } i_ = ftell(f); @@ -99,13 +94,10 @@ class MatrixMarketFile final std::terminate(); }; - ~MatrixMarketFile() { - release(); - }; + ~MatrixMarketFile() { release(); }; /// Release the memory mapping and file descriptor early. - void release() - { + void release() { if (base_ && munmap(base_, e_)) { fprintf(stderr, "munmap failed, %d: %s\n", errno, strerror(errno)); } @@ -118,34 +110,21 @@ class MatrixMarketFile final }; /// ADL - friend void release(MatrixMarketFile& mm) { - mm.release(); - } + friend void release(MatrixMarketFile& mm) { mm.release(); } - int getNRows() const { - return n_; - } + int getNRows() const { return n_; } - int getNCols() const { - return m_; - } + int getNCols() const { return m_; } - int getNEdges() const { - return nnz_; - } + int getNEdges() const { return nnz_; } - bool isPattern() const { - return mm_is_pattern(type_); - } + bool isPattern() const { return mm_is_pattern(type_); } - bool isSymmetric() const { - return mm_is_symmetric(type_); - } + bool isSymmetric() const { return mm_is_symmetric(type_); } // Iterator over edges in the file. template - class iterator - { + class iterator { const char* i_; /// Read the next token in the stream as a U, and update the pointer. @@ -153,27 +132,25 @@ class MatrixMarketFile final /// This horrible code is required because normal stream processing is very /// slow, while this tokenized version is just sort of slow. template - static constexpr U get(const char* (&i)) { - U v; + static constexpr U get(const char*(&i)) { + U v; char* e; if constexpr (std::is_same_v) { v = std::strtol(i, &e, 10); - } - else { + } else { v = std::strtod(i, &e); } i = e; return v; } - public: - iterator(const char* i) : i_(i) { - } + public: + iterator(const char* i) : i_(i) {} std::tuple operator*() const { const char* i = i_; - int u = get(i) - 1; - int v = get(i) - 1; + int u = get(i) - 1; + int v = get(i) - 1; return std::tuple(u, v, get(i)...); } @@ -182,24 +159,22 @@ class MatrixMarketFile final return *this; } - bool operator!=(const iterator& b) const { - return i_ != b.i_; - } + bool operator!=(const iterator& b) const { return i_ != b.i_; } }; template iterator begin() const { - return { base_ + i_ }; + return {base_ + i_}; } template iterator end() const { - return { base_ + e_ }; + return {base_ + e_}; } template iterator at(long edge) const { - if (edge == 0) return begin(); + if (edge == 0) return begin(); if (edge == nnz_) return end(); // Use the edge id to come up with an approximation of the byte to start @@ -210,7 +185,7 @@ class MatrixMarketFile final --approx; } ++approx; - return { base_ + approx }; + return {base_ + approx}; } }; @@ -218,4 +193,4 @@ template auto edges(const MatrixMarketFile& mm, int j, int k) { return Range(mm.template at(j), mm.template at(k)); } -} +} // namespace mmio diff --git a/include/io/mmio.hpp b/include/io/mmio.hpp index 5bfc795a..3d3d602d 100644 --- a/include/io/mmio.hpp +++ b/include/io/mmio.hpp @@ -15,14 +15,14 @@ #include #include #include +#include #include #include #include #include #include -#include -#include #include +#include #include "MatrixMarketFile.hpp" #include "containers/edge_list.hpp" @@ -344,7 +344,6 @@ void write_mm(const std::string& filename, adjacency& A, con adjacency_stream(outputStream, A, file_symmetry, w_type); } - #if 0 static size_t block_min(int thread, size_t M, int threads) { diff --git a/include/util/disjoint_set.hpp b/include/util/disjoint_set.hpp index ba9deab9..ecee465d 100644 --- a/include/util/disjoint_set.hpp +++ b/include/util/disjoint_set.hpp @@ -163,12 +163,10 @@ class disjoint_set { template void allToSingletons(ExecutionPolicy&& policy = {}) { size_t i = 0; - std::for_each( - policy, - this->sets_, this->sets_ + this->maxid_, [&i, this]() { - this->sets[i] = i; - ++i; - }); + std::for_each(policy, this->sets_, this->sets_ + this->maxid_, [&i, this]() { + this->sets[i] = i; + ++i; + }); } template static void allToSingletons(L* arr, const size_t size) { diff --git a/include/util/types.hpp b/include/util/types.hpp index 5b1d7a8c..233f1537 100644 --- a/include/util/types.hpp +++ b/include/util/types.hpp @@ -17,8 +17,8 @@ namespace nw { namespace graph { - // using vertex_id_t = uint32_t; - // using index_t = std::size_t; +// using vertex_id_t = uint32_t; +// using index_t = std::size_t; } // namespace graph } // namespace nw diff --git a/include/util/util.hpp b/include/util/util.hpp index b50a33d7..5d0bfb02 100644 --- a/include/util/util.hpp +++ b/include/util/util.hpp @@ -118,19 +118,16 @@ constexpr auto select(Tuple&& t) -> std::tuple using select_t = decltype(select(std::declval())); - template struct null_vertex_s { constexpr static vertex_id_type value = std::numeric_limits::max(); }; - template inline constexpr auto null_vertex_v() { return null_vertex_s::value; } - template >> void histogram(InputIterator first, InputIterator last, RandomAccessIterator o_first, RandomAccessIterator o_last, size_t idx = 0) { From 13aca8b28b820b7372a7af16292840599864def1 Mon Sep 17 00:00:00 2001 From: Andrew Lumsdaine Date: Mon, 28 Dec 2020 16:52:31 -0800 Subject: [PATCH 007/385] refactor vertex_id_t --- include/adaptors/bfs_edge_range.hpp | 11 +++- include/adaptors/cyclic_range_adapter.hpp | 2 +- include/adaptors/edge_range.hpp | 4 +- include/adaptors/worklist.hpp | 6 +- include/algorithms/betweenness_centrality.hpp | 45 ++++++++++---- include/algorithms/page_rank.hpp | 62 ++++++++++++------- include/containers/compressed.hpp | 2 + include/util/AtomicBitVector.hpp | 2 +- 8 files changed, 92 insertions(+), 42 deletions(-) diff --git a/include/adaptors/bfs_edge_range.hpp b/include/adaptors/bfs_edge_range.hpp index 4cdbc6a4..069688e8 100644 --- a/include/adaptors/bfs_edge_range.hpp +++ b/include/adaptors/bfs_edge_range.hpp @@ -29,8 +29,10 @@ namespace graph { enum three_colors { black, white, grey }; -template > +template > class bfs_edge_range { +private: + using vertex_id_t = typename Graph::vertex_id_t; public: bfs_edge_range(Graph& graph, vertex_id_t seed = 0) : the_graph_(graph), colors_(graph.size(), white) { @@ -118,6 +120,8 @@ class bfs_edge_range { template class bfs_edge_range2 { private: + using vertex_id_t = typename Graph::vertex_id_t; + public: bfs_edge_range2(Graph& graph, PriorityQueue& Q, std::tuple seed = {0, 0}) : the_graph_(graph), Q_(Q), colors_(graph.end() - graph.begin(), white) { @@ -199,8 +203,11 @@ class bfs_edge_range2 { std::vector colors_; }; -template > +template > class bfs_edge_range3 { +private: + using vertex_id_t = typename Graph::vertex_id_t; + public: bfs_edge_range3(Graph& graph, vertex_id_t seed = 0) : the_graph_(graph), colors_(graph.end() - graph.begin(), white) { Q_[0].push(seed); diff --git a/include/adaptors/cyclic_range_adapter.hpp b/include/adaptors/cyclic_range_adapter.hpp index a0d85b2f..3e21e45c 100644 --- a/include/adaptors/cyclic_range_adapter.hpp +++ b/include/adaptors/cyclic_range_adapter.hpp @@ -4,7 +4,7 @@ #include "util/types.hpp" #include "util/util.hpp" #include -#include +#include namespace nw { namespace graph { diff --git a/include/adaptors/edge_range.hpp b/include/adaptors/edge_range.hpp index 62fc2d48..789e35d8 100644 --- a/include/adaptors/edge_range.hpp +++ b/include/adaptors/edge_range.hpp @@ -14,7 +14,7 @@ #include "util/print_types.hpp" #include "util/types.hpp" #include "util/util.hpp" -#include +#include #include namespace nw { @@ -25,6 +25,8 @@ class edge_range { static_assert(((Is < Graph::getNAttr()) && ...), "Attribute index out of range"); static constexpr size_t cutoff_ = 16; + using vertex_id_t = typename Graph::vertex_id_t; + typename Graph::iterator outer_base_; typename Graph::iterator outer_begin_; typename Graph::iterator outer_end_; diff --git a/include/adaptors/worklist.hpp b/include/adaptors/worklist.hpp index c468ffdd..21c22dec 100644 --- a/include/adaptors/worklist.hpp +++ b/include/adaptors/worklist.hpp @@ -27,7 +27,7 @@ namespace graph { //**************************************************************************** //template > -template > +template > class worklist_range { public: worklist_range(Graph& graph) : the_graph_(graph) {} @@ -78,7 +78,7 @@ class worklist_range { }; //**************************************************************************** -template > +template > class tbbworklist_range { public: tbbworklist_range(Graph& graph) : the_graph_(graph) {} @@ -143,7 +143,7 @@ class tbbworklist_range { }; //**************************************************************************** -template > +template > class tbbworklist_range2 { public: tbbworklist_range2(Graph& graph) : the_graph_(graph), buckets_(10000) {} diff --git a/include/algorithms/betweenness_centrality.hpp b/include/algorithms/betweenness_centrality.hpp index 29fc1417..e62a5f3d 100644 --- a/include/algorithms/betweenness_centrality.hpp +++ b/include/algorithms/betweenness_centrality.hpp @@ -63,6 +63,8 @@ class Spinlock { //**************************************************************************** template std::vector betweenness_brandes(Graph& A) { + using vertex_id_t = typename Graph::vertex_id_t; + size_t n_vtx = A.size(); std::vector centrality(n_vtx, 0); auto G = A.begin(); @@ -119,7 +121,9 @@ std::vector betweenness_brandes(Graph& A) { } template -std::vector approx_betweenness_brandes(Graph& A, std::vector& sources) { +std::vector approx_betweenness_brandes(Graph& A, std::vector& sources) { + using vertex_id_t = typename Graph::vertex_id_t; + size_t n_vtx = A.size(); std::vector centrality(n_vtx, 0); auto G = A.begin(); @@ -174,7 +178,9 @@ std::vector approx_betweenness_brandes(Graph& A, std::vector -std::vector approx_betweenness_worklist_serial(Graph& A, std::vector& sources) { +std::vector approx_betweenness_worklist_serial(Graph& A, std::vector& sources) { + using vertex_id_t = typename Graph::vertex_id_t; + size_t n_vtx = A.size(); std::vector centrality(n_vtx, 0); auto G = A.begin(); @@ -342,7 +348,10 @@ std::vector approx_betweenness_worklist_serial(Graph& A, std::vector -std::vector approx_betweenness_worklist(Graph& A, std::vector& sources, size_t num_threads, size_t DELTA) { +std::vector approx_betweenness_worklist(Graph& A, std::vector& sources, size_t num_threads, + size_t DELTA) { + using vertex_id_t = typename Graph::vertex_id_t; + size_t n_vtx = A.size(); std::vector centrality(n_vtx, 0); auto G = A.begin(); @@ -669,8 +678,10 @@ std::vector approx_betweenness_worklist(Graph& A, std::vector -std::vector approx_betweenness_worklist_noabstraction(Graph& A, std::vector& sources, size_t num_threads, - size_t par_thresh, size_t DELTA = 1) { +std::vector approx_betweenness_worklist_noabstraction(Graph& A, std::vector& sources, + size_t num_threads, size_t par_thresh, size_t DELTA = 1) { + using vertex_id_t = typename Graph::vertex_id_t; + size_t n_vtx = A.size(); std::vector centrality(n_vtx, 0.0); auto G = A.begin(); @@ -1282,7 +1293,8 @@ std::vector Brandes(const Graph &g, const std::vector sour #endif template -auto bc2_v0(Graph& graph, const std::vector sources) { +auto bc2_v0(Graph& graph, const std::vector sources) { + using vertex_id_t = typename Graph::vertex_id_t; auto g = graph.begin(); vertex_id_t N = graph.max() + 1; @@ -1347,7 +1359,8 @@ auto bc2_v0(Graph& graph, const std::vector sources) { } template -auto bc2_v1(Graph& graph, const std::vector sources) { +auto bc2_v1(Graph& graph, const std::vector sources) { + using vertex_id_t = typename Graph::vertex_id_t; auto g = graph.begin(); vertex_id_t N = graph.max() + 1; @@ -1414,7 +1427,8 @@ auto bc2_v1(Graph& graph, const std::vector sources) { template -auto bc2_v2(Graph& graph, const std::vector& sources, ExecutionPolicy&& policy = {}) { +auto bc2_v2(Graph& graph, const std::vector& sources, ExecutionPolicy&& policy = {}) { + using vertex_id_t = typename Graph::vertex_id_t; auto g = graph.begin(); vertex_id_t N = graph.max() + 1; @@ -1488,8 +1502,9 @@ auto bc2_v2(Graph& graph, const std::vector& sources, ExecutionPoli template -auto bc2_v3(Graph& graph, const std::vector& sources, OuterExecutionPolicy&& outer_policy = {}, +auto bc2_v3(Graph& graph, const std::vector& sources, OuterExecutionPolicy&& outer_policy = {}, InnerExecutionPolicy&& inner_policy = {}) { + using vertex_id_t = typename Graph::vertex_id_t; auto g = graph.begin(); vertex_id_t N = graph.max() + 1; @@ -1588,8 +1603,10 @@ auto bc2_v3(Graph& graph, const std::vector& sources, OuterExecutio template -auto bc2_v4(Graph&& graph, const std::vector& sources, int threads, OuterExecutionPolicy&& outer_policy = {}, - InnerExecutionPolicy&& inner_policy = {}) { +auto bc2_v4(Graph&& graph, const std::vector& sources, int threads, + OuterExecutionPolicy&& outer_policy = {}, InnerExecutionPolicy&& inner_policy = {}) { + using vertex_id_t = typename Graph::vertex_id_t; + auto g = graph.begin(); vertex_id_t N = graph.max() + 1; size_t M = graph.to_be_indexed_.size(); @@ -1677,8 +1694,10 @@ auto bc2_v4(Graph&& graph, const std::vector& sources, int threads, template -auto bc2_v5(Graph&& graph, const std::vector& sources, int threads, OuterExecutionPolicy&& outer_policy = {}, - InnerExecutionPolicy&& inner_policy = {}) { +auto bc2_v5(Graph&& graph, const std::vector& sources, int threads, + OuterExecutionPolicy&& outer_policy = {}, InnerExecutionPolicy&& inner_policy = {}) { + using vertex_id_t = typename Graph::vertex_id_t; + vertex_id_t N = graph.max() + 1; size_t M = graph.to_be_indexed_.size(); auto&& edges = std::get<0>(*(graph[0]).begin()); diff --git a/include/algorithms/page_rank.hpp b/include/algorithms/page_rank.hpp index fc93dd19..d0cb2ce1 100644 --- a/include/algorithms/page_rank.hpp +++ b/include/algorithms/page_rank.hpp @@ -131,6 +131,8 @@ void page_rank_range_for(GraphT& graph, std::vector& page_rank, RealT dam template void page_rank_vc(Graph& graph, std::vector& page_rank, const Real damping_factor = 0.85, const Real threshold = 1.e-4, const size_t max_iters = std::numeric_limits::max()) { + using vertex_id_t = typename Graph::vertex_id_t; + const Real init_score = 1.0 / page_rank.size(); const Real base_score = (1.0 - damping_factor) / page_rank.size(); @@ -171,9 +173,10 @@ void page_rank_vc(Graph& graph, std::vector& page_rank, const Real damping } template -void page_rank_v1(Graph& graph, const std::vector& degrees, std::vector& page_rank, +void page_rank_v1(Graph& graph, const std::vector& degrees, std::vector& page_rank, const Real damping_factor = 0.85, const Real threshold = 1.e-4, const size_t max_iters = std::numeric_limits::max()) { + using vertex_id_t = typename Graph::vertex_id_t; const Real init_score = 1.0 / page_rank.size(); const Real base_score = (1.0 - damping_factor) / page_rank.size(); @@ -208,9 +211,10 @@ void page_rank_v1(Graph& graph, const std::vector& degrees, std::ve } template -void page_rank_v2(Graph& graph, const std::vector& degrees, std::vector& page_rank, +void page_rank_v2(Graph& graph, const std::vector& degrees, std::vector& page_rank, const Real damping_factor = 0.85, const Real threshold = 1.e-4, const size_t max_iters = std::numeric_limits::max()) { + using vertex_id_t = typename Graph::vertex_id_t; const Real init_score = 1.0 / page_rank.size(); const Real base_score = (1.0 - damping_factor) / page_rank.size(); @@ -241,9 +245,11 @@ void page_rank_v2(Graph& graph, const std::vector& degrees, std::ve } template -void page_rank_v4(Graph& graph, const std::vector& degrees, std::vector& page_rank, +void page_rank_v4(Graph& graph, const std::vector& degrees, std::vector& page_rank, const Real damping_factor = 0.85, const Real threshold = 1.e-4, const size_t max_iters = std::numeric_limits::max(), size_t num_threads = 1) { + using vertex_id_t = typename Graph::vertex_id_t; + const Real init_score = 1.0 / page_rank.size(); const Real base_score = (1.0 - damping_factor) / page_rank.size(); @@ -294,9 +300,10 @@ void page_rank_v4(Graph& graph, const std::vector& degrees, std::ve } template -[[gnu::noinline]] void page_rank_v6(Graph& graph, const std::vector& degrees, std::vector& page_rank, - const Real damping_factor = 0.85, const Real threshold = 1.e-4, +[[gnu::noinline]] void page_rank_v6(Graph& graph, const std::vector& degrees, + std::vector& page_rank, const Real damping_factor = 0.85, const Real threshold = 1.e-4, const size_t max_iters = std::numeric_limits::max(), size_t num_threads = 1) { + const Real init_score = 1.0 / page_rank.size(); const Real base_score = (1.0 - damping_factor) / page_rank.size(); @@ -352,9 +359,11 @@ template } template -void page_rank_v7(Graph& graph, const std::vector& degrees, std::vector& page_rank, +void page_rank_v7(Graph& graph, const std::vector& degrees, std::vector& page_rank, const Real damping_factor = 0.85, const Real threshold = 1.e-4, const size_t max_iters = std::numeric_limits::max(), size_t num_threads = 1) { + using vertex_id_t = typename Graph::vertex_id_t; + const Real init_score = 1.0 / page_rank.size(); const Real base_score = (1.0 - damping_factor) / page_rank.size(); @@ -400,9 +409,11 @@ void page_rank_v7(Graph& graph, const std::vector& degrees, std::ve } template -void page_rank_v8(Graph& graph, const std::vector& degrees, std::vector& page_rank, +void page_rank_v8(Graph& graph, const std::vector& degrees, std::vector& page_rank, const Real damping_factor = 0.85, const Real threshold = 1.e-4, const size_t max_iters = std::numeric_limits::max(), size_t num_threads = 1) { + using vertex_id_t = typename Graph::vertex_id_t; + const Real init_score = 1.0 / page_rank.size(); const Real base_score = (1.0 - damping_factor) / page_rank.size(); @@ -437,8 +448,11 @@ void page_rank_v8(Graph& graph, const std::vector& degrees, std::ve } template -[[gnu::noinline]] void page_rank_v9(Graph& graph, const std::vector& degrees, std::vector& page_rank, - Real damping_factor, Real threshold, size_t max_iters, size_t num_threads) { +[[gnu::noinline]] void page_rank_v9(Graph& graph, const std::vector& degrees, + std::vector& page_rank, Real damping_factor, Real threshold, size_t max_iters, + size_t num_threads) { + using vertex_id_t = typename Graph::vertex_id_t; + std::size_t N = page_rank.size(); Real init_score = 1.0 / N; Real base_score = (1.0 - damping_factor) / N; @@ -478,8 +492,9 @@ template } template -[[gnu::noinline]] void page_rank_v10(Graph& graph, const std::vector& degrees, std::vector& page_rank, - Real damping_factor, Real threshold, size_t max_iters, size_t num_threads) { +[[gnu::noinline]] void page_rank_v10(Graph& graph, const std::vector& degrees, + std::vector& page_rank, Real damping_factor, Real threshold, size_t max_iters, + size_t num_threads) { std::size_t N = graph.size(); Real init_score = 1.0 / N; Real base_score = (1.0 - damping_factor) / N; @@ -536,8 +551,9 @@ template } template -[[gnu::noinline]] void page_rank_v11(Graph& graph, const std::vector& degrees, std::vector& page_rank, - Real damping_factor, Real threshold, size_t max_iters, size_t num_threads) { +[[gnu::noinline]] void page_rank_v11(Graph& graph, const std::vector& degrees, + std::vector& page_rank, Real damping_factor, Real threshold, size_t max_iters, + size_t num_threads) { std::size_t N = graph.size(); Real init_score = 1.0 / N; Real base_score = (1.0 - damping_factor) / N; @@ -598,8 +614,9 @@ template } template -[[gnu::noinline]] void page_rank_v12(Graph& graph, const std::vector& degrees, std::vector& page_rank, - Real damping_factor, Real threshold, size_t max_iters, size_t num_threads) { +[[gnu::noinline]] void page_rank_v12(Graph& graph, const std::vector& degrees, + std::vector& page_rank, Real damping_factor, Real threshold, size_t max_iters, + size_t num_threads) { std::size_t N = graph.size(); Real init_score = 1.0 / N; Real base_score = (1.0 - damping_factor) / N; @@ -658,8 +675,10 @@ template } template -[[gnu::noinline]] void page_rank_v3(Graph& graph, const std::vector& degrees, std::vector& page_rank, - Real damping_factor, Real threshold, size_t max_iters) { +[[gnu::noinline]] void page_rank_v3(Graph& graph, const std::vector& degrees, + std::vector& page_rank, Real damping_factor, Real threshold, size_t max_iters) { + using vertex_id_t = typename Graph::vertex_id_t; + std::size_t N = graph.size(); Real init_score = 1.0 / N; Real base_score = (1.0 - damping_factor) / N; @@ -724,8 +743,9 @@ template } template -[[gnu::noinline]] void page_rank_v13(Graph& graph, const std::vector& degrees, std::vector& page_rank, - Real damping_factor, Real threshold, size_t max_iters, size_t num_threads) { +[[gnu::noinline]] void page_rank_v13(Graph& graph, const std::vector& degrees, + std::vector& page_rank, Real damping_factor, Real threshold, size_t max_iters, + size_t num_threads) { std::size_t N = graph.size(); Real init_score = 1.0 / N; Real base_score = (1.0 - damping_factor) / N; @@ -795,8 +815,8 @@ template } template -[[gnu::noinline]] std::size_t page_rank_v14(Graph&& graph, const std::vector& degrees, std::vector& page_rank, - Real damping_factor, Real threshold, size_t max_iters) { +[[gnu::noinline]] std::size_t page_rank_v14(Graph&& graph, const std::vector& degrees, + std::vector& page_rank, Real damping_factor, Real threshold, size_t max_iters) { std::size_t N = graph.size(); Real init_score = 1.0 / N; Real base_score = (1.0 - damping_factor) / N; diff --git a/include/containers/compressed.hpp b/include/containers/compressed.hpp index 8c1a8029..561f73eb 100644 --- a/include/containers/compressed.hpp +++ b/include/containers/compressed.hpp @@ -499,6 +499,8 @@ class index_compressed : public graph_base, public indexed_struct_of_arrays; public: + using vertex_id_t = vertex_id_type; + index_compressed(size_t N) : graph_base(N), base(N) {} void close_for_push_back() { base::close_for_push_back(); }; diff --git a/include/util/AtomicBitVector.hpp b/include/util/AtomicBitVector.hpp index de581955..4971a1df 100644 --- a/include/util/AtomicBitVector.hpp +++ b/include/util/AtomicBitVector.hpp @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include namespace nw { From f42bcb41734cd4893d441d2457ca12506deffbf7 Mon Sep 17 00:00:00 2001 From: Andrew Lumsdaine Date: Mon, 28 Dec 2020 16:56:17 -0800 Subject: [PATCH 008/385] remove types.hpp --- include/util/types.hpp | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100644 include/util/types.hpp diff --git a/include/util/types.hpp b/include/util/types.hpp deleted file mode 100644 index 233f1537..00000000 --- a/include/util/types.hpp +++ /dev/null @@ -1,26 +0,0 @@ -// -// This file is part of BGL17 (aka NWGraph aka GraphPack aka the Graph Standard Library) -// (c) Pacific Northwest National Laboratory 2019, 2020 -// -// Licensed under Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License -// https://creativecommons.org/licenses/by-nc-sa/4.0/ -// -// Author: Andrew Lumsdaine -// - -#ifndef NW_GRAPH_TYPES_HPP -#define NW_GRAPH_TYPES_HPP - -#include -#include - -namespace nw { -namespace graph { - -// using vertex_id_t = uint32_t; -// using index_t = std::size_t; - -} // namespace graph -} // namespace nw - -#endif // NW_GRAPH_TYPES_HPP From eb0ae3c9b57317f93c91089d1760165aec2fb7ce Mon Sep 17 00:00:00 2001 From: Andrew Lumsdaine Date: Mon, 28 Dec 2020 16:56:21 -0800 Subject: [PATCH 009/385] remove types.hpp --- include/adaptors/back_edge_range.hpp | 1 - include/adaptors/bfs_edge_range.hpp | 1 - include/adaptors/bfs_range.hpp | 1 - include/adaptors/cyclic_range_adapter.hpp | 1 - include/adaptors/dag_range.hpp | 2 -- include/adaptors/dfs_range.hpp | 1 - include/adaptors/edge_range.hpp | 1 - include/adaptors/filtered_bfs_range.hpp | 1 - include/adaptors/neighbor_range.hpp | 1 - include/adaptors/new_dfs_range.hpp | 1 - include/adaptors/plain_range.hpp | 1 - include/adaptors/random_range.hpp | 1 - include/adaptors/reverse.hpp | 1 - include/adaptors/worklist.hpp | 1 - include/algorithms/betweenness_centrality.hpp | 1 - include/algorithms/bfs.hpp | 1 - include/algorithms/boykov_kolmogorov.hpp | 1 - include/algorithms/connected_components.hpp | 1 - include/algorithms/dag_based_mis.hpp | 1 - include/algorithms/delta_stepping.hpp | 2 -- include/algorithms/dijkstra.hpp | 1 - include/algorithms/k_core.hpp | 1 - include/algorithms/max_flow.hpp | 1 - include/algorithms/page_rank.hpp | 1 - include/algorithms/spanning_tree.hpp | 1 - include/algorithms/triangle_count.hpp | 1 - include/containers/vovos.hpp | 1 - include/util/disjoint_set.hpp | 1 - include/util/traits.hpp | 1 - include/util/util.hpp | 1 - include/util/util_par.hpp | 2 -- 31 files changed, 34 deletions(-) diff --git a/include/adaptors/back_edge_range.hpp b/include/adaptors/back_edge_range.hpp index 7f3ff5a8..f36ef978 100644 --- a/include/adaptors/back_edge_range.hpp +++ b/include/adaptors/back_edge_range.hpp @@ -7,7 +7,6 @@ // // Author: Kevin Deweese // -#include "util/types.hpp" #include "util/util.hpp" #include diff --git a/include/adaptors/bfs_edge_range.hpp b/include/adaptors/bfs_edge_range.hpp index 069688e8..24cb7e28 100644 --- a/include/adaptors/bfs_edge_range.hpp +++ b/include/adaptors/bfs_edge_range.hpp @@ -18,7 +18,6 @@ // template