libsemigroups  v3.2.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
1255 // TODO(1) add add_cycle with checks version.
1256 template <typename Node, typename Iterator>
1258 Iterator first,
1259 Iterator last);
1260
1276 template <typename Node>
1277 void add_cycle(WordGraph<Node>& wg, size_t N) {
1278 size_t M = wg.number_of_nodes();
1279 wg.add_nodes(N);
1280 add_cycle_no_checks(wg, wg.cbegin_nodes() + M, wg.cend_nodes());
1281 }
1282
1297 template <typename Node>
1298 [[nodiscard]] auto adjacency_matrix(WordGraph<Node> const& wg);
1299
1310 template <typename Node>
1311 [[nodiscard]] Dot dot(WordGraph<Node> const& wg);
1312
1339 template <typename Node>
1340 [[nodiscard]] bool equal_to_no_checks(WordGraph<Node> const& x,
1341 WordGraph<Node> const& y,
1342 Node first,
1343 Node last);
1344
1369 template <typename Node>
1370 [[nodiscard]] bool equal_to(WordGraph<Node> const& x,
1371 WordGraph<Node> const& y,
1372 Node first,
1373 Node last);
1374
1406 template <typename Node1, typename Node2, typename Iterator>
1407 [[nodiscard]] Node1 follow_path(WordGraph<Node1> const& wg,
1408 Node2 source,
1409 Iterator first,
1410 Iterator last);
1411
1439 // TODO(2) example
1440 // not noexcept because WordGraph::target isn't
1441 template <typename Node1, typename Node2>
1442 [[nodiscard]] Node1 follow_path(WordGraph<Node1> const& wg,
1443 Node2 from,
1444 word_type const& path) {
1445 static_assert(sizeof(Node2) <= sizeof(Node1));
1446 return follow_path(wg, from, path.cbegin(), path.cend());
1447 }
1448
1475 template <typename Node1, typename Node2, typename Iterator>
1476 [[nodiscard]] Node1 follow_path_no_checks(WordGraph<Node1> const& wg,
1477 Node2 from,
1478 Iterator first,
1479 Iterator last) noexcept;
1480
1507 template <typename Node1, typename Node2>
1508 [[nodiscard]] Node1 follow_path_no_checks(WordGraph<Node1> const& wg,
1509 Node2 from,
1510 word_type const& path) noexcept {
1511 static_assert(sizeof(Node2) <= sizeof(Node1));
1512 return follow_path_no_checks(wg, from, path.cbegin(), path.cend());
1513 }
1514
1547 // Not noexcept because detail::is_acyclic isn't
1548 template <typename Node>
1549 [[nodiscard]] bool is_acyclic(WordGraph<Node> const& wg);
1550
1595 // Not noexcept because detail::is_acyclic isn't
1596 template <typename Node1, typename Node2>
1597 [[nodiscard]] bool is_acyclic(WordGraph<Node1> const& wg, Node2 source);
1598
1628 // Not noexcept because detail::is_acyclic isn't
1629 template <typename Node1, typename Node2>
1630 [[nodiscard]] bool is_acyclic(WordGraph<Node1> const& wg,
1631 Node2 source,
1632 Node2 target);
1633
1673 // TODO(1) add a version of this function with one that returns a float
1674 // representing the proportion of the nodes in the range that are compatible
1675 // with the rules. Don't replace the current version because it can return
1676 // early knowing that it isn't compatible.
1677 template <typename Node,
1678 typename Iterator1,
1679 typename Iterator2,
1680 typename Iterator3>
1681 [[nodiscard]] bool is_compatible_no_checks(WordGraph<Node> const& wg,
1682 Iterator1 first_node,
1683 Iterator2 last_node,
1684 Iterator3 first_rule,
1685 Iterator3 last_rule);
1686
1728 template <
1729 typename Node,
1730 typename Iterator1,
1731 typename Iterator2,
1732 typename Iterator3,
1733 std::enable_if_t<!std::is_same_v<std::decay_t<Iterator3>, word_type>>>
1734 [[nodiscard]] bool is_compatible(WordGraph<Node> const& wg,
1735 Iterator1 first_node,
1736 Iterator2 last_node,
1737 Iterator3 first_rule,
1738 Iterator3 last_rule);
1739
1771 template <typename Node, typename Iterator1, typename Iterator2>
1773 Iterator1 first_node,
1774 Iterator2 last_node,
1775 word_type const& lhs,
1776 word_type const& rhs);
1777
1813 template <typename Node, typename Iterator1, typename Iterator2>
1815 Iterator1 first_node,
1816 Iterator2 last_node,
1817 word_type const& lhs,
1818 word_type const& rhs);
1819
1851 template <typename Node, typename Iterator1, typename Iterator2>
1852 [[nodiscard]] bool is_complete_no_checks(WordGraph<Node> const& wg,
1853 Iterator1 first_node,
1854 Iterator2 last_node);
1855
1885 template <typename Node, typename Iterator1, typename Iterator2>
1886 [[nodiscard]] bool is_complete(WordGraph<Node> const& wg,
1887 Iterator1 first_node,
1888 Iterator2 last_node);
1889
1907 template <typename Node>
1908 [[nodiscard]] bool is_complete(WordGraph<Node> const& wg) noexcept {
1909 return wg.number_of_edges() == wg.number_of_nodes() * wg.out_degree();
1910 }
1911
1933 template <typename Node>
1934 [[nodiscard]] bool is_connected(WordGraph<Node> const& wg);
1935
1985 template <typename Node1, typename Node2>
1986 [[nodiscard]] bool is_reachable_no_checks(WordGraph<Node1> const& wg,
1987 Node2 source,
1988 Node2 target);
1989
2021 template <typename Node1, typename Node2>
2022 [[nodiscard]] bool is_reachable(WordGraph<Node1> const& wg,
2023 Node2 source,
2024 Node2 target);
2025
2057 // TODO(1) should have a version that returns the node that everything is
2058 // reachable from
2059 template <typename Node>
2060 [[nodiscard]] bool is_strictly_cyclic(WordGraph<Node> const& wg);
2061
2088 template <typename Node1, typename Node2, typename Iterator>
2089 [[nodiscard]] std::pair<Node1, Iterator>
2091 Node2 source,
2092 Iterator first,
2093 Iterator last) noexcept;
2094
2120 template <typename Node1, typename Node2, typename Iterator>
2121 [[nodiscard]] std::pair<Node1, Iterator>
2123 Node2 source,
2124 Iterator first,
2125 Iterator last);
2126
2148 template <typename Node1, typename Node2>
2151 Node2 source,
2152 word_type const& w);
2153
2175 template <typename Node1, typename Node2>
2178 Node2 source,
2179 word_type const& w);
2180
2201 // TODO(1) tests
2202 // TODO(1) version where std::unordered_set is passed by reference, or make
2203 // this a class that stores its stack and unordered_set, not clear why we'd
2204 // single out the unordered_set to be passed by reference.
2205 // TODO(2) version which is an iterator i.e. returns an iterator or range
2206 // object that allows use to step through the nodes reachable from a given
2207 // node
2208 template <typename Node1, typename Node2>
2209 [[nodiscard]] std::unordered_set<Node1>
2210 nodes_reachable_from(WordGraph<Node1> const& wg, Node2 source);
2211
2232 template <typename Node1, typename Node2>
2233 [[nodiscard]] std::unordered_set<Node1>
2234 ancestors_of(WordGraph<Node1> const& wg, Node2 target);
2235
2257 template <typename Node1, typename Node2>
2258 [[nodiscard]] std::unordered_set<Node1>
2260
2282 template <typename Node1, typename Node2>
2283 [[nodiscard]] std::unordered_set<Node1>
2285
2306 template <typename Node1, typename Node2>
2307 [[nodiscard]] size_t
2309 return nodes_reachable_from(wg, source).size();
2310 }
2311
2330 template <typename Node1, typename Node2>
2331 [[nodiscard]] size_t
2333 Node2 source) {
2334 return nodes_reachable_from_no_checks(wg, source).size();
2335 }
2336
2358 template <typename Node>
2359 WordGraph<Node> random_acyclic(size_t number_of_nodes,
2360 size_t out_degree,
2361 std::mt19937 mt
2363
2383 template <typename Node1, typename Node2>
2385 Node2 root,
2386 Forest& f);
2387
2406 template <typename Node1, typename Node2>
2407 void spanning_tree(WordGraph<Node1> const& wg, Node2 root, Forest& f);
2408
2429 template <typename Node1, typename Node2>
2431 Node2 root);
2432
2452 template <typename Node1, typename Node2>
2453 [[nodiscard]] Forest spanning_tree(WordGraph<Node1> const& wg, Node2 root);
2454
2478 // Not nodiscard because sometimes we just don't want the output
2479 template <typename Graph>
2480 bool standardize(Graph& wg, Forest& f, Order val);
2481
2505 // Not nodiscard because sometimes we just don't want the output
2506 template <typename Graph>
2508
2525 template <typename Node>
2527 Order val = Order::shortlex);
2528
2542 template <typename Node>
2544
2566 template <typename Node, typename Iterator>
2568 Iterator first,
2569 Iterator last);
2570
2582 // not noexcept because it throws an exception!
2583 template <typename Node>
2585 typename WordGraph<Node>::label_type a);
2586
2599 template <typename Node>
2601 word_type const& word);
2602
2618 template <typename Node, typename Iterator>
2620 Iterator first,
2621 Iterator last);
2622
2635 // not noexcept because it throws an exception!
2636 template <typename Node1, typename Node2>
2638
2654 // not noexcept because it throws an exception!
2655 template <typename Node, typename Iterator1, typename Iterator2>
2657 Iterator1 first,
2658 Iterator2 last);
2659
2683 template <typename Node>
2685
2712 template <typename Node1, typename Node2>
2713 [[nodiscard]] std::vector<Node1>
2714 topological_sort(WordGraph<Node1> const& wg, Node2 source);
2715
2716 } // namespace word_graph
2717
2719 // WordGraph - non-member functions
2721
2731 template <typename Thing>
2732 static constexpr bool IsWordGraph [[deprecated]]
2734
2754 template <typename Node>
2756
2767
2796 // Passing the 2nd parameter "targets" by value disambiguates it from the
2797 // other make<WordGraph>.
2798 template <typename Return>
2799 [[nodiscard]] std::enable_if_t<is_specialization_of_v<Return, WordGraph>,
2800 Return>
2801 make(size_t num_nodes,
2803
2806 // clang-format off
2807 // NOLINTNEXTLINE(whitespace/line_length)
2809 // clang-format on
2810 template <typename Return>
2811 [[nodiscard]] std::enable_if_t<is_specialization_of_v<Return, WordGraph>,
2812 Return>
2813 make(size_t num_nodes,
2815
2816 namespace detail {
2817 template <typename Subclass>
2818 class JoinerMeeterCommon {
2819 private:
2820 template <typename Node1, typename Node2>
2821 void throw_if_bad_args(WordGraph<Node1> const& x,
2822 Node2 xroot,
2823 WordGraph<Node1> const& y,
2824 Node2 yroot);
2825
2826 public:
2827 template <typename Node>
2828 void call_no_checks(WordGraph<Node>& xy,
2829 WordGraph<Node> const& x,
2830 Node xroot,
2831 WordGraph<Node> const& y,
2832 Node yroot);
2833
2834 template <typename Node>
2835 void call_no_checks(WordGraph<Node>& xy,
2836 WordGraph<Node> const& x,
2837 WordGraph<Node> const& y) {
2838 return call_no_checks(
2839 xy, x, static_cast<Node>(0), y, static_cast<Node>(0));
2840 }
2841
2842 template <typename Node, typename... Args>
2843 [[nodiscard]] auto call_no_checks(WordGraph<Node> const& x,
2844 Args&&... args)
2845 -> std::enable_if_t<sizeof...(Args) % 2 == 1, WordGraph<Node>> {
2846 // The versions of this function changing the 1st argument in-place
2847 // always have an odd number of arguments, so we check that it's even
2848 // here (the argument x and an odd number of further arguments).
2849 WordGraph<Node> xy;
2850 static_cast<Subclass&>(*this).call_no_checks(
2851 xy, x, std::forward<Args>(args)...);
2852 return xy;
2853 }
2854
2855 // There's no operator() with the number of nodes reachable from the
2856 // roots as arguments (7 args in total) because we'd have to check that
2857 // they were valid, and the only way to do this is to recompute them.
2858
2859 template <typename Node>
2860 void operator()(WordGraph<Node>& xy,
2861 WordGraph<Node> const& x,
2862 Node xroot,
2863 WordGraph<Node> const& y,
2864 Node yroot) {
2865 throw_if_bad_args(x, xroot, y, yroot);
2866 call_no_checks(xy, x, xroot, y, yroot);
2867 }
2868
2869 template <typename Node>
2870 void operator()(WordGraph<Node>& xy,
2871 WordGraph<Node> const& x,
2872 WordGraph<Node> const& y) {
2873 return operator()(xy, x, static_cast<Node>(0), y, static_cast<Node>(0));
2874 }
2875
2876 template <typename Node, typename... Args>
2877 [[nodiscard]] auto operator()(WordGraph<Node> const& x, Args&&... args)
2878 -> std::enable_if_t<sizeof...(Args) % 2 == 1, WordGraph<Node>> {
2879 // The versions of this function changing the 1st argument in-place
2880 // always have an odd number of arguments, so we check that it's even
2881 // here (the argument x and an odd number of further arguments).
2882 WordGraph<Node> xy;
2883 operator()(xy, x, std::forward<Args>(args)...);
2884 return xy;
2885 }
2886
2887 template <typename Node1, typename Node2>
2888 bool is_subrelation_no_checks(WordGraph<Node1> const& x,
2889 Node2 xroot,
2890 WordGraph<Node1> const& y,
2891 Node2 yroot);
2892
2893 template <typename Node>
2894 bool is_subrelation_no_checks(WordGraph<Node> const& x,
2895 WordGraph<Node> const& y) {
2896 return is_subrelation_no_checks(
2897 x, static_cast<Node>(0), y, static_cast<Node>(0));
2898 }
2899
2900 // There's no subrelation with the number of nodes reachable from the
2901 // roots as arguments (6 args in total) because we'd have to check that
2902 // they were valid, and the only way to do this is to recompute them.
2903
2904 template <typename Node1, typename Node2>
2905 bool is_subrelation(WordGraph<Node1> const& x,
2906 Node2 xroot,
2907 WordGraph<Node1> const& y,
2908 Node2 yroot) {
2909 throw_if_bad_args(x, xroot, y, yroot);
2910 return is_subrelation_no_checks(x, xroot, y, yroot);
2911 }
2912
2913 template <typename Node>
2914 bool is_subrelation(WordGraph<Node> const& x, WordGraph<Node> const& y) {
2915 return is_subrelation(x, static_cast<Node>(0), y, static_cast<Node>(0));
2916 }
2917 }; // JoinerMeeterCommon
2918 } // namespace detail
2919
2931 // This class is intentionally not a template so that we don't have to
2932 // specify the types of the nodes when constructing one of these objects.
2933 // Instead every member function has a template parameter Node, which is
2934 // deduced from the argument.
2935 class Joiner : public detail::JoinerMeeterCommon<Joiner> {
2936 private:
2937 detail::Duf<> _uf;
2939 std::vector<uint64_t> _lookup;
2940
2941 template <typename Node>
2942 [[nodiscard]] Node find(WordGraph<Node> const& x,
2943 size_t xnum_nodes_reachable_from_root,
2944 WordGraph<Node> const& y,
2945 uint64_t n,
2946 typename WordGraph<Node>::label_type a) const;
2947
2948 template <typename Node>
2949 void run(WordGraph<Node> const& x,
2950 size_t xnum_nodes_reachable_from_root,
2951 Node xroot,
2952 WordGraph<Node> const& y,
2953 size_t ynum_nodes_reachable_from_root,
2954 Node yroot);
2955
2956 public:
2961
2966
2971
2976
2981
2982 ~Joiner();
2983
3012 template <typename Node>
3014 WordGraph<Node> const& x,
3015 size_t xnum_nodes_reachable_from_root,
3016 Node xroot,
3017 WordGraph<Node> const& y,
3018 size_t ynum_nodes_reachable_from_root,
3019 Node yroot);
3020
3054 // Is x a subrelation of y?
3055 template <typename Node1, typename Node2>
3056 [[nodiscard]] bool
3058 size_t xnum_nodes_reachable_from_root,
3059 Node2 xroot,
3060 WordGraph<Node1> const& y,
3061 size_t ynum_nodes_reachable_from_root,
3062 Node2 yroot);
3063#ifdef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
3087 template <typename Node>
3089 WordGraph<Node> const& x,
3090 Node xroot,
3091 WordGraph<Node> const& y,
3092 Node yroot);
3093
3113 template <typename Node>
3115 WordGraph<Node> const& x,
3116 WordGraph<Node> const& y);
3117
3137 template <typename Node, typename... Args>
3138 [[nodiscard]] auto call_no_checks(WordGraph<Node> const& x, Args&&... args);
3139
3165 template <typename Node>
3167 WordGraph<Node> const& x,
3168 Node xroot,
3169 WordGraph<Node> const& y,
3170 Node yroot);
3171
3193 template <typename Node>
3195 WordGraph<Node> const& x,
3196 WordGraph<Node> const& y);
3197
3215 template <typename Node, typename... Args>
3216 [[nodiscard]] auto operator()(WordGraph<Node> const& x, Args&&... args);
3217
3247 // Is x a subrelation of y?
3248 template <typename Node1, typename Node2>
3250 Node2 xroot,
3251 WordGraph<Node1> const& y,
3252 Node2 yroot);
3253
3276 template <typename Node>
3278 WordGraph<Node> const& y);
3279
3280 // There's no subrelation with the number of nodes reachable from the
3281 // roots as arguments (6 args in total) because we'd have to check that
3282 // they were valid, and the only way to do this is to recompute them.
3283
3312 template <typename Node1, typename Node2>
3314 Node2 xroot,
3315 WordGraph<Node1> const& y,
3316 Node2 yroot);
3317
3342 template <typename Node>
3344
3345#else
3346 using detail::JoinerMeeterCommon<Joiner>::call_no_checks;
3347 using detail::JoinerMeeterCommon<Joiner>::operator();
3348 using detail::JoinerMeeterCommon<Joiner>::is_subrelation_no_checks;
3349 using detail::JoinerMeeterCommon<Joiner>::is_subrelation;
3350#endif
3351 }; // Joiner
3352
3365 // Class for forming the meet of two word graphs
3366 class Meeter : public detail::JoinerMeeterCommon<Meeter> {
3367 private:
3368 using node_type = std::pair<uint64_t, uint64_t>;
3369
3372 std::vector<node_type> _todo_new;
3373
3374 public:
3379
3384
3389
3394
3399
3400 ~Meeter();
3401
3404 template <typename Node>
3406 WordGraph<Node> const& x,
3407 size_t xnum_nodes_reachable_from_root,
3408 Node xroot,
3409 WordGraph<Node> const& y,
3410 size_t ynum_nodes_reachable_from_root,
3411 Node yroot);
3412
3415 // is x a subrelation of y
3416 template <typename Node1, typename Node2>
3417 [[nodiscard]] bool
3419 size_t xnum_nodes_reachable_from_root,
3420 Node2 xroot,
3421 WordGraph<Node1> const& y,
3422 size_t ynum_nodes_reachable_from_root,
3423 Node2 yroot);
3424
3425#ifdef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
3428 template <typename Node>
3430 WordGraph<Node> const& x,
3431 Node xroot,
3432 WordGraph<Node> const& y,
3433 Node yroot);
3434
3437 template <typename Node>
3439 WordGraph<Node> const& x,
3440 WordGraph<Node> const& y);
3441
3461 template <typename Node, typename... Args>
3462 [[nodiscard]] auto call_no_checks(WordGraph<Node> const& x, Args&&... args);
3463
3466 template <typename Node>
3468 WordGraph<Node> const& x,
3469 Node xroot,
3470 WordGraph<Node> const& y,
3471 Node yroot);
3472
3475 template <typename Node>
3477 WordGraph<Node> const& x,
3478 WordGraph<Node> const& y);
3479
3497 template <typename Node, typename... Args>
3498 [[nodiscard]] auto operator()(WordGraph<Node> const& x, Args&&... args);
3499
3502 template <typename Node1, typename Node2>
3504 Node2 xroot,
3505 WordGraph<Node1> const& y,
3506 Node2 yroot);
3507
3510 template <typename Node>
3512 WordGraph<Node> const& y);
3513
3516 template <typename Node1, typename Node2>
3518 Node2 xroot,
3519 WordGraph<Node1> const& y,
3520 Node2 yroot);
3521
3524 template <typename Node>
3526#else
3527 using detail::JoinerMeeterCommon<Meeter>::call_no_checks;
3528 using detail::JoinerMeeterCommon<Meeter>::operator();
3529 using detail::JoinerMeeterCommon<Meeter>::is_subrelation_no_checks;
3530 using detail::JoinerMeeterCommon<Meeter>::is_subrelation;
3531#endif
3532 }; // class Meeter
3533
3548 template <typename Node>
3550
3563 [[nodiscard]] static inline std::string
3565 (void) meet;
3566 return "<Meeter of word graphs>";
3567 }
3568
3581 [[nodiscard]] static inline std::string
3583 (void) join;
3584 return "<Joiner of word graphs>";
3585 }
3586
3606 template <typename Node>
3608 std::string const& prefix = "",
3609 std::string const& braces = "{}",
3610 std::string const& suffix = "");
3611} // namespace libsemigroups
3612
3613#include "word-graph.tpp"
3614
3615#endif // LIBSEMIGROUPS_WORD_GRAPH_HPP_
T cbegin(T... args)
A representation of a graph in the DOT language of Graphviz.
Definition dot.hpp:115
Class representing a collection of spanning trees of a word graph.
Definition forest.hpp:42
Class for taking joins of word graphs.
Definition word-graph.hpp:2935
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:3366
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:4296
enable_if_is_same< Return, Blocks > make(Container const &cont)
Check the arguments, construct a Blocks object, and check it.
Definition bipart.hpp:855
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:83
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:45
@ shortlex
Definition order.hpp:51
static constexpr bool IsWordGraph
Helper variable template.
Definition word-graph.hpp:2733
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:2308
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:1277
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:2332
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)