Skip to content

Commit

Permalink
Knuth bendix hpp (libsemigroups#623)
Browse files Browse the repository at this point in the history
* Refactor x 2

* Split NormalFormRange into sep. file

* Refactor x3

* Add file to Makefile.am

* Refactor x4

* Refactor x5

* Refactor x6

* Formatting

* Refactor x7

* Add TODO

* Fixes from python

* Linting + formatting

* Fix wrong arg order for non_trivial_classes

* Use V3 test macro for ToddCoxeter

* Format

* Add missing full stops
  • Loading branch information
james-d-mitchell authored Dec 12, 2024
1 parent 182529f commit e258212
Show file tree
Hide file tree
Showing 17 changed files with 1,896 additions and 1,582 deletions.
1 change: 1 addition & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ detailinclude_HEADERS += include/libsemigroups/detail/kambites-nf.hpp
detailinclude_HEADERS += include/libsemigroups/detail/kbe.hpp
detailinclude_HEADERS += include/libsemigroups/detail/kbe.tpp
detailinclude_HEADERS += include/libsemigroups/detail/ke.hpp
detailinclude_HEADERS += include/libsemigroups/detail/knuth-bendix-nf.hpp
detailinclude_HEADERS += include/libsemigroups/detail/multi-string-view.hpp
detailinclude_HEADERS += include/libsemigroups/detail/node-managed-graph.hpp
detailinclude_HEADERS += include/libsemigroups/detail/node-managed-graph.tpp
Expand Down
13 changes: 2 additions & 11 deletions docs/DoxygenLayout.xml
Original file line number Diff line number Diff line change
Expand Up @@ -141,17 +141,8 @@
<tab type="user" visible="yes" url="@ref libsemigroups::kambites" title="Kambites helper functions" />
</tab>
<tab type="usergroup" visible="yes" url="@ref knuth_bendix_group" title="Knuth-Bendix">
<tab type="usergroup" visible="yes" url="@ref knuth_bendix_class_group" title="The KnuthBendix class">
<tab type="user" visible="yes" url="@ref knuth_bendix_class_mem_types_group" title="Member types"/>
<tab type="user" visible="yes" url="@ref knuth_bendix_class_init_group" title="Constructors + Initializers"/>
<tab type="user" visible="yes" url="@ref knuth_bendix_class_settings_group" title="Settings"/>
<tab type="user" visible="yes" url="@ref knuth_bendix_class_intf_group" title="Common functions"/>
<tab type="user" visible="yes" url="@ref knuth_bendix_class_accessors_group" title="Accessors"/>
<tab type="user" visible="yes" url="@ref knuth_bendix_class_mod_group" title="Modifiers"/>
<tab type="user" visible="yes" url="@ref knuth_bendix_class_word_index_group" title="Word -> index"/>
<tab type="user" visible="yes" url="@ref knuth_bendix_class_index_word_group" title="Index -> word"/>
</tab>
<tab type="user" visible="yes" url="@ref knuth_bendix_helpers_group" title="Knuth-Bendix helper functions" />
<tab type="user" visible="yes" url="@ref libsemigroups::KnuthBendix" title="The KnuthBendix class"/>
<tab type="user" visible="yes" url="@ref libsemigroups::knuth_bendix" title="Knuth-Bendix helper functions"/>
</tab>
<tab type="user" visible="yes" url="@ref freeband_group" title="Radoszewski-Rytter" />
<tab type="user" visible="yes" url="@ref schreier_sims_group" title="Schreier-Sims" />
Expand Down
7 changes: 4 additions & 3 deletions include/libsemigroups/cong-intf.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ namespace libsemigroups {
Iterator2 last1,
Iterator3 first2,
Iterator4 last2) {
LIBSEMIGROUPS_ASSERT(!started());
_generating_pairs.emplace_back(first1, last1);
_generating_pairs.emplace_back(first2, last2);
return static_cast<Subclass&>(*this);
Expand Down Expand Up @@ -1127,7 +1128,7 @@ namespace libsemigroups {
typename Range,
typename OutputWord = std::decay_t<typename Range::output_type>,
typename = std::enable_if_t<rx::is_input_or_sink_v<Range>>>
[[nodiscard]] std::vector<std::vector<OutputWord>> partition(Subclass& kb,
[[nodiscard]] std::vector<std::vector<OutputWord>> partition(Subclass& ci,
Range r) {
// Congruence + ToddCoxeter have their own overloads for this
static_assert(!std::is_same_v<Subclass, ToddCoxeter>
Expand All @@ -1145,8 +1146,8 @@ namespace libsemigroups {

while (!r.at_end()) {
auto next = r.get();
if (kb.presentation().contains_empty_word() || !next.empty()) {
auto next_nf = congruence_interface::reduce(kb, next);
if (ci.presentation().contains_empty_word() || !next.empty()) {
auto next_nf = congruence_interface::reduce(ci, next);
auto [it, inserted] = map.emplace(next_nf, index);
if (inserted) {
result.emplace_back();
Expand Down
82 changes: 82 additions & 0 deletions include/libsemigroups/detail/knuth-bendix-nf.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
//
// libsemigroups - C++ library for semigroups and monoids
// Copyright (C) 2024 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 <http://www.gnu.org/licenses/>.
//

// This file contains an implementation of a range object for producing normal
// forms for a KnuthBendix object.

#ifndef LIBSEMIGROUPS_DETAIL_KNUTH_BENDIX_NF_HPP_
#define LIBSEMIGROUPS_DETAIL_KNUTH_BENDIX_NF_HPP_

namespace detail {

template <typename Word, typename Rewriter, typename ReductionOrder>
class KnuthBendixNormalFormRange : public Paths<uint32_t> {
using Paths_ = Paths<uint32_t>;

mutable Word _current;
KnuthBendix<Rewriter, ReductionOrder>* _kb;

public:
using size_type = typename Paths_::size_type;
using output_type = Word const&;

explicit KnuthBendixNormalFormRange(
KnuthBendix<Rewriter, ReductionOrder>& kb)
: Paths(kb.gilman_graph()), _current(), _kb(&kb) {
// It's possible that the gilman graph is empty, so the call to
// source_no_checks(0) is technically invalid, but nothing goes wrong,
// so we just go with it. This is slightly smelly.
Paths_::source_no_checks(0);
if (!kb.presentation().contains_empty_word()) {
Paths_::next();
}
}

output_type get() const {
word_type const& w = Paths_::get();
_current.clear();
for (auto c : w) {
_current.push_back(_kb->presentation().letter_no_checks(c));
}
return _current;
}

KnuthBendixNormalFormRange& min(size_type val) noexcept {
// TODO(0) should not allow 0 unless contains_empty_word
Paths_::min(val);
return *this;
}

KnuthBendixNormalFormRange& max(size_type val) noexcept {
Paths_::max(val);
return *this;
}

using Paths_::at_end;
using Paths_::count;
using Paths_::max;
using Paths_::min;
using Paths_::next;
using Paths_::size_hint;

static constexpr bool is_finite = true; // this isn't always true!
static constexpr bool is_idempotent = true;
}; // class KnuthBendixNormalFormRange

} // namespace detail
#endif // LIBSEMIGROUPS_DETAIL_KNUTH_BENDIX_NF_HPP_
Loading

0 comments on commit e258212

Please sign in to comment.