Skip to content

Commit b2e499b

Browse files
committed
maybe it will work with ID remapping
1 parent c9e6776 commit b2e499b

6 files changed

Lines changed: 70 additions & 128 deletions

File tree

include/gl/graph.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,8 @@ class graph final {
253253
return this->_impl.degree_map();
254254
}
255255

256+
// TODO: add a get_vertex_properties function
257+
256258
[[nodiscard]] gl_attr_force_inline auto vertex_properties_map() const noexcept
257259
requires(not type_traits::is_default_properties_type_v<vertex_properties_type>)
258260
{

include/gl/impl/adjacency_list.hpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,10 @@ class adjacency_list final {
7575
return specialized_impl::degree_map(*this);
7676
}
7777

78-
template <bool GetRemovedEdgeIds>
79-
gl_attr_force_inline auto remove_vertex(const types::id_type vertex_id) {
80-
return specialized_impl::template remove_vertex<GetRemovedEdgeIds>(*this, vertex_id);
78+
std::vector<types::id_type> remove_vertex(const types::id_type vertex_id) {
79+
const auto removed_edge_ids = specialized_impl::remove_vertex(*this, vertex_id);
80+
// TODO: sort removed_edge_ids & align edge ids (remapping)
81+
return removed_edge_ids;
8182
}
8283

8384
// --- edge methods ---

include/gl/impl/adjacency_matrix.hpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,10 @@ class adjacency_matrix final {
8282
return specialized_impl::degree_map(*this);
8383
}
8484

85-
template <bool GetRemovedEdgeIds>
86-
gl_attr_force_inline auto remove_vertex(const types::id_type vertex_id) {
87-
return specialized_impl::template remove_vertex<GetRemovedEdgeIds>(*this, vertex_id);
85+
std::vector<types::id_type> remove_vertex(const types::id_type vertex_id) {
86+
const auto removed_edge_ids = specialized_impl::remove_vertex(*this, vertex_id);
87+
// TODO: sort removed_edge_ids & align edge ids (remapping)
88+
return removed_edge_ids;
8889
}
8990

9091
// --- edge methods ---

include/gl/impl/specialized/adjacency_list.hpp

Lines changed: 26 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88

99
#include <algorithm>
1010
#include <format>
11+
#include <iostream>
1112
#include <ranges>
12-
#include <unordered_set>
1313
#include <vector>
1414

1515
namespace gl::impl {
@@ -108,59 +108,35 @@ struct directed_adjacency_list {
108108
return degree_map;
109109
}
110110

111-
template <bool GetRemovedEdgeIds>
112-
static auto remove_vertex(impl_type& self, const types::id_type vertex_id)
113-
requires(GetRemovedEdgeIds)
114-
{
115-
std::vector<types::id_type> removed_edges;
116-
removed_edges.reserve(self._list[vertex_id].size());
117-
std::ranges::copy(
118-
self._list[vertex_id] | std::views::transform(&edge_list_item::id),
119-
std::back_inserter(removed_edges)
120-
);
111+
static std::vector<types::id_type> remove_vertex(
112+
impl_type& self, const types::id_type vertex_id
113+
) {
114+
auto removed_edges =
115+
self._list[vertex_id] | std::views::transform(&edge_list_item::id)
116+
| std::ranges::to<std::vector>();
121117

122118
// remove all edges incident to the vertex
123119
for (types::id_type id = constants::initial_id; id < self._list.size(); ++id) {
124120
auto& adj_edges = self._list[id];
125121
if (id == vertex_id or adj_edges.empty())
126122
continue;
127123

128-
const auto removed_subrng = std::ranges::remove_if(
129-
adj_edges, [vertex_id](const auto& item) { return item.target_id == vertex_id; }
130-
);
131-
std::ranges::copy(
132-
removed_subrng | std::views::transform(&edge_list_item::id),
133-
std::back_inserter(removed_edges)
134-
);
124+
const auto removed_subrng =
125+
std::ranges::remove_if(adj_edges, [vertex_id, &removed_edges](const auto& item) {
126+
if (item.target_id == vertex_id) {
127+
removed_edges.push_back(item.id);
128+
return true;
129+
}
130+
return false;
131+
});
135132
adj_edges.erase(removed_subrng.begin(), removed_subrng.end());
136133
}
137134

138135
// remove the list of edges incident from the vertex entirely
139136
self._list.erase(std::next(std::begin(self._list), vertex_id));
140-
141137
return removed_edges;
142138
}
143139

144-
template <bool GetRemovedEdgeIds>
145-
static auto remove_vertex(impl_type& self, const types::id_type vertex_id)
146-
requires(not GetRemovedEdgeIds)
147-
{
148-
// remove all edges incident to the vertex
149-
for (types::id_type id = constants::initial_id; id < self._list.size(); ++id) {
150-
auto& adj_edges = self._list[id];
151-
if (id == vertex_id or adj_edges.empty())
152-
continue;
153-
154-
const auto removed_subrng = std::ranges::remove_if(
155-
adj_edges, [vertex_id](const auto& item) { return item.target_id == vertex_id; }
156-
);
157-
adj_edges.erase(removed_subrng.begin(), removed_subrng.end());
158-
}
159-
160-
// remove the list of edges incident from the vertex entirely
161-
self._list.erase(std::next(std::begin(self._list), vertex_id));
162-
}
163-
164140
static gl_attr_force_inline void add_edge(
165141
impl_type& self, types::id_type edge_id, types::id_type source_id, types::id_type target_id
166142
) {
@@ -183,6 +159,7 @@ struct directed_adjacency_list {
183159
static gl_attr_force_inline void remove_edge(impl_type& self, const edge_type& edge) {
184160
auto& adj_edges = self._list[edge.first()];
185161
adj_edges.erase(detail::strict_find(adj_edges, edge));
162+
// TODO: align edge ids (common)
186163
}
187164
};
188165

@@ -233,8 +210,9 @@ struct undirected_adjacency_list {
233210
return degree_map;
234211
}
235212

236-
template <bool GetRemovedEdgeIds>
237-
static auto remove_vertex(impl_type& self, const types::id_type vertex_id) {
213+
static std::vector<types::id_type> remove_vertex(
214+
impl_type& self, const types::id_type vertex_id
215+
) {
238216
// remove all edges incident with the vertex (scan only the selected vertices)
239217
for (const auto& item : self._list[vertex_id]) {
240218
if (item.target_id == vertex_id)
@@ -248,16 +226,11 @@ struct undirected_adjacency_list {
248226
}
249227

250228
// remove the list of edges incident from the vertex entirely
251-
if constexpr (GetRemovedEdgeIds) {
252-
const auto removed_edges =
253-
self._list[vertex_id] | std::views::transform(&edge_list_item::id)
254-
| std::ranges::to<std::vector>;
255-
self._list.erase(std::next(std::begin(self._list), vertex_id));
256-
return removed_edges;
257-
}
258-
else {
259-
self._list.erase(std::next(std::begin(self._list), vertex_id));
260-
}
229+
const auto removed_edges =
230+
self._list[vertex_id] | std::views::transform(&edge_list_item::id)
231+
| std::ranges::to<std::vector>();
232+
self._list.erase(std::next(std::begin(self._list), vertex_id));
233+
return removed_edges;
261234
}
262235

263236
static void add_edge(
@@ -295,6 +268,8 @@ struct undirected_adjacency_list {
295268
adj_edges_first.erase(detail::strict_find(adj_edges_first, edge));
296269
adj_edges_second.erase(detail::strict_find(adj_edges_second, edge));
297270
}
271+
272+
// TODO: align edge ids (common)
298273
}
299274
};
300275

include/gl/impl/specialized/adjacency_matrix.hpp

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,9 @@ struct directed_adjacency_matrix {
118118
return degree_map;
119119
}
120120

121-
template <bool GetRemovedEdgeIds>
122-
static auto remove_vertex(impl_type& self, const types::id_type vertex_id)
123-
requires(GetRemovedEdgeIds)
124-
{
121+
static std::vector<types::id_type> remove_vertex(
122+
impl_type& self, const types::id_type vertex_id
123+
) {
125124
auto removed_edges =
126125
self._matrix[vertex_id]
127126
| std::views::filter([](auto edge_id) { return edge_id != constants::invalid_id; })
@@ -138,15 +137,6 @@ struct directed_adjacency_matrix {
138137
return removed_edges;
139138
}
140139

141-
template <bool GetRemovedEdgeIds>
142-
static auto remove_vertex(impl_type& self, const types::id_type vertex_id)
143-
requires(not GetRemovedEdgeIds)
144-
{
145-
self._matrix.erase(std::next(std::begin(self._matrix), vertex_id));
146-
for (auto& row : self._matrix)
147-
row.erase(std::next(std::begin(row), vertex_id));
148-
}
149-
150140
static inline void add_edge(
151141
impl_type& self, types::id_type edge_id, types::id_type source_id, types::id_type target_id
152142
) {
@@ -170,6 +160,7 @@ struct directed_adjacency_matrix {
170160

171161
static inline void remove_edge(impl_type& self, const edge_type& edge) {
172162
detail::strict_get(self._matrix, edge) = constants::invalid_id;
163+
// TODO: align edge ids (common)
173164
}
174165
};
175166

@@ -232,22 +223,18 @@ struct undirected_adjacency_matrix {
232223
return degree_map;
233224
}
234225

235-
template <bool GetRemovedEdgeIds>
236-
static auto remove_vertex(impl_type& self, const types::id_type vertex_id) {
226+
static std::vector<types::id_type> remove_vertex(
227+
impl_type& self, const types::id_type vertex_id
228+
) {
237229
for (auto& row : self._matrix)
238230
row.erase(std::next(std::begin(row), vertex_id));
239231

240-
if constexpr (GetRemovedEdgeIds) {
241-
const auto removed_edges =
242-
self._matrix[vertex_id]
243-
| std::views::filter([](auto edge_id) { return edge_id != constants::invalid_id; })
244-
| std::ranges::to<std::vector>;
245-
self._matrix.erase(std::next(std::begin(self._matrix), vertex_id));
246-
return removed_edges;
247-
}
248-
else {
249-
self._matrix.erase(std::next(std::begin(self._matrix), vertex_id));
250-
}
232+
const auto removed_edges =
233+
self._matrix[vertex_id]
234+
| std::views::filter([](auto edge_id) { return edge_id != constants::invalid_id; })
235+
| std::ranges::to<std::vector>;
236+
self._matrix.erase(std::next(std::begin(self._matrix), vertex_id));
237+
return removed_edges;
251238
}
252239

253240
static void add_edge(
@@ -287,6 +274,8 @@ struct undirected_adjacency_matrix {
287274
// it will also be present in the second matrix cell
288275
self._matrix[edge.second()][edge.first()] = constants::invalid_id;
289276
}
277+
278+
// TODO: align edge ids (common)
290279
}
291280
};
292281

tests/source/gl/test_adjacency_list.cpp

Lines changed: 19 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -343,29 +343,7 @@ TEST_CASE_FIXTURE(
343343

344344
TEST_CASE_FIXTURE(
345345
test_directed_adjacency_list,
346-
"remove_vertex<GetRemovedEdgeIds=false> should remove the given vertex and all edges incident "
347-
"with it"
348-
) {
349-
init_complete_graph();
350-
351-
const auto removed_vertex_id = constants::first_element_idx;
352-
sut.remove_vertex<false>(removed_vertex_id);
353-
354-
constexpr auto n_vertices_after_remove = constants::n_elements - constants::one_element;
355-
constexpr auto n_incident_edges_after_remove =
356-
n_incident_edges_for_fully_connected_vertex - constants::one_element;
357-
358-
REQUIRE_EQ(size(sut), n_vertices_after_remove);
359-
for (const auto vertex_id :
360-
constants::vertex_id_view | std::views::take(n_vertices_after_remove)) {
361-
CHECK_EQ(sut.adjacent_edges(vertex_id).size(), n_incident_edges_after_remove);
362-
}
363-
}
364-
365-
TEST_CASE_FIXTURE(
366-
test_directed_adjacency_list,
367-
"remove_vertex<GetRemovedEdgeIds=true> should remove the given vertex and all edges incident "
368-
"with it"
346+
"remove_vertex should remove the given vertex and all edges incident with it"
369347
) {
370348
const auto edge1 = add_edge(constants::vertex_id_1, constants::vertex_id_2);
371349
const auto edge3 = add_edge(constants::vertex_id_2, constants::vertex_id_1);
@@ -376,27 +354,19 @@ TEST_CASE_FIXTURE(
376354
const auto edge6 = add_edge(constants::vertex_id_3, constants::vertex_id_2);
377355

378356
const auto removed_vertex_id = constants::vertex_id_1;
379-
const auto removed_edge_ids = sut.remove_vertex<true>(removed_vertex_id);
357+
const auto removed_edge_ids = sut.remove_vertex(removed_vertex_id);
380358

381359
REQUIRE_EQ(removed_edge_ids.size(), 4uz);
382360
for (const auto edge_id : {edge1.id(), edge2.id(), edge3.id(), edge4.id()})
383361
CHECK(std::ranges::contains(removed_edge_ids, edge_id));
384362
for (const auto edge_id : {edge5.id(), edge6.id()})
385363
CHECK_FALSE(std::ranges::contains(removed_edge_ids, edge_id));
386364

387-
constexpr auto n_vertices_after_remove = constants::n_elements - constants::one_element;
388-
constexpr auto n_incident_edges_after_remove =
389-
n_incident_edges_for_fully_connected_vertex - constants::one_element;
390-
391-
REQUIRE_EQ(size(sut), n_vertices_after_remove);
392-
for (const auto vertex_id :
393-
constants::vertex_id_view | std::views::take(n_vertices_after_remove)) {
394-
CHECK_EQ(sut.adjacent_edges(vertex_id).size(), n_incident_edges_after_remove);
395-
}
365+
CHECK_EQ(size(sut), constants::n_elements - 1uz);
366+
CHECK_EQ(sut.adjacent_edges(constants::vertex_id_1).size(), 1uz); // IDs were aligned
367+
CHECK_EQ(sut.adjacent_edges(constants::vertex_id_2).size(), 1uz); // IDs were aligned
396368
}
397369

398-
// TODO: add test case with GetRemovedEdgeIds=true
399-
400370
struct test_undirected_adjacency_list : public test_adjacency_list {
401371
using edge_type = gl::undirected_edge<>;
402372
using sut_type = gl::impl::adjacency_list<gl::list_graph_traits<gl::undirected_t>>;
@@ -670,20 +640,24 @@ TEST_CASE_FIXTURE(
670640
test_undirected_adjacency_list,
671641
"remove_vertex should remove the given vertex and all edges incident with it"
672642
) {
673-
init_complete_graph();
643+
const auto edge1 = add_edge(constants::vertex_id_1, constants::vertex_id_2);
644+
const auto edge3 = add_edge(constants::vertex_id_2, constants::vertex_id_1);
645+
const auto edge2 = add_edge(constants::vertex_id_1, constants::vertex_id_3);
646+
const auto edge4 = add_edge(constants::vertex_id_3, constants::vertex_id_1);
647+
648+
const auto edge5 = add_edge(constants::vertex_id_2, constants::vertex_id_3);
674649

675650
const auto removed_vertex_id = constants::first_element_idx;
676-
sut.remove_vertex<false>(removed_vertex_id);
651+
const auto removed_edge_ids = sut.remove_vertex(removed_vertex_id);
677652

678-
constexpr auto n_vertices_after_remove = constants::n_elements - constants::one_element;
679-
constexpr auto n_incident_edges_after_remove =
680-
n_incident_edges_for_fully_connected_vertex - constants::one_element;
653+
REQUIRE_EQ(removed_edge_ids.size(), 4uz);
654+
for (const auto edge_id : {edge1.id(), edge2.id(), edge3.id(), edge4.id()})
655+
CHECK(std::ranges::contains(removed_edge_ids, edge_id));
656+
CHECK_FALSE(std::ranges::contains(removed_edge_ids, edge5.id()));
681657

682-
REQUIRE_EQ(size(sut), n_vertices_after_remove);
683-
for (const auto vertex_id :
684-
constants::vertex_id_view | std::views::take(n_vertices_after_remove)) {
685-
CHECK_EQ(sut.adjacent_edges(vertex_id).size(), n_incident_edges_after_remove);
686-
}
658+
CHECK_EQ(size(sut), constants::n_elements - 1uz);
659+
CHECK_EQ(sut.adjacent_edges(constants::vertex_id_1).size(), 1uz); // IDs were aligned
660+
CHECK_EQ(sut.adjacent_edges(constants::vertex_id_2).size(), 1uz); // IDs were aligned
687661
}
688662

689663
TEST_SUITE_END(); // test_adjacency_list

0 commit comments

Comments
 (0)