Skip to content

Commit db1112d

Browse files
committed
hypergraph util functions
1 parent 4f8c636 commit db1112d

5 files changed

Lines changed: 402 additions & 16 deletions

File tree

include/gl/util/ranges.hpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#pragma once
66

7+
#include <algorithm>
78
#include <ranges>
89

910
namespace gl::util {
@@ -20,4 +21,22 @@ constexpr auto range_size(R&& r) {
2021
return std::ranges::distance(std::begin(r), std::end(r));
2122
}
2223

24+
template <std::ranges::forward_range R>
25+
[[nodiscard]] constexpr bool is_constant(R&& range) noexcept {
26+
if (std::ranges::empty(range))
27+
return true;
28+
29+
return std::ranges::all_of(range, [target = *std::ranges::begin(range)](const auto& val) {
30+
return val == target;
31+
});
32+
}
33+
34+
template <std::ranges::forward_range R>
35+
[[nodiscard]] constexpr bool all_equal(R&& range, const std::ranges::range_value_t<R>& k) noexcept {
36+
if (std::ranges::empty(range))
37+
return true;
38+
39+
return std::ranges::all_of(range, [&k](const auto& val) { return val == k; });
40+
}
41+
2342
} // namespace gl::util

include/hgl/hypergraph.hpp

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "hgl/hypergraph_traits.hpp"
1111
#include "hgl/util.hpp"
1212

13+
#include <algorithm>
1314
#include <memory>
1415
#include <set>
1516
#include <type_traits>
@@ -709,4 +710,154 @@ concept c_bf_directed_hypergraph =
709710

710711
} // namespace type_traits
711712

713+
// --- degree bounds ---
714+
715+
[[nodiscard]] types::size_type max_degree(const type_traits::c_hypergraph auto& hypergraph
716+
) noexcept {
717+
const auto degrees = hypergraph.degree_map();
718+
return degrees.empty() ? 0uz : *std::ranges::max_element(degrees);
719+
}
720+
721+
[[nodiscard]] types::size_type min_degree(const type_traits::c_hypergraph auto& hypergraph
722+
) noexcept {
723+
const auto degrees = hypergraph.degree_map();
724+
return degrees.empty() ? 0uz : *std::ranges::min_element(degrees);
725+
}
726+
727+
[[nodiscard]] types::size_type max_out_degree(
728+
const type_traits::c_bf_directed_hypergraph auto& hypergraph
729+
) noexcept {
730+
const auto degrees = hypergraph.out_degree_map();
731+
return degrees.empty() ? 0uz : *std::ranges::max_element(degrees);
732+
}
733+
734+
[[nodiscard]] types::size_type min_out_degree(
735+
const type_traits::c_bf_directed_hypergraph auto& hypergraph
736+
) noexcept {
737+
const auto degrees = hypergraph.out_degree_map();
738+
return degrees.empty() ? 0uz : *std::ranges::min_element(degrees);
739+
}
740+
741+
[[nodiscard]] types::size_type max_in_degree(
742+
const type_traits::c_bf_directed_hypergraph auto& hypergraph
743+
) noexcept {
744+
const auto degrees = hypergraph.in_degree_map();
745+
return degrees.empty() ? 0uz : *std::ranges::max_element(degrees);
746+
}
747+
748+
[[nodiscard]] types::size_type min_in_degree(
749+
const type_traits::c_bf_directed_hypergraph auto& hypergraph
750+
) noexcept {
751+
const auto degrees = hypergraph.in_degree_map();
752+
return degrees.empty() ? 0uz : *std::ranges::min_element(degrees);
753+
}
754+
755+
// --- hyperedge size bounds ---
756+
757+
[[nodiscard]] types::size_type rank(const type_traits::c_hypergraph auto& hypergraph) noexcept {
758+
const auto sizes = hypergraph.hyperedge_size_map();
759+
return sizes.empty() ? 0uz : *std::ranges::max_element(sizes);
760+
}
761+
762+
[[nodiscard]] types::size_type corank(const type_traits::c_hypergraph auto& hypergraph) noexcept {
763+
const auto sizes = hypergraph.hyperedge_size_map();
764+
return sizes.empty() ? 0uz : *std::ranges::min_element(sizes);
765+
}
766+
767+
[[nodiscard]] types::size_type max_tail_size(
768+
const type_traits::c_bf_directed_hypergraph auto& hypergraph
769+
) noexcept {
770+
const auto sizes = hypergraph.tail_size_map();
771+
return sizes.empty() ? 0uz : *std::ranges::max_element(sizes);
772+
}
773+
774+
[[nodiscard]] types::size_type min_tail_size(
775+
const type_traits::c_bf_directed_hypergraph auto& hypergraph
776+
) noexcept {
777+
const auto sizes = hypergraph.tail_size_map();
778+
return sizes.empty() ? 0uz : *std::ranges::min_element(sizes);
779+
}
780+
781+
[[nodiscard]] types::size_type max_head_size(
782+
const type_traits::c_bf_directed_hypergraph auto& hypergraph
783+
) noexcept {
784+
const auto sizes = hypergraph.head_size_map();
785+
return sizes.empty() ? 0uz : *std::ranges::max_element(sizes);
786+
}
787+
788+
[[nodiscard]] types::size_type min_head_size(
789+
const type_traits::c_bf_directed_hypergraph auto& hypergraph
790+
) noexcept {
791+
const auto sizes = hypergraph.head_size_map();
792+
return sizes.empty() ? 0uz : *std::ranges::min_element(sizes);
793+
}
794+
795+
// --- regularity ---
796+
797+
[[nodiscard]] bool is_regular(
798+
const type_traits::c_hypergraph auto& hypergraph, const types::size_type k
799+
) noexcept {
800+
return util::all_equal(hypergraph.degree_map(), k);
801+
}
802+
803+
[[nodiscard]] bool is_regular(const type_traits::c_hypergraph auto& hypergraph) noexcept {
804+
return util::is_constant(hypergraph.degree_map());
805+
}
806+
807+
[[nodiscard]] bool is_out_regular(
808+
const type_traits::c_bf_directed_hypergraph auto& hypergraph, const types::size_type k
809+
) noexcept {
810+
return util::all_equal(hypergraph.out_degree_map(), k);
811+
}
812+
813+
[[nodiscard]] bool is_out_regular(const type_traits::c_bf_directed_hypergraph auto& hypergraph
814+
) noexcept {
815+
return util::is_constant(hypergraph.out_degree_map());
816+
}
817+
818+
[[nodiscard]] bool is_in_regular(
819+
const type_traits::c_bf_directed_hypergraph auto& hypergraph, const types::size_type k
820+
) noexcept {
821+
return util::all_equal(hypergraph.in_degree_map(), k);
822+
}
823+
824+
[[nodiscard]] bool is_in_regular(const type_traits::c_bf_directed_hypergraph auto& hypergraph
825+
) noexcept {
826+
return util::is_constant(hypergraph.in_degree_map());
827+
}
828+
829+
// --- uniformity ---
830+
831+
[[nodiscard]] bool is_uniform(
832+
const type_traits::c_hypergraph auto& hypergraph, const types::size_type k
833+
) noexcept {
834+
return util::all_equal(hypergraph.hyperedge_size_map(), k);
835+
}
836+
837+
[[nodiscard]] bool is_uniform(const type_traits::c_hypergraph auto& hypergraph) noexcept {
838+
return util::is_constant(hypergraph.hyperedge_size_map());
839+
}
840+
841+
[[nodiscard]] bool is_tail_uniform(
842+
const type_traits::c_bf_directed_hypergraph auto& hypergraph, const types::size_type k
843+
) noexcept {
844+
return util::all_equal(hypergraph.tail_size_map(), k);
845+
}
846+
847+
[[nodiscard]] bool is_tail_uniform(const type_traits::c_bf_directed_hypergraph auto& hypergraph
848+
) noexcept {
849+
return util::is_constant(hypergraph.tail_size_map());
850+
}
851+
852+
[[nodiscard]] bool is_head_uniform(
853+
const type_traits::c_bf_directed_hypergraph auto& hypergraph, const types::size_type k
854+
) noexcept {
855+
return util::all_equal(hypergraph.head_size_map(), k);
856+
}
857+
858+
[[nodiscard]] bool is_head_uniform(const type_traits::c_bf_directed_hypergraph auto& hypergraph
859+
) noexcept {
860+
return util::is_constant(hypergraph.head_size_map());
861+
}
862+
712863
} // namespace hgl

include/hgl/impl/incidence_matrix.hpp

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -193,20 +193,26 @@ class incidence_matrix<hgl::undirected_t, LayoutTag> final {
193193
template <impl::element_type Element>
194194
[[nodiscard]] std::vector<types::size_type> _count_map(const types::size_type n_elements
195195
) const noexcept {
196-
std::vector<types::size_type> size_map(this->_matrix.size(), 0uz);
196+
std::vector<types::size_type> size_map(n_elements, 0uz);
197197

198198
if constexpr (Element == layout_tag::major_element) { // count map major
199-
for (const auto& [i, row] : this->_matrix | std::views::enumerate)
200-
size_map[i] = static_cast<types::size_type>(std::ranges::count(row, true));
199+
const types::size_type limit =
200+
std::min(n_elements, static_cast<types::size_type>(this->_matrix.size()));
201+
for (types::size_type i = 0uz; i < limit; ++i) {
202+
size_map[i] =
203+
static_cast<types::size_type>(std::ranges::count(this->_matrix[i], true));
204+
}
201205
}
202206
else { // count map minor
203-
for (const auto& row : this->_matrix)
204-
for (types::size_type j = 0uz; j < this->_matrix_row_size; j++)
205-
if (row[j])
207+
const types::size_type limit = std::min(n_elements, this->_matrix_row_size);
208+
for (const auto& row : this->_matrix) {
209+
for (types::size_type j = 0uz; j < limit; ++j) {
210+
if (row[j]) {
206211
++size_map[j];
212+
}
213+
}
214+
}
207215
}
208-
209-
size_map.resize(n_elements, 0uz);
210216
return size_map;
211217
}
212218

@@ -487,22 +493,30 @@ class incidence_matrix<hgl::bf_directed_t, LayoutTag> final {
487493
[[nodiscard]] std::vector<types::size_type> _count_map(
488494
const types::size_type n_elements, std::predicate<incidence_type> auto&& pred
489495
) const noexcept {
490-
std::vector<types::size_type> size_map(this->_matrix.size(), 0uz);
496+
std::vector<types::size_type> size_map(n_elements, 0uz);
491497

492498
if constexpr (Element == layout_tag::major_element) { // count map major
493-
for (types::size_type i = 0uz; i < this->_matrix.size(); i++)
494-
for (const auto val : this->_matrix[i])
495-
if (pred(val))
499+
const types::size_type limit =
500+
std::min(n_elements, static_cast<types::size_type>(this->_matrix.size()));
501+
for (types::size_type i = 0uz; i < limit; ++i) {
502+
for (const auto val : this->_matrix[i]) {
503+
if (pred(val)) {
496504
++size_map[i];
505+
}
506+
}
507+
}
497508
}
498509
else { // count map minor
499-
for (const auto& row : this->_matrix)
500-
for (types::size_type j = 0uz; j < this->_matrix_row_size; j++)
501-
if (pred(row[j]))
510+
for (const auto& row : this->_matrix) {
511+
const types::size_type limit = std::min(n_elements, this->_matrix_row_size);
512+
for (types::size_type j = 0uz; j < limit; ++j) {
513+
if (pred(row[j])) {
502514
++size_map[j];
515+
}
516+
}
517+
}
503518
}
504519

505-
size_map.resize(n_elements, 0uz);
506520
return size_map;
507521
}
508522

include/hgl/util.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88

99
namespace hgl::util {
1010

11+
using gl::util::all_equal;
1112
using gl::util::deref_view;
13+
using gl::util::is_constant;
1214
using gl::util::range_size;
1315

1416
} // namespace hgl::util

0 commit comments

Comments
 (0)