libsemigroups  v3.5.1
C++ library for semigroups and monoids
Loading...
Searching...
No Matches
node-managed-graph.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 the declaration of the NodeManagedGraph class, used
20// by Stephen and by ToddCoxeterImpl.
21
22// TODO:
23// * iwyu
24// * code coverage
25
26#ifndef LIBSEMIGROUPS_DETAIL_NODE_MANAGED_GRAPH_HPP_
27#define LIBSEMIGROUPS_DETAIL_NODE_MANAGED_GRAPH_HPP_
28
29#include <cstddef> // for size_t
30#include <cstdint> // for uint32_t
31#include <stack> // for stack
32#include <type_traits> // for is_base_of
33#include <utility> // for pair
34#include <vector> // for vector
35
36#include "libsemigroups/presentation.hpp" // for Presentation, Presentation<>:...
37#include "libsemigroups/runner.hpp"
38#include "libsemigroups/types.hpp" // for word_type
39#include "libsemigroups/word-graph-helpers.hpp" // for word_graph
40#include "libsemigroups/word-graph.hpp" // for WordGraph
41
42#include "felsch-graph.hpp"
43#include "node-manager.hpp" // for NodeManager
44#include "report.hpp" // for REPORT_DEFAULT
45#include "timer.hpp" // for Timer
46#include "word-graph-with-sources.hpp" // for WordGraphWithSources
47
48namespace libsemigroups {
49 namespace detail {
50
51 template <typename Node>
52 class NodeManagedGraph : public WordGraphWithSources<Node>,
53 public NodeManager<Node>,
54 public Reporter {
55 public:
57 // Aliases - public
59
60 using BaseGraph = WordGraphWithSources<Node>;
61 using node_type = typename BaseGraph::node_type;
62 using label_type = typename BaseGraph::label_type;
63
64 static_assert(
65 std::is_base_of_v<WordGraphWithSources<node_type>, BaseGraph>,
66 "the template parameter BaseGraph must be derived from "
67 "WordGraphWithSources");
68
69 protected:
71 // Data - protected
73
74 using Coincidence = std::pair<node_type, node_type>;
75 using Coincidences = std::stack<Coincidence>;
76 struct CollectCoincidences; // forward decl
77
78 Coincidences _coinc;
79
80 private:
82 // Data - private
84
85 struct Settings; // forward decl
86 struct Stats; // forward decl
87
88 Settings _settings;
89 mutable Stats _stats;
90
91 public:
93 // BaseGraph mem fns
95
97
98 NodeManagedGraph& target_no_checks(node_type s,
99 label_type a,
100 node_type t) noexcept {
101 _stats.num_edges_active += (t != UNDEFINED);
102 WordGraphWithSources<Node>::target_no_checks(s, a, t);
103 // The next assertion is extremely slow so don't do it!
104 // LIBSEMIGROUPS_ASSERT(_stats.num_edges_active
105 // == count_number_of_edges_active());
106 return *this;
107 }
108 using BaseGraph::target_no_checks;
109
110 using NodeManager<node_type>::cursor;
111 using NodeManager<node_type>::lookahead_cursor;
112
114 // Constructors + initializers
116
117 NodeManagedGraph();
118 NodeManagedGraph& init();
119
120 NodeManagedGraph(NodeManagedGraph const&);
121 NodeManagedGraph(NodeManagedGraph&&);
122 NodeManagedGraph& operator=(NodeManagedGraph const&);
123 NodeManagedGraph& operator=(NodeManagedGraph&&);
124 ~NodeManagedGraph();
125
126 template <typename OtherNode>
127 explicit NodeManagedGraph(WordGraph<OtherNode> const& wg)
128 : BaseGraph(wg), NodeManager<node_type>() {
129 // NodeManager always has one node active
130 NodeManager<node_type>::add_active_nodes(
131 WordGraph<node_type>::number_of_nodes() - 1);
132 _stats.num_edges_active += wg.number_of_edges();
133 }
134
135 template <typename OtherNode>
136 NodeManagedGraph& init(WordGraph<OtherNode> const& wg) {
137 init();
138 BaseGraph::init(wg);
139 // NodeManager always has one node active
140 NodeManager<node_type>::add_active_nodes(
141 WordGraph<node_type>::number_of_nodes() - 1);
142 _stats.num_edges_active += wg.number_of_edges();
143 return *this;
144 }
145
146 template <typename OtherNode>
147 NodeManagedGraph& operator=(WordGraph<OtherNode> const& wg);
148
149 NodeManagedGraph& reserve(size_t n);
150
152 // Operators
154
155 [[nodiscard]] bool operator==(WordGraph<node_type> const& that) const {
156 return static_cast<WordGraph<node_type> const&>(*this) == that;
157 }
158
160 // Settings
162
163 NodeManagedGraph& large_collapse(size_t val) noexcept {
164 _settings.large_collapse = val;
165 return *this;
166 }
167
168 [[nodiscard]] size_t large_collapse() const noexcept {
169 return _settings.large_collapse;
170 }
171
173 // Stats
175
176 [[nodiscard]] Stats& stats() noexcept {
177 return _stats;
178 }
179
180 [[nodiscard]] Stats& stats() const noexcept {
181 return _stats;
182 }
183
184 void stats_check_point() const;
185
187 // Accessors
189
190 [[nodiscard]] uint64_t number_of_edges_active() const noexcept {
191 return _stats.num_edges_active;
192 }
193
194 // 100% not thread safe
195 [[nodiscard]] uint64_t count_number_of_edges_active() const noexcept;
196
197 [[nodiscard]] size_t number_of_coincidences() const noexcept {
198 return _coinc.size();
199 }
200
202 // Modifiers
204
205 node_type new_node();
206
207 template <bool RegisterDefs = false>
208 [[nodiscard]] std::pair<bool, node_type>
209 complete_path(node_type c,
210 word_type::const_iterator first,
211 word_type::const_iterator last) noexcept;
212
213 void merge_nodes_no_checks(node_type x, node_type y) {
214 _coinc.emplace(x, y);
215 }
216
217 // Returns true if any changes were made to the graph and false o/w.
218 template <typename Functor = Noop>
219 bool process_coincidences(Functor&& = Noop{});
220
221 void standardize(std::vector<node_type> const& p,
222 std::vector<node_type> const& q) {
223 auto& c = lookahead_cursor();
224 if (c < q.size()) {
225 c = q[c];
226 }
227 BaseGraph::permute_nodes_no_checks(
228 p, q, NodeManager<node_type>::number_of_nodes_active());
229 NodeManager<node_type>::compact();
230 }
231
232 void permute_nodes_no_checks(std::vector<node_type> const& p,
233 std::vector<node_type> const& q) {
234 BaseGraph::permute_nodes_no_checks(
235 p, q, NodeManager<node_type>::number_of_nodes_active());
236 NodeManager<node_type>::apply_permutation(p);
237 }
238
239 // Not currently used for anything, previously required for immediate
240 // standardization
241 void swap_nodes_no_checks(node_type c, node_type d);
242 }; // class NodeManagedGraph
243
244 namespace node_managed_graph {
245 template <typename BaseGraph>
246 typename BaseGraph::node_type
247 random_active_node(NodeManagedGraph<BaseGraph> const& nmg);
248
249 } // namespace node_managed_graph
250
251 } // namespace detail
252} // namespace libsemigroups
253
254#include "node-managed-graph.tpp"
255
256#endif // LIBSEMIGROUPS_DETAIL_NODE_MANAGED_GRAPH_HPP_
size_type out_degree() const noexcept
Returns the out-degree.
Definition word-graph.hpp:842
Undefined const UNDEFINED
Value for something undefined.
Namespace for everything in the libsemigroups library.
Definition action.hpp:44
T size(T... args)