LAL: Linear Arrangement Library 21.07.01
A library focused on algorithms on linear arrangements of graphs.
Loading...
Searching...
No Matches
E_iterator.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 - 2021
7 *
8 * This file is part of Linear Arrangement Library. To see the full code
9 * visit the webpage:
10 * https://github.com/lluisalemanypuig/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 <utility>
46#include <tuple>
47
48// lal includes
49#include <lal/graphs/directed_graph.hpp>
50#include <lal/graphs/undirected_graph.hpp>
51
52namespace lal {
53namespace iterators {
54
84template<
85 typename GRAPH,
86 bool is_directed = std::is_base_of_v<graphs::directed_graph, GRAPH>,
87 std::enable_if_t<
88 std::is_base_of_v<graphs::directed_graph, GRAPH> ||
89 std::is_base_of_v<graphs::undirected_graph, GRAPH>
90 , bool
91 > = true
92>
94public:
95 /* CONSTRUCTORS */
96
101 E_iterator(const GRAPH& g) noexcept : m_G(g) {
102 reset();
103 }
105 ~E_iterator() = default;
106
107 /* GETTERS */
108
110 inline bool end() const noexcept { return m_reached_end; }
111
113 inline edge get_edge() const noexcept { return m_cur_edge; }
114
115 /* MODIFIERS */
116
118 inline void next() noexcept {
119 if (not m_exists_next) {
120 m_reached_end = true;
121 return;
122 }
123
125
126 // find the next edge
127 std::tie(m_exists_next, m_cur) = find_next_edge();
128 }
129
131 inline void reset() noexcept {
132 __reset();
133 next();
134 }
135
136private:
137 typedef std::pair<node,std::size_t> E_pointer;
138
139private:
141 const GRAPH& m_G;
143 E_pointer m_cur;
145 bool m_exists_next = true;
147 bool m_reached_end = false;
150
151private:
153 inline void __reset() noexcept {
154 m_exists_next = true;
155 m_reached_end = false;
156
157 m_cur.first = 0;
158 m_cur.second = static_cast<std::size_t>(-1);
159
160 auto [found, new_pointer] = find_next_edge();
161 if (not found) {
162 // if we can't find the next edge, then there is no next...
163 m_exists_next = false;
164 m_reached_end = true;
165 return;
166 }
167
168 // since an edge was found, store it in current
169 m_cur = new_pointer;
171
172 // how do we know there is a next edge?
173 // well, find it!
174 auto [f2, _] = find_next_edge();
175 m_exists_next = f2;
176
177#if defined DEBUG
178 if (m_G.get_num_edges() == 1) {
179 assert(m_exists_next == false);
180 assert(m_reached_end == false);
181 }
182#endif
183
184 // this is the case of the graph having only one edge
185 if (not m_exists_next) {
186 m_exists_next = true;
187 }
188 }
189
191 inline edge make_current_edge() const noexcept {
192 node s, t;
193 if constexpr (is_directed) {
194 s = m_cur.first;
195 t = m_G.get_out_neighbours(s)[m_cur.second];
196 }
197 else {
198 s = m_cur.first;
199 t = m_G.get_neighbours(s)[m_cur.second];
200 }
201 return edge(s,t);
202 }
203
210 template<bool isdir = is_directed, std::enable_if_t<isdir, bool> = true>
211 inline std::pair<bool, E_pointer> find_next_edge() const noexcept {
212 const uint32_t n = m_G.get_num_nodes();
213
214 node s = m_cur.first;
215 std::size_t pt = m_cur.second;
216 bool found = false;
217
218 ++pt;
219 if (s < n and pt < m_G.get_out_degree(s)) {
220 found = true;
221 }
222 else {
223 pt = 0;
224 ++s;
225 while (s < n and m_G.get_out_degree(s) == 0) { ++s; }
226 found = s < n;
227 }
228 return make_pair(found, E_pointer(s, pt));
229 }
236 template<bool isdir = is_directed, std::enable_if_t<not isdir, bool> = true>
237 inline std::pair<bool, E_pointer> find_next_edge() const noexcept {
238 const uint32_t n = m_G.get_num_nodes();
239
240 node s = m_cur.first;
241 std::size_t pt = m_cur.second + 1;
242 bool found = false;
243
244 while (s < n and not found) {
245 const auto& Ns = m_G.get_neighbours(s);
246 while (pt < Ns.size() and s > Ns[pt]) { ++pt; }
247
248 found = pt < Ns.size();
249 if (not found) {
250 ++s;
251 pt = 0;
252 }
253 }
254 return make_pair(found, E_pointer(s, pt));
255 }
256};
257
258} // -- namespace iterators
259} // -- namespace lal
Iterator over the set of edges of a graph.
Definition E_iterator.hpp:93
void __reset() noexcept
Sets the iterator at the beginning of the set of edges.
Definition E_iterator.hpp:153
E_pointer m_cur
Pointer to the next edge.
Definition E_iterator.hpp:143
void reset() noexcept
Sets the iterator at the beginning of the set of edges.
Definition E_iterator.hpp:131
void next() noexcept
Moves the iterator to the next edge.
Definition E_iterator.hpp:118
edge m_cur_edge
Copy of the current edge.
Definition E_iterator.hpp:149
std::pair< bool, E_pointer > find_next_edge() const noexcept
Finds the next edge on a directed graph.
Definition E_iterator.hpp:211
bool m_exists_next
Is there a next edge to iterate over?
Definition E_iterator.hpp:145
edge make_current_edge() const noexcept
Returns the edge pointed by m_cur.
Definition E_iterator.hpp:191
edge get_edge() const noexcept
Returns the current edge.
Definition E_iterator.hpp:113
const GRAPH & m_G
The graph whose edges have to be iterated on.
Definition E_iterator.hpp:141
E_iterator(const GRAPH &g) noexcept
Constructor.
Definition E_iterator.hpp:101
~E_iterator()=default
Default destructor.
bool end() const noexcept
Returns true if the end of the iteration was reached.
Definition E_iterator.hpp:110
bool m_reached_end
Has the end of the iteration been reached?
Definition E_iterator.hpp:147
Main namespace of the library.
Definition definitions.hpp:48
std::pair< node, node > edge
Edge type.
Definition definitions.hpp:75
uint32_t node
Node type.
Definition definitions.hpp:51