LAL: Linear Arrangement Library 24.10.00
A library focused on algorithms on linear arrangements of graphs.
Loading...
Searching...
No Matches
tree_classification.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 <array>
49
50// lal includes
51#include <lal/graphs/tree_type.hpp>
52#include <lal/graphs/rooted_tree.hpp>
53#include <lal/graphs/free_tree.hpp>
54#include <lal/detail/array.hpp>
55
56namespace lal {
57namespace detail {
58
66template <
67 class tree_t,
68 std::enable_if_t< std::is_base_of_v<graphs::tree, tree_t>, bool> = true
69>
71(const tree_t& t, std::array<bool, graphs::__tree_type_size>& tree_types)
72noexcept
73{
74#if defined DEBUG
75 assert(t.is_tree());
76#endif
77 // -------------------------------------------------------------------------
78 // utilities
79
80 bool is_some = false; // the type of the tree is different from 'unknown'
81
82 const auto unset_type =
83 [&](const graphs::tree_type& tt) {
84 tree_types[static_cast<std::size_t>(tt)] = false;
85 };
86 const auto set_type =
87 [&](const graphs::tree_type& tt) {
88 tree_types[static_cast<std::size_t>(tt)] = true;
89 is_some = true;
90 };
91
92 // only neighbour of a vertex of a tree in its underlying UNDIRECTED structure
93 const auto get_only_neighbour =
94 [&](node u) -> node {
95 if constexpr (std::is_base_of_v<graphs::free_tree, tree_t>) {
96 return t.get_neighbors(u)[0];
97 }
98 else {
99 return (t.get_out_degree(u) == 0 ?
100 t.get_in_neighbors(u)[0] :
101 t.get_out_neighbors(u)[0]
102 );
103 }
104 };
105
106 // -------------------------------------------------------------------------
107
108 // number of vertices
109 const uint64_t n = t.get_num_nodes();
110 if (n == 0) {
111 set_type(graphs::tree_type::empty);
112 unset_type(graphs::tree_type::unknown);
113 return;
114 }
115 if (n == 1) {
118 unset_type(graphs::tree_type::unknown);
119 return;
120 }
121 if (n == 2) {
123 set_type(graphs::tree_type::star);
126 unset_type(graphs::tree_type::unknown);
127 return;
128 }
129 if (n == 3) {
131 set_type(graphs::tree_type::star);
134 unset_type(graphs::tree_type::unknown);
135 return;
136 }
137
138 // n >= 4
139
140 // number of vertices
141 uint64_t n_deg_eq_1 = 0; // of degree = 1
142 uint64_t n_deg_eq_2 = 0; // of degree = 2
143 uint64_t n_deg_ge_2 = 0; // of degree >= 2
144 uint64_t n_deg_ge_3 = 0; // of degree >= 3
145
146 // degree of the internal vertices
147 array<int64_t> deg_internal(n, 0);
148
149 // fill in data
150 for (node u = 0; u < n; ++u) {
151 // 'du' is the degree of the vertex in the underlying undirected graph
152 const int64_t du = static_cast<int64_t>(t.get_degree(u));
153 deg_internal[u] += (du > 1)*du;
154
155 n_deg_eq_1 += du == 1;
156 n_deg_eq_2 += du == 2;
157 n_deg_ge_2 += du > 1;
158 n_deg_ge_3 += du > 2;
159
160 // this reduces the degree of the internal vertices
161 // as many times as leaves are connected to them
162 deg_internal[ get_only_neighbour(u) ] -= (du == 1);
163 }
164
165 bool is_linear = false;
166 bool is_star = false;
167 bool is_quasistar = false;
168 bool is_bistar = false;
169 bool is_caterpillar = false;
170 bool is_spider = false;
171 bool is_two_linear = false;
172
173 // LINEAR
174 if (n_deg_eq_1 == 2) {
175 // if there are only two leaves then we must
176 // have that the remaining vertices are of degree 2.
177#if defined DEBUG
178 assert(n_deg_ge_2 == n - 2);
179#endif
180 is_linear = true;
181 is_caterpillar = true;
182 }
183
184 // BISTAR
185 if (n_deg_ge_2 == 2 and n - n_deg_ge_2 == n_deg_eq_1) {
186 is_bistar = true;
187 is_caterpillar = true;
188 is_two_linear = true;
189 }
190
191 // QUASISTAR
192 if (n - n_deg_ge_2 == n_deg_eq_1 and
193 (
194 (n_deg_eq_2 == 2 and n_deg_ge_3 == 0) or
195 (n_deg_ge_3 == 1 and n_deg_eq_2 == 1)
196 )
197 )
198 {
199 is_quasistar = true;
200 is_bistar = true;
201 is_caterpillar = true;
202 is_spider = n > 4;
203 is_two_linear = false;
204 }
205
206 // STAR
207 if (n_deg_ge_2 == 1 and n_deg_eq_1 == n - 1) {
208 is_star = true;
209 is_quasistar = true;
210 is_bistar = true;
211 is_caterpillar = true;
212 is_spider = true;
213 }
214
215 // SPIDER
216 if (n_deg_ge_3 == 1 and n_deg_eq_1 + n_deg_eq_2 == n - 1) {
217 is_spider = true;
218 }
219
220 // 2-LINEAR
221 if (n_deg_ge_3 == 2 and n_deg_eq_1 + n_deg_eq_2 == n - 2) {
222 is_two_linear = true;
223 }
224
225 if (not is_caterpillar) {
226 // If we are left with 2, or 0, vertices with degree 1,
227 // it means that after removing the leaves of the tree
228 // all vertices are internal (degree 2), i.e., they are
229 // part of a linear tree. Needless to say that these
230 // two vertices of degree 1 are the endpoints of the
231 // linear tree.
232 uint64_t n1 = 0;
233 for (node u = 0; u < n and n1 <= 2; ++u) {
234 n1 += deg_internal[u] == 1;
235 }
236 is_caterpillar = n1 == 2 or n1 == 0;
237 }
238
239 if (is_linear) { set_type(graphs::tree_type::linear); }
240 else { unset_type(graphs::tree_type::linear); }
241
242 if (is_star) { set_type(graphs::tree_type::star); }
243 else { unset_type(graphs::tree_type::star); }
244
245 if (is_quasistar) { set_type(graphs::tree_type::quasistar); }
246 else { unset_type(graphs::tree_type::quasistar); }
247
248 if (is_bistar) { set_type(graphs::tree_type::bistar); }
249 else { unset_type(graphs::tree_type::bistar); }
250
251 if (is_caterpillar) { set_type(graphs::tree_type::caterpillar); }
252 else { unset_type(graphs::tree_type::caterpillar); }
253
254 if (is_spider) { set_type(graphs::tree_type::spider); }
255 else { unset_type(graphs::tree_type::spider); }
256
257 if (is_two_linear) { set_type(graphs::tree_type::two_linear); }
258 else { unset_type(graphs::tree_type::two_linear); }
259
260 if (is_some) { unset_type(graphs::tree_type::unknown); }
261 else { set_type(graphs::tree_type::unknown); }
262}
263
264} // -- namespace detail
265} // -- namespace lal
void classify_tree(const tree_t &t, std::array< bool, graphs::__tree_type_size > &tree_types) noexcept
Classify a tree into one of the types graphs::tree_type.
Definition tree_classification.hpp:71
tree_type
Enumeration of several types of trees.
Definition tree_type.hpp:57
@ caterpillar
Caterpillar trees.
@ bistar
Bi-star trees.
@ singleton
Singleton tree.
@ two_linear
2-linear trees.
@ linear
Linear trees.
@ quasistar
Quasi star trees.
@ unknown
The tree could not be classified.
@ spider
Spider trees.
Main namespace of the library.
Definition basic_types.hpp:48
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