VeloGraphX
High-performance dynamic graph analytics in C++20
Loading...
Searching...
No Matches
graph_access.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <concepts>
4#include <cstddef>
5#include <cstdint>
6#include <type_traits>
7#include <utility>
8
10
11namespace velographx {
12
13namespace graph_access_detail {
14
15template <class T>
16[[nodiscard]] constexpr VertexId neighbor_target(const T& value) noexcept {
17 if constexpr (requires { value.first; }) {
18 return static_cast<VertexId>(value.first);
19 } else {
20 return static_cast<VertexId>(value);
21 }
22}
23
24template <class T>
25[[nodiscard]] constexpr auto neighbor_weight(const T& value) noexcept {
26 return value.second;
27}
28
29template <class Graph>
30concept MemberVertexCount = requires(const Graph& graph) {
31 { graph.vertex_count() } -> std::convertible_to<std::size_t>;
32};
33
34template <class Graph>
35concept AdlVertexCount = requires(const Graph& graph) {
36 { vx_vertex_count(graph) } -> std::convertible_to<std::size_t>;
37};
38
39template <class Graph>
40concept MemberDirected = requires(const Graph& graph) {
41 { graph.directed() } -> std::convertible_to<bool>;
42};
43
44template <class Graph>
45concept AdlDirected = requires(const Graph& graph) {
46 { vx_is_directed(graph) } -> std::convertible_to<bool>;
47};
48
49template <class Graph>
50concept MemberVersion = requires(const Graph& graph) {
51 { graph.version() } -> std::convertible_to<std::uint64_t>;
52};
53
54template <class Graph>
55concept AdlVersion = requires(const Graph& graph) {
56 { vx_version(graph) } -> std::convertible_to<std::uint64_t>;
57};
58
59} // namespace graph_access_detail
60
61template <class Graph>
65
66template <class Graph>
69
70template <ReadableGraph Graph>
71[[nodiscard]] constexpr std::size_t vertex_count(const Graph& graph) {
73 return static_cast<std::size_t>(graph.vertex_count());
74 } else {
75 return static_cast<std::size_t>(vx_vertex_count(graph));
76 }
77}
78
79template <ReadableGraph Graph>
80[[nodiscard]] constexpr bool is_directed(const Graph& graph) {
82 return static_cast<bool>(graph.directed());
83 } else {
84 return static_cast<bool>(vx_is_directed(graph));
85 }
86}
87
88template <MutableGraph Graph>
89[[nodiscard]] constexpr std::uint64_t graph_version(const Graph& graph) {
91 return static_cast<std::uint64_t>(graph.version());
92 } else {
93 return static_cast<std::uint64_t>(vx_version(graph));
94 }
95}
96
97template <ReadableGraph Graph, class Fn>
98void for_each_neighbor(const Graph& graph, VertexId u, Fn&& fn) {
99 if constexpr (requires { graph.for_each_neighbor(u, std::forward<Fn>(fn)); }) {
100 graph.for_each_neighbor(u, std::forward<Fn>(fn));
101 } else if constexpr (requires { vx_for_each_neighbor(graph, u, std::forward<Fn>(fn)); }) {
102 vx_for_each_neighbor(graph, u, std::forward<Fn>(fn));
103 } else {
104 for (const auto& neighbor : graph.neighbors(u)) {
106 }
107 }
108}
109
110template <ReadableGraph Graph, class Fn>
111void for_each_weighted_neighbor(const Graph& graph, VertexId u, Fn&& fn) {
112 if constexpr (requires { vx_for_each_weighted_neighbor(graph, u, std::forward<Fn>(fn)); }) {
113 vx_for_each_weighted_neighbor(graph, u, std::forward<Fn>(fn));
114 } else if constexpr (requires { graph.for_each_neighbor(u, std::forward<Fn>(fn)); }) {
115 graph.for_each_neighbor(u, std::forward<Fn>(fn));
116 } else {
117 for (const auto& neighbor : graph.neighbors(u)) {
119 }
120 }
121}
122
123template <ReadableGraph Graph, class Fn>
124void for_each_in_neighbor(const Graph& graph, VertexId v, Fn&& fn) {
125 if constexpr (requires { graph.for_each_in_neighbor(v, std::forward<Fn>(fn)); }) {
126 graph.for_each_in_neighbor(v, std::forward<Fn>(fn));
127 } else if constexpr (requires { vx_for_each_in_neighbor(graph, v, std::forward<Fn>(fn)); }) {
128 vx_for_each_in_neighbor(graph, v, std::forward<Fn>(fn));
129 } else if constexpr (requires { graph.in_neighbors(v); }) {
130 for (const auto& neighbor : graph.in_neighbors(v)) {
132 }
133 } else {
134 for (VertexId u = 0; u < vertex_count(graph); ++u) {
135 for_each_neighbor(graph, u, [&](VertexId dst) {
136 if (dst == v) fn(u);
137 });
138 }
139 }
140}
141
142template <ReadableGraph Graph>
143[[nodiscard]] std::size_t neighbor_count(const Graph& graph, VertexId u) {
144 if constexpr (requires { graph.degree(u); }) {
145 return static_cast<std::size_t>(graph.degree(u));
146 } else if constexpr (requires { vx_neighbor_count(graph, u); }) {
147 return static_cast<std::size_t>(vx_neighbor_count(graph, u));
148 } else {
149 std::size_t count = 0;
150 for_each_neighbor(graph, u, [&](VertexId) { ++count; });
151 return count;
152 }
153}
154
155template <ReadableGraph Graph>
156[[nodiscard]] bool has_edge(const Graph& graph, VertexId u, VertexId v) {
157 if constexpr (requires { graph.has_edge(u, v); }) {
158 return graph.has_edge(u, v);
159 } else if constexpr (requires { vx_has_edge(graph, u, v); }) {
160 return vx_has_edge(graph, u, v);
161 } else {
162 bool found = false;
163 for_each_neighbor(graph, u, [&](VertexId dst) { found = found || dst == v; });
164 return found;
165 }
166}
167
168template <ReadableGraph Graph>
169[[nodiscard]] auto edge_weight(const Graph& graph, VertexId u, VertexId v) {
170 if constexpr (requires { vx_edge_weight(graph, u, v); }) {
171 return vx_edge_weight(graph, u, v);
172 } else {
173 return graph.weight(u, v);
174 }
175}
176
177template <class Graph, class Batch>
178void apply_updates(Graph& graph, const Batch& batch) {
179 if constexpr (requires { graph.apply(batch); }) {
180 graph.apply(batch);
181 } else {
182 vx_apply_updates(graph, batch);
183 }
184}
185
186} // namespace velographx
constexpr auto neighbor_weight(const T &value) noexcept
constexpr VertexId neighbor_target(const T &value) noexcept
void apply_updates(Graph &graph, const Batch &batch)
void for_each_neighbor(const Graph &graph, VertexId u, Fn &&fn)
auto edge_weight(const Graph &graph, VertexId u, VertexId v)
bool has_edge(const Graph &graph, VertexId u, VertexId v)
constexpr bool is_directed(const Graph &graph)
void for_each_weighted_neighbor(const Graph &graph, VertexId u, Fn &&fn)
constexpr std::uint64_t graph_version(const Graph &graph)
std::size_t neighbor_count(const Graph &graph, VertexId u)
std::uint32_t VertexId
Definition frontier.hpp:6
constexpr std::size_t vertex_count(const Graph &graph)
void for_each_in_neighbor(const Graph &graph, VertexId v, Fn &&fn)