49#include <lal/graphs/directed_graph.hpp>
50#include <lal/graphs/undirected_graph.hpp>
51#include <lal/detail/identity_arrangement.hpp>
52#include <lal/detail/graphs/utils.hpp>
53#include <lal/detail/data_array.hpp>
55#define idx(i,j, C) ((i)*(C) + (j))
56#define DECIDED_C_GT (upper_bound + 1)
93template <
bool dec
ide_upper_bound,
class graph_t, linarr_type arr_type>
97 unsigned char *
const __restrict__ bn,
98 uint64_t *
const __restrict__ M,
99 uint64_t *
const __restrict__ K,
104 const uint64_t n = g.get_num_nodes();
105 std::fill(bn, &bn[n], 0);
106 std::fill(K, &K[(n - 3)*(n - 3)], 0);
113 for (
position_t pu = 0ull; pu < n - 3; ++pu) {
115 const node u = arr[pu + 1ull];
117 detail::get_bool_neighbours<graph_t>(g, u, bn);
119 uint64_t k = g.get_degree(u);
124 k -= bn[u0] + bn[u1];
133 const node ui = arr[i - 1ull];
141 M[ idx(*pu, *i - 3, n-3) ] = k;
152 K[idx(n-4,n-4, n-3)] = M[idx(n-4,n-4, n-3)];
155 uint64_t * __restrict__ next_k_it;
157 uint64_t * __restrict__ m_it;
159 uint64_t * __restrict__ k_it;
161 for (uint64_t ii = 1; ii < n - 3; ++ii) {
162 const uint64_t i = n - 3 - ii - 1;
165 m_it = &M[ idx(i,i, n-3) ];
170 k_it = &K[ idx(i,i, n-3) ];
173 next_k_it = k_it + n - 3;
175 for (uint64_t j = i; j < n - 3; ++j) {
178 *k_it++ = *m_it++ + *next_k_it++;
186 const auto process_neighbours =
200 if (pu < pv and 2 <= pv and pv < n - 1) {
201 C += K[idx(pu,pv-2, n-3)];
205 for (
position pu = 0; pu < n - 3; ++pu) {
208 if constexpr (std::is_base_of_v<graphs::directed_graph, graph_t>) {
211 process_neighbours(pu, v);
212 if constexpr (decide_upper_bound) {
213 if (C > upper_bound) {
return DECIDED_C_GT; }
218 process_neighbours(pu, v);
219 if constexpr (decide_upper_bound) {
220 if (C > upper_bound) {
return DECIDED_C_GT; }
227 process_neighbours(pu, v);
228 if constexpr (decide_upper_bound) {
229 if (C > upper_bound) {
return DECIDED_C_GT; }
257template <
class graph_t,
class arrangement_t>
259(
const graph_t& g,
const arrangement_t& arr)
262 const uint64_t n = g.get_num_nodes();
265 assert(arr.m_arr.size() == 0 or arr.m_arr.size() == n);
268 if (n < 4) {
return 0; }
273 const std::size_t n_elems = 2*(n - 3)*(n - 3);
277 uint64_t *
const __restrict__ M = &all_memory[0];
279 uint64_t *
const __restrict__ K = &all_memory[0 + (n - 3)*(n - 3)];
281 return dyn_prog::compute<false>(g, arr, bool_neighs.
begin(), M,K, 0);
294template <
class graph_t>
296(
const graph_t& g,
const std::vector<linear_arrangement>& arrs)
299 const uint64_t n = g.get_num_nodes();
301 std::vector<uint64_t> cs(arrs.size(), 0);
302 if (n < 4) {
return cs; }
305 const std::size_t n_elems = 2*(n - 3)*(n - 3);
309 uint64_t *
const __restrict__ M = &all_memory[0];
311 uint64_t *
const __restrict__ K = &all_memory[0 + (n - 3)*(n - 3)];
317 for (std::size_t i = 0; i < arrs.size(); ++i) {
320 assert(arrs[i].size() == n);
324 cs[i] = dyn_prog::compute<false>
350template <
class graph_t,
class arrangement_t>
353 const arrangement_t& arr,
358 const uint64_t n = g.get_num_nodes();
361 assert(arr.m_arr.size() == 0 or arr.m_arr.size() == n);
367 const std::size_t n_elems = 2*(n - 3)*(n - 3);
371 uint64_t *
const __restrict__ M = &all_memory[0];
373 uint64_t *
const __restrict__ K = &all_memory[0 + (n - 3)*(n - 3)];
375 return dyn_prog::compute<true>(g, arr, bool_neighs.
begin(), M,K, upper_bound);
390template <
class graph_t>
393 const std::vector<linear_arrangement>& arrs,
398 const uint64_t n = g.get_num_nodes();
400 std::vector<uint64_t> cs(arrs.size(), 0);
401 if (n < 4) {
return cs; }
404 const std::size_t n_elems = 2*(n - 3)*(n - 3);
408 uint64_t *
const __restrict__ M = &all_memory[0];
410 uint64_t *
const __restrict__ K = &all_memory[0 + (n - 3)*(n - 3)];
416 for (std::size_t i = 0; i < arrs.size(); ++i) {
419 assert(arrs[i].size() == n);
423 cs[i] = dyn_prog::compute<true>
444template <
class graph_t>
447 const std::vector<linear_arrangement>& arrs,
448 const std::vector<uint64_t>& upper_bounds
454 assert(arrs.size() == upper_bounds.size());
457 const uint64_t n = g.get_num_nodes();
459 std::vector<uint64_t> cs(arrs.size(), 0);
460 if (n < 4) {
return cs; }
463 const std::size_t n_elems = 2*(n - 3)*(n - 3);
467 uint64_t *
const __restrict__ M = &all_memory[0];
469 uint64_t *
const __restrict__ K = &all_memory[0 + (n - 3)*(n - 3)];
475 for (std::size_t i = 0; i < arrs.size(); ++i) {
478 assert(arrs[i].size() == n);
482 cs[i] = dyn_prog::compute<true>
uint64_t compute(const graph_t &g, const linarr_wrapper< arr_type > &arr, unsigned char *const __restrict__ bn, uint64_t *const __restrict__ M, uint64_t *const __restrict__ K, uint64_t upper_bound) noexcept
Dynamic programming computation of for undirected graphs.
Definition: C_dyn_prog.hpp:95
uint64_t n_C_dynamic_programming(const graph_t &g, const arrangement_t &arr) noexcept
Dynamic programming computation of .
Definition: C_dyn_prog.hpp:259
uint64_t is_n_C_dynamic_programming_lesseq_than(const graph_t &g, const arrangement_t &arr, uint64_t upper_bound) noexcept
Dynamic programming computation of .
Definition: C_dyn_prog.hpp:351
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
std::vector< node > neighbourhood
List of nodes.
Definition: basic_types.hpp:62
Wrapper of a C array for autmatic deallocation of memory.
Definition: data_array.hpp:59
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 node type.
Definition: basic_types.hpp:67
Typesafe position type.
Definition: basic_types.hpp:168