Skip to content

Commit bcc0a68

Browse files
committed
wip: adj list/matrix alignment + tests
1 parent 755769b commit bcc0a68

26 files changed

Lines changed: 5111 additions & 5287 deletions

include/gl/edge_descriptor.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class edge_descriptor final {
4242
properties_type properties
4343
)
4444
requires(not type_traits::is_default_properties_type_v<properties_type>)
45-
: _id(id) _vertices(first, second), _properties(properties) {}
45+
: _id(id), _vertices(first, second), _properties(properties) {}
4646

4747
edge_descriptor(edge_descriptor&&) = default;
4848
edge_descriptor& operator=(edge_descriptor&&) = default;
@@ -68,10 +68,12 @@ class edge_descriptor final {
6868
return this->_vertices;
6969
}
7070

71+
// TODO: rename to source
7172
[[nodiscard]] gl_attr_force_inline const types::id_type first() const noexcept {
7273
return this->_vertices.first;
7374
}
7475

76+
// TODO: rename to target
7577
[[nodiscard]] gl_attr_force_inline const types::id_type second() const noexcept {
7678
return this->_vertices.second;
7779
}

include/gl/edge_tags.hpp

Lines changed: 2 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ class edge_descriptor;
2626

2727
namespace type_traits {
2828

29+
// TODO: use concepts
30+
2931
template <typename T>
3032
inline constexpr bool is_directed_v = false;
3133

@@ -45,28 +47,6 @@ inline constexpr bool is_undirected_v<EdgeType> =
4547
struct directed_t {
4648
using type = std::type_identity_t<directed_t>;
4749

48-
template <type_traits::c_instantiation_of<edge_descriptor> EdgeType>
49-
requires(type_traits::is_directed_v<EdgeType>)
50-
using edge_ptr_type = std::unique_ptr<EdgeType>;
51-
52-
template <type_traits::c_instantiation_of<edge_descriptor> EdgeType>
53-
requires(type_traits::is_directed_v<EdgeType>)
54-
[[nodiscard]] gl_attr_force_inline static edge_ptr_type<EdgeType> make(
55-
const types::id_type first, const types::id_type second
56-
) {
57-
return std::make_unique<EdgeType>(first, second);
58-
}
59-
60-
template <type_traits::c_instantiation_of<edge_descriptor> EdgeType>
61-
requires(type_traits::is_directed_v<EdgeType>)
62-
[[nodiscard]] gl_attr_force_inline static edge_ptr_type<EdgeType> make(
63-
const types::id_type first,
64-
const types::id_type second,
65-
const typename EdgeType::properties_type& properties
66-
) {
67-
return std::make_unique<EdgeType>(first, second, properties);
68-
}
69-
7050
template <type_traits::c_instantiation_of<edge_descriptor> EdgeType>
7151
requires(type_traits::is_directed_v<EdgeType>)
7252
[[nodiscard]] gl_attr_force_inline static bool is_incident_from(
@@ -87,28 +67,6 @@ struct directed_t {
8767
struct undirected_t {
8868
using type = std::type_identity_t<undirected_t>;
8969

90-
template <type_traits::c_instantiation_of<edge_descriptor> EdgeType>
91-
requires(type_traits::is_undirected_v<EdgeType>)
92-
using edge_ptr_type = std::shared_ptr<EdgeType>;
93-
94-
template <type_traits::c_instantiation_of<edge_descriptor> EdgeType>
95-
requires(type_traits::is_undirected_v<EdgeType>)
96-
[[nodiscard]] gl_attr_force_inline static edge_ptr_type<EdgeType> make(
97-
const types::id_type first, const types::id_type second
98-
) {
99-
return std::make_shared<EdgeType>(first, second);
100-
}
101-
102-
template <type_traits::c_instantiation_of<edge_descriptor> EdgeType>
103-
requires(type_traits::is_undirected_v<EdgeType>)
104-
[[nodiscard]] gl_attr_force_inline static edge_ptr_type<EdgeType> make(
105-
const types::id_type first,
106-
const types::id_type second,
107-
const typename EdgeType::properties_type& properties
108-
) {
109-
return std::make_shared<EdgeType>(first, second, properties);
110-
}
111-
11270
template <type_traits::c_instantiation_of<edge_descriptor> EdgeType>
11371
requires(type_traits::is_undirected_v<EdgeType>)
11472
[[nodiscard]] gl_attr_force_inline static bool is_incident_from(
@@ -126,31 +84,4 @@ struct undirected_t {
12684
}
12785
};
12886

129-
namespace types {
130-
131-
template <type_traits::c_instantiation_of<edge_descriptor> EdgeType>
132-
using edge_ptr_type = typename EdgeType::directional_tag::template edge_ptr_type<EdgeType>;
133-
134-
} // namespace types
135-
136-
namespace detail {
137-
138-
template <type_traits::c_instantiation_of<edge_descriptor> EdgeType>
139-
[[nodiscard]] gl_attr_force_inline types::edge_ptr_type<EdgeType> make_edge(
140-
const types::id_type first, const types::id_type second
141-
) {
142-
return EdgeType::directional_tag::template make<EdgeType>(first, second);
143-
}
144-
145-
template <type_traits::c_instantiation_of<edge_descriptor> EdgeType>
146-
[[nodiscard]] gl_attr_force_inline types::edge_ptr_type<EdgeType> make_edge(
147-
const types::id_type first,
148-
const types::id_type second,
149-
const typename EdgeType::properties_type& properties
150-
) {
151-
return EdgeType::directional_tag::template make<EdgeType>(first, second, properties);
152-
}
153-
154-
} // namespace detail
155-
15687
} // namespace gl

include/gl/graph.hpp

Lines changed: 32 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,9 @@ class graph final {
159159
}
160160
}
161161

162-
template <type_traits::c_sized_range_of<vertex_properties_type> VertexPropertiesRange>
163-
void add_vertices_with(const VertexPropertiesRange& properties_range)
162+
void add_vertices_with(
163+
const type_traits::c_sized_range_of<vertex_properties_type> auto& properties_range
164+
)
164165
requires(not type_traits::is_default_properties_type_v<vertex_properties_type>)
165166
{
166167
const auto n = std::ranges::size(properties_range);
@@ -186,8 +187,9 @@ class graph final {
186187
this->remove_vertex(vertex.id());
187188
}
188189

189-
template <type_traits::c_sized_range_of<types::id_type> IdRange>
190-
void remove_vertices_from(const IdRange& vertex_id_range) {
190+
void remove_vertices_from(
191+
const type_traits::c_sized_range_of<types::id_type> auto& vertex_id_range
192+
) {
191193
// sorts the ids in a descending order and removes duplicate ids
192194
std::set<types::id_type, std::greater<types::id_type>> vertex_id_set(
193195
std::ranges::begin(vertex_id_range), std::ranges::end(vertex_id_range)
@@ -198,26 +200,14 @@ class graph final {
198200
this->_remove_vertex_impl(vertex_id);
199201
}
200202

201-
template <type_traits::c_sized_range_of<types::const_ref_wrap<vertex_type>> VertexRefRange>
202-
void remove_vertices_from(const VertexRefRange& vertex_ref_range) {
203-
// TODO [C++26]: replace with std::greater
204-
struct vertex_ref_greater_comparator {
205-
[[nodiscard]] bool operator()(
206-
const types::const_ref_wrap<vertex_type>& lhs,
207-
const types::const_ref_wrap<vertex_type>& rhs
208-
) const {
209-
return lhs.get() > rhs.get();
210-
}
211-
};
212-
213-
// sorts the ids in a descending order and removes duplicate ids
214-
std::set<types::const_ref_wrap<vertex_type>, vertex_ref_greater_comparator> vertex_ref_set(
215-
std::ranges::begin(vertex_ref_range), std::ranges::end(vertex_ref_range)
216-
);
217-
203+
void remove_vertices_from(const type_traits::c_sized_range_of<vertex_type> auto& vertex_range) {
218204
// TODO: optimize
219-
for (const auto& vertex_ref : vertex_ref_set)
220-
this->_remove_vertex_impl(vertex_ref.get().id());
205+
// sort the ids in a descending order and removes duplicate ids
206+
std::set<vertex_type> vertex_set(
207+
std::ranges::begin(vertex_range), std::ranges::end(vertex_range)
208+
);
209+
for (const auto& vertex : vertex_set)
210+
this->_remove_vertex_impl(vertex.id());
221211
}
222212

223213
[[nodiscard]] gl_attr_force_inline types::size_type in_degree(const types::id_type vertex_id
@@ -324,8 +314,11 @@ class graph final {
324314
return this->add_edge(first.id(), second.id(), properties);
325315
}
326316

327-
template <type_traits::c_sized_range_of<types::id_type> IdRange>
328-
void add_edges_from(const types::id_type source_id, const IdRange& target_id_range) {
317+
void add_edges_from(
318+
const types::id_type source_id,
319+
const type_traits::c_sized_range_of<types::id_type> auto& target_id_range
320+
) {
321+
// TODO: validate no duplicate target ids
329322
this->_verify_vertex_id(source_id);
330323

331324
for (const auto target_id : target_id_range) {
@@ -342,23 +335,25 @@ class graph final {
342335
}
343336

344337
// TODO: range of convertible_to<const vertex_type&>
345-
template <type_traits::c_sized_range_of<types::const_ref_wrap<vertex_type>> VertexRefRange>
346338
gl_attr_force_inline void add_edges_from(
347-
const vertex_type& source, const VertexRefRange& target_range
339+
const vertex_type& source,
340+
const type_traits::c_sized_range_of<vertex_type> auto& target_range
348341
) {
342+
// TODO: validate no duplicate targets
349343
this->_verify_vertex_id(source.id());
350344

351-
for (const auto& target_ref : target_range) {
352-
const auto& target = target_ref.get();
345+
for (const auto& target : target_range) {
353346
this->_verify_vertex_id(target.id());
354347
if constexpr (not type_traits::is_default_properties_type_v<edge_properties_type>)
355348
this->_edge_properties.emplace_back(std::make_unique<edge_properties_type>());
356349
}
357350

358351
const auto prev_n_edges = this->_n_unique_edges;
359-
this->_n_unique_edges += std::ranges::size(target_id_range);
352+
this->_n_unique_edges += std::ranges::size(target_range);
360353
this->_impl.add_edges_from(
361-
std::views::iota(prev_n_edges, this->_n_unique_edges), source_id, target_id_range
354+
std::views::iota(prev_n_edges, this->_n_unique_edges),
355+
source.id(),
356+
target_range | std::views::transform(&vertex_type::id)
362357
);
363358
}
364359

@@ -370,8 +365,9 @@ class graph final {
370365
return this->_impl.has_edge(first_id, second_id);
371366
}
372367

373-
[[nodiscard]] gl_attr_force_inline has_edge(const vertex_type& first, const vertex_type& second)
374-
const {
368+
[[nodiscard]] gl_attr_force_inline bool has_edge(
369+
const vertex_type& first, const vertex_type& second
370+
) const {
375371
return this->has_edge(first.id(), second.id());
376372
}
377373

@@ -393,21 +389,12 @@ class graph final {
393389
return this->_impl.get_edge(first.id(), second.id());
394390
}
395391

396-
[[nodiscard]] inline std::vector<types::const_ref_wrap<edge_type>> get_edges(
392+
[[nodiscard]] inline std::vector<edge_type> get_edges(
397393
const types::id_type first_id, const types::id_type second_id
398394
) const {
399-
using edge_ref_set = std::vector<types::const_ref_wrap<edge_type>>;
400-
401395
this->_verify_vertex_id(first_id);
402396
this->_verify_vertex_id(second_id);
403-
404-
if constexpr (std::same_as<implementation_tag, impl::list_t>) {
405-
return this->_impl.get_edges(first_id, second_id);
406-
}
407-
else {
408-
const auto edge_opt = this->_impl.get_edge(first_id, second_id);
409-
return edge_opt.has_value() ? edge_ref_set{edge_opt.value()} : edge_ref_set{};
410-
}
397+
return this->_impl.get_edges(first_id, second_id);
411398
}
412399

413400
[[nodiscard]] std::vector<types::const_ref_wrap<edge_type>> get_edges(
@@ -424,8 +411,7 @@ class graph final {
424411
}
425412

426413
// TODO: range of convertible_to<const edge_type&>
427-
template <type_traits::c_range_of<types::const_ref_wrap<edge_type>> EdgeRefRange>
428-
inline void remove_edges_from(const EdgeRefRange edges) {
414+
inline void remove_edges_from(const type_traits::c_range_of<edge_type> auto& edges) {
429415
// TODO: optimize
430416
for (const auto& edge_ref : edges)
431417
this->_impl.remove_edge(edge_ref.get());

include/gl/graph_traits.hpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,9 @@ template <
1717
type_traits::c_graph_impl_tag ImplTag = impl::list_t>
1818
struct graph_traits {
1919
using vertex_type = vertex_descriptor<VertexProperties>;
20-
using vertex_ptr_type = types::vertex_ptr_type<vertex_type>;
2120
using vertex_properties_type = typename vertex_type::properties_type;
2221

2322
using edge_type = edge_descriptor<EdgeDirectionalTag, EdgeProperties>;
24-
using edge_ptr_type = types::edge_ptr_type<edge_type>;
2523
using edge_directional_tag = typename edge_type::directional_tag;
2624
using edge_properties_type = typename edge_type::properties_type;
2725

include/gl/impl/adjacency_list.hpp

Lines changed: 21 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,9 @@ template <type_traits::c_list_graph_traits GraphTraits>
1616
class adjacency_list final {
1717
public:
1818
using vertex_type = typename GraphTraits::vertex_type;
19-
2019
using edge_type = typename GraphTraits::edge_type;
21-
using edge_directional_tag = typename GraphTraits::edge_directional_tag;
22-
23-
using edge_list_type = std::vector<specialized::edge_list_item>;
24-
using edge_iterator_type =
25-
types::dereferencing_iterator<typename edge_list_type::const_iterator>;
26-
27-
// TODO: reverese iterators should be available for bidirectional ranges
28-
29-
using list_type = std::vector<edge_list_type>;
20+
using edge_item_list_type = std::vector<specialized::edge_list_item>;
21+
using adjacency_list_type = std::vector<edge_item_list_type>;
3022

3123
adjacency_list(const adjacency_list&) = delete;
3224
adjacency_list& operator=(const adjacency_list&) = delete;
@@ -40,16 +32,14 @@ class adjacency_list final {
4032

4133
~adjacency_list() = default;
4234

43-
// --- general methods ---
44-
4535
// --- vertex methods ---
4636

4737
gl_attr_force_inline void add_vertex() {
48-
this->_list.emplace_back(edge_list_type{});
38+
this->_list.emplace_back(edge_item_list_type{});
4939
}
5040

5141
inline void add_vertices(const types::size_type n) {
52-
this->_list.resize(this->n_vertices() + n, edge_list_type{});
42+
this->_list.resize(this->_list.size() + n, edge_item_list_type{});
5343
}
5444

5545
[[nodiscard]] gl_attr_force_inline types::size_type in_degree(const types::id_type vertex_id
@@ -79,23 +69,21 @@ class adjacency_list final {
7969
return specialized_impl::degree_map(*this);
8070
}
8171

82-
gl_attr_force_inline void remove_vertex(const types::id_type vertex_id) {
83-
specialized_impl::remove_vertex(*this, vertex_id);
72+
template <bool GetRemovedEdgeIds>
73+
gl_attr_force_inline auto remove_vertex(const types::id_type vertex_id) {
74+
return specialized_impl::template remove_vertex<GetRemovedEdgeIds>(*this, vertex_id);
8475
}
8576

8677
// --- edge methods ---
8778

88-
// clang-format off
89-
// gl_attr_force_inline misplacement
90-
91-
gl_attr_force_inline void add_edge(types::id_type id, types::id_type first, types::id_type second) {
92-
return specialized_impl::add_edge(*this, std::move(edge));
79+
gl_attr_force_inline void add_edge(
80+
types::id_type id, types::id_type source_id, types::id_type target_id
81+
) {
82+
specialized_impl::add_edge(*this, id, source_id, target_id);
9383
}
9484

95-
// clang-format on
96-
9785
gl_attr_force_inline void add_edges_from(
98-
const type_traits::c_sized_range_od<types::id_type> auto& edge_ids,
86+
const type_traits::c_sized_range_of<types::id_type> auto& edge_ids,
9987
const types::id_type source_id,
10088
const type_traits::c_sized_range_of<types::id_type> auto& target_ids
10189
) {
@@ -144,17 +132,19 @@ class adjacency_list final {
144132
);
145133
}
146134

147-
[[nodiscard]] auto get_edges(const types::id_type source_id, const types::id_type target_id)
148-
const {
135+
[[nodiscard]] std::vector<edge_type> get_edges(
136+
const types::id_type source_id, const types::id_type target_id
137+
) const {
149138
return this->_list[source_id] | std::views::filter([&target_id](const auto& item) {
150139
return item.target_id == target_id;
151140
})
152141
| std::views::transform([source_id](const auto& item) {
153142
return edge_type{item.id, source_id, item.target_id};
154-
});
143+
})
144+
| std::ranges::to<std::vector>();
155145
}
156146

157-
[[nodiscard]] auto get_edges(
147+
[[nodiscard]] std::vector<edge_type> get_edges(
158148
const types::id_type source_id,
159149
const types::id_type target_id,
160150
const auto& edge_properties_map
@@ -166,7 +156,8 @@ class adjacency_list final {
166156
return edge_type{
167157
item.id, source_id, item.target_id, edge_properties_map[item.id]
168158
};
169-
});
159+
})
160+
| std::ranges::to<std::vector>();
170161
}
171162

172163
gl_attr_force_inline void remove_edge(const edge_type& edge) {
@@ -194,8 +185,7 @@ class adjacency_list final {
194185
using specialized_impl = typename specialized::list_impl_traits<adjacency_list>::type;
195186
friend specialized_impl;
196187

197-
list_type _list{};
198-
types::size_type _n_unique_edges{constants::default_size};
188+
adjacency_list_type _list{};
199189
};
200190

201191
} // namespace gl::impl

0 commit comments

Comments
 (0)