Skip to content

Commit 898842a

Browse files
committed
incidence matrix impl + uts
1 parent d64e1c2 commit 898842a

2 files changed

Lines changed: 420 additions & 0 deletions

File tree

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
// Copyright (c) 2024-2026 Jakub Musiał
2+
// This file is part of the CPP-GL project (https://github.com/SpectraL519/cpp-gl).
3+
// Licensed under the MIT License. See the LICENSE file in the project root for full license information.
4+
5+
#pragma once
6+
7+
#include "hgl/types/types.hpp"
8+
9+
#include <algorithm>
10+
#include <ranges>
11+
#include <vector>
12+
13+
#ifdef HGL_TESTING
14+
namespace hgl_testing {
15+
struct test_incidence_matrix;
16+
} // namespace hgl_testing
17+
#endif
18+
19+
namespace hgl::impl {
20+
21+
class undirected_incidence_matrix final {
22+
public:
23+
using matrix_row_type = std::vector<bool>;
24+
using hypergraph_storage_type = std::vector<matrix_row_type>;
25+
26+
undirected_incidence_matrix(const undirected_incidence_matrix&) = delete;
27+
undirected_incidence_matrix& operator=(const undirected_incidence_matrix&) = delete;
28+
29+
undirected_incidence_matrix() = default;
30+
31+
undirected_incidence_matrix(
32+
const types::size_type n_vertices, const types::size_type n_hyperedges
33+
)
34+
: _matrix_row_size{n_hyperedges}, _matrix{n_vertices} {
35+
for (auto& row : this->_matrix)
36+
row.resize(this->_matrix_row_size, false);
37+
}
38+
39+
undirected_incidence_matrix(undirected_incidence_matrix&&) = default;
40+
undirected_incidence_matrix& operator=(undirected_incidence_matrix&&) = default;
41+
42+
~undirected_incidence_matrix() = default;
43+
44+
// --- vertex methods ---
45+
46+
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+
);
50+
}
51+
52+
gl_attr_force_inline void remove_vertex(const types::id_type vertex_id) noexcept {
53+
this->_matrix.erase(this->_matrix.begin() + vertex_id);
54+
}
55+
56+
[[nodiscard]] gl_attr_force_inline auto incident_hyperedges(const types::id_type vertex_id
57+
) 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+
);
64+
}
65+
66+
[[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;
71+
}
72+
73+
// --- hyperedge methods ---
74+
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);
79+
}
80+
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);
85+
}
86+
87+
[[nodiscard]] gl_attr_force_inline auto incident_vertices(const types::id_type hyperedge_id
88+
) 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+
});
93+
}
94+
95+
[[nodiscard]] types::size_type hyperedge_size(const types::id_type hyperedge_id
96+
) 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;
101+
}
102+
103+
// --- binding methods ---
104+
105+
gl_attr_force_inline void bind(
106+
const types::id_type vertex_id, const types::id_type hyperedge_id
107+
) noexcept {
108+
this->_matrix[vertex_id][hyperedge_id] = true;
109+
}
110+
111+
gl_attr_force_inline void unbind(
112+
const types::id_type vertex_id, const types::id_type hyperedge_id
113+
) noexcept {
114+
this->_matrix[vertex_id][hyperedge_id] = false;
115+
}
116+
117+
[[nodiscard]] gl_attr_force_inline bool are_bound(
118+
const types::id_type vertex_id, const types::id_type hyperedge_id
119+
) const noexcept {
120+
return this->_matrix[vertex_id][hyperedge_id];
121+
}
122+
123+
#ifdef HGL_TESTING
124+
friend struct hgl_testing::test_incidence_matrix;
125+
#endif
126+
127+
private:
128+
types::size_type _matrix_row_size = 0uz;
129+
hypergraph_storage_type _matrix;
130+
};
131+
132+
} // namespace hgl::impl

0 commit comments

Comments
 (0)