LAL: Linear Arrangement Library 23.01.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 - 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#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/data_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>
70void classify_tree(const tree_t& t, std::array<bool, graphs::__tree_type_size>& array)
71noexcept
72{
73#if defined DEBUG
74 assert(t.is_tree());
75#endif
76 // -------------------------------------------------------------------------
77 // utilities
78
79 bool is_some = false; // the type of the tree is different from 'unknown'
80
81 const auto set_type =
82 [&](const graphs::tree_type& tt) {
83 array[static_cast<std::size_t>(tt)] = true;
84 is_some = true;
85 };
86
87 // only neighbour of a vertex of a tree in its underlying UNDIRECTED structure
88 const auto get_only_neighbour =
89 [&](lal::node u) -> lal::node {
90 if constexpr (std::is_base_of_v<lal::graphs::free_tree, tree_t>) {
91 return t.get_neighbours(u)[0];
92 }
93 else {
94 return (t.get_out_degree(u) == 0 ?
95 t.get_in_neighbours(u)[0] :
96 t.get_out_neighbours(u)[0]
97 );
98 }
99 };
100
101 // -------------------------------------------------------------------------
102
103 // number of vertices
104 const uint64_t n = t.get_num_nodes();
105 if (n == 0) {
106 set_type(graphs::tree_type::empty);
107 array[static_cast<std::size_t>(graphs::tree_type::unknown)] = false;
108 return;
109 }
110 if (n == 1) {
113 array[static_cast<std::size_t>(graphs::tree_type::unknown)] = false;
114 return;
115 }
116 if (n == 2) {
118 set_type(graphs::tree_type::star);
121 array[static_cast<std::size_t>(graphs::tree_type::unknown)] = false;
122 return;
123 }
124 if (n == 3) {
126 set_type(graphs::tree_type::star);
129 array[static_cast<std::size_t>(graphs::tree_type::unknown)] = false;
130 return;
131 }
132
133 // N >= 4
134
135 bool is_linear = false;
136 bool is_star = false;
137 bool is_quasistar = false;
138 bool is_bistar = false;
139 bool is_caterpillar = false;
140 bool is_spider = false;
141 bool is_two_linear = false;
142
143 // number of vertices
144 uint64_t n_deg_eq_1 = 0; // of degree = 1
145 uint64_t n_deg_eq_2 = 0; // of degree = 2
146 uint64_t n_deg_ge_2 = 0; // of degree >= 2
147 uint64_t n_deg_ge_3 = 0; // of degree >= 3
148
149 // degree of the internal vertices
150 data_array<int64_t> deg_internal(n, 0);
151
152 // fill in data
153 for (lal::node u = 0; u < n; ++u) {
154 // 'du' is the degree of the vertex in the underlying undirected graph
155 const int64_t du = static_cast<int64_t>(t.get_degree(u));
156 deg_internal[u] += (du > 1)*du;
157
158 n_deg_eq_1 += du == 1;
159 n_deg_eq_2 += du == 2;
160 n_deg_ge_2 += du > 1;
161 n_deg_ge_3 += du > 2;
162
163 // this reduces the degree of the internal vertices
164 // as many times as leaves are connected to them
165 if (du == 1) {
166 deg_internal[ get_only_neighbour(u) ] -= 1;
167 }
168 }
169
170 // LINEAR
171 if (n_deg_eq_1 == 2) {
172 // if there are only two leaves then we must
173 // have that the remaining vertices are of degree 2.
174#if defined DEBUG
175 assert(n_deg_ge_2 == n - 2);
176#endif
177 is_linear = true;
178 is_caterpillar = true;
179 }
180
181 // BISTAR
182 if (n_deg_ge_2 == 2 and n - n_deg_ge_2 == n_deg_eq_1) {
183 is_bistar = true;
184 is_caterpillar = true;
185 }
186
187 // QUASISTAR
188 if (n - n_deg_ge_2 == n_deg_eq_1 and
189 (
190 (n_deg_eq_2 == 2 and n_deg_ge_3 == 0) or
191 (n_deg_ge_3 == 1 and n_deg_eq_2 == 1)
192 )
193 )
194 {
195 is_quasistar = true;
196 is_caterpillar = true;
197 }
198
199 // STAR
200 if (n_deg_ge_2 == 1 and n_deg_eq_1 == n - 1) {
201 is_star = true;
202 is_caterpillar = true;
203 }
204
205 // SPIDER
206 if (n_deg_ge_3 == 1 and n_deg_eq_1 + n_deg_eq_2 == n - 1) {
207 is_spider = true;
208 }
209
210 // 2-LINEAR
211 if (n_deg_ge_3 == 2 and n_deg_eq_1 + n_deg_eq_2 == n - 2) {
212 is_two_linear = true;
213 }
214
215 if (not is_caterpillar) {
216 // If we are left with 2, or 0, vertices with degree 1,
217 // it means that after removing the leaves of the tree
218 // all vertices are internal (degree 2), i.e., they are
219 // part of a linear tree. Needless to say that these
220 // two vertices of degree 1 are the endpoints of the
221 // linear tree.
222 uint64_t n1 = 0;
223 for (lal::node u = 0; u < n; ++u) {
224 n1 += deg_internal[u] == 1;
225 }
226
227 is_caterpillar = n1 == 2 or n1 == 0;
228 }
229
230 if (is_linear) { set_type(graphs::tree_type::linear); }
231 if (is_star) { set_type(graphs::tree_type::star); }
232 if (is_quasistar) { set_type(graphs::tree_type::quasistar); }
233 if (is_bistar) { set_type(graphs::tree_type::bistar); }
234 if (is_caterpillar) { set_type(graphs::tree_type::caterpillar); }
235 if (is_spider) { set_type(graphs::tree_type::spider); }
236 if (is_two_linear ) { set_type(graphs::tree_type::two_linear); }
237
238 if (is_some) {
239 array[static_cast<std::size_t>(graphs::tree_type::unknown)] = false;
240 }
241}
242
243} // -- namespace detail
244} // -- namespace lal
void classify_tree(const tree_t &t, std::array< bool, graphs::__tree_type_size > &array) noexcept
Classify a tree into one of the types lal::graphs::tree_type.
Definition: tree_classification.hpp:70
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.
@ empty
Empty tree./.
@ quasistar
Quasi star trees.
@ unknown
The tree could not be classified.
@ spider
Spider 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
Wrapper of a C array for autmatic deallocation of memory.
Definition: data_array.hpp:59