LAL: Linear Arrangement Library 24.10.00
A library focused on algorithms on linear arrangements of graphs.
Loading...
Searching...
No Matches
tree_isomorphism.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#include <algorithm>
46
47// lal includes
48#include <lal/graphs/rooted_tree.hpp>
49#include <lal/detail/macros/basic_convert.hpp>
50#include <lal/detail/array.hpp>
51
52namespace lal {
53namespace detail {
54
70template <
71 class tree_t,
72 std::enable_if_t< std::is_base_of_v<graphs::tree, tree_t>, bool> = true
73>
74[[nodiscard]] char fast_non_iso(const tree_t& t1, const tree_t& t2) noexcept
75{
76 // check number of nodes
77 if (t1.get_num_nodes() != t2.get_num_nodes()) { return 1; }
78
79 const uint64_t n = t1.get_num_nodes();
80
81 // trees ARE isomorphic
82 if (n <= 2) { return 0; }
83
84 uint64_t nL_t1 = 0; // number of leaves of t1
85 uint64_t nL_t2 = 0; // number of leaves of t2
86 uint64_t k2_t1 = 0; // sum of squared degrees of t1
87 uint64_t k2_t2 = 0; // sum of squared degrees of t2
88 uint64_t maxdeg_t1 = 0; // max degree of t1
89 uint64_t maxdeg_t2 = 0; // max degree of t2
90 for (node u = 0; u < n; ++u) {
91 const uint64_t ku1 = to_uint64(t1.get_degree(u));
92 const uint64_t ku2 = to_uint64(t2.get_degree(u));
93
94 nL_t1 += t1.get_degree(u) == 1;
95 nL_t2 += t2.get_degree(u) == 1;
96 k2_t1 += ku1*ku1;
97 k2_t2 += ku2*ku2;
98 maxdeg_t1 = (maxdeg_t1 < ku1 ? ku1 : maxdeg_t1);
99 maxdeg_t2 = (maxdeg_t2 < ku2 ? ku2 : maxdeg_t2);
100 }
101
102 // check number of leaves
103 if (nL_t1 != nL_t2) { return 1; }
104 // check maximum degree
105 if (maxdeg_t1 != maxdeg_t2) { return 1; }
106 // check sum of squared degrees
107 if (k2_t1 != k2_t2) { return 1; }
108
109 // trees MIGHT BE isomorphic
110 return 2;
111}
112
132(
133 const graphs::rooted_tree& t,
134 const node u,
135 std::size_t idx,
136 array<std::string>& aux_memory_for_names,
137 array<std::string>& keep_name_of
138)
139noexcept
140{
141 if (t.get_out_degree(u) == 0) {
142 keep_name_of[u] = "10";
143 return;
144 }
145
146 // make childrens' names
147 const std::size_t begin_idx = idx;
148 for (node v : t.get_out_neighbors(u)) {
149 // make the name for v
150 assign_name_and_keep(t,v, idx+1, aux_memory_for_names, keep_name_of);
151
152 aux_memory_for_names[idx] = keep_name_of[v];
153 ++idx;
154 }
155 std::sort(&aux_memory_for_names[begin_idx], &aux_memory_for_names[idx]);
156
157 // join the names in a single string to make the name of vertex 'v'
158 keep_name_of[u] = "1";
159 for (std::size_t j = begin_idx; j < idx; ++j) {
160 keep_name_of[u] += aux_memory_for_names[j];
161 }
162 keep_name_of[u] += "0";
163}
164
180[[nodiscard]] inline std::string assign_name
181(
182 const graphs::rooted_tree& t,
183 const node u,
184 array<std::string>& names,
185 std::size_t idx
186)
187noexcept
188{
189 if (t.get_out_degree(u) == 0) {
190 return std::string("10");
191 }
192
193 // make childrens' names
194 const std::size_t begin_idx = idx;
195 for (node v : t.get_out_neighbors(u)) {
196 // make the name for v
197 names[idx] = assign_name(t,v, names, idx+1);
198 ++idx;
199 }
200 std::sort(&names[begin_idx], &names[idx]);
201
202 // join the names in a single string to make the name of vertex 'v'
203 std::string name = "1";
204 for (std::size_t j = begin_idx; j < idx; ++j) {
205 name += names[j];
206 }
207 name += "0";
208
209 return name;
210}
211
218[[nodiscard]] inline bool are_rooted_trees_isomorphic
219(const graphs::rooted_tree& t1, const graphs::rooted_tree& t2)
220noexcept
221{
222 const auto discard = fast_non_iso(t1,t2);
223 if (discard == 0) { return true; }
224 if (discard == 1) { return false; }
225
226 array<std::string> names(t1.get_num_nodes());
227 const std::string name_r1 = assign_name(t1, t1.get_root(), names, 0);
228 const std::string name_r2 = assign_name(t2, t2.get_root(), names, 0);
229 return name_r1 == name_r2;
230}
231
232} // -- namespace detail
233} // -- namespace lal
Rooted tree graph class.
Definition rooted_tree.hpp:109
char fast_non_iso(const tree_t &t1, const tree_t &t2) noexcept
Fast tree non-isomorphism test.
Definition tree_isomorphism.hpp:74
std::string assign_name(const graphs::rooted_tree &t, const node u, array< std::string > &names, std::size_t idx) noexcept
Assigns a name to node 'u', root of the current subtree.
Definition tree_isomorphism.hpp:181
bool are_rooted_trees_isomorphic(const graphs::rooted_tree &t1, const graphs::rooted_tree &t2) noexcept
Test whether two rooted trees are isomorphic or not.
Definition tree_isomorphism.hpp:219
void assign_name_and_keep(const graphs::rooted_tree &t, const node u, std::size_t idx, array< std::string > &aux_memory_for_names, array< std::string > &keep_name_of) noexcept
Assigns a name to node 'u', root of the current subtree.
Definition tree_isomorphism.hpp:132
constexpr uint64_t to_uint64(const T &t) noexcept
Conversion to uint64_t.
Definition basic_convert.hpp:52
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