LAL: Linear Arrangement Library 24.10.00
A library focused on algorithms on linear arrangements of graphs.
Loading...
Searching...
No Matches
ladder.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// C++ includes
43#if defined DEBUG
44#include <cassert>
45#endif
46#include <cstring> // for 'memset' below
47#include <vector>
48
49// lal includes
50#include <lal/detail/arrangement_wrapper.hpp>
51#include <lal/detail/graphs/utils.hpp>
52#include <lal/detail/array.hpp>
53
54#define DECIDED_C_GT (upper_bound + 1)
55
56namespace lal {
57namespace detail {
58namespace crossings {
59
65namespace ladder {
66
67// =============================================================================
68// ACTUAL ALGORITHM
69// =============================================================================
70
88template <bool decide_upper_bound, class graph_t, class arrangement_t>
89[[nodiscard]] uint64_t compute
90(
91 const graph_t& g,
92 const arrangement_t& arr,
93 unsigned char * const __restrict__ bn,
94 uint64_t * const __restrict__ L1,
95 const uint64_t upper_bound
96)
97noexcept
98{
99 const uint64_t n = g.get_num_nodes();
100
101 /* compute number of crossings */
102 uint64_t C = 0;
103
104 // no need to reach the last position of the arrangement
105 for (position pu = 0; pu < n - 1; ++pu) {
106 const node u = arr[position_t{pu}];
107
108 // amount of crossings the edges incident to this node and
109 // connecting nodes "to the right" of 'u' in the arrangement
110 uint64_t S = 0;
111
112 // neighbors of node u, as a list of Boolean values.
114
115 for (position pv = pu + 1; pv < n; ++pv) {
116 const node v = arr[position_t{pv}];
117 S += L1[pv];
118
119 // --
120 /*if (bn[v]) {
121 C += S - L1[q];
122 ++L1[q];
123 }*/
124 C += bn[v]*(S - L1[pv]);
125 L1[pv] += bn[v];
126 // --
127
128 if constexpr (decide_upper_bound) {
129 if (C > upper_bound) {
130 return DECIDED_C_GT;
131 }
132 }
133
134 bn[v] = 0;
135 }
136
137 L1[pu] = 0;
138 }
139
140 // none of the conditions above were true, so we must have
141 // C <= upper_bound
142 return C;
143}
144
145} // -- namespace ladder
146
147// =============================================================================
148// CALLS TO ALGORITHM
149// =============================================================================
150
151// ------------------
152// single arrangement
153
162template <class graph_t, class arrangement_t>
163[[nodiscard]] uint64_t n_C_ladder
164(const graph_t& g, const arrangement_t& arr)
165noexcept
166{
167 const uint64_t n = g.get_num_nodes();
168
169#if defined DEBUG
170 assert(arr.size() == 0 or arr.size() == n);
171#endif
172
173 if (n < 4) { return 0; }
174
175 // boolean neighbourhood of nodes
176 array<unsigned char> boolean_neighborhood(n, 0);
177 // array L1 (same as in the pseudocode) ( size n )
178 array<uint64_t> L1(n, 0);
179
181 (g, arr, boolean_neighborhood.begin(), L1.begin(), 0);
182}
183
184// --------------------
185// list of arrangements
186
194template <class graph_t>
195[[nodiscard]] std::vector<uint64_t> n_C_ladder
196(const graph_t& g, const std::vector<linear_arrangement>& arrs)
197noexcept
198{
199 const uint64_t n = g.get_num_nodes();
200
201 std::vector<uint64_t> cs(arrs.size(), 0);
202 if (n < 4) { return cs; }
203
204 // boolean neighbourhood of nodes
205 array<unsigned char> boolean_neighborhood(n, 0);
206 // array L1 (same as in the pseudocode) ( size n )
207 array<uint64_t> L1(n, 0);
208
209 /* compute C for every linear arrangement */
210 for (std::size_t i = 0; i < arrs.size(); ++i) {
211#if defined DEBUG
212 // ensure that no linear arrangement is empty
213 assert(arrs[i].size() == n);
214#endif
215
216 // compute C
218 (g, nonidentity_arr(arrs[i]), boolean_neighborhood.begin(), L1.begin(), 0);
219
220 boolean_neighborhood.fill(0);
221 L1[n - 1] = 0;
222 }
223
224 return cs;
225}
226
227// -----------------------------------------------------------------------------
228// DECISION
229
230// ------------------
231// single arrangement
232
243template <class graph_t, class arrangement_t>
244[[nodiscard]] uint64_t is_n_C_ladder_lesseq_than
245(
246 const graph_t& g,
247 const arrangement_t& arr,
248 const uint64_t upper_bound
249)
250noexcept
251{
252 const uint64_t n = g.get_num_nodes();
253
254#if defined DEBUG
255 assert(arr.size() == 0 or arr.size() == n);
256#endif
257
258 if (n < 4) { return 0; }
259
260 // boolean neighbourhood of nodes
261 array<unsigned char> boolean_neighborhood(n, 0);
262 // array L1 (same as in the pseudocode) ( size n )
263 array<uint64_t> L1(n, 0);
264
265 return
267 (g, arr, boolean_neighborhood.begin(), L1.begin(), upper_bound);
268}
269
270// --------------------
271// list of arrangements
272
282template <class graph_t>
283[[nodiscard]] std::vector<uint64_t> is_n_C_ladder_lesseq_than
284(
285 const graph_t& g,
286 const std::vector<linear_arrangement>& arrs,
287 const uint64_t upper_bound
288)
289noexcept
290{
291 const uint64_t n = g.get_num_nodes();
292
293 std::vector<uint64_t> cs(arrs.size(), 0);
294 if (n < 4) { return cs; }
295
296 // boolean neighbourhood of nodes
297 array<unsigned char> boolean_neighborhood(n, 0);
298 // array L1 (same as in the pseudocode) ( size n )
299 array<uint64_t> L1(n, 0);
300
301 /* compute C for every linear arrangement */
302 for (std::size_t i = 0; i < arrs.size(); ++i) {
303#if defined DEBUG
304 // ensure that no linear arrangement is empty
305 assert(arrs[i].size() == n);
306#endif
307
308 // compute C
310 (g, nonidentity_arr(arrs[i]),
311 boolean_neighborhood.begin(), L1.begin(), upper_bound);
312
313 for (uint64_t z = 0; z < n; ++z) {
314 L1[z] = 0;
315 boolean_neighborhood[z] = 0;
316 }
317 L1[n - 1] = 0;
318 }
319
320 return cs;
321}
322
333template <class graph_t>
334[[nodiscard]] std::vector<uint64_t> is_n_C_ladder_lesseq_than
335(
336 const graph_t& g,
337 const std::vector<linear_arrangement>& arrs,
338 const std::vector<uint64_t>& upper_bounds
339)
340noexcept
341{
342#if defined DEBUG
343 // ensure that there are as many linear arrangements as upper bounds
344 assert(arrs.size() == upper_bounds.size());
345#endif
346
347 const uint64_t n = g.get_num_nodes();
348
349 std::vector<uint64_t> cs(arrs.size(), 0);
350 if (n < 4) { return cs; }
351
352 // boolean neighbourhood of nodes
353 array<unsigned char> boolean_neighborhood(n, 0);
354 // array L1 (same as in the pseudocode) ( size n )
355 array<uint64_t> L1(n, 0);
356
357 /* compute C for every linear arrangement */
358 for (std::size_t i = 0; i < arrs.size(); ++i) {
359#if defined DEBUG
360 // ensure that no linear arrangement is empty
361 assert(arrs[i].size() == n);
362#endif
363
364 // compute C
365 boolean_neighborhood.fill(0);
366
368 (g, nonidentity_arr(arrs[i]),
369 boolean_neighborhood.begin(), L1.begin(), upper_bounds[i]);
370
371 for (uint64_t z = 0; z < n; ++z) {
372 L1[z] = 0;
373 boolean_neighborhood[z] = 0;
374 }
375 L1[n - 1] = 0;
376 }
377
378 return cs;
379}
380
381} // -- namespace crossings
382} // -- namespace detail
383} // -- namespace lal
uint64_t compute(const graph_t &g, const arrangement_t &arr, unsigned char *const __restrict__ bn, uint64_t *const __restrict__ L1, const uint64_t upper_bound) noexcept
Ladder computation of for undirected graphs.
Definition ladder.hpp:90
uint64_t is_n_C_ladder_lesseq_than(const graph_t &g, const arrangement_t &arr, const uint64_t upper_bound) noexcept
Ladder computation of with early termination.
Definition ladder.hpp:245
uint64_t n_C_ladder(const graph_t &g, const arrangement_t &arr) noexcept
Ladder computation of .
Definition ladder.hpp:164
void get_bool_neighbors(const graph_t &g, const node u, char_type *const neighs) noexcept
Retrieves the neighbors of a node in an undirected graph as a list of 0-1 values.
Definition utils.hpp:73
arrangement_wrapper< arrangement_type::nonidentity > nonidentity_arr(const linear_arrangement &arr) noexcept
Shorthand for a nonidentity arrangement.
Definition arrangement_wrapper.hpp:133
Main namespace of the library.
Definition basic_types.hpp:48
uint64_t position
Node's position type.
Definition basic_types.hpp:53
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
void fill(const T &v) noexcept
Assign the same value to every element in the data.
Definition array.hpp:272
T * begin() noexcept
Non-constant raw pointer to first element.
Definition array.hpp:300
Typesafe position type.
Definition basic_types.hpp:244