55#pragma once
66
77#include " hgl/types/types.hpp"
8+ #include " layout_tags.hpp"
89
910#include < algorithm>
1011#include < ranges>
@@ -18,8 +19,12 @@ struct test_incidence_matrix;
1819
1920namespace hgl ::impl {
2021
22+ template <type_traits::c_hypergraph_layout_tag LayoutTag>
2123class undirected_incidence_matrix final {
2224public:
25+ using layout_tag = LayoutTag;
26+
27+ // Rows are "Major", Columns are "Minor"
2328 using matrix_row_type = std::vector<bool >;
2429 using hypergraph_storage_type = std::vector<matrix_row_type>;
2530
@@ -31,10 +36,10 @@ class undirected_incidence_matrix final {
3136 undirected_incidence_matrix (
3237 const types::size_type n_vertices, const types::size_type n_hyperedges
3338 )
34- : _matrix_row_size{n_hyperedges}, _matrix{n_vertices} {
35- for ( auto & row : this -> _matrix )
36- row. resize ( this -> _matrix_row_size , false );
37- }
39+ : _minor_size{ layout_tag::minor (n_vertices, n_hyperedges)},
40+ _major_storage (
41+ layout_tag::major (n_vertices, n_hyperedges), matrix_row_type(_minor_size , false )
42+ ) { }
3843
3944 undirected_incidence_matrix (undirected_incidence_matrix&&) = default;
4045 undirected_incidence_matrix& operator =(undirected_incidence_matrix&&) = default ;
@@ -44,89 +49,151 @@ class undirected_incidence_matrix final {
4449 // --- vertex methods ---
4550
4651 gl_attr_force_inline void add_vertices (const types::size_type n) noexcept {
47- this ->_matrix .resize (
48- this ->_matrix .size () + n, matrix_row_type (this ->_matrix_row_size , false )
49- );
52+ if constexpr (std::same_as<layout_tag, impl::vertex_major_t >)
53+ this ->_add_major (n);
54+ else
55+ this ->_add_minor (n);
5056 }
5157
5258 gl_attr_force_inline void remove_vertex (const types::id_type vertex_id) noexcept {
53- this ->_matrix .erase (this ->_matrix .begin () + vertex_id);
59+ if constexpr (std::same_as<layout_tag, impl::vertex_major_t >)
60+ this ->_remove_major (vertex_id);
61+ else
62+ this ->_remove_minor (vertex_id);
5463 }
5564
5665 [[nodiscard]] gl_attr_force_inline auto incident_hyperedges (const types::id_type vertex_id
5766 ) const noexcept {
58- return std::views::iota (0uz, this ->_matrix_row_size )
59- | std::views::filter (
60- [&vertex_row = this ->_matrix [vertex_id]](const auto hyperedge_id) -> bool {
61- return vertex_row[hyperedge_id];
62- }
63- );
67+ if constexpr (std::same_as<layout_tag, impl::vertex_major_t >)
68+ return this ->_incident_to_major (vertex_id);
69+ else
70+ return this ->_incident_to_minor (vertex_id);
6471 }
6572
6673 [[nodiscard]] types::size_type degree (const types::id_type vertex_id) const noexcept {
67- types::size_type deg = 0 ;
68- for ( const bool is_hyperedge_incident : this ->_matrix [ vertex_id])
69- deg += static_cast <types::size_type>(is_hyperedge_incident);
70- return deg ;
74+ if constexpr (std::same_as<layout_tag, impl:: vertex_major_t >)
75+ return this ->_count_major_bits ( vertex_id);
76+ else
77+ return this -> _count_minor_bits (vertex_id) ;
7178 }
7279
7380 // --- hyperedge methods ---
7481
75- void add_hyperedges (const types::size_type n) noexcept {
76- this ->_matrix_row_size += n;
77- for (auto & row : this ->_matrix )
78- row.resize (this ->_matrix_row_size , false );
82+ gl_attr_force_inline void add_hyperedges (const types::size_type n) noexcept {
83+ if constexpr (std::same_as<layout_tag, impl::hyperedge_major_t >)
84+ this ->_add_major (n);
85+ else
86+ this ->_add_minor (n);
7987 }
8088
81- void remove_hyperedge (const types::id_type hyperedge_id) noexcept {
82- this ->_matrix_row_size --;
83- for (auto & row : this ->_matrix )
84- row.erase (row.begin () + hyperedge_id);
89+ gl_attr_force_inline void remove_hyperedge (const types::id_type hyperedge_id) noexcept {
90+ if constexpr (std::same_as<layout_tag, impl::hyperedge_major_t >)
91+ this ->_remove_major (hyperedge_id);
92+ else
93+ this ->_remove_minor (hyperedge_id);
8594 }
8695
8796 [[nodiscard]] gl_attr_force_inline auto incident_vertices (const types::id_type hyperedge_id
8897 ) const noexcept {
89- return std::views::iota (0uz, this -> _matrix . size () )
90- | std::views::filter ([ this , hyperedge_id]( const auto vertex_id) {
91- return this -> _matrix [vertex_id][hyperedge_id];
92- } );
98+ if constexpr ( std::same_as<layout_tag, impl:: hyperedge_major_t > )
99+ return this -> _incident_to_major (hyperedge_id);
100+ else
101+ return this -> _incident_to_minor (hyperedge_id );
93102 }
94103
95104 [[nodiscard]] types::size_type hyperedge_size (const types::id_type hyperedge_id
96105 ) const noexcept {
97- types::size_type size = 0 ;
98- for ( const auto & row : this ->_matrix )
99- size += static_cast <types::size_type>(row[hyperedge_id]);
100- return size ;
106+ if constexpr (std::same_as<layout_tag, impl:: hyperedge_major_t >)
107+ return this ->_count_major_bits (hyperedge_id);
108+ else
109+ return this -> _count_minor_bits (hyperedge_id) ;
101110 }
102111
103112 // --- binding methods ---
104113
105114 gl_attr_force_inline void bind (
106115 const types::id_type vertex_id, const types::id_type hyperedge_id
107116 ) noexcept {
108- this ->_matrix [vertex_id][hyperedge_id] = true ;
117+ const auto [major_id, minor_id] = layout_tag::majmin (vertex_id, hyperedge_id);
118+ this ->_major_storage [major_id][minor_id] = true ;
109119 }
110120
111121 gl_attr_force_inline void unbind (
112122 const types::id_type vertex_id, const types::id_type hyperedge_id
113123 ) noexcept {
114- this ->_matrix [vertex_id][hyperedge_id] = false ;
124+ const auto [major_id, minor_id] = layout_tag::majmin (vertex_id, hyperedge_id);
125+ this ->_major_storage [major_id][minor_id] = false ;
115126 }
116127
117128 [[nodiscard]] gl_attr_force_inline bool are_bound (
118129 const types::id_type vertex_id, const types::id_type hyperedge_id
119130 ) const noexcept {
120- return this ->_matrix [vertex_id][hyperedge_id];
131+ const auto [major_id, minor_id] = layout_tag::majmin (vertex_id, hyperedge_id);
132+ return this ->_major_storage [major_id][minor_id];
121133 }
122134
123135#ifdef HGL_TESTING
124136 friend struct hgl_testing ::test_incidence_matrix;
125137#endif
126138
127139private:
128- types::size_type _matrix_row_size = 0uz;
129- hypergraph_storage_type _matrix;
140+ types::size_type _minor_size = 0uz; // matrix row size
141+ hypergraph_storage_type _major_storage;
142+
143+ gl_attr_force_inline void _add_major (const types::size_type n) noexcept {
144+ this ->_major_storage .resize (
145+ this ->_major_storage .size () + n, matrix_row_type (this ->_minor_size , false )
146+ );
147+ }
148+
149+ void _add_minor (const types::size_type n) noexcept {
150+ this ->_minor_size += n;
151+ for (auto & row : this ->_major_storage )
152+ row.resize (this ->_minor_size , false );
153+ }
154+
155+ gl_attr_force_inline void _remove_major (const types::id_type major_id) noexcept {
156+ this ->_major_storage .erase (this ->_major_storage .begin () + major_id);
157+ }
158+
159+ gl_attr_force_inline void _remove_minor (const types::id_type minor_id) noexcept {
160+ if (this ->_minor_size == 0 )
161+ return ;
162+ this ->_minor_size --;
163+ for (auto & row : this ->_major_storage ) {
164+ row.erase (row.begin () + minor_id);
165+ }
166+ }
167+
168+ [[nodiscard]] auto _incident_to_major (const types::id_type major_id) const noexcept {
169+ return std::views::iota (0uz, this ->_minor_size )
170+ | std::views::filter (
171+ [&row = this ->_major_storage [major_id]](const types::id_type minor_id) {
172+ return row[minor_id];
173+ }
174+ );
175+ }
176+
177+ [[nodiscard]] auto _incident_to_minor (const types::id_type minor_id) const noexcept {
178+ return std::views::iota (0uz, this ->_major_storage .size ())
179+ | std::views::filter ([this , minor_id](const types::id_type major_id) {
180+ return this ->_major_storage [major_id][minor_id];
181+ });
182+ }
183+
184+ [[nodiscard]] types::size_type _count_major_bits (const types::id_type major_id) const noexcept {
185+ types::size_type count = 0 ;
186+ for (const bool bit : this ->_major_storage [major_id])
187+ count += static_cast <types::size_type>(bit);
188+ return count;
189+ }
190+
191+ [[nodiscard]] types::size_type _count_minor_bits (const types::id_type minor_id) const noexcept {
192+ types::size_type count = 0 ;
193+ for (const auto & row : this ->_major_storage )
194+ count += static_cast <types::size_type>(row[minor_id]);
195+ return count;
196+ }
130197};
131198
132199} // namespace hgl::impl
0 commit comments