1 //
2 // libsemigroups - C++ library for semigroups and monoids
3 // Copyright (C) 2019 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 #include <cstddef>  // for size_t
20 #include <vector>   // for vector
21 
22 #include "catch.hpp"  // for REQUIRE, AssertionHandler, REQUIRE_THROWS_AS
23 #include "libsemigroups/element-adapters.hpp"  // for Degree etc
24 #include "libsemigroups/element.hpp"           // for PBR
25 #include "libsemigroups/froidure-pin.hpp"      // for FroidurePin
26 #include "test-main.hpp"                       // for LIBSEMIGROUPS_TEST_CASE
27 
28 namespace libsemigroups {
29   struct LibsemigroupsException;
30 }
31 
32 namespace libsemigroups {
33 
34   constexpr bool REPORT = false;
35 
36   LIBSEMIGROUPS_TEST_CASE("FroidurePin",
37                           "105",
38                           "(pbrs)",
39                           "[quick][froidure-pin][pbr]") {
40     auto             rg   = ReportGuard(REPORT);
41     std::vector<PBR> gens = {PBR({{3, 5},
42                                   {0, 1, 2, 3, 4, 5},
43                                   {0, 2, 3, 4, 5},
44                                   {0, 1, 2, 3, 5},
45                                   {0, 2, 5},
46                                   {1, 2, 3, 4, 5}}),
47                              PBR({{0, 3, 4, 5},
48                                   {2, 4, 5},
49                                   {1, 2, 5},
50                                   {2, 3, 4, 5},
51                                   {2, 3, 4, 5},
52                                   {1, 2, 4}}),
53                              PBR({{0, 3, 4, 5},
54                                   {2, 4, 5},
55                                   {1, 2, 5},
56                                   {2, 3, 4, 5},
57                                   {2, 3, 4, 5},
58                                   {1, 2, 4}})};
59     FroidurePin<PBR> S(gens);
60 
61     S.reserve(4);
62 
63     REQUIRE(S.size() == 4);
64     REQUIRE(S.nr_idempotents() == 2);
65     size_t pos = 0;
66 
67     for (auto it = S.cbegin(); it < S.cend(); ++it) {
68       REQUIRE(S.position(*it) == pos);
69       pos++;
70     }
71     S.add_generators({PBR({{3, 4, 5},
72                            {2, 4, 5},
73                            {1, 2, 4},
74                            {0, 3, 5},
75                            {1, 2, 3, 5},
76                            {1, 2, 3}})});
77     REQUIRE(S.size() == 6);
78     S.closure({PBR({{3, 4, 5},
79                     {2, 4, 5},
80                     {1, 2, 4},
81                     {0, 3, 5},
82                     {1, 2, 3, 5},
83                     {1, 2, 3}})});
84     REQUIRE(S.size() == 6);
85     REQUIRE(S.minimal_factorisation(PBR({{3, 5},
86                                          {0, 1, 2, 3, 4, 5},
87                                          {0, 2, 3, 4, 5},
88                                          {0, 1, 2, 3, 5},
89                                          {0, 2, 5},
90                                          {1, 2, 3, 4, 5}})
91                                     * PBR({{3, 4, 5},
92                                            {2, 4, 5},
93                                            {1, 2, 4},
94                                            {0, 3, 5},
95                                            {1, 2, 3, 5},
96                                            {1, 2, 3}}))
97             == word_type({0, 0}));
98     REQUIRE(S.minimal_factorisation(5) == word_type({3, 3}));
99     REQUIRE(S.at(5)
100             == PBR({{3, 4, 5},
101                     {2, 4, 5},
102                     {1, 2, 4},
103                     {0, 3, 5},
104                     {1, 2, 3, 5},
105                     {1, 2, 3}})
106                    * PBR({{3, 4, 5},
107                           {2, 4, 5},
108                           {1, 2, 4},
109                           {0, 3, 5},
110                           {1, 2, 3, 5},
111                           {1, 2, 3}}));
112     REQUIRE_THROWS_AS(S.minimal_factorisation(1000000000),
113                       LibsemigroupsException);
114     pos = 0;
115     for (auto it = S.cbegin_idempotents(); it < S.cend_idempotents(); ++it) {
116       REQUIRE(*it * *it == *it);
117       pos++;
118     }
119     REQUIRE(pos == S.nr_idempotents());
120     for (auto it = S.cbegin_sorted() + 1; it < S.cend_sorted(); ++it) {
121       REQUIRE(*(it - 1) < *it);
122     }
123   }
124 }  // namespace libsemigroups
125