libsemigroups  v3.5.2
C++ library for semigroups and monoids
Loading...
Searching...
No Matches
forest.hpp
1//
2// libsemigroups - C++ library for semigroups and monoids
3// Copyright (C) 2019-2026 Finn Smith + James Mitchell
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with this program. If not, see <http://www.gnu.org/licenses/>.
17//
18
19#ifndef LIBSEMIGROUPS_FOREST_HPP_
20#define LIBSEMIGROUPS_FOREST_HPP_
21
22#include <cstddef> // for size_t, ptrdiff_t
23#include <cstdint> // for uint32_t
24#include <initializer_list> // for initializer_list
25#include <iterator> // for forward_iterator_tag
26#include <string> // for string, basic_string
27#include <vector> // for vector, operator==
28
29#include "constants.hpp" // for UNDEFINED, operator!=, operator==
30#include "debug.hpp" // for LIBSEMIGROUPS_ASSERT
31#include "dot.hpp" // for Dot
32#include "exception.hpp" // for LIBSEMIGROUPS_EXCEPTION
33#include "types.hpp" // for word_type, enable_if_is_same
34
35#include "detail/fmt.hpp" // for formatter, string_view
36
37namespace libsemigroups {
46 class Forest {
47 std::vector<uint32_t> _edge_label;
49
50 public:
52 using node_type = uint32_t;
53
55 using label_type = uint32_t;
56
57 private:
59
60 public:
67 explicit Forest(size_t n = 0)
68 : _edge_label(n, static_cast<uint32_t>(UNDEFINED)),
69 _parent(n, static_cast<uint32_t>(UNDEFINED)) {}
70
82 Forest& init(size_t n = 0);
83
85 Forest(Forest const&) = default;
86
88 Forest(Forest&&) = default;
89
91 Forest& operator=(Forest const&) = default;
92
94 Forest& operator=(Forest&&) = default;
95
96 ~Forest();
97
106
115 [[nodiscard]] bool operator==(Forest const& that) const {
116 return _parent == that._parent && _edge_label == that._edge_label;
117 }
118
126 [[nodiscard]] bool operator!=(Forest const& that) const {
127 return !(*this == that);
128 }
129
145 Forest& add_nodes(size_t n);
146
160 [[nodiscard]] bool empty() const noexcept {
161 return _parent.empty();
162 }
163
187 label_type gen) {
188 LIBSEMIGROUPS_ASSERT(node < number_of_nodes() || node == UNDEFINED);
189 LIBSEMIGROUPS_ASSERT(parent < number_of_nodes() || parent == UNDEFINED);
190
191 _parent[node] = parent;
192 _edge_label[node] = gen;
193 return *this;
194 }
195
220 label_type gen);
221
234 [[nodiscard]] size_t number_of_nodes() const noexcept {
235 return _parent.size();
236 }
237
253 [[nodiscard]] node_type parent(node_type i) const {
255 return _parent[i];
256 }
257
273 // not noexcept because std::vector::operator[] isn't.
274 [[nodiscard]] node_type parent_no_checks(node_type i) const {
275 return _parent[i];
276 }
277
293 // not noexcept because std::vector::operator[] isn't.
294 [[nodiscard]] label_type label(node_type i) const {
296 return _edge_label[i];
297 }
298
314 [[nodiscard]] label_type label_no_checks(node_type i) const {
315 return _edge_label[i];
316 }
317
332 [[nodiscard]] std::vector<node_type> const& parents() const noexcept {
333 return _parent;
334 }
335
351 [[nodiscard]] std::vector<label_type> const& labels() const noexcept {
352 return _edge_label;
353 }
354
372 template <typename Iterator>
373 Iterator path_to_root_no_checks(Iterator d_first, node_type i) const;
374
393 template <typename Iterator>
394 Iterator path_to_root(Iterator d_first, node_type i) const {
397 return path_to_root_no_checks(d_first, i);
398 }
399
417 template <typename Iterator>
418 Iterator path_from_root_no_checks(Iterator d_first, node_type i) const;
419
440 template <typename Iterator>
441 Iterator path_from_root(Iterator d_first, node_type i) const {
444 return path_from_root_no_checks(d_first, i);
445 }
446
453
454 private:
455 class const_iterator_path {
456 private:
457 node_type _current_node;
458 Forest const* _forest;
459
460 public:
461 using iterator_category = std::forward_iterator_tag;
462 using value_type = label_type;
463 using difference_type = std::ptrdiff_t;
464 using pointer = label_type*;
465 using reference = label_type&;
466
467 const_iterator_path(Forest const* f, node_type n)
468 : _current_node(n), _forest(f) {}
469
470 const_iterator_path() = delete;
471
472 const_iterator_path(const_iterator_path const& that) = default;
473 const_iterator_path& operator=(const_iterator_path const& that) = default;
474 const_iterator_path(const_iterator_path&& that) noexcept = default;
475 const_iterator_path& operator=(const_iterator_path&& that) noexcept
476 = default;
477
478 ~const_iterator_path() = default;
479
480 [[nodiscard]] value_type operator*() const;
481
482 // pointer operator->() const {
483 // return TODO;
484 // }
485
486 // Pre-increment
487 const_iterator_path& operator++();
488
489 // Post-increment
490 const_iterator_path operator++(int) {
491 const_iterator_path tmp = *this;
492 ++(*this);
493 return tmp;
494 }
495
496 [[nodiscard]] bool operator==(const_iterator_path const& that) const;
497
498 [[nodiscard]] bool operator!=(const_iterator_path const& that) const {
499 return !(*this == that);
500 }
501 };
502
503 public:
522 [[nodiscard]] const_iterator_path
524 return const_iterator_path(this, n);
525 }
526
545 [[nodiscard]] const_iterator_path
547 (void) n;
548 return const_iterator_path(this, UNDEFINED);
549 }
550
565 [[nodiscard]] const_iterator_path cbegin_path_to_root(node_type n) const {
568 }
569
584 [[nodiscard]] const_iterator_path cend_path_to_root(node_type n) const {
587 }
588 }; // class Forest
589
600
623 template <typename Return>
626 std::vector<uint32_t> const& edge_labels);
627
651 template <typename Return>
655 return make<Forest>(std::vector<uint32_t>(parent),
656 std::vector(edge_labels));
657 }
658
670
676 namespace forest {
689 word_type& w,
691
706 word_type& w,
708
725
742
758
774
790 [[nodiscard]] word_type path_to_root(Forest const& f, Forest::node_type n);
791
807 [[nodiscard]] word_type path_from_root(Forest const& f,
809
822 [[nodiscard]] size_t depth_no_checks(Forest const& f, Forest::node_type n);
823
837 [[nodiscard]] inline size_t depth(Forest const& f, Forest::node_type n) {
839 return depth_no_checks(f, n);
840 }
841
854 [[nodiscard]] inline bool is_root_no_checks(Forest const& f,
856 return f.parent_no_checks(n) == UNDEFINED;
857 }
858
871 [[nodiscard]] inline bool is_root(Forest const& f, Forest::node_type n) {
873 return is_root_no_checks(f, n);
874 }
875
887 [[nodiscard]] Forest::label_type max_label(Forest const& f);
888
904 [[nodiscard]] bool is_forest(Forest const& f);
905
906 namespace detail {
911 public:
912#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
913 // We don't document these because we have to redeclare them in
914 // PathsFromRoots and PathsToRoots anyway.
915 using size_type = typename std::vector<word_type>::size_type;
916 using output_type = word_type const&;
917 using node_type = Forest::node_type;
918 static constexpr bool is_finite = true;
919 static constexpr bool is_idempotent = true;
920#endif
921
922 protected:
923 node_type _current_node;
924 word_type _current_path;
926 Forest const* _forest;
927 word_type _visited;
928
929 // Lazily compute depth of a node in the tree
930 size_type depth(node_type n);
931
932 public:
938
941
944
947 = default;
948
951
962 explicit PathsFromToRootsCommon(Forest const& f);
963
976
986 [[nodiscard]] node_type target() const noexcept {
987 return _current_node;
988 }
989
999 [[nodiscard]] output_type get() const noexcept {
1000 return _current_path;
1001 }
1002
1009 [[nodiscard]] bool at_end() const noexcept {
1010 return _forest->empty()
1011 || _current_node >= _forest->number_of_nodes();
1012 }
1013
1023 [[nodiscard]] size_type size_hint() const noexcept {
1024 if (at_end()) {
1025 return 0;
1026 }
1027 return _forest->number_of_nodes() - _current_node;
1028 }
1029
1035 [[nodiscard]] size_type count() const noexcept {
1036 return size_hint();
1037 }
1038
1048 [[nodiscard]] Forest const& forest() const noexcept {
1049 return *_forest;
1050 }
1051 }; // class PathsFromToRootsCommonRoots
1052 } // namespace detail
1053
1093 using detail::PathsFromToRootsCommon::depth;
1094
1095 public:
1098
1100 using output_type = word_type const&;
1101
1104
1106 static constexpr bool is_finite = true;
1107
1111 static constexpr bool is_idempotent = true;
1112
1121
1126 void next();
1127
1141
1175 // This can't go in the base class because the base class has no "next"
1176 // mem fn and so rx::begin/end don't compile.
1177 [[nodiscard]] auto begin() noexcept {
1178 return rx::begin(*this);
1179 }
1180
1198 // This can't go in the base class because the base class has no "next"
1199 // mem fn and so rx::begin/end don't compile.
1200 [[nodiscard]] auto end() noexcept {
1201 return rx::end(*this);
1202 }
1203 }; // class PathsFromRoots
1204
1244 using detail::PathsFromToRootsCommon::depth;
1245
1246 public:
1249
1251 using output_type = word_type const&;
1252
1255
1257 static constexpr bool is_finite = true;
1258
1262 static constexpr bool is_idempotent = true;
1263
1272
1277 void next();
1278
1292
1326 // This can't go in the base class because the base class has no "next"
1327 // mem fn and so rx::begin/end don't compile.
1328 [[nodiscard]] auto begin() noexcept {
1329 return rx::begin(*this);
1330 }
1331
1349 // This can't go in the base class because the base class has no "next"
1350 // mem fn and so rx::begin/end don't compile.
1351 [[nodiscard]] auto end() noexcept {
1352 return rx::end(*this);
1353 }
1354 }; // class PathsToRoots
1355
1364 [[nodiscard]] Dot dot(Forest const& f);
1365
1381 Dot dot(Forest const& f, std::vector<std::string> const& labels);
1382
1383 } // namespace forest
1384
1395 [[nodiscard]] std::string
1397 std::string const& sep = "::");
1398
1409 [[nodiscard]] std::string
1411 std::string const& sep = "::");
1412
1413} // namespace libsemigroups
1414
1415namespace fmt {
1416 template <>
1417 struct formatter<libsemigroups::Forest> : formatter<std::string> {
1438 template <typename FormatContext>
1439 auto format(libsemigroups::Forest const& f, FormatContext& ctx) const {
1440 return formatter<string_view>::format(
1441 fmt::format("{{{}, {}}}", f.parents(), f.labels()), ctx);
1442 }
1443 };
1444} // namespace fmt
1445
1446#include "forest.tpp"
1447
1448#endif // LIBSEMIGROUPS_FOREST_HPP_
A representation of a graph in the DOT language of Graphviz.
Definition dot.hpp:116
Class representing a collection of spanning trees of a word graph.
Definition forest.hpp:46
const_iterator_path cbegin_path_to_root_no_checks(node_type n) const noexcept
Returns a const iterator pointing at the first letter of a word from a given node to its root.
Definition forest.hpp:523
uint32_t node_type
Alias for the type of nodes in a forest.
Definition forest.hpp:52
Iterator path_to_root(Iterator d_first, node_type i) const
Store the labels of the edges on the path to a root node from a given node.
Definition forest.hpp:394
size_t number_of_nodes() const noexcept
Returns the number of nodes in the forest.
Definition forest.hpp:234
Forest & init(size_t n=0)
Reinitialize an existing Forest object.
bool empty() const noexcept
Check if there are any nodes in the forest.
Definition forest.hpp:160
node_type parent_no_checks(node_type i) const
Returns the parent of a node.
Definition forest.hpp:274
Forest(Forest const &)=default
Default copy constructor.
const_iterator_path cend_path_to_root_no_checks(node_type n) const noexcept
Returns a const iterator pointing one beyond the last letter in a word from a given node to its root.
Definition forest.hpp:546
Forest & operator=(Forest const &)=default
Default copy assignment constructor.
Iterator path_from_root(Iterator d_first, node_type i) const
Store the labels of the edges on the path from a root node to a given node.
Definition forest.hpp:441
bool operator==(Forest const &that) const
Compare Forest objects for equality.
Definition forest.hpp:115
std::vector< node_type > const & parents() const noexcept
Returns a const reference to the vector of parents.
Definition forest.hpp:332
Forest & operator=(Forest &&)=default
Default move assignment constructor.
node_type parent(node_type i) const
Returns the parent of a node.
Definition forest.hpp:253
const_iterator_path cend_path_to_root(node_type n) const
Returns a const iterator pointing one beyond the last letter in a word from a given node to its root.
Definition forest.hpp:584
std::string to_human_readable_repr(Forest const &f)
Return a human readable representation of a Forest object.
Forest(size_t n=0)
Constructs a forest with n nodes.
Definition forest.hpp:67
Forest & add_nodes(size_t n)
Add nodes to the Forest.
bool operator!=(Forest const &that) const
Compare Forest objects for inequality.
Definition forest.hpp:126
Iterator path_to_root_no_checks(Iterator d_first, node_type i) const
Store the labels of the edges on the path to a root node from a given node.
uint32_t label_type
Alias for the type of edge labels in a forest.
Definition forest.hpp:55
label_type label(node_type i) const
Returns the label of the edge from a node to its parent.
Definition forest.hpp:294
Forest & set_parent_and_label_no_checks(node_type node, node_type parent, label_type gen)
Set the parent and edge label for a node.
Definition forest.hpp:185
void throw_if_not_acyclic() const
Throw an exception if the Forest is not acyclic.
Definition forest.hpp:103
label_type label_no_checks(node_type i) const
Returns the label of the edge from a node to its parent.
Definition forest.hpp:314
std::vector< label_type > const & labels() const noexcept
Returns a const reference to the vector of edge labels.
Definition forest.hpp:351
Iterator path_from_root_no_checks(Iterator d_first, node_type i) const
Store the labels of the edges on the path from a root node to a given node.
void throw_if_node_out_of_bounds(node_type v) const
Throw an exception if a node is out of bound.
const_iterator_path cbegin_path_to_root(node_type n) const
Returns a const iterator pointing at the first letter of a word from a given node to its root.
Definition forest.hpp:565
Forest & set_parent_and_label(node_type node, node_type parent, label_type gen)
Set the parent and edge label for a node.
Forest(Forest &&)=default
Default move constructor.
Range for iterating through paths in a Forest.
Definition forest.hpp:1092
static constexpr bool is_finite
Value indicating that the range is finite.
Definition forest.hpp:1106
void next()
Advance to the next path in the range.
word_type const & output_type
The type of the output of a PathsFromRoots object.
Definition forest.hpp:1100
typename std::vector< word_type >::size_type size_type
Alias for the size type.
Definition forest.hpp:1097
auto begin() noexcept
Returns an input iterator pointing to the first word in the range.
Definition forest.hpp:1177
PathsFromRoots & skip_n(size_type n)
Skip a number of paths in the range.
Forest::node_type node_type
The type of nodes in the underlying Forest.
Definition forest.hpp:1103
auto end() noexcept
Returns an input iterator pointing one beyond the last word in the range.
Definition forest.hpp:1200
static constexpr bool is_idempotent
Definition forest.hpp:1111
Range for iterating through paths in a Forest.
Definition forest.hpp:1243
static constexpr bool is_finite
Value indicating that the range is finite.
Definition forest.hpp:1257
void next()
Advance to the next path in the range.
word_type const & output_type
The type of the output of a PathsToRoots object.
Definition forest.hpp:1251
typename std::vector< word_type >::size_type size_type
Alias for the size type.
Definition forest.hpp:1248
auto begin() noexcept
Returns an input iterator pointing to the first word in the range.
Definition forest.hpp:1328
PathsToRoots & skip_n(size_type n)
Skip a number of paths in the range.
Forest::node_type node_type
The type of nodes in the underlying Forest.
Definition forest.hpp:1254
auto end() noexcept
Returns an input iterator pointing one beyond the last word in the range.
Definition forest.hpp:1351
static constexpr bool is_idempotent
Definition forest.hpp:1262
output_type get() const noexcept
Returns a reference to the current path.
Definition forest.hpp:999
PathsFromToRootsCommon & operator=(PathsFromToRootsCommon const &)=default
Default copy assignment operator.
PathsFromToRootsCommon & operator=(PathsFromToRootsCommon &&)=default
Default move assignment operator.
PathsFromToRootsCommon & init(Forest const &f)
Re-initialize from a Forest.
Forest const & forest() const noexcept
Returns the underlying Forest object.
Definition forest.hpp:1048
size_type size_hint() const noexcept
Get the size of the range.
Definition forest.hpp:1023
PathsFromToRootsCommon(PathsFromToRootsCommon const &)=default
Default copy constructor.
size_type count() const noexcept
Get the size of the range.
Definition forest.hpp:1035
node_type target() const noexcept
Get the current target of the path.
Definition forest.hpp:986
PathsFromToRootsCommon(PathsFromToRootsCommon &&)=default
Default move constructor.
PathsFromToRootsCommon(Forest const &f)
Construct from a Forest.
bool at_end() const noexcept
Check if the range is exhausted.
Definition forest.hpp:1009
std::string to_human_readable_repr(Action< Element, Point, Func, Traits, LeftOrRight > const &action)
Return a human readable representation of an Action object.
Bipartition operator*(Bipartition const &x, Bipartition const &y)
Multiply two bipartitions.
Undefined const UNDEFINED
Value for something undefined.
enable_if_is_same< Return, Blocks > make(Container const &cont)
Check the arguments, construct a Blocks object, and check it.
Definition bipart.hpp:856
std::enable_if_t< std::is_same_v< Given, Expected >, Expected > enable_if_is_same
Alias equal to the second template parameter if both template parameters are equal.
Definition types.hpp:48
std::vector< letter_type > word_type
Type for a word over the generators of a semigroup.
Definition types.hpp:99
auto format(libsemigroups::Forest const &f, FormatContext &ctx) const
Custom formatter for Forest objects.
Definition forest.hpp:1439
Helper functions for the Forest class.
Definition forest.hpp:676
bool is_root_no_checks(Forest const &f, Forest::node_type n)
Check if a node is the root of any tree in the Forest.
Definition forest.hpp:854
bool is_forest(Forest const &f)
Check whether a Forest object is well-defined.
bool is_root(Forest const &f, Forest::node_type n)
Check if a node is the root of any tree in the Forest.
Definition forest.hpp:871
size_t depth(Forest const &f, Forest::node_type n)
Returns the depth of a node in the forest, i.e. the distance, in terms of the number of edges,...
Definition forest.hpp:837
size_t depth_no_checks(Forest const &f, Forest::node_type n)
Returns the depth of a node in the forest, n.e. the distance, in terms of the number of edges,...
void path_to_root(Forest const &f, word_type &w, Forest::node_type n)
Modifies w to contain the labels of the edges on the path to a root node from n.
void path_from_root_no_checks(Forest const &f, word_type &w, Forest::node_type n)
Modifies w to contain the labels of the edges on the path from a root node to n.
Dot dot(Forest const &f)
Returns a Dot object representing a Forest.
Forest::label_type max_label(Forest const &f)
Returns the maximum label of any edge in a Forest.
void path_to_root_no_checks(Forest const &f, word_type &w, Forest::node_type n)
Modifies w to contain the labels of the edges on the path to a root node from n.
void path_from_root(Forest const &f, word_type &w, Forest::node_type n)
Modifies w to contain the labels of the edges on the path from a root node to n.
Namespace for everything in the libsemigroups library.
Definition action.hpp:44