LAL: Linear Arrangement Library 24.10.00
A library focused on algorithms on linear arrangements of graphs.
Loading...
Searching...
No Matches
retrieve_subtrees.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#if defined DEBUG
46#include <cassert>
47#endif
48#include <utility>
49
50// lal includes
51#include <lal/graphs/rooted_tree.hpp>
52#include <lal/detail/graphs/traversal.hpp>
53#include <lal/detail/array.hpp>
54
55namespace lal {
56namespace detail {
57
72template <bool get_subsizes>
73[[nodiscard]] std::pair<std::vector<edge>, uint64_t *> get_edges_subtree
74(const graphs::rooted_tree& T, const node u, const bool relabel)
75noexcept
76{
77#if defined DEBUG
78 assert(T.is_rooted_tree());
79 assert(T.has_node(u));
80 if constexpr (get_subsizes) {
81 assert(relabel);
82 }
83#endif
84
85 std::vector<edge> es;
86 uint64_t *sizes = nullptr;
87
88 const uint64_t n = T.get_num_nodes();
89 if (n <= 1) { return {std::move(es), sizes}; }
90
91 // reserve some space for the vector edges
92 // initialize the array of sizes if needed
93 bool update_sizes = false;
94 if (T.are_size_subtrees_valid()) {
95 es.reserve(T.get_num_nodes_subtree(u));
96 if constexpr (get_subsizes) {
97 // The caller wants this function to retrieve the sizes of
98 // the subtrees. This can be done because the sizes are valid.
99
100 // Use only the space that is strictly necessary.
101 sizes = new uint64_t[T.get_num_nodes_subtree(u)]{0};
102 update_sizes = true;
103 }
104 }
105 else {
106 es.reserve(n/2);
107 sizes = nullptr; // reiterate that we shouldn't do this here
108 }
109
110 // data structures for node relabelling
111 array<node> relabelling(n, n + 1);
112
113 // relabel 'u' to '0' and make it the root
114 relabelling[u] = 0;
115 node next_label = 1;
116 if (update_sizes) {
117 sizes[relabelling[u]] = T.get_num_nodes_subtree(u);
118 }
119
121 bfs.set_use_rev_edges(false);
122 // retrieve edges and relabel them at the same time
123 if (relabel) {
124 bfs.set_process_neighbour(
125 [&](const auto&, node s, node t, bool left_to_right) -> void {
126 // change the orientation of the edge whenever appropriate
127 // left_to_right: true ---> "s->t"
128 // left_to_right: false ---> "t->s"
129 if (not left_to_right) { std::swap(s,t); }
130
131 edge e;
132 // relabel first node
133 if (relabelling[s] >= n) {
134 relabelling[s] = next_label;
135 ++next_label;
136 if (update_sizes) {
137 sizes[relabelling[s]] = T.get_num_nodes_subtree(s);
138 }
139 }
140 e.first = relabelling[s];
141
142 // relabel second node
143 if (relabelling[t] >= n) {
144 relabelling[t] = next_label;
145 ++next_label;
146 if (update_sizes) {
147 sizes[relabelling[t]] = T.get_num_nodes_subtree(t);
148 }
149 }
150 e.second = relabelling[t];
151
152 es.emplace_back(e);
153 }
154 );
155 }
156 else {
157 bfs.set_process_neighbour(
158 [&](const auto&, node s, node t, bool left_to_right) -> void {
159 // change the orientation of the edge whenever appropriate
160 // dir: true ---> "s->t"
161 // dir: false ---> "t->s"
162 if (not left_to_right) { std::swap(s,t); }
163 if (update_sizes) {
164 sizes[s] = T.get_num_nodes_subtree(s);
165 sizes[t] = T.get_num_nodes_subtree(t);
166 }
167 es.emplace_back(s,t);
168 }
169 );
170 }
171 bfs.start_at(u);
172
173 return {std::move(es), sizes};
174}
175
176} // -- namespace detail
177} // -- namespace lal
Abstract graph Breadth-First Search traversal.
Definition traversal.hpp:89
Rooted tree graph class.
Definition rooted_tree.hpp:109
std::pair< std::vector< edge >, uint64_t * > get_edges_subtree(const graphs::rooted_tree &T, const node u, const bool relabel) noexcept
Retrieves the edges of a subtree.
Definition retrieve_subtrees.hpp:74
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
Wrapper of a C array for automatic deallocation of memory.
Definition array.hpp:59
T & first() noexcept
Non-constant reference to the first element in the array.
Definition array.hpp:243