LAL: Linear Arrangement Library 23.01.00
A library focused on algorithms on linear arrangements of graphs.
Loading...
Searching...
No Matches
DMax_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 - 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 * 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 * LARCA (Laboratory for Relational Algorithmics, Complexity and Learning)
41 * CQL (Complexity and Quantitative Linguistics Lab)
42 * Office S124, 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/DMax_utils.hpp>
60#include <lal/detail/linarr/Dopt_utils.hpp>
61#include <lal/detail/linarr/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} {}
103 edge_size_sigma(edge _e, uint64_t _size, std::size_t _sigma) noexcept
104 : e{_e}, size{_size}, sigma{_sigma}
105 {}
106};
107
109typedef std::vector<std::vector<sorted_adjacency_list_info>>
111
113
120inline
122noexcept
123{
124 typedef std::pair<edge, uint64_t> edge_size;
125
126 const uint64_t n = t.get_num_nodes();
127 const uint64_t m = n - 1;
128
129 // M[u] : adjacency list of vertex u sorted decreasingly according
130 // to the sizes of the subtrees.
132
133 // bidirectional sizes
135 {
137
138 // sort all tuples in bidir_sizes using the size of the subtree
139 sorting::counting_sort<edge_size, sorting::non_increasing_t>
140 (
141 S.begin(), S.end(), n, S.size(),
142 [](const edge_size& T) -> std::size_t { return std::get<1>(T); }
143 );
144 }
145
146 // put the sorted bidirectional sizes into an adjacency list
148 for (std::size_t idx = 0; idx < S.size(); ++idx) {
149 const auto& T = S[idx];
150
151 const auto [u, v] = T.first;
152 const uint64_t nv = T.second;
153 const uint64_t sigma_u_v = M[u].size();
154
155 M[u].push_back({
156 // node identifier
157 v,
158 // The size of the subtree T^u_v
159 nv,
160 // index_of_child_within_parents_list:
161 // The index of 'v' within the list of 'u'
162 sigma_u_v,
163 // index_of_parent_within_childs_list:
164 // calculated after M is filled
165 0,
166 // The sum of all the sizes including this size
167 nv + (M[u].size() > 0 ? M[u].back().partial_sum : 0)
168 });
169
170 J[idx] = {{v,u}, n - nv, sigma_u_v};
171
172#if defined DEBUG
173 assert(t.has_edge(u,v));
174#endif
175 }
176
177#if defined DEBUG
178 for (node u = 0; u < n; ++u) {
179 assert(M[u].size() == t.get_degree(u));
180 }
181#endif
182
183 // sort all tuples in bidir_idxs using the size of the subtree
186 (
187 J.begin(), J.end(), n, J.size(),
188 [](const edge_size_sigma& T) -> std::size_t { return T.size; }
189 );
190
192 for (const auto& [e, suv, sigma_v_u] : J) {
193 const auto u = e.first;
194
195 M[u][ I[u] ].index_of_parent_within_childs_list = sigma_v_u;
196 ++I[u];
197 }
198
199 return M;
200}
201
215};
216
231template <return_type_all_maxs res_type>
237 >,
239 std::pair<std::vector<uint64_t>, uint64_t>,
240 std::vector<uint64_t>,
241 uint64_t
242 >
243>
245{
246 constexpr bool calculate_max_root =
249
250 const uint64_t n = t.get_num_nodes();
251
252 // the value of DMax for all vertices
253 std::vector<uint64_t> DMax_per_vertex(n, 0);
254
255 if (n == 1) {
256 DMax_per_vertex[0] = 0;
258 return {std::move(DMax_per_vertex), 0};
259 }
260 else if constexpr (res_type == return_type_all_maxs::DMax_value_vertex) {
261 return DMax_per_vertex;
262 }
263 else if constexpr (res_type == return_type_all_maxs::max_root) {
264 return 0;
265 }
266 }
267 if (n == 2) {
268 DMax_per_vertex[0] = 1;
269 DMax_per_vertex[1] = 1;
271 return {std::move(DMax_per_vertex), 0};
272 }
273 else if constexpr (res_type == return_type_all_maxs::DMax_value_vertex) {
274 return DMax_per_vertex;
275 }
276 else if constexpr (res_type == return_type_all_maxs::max_root) {
277 return 0;
278 }
279 }
280
281 const auto M = make_sorted_adjacency_list(t);
282
283 // starting vertex for the algorithm
284 const node starting_vertex = 0;
285#if defined DEBUG
286 assert(starting_vertex < n);
287#endif
288
289 // calculate DMax for the starting vertex
290 {
291 graphs::rooted_tree rt(t, starting_vertex);
293 DMax_per_vertex[starting_vertex] = projective::AEF<false>(rt);
294 }
295
296 // the maximum value and the corresponding node
297 uint64_t max_DMax = DMax_per_vertex[starting_vertex];
298 node max_root = starting_vertex;
299
300 // calculate the value of DMax for all vertices
301 data_array<char> visited(n, 0);
302 visited[starting_vertex] = 1;
303 std::queue<node> Q;
304 Q.push(starting_vertex);
305
306 while (not Q.empty()) {
307 const node u = Q.front();
308 Q.pop();
309
310 const auto& Mu = M[u];
311 for (const auto& [v, s_u_v, sigma_u_v, sigma_v_u, partial_sum_ui] : Mu) {
312 if (visited[v] == 1) { continue; }
313
314 const uint64_t s_v_u = n - s_u_v;
315 const uint64_t partial_sum_vi = M[v][sigma_v_u].partial_sum;
316
317 DMax_per_vertex[v] =
318 DMax_per_vertex[u]
319 + (partial_sum_vi + (t.get_degree(v) - (sigma_v_u + 1))*s_v_u)
320 - (partial_sum_ui + (t.get_degree(u) - (sigma_u_v + 1))*s_u_v)
321 ;
322
323 visited[v] = 1;
324 Q.push(v);
325
326 if constexpr (calculate_max_root) {
327 if (max_DMax < DMax_per_vertex[v]) {
328 max_DMax = DMax_per_vertex[v];
329 max_root = v;
330 }
331 }
332 }
333 }
334
336 return {std::move(DMax_per_vertex), max_root};
337 }
338 else if constexpr (res_type == return_type_all_maxs::DMax_value_vertex) {
339 return DMax_per_vertex;
340 }
341 else if constexpr (res_type == return_type_all_maxs::max_root) {
342 return max_root;
343 }
344}
345
360template <bool make_arrangement>
361std::conditional_t<
362 make_arrangement,
363 std::pair<uint64_t, linear_arrangement>,
364 uint64_t
365>
366AEF(const graphs::free_tree& t) noexcept
367{
368 const uint64_t n = t.get_num_nodes();
369
370 // in case the tree is caterpillar and the arrangement is
371 // not required then simply apply the formula
372 if constexpr (not make_arrangement) {
373 if (t.is_tree_type_valid() and t.is_of_tree_type(graphs::tree_type::caterpillar)) {
374 return (n*(n - 1))/2;
375 }
376 }
377
378 if (n == 1) {
379 if constexpr (make_arrangement) {
380 return {0, linear_arrangement::identity(1)};
381 }
382 else {
383 return 0;
384 }
385 }
386 if (n == 2) {
387 if constexpr (make_arrangement) {
388 return {1, linear_arrangement::identity(2)};
389 }
390 else {
391 return 1;
392 }
393 }
394
395 const node max_root =
396 all_max_sum_lengths_values<return_type_all_maxs::max_root>(t);
397
398 // root the tree at a maximizing node
401 return projective::AEF<make_arrangement>(rt);
402}
403
404} // -- namespace planar
405} // -- namespace DMax
406} // -- namespace detail
407} // -- namespace lal
Free tree graph class.
Definition: free_tree.hpp:60
Rooted tree graph class.
Definition: rooted_tree.hpp:103
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:452
std::vector< std::vector< sorted_adjacency_list_info > > sorted_adjacency_list
Useful shorthand for a sorted adjacency list.
Definition: DMax_Planar_AEF.hpp:110
return_type_all_maxs
All return types as enumeration values.
Definition: DMax_Planar_AEF.hpp:207
@ 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: DMax_Planar_AEF.hpp:366
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: DMax_Planar_AEF.hpp:244
sorted_adjacency_list make_sorted_adjacency_list(const graphs::free_tree &t) noexcept
Construct the for every vertex in the tree. .
Definition: DMax_Planar_AEF.hpp:121
void counting_sort(const value_iterator_t begin, const value_iterator_t end, const std::size_t largest_key_plus_1, const std::function< std::size_t(const value_t &)> &key, countingsort::memory< value_t > &mem) noexcept
Counting sort algorithm with reusable memory.
Definition: counting_sort.hpp:155
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:158
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:50
std::pair< node, node > edge
See Edge page for further details.
Definition: basic_types.hpp:58
uint64_t node
Node type. See Node / Vertex page for further details.
Definition: basic_types.hpp:53
A tuple used to construct the sorted adjacency list.
Definition: DMax_Planar_AEF.hpp:92
uint64_t size
Directional size (u,v)
Definition: DMax_Planar_AEF.hpp:96
std::size_t sigma
Index of 'v' within list of 'u'.
Definition: DMax_Planar_AEF.hpp:98
edge_size_sigma(edge _e, uint64_t _size, std::size_t _sigma) noexcept
Constructor.
Definition: DMax_Planar_AEF.hpp:103
edge e
Edge (u,v)
Definition: DMax_Planar_AEF.hpp:94
edge_size_sigma() noexcept
Constructor.
Definition: DMax_Planar_AEF.hpp:101
A piece of information within u's list.
Definition: DMax_Planar_AEF.hpp:70
uint64_t size
The number of nodes in the tree T^parent_child.
Definition: DMax_Planar_AEF.hpp:76
uint64_t index_of_parent_within_childs_list
Definition: DMax_Planar_AEF.hpp:85
uint64_t index_of_child_within_parents_list
Definition: DMax_Planar_AEF.hpp:81
node child
Definition: DMax_Planar_AEF.hpp:73
uint64_t partial_sum
The sum of this size plus all the sizes before it.
Definition: DMax_Planar_AEF.hpp:88
A sequence of Boolean values.
Definition: bool_sequence.hpp:52
Wrapper of a C array for autmatic deallocation of memory.
Definition: data_array.hpp:59
T & first() noexcept
Non-constant reference to the first element in the array.
Definition: data_array.hpp:234
std::size_t size() const noexcept
Size of the array.
Definition: data_array.hpp:204
T * end() noexcept
Non-constant raw pointer to last+1 element.
Definition: data_array.hpp:293
T * begin() noexcept
Non-constant raw pointer to first element.
Definition: data_array.hpp:291
Struct used in many algorithms to sort edges according to some integer value.
Definition: pairs_utils.hpp:65
Non-increasing sort.
Definition: sorting_types.hpp:51
A sequence of types.
Definition: type_sequence.hpp:51