Skip to content

Commit 6c4ce5e

Browse files
committed
alg properties doc + moved property functions to algorithm/properties.hpp
1 parent 0c08429 commit 6c4ce5e

9 files changed

Lines changed: 572 additions & 426 deletions

File tree

docs/hgl/algorithms/overview.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,4 @@ Explore the specific layers of the algorithm module below:
8181
- [**Standard Traversals**](traversal.md#standard-traversals): Unrestricted wrappers for basic component discovery across any hypergraph topology (`breadth_first_search`, `depth_first_search`).
8282
- [**Backward Searches**](traversal.md#backward-searches-b-reachability): Traversals enforcing strict B-reachability semantics on BF-directed hypergraphs (`backward_bfs`, `backward_dfs`), where a hyperedge is only traversed once *all* of its tail vertices are visited.
8383
- [**Forward Searches**](traversal.md#forward-searches-f-reachability): Traversals enforcing strict F-reachability semantics on BF-directed hypergraphs (`forward_bfs`, `forward_dfs`), where a hyperedge is only traversed once *all* of its head vertices are visited.
84+
- [**Hypergraph Properties**](properties.md): Lightweight functional utilities for evaluating global structural characteristics, including degree bounds, rank, corank, regularity, and uniformity.

docs/hgl/algorithms/properties.md

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
# Hypergraph Properties
2+
3+
Beyond hypergraph traversals, the HGL algorithms module provides a suite of lightweight, functional utilities to evaluate the global structural properties of a hypergraph. These algorithms allow you to quickly determine bounds, uniformity, and regularity across the topology.
4+
5+
These algorithms are grouped into four primary categories:
6+
7+
- [Vertex Degree Bounds](#vertex-degree-bounds): Functions for evaluating the minimum and maximum connectivity of vertices.
8+
- [Hyperedge Size Bounds](#hyperedge-size-bounds-rank--corank): Functions for evaluating the scale of hyperedges (Rank and Corank).
9+
- [Regularity](#regularity): Functions to check if all vertices share the same degree.
10+
- [Uniformity](#uniformity): Functions to check if all hyperedges contain the same number of vertices.
11+
12+
> [!NOTE] Algorithmic Complexity
13+
>
14+
> All property algorithms in this module operate by requesting a `degree_map()` or `hyperedge_size_map()` from the underlying hypergraph structure, and then performing a linear $\mathcal{O}(N)$ reduction (like `std::ranges::max_element` or a constant-check loop). Thus, the actual performance of these algorithms is entirely dictated by the complexity of generating the size/degree map, which varies depending on your chosen [Representation Layout](../architecture.md#representation-layouts).
15+
16+
---
17+
18+
## Vertex Degree Bounds
19+
20+
These functions evaluate the minimum and maximum degrees present within the hypergraph.
21+
22+
### Formal Definitions
23+
24+
For an undirected hypergraph $H = (V, E)$:
25+
26+
- **Maximum Degree** $\Delta(H)$: The largest degree of any vertex in the hypergraph. $\Delta(H) = \max\limits_{v \in V} deg(v)$
27+
- **Minimum Degree** $\delta(H)$: The smallest degree of any vertex in the hypergraph. $\delta(H) = \min\limits_{v \in V} deg(v)$
28+
29+
For BF-directed hypergraphs, these concepts are further split into **in-degree** (the number of incoming/head hyperedges) and **out-degree** (the number of outgoing/tail hyperedges).
30+
31+
### Available Functions
32+
33+
**Undirected & Directed (Total Degree):**
34+
35+
- [**max_degree(hypergraph)**](../../cpp-gl/group__HGL-Algorithm.md#function-max_degree): Returns the maximum degree $\Delta(H)$ among all vertices.
36+
- [**min_degree(hypergraph)**](../../cpp-gl/group__HGL-Algorithm.md#function-min_degree): Returns the minimum degree $\delta(H)$ among all vertices.
37+
38+
**BF-Directed Specifically:**
39+
40+
- [**max_out_degree(hypergraph)**](../../cpp-gl/group__HGL-Algorithm.md#function-max_out_degree): Returns the maximum out-degree among all vertices.
41+
- [**min_out_degree(hypergraph)**](../../cpp-gl/group__HGL-Algorithm.md#function-min_out_degree): Returns the minimum out-degree among all vertices.
42+
- [**max_in_degree(hypergraph)**](../../cpp-gl/group__HGL-Algorithm.md#function-max_in_degree): Returns the maximum in-degree among all vertices.
43+
- [**min_in_degree(hypergraph)**](../../cpp-gl/group__HGL-Algorithm.md#function-min_in_degree): Returns the minimum in-degree among all vertices.
44+
45+
**Note:** If the hypergraph is empty, these functions safely return `0`.
46+
47+
---
48+
49+
## Hyperedge Size Bounds (Rank & Corank)
50+
51+
Unlike standard graphs where all edges have a size of exactly 2, hyperedges can encompass any number of vertices. The bounds of these sizes define the hypergraph's Rank and Corank.
52+
53+
### Formal Definitions
54+
55+
For an undirected hypergraph $H = (V, E)$:
56+
57+
- **Rank** $r(H)$: The maximum size (cardinality) of any hyperedge in the hypergraph. $r(H) = \max\limits_{e \in E} |e|$
58+
- **Corank** $cr(H)$: The minimum size (cardinality) of any hyperedge in the hypergraph. $cr(H) = \min\limits_{e \in E} |e|$
59+
60+
### Available Functions
61+
62+
**Undirected & Directed (Total Size):**
63+
64+
- [**rank(hypergraph)**](../../cpp-gl/group__HGL-Algorithm.md#function-rank): Calculates the maximum size of any hyperedge.
65+
- [**corank(hypergraph)**](../../cpp-gl/group__HGL-Algorithm.md#function-corank): Calculates the minimum size of any hyperedge.
66+
67+
**BF-Directed Specifically:**
68+
69+
- [**max_tail_size(hypergraph)**](../../cpp-gl/group__HGL-Algorithm.md#function-max_tail_size): Calculates the maximum number of tail (source) vertices among all hyperedges.
70+
- [**min_tail_size(hypergraph)**](../../cpp-gl/group__HGL-Algorithm.md#function-min_tail_size): Calculates the minimum number of tail (source) vertices among all hyperedges.
71+
- [**max_head_size(hypergraph)**](../../cpp-gl/group__HGL-Algorithm.md#function-max_head_size): Calculates the maximum number of head (destination) vertices among all hyperedges.
72+
- [**min_head_size(hypergraph)**](../../cpp-gl/group__HGL-Algorithm.md#function-min_head_size): Calculates the minimum number of head (destination) vertices among all hyperedges.
73+
74+
---
75+
76+
## Regularity
77+
78+
A hypergraph is evaluated based on the consistency of its vertices' connectivity.
79+
80+
### Formal Definitions
81+
82+
- **$k$-Regular:** A hypergraph $H$ is $k$-regular if every vertex $v \in V$ is incident to exactly $k$ hyperedges: $(\forall v \in V)(deg(v) = k)$
83+
- **Regular:** A hypergraph is structurally regular if there exists some integer $k$ such that the hypergraph is $k$-regular (i.e., all vertices have the exact same degree): $(\exists k \in \mathbb{N})(\forall v \in V)(deg(v) = k)$
84+
85+
### Available Functions
86+
87+
**Undirected & Directed (Total Degree):**
88+
89+
- [**is_regular(hypergraph, k)**](../../cpp-gl/group__HGL-Algorithm.md#function-is_regular): Evaluates if all vertices have a degree of exactly `k`.
90+
- [**is_regular(hypergraph)**](../../cpp-gl/group__HGL-Algorithm.md#function-is_regular): Evaluates if all vertices share the same degree, regardless of what that specific degree is.
91+
92+
**BF-Directed Specifically:**
93+
94+
- [**is_out_regular(hypergraph, k)**](../../cpp-gl/group__HGL-Algorithm.md#function-is_out_regular) / [**is_out_regular(hypergraph)**](../../cpp-gl/group__HGL-Algorithm.md#function-is_out_regular): Evaluates if the hypergraph is out-$k$-regular or structurally out-regular (based strictly on out-degrees).
95+
- [**is_in_regular(hypergraph, k)**](../../cpp-gl/group__HGL-Algorithm.md#function-is_in_regular) / [**is_in_regular(hypergraph)**](../../cpp-gl/group__HGL-Algorithm.md#function-is_in_regular): Evaluates if the hypergraph is in-$k$-regular or structurally in-regular (based strictly on in-degrees).
96+
97+
---
98+
99+
## Uniformity
100+
101+
A hypergraph is evaluated based on the consistency of its hyperedges' sizes.
102+
103+
### Formal Definitions
104+
105+
- **$k$-Uniform:** A hypergraph $H$ is $k$-uniform if every hyperedge $e \in E$ contains exactly $k$ vertices: $(\forall e \in E)(|e| = k)$
106+
*Note: A 2-uniform undirected hypergraph is equivalent to a standard undirected graph.*
107+
- **Uniform:** A hypergraph is structurally uniform if there exists some integer $k$ such that the hypergraph is $k$-uniform (i.e., all hyperedges have the exact same size): $(\exists k \in \mathbb{N})(\forall e \in E)(|e| = k)$
108+
109+
### Available Functions
110+
111+
**Undirected & Directed (Total Size):**
112+
113+
- [**is_uniform(hypergraph, k)**](../../cpp-gl/group__HGL-Algorithm.md#function-is_uniform): Evaluates if all hyperedges contain exactly `k` vertices.
114+
- [**is_uniform(hypergraph)**](../../cpp-gl/group__HGL-Algorithm.md#function-is_uniform): Evaluates if all hyperedges are the exact same size.
115+
116+
**BF-Directed Specifically:**
117+
118+
- [**is_tail_uniform(hypergraph, k)**](../../cpp-gl/group__HGL-Algorithm.md#function-is_tail_uniform) / [**is_tail_uniform(hypergraph)**](../../cpp-gl/group__HGL-Algorithm.md#function-is_tail_uniform): Evaluates if all hyperedges have a tail size of exactly `k`, or share the same tail size.
119+
- [**is_head_uniform(hypergraph, k)**](../../cpp-gl/group__HGL-Algorithm.md#function-is_head_uniform) / [**is_head_uniform(hypergraph)**](../../cpp-gl/group__HGL-Algorithm.md#function-is_head_uniform): Evaluates if all hyperedges have a head size of exactly `k`, or share the same head size.

docs/hgl/properties.md

Lines changed: 0 additions & 1 deletion
This file was deleted.

include/hgl/algorithm.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,6 @@
2020
#include "hgl/algorithm/traversal/backward_search.hpp"
2121
#include "hgl/algorithm/traversal/forward_search.hpp"
2222

23+
#include "hgl/algorithm/properties.hpp"
24+
2325
// clang-format on
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
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+
/// @file hgl/algorithm/properties.hpp
6+
/// @brief Defines lightweight, functional utilities to evaluate the global structural properties of a hypergraph.
7+
8+
#pragma once
9+
10+
#include "hgl/hypergraph.hpp"
11+
#include "hgl/util.hpp"
12+
13+
namespace hgl::algorithm {
14+
15+
// --- degree bounds ---
16+
17+
/// @ingroup HGL-Algorithm
18+
/// @brief Calculates the maximum degree among all vertices in a hypergraph.
19+
[[nodiscard]] size_type max_degree(const traits::c_hypergraph auto& hypergraph) noexcept {
20+
const auto degrees = hypergraph.degree_map();
21+
return degrees.empty() ? 0uz : *std::ranges::max_element(degrees);
22+
}
23+
24+
/// @ingroup HGL-Algorithm
25+
/// @brief Calculates the minimum degree among all vertices in a hypergraph.
26+
[[nodiscard]] size_type min_degree(const traits::c_hypergraph auto& hypergraph) noexcept {
27+
const auto degrees = hypergraph.degree_map();
28+
return degrees.empty() ? 0uz : *std::ranges::min_element(degrees);
29+
}
30+
31+
/// @ingroup HGL-Algorithm
32+
/// @brief Calculates the maximum out-degree among all vertices in a *BF-directed* hypergraph.
33+
[[nodiscard]] size_type max_out_degree(const traits::c_bf_directed_hypergraph auto& hypergraph
34+
) noexcept {
35+
const auto degrees = hypergraph.out_degree_map();
36+
return degrees.empty() ? 0uz : *std::ranges::max_element(degrees);
37+
}
38+
39+
/// @ingroup HGL-Algorithm
40+
/// @brief Calculates the minimum out-degree among all vertices in a *BF-directed* hypergraph.
41+
[[nodiscard]] size_type min_out_degree(const traits::c_bf_directed_hypergraph auto& hypergraph
42+
) noexcept {
43+
const auto degrees = hypergraph.out_degree_map();
44+
return degrees.empty() ? 0uz : *std::ranges::min_element(degrees);
45+
}
46+
47+
/// @ingroup HGL-Algorithm
48+
/// @brief Calculates the maximum in-degree among all vertices in a *BF-directed* hypergraph.
49+
[[nodiscard]] size_type max_in_degree(const traits::c_bf_directed_hypergraph auto& hypergraph
50+
) noexcept {
51+
const auto degrees = hypergraph.in_degree_map();
52+
return degrees.empty() ? 0uz : *std::ranges::max_element(degrees);
53+
}
54+
55+
/// @ingroup HGL-Algorithm
56+
/// @brief Calculates the minimum in-degree among all vertices in a *BF-directed* hypergraph.
57+
[[nodiscard]] size_type min_in_degree(const traits::c_bf_directed_hypergraph auto& hypergraph
58+
) noexcept {
59+
const auto degrees = hypergraph.in_degree_map();
60+
return degrees.empty() ? 0uz : *std::ranges::min_element(degrees);
61+
}
62+
63+
// --- hyperedge size bounds ---
64+
65+
/// @ingroup HGL-Algorithm
66+
/// @brief Calculates the rank (maximum size of any hyperedge) of a hypergraph.
67+
[[nodiscard]] size_type rank(const traits::c_hypergraph auto& hypergraph) noexcept {
68+
const auto sizes = hypergraph.hyperedge_size_map();
69+
return sizes.empty() ? 0uz : *std::ranges::max_element(sizes);
70+
}
71+
72+
/// @ingroup HGL-Algorithm
73+
/// @brief Calculates the corank (minimum size of any hyperedge) of a hypergraph.
74+
[[nodiscard]] size_type corank(const traits::c_hypergraph auto& hypergraph) noexcept {
75+
const auto sizes = hypergraph.hyperedge_size_map();
76+
return sizes.empty() ? 0uz : *std::ranges::min_element(sizes);
77+
}
78+
79+
/// @ingroup HGL-Algorithm
80+
/// @brief Calculates the maximum tail size among all hyperedges in a *BF-directed* hypergraph.
81+
[[nodiscard]] size_type max_tail_size(const traits::c_bf_directed_hypergraph auto& hypergraph
82+
) noexcept {
83+
const auto sizes = hypergraph.tail_size_map();
84+
return sizes.empty() ? 0uz : *std::ranges::max_element(sizes);
85+
}
86+
87+
/// @ingroup HGL-Algorithm
88+
/// @brief Calculates the minimum tail size among all hyperedges in a *BF-directed* hypergraph.
89+
[[nodiscard]] size_type min_tail_size(const traits::c_bf_directed_hypergraph auto& hypergraph
90+
) noexcept {
91+
const auto sizes = hypergraph.tail_size_map();
92+
return sizes.empty() ? 0uz : *std::ranges::min_element(sizes);
93+
}
94+
95+
/// @ingroup HGL-Algorithm
96+
/// @brief Calculates the maximum head size among all hyperedges in a *BF-directed* hypergraph.
97+
[[nodiscard]] size_type max_head_size(const traits::c_bf_directed_hypergraph auto& hypergraph
98+
) noexcept {
99+
const auto sizes = hypergraph.head_size_map();
100+
return sizes.empty() ? 0uz : *std::ranges::max_element(sizes);
101+
}
102+
103+
/// @ingroup HGL-Algorithm
104+
/// @brief Calculates the minimum head size among all hyperedges in a *BF-directed* hypergraph.
105+
[[nodiscard]] size_type min_head_size(const traits::c_bf_directed_hypergraph auto& hypergraph
106+
) noexcept {
107+
const auto sizes = hypergraph.head_size_map();
108+
return sizes.empty() ? 0uz : *std::ranges::min_element(sizes);
109+
}
110+
111+
// --- regularity ---
112+
113+
/// @ingroup HGL-Algorithm
114+
/// @brief Evaluates whether the given hypergraph is $k$-regular (all vertices have a degree of $k$).
115+
[[nodiscard]] bool is_regular(
116+
const traits::c_hypergraph auto& hypergraph, const size_type k
117+
) noexcept {
118+
return util::all_equal(hypergraph.degree_map(), k);
119+
}
120+
121+
/// @ingroup HGL-Algorithm
122+
/// @brief Evaluates whether the given hypergraph is structurally regular (all vertices have the same degree).
123+
[[nodiscard]] bool is_regular(const traits::c_hypergraph auto& hypergraph) noexcept {
124+
return util::is_constant(hypergraph.degree_map());
125+
}
126+
127+
/// @ingroup HGL-Algorithm
128+
/// @brief Evaluates whether the given *BF-directed* hypergraph is out-$k$-regular (all vertices have an out-degree of $k$).
129+
[[nodiscard]] bool is_out_regular(
130+
const traits::c_bf_directed_hypergraph auto& hypergraph, const size_type k
131+
) noexcept {
132+
return util::all_equal(hypergraph.out_degree_map(), k);
133+
}
134+
135+
/// @ingroup HGL-Algorithm
136+
/// @brief Evaluates whether the given *BF-directed* hypergraph is out-regular (all vertices have the same out-degree).
137+
[[nodiscard]] bool is_out_regular(const traits::c_bf_directed_hypergraph auto& hypergraph
138+
) noexcept {
139+
return util::is_constant(hypergraph.out_degree_map());
140+
}
141+
142+
/// @ingroup HGL-Algorithm
143+
/// @brief Evaluates whether the given *BF-directed* hypergraph is in-$k$-regular (all vertices have an in-degree of $k$).
144+
[[nodiscard]] bool is_in_regular(
145+
const traits::c_bf_directed_hypergraph auto& hypergraph, const size_type k
146+
) noexcept {
147+
return util::all_equal(hypergraph.in_degree_map(), k);
148+
}
149+
150+
/// @ingroup HGL-Algorithm
151+
/// @brief Evaluates whether the given *BF-directed* hypergraph is in-regular (all vertices have the same in-degree).
152+
[[nodiscard]] bool is_in_regular(const traits::c_bf_directed_hypergraph auto& hypergraph) noexcept {
153+
return util::is_constant(hypergraph.in_degree_map());
154+
}
155+
156+
// --- uniformity ---
157+
158+
/// @ingroup HGL-Algorithm
159+
/// @brief Evaluates whether the given hypergraph is $k$-uniform (all hyperedges have a size of $k$).
160+
[[nodiscard]] bool is_uniform(
161+
const traits::c_hypergraph auto& hypergraph, const size_type k
162+
) noexcept {
163+
return util::all_equal(hypergraph.hyperedge_size_map(), k);
164+
}
165+
166+
/// @ingroup HGL-Algorithm
167+
/// @brief Evaluates whether the given hypergraph is structurally uniform (all hyperedges have the exact same size).
168+
[[nodiscard]] bool is_uniform(const traits::c_hypergraph auto& hypergraph) noexcept {
169+
return util::is_constant(hypergraph.hyperedge_size_map());
170+
}
171+
172+
/// @ingroup HGL-Algorithm
173+
/// @brief Evaluates whether the given *BF-directed* hypergraph is tail-$k$-uniform (all hyperedges have a tail size of $k$).
174+
[[nodiscard]] bool is_tail_uniform(
175+
const traits::c_bf_directed_hypergraph auto& hypergraph, const size_type k
176+
) noexcept {
177+
return util::all_equal(hypergraph.tail_size_map(), k);
178+
}
179+
180+
/// @ingroup HGL-Algorithm
181+
/// @brief Evaluates whether the given *BF-directed* hypergraph is tail-uniform (all hyperedges have the exact same tail size).
182+
[[nodiscard]] bool is_tail_uniform(const traits::c_bf_directed_hypergraph auto& hypergraph
183+
) noexcept {
184+
return util::is_constant(hypergraph.tail_size_map());
185+
}
186+
187+
/// @ingroup HGL-Algorithm
188+
/// @brief Evaluates whether the given *BF-directed* hypergraph is head-$k$-uniform (all hyperedges have a head size of $k$).
189+
[[nodiscard]] bool is_head_uniform(
190+
const traits::c_bf_directed_hypergraph auto& hypergraph, const size_type k
191+
) noexcept {
192+
return util::all_equal(hypergraph.head_size_map(), k);
193+
}
194+
195+
/// @ingroup HGL-Algorithm
196+
/// @brief Evaluates whether the given *BF-directed* hypergraph is head-uniform (all hyperedges have the exact same head size).
197+
[[nodiscard]] bool is_head_uniform(const traits::c_bf_directed_hypergraph auto& hypergraph
198+
) noexcept {
199+
return util::is_constant(hypergraph.head_size_map());
200+
}
201+
202+
} // namespace hgl::algorithm

0 commit comments

Comments
 (0)