libsemigroups  v3.0.0
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-2025 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 <algorithm> // for fill
23#include <cstddef> // for size_t
24#include <initializer_list> // for initializer_list
25#include <iterator> // for begin, end
26#include <vector> // for vector, allocator, operator==
27
28#include "constants.hpp" // for Undefined, Max, UNDEFINED, operator!=
29#include "debug.hpp" // for LIBSEMIGROUPS_ASSERT
30#include "exception.hpp" // for LIBSEMIGROUPS_EXCEPTION
31#include "types.hpp" // for word_type, enable_if_is_same
32
33namespace libsemigroups {
42 class Forest {
43 std::vector<size_t> _edge_label;
44 std::vector<size_t> _parent;
45
46 public:
48 using node_type = size_t;
49
51 using label_type = size_t;
52
59 explicit Forest(size_t n = 0)
60 : _edge_label(n, static_cast<size_t>(UNDEFINED)),
61 _parent(n, static_cast<size_t>(UNDEFINED)) {}
62
74 Forest& init(size_t n = 0);
75
77 Forest(Forest const&) = default;
78
80 Forest(Forest&&) = default;
81
83 Forest& operator=(Forest const&) = default;
84
86 Forest& operator=(Forest&&) = default;
87
88 ~Forest();
89
98 [[nodiscard]] bool operator==(Forest const& that) const {
99 return _parent == that._parent && _edge_label == that._edge_label;
100 }
101
109 [[nodiscard]] bool operator!=(Forest const& that) const {
110 return !(*this == that);
111 }
112
128 Forest& add_nodes(size_t n);
129
143 [[nodiscard]] bool empty() const noexcept {
144 return _parent.empty();
145 }
146
170 label_type gen) {
171 _parent[node] = parent;
172 _edge_label[node] = gen;
173 return *this;
174 }
175
195 // not noexcept because std::vector::operator[] isn't.
203
216 [[nodiscard]] size_t number_of_nodes() const noexcept {
217 return _parent.size();
218 }
219
235 // not noexcept because std::vector::operator[] isn't.
236 [[nodiscard]] node_type parent(node_type i) const {
238 return _parent[i];
239 }
240
256 [[nodiscard]] node_type parent_no_checks(node_type i) const {
257 return _parent[i];
258 }
259
275 // not noexcept because std::vector::operator[] isn't.
276 [[nodiscard]] label_type label(node_type i) const {
278 return _edge_label[i];
279 }
280
296 [[nodiscard]] label_type label_no_checks(node_type i) const {
297 return _edge_label[i];
298 }
299
314 [[nodiscard]] std::vector<node_type> const& parents() const noexcept {
315 return _parent;
316 }
317
333 [[nodiscard]] std::vector<label_type> const& labels() const noexcept {
334 return _edge_label;
335 }
336
352 template <typename Iterator>
353 Iterator path_to_root_no_checks(Iterator d_first, node_type i) const {
354 LIBSEMIGROUPS_ASSERT(i < _parent.size());
355 LIBSEMIGROUPS_ASSERT(i < _edge_label.size());
356 auto it = d_first;
357 for (; parent_no_checks(i) != UNDEFINED; ++it) {
358 *it = label_no_checks(i);
359 LIBSEMIGROUPS_ASSERT(i != parent_no_checks(i));
360 i = parent_no_checks(i);
361 }
362 return it;
363 }
364
371 };
372
383
406 template <typename Return>
409 if (parent.size() != edge_labels.size()) {
411 "expected the 1st and 2nd arguments (parents and edge labels) to "
412 "have equal size equal, found {} != {}",
413 parent.size(),
414 edge_labels.size());
415 }
416 size_t const num_nodes = parent.size();
417 Forest result(num_nodes);
418 for (size_t i = 0; i < num_nodes; ++i) {
419 auto p = *(parent.begin() + i);
420 auto l = *(edge_labels.begin() + i);
421 if (p != UNDEFINED && l != UNDEFINED) {
422 result.set_parent_and_label(i, p, l);
423 } else if (!(p == UNDEFINED && l == UNDEFINED)) {
425 "roots not at the same indices in the 1st and 2nd arguments "
426 "(parents and edge labels), expected UNDEFINED at index {} found "
427 "{} and {}",
428 i,
429 p,
430 l);
431 }
432 }
433 return result;
434 }
435
459 template <typename Return>
462 std::initializer_list<size_t> edge_labels) {
463 return make<Forest>(std::vector<size_t>(parent), std::vector(edge_labels));
464 }
465
477
483 namespace forest {
496 word_type& w,
498
513
527
541 [[nodiscard]] word_type path_to_root(Forest const& f, Forest::node_type i);
542
543 } // namespace forest
544} // namespace libsemigroups
545
546namespace fmt {
547 template <>
548 struct formatter<libsemigroups::Forest> : formatter<std::string> {
569 template <typename FormatContext>
570 auto format(libsemigroups::Forest const& f, FormatContext& ctx) const {
571 return formatter<string_view>::format(
572 fmt::format("{{{}, {}}}", f.parents(), f.labels()), ctx);
573 }
574 };
575} // namespace fmt
576#endif // LIBSEMIGROUPS_FOREST_HPP_
T begin(T... args)
Class representing a collection of spanning trees of a word graph.
Definition forest.hpp:42
size_t number_of_nodes() const noexcept
Returns the number of nodes in the forest.
Definition forest.hpp:216
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:143
node_type parent_no_checks(node_type i) const
Returns the parent of a node.
Definition forest.hpp:256
Forest(Forest const &)=default
Default copy constructor.
Forest & operator=(Forest const &)=default
Default copy assignment constructor.
bool operator==(Forest const &that) const
Compare Forest objects for equality.
Definition forest.hpp:98
std::vector< node_type > const & parents() const noexcept
Returns a const reference to the vector of parents.
Definition forest.hpp:314
Forest & operator=(Forest &&)=default
Default move assignment constructor.
node_type parent(node_type i) const
Returns the parent of a node.
Definition forest.hpp:236
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:59
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:109
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 i.
Definition forest.hpp:353
label_type label(node_type i) const
Returns the label of the edge from a node to its parent.
Definition forest.hpp:276
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:168
size_t label_type
Alias for the type of edge labels in a forest.
Definition forest.hpp:51
size_t node_type
Alias for the type of nodes in a forest.
Definition forest.hpp:48
label_type label_no_checks(node_type i) const
Returns the label of the edge from a node to its parent.
Definition forest.hpp:296
std::vector< label_type > const & labels() const noexcept
Returns a const reference to the vector of edge labels.
Definition forest.hpp:333
void throw_if_node_out_of_bounds(node_type v) const
Throw an exception if a node is out of bound.
Forest & set_parent_and_label(node_type node, node_type parent, label_type gen)
Set the parent and edge label for a node.
Definition forest.hpp:196
Forest(Forest &&)=default
Default move constructor.
Undefined const UNDEFINED
Value for something undefined.
#define LIBSEMIGROUPS_EXCEPTION(...)
Throw a LibsemigroupsException.
Definition exception.hpp:95
enable_if_is_same< Return, Blocks > make(Container const &cont)
Check the arguments, construct a Blocks object, and check it.
Definition bipart.hpp:798
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:50
std::vector< letter_type > word_type
Type for a word over the generators of a semigroup.
Definition types.hpp:101
auto format(libsemigroups::Forest const &f, FormatContext &ctx) const
Custom formatter for Forest objects.
Definition forest.hpp:570
Helper functions for the Forest class.
Definition forest.hpp:483
void path_to_root(Forest const &f, word_type &w, Forest::node_type i)
Modifies w to contain the labels of the edges on the path to a root node from i.
void path_to_root_no_checks(Forest const &f, word_type &w, Forest::node_type i)
Modifies w to contain the labels of the edges on the path to a root node from i.
Namespace for everything in the libsemigroups library.
Definition action.hpp:44
T size(T... args)