44
55#pragma once
66
7+ #include " gl/types/types.hpp"
78#include " hgl/constants.hpp"
89#include " hgl/directional_tags.hpp"
910#include " hgl/hypergraph_traits.hpp"
1011#include " hgl/util.hpp"
1112
13+ #include < algorithm>
1214#include < memory>
1315#include < set>
1416#include < type_traits>
@@ -452,6 +454,10 @@ class hypergraph final {
452454 return this ->degree (vertex.id ());
453455 }
454456
457+ [[nodiscard]] std::vector<types::size_type> degree_map () const {
458+ return this ->_impl .degree_map (this ->_n_vertices );
459+ }
460+
455461 [[nodiscard]] auto outgoing_hyperedges (const types::id_type vertex_id)
456462 requires std::same_as<directional_tag, bf_directed_t>
457463 {
@@ -479,6 +485,12 @@ class hypergraph final {
479485 return this ->out_degree (vertex.id ());
480486 }
481487
488+ [[nodiscard]] std::vector<types::size_type> out_degree_map () const
489+ requires std::same_as<directional_tag, bf_directed_t>
490+ {
491+ return this ->_impl .out_degree_map (this ->_n_vertices );
492+ }
493+
482494 [[nodiscard]] auto incoming_hyperedges (const types::id_type vertex_id)
483495 requires std::same_as<directional_tag, bf_directed_t>
484496 {
@@ -506,6 +518,12 @@ class hypergraph final {
506518 return this ->in_degree (vertex.id ());
507519 }
508520
521+ [[nodiscard]] std::vector<types::size_type> in_degree_map () const
522+ requires std::same_as<directional_tag, bf_directed_t>
523+ {
524+ return this ->_impl .in_degree_map (this ->_n_vertices );
525+ }
526+
509527 [[nodiscard]] auto incident_vertices (const types::id_type hyperedge_id) {
510528 this ->_verify_hyperedge_id (hyperedge_id);
511529 return this ->_impl .incident_vertices (hyperedge_id)
@@ -527,6 +545,10 @@ class hypergraph final {
527545 return this ->hyperedge_size (hyperedge.id ());
528546 }
529547
548+ [[nodiscard]] std::vector<types::size_type> hyperedge_size_map () const {
549+ return this ->_impl .hyperedge_size_map (this ->_n_hyperedges );
550+ }
551+
530552 [[nodiscard]] auto tail_vertices (const types::id_type hyperedge_id)
531553 requires std::same_as<directional_tag, bf_directed_t>
532554 {
@@ -555,6 +577,12 @@ class hypergraph final {
555577 return this ->tail_size (hyperedge.id ());
556578 }
557579
580+ [[nodiscard]] std::vector<types::size_type> tail_size_map () const
581+ requires std::same_as<directional_tag, bf_directed_t>
582+ {
583+ return this ->_impl .tail_size_map (this ->_n_hyperedges );
584+ }
585+
558586 [[nodiscard]] auto head_vertices (const types::id_type hyperedge_id)
559587 requires std::same_as<directional_tag, bf_directed_t>
560588 {
@@ -583,6 +611,12 @@ class hypergraph final {
583611 return this ->head_size (hyperedge.id ());
584612 }
585613
614+ [[nodiscard]] std::vector<types::size_type> head_size_map () const
615+ requires std::same_as<directional_tag, bf_directed_t>
616+ {
617+ return this ->_impl .head_size_map (this ->_n_hyperedges );
618+ }
619+
586620private:
587621 // --- vertex methods ---
588622
@@ -659,4 +693,171 @@ class hypergraph final {
659693 [[no_unique_address]] hyperedge_properties_map_type _hyperedge_properties{};
660694};
661695
696+ // --- general hypergraph utility ---
697+
698+ namespace type_traits {
699+
700+ template <typename G>
701+ concept c_hypergraph = c_instantiation_of<G, hypergraph>;
702+
703+ template <typename G>
704+ concept c_undirected_hypergraph =
705+ c_hypergraph<G> and std::same_as<typename G::directional_tag, undirected_t >;
706+
707+ template <typename G>
708+ concept c_bf_directed_hypergraph =
709+ c_hypergraph<G> and std::same_as<typename G::directional_tag, bf_directed_t >;
710+
711+ } // namespace type_traits
712+
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+
662863} // namespace hgl
0 commit comments