LAL: Linear Arrangement Library 23.01.00
A library focused on algorithms on linear arrangements of graphs.
Loading...
Searching...
No Matches
C_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 - 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// 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/identity_arrangement.hpp>
51#include <lal/detail/graphs/utils.hpp>
52#include <lal/detail/data_array.hpp>
53
54#define DECIDED_C_GT (upper_bound + 1)
55#define DECIDED_C_LE C
56
57namespace lal {
58namespace detail {
59namespace crossings {
60
66namespace ladder {
67
68// =============================================================================
69// ACTUAL ALGORITHM
70// =============================================================================
71
89template <bool decide_upper_bound, class graph_t, linarr_type arr_type>
90uint64_t compute(
91 const graph_t& g,
92 const linarr_wrapper<arr_type>& arr,
93 unsigned char * const __restrict__ bn,
94 uint64_t * const __restrict__ L1,
95 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 // neighbours of node u, as a list of Boolean values.
113 detail::get_bool_neighbours<graph_t>(g, u, bn);
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>
163uint64_t n_C_ladder(const graph_t& g, const arrangement_t& arr)
164noexcept
165{
166 const uint64_t n = g.get_num_nodes();
167
168#if defined DEBUG
169 assert(arr.m_arr.size() == 0 or arr.m_arr.size() == n);
170#endif
171
172 if (n < 4) { return 0; }
173
174 // boolean neighbourhood of nodes
175 data_array<unsigned char> boolean_neighborhood(n, 0);
176 // array L1 (same as in the pseudocode) ( size n )
177 data_array<uint64_t> L1(n, 0);
178
179 return ladder::compute<false>
180 (g, arr, boolean_neighborhood.begin(), L1.begin(), 0);
181}
182
183// --------------------
184// list of arrangements
185
193template <class graph_t>
194std::vector<uint64_t> n_C_ladder
195(const graph_t& g, const std::vector<linear_arrangement>& arrs)
196noexcept
197{
198 const uint64_t n = g.get_num_nodes();
199
200 std::vector<uint64_t> cs(arrs.size(), 0);
201 if (n < 4) { return cs; }
202
203 // boolean neighbourhood of nodes
204 data_array<unsigned char> boolean_neighborhood(n, 0);
205 // array L1 (same as in the pseudocode) ( size n )
206 data_array<uint64_t> L1(n, 0);
207
208 /* compute C for every linear arrangement */
209 for (std::size_t i = 0; i < arrs.size(); ++i) {
210#if defined DEBUG
211 // ensure that no linear arrangement is empty
212 assert(arrs[i].size() == n);
213#endif
214
215 // compute C
216 cs[i] = ladder::compute<false>
217 (g, nonident_arr(arrs[i]), boolean_neighborhood.begin(), L1.begin(), 0);
218
219 boolean_neighborhood.fill(0);
220 L1[n - 1] = 0;
221 }
222
223 return cs;
224}
225
226// -----------------------------------------------------------------------------
227// DECISION
228
229// ------------------
230// single arrangement
231
242template <class graph_t, class arrangement_t>
244 const graph_t& g,
245 const arrangement_t& arr,
246 uint64_t upper_bound
247)
248noexcept
249{
250 const uint64_t n = g.get_num_nodes();
251
252#if defined DEBUG
253 assert(arr.m_arr.size() == 0 or arr.m_arr.size() == n);
254#endif
255
256 if (n < 4) { return 0; }
257
258 // boolean neighbourhood of nodes
259 data_array<unsigned char> boolean_neighborhood(n, 0);
260 // array L1 (same as in the pseudocode) ( size n )
261 data_array<uint64_t> L1(n, 0);
262
263 return
264 ladder::compute<true>
265 (g, arr, boolean_neighborhood.begin(), L1.begin(), upper_bound);
266}
267
268// --------------------
269// list of arrangements
270
280template <class graph_t>
281std::vector<uint64_t> is_n_C_ladder_lesseq_than(
282 const graph_t& g,
283 const std::vector<linear_arrangement>& arrs,
284 uint64_t upper_bound
285)
286noexcept
287{
288 const uint64_t n = g.get_num_nodes();
289
290 std::vector<uint64_t> cs(arrs.size(), 0);
291 if (n < 4) { return cs; }
292
293 // boolean neighbourhood of nodes
294 data_array<unsigned char> boolean_neighborhood(n, 0);
295 // array L1 (same as in the pseudocode) ( size n )
296 data_array<uint64_t> L1(n, 0);
297
298 /* compute C for every linear arrangement */
299 for (std::size_t i = 0; i < arrs.size(); ++i) {
300#if defined DEBUG
301 // ensure that no linear arrangement is empty
302 assert(arrs[i].size() == n);
303#endif
304
305 // compute C
306 cs[i] = ladder::compute<true>
307 (g, nonident_arr(arrs[i]),
308 boolean_neighborhood.begin(), L1.begin(), upper_bound);
309
310 for (uint64_t z = 0; z < n; ++z) {
311 L1[z] = 0;
312 boolean_neighborhood[z] = 0;
313 }
314 L1[n - 1] = 0;
315 }
316
317 return cs;
318}
319
330template <class graph_t>
331std::vector<uint64_t> is_n_C_ladder_lesseq_than(
332 const graph_t& g,
333 const std::vector<linear_arrangement>& arrs,
334 const std::vector<uint64_t>& upper_bounds
335)
336noexcept
337{
338#if defined DEBUG
339 // ensure that there are as many linear arrangements as upper bounds
340 assert(arrs.size() == upper_bounds.size());
341#endif
342
343 const uint64_t n = g.get_num_nodes();
344
345 std::vector<uint64_t> cs(arrs.size(), 0);
346 if (n < 4) { return cs; }
347
348 // boolean neighbourhood of nodes
349 data_array<unsigned char> boolean_neighborhood(n, 0);
350 // array L1 (same as in the pseudocode) ( size n )
351 data_array<uint64_t> L1(n, 0);
352
353 /* compute C for every linear arrangement */
354 for (std::size_t i = 0; i < arrs.size(); ++i) {
355#if defined DEBUG
356 // ensure that no linear arrangement is empty
357 assert(arrs[i].size() == n);
358#endif
359
360 // compute C
361 boolean_neighborhood.fill(0);
362
363 cs[i] = ladder::compute<true>
364 (g, nonident_arr(arrs[i]),
365 boolean_neighborhood.begin(), L1.begin(), upper_bounds[i]);
366
367 for (uint64_t z = 0; z < n; ++z) {
368 L1[z] = 0;
369 boolean_neighborhood[z] = 0;
370 }
371 L1[n - 1] = 0;
372 }
373
374 return cs;
375}
376
377} // -- namespace crossings
378} // -- namespace detail
379} // -- namespace lal
uint64_t compute(const graph_t &g, const linarr_wrapper< arr_type > &arr, unsigned char *const __restrict__ bn, uint64_t *const __restrict__ L1, uint64_t upper_bound) noexcept
Ladder computation of for undirected graphs.
Definition: C_ladder.hpp:90
uint64_t is_n_C_ladder_lesseq_than(const graph_t &g, const arrangement_t &arr, uint64_t upper_bound) noexcept
Ladder computation of with early termination.
Definition: C_ladder.hpp:243
uint64_t n_C_ladder(const graph_t &g, const arrangement_t &arr) noexcept
Ladder computation of .
Definition: C_ladder.hpp:163
linarr_wrapper< linarr_type::nonident > nonident_arr(const linear_arrangement &arr) noexcept
Shorthand for a nonidentity arrangement.
Definition: identity_arrangement.hpp:121
Main namespace of the library.
Definition: basic_types.hpp:50
uint64_t position
Node's position type.
Definition: basic_types.hpp:55
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
void fill(const T &v) noexcept
Assign the same value to every element in the data.
Definition: data_array.hpp:263
T * begin() noexcept
Non-constant raw pointer to first element.
Definition: data_array.hpp:291
A wrapper to easily use identity arrangements.
Definition: identity_arrangement.hpp:72
Typesafe position type.
Definition: basic_types.hpp:168