LAL: Linear Arrangement Library 24.10.00
A library focused on algorithms on linear arrangements of graphs.
Loading...
Searching...
No Matches
traversal.hpp
1/*********************************************************************
2 *
3 * Linear Arrangement Library - A library that implements a collection
4 * algorithms for linear arrangments of graphs.
5 *
6 * Copyright (C) 2019 - 2024
7 *
8 * This file is part of Linear Arrangement Library. The full code is available
9 * at:
10 * https://github.com/LAL-project/linear-arrangement-library.git
11 *
12 * Linear Arrangement Library is free software: you can redistribute it
13 * and/or modify it under the terms of the GNU Affero General Public License
14 * as published by the Free Software Foundation, either version 3 of the
15 * License, or (at your option) any later version.
16 *
17 * Linear Arrangement Library is distributed in the hope that it will be
18 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Affero General Public License for more details.
21 *
22 * You should have received a copy of the GNU Affero General Public License
23 * along with Linear Arrangement Library. If not, see <http://www.gnu.org/licenses/>.
24 *
25 * Contact:
26 *
27 * LluĂ­s Alemany Puig (lluis.alemany.puig@upc.edu)
28 * LQMC (Quantitative, Mathematical, and Computational Linguisitcs)
29 * CQL (Complexity and Quantitative Linguistics Lab)
30 * Jordi Girona St 1-3, Campus Nord UPC, 08034 Barcelona. CATALONIA, SPAIN
31 * Webpage: https://cqllab.upc.edu/people/lalemany/
32 *
33 * Ramon Ferrer i Cancho (rferrericancho@cs.upc.edu)
34 * LQMC (Quantitative, Mathematical, and Computational Linguisitcs)
35 * CQL (Complexity and Quantitative Linguistics Lab)
36 * Office 220, Omega building
37 * Jordi Girona St 1-3, Campus Nord UPC, 08034 Barcelona. CATALONIA, SPAIN
38 * Webpage: https://cqllab.upc.edu/people/rferrericancho/
39 *
40 ********************************************************************/
41
42#pragma once
43
44// C++ includes
45#include <functional>
46
47// lal includes
48#include <lal/basic_types.hpp>
49#include <lal/graphs/directed_graph.hpp>
50#include <lal/graphs/undirected_graph.hpp>
51#include <lal/detail/array.hpp>
52#include <lal/detail/queue_array.hpp>
53
54namespace lal {
55namespace detail {
56
85template <
86 class graph_t,
87 std::enable_if_t< std::is_base_of_v<graphs::graph, graph_t>, bool > = true
88>
89class BFS {
90public:
92 typedef std::function<void (const BFS<graph_t>&, const node)> BFS_process_one;
94 typedef std::function<void (const BFS<graph_t>&, const node, const node, const bool)> BFS_process_two;
96 typedef std::function<bool (const BFS<graph_t>&, const node)> BFS_bool_one;
98 typedef std::function<bool (const BFS<graph_t>&, const node, const node, const bool)> BFS_bool_two;
99
100public:
101
107 static constexpr bool is_graph_directed =
108 std::is_base_of_v<graphs::directed_graph, graph_t>;
109 // ! Note that this member attribute is public, and so it should not have
110 // a leading 'm_' like the other private/protected members.
111
112public:
114 BFS(const graph_t& g) noexcept :
115 m_G(g),
116 m_vis(m_G.get_num_nodes())
117 {
118 reset();
119 }
121 ~BFS() noexcept = default;
122
135 void reset() noexcept {
137 m_queue.init(m_G.get_num_nodes());
138
139 set_use_rev_edges(false);
141
146 }
147
152 void start_at(const node source) noexcept {
153 m_queue.push(source);
154 m_vis[source] = 1;
155 do_traversal();
156 }
157
162 void start_at(const std::vector<node>& sources) noexcept {
163 for (const node& u : sources) {
164 m_queue.push(u);
165 m_vis[u] = 1;
166 }
167 do_traversal();
168 }
169
170 /* SETTERS */
171
173 void set_use_rev_edges(const bool use) noexcept { m_use_rev_edges = use; }
174
176 void set_terminate_default() noexcept {
177 m_terminate = [](const BFS<graph_t>&, const node) -> bool { return false; };
178 m_is_terminate_set = false;
179 }
181 void set_terminate(const BFS_bool_one& f) noexcept {
182 m_terminate = f;
183 m_is_terminate_set = true;
184 }
185
188 m_process_current = [](const BFS<graph_t>&, const node) -> void { };
190 }
192 void set_process_current(const BFS_process_one& f) noexcept {
195 }
196
199 m_process_neighbour = [](const BFS<graph_t>&, const node, const node, const bool) -> void { };
201 }
203 void set_process_neighbour(const BFS_process_two& f) noexcept {
206 }
207
209 void set_node_add_default() noexcept {
210 m_add_node = [](const BFS<graph_t>&, const node, const node, const bool) -> bool { return true; };
211 m_is_add_node_set = false;
212 }
214 void set_node_add(const BFS_bool_two& f) noexcept {
215 m_add_node = f;
216 m_is_add_node_set = true;
217 }
218
224 void set_process_visited_neighbors(const bool v) noexcept {
226 }
227
233 void clear_visited() noexcept { m_vis.fill(0); }
234
240 void clear_queue() noexcept {
241 m_queue.reset();
242 }
243
249 void set_visited(const node u, const char vis) noexcept {
250#if defined DEBUG
251 assert(vis == 0 or vis == 1);
252#endif
253 m_vis[u] = vis;
254 }
255
256 /* GETTERS */
257
259 [[nodiscard]] bool node_was_visited(const node u) const noexcept {
260 return m_vis[u] == 1;
261 }
262
264 [[nodiscard]] bool all_visited() const noexcept {
265 return std::all_of(m_vis.begin(), m_vis.end(), [](auto x){return x == 1;});
266 }
267
269 [[nodiscard]] const graph_t& get_graph() const noexcept { return m_G; }
270
272 [[nodiscard]] const array<char>& get_visited() const noexcept { return m_vis; }
273
274protected:
292 void deal_with_neighbour(const node s, const node t, const bool ltr) noexcept
293 {
294 // Process the neighbour 't' of 's'.
295 const bool t_vis = node_was_visited(t);
296
297 if ((not t_vis) or (t_vis and m_process_visited_neighbors)) {
299 m_process_neighbour(*this, s, t, ltr);
300 }
301 }
302
303 if (not t_vis) {
304 const bool add_node =
305 m_is_add_node_set ? m_add_node(*this, s, t, ltr) : true;
306
307 if (add_node) {
308 m_queue.push(t);
309 // set node as visited
310 m_vis[t] = 1;
311 }
312 }
313 }
314
316 void process_neighbors(const node s) noexcept {
317 if constexpr (not is_graph_directed) {
318 // for undirected graphs
319
320 for (const node& t : m_G.get_neighbors(s)) {
321 // Edges are processed in the direction "s -> t".
322 // This is also the 'natural' orientation of the edge,
323 // so this explains the 'true'.
324 deal_with_neighbour(s, t, true);
325 }
326 }
327 else {
328 // for directed graphs
329
330 for (const node& t : m_G.get_out_neighbors(s)) {
331 // Edges are processed in the direction "s -> t".
332 // This is also the 'natural' orientation of the edge,
333 // hence the 'true'.
334 deal_with_neighbour(s, t, true);
335 }
336 // process in-neighbors whenever appropriate
337 if (m_use_rev_edges) {
338 for (const node& t : m_G.get_in_neighbors(s)) {
339 // Edges are processed in the direction "s -> t".
340 // However, the 'natural' orientation of the edge
341 // is "t -> s", hence the 'false'.
342 deal_with_neighbour(s, t, false);
343 }
344 }
345 }
346 }
347
396 void do_traversal() noexcept {
397 while (m_queue.size() > 0) {
398 const node s = m_queue.pop();
399
400 // process current node
402 m_process_current(*this, s);
403 }
404
405 // check user-defined early termination condition
406 if (m_is_terminate_set) {
407 if (m_terminate(*this, s)) { break; }
408 }
409
411 }
412 }
413
414protected:
416 const graph_t& m_G;
417
420
433 bool m_use_rev_edges = false;
434
435protected:
446
457
471
482};
483
484} // -- namespace detail
485} // -- namespace lal
Abstract graph Breadth-First Search traversal.
Definition traversal.hpp:89
std::function< void(const BFS< graph_t > &, const node, const node, const bool)> BFS_process_two
Two nodes processing function.
Definition traversal.hpp:94
void process_neighbors(const node s) noexcept
Process the neighbors of node s.
Definition traversal.hpp:316
void do_traversal() noexcept
Traversal through the graph's vertices.
Definition traversal.hpp:396
bool m_process_visited_neighbors
Should the traversal process previously-visitied neighbors?
Definition traversal.hpp:424
void start_at(const node source) noexcept
Start traversal at a given node.
Definition traversal.hpp:152
BFS_bool_one m_terminate
Early terminating function.
Definition traversal.hpp:443
static constexpr bool is_graph_directed
Is the graph used to initiliaze the object directed?
Definition traversal.hpp:107
bool m_is_add_node_set
Is function m_add_node set?
Definition traversal.hpp:481
void clear_queue() noexcept
Clear the memory allocated for this structure.
Definition traversal.hpp:240
std::function< bool(const BFS< graph_t > &, const node)> BFS_bool_one
One node decision function.
Definition traversal.hpp:96
void reset() noexcept
Set the graph traversal to its default state.
Definition traversal.hpp:135
void set_visited(const node u, const char vis) noexcept
Set node u as visited or not.
Definition traversal.hpp:249
std::function< bool(const BFS< graph_t > &, const node, const node, const bool)> BFS_bool_two
Two nodes decision function.
Definition traversal.hpp:98
void set_process_current(const BFS_process_one &f) noexcept
Set the function that controls the processing of the current node.
Definition traversal.hpp:192
const graph_t & m_G
Constant reference to the graph.
Definition traversal.hpp:416
void set_terminate(const BFS_bool_one &f) noexcept
Set the function that controls the termination of the loop.
Definition traversal.hpp:181
BFS(const graph_t &g) noexcept
Constructor.
Definition traversal.hpp:114
bool m_is_process_current_set
Is function m_process_current set?
Definition traversal.hpp:456
bool all_visited() const noexcept
Have all nodes been visited?
Definition traversal.hpp:264
void deal_with_neighbour(const node s, const node t, const bool ltr) noexcept
Deal with a neighbour of an input node.
Definition traversal.hpp:292
BFS_process_one m_process_current
Node processing function.
Definition traversal.hpp:454
void set_node_add_default() noexcept
Set the default value of m_add_node.
Definition traversal.hpp:209
void set_terminate_default() noexcept
Set the default value of m_terminate.
Definition traversal.hpp:176
void set_process_visited_neighbors(const bool v) noexcept
Should the algorithm call the neighbour processing function for already visited neighbors?
Definition traversal.hpp:224
void set_node_add(const BFS_bool_two &f) noexcept
Set the function that controls when a node is to be added to the queue.
Definition traversal.hpp:214
bool m_use_rev_edges
In directed graphs, traverse edges in the reverse direction.
Definition traversal.hpp:433
std::function< void(const BFS< graph_t > &, const node)> BFS_process_one
Single node processing function.
Definition traversal.hpp:92
bool node_was_visited(const node u) const noexcept
Returns whether or not node u has been visited.
Definition traversal.hpp:259
void set_process_neighbour(const BFS_process_two &f) noexcept
Set the function that controls the processing of the current neighbour.
Definition traversal.hpp:203
void clear_visited() noexcept
Sets all nodes to not visited.
Definition traversal.hpp:233
const graph_t & get_graph() const noexcept
Returns a constant reference to the graph.
Definition traversal.hpp:269
~BFS() noexcept=default
Destructor.
BFS_process_two m_process_neighbour
Node processing function.
Definition traversal.hpp:468
bool m_is_terminate_set
Is function m_terminate set?
Definition traversal.hpp:445
void set_use_rev_edges(const bool use) noexcept
Set whether the traversal can use reversed edges.
Definition traversal.hpp:173
bool m_is_process_neighbour_set
Is function m_process_neighbour set?
Definition traversal.hpp:470
void start_at(const std::vector< node > &sources) noexcept
Start the traversal at every given node.
Definition traversal.hpp:162
BFS_bool_two m_add_node
Node addition function.
Definition traversal.hpp:479
queue_array< node > m_queue
The structure of the traversal.
Definition traversal.hpp:419
void set_process_current_default() noexcept
Set the default value of m_process_current.
Definition traversal.hpp:187
const array< char > & get_visited() const noexcept
Return visited nodes information.
Definition traversal.hpp:272
void set_process_neighbour_default() noexcept
Set the default value of m_process_neighbour.
Definition traversal.hpp:198
array< char > m_vis
The set of visited nodes.
Definition traversal.hpp:422
Simple array-like fixed-size queue.
Definition queue_array.hpp:69
void init(const std::size_t n) noexcept
Initializes the queue to hold n elements.
Definition queue_array.hpp:72
void reset() noexcept
Makes the queue usable again.
Definition queue_array.hpp:131
std::size_t size() const noexcept
Returns the size of the queue.
Definition queue_array.hpp:121
value_t && pop() noexcept
Pops the first element of the queue.
Definition queue_array.hpp:98
void push(const value_t &v) noexcept
Insert a new element to the queue.
Definition queue_array.hpp:79
Main namespace of the library.
Definition basic_types.hpp:48
uint64_t node
Node type. See Node / Vertex page for further details.
Definition basic_types.hpp:51
Wrapper of a C array for automatic deallocation of memory.
Definition array.hpp:59
void fill(const T &v) noexcept
Assign the same value to every element in the data.
Definition array.hpp:272
T * begin() noexcept
Non-constant raw pointer to first element.
Definition array.hpp:300
T * end() noexcept
Non-constant raw pointer to last+1 element.
Definition array.hpp:302