libsemigroups  v3.0.0
C++ library for semigroups and monoids
Loading...
Searching...
No Matches
word-graph-with-sources.hpp
1//
2// libsemigroups - C++ library for semigroups and monoids
3// Copyright (C) 2022-2025 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 a declaration of a class for WordGraphs with
20// additional information about the edges leading into every node (not only
21// those leaving every node).
22//
23// In the comments in this file we refer to "valid nodes", this means nodes in
24// the graph where the values returned by first_source_no_checks and
25// next_source_no_checks are valid (i.e. correspond to edges in the underlying
26// WordGraph that point into the current node). Validity of nodes is not tracked
27// by WordGraphWithSources, and it is the responsibility of the caller to ensure
28// that nodes are valid where required by the various member functions of
29// WordGraphWithSources.
30
31#ifndef LIBSEMIGROUPS_DETAIL_WORD_GRAPH_WITH_SOURCES_HPP_
32#define LIBSEMIGROUPS_DETAIL_WORD_GRAPH_WITH_SOURCES_HPP_
33
34// TODO:
35// * test file
36// * doc
37// * add _no_checks where appropriate
38
39#include <cstddef> // for size_t
40#include <stack> // for stack
41#include <utility> // for pair
42#include <vector> // for vector
43
44#include "libsemigroups/config.hpp" // for LIBSEMIGROUPS_DEBUG
45#include "libsemigroups/constants.hpp" // for UNDEFINED
46#include "libsemigroups/types.hpp" // for letter_type
47#include "libsemigroups/word-graph.hpp" // for WordGraph
48
49#include "containers.hpp" // for DynamicArray2
50
51namespace libsemigroups {
52
53 namespace detail {
54 template <typename Node>
55 class WordGraphWithSources : public WordGraph<Node> {
56 public:
57 using node_type = Node;
58 using label_type = typename WordGraph<Node>::label_type;
59 using size_type = typename WordGraph<Node>::size_type;
60
61 private:
62 detail::DynamicArray2<node_type> _preim_init;
63 detail::DynamicArray2<node_type> _preim_next;
64
65 public:
66 // So that we can use out_degree and number_of_nodes in assertions
67 using WordGraph<Node>::out_degree;
68 using WordGraph<Node>::number_of_nodes;
69
70 explicit WordGraphWithSources(size_type m = 0, size_type n = 0)
71 : WordGraph<node_type>(m, n),
72 _preim_init(n, m, UNDEFINED),
73 _preim_next(n, m, UNDEFINED) {}
74
75 void init(size_type m = 0, size_type n = 0);
76
77 template <typename ThatNode>
78 explicit WordGraphWithSources(WordGraph<ThatNode> const& that);
79
80 template <typename ThatNode>
81 void init(WordGraph<ThatNode> const& that);
82
83 template <typename ThatNode>
84 explicit WordGraphWithSources(WordGraph<ThatNode>&& that);
85
86 template <typename ThatNode>
87 void init(WordGraph<ThatNode>&& that);
88
89 WordGraphWithSources(WordGraphWithSources&&) = default;
90 WordGraphWithSources(WordGraphWithSources const&) = default;
91 WordGraphWithSources& operator=(WordGraphWithSources const&) = default;
92 WordGraphWithSources& operator=(WordGraphWithSources&&) = default;
93
94 ~WordGraphWithSources();
95
96 // the template is for uniformity of interface with FelschGraph
97 template <bool = true>
98 void target_no_checks(node_type c, label_type x, node_type d) noexcept {
99 LIBSEMIGROUPS_ASSERT(c < number_of_nodes());
100 LIBSEMIGROUPS_ASSERT(x < out_degree());
101 LIBSEMIGROUPS_ASSERT(d < number_of_nodes());
103 add_source_no_checks(d, x, c);
104 }
105
106 // Can't use using WordGraph<node_type>::target here because it doesn't
107 // work (compiles but run time error, probably confusing the function
108 // above with the WordGraph<node_type> function of the same name
109 [[nodiscard]] node_type target(node_type v, label_type lbl) const {
110 return WordGraph<node_type>::target(v, lbl);
111 }
112
113 [[nodiscard]] node_type target_no_checks(node_type v,
114 label_type lbl) const {
116 }
117
118 void remove_target_no_checks(node_type c, label_type x) noexcept {
119 LIBSEMIGROUPS_ASSERT(c < number_of_nodes());
120 LIBSEMIGROUPS_ASSERT(x < out_degree());
121 remove_source_no_checks(WordGraph<Node>::target_no_checks(c, x), x, c);
123 }
124
125 void add_nodes(size_type m) {
127 _preim_init.add_rows(m);
128 _preim_next.add_rows(m);
129 }
130
131 void add_to_out_degree(size_type m) {
132 _preim_init.add_cols(m);
133 _preim_next.add_cols(m);
135 }
136
137 inline node_type first_source_no_checks(node_type c,
138 letter_type x) const noexcept {
139 LIBSEMIGROUPS_ASSERT(c < number_of_nodes());
140 LIBSEMIGROUPS_ASSERT(x < out_degree());
141 LIBSEMIGROUPS_ASSERT(c < _preim_init.number_of_rows());
142 LIBSEMIGROUPS_ASSERT(x < _preim_init.number_of_cols());
143 return _preim_init.get(c, x);
144 }
145
146 inline node_type next_source_no_checks(node_type c,
147 letter_type x) const noexcept {
148 LIBSEMIGROUPS_ASSERT(c < number_of_nodes());
149 LIBSEMIGROUPS_ASSERT(x < out_degree());
150 LIBSEMIGROUPS_ASSERT(c < _preim_next.number_of_rows());
151 LIBSEMIGROUPS_ASSERT(x < _preim_next.number_of_cols());
152 return _preim_next.get(c, x);
153 }
154
155 void induced_subgraph_no_checks(node_type first, node_type last);
156
157 // The permutation q must map the valid nodes to the [0, .. , n), where
158 // n is the number of valid nodes, and p = q ^ -1.
159 void permute_nodes_no_checks(std::vector<node_type> const& p,
160 std::vector<node_type> const& q,
161 size_t n);
162
163 // Swaps valid nodes c and d, if c or d is not valid, then this will
164 // fail spectacularly (no checks are performed)
165 void swap_nodes_no_checks(node_type c, node_type d);
166
167 // Rename c to d, i.e. node d has the exact same in- and out-neighbours
168 // as c after this is called. Assumed that c is valid when this function
169 // is called, and that d is valid after it is called. This is a
170 // one-sided version of swap nodes.
171 void rename_node_no_checks(node_type c, node_type d);
172
173 template <typename NewEdgeFunc, typename IncompatibleFunc>
174 void merge_nodes_no_checks(node_type min,
175 node_type max,
176 NewEdgeFunc&& new_edge,
177 IncompatibleFunc&& incompat);
178
179 // Is d a source of c under x? This is costly!
180 bool is_source_no_checks(node_type c, label_type x, node_type d) const;
181
182 void remove_all_sources_and_targets_no_checks(node_type c);
183 void remove_all_sources_no_checks(node_type c);
184
185 void add_source_no_checks(node_type c,
186 label_type x,
187 node_type d) noexcept;
188
189 template <typename It>
190 void rebuild_sources_no_checks(It first, It last);
191
192 // TODO to cpp/tpp file
193 void disjoint_union_inplace_no_checks(WordGraph<Node> const& that) {
194 size_t N = number_of_nodes();
195 add_nodes(that.number_of_nodes());
196 for (auto s : that.nodes()) {
197 for (auto [a, t] : that.labels_and_targets_no_checks(s)) {
198 if (t != UNDEFINED) {
199 target_no_checks(s + N, a, t + N);
200 }
201 }
202 }
203 }
204
205 private:
206 void remove_source_no_checks(node_type cx, label_type x, node_type d);
207 void replace_target_no_checks(node_type c, label_type x, node_type d);
208 void replace_source_no_checks(node_type c,
209 node_type d,
210 label_type x,
211 node_type cx);
212 };
213 } // namespace detail
214} // namespace libsemigroups
215
216#include "word-graph-with-sources.tpp"
217
218#endif // LIBSEMIGROUPS_DETAIL_WORD_GRAPH_WITH_SOURCES_HPP_
size_type out_degree() const noexcept
Returns the out-degree.
Definition word-graph.hpp:823
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:355
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:377
WordGraph & add_to_out_degree(size_type nr)
Add to the out-degree of every node.
size_type number_of_nodes() const noexcept
Returns the number of nodes.
Definition word-graph.hpp:747
Undefined const UNDEFINED
Value for something undefined.
size_t letter_type
Type for the index of a generator of a semigroup.
Definition types.hpp:98
Namespace for everything in the libsemigroups library.
Definition action.hpp:44