Skip to content

Commit bcbe88d

Browse files
authored
YT-CPPHGL-10: Implement the remaining methods of the hypergraph class for undirected hypergraph operations
- Replaced the directional-specific incidence list and matrix classes with template specializations of a common `model<DirectionalTag, LayoutTag>` classes - Aligned the `hypergraph` class to store an implementation class instance - Aligned the following methods of the `hypergraph` class to use the underlying implementation: - Adding and removing vertices - Adding and removing hyperedges - Added the following methods to the `hypergraph` class: - Binding and unbinding vertices to hyperedges - Retrieving the degree of a vertex - Retrieving the set of hyperedges incident with (containing) a given vertex - Retrieving the number of vertices incident with a given hyperedge - Retrieving the set of vertices incident with (contained by) a given hyperedge
1 parent 3a8f0bc commit bcbe88d

10 files changed

Lines changed: 523 additions & 150 deletions

include/hgl/directional_tags.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
#pragma once
66

7-
#include "types/type_traits.hpp"
7+
#include "hgl/types/type_traits.hpp"
88

99
namespace hgl {
1010

include/hgl/hypergraph.hpp

Lines changed: 138 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44

55
#pragma once
66

7-
#include "constants.hpp"
8-
#include "hypergraph_traits.hpp"
9-
#include "util.hpp"
7+
#include "hgl/constants.hpp"
8+
#include "hgl/hypergraph_traits.hpp"
9+
#include "hgl/util.hpp"
1010

1111
#include <memory>
1212
#include <set>
@@ -21,6 +21,8 @@ class hypergraph final {
2121
using traits_type = HypergraphTraits;
2222
using directional_tag = typename traits_type::directional_tag;
2323
using implementation_tag = typename traits_type::implementation_tag;
24+
using implementation_type =
25+
typename implementation_tag::template implementation_type<directional_tag>;
2426

2527
using vertex_type = typename traits_type::vertex_type;
2628
using vertex_properties_type = typename traits_type::vertex_properties_type;
@@ -40,7 +42,7 @@ class hypergraph final {
4042
hypergraph& operator=(const hypergraph&) = delete;
4143

4244
hypergraph(const types::size_type n_vertices = 0uz, const types::size_type n_hyperedges = 0uz)
43-
: _n_vertices(n_vertices), _n_hyperedges(n_hyperedges) {
45+
: _n_vertices(n_vertices), _n_hyperedges(n_hyperedges), _impl(n_vertices, n_hyperedges) {
4446
if constexpr (type_traits::c_non_empty_properties<vertex_properties_type>) {
4547
this->_vertex_properties.reserve(n_vertices);
4648
for (const auto _ : this->vertex_ids())
@@ -67,21 +69,8 @@ class hypergraph final {
6769

6870
// --- vertex methods ---
6971

70-
[[nodiscard]] gl_attr_force_inline auto vertices() const
71-
requires(type_traits::c_empty_properties<vertex_properties_type>)
72-
{
73-
return this->vertex_ids()
74-
| std::views::transform([](const types::id_type id) { return vertex_type{id}; });
75-
}
76-
77-
[[nodiscard]] gl_attr_force_inline auto vertices() const
78-
requires(type_traits::c_non_empty_properties<vertex_properties_type>)
79-
{
80-
return this->_vertex_properties | std::views::enumerate
81-
| std::views::transform([](const auto& property_item) {
82-
const auto& [id, ptr] = property_item;
83-
return vertex_type{static_cast<types::id_type>(id), *ptr};
84-
});
72+
[[nodiscard]] gl_attr_force_inline auto vertices() noexcept {
73+
return this->vertex_ids() | std::views::transform(this->_create_vertex_descriptor());
8574
}
8675

8776
[[nodiscard]] gl_attr_force_inline auto vertex_ids() const noexcept {
@@ -105,7 +94,7 @@ class hypergraph final {
10594
}
10695

10796
vertex_type add_vertex() {
108-
// this->_impl.add_vertex();
97+
this->_impl.add_vertices(1uz);
10998
const auto new_vertex_id = this->_n_vertices++;
11099

111100
if constexpr (type_traits::c_non_empty_properties<vertex_properties_type>)
@@ -120,7 +109,7 @@ class hypergraph final {
120109
vertex_type add_vertex_with(vertex_properties_type properties)
121110
requires(type_traits::c_non_empty_properties<vertex_properties_type>)
122111
{
123-
// this->_impl.add_vertex();
112+
this->_impl.add_vertices(1uz);
124113
return vertex_type{
125114
this->_n_vertices++,
126115
*this->_vertex_properties.emplace_back(
@@ -130,7 +119,7 @@ class hypergraph final {
130119
}
131120

132121
void add_vertices(const types::size_type n) {
133-
// this->_impl.add_vertices(n);
122+
this->_impl.add_vertices(n);
134123
this->_n_vertices += n;
135124

136125
if constexpr (type_traits::c_non_empty_properties<vertex_properties_type>) {
@@ -148,7 +137,7 @@ class hypergraph final {
148137
{
149138
const auto n = std::ranges::size(properties_range);
150139

151-
// this->_impl.add_vertices(n);
140+
this->_impl.add_vertices(n);
152141
this->_n_vertices += n;
153142

154143
if constexpr (type_traits::c_non_empty_properties<vertex_properties_type>) {
@@ -160,8 +149,7 @@ class hypergraph final {
160149
}
161150
}
162151

163-
void remove_vertex(const types::id_type vertex_id) {
164-
this->_verify_vertex_id(vertex_id);
152+
gl_attr_force_inline void remove_vertex(const types::id_type vertex_id) {
165153
this->_remove_vertex_impl(vertex_id);
166154
}
167155

@@ -210,21 +198,8 @@ class hypergraph final {
210198

211199
// --- hyperedge methods ---
212200

213-
[[nodiscard]] gl_attr_force_inline auto hyperedges() const
214-
requires(type_traits::c_empty_properties<hyperedge_properties_type>)
215-
{
216-
return this->hyperedge_ids()
217-
| std::views::transform([](const types::id_type id) { return hyperedge_type{id}; });
218-
}
219-
220-
[[nodiscard]] gl_attr_force_inline auto hyperedges() const
221-
requires(type_traits::c_non_empty_properties<hyperedge_properties_type>)
222-
{
223-
return this->_hyperedge_properties | std::views::enumerate
224-
| std::views::transform([](const auto& property_item) {
225-
const auto& [id, ptr] = property_item;
226-
return hyperedge_type{static_cast<types::id_type>(id), *ptr};
227-
});
201+
[[nodiscard]] gl_attr_force_inline auto hyperedges() noexcept {
202+
return this->hyperedge_ids() | std::views::transform(this->_create_hyperedge_descriptor());
228203
}
229204

230205
[[nodiscard]] gl_attr_force_inline auto hyperedge_ids() const noexcept {
@@ -248,7 +223,7 @@ class hypergraph final {
248223
}
249224

250225
hyperedge_type add_hyperedge() {
251-
// this->_impl.add_hyperedge();
226+
this->_impl.add_hyperedges(1uz);
252227
const auto new_hyperedge_id = this->_n_hyperedges++;
253228

254229
if constexpr (type_traits::c_non_empty_properties<hyperedge_properties_type>)
@@ -265,7 +240,7 @@ class hypergraph final {
265240
hyperedge_type add_hyperedge_with(hyperedge_properties_type properties)
266241
requires(type_traits::c_non_empty_properties<hyperedge_properties_type>)
267242
{
268-
// this->_impl.add_hyperedge();
243+
this->_impl.add_hyperedges(1uz);
269244
return hyperedge_type{
270245
this->_n_hyperedges++,
271246
*this->_hyperedge_properties.emplace_back(
@@ -275,7 +250,7 @@ class hypergraph final {
275250
}
276251

277252
void add_hyperedges(const types::size_type n) {
278-
// this->_impl.add_hyperedges(n);
253+
this->_impl.add_hyperedges(n);
279254
this->_n_hyperedges += n;
280255

281256
if constexpr (type_traits::c_non_empty_properties<hyperedge_properties_type>) {
@@ -294,7 +269,7 @@ class hypergraph final {
294269
{
295270
const auto n = std::ranges::size(properties_range);
296271

297-
// this->_impl.add_hyperedges(n);
272+
this->_impl.add_hyperedges(n);
298273
this->_n_hyperedges += n;
299274

300275
if constexpr (type_traits::c_non_empty_properties<hyperedge_properties_type>) {
@@ -306,8 +281,7 @@ class hypergraph final {
306281
}
307282
}
308283

309-
void remove_hyperedge(const types::id_type hyperedge_id) {
310-
this->_verify_hyperedge_id(hyperedge_id);
284+
gl_attr_force_inline void remove_hyperedge(const types::id_type hyperedge_id) {
311285
this->_remove_hyperedge_impl(hyperedge_id);
312286
}
313287

@@ -356,6 +330,82 @@ class hypergraph final {
356330
return *this->_hyperedge_properties[id];
357331
}
358332

333+
// --- incidence methods ---
334+
335+
void bind(const types::id_type vertex_id, const types::id_type hyperedge_id) {
336+
this->_verify_vertex_id(vertex_id);
337+
this->_verify_hyperedge_id(hyperedge_id);
338+
this->_impl.bind(vertex_id, hyperedge_id);
339+
}
340+
341+
gl_attr_force_inline void bind(const vertex_type& vertex, const hyperedge_type& hyperedge) {
342+
this->bind(vertex.id(), hyperedge.id());
343+
}
344+
345+
void unbind(const types::id_type vertex_id, const types::id_type hyperedge_id) {
346+
this->_verify_vertex_id(vertex_id);
347+
this->_verify_hyperedge_id(hyperedge_id);
348+
this->_impl.unbind(vertex_id, hyperedge_id);
349+
}
350+
351+
gl_attr_force_inline void unbind(const vertex_type& vertex, const hyperedge_type& hyperedge) {
352+
this->unbind(vertex.id(), hyperedge.id());
353+
}
354+
355+
[[nodiscard]] bool are_incident(
356+
const types::id_type vertex_id, const types::id_type hyperedge_id
357+
) const {
358+
this->_verify_vertex_id(vertex_id);
359+
this->_verify_hyperedge_id(hyperedge_id);
360+
return this->_impl.are_bound(vertex_id, hyperedge_id);
361+
}
362+
363+
[[nodiscard]] gl_attr_force_inline bool are_incident(
364+
const vertex_type& vertex, const hyperedge_type& hyperedge
365+
) const {
366+
return this->are_incident(vertex.id(), hyperedge.id());
367+
}
368+
369+
[[nodiscard]] auto incident_hyperedges(const types::id_type vertex_id) {
370+
this->_verify_vertex_id(vertex_id);
371+
return this->_impl.incident_hyperedges(vertex_id)
372+
| std::views::transform(this->_create_hyperedge_descriptor());
373+
}
374+
375+
[[nodiscard]] gl_attr_force_inline auto incident_hyperedges(const vertex_type& vertex) {
376+
return this->incident_hyperedges(vertex.id());
377+
}
378+
379+
[[nodiscard]] types::size_type degree(const types::id_type vertex_id) const {
380+
this->_verify_vertex_id(vertex_id);
381+
return this->_impl.degree(vertex_id);
382+
}
383+
384+
[[nodiscard]] gl_attr_force_inline types::size_type degree(const vertex_type& vertex) const {
385+
return this->degree(vertex.id());
386+
}
387+
388+
[[nodiscard]] auto incident_vertices(const types::id_type hyperedge_id) {
389+
this->_verify_hyperedge_id(hyperedge_id);
390+
return this->_impl.incident_vertices(hyperedge_id)
391+
| std::views::transform(this->_create_vertex_descriptor());
392+
}
393+
394+
[[nodiscard]] gl_attr_force_inline auto incident_vertices(const hyperedge_type& hyperedge) {
395+
return this->incident_vertices(hyperedge.id());
396+
}
397+
398+
[[nodiscard]] types::size_type hyperedge_size(const types::id_type hyperedge_id) const {
399+
this->_verify_hyperedge_id(hyperedge_id);
400+
return this->_impl.hyperedge_size(hyperedge_id);
401+
}
402+
403+
[[nodiscard]] gl_attr_force_inline types::size_type hyperedge_size(
404+
const hyperedge_type& hyperedge
405+
) const {
406+
return this->hyperedge_size(hyperedge.id());
407+
}
408+
359409
private:
360410
// --- vertex methods ---
361411

@@ -365,10 +415,13 @@ class hypergraph final {
365415
}
366416

367417
void _remove_vertex_impl(const types::id_type vertex_id) {
418+
if (not this->has_vertex(vertex_id))
419+
return;
420+
421+
this->_impl.remove_vertex(vertex_id);
368422
this->_n_vertices--;
369423
if constexpr (type_traits::c_non_empty_properties<vertex_properties_type>)
370424
this->_vertex_properties.erase(this->_vertex_properties.begin() + vertex_id);
371-
// TODO: impl::remove_vertex(vertex_id)
372425
}
373426

374427
// --- hyperedge methods ---
@@ -379,14 +432,52 @@ class hypergraph final {
379432
}
380433

381434
void _remove_hyperedge_impl(const types::id_type hyperedge_id) {
435+
if (not this->has_hyperedge(hyperedge_id))
436+
return;
437+
438+
this->_impl.remove_hyperedge(hyperedge_id);
382439
this->_n_hyperedges--;
383440
if constexpr (type_traits::c_non_empty_properties<hyperedge_properties_type>)
384441
this->_hyperedge_properties.erase(this->_hyperedge_properties.begin() + hyperedge_id);
385442
}
386443

444+
// --- transformations ---
445+
446+
gl_attr_force_inline auto _create_vertex_descriptor() noexcept
447+
requires(type_traits::c_empty_properties<vertex_properties_type>)
448+
{
449+
return [](const types::id_type id) { return vertex_type{id}; };
450+
}
451+
452+
gl_attr_force_inline auto _create_vertex_descriptor() noexcept
453+
requires(type_traits::c_non_empty_properties<vertex_properties_type>)
454+
{
455+
return [&pmap = this->_vertex_properties](const types::id_type id) {
456+
return vertex_type{id, *pmap[id]};
457+
};
458+
}
459+
460+
gl_attr_force_inline auto _create_hyperedge_descriptor() noexcept
461+
requires(type_traits::c_empty_properties<hyperedge_properties_type>)
462+
{
463+
return [](const types::id_type id) { return hyperedge_type{id}; };
464+
}
465+
466+
gl_attr_force_inline auto _create_hyperedge_descriptor() noexcept
467+
requires(type_traits::c_non_empty_properties<hyperedge_properties_type>)
468+
{
469+
return [&pmap = this->_hyperedge_properties](const types::id_type id) {
470+
return hyperedge_type{id, *pmap[id]};
471+
};
472+
}
473+
474+
// --- data members ---
475+
387476
types::size_type _n_vertices = 0uz;
388477
types::size_type _n_hyperedges = 0uz;
389478

479+
implementation_type _impl{};
480+
390481
[[no_unique_address]] vertex_properties_map_type _vertex_properties{};
391482
[[no_unique_address]] hyperedge_properties_map_type _hyperedge_properties{};
392483
};

include/hgl/hypergraph_elements.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44

55
#pragma once
66

7-
#include "constants.hpp"
87
#include "gl/vertex_descriptor.hpp"
9-
#include "types/type_traits.hpp"
10-
#include "types/types.hpp"
8+
#include "hgl/constants.hpp"
9+
#include "hgl/types/type_traits.hpp"
10+
#include "hgl/types/types.hpp"
1111

1212
namespace hgl {
1313

include/hgl/hypergraph_traits.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44

55
#pragma once
66

7-
#include "directional_tags.hpp"
8-
#include "hypergraph_elements.hpp"
9-
#include "impl/impl_tags.hpp"
10-
#include "impl/layout_tags.hpp"
7+
#include "hgl/directional_tags.hpp"
8+
#include "hgl/hypergraph_elements.hpp"
9+
#include "hgl/impl/impl_tags.hpp"
10+
#include "hgl/impl/layout_tags.hpp"
1111

1212
namespace hgl {
1313

include/hgl/impl/impl_tags.hpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@
44

55
#pragma once
66

7+
#include "hgl/directional_tags.hpp"
8+
#include "hgl/impl/incidence_list.hpp"
9+
#include "hgl/impl/incidence_matrix.hpp"
10+
#include "hgl/impl/layout_tags.hpp"
711
#include "hgl/types/type_traits.hpp"
812
#include "hgl/types/types.hpp"
9-
#include "layout_tags.hpp"
1013

1114
namespace hgl {
1215

@@ -15,11 +18,17 @@ namespace impl {
1518
template <type_traits::c_hypergraph_layout_tag LayoutTag>
1619
struct list_t {
1720
using layout_tag = LayoutTag;
21+
22+
template <type_traits::c_hypergraph_directional_tag DirectionalTag>
23+
using implementation_type = incidence_list<DirectionalTag, LayoutTag>;
1824
};
1925

2026
template <type_traits::c_hypergraph_layout_tag LayoutTag>
2127
struct matrix_t {
2228
using layout_tag = LayoutTag;
29+
30+
template <type_traits::c_hypergraph_directional_tag DirectionalTag>
31+
using implementation_type = incidence_matrix<DirectionalTag, LayoutTag>;
2332
};
2433

2534
} // namespace impl

0 commit comments

Comments
 (0)