77#include " hgl/types/types.hpp"
88
99#include < algorithm>
10+ #include < ranges>
1011#include < vector>
1112
1213#ifdef HGL_TESTING
@@ -45,11 +46,36 @@ class undirected_hyperedge_list final {
4546
4647 // --- vertex methods ---
4748
48- gl_attr_force_inline void add_vertices (const types::size_type) const noexcept {}
49+ // clang-format off
50+
51+ gl_attr_force_inline void add_vertices ([[maybe_unused]] const types::size_type) const noexcept {}
52+
53+ // clang-format on
4954
5055 void remove_vertex (const types::id_type vertex_id) noexcept {
51- for (auto & hyperedge_vertices : this ->_storage )
52- this ->_unbind_impl (hyperedge_vertices, vertex_id);
56+ for (auto & hyperedge : this ->_storage ) {
57+ auto vertex_it = std::ranges::lower_bound (hyperedge, vertex_id);
58+ if (vertex_it != hyperedge.end () and *vertex_it == vertex_id)
59+ vertex_it = hyperedge.erase (vertex_it); // unbind the vertex
60+ while (vertex_it != hyperedge.end ())
61+ --(*vertex_it++); // decrement ids > vertex_id
62+ }
63+ }
64+
65+ [[nodiscard]] gl_attr_force_inline auto incident_hyperedges (const types::id_type vertex_id
66+ ) const noexcept {
67+ return std::views::iota (0uz, this ->_storage .size ())
68+ | std::views::filter ([this , vertex_id](types::id_type hid) {
69+ return this ->_are_bound_impl (this ->_storage [hid], vertex_id);
70+ });
71+ }
72+
73+ [[nodiscard]] types::size_type degree (const types::id_type vertex_id) const noexcept {
74+ types::size_type deg = 0uz;
75+ for (const auto & hyperedge : this ->_storage )
76+ if (this ->_are_bound_impl (hyperedge, vertex_id))
77+ ++deg;
78+ return deg;
5379 }
5480
5581 // --- hyperedge methods ---
@@ -62,52 +88,53 @@ class undirected_hyperedge_list final {
6288 this ->_storage .erase (this ->_storage .begin () + hyperedge_id);
6389 }
6490
65- [[nodiscard]] gl_attr_force_inline types::size_type hyperedge_size (
66- const types::id_type hyperedge_id
91+ [[nodiscard]] gl_attr_force_inline auto incident_vertices (const types::id_type hyperedge_id
6792 ) const noexcept {
68- return this ->_storage [hyperedge_id]. size ( );
93+ return std::views::all ( this ->_storage [hyperedge_id]);
6994 }
7095
71- [[nodiscard]] gl_attr_force_inline auto hyperedge_vertices (const types::id_type hyperedge_id
96+ [[nodiscard]] gl_attr_force_inline types::size_type hyperedge_size (
97+ const types::id_type hyperedge_id
7298 ) const noexcept {
73- return std::views::all ( this ->_storage [hyperedge_id]);
99+ return this ->_storage [hyperedge_id]. size ( );
74100 }
75101
76102 // --- binding methods ---
77103
78- void bind (const types::id_type hyperedge_id , const types::id_type vertex_id ) noexcept {
79- auto & hyperedge_vertices = this ->_storage [hyperedge_id];
104+ void bind (const types::id_type vertex_id , const types::id_type hyperedge_id ) noexcept {
105+ auto & hyperedge = this ->_storage [hyperedge_id];
80106
81107 // insert the id at the correct position to keep the vertex-id collection sorted
82- const auto it = std::ranges::lower_bound (hyperedge_vertices , vertex_id);
83- if (it == hyperedge_vertices .end () or *it != vertex_id)
84- hyperedge_vertices .insert (it, vertex_id);
108+ const auto it = std::ranges::lower_bound (hyperedge , vertex_id);
109+ if (it == hyperedge .end () or *it != vertex_id)
110+ hyperedge .insert (it, vertex_id);
85111 }
86112
87113 gl_attr_force_inline void unbind (
88- const types::id_type hyperedge_id , const types::id_type vertex_id
114+ const types::id_type vertex_id , const types::id_type hyperedge_id
89115 ) noexcept {
90- this ->_unbind_impl (this ->_storage [hyperedge_id], vertex_id);
116+ auto & hyperedge = this ->_storage [hyperedge_id];
117+ const auto vertex_it = std::ranges::lower_bound (hyperedge, vertex_id);
118+ if (vertex_it != hyperedge.end () and *vertex_it == vertex_id)
119+ hyperedge.erase (vertex_it);
91120 }
92121
93- [[nodiscard]] bool are_bound (const types::id_type hyperedge_id, const types::id_type vertex_id)
94- const noexcept {
95- auto & hyperedge_vertices = this ->_storage [hyperedge_id];
96- const auto vertex_it = std::ranges::lower_bound (hyperedge_vertices, vertex_id);
97- return vertex_it != hyperedge_vertices.end () and *vertex_it == vertex_id;
122+ [[nodiscard]] gl_attr_force_inline bool are_bound (
123+ const types::id_type vertex_id, const types::id_type hyperedge_id
124+ ) const noexcept {
125+ return this ->_are_bound_impl (this ->_storage [hyperedge_id], vertex_id);
98126 }
99127
100128#ifdef HGL_TESTING
101129 friend struct hgl_testing ::test_hyperedge_list;
102130#endif
103131
104132private:
105- void _unbind_impl (
106- hyperedge_storage_type& hyperedge_vertices, const types::id_type vertex_id
107- ) noexcept {
108- const auto vertex_it = std::ranges::lower_bound (hyperedge_vertices, vertex_id);
109- if (vertex_it != hyperedge_vertices.end () and *vertex_it == vertex_id)
110- hyperedge_vertices.erase (vertex_it);
133+ [[nodiscard]] bool _are_bound_impl (
134+ const hyperedge_storage_type& hyperedge, const types::id_type vertex_id
135+ ) const noexcept {
136+ const auto vertex_it = std::ranges::lower_bound (hyperedge, vertex_id);
137+ return vertex_it != hyperedge.end () and *vertex_it == vertex_id;
111138 }
112139
113140 hypergraph_storage_type _storage;
0 commit comments