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