libsemigroups  v3.3.0
C++ library for semigroups and monoids
Loading...
Searching...
No Matches
is-transf.hpp
1//
2// libsemigroups - C++ library for semigroups and monoids
3// Copyright (C) 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// This file contains some functions for checking whether or not a container
19// defines a partial transformation, full transformation, partial permutation,
20// or permutation. These are used in transf.hpp for argument checking, and also
21// in hpcombi.hpp for the same.
22
23#ifndef LIBSEMIGROUPS_IS_TRANSF_HPP_
24#define LIBSEMIGROUPS_IS_TRANSF_HPP_
25
26#include <algorithm> // for none_of, find_if
27#include <cstddef> // for size_t
28#include <iterator> // for distance
29#include <string_view> // for string_view
30#include <type_traits> // for decay_t, is_unsigned_v
31#include <unordered_map> // for unordered_map
32#include <utility> // for declval, pair
33
34#include "constants.hpp" // for UNDEFINED
35
36#include "detail/print.hpp" // for to_printable
37
38namespace libsemigroups {
39
40 namespace detail {
41
42 // Returns "{it, pos}" where "it" is an iterator point to the first
43 // repeated element and "pos" is the position of the first occurrence of
44 // that element. Returns {last, std::distance(first, last)} if not
45 // duplicates.
46 template <typename Iterator>
47 std::pair<Iterator, size_t> find_duplicates(
48 Iterator first,
49 Iterator last,
50 std::unordered_map<std::decay_t<decltype(*first)>, size_t>& seen);
51
52 template <typename Iterator>
53 [[nodiscard]] std::pair<Iterator, size_t> find_duplicates(Iterator first,
54 Iterator last) {
55 std::unordered_map<std::decay_t<decltype(*first)>, size_t> seen;
56 return find_duplicates(first, last, seen);
57 }
58
59 template <typename Iterator>
60 [[nodiscard]] bool has_duplicates(Iterator first, Iterator last) {
61 return find_duplicates(first, last).first != last;
62 }
63
64 template <typename Iterator>
65 void throw_if_duplicates(
66 Iterator first,
67 Iterator last,
68 std::unordered_map<std::decay_t<decltype(*first)>, size_t>& seen,
69 std::string_view where);
70
71 template <typename Iterator>
72 void throw_if_duplicates(Iterator first,
73 Iterator last,
74 std::string_view where) {
75 std::unordered_map<std::decay_t<decltype(*first)>, size_t> seen;
76 throw_if_duplicates(first, last, seen, where);
77 }
78
79 template <typename Iterator, typename Func>
80 void throw_if_value_out_of_range(Iterator first,
81 Iterator last,
82 Func&& func,
83 std::string_view where);
84
85 template <typename Iterator>
86 void throw_if_not_ptransf(Iterator first, Iterator last, size_t deg);
87
88 template <typename Iterator>
89 void throw_if_not_ptransf(Iterator first, Iterator last) {
90 throw_if_not_ptransf(first, last, std::distance(first, last));
91 }
92
93 template <typename Iterator>
94 void throw_if_not_ptransf(Iterator dom_first,
95 Iterator dom_last,
96 Iterator img_first,
97 Iterator img_last,
98 size_t deg);
99
100 template <typename Iterator>
101 void throw_if_not_transf(Iterator first, Iterator last, size_t deg);
102
103 template <typename Iterator>
104 void throw_if_not_transf(Iterator first, Iterator last) {
105 throw_if_not_transf(first, last, std::distance(first, last));
106 }
107
108 template <typename Iterator>
109 void throw_if_not_perm(Iterator first, Iterator last, size_t deg) {
110 throw_if_not_transf(first, last, deg);
111 throw_if_duplicates(first, last, "image");
112 }
113
114 template <typename Iterator>
115 void throw_if_not_perm(Iterator first, Iterator last) {
116 throw_if_not_perm(first, last, std::distance(first, last));
117 }
118
119 template <typename Iterator>
120 void throw_if_not_pperm(Iterator first, Iterator last, size_t deg) {
121 throw_if_not_ptransf(first, last, deg);
122 throw_if_duplicates(first, last, "image");
123 }
124
125 template <typename Iterator>
126 void throw_if_not_pperm(Iterator first, Iterator last) {
127 throw_if_not_ptransf(first, last);
128 throw_if_duplicates(first, last, "image");
129 }
130
131 template <typename Iterator>
132 void throw_if_not_pperm(Iterator dom_first,
133 Iterator dom_last,
134 Iterator img_first,
135 Iterator img_last,
136 size_t deg) {
137 throw_if_not_ptransf(dom_first, dom_last, img_first, img_last, deg);
138 throw_if_duplicates(img_first, img_last, "image");
139 }
140 } // namespace detail
141
171 template <typename Iterator>
172 [[nodiscard]] bool is_ptransf(Iterator first, Iterator last, size_t deg) {
173 static_assert(
174 std::is_unsigned_v<std::decay_t<decltype(*std::declval<Iterator>())>>);
175 return std::none_of(first, last, [&deg](auto val) {
176 return val >= deg && val != UNDEFINED;
177 });
178 }
179
204 template <typename Iterator>
205 [[nodiscard]] bool is_ptransf(Iterator first, Iterator last) {
206 return is_ptransf(first, last, std::distance(first, last));
207 }
208
234 template <typename Iterator>
235 [[nodiscard]] bool is_transf(Iterator first, Iterator last, size_t deg) {
236 static_assert(
237 std::is_unsigned_v<std::decay_t<decltype(*std::declval<Iterator>())>>);
238 return std::none_of(first, last, [&deg](auto val) { return val >= deg; });
239 }
240
264 template <typename Iterator>
265 [[nodiscard]] bool is_transf(Iterator first, Iterator last) {
266 return is_transf(first, last, std::distance(first, last));
267 }
268
297 template <typename Iterator>
298 [[nodiscard]] bool is_pperm(Iterator first, Iterator last, size_t deg) {
299 return is_ptransf(first, last, deg) && !detail::has_duplicates(first, last);
300 }
301
328 template <typename Iterator>
329 [[nodiscard]] bool is_pperm(Iterator first, Iterator last) {
330 return is_pperm(first, last, std::distance(first, last));
331 }
332
357 template <typename Iterator>
358 [[nodiscard]] bool is_perm(Iterator first, Iterator last, size_t deg) {
359 return is_transf(first, last, deg) && !detail::has_duplicates(first, last);
360 }
361
386 template <typename Iterator>
387 [[nodiscard]] bool is_perm(Iterator first, Iterator last) {
388 return is_perm(first, last, std::distance(first, last));
389 }
390} // namespace libsemigroups
391
392#include "is-transf.tpp"
393
394#endif // LIBSEMIGROUPS_IS_TRANSF_HPP_
T none_of(T... args)
T distance(T... args)
Undefined const UNDEFINED
Value for something undefined.
bool is_ptransf(Iterator first, Iterator last, size_t deg)
Returns whether or not the argument describes a partial transformation.
Definition is-transf.hpp:172
bool is_transf(Iterator first, Iterator last, size_t deg)
Returns whether or not the argument describes a transformation.
Definition is-transf.hpp:235
bool is_pperm(Iterator first, Iterator last, size_t deg)
Returns whether or not the argument describes a partial permutation.
Definition is-transf.hpp:298
bool is_perm(Iterator first, Iterator last, size_t deg)
Returns whether or not the argument describes a permutation.
Definition is-transf.hpp:358
Namespace for everything in the libsemigroups library.
Definition action.hpp:44