Skip to content

Commit 14b9a1d

Browse files
committed
new vertex getters tests (impl)
1 parent 59d480d commit 14b9a1d

4 files changed

Lines changed: 143 additions & 9 deletions

File tree

include/gl/impl/specialized/adjacency_matrix.hpp

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -113,14 +113,19 @@ struct directed_adjacency_matrix {
113113

114114
[[nodiscard]] static auto successor_ids(const impl_type& self, id_type vertex_id) {
115115
return self._matrix[to_idx(vertex_id)] | std::views::enumerate
116-
| std::views::filter([](auto entry) { return entry.second != invalid_id; })
117-
| std::views::transform([](auto entry) { return static_cast<id_type>(entry.first); });
116+
| std::views::filter([](auto entry) {
117+
auto [target_id, edge_id] = entry;
118+
return edge_id != invalid_id;
119+
})
120+
| std::views::transform([](auto entry) {
121+
auto [target_id, edge_id] = entry;
122+
return static_cast<id_type>(target_id);
123+
});
118124
}
119125

120126
[[nodiscard]] static auto predecessor_ids(const impl_type& self, id_type vertex_id) {
121-
const auto v_idx = to_idx(vertex_id);
122127
return std::views::iota(initial_id_v<id_type>, static_cast<id_type>(self._matrix.size()))
123-
| std::views::filter([&](const auto src_id) {
128+
| std::views::filter([&self, v_idx = to_idx(vertex_id)](const auto src_id) {
124129
return self._matrix[to_idx(src_id)][v_idx] != invalid_id;
125130
});
126131
}
@@ -302,8 +307,14 @@ struct undirected_adjacency_matrix {
302307

303308
[[nodiscard]] static auto neighbor_ids(const impl_type& self, id_type vertex_id) {
304309
return self._matrix[to_idx(vertex_id)] | std::views::enumerate
305-
| std::views::filter([](auto entry) { return entry.second != invalid_id; })
306-
| std::views::transform([](auto entry) { return static_cast<id_type>(entry.first); });
310+
| std::views::filter([](auto entry) {
311+
auto [target_id, edge_id] = entry;
312+
return edge_id != invalid_id;
313+
})
314+
| std::views::transform([](auto entry) {
315+
auto [target_id, edge_id] = entry;
316+
return static_cast<id_type>(target_id);
317+
});
307318
}
308319

309320
[[nodiscard]] gl_attr_force_inline static auto predecessor_ids(

include/gl/impl/specialized/flat_adjacency_matrix.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ struct directed_flat_adjacency_matrix {
124124
[[nodiscard]] gl_attr_force_inline static auto predecessor_ids(
125125
const impl_type& self, id_type vertex_id
126126
) {
127-
return std::views::iota(initial_id, static_cast<id_type>(self._matrix.n_rows()))
127+
return std::views::iota(initial_id_v<id_type>, static_cast<id_type>(self._matrix.n_rows()))
128128
| std::views::filter([&self, v_idx = to_idx(vertex_id)](const auto r_id) {
129129
return self._matrix[to_idx(r_id), v_idx] != invalid_id;
130130
});
@@ -133,7 +133,7 @@ struct directed_flat_adjacency_matrix {
133133
[[nodiscard]] gl_attr_force_inline static auto successor_ids(
134134
const impl_type& self, id_type vertex_id
135135
) {
136-
return std::views::iota(initial_id, static_cast<id_type>(self._matrix.n_cols()))
136+
return std::views::iota(initial_id_v<id_type>, static_cast<id_type>(self._matrix.n_cols()))
137137
| std::views::filter([&self, v_idx = to_idx(vertex_id)](const auto c_id) {
138138
return self._matrix[v_idx, to_idx(c_id)] != invalid_id;
139139
});
@@ -302,7 +302,7 @@ struct undirected_flat_adjacency_matrix {
302302
[[nodiscard]] gl_attr_force_inline static auto neighbor_ids(
303303
const impl_type& self, id_type vertex_id
304304
) {
305-
return std::views::iota(initial_id, static_cast<id_type>(self._matrix.n_cols()))
305+
return std::views::iota(initial_id_v<id_type>, static_cast<id_type>(self._matrix.n_cols()))
306306
| std::views::filter([&self, v_idx = to_idx(vertex_id)](const auto c_id) {
307307
return self._matrix[v_idx, to_idx(c_id)] != invalid_id;
308308
});

tests/source/gl/test_adjacency_list.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,51 @@ TEST_CASE_TEMPLATE_DEFINE("directed adjacency list tests", SutType, directed_adj
208208

209209
// --- vertex getters ---
210210

211+
SUBCASE("successor_ids should return the ids of vertices to which the outgoing edges are "
212+
"directed") {
213+
add_edge(constants::v1_id, constants::v2_id);
214+
add_edge(constants::v1_id, constants::v3_id);
215+
216+
const auto successors =
217+
sut.successor_ids(constants::v1_id) | std::ranges::to<std::vector>();
218+
219+
REQUIRE_EQ(successors.size(), 2uz);
220+
CHECK(std::ranges::contains(successors, constants::v2_id));
221+
CHECK(std::ranges::contains(successors, constants::v3_id));
222+
223+
const auto successors_v2 =
224+
sut.successor_ids(constants::v2_id) | std::ranges::to<std::vector>();
225+
CHECK_EQ(successors_v2.size(), 0uz);
226+
}
227+
228+
SUBCASE("predecessor_ids should return the ids of vertices from which the incoming edges "
229+
"originate") {
230+
add_edge(constants::v2_id, constants::v1_id);
231+
add_edge(constants::v3_id, constants::v1_id);
232+
233+
const auto predecessors =
234+
sut.predecessor_ids(constants::v1_id) | std::ranges::to<std::vector>();
235+
236+
REQUIRE_EQ(predecessors.size(), 2uz);
237+
CHECK(std::ranges::contains(predecessors, constants::v2_id));
238+
CHECK(std::ranges::contains(predecessors, constants::v3_id));
239+
240+
const auto predecessors_v2 =
241+
sut.predecessor_ids(constants::v2_id) | std::ranges::to<std::vector>();
242+
CHECK_EQ(predecessors_v2.size(), 0uz);
243+
}
244+
245+
SUBCASE("neighbor_ids should return the combined ids of predecessors and successors") {
246+
add_edge(constants::v2_id, constants::v1_id); // v2 is a predecessor
247+
add_edge(constants::v1_id, constants::v3_id); // v3 is a successor
248+
249+
const auto neighbors = sut.neighbor_ids(constants::v1_id) | std::ranges::to<std::vector>();
250+
251+
REQUIRE_EQ(neighbors.size(), 2uz);
252+
CHECK(std::ranges::contains(neighbors, constants::v2_id));
253+
CHECK(std::ranges::contains(neighbors, constants::v3_id));
254+
}
255+
211256
// --- degree getters ---
212257

213258
SUBCASE("degree should return the number of edges incident with the given vertex") {
@@ -526,6 +571,25 @@ TEST_CASE_TEMPLATE_DEFINE("undirected adjacency list tests", SutType, undirected
526571

527572
// --- vertex getters ---
528573

574+
SUBCASE("neighbor/predecessor/successor_ids should return the same sets of adjacent vertices "
575+
"for undirected graphs") {
576+
add_edge(constants::v1_id, constants::v2_id);
577+
add_edge(constants::v3_id, constants::v1_id);
578+
579+
const auto neighbors = sut.neighbor_ids(constants::v1_id) | std::ranges::to<std::vector>();
580+
const auto predecessors =
581+
sut.predecessor_ids(constants::v1_id) | std::ranges::to<std::vector>();
582+
const auto successors =
583+
sut.successor_ids(constants::v1_id) | std::ranges::to<std::vector>();
584+
585+
REQUIRE_EQ(neighbors.size(), 2uz);
586+
CHECK(std::ranges::contains(neighbors, constants::v2_id));
587+
CHECK(std::ranges::contains(neighbors, constants::v3_id));
588+
589+
CHECK(std::ranges::is_permutation(neighbors, predecessors));
590+
CHECK(std::ranges::is_permutation(neighbors, successors));
591+
}
592+
529593
// --- degree getters ---
530594

531595
SUBCASE("-/in/out__degree should return the number of edges incident with/to/from the given "

tests/source/gl/test_adjacency_matrix.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,43 @@ TEST_CASE_TEMPLATE_DEFINE("directed adjacency matrix tests", SutType, directed_a
254254

255255
// --- vertex getters ---
256256

257+
SUBCASE("successor_ids should return the ids of vertices to which the outgoing edges are "
258+
"directed") {
259+
add_edge(constants::v1_id, constants::v2_id);
260+
add_edge(constants::v1_id, constants::v3_id);
261+
262+
auto successors = sut.successor_ids(constants::v1_id);
263+
264+
REQUIRE_EQ(gl::util::range_size(successors), 2uz);
265+
CHECK(std::ranges::contains(successors, constants::v2_id));
266+
CHECK(std::ranges::contains(successors, constants::v3_id));
267+
CHECK_EQ(gl::util::range_size(sut.successor_ids(constants::v2_id)), 0uz);
268+
}
269+
270+
SUBCASE("predecessor_ids should return the ids of vertices from which the incoming edges "
271+
"originate") {
272+
add_edge(constants::v2_id, constants::v1_id);
273+
add_edge(constants::v3_id, constants::v1_id);
274+
275+
auto predecessors = sut.predecessor_ids(constants::v1_id);
276+
277+
REQUIRE_EQ(gl::util::range_size(predecessors), 2uz);
278+
CHECK(std::ranges::contains(predecessors, constants::v2_id));
279+
CHECK(std::ranges::contains(predecessors, constants::v3_id));
280+
CHECK_EQ(gl::util::range_size(sut.predecessor_ids(constants::v2_id)), 0uz);
281+
}
282+
283+
SUBCASE("neighbor_ids should return the combined ids of predecessors and successors") {
284+
add_edge(constants::v2_id, constants::v1_id);
285+
add_edge(constants::v1_id, constants::v3_id);
286+
287+
auto neighbors = sut.neighbor_ids(constants::v1_id);
288+
289+
REQUIRE_EQ(gl::util::range_size(neighbors), 2uz);
290+
CHECK(std::ranges::contains(neighbors, constants::v2_id));
291+
CHECK(std::ranges::contains(neighbors, constants::v3_id));
292+
}
293+
257294
// --- degree getters ---
258295

259296
SUBCASE("degree should return the number of edges incident with the given vertex") {
@@ -562,6 +599,28 @@ TEST_CASE_TEMPLATE_DEFINE(
562599

563600
// --- vertex getters ---
564601

602+
SUBCASE("neighbor/predecessor/successor_ids should return the same sets of adjacent vertices "
603+
"for undirected graphs") {
604+
add_edge(constants::v1_id, constants::v2_id);
605+
add_edge(constants::v3_id, constants::v1_id);
606+
607+
auto neighbors_view = sut.neighbor_ids(constants::v1_id);
608+
auto predecessors_view = sut.predecessor_ids(constants::v1_id);
609+
auto successors_view = sut.successor_ids(constants::v1_id);
610+
611+
REQUIRE_EQ(gl::util::range_size(neighbors_view), 2uz);
612+
CHECK(std::ranges::contains(neighbors_view, constants::v2_id));
613+
CHECK(std::ranges::contains(neighbors_view, constants::v3_id));
614+
615+
// Evaluate views to vectors to ensure robust equivalence checks
616+
const auto neighbors = neighbors_view | std::ranges::to<std::vector>();
617+
const auto predecessors = predecessors_view | std::ranges::to<std::vector>();
618+
const auto successors = successors_view | std::ranges::to<std::vector>();
619+
620+
CHECK(std::ranges::equal(neighbors, predecessors));
621+
CHECK(std::ranges::equal(neighbors, successors));
622+
}
623+
565624
// --- degree getters ---
566625

567626
SUBCASE("-/in/out_degree should return the number of edges incident with/to/from the given "

0 commit comments

Comments
 (0)