LAL: Linear Arrangement Library 23.01.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 - 2023
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 (lalemany@cs.upc.edu)
28 * LARCA (Laboratory for Relational Algorithmics, Complexity and Learning)
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 * LARCA (Laboratory for Relational Algorithmics, Complexity and Learning)
35 * CQL (Complexity and Quantitative Linguistics Lab)
36 * Office S124, 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/data_array.hpp>
52#include <lal/detail/linear_queue.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>&, node)> BFS_process_one;
94 typedef std::function<void (const BFS<graph_t>&, node, node, bool)> BFS_process_two;
96 typedef std::function<bool (const BFS<graph_t>&, node)> BFS_bool_one;
98 typedef std::function<bool (const BFS<graph_t>&, node, node)> 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(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(bool use) noexcept { m_use_rev_edges = use; }
174
176 void set_terminate_default() noexcept
177 { m_term = [](const BFS<graph_t>&, const node) -> bool { return false; }; }
179 void set_terminate(const BFS_bool_one& f) noexcept
180 { m_term = f; }
181
184 { m_proc_cur = [](const BFS<graph_t>&, const node) -> void { }; }
186 void set_process_current(const BFS_process_one& f) noexcept
187 { m_proc_cur = f; }
188
191 { m_proc_neigh = [](const BFS<graph_t>&, const node, const node, bool) -> void { }; }
194 { m_proc_neigh = f; }
195
197 void set_node_add_default() noexcept
198 { m_add_node = [](const BFS<graph_t>&, const node, const node) -> bool { return true; }; }
200 void set_node_add(const BFS_bool_two& f) noexcept
201 { m_add_node = f; }
202
208 void set_process_visited_neighbours(bool v) noexcept
209 { m_proc_vis_neighs = v; }
210
216 void clear_visited() noexcept { m_vis.fill(0); }
217
223 void clear_queue() noexcept {
224 m_queue.reset();
225 }
226
232 void set_visited(node u, char vis) noexcept {
233#if defined DEBUG
234 assert(vis == 0 or vis == 1);
235#endif
236 m_vis[u] = vis;
237 }
238
239 /* GETTERS */
240
242 bool node_was_visited(node u) const noexcept { return m_vis[u] == 1; }
243
245 bool all_visited() const noexcept {
246 return std::all_of(m_vis.begin(), m_vis.end(), [](auto x){return x == 1;});
247 }
248
250 const graph_t& get_graph() const noexcept { return m_G; }
251
253 const data_array<char>& get_visited() const noexcept { return m_vis; }
254
255protected:
273 void deal_with_neighbour(node s, node t, bool ltr) noexcept {
274 // Process the neighbour 't' of 's'.
275 const bool t_vis = node_was_visited(t);
276
277 if ((not t_vis) or (t_vis and m_proc_vis_neighs)) {
278 m_proc_neigh(*this, s, t, ltr);
279 }
280
281 if ((not t_vis) and m_add_node(*this, s, t)) {
282 m_queue.push(t);
283 // set node as visited
284 m_vis[t] = 1;
285 }
286 }
287
289 void process_neighbours(node s) noexcept {
290 if constexpr (not is_graph_directed) {
291 // for undirected graphs
292
293 for (const node& t : m_G.get_neighbours(s)) {
294 // Edges are processed in the direction "s -> t".
295 // This is also the 'natural' orientation of the edge,
296 // so this explains the 'true'.
297 deal_with_neighbour(s, t, true);
298 }
299 }
300 else {
301 // for directed graphs
302
303 for (const node& t : m_G.get_out_neighbours(s)) {
304 // Edges are processed in the direction "s -> t".
305 // This is also the 'natural' orientation of the edge,
306 // hence the 'true'.
307 deal_with_neighbour(s, t, true);
308 }
309 // process in-neighbours whenever appropriate
310 if (m_use_rev_edges) {
311 for (const node& t : m_G.get_in_neighbours(s)) {
312 // Edges are processed in the direction "s -> t".
313 // However, the 'natural' orientation of the edge
314 // is "t -> s", hence the 'false'.
315 deal_with_neighbour(s, t, false);
316 }
317 }
318 }
319 }
320
370 void do_traversal() noexcept {
371 while (m_queue.size() > 0) {
372 const node s = m_queue.pop();
373
374 // process current node
375 m_proc_cur(*this, s);
376
377 // check user-defined early termination condition
378 if (m_term(*this, s)) { break; }
379
381 }
382 }
383
384protected:
386 const graph_t& m_G;
387
390
394 bool m_proc_vis_neighs = false;
403 bool m_use_rev_edges = false;
404
405protected:
414
423
435
444};
445
446} // -- namespace detail
447} // -- namespace lal
Abstract graph Breadth-First Search traversal.
Definition: traversal.hpp:89
void do_traversal() noexcept
Traversal through the graph's vertices.
Definition: traversal.hpp:370
void set_visited(node u, char vis) noexcept
Set node u as visited or not.
Definition: traversal.hpp:232
void deal_with_neighbour(node s, node t, bool ltr) noexcept
Deal with a neighbour of an input node.
Definition: traversal.hpp:273
std::function< bool(const BFS< graph_t > &, node)> BFS_bool_one
One node decision function.
Definition: traversal.hpp:96
static constexpr bool is_graph_directed
Is the graph used to initiliaze the object directed?
Definition: traversal.hpp:107
void clear_queue() noexcept
Clear the memory allocated for this structure.
Definition: traversal.hpp:223
void process_neighbours(node s) noexcept
Process the neighbours of node s.
Definition: traversal.hpp:289
void reset() noexcept
Set the graph traversal to its default state.
Definition: traversal.hpp:135
BFS_bool_one m_term
graph_traversal early terminating function.
Definition: traversal.hpp:413
void set_process_current(const BFS_process_one &f) noexcept
Set the function that controls the processing of the current node.
Definition: traversal.hpp:186
const graph_t & m_G
Constant reference to the graph.
Definition: traversal.hpp:386
std::function< bool(const BFS< graph_t > &, node, node)> BFS_bool_two
Two nodes decision function.
Definition: traversal.hpp:98
std::function< void(const BFS< graph_t > &, node, node, bool)> BFS_process_two
Two nodes processing function.
Definition: traversal.hpp:94
std::function< void(const BFS< graph_t > &, node)> BFS_process_one
Single node processing function.
Definition: traversal.hpp:92
linear_queue< node > m_queue
The structure of the traversal.
Definition: traversal.hpp:389
void set_terminate(const BFS_bool_one &f) noexcept
Set the function that controls the termination of the loop.
Definition: traversal.hpp:179
BFS(const graph_t &g) noexcept
Constructor.
Definition: traversal.hpp:114
bool all_visited() const noexcept
Have all nodes been visited?
Definition: traversal.hpp:245
void set_node_add_default() noexcept
Set the default value of m_add_node.
Definition: traversal.hpp:197
void set_terminate_default() noexcept
Set the default value of m_term.
Definition: traversal.hpp:176
void start_at(node source) noexcept
Start traversal at a given node.
Definition: traversal.hpp:152
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:200
bool m_use_rev_edges
In directed graphs, traverse edges in the reverse direction.
Definition: traversal.hpp:403
bool node_was_visited(node u) const noexcept
Returns whether or not node u has been visited.
Definition: traversal.hpp:242
void set_process_neighbour(const BFS_process_two &f) noexcept
Set the function that controls the processing of the current neighbour.
Definition: traversal.hpp:193
data_array< char > m_vis
The set of visited nodes.
Definition: traversal.hpp:392
void clear_visited() noexcept
Sets all nodes to not visited.
Definition: traversal.hpp:216
const graph_t & get_graph() const noexcept
Returns a constant reference to the graph.
Definition: traversal.hpp:250
~BFS() noexcept=default
Destructor.
const data_array< char > & get_visited() const noexcept
Return visited nodes information.
Definition: traversal.hpp:253
void set_process_visited_neighbours(bool v) noexcept
Should the algorithm call the neighbour processing function for already visited neighbours?
Definition: traversal.hpp:208
void start_at(const std::vector< node > &sources) noexcept
Start the traversal at every given node.
Definition: traversal.hpp:162
bool m_proc_vis_neighs
Should the traversal process previously-visitied neighbours?
Definition: traversal.hpp:394
BFS_bool_two m_add_node
graph_traversal node addition function.
Definition: traversal.hpp:443
void set_process_current_default() noexcept
Set the default value of m_proc_cur.
Definition: traversal.hpp:183
void set_use_rev_edges(bool use) noexcept
Set whether the traversal can use reversed edges.
Definition: traversal.hpp:173
void set_process_neighbour_default() noexcept
Set the default value of m_proc_neigh.
Definition: traversal.hpp:190
BFS_process_two m_proc_neigh
graph_traversal neighbour node processing function.
Definition: traversal.hpp:434
BFS_process_one m_proc_cur
graph_traversal node processing function.
Definition: traversal.hpp:422
Simple array-like fixed-size queue.
Definition: linear_queue.hpp:69
T && pop() noexcept
Pops the first element of the queue.
Definition: linear_queue.hpp:98
void reset() noexcept
Makes the queue usable again.
Definition: linear_queue.hpp:131
std::size_t size() const noexcept
Returns the size of the queue.
Definition: linear_queue.hpp:121
void push(const T &v) noexcept
Insert a new element to the queue.
Definition: linear_queue.hpp:79
void init(std::size_t n) noexcept
Initializes the queue to hold n elements.
Definition: linear_queue.hpp:72
Main namespace of the library.
Definition: basic_types.hpp:50
uint64_t node
Node type. See Node / Vertex page for further details.
Definition: basic_types.hpp:53
Wrapper of a C array for autmatic deallocation of memory.
Definition: data_array.hpp:59
void fill(const T &v) noexcept
Assign the same value to every element in the data.
Definition: data_array.hpp:263
T * end() noexcept
Non-constant raw pointer to last+1 element.
Definition: data_array.hpp:293
T * begin() noexcept
Non-constant raw pointer to first element.
Definition: data_array.hpp:291