LAL: Linear Arrangement Library 23.01.00
A library focused on algorithms on linear arrangements of graphs.
Loading...
Searching...
No Matches
tree_maximum_caterpillar.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 <tuple>
46
47// lal includes
48#include <lal/graphs/tree_type.hpp>
49#include <lal/graphs/tree.hpp>
50#include <lal/detail/graphs/traversal.hpp>
51#include <lal/detail/data_array.hpp>
52#include <lal/detail/linear_queue.hpp>
53#include <lal/detail/type_traits/conditional_list.hpp>
54
55namespace lal {
56namespace detail {
57namespace maximum_subtrees {
58namespace caterpillar {
59
61enum result {
82};
83
97template <class tree_t>
99 const tree_t& t,
100 node start_at,
101 BFS<tree_t>& bfs,
102 data_array<uint64_t>& num_vertices_in_path,
104)
105noexcept
106{
107 const auto n = t.get_num_nodes();
108
109 bfs.reset();
110 bfs.set_use_rev_edges( BFS<tree_t>::is_graph_directed );
111
112 num_vertices_in_path.fill(0);
113 num_vertices_in_path[start_at] = 1;
114 uint64_t max_num_vertices = 0;
115
116 node farthest = n + 1;
117
118 bfs.set_process_neighbour(
119 [&](const auto&, node u, node v, bool) {
120 num_vertices_in_path[v] = num_vertices_in_path[u] + weight[u] + 1;
121 if (max_num_vertices < num_vertices_in_path[v]) {
122 max_num_vertices = num_vertices_in_path[v];
123 farthest = v;
124 }
125 }
126 );
127 bfs.start_at(start_at);
128
129 return farthest;
130}
131
146template <
147 result ret_type,
148 class tree_t,
149 std::enable_if_t< std::is_base_of_v<graphs::tree, tree_t>, bool > = true
150>
153 ret_type == result::distance,
154 ret_type == result::distance_vertices,
156 >,
158 uint64_t,
159 std::tuple<uint64_t, std::vector<char>>,
160 std::tuple<uint64_t, std::vector<node>, std::vector<char>>
161 >
162>
163max_subtree(const tree_t& t) noexcept
164{
165 typedef std::vector<node> path;
166
167 const auto n = t.get_num_nodes();
168
169 // the easiest case: we know the tree is a caterpillar
170 if (t.is_tree_type_valid() and t.is_of_tree_type(graphs::tree_type::caterpillar)) {
171 if constexpr (ret_type == result::distance) {
172 return 0;
173 }
174 else if constexpr (ret_type == result::distance_vertices) {
175 return {0, std::vector<char>(n, 1)};
176 }
177
178 // if the value to return contains the caterpillar's backbone, then
179 // we basically need to repeat the code below.
180 }
181
182 // more difficult case: we have no clue what the input tree is.
183
184 if (n == 1) {
185 if constexpr (ret_type == result::distance) {
186 return 0;
187 }
188 else if constexpr (ret_type == result::distance_vertices) {
189 return {0, {1}};
190 }
191 else {
192 return {0, {0}, {1}};
193 }
194 }
195 if (n == 2) {
196 if constexpr (ret_type == result::distance) {
197 return 0;
198 }
199 else if constexpr (ret_type == result::distance_vertices) {
200 return {0, {1,1}};
201 }
202 else {
203 return {0, {0,1}, {1,1}};
204 }
205 }
206
207 // -------------------------------------------------------------------------
208 // initialize data
209
210 data_array<uint64_t> weight(n);
211 for (node u = 0; u < n; ++u) {
212 weight[u] = (t.get_degree(u) == 1 ? 0 : t.get_degree(u) - 2);
213 }
214
215 // the traversal object
216 BFS bfs(t);
217
218 // distance to every vertex from source
219 data_array<uint64_t> num_vertices_in_path(n, 0);
220
221 // -------------------------------------------------------------------------
222 // do the two traversals
223
224 // v_star: farthest from source
225 // w_star: farthest from v_star
226
227 // traverse the tree and find the first 'farthest' vertex (v_star)
228 const node v_star = find_farthest_vertex(t, 0, bfs, num_vertices_in_path, weight);
229
230 // traverse the tree again and find the second 'farthest' vertex (w_star)
231 const node w_star = find_farthest_vertex(t, v_star, bfs, num_vertices_in_path, weight);
232
233 // calculate the caterpillar distance
234 const auto caterpillar_distance = n - num_vertices_in_path[w_star];
235
236 // the tree is not a caterpillar
237 if constexpr (ret_type == result::distance) {
238 return caterpillar_distance;
239 }
240
241 // We detected that the input tree is a caterpillar tree.
242 // In case the caterpillar distance is 0, the return result
243 // may be easy to calculate.
244 if (caterpillar_distance == 0) {
245 if constexpr (ret_type == result::distance_vertices) {
246 return {caterpillar_distance, std::vector<char>(n,1)};
247 }
248
249 // Unfortunately, when (ret_type == max_caterpillar_result::distance_structure)
250 // we have to compute the backbone
251 }
252
253 /* We have to do all of this even if
254 *
255 * (ret_type == max_caterpillar_result::distance_vertices)
256 */
257
258 // sequence of vertices that define the caterpillar's backbone
259 path maximum_caterpillar_backbone;
260
261 // the set of nodes in the maximum spanning caterpillar
262 std::vector<char> is_node_in_maximum_caterpillar(n, 0);
263
264 // path to the current vertex in the traversal
265 path path_to_current;
266
267 // initialize the queue
268 linear_queue<path> path_queue;
269 path_queue.init(n);
270 path_queue.push({w_star});
271
272 // set up the BFS
273 bfs.reset();
275
277 [&](const auto&, node) {
278 path_to_current = path_queue.pop();
279 });
280
281 bfs.set_terminate(
282 [&](const auto&, node u) {
283 if (u == v_star) {
284 maximum_caterpillar_backbone = std::move(path_to_current);
285 }
286 return u == v_star;
287 });
288
290 [&](const auto&, node, node v, bool) {
291 auto path_to_v = path_to_current;
292 path_to_v.push_back(v);
293 path_queue.push(std::move(path_to_v));
294 });
295
296 // retrieve the backbone
297 bfs.start_at(w_star);
298
299 // find all vertices in the caterpillar by traversing the backbone
300 for (node u : maximum_caterpillar_backbone) {
301 is_node_in_maximum_caterpillar[u] = 1;
302 if constexpr (not BFS<tree_t>::is_graph_directed) {
303 for (node v : t.get_neighbours(u)) {
304 is_node_in_maximum_caterpillar[v] = 1;
305 }
306 }
307 else {
308 for (node v : t.get_in_neighbours(u)) {
309 is_node_in_maximum_caterpillar[v] = 1;
310 }
311 for (node v : t.get_out_neighbours(u)) {
312 is_node_in_maximum_caterpillar[v] = 1;
313 }
314 }
315 }
316
317 if constexpr (ret_type == result::distance_vertices) {
318 return {
319 caterpillar_distance,
320 std::move(is_node_in_maximum_caterpillar)
321 };
322 }
323 else if constexpr (ret_type == result::distance_structure) {
324 return {
325 caterpillar_distance,
326 std::move(maximum_caterpillar_backbone),
327 std::move(is_node_in_maximum_caterpillar)
328 };
329 }
330}
331
332} // -- namespace caterpillar
333} // -- namespace maximum_subtrees
334} // -- namespace detail
335} // -- namespace lal
Abstract graph Breadth-First Search traversal.
Definition: traversal.hpp:89
void reset() noexcept
Set the graph traversal to its default state.
Definition: traversal.hpp:135
void set_process_current(const BFS_process_one &f) noexcept
Set the function that controls the processing of the current node.
Definition: traversal.hpp:186
void set_terminate(const BFS_bool_one &f) noexcept
Set the function that controls the termination of the loop.
Definition: traversal.hpp:179
void start_at(node source) noexcept
Start traversal at a given node.
Definition: traversal.hpp:152
void set_process_neighbour(const BFS_process_two &f) noexcept
Set the function that controls the processing of the current neighbour.
Definition: traversal.hpp:193
void set_use_rev_edges(bool use) noexcept
Set whether the traversal can use reversed edges.
Definition: traversal.hpp:173
Simple array-like fixed-size queue.
Definition: linear_queue.hpp:69
T && pop() noexcept
Pops the first element of the queue.
Definition: linear_queue.hpp:98
void push(const T &v) noexcept
Insert a new element to the queue.
Definition: linear_queue.hpp:79
void init(std::size_t n) noexcept
Initializes the queue to hold n elements.
Definition: linear_queue.hpp:72
conditional_list_t< bool_sequence< ret_type==result::distance, ret_type==result::distance_vertices, ret_type==result::distance_structure >, type_sequence< uint64_t, std::tuple< uint64_t, std::vector< char > >, std::tuple< uint64_t, std::vector< node >, std::vector< char > > > > max_subtree(const tree_t &t) noexcept
Calculate the maximum spanning caterpillar of a tree.
Definition: tree_maximum_caterpillar.hpp:163
node find_farthest_vertex(const tree_t &t, node start_at, BFS< tree_t > &bfs, data_array< uint64_t > &num_vertices_in_path, data_array< uint64_t > &weight) noexcept
Find the farthest vertex from start_at in the tree.
Definition: tree_maximum_caterpillar.hpp:98
result
What is to be calculated when finding the maximum spanning caterpillar.
Definition: tree_maximum_caterpillar.hpp:61
@ distance_structure
Caterpillar distance plus the caterpillar's structure.
Definition: tree_maximum_caterpillar.hpp:81
@ distance
Only the caterpillar distance.
Definition: tree_maximum_caterpillar.hpp:63
@ distance_vertices
Caterpillar distance plus caterpillar structure's nodes.
Definition: tree_maximum_caterpillar.hpp:70
typename conditional_list< bool_seq, type_seq >::type conditional_list_t
Shorthand for conditional_list.
Definition: conditional_list.hpp:78
@ caterpillar
Caterpillar trees.
Main namespace of the library.
Definition: basic_types.hpp:50
uint64_t node
Node type. See Node / Vertex page for further details.
Definition: basic_types.hpp:53
A sequence of Boolean values.
Definition: bool_sequence.hpp:52
Wrapper of a C array for autmatic deallocation of memory.
Definition: data_array.hpp:59
A sequence of types.
Definition: type_sequence.hpp:51