LAL: Linear Arrangement Library 24.10.00
A library focused on algorithms on linear arrangements of graphs.
Loading...
Searching...
No Matches
cycles.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// lal includes
45#include <lal/graphs/directed_graph.hpp>
46#include <lal/detail/graphs/traversal.hpp>
47#include <lal/detail/array.hpp>
48
49namespace lal {
50namespace detail {
51
59[[nodiscard]] inline bool find_cycle
60(
62 const node u,
63 char * const __restrict__ visited,
64 char * const __restrict__ in_stack
65)
66noexcept
67{
68 if (visited[u]) { return false; }
69 visited[u] = 1;
70
71 in_stack[u] = 1;
72 for (const node v : g.get_out_neighbors(u)) {
73 if (in_stack[v]) {
74 return true;
75 }
76 if (visited[v] == 0 and find_cycle(g,v,visited,in_stack)) {
77 return true;
78 }
79 }
80
81 in_stack[u] = 0;
82 return false;
83}
84
92[[nodiscard]] inline bool has_directed_cycles(
94 char * const __restrict__ vis,
95 char * const __restrict__ in_stack
96)
97noexcept
98{
99 const uint64_t n = g.get_num_nodes();
100 std::fill(&vis[0], &vis[n], 0);
101 std::fill(&in_stack[0], &in_stack[n], 0);
102 bool has_cycle = false;
103 for (node u = 0; u < n and not has_cycle; ++u) {
104 if (vis[u] == 0) {
105 has_cycle = find_cycle(g, u, vis, in_stack);
106 }
107 }
108 return has_cycle;
109}
110
116[[nodiscard]] inline bool has_directed_cycles
117(const graphs::directed_graph& g)
118noexcept
119{
120 const uint64_t n = g.get_num_nodes();
121 array<char> all_mem(2*n);
122 char * const __restrict__ vis = all_mem.begin();
123 char * const __restrict__ in_stack = all_mem.at(n);
124 return has_directed_cycles(g, vis, in_stack);
125}
126
136template <class graph_t>
137[[nodiscard]] bool has_undirected_cycles
138(const graph_t& g, BFS<graph_t>& bfs)
139noexcept
140{
141 const auto n = g.get_num_nodes();
142
143 // parent[s] = t <->
144 // (in the traversal) s was reached from t (NOTE THE DIFFERENT ORDER).
145 // Note that read operations "if (parent[s] != t)" always come after
146 // the first write "parent[t] = s".
147 array<node> parent(n, n+1);
148 // a cycle was found
149 bool cycle_found = false;
150
151 // we need to traverse "reversed edges" in directed graphs
152 bfs.set_use_rev_edges( BFS<graph_t>::is_graph_directed );
153 // we need this to detect cycles
154 bfs.set_process_visited_neighbors(true);
155 // -- functions for the traversal
156 bfs.set_terminate(
157 [&](const BFS<graph_t>&, const node) -> bool { return cycle_found; }
158 );
159 bfs.set_process_neighbour(
160 [&](const auto& _bfs, node s, node t, bool) -> void {
161 // Since we want to do the traversal on the directed graphs likewise on
162 // the undirected graphs, the direction is ignored. We do not want to
163 // treat the nodes 's' and 't' as in the edge "t->s" but as in the
164 // edge "s->t" so as to mimic an "undirected traversal" on directed
165 // graphs.
166
167 if (_bfs.node_was_visited(t)) {
168 // if t was visted before then
169 // "s -> t" and later "t -> s"
170 // or
171 // "s -> ..." and later "... -> s"
172 // where '...' does not contain 't'
173 if (parent[s] != t) {
174 // node 't' was reached from some node
175 // other than 's' in previous iterations
176 cycle_found = true;
177 }
178 }
179 parent[t] = s;
180 }
181 );
182
183 // find cycles
184 for (node u = 0; u < n and not cycle_found; ++u) {
185 if (not bfs.node_was_visited(u)) {
186 bfs.clear_queue();
187 bfs.start_at(u);
188 }
189 }
190 return cycle_found;
191}
192
201template <class graph_t>
202[[nodiscard]] bool has_undirected_cycles
203(const graph_t& g)
204noexcept
205{
206 // BFS traversal object
207 BFS<graph_t> bfs(g);
208 return has_undirected_cycles(g, bfs);
209}
210
211} // -- namespace detail
212} // -- namespace lal
Abstract graph Breadth-First Search traversal.
Definition traversal.hpp:89
Directed graph class.
Definition directed_graph.hpp:67
bool has_directed_cycles(const graphs::directed_graph &g, char *const __restrict__ vis, char *const __restrict__ in_stack) noexcept
Returns true if, and only if, the graph has DIRECTED cycles.
Definition cycles.hpp:92
bool has_undirected_cycles(const graph_t &g, BFS< graph_t > &bfs) noexcept
Returns true if, and only if, the graph has UNDIRECTED cycles.
Definition cycles.hpp:138
bool find_cycle(const graphs::directed_graph &g, const node u, char *const __restrict__ visited, char *const __restrict__ in_stack) noexcept
Returns true if, and only if, the graph has cycles.
Definition cycles.hpp:60
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
T * begin() noexcept
Non-constant raw pointer to first element.
Definition array.hpp:300
T * at(const std::size_t i) noexcept
Pointer at a specific location of the array.
Definition array.hpp:281