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