From f12afc88eb34bf495b6b5479ab64ae0d69be9e2e Mon Sep 17 00:00:00 2001 From: Phil Ratzloff Date: Tue, 27 Aug 2024 19:50:39 -0400 Subject: [PATCH 1/5] Throw out_of_range if distances or predecessors size are less than the number of vertices Added concept constraint to require distances and predecessors to be sized_range Use iota to initialize predecessors --- .../algorithm/bellman_ford_shortest_paths.hpp | 30 +++++++++++++++---- .../graph/algorithm/common_shortest_paths.hpp | 7 ++--- .../algorithm/dijkstra_shortest_paths.hpp | 21 ++++++++++++- 3 files changed, 47 insertions(+), 11 deletions(-) diff --git a/include/graph/algorithm/bellman_ford_shortest_paths.hpp b/include/graph/algorithm/bellman_ford_shortest_paths.hpp index ebc0f13..428b26e 100644 --- a/include/graph/algorithm/bellman_ford_shortest_paths.hpp +++ b/include/graph/algorithm/bellman_ford_shortest_paths.hpp @@ -107,9 +107,11 @@ template , class Compare = less>, class Combine = plus>> -requires convertible_to, vertex_id_t> && // - is_arithmetic_v> && // - convertible_to, ranges::range_value_t> && +requires convertible_to, vertex_id_t> && // + is_arithmetic_v> && // + convertible_to, ranges::range_value_t> && // + ranges::sized_range && // + ranges::sized_range && // basic_edge_weight_function, Compare, Combine> // && bellman_visitor bool bellman_ford_shortest_paths( @@ -143,6 +145,20 @@ bool bellman_ford_shortest_paths( return false; }; + if (size(distances) < size(vertices(g))) { + throw out_of_range( + fmt::format("bellman_ford_shortest_paths: size of distances is {} is less than the number of vertices {}", + size(distances), size(vertices(g)))); + } + + if constexpr (!is_same_v) { + if (size(predecessor) < size(vertices(g))) { + throw out_of_range( + fmt::format("bellman_ford_shortest_paths: size of predecessor is {} is less than the number of vertices {}", + size(predecessor), size(vertices(g)))); + } + } + constexpr auto zero = shortest_path_zero(); constexpr auto infinite = shortest_path_invalid_distance(); @@ -210,8 +226,10 @@ template , class Compare = less>, class Combine = plus>> -requires is_arithmetic_v> && // - convertible_to, ranges::range_value_t> && +requires is_arithmetic_v> && // + convertible_to, ranges::range_value_t> && // + ranges::sized_range && // + ranges::sized_range && // basic_edge_weight_function, Compare, Combine> // && bellman_visitor bool bellman_ford_shortest_paths( @@ -267,6 +285,7 @@ template >> requires convertible_to, vertex_id_t> && // is_arithmetic_v> && // + ranges::sized_range && // basic_edge_weight_function, Compare, Combine> //&& bellman_visitor bool bellman_ford_shortest_distances( @@ -290,6 +309,7 @@ template >, class Combine = plus>> requires is_arithmetic_v> && // + ranges::sized_range && // basic_edge_weight_function, Compare, Combine> //&& bellman_visitor bool bellman_ford_shortest_distances( diff --git a/include/graph/algorithm/common_shortest_paths.hpp b/include/graph/algorithm/common_shortest_paths.hpp index 88400d1..f806ac7 100644 --- a/include/graph/algorithm/common_shortest_paths.hpp +++ b/include/graph/algorithm/common_shortest_paths.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #ifndef GRAPH_COMMON_SHORTEST_PATHS_HPP # define GRAPH_COMMON_SHORTEST_PATHS_HPP @@ -70,11 +71,7 @@ constexpr void init_shortest_paths(Distances& distances) { template constexpr void init_shortest_paths(Distances& distances, Predecessors& predecessors) { init_shortest_paths(distances); - - using pred_t = ranges::range_value_t; - pred_t i = pred_t(); - for (auto& pred : predecessors) - pred = i++; + ranges::iota(predecessors, 0); } /** diff --git a/include/graph/algorithm/dijkstra_shortest_paths.hpp b/include/graph/algorithm/dijkstra_shortest_paths.hpp index 8944926..99d71ef 100644 --- a/include/graph/algorithm/dijkstra_shortest_paths.hpp +++ b/include/graph/algorithm/dijkstra_shortest_paths.hpp @@ -103,6 +103,8 @@ template >> requires convertible_to, vertex_id_t> && // is_arithmetic_v> && // + ranges::sized_range && // + ranges::sized_range && // convertible_to, ranges::range_value_t> && basic_edge_weight_function, Compare, Combine> // && dijkstra_visitor @@ -137,6 +139,19 @@ void dijkstra_shortest_paths( return false; }; + if (size(distances) < size(vertices(g))) { + throw out_of_range( + fmt::format("dijkstra_shortest_paths: size of distances of {} is less than the number of vertices {}", + size(distances), size(vertices(g)))); + } + if constexpr (!is_same_v) { + if (size(predecessor) < size(vertices(g))) { + throw out_of_range( + fmt::format("dijkstra_shortest_paths: size of predecessor of {} is less than the number of vertices {}", + size(predecessor), size(vertices(g)))); + } + } + constexpr auto zero = shortest_path_zero(); constexpr auto infinite = shortest_path_invalid_distance(); @@ -176,7 +191,7 @@ void dijkstra_shortest_paths( // Negative weights are not allowed for Dijkstra's algorithm if constexpr (is_signed_v) { if (w < zero) { - throw graph_error( + throw out_of_range( fmt::format("dijkstra_shortest_paths: invalid negative edge weight of '{}' encountered", w)); } } @@ -220,6 +235,8 @@ template >, class Combine = plus>> requires is_arithmetic_v> && // + ranges::sized_range && // + ranges::sized_range && // convertible_to, ranges::range_value_t> && basic_edge_weight_function, Compare, Combine> // && dijkstra_visitor @@ -271,6 +288,7 @@ template >, class Combine = plus>> requires convertible_to, vertex_id_t> && // + ranges::sized_range && // is_arithmetic_v> && // basic_edge_weight_function, Compare, Combine> //&& dijkstra_visitor @@ -295,6 +313,7 @@ template >, class Combine = plus>> requires is_arithmetic_v> && // + ranges::sized_range && // basic_edge_weight_function, Compare, Combine> //&& dijkstra_visitor void dijkstra_shortest_distances( From 3c0972660429b90807814373ca5a25cf0a2f4be5 Mon Sep 17 00:00:00 2001 From: Phil Ratzloff Date: Wed, 28 Aug 2024 21:58:53 -0400 Subject: [PATCH 2/5] Add find_negative_cycle() for Bellman-Ford Bellman-Ford algorithms now return optional> --- .../algorithm/bellman_ford_shortest_paths.hpp | 82 +++++++++++-------- .../graph/algorithm/common_shortest_paths.hpp | 2 +- 2 files changed, 51 insertions(+), 33 deletions(-) diff --git a/include/graph/algorithm/bellman_ford_shortest_paths.hpp b/include/graph/algorithm/bellman_ford_shortest_paths.hpp index 428b26e..425da7c 100644 --- a/include/graph/algorithm/bellman_ford_shortest_paths.hpp +++ b/include/graph/algorithm/bellman_ford_shortest_paths.hpp @@ -18,13 +18,12 @@ #include "graph/algorithm/common_shortest_paths.hpp" #include +#include #include #ifndef GRAPH_BELLMAN_SHORTEST_PATHS_HPP # define GRAPH_BELLMAN_SHORTEST_PATHS_HPP -//# define ENABLE_EVAL_NEG_WEIGHT_CYCLE 1 // for debugging - namespace std::graph { template @@ -68,6 +67,39 @@ concept bellman_visitor = //is_arithmetic && { v.on_edge_not_minimized(edesc) }; }; +/** + * @brief Get the vertex ids in a negative weight cycle. + * + * If a negative weight cycle exists, the vertex ids in the cycle are output to the output iterator. + * If no negative weight cycle exists, the output iterator is not modified. + * + * @tparam G The graph type. + * @tparam Predecessors The predecessor range type. + * @tparam OutputIterator The output iterator type. + * + * @param g The graph. + * @param predecessor The predecessor range. + * @param cycle_vertex_id A vertex id in the negative weight cycle. IF no negative weight cycle exists + * then there will be no vertex id defined. + * @param out_cycle The output iterator that the vertex ids in the cycle are output to. + */ +template +requires output_iterator> +void find_negative_cycle(G& g, + const Predecessors& predecessor, + const optional>& cycle_vertex_id, + OutputIterator out_cycle) { + // Does a negative weight cycle exist? + if (cycle_vertex_id.has_value()) { + vertex_id_t uid = cycle_vertex_id.value(); + do { + *out_cycle++ = uid; + uid = predecessor[uid]; + } while (uid != cycle_vertex_id.value()); + } +} + + /** * @brief Bellman-Ford's single-source shortest paths algorithm with a visitor. * @@ -85,7 +117,7 @@ concept bellman_visitor = //is_arithmetic && * bellman_visitor_base. * * Throws: - * - out_of_range if the source vertex is out of range. + * - out_of_range if a source vertex id is out of range. * * @tparam G The graph type, * @tparam Distances The distance random access range. @@ -96,8 +128,9 @@ concept bellman_visitor = //is_arithmetic && * @tparam Compare Comparison function for Distance values. Defaults to less. * @tparam Combine Combine function for Distance values. Defaults to plus. * - * @return true if all edges were minimized, false if a negative weight cycle was found. If an edge - * was not minimized, the on_edge_not_minimized event is called. + * @return optional>, where no vertex id is returned if all edges were minimized. + * If an edge was not minimized, the on_edge_not_minimized event is called and a vertex id + * in the negative weight cycle is returned. */ template , vertex_id_t> && ranges::sized_range && // basic_edge_weight_function, Compare, Combine> // && bellman_visitor -bool bellman_ford_shortest_paths( +[[nodiscard]] optional> bellman_ford_shortest_paths( G& g, const Sources& sources, Distances& distances, @@ -127,6 +160,7 @@ bool bellman_ford_shortest_paths( using id_type = vertex_id_t; using DistanceValue = ranges::range_value_t; using weight_type = invoke_result_t>; + using return_type = optional>; // relxing the target is the function of reducing the distance from the source to the target auto relax_target = [&g, &predecessor, &distances, &compare, &combine] // @@ -190,33 +224,16 @@ bool bellman_ford_shortest_paths( for (auto&& [uid, vid, uv, w] : views::edgelist(g, weight)) { if (compare(combine(distances[uid], w), distances[vid])) { visitor.on_edge_not_minimized({uid, vid, uv}); - -# if ENABLE_EVAL_NEG_WEIGHT_CYCLE // for debugging - // A negative cycle exists; find a vertex on the cycle - // (Thanks to Wikipedia's Bellman-Ford article for this code) - predecessor[vid] = uid; - vector visited(num_vertices(g), false); - visited[vid] = true; - while (!visited[uid]) { - visited[uid] = true; - uid = predecessor[uid]; - } - // uid is a vertex in a negative cycle, fill ncycle with the vertices in the cycle - vector ncycle; - ncycle.push_back(uid); - vid = predecessor[uid]; - while (vid != uid) { - ncycle.push_back(vid); - vid = predecessor[vid] + if constexpr (!is_same_v) { + predecessor[vid] = uid; // close the cycle } -# endif - return false; + return return_type(uid); } else { visitor.on_edge_minimized({uid, vid, uv}); } } - return true; + return return_type(); } template > && ranges::sized_range && // basic_edge_weight_function, Compare, Combine> // && bellman_visitor -bool bellman_ford_shortest_paths( +[[nodiscard]] optional> bellman_ford_shortest_paths( G& g, const vertex_id_t source, Distances& distances, @@ -273,8 +290,9 @@ bool bellman_ford_shortest_paths( * @tparam Compare Comparison function for Distance values. Defaults to less. * @tparam Combine Combine function for Distance values. Defaults to plus. * - * @return true if all edges were minimized, false if a negative weight cycle was found. If an edge - * was not minimized, the on_edge_not_minimized event is called. + * @return optional>, where no vertex id is returned if all edges were minimized. + * If an edge was not minimized, the on_edge_not_minimized event is called and a vertex id + * in the negative weight cycle is returned. */ template , vertex_id_t> && // ranges::sized_range && // basic_edge_weight_function, Compare, Combine> //&& bellman_visitor -bool bellman_ford_shortest_distances( +[[nodiscard]] optional> bellman_ford_shortest_distances( G& g, const Sources& sources, Distances& distances, @@ -312,7 +330,7 @@ requires is_arithmetic_v> && // ranges::sized_range && // basic_edge_weight_function, Compare, Combine> //&& bellman_visitor -bool bellman_ford_shortest_distances( +[[nodiscard]] optional> bellman_ford_shortest_distances( G& g, const vertex_id_t source, Distances& distances, diff --git a/include/graph/algorithm/common_shortest_paths.hpp b/include/graph/algorithm/common_shortest_paths.hpp index f806ac7..900b37b 100644 --- a/include/graph/algorithm/common_shortest_paths.hpp +++ b/include/graph/algorithm/common_shortest_paths.hpp @@ -71,7 +71,7 @@ constexpr void init_shortest_paths(Distances& distances) { template constexpr void init_shortest_paths(Distances& distances, Predecessors& predecessors) { init_shortest_paths(distances); - ranges::iota(predecessors, 0); + iota(predecessors.begin(), predecessors.end(), 0); } /** From e7a6d20ec0bb75a11c36149f0de340051c5a4edd Mon Sep 17 00:00:00 2001 From: Phil Ratzloff Date: Sat, 31 Aug 2024 12:52:06 -0400 Subject: [PATCH 3/5] Change "invalid distance" to "infinite distance" --- benchmark/mm_bench_dijkstra.cpp | 2 +- .../graph/algorithm/bellman_ford_shortest_paths.hpp | 2 +- include/graph/algorithm/common_shortest_paths.hpp | 10 +++++----- include/graph/algorithm/dijkstra_shortest_paths.hpp | 2 +- include/graph/algorithm/experimental/bfs_cmn.hpp | 10 +++++----- include/graph/algorithm/experimental/co_dijkstra.hpp | 2 +- .../graph/algorithm/experimental/visitor_dijkstra.hpp | 2 +- tests/bellman_shortest_paths_tests.cpp | 2 +- tests/co_dijkstra_tests.cpp | 2 +- tests/dijkstra_shortest_paths_tests.cpp | 2 +- 10 files changed, 18 insertions(+), 18 deletions(-) diff --git a/benchmark/mm_bench_dijkstra.cpp b/benchmark/mm_bench_dijkstra.cpp index 3670691..8be6405 100644 --- a/benchmark/mm_bench_dijkstra.cpp +++ b/benchmark/mm_bench_dijkstra.cpp @@ -63,7 +63,7 @@ std::string current_timestamp() { template size_t vertices_visited(const std::vector& distances) { size_t visited = std::accumulate(distances.begin(), distances.end(), 0ULL, [](size_t count, Distance dist) { - return (dist != shortest_path_invalid_distance()) ? count + 1 : count; + return (dist != shortest_path_infinite_distance()) ? count + 1 : count; }); //fmt::println("{:L} vertices were actually visited", visited); return visited; diff --git a/include/graph/algorithm/bellman_ford_shortest_paths.hpp b/include/graph/algorithm/bellman_ford_shortest_paths.hpp index 425da7c..b0017bf 100644 --- a/include/graph/algorithm/bellman_ford_shortest_paths.hpp +++ b/include/graph/algorithm/bellman_ford_shortest_paths.hpp @@ -194,7 +194,7 @@ requires convertible_to, vertex_id_t> && } constexpr auto zero = shortest_path_zero(); - constexpr auto infinite = shortest_path_invalid_distance(); + constexpr auto infinite = shortest_path_infinite_distance(); const id_type N = static_cast(num_vertices(g)); diff --git a/include/graph/algorithm/common_shortest_paths.hpp b/include/graph/algorithm/common_shortest_paths.hpp index 900b37b..2a8dee7 100644 --- a/include/graph/algorithm/common_shortest_paths.hpp +++ b/include/graph/algorithm/common_shortest_paths.hpp @@ -20,15 +20,15 @@ concept edge_weight_function = // e.g. weight(uv) /** * @ingroup graph_algorithms - * @brief Returns a value to define an invalid distance used to initialize distance values + * @brief Returns a value to define an infinite distance used to initialize distance values * in the distance range before one of the shorts paths functions. * * @tparam DistanceValue The type of the distance. * - * @return A unique sentinal value to indicate that a value is invalid, or undefined. + * @return A unique sentinal value for an infinite distance. */ template -constexpr auto shortest_path_invalid_distance() { +constexpr auto shortest_path_infinite_distance() { return numeric_limits::max(); } @@ -47,7 +47,7 @@ constexpr auto shortest_path_zero() { /** * @ingroup graph_algorithms - * @brief Intializes the distance values to shortest_path_invalid_distance(). + * @brief Intializes the distance values to shortest_path_infinite_distance(). * * @tparam Distances The range type of the distances. * @@ -55,7 +55,7 @@ constexpr auto shortest_path_zero() { */ template constexpr void init_shortest_paths(Distances& distances) { - ranges::fill(distances, shortest_path_invalid_distance>()); + ranges::fill(distances, shortest_path_infinite_distance>()); } /** diff --git a/include/graph/algorithm/dijkstra_shortest_paths.hpp b/include/graph/algorithm/dijkstra_shortest_paths.hpp index 99d71ef..a07518e 100644 --- a/include/graph/algorithm/dijkstra_shortest_paths.hpp +++ b/include/graph/algorithm/dijkstra_shortest_paths.hpp @@ -153,7 +153,7 @@ void dijkstra_shortest_paths( } constexpr auto zero = shortest_path_zero(); - constexpr auto infinite = shortest_path_invalid_distance(); + constexpr auto infinite = shortest_path_infinite_distance(); const id_type N = static_cast(num_vertices(g)); diff --git a/include/graph/algorithm/experimental/bfs_cmn.hpp b/include/graph/algorithm/experimental/bfs_cmn.hpp index d82cada..ee3ebb8 100644 --- a/include/graph/algorithm/experimental/bfs_cmn.hpp +++ b/include/graph/algorithm/experimental/bfs_cmn.hpp @@ -7,15 +7,15 @@ namespace std::graph::experimental { /** * @ingroup graph_algorithms - * @brief Returns a value to define an invalid distance used to initialize distance values + * @brief Returns a value to define an infinite distance used to initialize distance values * in the distance range before one of the shorts paths functions. * * @tparam DistanceValue The type of the distance. * - * @return A unique sentinal value to indicate that a value is invalid, or undefined. + * @return A value for an infinite distance. */ template -constexpr auto shortest_path_invalid_distance() { +constexpr auto shortest_path_infinite_distance() { return numeric_limits::max(); } @@ -34,7 +34,7 @@ constexpr auto shortest_path_zero() { /** * @ingroup graph_algorithms - * @brief Intializes the distance values to shortest_path_invalid_distance(). + * @brief Intializes the distance values to shortest_path_infinite_distance(). * * @tparam Distances The range type of the distances. * @@ -42,7 +42,7 @@ constexpr auto shortest_path_zero() { */ template constexpr void init_shortest_paths(Distances& distances) { - ranges::fill(distances, shortest_path_invalid_distance>()); + ranges::fill(distances, shortest_path_infinite_distance>()); } /** diff --git a/include/graph/algorithm/experimental/co_dijkstra.hpp b/include/graph/algorithm/experimental/co_dijkstra.hpp index af73f0e..67b5518 100644 --- a/include/graph/algorithm/experimental/co_dijkstra.hpp +++ b/include/graph/algorithm/experimental/co_dijkstra.hpp @@ -124,7 +124,7 @@ Generator> co_dijkstra( # endif constexpr auto zero = shortest_path_zero(); - constexpr auto infinite = shortest_path_invalid_distance(); + constexpr auto infinite = shortest_path_infinite_distance(); const id_type N(static_cast(num_vertices(g_))); diff --git a/include/graph/algorithm/experimental/visitor_dijkstra.hpp b/include/graph/algorithm/experimental/visitor_dijkstra.hpp index fcd75bb..dfb0869 100644 --- a/include/graph/algorithm/experimental/visitor_dijkstra.hpp +++ b/include/graph/algorithm/experimental/visitor_dijkstra.hpp @@ -188,7 +188,7 @@ void dijkstra_with_visitor( #endif constexpr auto zero = shortest_path_zero(); - constexpr auto infinite = shortest_path_invalid_distance(); + constexpr auto infinite = shortest_path_infinite_distance(); const id_type N(static_cast(num_vertices(g))); diff --git a/tests/bellman_shortest_paths_tests.cpp b/tests/bellman_shortest_paths_tests.cpp index 0693256..0b3aedb 100644 --- a/tests/bellman_shortest_paths_tests.cpp +++ b/tests/bellman_shortest_paths_tests.cpp @@ -53,7 +53,7 @@ using std::graph::edge_reference_t; using std::graph::views::vertexlist; -using std::graph::shortest_path_invalid_distance; +using std::graph::shortest_path_infinite_distance; using std::graph::init_shortest_paths; using std::graph::bellman_ford_shortest_paths; using std::graph::bellman_ford_shortest_distances; diff --git a/tests/co_dijkstra_tests.cpp b/tests/co_dijkstra_tests.cpp index db1917b..52cb02f 100644 --- a/tests/co_dijkstra_tests.cpp +++ b/tests/co_dijkstra_tests.cpp @@ -44,7 +44,7 @@ using std::graph::find_vertex_edge; using std::graph::experimental::co_dijkstra; using std::graph::experimental::bfs_vertex_value_t; using std::graph::experimental::bfs_edge_value_t; -using std::graph::experimental::shortest_path_invalid_distance; +using std::graph::experimental::shortest_path_infinite_distance; using std::graph::experimental::init_shortest_paths; using routes_vol_graph_traits = std::graph::container::vol_graph_traits; diff --git a/tests/dijkstra_shortest_paths_tests.cpp b/tests/dijkstra_shortest_paths_tests.cpp index 0940f36..8ae080a 100644 --- a/tests/dijkstra_shortest_paths_tests.cpp +++ b/tests/dijkstra_shortest_paths_tests.cpp @@ -53,7 +53,7 @@ using std::graph::edge_reference_t; using std::graph::views::vertexlist; -using std::graph::shortest_path_invalid_distance; +using std::graph::shortest_path_infinite_distance; using std::graph::init_shortest_paths; using std::graph::dijkstra_shortest_paths; using std::graph::dijkstra_shortest_distances; From 0290eda2614769686f302a21d1ffa29c8764d927 Mon Sep 17 00:00:00 2001 From: Phil Ratzloff Date: Mon, 2 Sep 2024 15:16:31 -0400 Subject: [PATCH 4/5] Move namespace std::graph --> graph This makes it usable as a stand-alone library without the pretension it will make it into the standard Add graph_using.hpp to explicitly bring common types & functions into the graph namespace --- ToDo.md | 4 +- benchmark/mm_bench_dijkstra.cpp | 4 +- benchmark/mm_load.hpp | 18 +- benchmark/mm_load_example.cpp | 2 +- benchmark/nwgraph_dijkstra.hpp | 2 +- docs/sphinx/conf.py | 4 +- docs/sphinx/graph-v2-api.rst | 28 +- example/CppCon2021/examples/bacon.cpp | 2 +- example/CppCon2021/examples/graphs.cpp | 10 +- example/CppCon2021/examples/imdb.cpp | 4 +- example/CppCon2021/examples/ospf.cpp | 26 +- example/CppCon2021/include/bfs_edge_range.hpp | 10 +- example/CppCon2021/include/dijkstra.hpp | 2 +- example/CppCon2021/include/utilities.hpp | 16 +- example/CppCon2022/germany_routes_example.cpp | 8 +- example/CppCon2022/graphviz_output.hpp | 12 +- example/CppCon2022/rr_adaptor.hpp | 12 +- example/PageRank/pagerank.hpp | 4 +- example/PageRank/pagerank_tests.cpp | 40 +-- .../algorithm/bellman_ford_shortest_paths.hpp | 150 +++++---- .../graph/algorithm/common_shortest_paths.hpp | 14 +- .../graph/algorithm/connected_components.hpp | 20 +- include/graph/algorithm/dijkstra_clrs.hpp | 41 ++- .../algorithm/dijkstra_shortest_paths.hpp | 139 +++++---- .../graph/algorithm/experimental/bfs_cmn.hpp | 10 +- .../graph/algorithm/experimental/co_bfs.hpp | 8 +- .../graph/algorithm/experimental/co_cmn.hpp | 12 +- .../algorithm/experimental/co_dijkstra.hpp | 74 +++-- .../experimental/visitor_dijkstra.hpp | 85 +++--- include/graph/algorithm/mis.hpp | 8 +- include/graph/algorithm/mst.hpp | 81 +++-- include/graph/algorithm/tc.hpp | 14 +- .../graph/algorithm/transitive_closure.hpp | 10 +- include/graph/container/compressed_graph.hpp | 279 +++++++++-------- include/graph/container/container_utility.hpp | 22 +- include/graph/container/dynamic_graph.hpp | 158 +++++----- include/graph/container/utility_edgelist.hpp | 8 +- include/graph/detail/co_generator.hpp | 4 +- include/graph/detail/graph_cpo.hpp | 287 +++++++++--------- include/graph/detail/graph_using.hpp | 92 ++++++ include/graph/edgelist.hpp | 26 +- include/graph/graph.hpp | 32 +- include/graph/graph_descriptors.hpp | 12 +- include/graph/graph_utility.hpp | 86 +++--- include/graph/views/breadth_first_search.hpp | 131 ++++---- include/graph/views/depth_first_search.hpp | 119 ++++---- include/graph/views/edgelist.hpp | 92 +++--- include/graph/views/incidence.hpp | 33 +- include/graph/views/neighbors.hpp | 34 +-- include/graph/views/vertexlist.hpp | 56 ++-- tests/bellman_shortest_paths_tests.cpp | 100 +++--- tests/bfs_tests.cpp | 92 +++--- tests/cc_tests.cpp | 44 +-- tests/co_bfs_tests.cpp | 62 ++-- tests/co_dijkstra_tests.cpp | 64 ++-- tests/csv_routes.hpp | 68 ++--- tests/csv_routes_csr_tests.cpp | 64 ++-- tests/csv_routes_dov_tests.cpp | 62 ++-- tests/csv_routes_vofl_tests.cpp | 62 ++-- tests/dfs_tests.cpp | 96 +++--- tests/dijkstra_shortest_paths_tests.cpp | 76 ++--- tests/edgelist_tests.cpp | 48 +-- tests/edgelist_view_tests.cpp | 100 +++--- tests/examples.cpp | 34 +-- tests/examples_tests.cpp | 2 +- tests/incidence_tests.cpp | 86 +++--- tests/mis_tests.cpp | 42 +-- tests/mst_tests.cpp | 84 ++--- tests/neighbors_tests.cpp | 88 +++--- tests/tc_tests.cpp | 6 +- tests/transitive_closure_tests.cpp | 28 +- tests/vertexlist_tests.cpp | 88 +++--- tests/visitor_dijkstra_tests.cpp | 60 ++-- 73 files changed, 1942 insertions(+), 1859 deletions(-) create mode 100644 include/graph/detail/graph_using.hpp diff --git a/ToDo.md b/ToDo.md index 1aed436..f5efd46 100644 --- a/ToDo.md +++ b/ToDo.md @@ -34,8 +34,8 @@ - [x] cancel() CPO? bfs, dfs: no, member only - [x] replace is_undirected_edge_v & undirected_incidence_graph with is_unordered_edge_v - [ ] Views - - [x] view classes should be in std::graph - - [x] view functions should be in std::graph::view + - [x] view classes should be in graph + - [x] view functions should be in graph::view - [ ] add range overloads to appropriate views (DFS, BFS, topo_sort, etc.) - [ ] vertexlist - [ ] Use VVF&& instead of const VVF& diff --git a/benchmark/mm_bench_dijkstra.cpp b/benchmark/mm_bench_dijkstra.cpp index 8be6405..7eab241 100644 --- a/benchmark/mm_bench_dijkstra.cpp +++ b/benchmark/mm_bench_dijkstra.cpp @@ -46,8 +46,8 @@ using std::endl; using fmt::print; using fmt::println; -using namespace std::graph; -using namespace std::graph::experimental; +using namespace graph; +using namespace graph::experimental; struct bench_results { size_t vertices_discovered = 0; diff --git a/benchmark/mm_load.hpp b/benchmark/mm_load.hpp index 494147d..f8d27bc 100644 --- a/benchmark/mm_load.hpp +++ b/benchmark/mm_load.hpp @@ -29,8 +29,8 @@ using std::convertible_to; using std::ranges::forward_range; using std::ranges::random_access_range; using std::ranges::range_value_t; -using std::graph::adjacency_list; -using std::graph::container::compressed_graph; +using graph::adjacency_list; +using graph::container::compressed_graph; namespace fmm = fast_matrix_market; template @@ -287,14 +287,14 @@ struct graph_stats { size_t max_degree = 0; size_t self_loops_removed = 0; - template + template graph_stats(const G& g, size_t self_loops = 0) - : vertex_count(std::graph::num_vertices(g)) - , edge_count(static_cast(std::graph::num_edges(g))) + : vertex_count(graph::num_vertices(g)) + , edge_count(static_cast(graph::num_edges(g))) , self_loops_removed(self_loops) { - for (auto&& u : std::graph::vertices(g)) { - min_degree = std::min(min_degree, size(std::graph::edges(g, u))); - max_degree = std::max(max_degree, size(std::graph::edges(g, u))); + for (auto&& u : graph::vertices(g)) { + min_degree = std::min(min_degree, size(graph::edges(g, u))); + max_degree = std::max(max_degree, size(graph::edges(g, u))); } } }; @@ -353,7 +353,7 @@ template ; - using edge_desc = std::graph::copyable_edge_t; + using edge_desc = graph::copyable_edge_t; auto edge_proj = [](const zip_value& val) -> edge_desc { return edge_desc{std::get<0>(val), std::get<1>(val), std::get<2>(val)}; }; diff --git a/benchmark/mm_load_example.cpp b/benchmark/mm_load_example.cpp index 696c4c6..7e538fb 100644 --- a/benchmark/mm_load_example.cpp +++ b/benchmark/mm_load_example.cpp @@ -6,7 +6,7 @@ using std::tuple; using std::vector; -using namespace std::graph::container; +using namespace graph::container; // Dataset: gap_twitter, symmetry_type::general, 1,468,364,884 rows // Deb/Rel parallel_ok num_threads Read Rows/Sec LoadSimple Edges/Sec LoadCompressed Edges/Sec diff --git a/benchmark/nwgraph_dijkstra.hpp b/benchmark/nwgraph_dijkstra.hpp index 5a22ed5..3478126 100644 --- a/benchmark/nwgraph_dijkstra.hpp +++ b/benchmark/nwgraph_dijkstra.hpp @@ -5,7 +5,7 @@ template static auto nwgraph_dijkstra( Graph&& graph, const Sources& sources, Weight weight = [](auto& e) -> auto& { return std::get<1>(e); }) { - using namespace std::graph; + using namespace graph; using vertex_id_type = vertex_id_t; using distance_t = int64_t; diff --git a/docs/sphinx/conf.py b/docs/sphinx/conf.py index 2096211..f49f120 100644 --- a/docs/sphinx/conf.py +++ b/docs/sphinx/conf.py @@ -92,7 +92,7 @@ #html_theme = 'sphinx13' html_theme = 'sphinx_rtd_theme' # html_theme = 'sphinx_book_theme' -html_title = "std::graph Documentation" +html_title = "graph Documentation" # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, @@ -114,7 +114,7 @@ # -- Options for the C++ Domain ---------------------------------------------- -cpp_index_common_prefix = ['std::', 'std::graph::'] +cpp_index_common_prefix = ['std::', 'graph::'] # -- Options for Breathe ----------------------------------------------------- diff --git a/docs/sphinx/graph-v2-api.rst b/docs/sphinx/graph-v2-api.rst index b33e8ec..0c052ec 100644 --- a/docs/sphinx/graph-v2-api.rst +++ b/docs/sphinx/graph-v2-api.rst @@ -8,25 +8,25 @@ Graph-V2 API Reference Concepts -------- -.. doxygenconcept:: std::graph::vertex_range +.. doxygenconcept:: graph::vertex_range -.. doxygenconcept:: std::graph::targeted_edge +.. doxygenconcept:: graph::targeted_edge -.. doxygenconcept:: std::graph::sourced_edge +.. doxygenconcept:: graph::sourced_edge -.. doxygenconcept:: std::graph::adjacency_list +.. doxygenconcept:: graph::adjacency_list -.. doxygenconcept:: std::graph::sourced_adjacency_list +.. doxygenconcept:: graph::sourced_adjacency_list -.. doxygenconcept:: std::graph::has_degree +.. doxygenconcept:: graph::has_degree -.. doxygenconcept:: std::graph::has_find_vertex +.. doxygenconcept:: graph::has_find_vertex -.. doxygenconcept:: std::graph::has_contains_edge +.. doxygenconcept:: graph::has_contains_edge -.. doxygenconcept:: std::graph::ordered_edge +.. doxygenconcept:: graph::ordered_edge -.. doxygenconcept:: std::graph::unordered_edge +.. doxygenconcept:: graph::unordered_edge -------------------------------- @@ -37,13 +37,13 @@ Concepts Algorithms ---------- -.. doxygenfunction:: std::graph::dijkstra_shortest_distances +.. doxygenfunction:: graph::dijkstra_shortest_distances -.. doxygenfunction:: std::graph::dijkstra_shortest_paths +.. doxygenfunction:: graph::dijkstra_shortest_paths -.. doxygenfunction:: std::graph::bellman_ford_shortest_distances +.. doxygenfunction:: graph::bellman_ford_shortest_distances -.. doxygenfunction:: std::graph::bellman_ford_shortest_paths +.. doxygenfunction:: graph::bellman_ford_shortest_paths -------------------------------- diff --git a/example/CppCon2021/examples/bacon.cpp b/example/CppCon2021/examples/bacon.cpp index 50bf8eb..e83a66f 100644 --- a/example/CppCon2021/examples/bacon.cpp +++ b/example/CppCon2021/examples/bacon.cpp @@ -14,7 +14,7 @@ int main() { std::vector bacon_number(size(actors)); // for (auto&& [u, v] : bfs_edge_range(costars, 1)) { - for (auto&& [u, v, uv] : std::graph::views::sourced_edges_breadth_first_search(costars, 1)) { + for (auto&& [u, v, uv] : graph::views::sourced_edges_breadth_first_search(costars, 1)) { bacon_number[v] = bacon_number[u] + 1; } diff --git a/example/CppCon2021/examples/graphs.cpp b/example/CppCon2021/examples/graphs.cpp index c50115a..ba7f36f 100644 --- a/example/CppCon2021/examples/graphs.cpp +++ b/example/CppCon2021/examples/graphs.cpp @@ -39,7 +39,7 @@ int main() { */ std::vector> G(34); push_back_plain_fill(karate_index_edge_list, G, false, 0); - static_assert(std::graph::adjacency_list); + static_assert(graph::adjacency_list); std::vector>> H(34); push_back_plain_fill(karate_index_edge_list, H, false, 0); @@ -79,16 +79,16 @@ int main() { auto s = make_property_graph(spice_vertices, spice_edges_values); //bfs_edge_range(n, 1); - std::graph::views::edges_breadth_first_search(n, 1); + graph::views::edges_breadth_first_search(n, 1); //bfs_edge_range(o, 1); - std::graph::views::edges_breadth_first_search(o, 1); + graph::views::edges_breadth_first_search(o, 1); //bfs_edge_range(p, 1); - std::graph::views::edges_breadth_first_search(p, 1); + graph::views::edges_breadth_first_search(p, 1); //bfs_edge_range(q, 0); - std::graph::views::edges_breadth_first_search(q, 0); + graph::views::edges_breadth_first_search(q, 0); return 0; } diff --git a/example/CppCon2021/examples/imdb.cpp b/example/CppCon2021/examples/imdb.cpp index c753c0c..bedee14 100644 --- a/example/CppCon2021/examples/imdb.cpp +++ b/example/CppCon2021/examples/imdb.cpp @@ -44,8 +44,8 @@ int main() { std::vector together_in(L.size()); //for (auto&& [u, v, k] : bfs_edge_range(L, kevin_bacon)) { - auto kprop = [&L](auto&& e) { return std::get<1>(std::graph::edge_value(L, e)); }; - for (auto&& [u, v, uv, k] : std::graph::views::sourced_edges_breadth_first_search(L, kevin_bacon, kprop)) { + auto kprop = [&L](auto&& e) { return std::get<1>(graph::edge_value(L, e)); }; + for (auto&& [u, v, uv, k] : graph::views::sourced_edges_breadth_first_search(L, kevin_bacon, kprop)) { distance[v] = distance[u] + 1; parents[v] = u; together_in[v] = k; diff --git a/example/CppCon2021/examples/ospf.cpp b/example/CppCon2021/examples/ospf.cpp index 071c00c..61ae19c 100644 --- a/example/CppCon2021/examples/ospf.cpp +++ b/example/CppCon2021/examples/ospf.cpp @@ -16,13 +16,13 @@ int main() { - static_assert(std::graph::adjacency_list); + static_assert(graph::adjacency_list); //auto d = dijkstra(ospf_index_adjacency_list, 5UL); std::vector d(size(ospf_index_adjacency_list)); std::vector p(size(ospf_index_adjacency_list)); - std::graph::init_shortest_paths(d, p); - std::graph::dijkstra_shortest_paths(ospf_index_adjacency_list, 5UL, d, p, [](auto&& ee) { return std::get<1>(ee); }); + graph::init_shortest_paths(d, p); + graph::dijkstra_shortest_paths(ospf_index_adjacency_list, 5UL, d, p, [](auto&& ee) { return std::get<1>(ee); }); std::cout << "----------------" << std::endl; std::cout << "Contents of ospf_index_adjacency_list (the correct answer)" << std::endl; @@ -42,13 +42,13 @@ int main() { auto I = make_property_graph>>>(ospf_vertices, ospf_edges, true); - static_assert(std::graph::adjacency_list); + static_assert(graph::adjacency_list); //auto e = dijkstra(G, 5UL, [](auto&& ee) { return std::get<1>(ee); }); - p.resize(std::graph::num_vertices(G)); - std::vector e(std::graph::num_vertices(G)); - std::graph::init_shortest_paths(e, p); - std::graph::dijkstra_shortest_paths(G, 5UL, e, p, [](auto&& ee) { return std::get<1>(ee); }); + p.resize(graph::num_vertices(G)); + std::vector e(graph::num_vertices(G)); + graph::init_shortest_paths(e, p); + graph::dijkstra_shortest_paths(G, 5UL, e, p, [](auto&& ee) { return std::get<1>(ee); }); for (size_t i = 0; i < size(ospf_vertices); ++i) { std::cout << std::setw(6) << ospf_vertices[i] << std::setw(6) << e[i] << std::endl; @@ -59,13 +59,13 @@ int main() { auto J = make_index_graph(ospf_vertices, ospf_edges, true); - //std::graph::dijkstra_shortest_paths(G, 5UL, e, p, w); + //graph::dijkstra_shortest_paths(G, 5UL, e, p, w); //auto f = dijkstra(J, 5, [](auto&& ee) { return std::get<2>(ospf_edges[std::get<1>(ee)]); }); - p.resize(std::graph::num_vertices(G)); - std::vector f(std::graph::num_vertices(G)); - std::graph::init_shortest_paths(f, p); - std::graph::dijkstra_shortest_paths(J, 5UL, f, p, [](auto&& ee) { return std::get<2>(ospf_edges[std::get<1>(ee)]); }); + p.resize(graph::num_vertices(G)); + std::vector f(graph::num_vertices(G)); + graph::init_shortest_paths(f, p); + graph::dijkstra_shortest_paths(J, 5UL, f, p, [](auto&& ee) { return std::get<2>(ospf_edges[std::get<1>(ee)]); }); for (size_t i = 0; i < size(ospf_vertices); ++i) { std::cout << std::setw(6) << ospf_vertices[i] << std::setw(6) << e[i] << std::endl; diff --git a/example/CppCon2021/include/bfs_edge_range.hpp b/example/CppCon2021/include/bfs_edge_range.hpp index 0640d9b..9d9cd1c 100644 --- a/example/CppCon2021/include/bfs_edge_range.hpp +++ b/example/CppCon2021/include/bfs_edge_range.hpp @@ -13,11 +13,11 @@ enum three_colors { black, white, grey }; -template >> -requires std::graph::adjacency_list +template >> +requires graph::adjacency_list class bfs_edge_range { private: - using vertex_id_type = std::graph::vertex_id_t; + using vertex_id_type = graph::vertex_id_t; public: explicit bfs_edge_range(Graph& graph, vertex_id_type seed = 0) : the_graph_(graph), visited_(graph.size(), false) { @@ -39,7 +39,7 @@ class bfs_edge_range { typename Graph::iterator G; vertex_id_type v_; //typename inner_range_t::iterator u_begin, u_end; - std::graph::vertex_iterator_t u_begin, u_end; + graph::vertex_iterator_t u_begin, u_end; public: bfs_edge_range_iterator(bfs_edge_range& range) @@ -106,7 +106,7 @@ class bfs_edge_range { }; template -requires std::graph::adjacency_list +requires graph::adjacency_list class bfs_edge_range_2 { private: using vertex_id_type = typename Graph::vertex_id_type; diff --git a/example/CppCon2021/include/dijkstra.hpp b/example/CppCon2021/include/dijkstra.hpp index 01e02fe..bf920ae 100644 --- a/example/CppCon2021/include/dijkstra.hpp +++ b/example/CppCon2021/include/dijkstra.hpp @@ -21,7 +21,7 @@ #include template > WeightFunction = + invocable> WeightFunction = std::function>(const inner_value_t&)>> auto dijkstra( const Graph& graph, vertex_id_t source, WeightFunction weights = [](const inner_value_t& e) { diff --git a/example/CppCon2021/include/utilities.hpp b/example/CppCon2021/include/utilities.hpp index 40eb979..fc66e8f 100644 --- a/example/CppCon2021/include/utilities.hpp +++ b/example/CppCon2021/include/utilities.hpp @@ -151,7 +151,7 @@ auto make_index_edges(M& map, const E& edges) { */ template >> + graph::basic_adjacency_list Graph = std::vector>> auto make_plain_graph(const V& vertices, const E& edges, bool directed = true, size_t idx = 0) { auto vertex_map = make_index_map(vertices); auto index_edges = make_plain_edges(vertex_map, edges); @@ -167,7 +167,7 @@ auto make_plain_graph(const V& vertices, const E& edges, bool directed = true, s */ template >>> + graph::basic_adjacency_list Graph = std::vector>>> auto make_index_graph(const V& vertices, const E& edges, bool directed = true, size_t idx = 0) { auto vertex_map = make_index_map(vertices); @@ -185,7 +185,7 @@ auto make_index_graph(const V& vertices, const E& edges, bool directed = true, s */ template >> auto make_property_graph(const V& vertices, const E& edges, bool directed = true, size_t idx = 0) { @@ -226,7 +226,7 @@ auto data_to_graph_edge_list(const V& left_vertices, const V& right_vertices, co template >> auto make_plain_bipartite_graph(const V1& left_vertices, const V2& right_vertices, const E& edges, size_t idx = 0) { @@ -273,7 +273,7 @@ auto make_bipartite_graph(const V& left_vertices, const V& right_vertices, const template >> auto make_bipartite_graphs(const V& left_vertices, const V& right_vertices, const E& edges) { @@ -295,9 +295,9 @@ auto join(const Graph1& G, const Graph2& H) { for (size_t i = 0; i < H.size(); ++i) { for (auto&& k : H[i]) { - for (auto&& j : G[std::graph::target_id(H, k)]) { - if (std::graph::target_id(G, j) != i) { - s_overlap.push_back({i, std::graph::target_id(G, j), std::graph::target_id(H, k)}); + for (auto&& j : G[graph::target_id(H, k)]) { + if (graph::target_id(G, j) != i) { + s_overlap.push_back({i, graph::target_id(G, j), graph::target_id(H, k)}); } } } diff --git a/example/CppCon2022/germany_routes_example.cpp b/example/CppCon2022/germany_routes_example.cpp index 286d018..afcc49a 100644 --- a/example/CppCon2022/germany_routes_example.cpp +++ b/example/CppCon2022/germany_routes_example.cpp @@ -12,9 +12,9 @@ #include using namespace std::ranges; -using namespace std::graph; -using namespace std::graph::container; -using namespace std::graph::views; +using namespace graph; +using namespace graph::container; +using namespace graph::views; using namespace std::literals; using std::cout; @@ -105,7 +105,7 @@ TEST_CASE("Germany Routes Presentation", "[presentation][germany][routes][shorte cout << "Traverse the vertices & outgoing edges" << endl; for (auto&& [uid, u] : vertexlist(g)) { // [id,vertex&] cout << city_id(g, uid) << endl; // city name [id] - for (auto&& [vid, uv] : std::graph::views::incidence(g, uid)) { // [target_id,edge&] + for (auto&& [vid, uv] : graph::views::incidence(g, uid)) { // [target_id,edge&] cout << " --> " << city_id(g, vid) << endl; // "--> "target city" [target_id] } diff --git a/example/CppCon2022/graphviz_output.hpp b/example/CppCon2022/graphviz_output.hpp index 68b8a8c..b70df1b 100644 --- a/example/CppCon2022/graphviz_output.hpp +++ b/example/CppCon2022/graphviz_output.hpp @@ -31,7 +31,7 @@ void output_routes_graphviz( const directedness dir, std::string_view bgcolor = std::string_view() // "transparent" or see http://graphviz.org/docs/attr-types/color/ ) { - using namespace std::graph; + using namespace graph; using namespace std::literals; std::string fn(filename); std::ofstream of(fn); @@ -74,7 +74,7 @@ void output_routes_graphviz_adjlist( std::string_view filename, std::string_view bgcolor = std::string_view() // "transparent" or see http://graphviz.org/docs/attr-types/color/ ) { - using namespace std::graph; + using namespace graph; using namespace std::literals; std::string fn(filename); std::ofstream of(fn); @@ -110,11 +110,11 @@ template void output_routes_graphviz_dfs_vertices( G& g, std::string_view filename, - std::graph::vertex_id_t seed, + graph::vertex_id_t seed, std::string_view bgcolor = std::string_view() // "transparent" or see http://graphviz.org/docs/attr-types/color/ ) { - using namespace std::graph; - using namespace std::graph::views; + using namespace graph; + using namespace graph::views; using namespace std::literals; std::string fn(filename); std::ofstream of(fn); @@ -141,7 +141,7 @@ void output_routes_graphviz_dfs_vertices( visited[seed] = true; // output descendents - for (auto&& [uid, vid, uv] : std::graph::views::sourced_edges_depth_first_search(g, seed)) { + for (auto&& [uid, vid, uv] : graph::views::sourced_edges_depth_first_search(g, seed)) { // Output newly discovered vertex if (!visited[vid]) { //of << " " << vid << " [shape=Mrecord, label=\"{" << vid << "|" << vertex_value(g, *find_vertex(g, uid)) diff --git a/example/CppCon2022/rr_adaptor.hpp b/example/CppCon2022/rr_adaptor.hpp index 159d0b7..b310a8d 100644 --- a/example/CppCon2022/rr_adaptor.hpp +++ b/example/CppCon2022/rr_adaptor.hpp @@ -105,8 +105,8 @@ class rr_adaptor { using edge_type = std::ranges::range_value_t; // using vertex_id_type = std::remove_cv_t>>; using edge_value_type = std::conditional_t<(std::tuple_size_v> <= 1), - void, - std::tuple_element_t<1, to_tuple_t>>; + void, + std::tuple_element_t<1, to_tuple_t>>; using vertex_value_type = std::ranges::range_value_t; public: @@ -148,9 +148,9 @@ class rr_adaptor { } void push(edges_range& edges, const edge_type& val) { - if constexpr (std::graph::container::has_push_back) + if constexpr (graph::container::has_push_back) edges.push_back(val); - else if constexpr (std::graph::container::has_push_front) + else if constexpr (graph::container::has_push_front) edges.push_front(val); } @@ -364,9 +364,9 @@ class rr_adaptor2 { } void push(edges_range& edges, const edge_type& val) { - if constexpr (std::graph::container::has_push_back) + if constexpr (graph::container::has_push_back) edges.push_back(val); - else if constexpr (std::graph::container::has_push_front) + else if constexpr (graph::container::has_push_front) edges.push_front(val); } diff --git a/example/PageRank/pagerank.hpp b/example/PageRank/pagerank.hpp index 6af40e1..83ff96a 100644 --- a/example/PageRank/pagerank.hpp +++ b/example/PageRank/pagerank.hpp @@ -22,7 +22,7 @@ #include #include -namespace std::graph { +namespace graph { /** * @brief Requirements for an edge value function: evf(uv) -> value. @@ -117,6 +117,6 @@ void pagerank( } } -} // namespace std::graph +} // namespace graph #endif // GRAPH_PAGERANK_HPP diff --git a/example/PageRank/pagerank_tests.cpp b/example/PageRank/pagerank_tests.cpp index 2443393..20a7932 100644 --- a/example/PageRank/pagerank_tests.cpp +++ b/example/PageRank/pagerank_tests.cpp @@ -19,24 +19,24 @@ using std::cout; using std::endl; -using std::graph::vertex_t; -using std::graph::vertex_id_t; -using std::graph::vertex_reference_t; -using std::graph::vertex_iterator_t; -using std::graph::vertex_edge_range_t; -using std::graph::edge_t; - -using std::graph::vertices; -using std::graph::edges; -using std::graph::vertex_value; -using std::graph::target_id; -using std::graph::target; -using std::graph::edge_value; -using std::graph::find_vertex; -using std::graph::vertex_id; - -using routes_volf_graph_traits = std::graph::container::vofl_graph_traits; -using routes_volf_graph_type = std::graph::container::dynamic_adjacency_graph; +using graph::vertex_t; +using graph::vertex_id_t; +using graph::vertex_reference_t; +using graph::vertex_iterator_t; +using graph::vertex_edge_range_t; +using graph::edge_t; + +using graph::vertices; +using graph::edges; +using graph::vertex_value; +using graph::target_id; +using graph::target; +using graph::edge_value; +using graph::find_vertex; +using graph::vertex_id; + +using routes_volf_graph_traits = graph::container::vofl_graph_traits; +using routes_volf_graph_type = graph::container::dynamic_adjacency_graph; TEST_CASE("PageRank", "[pagerank]") { init_console(); @@ -44,13 +44,13 @@ TEST_CASE("PageRank", "[pagerank]") { auto&& g = load_ordered_graph(TEST_DATA_ROOT_DIR "germany_routes.csv", name_order_policy::source_order_found); std::vector page_rank(size(vertices(g))); - std::graph::pagerank(g, page_rank, 0.85, 1e-4, 10); + graph::pagerank(g, page_rank, 0.85, 1e-4, 10); std::vector answer = {0.051086017487729, 0.065561667371485, 0.106818581147795, 0.141889899564636, 0.065561667371485, 0.078952299317762, 0.065561667371485, 0.078952299317762, 0.260972178563747, 0.084643725419772}; - for (auto&& [uid, u] : std::graph::views::vertexlist(g)) { + for (auto&& [uid, u] : graph::views::vertexlist(g)) { REQUIRE(page_rank[uid] == Approx(answer[uid]).epsilon(1e-4)); } } \ No newline at end of file diff --git a/include/graph/algorithm/bellman_ford_shortest_paths.hpp b/include/graph/algorithm/bellman_ford_shortest_paths.hpp index b0017bf..28ce906 100644 --- a/include/graph/algorithm/bellman_ford_shortest_paths.hpp +++ b/include/graph/algorithm/bellman_ford_shortest_paths.hpp @@ -19,12 +19,13 @@ #include #include +#include #include #ifndef GRAPH_BELLMAN_SHORTEST_PATHS_HPP # define GRAPH_BELLMAN_SHORTEST_PATHS_HPP -namespace std::graph { +namespace graph { template class bellman_visitor_base { @@ -83,12 +84,12 @@ concept bellman_visitor = //is_arithmetic && * then there will be no vertex id defined. * @param out_cycle The output iterator that the vertex ids in the cycle are output to. */ -template +template requires output_iterator> -void find_negative_cycle(G& g, - const Predecessors& predecessor, - const optional>& cycle_vertex_id, - OutputIterator out_cycle) { +void find_negative_cycle(G& g, + const Predecessors& predecessor, + const std::optional>& cycle_vertex_id, + OutputIterator out_cycle) { // Does a negative weight cycle exist? if (cycle_vertex_id.has_value()) { vertex_id_t uid = cycle_vertex_id.value(); @@ -132,35 +133,34 @@ void find_negative_cycle(G& g, * If an edge was not minimized, the on_edge_not_minimized event is called and a vertex id * in the negative weight cycle is returned. */ -template (edge_reference_t)>, +template (edge_reference_t)>, class Visitor = bellman_visitor_base, - class Compare = less>, - class Combine = plus>> -requires convertible_to, vertex_id_t> && // - is_arithmetic_v> && // - convertible_to, ranges::range_value_t> && // - ranges::sized_range && // - ranges::sized_range && // - basic_edge_weight_function, Compare, Combine> + class Compare = less>, + class Combine = plus>> +requires convertible_to, vertex_id_t> && // + is_arithmetic_v> && // + convertible_to, range_value_t> && // + sized_range && // + sized_range && // + basic_edge_weight_function, Compare, Combine> // && bellman_visitor -[[nodiscard]] optional> bellman_ford_shortest_paths( +[[nodiscard]] std::optional> bellman_ford_shortest_paths( G& g, const Sources& sources, Distances& distances, Predecessors& predecessor, - WF&& weight = - [](edge_reference_t uv) { return ranges::range_value_t(1); }, // default weight(uv) -> 1 + WF&& weight = [](edge_reference_t uv) { return range_value_t(1); }, // default weight(uv) -> 1 Visitor&& visitor = bellman_visitor_base(), - Compare&& compare = less>(), - Combine&& combine = plus>()) { + Compare&& compare = less>(), + Combine&& combine = plus>()) { using id_type = vertex_id_t; - using DistanceValue = ranges::range_value_t; + using DistanceValue = range_value_t; using weight_type = invoke_result_t>; - using return_type = optional>; + using return_type = std::optional>; // relxing the target is the function of reducing the distance from the source to the target auto relax_target = [&g, &predecessor, &distances, &compare, &combine] // @@ -180,14 +180,14 @@ requires convertible_to, vertex_id_t> && }; if (size(distances) < size(vertices(g))) { - throw out_of_range( + throw std::out_of_range( fmt::format("bellman_ford_shortest_paths: size of distances is {} is less than the number of vertices {}", size(distances), size(vertices(g)))); } if constexpr (!is_same_v) { if (size(predecessor) < size(vertices(g))) { - throw out_of_range( + throw std::out_of_range( fmt::format("bellman_ford_shortest_paths: size of predecessor is {} is less than the number of vertices {}", size(predecessor), size(vertices(g)))); } @@ -201,7 +201,8 @@ requires convertible_to, vertex_id_t> && // Seed the queue with the initial vertice(s) for (auto&& source : sources) { if (source >= N || source < 0) { - throw out_of_range(fmt::format("bellman_ford_shortest_paths: source vertex id '{}' is out of range", source)); + throw std::out_of_range( + fmt::format("bellman_ford_shortest_paths: source vertex id '{}' is out of range", source)); } distances[static_cast(source)] = zero; // mark source as discovered } @@ -236,30 +237,29 @@ requires convertible_to, vertex_id_t> && return return_type(); } -template (edge_reference_t)>, +template (edge_reference_t)>, class Visitor = bellman_visitor_base, - class Compare = less>, - class Combine = plus>> -requires is_arithmetic_v> && // - convertible_to, ranges::range_value_t> && // - ranges::sized_range && // - ranges::sized_range && // - basic_edge_weight_function, Compare, Combine> + class Compare = less>, + class Combine = plus>> +requires is_arithmetic_v> && // + convertible_to, range_value_t> && // + sized_range && // + sized_range && // + basic_edge_weight_function, Compare, Combine> // && bellman_visitor -[[nodiscard]] optional> bellman_ford_shortest_paths( +[[nodiscard]] std::optional> bellman_ford_shortest_paths( G& g, const vertex_id_t source, Distances& distances, Predecessors& predecessor, - WF&& weight = - [](edge_reference_t uv) { return ranges::range_value_t(1); }, // default weight(uv) -> 1 + WF&& weight = [](edge_reference_t uv) { return range_value_t(1); }, // default weight(uv) -> 1 Visitor&& visitor = bellman_visitor_base(), - Compare&& compare = less>(), - Combine&& combine = plus>()) { - return bellman_ford_shortest_paths(g, ranges::subrange(&source, (&source + 1)), distances, predecessor, weight, + Compare&& compare = less>(), + Combine&& combine = plus>()) { + return bellman_ford_shortest_paths(g, subrange(&source, (&source + 1)), distances, predecessor, weight, forward(visitor), forward(compare), forward(combine)); } @@ -294,56 +294,54 @@ requires is_arithmetic_v> && * If an edge was not minimized, the on_edge_not_minimized event is called and a vertex id * in the negative weight cycle is returned. */ -template (edge_reference_t)>, +template (edge_reference_t)>, class Visitor = bellman_visitor_base, - class Compare = less>, - class Combine = plus>> -requires convertible_to, vertex_id_t> && // - is_arithmetic_v> && // - ranges::sized_range && // - basic_edge_weight_function, Compare, Combine> + class Compare = less>, + class Combine = plus>> +requires convertible_to, vertex_id_t> && // + is_arithmetic_v> && // + sized_range && // + basic_edge_weight_function, Compare, Combine> //&& bellman_visitor -[[nodiscard]] optional> bellman_ford_shortest_distances( +[[nodiscard]] std::optional> bellman_ford_shortest_distances( G& g, const Sources& sources, Distances& distances, - WF&& weight = - [](edge_reference_t uv) { return ranges::range_value_t(1); }, // default weight(uv) -> 1 + WF&& weight = [](edge_reference_t uv) { return range_value_t(1); }, // default weight(uv) -> 1 Visitor&& visitor = bellman_visitor_base(), - Compare&& compare = less>(), - Combine&& combine = plus>()) { + Compare&& compare = less>(), + Combine&& combine = plus>()) { return bellman_ford_shortest_paths(g, sources, distances, _null_predecessors, forward(weight), std::forward(visitor), std::forward(compare), std::forward(combine)); } -template (edge_reference_t)>, +template (edge_reference_t)>, class Visitor = bellman_visitor_base, - class Compare = less>, - class Combine = plus>> -requires is_arithmetic_v> && // - ranges::sized_range && // - basic_edge_weight_function, Compare, Combine> + class Compare = less>, + class Combine = plus>> +requires is_arithmetic_v> && // + sized_range && // + basic_edge_weight_function, Compare, Combine> //&& bellman_visitor -[[nodiscard]] optional> bellman_ford_shortest_distances( +[[nodiscard]] std::optional> bellman_ford_shortest_distances( G& g, const vertex_id_t source, Distances& distances, - WF&& weight = - [](edge_reference_t uv) { return ranges::range_value_t(1); }, // default weight(uv) -> 1 + WF&& weight = [](edge_reference_t uv) { return range_value_t(1); }, // default weight(uv) -> 1 Visitor&& visitor = bellman_visitor_base(), - Compare&& compare = less>(), - Combine&& combine = plus>()) { - return bellman_ford_shortest_paths(g, ranges::subrange(&source, (&source + 1)), distances, _null_predecessors, + Compare&& compare = less>(), + Combine&& combine = plus>()) { + return bellman_ford_shortest_paths(g, subrange(&source, (&source + 1)), distances, _null_predecessors, forward(weight), std::forward(visitor), std::forward(compare), std::forward(combine)); } -} // namespace std::graph +} // namespace graph #endif // GRAPH_BELLMAN_SHORTEST_PATHS_HPP diff --git a/include/graph/algorithm/common_shortest_paths.hpp b/include/graph/algorithm/common_shortest_paths.hpp index 2a8dee7..0521ef9 100644 --- a/include/graph/algorithm/common_shortest_paths.hpp +++ b/include/graph/algorithm/common_shortest_paths.hpp @@ -6,12 +6,12 @@ #ifndef GRAPH_COMMON_SHORTEST_PATHS_HPP # define GRAPH_COMMON_SHORTEST_PATHS_HPP -namespace std::graph { +namespace graph { template // For exposition only concept basic_edge_weight_function = // e.g. weight(uv) - is_arithmetic_v && strict_weak_order && - assignable_from, - invoke_result_t>>>; + is_arithmetic_v && std::strict_weak_order && + std::assignable_from, + invoke_result_t>>>; template // For exposition only concept edge_weight_function = // e.g. weight(uv) @@ -29,7 +29,7 @@ concept edge_weight_function = // e.g. weight(uv) */ template constexpr auto shortest_path_infinite_distance() { - return numeric_limits::max(); + return std::numeric_limits::max(); } /** @@ -55,7 +55,7 @@ constexpr auto shortest_path_zero() { */ template constexpr void init_shortest_paths(Distances& distances) { - ranges::fill(distances, shortest_path_infinite_distance>()); + std::ranges::fill(distances, shortest_path_infinite_distance>()); } /** @@ -103,6 +103,6 @@ class _null_range_type : public std::vector { inline static _null_range_type _null_predecessors; -} // namespace std::graph +} // namespace graph #endif // GRAPH_COMMON_SHORTEST_PATHS_HPP diff --git a/include/graph/algorithm/connected_components.hpp b/include/graph/algorithm/connected_components.hpp index bbc45ad..ee196bd 100644 --- a/include/graph/algorithm/connected_components.hpp +++ b/include/graph/algorithm/connected_components.hpp @@ -23,12 +23,12 @@ #ifndef GRAPH_CC_HPP # define GRAPH_CC_HPP -namespace std::graph { +namespace graph { -template -requires ranges::random_access_range> && integral> +template +requires random_access_range> && integral> void kosaraju(G&& g, // graph GT&& g_t, // graph transpose Component& component // out: strongly connected component assignment @@ -47,7 +47,7 @@ void kosaraju(G&& g, // graph visited[uid] = true; std::stack> active; active.push(uid); - auto dfs = std::graph::views::sourced_edges_depth_first_search(g, uid); + auto dfs = graph::views::sourced_edges_depth_first_search(g, uid); for (auto&& [vid, wid, vw] : dfs) { while (vid != active.top()) { order.push_back(active.top()); @@ -84,9 +84,9 @@ void kosaraju(G&& g, // graph } } -template -requires ranges::random_access_range> && integral> +template +requires random_access_range> && integral> void connected_components(G&& g, // graph Component& component // out: connected component assignment ) { @@ -111,6 +111,6 @@ void connected_components(G&& g, // graph } } -} // namespace std::graph +} // namespace graph #endif //GRAPH_CC_HPP diff --git a/include/graph/algorithm/dijkstra_clrs.hpp b/include/graph/algorithm/dijkstra_clrs.hpp index 5ec1445..6d0cc52 100644 --- a/include/graph/algorithm/dijkstra_clrs.hpp +++ b/include/graph/algorithm/dijkstra_clrs.hpp @@ -5,11 +5,11 @@ #include #include -namespace std::graph { +namespace graph { template concept edge_weight_function = // e.g. weight(uv) - copy_constructible && is_arithmetic_v>>; + std::copy_constructible && is_arithmetic_v>>; //edge_weight_function && @@ -18,18 +18,14 @@ concept edge_weight_function = // e.g. weight(uv) template concept basic_edge_weight_function2 = // e.g. weight(uv) - is_arithmetic_v> && - strict_weak_order, ranges::range_value_t> && - assignable_from, invoke_result_t>>>; + is_arithmetic_v> && + std::strict_weak_order, range_value_t> && + std::assignable_from, invoke_result_t>>>; template concept edge_weight_function2 = // e.g. weight(uv) is_arithmetic_v>> && - basic_edge_weight_function2>, - plus>>; + basic_edge_weight_function2>, plus>>; class null_range_type : public std::vector { @@ -84,22 +80,21 @@ constexpr auto print_types(Ts...) { * The edge weight function must not throw an exception. * The edge weight function must not modify the graph, the edge, or the vertex (nor any of their associated data). */ -template (edge_reference_t)>> -requires ranges::random_access_range> && // - integral> && // - is_arithmetic_v> && // - convertible_to, ranges::range_value_t> && // +template (edge_reference_t)>> +requires random_access_range> && // + integral> && // + is_arithmetic_v> && // + convertible_to, range_value_t> && // edge_weight_function void dijkstra_clrs( G&& g, // graph vertex_id_t seed, // starting vertex_id Distance& distance, // out: distance[uid] of uid from seed Predecessor& predecessor, // out: predecessor[uid] of uid in path - WF&& weight = - [](edge_reference_t uv) { return ranges::range_value_t(1); }) // default weight(uv) -> 1 + WF&& weight = [](edge_reference_t uv) { return range_value_t(1); }) // default weight(uv) -> 1 { using id_type = vertex_id_t; using weight_type = invoke_result_t>; @@ -109,7 +104,7 @@ void dijkstra_clrs( size_t N(size(vertices(g))); // Question(Andrew): Do we want a num_vertices(g) CPO? assert(seed < N && seed >= 0); - std::ranges::fill(distance, numeric_limits::max()); + std::ranges::fill(distance, std::numeric_limits::max()); distance[seed] = 0; struct weighted_vertex { @@ -120,7 +115,7 @@ void dijkstra_clrs( // Remark(Andrew): We may want to make this parameterizable as different types of heaps give different performance // But std::priority_queue is probably reasonable for now using q_compare = decltype([](const weighted_vertex& a, const weighted_vertex& b) { return a.weight > b.weight; }); - std::priority_queue, q_compare> Q; + std::priority_queue, q_compare> Q; // Remark(Andrew): CLRS puts all vertices in the queue to start but standard practice seems to be to enqueue source Q.push({seed, distance[seed]}); @@ -142,4 +137,4 @@ void dijkstra_clrs( } } -} // namespace std::graph +} // namespace graph diff --git a/include/graph/algorithm/dijkstra_shortest_paths.hpp b/include/graph/algorithm/dijkstra_shortest_paths.hpp index a07518e..667d43e 100644 --- a/include/graph/algorithm/dijkstra_shortest_paths.hpp +++ b/include/graph/algorithm/dijkstra_shortest_paths.hpp @@ -24,7 +24,7 @@ #ifndef GRAPH_DIJKSTRA_SHORTEST_PATHS_HPP # define GRAPH_DIJKSTRA_SHORTEST_PATHS_HPP -namespace std::graph { +namespace graph { template class dijkstra_visitor_base { @@ -93,33 +93,32 @@ concept dijkstra_visitor = //is_arithmetic && * @tparam Compare Comparison function for Distance values. Defaults to less. * @tparam Combine Combine function for Distance values. Defaults to plus. */ -template (edge_reference_t)>, +template (edge_reference_t)>, class Visitor = dijkstra_visitor_base, - class Compare = less>, - class Combine = plus>> -requires convertible_to, vertex_id_t> && // - is_arithmetic_v> && // - ranges::sized_range && // - ranges::sized_range && // - convertible_to, ranges::range_value_t> && - basic_edge_weight_function, Compare, Combine> + class Compare = less>, + class Combine = plus>> +requires convertible_to, vertex_id_t> && // + is_arithmetic_v> && // + sized_range && // + sized_range && // + convertible_to, range_value_t> && + basic_edge_weight_function, Compare, Combine> // && dijkstra_visitor void dijkstra_shortest_paths( G& g, const Sources& sources, Distances& distances, Predecessors& predecessor, - WF&& weight = - [](edge_reference_t uv) { return ranges::range_value_t(1); }, // default weight(uv) -> 1 + WF&& weight = [](edge_reference_t uv) { return range_value_t(1); }, // default weight(uv) -> 1 Visitor&& visitor = dijkstra_visitor_base(), - Compare&& compare = less>(), - Combine&& combine = plus>()) { + Compare&& compare = less>(), + Combine&& combine = plus>()) { using id_type = vertex_id_t; - using distance_type = ranges::range_value_t; + using distance_type = range_value_t; using weight_type = invoke_result_t>; // relxing the target is the function of reducing the distance from the source to the target @@ -140,13 +139,13 @@ void dijkstra_shortest_paths( }; if (size(distances) < size(vertices(g))) { - throw out_of_range( + throw std::out_of_range( fmt::format("dijkstra_shortest_paths: size of distances of {} is less than the number of vertices {}", size(distances), size(vertices(g)))); } if constexpr (!is_same_v) { if (size(predecessor) < size(vertices(g))) { - throw out_of_range( + throw std::out_of_range( fmt::format("dijkstra_shortest_paths: size of predecessor of {} is less than the number of vertices {}", size(predecessor), size(vertices(g)))); } @@ -160,7 +159,7 @@ void dijkstra_shortest_paths( auto qcompare = [&distances](id_type a, id_type b) { return distances[static_cast(a)] > distances[static_cast(b)]; }; - using Queue = std::priority_queue, decltype(qcompare)>; + using Queue = std::priority_queue, decltype(qcompare)>; Queue queue(qcompare); // (The optimizer removes this loop if on_initialize_vertex() is empty.) @@ -171,7 +170,7 @@ void dijkstra_shortest_paths( // Seed the queue with the initial vertice(s) for (auto&& source : sources) { if (source >= N || source < 0) { - throw out_of_range(fmt::format("dijkstra_shortest_paths: source vertex id '{}' is out of range", source)); + throw std::out_of_range(fmt::format("dijkstra_shortest_paths: source vertex id '{}' is out of range", source)); } queue.push(source); distances[static_cast(source)] = zero; // mark source as discovered @@ -189,9 +188,9 @@ void dijkstra_shortest_paths( visitor.on_examine_edge({uid, vid, uv}); // Negative weights are not allowed for Dijkstra's algorithm - if constexpr (is_signed_v) { + if constexpr (std::is_signed_v) { if (w < zero) { - throw out_of_range( + throw std::out_of_range( fmt::format("dijkstra_shortest_paths: invalid negative edge weight of '{}' encountered", w)); } } @@ -207,7 +206,8 @@ void dijkstra_shortest_paths( queue.push(vid); } else { // This is an indicator of a bug in the algorithm and should be investigated. - throw logic_error("dijkstra_shortest_paths: unexpected state where an edge to a new vertex was not relaxed"); + throw std::logic_error( + "dijkstra_shortest_paths: unexpected state where an edge to a new vertex was not relaxed"); } } else { // non-tree edge @@ -227,30 +227,29 @@ void dijkstra_shortest_paths( } // while(!queue.empty()) } -template (edge_reference_t)>, +template (edge_reference_t)>, class Visitor = dijkstra_visitor_base, - class Compare = less>, - class Combine = plus>> -requires is_arithmetic_v> && // - ranges::sized_range && // - ranges::sized_range && // - convertible_to, ranges::range_value_t> && - basic_edge_weight_function, Compare, Combine> + class Compare = less>, + class Combine = plus>> +requires is_arithmetic_v> && // + sized_range && // + sized_range && // + convertible_to, range_value_t> && + basic_edge_weight_function, Compare, Combine> // && dijkstra_visitor void dijkstra_shortest_paths( G& g, const vertex_id_t source, Distances& distances, Predecessors& predecessor, - WF&& weight = - [](edge_reference_t uv) { return ranges::range_value_t(1); }, // default weight(uv) -> 1 + WF&& weight = [](edge_reference_t uv) { return range_value_t(1); }, // default weight(uv) -> 1 Visitor&& visitor = dijkstra_visitor_base(), - Compare&& compare = less>(), - Combine&& combine = plus>()) { - dijkstra_shortest_paths(g, ranges::subrange(&source, (&source + 1)), distances, predecessor, weight, + Compare&& compare = less>(), + Combine&& combine = plus>()) { + dijkstra_shortest_paths(g, subrange(&source, (&source + 1)), distances, predecessor, weight, forward(visitor), forward(compare), forward(combine)); } @@ -280,56 +279,54 @@ void dijkstra_shortest_paths( * @tparam Compare Comparison function for Distance values. Defaults to less. * @tparam Combine Combine function for Distance values. Defaults to plus. */ -template (edge_reference_t)>, +template (edge_reference_t)>, class Visitor = dijkstra_visitor_base, - class Compare = less>, - class Combine = plus>> -requires convertible_to, vertex_id_t> && // - ranges::sized_range && // - is_arithmetic_v> && // - basic_edge_weight_function, Compare, Combine> + class Compare = less>, + class Combine = plus>> +requires convertible_to, vertex_id_t> && // + sized_range && // + is_arithmetic_v> && // + basic_edge_weight_function, Compare, Combine> //&& dijkstra_visitor void dijkstra_shortest_distances( G& g, const Sources& sources, Distances& distances, - WF&& weight = - [](edge_reference_t uv) { return ranges::range_value_t(1); }, // default weight(uv) -> 1 + WF&& weight = [](edge_reference_t uv) { return range_value_t(1); }, // default weight(uv) -> 1 Visitor&& visitor = dijkstra_visitor_base(), - Compare&& compare = less>(), - Combine&& combine = plus>()) { + Compare&& compare = less>(), + Combine&& combine = plus>()) { dijkstra_shortest_paths(g, sources, distances, _null_predecessors, forward(weight), std::forward(visitor), std::forward(compare), std::forward(combine)); } -template (edge_reference_t)>, +template (edge_reference_t)>, class Visitor = dijkstra_visitor_base, - class Compare = less>, - class Combine = plus>> -requires is_arithmetic_v> && // - ranges::sized_range && // - basic_edge_weight_function, Compare, Combine> + class Compare = less>, + class Combine = plus>> +requires is_arithmetic_v> && // + sized_range && // + basic_edge_weight_function, Compare, Combine> //&& dijkstra_visitor void dijkstra_shortest_distances( G& g, const vertex_id_t source, Distances& distances, - WF&& weight = - [](edge_reference_t uv) { return ranges::range_value_t(1); }, // default weight(uv) -> 1 + WF&& weight = [](edge_reference_t uv) { return range_value_t(1); }, // default weight(uv) -> 1 Visitor&& visitor = dijkstra_visitor_base(), - Compare&& compare = less>(), - Combine&& combine = plus>()) { - dijkstra_shortest_paths(g, ranges::subrange(&source, (&source + 1)), distances, _null_predecessors, - forward(weight), std::forward(visitor), std::forward(compare), + Compare&& compare = less>(), + Combine&& combine = plus>()) { + dijkstra_shortest_paths(g, subrange(&source, (&source + 1)), distances, _null_predecessors, forward(weight), + std::forward(visitor), std::forward(compare), std::forward(combine)); } -} // namespace std::graph +} // namespace graph #endif // GRAPH_DIJKSTRA_SHORTEST_PATHS_HPP diff --git a/include/graph/algorithm/experimental/bfs_cmn.hpp b/include/graph/algorithm/experimental/bfs_cmn.hpp index ee3ebb8..2024e72 100644 --- a/include/graph/algorithm/experimental/bfs_cmn.hpp +++ b/include/graph/algorithm/experimental/bfs_cmn.hpp @@ -4,7 +4,7 @@ #include #include -namespace std::graph::experimental { +namespace graph::experimental { /** * @ingroup graph_algorithms * @brief Returns a value to define an infinite distance used to initialize distance values @@ -16,7 +16,7 @@ namespace std::graph::experimental { */ template constexpr auto shortest_path_infinite_distance() { - return numeric_limits::max(); + return std::numeric_limits::max(); } /** @@ -42,7 +42,7 @@ constexpr auto shortest_path_zero() { */ template constexpr void init_shortest_paths(Distances& distances) { - ranges::fill(distances, shortest_path_infinite_distance>()); + std::ranges::fill(distances, shortest_path_infinite_distance>()); } /** @@ -59,7 +59,7 @@ template constexpr void init_shortest_paths(Distances& distances, Predecessors& predecessors) { init_shortest_paths(distances); - using pred_t = ranges::range_value_t; + using pred_t = range_value_t; pred_t i = pred_t(); for (auto& pred : predecessors) pred = i++; @@ -84,4 +84,4 @@ concept _queueable = requires(Q&& q, typename Q::value_type value) { { q.empty() }; { q.size() }; }; -} // namespace std::graph::experimental +} // namespace graph::experimental diff --git a/include/graph/algorithm/experimental/co_bfs.hpp b/include/graph/algorithm/experimental/co_bfs.hpp index 62434a0..afd84fa 100644 --- a/include/graph/algorithm/experimental/co_bfs.hpp +++ b/include/graph/algorithm/experimental/co_bfs.hpp @@ -15,7 +15,7 @@ #ifndef GRAPH_CO_BFS_HPP # define GRAPH_CO_BFS_HPP -namespace std::graph::experimental { +namespace graph::experimental { // These events duplicate boost::graph's BFSVisitorConcept enum class bfs_events { @@ -64,7 +64,7 @@ Generator> co_bfs(G&& g, // graph size_t N(num_vertices(g)); assert(seed < N && seed >= 0); - vector color(N, three_colors::white); + std::vector color(N, three_colors::white); if ((events & bfs_events::initialize_vertex) != bfs_events::none) { for (id_type uid = 0; uid < num_vertices(g); ++uid) { @@ -75,7 +75,7 @@ Generator> co_bfs(G&& g, // graph yield_vertex(bfs_events::discover_vertex, seed); using q_compare = decltype([](const id_type& a, const id_type& b) { return a > b; }); - std::priority_queue, q_compare> Q; + std::priority_queue, q_compare> Q; // Remark(Andrew): CLRS puts all vertices in the queue to start but standard practice seems to be to enqueue source Q.push(seed); @@ -130,6 +130,6 @@ enum event_visitor_enum { on_edge_not_minimized_num }; -} // namespace std::graph::experimental +} // namespace graph::experimental #endif // GRAPH_CO_BFS_HPP diff --git a/include/graph/algorithm/experimental/co_cmn.hpp b/include/graph/algorithm/experimental/co_cmn.hpp index 817975d..236a6af 100644 --- a/include/graph/algorithm/experimental/co_cmn.hpp +++ b/include/graph/algorithm/experimental/co_cmn.hpp @@ -7,13 +7,13 @@ #include -namespace std::graph::experimental { +namespace graph::experimental { template concept basic_edge_weight_function = // e.g. weight(uv) - is_arithmetic_v && strict_weak_order && - assignable_from, - invoke_result_t>>>; + is_arithmetic_v && std::strict_weak_order && + std::assignable_from, + invoke_result_t>>>; template concept edge_weight_function = // e.g. weight(uv) @@ -27,7 +27,7 @@ using bfs_vertex_value_t = vertex_descriptor, reference_wrapper using bfs_edge_value_t = edge_descriptor, true, reference_wrapper>, void>; template -using bfs_variant_value_t = variant, bfs_edge_value_t>; +using bfs_variant_value_t = std::variant, bfs_edge_value_t>; template using bfs_value_t = pair>; @@ -49,4 +49,4 @@ struct event_not_overridden {}; } -} // namespace std::graph::experimental +} // namespace graph::experimental diff --git a/include/graph/algorithm/experimental/co_dijkstra.hpp b/include/graph/algorithm/experimental/co_dijkstra.hpp index 67b5518..bbab5c8 100644 --- a/include/graph/algorithm/experimental/co_dijkstra.hpp +++ b/include/graph/algorithm/experimental/co_dijkstra.hpp @@ -15,7 +15,7 @@ #ifndef GRAPH_CO_DIJKSTRA_CLRS_HPP # define GRAPH_CO_DIJKSTRA_CLRS_HPP -namespace std::graph::experimental { +namespace graph::experimental { // Helper macros to keep the visual clutter down in a coroutine. I'd like to investigate using CRTP to avoid them, @@ -76,29 +76,28 @@ constexpr dijkstra_events operator|(dijkstra_events lhs, dijkstra_events rhs) no * @tparam WF Edge weight function. Defaults to a function that returns 1. * @tparam Queue The queue type. Defaults to a priority_queue. */ -template >, - class Combine = plus>, - class WF = std::function(edge_reference_t)>> -requires convertible_to, vertex_id_t> && // - is_arithmetic_v> && // - convertible_to, ranges::range_value_t> && // - basic_edge_weight_function, Compare, Combine> +template >, + class Combine = plus>, + class WF = std::function(edge_reference_t)>> +requires convertible_to, vertex_id_t> && // + is_arithmetic_v> && // + convertible_to, range_value_t> && // + basic_edge_weight_function, Compare, Combine> Generator> co_dijkstra( G& g_, const dijkstra_events events, const Seeds& seeds, Predecessors& predecessor, Distances& distances, - WF& weight = - [](edge_reference_t uv) { return ranges::range_value_t(1); }, // default weight(uv) -> 1 - Compare&& compare = less>(), - Combine&& combine = plus>()) { + WF& weight = [](edge_reference_t uv) { return range_value_t(1); }, // default weight(uv) -> 1 + Compare&& compare = less>(), + Combine&& combine = plus>()) { using id_type = vertex_id_t; - using DistanceValue = ranges::range_value_t; + using DistanceValue = range_value_t; using weight_type = invoke_result_t>; using bfs_vertex_type = bfs_vertex_value_t; using bfs_edge_type = bfs_edge_value_t; @@ -131,7 +130,7 @@ Generator> co_dijkstra( auto qcompare = [&distances](id_type a, id_type b) { return distances[static_cast(a)] > distances[static_cast(b)]; }; - using Queue = std::priority_queue, vector>, decltype(qcompare)>; + using Queue = std::priority_queue, std::vector>, decltype(qcompare)>; Queue queue(qcompare); if ((events & dijkstra_events::initialize_vertex) == dijkstra_events::initialize_vertex) { @@ -169,7 +168,7 @@ Generator> co_dijkstra( dijkstra_yield_edge(dijkstra_events::examine_edge, uid, vid, uv); // Negative weights are not allowed for Dijkstra's algorithm - if constexpr (is_signed_v) { + if constexpr (std::is_signed_v) { if (w < zero) { throw graph_error("co_dijkstra: negative edge weight"); } @@ -229,35 +228,34 @@ Generator> co_dijkstra( // refinements needed // 1. queue is created 2x -template >, - class Combine = plus>, - class WF = std::function(edge_reference_t)>, - _queueable Queue = priority_queue, - vector>, - greater>>> -requires is_arithmetic_v> && // - convertible_to, ranges::range_value_t> && // - basic_edge_weight_function, Compare, Combine> +template >, + class Combine = plus>, + class WF = std::function(edge_reference_t)>, + _queueable Queue = std::priority_queue, + std::vector>, + std::greater>>> +requires is_arithmetic_v> && // + convertible_to, range_value_t> && // + basic_edge_weight_function, Compare, Combine> Generator> co_dijkstra( G& g_, const dijkstra_events events, vertex_id_t seed, Predecessors& predecessor, Distances& distances, - WF& weight = - [](edge_reference_t uv) { return ranges::range_value_t(1); }, // default weight(uv) -> 1 - Compare&& compare = less>(), - Combine&& combine = plus>(), + WF& weight = [](edge_reference_t uv) { return range_value_t(1); }, // default weight(uv) -> 1 + Compare&& compare = less>(), + Combine&& combine = plus>(), Queue queue = Queue()) { - //ranges::subrange seeds{&seed, (&seed + 1)}; // segfault in gcc-13 when iterating over seeds in called co_dijkstra - array, 1> seeds{seed}; + //subrange seeds{&seed, (&seed + 1)}; // segfault in gcc-13 when iterating over seeds in called co_dijkstra + std::array, 1> seeds{seed}; return co_dijkstra(g_, events, seeds, predecessor, distances, weight, forward(compare), forward(combine), queue); } -} // namespace std::graph::experimental +} // namespace graph::experimental #endif // GRAPH_CO_DIJKSTRA_CLRS_HPP diff --git a/include/graph/algorithm/experimental/visitor_dijkstra.hpp b/include/graph/algorithm/experimental/visitor_dijkstra.hpp index dfb0869..4181377 100644 --- a/include/graph/algorithm/experimental/visitor_dijkstra.hpp +++ b/include/graph/algorithm/experimental/visitor_dijkstra.hpp @@ -8,7 +8,7 @@ #include #include -namespace std::graph::experimental { +namespace graph::experimental { /** * @ingroup graph_algorithms @@ -86,7 +86,7 @@ concept _has_overridden_on_initialize_vertex = requires(V obj, typename V::verte { &V::on_initialize_vertex } -> same_as; }; -template +template class _dijkstra_distance_compare { const Distances& distances_; @@ -101,22 +101,22 @@ class _dijkstra_distance_compare { template using _dijkstra_queue = - priority_queue, vector>, _dijkstra_distance_compare>; + std::priority_queue, std::vector>, _dijkstra_distance_compare>; -using DD = vector; +using DD = std::vector; DD dd; -using GG = vector>>; +using GG = std::vector>>; GG gg; using CC = _dijkstra_distance_compare; -using PQV = vector>; +using PQV = std::vector>; -priority_queue, vector>, _dijkstra_distance_compare> - pq(CC(gg, dd), vector>()); +std::priority_queue, std::vector>, _dijkstra_distance_compare> + pq(CC(gg, dd), std::vector>()); -_dijkstra_queue pq2{CC(gg, dd), vector>()}; +_dijkstra_queue pq2{CC(gg, dd), std::vector>()}; /** * @brief dijkstra shortest paths @@ -138,20 +138,20 @@ _dijkstra_queue pq2{CC(gg, dd), vector>()}; */ template (edge_reference_t)>, - class Compare = less>, - class Combine = plus> + input_range Sources, + random_access_range Distances, + random_access_range Predecessors, + class WF = std::function(edge_reference_t)>, + class Compare = less>, + class Combine = plus> //queueable Que = _dijkstra_queue // not used > -requires convertible_to, vertex_id_t> && // - is_arithmetic_v> && // - convertible_to, ranges::range_value_t> && +requires convertible_to, vertex_id_t> && // + is_arithmetic_v> && // + convertible_to, range_value_t> && basic_edge_weight_function, + range_value_t, Compare, Combine> //&& dijkstra_visitor void dijkstra_with_visitor( @@ -159,13 +159,12 @@ void dijkstra_with_visitor( const Sources& sources, Predecessors& predecessor, Distances& distances, - WF& weight = - [](edge_reference_t uv) { return ranges::range_value_t(1); }, // default weight(uv) -> 1 + WF& weight = [](edge_reference_t uv) { return range_value_t(1); }, // default weight(uv) -> 1 Visitor&& visitor = dijkstra_visitor_base(), - Compare&& compare = less>(), - Combine&& combine = plus>()) { + Compare&& compare = less>(), + Combine&& combine = plus>()) { using id_type = vertex_id_t; - using DistanceValue = ranges::range_value_t; + using DistanceValue = range_value_t; using weight_type = invoke_result_t>; #if ENABLE_INLINE_RELAX_TARGET == 0 @@ -205,7 +204,7 @@ void dijkstra_with_visitor( auto qcompare = [&distances](id_type a, id_type b) { return distances[static_cast(a)] > distances[static_cast(b)]; }; - using Queue = std::priority_queue, vector>, decltype(qcompare)>; + using Queue = std::priority_queue, std::vector>, decltype(qcompare)>; Queue queue(qcompare); // (The optimizer removes this loop if on_initialize_vertex() is empty.) @@ -216,7 +215,7 @@ void dijkstra_with_visitor( // Seed the queue with the initial vertice(s) for (auto&& source : sources) { if (source >= N || source < 0) { - throw out_of_range("dijkstra_with_visitor: source vertex out of range"); + throw std::out_of_range("dijkstra_with_visitor: source vertex out of range"); } queue.push(source); distances[static_cast(source)] = zero; // mark source as discovered @@ -242,7 +241,7 @@ void dijkstra_with_visitor( visitor.on_examine_edge({uid, vid, uv}); // Negative weights are not allowed for Dijkstra's algorithm - if constexpr (is_signed_v) { + if constexpr (std::is_signed_v) { if (w < zero) { throw graph_error("dijkstra_with_visitor: negative edge weight"); } @@ -275,7 +274,8 @@ void dijkstra_with_visitor( queue.push(vid); } else { // This is an indicator of a bug in the algorithm and should be investigated. - throw logic_error("dijkstra_with_visitor: unexpected state where an edge to a new vertex was not relaxed"); + throw std::logic_error( + "dijkstra_with_visitor: unexpected state where an edge to a new vertex was not relaxed"); } } else { // non-tree edge @@ -301,17 +301,17 @@ void dijkstra_with_visitor( template (edge_reference_t)>, - class Compare = less>, - class Combine = plus>, + random_access_range Distances, + random_access_range Predecessors, + class WF = std::function(edge_reference_t)>, + class Compare = less>, + class Combine = plus>, queueable Que = _dijkstra_queue> -requires is_arithmetic_v> && // - convertible_to, ranges::range_value_t> && +requires is_arithmetic_v> && // + convertible_to, range_value_t> && basic_edge_weight_function, + range_value_t, Compare, Combine> //&& dijkstra_visitor void dijkstra_with_visitor( @@ -320,12 +320,11 @@ void dijkstra_with_visitor( vertex_id_t source, Predecessors& predecessor, Distances& distances, - WF& weight = - [](edge_reference_t uv) { return ranges::range_value_t(1); }, // default weight(uv) -> 1 - Compare&& compare = less>(), - Combine&& combine = plus>()) { - dijkstra_with_visitor(g, forward(visitor), ranges::subrange(&source, (&source + 1)), predecessor, distances, - weight, forward(compare), forward(combine)); + WF& weight = [](edge_reference_t uv) { return range_value_t(1); }, // default weight(uv) -> 1 + Compare&& compare = less>(), + Combine&& combine = plus>()) { + dijkstra_with_visitor(g, forward(visitor), subrange(&source, (&source + 1)), predecessor, distances, weight, + forward(compare), forward(combine)); } -} // namespace std::graph::experimental +} // namespace graph::experimental diff --git a/include/graph/algorithm/mis.hpp b/include/graph/algorithm/mis.hpp index 0f65b71..25f9961 100644 --- a/include/graph/algorithm/mis.hpp +++ b/include/graph/algorithm/mis.hpp @@ -19,7 +19,7 @@ #ifndef GRAPH_MIS_HPP # define GRAPH_MIS_HPP -namespace std::graph { +namespace graph { /** * @ingroup graph_algorithms @@ -36,9 +36,7 @@ namespace std::graph { */ template -requires ranges::random_access_range> && integral> && - std::output_iterator> - +requires random_access_range> && integral> && output_iterator> void maximal_independent_set(G&& g, // graph Iter mis, // out: maximal independent set vertex_id_t seed = 0 // seed vtx @@ -63,6 +61,6 @@ void maximal_independent_set(G&& g, // graph } } -} // namespace std::graph +} // namespace graph #endif //GRAPH_MIS_HPP diff --git a/include/graph/algorithm/mst.hpp b/include/graph/algorithm/mst.hpp index eee98a4..1bc02b3 100644 --- a/include/graph/algorithm/mst.hpp +++ b/include/graph/algorithm/mst.hpp @@ -21,7 +21,7 @@ #ifndef GRAPH_MST_HPP # define GRAPH_MST_HPP -namespace std::graph { +namespace graph { template struct disjoint_element { @@ -30,7 +30,7 @@ struct disjoint_element { }; template -using disjoint_vector = vector>; +using disjoint_vector = std::vector>; template VId disjoint_find(disjoint_vector& subsets, VId vtx) { @@ -105,7 +105,7 @@ template // For exposition only concept _basic_edgelist_type = is_same_v; template // For exposition only -concept _basic_index_edgelist_type = _basic_edgelist_type && is_integral_v; +concept _basic_index_edgelist_type = _basic_edgelist_type && integral; template // For exposition only concept _edgelist_type = _basic_edgelist_type && _has_edgelist_value; @@ -115,17 +115,16 @@ concept _index_edgelist_type = _basic_index_edgelist_type && _has_edgelist template // For exposition only -concept x_basic_edgelist_range = ranges::forward_range && _basic_edgelist_type>; +concept x_basic_edgelist_range = forward_range && _basic_edgelist_type>; template // For exposition only -concept x_basic_index_edgelist_range = - ranges::forward_range && _basic_index_edgelist_type>; +concept x_basic_index_edgelist_range = forward_range && _basic_index_edgelist_type>; template // For exposition only -concept x_edgelist_range = ranges::forward_range && _edgelist_type>; +concept x_edgelist_range = forward_range && _edgelist_type>; template // For exposition only -concept x_index_edgelist_range = ranges::forward_range && _index_edgelist_type>; +concept x_index_edgelist_range = forward_range && _index_edgelist_type>; /*template struct has_edge : false_type { }; @@ -168,13 +167,13 @@ void kruskal(IELR&& e, // graph OELR&& t, // tree CompareOp compare // edge value comparitor ) { - using edge_descriptor = ranges::range_value_t; - using VId = remove_const::type; + using edge_descriptor = range_value_t; + using VId = remove_const_t; using EV = edge_descriptor::value_type; - vector> e_copy; - ranges::transform(e, back_inserter(e_copy), - [](auto&& ed) { return make_tuple(ed.source_id, ed.target_id, ed.value); }); + std::vector> e_copy; + std::ranges::transform(e, back_inserter(e_copy), + [](auto&& ed) { return std::make_tuple(ed.source_id, ed.target_id, ed.value); }); VId N = 0; auto outer_compare = [&](auto&& i, auto&& j) { if (get<0>(i) > N) { @@ -185,7 +184,7 @@ void kruskal(IELR&& e, // graph } return compare(get<2>(i), get<2>(j)); }; - ranges::sort(e_copy, outer_compare); + std::ranges::sort(e_copy, outer_compare); disjoint_vector subsets(N + 1); for (VId uid = 0; uid < N; ++uid) { @@ -196,7 +195,7 @@ void kruskal(IELR&& e, // graph t.reserve(N); for (auto&& [uid, vid, val] : e_copy) { if (disjoint_union_find(subsets, uid, vid)) { - t.push_back(ranges::range_value_t()); + t.push_back(range_value_t()); t.back().source_id = uid; t.back().target_id = vid; t.back().value = val; @@ -217,7 +216,7 @@ void kruskal(IELR&& e, // graph * @param t The output edgelist containing the tree. */ template -requires permutable> +requires std::permutable> void inplace_kruskal(IELR&& e, OELR&& t) { inplace_kruskal(e, t, [](auto&& i, auto&& j) { return i < j; }); } @@ -237,13 +236,13 @@ void inplace_kruskal(IELR&& e, OELR&& t) { * @param compare The comparison operator. */ template -requires permutable> +requires std::permutable> void inplace_kruskal(IELR&& e, // graph OELR&& t, // tree CompareOp compare // edge value comparitor ) { - using edge_descriptor = ranges::range_value_t; - using VId = remove_const::type; + using edge_descriptor = range_value_t; + using VId = remove_const_t; VId N = 0; auto outer_compare = [&](auto&& i, auto&& j) { @@ -255,7 +254,7 @@ void inplace_kruskal(IELR&& e, // graph } return compare(i.value, j.value); }; - ranges::sort(e, outer_compare); + std::ranges::sort(e, outer_compare); disjoint_vector subsets(N + 1); for (VId uid = 0; uid < N; ++uid) { @@ -266,7 +265,7 @@ void inplace_kruskal(IELR&& e, // graph t.reserve(N); for (auto&& [uid, vid, val] : e) { if (disjoint_union_find(subsets, uid, vid)) { - t.push_back(ranges::range_value_t()); + t.push_back(range_value_t()); t.back().source_id = uid; t.back().target_id = vid; t.back().value = val; @@ -288,10 +287,10 @@ void inplace_kruskal(IELR&& e, // graph * caller must assure size(predecessor) >= size(vertices(g)). * @param seed The single source vertex to start the search. */ -template -requires ranges::random_access_range> && integral> +template +requires random_access_range> && integral> void prim(G&& g, // graph Predecessor& predecessor, // out: predecessor[uid] of uid in tree Weight& weight, // out: edge value weight[uid] from tree edge uid to predecessor[uid] @@ -299,7 +298,7 @@ void prim(G&& g, // graph ) { prim( g, predecessor, weight, [](auto&& i, auto&& j) { return i < j; }, - numeric_limits>::max(), seed); + std::numeric_limits>::max(), seed); } /** @@ -319,21 +318,21 @@ void prim(G&& g, // graph * @param init_dist The initial distance value. * @param seed The single source vertex to start the search. */ -template -requires ranges::random_access_range> && integral> -void prim(G&& g, // graph - Predecessor& predecessor, // out: predecessor[uid] of uid in tree - Weight& weight, // out: edge value weight[uid] from tree edge uid to predecessor[uid] - CompareOp compare, // edge value comparitor - ranges::range_value_t init_dist, // initial distance - vertex_id_t seed = 0 // seed vtx +requires random_access_range> && integral> +void prim(G&& g, // graph + Predecessor& predecessor, // out: predecessor[uid] of uid in tree + Weight& weight, // out: edge value weight[uid] from tree edge uid to predecessor[uid] + CompareOp compare, // edge value comparitor + range_value_t init_dist, // initial distance + vertex_id_t seed = 0 // seed vtx ) { - typedef ranges::range_value_t EV; - size_t N(size(vertices(g))); - vector distance(N, init_dist); + typedef range_value_t EV; + size_t N(size(vertices(g))); + std::vector distance(N, init_dist); distance[seed] = 0; predecessor[seed] = seed; @@ -342,7 +341,7 @@ void prim(G&& g, // graph auto evf = [&g](edge_reference_t uv) { return edge_value(g, uv); }; auto outer_compare = [&](auto&& i, auto&& j) { return compare(get<1>(i), get<1>(j)); }; - priority_queue, decltype(outer_compare)> Q(outer_compare); + std::priority_queue, decltype(outer_compare)> Q(outer_compare); Q.push({seed, distance[seed]}); while (!Q.empty()) { auto uid = get<0>(Q.top()); @@ -358,6 +357,6 @@ void prim(G&& g, // graph } } } -} // namespace std::graph +} // namespace graph #endif //GRAPH_MST_HPP diff --git a/include/graph/algorithm/tc.hpp b/include/graph/algorithm/tc.hpp index 2e9a344..9971605 100644 --- a/include/graph/algorithm/tc.hpp +++ b/include/graph/algorithm/tc.hpp @@ -18,7 +18,7 @@ #ifndef GRAPH_TC_HPP # define GRAPH_TC_HPP -namespace std::graph { +namespace graph { /** * @ingroup graph_algorithms @@ -31,23 +31,23 @@ namespace std::graph { * @param g The graph. */ template -requires ranges::random_access_range> && integral> +requires random_access_range> && integral> size_t triangle_count(G&& g) { size_t N(size(vertices(g))); size_t triangles(0); for (vertex_id_t uid = 0; uid < N; ++uid) { - std::graph::incidence_iterator i(g, uid); - auto ie = ranges::end(edges(g, uid)); + graph::incidence_iterator i(g, uid); + auto ie = end(edges(g, uid)); while (i != ie) { auto&& [vid, uv] = *i; if (vid < uid) { ++i; continue; } - std::graph::incidence_iterator j(g, vid); + graph::incidence_iterator j(g, vid); - auto je = ranges::end(edges(g, vid)); + auto je = end(edges(g, vid)); auto i2 = i; // Alternatively use std::set_intersection(i2, ie, j, je, counter) but this is slower @@ -69,6 +69,6 @@ size_t triangle_count(G&& g) { } return triangles; } -} // namespace std::graph +} // namespace graph #endif //GRAPH_TC_HPP \ No newline at end of file diff --git a/include/graph/algorithm/transitive_closure.hpp b/include/graph/algorithm/transitive_closure.hpp index b51a62e..100a780 100644 --- a/include/graph/algorithm/transitive_closure.hpp +++ b/include/graph/algorithm/transitive_closure.hpp @@ -5,7 +5,7 @@ #include "graph/views/incidence.hpp" #include -namespace std::graph { +namespace graph { template struct reaches { @@ -23,8 +23,8 @@ struct reaches { * Warshall's algorithm. Complexity is O(n^3). */ // clang-format off -template > - requires ranges::random_access_range> && +template > + requires random_access_range> && integral> && output_iterator> //&& directed @@ -32,7 +32,7 @@ template > constexpr void warshall_transitive_closure(G& g, OutIter result_iter, Alloc alloc = Alloc()) { using views::vertexlist; using views::incidence; - const size_t V = ranges::size(g); + const size_t V = size(g); std::vector reach(V * V, alloc); // adjacency matrix bitmap // transform edges into adjacency matrix bitmap @@ -53,4 +53,4 @@ constexpr void warshall_transitive_closure(G& g, OutIter result_iter, Alloc allo *result_iter = {uid, vid}; } -} // namespace std::graph +} // namespace graph diff --git a/include/graph/container/compressed_graph.hpp b/include/graph/container/compressed_graph.hpp index 79ff091..db0d832 100644 --- a/include/graph/container/compressed_graph.hpp +++ b/include/graph/container/compressed_graph.hpp @@ -28,7 +28,7 @@ // [uid,vval] <-- copyable_vertex // [uid,vid,eval] <-- copyable_edge // -namespace std::graph::container { +namespace graph::container { /** * @ingroup graph_containers @@ -46,8 +46,8 @@ namespace std::graph::container { * * @return A @c pair with the max vertex id used and the number of edges scanned. */ -template -requires copyable_edge>, VId, EV> +template +requires copyable_edge>, VId, EV> constexpr auto max_vertex_id(const ERng& erng, const EProj& eprojection) { size_t edge_count = 0; VId max_id = 0; @@ -63,12 +63,12 @@ constexpr auto max_vertex_id(const ERng& erng, const EProj& eprojection) { // // forward declarations // -template > // for internal containers +template > // for internal containers class compressed_graph; /** @@ -120,15 +120,15 @@ struct csr_col { template class csr_row_values { using row_type = csr_row; // index into col_index_ - using row_allocator_type = typename allocator_traits::template rebind_alloc; - using row_index_vector = vector; + using row_allocator_type = typename std::allocator_traits::template rebind_alloc; + using row_index_vector = std::vector; public: using graph_type = compressed_graph; using vertex_type = row_type; using vertex_value_type = VV; - using allocator_type = typename allocator_traits::template rebind_alloc; - using vector_type = vector; + using allocator_type = typename std::allocator_traits::template rebind_alloc; + using vector_type = std::vector; using value_type = VV; using size_type = size_t; //VId; @@ -166,12 +166,12 @@ class csr_row_values { constexpr void swap(csr_row_values& other) noexcept { swap(v_, other.v_); } - template - //requires views::copyable_vertex>, VId, VV> + template + //requires views::copyable_vertex>, VId, VV> constexpr void load_row_values(const VRng& vrng, VProj projection, size_type vertex_count) { - if constexpr (ranges::sized_range) - vertex_count = max(vertex_count, ranges::size(vrng)); - resize(ranges::size(vrng)); + if constexpr (sized_range) + vertex_count = max(vertex_count, size(vrng)); + resize(size(vrng)); for (auto&& vtx : vrng) { const auto& [id, value] = projection(vtx); @@ -184,12 +184,12 @@ class csr_row_values { } } - template - //requires views::copyable_vertex>, VId, VV> + template + //requires views::copyable_vertex>, VId, VV> constexpr void load_row_values(VRng&& vrng, VProj projection, size_type vertex_count) { - if constexpr (ranges::sized_range) - vertex_count = max(vertex_count, ranges::size(vrng)); - resize(ranges::size(vrng)); + if constexpr (sized_range) + vertex_count = max(vertex_count, std::ranges::size(vrng)); + resize(std::ranges::size(vrng)); for (auto&& vtx : vrng) { auto&& [id, value] = projection(vtx); @@ -208,13 +208,13 @@ class csr_row_values { private: friend constexpr vertex_value_type& vertex_value(graph_type& g, vertex_type& u) { - static_assert(ranges::contiguous_range, "row_index_ must be a contiguous range to evaluate uidx"); + static_assert(contiguous_range, "row_index_ must be a contiguous range to evaluate uidx"); auto uidx = g.index_of(u); csr_row_values& row_vals = g; return row_vals.v_[uidx]; } friend constexpr const vertex_value_type& vertex_value(const graph_type& g, const vertex_type& u) { - static_assert(ranges::contiguous_range, "row_index_ must be a contiguous range to evaluate uidx"); + static_assert(contiguous_range, "row_index_ must be a contiguous range to evaluate uidx"); auto uidx = g.index_of(u); const csr_row_values& row_vals = g; return row_vals.v_[uidx]; @@ -233,7 +233,7 @@ class csr_row_values { using value_type = void; using size_type = size_t; //VId; -public: // Properties +public: // Properties [[nodiscard]] constexpr size_type size() const noexcept { return 0; } [[nodiscard]] constexpr bool empty() const noexcept { return true; } [[nodiscard]] constexpr size_type capacity() const noexcept { return 0; } @@ -269,15 +269,15 @@ class csr_row_values { template class csr_col_values { using col_type = csr_col; // target_id - using col_allocator_type = typename allocator_traits::template rebind_alloc; - using col_index_vector = vector; + using col_allocator_type = typename std::allocator_traits::template rebind_alloc; + using col_index_vector = std::vector; public: using graph_type = compressed_graph; using edge_type = col_type; // index into v_ using edge_value_type = EV; - using allocator_type = typename allocator_traits::template rebind_alloc; - using vector_type = vector; + using allocator_type = typename std::allocator_traits::template rebind_alloc; + using vector_type = std::vector; using value_type = EV; using size_type = size_t; //VId; @@ -345,7 +345,7 @@ class csr_col_values { using value_type = void; using size_type = size_t; //VId; -public: // Properties +public: // Properties [[nodiscard]] constexpr size_type size() const noexcept { return 0; } [[nodiscard]] constexpr bool empty() const noexcept { return true; } [[nodiscard]] constexpr size_type capacity() const noexcept { return 0; } @@ -387,35 +387,35 @@ class compressed_graph_base using col_values_base = csr_col_values; using row_type = csr_row; // index into col_index_ - using row_allocator_type = typename allocator_traits::template rebind_alloc; - using row_index_vector = vector; + using row_allocator_type = typename std::allocator_traits::template rebind_alloc; + using row_index_vector = std::vector; using col_type = csr_col; // target_id - using col_allocator_type = typename allocator_traits::template rebind_alloc; - using col_index_vector = vector; + using col_allocator_type = typename std::allocator_traits::template rebind_alloc; + using col_index_vector = std::vector; public: // Types using graph_type = compressed_graph_base; using partition_id_type = VId; - using partition_vector = vector; + using partition_vector = std::vector; using vertex_id_type = VId; using vertex_type = row_type; using vertex_value_type = VV; - using vertices_type = ranges::subrange>; - using const_vertices_type = ranges::subrange>; + using vertices_type = subrange>; + using const_vertices_type = subrange>; using edge_type = col_type; // index into v_ using edge_value_type = EV; using edge_index_type = EIndex; - using edges_type = ranges::subrange>; - using const_edges_type = ranges::subrange>; + using edges_type = subrange>; + using const_edges_type = subrange>; using const_iterator = typename row_index_vector::const_iterator; using iterator = typename row_index_vector::iterator; - using size_type = ranges::range_size_t; + using size_type = range_size_t; public: // Construction/Destruction constexpr compressed_graph_base() = default; @@ -445,12 +445,12 @@ class compressed_graph_base * @param partition_start_ids Range of starting vertex ids for each partition. If empty, all vertices are in partition 0. * @param alloc Allocator to use for internal containers */ - template - //requires copyable_edge>, VId, EV> && // - // convertible_to, VId> + template + //requires copyable_edge>, VId, EV> && // + // convertible_to, VId> constexpr compressed_graph_base(const ERng& erng, EProj eprojection = {}, - const PartRng& partition_start_ids = vector(), + const PartRng& partition_start_ids = std::vector(), const Alloc& alloc = Alloc()) : row_values_base(alloc) , col_values_base(alloc) @@ -479,19 +479,19 @@ class compressed_graph_base * @param partition_start_ids Range of starting vertex ids for each partition. If empty, all vertices are in partition 0. * @param alloc Allocator to use for internal containers */ - template - requires convertible_to, VId> - //requires copyable_edge>, VId, EV> && - // copyable_vertex>, VId, VV> + requires convertible_to, VId> + //requires copyable_edge>, VId, EV> && + // copyable_vertex>, VId, VV> constexpr compressed_graph_base(const ERng& erng, const VRng& vrng, EProj eprojection = {}, // eproj(eval) -> {source_id,target_id [,value]} VProj vprojection = {}, // vproj(vval) -> {target_id [,value]} - const PartRng& partition_start_ids = vector(), + const PartRng& partition_start_ids = std::vector(), const Alloc& alloc = Alloc()) : row_values_base(alloc) , col_values_base(alloc) @@ -510,7 +510,8 @@ class compressed_graph_base * @param ilist Initializer list of @c copyable_edge_t -> [source_id, target_id, value] * @param alloc Allocator to use for internal containers */ - constexpr compressed_graph_base(const initializer_list>& ilist, const Alloc& alloc = Alloc()) + constexpr compressed_graph_base(const std::initializer_list>& ilist, + const Alloc& alloc = Alloc()) : row_values_base(alloc), col_values_base(alloc), row_index_(alloc), col_index_(alloc), partition_(alloc) { auto part_fnc = [](vertex_id_t) -> partition_id_t { return 0; }; load_edges(ilist, identity()); @@ -518,7 +519,7 @@ class compressed_graph_base } public: -public: // Operations +public: // Operations void reserve_vertices(size_type count) { row_index_.reserve(count + 1); // +1 for terminating row row_values_base::reserve(count); @@ -551,10 +552,10 @@ class compressed_graph_base * preserved in the internal vector. * @param vprojection Projection function for @c vrng values */ - template - //requires views::copyable_vertex>, VId, VV> + template + //requires views::copyable_vertex>, VId, VV> constexpr void load_vertices(const VRng& vrng, VProj vprojection, size_type vertex_count = 0) { - row_values_base::load_row_values(vrng, vprojection, max(vertex_count, ranges::size(vrng))); + row_values_base::load_row_values(vrng, vprojection, max(vertex_count, size(vrng))); } /** @@ -570,10 +571,10 @@ class compressed_graph_base * @param vrng Range of values to load for vertices. The order of the values is preserved in the internal vector. * @param vprojection Projection function for @c vrng values */ - template - //requires views::copyable_vertex>, VId, VV> + template + //requires views::copyable_vertex>, VId, VV> constexpr void load_vertices(VRng& vrng, VProj vprojection = {}, size_type vertex_count = 0) { - row_values_base::load_row_values(vrng, vprojection, max(vertex_count, ranges::size(vrng))); + row_values_base::load_row_values(vrng, vprojection, max(vertex_count, size(vrng))); } /** @@ -616,13 +617,13 @@ class compressed_graph_base * edge range. */ template - //requires views::copyable_edge>, VId, EV> + //requires views::copyable_edge>, VId, EV> constexpr void load_edges(ERng&& erng, EProj eprojection = {}, size_type vertex_count = 0, size_type edge_count = 0) { // should only be loading into an empty graph assert(row_index_.empty() && col_index_.empty() && static_cast(*this).empty()); // Nothing to do? - if (ranges::begin(erng) == ranges::end(erng)) { + if (begin(erng) == end(erng)) { terminate_partitions(); return; } @@ -630,13 +631,13 @@ class compressed_graph_base // We can get the last vertex id from the list because erng is required to be ordered by // the source id. It's possible a target_id could have a larger id also, which is taken // care of at the end of this function. - vertex_count = std::max(vertex_count, + vertex_count = max(vertex_count, static_cast(last_erng_id(erng, eprojection) + 1)); // +1 for zero-based index reserve_vertices(vertex_count); // Eval number of input rows and reserve space for the edges, if possible - if constexpr (ranges::sized_range) - edge_count = max(edge_count, ranges::size(erng)); + if constexpr (sized_range) + edge_count = max(edge_count, size(erng)); reserve_edges(edge_count); // Add edges @@ -648,7 +649,7 @@ class compressed_graph_base vertex_type{static_cast(col_index_.size())}); col_index_.push_back(edge_type{edge.target_id}); if constexpr (!is_void_v) - static_cast(*this).emplace_back(std::move(edge.value)); + static_cast(*this).emplace_back(move(edge.value)); last_uid = edge.source_id; max_vid = max(max_vid, edge.target_id); } @@ -668,14 +669,14 @@ class compressed_graph_base // The only diff with this and ERng&& is v_.push_back vs. v_.emplace_back template - //requires views::copyable_edge>, VId, EV> + //requires views::copyable_edge>, VId, EV> constexpr void load_edges(const ERng& erng, EProj eprojection = {}, size_type vertex_count = 0, size_type edge_count = 0) { // should only be loading into an empty graph assert(row_index_.empty() && col_index_.empty() && static_cast(*this).empty()); // Nothing to do? - if (ranges::begin(erng) == ranges::end(erng)) { + if (begin(erng) == end(erng)) { terminate_partitions(); return; } @@ -683,13 +684,13 @@ class compressed_graph_base // We can get the last vertex id from the list because erng is required to be ordered by // the source id. It's possible a target_id could have a larger id also, which is taken // care of at the end of this function. - vertex_count = std::max(vertex_count, + vertex_count = max(vertex_count, static_cast(last_erng_id(erng, eprojection) + 1)); // +1 for zero-based index reserve_vertices(vertex_count); // Eval number of input rows and reserve space for the edges, if possible - if constexpr (ranges::sized_range) - edge_count = max(edge_count, ranges::size(erng)); + if constexpr (sized_range) + edge_count = max(edge_count, size(erng)); reserve_edges(edge_count); // Add edges @@ -745,14 +746,14 @@ class compressed_graph_base * @param vprojection Vertex projection function object * @param partition_start_ids Range of starting vertex ids for each partition. If empty, all vertices are in partition 0. */ - template - requires convertible_to, VId> - //requires views::copyable_edge>, VId, EV> && - // views::copyable_vertex>, VId, VV> + requires convertible_to, VId> + //requires views::copyable_edge>, VId, EV> && + // views::copyable_vertex>, VId, VV> constexpr void load(const ERng& erng, const VRng& vrng, EProj eprojection = {}, VProj vprojection = {}) { load_edges(erng, eprojection); load_vertices(vrng, vprojection); // load the values @@ -762,9 +763,9 @@ class compressed_graph_base template constexpr vertex_id_type last_erng_id(ERng&& erng, EProj eprojection) const { vertex_id_type last_id = vertex_id_type(); - if constexpr (ranges::bidirectional_range) { - if (ranges::begin(erng) != ranges::end(erng)) { - auto lastIt = ranges::end(erng); + if constexpr (bidirectional_range) { + if (begin(erng) != end(erng)) { + auto lastIt = end(erng); --lastIt; auto&& e = eprojection(*lastIt); // copyable_edge last_id = max(e.source_id, e.target_id); @@ -784,10 +785,8 @@ class compressed_graph_base } public: // Operations - constexpr ranges::iterator_t find_vertex(vertex_id_type id) noexcept { - return row_index_.begin() + id; - } - constexpr ranges::iterator_t find_vertex(vertex_id_type id) const noexcept { + constexpr iterator_t find_vertex(vertex_id_type id) noexcept { return row_index_.begin() + id; } + constexpr iterator_t find_vertex(vertex_id_type id) const noexcept { return row_index_.begin() + id; } @@ -814,13 +813,13 @@ class compressed_graph_base private: // CPO properties friend constexpr vertices_type vertices(compressed_graph_base& g) { if (g.row_index_.empty()) - return vertices_type(g.row_index_); // really empty + return vertices_type(g.row_index_); // really empty else return vertices_type(g.row_index_.begin(), g.row_index_.end() - 1); // don't include terminating row } friend constexpr const_vertices_type vertices(const compressed_graph_base& g) { if (g.row_index_.empty()) - return const_vertices_type(g.row_index_); // really empty + return const_vertices_type(g.row_index_); // really empty else return const_vertices_type(g.row_index_.begin(), g.row_index_.end() - 1); // don't include terminating row } @@ -835,17 +834,17 @@ class compressed_graph_base } friend constexpr edges_type edges(graph_type& g, vertex_type& u) { - static_assert(ranges::contiguous_range, "row_index_ must be a contiguous range to get next row"); + static_assert(contiguous_range, "row_index_ must be a contiguous range to get next row"); vertex_type* u2 = &u + 1; - assert(static_cast(u2 - &u) < g.row_index_.size()); // in row_index_ bounds? + assert(static_cast(u2 - &u) < g.row_index_.size()); // in row_index_ bounds? assert(static_cast(u.index) <= g.col_index_.size() && static_cast(u2->index) <= g.col_index_.size()); // in col_index_ bounds? return edges_type(g.col_index_.begin() + u.index, g.col_index_.begin() + u2->index); } friend constexpr const_edges_type edges(const graph_type& g, const vertex_type& u) { - static_assert(ranges::contiguous_range, "row_index_ must be a contiguous range to get next row"); + static_assert(contiguous_range, "row_index_ must be a contiguous range to get next row"); const vertex_type* u2 = &u + 1; - assert(static_cast(u2 - &u) < g.row_index_.size()); // in row_index_ bounds? + assert(static_cast(u2 - &u) < g.row_index_.size()); // in row_index_ bounds? assert(static_cast(u.index) <= g.col_index_.size() && static_cast(u2->index) <= g.col_index_.size()); // in col_index_ bounds? return const_edges_type(g.col_index_.begin() + u.index, g.col_index_.begin() + u2->index); @@ -854,7 +853,7 @@ class compressed_graph_base friend constexpr edges_type edges(graph_type& g, const vertex_id_type uid) { assert(static_cast(uid + 1) < g.row_index_.size()); // in row_index_ bounds? assert(static_cast(g.row_index_[static_cast(uid) + 1].index) <= - g.col_index_.size()); // in col_index_ bounds? + g.col_index_.size()); // in col_index_ bounds? return edges_type(g.col_index_.begin() + g.row_index_[static_cast(uid)].index, g.col_index_.begin() + g.row_index_[static_cast(uid + 1)].index); } @@ -892,7 +891,7 @@ class compressed_graph_base friend constexpr auto vertices(const compressed_graph_base& g, partition_id_type pid) { assert(static_cast(pid) < g.partition_.size() - 1); - return ranges::subrange(g.row_index_.begin() + g.partition_[pid], g.row_index_.begin() + g.partition_[pid + 1]); + return subrange(g.row_index_.begin() + g.partition_[pid], g.row_index_.begin() + g.partition_[pid + 1]); } friend row_values_base; @@ -951,32 +950,32 @@ class compressed_graph : public compressed_graph_base - requires copyable_edge>, VId, EV> && - convertible_to, VId> + template + requires copyable_edge>, VId, EV> && + convertible_to, VId> constexpr compressed_graph(const ERng& erng, EProj eprojection, - const PartRng& partition_start_ids = vector(), + const PartRng& partition_start_ids = std::vector(), const Alloc& alloc = Alloc()) : base_type(erng, eprojection, partition_start_ids, alloc) {} - template - requires copyable_edge>, VId, EV> && - convertible_to, VId> + template + requires copyable_edge>, VId, EV> && + convertible_to, VId> constexpr compressed_graph(const graph_value_type& value, const ERng& erng, EProj eprojection, - const PartRng& partition_start_ids = vector(), + const PartRng& partition_start_ids = std::vector(), const Alloc& alloc = Alloc()) : base_type(erng, eprojection, partition_start_ids, alloc), value_(value) {} - template - requires copyable_edge>, VId, EV> && - convertible_to, VId> + template + requires copyable_edge>, VId, EV> && + convertible_to, VId> constexpr compressed_graph(graph_value_type&& value, const ERng& erng, EProj eprojection, - const PartRng& partition_start_ids = vector(), + const PartRng& partition_start_ids = std::vector(), const Alloc& alloc = Alloc()) : base_type(erng, eprojection, partition_start_ids, alloc), value_(move(value)) {} @@ -984,57 +983,57 @@ class compressed_graph : public compressed_graph_base - requires copyable_edge>, VId, EV> && - copyable_vertex>, VId, VV> && - convertible_to, VId> + requires copyable_edge>, VId, EV> && + copyable_vertex>, VId, VV> && + convertible_to, VId> constexpr compressed_graph(const ERng& erng, const VRng& vrng, EProj eprojection = {}, VProj vprojection = {}, - const PartRng& partition_start_ids = vector(), + const PartRng& partition_start_ids = std::vector(), const Alloc& alloc = Alloc()) : base_type(erng, vrng, eprojection, vprojection, partition_start_ids, alloc) {} - template - requires copyable_edge>, VId, EV> && - copyable_vertex>, VId, VV> && - convertible_to, VId> + requires copyable_edge>, VId, EV> && + copyable_vertex>, VId, VV> && + convertible_to, VId> constexpr compressed_graph(const graph_value_type& value, const ERng& erng, const VRng& vrng, EProj eprojection = {}, VProj vprojection = {}, - const PartRng& partition_start_ids = vector(), + const PartRng& partition_start_ids = std::vector(), const Alloc& alloc = Alloc()) : base_type(erng, vrng, eprojection, vprojection, partition_start_ids, alloc), value_(value) {} - template - requires copyable_edge>, VId, EV> && - copyable_vertex>, VId, VV> && - convertible_to, VId> + requires copyable_edge>, VId, EV> && + copyable_vertex>, VId, VV> && + convertible_to, VId> constexpr compressed_graph(graph_value_type&& value, const ERng& erng, const VRng& vrng, EProj eprojection = {}, VProj vprojection = {}, - const PartRng& partition_start_ids = vector(), + const PartRng& partition_start_ids = std::vector(), const Alloc& alloc = Alloc()) : base_type(erng, vrng, eprojection, vprojection, partition_start_ids, alloc), value_(move(value)) {} - constexpr compressed_graph(const initializer_list>& ilist, const Alloc& alloc = Alloc()) + constexpr compressed_graph(const std::initializer_list>& ilist, const Alloc& alloc = Alloc()) : base_type(ilist, alloc) {} private: // CPO properties @@ -1082,34 +1081,34 @@ class compressed_graph constexpr compressed_graph& operator=(compressed_graph&&) = default; // edge-only construction - template > - requires copyable_edge>, VId, EV> + template > + requires copyable_edge>, VId, EV> constexpr compressed_graph(const ERng& erng, EProj eprojection = identity(), - const PartRng& partition_start_ids = vector(), + const PartRng& partition_start_ids = std::vector(), const Alloc& alloc = Alloc()) : base_type(erng, eprojection, partition_start_ids, alloc) {} // edge and vertex value construction - template > - requires copyable_edge>, VId, EV> && - copyable_vertex>, VId, VV> && - convertible_to, VId> + template > + requires copyable_edge>, VId, EV> && + copyable_vertex>, VId, VV> && + convertible_to, VId> constexpr compressed_graph(const ERng& erng, const VRng& vrng, EProj eprojection = {}, VProj vprojection = {}, - const PartRng& partition_start_ids = vector(), + const PartRng& partition_start_ids = std::vector(), const Alloc& alloc = Alloc()) : base_type(erng, vrng, eprojection, vprojection, partition_start_ids, alloc) {} // initializer list using edge_descriptor - constexpr compressed_graph(const initializer_list>& ilist, const Alloc& alloc = Alloc()) + constexpr compressed_graph(const std::initializer_list>& ilist, const Alloc& alloc = Alloc()) : base_type(ilist, alloc) {} }; -} // namespace std::graph::container +} // namespace graph::container diff --git a/include/graph/container/container_utility.hpp b/include/graph/container/container_utility.hpp index f9cc611..2cac167 100644 --- a/include/graph/container/container_utility.hpp +++ b/include/graph/container/container_utility.hpp @@ -3,7 +3,7 @@ #ifndef CONTAINER_UTILITY_HPP # define CONTAINER_UTILITY_HPP -namespace std::graph::container { +namespace graph::container { //-------------------------------------------------------------------------------------------------- @@ -82,8 +82,8 @@ constexpr auto push_or_insert(C& container) { template requires has_array_operator constexpr auto assign_or_insert(C& container) { - if constexpr (ranges::random_access_range) { - static_assert(ranges::sized_range, "random_access container is assumed to have size()"); + if constexpr (random_access_range) { + static_assert(sized_range, "random_access container is assumed to have size()"); return [&container](const K& id, typename C::value_type&& value) { typename C::size_type k = static_cast(id); assert(k < container.size()); @@ -99,7 +99,7 @@ constexpr auto assign_or_insert(C& container) { // ERng is a forward_range because it is traversed twice; once to get the max vertex_id // and a second time to load the edges. template -concept edge_value_extractor = ranges::forward_range && invocable && +concept edge_value_extractor = forward_range && invocable && invocable; namespace detail { @@ -120,9 +120,9 @@ namespace detail { template struct graph_value_needs_wrap - : integral_constant::value || is_array::value || is_union::value || is_reference::value> { - }; + : std::integral_constant::value || std::is_array::value || std::is_union::value || + std::is_reference::value> {}; template constexpr auto user_value(T& v) -> T& { @@ -149,15 +149,15 @@ struct weight_value { }; struct name_value { - string name; + std::string name; name_value() = default; name_value(const name_value&) = default; name_value& operator=(const name_value&) = default; - name_value(const string& s) : name(s) {} - name_value(string&& s) : name(std::move(s)) {} + name_value(const std::string& s) : name(s) {} + name_value(std::string&& s) : name(std::move(s)) {} }; -} // namespace std::graph::container +} // namespace graph::container #endif //CONTAINER_UTILITY_HPP diff --git a/include/graph/container/dynamic_graph.hpp b/include/graph/container/dynamic_graph.hpp index 635152f..1f51f7f 100644 --- a/include/graph/container/dynamic_graph.hpp +++ b/include/graph/container/dynamic_graph.hpp @@ -27,7 +27,7 @@ // [uid,vid,eval] <-- copyable_edge // -namespace std::graph::container { +namespace graph::container { //-------------------------------------------------------------------------------------------------- // dynamic_graph traits forward references @@ -93,8 +93,8 @@ struct vofl_graph_traits { using vertex_type = dynamic_vertex; using graph_type = dynamic_graph; - using vertices_type = vector; - using edges_type = forward_list; + using vertices_type = std::vector; + using edges_type = std::forward_list; }; /** @@ -125,8 +125,8 @@ struct vol_graph_traits { using vertex_type = dynamic_vertex; using graph_type = dynamic_graph; - using vertices_type = vector; - using edges_type = list; + using vertices_type = std::vector; + using edges_type = std::list; }; /** @@ -157,8 +157,8 @@ struct vov_graph_traits { using vertex_type = dynamic_vertex; using graph_type = dynamic_graph; - using vertices_type = vector; - using edges_type = vector; + using vertices_type = std::vector; + using edges_type = std::vector; }; /** @@ -685,11 +685,13 @@ class dynamic_vertex_base { friend constexpr typename edges_type::iterator find_vertex_edge(graph_type& g, vertex_id_type uid, vertex_id_type vid) { - return ranges::find(g[uid].edges_, [&g, &vid](const edge_type& uv) -> bool { return target_id(g, uv) == vid; }); + return std::ranges::find(g[uid].edges_, + [&g, &vid](const edge_type& uv) -> bool { return target_id(g, uv) == vid; }); } friend constexpr typename edges_type::const_iterator find_vertex_edge(const graph_type& g, vertex_id_type uid, vertex_id_type vid) { - return ranges::find(g[uid].edges_, [&g, &vid](const edge_type& uv) -> bool { return target_id(g, uv) == vid; }); + return std::ranges::find(g[uid].edges_, + [&g, &vid](const edge_type& uv) -> bool { return target_id(g, uv) == vid; }); } }; @@ -834,7 +836,7 @@ class dynamic_graph_base { using graph_traits = Traits; using partition_id_type = VId; - using partition_vector = vector; + using partition_vector = std::vector; using vertex_id_type = VId; using vertex_type = dynamic_vertex; @@ -894,13 +896,13 @@ class dynamic_graph_base { * @param partition_start_ids Range of starting vertex ids for each partition. If empty, all vertices are in partition 0. * @param alloc The allocator used for vertices and edges containers. */ - template - requires convertible_to, VId> + template + requires convertible_to, VId> dynamic_graph_base(ERng&& erng, VRng&& vrng, EProj eproj, VProj vproj, - const PartRng& partition_start_ids = vector(), + const PartRng& partition_start_ids = std::vector(), vertex_allocator_type alloc = vertex_allocator_type()) : vertices_(alloc), partition_(partition_start_ids, alloc) { load_vertices(vrng, vproj); @@ -933,11 +935,11 @@ class dynamic_graph_base { * @param partition_start_ids Range of starting vertex ids for each partition. If empty, all vertices are in partition 0. * @param alloc The allocator used for vertices and edges containers. */ - template - requires convertible_to, VId> + template + requires convertible_to, VId> dynamic_graph_base(ERng&& erng, EProj eproj, - const PartRng& partition_start_ids = vector(), + const PartRng& partition_start_ids = std::vector(), vertex_allocator_type alloc = vertex_allocator_type()) : vertices_(alloc), partition_(partition_start_ids, alloc) { load_edges(move(erng), eproj); @@ -969,12 +971,12 @@ class dynamic_graph_base { * @param partition_start_ids Range of starting vertex ids for each partition. If empty, all vertices are in partition 0. * @param alloc The allocator used for vertices and edges containers. */ - template - requires convertible_to, VId> + template + requires convertible_to, VId> dynamic_graph_base(size_type vertex_count, ERng&& erng, EProj eproj, - const PartRng& partition_start_ids = vector(), + const PartRng& partition_start_ids = std::vector(), vertex_allocator_type alloc = vertex_allocator_type()) : vertices_(alloc), partition_(partition_start_ids, alloc) { load_edges(vertex_count, 0, move(erng), eproj); @@ -989,8 +991,8 @@ class dynamic_graph_base { * @param il The initializer list of copyable edge values. * @param alloc The allocator to use for the vertices and edges containers. */ - dynamic_graph_base(const initializer_list>& il, - edge_allocator_type alloc = edge_allocator_type()) + dynamic_graph_base(const std::initializer_list>& il, + edge_allocator_type alloc = edge_allocator_type()) : vertices_(alloc), partition_(alloc) { size_t last_id = 0; for (auto&& e : il) @@ -1023,14 +1025,14 @@ class dynamic_graph_base { */ template void load_vertices(const VRng& vrng, VProj vproj = {}, size_type vertex_count = 0) { - if constexpr (ranges::sized_range && resizable) { - vertex_count = max(vertex_count, ranges::size(vertices_)); - resize_vertices(max(vertex_count, ranges::size(vrng))); + if constexpr (sized_range && resizable) { + vertex_count = max(vertex_count, size(vertices_)); + resize_vertices(max(vertex_count, size(vrng))); } for (auto&& v : vrng) { auto&& [id, value] = vproj(v); //copyable_vertex_t size_t k = static_cast(id); - if constexpr (ranges::random_access_range) + if constexpr (random_access_range) assert(k < vertices_.size()); vertices_[k].value() = value; } @@ -1063,16 +1065,16 @@ class dynamic_graph_base { */ template void load_vertices(VRng&& vrng, VProj vproj = {}, size_type vertex_count = 0) { - if constexpr (ranges::sized_range && resizable) { - vertex_count = max(vertex_count, ranges::size(vertices_)); - resize_vertices(max(vertex_count, ranges::size(vrng))); + if constexpr (sized_range && resizable) { + vertex_count = max(vertex_count, std::ranges::size(vertices_)); + resize_vertices(max(vertex_count, std::ranges::size(vrng))); } for (auto&& v : vrng) { auto&& [id, value] = vproj(v); //copyable_vertex_t size_t k = static_cast(id); - if constexpr (ranges::random_access_range) + if constexpr (random_access_range) assert(k < vertices_.size()); - vertices_[k].value() = std::move(value); + vertices_[k].value() = move(value); } } @@ -1115,11 +1117,11 @@ class dynamic_graph_base { if (static_cast(e.source_id) >= vertices_.size()) { assert(false); - throw runtime_error("source id exceeds the number of vertices in load_edges"); + throw std::runtime_error("source id exceeds the number of vertices in load_edges"); } if (static_cast(e.target_id) >= vertices_.size()) { assert(false); - throw runtime_error("target id exceeds the number of vertices in load_edges"); + throw std::runtime_error("target id exceeds the number of vertices in load_edges"); } auto&& edge_adder = push_or_insert(vertices_[e.source_id].edges()); @@ -1183,11 +1185,11 @@ class dynamic_graph_base { if (static_cast(e.source_id) >= vertices_.size()) { assert(false); - throw runtime_error("source id exceeds the number of vertices in load_edges"); + throw std::runtime_error("source id exceeds the number of vertices in load_edges"); } if (static_cast(e.target_id) >= vertices_.size()) { assert(false); - throw runtime_error("target id exceeds the number of vertices in load_edges"); + throw std::runtime_error("target id exceeds the number of vertices in load_edges"); } auto&& edge_adder = push_or_insert(vertices_[e.source_id].edges()); @@ -1254,7 +1256,7 @@ class dynamic_graph_base { constexpr typename vertices_type::value_type& operator[](size_type i) noexcept { return vertices_[i]; } constexpr const typename vertices_type::value_type& operator[](size_type i) const noexcept { return vertices_[i]; } -public: // Operations +public: // Operations void reserve_vertices(size_type count) { if constexpr (reservable) // reserve if we can; otherwise ignored vertices_.reserve(count); @@ -1271,13 +1273,13 @@ class dynamic_graph_base { // ignored for this graph; may be meaningful for another data structure like CSR } -private: // Member Variables +private: // Member Variables vertices_type vertices_; partition_vector partition_; // partition_[n] holds the first vertex id for each partition n // holds +1 extra terminating partition size_t edge_count_ = 0; // total number of edges in the graph -private: // CPO properties +private: // CPO properties friend constexpr vertices_type& vertices(dynamic_graph_base& g) { return g.vertices_; } friend constexpr const vertices_type& vertices(const dynamic_graph_base& g) { return g.vertices_; } @@ -1311,7 +1313,7 @@ class dynamic_graph_base { friend constexpr auto vertices(const dynamic_graph_base& g, partition_id_type pid) { assert(static_cast(pid) < g.partition_.size() - 1); - return ranges::subrange(g.vertices_.begin() + g.partition_[pid], g.vertices_.begin() + g.partition_[pid + 1]); + return subrange(g.vertices_.begin() + g.partition_[pid], g.vertices_.begin() + g.partition_[pid + 1]); } }; @@ -1438,13 +1440,13 @@ class dynamic_graph : public dynamic_graph_base - requires convertible_to, VId> + template + requires convertible_to, VId> dynamic_graph(const ERng& erng, const VRng& vrng, EProj eproj = {}, VProj vproj = {}, - const PartRng& partition_start_ids = vector(), + const PartRng& partition_start_ids = std::vector(), allocator_type alloc = allocator_type()) : base_type(erng, vrng, eproj, vproj, partition_start_ids, alloc) {} @@ -1477,14 +1479,14 @@ class dynamic_graph : public dynamic_graph_base - requires convertible_to, VId> + template + requires convertible_to, VId> dynamic_graph(const GV& gv, const ERng& erng, const VRng& vrng, EProj eproj = {}, VProj vproj = {}, - const PartRng& partition_start_ids = vector(), + const PartRng& partition_start_ids = std::vector(), allocator_type alloc = allocator_type()) : base_type(erng, vrng, eproj, vproj, partition_start_ids, alloc), value_(gv) {} @@ -1517,14 +1519,14 @@ class dynamic_graph : public dynamic_graph_base - requires convertible_to, VId> + template + requires convertible_to, VId> dynamic_graph(const ERng& erng, const VRng& vrng, EProj eproj, VProj vproj, GV&& gv, - const PartRng& partition_start_ids = vector(), + const PartRng& partition_start_ids = std::vector(), allocator_type alloc = allocator_type()) : base_type(erng, vrng, eproj, vproj, partition_start_ids, alloc), value_(move(gv)) {} @@ -1554,11 +1556,11 @@ class dynamic_graph : public dynamic_graph_base + template dynamic_graph(vertex_id_type max_vertex_id, ERng& erng, EProj eproj = {}, - const PartRng& partition_start_ids = vector(), + const PartRng& partition_start_ids = std::vector(), allocator_type alloc = allocator_type()) : base_type(max_vertex_id, erng, eproj, partition_start_ids, alloc) {} @@ -1582,13 +1584,13 @@ class dynamic_graph : public dynamic_graph_base - requires convertible_to, VId> + template + requires convertible_to, VId> dynamic_graph(const GV& gv, vertex_id_type max_vertex_id, ERng& erng, EProj eproj = {}, - const PartRng& partition_start_ids = vector(), + const PartRng& partition_start_ids = std::vector(), allocator_type alloc = allocator_type()) : base_type(max_vertex_id, erng, eproj, partition_start_ids, alloc), value_(gv) {} @@ -1612,13 +1614,13 @@ class dynamic_graph : public dynamic_graph_base - requires convertible_to, VId> + template + requires convertible_to, VId> dynamic_graph(GV&& gv, vertex_id_type max_vertex_id, ERng& erng, EProj eproj = {}, - const PartRng& partition_start_ids = vector(), + const PartRng& partition_start_ids = std::vector(), allocator_type alloc = allocator_type()) : base_type(max_vertex_id, erng, eproj, partition_start_ids, alloc), value_(move(gv)) {} @@ -1645,11 +1647,11 @@ class dynamic_graph : public dynamic_graph_base - requires convertible_to, VId> + template + requires convertible_to, VId> dynamic_graph(ERng& erng, EProj eproj = {}, - const PartRng& partition_start_ids = vector(), + const PartRng& partition_start_ids = std::vector(), allocator_type alloc = allocator_type()) : base_type(erng, eproj, partition_start_ids, alloc) {} @@ -1673,12 +1675,12 @@ class dynamic_graph : public dynamic_graph_base - requires convertible_to, VId> + template + requires convertible_to, VId> dynamic_graph(const GV& gv, ERng& erng, EProj eproj = {}, - const PartRng& partition_start_ids = vector(), + const PartRng& partition_start_ids = std::vector(), allocator_type alloc = allocator_type()) : base_type(erng, eproj, partition_start_ids, alloc), value_(gv) {} @@ -1702,12 +1704,12 @@ class dynamic_graph : public dynamic_graph_base - requires convertible_to, VId> + template + requires convertible_to, VId> dynamic_graph(GV&& gv, ERng& erng, EProj eproj = {}, - const PartRng& partition_start_ids = vector(), + const PartRng& partition_start_ids = std::vector(), allocator_type alloc = allocator_type()) : base_type(erng, eproj, partition_start_ids, alloc), value_(move(gv)) {} @@ -1722,7 +1724,8 @@ class dynamic_graph : public dynamic_graph_base>& il, edge_allocator_type alloc = edge_allocator_type()) + dynamic_graph(const std::initializer_list>& il, + edge_allocator_type alloc = edge_allocator_type()) : base_type(il, alloc) {} public: @@ -1732,7 +1735,7 @@ class dynamic_graph : public dynamic_graph_base * @param partition_start_ids Range of starting vertex ids for each partition. If empty, all vertices are in partition 0. * @param alloc The allocator used for the vertices and edges containers. */ - template - requires convertible_to, VId> + template + requires convertible_to, VId> dynamic_graph(ERng& erng, EProj eproj = {}, - const PartRng& partition_start_ids = vector(), + const PartRng& partition_start_ids = std::vector(), allocator_type alloc = allocator_type()) : base_type(erng, eproj, partition_start_ids, alloc) {} @@ -1834,12 +1837,12 @@ class dynamic_graph * @param partition_start_ids Range of starting vertex ids for each partition. If empty, all vertices are in partition 0. * @param alloc The allocator used for the vertices and edges containers. */ - template - requires convertible_to, VId> + template + requires convertible_to, VId> dynamic_graph(vertex_id_type max_vertex_id, ERng& erng, EProj eproj = {}, - const PartRng& partition_start_ids = vector(), + const PartRng& partition_start_ids = std::vector(), allocator_type alloc = allocator_type()) : base_type(max_vertex_id, erng, eproj, partition_start_ids, alloc) {} @@ -1869,13 +1872,13 @@ class dynamic_graph * @param partition_start_ids Range of starting vertex ids for each partition. If empty, all vertices are in partition 0. * @param alloc The allocator used for the vertices and edges containers. */ - template - requires convertible_to, VId> + template + requires convertible_to, VId> dynamic_graph(ERng& erng, VRng& vrng, EProj eproj = {}, VProj vproj = {}, - const PartRng& partition_start_ids = vector(), + const PartRng& partition_start_ids = std::vector(), allocator_type alloc = allocator_type()) : base_type(erng, vrng, eproj, vproj, partition_start_ids, alloc) {} @@ -1887,9 +1890,10 @@ class dynamic_graph * @param il The initializer list of copyable edge values. * @param alloc The allocator to use for the vertices and edges containers. */ - dynamic_graph(const initializer_list>& il, edge_allocator_type alloc = edge_allocator_type()) + dynamic_graph(const std::initializer_list>& il, + edge_allocator_type alloc = edge_allocator_type()) : base_type(il, alloc) {} }; -} // namespace std::graph::container +} // namespace graph::container diff --git a/include/graph/container/utility_edgelist.hpp b/include/graph/container/utility_edgelist.hpp index 920efdb..b483279 100644 --- a/include/graph/container/utility_edgelist.hpp +++ b/include/graph/container/utility_edgelist.hpp @@ -2,7 +2,7 @@ #include "graph/edgelist.hpp" -namespace std::graph::container { +namespace graph::container { template class utility_edgelist { @@ -44,8 +44,8 @@ class utility_edgelist { using type = std::conditional_t<(std::numeric_limits::max() > std::numeric_limits::max()), T, U>; }; - //VSourceId max_vid() { return std::max(source_max_, target_max_); } - VLargeId::type max_vid() { return std::max(source_max_, target_max_); } + //VSourceId max_vid() { return max(source_max_, target_max_); } + VLargeId::type max_vid() { return max(source_max_, target_max_); } VSourceId max_source() { return source_max_; } VTargetId max_target() { return target_max_; } @@ -87,4 +87,4 @@ class utility_edgelist { bool directed_; }; -} // namespace std::graph::container \ No newline at end of file +} // namespace graph::container \ No newline at end of file diff --git a/include/graph/detail/co_generator.hpp b/include/graph/detail/co_generator.hpp index a630bf9..acfebf4 100644 --- a/include/graph/detail/co_generator.hpp +++ b/include/graph/detail/co_generator.hpp @@ -2,7 +2,7 @@ #include -namespace std::graph { +namespace graph { // A simple generator from https://en.cppreference.com/w/cpp/language/coroutines. template @@ -145,4 +145,4 @@ Generator fib_seq_wrap(unsigned n) { } #endif //0 -} // namespace std::graph +} // namespace graph diff --git a/include/graph/detail/graph_cpo.hpp b/include/graph/detail/graph_cpo.hpp index 46c31e8..5141f3b 100644 --- a/include/graph/detail/graph_cpo.hpp +++ b/include/graph/detail/graph_cpo.hpp @@ -6,14 +6,19 @@ #ifndef GRAPH_CPO_HPP # define GRAPH_CPO_HPP -namespace std::graph { - -# ifndef _MSC_VER +namespace graph { + +# ifdef _MSC_VER +using std::_Has_class_or_enum_type; +using std::_Fake_copy_init; +using std::_Always_false; +using std::_Choice_t; +# else // Taken from gcc11 definition of __decay_copy(). // Very similar (identical?) to std::_Fake_copy_init in msvc. struct _Decay_copy final { template - constexpr decay_t<_Tp> operator()(_Tp&& __t) const noexcept(is_nothrow_convertible_v<_Tp, decay_t<_Tp>>) { + constexpr std::decay_t<_Tp> operator()(_Tp&& __t) const noexcept(std::is_nothrow_convertible_v<_Tp, std::decay_t<_Tp>>) { return std::forward<_Tp>(__t); } } inline constexpr _Fake_copy_init{}; @@ -27,7 +32,7 @@ template inline constexpr bool _Always_false = false; template -inline constexpr bool _Is_nonbool_integral = is_integral_v<_Ty> && !is_same_v, bool>; +inline constexpr bool _Is_nonbool_integral = std::is_integral_v<_Ty> && !std::is_same_v, bool>; template inline constexpr bool _Integer_class = requires { @@ -52,31 +57,31 @@ struct _Choice_t { // Support the use of std containers, tuple and pair for adj list definitions (e.g. vector>) // template -concept _al_adjlist = ranges::forward_range<_G> && ranges::forward_range>; +concept _al_adjlist = forward_range<_G> && forward_range>; // Edge type for range-of-ranges template <_al_adjlist _G> -using _al_edge_t = ranges::range_value_t>; +using _al_edge_t = range_value_t>; template concept _al_simple_id = _al_adjlist<_G> && integral<_al_edge_t<_G>>; template -concept _al_tuple_id = _al_adjlist<_G> && integral>>; +concept _al_tuple_id = _al_adjlist<_G> && integral>>; // // Support the use of std containers, tuple and pair for edgelist definitions (e.g. vector>) // template -concept _el_edgelist = ranges::input_range && !ranges::range>; +concept _el_edgelist = input_range && !range>; // // An edge type cannot be a range, which distinguishes it from an adjacency list // that is a range-of-ranges. // template // For exposition only -concept _el_edge = !ranges::range<_E>; +concept _el_edge = !range<_E>; // // Support the use of std containers for edgelist edge definitions @@ -107,9 +112,9 @@ concept _el_basic_sourced_index_edge_desc = // Tags are defined in tag_invoke namespace to avoid conflicts with function names -// in std::graph, allowing customization for default behavior. +// in graph, allowing customization for default behavior. // -// graphs must use tags like std::graph::tag_invoke::vertex_id_fn_t when defining +// graphs must use tags like graph::tag_invoke::vertex_id_fn_t when defining // CPO specialization. // // Minimal requirements for a graph with random_access vertices(g) @@ -130,7 +135,7 @@ concept _el_basic_sourced_index_edge_desc = template -using graph_reference_t = add_lvalue_reference; +using graph_reference_t = std::add_lvalue_reference; /** @@ -145,7 +150,7 @@ using graph_reference_t = add_lvalue_reference; * template * class my_graph { ... }; * } - * namespace std::graph { + * namespace graph { * template<> * struct is_adjacency_matrix> : true_type; * } @@ -154,7 +159,7 @@ using graph_reference_t = add_lvalue_reference; * @tparam G The graph type */ template -struct define_adjacency_matrix : public false_type {}; // specialized for graph container +struct define_adjacency_matrix : public std::false_type {}; // specialized for graph container template struct is_adjacency_matrix : public define_adjacency_matrix {}; @@ -186,13 +191,13 @@ namespace _Vertices { { _Fake_copy_init(__g.vertices()) }; }; template - concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g) { { _Fake_copy_init(vertices(__g)) }; // intentional ADL }; template - concept _Can_ref_eval = _Has_class_or_enum_type<_G> && ranges::random_access_range<_G>; + concept _Can_ref_eval = _Has_class_or_enum_type<_G> && random_access_range<_G>; class _Cpo { private: @@ -200,7 +205,7 @@ namespace _Vertices { template [[nodiscard]] static consteval _Choice_t<_St_ref> _Choose_ref() noexcept { - static_assert(is_lvalue_reference_v<_G>); + static_assert(std::is_lvalue_reference_v<_G>); if constexpr (_Has_ref_member<_G>) { return {_St_ref::_Member, noexcept(_Fake_copy_init(declval<_G>().vertices()))}; } else if constexpr (_Has_ref_ADL<_G>) { @@ -238,7 +243,7 @@ namespace _Vertices { return __g.vertices(); } else if constexpr (_Strat_ref == _St_ref::_Non_member) { //static_assert(is_reference_v); - return vertices(__g); // intentional ADL + return vertices(__g); // intentional ADL } else if constexpr (_Strat_ref == _St_ref::_Auto_eval) { return std::forward<_G>(__g); // intentional ADL } else { @@ -257,28 +262,28 @@ inline namespace _Cpos { * @tparam G The graph type. */ template -using vertex_range_t = decltype(std::graph::vertices(declval())); +using vertex_range_t = decltype(graph::vertices(std::declval())); /** * @brief The vertex iterator type for a graph G. * @tparam G The graph type. */ template -using vertex_iterator_t = ranges::iterator_t>; +using vertex_iterator_t = iterator_t>; /** * @brief The vertex type for a graph G. * @tparam G The graph type. */ template -using vertex_t = ranges::range_value_t>; +using vertex_t = range_value_t>; /** * @brief The vertex reference type for a graph G. * @tparam G The graph type. */ template -using vertex_reference_t = ranges::range_reference_t>; +using vertex_reference_t = range_reference_t>; // @@ -297,12 +302,12 @@ namespace _Vertex_id { { _Fake_copy_init(ui->vertex_id(__g)) }; }; template - concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, const vertex_iterator_t<_G> ui) { { _Fake_copy_init(vertex_id(__g, ui)) }; // intentional ADL }; template - concept _Can_ref_eval = ranges::random_access_range>; + concept _Can_ref_eval = random_access_range>; class _Cpo { private: @@ -310,7 +315,7 @@ namespace _Vertex_id { template [[nodiscard]] static consteval _Choice_t<_St_ref> _Choose_ref() noexcept { - static_assert(is_lvalue_reference_v<_G>); + static_assert(std::is_lvalue_reference_v<_G>); if constexpr (_Has_ref_member<_G>) { return {_St_ref::_Member, noexcept(_Fake_copy_init(declval>()->vertex_id(declval<_G>())))}; @@ -319,9 +324,8 @@ namespace _Vertex_id { _St_ref::_Non_member, noexcept(_Fake_copy_init(vertex_id(declval<_G>(), declval>())))}; // intentional ADL } else if constexpr (_Can_ref_eval<_G>) { - return {_St_ref::_Auto_eval, - noexcept(_Fake_copy_init(declval>() - - ranges::begin(vertices(declval<_G>()))))}; // intentional ADL + return {_St_ref::_Auto_eval, noexcept(_Fake_copy_init(declval>() - + begin(vertices(declval<_G>()))))}; // intentional ADL } else { return {_St_ref::_None}; } @@ -397,7 +401,7 @@ namespace _Vertex_id { } else if constexpr (_Strat_ref == _St_ref::_Non_member) { return vertex_id(__g, ui); // intentional ADL } else if constexpr (_Strat_ref == _St_ref::_Auto_eval) { - return static_cast<_al_vertex_id_t<_G>>(ui - ranges::begin(vertices(__g))); + return static_cast<_al_vertex_id_t<_G>>(ui - begin(vertices(__g))); } else { static_assert(_Always_false<_G>, "vertices(g) is not defined or is not random-access"); } @@ -452,7 +456,7 @@ struct _vertex_id_type { # endif template -using vertex_id_t = decltype(vertex_id(declval(), declval>())); +using vertex_id_t = decltype(vertex_id(std::declval(), std::declval>())); //template //using vertex_id_t = typename _vertex_id_type::type; @@ -475,7 +479,7 @@ namespace _Find_vertex { }; template - concept _Has_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, const vertex_id_t<_G>& uid) { { _Fake_copy_init(find_vertex(__g, uid)) }; // intentional ADL }; @@ -486,7 +490,7 @@ namespace _Find_vertex { template [[nodiscard]] static consteval _Choice_t<_St> _Choose() noexcept { - static_assert(is_lvalue_reference_v<_G>); + static_assert(std::is_lvalue_reference_v<_G>); if constexpr (_Has_member<_G>) { return {_St::_Member, noexcept(_Fake_copy_init(declval<_G>().find_vertex(declval>())))}; } else if constexpr (_Has_ADL<_G>) { @@ -523,7 +527,7 @@ namespace _Find_vertex { } else if constexpr (_Strat == _St::_Non_member) { return find_vertex(__g, uid); // intentional ADL } else if constexpr (random_access_iterator>) { - auto uid_diff = static_cast>>(uid); + auto uid_diff = static_cast>>(uid); if (uid_diff < ssize(vertices(__g))) return begin(vertices(__g)) + uid_diff; else @@ -562,20 +566,20 @@ namespace _Edges { { _Fake_copy_init(u.edges(__g)) }; }; template - concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, const vertex_reference_t<_G>& u) { { _Fake_copy_init(edges(__g, u)) }; // intentional ADL }; template - concept _Can_ref_eval = _Has_class_or_enum_type<_G> && ranges::forward_range>; + concept _Can_ref_eval = _Has_class_or_enum_type<_G> && forward_range>; template - concept _Has_id_ADL = _Has_class_or_enum_type<_G> // + concept _Has_id_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, const vertex_id_t<_G>& uid) { { _Fake_copy_init(edges(__g, uid)) }; // intentional ADL }; template - concept _Can_id_eval = _Has_class_or_enum_type<_G> && ranges::forward_range> // + concept _Can_id_eval = _Has_class_or_enum_type<_G> && forward_range> // && requires(_G&& __g, vertex_id_t<_G> uid) { { _Fake_copy_init(find_vertex(__g, uid)) }; }; @@ -587,7 +591,7 @@ namespace _Edges { template [[nodiscard]] static consteval _Choice_t<_St_id> _Choose_id() noexcept { - static_assert(is_lvalue_reference_v<_G>); + static_assert(std::is_lvalue_reference_v<_G>); if constexpr (_Has_id_ADL<_G>) { return {_St_id::_Non_member, noexcept(_Fake_copy_init(edges(declval<_G>(), declval>())))}; // intentional ADL @@ -604,7 +608,7 @@ namespace _Edges { template [[nodiscard]] static consteval _Choice_t<_St_ref> _Choose_ref() noexcept { - static_assert(is_lvalue_reference_v<_G>); + static_assert(std::is_lvalue_reference_v<_G>); if constexpr (_Has_ref_member<_G>) { return {_St_ref::_Member, noexcept(_Fake_copy_init(declval>().edges(declval<_G>())))}; } else if constexpr (_Has_ref_ADL<_G>) { @@ -645,7 +649,7 @@ namespace _Edges { } else if constexpr (_Strat_ref == _St_ref::_Non_member) { return edges(__g, u); // intentional ADL } else if constexpr (_Strat_ref == _St_ref::_Auto_eval) { - return u; // default impl + return u; // default impl } else { static_assert(_Always_false<_G>, "edges(g,u) is not defined and the default implementation cannot be evaluated"); @@ -671,7 +675,7 @@ namespace _Edges { constexpr _St_id _Strat_id = _Choice_id<_G&>._Strategy; if constexpr (_Strat_id == _St_id::_Non_member) { - return edges(__g, uid); // intentional ADL + return edges(__g, uid); // intentional ADL } else if constexpr (_Strat_id == _St_id::_Auto_eval) { return *find_vertex(__g, uid); // default impl } else { @@ -698,21 +702,21 @@ using vertex_edge_range_t = decltype(edges(declval(), declval -using vertex_edge_iterator_t = ranges::iterator_t>; +using vertex_edge_iterator_t = iterator_t>; /** * @brief The edge type for graph G. * @tparam G The graph type. */ template -using edge_t = ranges::range_value_t>; +using edge_t = range_value_t>; /** * @brief The edge reference type for graph G. * @tparam G The graph type. */ template -using edge_reference_t = ranges::range_reference_t>; +using edge_reference_t = range_reference_t>; // @@ -731,14 +735,14 @@ namespace _NumEdges { { _Fake_copy_init(__g.num_edges()) }; }; template - concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g) { { _Fake_copy_init(num_edges(__g)) }; // intentional ADL }; template concept _Can_ref_eval = requires(_G&& __g, vertex_t<_G> __u) { { vertices(__g) }; - { _Fake_copy_init(ranges::distance(edges(__g, __u))) }; + { _Fake_copy_init(std::ranges::distance(edges(__g, __u))) }; }; class _Cpo { @@ -748,14 +752,14 @@ namespace _NumEdges { template [[nodiscard]] static consteval _Choice_t<_St_ref> _Choose_ref() noexcept { - static_assert(is_lvalue_reference_v<_G>); + static_assert(std::is_lvalue_reference_v<_G>); if constexpr (_Has_ref_member<_G>) { return {_St_ref::_Member, noexcept(_Fake_copy_init(declval<_G>().num_edges()))}; } else if constexpr (_Has_ref_ADL<_G>) { return {_St_ref::_Non_member, noexcept(_Fake_copy_init(num_edges(declval<_G>())))}; // intentional ADL } else if constexpr (_Can_ref_eval<_G>) { - return {_St_ref::_Auto_eval, - noexcept(_Fake_copy_init(ranges::distance(edges(declval<_G>(), declval>()))))}; + return {_St_ref::_Auto_eval, noexcept(_Fake_copy_init(std::ranges::distance( + edges(declval<_G>(), declval>()))))}; } else { return {_St_ref::_None}; } @@ -792,10 +796,10 @@ namespace _NumEdges { } else if constexpr (_Strat_id == _St_ref::_Non_member) { return num_edges(__g); // intentional ADL } else if constexpr (_Strat_id == _St_ref::_Auto_eval) { - using size_type = decltype(ranges::distance(edges(__g, declval>()))); + using size_type = decltype(std::ranges::distance(edges(__g, declval>()))); size_type n = 0; // default impl for (auto&& u : vertices(__g)) - n += ranges::distance(edges(__g, u)); + n += std::ranges::distance(edges(__g, u)); return n; } else { static_assert(_Always_false<_G>, @@ -857,7 +861,7 @@ namespace _Target_id { template [[nodiscard]] static consteval _Choice_t<_St_adjl_ref> _Choose_adjl_ref() noexcept { - static_assert(is_lvalue_reference_v<_G>); + static_assert(std::is_lvalue_reference_v<_G>); if constexpr (_Has_adjl_ref_member<_G>) { return {_St_adjl_ref::_Member, @@ -886,7 +890,7 @@ namespace _Target_id { template [[nodiscard]] static consteval _Choice_t<_St_edgl_ref> _Choose_edgl_ref() noexcept { - //static_assert(is_lvalue_reference_v<_E>); + //static_assert(std::is_lvalue_reference_v<_E>); if constexpr (_Has_edgl_ref_member<_E>) { return {_St_edgl_ref::_Member, noexcept(_Fake_copy_init(declval<_E&>().target_id()))}; @@ -1019,7 +1023,7 @@ namespace _Source_id { { _Fake_copy_init(uv.source_id(__g)) }; }; template - concept _Has_adjl_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_adjl_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, const edge_reference_t<_G>& uv) { { _Fake_copy_init(source_id(__g, uv)) }; // intentional ADL }; @@ -1029,7 +1033,7 @@ namespace _Source_id { { _Fake_copy_init(__e.source_id()) }; }; template - concept _Has_edgl_ref_ADL = _Has_class_or_enum_type<_E> // + concept _Has_edgl_ref_ADL = _Has_class_or_enum_type<_E> // && requires(_E&& __e) { { _Fake_copy_init(source_id(__e)) }; // intentional ADL }; @@ -1046,7 +1050,7 @@ namespace _Source_id { template [[nodiscard]] static consteval _Choice_t<_St_adjl_ref> _Choose_adjl_ref() noexcept { - static_assert(is_lvalue_reference_v<_G>); + static_assert(std::is_lvalue_reference_v<_G>); if constexpr (_Has_adjl_ref_member<_G>) { return {_St_adjl_ref::_Member, noexcept(_Fake_copy_init(declval>().source_id(declval<_G>())))}; @@ -1066,7 +1070,7 @@ namespace _Source_id { template [[nodiscard]] static consteval _Choice_t<_St_edgl_ref> _Choose_edgl_ref() noexcept { - //static_assert(is_lvalue_reference_v<_E>); + //static_assert(std::is_lvalue_reference_v<_E>); if constexpr (_Has_edgl_ref_member<_E>) { return {_St_edgl_ref::_Member, noexcept(_Fake_copy_init(declval<_E>().source_id()))}; } else if constexpr (_Has_edgl_ref_ADL<_E>) { @@ -1138,7 +1142,7 @@ namespace _Source_id { } else if constexpr (_Strat_ref == _St_edgl_ref::_Non_member) { return source_id(__e); // intentional ADL } else if constexpr (_Strat_ref == _St_edgl_ref::_Tuple_id) { - return get<1>(__e); // first element of tuple/pair + return get<1>(__e); // first element of tuple/pair } else if constexpr (_Strat_ref == _St_edgl_ref::_EDesc_id) { return __e.source_id; } else { @@ -1175,12 +1179,12 @@ namespace _Target { # endif // ^^^ workaround ^^^ template - concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, const edge_reference_t<_G>& uv) { { _Fake_copy_init(target(__g, uv)) }; // intentional ADL }; template - concept _Can_ref_eval = ranges::random_access_range> // + concept _Can_ref_eval = random_access_range> // && requires(_G&& __g, edge_reference_t<_G> uv, vertex_id_t<_G> uid) { { _Fake_copy_init(find_vertex(__g, uid)) }; { _Fake_copy_init(target_id(__g, uv)) } -> integral; @@ -1192,7 +1196,7 @@ namespace _Target { template [[nodiscard]] static consteval _Choice_t<_St_ref> _Choose_ref() noexcept { - static_assert(is_lvalue_reference_v<_G>); + static_assert(std::is_lvalue_reference_v<_G>); if constexpr (_Has_ref_ADL<_G>) { return {_St_ref::_Non_member, @@ -1259,12 +1263,12 @@ namespace _Source { # endif // ^^^ workaround ^^^ template - concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, const edge_reference_t<_G>& uv) { { _Fake_copy_init(source(__g, uv)) }; // intentional ADL }; template - concept _Can_ref_eval = ranges::random_access_range> // + concept _Can_ref_eval = random_access_range> // && requires(_G&& __g, edge_reference_t<_G> uv) { { _Fake_copy_init(source_id(__g, uv)) } -> integral; }; @@ -1275,7 +1279,7 @@ namespace _Source { template [[nodiscard]] static consteval _Choice_t<_St_ref> _Choose_ref() noexcept { - static_assert(is_lvalue_reference_v<_G>); + static_assert(std::is_lvalue_reference_v<_G>); if constexpr (_Has_ref_ADL<_G>) { return {_St_ref::_Non_member, noexcept(_Fake_copy_init(source(declval<_G>(), declval>())))}; // intentional ADL @@ -1352,7 +1356,7 @@ namespace _Find_vertex_edge { }; template - concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, vertex_reference_t<_G> u, const vertex_id_t<_G>& vid) { { _Fake_copy_init(find_vertex_edge(__g, u, vid)) }; // intentional ADL }; @@ -1363,7 +1367,7 @@ namespace _Find_vertex_edge { }; template - concept _Has_id_ADL = _Has_class_or_enum_type<_G> // + concept _Has_id_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, vertex_id_t<_G> uid, const vertex_id_t<_G>& vid) { { _Fake_copy_init(find_vertex_edge(__g, uid, vid)) }; // intentional ADL }; @@ -1380,7 +1384,7 @@ namespace _Find_vertex_edge { template [[nodiscard]] static consteval _Choice_t<_St_ref> _Choose_ref() noexcept { - static_assert(is_lvalue_reference_v<_G>); + static_assert(std::is_lvalue_reference_v<_G>); if constexpr (_Has_ref_member<_G>) { return {_St_ref::_Member, noexcept(_Fake_copy_init(declval>().find_vertex_edge( declval<_G>(), declval>())))}; @@ -1391,8 +1395,8 @@ namespace _Find_vertex_edge { } else if constexpr (_Can_ref_eval<_G>) { using fnc_find_t = decltype([](edge_reference_t<_G>) -> bool { return true; }); return {_St_ref::_Auto_eval, - noexcept(_Fake_copy_init(ranges::find_if(edges(declval<_G>(), declval>()), - declval())))}; // intentional ADL + noexcept(_Fake_copy_init(std::ranges::find_if(edges(declval<_G>(), declval>()), + declval())))}; // intentional ADL } else { return {_St_ref::_None}; } @@ -1403,7 +1407,7 @@ namespace _Find_vertex_edge { template [[nodiscard]] static consteval _Choice_t<_St_id> _Choose_id() noexcept { - static_assert(is_lvalue_reference_v<_G>); + static_assert(std::is_lvalue_reference_v<_G>); if constexpr (_Has_id_ADL<_G>) { return {_St_id::_Non_member, noexcept(_Fake_copy_init(find_vertex_edge(declval<_G>(), declval>(), @@ -1411,8 +1415,8 @@ namespace _Find_vertex_edge { } else if constexpr (_Can_id_eval<_G>) { using fnc_find_t = decltype([](edge_reference_t<_G>) -> bool { return true; }); return {_St_id::_Auto_eval, - noexcept(_Fake_copy_init(ranges::find_if(edges(declval<_G>(), declval>()), - declval())))}; // intentional ADL + noexcept(_Fake_copy_init(std::ranges::find_if(edges(declval<_G>(), declval>()), + declval())))}; // intentional ADL } else { return {_St_id::_None}; } @@ -1445,7 +1449,7 @@ namespace _Find_vertex_edge { } else if constexpr (_Strat == _St_ref::_Non_member) { return find_vertex_edge(__g, u, vid); // intentional ADL } else if constexpr (_Strat == _St_ref::_Auto_eval) { - return ranges::find_if(edges(__g, u), [&__g, &vid](auto&& uv) { return target_id(__g, uv) == vid; }); + return std::ranges::find_if(edges(__g, u), [&__g, &vid](auto&& uv) { return target_id(__g, uv) == vid; }); } else { static_assert(_Always_false<_G>, "find_vertex_edge(g,uid) has not been defined and the default implemenation cannot be evaluated"); @@ -1473,7 +1477,7 @@ namespace _Find_vertex_edge { if constexpr (_Strat == _St_id::_Non_member) { return find_vertex_edge(__g, uid, uid); // intentional ADL } else if constexpr (_Strat == _St_id::_Auto_eval) { - return ranges::find_if(edges(__g, uid), [&__g, &vid](auto&& uv) { return target_id(__g, uv) == vid; }); + return std::ranges::find_if(edges(__g, uid), [&__g, &vid](auto&& uv) { return target_id(__g, uv) == vid; }); } else { static_assert(_Always_false<_G>, "find_vertex_edge(g,uid) has not been defined and the default implemenation cannot be evaluated"); @@ -1490,7 +1494,7 @@ inline namespace _Cpos { // // contains_edge(g,uid,vid) -> bool // default = uid < size(vertices(g)) && vid < size(vertices(g)), if adjacency_matrix -// = find_vertex_edge(g,uid) != ranges::end(edges(g,uid)); +// = find_vertex_edge(g,uid) != end(edges(g,uid)); // namespace _Contains_edge { # if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-1681199 @@ -1500,14 +1504,14 @@ namespace _Contains_edge { # endif // ^^^ workaround ^^^ template - concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, const vertex_id_t<_G>& uid, const vertex_id_t<_G>& vid) { { _Fake_copy_init(contains_edge(__g, uid, vid)) }; // intentional ADL }; template concept _Can_matrix_eval = _Has_class_or_enum_type<_G> && is_adjacency_matrix_v<_G> // - && ranges::sized_range>; + && sized_range>; template concept _Can_id_eval = _Has_class_or_enum_type<_G> // @@ -1522,14 +1526,14 @@ namespace _Contains_edge { template [[nodiscard]] static consteval _Choice_t<_St_ref> _Choose_ref() noexcept { - static_assert(is_lvalue_reference_v<_G>); + static_assert(std::is_lvalue_reference_v<_G>); if constexpr (_Has_ref_ADL<_G>) { return {_St_ref::_Non_member, noexcept(_Fake_copy_init(contains_edge(declval<_G>(), declval>(), declval>())))}; // intentional ADL } else if constexpr (_Can_matrix_eval<_G>) { return {_St_ref::_Matrix_eval, - noexcept(_Fake_copy_init(declval>() < ranges::size(vertices(declval<_G>()))))}; + noexcept(_Fake_copy_init(declval>() < size(vertices(declval<_G>()))))}; } else if constexpr (_Can_id_eval<_G>) { return {_St_ref::_Auto_eval, noexcept(_Fake_copy_init( @@ -1550,8 +1554,8 @@ namespace _Contains_edge { * Complexity: O(1) * * Default implementation: - * uid < ranges::size(vertices(__g)) && vid < ranges::size(vertices(__g)), if is_adjacency_matrix_v<_G> - * find_vertex_edge(g, uid) != ranges::end(edges(g, uid)), otherwise + * uid < size(vertices(__g)) && vid < size(vertices(__g)), if is_adjacency_matrix_v<_G> + * find_vertex_edge(g, uid) != end(edges(g, uid)), otherwise * * @tparam G The graph type. * @param g A graph instance. @@ -1567,10 +1571,10 @@ namespace _Contains_edge { if constexpr (_Strat_ref == _St_ref::_Non_member) { return contains_edge(__g, uid, vid); // intentional ADL } else if constexpr (_Strat_ref == _St_ref::_Matrix_eval) { - return uid < ranges::size(vertices(__g)) && vid < ranges::size(vertices(__g)); + return uid < size(vertices(__g)) && vid < size(vertices(__g)); } else if constexpr (_Strat_ref == _St_ref::_Auto_eval) { auto ui = find_vertex(__g, uid); - return find_vertex_edge(__g, *ui, vid) != ranges::end(edges(__g, *ui)); + return find_vertex_edge(__g, *ui, vid) != end(edges(__g, *ui)); } else { static_assert(_Always_false<_G>, "contains_edge(g,uv) is not defined, or find_vertex_(g,uid) and source_id(g,uv) are not defined"); @@ -1599,7 +1603,7 @@ namespace _Partition_id { { _Fake_copy_init(u.partition_id(__g)) }; }; template - concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, const vertex_reference_t<_G>& u) { { _Fake_copy_init(partition_id(__g, u)) }; // intentional ADL }; @@ -1610,7 +1614,7 @@ namespace _Partition_id { }; template - concept _Has_id_ADL = _Has_class_or_enum_type<_G> // + concept _Has_id_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, const vertex_id_t<_G>& uid) { { _Fake_copy_init(partition_id(__g, uid)) }; // intentional ADL }; @@ -1627,12 +1631,12 @@ namespace _Partition_id { template [[nodiscard]] static consteval _Choice_t<_St_id> _Choose_id() noexcept { - static_assert(is_lvalue_reference_v<_G>); + static_assert(std::is_lvalue_reference_v<_G>); if constexpr (_Has_id_ADL<_G>) { return {_St_id::_Non_member, noexcept(_Fake_copy_init(partition_id(declval<_G>(), declval>())))}; // intentional ADL } else if constexpr (_Can_id_eval<_G>) { - return {_St_id::_Auto_eval, noexcept(_Fake_copy_init(vertex_id_t<_G>(0)))}; // default impl + return {_St_id::_Auto_eval, noexcept(_Fake_copy_init(vertex_id_t<_G>(0)))}; // default impl } else { return {_St_id::_None}; } @@ -1643,7 +1647,7 @@ namespace _Partition_id { template [[nodiscard]] static consteval _Choice_t<_St_ref> _Choose_ref() noexcept { - static_assert(is_lvalue_reference_v<_G>); + static_assert(std::is_lvalue_reference_v<_G>); if constexpr (_Has_ref_member<_G>) { return {_St_ref::_Member, noexcept(_Fake_copy_init(declval>().partition_id(declval<_G>())))}; @@ -1684,7 +1688,7 @@ namespace _Partition_id { } else if constexpr (_Strat_ref == _St_ref::_Non_member) { return partition_id(__g, u); // intentional ADL } else if constexpr (_Strat_ref == _St_ref::_Auto_eval) { - return vertex_id_t<_G>{0}; // default impl + return vertex_id_t<_G>{0}; // default impl } else { static_assert(_Always_false<_G>, "partition_id(g,u) is not defined and the default implementation cannot be evaluated"); @@ -1712,7 +1716,7 @@ namespace _Partition_id { if constexpr (_Strat_id == _St_id::_Non_member) { return partition_id(__g, uid); // intentional ADL } else if constexpr (_Strat_id == _St_id::_Auto_eval) { - return vertex_id_t<_G>{0}; // default impl + return vertex_id_t<_G>{0}; // default impl } else { static_assert(_Always_false<_G>, "partition_id(g,uid) is not defined and the default implementation cannot be evaluated"); @@ -1745,25 +1749,25 @@ namespace _NumVertices { { _Fake_copy_init(__g.num_vertices(__g)) }; }; template - concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g) { { _Fake_copy_init(num_vertices(__g)) }; // intentional ADL }; template - concept _Can_ref_eval = ranges::sized_range> // + concept _Can_ref_eval = sized_range> // && requires(_G&& __g) { - { _Fake_copy_init(ranges::size(vertices(__g))) }; + { _Fake_copy_init(size(vertices(__g))) }; }; template - concept _Has_id_ADL = _Has_class_or_enum_type<_G> // + concept _Has_id_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, partition_id_t<_G> pid) { { _Fake_copy_init(num_vertices(__g, pid)) }; // intentional ADL }; template - concept _Can_id_eval = ranges::sized_range> // + concept _Can_id_eval = sized_range> // && requires(_G&& __g, partition_id_t<_G> pid) { - { _Fake_copy_init(ranges::size(vertices(__g, pid))) }; + { _Fake_copy_init(size(vertices(__g, pid))) }; }; class _Cpo { @@ -1773,13 +1777,13 @@ namespace _NumVertices { template [[nodiscard]] static consteval _Choice_t<_St_ref> _Choose_ref() noexcept { - static_assert(is_lvalue_reference_v<_G>); + static_assert(std::is_lvalue_reference_v<_G>); if constexpr (_Has_ref_member<_G>) { return {_St_ref::_Member, noexcept(_Fake_copy_init(declval<_G>().num_vertices()))}; } else if constexpr (_Has_ref_ADL<_G>) { return {_St_ref::_Non_member, noexcept(_Fake_copy_init(num_vertices(declval<_G>())))}; // intentional ADL } else if constexpr (_Can_ref_eval<_G>) { - return {_St_ref::_Auto_eval, noexcept(_Fake_copy_init(ranges::size(vertices(declval<_G>()))))}; + return {_St_ref::_Auto_eval, noexcept(_Fake_copy_init(size(vertices(declval<_G>()))))}; } else { return {_St_ref::_None}; } @@ -1790,14 +1794,15 @@ namespace _NumVertices { template [[nodiscard]] static consteval _Choice_t<_St_id> _Choose_id() noexcept { - static_assert(is_lvalue_reference_v<_G>); + static_assert(std::is_lvalue_reference_v<_G>); if constexpr (_Has_id_ADL<_G>) { return { _St_id::_Non_member, noexcept(_Fake_copy_init(num_vertices(declval<_G>(), declval>())))}; // intentional ADL } else if constexpr (_Can_id_eval<_G>) { - return {_St_id::_Auto_eval, noexcept(_Fake_copy_init(ranges::size( - vertices(declval<_G>(), declval>()))))}; // default impl + return { + _St_id::_Auto_eval, + noexcept(_Fake_copy_init(size(vertices(declval<_G>(), declval>()))))}; // default impl } else { return {_St_id::_None}; } @@ -1827,9 +1832,9 @@ namespace _NumVertices { static_assert(_Strat_id == _St_id::_Auto_eval); if constexpr (_Strat_id == _St_id::_Non_member) { - return num_vertices(__g, pid); // intentional ADL + return num_vertices(__g, pid); // intentional ADL } else if constexpr (_Strat_id == _St_id::_Auto_eval) { - return ranges::size(vertices(__g, pid)); // default impl + return size(vertices(__g, pid)); // default impl } else { static_assert(_Always_false<_G>, "num_vertices(g,pid) is not defined and the default implementation cannot be evaluated"); @@ -1855,9 +1860,9 @@ namespace _NumVertices { if constexpr (_Strat_id == _St_ref::_Member) { return __g.num_vertices(); } else if constexpr (_Strat_id == _St_ref::_Non_member) { - return num_vertices(__g); // intentional ADL + return num_vertices(__g); // intentional ADL } else if constexpr (_Strat_id == _St_ref::_Auto_eval) { - return ranges::size(vertices(__g)); // default impl + return size(vertices(__g)); // default impl } else { static_assert(_Always_false<_G>, "num_vertices(g) is not defined and the default implementation cannot be evaluated"); @@ -1886,23 +1891,23 @@ namespace _Degree { { _Fake_copy_init(u.degree(__g)) }; }; template - concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, const vertex_reference_t<_G>& u) { { _Fake_copy_init(degree(__g, u)) }; // intentional ADL }; template - concept _Can_ref_eval = ranges::sized_range> // + concept _Can_ref_eval = sized_range> // && requires(_G&& __g, vertex_reference_t<_G> u) { { _Fake_copy_init(edges(__g, u)) }; }; template - concept _Has_id_ADL = _Has_class_or_enum_type<_G> // + concept _Has_id_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, const vertex_id_t<_G>& uid) { { _Fake_copy_init(degree(__g, uid)) }; // intentional ADL }; template - concept _Can_id_eval = ranges::sized_range> // + concept _Can_id_eval = sized_range> // && requires(_G&& __g, vertex_id_t<_G>& uid) { { _Fake_copy_init(edges(__g, uid)) }; }; @@ -1914,13 +1919,13 @@ namespace _Degree { template [[nodiscard]] static consteval _Choice_t<_St_id> _Choose_id() noexcept { - static_assert(is_lvalue_reference_v<_G>); + static_assert(std::is_lvalue_reference_v<_G>); if constexpr (_Has_id_ADL<_G>) { return {_St_id::_Non_member, noexcept(_Fake_copy_init(degree(declval<_G>(), declval>())))}; // intentional ADL } else if constexpr (_Can_id_eval<_G>) { - return {_St_id::_Auto_eval, noexcept(_Fake_copy_init(ranges::size( - edges(declval<_G>(), declval>()))))}; // default impl + return {_St_id::_Auto_eval, + noexcept(_Fake_copy_init(size(edges(declval<_G>(), declval>()))))}; // default impl } else { return {_St_id::_None}; } @@ -1931,7 +1936,7 @@ namespace _Degree { template [[nodiscard]] static consteval _Choice_t<_St_ref> _Choose_ref() noexcept { - static_assert(is_lvalue_reference_v<_G>); + static_assert(std::is_lvalue_reference_v<_G>); if constexpr (_Has_ref_member<_G>) { return {_St_ref::_Member, noexcept(_Fake_copy_init(declval>().degree(declval<_G>())))}; } else if constexpr (_Has_ref_ADL<_G>) { @@ -1939,7 +1944,7 @@ namespace _Degree { noexcept(_Fake_copy_init(degree(declval<_G>(), declval>())))}; // intentional ADL } else if constexpr (_Can_ref_eval<_G>) { return {_St_ref::_Auto_eval, - noexcept(_Fake_copy_init(ranges::size(edges(declval<_G>(), declval>()))))}; + noexcept(_Fake_copy_init(size(edges(declval<_G>(), declval>()))))}; } else { return {_St_ref::_None}; } @@ -1970,9 +1975,9 @@ namespace _Degree { if constexpr (_Strat_ref == _St_ref::_Member) { return u.degree(__g); } else if constexpr (_Strat_ref == _St_ref::_Non_member) { - return degree(__g, u); // intentional ADL + return degree(__g, u); // intentional ADL } else if constexpr (_Strat_ref == _St_ref::_Auto_eval) { - return ranges::size(edges(__g, u)); // default impl + return size(edges(__g, u)); // default impl } else { static_assert(_Always_false<_G>, "degree(g,u) is not defined and the default implementation cannot be evaluated"); @@ -1998,9 +2003,9 @@ namespace _Degree { constexpr _St_id _Strat_id = _Choice_id<_G&>._Strategy; if constexpr (_Strat_id == _St_id::_Non_member) { - return degree(__g, uid); // intentional ADL + return degree(__g, uid); // intentional ADL } else if constexpr (_Strat_id == _St_id::_Auto_eval) { - return ranges::size(edges(__g, uid)); // default impl + return size(edges(__g, uid)); // default impl } else { static_assert(_Always_false<_G>, "degree(g,uid) is not defined and the default implementation cannot be evaluated"); @@ -2031,7 +2036,7 @@ namespace _Vertex_value { { _Fake_copy_init(u.vertex_value(__g)) }; }; template - concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, vertex_reference_t<_G> u) { { _Fake_copy_init(vertex_value(__g, u)) }; // intentional ADL }; @@ -2042,7 +2047,7 @@ namespace _Vertex_value { template [[nodiscard]] static consteval _Choice_t<_St_ref> _Choose_ref() noexcept { - static_assert(is_lvalue_reference_v<_G>); + static_assert(std::is_lvalue_reference_v<_G>); if constexpr (_Has_ref_member<_G>) { return {_St_ref::_Member, noexcept(_Fake_copy_init(declval>().vertex_value( declval>())))}; @@ -2111,13 +2116,13 @@ namespace _Edge_value { { _Fake_copy_init(uv.edge_value(__g)) }; }; template - concept _Has_adjl_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_adjl_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g, edge_reference_t<_G> uv) { { _Fake_copy_init(edge_value(__g, uv)) }; // intentional ADL }; template concept _Can_adjl_ref_eval = - _Has_class_or_enum_type<_G> && ranges::forward_range> // + _Has_class_or_enum_type<_G> && forward_range> // && requires(edge_reference_t<_G> uv) { uv; }; // vertex is just a range, and edge type defined? @@ -2126,7 +2131,7 @@ namespace _Edge_value { { _Fake_copy_init(__e.edge_value()) }; }; template - concept _Has_edgl_ref_ADL = _Has_class_or_enum_type<_E> // + concept _Has_edgl_ref_ADL = _Has_class_or_enum_type<_E> // && requires(_E&& __e) { { _Fake_copy_init(edge_value(__e)) }; // intentional ADL }; @@ -2145,7 +2150,7 @@ namespace _Edge_value { template [[nodiscard]] static consteval _Choice_t<_St_adjl_ref> _Choose_adjl_ref() noexcept { - static_assert(is_lvalue_reference_v<_G>); + static_assert(std::is_lvalue_reference_v<_G>); if constexpr (_Has_adjl_ref_member<_G>) { return { _St_adjl_ref::_Member, @@ -2169,7 +2174,7 @@ namespace _Edge_value { template [[nodiscard]] static consteval _Choice_t<_St_edgl_ref> _Choose_edgl_ref() noexcept { - //static_assert(is_lvalue_reference_v<_E>); + //static_assert(std::is_lvalue_reference_v<_E>); if constexpr (_Has_edgl_ref_member<_E>) { return {_St_edgl_ref::_Member, noexcept(_Fake_copy_init(declval<_E>().edge_value()))}; } else if constexpr (_Has_edgl_ref_ADL<_E>) { @@ -2215,7 +2220,7 @@ namespace _Edge_value { } else if constexpr (_Strat_ref == _St_adjl_ref::_Non_member) { return edge_value(__g, uv); // intentional ADL } else if constexpr (_Strat_ref == _St_adjl_ref::_Auto_eval) { - return uv; // intentional ADL + return uv; // intentional ADL } else { static_assert(_Always_false<_G>, "edge_value(g,uv) must be defined for the graph"); } @@ -2244,7 +2249,7 @@ namespace _Edge_value { } else if constexpr (_Strat_ref == _St_edgl_ref::_Non_member) { return edge_value(__e); // intentional ADL } else if constexpr (_Strat_ref == _St_edgl_ref::_Tuple_id) { - return get<2>(__e); // first element of tuple/pair + return get<2>(__e); // first element of tuple/pair } else if constexpr (_Strat_ref == _St_edgl_ref::_EDesc_id) { return __e.value; } else { @@ -2291,7 +2296,7 @@ namespace _Graph_value { { _Fake_copy_init(__g.graph_value()) }; }; template - concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g) { { _Fake_copy_init(graph_value(__g)) }; // intentional ADL }; @@ -2302,7 +2307,7 @@ namespace _Graph_value { template [[nodiscard]] static consteval _Choice_t<_St_ref> _Choose_ref() noexcept { - static_assert(is_lvalue_reference_v<_G>); + static_assert(std::is_lvalue_reference_v<_G>); if constexpr (_Has_ref_member<_G>) { return {_St_ref::_Member, noexcept(_Fake_copy_init(declval>().graph_value()))}; } else if constexpr (_Has_ref_ADL<_G>) { @@ -2363,7 +2368,7 @@ namespace _Num_partitions { { _Fake_copy_init(__g.num_partitions()) }; }; template - concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g) { { _Fake_copy_init(num_partitions(__g)) }; // intentional ADL }; @@ -2379,7 +2384,7 @@ namespace _Num_partitions { template [[nodiscard]] static consteval _Choice_t<_St_ref> _Choose_ref() noexcept { - static_assert(is_lvalue_reference_v<_G>); + static_assert(std::is_lvalue_reference_v<_G>); if constexpr (_Has_ref_member<_G>) { return {_St_ref::_Member, noexcept(_Fake_copy_init(declval<_G>().num_partitions()))}; } else if constexpr (_Has_ref_ADL<_G>) { @@ -2417,7 +2422,7 @@ namespace _Num_partitions { } else if constexpr (_Strat_ref == _St_ref::_Non_member) { return num_partitions(__g); // intentional ADL } else if constexpr (_Strat_ref == _St_ref::_Auto_eval) { - return vertex_id_t<_G>(1); // default impl + return vertex_id_t<_G>(1); // default impl } else { static_assert(_Always_false<_G>, "num_partitions(g) is not defined and the default implementation cannot be evaluated"); @@ -2447,14 +2452,14 @@ namespace _HasEdge { { _Fake_copy_init(__g.has_edge()) }; }; template - concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // + concept _Has_ref_ADL = _Has_class_or_enum_type<_G> // && requires(_G&& __g) { { _Fake_copy_init(has_edge(__g)) }; // intentional ADL }; template concept _Can_ref_eval = requires(_G&& __g, vertex_t<_G> __u) { { vertices(__g) }; - { _Fake_copy_init(ranges::empty(edges(__g, __u))) }; + { _Fake_copy_init(empty(edges(__g, __u))) }; }; // This is for edges(g, pid) which is not defined in the proposal. @@ -2478,14 +2483,14 @@ namespace _HasEdge { template [[nodiscard]] static consteval _Choice_t<_St_ref> _Choose_ref() noexcept { - static_assert(is_lvalue_reference_v<_G>); + static_assert(std::is_lvalue_reference_v<_G>); if constexpr (_Has_ref_member<_G>) { return {_St_ref::_Member, noexcept(_Fake_copy_init(declval<_G>().has_edge()))}; } else if constexpr (_Has_ref_ADL<_G>) { return {_St_ref::_Non_member, noexcept(_Fake_copy_init(has_edge(declval<_G>())))}; // intentional ADL } else if constexpr (_Can_ref_eval<_G>) { return {_St_ref::_Auto_eval, - noexcept(_Fake_copy_init(ranges::empty(edges(declval<_G>(), declval>()))))}; + noexcept(_Fake_copy_init(empty(edges(declval<_G>(), declval>()))))}; } else { return {_St_ref::_None}; } @@ -2496,7 +2501,7 @@ namespace _HasEdge { //template //[[nodiscard]] static consteval _Choice_t<_St_id> _Choose_id() noexcept { - // static_assert(is_lvalue_reference_v<_G>); + // static_assert(std::is_lvalue_reference_v<_G>); // if constexpr (_Has_id_ADL<_G>) { // return { // _St_id::_Non_member, @@ -2540,7 +2545,7 @@ namespace _HasEdge { return has_edge(__g); // intentional ADL } else if constexpr (_Strat_id == _St_ref::_Auto_eval) { for (auto&& u : vertices(__g)) - if (ranges::empty(edges(__g, u))) + if (empty(edges(__g, u))) return true; return false; } else { @@ -2571,7 +2576,7 @@ namespace _HasEdge { // if constexpr (_Strat_id == _St_id::_Non_member) { // return has_edge(__g, pid); // intentional ADL // } else if constexpr (_Strat_id == _St_id::_Auto_eval) { - // return ranges::size(vertices(__g, pid)); // default impl + // return size(vertices(__g, pid)); // default impl // } else { // static_assert(_Always_false<_G>, // "has_edge(g,pid) is not defined and the default implementation cannot be evaluated"); @@ -2585,6 +2590,6 @@ inline namespace _Cpos { } -} // namespace std::graph +} // namespace graph #endif //GRAPH_CPO_HPP diff --git a/include/graph/detail/graph_using.hpp b/include/graph/detail/graph_using.hpp new file mode 100644 index 0000000..d5e1d20 --- /dev/null +++ b/include/graph/detail/graph_using.hpp @@ -0,0 +1,92 @@ +#pragma once +#include +#include +#include +#include + +namespace graph { +// Containers are not included to avoid potential conflicts: vector, list, string, etc. + +// common types +using std::pair; +using std::tuple; +using std::tuple_element_t; +using std::tuple_size_v; +using std::reference_wrapper; +using std::forward_iterator_tag; +using std::plus; +using std::less; +using std::declval; + +// type traits +using std::is_arithmetic_v; +using std::is_convertible_v; +using std::is_same_v; + +using std::remove_cv_t; +using std::remove_const_t; +using std::remove_volatile_t; +using std::remove_reference_t; +using std::remove_pointer_t; +using std::remove_cvref_t; +using std::is_arithmetic_v; +using std::is_void_v; + +// concepts +using std::same_as; +using std::convertible_to; +using std::integral; +using std::invoke_result; +using std::invoke_result_t; +using std::invocable; +using std::regular_invocable; + +// range concepts +using std::ranges::range; +using std::ranges::sized_range; +using std::ranges::input_range; +using std::ranges::output_range; +using std::ranges::forward_range; +using std::ranges::bidirectional_range; +using std::ranges::random_access_range; +using std::ranges::contiguous_range; +using std::ranges::common_range; + +// iterator concepts +using std::input_iterator; +using std::output_iterator; +using std::forward_iterator; +using std::bidirectional_iterator; +using std::random_access_iterator; +using std::contiguous_iterator; + +// range types +using std::identity; +using std::ranges::subrange; + +using std::ranges::iterator_t; +using std::ranges::sentinel_t; +//using std::ranges::const_iterator_t; // C++23 +//using std::ranges::const_sentinel_t; // C++23 + +using std::ranges::range_difference_t; +using std::ranges::range_size_t; +using std::ranges::range_value_t; + +using std::ranges::range_reference_t; +using std::ranges::range_rvalue_reference_t; +//using std::ranges::range_const_reference_t; // C++23 +//using std::ranges::range_common_reference_t; // not in gcc-13 for C++20 + +// utility functions +using std::move; +using std::forward; +using std::ranges::begin; +using std::ranges::end; +using std::ranges::size; +using std::ranges::ssize; +using std::ranges::empty; +using std::tuple_cat; +using std::max; +using std::min; +} // namespace graph diff --git a/include/graph/edgelist.hpp b/include/graph/edgelist.hpp index 8e46d89..42803c2 100644 --- a/include/graph/edgelist.hpp +++ b/include/graph/edgelist.hpp @@ -70,30 +70,30 @@ // EV val Edge Value // -// merge implementation into std::graph with single namespace? +// merge implementation into graph with single namespace? // Issues: // 1. name conflict with edgelist view? No: basic_sourced_edgelist vs. views::edgelist. // 2. template aliases can't be distinguished by concepts // 3. vertex_id_t definition for adjlist and edgelist have be done in separate locations -namespace std::graph { +namespace graph { namespace edgelist { // // edgelist concepts // - template // For exposition only - concept basic_sourced_edgelist = ranges::input_range && // - !ranges::range> && // distinguish from adjacency list - requires(ranges::range_value_t e) { + template // For exposition only + concept basic_sourced_edgelist = input_range && // + !range> && // distinguish from adjacency list + requires(range_value_t e) { { source_id(e) }; { target_id(e) } -> same_as; }; template // For exposition only concept basic_sourced_index_edgelist = basic_sourced_edgelist && // - requires(ranges::range_value_t e) { + requires(range_value_t e) { { source_id(e) } -> integral; { target_id(e) } -> integral; // this is redundant, but makes it clear }; @@ -102,12 +102,12 @@ namespace edgelist { template // For exposition only concept has_edge_value = basic_sourced_edgelist && // - requires(ranges::range_value_t e) { + requires(range_value_t e) { { edge_value(e) }; }; template - struct is_directed : public false_type {}; // specialized for graph container + struct is_directed : public std::false_type {}; // specialized for graph container template inline constexpr bool is_directed_v = is_directed::value; @@ -120,13 +120,13 @@ namespace edgelist { using edge_range_t = EL; template // For exposition only - using edge_iterator_t = ranges::iterator_t>; + using edge_iterator_t = iterator_t>; template // For exposition only - using edge_t = ranges::range_value_t>; + using edge_t = range_value_t>; template // For exposition only - using edge_reference_t = ranges::range_reference_t>; + using edge_reference_t = range_reference_t>; template // For exposition only using edge_value_t = decltype(edge_value(declval>>())); @@ -144,6 +144,6 @@ namespace edgelist { //using vid_t = decltype(source_id(declval>())); } // namespace edgelist -} // namespace std::graph +} // namespace graph #endif diff --git a/include/graph/graph.hpp b/include/graph/graph.hpp index b2c2a6d..40b46b3 100644 --- a/include/graph/graph.hpp +++ b/include/graph/graph.hpp @@ -57,7 +57,7 @@ #ifndef GRAPH_HPP # define GRAPH_HPP -namespace std::graph { +namespace graph { // // graph concepts @@ -116,17 +116,17 @@ concept sourced_targeted_edge = targeted_edge && sourced_edge; * * @tparam G The graph type. */ -template // (exposition only) -concept _common_vertex_range = ranges::sized_range> && // +template // (exposition only) +concept _common_vertex_range = sized_range> && // requires(G&& g, vertex_iterator_t ui) { vertex_id(g, ui); }; template // For exposition only concept vertex_range = _common_vertex_range> && // - ranges::forward_range>; + forward_range>; -template // For exposition only -concept index_vertex_range = _common_vertex_range> && // - ranges::random_access_range> && // +template // For exposition only +concept index_vertex_range = _common_vertex_range> && // + random_access_range> && // integral>; // Will something like this be needed when vertices are in a map? TBD @@ -140,13 +140,13 @@ concept index_vertex_range = _common_vertex_range> && / */ template // For exposition only concept basic_targeted_edge_range = requires(G&& g, vertex_id_t uid) { - { edges(g, uid) } -> ranges::forward_range; + { edges(g, uid) } -> forward_range; }; template // For exposition only concept targeted_edge_range = basic_targeted_edge_range && // requires(G&& g, vertex_reference_t u) { - { edges(g, u) } -> ranges::forward_range; + { edges(g, u) } -> forward_range; }; //-------------------------------------------------------------------------------------------- @@ -365,7 +365,7 @@ concept has_contains_edge = requires(G&& g, vertex_id_t uid, vertex_id_t v * template class< T> * class my_edge { int src_id; int tgt_id; ... }; * } - * namespace std::graph { + * namespace graph { * template * struct define_unordered_edge, my_namespace::my_edge> : public true_type {}; * } @@ -374,9 +374,9 @@ concept has_contains_edge = requires(G&& g, vertex_id_t uid, vertex_id_t v */ template -struct define_unordered_edge : public false_type {}; // specialized for graph container edge +struct define_unordered_edge : public std::false_type {}; // specialized for graph container edge -template // For exposition only +template // For exposition only concept unordered_edge = basic_sourced_edge && define_unordered_edge::value; // @@ -389,13 +389,13 @@ concept ordered_edge = !unordered_edge; // // graph_error // -class graph_error : public runtime_error { +class graph_error : public std::runtime_error { public: - explicit graph_error(const string& what_arg) : runtime_error(what_arg) {} - explicit graph_error(const char* what_arg) : runtime_error(what_arg) {} + explicit graph_error(const std::string& what_arg) : std::runtime_error(what_arg) {} + explicit graph_error(const char* what_arg) : std::runtime_error(what_arg) {} }; -} // namespace std::graph +} // namespace graph #endif //GRAPH_HPP diff --git a/include/graph/graph_descriptors.hpp b/include/graph/graph_descriptors.hpp index c63cd13..b1ff86b 100644 --- a/include/graph/graph_descriptors.hpp +++ b/include/graph/graph_descriptors.hpp @@ -1,6 +1,8 @@ #pragma once +#include +#include "detail/graph_using.hpp" -namespace std::graph { +namespace graph { // // vertex_descriptor // for(auto&& [uid, u] : vertexlist(g)) @@ -278,13 +280,13 @@ using copyable_neighbor_t = neighbor_descriptor; // {source // view concepts // template // For exposition only -concept copyable_vertex = convertible_to>; +concept copyable_vertex = std::convertible_to>; template // For exposition only -concept copyable_edge = convertible_to>; +concept copyable_edge = std::convertible_to>; template // For exposition only -concept copyable_neighbor = convertible_to>; +concept copyable_neighbor = std::convertible_to>; // // is_sourced @@ -296,4 +298,4 @@ inline constexpr bool is_sourced_v> = true; template inline constexpr bool is_sourced_v> = true; -} // namespace std::graph +} // namespace graph diff --git a/include/graph/graph_utility.hpp b/include/graph/graph_utility.hpp index f0691b0..f95a8e1 100644 --- a/include/graph/graph_utility.hpp +++ b/include/graph/graph_utility.hpp @@ -5,7 +5,7 @@ #include #include "graph/edgelist.hpp" -namespace std::graph { +namespace graph { // Common types for DFS & BFS views enum three_colors : int8_t { black, white, gray }; // { finished, undiscovered, discovered } @@ -82,9 +82,9 @@ void push_back_fill(const EdgeList& edge_list, Adjacency& adj, bool directed, si /** * Make a map from data to the index value of each element in its container */ -template +template auto make_index_map(const R& range) { - using value_type = ranges::range_value_t; + using value_type = range_value_t; std::map the_map; for (size_t i = 0; i < size(range); ++i) { @@ -96,8 +96,8 @@ auto make_index_map(const R& range) { /** * Make an edge list with properties copied from original data, e.g., vector> */ -//template