LAL: Linear Arrangement Library 24.10.00
A library focused on algorithms on linear arrangements of graphs.
Loading...
Searching...
No Matches
Planar_AEF.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 * Juan Luis Esteban (esteban@cs.upc.edu)
34 * LOGPROG: Logics and Programming Research Group
35 * Office 110, Omega building
36 * Jordi Girona St 1-3, Campus Nord UPC, 08034 Barcelona. CATALONIA, SPAIN
37 * Webpage: https://www.cs.upc.edu/~esteban/
38 *
39 * Ramon Ferrer i Cancho (rferrericancho@cs.upc.edu)
40 * LQMC (Quantitative, Mathematical, and Computational Linguisitcs)
41 * CQL (Complexity and Quantitative Linguistics Lab)
42 * Office 220, Omega building
43 * Jordi Girona St 1-3, Campus Nord UPC, 08034 Barcelona. CATALONIA, SPAIN
44 * Webpage: https://cqllab.upc.edu/people/rferrericancho/
45 *
46 ********************************************************************/
47
48#pragma once
49
50// C++ includes
51#if defined DEBUG
52#include <cassert>
53#endif
54#include <vector>
55#include <queue>
56
57// lal includes
58#include <lal/graphs/rooted_tree.hpp>
59#include <lal/detail/linarr/D/DMax/utils.hpp>
60#include <lal/detail/linarr/D/Dopt_utils.hpp>
61#include <lal/detail/linarr/D/DMax/Projective_AEF.hpp>
62#include <lal/detail/type_traits/conditional_list.hpp>
63
64namespace lal {
65namespace detail {
66namespace DMax {
67namespace planar {
68
73 node child; // v
74
76 uint64_t size;
77
81 uint64_t index_of_child_within_parents_list; // sigma(u,v)
82
85 uint64_t index_of_parent_within_childs_list; // sigma(v,u)
86
88 uint64_t partial_sum;
89};
90
96 uint64_t size;
98 std::size_t sigma;
99
101 edge_size_sigma() noexcept : e{}, size{0}, sigma{0} {}
104 const edge _e,
105 const uint64_t _size,
106 const std::size_t _sigma
107 )
108 noexcept :
109 e{_e}, size{_size}, sigma{_sigma}
110 {}
111};
112
114typedef std::vector<std::vector<sorted_adjacency_list_info>>
116
118
125[[nodiscard]] inline
127noexcept
128{
129 typedef std::pair<edge, uint64_t> edge_size;
130
131 const uint64_t n = t.get_num_nodes();
132 const uint64_t m = n - 1;
133
134 // M[u] : adjacency list of vertex u sorted decreasingly according
135 // to the sizes of the subtrees.
137
138 // bidirectional sizes
139 array<edge_size> S(2*m);
140 {
142
143 // sort all tuples in bidir_sizes using the size of the subtree
145 (
146 S.begin(), S.end(), n, S.size(),
147 [](const edge_size& T) -> std::size_t { return std::get<1>(T); }
148 );
149 }
150
151 // put the sorted bidirectional sizes into an adjacency list
153 for (std::size_t idx = 0; idx < S.size(); ++idx) {
154 const auto& T = S[idx];
155
156 const auto [u, v] = T.first;
157 const uint64_t nv = T.second;
158 const uint64_t sigma_u_v = M[u].size();
159
160 M[u].push_back({
161 // node identifier
162 v,
163 // The size of the subtree T^u_v
164 nv,
165 // index_of_child_within_parents_list:
166 // The index of 'v' within the list of 'u'
167 sigma_u_v,
168 // index_of_parent_within_childs_list:
169 // calculated after M is filled
170 0,
171 // The sum of all the sizes including this size
172 nv + (M[u].size() > 0 ? M[u].back().partial_sum : 0)
173 });
174
175 J[idx] = {{v,u}, n - nv, sigma_u_v};
176
177#if defined DEBUG
178 assert(t.has_edge(u,v));
179#endif
180 }
181
182#if defined DEBUG
183 for (node u = 0; u < n; ++u) {
184 assert(M[u].size() == t.get_degree(u));
185 }
186#endif
187
188 // sort all tuples in bidir_idxs using the size of the subtree
191 (
192 J.begin(), J.end(), n, J.size(),
193 [](const edge_size_sigma& T) -> std::size_t { return T.size; }
194 );
195
196 array<std::size_t> I(n, 0);
197 for (const auto& [e, suv, sigma_v_u] : J) {
198 const auto u = e.first;
199
200 M[u][ I[u] ].index_of_parent_within_childs_list = sigma_v_u;
201 ++I[u];
202 }
203
204 return M;
205}
206
221
236template <return_type_all_maxs res_type>
237[[nodiscard]] conditional_list_t<
242 >,
244 std::pair<std::vector<uint64_t>, uint64_t>,
245 std::vector<uint64_t>,
246 uint64_t
247 >
248>
250{
251 constexpr bool calculate_max_root =
254
255 const uint64_t n = t.get_num_nodes();
256
257 // the value of DMax for all vertices
258 std::vector<uint64_t> DMax_per_vertex(n, 0);
259
260 if (n == 1) {
261 DMax_per_vertex[0] = 0;
263 return {std::move(DMax_per_vertex), 0};
264 }
265 else if constexpr (res_type == return_type_all_maxs::DMax_value_vertex) {
266 return DMax_per_vertex;
267 }
268 else if constexpr (res_type == return_type_all_maxs::max_root) {
269 return 0;
270 }
271 }
272 if (n == 2) {
273 DMax_per_vertex[0] = 1;
274 DMax_per_vertex[1] = 1;
276 return {std::move(DMax_per_vertex), 0};
277 }
278 else if constexpr (res_type == return_type_all_maxs::DMax_value_vertex) {
279 return DMax_per_vertex;
280 }
281 else if constexpr (res_type == return_type_all_maxs::max_root) {
282 return 0;
283 }
284 }
285
286 const auto M = make_sorted_adjacency_list(t);
287
288 // starting vertex for the algorithm
289 const node starting_vertex = 0;
290#if defined DEBUG
291 assert(starting_vertex < n);
292#endif
293
294 // calculate DMax for the starting vertex
295 {
296 graphs::rooted_tree rt(t, starting_vertex);
298 DMax_per_vertex[starting_vertex] = projective::AEF<false>(rt);
299 }
300
301 // the maximum value and the corresponding node
302 uint64_t max_DMax = DMax_per_vertex[starting_vertex];
303 node max_root = starting_vertex;
304
305 // calculate the value of DMax for all vertices
306 array<char> visited(n, 0);
307 visited[starting_vertex] = 1;
308 std::queue<node> Q;
309 Q.push(starting_vertex);
310
311 while (not Q.empty()) {
312 const node u = Q.front();
313 Q.pop();
314
315 const auto& Mu = M[u];
316 for (const auto& [v, s_u_v, sigma_u_v, sigma_v_u, partial_sum_ui] : Mu) {
317 if (visited[v] == 1) { continue; }
318
319 const uint64_t s_v_u = n - s_u_v;
320 const uint64_t partial_sum_vi = M[v][sigma_v_u].partial_sum;
321
322 DMax_per_vertex[v] =
323 DMax_per_vertex[u]
324 + (partial_sum_vi + (t.get_degree(v) - (sigma_v_u + 1))*s_v_u)
325 - (partial_sum_ui + (t.get_degree(u) - (sigma_u_v + 1))*s_u_v)
326 ;
327
328 visited[v] = 1;
329 Q.push(v);
330
331 if constexpr (calculate_max_root) {
332 if (max_DMax < DMax_per_vertex[v]) {
333 max_DMax = DMax_per_vertex[v];
334 max_root = v;
335 }
336 }
337 }
338 }
339
341 return {std::move(DMax_per_vertex), max_root};
342 }
343 else if constexpr (res_type == return_type_all_maxs::DMax_value_vertex) {
344 return DMax_per_vertex;
345 }
346 else if constexpr (res_type == return_type_all_maxs::max_root) {
347 return max_root;
348 }
349}
350
365template <bool make_arrangement>
366[[nodiscard]] std::conditional_t<
367 make_arrangement,
368 std::pair<uint64_t, linear_arrangement>,
369 uint64_t
370>
371AEF(const graphs::free_tree& t) noexcept
372{
373 const uint64_t n = t.get_num_nodes();
374
375 // in case the tree is caterpillar and the arrangement is
376 // not required then simply apply the formula
377 if constexpr (not make_arrangement) {
378 if (t.is_tree_type_valid() and t.is_of_tree_type(graphs::tree_type::caterpillar)) {
379 return (n*(n - 1))/2;
380 }
381 }
382
383 if (n == 1) {
384 if constexpr (make_arrangement) {
385 return {0, linear_arrangement::identity(1)};
386 }
387 else {
388 return 0;
389 }
390 }
391 if (n == 2) {
392 if constexpr (make_arrangement) {
393 return {1, linear_arrangement::identity(2)};
394 }
395 else {
396 return 1;
397 }
398 }
399
400 const node max_root =
402
403 // root the tree at a maximizing node
407}
408
409} // -- namespace planar
410} // -- namespace DMax
411} // -- namespace detail
412} // -- namespace lal
Free tree graph class.
Definition free_tree.hpp:60
Rooted tree graph class.
Definition rooted_tree.hpp:109
void calculate_size_subtrees() noexcept
Calculates the number of nodes at every rooted subtree.
void identity() noexcept
Makes this arrangement an identity arrangement.
Definition linear_arrangement.hpp:507
std::vector< std::vector< sorted_adjacency_list_info > > sorted_adjacency_list
Useful shorthand for a sorted adjacency list.
Definition Planar_AEF.hpp:115
return_type_all_maxs
All return types as enumeration values.
Definition Planar_AEF.hpp:212
@ DMax_value_vertex
Return only the max projective values for every vertex of the tree.
@ max_root
Return only a vertex that maximizes the maximum projective.
std::conditional_t< make_arrangement, std::pair< uint64_t, linear_arrangement >, uint64_t > AEF(const graphs::free_tree &t) noexcept
Maximum planar arrangement of a free tree.
Definition Planar_AEF.hpp:371
conditional_list_t< bool_sequence< res_type==return_type_all_maxs::DMax_value_vertex_and_max_root, res_type==return_type_all_maxs::DMax_value_vertex, res_type==return_type_all_maxs::max_root >, type_sequence< std::pair< std::vector< uint64_t >, uint64_t >, std::vector< uint64_t >, uint64_t > > all_max_sum_lengths_values(const graphs::free_tree &t) noexcept
Maximum planar arrangement of a free tree.
Definition Planar_AEF.hpp:249
sorted_adjacency_list make_sorted_adjacency_list(const graphs::free_tree &t) noexcept
Construct the for every vertex in the tree. .
Definition Planar_AEF.hpp:126
std::conditional_t< make_arrangement, std::pair< uint64_t, linear_arrangement >, uint64_t > AEF(const graphs::rooted_tree &t) noexcept
Maximum projective arrangement of a rooted tree.
Definition Projective_AEF.hpp:86
@ non_increasing
Non-increasing sort.
void counting_sort(const value_iterator_t begin, const value_iterator_t end, const std::size_t largest_key_plus_1, const Callable &key, countingsort::memory< value_t > &mem) noexcept
Counting sort algorithm with reusable memory.
Definition counting_sort.hpp:152
uint64_t calculate_bidirectional_sizes(const tree_t &t, const uint64_t n, const node u, const node v, iterator_t &it) noexcept
Calculates the values for the edges reachable from in the subtree .
Definition size_subtrees.hpp:168
typename conditional_list< bool_seq, type_seq >::type conditional_list_t
Shorthand for conditional_list.
Definition conditional_list.hpp:78
@ caterpillar
Caterpillar trees.
Main namespace of the library.
Definition basic_types.hpp:48
std::pair< node, node > edge
See Edge page for further details.
Definition basic_types.hpp:56
uint64_t node
Node type. See Node / Vertex page for further details.
Definition basic_types.hpp:51
A tuple used to construct the sorted adjacency list.
Definition Planar_AEF.hpp:92
uint64_t size
Directional size (u,v)
Definition Planar_AEF.hpp:96
std::size_t sigma
Index of 'v' within list of 'u'.
Definition Planar_AEF.hpp:98
edge e
Edge (u,v)
Definition Planar_AEF.hpp:94
edge_size_sigma() noexcept
Constructor.
Definition Planar_AEF.hpp:101
edge_size_sigma(const edge _e, const uint64_t _size, const std::size_t _sigma) noexcept
Constructor.
Definition Planar_AEF.hpp:103
A piece of information within u's list.
Definition Planar_AEF.hpp:70
uint64_t size
The number of nodes in the tree T^parent_child.
Definition Planar_AEF.hpp:76
uint64_t index_of_parent_within_childs_list
Definition Planar_AEF.hpp:85
uint64_t index_of_child_within_parents_list
Definition Planar_AEF.hpp:81
uint64_t partial_sum
The sum of this size plus all the sizes before it.
Definition Planar_AEF.hpp:88
Wrapper of a C array for automatic deallocation of memory.
Definition array.hpp:59
T & first() noexcept
Non-constant reference to the first element in the array.
Definition array.hpp:243
T * begin() noexcept
Non-constant raw pointer to first element.
Definition array.hpp:300
T * end() noexcept
Non-constant raw pointer to last+1 element.
Definition array.hpp:302
std::size_t size() const noexcept
Size of the array.
Definition array.hpp:215
A sequence of Boolean values.
Definition bool_sequence.hpp:52
Struct used in many algorithms to sort edges according to some integer value.
Definition pairs_utils.hpp:65
A sequence of types.
Definition type_sequence.hpp:51