libsemigroups  v3.3.0
C++ library for semigroups and monoids
Loading...
Searching...
No Matches
word-graph.hpp
1//
2// libsemigroups - C++ library for semigroups and monoids
3// Copyright (C) 2019-2025 Finn Smith + James D. 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// This file contains declarations related to word graphs (which are basically
20// deterministic automata without initial or accept states).
21
22#ifndef LIBSEMIGROUPS_WORD_GRAPH_HPP_
23#define LIBSEMIGROUPS_WORD_GRAPH_HPP_
24
25#include <algorithm> // for uniform_int_distribution
26#include <cstddef> // for size_t
27#include <cstdint> // for uint32_t
28#include <ostream> // for operator<<
29#include <queue> // for queue
30#include <random> // for mt19937
31#include <stack> // for stack
32#include <string> // for to_string
33#include <tuple> // for tie
34#include <type_traits> // for is_integral, is_unsigned
35#include <unordered_set> // for unordered_set
36#include <utility> // for pair
37#include <vector> // for vector
38
39#include "config.hpp" // for LIBSEMIGROUPS_EIGEN_EN...
40#include "constants.hpp" // for UNDEFINED
41#include "debug.hpp" // for LIBSEMIGROUPS_ASSERT
42#include "dot.hpp" // for Dot
43#include "exception.hpp" // for LIBSEMIGROUPS_EXCEPTION
44#include "forest.hpp" // for Forest
45#include "is_specialization_of.hpp" // for is_specialization_of_v
46#include "order.hpp" // for Order
47#include "ranges.hpp" // for ??
48#include "types.hpp" // for word_type, enable_if_is_same
49
50#include "detail/containers.hpp" // for DynamicArray2
51#include "detail/int-range.hpp" // for IntRange
52#include "detail/stl.hpp" // for IsIterator
53#include "detail/uf.hpp" // for Duf
54
55#ifdef LIBSEMIGROUPS_EIGEN_ENABLED
56#include "detail/eigen.hpp"
57#else
58#include "matrix.hpp"
59#endif
60
61namespace libsemigroups {
62
67
82 template <typename Node>
83 class WordGraph {
84 static_assert(std::is_integral<Node>(),
85 "the template parameter Node must be an integral type!");
86 static_assert(
88 "the template parameter Node must be an unsigned integral type!");
89
90 template <typename N>
91 friend class WordGraph;
92
93 public:
95 // WordGraph - typedefs - public
97
99 using node_type = Node;
100
102 using label_type = Node;
103
106
107#ifdef LIBSEMIGROUPS_EIGEN_ENABLED
110 = Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>;
111#else
114#endif
115
118 typename detail::IntRange<Node>::const_iterator;
119
122 typename detail::IntRange<Node>::const_reverse_iterator;
123
126 typename detail::DynamicArray2<Node>::const_iterator;
127
128 protected:
130 // WordGraph - data members - protected
132
133 mutable detail::DynamicArray2<Node> _dynamic_array_2;
134
135 private:
137 // WordGraph - data members - private
139
140 size_type _degree;
141 size_type _nr_nodes;
142 // TODO(1) remove when WordGraphView is implemented
143 size_type _num_active_nodes;
144
145 public:
147 // WordGraph - constructors + destructor - public
149
165 // Not noexcept
166 explicit WordGraph(size_type m = 0, size_type n = 0);
167
186 WordGraph& init(size_type m = 0, size_type n = 0);
187
189 WordGraph(WordGraph const&);
190
200 template <typename OtherNode>
201 WordGraph(WordGraph<OtherNode> const& that);
202
223 template <typename OtherNode>
224 WordGraph& init(WordGraph<OtherNode> const& that);
225
227 WordGraph(WordGraph&&);
228
230 WordGraph& operator=(WordGraph const&);
231
233 WordGraph& operator=(WordGraph&&);
234
235 ~WordGraph();
236
257 static WordGraph random(size_type number_of_nodes,
259 std::mt19937 mt
261
285 // Not noexcept because DynamicArray2::add_cols isn't.
286 WordGraph& reserve(size_type m, size_type n);
287
289 // WordGraph - modifiers - public
291
310 // Not noexcept because DynamicArray2::add_rows isn't.
311 WordGraph& add_nodes(size_type nr);
312
332 // Not noexcept because DynamicArray2::add_cols isn't.
333 WordGraph& add_to_out_degree(size_type nr);
334
352 // Not noexcept because throw_if_node_out_of_bounds/label aren't
353 // return *this by reference.
354 WordGraph& target(node_type s, label_type a, node_type t);
355
374 //! No checks whatsoever on the validity of the arguments are performed.
375 inline WordGraph& target_no_checks(node_type s, label_type a, node_type t) {
376 _dynamic_array_2.set(s, a, t);
377 return *this;
378 }
379
396 //! No checks whatsoever on the validity of the arguments are performed.
397 inline WordGraph& remove_target_no_checks(node_type s, label_type a) {
398 _dynamic_array_2.set(s, a, UNDEFINED);
399 return *this;
400 }
401
415 WordGraph& remove_target(node_type s, label_type a);
416
427 WordGraph& remove_label(label_type a);
428
444
457 //! out-degree.
458 inline WordGraph& remove_all_targets() {
459 std::fill(_dynamic_array_2.begin(), _dynamic_array_2.end(), UNDEFINED);
460 return *this;
461 }
462
482 // swap m - a - > m' and n - a -> n'
484 _dynamic_array_2.swap(m, a, n, a);
485 return *this;
486 }
487
503 WordGraph& swap_targets(node_type m, node_type n, label_type a);
504
520 //! is the out-degree of the word graph.
521 [[nodiscard]] bool operator==(WordGraph const& that) const {
522 return _dynamic_array_2 == that._dynamic_array_2;
523 }
524
540 //! is the out-degree of the word graph.
541 [[nodiscard]] bool operator!=(WordGraph const& that) const {
542 return !operator==(that);
543 }
544
560 //! is the out-degree of the word graph.
561 [[nodiscard]] bool operator<(WordGraph const& that) const {
562 return _dynamic_array_2 < that._dynamic_array_2;
563 }
564
580 //! is the out-degree of the word graph.
581 [[nodiscard]] bool operator<=(WordGraph const& that) const {
582 return _dynamic_array_2 <= that._dynamic_array_2;
583 }
584
600 //! is the out-degree of the word graph.
601 [[nodiscard]] bool operator>(WordGraph const& that) const {
602 return _dynamic_array_2 > that._dynamic_array_2;
603 }
604
620 //! is the out-degree of the word graph.
621 [[nodiscard]] bool operator>=(WordGraph const& that) const {
622 return _dynamic_array_2 > that._dynamic_array_2;
623 }
624
635 // not noexcept because Hash<T>::operator() isn't
636 [[nodiscard]] size_t hash_value() const {
637 return std::hash<decltype(_dynamic_array_2)>()(_dynamic_array_2);
638 }
639
641 // WordGraph - nodes, targets, etc - public
643
661 // Not noexcept because throw_if_node_out_of_bounds/label aren't
662 [[nodiscard]] node_type target(node_type source, label_type a) const;
663
683 // Not noexcept because DynamicArray2::get is not
684 [[nodiscard]] node_type inline target_no_checks(node_type s,
685 label_type a) const {
686 return _dynamic_array_2.get(s, a);
687 }
688
717 // Not noexcept because DynamicArray2::get is not
720
751 // Not noexcept because next_label_and_target_no_checks is not
754
766 //! Constant.
767 [[nodiscard]] size_type inline number_of_nodes() const noexcept {
768 return _nr_nodes;
769 }
770
771#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
772 WordGraph& number_of_active_nodes(size_type val) {
773 _num_active_nodes = val;
774 return *this;
775 }
776
777 [[nodiscard]] size_type inline number_of_active_nodes() const noexcept {
778 return _num_active_nodes;
779 }
780#endif
781
795 // Not noexcept because std::count isn't
796 [[nodiscard]] size_type number_of_edges() const;
797
812 [[nodiscard]] size_type number_of_edges(node_type s) const;
813
829 [[nodiscard]] size_type number_of_edges_no_checks(node_type s) const;
830
842 //! Constant.
843 [[nodiscard]] size_type out_degree() const noexcept {
844 return _degree;
845 }
846
860 //! Constant.
861 const_iterator_nodes cbegin_nodes() const noexcept {
862 return detail::IntRange<node_type>(0, number_of_nodes()).cbegin();
863 }
864
878 //! Constant.
879 [[nodiscard]] const_iterator_nodes cend_nodes() const noexcept {
880 return detail::IntRange<node_type>(0, number_of_nodes()).cend();
881 }
882
900 // Not noexcept because throw_if_node_out_of_bounds isn't
901 [[nodiscard]] const_iterator_targets cbegin_targets(node_type source) const;
902
927 cbegin_targets_no_checks(node_type source) const noexcept {
928 return _dynamic_array_2.cbegin_row(source);
929 }
930
948 // Not noexcept because throw_if_node_out_of_bounds isn't
949 [[nodiscard]] const_iterator_targets cend_targets(node_type source) const;
950
975 cend_targets_no_checks(node_type source) const noexcept {
976 return _dynamic_array_2.cbegin_row(source) + _degree;
977 }
978
987 //! \noexcept
988 [[nodiscard]] auto nodes() const noexcept {
989 return rx::seq<node_type>() | rx::take(number_of_nodes());
990 }
991
1001 //! \noexcept
1002 [[nodiscard]] auto labels() const noexcept {
1003 return rx::seq<label_type>() | rx::take(out_degree());
1004 }
1005
1023 [[nodiscard]] rx::iterator_range<const_iterator_targets>
1024 targets_no_checks(node_type source) const noexcept {
1025 return rx::iterator_range(cbegin_targets_no_checks(source),
1026 cend_targets_no_checks(source));
1027 }
1028
1041 [[nodiscard]] rx::iterator_range<const_iterator_targets>
1042 targets(node_type source) const;
1043
1061 [[nodiscard]] auto
1062 labels_and_targets_no_checks(node_type source) const noexcept {
1063 return rx::zip(rx::seq<node_type>(), targets_no_checks(source));
1064 }
1065
1077 [[nodiscard]] auto labels_and_targets(node_type source) const;
1078
1097 WordGraph& induced_subgraph_no_checks(node_type first, node_type last);
1098
1113 WordGraph& induced_subgraph(node_type first, node_type last);
1114
1137 template <typename Iterator,
1138 typename = std::enable_if_t<detail::IsIterator<Iterator>::value>>
1139 WordGraph& induced_subgraph_no_checks(Iterator first, Iterator last);
1140
1162 template <typename Iterator,
1163 typename = std::enable_if_t<detail::IsIterator<Iterator>::value>>
1164 WordGraph& induced_subgraph(Iterator first, Iterator last);
1165
1181 WordGraph& disjoint_union_inplace_no_checks(WordGraph<Node> const& that);
1182
1195 WordGraph& disjoint_union_inplace(WordGraph<Node> const& that);
1196
1197#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
1198 // These are currently undocumented, because they are hard to use correctly,
1199 // shouldn't p and q be actual permutation objects?
1200
1201 // requires access to _dynamic_array_2 so can't be helper
1202 WordGraph& permute_nodes_no_checks(std::vector<node_type> const& p,
1203 std::vector<node_type> const& q,
1204 size_t m);
1205
1206 WordGraph& permute_nodes_no_checks(std::vector<node_type> const& p,
1207 std::vector<node_type> const& q) {
1208 return permute_nodes_no_checks(p, q, p.size());
1209 }
1210
1211 WordGraph& standardize(std::vector<node_type> const& p,
1212 std::vector<node_type> const& q) {
1213 return permute_nodes_no_checks(p, q, p.size());
1214 }
1215#endif
1216 }; // WordGraph
1217
1227 namespace word_graph {
1228
1230 // WordGraph - helper functions - in alphabetical order!!!
1232
1257 // TODO(1) add add_cycle with checks version.
1258 template <typename Node, typename Iterator>
1259 [[deprecated]] void add_cycle_no_checks(WordGraph<Node>& wg,
1260 Iterator first,
1261 Iterator last);
1262
1280 template <typename Node>
1281 [[deprecated]] void add_cycle(WordGraph<Node>& wg, size_t N) {
1282 size_t M = wg.number_of_nodes();
1283 wg.add_nodes(N);
1284 add_cycle_no_checks(wg, wg.cbegin_nodes() + M, wg.cend_nodes());
1285 }
1286
1303 template <typename Node>
1304 [[deprecated]] [[nodiscard]] auto
1306
1319 template <typename Node>
1320 [[deprecated]] [[nodiscard]] Dot dot(WordGraph<Node> const& wg);
1321
1351 template <typename Node>
1352 [[deprecated]] [[nodiscard]] bool
1354 WordGraph<Node> const& y,
1355 Node first,
1356 Node last);
1357
1388 template <typename Node>
1389 [[deprecated]] [[nodiscard]] bool equal_to(WordGraph<Node> const& x,
1390 WordGraph<Node> const& y,
1391 Node first,
1392 Node last);
1393
1430 template <typename Node1, typename Node2, typename Iterator>
1431 [[deprecated]] [[nodiscard]] Node1 follow_path(WordGraph<Node1> const& wg,
1432 Node2 source,
1433 Iterator first,
1434 Iterator last);
1435
1468 // TODO(2) example
1469 // not noexcept because WordGraph::target isn't
1470 template <typename Node1, typename Node2>
1471 [[deprecated]] [[nodiscard]] Node1 follow_path(WordGraph<Node1> const& wg,
1472 Node2 from,
1473 word_type const& path) {
1474 static_assert(sizeof(Node2) <= sizeof(Node1));
1475 return follow_path(wg, from, path.cbegin(), path.cend());
1476 }
1477
1509 template <typename Node1, typename Node2, typename Iterator>
1510 [[deprecated]] [[nodiscard]] Node1
1512 Node2 from,
1513 Iterator first,
1514 Iterator last) noexcept;
1515
1547 template <typename Node1, typename Node2>
1548 [[deprecated]] [[nodiscard]] Node1
1550 Node2 from,
1551 word_type const& path) noexcept {
1552 static_assert(sizeof(Node2) <= sizeof(Node1));
1553 return follow_path_no_checks(wg, from, path.cbegin(), path.cend());
1554 }
1555
1593 // Not noexcept because detail::is_acyclic isn't
1594 template <typename Node>
1595 [[deprecated]] [[nodiscard]] bool is_acyclic(WordGraph<Node> const& wg);
1596
1646 // Not noexcept because detail::is_acyclic isn't
1647 template <typename Node1, typename Node2>
1648 [[deprecated]] [[nodiscard]] bool is_acyclic(WordGraph<Node1> const& wg,
1649 Node2 source);
1650
1685 // Not noexcept because detail::is_acyclic isn't
1686 template <typename Node1, typename Node2>
1687 [[deprecated]] [[nodiscard]] bool is_acyclic(WordGraph<Node1> const& wg,
1688 Node2 source,
1689 Node2 target);
1690
1735 // TODO(1) add a version of this function with one that returns a float
1736 // representing the proportion of the nodes in the range that are compatible
1737 // with the rules. Don't replace the current version because it can return
1738 // early knowing that it isn't compatible.
1739 template <typename Node,
1740 typename Iterator1,
1741 typename Iterator2,
1742 typename Iterator3>
1743 [[deprecated]] [[nodiscard]] bool
1745 Iterator1 first_node,
1746 Iterator2 last_node,
1747 Iterator3 first_rule,
1748 Iterator3 last_rule);
1749
1796 template <
1797 typename Node,
1798 typename Iterator1,
1799 typename Iterator2,
1800 typename Iterator3,
1801 std::enable_if_t<!std::is_same_v<std::decay_t<Iterator3>, word_type>>>
1802 [[deprecated]] [[nodiscard]] bool is_compatible(WordGraph<Node> const& wg,
1803 Iterator1 first_node,
1804 Iterator2 last_node,
1805 Iterator3 first_rule,
1806 Iterator3 last_rule);
1807
1844 template <typename Node, typename Iterator1, typename Iterator2>
1845 [[deprecated]] bool is_compatible_no_checks(WordGraph<Node> const& wg,
1846 Iterator1 first_node,
1847 Iterator2 last_node,
1848 word_type const& lhs,
1849 word_type const& rhs);
1850
1889 template <typename Node, typename Iterator1, typename Iterator2>
1890 [[deprecated]] bool is_compatible(WordGraph<Node> const& wg,
1891 Iterator1 first_node,
1892 Iterator2 last_node,
1893 word_type const& lhs,
1894 word_type const& rhs);
1895
1930 template <typename Node, typename Iterator1, typename Iterator2>
1931 [[deprecated]] [[nodiscard]] bool
1933 Iterator1 first_node,
1934 Iterator2 last_node);
1935
1968 template <typename Node, typename Iterator1, typename Iterator2>
1969 [[deprecated]] [[nodiscard]] bool is_complete(WordGraph<Node> const& wg,
1970 Iterator1 first_node,
1971 Iterator2 last_node);
1972
1993 template <typename Node>
1994 [[deprecated]] [[nodiscard]] bool
1995 is_complete(WordGraph<Node> const& wg) noexcept {
1996 return wg.number_of_edges() == wg.number_of_nodes() * wg.out_degree();
1997 }
1998
2023 template <typename Node>
2024 [[deprecated]] [[nodiscard]] bool is_connected(WordGraph<Node> const& wg);
2025
2078 template <typename Node1, typename Node2>
2079 [[deprecated]] [[nodiscard]] bool
2081 Node2 source,
2082 Node2 target);
2083
2118 template <typename Node1, typename Node2>
2119 [[deprecated]] [[nodiscard]] bool is_reachable(WordGraph<Node1> const& wg,
2120 Node2 source,
2121 Node2 target);
2122
2157 // TODO(1) should have a version that returns the node that everything is
2158 // reachable from
2159 template <typename Node>
2160 [[deprecated]] [[nodiscard]] bool
2162
2192 template <typename Node1, typename Node2, typename Iterator>
2193 [[deprecated]] [[nodiscard]] std::pair<Node1, Iterator>
2195 Node2 source,
2196 Iterator first,
2197 Iterator last) noexcept;
2198
2227 template <typename Node1, typename Node2, typename Iterator>
2228 [[deprecated]] [[nodiscard]] std::pair<Node1, Iterator>
2230 Node2 source,
2231 Iterator first,
2232 Iterator last);
2233
2258 template <typename Node1, typename Node2>
2261 Node2 source,
2262 word_type const& w);
2263
2288 template <typename Node1, typename Node2>
2291 Node2 source,
2292 word_type const& w);
2293
2317 // TODO(1) tests
2318 // TODO(1) version where std::unordered_set is passed by reference, or make
2319 // this a class that stores its stack and unordered_set, not clear why we'd
2320 // single out the unordered_set to be passed by reference.
2321 // TODO(2) version which is an iterator i.e. returns an iterator or range
2322 // object that allows use to step through the nodes reachable from a given
2323 // node
2324 template <typename Node1, typename Node2>
2325 [[deprecated]] [[nodiscard]] std::unordered_set<Node1>
2326 nodes_reachable_from(WordGraph<Node1> const& wg, Node2 source);
2327
2351 template <typename Node1, typename Node2>
2352 [[deprecated]] [[nodiscard]] std::unordered_set<Node1>
2353 ancestors_of(WordGraph<Node1> const& wg, Node2 target);
2354
2379 template <typename Node1, typename Node2>
2380 [[deprecated]] [[nodiscard]] std::unordered_set<Node1>
2382
2407 template <typename Node1, typename Node2>
2408 [[deprecated]] [[nodiscard]] std::unordered_set<Node1>
2410
2434 template <typename Node1, typename Node2>
2435 [[deprecated]] [[nodiscard]] size_t
2437 return nodes_reachable_from(wg, source).size();
2438 }
2439
2461 template <typename Node1, typename Node2>
2462 [[deprecated]] [[nodiscard]] size_t
2464 Node2 source) {
2465 return nodes_reachable_from_no_checks(wg, source).size();
2466 }
2467
2492 template <typename Node>
2493 [[deprecated]] WordGraph<Node>
2494 random_acyclic(size_t number_of_nodes,
2495 size_t out_degree,
2497
2520 template <typename Node1, typename Node2>
2521 [[deprecated]] void spanning_tree_no_checks(WordGraph<Node1> const& wg,
2522 Node2 root,
2523 Forest& f);
2524
2546 template <typename Node1, typename Node2>
2547 [[deprecated]] void spanning_tree(WordGraph<Node1> const& wg,
2548 Node2 root,
2549 Forest& f);
2550
2574 template <typename Node1, typename Node2>
2575 [[deprecated]] [[nodiscard]] Forest
2577
2600 template <typename Node1, typename Node2>
2601 [[deprecated]] [[nodiscard]] Forest
2602 spanning_tree(WordGraph<Node1> const& wg, Node2 root);
2603
2630 // Not nodiscard because sometimes we just don't want the output
2631 template <typename Graph>
2632 [[deprecated]] bool standardize(Graph& wg, Forest& f, Order val);
2633
2660 // Not nodiscard because sometimes we just don't want the output
2661 template <typename Graph>
2662 [[deprecated]] std::pair<bool, Forest> standardize(Graph& wg,
2663 Order val
2664 = Order::shortlex);
2665
2685 template <typename Node>
2686 [[deprecated]] bool is_standardized(WordGraph<Node> const& wg,
2687 Order val = Order::shortlex);
2688
2702 template <typename Node>
2704
2726 template <typename Node, typename Iterator>
2728 Iterator first,
2729 Iterator last);
2730
2742 // not noexcept because it throws an exception!
2743 template <typename Node>
2745 typename WordGraph<Node>::label_type a);
2746
2759 template <typename Node>
2761 word_type const& word);
2762
2778 template <typename Node, typename Iterator>
2780 Iterator first,
2781 Iterator last);
2782
2795 // not noexcept because it throws an exception!
2796 template <typename Node1, typename Node2>
2798
2814 // not noexcept because it throws an exception!
2815 template <typename Node, typename Iterator1, typename Iterator2>
2817 Iterator1 first,
2818 Iterator2 last);
2819
2846 template <typename Node>
2847 [[deprecated]] [[nodiscard]] std::vector<Node>
2849
2879 template <typename Node1, typename Node2>
2880 [[deprecated]] [[nodiscard]] std::vector<Node1>
2881 topological_sort(WordGraph<Node1> const& wg, Node2 source);
2882
2883 } // namespace word_graph
2884
2886 // WordGraph - non-member functions
2888
2898 template <typename Thing>
2899 static constexpr bool IsWordGraph [[deprecated]]
2901
2924 template <typename Node>
2925 // TODO 0: This should be deprecated, but this was causing JDE issues
2927
2938
2970 // Passing the 2nd parameter "targets" by value disambiguates it from the
2971 // other make<WordGraph>.
2972 template <typename Return>
2973 [[deprecated]] [[nodiscard]] std::enable_if_t<
2975 Return>
2976 make(size_t num_nodes,
2978
2981 // clang-format off
2982 // NOLINTNEXTLINE(whitespace/line_length)
2984 // clang-format on
2985 template <typename Return>
2986 [[deprecated]] [[nodiscard]] std::
2987 enable_if_t<is_specialization_of_v<Return, WordGraph>, Return>
2988 make(size_t num_nodes,
2990
2991 namespace detail {
2992 template <typename Subclass>
2993 class [[deprecated]] JoinerMeeterCommon {
2994 private:
2995 template <typename Node1, typename Node2>
2996 void throw_if_bad_args(WordGraph<Node1> const& x,
2997 Node2 xroot,
2998 WordGraph<Node1> const& y,
2999 Node2 yroot);
3000
3001 public:
3002 template <typename Node>
3003 void call_no_checks(WordGraph<Node>& xy,
3004 WordGraph<Node> const& x,
3005 Node xroot,
3006 WordGraph<Node> const& y,
3007 Node yroot);
3008
3009 template <typename Node>
3010 void call_no_checks(WordGraph<Node>& xy,
3011 WordGraph<Node> const& x,
3012 WordGraph<Node> const& y) {
3013 return call_no_checks(
3014 xy, x, static_cast<Node>(0), y, static_cast<Node>(0));
3015 }
3016
3017 template <typename Node, typename... Args>
3018 [[nodiscard]] auto call_no_checks(WordGraph<Node> const& x,
3019 Args&&... args)
3020 -> std::enable_if_t<sizeof...(Args) % 2 == 1, WordGraph<Node>> {
3021 // The versions of this function changing the 1st argument in-place
3022 // always have an odd number of arguments, so we check that it's even
3023 // here (the argument x and an odd number of further arguments).
3024 WordGraph<Node> xy;
3025 static_cast<Subclass&>(*this).call_no_checks(
3026 xy, x, std::forward<Args>(args)...);
3027 return xy;
3028 }
3029
3030 // There's no operator() with the number of nodes reachable from the
3031 // roots as arguments (7 args in total) because we'd have to check that
3032 // they were valid, and the only way to do this is to recompute them.
3033
3034 template <typename Node>
3035 void operator()(WordGraph<Node>& xy,
3036 WordGraph<Node> const& x,
3037 Node xroot,
3038 WordGraph<Node> const& y,
3039 Node yroot) {
3040 throw_if_bad_args(x, xroot, y, yroot);
3041 call_no_checks(xy, x, xroot, y, yroot);
3042 }
3043
3044 template <typename Node>
3045 void operator()(WordGraph<Node>& xy,
3046 WordGraph<Node> const& x,
3047 WordGraph<Node> const& y) {
3048 return operator()(xy, x, static_cast<Node>(0), y, static_cast<Node>(0));
3049 }
3050
3051 template <typename Node, typename... Args>
3052 [[nodiscard]] auto operator()(WordGraph<Node> const& x, Args&&... args)
3053 -> std::enable_if_t<sizeof...(Args) % 2 == 1, WordGraph<Node>> {
3054 // The versions of this function changing the 1st argument in-place
3055 // always have an odd number of arguments, so we check that it's even
3056 // here (the argument x and an odd number of further arguments).
3057 WordGraph<Node> xy;
3058 operator()(xy, x, std::forward<Args>(args)...);
3059 return xy;
3060 }
3061
3062 template <typename Node1, typename Node2>
3063 bool is_subrelation_no_checks(WordGraph<Node1> const& x,
3064 Node2 xroot,
3065 WordGraph<Node1> const& y,
3066 Node2 yroot);
3067
3068 template <typename Node>
3069 bool is_subrelation_no_checks(WordGraph<Node> const& x,
3070 WordGraph<Node> const& y) {
3071 return is_subrelation_no_checks(
3072 x, static_cast<Node>(0), y, static_cast<Node>(0));
3073 }
3074
3075 // There's no subrelation with the number of nodes reachable from the
3076 // roots as arguments (6 args in total) because we'd have to check that
3077 // they were valid, and the only way to do this is to recompute them.
3078
3079 template <typename Node1, typename Node2>
3080 bool is_subrelation(WordGraph<Node1> const& x,
3081 Node2 xroot,
3082 WordGraph<Node1> const& y,
3083 Node2 yroot) {
3084 throw_if_bad_args(x, xroot, y, yroot);
3085 return is_subrelation_no_checks(x, xroot, y, yroot);
3086 }
3087
3088 template <typename Node>
3089 bool is_subrelation(WordGraph<Node> const& x, WordGraph<Node> const& y) {
3090 return is_subrelation(x, static_cast<Node>(0), y, static_cast<Node>(0));
3091 }
3092 }; // JoinerMeeterCommon
3093 } // namespace detail
3094
3109 // This class is intentionally not a template so that we don't have to
3110 // specify the types of the nodes when constructing one of these objects.
3111 // Instead every member function has a template parameter Node, which is
3112 // deduced from the argument.
3113#pragma GCC diagnostic push
3114#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
3115 class [[deprecated]] Joiner : public detail::JoinerMeeterCommon<Joiner> {
3116#pragma GCC diagnostic pop
3117 private:
3118 detail::Duf<> _uf;
3120 std::vector<uint64_t> _lookup;
3121
3122 template <typename Node>
3123 [[nodiscard]] Node find(WordGraph<Node> const& x,
3124 size_t xnum_nodes_reachable_from_root,
3125 WordGraph<Node> const& y,
3126 uint64_t n,
3127 typename WordGraph<Node>::label_type a) const;
3128
3129 template <typename Node>
3130 void run(WordGraph<Node> const& x,
3131 size_t xnum_nodes_reachable_from_root,
3132 Node xroot,
3133 WordGraph<Node> const& y,
3134 size_t ynum_nodes_reachable_from_root,
3135 Node yroot);
3136
3137 public:
3142
3147
3152
3157
3162
3163 ~Joiner();
3164
3193 template <typename Node>
3195 WordGraph<Node> const& x,
3196 size_t xnum_nodes_reachable_from_root,
3197 Node xroot,
3198 WordGraph<Node> const& y,
3199 size_t ynum_nodes_reachable_from_root,
3200 Node yroot);
3201
3235 // Is x a subrelation of y?
3236 template <typename Node1, typename Node2>
3237 [[nodiscard]] bool
3239 size_t xnum_nodes_reachable_from_root,
3240 Node2 xroot,
3241 WordGraph<Node1> const& y,
3242 size_t ynum_nodes_reachable_from_root,
3243 Node2 yroot);
3244#ifdef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
3268 template <typename Node>
3270 WordGraph<Node> const& x,
3271 Node xroot,
3272 WordGraph<Node> const& y,
3273 Node yroot);
3274
3294 template <typename Node>
3296 WordGraph<Node> const& x,
3297 WordGraph<Node> const& y);
3298
3318 template <typename Node, typename... Args>
3319 [[nodiscard]] auto call_no_checks(WordGraph<Node> const& x, Args&&... args);
3320
3346 template <typename Node>
3348 WordGraph<Node> const& x,
3349 Node xroot,
3350 WordGraph<Node> const& y,
3351 Node yroot);
3352
3374 template <typename Node>
3376 WordGraph<Node> const& x,
3377 WordGraph<Node> const& y);
3378
3396 template <typename Node, typename... Args>
3397 [[nodiscard]] auto operator()(WordGraph<Node> const& x, Args&&... args);
3398
3428 // Is x a subrelation of y?
3429 template <typename Node1, typename Node2>
3431 Node2 xroot,
3432 WordGraph<Node1> const& y,
3433 Node2 yroot);
3434
3457 template <typename Node>
3459 WordGraph<Node> const& y);
3460
3461 // There's no subrelation with the number of nodes reachable from the
3462 // roots as arguments (6 args in total) because we'd have to check that
3463 // they were valid, and the only way to do this is to recompute them.
3464
3493 template <typename Node1, typename Node2>
3495 Node2 xroot,
3496 WordGraph<Node1> const& y,
3497 Node2 yroot);
3498
3523 template <typename Node>
3525
3526#else
3527#pragma GCC diagnostic push
3528#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
3529 using detail::JoinerMeeterCommon<Joiner>::call_no_checks;
3530 using detail::JoinerMeeterCommon<Joiner>::operator();
3531 using detail::JoinerMeeterCommon<Joiner>::is_subrelation_no_checks;
3532 using detail::JoinerMeeterCommon<Joiner>::is_subrelation;
3533#pragma GCC diagnostic pop
3534#endif
3535 }; // Joiner
3536
3552 // Class for forming the meet of two word graphs
3553#pragma GCC diagnostic push
3554#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
3555 class [[deprecated]] Meeter : public detail::JoinerMeeterCommon<Meeter> {
3556#pragma GCC diagnostic pop
3557 private:
3558 using node_type = std::pair<uint64_t, uint64_t>;
3559
3562 std::vector<node_type> _todo_new;
3563
3564 public:
3569
3574
3579
3584
3589
3590 ~Meeter();
3591
3594 template <typename Node>
3596 WordGraph<Node> const& x,
3597 size_t xnum_nodes_reachable_from_root,
3598 Node xroot,
3599 WordGraph<Node> const& y,
3600 size_t ynum_nodes_reachable_from_root,
3601 Node yroot);
3602
3605 // is x a subrelation of y
3606 template <typename Node1, typename Node2>
3607 [[nodiscard]] bool
3609 size_t xnum_nodes_reachable_from_root,
3610 Node2 xroot,
3611 WordGraph<Node1> const& y,
3612 size_t ynum_nodes_reachable_from_root,
3613 Node2 yroot);
3614
3615#ifdef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
3618 template <typename Node>
3620 WordGraph<Node> const& x,
3621 Node xroot,
3622 WordGraph<Node> const& y,
3623 Node yroot);
3624
3627 template <typename Node>
3629 WordGraph<Node> const& x,
3630 WordGraph<Node> const& y);
3631
3651 template <typename Node, typename... Args>
3652 [[nodiscard]] auto call_no_checks(WordGraph<Node> const& x, Args&&... args);
3653
3656 template <typename Node>
3658 WordGraph<Node> const& x,
3659 Node xroot,
3660 WordGraph<Node> const& y,
3661 Node yroot);
3662
3665 template <typename Node>
3667 WordGraph<Node> const& x,
3668 WordGraph<Node> const& y);
3669
3687 template <typename Node, typename... Args>
3688 [[nodiscard]] auto operator()(WordGraph<Node> const& x, Args&&... args);
3689
3692 template <typename Node1, typename Node2>
3694 Node2 xroot,
3695 WordGraph<Node1> const& y,
3696 Node2 yroot);
3697
3700 template <typename Node>
3702 WordGraph<Node> const& y);
3703
3706 template <typename Node1, typename Node2>
3708 Node2 xroot,
3709 WordGraph<Node1> const& y,
3710 Node2 yroot);
3711
3714 template <typename Node>
3716#else
3717#pragma GCC diagnostic push
3718#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
3719 using detail::JoinerMeeterCommon<Meeter>::call_no_checks;
3720 using detail::JoinerMeeterCommon<Meeter>::operator();
3721 using detail::JoinerMeeterCommon<Meeter>::is_subrelation_no_checks;
3722 using detail::JoinerMeeterCommon<Meeter>::is_subrelation;
3723#pragma GCC diagnostic pop
3724#endif
3725 }; // class Meeter
3726
3744 template <typename Node>
3745 [[deprecated]] [[nodiscard]] std::string
3747
3763 [[deprecated]] [[nodiscard]] static inline std::string
3765 (void) meet;
3766 return "<Meeter of word graphs>";
3767 }
3768
3784 [[deprecated]] [[nodiscard]] static inline std::string
3786 (void) join;
3787 return "<Joiner of word graphs>";
3788 }
3789
3812 template <typename Node>
3813 [[deprecated]] [[nodiscard]] std::string
3815 std::string const& prefix = "",
3816 std::string const& braces = "{}",
3817 std::string const& suffix = "");
3818} // namespace libsemigroups
3819
3820#include "word-graph.tpp"
3821
3822#endif // LIBSEMIGROUPS_WORD_GRAPH_HPP_
T cbegin(T... args)
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
Class for taking joins of word graphs.
Definition word-graph.hpp:3115
bool is_subrelation_no_checks(WordGraph< Node > const &x, WordGraph< Node > const &y)
Check if the language accepted by one word graph is contained in that defined by another word graph.
auto call_no_checks(WordGraph< Node > const &x, Args &&... args)
Returns a word graph containing the join/meet of two given word graphs.
auto operator()(WordGraph< Node > const &x, Args &&... args)
Returns a word graph containing the join/meet of two given word graphs.
Joiner(Joiner const &)
Default copy constructor.
void call_no_checks(WordGraph< Node > &xy, WordGraph< Node > const &x, Node xroot, WordGraph< Node > const &y, Node yroot)
Replace the contents of a word graph with the join/meet of two given word graphs with respect to give...
bool is_subrelation(WordGraph< Node1 > const &x, Node2 xroot, WordGraph< Node1 > const &y, Node2 yroot)
Check if the language accepted by one word graph is contained in that defined by another word graph.
Joiner(Joiner &&)
Default move constructor.
bool is_subrelation_no_checks(WordGraph< Node1 > const &x, Node2 xroot, WordGraph< Node1 > const &y, Node2 yroot)
Check if the language accepted by one word graph is contained in that defined by another word graph.
Joiner()
Default constructor.
Joiner & operator=(Joiner const &)
Default copy assignment operator.
void call_no_checks(WordGraph< Node > &xy, WordGraph< Node > const &x, WordGraph< Node > const &y)
Replace the contents of a word graph with the join/meet of two given word graphs with respect to give...
Joiner & operator=(Joiner &&)
Default move assignment operator.
bool is_subrelation(WordGraph< Node > const &x, WordGraph< Node > const &y)
Check if the language accepted by one word graph is contained in that defined by another word graph.
void operator()(WordGraph< Node > &xy, WordGraph< Node > const &x, WordGraph< Node > const &y)
Replace the contents of a word graph with the join/meet of two given word graphs with respect to give...
void call_no_checks(WordGraph< Node > &xy, WordGraph< Node > const &x, size_t xnum_nodes_reachable_from_root, Node xroot, WordGraph< Node > const &y, size_t ynum_nodes_reachable_from_root, Node yroot)
Replace the contents of a word graph with the join/meet of two given word graphs with respect to give...
bool is_subrelation_no_checks(WordGraph< Node1 > const &x, size_t xnum_nodes_reachable_from_root, Node2 xroot, WordGraph< Node1 > const &y, size_t ynum_nodes_reachable_from_root, Node2 yroot)
Check if the language accepted by one word graph is contained in that accepted by another word graph.
void operator()(WordGraph< Node > &xy, WordGraph< Node > const &x, Node xroot, WordGraph< Node > const &y, Node yroot)
Replace the contents of a word graph with the join/meet of two given word graphs with respect to give...
Class for taking meets of word graphs.
Definition word-graph.hpp:3555
bool is_subrelation_no_checks(WordGraph< Node > const &x, WordGraph< Node > const &y)
Check if the language accepted by one word graph is contained in that defined by another word graph.
auto call_no_checks(WordGraph< Node > const &x, Args &&... args)
Returns a word graph containing the join/meet of two given word graphs.
auto operator()(WordGraph< Node > const &x, Args &&... args)
Returns a word graph containing the join/meet of two given word graphs.
void call_no_checks(WordGraph< Node > &xy, WordGraph< Node > const &x, Node xroot, WordGraph< Node > const &y, Node yroot)
Replace the contents of a word graph with the join/meet of two given word graphs with respect to give...
bool is_subrelation(WordGraph< Node1 > const &x, Node2 xroot, WordGraph< Node1 > const &y, Node2 yroot)
Check if the language accepted by one word graph is contained in that defined by another word graph.
bool is_subrelation_no_checks(WordGraph< Node1 > const &x, Node2 xroot, WordGraph< Node1 > const &y, Node2 yroot)
Check if the language accepted by one word graph is contained in that defined by another word graph.
Meeter & operator=(Meeter const &)
Default copy assignment operator.
void call_no_checks(WordGraph< Node > &xy, WordGraph< Node > const &x, WordGraph< Node > const &y)
Replace the contents of a word graph with the join/meet of two given word graphs with respect to give...
Meeter()
Default constructor.
Meeter & operator=(Meeter &&)
Default move assignment operator.
bool is_subrelation(WordGraph< Node > const &x, WordGraph< Node > const &y)
Check if the language accepted by one word graph is contained in that defined by another word graph.
void operator()(WordGraph< Node > &xy, WordGraph< Node > const &x, WordGraph< Node > const &y)
Replace the contents of a word graph with the join/meet of two given word graphs with respect to give...
Meeter(Meeter &&)
Default move constructor.
void call_no_checks(WordGraph< Node > &xy, WordGraph< Node > const &x, size_t xnum_nodes_reachable_from_root, Node xroot, WordGraph< Node > const &y, size_t ynum_nodes_reachable_from_root, Node yroot)
Replace the contents of a word graph with the join/meet of two given word graphs with respect to give...
Meeter(Meeter const &)
Default copy constructor.
bool is_subrelation_no_checks(WordGraph< Node1 > const &x, size_t xnum_nodes_reachable_from_root, Node2 xroot, WordGraph< Node1 > const &y, size_t ynum_nodes_reachable_from_root, Node2 yroot)
Check if the language accepted by one word graph is contained in that accepted by another word graph.
void operator()(WordGraph< Node > &xy, WordGraph< Node > const &x, Node xroot, WordGraph< Node > const &y, Node yroot)
Replace the contents of a word graph with the join/meet of two given word graphs with respect to give...
Class for representing word graphs.
Definition word-graph.hpp:83
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > adjacency_matrix_type
Definition word-graph.hpp:109
bool operator<(WordGraph const &that) const
Check if a word graph is less than another.
Definition word-graph.hpp:560
element_index_type node_type
Definition word-graph.hpp:99
auto nodes() const noexcept
Returns a range object containing all nodes in a word graph.
Definition word-graph.hpp:987
auto labels_and_targets(node_type source) const
Returns a range object containing pairs consisting of edge labels and target nodes.
const_iterator_nodes cend_nodes() const noexcept
Returns a random access iterator pointing one-past-the-last node of the word graph.
Definition word-graph.hpp:878
WordGraph & disjoint_union_inplace(WordGraph< Node > const &that)
Unites a word graph in-place.
std::pair< label_type, node_type > next_label_and_target_no_checks(node_type s, label_type a) const
Get the next target of an edge incident to a given node that doesn't equal UNDEFINED.
WordGraph & remove_label(label_type a)
Removes a given label from the word graph.
WordGraph & swap_targets(node_type m, node_type n, label_type a)
Swaps the edge with specified label from one node with another.
size_type number_of_edges() const
Returns the number of edges.
bool operator>(WordGraph const &that) const
Check if a word graph is greater than another.
Definition word-graph.hpp:600
const_iterator_targets cbegin_targets_no_checks(node_type source) const noexcept
Returns a random access iterator pointing at the target of the edge with label 0 incident to a given ...
Definition word-graph.hpp:926
element_index_type label_type
Definition word-graph.hpp:102
bool operator<=(WordGraph const &that) const
Check if a word graph is less than or equal to another.
Definition word-graph.hpp:580
auto labels_and_targets_no_checks(node_type source) const noexcept
Returns a range object containing pairs consisting of edge labels and target nodes.
Definition word-graph.hpp:1061
WordGraph & induced_subgraph(node_type first, node_type last)
Modify in-place to contain the subgraph induced by a range of nodes.
rx::iterator_range< const_iterator_targets > targets_no_checks(node_type source) const noexcept
Returns a range object containing all the targets of edges with a given source.
Definition word-graph.hpp:1023
WordGraph & remove_all_targets()
Remove all of the edges in the word graph.
Definition word-graph.hpp:457
const_iterator_targets cbegin_targets(node_type source) const
Returns a random access iterator pointing at the target of the edge with label 0 incident to a given ...
WordGraph & disjoint_union_inplace_no_checks(WordGraph< Node > const &that)
Unites a word graph in-place.
WordGraph & remove_target(node_type s, label_type a)
Remove an edge from a node with a given label.
WordGraph & swap_targets_no_checks(node_type m, node_type n, label_type a)
Swaps the edge with specified label from one node with another.
Definition word-graph.hpp:482
bool operator>=(WordGraph const &that) const
Check if a word graph is greater than or equal to another.
Definition word-graph.hpp:620
bool operator!=(WordGraph const &that) const
Check if two word graphs are inequal.
Definition word-graph.hpp:540
auto labels() const noexcept
Returns a range object containing all labels of edges in a word graph.
Definition word-graph.hpp:1001
WordGraph & reserve(size_type m, size_type n)
Ensures that the word graph has capacity for a given number of nodes, and out-degree.
const_iterator_targets cend_targets_no_checks(node_type source) const noexcept
Returns a random access iterator pointing one beyond the target of the edge with label out_degree() -...
Definition word-graph.hpp:974
size_type out_degree() const noexcept
Definition word-graph.hpp:842
const_iterator_nodes cbegin_nodes() const noexcept
Returns a random access iterator pointing at the first node of the word graph.
Definition word-graph.hpp:860
bool operator==(WordGraph const &that) const
Check if two word graphs are equal.
Definition word-graph.hpp:520
typename detail::DynamicArray2< element_index_type >::const_iterator const_iterator_targets
Definition word-graph.hpp:124
rx::iterator_range< const_iterator_targets > targets(node_type source) const
Returns a range object containing all the targets of edges with a given source.
WordGraph & operator=(WordGraph const &)
Default copy assignment constructor.
WordGraph & target(node_type s, label_type a, node_type t)
Add an edge from one node to another with a given label.
WordGraph & add_nodes(size_type nr)
Add a number of new nodes.
WordGraph & target_no_checks(node_type s, label_type a, node_type t)
Add an edge from one node to another with a given label.
Definition word-graph.hpp:374
const_iterator_targets cend_targets(node_type source) const
Returns a random access iterator pointing one beyond the target of the edge with label out_degree() -...
WordGraph & init(size_type m=0, size_type n=0)
Re-initialize the word graph to have m nodes and out-degree n.
WordGraph & remove_target_no_checks(node_type s, label_type a)
Remove an edge from a node with a given label.
Definition word-graph.hpp:396
std::pair< label_type, node_type > next_label_and_target(node_type s, label_type a) const
Get the next target of an edge incident to a given node that doesn't equal UNDEFINED.
typename detail::IntRange< element_index_type >::const_reverse_iterator const_reverse_iterator_nodes
Definition word-graph.hpp:120
WordGraph & remove_label_no_checks(label_type a)
Removes a given label from the word graph.
WordGraph & add_to_out_degree(size_type nr)
Add to the out-degree of every node.
static WordGraph random(size_type number_of_nodes, size_type out_degree, std::mt19937 mt=std::mt19937(std::random_device()()))
Construct a random word graph from number of nodes and out-degree.
size_t hash_value() const
Returns a hash value.
Definition word-graph.hpp:635
size_type number_of_nodes() const noexcept
Definition word-graph.hpp:766
typename detail::IntRange< element_index_type >::const_iterator const_iterator_nodes
Definition word-graph.hpp:116
std::size_t size_type
Definition word-graph.hpp:105
WordGraph & induced_subgraph_no_checks(node_type first, node_type last)
Modify in-place to contain the subgraph induced by a range of nodes.
size_type number_of_edges_no_checks(node_type s) const
Returns the number of edges with given source node.
T cend(T... args)
T fill(T... args)
T forward(T... args)
std::string to_human_readable_repr(Action< Element, Point, Func, Traits, LeftOrRight > const &action)
Return a human readable representation of an Action object.
std::ostringstream & operator<<(std::ostringstream &os, BMat8 const &x)
Insertion operator.
Undefined const UNDEFINED
Value for something undefined.
std::conditional_t< R==0||C==0, DynamicIntMat< Scalar >, StaticIntMat< R, C, Scalar > > IntMat
Alias template for integer matrices.
Definition matrix.hpp:4300
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::string to_input_string(Transf< N, Scalar > const &x, std::string_view prefix="", std::string_view braces="{}")
Return a string that can be used to recreate a transformation.
constexpr bool is_specialization_of_v
Helper variable template for is_specialization_of.
Definition is_specialization_of.hpp:84
std::vector< letter_type > word_type
Type for a word over the generators of a semigroup.
Definition types.hpp:99
Order
The possible orderings of words and strings.
Definition order.hpp:54
@ shortlex
Definition order.hpp:60
static constexpr bool IsWordGraph
Helper variable template.
Definition word-graph.hpp:2900
Namespace containing helper functions for the WordGraph class.
Definition word-graph.hpp:1227
auto adjacency_matrix(WordGraph< Node > const &wg)
Returns the adjacency matrix of a word graph.
void spanning_tree_no_checks(WordGraph< Node1 > const &wg, Node2 root, Forest &f)
Replace the contents of a Forest by a spanning tree of the nodes reachable from a given node in a wor...
void throw_if_any_target_out_of_bounds(WordGraph< Node > const &wg)
Throws if the target of any edge is out of bounds.
std::unordered_set< Node1 > ancestors_of_no_checks(WordGraph< Node1 > const &wg, Node2 target)
Returns the std::unordered_set of nodes that can reach a given node in a word graph.
void throw_if_node_out_of_bounds(WordGraph< Node1 > const &wg, Node2 n)
Throws if a node is out of bounds.
std::pair< Node1, Iterator > last_node_on_path(WordGraph< Node1 > const &wg, Node2 source, Iterator first, Iterator last)
Returns the last node on the path labelled by a word and an iterator to the position in the word reac...
bool is_strictly_cyclic(WordGraph< Node > const &wg)
Check if every node is reachable from some node.
std::unordered_set< Node1 > nodes_reachable_from(WordGraph< Node1 > const &wg, Node2 source)
Returns the std::unordered_set of nodes reachable from a given node in a word graph.
bool is_connected(WordGraph< Node > const &wg)
Check if a word graph is connected.
bool equal_to_no_checks(WordGraph< Node > const &x, WordGraph< Node > const &y, Node first, Node last)
Compares two word graphs on a range of nodes.
bool equal_to(WordGraph< Node > const &x, WordGraph< Node > const &y, Node first, Node last)
Compares two word graphs on a range of nodes.
size_t number_of_nodes_reachable_from(WordGraph< Node1 > const &wg, Node2 source)
Returns the number of nodes reachable from a given node in a word graph.
Definition word-graph.hpp:2436
bool is_reachable(WordGraph< Node1 > const &wg, Node2 source, Node2 target)
Check if there is a path from one node to another.
bool is_compatible(WordGraph< Node > const &wg, Iterator1 first_node, Iterator2 last_node, Iterator3 first_rule, Iterator3 last_rule)
Check if a word graph is compatible with some relations at a range of nodes.
std::vector< Node > topological_sort(WordGraph< Node > const &wg)
Returns the nodes of the word graph in topological order (see below) if possible.
bool is_complete(WordGraph< Node > const &wg, Iterator1 first_node, Iterator2 last_node)
Check if every node in a range has exactly WordGraph::out_degree out-edges.
std::pair< Node1, Iterator > last_node_on_path_no_checks(WordGraph< Node1 > const &wg, Node2 source, Iterator first, Iterator last) noexcept
Returns the last node on the path labelled by a word and an iterator to the position in the word reac...
std::unordered_set< Node1 > nodes_reachable_from_no_checks(WordGraph< Node1 > const &wg, Node2 source)
Returns the std::unordered_set of nodes reachable from a given node in a word graph.
std::unordered_set< Node1 > ancestors_of(WordGraph< Node1 > const &wg, Node2 target)
Returns the std::unordered_set of nodes that can reach a given node in a word graph.
WordGraph< Node > random_acyclic(size_t number_of_nodes, size_t out_degree, std::mt19937 mt=std::mt19937(std::random_device()()))
Construct a random connected acyclic word graph with given number of nodes, and out-degree.
void throw_if_label_out_of_bounds(WordGraph< Node > const &wg, typename WordGraph< Node >::label_type a)
Throws if a label is out of bounds.
void add_cycle(WordGraph< Node > &wg, size_t N)
Adds a cycle consisting of N new nodes.
Definition word-graph.hpp:1281
bool is_compatible_no_checks(WordGraph< Node > const &wg, Iterator1 first_node, Iterator2 last_node, Iterator3 first_rule, Iterator3 last_rule)
Check if a word graph is compatible with some relations at a range of nodes.
bool is_reachable_no_checks(WordGraph< Node1 > const &wg, Node2 source, Node2 target)
Check if there is a path from one node to another.
bool standardize(Graph &wg, Forest &f, Order val)
Standardizes a word graph in-place.
size_t number_of_nodes_reachable_from_no_checks(WordGraph< Node1 > const &wg, Node2 source)
Returns the number of nodes reachable from a given node in a word graph.
Definition word-graph.hpp:2463
bool is_complete_no_checks(WordGraph< Node > const &wg, Iterator1 first_node, Iterator2 last_node)
Check if every node in a range has exactly WordGraph::out_degree out-edges.
Node1 follow_path_no_checks(WordGraph< Node1 > const &wg, Node2 from, Iterator first, Iterator last) noexcept
Follow the path from a specified node labelled by a word.
bool is_standardized(WordGraph< Node > const &wg, Order val=Order::shortlex)
Check if a word graph is standardized.
bool is_acyclic(WordGraph< Node > const &wg)
Check if a word graph is acyclic.
void spanning_tree(WordGraph< Node1 > const &wg, Node2 root, Forest &f)
Replace the contents of a Forest by a spanning tree of the nodes reachable from a given node in a wor...
Node1 follow_path(WordGraph< Node1 > const &wg, Node2 source, Iterator first, Iterator last)
Find the node that a path starting at a given node leads to (if any).
void add_cycle_no_checks(WordGraph< Node > &wg, Iterator first, Iterator last)
Adds a cycle involving the specified range of nodes to a word graph.
Dot dot(WordGraph< Node > const &wg)
Returns a Dot object representing a word graph.
Namespace for everything in the libsemigroups library.
Definition action.hpp:44
T size(T... args)