LAL: Linear Arrangement Library 23.01.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 - 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 <algorithm>
46#include <cinttypes>
47#if defined DEBUG
48#include <cassert>
49#endif
50
51// lal includes
52#include <lal/graphs/rooted_tree.hpp>
53#include <lal/detail/macros/basic_convert.hpp>
54#include <lal/detail/data_array.hpp>
55
56namespace lal {
57namespace detail {
58
74template <
75 class tree_t,
76 std::enable_if_t< std::is_base_of_v<graphs::tree, tree_t>, bool> = true
77>
78char fast_non_iso(const tree_t& t1, const tree_t& t2) noexcept
79{
80 // check number of nodes
81 if (t1.get_num_nodes() != t2.get_num_nodes()) { return 1; }
82
83 const uint64_t n = t1.get_num_nodes();
84
85 // trees ARE isomorphic
86 if (n <= 2) { return 0; }
87
88 uint64_t nL_t1 = 0; // number of leaves of t1
89 uint64_t nL_t2 = 0; // number of leaves of t2
90 uint64_t k2_t1 = 0; // sum of squared degrees of t1
91 uint64_t k2_t2 = 0; // sum of squared degrees of t2
92 uint64_t maxdeg_t1 = 0; // max degree of t1
93 uint64_t maxdeg_t2 = 0; // max degree of t2
94 for (node u = 0; u < n; ++u) {
95 const uint64_t ku1 = to_uint64(t1.get_degree(u));
96 const uint64_t ku2 = to_uint64(t2.get_degree(u));
97
98 nL_t1 += t1.get_degree(u) == 1;
99 nL_t2 += t2.get_degree(u) == 1;
100 k2_t1 += ku1*ku1;
101 k2_t2 += ku2*ku2;
102 maxdeg_t1 = (maxdeg_t1 < ku1 ? ku1 : maxdeg_t1);
103 maxdeg_t2 = (maxdeg_t2 < ku2 ? ku2 : maxdeg_t2);
104 }
105
106 // check number of leaves
107 if (nL_t1 != nL_t2) { return 1; }
108 // check maximum degree
109 if (maxdeg_t1 != maxdeg_t2) { return 1; }
110 // check sum of squared degrees
111 if (k2_t1 != k2_t2) { return 1; }
112
113 // trees MIGHT BE isomorphic
114 return 2;
115}
116
136inline
138 const graphs::rooted_tree& t, node u,
139 std::size_t idx,
140 std::string * const aux_memory_for_names,
141 std::string * const keep_name_of
142)
143noexcept
144{
145 if (t.get_out_degree(u) == 0) {
146 keep_name_of[u] = "10";
147 return;
148 }
149
150 // make childrens' names
151 const std::size_t begin_idx = idx;
152 for (node v : t.get_out_neighbours(u)) {
153 // make the name for v
154 assign_name_and_keep(t,v, idx+1, aux_memory_for_names, keep_name_of);
155
156 aux_memory_for_names[idx] = keep_name_of[v];
157 ++idx;
158 }
159 std::sort(&aux_memory_for_names[begin_idx], &aux_memory_for_names[idx]);
160
161 // join the names in a single string to make the name of vertex 'v'
162 std::string name = "1";
163 for (std::size_t j = begin_idx; j < idx; ++j) {
164 name += aux_memory_for_names[j];
165 }
166 name += "0";
167 keep_name_of[u] = name;
168}
169
185inline
186std::string assign_name
187(const graphs::rooted_tree& t, node u, std::string * const names, std::size_t idx)
188noexcept
189{
190 if (t.get_out_degree(u) == 0) {
191 return std::string("10");
192 }
193
194 // make childrens' names
195 const std::size_t begin_idx = idx;
196 for (node v : t.get_out_neighbours(u)) {
197 // make the name for v
198 names[idx] = assign_name(t,v, names, idx+1);
199 ++idx;
200 }
201 std::sort(&names[begin_idx], &names[idx]);
202
203 // join the names in a single string to make the name of vertex 'v'
204 std::string name = "1";
205 for (std::size_t j = begin_idx; j < idx; ++j) {
206 name += names[j];
207 }
208 name += "0";
209
210 return name;
211}
212
214inline
216(const graphs::rooted_tree& t1, const graphs::rooted_tree& t2)
217noexcept
218{
219 const auto discard = detail::fast_non_iso(t1,t2);
220 if (discard == 0) { return true; }
221 if (discard == 1) { return false; }
222
223 data_array<std::string> names(t1.get_num_nodes());
224 const std::string name_r1 = assign_name(t1, t1.get_root(), names.begin(), 0);
225 const std::string name_r2 = assign_name(t2, t2.get_root(), names.begin(), 0);
226 return name_r1 == name_r2;
227}
228
229} // -- namespace detail
230} // -- namespace lal
Rooted tree graph class.
Definition: rooted_tree.hpp:103
char fast_non_iso(const tree_t &t1, const tree_t &t2) noexcept
Fast tree non-isomorphism test.
Definition: tree_isomorphism.hpp:78
bool are_full_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:216
std::string assign_name(const graphs::rooted_tree &t, node u, std::string *const names, std::size_t idx) noexcept
Assigns a name to node 'u', root of the current subtree.
Definition: tree_isomorphism.hpp:187
constexpr uint64_t to_uint64(const T &t) noexcept
Conversion to uint64_t.
Definition: basic_convert.hpp:57
void assign_name_and_keep(const graphs::rooted_tree &t, node u, std::size_t idx, std::string *const aux_memory_for_names, std::string *const keep_name_of) noexcept
Assigns a name to node 'u', root of the current subtree.
Definition: tree_isomorphism.hpp:137
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
T * begin() noexcept
Non-constant raw pointer to first element.
Definition: data_array.hpp:291