Skip to content

Commit 7f355d9

Browse files
committed
init_range -> init_node_range + bfs tmpl doc
1 parent 1490421 commit 7f355d9

12 files changed

Lines changed: 94 additions & 21 deletions

File tree

docs/gl/quick_start.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,12 @@ int main() {
4242
return 1;
4343
}
4444

45-
auto path_to_target = gl::algorithm::reconstruct_path(paths.predecessors, target_id); // (7)!
45+
auto path_to_target
46+
= gl::algorithm::reconstruct_path(paths.predecessors, target_id); // (7)!
4647
std::cout << "Shortest path distance to vertex " << target_id << ": "
4748
<< paths.distances[target_id] << "\nPath: "
48-
<< gl::io::range_formatter(path_to_target, " -> ", "", "") << '\n'; // (8)!
49+
<< gl::io::range_formatter(path_to_target, " -> ", "", "") // (8)!
50+
<< '\n';
4951

5052
return 0;
5153
}

include/gl/algorithm/templates/bfs.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ namespace gl::algorithm {
2929
///
3030
/// bool completed = gl::algorithm::bfs(
3131
/// graph,
32-
/// gl::algorithm::init_range<graph_type>(start_id), // (2)!
32+
/// gl::algorithm::init_node_range<graph_type>(start_id), // (2)!
3333
/// gl::algorithm::default_visit_vertex_predicate(visited), // (3)!
3434
/// [&](auto v, auto p) { // (4)!
3535
/// std::cout << "Visited vertex " << v << '\n';

include/gl/algorithm/templates/dfs.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ namespace gl::algorithm {
2828
///
2929
/// bool completed = gl::algorithm::dfs(
3030
/// graph,
31-
/// gl::algorithm::init_range<graph_type>(start_id), // (2)!
31+
/// gl::algorithm::init_node_range<graph_type>(start_id), // (2)!
3232
/// gl::algorithm::default_visit_vertex_predicate(visited), // (3)!
3333
/// [&](auto v, auto p) { // (4)!
3434
/// std::cout << "Visited vertex " << v << '\n';

include/gl/algorithm/templates/pfs.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ namespace gl::algorithm {
3434
/// [](const auto& lhs, const auto& rhs) { // (2)!
3535
/// return lhs.vertex_id > rhs.vertex_id;
3636
/// },
37-
/// gl::algorithm::init_range<graph_type>(start_id), // (3)!
37+
/// gl::algorithm::init_node_range<graph_type>(start_id), // (3)!
3838
/// gl::algorithm::default_visit_vertex_predicate(visited // (4)!
3939
/// [&](auto v, auto p) { // (5)!
4040
/// std::cout << "Priority visited vertex " << v << '\n';

include/gl/algorithm/topology/coloring.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ template <
7979

8080
const bool is_bipartite = bfs(
8181
graph,
82-
init_range<G>(root_id),
82+
init_node_range<G>(root_id),
8383
empty_callback{}, // visit predicate
8484
empty_callback{}, // visit callback
8585
[&coloring](typename G::id_type vertex_id, const edge_type& in_edge)

include/gl/algorithm/traversal/breadth_first_search.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ result_type<Result, predecessors_map<G>> breadth_first_search(
8787
if (root_vertex_id != no_root) {
8888
bfs(
8989
graph,
90-
init_range<G>(root_vertex_id),
90+
init_node_range<G>(root_vertex_id),
9191
default_visit_vertex_predicate(visited),
9292
default_visit_callback<G, Result>(visited, pred_map),
9393
default_enqueue_node_predicate<G, true>(visited),
@@ -99,7 +99,7 @@ result_type<Result, predecessors_map<G>> breadth_first_search(
9999
for (const auto root_id : graph.vertex_ids())
100100
bfs(
101101
graph,
102-
init_range<G>(root_id),
102+
init_node_range<G>(root_id),
103103
default_visit_vertex_predicate(visited),
104104
default_visit_callback<G, Result>(visited, pred_map),
105105
default_enqueue_node_predicate<G, true>(visited),

include/gl/algorithm/traversal/depth_first_search.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ result_type<Result, predecessors_map<G>> depth_first_search(
9595
if (root_vertex_id != no_root) {
9696
dfs(
9797
graph,
98-
init_range<G>(root_vertex_id),
98+
init_node_range<G>(root_vertex_id),
9999
default_visit_vertex_predicate(visited),
100100
default_visit_callback<G, Result>(visited, pred_map),
101101
default_enqueue_node_predicate<G, true>(visited),
@@ -107,7 +107,7 @@ result_type<Result, predecessors_map<G>> depth_first_search(
107107
for (const auto root_id : graph.vertex_ids())
108108
dfs(
109109
graph,
110-
init_range<G>(root_id),
110+
init_node_range<G>(root_id),
111111
default_visit_vertex_predicate(visited),
112112
default_visit_callback<G, Result>(visited, pred_map),
113113
default_enqueue_node_predicate<G, true>(visited),

include/gl/algorithm/util.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,16 @@ template <traits::c_id_type IdType>
4545
}
4646

4747
/// @ingroup GL GL-Algorithm
48-
/// @brief Initializes a search container (queue or stack) with the starting root vertex.
48+
/// @brief Initializes a search container with the starting root vertex.
4949
/// @tparam G The type of the graph.
5050
/// @tparam InitRangeType The underlying container type for the container.
5151
/// @param root_vertex_id The ID of the starting vertex.
5252
/// @return A container initialized with a single @ref search_node for the root vertex.
5353
template <
5454
traits::c_graph G,
5555
traits::c_forward_range_of<search_node<G>> InitRangeType = std::vector<search_node<G>>>
56-
[[nodiscard]] gl_attr_force_inline InitRangeType init_range(typename G::id_type root_vertex_id) {
56+
[[nodiscard]] gl_attr_force_inline InitRangeType init_node_range(typename G::id_type root_vertex_id
57+
) {
5758
return InitRangeType{search_node<G>{root_vertex_id}};
5859
}
5960

include/hgl/algorithm/templates/bfs.hpp

Lines changed: 74 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
// This file is part of the CPP-GL project (https://github.com/SpectraL519/cpp-gl).
33
// Licensed under the MIT License. See the LICENSE file in the project root for full license information.
44

5+
/// @file hgl/algorithm/templates/bfs.hpp
6+
/// @brief Generic Breadth-First Search (BFS) template algorithm engine for hypergraphs.
7+
58
#pragma once
69

710
#include "hgl/algorithm/core.hpp"
@@ -10,15 +13,82 @@
1013

1114
namespace hgl::algorithm {
1215

13-
/// @ingroup hgl_alg
16+
/// @ingroup HGL-Algorithm
17+
/// @brief A highly customizable, generic Breadth-First Search (BFS) algorithm engine for hypergraphs.
18+
///
19+
/// This template provides the strict structural execution of a queue-based Breadth-First Search
20+
/// over a hypergraph's topology. Because a hypergraph traversal inherently requires a two-step
21+
/// expansion (from a vertex to its incident hyperedges, and then to the adjacent vertices), this
22+
/// engine exposes specific hooks for both steps. Concrete algorithms are constructed by injecting
23+
/// logic into the provided callback and predicate hooks.
24+
///
25+
/// ### Example Usage
26+
/// ```cpp
27+
/// std::vector<bool> visited(hypergraph.n_vertices(), false); // (1)!
28+
///
29+
/// bool completed = hgl::algorithm::bfs(
30+
/// hypergraph,
31+
/// hgl::algorithm::init_node_range<H>(start_id), // (2)!
32+
/// [&](const auto& node) { return not visited[node.vertex_id]; }, // (3)!
33+
/// [&](const auto& node) { // (4)!
34+
/// visited[node.vertex_id] = true;
35+
/// std::cout << "Visited vertex " << node.vertex_id << '\n';
36+
/// return true; // Continue search
37+
/// },
38+
/// hgl::empty_callback{}, // (5)!
39+
/// [&](const auto& tgt_node) { return not visited[tgt_node.vertex_id]; } // (6)!
40+
/// );
41+
/// ```
42+
///
43+
/// 1\. Provide an external state array to track the visited vertices.
44+
///
45+
/// 2\. Initialize the search queue with a root @ref hgl::algorithm::search_node "search node" representing the starting point.
46+
///
47+
/// 3\. The *visit predicate* ensures vertices are not processed multiple times.
48+
///
49+
/// 4\. The concrete vertex visiting logic - marks the vertex as visited and logs it to the console.
50+
///
51+
/// 5\. Traverse all hyperedges unconditionally.
52+
///
53+
/// 6\. The *enqueue predicate* filters out already visited adjacent vertices before they enter the queue.
54+
///
55+
/// ### Template Parameters
56+
/// | Parameter | Description | Constraint |
57+
/// | :-------- | :--- | :--- |
58+
/// | Dir | The @ref hgl::algorithm::traversal_direction "traversal direction" (i.e., `forward` or `backward`). Relevant only for BF-directed hypergraphs. | Defaults to `forward`. |
59+
/// | H | The type of the hypergraph being searched. | Must satisfy the [**c_hypergraph**](hgl_concepts.md#hgl-traits-c-hypergraph) concept. |
60+
/// | InitQueueRangeType | A forward range of `search_node<H>` used to prime the BFS queue. | Must be a *forward range* of @ref hgl::algorithm::search_node "search nodes". |
61+
/// | VisitPredicate | Type of the callable deciding if a popped node should be processed. | Must be one of:<br/>- A `(const search_node<H>&) -> bool` callable<br/>- An @ref hgl::algorithm::empty_callback "empty_callback" |
62+
/// | VisitCallback | Type of the callable executed when a vertex is officially visited. | Must be one of:<br/>- A `(const search_node<H>&) -> bool` callable<br/>- An @ref hgl::algorithm::empty_callback "empty_callback" |
63+
/// | TraverseHePredicate | Type of the callable deciding if an incident hyperedge should be traversed. | Must be one of:<br/>- An `(id_type, id_type) -> decision` callable<br/>- An @ref hgl::algorithm::empty_callback "empty_callback" |
64+
/// | EnqueuePredicate | Type of the callable deciding if a target vertex should be enqueued via a specific hyperedge. | Must be one of:<br/>- A `(const search_node<H>&) -> decision` callable<br/>- An @ref hgl::algorithm::empty_callback "empty_callback" |
65+
/// | PreVisitCallback | Type of the callable executed immediately before `VisitCallback`. | Must be one of:<br/>- A `(const search_node<H>&) -> void` callable<br/>- An @ref hgl::algorithm::empty_callback "empty_callback" |
66+
/// | PostVisitCallback | Type of the callable executed after all adjacent elements are evaluated. | Must be one of:<br/>- A `(const search_node<H>&) -> void` callable<br/>- An @ref hgl::algorithm::empty_callback "empty_callback" |
67+
///
68+
/// @param hypergraph The hypergraph to traverse.
69+
/// @param initial_queue_content The initial set of search nodes to begin the traversal from.
70+
/// @param visit_pred Predicate to filter nodes immediately after popping them from the queue.
71+
/// @param visit Primary callback for node processing.
72+
/// @param traverse_he_pred Predicate to determine if an incident hyperedge should be traversed. Returns a @ref hgl::algorithm::decision "decision":
73+
/// - `accept` to traverse the hyperedge,
74+
/// - `reject` to skip the hyperedge,
75+
/// - `abort` to terminate the BFS entirely.
76+
/// @param enqueue_pred Predicate to determine if an adjacent vertex should be queued via a hyperedge. Returns a @ref hgl::algorithm::decision "decision":
77+
/// - `accept` to enqueue the vertex's search node,
78+
/// - `reject` to skip the node,
79+
/// - `abort` to terminate the BFS entirely.
80+
/// @param pre_visit Callback executed prior to the primary visit logic.
81+
/// @param post_visit Callback executed after all adjacent elements of the current node have been processed.
82+
/// @return `true` if the search completed normally, `false` if it was explicitly aborted via a callback.
83+
/// @hideparams
1484
template <
1585
traversal_direction Dir = traversal_direction::forward,
1686
traits::c_hypergraph H,
1787
traits::c_forward_range_of<search_node<H>> InitQueueRangeType = std::vector<search_node<H>>,
1888
traits::c_optional_predicate<const search_node<H>&> VisitPredicate = empty_callback,
1989
traits::c_optional_predicate<const search_node<H>&> VisitCallback = empty_callback,
2090
traits::c_optional_decision_predicate<typename H::id_type, typename H::id_type>
21-
TraverseHyperedgePredicate = empty_callback,
91+
TraverseHePredicate = empty_callback,
2292
traits::c_decision_predicate<const search_node<H>&> EnqueuePredicate = empty_callback,
2393
traits::c_optional_callback<void, const search_node<H>&> PreVisitCallback = empty_callback,
2494
traits::c_optional_callback<void, const search_node<H>&> PostVisitCallback = empty_callback>
@@ -27,7 +97,7 @@ bool bfs(
2797
const InitQueueRangeType& initial_queue_content,
2898
const VisitPredicate& visit_pred = {},
2999
const VisitCallback& visit = {},
30-
const TraverseHyperedgePredicate& traverse_he_pred = {},
100+
const TraverseHePredicate& traverse_he_pred = {},
31101
const EnqueuePredicate& enqueue_pred = {},
32102
const PreVisitCallback& pre_visit = {},
33103
const PostVisitCallback& post_visit = {}
@@ -57,7 +127,7 @@ bool bfs(
57127
return false;
58128

59129
for (const auto he_id : policy::target_hyperedges(hypergraph, curr_node.vertex_id)) {
60-
if constexpr (not traits::c_empty_callback<TraverseHyperedgePredicate>) {
130+
if constexpr (not traits::c_empty_callback<TraverseHePredicate>) {
61131
const auto traverse = traverse_he_pred(he_id, curr_node.vertex_id);
62132
if (traverse == decision::abort)
63133
return false;

include/hgl/algorithm/traversal/breadth_first_search.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ result_type<Result, search_tree<H>> breadth_first_search(
3131
if (root_vertex_id != no_root) {
3232
bfs(
3333
hypergraph,
34-
init_range<H>(root_vertex_id),
34+
init_node_range<H>(root_vertex_id),
3535
default_visit_predicate<H>(visited_vertices),
3636
default_visit_callback<H, Result>(visited_vertices, stree),
3737
default_traverse_hyperedge_predicate(visited_hyperedges),
@@ -44,7 +44,7 @@ result_type<Result, search_tree<H>> breadth_first_search(
4444
for (const auto root_id : hypergraph.vertex_ids())
4545
bfs(
4646
hypergraph,
47-
init_range<H>(root_id),
47+
init_node_range<H>(root_id),
4848
default_visit_predicate<H>(visited_vertices),
4949
default_visit_callback<H, Result>(visited_vertices, stree),
5050
default_traverse_hyperedge_predicate(visited_hyperedges),

0 commit comments

Comments
 (0)