libsemigroups  v3.6.0
C++ library for semigroups and monoids
Loading...
Searching...
No Matches
bmat-adapters.hpp
1//
2// libsemigroups - C++ library for semigroups and monoids
3// Copyright (C) 2020-2026 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// TODO(1): almost all parameters and t-parameters are not documented in this
20// file.
21
22#ifndef LIBSEMIGROUPS_BMAT_ADAPTERS_HPP_
23#define LIBSEMIGROUPS_BMAT_ADAPTERS_HPP_
24
25#include <cstddef> // for size_t
26#include <iterator> // for distance
27#include <type_traits> // for enable_if_t
28#include <utility> // for move
29#include <vector> // for vector, vector<>::ref...
30
31#include "action.hpp" // for RightAction
32#include "adapters.hpp" // for ImageRightAction
33#include "bitset.hpp" // for BitSet, IsBitSet
34#include "debug.hpp" // for LIBSEMIGROUPS_ASSERT
35#include "exception.hpp" // for LIBSEMIGROUPS_EXCEPTION
36#include "matrix.hpp" // for BMat
37
38#include "libsemigroups/detail/containers.hpp" // for StaticVector1
39
40namespace libsemigroups {
52 // ImageRight/LeftAction - BMat
54
70 // T = StaticVector1<BitSet<N>, N> or std::vector<BitSet<N>>
71 // Possibly further container when value_type is BitSet.
72 template <typename Mat, typename Container>
73#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
74 struct ImageRightAction<
75 Mat,
76 Container,
77 std::enable_if_t<IsBMat<Mat> && IsBitSet<typename Container::value_type>>>
78#else
79 struct ImageRightAction<Mat, Container>
80#endif
81 {
82 // TODO(now) Are pt and x the right way round in the doc?
87 // TODO(1) parameters not documented
88 // not noexcept because BitSet<N>::apply isn'Container
89 void operator()(Container& res, Container const& pt, Mat const& x) const {
90 using value_type = typename Container::value_type;
91 res.clear();
92
93 for (auto const& v : pt) {
94 value_type cup;
95 cup.reset();
96 v.apply([&x, &cup](size_t i) {
97 for (size_t j = 0; j < x.number_of_rows(); ++j) {
98 cup.set(j, cup[j] || x(i, j));
99 }
100 });
101 res.push_back(std::move(cup));
102 }
103 auto tmp = matrix::bitset_row_basis<Mat>(res);
104 std::swap(res, tmp);
105 }
106 };
107
120 // TODO(1) doc tparams
121 template <typename Mat, typename Container>
122#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
123 struct ImageLeftAction<Mat, Container, std::enable_if_t<IsBMat<Mat>>>
124#else
125 struct ImageLeftAction<Mat, Container>
126#endif
127 {
132 // TODO(1) doc parameters
133 void operator()(Container& res, Container const& pt, Mat const& x) const {
134 const_cast<Mat*>(&x)->transpose();
135 try {
137 } catch (...) {
138 const_cast<Mat*>(&x)->transpose();
139 throw;
140 }
141 const_cast<Mat*>(&x)->transpose();
142 }
143 };
144
146 // Lambda/Rho - BMat
148
164 // This currently limits the use of Konieczny to matrices of dimension at
165 // most 64 with the default traits class, since we cannot know the
166 // dimension of the matrices at compile time, only at run time.
167 // TODO(1) doc tparams
168 template <typename Mat>
169#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
170 struct LambdaValue<Mat, std::enable_if_t<IsBMat<Mat>>>
171#else
172 struct LambdaValue<Mat>
173#endif
174 {
176 static constexpr size_t N = BitSet<1>::max_size();
177
183 using type = detail::StaticVector1<BitSet<N>, N>;
184 };
185
199 // TODO(1) doc tparams
200 template <typename Mat>
201#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
202 struct RhoValue<Mat, std::enable_if_t<IsBMat<Mat>>>
203#else
204 struct RhoValue<Mat>
205#endif
206 {
212 using type = typename LambdaValue<Mat>::type;
213 };
214
215 // Benchmarks show that the following is the fastest (i.e. duplicating the
216 // code from ImageRightAction, and using StaticVector1). T =
217 // StaticVector1<BitSet>, std::vector<BitSet>, StaticVector1<std::bitset>,
218 // std::vector<std::bitset>
219
230 // TODO(1) doc tparameters
231 template <typename Mat, typename Container>
232#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
233 struct Lambda<Mat, Container, std::enable_if_t<IsBMat<Mat>>>
234#else
235 struct Lambda<Mat, Container>
236#endif
237 {
241 // TODO(1) doc parameters
242 void operator()(Container& res, Mat const& x) const {
243 using value_type = typename Container::value_type;
244 size_t const N = value_type().size();
245 if (x.number_of_rows() > N) {
247 "expected matrix of dimension at most {}, found {}",
248 N,
249 x.number_of_rows());
250 }
251 res.clear();
252 for (size_t i = 0; i < x.number_of_rows(); ++i) {
253 value_type cup;
254 cup.reset();
255 for (size_t j = 0; j < x.number_of_rows(); ++j) {
256 cup.set(j, x(i, j));
257 }
258 res.push_back(std::move(cup));
259 }
260 auto tmp = matrix::bitset_row_basis<Mat>(res);
261 std::swap(res, tmp);
262 }
263 };
264
265 // T = StaticVector1<BitSet>, std::vector<BitSet>,
266 // StaticVector1<std::bitset>, std::vector<std::bitset>
267
279 template <typename Mat, typename Container>
280#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
281 struct Rho<Mat, Container, std::enable_if_t<IsBMat<Mat>>>
282#else
283 struct Rho<Mat, Container>
284#endif
285 {
290 void operator()(Container& res, Mat const& x) const noexcept {
291 const_cast<Mat*>(&x)->transpose();
292 Lambda<Mat, Container>()(res, x);
293 const_cast<Mat*>(&x)->transpose();
294 }
295 };
296
298 // Rank - BMat
300
314 template <size_t N, typename Mat>
315#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
316 struct ImageRightAction<Mat, BitSet<N>, std::enable_if_t<IsBMat<Mat>>>
317#else
318 struct ImageRightAction<Mat, BitSet<N>>
319#endif
320 {
322 using result_type = BitSet<N>;
323
329 result_type const& pt,
330 Mat const& x) const {
331 static thread_local detail::StaticVector1<BitSet<N>, N> x_rows;
332 x_rows.clear();
333 for (size_t i = 0; i < x.number_of_rows(); ++i) {
334 BitSet<N> row(0);
335 for (size_t j = 0; j < x.number_of_rows(); ++j) {
336 if (x(i, j)) {
337 row.set(j, true);
338 }
339 }
340 x_rows.push_back(std::move(row));
341 }
342 res.reset();
343 pt.apply([&res](size_t i) { res |= x_rows[i]; });
344 }
345 };
346
358 template <typename Mat>
359#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
360 class RankState<Mat, std::enable_if_t<IsBMat<Mat>>>
361#else
362 class RankState<Mat>
363#endif
364 {
365 public:
369 using MaxBitSet = BitSet<BitSet<1>::max_size()>;
370
373
375 RankState() = delete;
376
378 RankState(RankState const&) = default;
379
381 RankState(RankState&&) = delete;
382
384 RankState& operator=(RankState const&) = delete;
385
388
400 template <typename T>
401 RankState(T first, T last) {
402 static thread_local std::vector<MaxBitSet> seeds;
403 LIBSEMIGROUPS_ASSERT(_orb.empty());
404 if (std::distance(first, last) == 0) {
406 "expected a positive number of generators in the second argument");
407 }
408 for (auto it = first; it < last; ++it) {
409 _orb.add_generator(*it);
410 }
411 for (size_t i = 0; i < first->number_of_rows(); ++i) {
412 MaxBitSet seed(0);
413 seed.set(i, true);
414 _orb.add_seed(seed);
415 }
416 }
417
421 type const& get() const {
422 _orb.run();
423 LIBSEMIGROUPS_ASSERT(_orb.finished());
424 return _orb;
425 }
426
427 private:
428 mutable type _orb;
429 };
430
440 template <typename Mat>
441#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
442 struct Rank<Mat, RankState<Mat>, std::enable_if_t<IsBMat<Mat>>>
443#else
444 struct Rank<Mat, RankState<Mat>>
445#endif
446 {
454 size_t operator()(RankState<Mat> const& state, Mat const& x) const {
455 using bitset_type = BitSet<BitSet<1>::max_size()>;
456 using orb_type = typename RankState<Mat>::type;
457 static thread_local std::vector<bool> seen;
458 static thread_local std::vector<bitset_type> x_rows;
459 seen.clear();
460 x_rows.clear();
461 orb_type const& orb = state.get();
462 LIBSEMIGROUPS_ASSERT(orb.finished());
463 seen.resize(orb.current_size());
464 for (size_t i = 0; i < x.number_of_rows(); ++i) {
465 bitset_type row(0);
466 for (size_t j = 0; j < x.number_of_rows(); ++j) {
467 if (x(i, j)) {
468 row.set(j, true);
469 }
470 }
471 x_rows.push_back(std::move(row));
472 }
473 size_t rnk = 0;
474 for (size_t i = 0; i < orb.current_size(); ++i) {
475 bitset_type const& row = orb[i];
476 bitset_type cup;
477 cup.reset();
478 row.apply([&cup](size_t j) { cup |= x_rows[j]; });
479 size_t pos = orb.position(cup);
480 LIBSEMIGROUPS_ASSERT(pos != UNDEFINED);
481 if (!seen[pos]) {
482 rnk++;
483 seen[pos] = true;
484 }
485 }
486 return rnk;
487 }
488 };
489
490} // namespace libsemigroups
491#endif // LIBSEMIGROUPS_BMAT_ADAPTERS_HPP_
RankState & operator=(RankState const &)=delete
Deleted.
RankState(RankState const &)=default
Deleted.
RankState & operator=(RankState &&)=delete
Deleted.
BitSet< BitSet< 1 >::max_size()> MaxBitSet
The maximum size of a bit set.
Definition bmat-adapters.hpp:369
RightAction< Mat, MaxBitSet, ImageRightAction< Mat, MaxBitSet > > type
Type of the RankState.
Definition bmat-adapters.hpp:372
type const & get() const
Returns the row orbit.
Definition bmat-adapters.hpp:421
RankState(RankState &&)=delete
Deleted.
RankState(T first, T last)
Construct a RankState instance using iterators.
Definition bmat-adapters.hpp:401
Base class for states for ranks.
Definition adapters.hpp:882
void type
Definition adapters.hpp:886
void run()
Run until finished.
T clear(T... args)
T distance(T... args)
Action< Element, Point, Func, Traits, side::right > RightAction
Definition action.hpp:933
Undefined const UNDEFINED
Value for something undefined.
#define LIBSEMIGROUPS_EXCEPTION(...)
Throw a LibsemigroupsException.
Definition exception.hpp:99
T move(T... args)
void bitset_row_basis(Container &&rows, std::decay_t< Container > &result)
Appends a basis for the space spanned by some bitsets to a container.
Namespace for everything in the libsemigroups library.
Definition action.hpp:44
T push_back(T... args)
T resize(T... args)
void operator()(Container &res, Container const &pt, Mat const &x) const
Store the image of pt under the left action of x.
Definition bmat-adapters.hpp:133
Adapter for the value of a left action.
Definition adapters.hpp:355
BitSet< N > result_type
The type of result.
Definition bmat-adapters.hpp:322
void operator()(result_type &res, result_type const &pt, Mat const &x) const
Store the image of pt under the right action of x.
Definition bmat-adapters.hpp:328
void operator()(Container &res, Container const &pt, Mat const &x) const
Store the image of pt under the right action of x.
Definition bmat-adapters.hpp:89
Adapter for the value of a right action.
Definition adapters.hpp:397
static constexpr size_t N
The maximum width of BitSet on the system.
Definition bmat-adapters.hpp:176
detail::StaticVector1< BitSet< N >, N > type
The type of Lambda Values.
Definition bmat-adapters.hpp:183
Adapter for lambda functions.
Definition adapters.hpp:798
void operator()(Container &res, Mat const &x) const
Modifies res in-place to contain the row space basis of x.
Definition bmat-adapters.hpp:242
Adapter for the action on LambdaValue's.
Definition adapters.hpp:838
size_t operator()(RankState< Mat > const &state, Mat const &x) const
Returns the rank of x.
Definition bmat-adapters.hpp:454
Adapter for calculating ranks.
Definition adapters.hpp:935
typename LambdaValue< Mat >::type type
The type of Rho Values.
Definition bmat-adapters.hpp:212
Adapter for rho functions.
Definition adapters.hpp:817
void operator()(Container &res, Mat const &x) const noexcept
Modifies res in-place to contain the column space basis of x.
Definition bmat-adapters.hpp:290
Adapter for the action on RhoValue's.
Definition adapters.hpp:859
T swap(T... args)