LAL: Linear Arrangement Library 24.10.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 - 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// 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 [[nodiscard]] bool end() const noexcept { return m_reached_end; }
118
120 [[nodiscard]] const edge& get_edge() const noexcept { return m_cur_edge; }
121
123 [[nodiscard]] edge_t get_edge_t() const noexcept { return m_cur_edge; }
124
126 [[nodiscard]] edge yield_edge() noexcept {
127 const auto e = get_edge();
128 next();
129 return e;
130 }
131
133 [[nodiscard]] 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:
162 typedef std::pair<node,std::size_t> E_pointer;
163
164private:
166 const graph_t& m_G;
168 const uint64_t m_num_nodes;
169
178
179private:
181 void __reset() noexcept {
182 m_exists_next = true;
183 m_reached_end = false;
184
185 m_cur.first = 0;
186 m_cur.second = static_cast<std::size_t>(-1);
187
188 auto [found, new_pointer] = find_next_edge();
189 if (not found) {
190 // if we can't find the next edge, then there is no next...
191 m_exists_next = false;
192 m_reached_end = true;
193 return;
194 }
195
196 // since an edge was found, store it in current
197 m_cur = new_pointer;
199
200 // how do we know there is a next edge?
201 // well, find it!
202 auto [f2, _] = find_next_edge();
203 m_exists_next = f2;
204
205#if defined DEBUG
206 if (m_G.get_num_edges() == 1) {
207 assert(not m_exists_next);
208 assert(not m_reached_end);
209 }
210#endif
211
212 // this is the case of the graph having only one edge
213 if (not m_exists_next) {
214 m_exists_next = true;
215 }
216 }
217
219 [[nodiscard]] edge make_current_edge() const noexcept {
220 node s, t;
221 if constexpr (is_directed) {
222 s = m_cur.first;
223 t = m_G.get_out_neighbors(s)[m_cur.second];
224 }
225 else {
226 s = m_cur.first;
227 t = m_G.get_neighbors(s)[m_cur.second];
228 }
229 return {s,t};
230 }
231
238 template <bool isdir = is_directed, std::enable_if_t<isdir, bool> = true>
239 [[nodiscard]] std::pair<bool, E_pointer> find_next_edge() const noexcept {
240 node s = m_cur.first;
241 std::size_t pt = m_cur.second;
242 bool found = false;
243
244 ++pt;
245 if (s < m_num_nodes and pt < m_G.get_out_degree(s)) {
246 found = true;
247 }
248 else {
249 pt = 0;
250 ++s;
251 while (s < m_num_nodes and m_G.get_out_degree(s) == 0) { ++s; }
252 found = s < m_num_nodes;
253 }
254 return {found, E_pointer(s, pt)};
255 }
262 template <bool isdir = is_directed, std::enable_if_t<not isdir, bool> = true>
263 [[nodiscard]] std::pair<bool, E_pointer> find_next_edge() const noexcept {
264 node s = m_cur.first;
265 std::size_t pt = m_cur.second + 1;
266 bool found = false;
267
268 while (s < m_num_nodes and not found) {
269 const auto& Ns = m_G.get_neighbors(s);
270 while (pt < Ns.size() and s > Ns[pt]) { ++pt; }
271
272 found = pt < Ns.size();
273 if (not found) {
274 ++s;
275 pt = 0;
276 }
277 }
278 return {found, E_pointer(s, pt)};
279 }
280};
281
282} // -- namespace iterators
283} // -- 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:175
void __reset() noexcept
Sets the iterator at the beginning of the set of edges.
Definition E_iterator.hpp:181
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:219
const uint64_t m_num_nodes
Number of nodes of the graph.
Definition E_iterator.hpp:168
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:166
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:171
bool m_exists_next
Is there a next edge to iterate over?
Definition E_iterator.hpp:173
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:239
std::pair< node, std::size_t > E_pointer
Useful typedef.
Definition E_iterator.hpp:162
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:177
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:48
std::pair< node, node > edge
See Edge page for further details.
Definition basic_types.hpp:56
uint64_t node
Node type. See Node / Vertex page for further details.
Definition basic_types.hpp:51
std::pair< node_t, node_t > edge_t
Similar to edge.
Definition basic_types.hpp:239