LAL: Linear Arrangement Library 21.07.01
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 - 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#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/internal/graphs/traversal.hpp>
53#include <lal/internal/data_array.hpp>
54
55namespace lal {
56namespace internal {
57
58/*
59 * @brief Retrieves the edges of a subtree
60 *
61 * @param T Input tree.
62 * @param u Root of the subtree.
63 * @param relabel Relabel the vertices? If so, vertex 'u' is relabelled to 0
64 * @param subsizes Store in an array the sizes of the subtrees of the subtree
65 * rooted at 'u'.
66 *
67 * @pre The tree is a valid rooted tree
68 * @pre The tree has vertex 'u'
69 * @post The function has NO ownership of the raw pointer returned in the pair.
70 * @post The pointer returned is not nullptr only when T.size_subtrees_valid()
71 * AND the boolean parameter sizes are BOTH true.
72 */
73template<bool get_subsizes>
74std::pair<std::vector<edge>, uint32_t *>
75get_edges_subtree
76(const graphs::rooted_tree& T, node u, bool relabel)
77{
78#if defined DEBUG
79 assert(T.is_rooted_tree());
80 assert(T.has_node(u));
81 if constexpr (get_subsizes) {
82 assert(relabel);
83 }
84#endif
85
86 std::vector<edge> es;
87 uint32_t *sizes = nullptr;
88
89 const uint32_t n = T.get_num_nodes();
90 if (n <= 1) { return {es, sizes}; }
91
92 // reserve some space for the vector edges
93 // initialise the array of sizes if needed
94 bool update_sizes = false;
95 if (T.are_size_subtrees_valid()) {
96 es.reserve(T.get_num_nodes_subtree(u));
97 if constexpr (get_subsizes) {
98 // The caller wants this function to retrieve the sizes of
99 // the subtrees. This can be done because the sizes are valid.
100
101 // Use only the space that is strictly necessary.
102 sizes = new uint32_t[T.get_num_nodes_subtree(u)]{0};
103 update_sizes = true;
104 }
105 }
106 else {
107 es.reserve(n/2);
108 sizes = nullptr; // reiterate that we shouldn't do this here
109 }
110
111 // data structures for node relabelling
112 data_array<node> relabelling(n, n + 1);
113
114 // relabel 'u' to '0' and make it the root
115 relabelling[u] = 0;
116 node next_label = 1;
117 if (update_sizes) {
118 sizes[relabelling[u]] = T.get_num_nodes_subtree(u);
119 }
120
121 BFS<graphs::rooted_tree> bfs(T);
122 bfs.set_use_rev_edges(false);
123 // retrieve edges and relabel them at the same time
124 if (relabel) {
125 bfs.set_process_neighbour(
126 [&](const auto&, node s, node t, bool left_to_right) -> void {
127 // change the orientation of the edge whenever appropriate
128 // left_to_right: true ---> "s->t"
129 // left_to_right: false ---> "t->s"
130 if (not left_to_right) { std::swap(s,t); }
131
132 edge e;
133 // relabel first node
134 if (relabelling[s] >= n) {
135 relabelling[s] = next_label;
136 ++next_label;
137 if (update_sizes) {
138 sizes[relabelling[s]] = T.get_num_nodes_subtree(s);
139 }
140 }
141 e.first = relabelling[s];
142
143 // relabel second node
144 if (relabelling[t] >= n) {
145 relabelling[t] = next_label;
146 ++next_label;
147 if (update_sizes) {
148 sizes[relabelling[t]] = T.get_num_nodes_subtree(t);
149 }
150 }
151 e.second = relabelling[t];
152
153 es.push_back(e);
154 }
155 );
156 }
157 else {
158 bfs.set_process_neighbour(
159 [&](const auto&, node s, node t, bool left_to_right) -> void {
160 // change the orientation of the edge whenever appropriate
161 // dir: true ---> "s->t"
162 // dir: false ---> "t->s"
163 if (not left_to_right) { std::swap(s,t); }
164 if (update_sizes) {
165 sizes[s] = T.get_num_nodes_subtree(s);
166 sizes[t] = T.get_num_nodes_subtree(t);
167 }
168 es.push_back(edge(s,t));
169 }
170 );
171 }
172 bfs.start_at(u);
173
174 return {es, sizes};
175}
176
177} // -- namespace internal
178} // -- namespace lal
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