LAL: Linear Arrangement Library 23.01.00
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 - 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 <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
92template <
93 typename graph_t,
94 bool is_directed = std::is_base_of_v<graphs::directed_graph, graph_t>,
95 std::enable_if_t<std::is_base_of_v<graphs::graph, graph_t>, bool> = true
96>
98public:
99 /* CONSTRUCTORS */
100
105 E_iterator(const graph_t& g) noexcept
106 : m_G(g),
107 m_num_nodes(m_G.get_num_nodes())
108 {
109 reset();
110 }
112 ~E_iterator() = default;
113
114 /* GETTERS */
115
117 bool end() const noexcept { return m_reached_end; }
118
120 const edge& get_edge() const noexcept { return m_cur_edge; }
121
123 edge_t get_edge_t() const noexcept { return m_cur_edge; }
124
126 edge yield_edge() noexcept {
127 const auto e = get_edge();
128 next();
129 return e;
130 }
131
133 edge_t yield_edge_t() noexcept {
134 const auto e = get_edge_t();
135 next();
136 return e;
137 }
138
139 /* MODIFIERS */
140
142 void next() noexcept {
143 if (not m_exists_next) {
144 m_reached_end = true;
145 return;
146 }
147
149
150 // find the next edge
151 std::tie(m_exists_next, m_cur) = find_next_edge();
152 }
153
155 void reset() noexcept {
156 __reset();
157 next();
158 }
159
160private:
161 typedef std::pair<node,std::size_t> E_pointer;
162
163private:
165 const graph_t& m_G;
167 const uint64_t m_num_nodes;
168
170 E_pointer m_cur;
172 bool m_exists_next = true;
174 bool m_reached_end = false;
177
178private:
180 void __reset() noexcept {
181 m_exists_next = true;
182 m_reached_end = false;
183
184 m_cur.first = 0;
185 m_cur.second = static_cast<std::size_t>(-1);
186
187 auto [found, new_pointer] = find_next_edge();
188 if (not found) {
189 // if we can't find the next edge, then there is no next...
190 m_exists_next = false;
191 m_reached_end = true;
192 return;
193 }
194
195 // since an edge was found, store it in current
196 m_cur = new_pointer;
198
199 // how do we know there is a next edge?
200 // well, find it!
201 auto [f2, _] = find_next_edge();
202 m_exists_next = f2;
203
204#if defined DEBUG
205 if (m_G.get_num_edges() == 1) {
206 assert(m_exists_next == false);
207 assert(m_reached_end == false);
208 }
209#endif
210
211 // this is the case of the graph having only one edge
212 if (not m_exists_next) {
213 m_exists_next = true;
214 }
215 }
216
218 edge make_current_edge() const noexcept {
219 node s, t;
220 if constexpr (is_directed) {
221 s = m_cur.first;
222 t = m_G.get_out_neighbours(s)[m_cur.second];
223 }
224 else {
225 s = m_cur.first;
226 t = m_G.get_neighbours(s)[m_cur.second];
227 }
228 return {s,t};
229 }
230
237 template <bool isdir = is_directed, std::enable_if_t<isdir, bool> = true>
238 std::pair<bool, E_pointer> find_next_edge() const noexcept {
239 node s = m_cur.first;
240 std::size_t pt = m_cur.second;
241 bool found = false;
242
243 ++pt;
244 if (s < m_num_nodes and pt < m_G.get_out_degree(s)) {
245 found = true;
246 }
247 else {
248 pt = 0;
249 ++s;
250 while (s < m_num_nodes and m_G.get_out_degree(s) == 0) { ++s; }
251 found = s < m_num_nodes;
252 }
253 return {found, E_pointer(s, pt)};
254 }
261 template <bool isdir = is_directed, std::enable_if_t<not isdir, bool> = true>
262 std::pair<bool, E_pointer> find_next_edge() const noexcept {
263 node s = m_cur.first;
264 std::size_t pt = m_cur.second + 1;
265 bool found = false;
266
267 while (s < m_num_nodes and not found) {
268 const auto& Ns = m_G.get_neighbours(s);
269 while (pt < Ns.size() and s > Ns[pt]) { ++pt; }
270
271 found = pt < Ns.size();
272 if (not found) {
273 ++s;
274 pt = 0;
275 }
276 }
277 return {found, E_pointer(s, pt)};
278 }
279};
280
281} // -- namespace iterators
282} // -- namespace lal
Iterator over the set of edges of a graph.
Definition: E_iterator.hpp:97
bool m_reached_end
Has the end of the iteration been reached?
Definition: E_iterator.hpp:174
void __reset() noexcept
Sets the iterator at the beginning of the set of edges.
Definition: E_iterator.hpp:180
void reset() noexcept
Sets the iterator at the beginning of the set of edges.
Definition: E_iterator.hpp:155
~E_iterator()=default
Default destructor.
edge make_current_edge() const noexcept
Returns the edge pointed by m_cur.
Definition: E_iterator.hpp:218
const uint64_t m_num_nodes
Number of nodes of the graph.
Definition: E_iterator.hpp:167
edge_t yield_edge_t() noexcept
Returns the current edge and advances the iterator.
Definition: E_iterator.hpp:133
const graph_t & m_G
The graph whose edges have to be iterated on.
Definition: E_iterator.hpp:165
void next() noexcept
Moves the iterator to the next edge.
Definition: E_iterator.hpp:142
E_iterator(const graph_t &g) noexcept
Constructor.
Definition: E_iterator.hpp:105
bool end() const noexcept
Returns true if the end of the iteration was reached.
Definition: E_iterator.hpp:117
E_pointer m_cur
Pointer to the next edge.
Definition: E_iterator.hpp:170
bool m_exists_next
Is there a next edge to iterate over?
Definition: E_iterator.hpp:172
const edge & get_edge() const noexcept
Returns the current edge.
Definition: E_iterator.hpp:120
std::pair< bool, E_pointer > find_next_edge() const noexcept
Finds the next edge on a directed graph.
Definition: E_iterator.hpp:238
edge_t get_edge_t() const noexcept
Returns the current edge.
Definition: E_iterator.hpp:123
edge m_cur_edge
Copy of the current edge.
Definition: E_iterator.hpp:176
edge yield_edge() noexcept
Returns the current edge and advances the iterator.
Definition: E_iterator.hpp:126
Main namespace of the library.
Definition: basic_types.hpp:50
std::pair< node, node > edge
See Edge page for further details.
Definition: basic_types.hpp:58
uint64_t node
Node type. See Node / Vertex page for further details.
Definition: basic_types.hpp:53
std::pair< node_t, node_t > edge_t
Similar to edge.
Definition: basic_types.hpp:163