LAL: Linear Arrangement Library 21.07.01
A library focused on algorithms on linear arrangements of graphs.
Loading...
Searching...
No Matches
tree_centroid.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 <vector>
49
50// lal includes
51#include <lal/definitions.hpp>
52#include <lal/graphs/rooted_tree.hpp>
53#include <lal/internal/graphs/size_subtrees.hpp>
54#include <lal/internal/sorting/counting_sort.hpp>
55
56namespace lal {
57namespace internal {
58
59namespace __lal {
60
61// N: actual number of vertices of the tree
62// n: number of vertices of the connected component of x
63// x: start at node x
64template<
65 class tree_type,
66 std::enable_if_t<
67 std::is_base_of_v<graphs::free_tree, tree_type> ||
68 std::is_base_of_v<graphs::rooted_tree, tree_type>,
69 bool> = true
70>
71std::pair<node, node> retrieve_centroid(
72 const tree_type& t,
73 const uint32_t N, const uint32_t n, const node x,
74 std::vector<std::vector<std::pair<node,uint32_t>>>& L,
75 std::vector<std::pair<edge, uint32_t>>& sizes_edge
76)
77{
78#if defined DEBUG
79 assert(n > 0);
80#endif
81
82 typedef std::pair<edge,uint32_t> edge_size;
83 typedef std::vector<edge_size>::iterator Iterator_Type;
84
85 // calculate s(u,v) with H&S algorithm (lemma 8)
86 {
87 sizes_edge.resize(2*(n - 1));
88 auto it = sizes_edge.begin();
89 internal::calculate_bidirectional_sizes
90 <tree_type, Iterator_Type>(t, n, x, it);
91
92 // sort all tuples in sizes_edge using the sizes
93 internal::counting_sort<edge_size, Iterator_Type, countingsort::decreasing_t>
94 (
95 sizes_edge.begin(), sizes_edge.end(), n, sizes_edge.size(),
96 [](const edge_size& edge_pair) -> size_t { return edge_pair.second; }
97 );
98 }
99
100 // put the s(u,v) into an adjacency list
101 // M[u] : adjacency list of vertex u sorted decreasingly according
102 // to the sizes of the subtrees.
103 L.resize(N);
104 for (const auto& [uv, suv] : sizes_edge) {
105 const auto [u, v] = uv;
106 L[u].push_back(std::make_pair(v,suv));
107 }
108
109 // find the first centroidal vertex
110 node c1 = N + 1;
111 bool found = false;
112 node u = x;
113 while (not found) {
114 const auto& [v, suv] = L[u][0];
115 u = (suv > n/2 ? v : u);
116 found = suv <= n/2;
117 }
118 c1 = u;
119
120#if defined DEBUG
121 assert(c1 < N);
122#endif
123
124 // find the second centroidal vertex among the
125 // neighbours of the first centroidal vertex
126 node c2 = N + 1;
127 for (const auto& p : L[c1]) {
128 const node v = p.first;
129 if (L[v][0].second <= n/2) {
130 c2 = v;
131 break;
132 }
133 }
134
135 return (c1 < c2 ? std::make_pair(c1, c2) : std::make_pair(c2, c1));
136}
137
138} // -- namespace __lal
139
140// -----------------------------------------------------------------------------
141
142/*
143 * @brief Calculate the centroid of the connected component that has node @e x.
144 *
145 * Here, "centroid" should NOT be confused with "centre". The centre is the set
146 * of (at most) two vertices that have minimum eccentricity. The centroid is the
147 * set of (at most) two vertices that have minimum weight, where the weight is
148 * the maximum size of the subtrees rooted at that vertex. In both case, if
149 * the set has two vertices then they are adjacent in the tree. See \cite Harary1969a
150 * for further details.
151 *
152 * A graph of type @ref lal::graphs::tree may lack some edges tree so it can have
153 * several connected components. Vertex @e x belongs to one of these connected
154 * components. So, this method finds the centroidal nodes of the connected
155 * component node @e x belongs to.
156 *
157 * This function uses @ref lal::internal::calculate_suvs, an algorithm described
158 * in \cite Hochberg2003a (see function's documentation for details).
159 * @param t Input tree.
160 * @param x Input node.
161 * @param[out] L A sorted and enriched adjacency list where @e M[u] is a list of
162 * pairs \f$(v,sv)\f$ where @e v is a neighbour of @e u and @e sv is the size of
163 * the subtree rooted at @e v with parent @e u. The list is sorted decreasingly.
164 * @param[out] sizes_edge See documentation of method internal::calculate_suvs.
165 * @returns A tuple of two values: the nodes in the centroid. If the
166 * tree has a single centroidal node, only the first node is valid and the second
167 * is assigned an invalid vertex index. It is guaranteed that the first vertex
168 * has smaller index value than the second.
169 */
170template<
171 class T,
172 std::enable_if_t<
173 std::is_base_of_v<graphs::free_tree, T> ||
174 std::is_base_of_v<graphs::rooted_tree, T>,
175 bool> = true
176>
177std::pair<node, node> retrieve_centroid(
178 const T& t, const node x,
179 std::vector<std::vector<std::pair<node,uint32_t>>>& L,
180 std::vector<std::pair<edge, uint32_t>>& sizes_edge
181)
182{
183 // actual number of vertices of the tree
184 const uint32_t component_size = t.get_num_nodes();
185 // calculate the size of the connected component
186 const uint32_t n = t.get_num_nodes_component(x);
187 // easy case
188 if (n == 1) {
189 return std::make_pair(x, component_size+1);
190 }
191 // general case
192 return __lal::retrieve_centroid(t, component_size, n, x, L, sizes_edge);
193}
194
195/*
196 * @brief Calculate the centroid of the connected component that has node @e x.
197 *
198 * For details on the parameters and return value see documentation of the
199 * function above.
200 */
201template<
202 class T,
203 std::enable_if_t<
204 std::is_base_of_v<graphs::free_tree, T> ||
205 std::is_base_of_v<graphs::rooted_tree, T>,
206 bool> = true
207>
208std::pair<node, node> retrieve_centroid(const T& t, const node x) {
209 std::vector<std::vector<std::pair<node,uint32_t>>> M;
210 std::vector<std::pair<edge, uint32_t>> sizes_edge;
211 return retrieve_centroid(t, x, M, sizes_edge);
212}
213
214// -----------------------------------------------------------------------------
215
216/*
217 * @brief Calculate the centroid of the tree @e t.
218 *
219 * Here, "centroid" should NOT be confused with "centre". The centre is the set
220 * of (at most) two vertices that have minimum eccentricity. The centroid is the
221 * set of (at most) two vertices that have minimum weight, where the weight is
222 * the maximum size of the subtrees rooted at that vertex. In both case, if
223 * the set has two vertices then they are adjacent in the tree. See \cite Harary1969a
224 * for further details.
225 *
226 * This function uses @ref lal::internal::calculate_suvs, an algorithm described
227 * in \cite Hochberg2003a (see function's documentation for details).
228 * @param t Input tree.
229 * @param[out] M A sorted and enriched adjacency list where @e M[u] is a list of
230 * pairs (v,sv) where @e v is a neighbour of @e u and @e sv is the size of the
231 * subtree rooted at @e v with parent @e u. The list is sorted decreasingly.
232 * @param[out] sizes_edge See documentation of method internal::calculate_suvs.
233 * @returns A tuple of two values: the nodes in the centroid. If the
234 * tree has a single centroidal node, only the first node is valid and the second
235 * is assigned an invalid vertex index. It is guaranteed that the first vertex
236 * has smaller index value than the second.
237 * @pre The tree @e t is a valid tree (see @ref lal::graphs::tree::is_tree).
238 */
239template<
240 class T,
241 std::enable_if_t<
242 std::is_base_of_v<graphs::free_tree, T> ||
243 std::is_base_of_v<graphs::rooted_tree, T>,
244 bool> = true
245>
246std::pair<node, node> retrieve_centroid(
247 const T& t,
248 std::vector<std::vector<std::pair<node,uint32_t>>>& L,
249 std::vector<std::pair<edge, uint32_t>>& sizes_edge
250)
251{
252 // actual number of vertices of the tree
253 const uint32_t n = t.get_num_nodes();
254 // easy case
255 if (n == 1) {
256 return std::make_pair(0, n+1);
257 }
258 // general case
259 return __lal::retrieve_centroid(t, n, n, 0, L, sizes_edge);
260}
261
262/*
263 * @brief Calculate the centroid of the tree @e t.
264 *
265 * For details on the parameters and return value see documentation of the
266 * function above.
267 */
268template<
269 class T,
270 std::enable_if_t<
271 std::is_base_of_v<graphs::free_tree, T> ||
272 std::is_base_of_v<graphs::rooted_tree, T>,
273 bool> = true
274>
275std::pair<node, node> retrieve_centroid(const T& t) {
276 std::vector<std::vector<std::pair<node,uint32_t>>> L;
277 std::vector<std::pair<edge, uint32_t>> sizes_edge;
278 return retrieve_centroid(t, L, sizes_edge);
279}
280
281} // -- namespace internal
282} // -- namespace lal
tree_type
Enumeration of several types of trees.
Definition tree_type.hpp:55
Main namespace of the library.
Definition definitions.hpp:48
std::pair< edge, edge > edge_pair
Edge pair type.
Definition definitions.hpp:77
uint32_t node
Node type.
Definition definitions.hpp:51