@@ -21,6 +21,7 @@ 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 = typename implementation_tag::implementation_type<directional_tag>;
2425
2526 using vertex_type = typename traits_type::vertex_type;
2627 using vertex_properties_type = typename traits_type::vertex_properties_type;
@@ -40,7 +41,7 @@ class hypergraph final {
4041 hypergraph& operator =(const hypergraph&) = delete ;
4142
4243 hypergraph (const types::size_type n_vertices = 0uz, const types::size_type n_hyperedges = 0uz)
43- : _n_vertices(n_vertices), _n_hyperedges(n_hyperedges) {
44+ : _n_vertices(n_vertices), _n_hyperedges(n_hyperedges), _impl(n_vertices, n_hyperedges) {
4445 if constexpr (type_traits::c_non_empty_properties<vertex_properties_type>) {
4546 this ->_vertex_properties .reserve (n_vertices);
4647 for (const auto _ : this ->vertex_ids ())
@@ -67,21 +68,8 @@ class hypergraph final {
6768
6869 // --- vertex methods ---
6970
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- });
71+ [[nodiscard]] gl_attr_force_inline auto vertices () noexcept {
72+ return this ->vertex_ids () | std::views::transform (this ->_create_vertex_descriptor ());
8573 }
8674
8775 [[nodiscard]] gl_attr_force_inline auto vertex_ids () const noexcept {
@@ -105,7 +93,7 @@ class hypergraph final {
10593 }
10694
10795 vertex_type add_vertex () {
108- // this->_impl.add_vertex( );
96+ this ->_impl .add_vertices (1uz );
10997 const auto new_vertex_id = this ->_n_vertices ++;
11098
11199 if constexpr (type_traits::c_non_empty_properties<vertex_properties_type>)
@@ -120,7 +108,7 @@ class hypergraph final {
120108 vertex_type add_vertex_with (vertex_properties_type properties)
121109 requires(type_traits::c_non_empty_properties<vertex_properties_type>)
122110 {
123- // this->_impl.add_vertex( );
111+ this ->_impl .add_vertices (1uz );
124112 return vertex_type{
125113 this ->_n_vertices ++,
126114 *this ->_vertex_properties .emplace_back (
@@ -130,7 +118,7 @@ class hypergraph final {
130118 }
131119
132120 void add_vertices (const types::size_type n) {
133- // this->_impl.add_vertices(n);
121+ this ->_impl .add_vertices (n);
134122 this ->_n_vertices += n;
135123
136124 if constexpr (type_traits::c_non_empty_properties<vertex_properties_type>) {
@@ -148,7 +136,7 @@ class hypergraph final {
148136 {
149137 const auto n = std::ranges::size (properties_range);
150138
151- // this->_impl.add_vertices(n);
139+ this ->_impl .add_vertices (n);
152140 this ->_n_vertices += n;
153141
154142 if constexpr (type_traits::c_non_empty_properties<vertex_properties_type>) {
@@ -160,8 +148,7 @@ class hypergraph final {
160148 }
161149 }
162150
163- void remove_vertex (const types::id_type vertex_id) {
164- this ->_verify_vertex_id (vertex_id);
151+ gl_attr_force_inline void remove_vertex (const types::id_type vertex_id) {
165152 this ->_remove_vertex_impl (vertex_id);
166153 }
167154
@@ -210,21 +197,8 @@ class hypergraph final {
210197
211198 // --- hyperedge methods ---
212199
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- });
200+ [[nodiscard]] gl_attr_force_inline auto hyperedges () noexcept {
201+ return this ->hyperedge_ids () | std::views::transform (this ->_create_hyperedge_descriptor ());
228202 }
229203
230204 [[nodiscard]] gl_attr_force_inline auto hyperedge_ids () const noexcept {
@@ -248,7 +222,7 @@ class hypergraph final {
248222 }
249223
250224 hyperedge_type add_hyperedge () {
251- // this->_impl.add_hyperedge( );
225+ this ->_impl .add_hyperedges (1uz );
252226 const auto new_hyperedge_id = this ->_n_hyperedges ++;
253227
254228 if constexpr (type_traits::c_non_empty_properties<hyperedge_properties_type>)
@@ -265,7 +239,7 @@ class hypergraph final {
265239 hyperedge_type add_hyperedge_with (hyperedge_properties_type properties)
266240 requires(type_traits::c_non_empty_properties<hyperedge_properties_type>)
267241 {
268- // this->_impl.add_hyperedge( );
242+ this ->_impl .add_hyperedges (1uz );
269243 return hyperedge_type{
270244 this ->_n_hyperedges ++,
271245 *this ->_hyperedge_properties .emplace_back (
@@ -275,7 +249,7 @@ class hypergraph final {
275249 }
276250
277251 void add_hyperedges (const types::size_type n) {
278- // this->_impl.add_hyperedges(n);
252+ this ->_impl .add_hyperedges (n);
279253 this ->_n_hyperedges += n;
280254
281255 if constexpr (type_traits::c_non_empty_properties<hyperedge_properties_type>) {
@@ -294,7 +268,7 @@ class hypergraph final {
294268 {
295269 const auto n = std::ranges::size (properties_range);
296270
297- // this->_impl.add_hyperedges(n);
271+ this ->_impl .add_hyperedges (n);
298272 this ->_n_hyperedges += n;
299273
300274 if constexpr (type_traits::c_non_empty_properties<hyperedge_properties_type>) {
@@ -306,8 +280,7 @@ class hypergraph final {
306280 }
307281 }
308282
309- void remove_hyperedge (const types::id_type hyperedge_id) {
310- this ->_verify_hyperedge_id (hyperedge_id);
283+ gl_attr_force_inline void remove_hyperedge (const types::id_type hyperedge_id) {
311284 this ->_remove_hyperedge_impl (hyperedge_id);
312285 }
313286
@@ -356,6 +329,68 @@ class hypergraph final {
356329 return *this ->_hyperedge_properties [id];
357330 }
358331
332+ // --- incidence methods ---
333+
334+ void bind (const types::id_type vertex_id, const types::id_type hyperedge_id) {
335+ this ->_verify_vertex_id (vertex_id);
336+ this ->_verify_hyperedge_id (hyperedge_id);
337+ this ->_impl .bind (vertex_id, hyperedge_id);
338+ }
339+
340+ gl_attr_force_inline void bind (const vertex_type& vertex, const hyperedge_type& hyperedge) {
341+ this ->bind (vertex.id (), hyperedge.id ());
342+ }
343+
344+ void unbind (const types::id_type vertex_id, const types::id_type hyperedge_id) {
345+ this ->_verify_vertex_id (vertex_id);
346+ this ->_verify_hyperedge_id (hyperedge_id);
347+ this ->_impl .unbind (vertex_id, hyperedge_id);
348+ }
349+
350+ gl_attr_force_inline void unbind (const vertex_type& vertex, const hyperedge_type& hyperedge) {
351+ this ->unbind (vertex.id (), hyperedge.id ());
352+ }
353+
354+ [[nodiscard]] auto incident_hyperedges (const types::id_type vertex_id) {
355+ this ->_verify_vertex_id (vertex_id);
356+ return this ->_impl .incident_hyperedges (vertex_id)
357+ | std::views::transform (this ->_create_hyperedge_descriptor ());
358+ }
359+
360+ [[nodiscard]] gl_attr_force_inline auto incident_hyperedges (const vertex_type& vertex) {
361+ return this ->incident_hyperedges (vertex.id ());
362+ }
363+
364+ [[nodiscard]] types::size_type degree (const types::id_type vertex_id) const {
365+ this ->_verify_vertex_id (vertex_id);
366+ return this ->_impl .degree (vertex_id);
367+ }
368+
369+ [[nodiscard]] gl_attr_force_inline types::size_type degree (const vertex_type& vertex) const {
370+ return this ->degree (vertex.id ());
371+ }
372+
373+ [[nodiscard]] auto incident_vertices (const types::id_type hyperedge_id) {
374+ this ->_verify_hyperedge_id (hyperedge_id);
375+ return this ->_impl .incident_vertices (hyperedge_id)
376+ | std::views::transform (this ->_create_vertex_descriptor ());
377+ }
378+
379+ [[nodiscard]] gl_attr_force_inline auto incident_vertices (const hyperedge_type& hyperedge) {
380+ return this ->incident_vertices (hyperedge.id ());
381+ }
382+
383+ [[nodiscard]] types::size_type hyperedge_size (const types::id_type hyperedge_id) const {
384+ this ->_verify_hyperedge_id (hyperedge_id);
385+ return this ->_impl .hyperedge_size (hyperedge_id);
386+ }
387+
388+ [[nodiscard]] gl_attr_force_inline types::size_type hyperedge_size (
389+ const hyperedge_type& hyperedge
390+ ) const {
391+ return this ->hyperedge_size (hyperedge.id ());
392+ }
393+
359394private:
360395 // --- vertex methods ---
361396
@@ -365,10 +400,13 @@ class hypergraph final {
365400 }
366401
367402 void _remove_vertex_impl (const types::id_type vertex_id) {
403+ if (not this ->has_vertex (vertex_id))
404+ return ;
405+
406+ this ->_impl .remove_vertex (vertex_id);
368407 this ->_n_vertices --;
369408 if constexpr (type_traits::c_non_empty_properties<vertex_properties_type>)
370409 this ->_vertex_properties .erase (this ->_vertex_properties .begin () + vertex_id);
371- // TODO: impl::remove_vertex(vertex_id)
372410 }
373411
374412 // --- hyperedge methods ---
@@ -379,14 +417,52 @@ class hypergraph final {
379417 }
380418
381419 void _remove_hyperedge_impl (const types::id_type hyperedge_id) {
420+ if (not this ->has_hyperedge (hyperedge_id))
421+ return ;
422+
423+ this ->_impl .remove_hyperedge (hyperedge_id);
382424 this ->_n_hyperedges --;
383425 if constexpr (type_traits::c_non_empty_properties<hyperedge_properties_type>)
384426 this ->_hyperedge_properties .erase (this ->_hyperedge_properties .begin () + hyperedge_id);
385427 }
386428
429+ // --- transformations ---
430+
431+ gl_attr_force_inline auto _create_vertex_descriptor () noexcept
432+ requires(type_traits::c_empty_properties<vertex_properties_type>)
433+ {
434+ return [](const types::id_type id) { return vertex_type{id}; };
435+ }
436+
437+ gl_attr_force_inline auto _create_vertex_descriptor () noexcept
438+ requires(type_traits::c_non_empty_properties<vertex_properties_type>)
439+ {
440+ return [&pmap = this ->_vertex_properties ](const types::id_type id) {
441+ return vertex_type{id, *pmap[id]};
442+ };
443+ }
444+
445+ gl_attr_force_inline auto _create_hyperedge_descriptor () noexcept
446+ requires(type_traits::c_empty_properties<hyperedge_properties_type>)
447+ {
448+ return [](const types::id_type id) { return hyperedge_type{id}; };
449+ }
450+
451+ gl_attr_force_inline auto _create_hyperedge_descriptor () noexcept
452+ requires(type_traits::c_non_empty_properties<hyperedge_properties_type>)
453+ {
454+ return [&pmap = this ->_hyperedge_properties ](const types::id_type id) {
455+ return hyperedge_type{id, *pmap[id]};
456+ };
457+ }
458+
459+ // --- data members ---
460+
387461 types::size_type _n_vertices = 0uz;
388462 types::size_type _n_hyperedges = 0uz;
389463
464+ implementation_type _impl{};
465+
390466 [[no_unique_address]] vertex_properties_map_type _vertex_properties{};
391467 [[no_unique_address]] hyperedge_properties_map_type _hyperedge_properties{};
392468};
0 commit comments