LAL: Linear Arrangement Library 24.10.00
A library focused on algorithms on linear arrangements of graphs.
Loading...
Searching...
No Matches
rooted_tree.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#include <optional>
49#include <vector>
50
51// lal includes
52#include <lal/linear_arrangement.hpp>
53#include <lal/graphs/directed_graph.hpp>
54#include <lal/graphs/tree.hpp>
55#include <lal/graphs/free_tree.hpp>
56
57namespace lal {
58namespace graphs {
59
109class rooted_tree : public directed_graph, virtual public tree {
110public:
111 /* CONSTRUCTORS */
112
114 rooted_tree() noexcept : tree(), directed_graph() { }
119 rooted_tree(const uint64_t n) noexcept {
121 }
122
128 rooted_tree(const directed_graph& t) noexcept;
129
136
141 rooted_tree(const rooted_tree& r) noexcept : graph(), tree(), directed_graph() {
143 }
144
149 rooted_tree(rooted_tree&& r) noexcept {
150 move_full_rooted_tree(std::forward<rooted_tree>(r));
151 }
152
165 (
166 const free_tree& t,
167 const node r,
168 const bool norm = true,
169 const bool check_norm = true
170 )
171 noexcept
172 {
173 init_rooted(t, r, norm, check_norm);
174 }
175
189 (
190 free_tree&& t,
191 const node r,
192 const bool norm = true,
193 const bool check_norm = true
194 )
195 noexcept
196 {
197 init_rooted(std::forward<free_tree>(t), r, norm, check_norm);
198 }
199
201 ~rooted_tree() noexcept { }
202
203 /* OPERATORS */
204
209 rooted_tree& operator= (const rooted_tree& r) noexcept {
211 return *this;
212 }
218 move_full_rooted_tree(std::forward<rooted_tree>(r));
219 return *this;
220 }
221
222 /* MODIFIERS */
223
244 (
245 const free_tree& t,
246 const node r,
247 const bool norm = true,
248 const bool check_norm = true
249 )
250 noexcept;
251
272 (
273 free_tree&& t,
274 const node r,
275 const bool norm = true,
276 const bool check_norm = true
277 )
278 noexcept;
279
280 rooted_tree& add_node() noexcept {
283 m_size_subtrees.push_back(1);
285 return *this;
286 }
287
305 (
306 const node u,
307 const bool connect = false,
308 const bool norm = true,
309 const bool check_norm = true
310 )
311 noexcept;
312
335 (
336 const node s,
337 const node t,
338 const bool norm = true,
339 const bool check_norm = true
340 )
341 noexcept;
342
355 rooted_tree& add_edge_bulk(const node s, const node t) noexcept;
356
365 void finish_bulk_add(const bool norm = true, const bool check = true) noexcept;
366
367 void finish_bulk_add_complete(const bool norm = true, const bool check = true) noexcept;
368
390 (
391 const std::vector<edge>& edges,
392 const bool norm = true,
393 const bool check_norm = true
394 )
395 noexcept;
396
430 (
431 const std::vector<edge>& edges,
432 const bool norm = true,
433 const bool check_norm = true
434 )
435 noexcept;
436
454 (
455 const node s,
456 const node t,
457 const bool norm = false,
458 const bool check_norm = true
459 )
460 noexcept;
461
474 rooted_tree& remove_edge_bulk(const node s, const node t) noexcept;
475
484 void finish_bulk_remove(const bool norm = true, const bool check = true) noexcept;
485
486 void finish_bulk_remove_complete(const bool norm = true, const bool check = true) noexcept;
487
506 (
507 const std::vector<edge>& edges,
508 const bool norm = true,
509 const bool check_norm = true
510 )
511 noexcept;
512
529 (
530 const node u,
531 const bool norm = true,
532 const bool check_norm = true
533 )
534 noexcept;
535
560 rooted_tree& disjoint_union(const rooted_tree& t, const bool connect_roots = true)
561 noexcept;
562
569 void calculate_size_subtrees() noexcept;
570
571 void calculate_tree_type() noexcept;
572
573 /* SETTERS */
574
586 void set_root(const node r) noexcept {
587 // if the tree is empty simply consider it has a root...
588 // although it really doesn't
589
590 if (get_num_nodes() > 0) {
591#if defined DEBUG
592 assert(has_node(r));
593 assert(is_root_valid(r));
594#endif
595 m_root = r;
596 }
599 }
600
601 /* GETTERS */
602
611 [[nodiscard]] bool is_root_valid(const node r) const noexcept {
612#if defined DEBUG
613 assert(has_node(r));
614#endif
615 return get_in_degree(r) == 0;
616 }
617
618 [[nodiscard]] bool can_add_edge(const node s, const node t) const noexcept;
619
620 [[nodiscard]] bool can_add_edges(const std::vector<edge>& edges) const noexcept;
621
622 [[nodiscard]] bool is_rooted() const noexcept { return true; }
623
634 [[nodiscard]] bool is_rooted_tree() const noexcept { return is_tree() and has_root(); }
635
637 [[nodiscard]] node get_root() const noexcept {
638#if defined DEBUG
639 assert(has_root());
640#endif
641 return *m_root;
642 }
645 [[nodiscard]] bool has_root() const noexcept { return m_root.has_value(); }
646
653 [[nodiscard]] uint64_t get_num_nodes_subtree(const node u) const noexcept {
654#if defined DEBUG
655 assert(has_node(u));
656 assert(are_size_subtrees_valid());
657#endif
658 return m_size_subtrees[u];
659 }
660
671 [[nodiscard]] bool are_size_subtrees_valid() const noexcept
672 { return m_are_size_subtrees_valid; }
673
704 [[nodiscard]] std::vector<edge> get_edges_subtree(const node u, const bool relab = false)
705 const noexcept;
706
714 [[nodiscard]] rooted_tree get_subtree(const node u) const noexcept;
715
722 (const bool norm = true, const bool check = true)
723 const noexcept;
724
734 [[nodiscard]] head_vector get_head_vector(const linear_arrangement& arr = {})
735 const noexcept;
736
747 [[nodiscard]] bool subtree_contains_node(const node r, const node u) const noexcept;
748
757 [[nodiscard]] bool are_nodes_siblings(const node u, const node v) const noexcept {
758 // if one of the in-degrees is zero, then 'u' and 'v' cannot be siblings
759 if (get_in_degree(u) == 0 or get_in_degree(v) == 0) {
760 return false;
761 }
762 // two nodes are siblings when their respective parent vertices
763 // are the same
764 return get_in_neighbors(u)[0] == get_in_neighbors(v)[0];
765 }
766
772 [[nodiscard]] bool node_has_parent(const node u) const noexcept {
773 return get_in_degree(u) > 0;
774 }
775
782 [[nodiscard]] node get_parent_node(const node u) const noexcept {
783#if defined DEBUG
784 assert(node_has_parent(u));
785#endif
786 return get_in_neighbors(u)[0];
787 }
788
789protected:
791 std::optional<node> m_root;
792
799 std::vector<uint64_t> m_size_subtrees;
802
803protected:
812 void _init(const uint64_t n) noexcept {
815 m_size_subtrees.resize(n);
817 if (n <= 1) {
818 set_root(0);
819 }
820 }
827 void _clear() noexcept {
830 m_size_subtrees.clear();
832 }
833
834 void actions_after_add_edge(const node u, const node v) noexcept;
835
836 void actions_after_add_edges(const edge_list& e) noexcept;
837
839
840 void actions_after_remove_edge(const node u, const node v) noexcept;
841
842 void actions_after_remove_edges(const edge_list& e) noexcept;
843
845
847
848 void actions_after_remove_node(const node u) noexcept;
849
851 (
852 const node u,
853 const node v,
854 uint64_t * const root_of,
855 uint64_t * const root_size
856 )
857 const noexcept;
858
860 (
861 const edge_list& edges,
862 uint64_t * const root_of,
863 uint64_t * const root_size
864 )
865 const noexcept;
866
868 (
869 uint64_t * const root_of,
870 uint64_t * const root_size
871 )
872 const noexcept;
873
875 (
876 const node u,
877 const node v,
878 uint64_t * const root_of,
879 uint64_t * const root_size
880 )
881 const noexcept;
882
884 (
885 const edge_list& edges,
886 uint64_t * const root_of,
887 uint64_t * const root_size
888 )
889 const noexcept;
890
892 (
893 uint64_t * const root_of,
894 uint64_t * const root_size
895 )
896 const noexcept;
897
899 const node u,
900 uint64_t * const root_of,
901 uint64_t * const root_size
902 )
903 const noexcept;
904
906 void copy_full_rooted_tree(const rooted_tree& r) noexcept {
907 // copy directed_graph class
909
910 // copy only tree's members
912
913 // copy this class' members
914 m_root = r.m_root;
915 m_size_subtrees = r.m_size_subtrees;
916 m_are_size_subtrees_valid = r.m_are_size_subtrees_valid;
917 }
920 // move-assign directed_graph class
921 move_full_directed_graph(std::forward<rooted_tree>(r));
922
923 // move-assign only tree's members
924 tree_only_move(std::forward<tree>(r));
925
926 // move this class' members
927 m_root.swap(r.m_root);
928 m_size_subtrees = std::move(r.m_size_subtrees);
929 m_are_size_subtrees_valid = r.m_are_size_subtrees_valid;
930
931 r.m_root.reset(); // old tree cannot have a root anymore.. it's been moved!
932 r.m_are_size_subtrees_valid = false;
933 }
934
935private:
938};
939
940} // -- namespace graphs
941} // -- namespace lal
Directed graph class.
Definition directed_graph.hpp:67
void move_full_directed_graph(directed_graph &&d) noexcept
Moves all members of this class and the parent class.
Definition directed_graph.hpp:505
directed_graph() noexcept
Empty constructor.
Definition directed_graph.hpp:72
void copy_full_directed_graph(const directed_graph &d) noexcept
Copies all members of this class and the parent class.
Definition directed_graph.hpp:497
virtual void _init(const uint64_t n) noexcept
Initializes the memory in the graph hierarchy.
Definition directed_graph.hpp:470
virtual void _clear() noexcept
Clears the memory of directed_graph and graph classes.
Definition directed_graph.hpp:475
const neighbourhood & get_in_neighbors(const node u) const noexcept
Returns the in-neighbors of node u.
Definition directed_graph.hpp:401
virtual directed_graph & add_node() noexcept
Adds a node to the graph.
Definition directed_graph.hpp:154
uint64_t get_in_degree(const node u) const noexcept
Returns the in-degree of a node.
Definition directed_graph.hpp:427
virtual directed_graph & remove_node(const node u, const bool norm=true, const bool check_norm=true) noexcept
Remove a node from this graph.
directed_graph & disjoint_union(const directed_graph &g) noexcept
Disjoint union of graphs.
Free tree graph class.
Definition free_tree.hpp:60
uint64_t get_num_nodes() const noexcept
Returns the number of ndoes.
Definition graph.hpp:207
graph() noexcept
Empty constructor.
Definition graph.hpp:73
bool has_node(const node u) const noexcept
Returns true if node u is in this graph.
Definition graph.hpp:201
Rooted tree graph class.
Definition rooted_tree.hpp:109
void finish_bulk_add(const bool norm=true, const bool check=true) noexcept
Finishes adding edges in bulk.
rooted_tree(rooted_tree &&r) noexcept
Move constructor.
Definition rooted_tree.hpp:149
void actions_before_remove_edges_incident_to(const node u) noexcept
Do some work before all edges incident to a node is removed.
free_tree to_free_tree(const bool norm=true, const bool check=true) const noexcept
Converts this rooted tree into a free tree (see free_tree).
void copy_full_rooted_tree(const rooted_tree &r) noexcept
Copies all members of this class and the parent classes.
Definition rooted_tree.hpp:906
void _clear() noexcept
Clears the memory in the graph hierarchy.
Definition rooted_tree.hpp:827
void actions_after_add_edge(const node u, const node v) noexcept
Do some extra work after the addition of an edge.
void actions_after_add_edges_bulk() noexcept
Do some extra work after the addition of several edges in bulk.
void actions_after_remove_node(const node u) noexcept
Do some work before the removal of a vertex.
bool can_add_edge(const node s, const node t) const noexcept
Can this edge be added?
rooted_tree & add_node() noexcept
Adds a node to the graph.
Definition rooted_tree.hpp:280
void set_root(const node r) noexcept
Set the root of this tree.
Definition rooted_tree.hpp:586
rooted_tree & remove_edge_bulk(const node s, const node t) noexcept
Removes an edge from the tree.
head_vector get_head_vector(const linear_arrangement &arr={}) const noexcept
Converts a rooted tree into a head vector.
std::optional< node > m_root
Root of the tree.
Definition rooted_tree.hpp:791
rooted_tree & operator=(const rooted_tree &r) noexcept
Copy assignment operator.
Definition rooted_tree.hpp:209
rooted_tree & remove_edges(const std::vector< edge > &edges, const bool norm=true, const bool check_norm=true) noexcept
Remove an edge from this graph.
~rooted_tree() noexcept
Destructor.
Definition rooted_tree.hpp:201
void actions_after_add_edges(const edge_list &e) noexcept
Do some extra work after the addition of several edges.
void update_union_find_after_add_edges_bulk(uint64_t *const root_of, uint64_t *const root_size) const noexcept
Update the union find data structure after the addition of several edges.
rooted_tree & add_edges(const std::vector< edge > &edges, const bool norm=true, const bool check_norm=true) noexcept
Adds a list of edges to the graph.
rooted_tree & add_edge(const node s, const node t, const bool norm=true, const bool check_norm=true) noexcept
Adds an edge to the tree.
void calculate_size_subtrees() noexcept
Calculates the number of nodes at every rooted subtree.
void finish_bulk_add_complete(const bool norm=true, const bool check=true) noexcept
Completes the inner structure of the tree after adding edges in bulk.
void actions_after_remove_edges_bulk() noexcept
Do some extra work after the removal of several edges in bulk.
void finish_bulk_remove_complete(const bool norm=true, const bool check=true) noexcept
Completes the inner structure of the tree after removing edges in bulk.
bool is_root_valid(const node r) const noexcept
Is the root valid?
Definition rooted_tree.hpp:611
void update_union_find_after_add_edges(const edge_list &edges, uint64_t *const root_of, uint64_t *const root_size) const noexcept
Update the union find data structure after the addition of a set of edges.
rooted_tree & add_edge_bulk(const node s, const node t) noexcept
Adds an edge to the graph.
void actions_after_remove_edge(const node u, const node v) noexcept
Do some extra work after the removal of an edge.
void update_union_find_before_remove_incident_edges_to(const node u, uint64_t *const root_of, uint64_t *const root_size) const noexcept
Update the union find data structure before the removal of all edges incident to a node.
std::vector< uint64_t > m_size_subtrees
Number of nodes of the subtrees rooted at a certain node.
Definition rooted_tree.hpp:799
void actions_after_remove_edges(const edge_list &e) noexcept
Do some extra work after the removal of several edges.
rooted_tree & remove_edges_incident_to(const node u, const bool norm=true, const bool check_norm=true) noexcept
Remove all edges incident to a given vertex.
bool are_nodes_siblings(const node u, const node v) const noexcept
Are two nodes siblings?
Definition rooted_tree.hpp:757
rooted_tree(free_tree &&t, const node r, const bool norm=true, const bool check_norm=true) noexcept
Constructor with tree and root node.
Definition rooted_tree.hpp:189
bool has_root() const noexcept
Definition rooted_tree.hpp:645
node get_root() const noexcept
Return the root of this tree.
Definition rooted_tree.hpp:637
std::vector< edge > get_edges_subtree(const node u, const bool relab=false) const noexcept
Retrieve the edges of the subtree rooted at u.
bool is_rooted() const noexcept
Returns whether this tree is a rooted tree.
Definition rooted_tree.hpp:622
rooted_tree(const directed_graph &t) noexcept
Copy constructor with directed graph.
rooted_tree(const rooted_tree &r) noexcept
Copy constructor.
Definition rooted_tree.hpp:141
void finish_bulk_remove(const bool norm=true, const bool check=true) noexcept
Finishes removing edges in bulk.
void calculate_tree_type() noexcept
Calculates the type of tree.
bool subtree_contains_node(const node r, const node u) const noexcept
Does the subtree rooted at r contain node u?
rooted_tree(const free_tree &t, const node r, const bool norm=true, const bool check_norm=true) noexcept
Constructor with free tree and root node.
Definition rooted_tree.hpp:165
void update_union_find_after_add_edge(const node u, const node v, uint64_t *const root_of, uint64_t *const root_size) const noexcept
Update the union find data structure after an edge addition.
void update_union_find_after_remove_edge(const node u, const node v, uint64_t *const root_of, uint64_t *const root_size) const noexcept
Update the union find data structure after an edge removal.
rooted_tree() noexcept
Empty constructor.
Definition rooted_tree.hpp:114
rooted_tree & remove_node(const node u, const bool connect=false, const bool norm=true, const bool check_norm=true) noexcept
Remove a node from this tree.
rooted_tree & remove_edge(const node s, const node t, const bool norm=false, const bool check_norm=true) noexcept
Remove an edge from this graph.
rooted_tree(directed_graph &&t) noexcept
Move constructor with directed graph.
void update_union_find_after_remove_edges_bulk(uint64_t *const root_of, uint64_t *const root_size) const noexcept
Update the union find data structure after the removal of several edges.
bool can_add_edges(const std::vector< edge > &edges) const noexcept
Can these edges be added?
void init_rooted(const free_tree &t, const node r, const bool norm=true, const bool check_norm=true) noexcept
Initializer with tree and root node.
void move_full_rooted_tree(rooted_tree &&r) noexcept
Moves all members of this class and the parent classes.
Definition rooted_tree.hpp:919
node get_parent_node(const node u) const noexcept
Parent vertex of a node.
Definition rooted_tree.hpp:782
rooted_tree & disjoint_union(const rooted_tree &t, const bool connect_roots=true) noexcept
Disjoint union of trees.
void _init(const uint64_t n) noexcept
Initializes the memory in the graph hierarchy.
Definition rooted_tree.hpp:812
uint64_t get_num_nodes_subtree(const node u) const noexcept
Get the size of a subtree rooted at a given node.
Definition rooted_tree.hpp:653
bool are_size_subtrees_valid() const noexcept
Is a recalculation of the subtree's sizes needed?
Definition rooted_tree.hpp:671
bool node_has_parent(const node u) const noexcept
Does a node have a parent vertex?
Definition rooted_tree.hpp:772
rooted_tree get_subtree(const node u) const noexcept
Retrieve the subtree rooted at node u.
rooted_tree & set_edges(const std::vector< edge > &edges, const bool norm=true, const bool check_norm=true) noexcept
Sets the edges to the graph.
bool is_rooted_tree() const noexcept
Is this tree a valid rooted tree?
Definition rooted_tree.hpp:634
rooted_tree(const uint64_t n) noexcept
Constructor with number of nodes and root node.
Definition rooted_tree.hpp:119
void update_union_find_after_remove_edges(const edge_list &edges, uint64_t *const root_of, uint64_t *const root_size) const noexcept
Update the union find data structure after the removal of a set of edges.
bool m_are_size_subtrees_valid
Are the contents of m_size_subtrees valid?
Definition rooted_tree.hpp:801
Tree graph class.
Definition tree.hpp:73
bool is_tree() const noexcept
Is this graph an actual tree?
Definition tree.hpp:177
tree() noexcept
Empty constructor.
Definition tree.hpp:78
void tree_only_invalidate() noexcept
Invalidates the aggregated information of the tree.
Definition tree.hpp:395
void tree_only_copy(const tree &t) noexcept
Copies only members of class tree.
Definition tree.hpp:359
void tree_only_move(tree &&t) noexcept
Moves only members of class tree.
Definition tree.hpp:367
void tree_only_add_node() noexcept
Adds a node to this tree.
Definition tree.hpp:382
void tree_only_init(const uint64_t n) noexcept
Initializes only the memory of class tree.
Definition tree.hpp:340
void tree_only_clear() noexcept
Clears the memory used by only class tree.
Definition tree.hpp:351
Linear arrangement of vertices.
Definition linear_arrangement.hpp:103
Main namespace of the library.
Definition basic_types.hpp:48
std::vector< uint64_t > head_vector
See Head vector page for further details.
Definition basic_types.hpp:58
std::pair< node, node > edge
See Edge page for further details.
Definition basic_types.hpp:56
std::vector< edge > edge_list
See Edge list page for further details.
Definition basic_types.hpp:60
uint64_t node
Node type. See Node / Vertex page for further details.
Definition basic_types.hpp:51