// // Semigroups package for GAP // Copyright (C) 2022 James D. Mitchell // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see <https://www.gnu.org/licenses/>. //
// This file contains a function LATTICE_OF_CONGRUENCES for finding the lattice // of congruences when there are too many generating congruences for // Froidure-Pin to handle.
#include"conglatt.hpp"
#include <algorithm> // for equal, max #include <chrono> // for time_point #include <cmath> // for log2 #include <cstddef> // for size_t #include <cstdint> // for uint16_t, uint32_t #include <iostream> // for cout #include <memory> // for unique_ptr #include <numeric> // for iota #include <unordered_map> // for unordered_map #include <utility> // for swap, pair #include <vector> // for vector
// GAP headers #include"gap_all.h"
// Semigroups package for GAP headers #include"semigroups-debug.hpp"// for SEMIGROUPS_ASSERT
// libsemigroups headers #include"libsemigroups/adapters.hpp"// for Hash #include"libsemigroups/report.hpp"// for should_report #include"libsemigroups/string.hpp"// for group_digits //
namespace semigroups { namespace { // This class is minimally adapted from libsemigroups::detail::UF, but // specialised for the problem at hand. template <typename T> class UF {
std::vector<T> _data;
size_t _log2_data_size;
public: //////////////////////////////////////////////////////////////////////// // Aliases - public //////////////////////////////////////////////////////////////////////// using size_type = size_t; using node_type = T; using container_type = std::vector<T>; using index_type = T;
// not noexcept because the constructors of std::vector and std::array // aren't explicit UF(size_type size)
: _data(size, 0),
_log2_data_size(
std::max(static_cast<size_t>(std::log2(_data.size())), static_cast<size_t>(1))) {
SEMIGROUPS_ASSERT(size != 0);
std::iota(_data.begin(), _data.end(), 0);
}
// not noexcept because the constructors of std::vector and std::array // aren't
UF(UF const&) = default;
UF& operator=(UF const&) = default;
UF(UF&&) = default;
UF& operator=(UF&&) = default;
~UF() = default;
// not noexcept because std::vector::operator[] isn't
index_type find(index_type x) const {
SEMIGROUPS_ASSERT(x < _data.size()); auto y = _data[x]; while (y != _data[y]) {
y = _data[y];
} return y;
}
// not noexcept because UF::find isn't void unite(index_type x, index_type y) {
SEMIGROUPS_ASSERT(x < _data.size());
SEMIGROUPS_ASSERT(y < _data.size());
x = find(x);
y = find(y); if (x < y) {
_data[y] = x;
} else {
_data[x] = y;
}
}
// Not noexcept because std::equal isn't booloperator==(UF const& that) const { return std::equal(that._data.cbegin(),
that._data.cend(),
_data.cbegin(),
_data.cend());
}
void normalize() { for (index_type i = 0; i < _data.size(); ++i) {
_data[i] = find(_data[i]);
}
}
namespace semigroups { namespace { // should be to_cpp<UF> auto to_uf(Obj lookup) { using UF = UF<uint16_t>;
SEMIGROUPS_ASSERT(IS_LIST(lookup));
size_t const n = LEN_LIST(lookup);
SEMIGROUPS_ASSERT(n < 65536);
UF uf(n); for (uint16_t i = 0; i < n; ++i) {
SEMIGROUPS_ASSERT(IS_INTOBJ(ELM_LIST(lookup, i)));
SEMIGROUPS_ASSERT(INT_INTOBJ(ELM_LIST(lookup, i)) >= 1);
SEMIGROUPS_ASSERT(INT_INTOBJ(ELM_LIST(lookup, i)) <= n);
uf.unite(i, INT_INTOBJ(ELM_LIST(lookup, i + 1)) - 1);
} return uf;
}
} // namespace
Obj LATTICE_OF_CONGRUENCES(Obj list) { using UF = UF<uint16_t>;
using libsemigroups::EqualTo; using libsemigroups::Hash; using libsemigroups::detail::group_digits;
using std::chrono::duration_cast; using std::chrono::nanoseconds; using std::chrono::seconds;
if (LEN_LIST(list) == 0) {
ErrorQuit( "the argument must be a list of length at least 1, found 0", 0L, 0L);
}
size_t const n = LEN_LIST(ELM_LIST(list, 1)); if (n > 65535) { // Then the values in the lookup won't fit into uint16_t
ErrorQuit("the lists in the argument must have length at most 65535, " "found %d",
(Int) LEN_LIST(list),
0L);
}
auto start_time = std::chrono::high_resolution_clock::now(); auto last_report = start_time;
uint32_t last_count = 1; bool report = libsemigroups::report::should_report();
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.