LAL: Linear Arrangement Library 24.10.00
A library focused on algorithms on linear arrangements of graphs.
Loading...
Searching...
No Matches
level_signature.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#pragma once
43
44// C++ includes
45#if defined DEBUG
46#include <cassert>
47#endif
48
49// lal includes
50#include <lal/iterators/E_iterator.hpp>
51#include <lal/linear_arrangement.hpp>
52#include <lal/properties/branchless_path.hpp>
53
54namespace lal {
55namespace detail {
56
72
89template <level_signature_type t>
91public:
93 level_signature() noexcept = default;
95 level_signature(const level_signature&) noexcept = default;
97 level_signature(level_signature&&) noexcept = default;
99 level_signature& operator=(const level_signature&) noexcept = default;
101 level_signature& operator=(level_signature&&) noexcept = default;
102
108 level_signature(const std::size_t n) noexcept : m_data(n, 0) { }
109
111 void init(const std::size_t n) noexcept {
112 m_data.resize(n, 0);
113 }
114
116 template <typename T>
117 [[nodiscard]] int64_t operator[] (const T i) const noexcept {
118 if constexpr (t == level_signature_type::per_position) {
119 static_assert(std::is_same_v<T, position_t>);
120 }
121 else {
122 static_assert(std::is_same_v<T, node_t>);
123 }
124 return m_data[*i];
125 }
127 template <typename T>
128 [[nodiscard]] int64_t& operator[] (const T i) noexcept {
129 if constexpr (t == level_signature_type::per_position) {
130 static_assert(std::is_same_v<T, position_t>);
131 }
132 else {
133 static_assert(std::is_same_v<T, node_t>);
134 }
135 return m_data[*i];
136 }
137
148 template <level_signature_type st = t>
149 [[nodiscard]] bool operator== (const level_signature<st>& L) const noexcept {
150 static_assert(st == t);
151 for (std::size_t i = 0; i < m_data.size(); ++i) {
152 if (m_data[i] != L.m_data[i]) { return false; }
153 }
154 return true;
155 }
156
165 template <
167 std::enable_if_t<st == level_signature_type::per_vertex, bool> = true
168 >
169 [[nodiscard]] int64_t get_vertex_level(const node u) const noexcept {
170 return m_data[u];
171 }
180 template <
182 std::enable_if_t<st == level_signature_type::per_vertex, bool> = true
183 >
184 void set_vertex_level(const node u, const int64_t l) noexcept {
185 m_data[u] = l;
186 }
187
196 template <
198 std::enable_if_t<st == level_signature_type::per_position, bool> = true
199 >
200 [[nodiscard]] int64_t get_position_level(const position p) const noexcept {
201 return m_data[p];
202 }
211 template <
213 std::enable_if_t<st == level_signature_type::per_position, bool> = true
214 >
215 void set_position_level(const position p, const int64_t l) noexcept {
216 m_data[p] = l;
217 }
218
225 void mirror() noexcept {
226 if constexpr (t == level_signature_type::per_position) {
227 const std::size_t n = m_data.size();
228 for (position p = 0ull; p < n/2; ++p) {
229 m_data[p] = -m_data[p];
230 m_data[n - 1ull - p] = -m_data[n - 1ull - p];
231 std::swap( m_data[p], m_data[n - 1ull - p] );
232 }
233 if (n%2 == 1) {
234 m_data[n/2] = -m_data[n/2];
235 }
236 }
237 else {
238 for (node u = 0ull; u < m_data.size(); ++u) {
239 m_data[u] = -m_data[u];
240 }
241 }
242 }
243
244private:
247};
248
250[[nodiscard]] inline constexpr bool is_per_vertex(const level_signature_type& t)
251noexcept
252{
254}
256[[nodiscard]] inline constexpr bool is_per_position(const level_signature_type& t)
257noexcept
258{
260}
261
266
277template <level_signature_type t, class graph_t>
278[[nodiscard]] bool is_thistle_vertex
279(
280 const graph_t& g,
281 const level_signature<t>& levels,
282 const node_t u,
283 const linear_arrangement& arr = {}
284)
285noexcept
286{
287 int64_t l;
288 if constexpr (t == level_signature_type::per_vertex) {
289 l = levels[u];
290 }
291 else {
292 l = (arr.size() == 0 ? levels[position_t{*u}] : levels[position_t{arr[u]}]);
293 }
294 return static_cast<uint64_t>( std::abs(l) ) != g.get_degree(*u);
295}
296
306template <level_signature_type t, class graph_t>
308(
309 const graph_t& g,
310 const linear_arrangement& arr,
312)
313noexcept
314{
316 while (not it.end()) {
317 const auto [u, v] = it.yield_edge_t();
318 const position_t pu = (arr.size() == 0 ? *u : arr[u]);
319 const position_t pv = (arr.size() == 0 ? *v : arr[v]);
320 if constexpr (t == level_signature_type::per_vertex) {
321 if (pu < pv) {
322 ++L[u];
323 --L[v];
324 }
325 else {
326 --L[u];
327 ++L[v];
328 }
329 }
330 else {
331 if (pu < pv) {
332 ++L[pu];
333 --L[pv];
334 }
335 else {
336 --L[pu];
337 ++L[pv];
338 }
339 }
340 }
341}
342
351template <level_signature_type t, class graph_t>
353(const graph_t& g, const linear_arrangement& arr)
354noexcept
355{
356 const auto n = g.get_num_nodes();
358 if constexpr (t == level_signature_type::per_vertex) {
359 for (node_t u = 0ull; u < n; ++u) { L[u] = 0; }
360 }
361 else {
362 for (position_t p = 0ull; p < n; ++p) { L[p] = 0; }
363 }
364
365 calculate_level_signature(g, arr, L);
366 return L;
367}
368
375template <class level_signature_t>
376[[nodiscard]] level_signature_t mirror_level_signature(const level_signature_t& L)
377noexcept
378{
379 level_signature_t L2 = L;
380 L2.mirror();
381 return L2;
382}
383
384} // -- namespace detail
385} // -- namespace lal
A class that implements level signatures of an array.
Definition level_signature.hpp:90
void set_position_level(const position p, const int64_t l) noexcept
Sets the level value of a position.
Definition level_signature.hpp:215
array< int64_t > m_data
The signature of level values.
Definition level_signature.hpp:246
int64_t get_position_level(const position p) const noexcept
Gets the level value of a position.
Definition level_signature.hpp:200
void init(const std::size_t n) noexcept
Initializes this level signature.
Definition level_signature.hpp:111
int64_t get_vertex_level(const node u) const noexcept
Gets the level value of a vertex.
Definition level_signature.hpp:169
int64_t operator[](const T i) const noexcept
Access position 'i'.
Definition level_signature.hpp:117
void mirror() noexcept
Mirrors this level signature.
Definition level_signature.hpp:225
bool operator==(const level_signature< st > &L) const noexcept
Equality test.
Definition level_signature.hpp:149
void set_vertex_level(const node u, const int64_t l) noexcept
Sets the level value of a vertex.
Definition level_signature.hpp:184
level_signature() noexcept=default
Default constructor.
Iterator over the set of edges of a graph.
Definition E_iterator.hpp:97
edge_t yield_edge_t() noexcept
Returns the current edge and advances the iterator.
Definition E_iterator.hpp:133
bool end() const noexcept
Returns true if the end of the iteration was reached.
Definition E_iterator.hpp:117
Linear arrangement of vertices.
Definition linear_arrangement.hpp:103
level_signature< level_signature_type::per_position > level_signature_per_position
A useful typedef for level signatures per position.
Definition level_signature.hpp:265
constexpr bool is_per_position(const level_signature_type &t) noexcept
Returns true if the template parameter is lal::detail::level_signature_type::per_position.
Definition level_signature.hpp:256
bool is_thistle_vertex(const graph_t &g, const level_signature< t > &levels, const node_t u, const linear_arrangement &arr={}) noexcept
Returns whether or not the input vertex is a thistle vertex.
Definition level_signature.hpp:279
level_signature_type
Types of level signature.
Definition level_signature.hpp:58
@ per_position
Given per position.
constexpr bool is_per_vertex(const level_signature_type &t) noexcept
Returns true if the template parameter is lal::detail::level_signature_type::per_vertex.
Definition level_signature.hpp:250
void calculate_level_signature(const graph_t &g, const linear_arrangement &arr, level_signature< t > &L) noexcept
Calculates the level signature of an arrangement of a graph.
Definition level_signature.hpp:308
level_signature_t mirror_level_signature(const level_signature_t &L) noexcept
Mirrors a level signature.
Definition level_signature.hpp:376
level_signature< level_signature_type::per_vertex > level_signature_per_vertex
A useful typedef for level signatures per vertex.
Definition level_signature.hpp:263
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
std::size_t size() const noexcept
Size of the array.
Definition array.hpp:215
void resize(const std::size_t new_size) noexcept
Resize the array.
Definition array.hpp:187
T * m_data
Pointer to the memory allocated by this array.
Definition array.hpp:318
Typesafe node type.
Definition basic_types.hpp:70
Typesafe position type.
Definition basic_types.hpp:244