Skip to content

Commit

Permalink
Not working Sims2
Browse files Browse the repository at this point in the history
  • Loading branch information
james-d-mitchell committed Nov 20, 2023
1 parent 31ed6e1 commit ded81ac
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 15 deletions.
2 changes: 2 additions & 0 deletions include/libsemigroups/sims1.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -863,6 +863,8 @@ namespace libsemigroups {

FelschGraph<word_type, node_type, std::vector<Definition>> _felsch_graph;

std::vector<word_type> _2_sided_include;
std::vector<word_type> _2_sided_words;
// This mutex does nothing for iterator, only does
// something for thread_iterator
std::mutex _mtx;
Expand Down
80 changes: 67 additions & 13 deletions src/sims1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,15 +94,22 @@ namespace libsemigroups {
letter_type g,
node_type t,
size_type e,
size_type n) noexcept
: source(s), generator(g), target(t), num_edges(e), num_nodes(n) {}
size_type n,
bool tin) noexcept
: source(s),
generator(g),
target(t),
num_edges(e),
num_nodes(n),
target_is_new_node(tin) {}
node_type source;
letter_type generator;
node_type target;
size_type num_edges; // Number of edges in the graph when
// *this was added to the stack
size_type num_nodes; // Number of nodes in the graph
// after the definition is made
bool target_is_new_node;
};

///////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -206,11 +213,14 @@ namespace libsemigroups {
void Sims1::iterator_base::init(size_type n) {
if (n != 0) {
if (n > 1 || _min_target_node == 1) {
_pending.emplace_back(0, 0, 1, 0, 2);
_pending.emplace_back(0, 0, 1, 0, 2, true);
}
if (_min_target_node == 0) {
_pending.emplace_back(0, 0, 0, 0, 1);
_pending.emplace_back(0, 0, 0, 0, 1, false);
}
// TODO maybe use less space in _2_sided_include
_2_sided_include.assign((n * (n - 1)), word_type());
_2_sided_words.assign(n, word_type());
}
}

Expand Down Expand Up @@ -243,7 +253,9 @@ namespace libsemigroups {

// Don't call number_of_edges because this calls the function in
// WordGraph
size_type const start = _felsch_graph.definitions().size();
size_type start = _felsch_graph.definitions().size();
size_type const prev_num_non_tree_edges
= 2 * ((start - _felsch_graph.number_of_active_nodes()) + 2);

_felsch_graph.set_target_no_checks(
current.source, current.generator, current.target);
Expand All @@ -258,6 +270,52 @@ namespace libsemigroups {
return false;
}

if (_sims1->kind() == congruence_kind::twosided) {
if (current.target_is_new_node) {
_2_sided_words[current.target] = _2_sided_words[current.source];
_2_sided_words[current.target].push_back(current.generator);
}
// TODO avoid extra copies here
// One relation in _2_sided_include for every non-tree edge
while (start < _felsch_graph.definitions().size()) {
for (size_t i = start, j = 0; i < _felsch_graph.definitions().size();
++i) {
auto e = _felsch_graph.definitions()[i];
if (current.target_is_new_node && e.first == current.source
&& e.second == current.generator) {
continue;
}
_2_sided_include[prev_num_non_tree_edges + 2 * j]
= _2_sided_words[e.first];
_2_sided_include[prev_num_non_tree_edges + 2 * j].push_back(
e.second);
_2_sided_include[prev_num_non_tree_edges + 2 * j + 1]
// TODO target_no_checks
= _2_sided_words[_felsch_graph.target(e.first, e.second)];
j++;
}
// TODO different things if current.target is a new node

size_t num_non_tree_edges
= 2
* (_felsch_graph.definitions().size()
- _felsch_graph.number_of_active_nodes() + 1);

first = _2_sided_include.cbegin();
last = _2_sided_include.cbegin() + num_non_tree_edges;
start = _felsch_graph.definitions().size();

if (!felsch_graph::make_compatible<RegisterDefs>(
_felsch_graph,
0,
_felsch_graph.number_of_active_nodes(),
first,
last)) {
return false;
}
}
}

first = _sims1->exclude().cbegin();
last = _sims1->exclude().cend();
node_type root = 0;
Expand Down Expand Up @@ -286,10 +344,10 @@ namespace libsemigroups {
{
std::lock_guard<std::mutex> lock(_mtx);
if (M < _max_num_classes) {
_pending.emplace_back(next, a, M, N, M + 1);
_pending.emplace_back(next, a, M, N, M + 1, true);
}
for (node_type b = M; b-- > _min_target_node;) {
_pending.emplace_back(next, a, b, N, M);
_pending.emplace_back(next, a, b, N, M, false);
}
}
stats.total_pending_now
Expand Down Expand Up @@ -526,16 +584,12 @@ namespace libsemigroups {
////////////////////////////////////////////////////////////////////////

Sims1& Sims1::kind(congruence_kind ck) {
if (ck == congruence_kind::twosided) {
LIBSEMIGROUPS_EXCEPTION("expected congruence_kind::right or "
"congruence_kind::left, found {}",
ck);
} else if (ck != kind()) {
if (ck == congruence_kind::left && kind() != ck) {
presentation::reverse(_presentation);
reverse(_include);
reverse(_exclude);
_kind = ck;
}
_kind = ck;
return *this;
}

Expand Down
44 changes: 42 additions & 2 deletions tests/test-sims1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@

namespace libsemigroups {

namespace {} // namespace

using word_graph_type = typename Sims1::word_graph_type;
using node_type = typename word_graph_type::node_type;

Expand Down Expand Up @@ -2837,6 +2835,48 @@ namespace libsemigroups {
REQUIRE(s.number_of_threads(4).number_of_congruences(std::pow(2, 6)) == 0);
}

LIBSEMIGROUPS_TEST_CASE("Sims1", "092", "2-sided example", "[quick][sims1]") {
Presentation<word_type> p;
p.alphabet(2);
p.contains_empty_word(true);
presentation::add_rule(p, 00_w, {});
presentation::add_rule(p, 01_w, 1_w);
presentation::add_rule(p, 11_w, 1_w);
Sims1 s(congruence_kind::twosided, p);
// REQUIRE(s.number_of_congruences(4) == 4); // Verified with GAP
auto it = s.cbegin(4);
REQUIRE(*(it++) == to_word_graph<node_type>(4, {{0, 0}}));
REQUIRE(*(it++) == to_word_graph<node_type>(4, {{0, 1}, {1, 1}}));
REQUIRE(*(it++) == to_word_graph<node_type>(4, {{1, 2}, {0, 2}, {2, 2}}));
REQUIRE(*(it++)
== to_word_graph<node_type>(4, {{1, 2}, {0, 2}, {3, 2}, {2, 2}}));
}

LIBSEMIGROUPS_TEST_CASE("Sims1", "093", "2-sided example", "[quick][sims1]") {
Sims1 s(congruence_kind::twosided, full_transformation_monoid(4));

REQUIRE(s.number_of_congruences(256) == 11); // Verified with GAP
}

LIBSEMIGROUPS_TEST_CASE("Sims1", "094", "2-sided example", "[quick][sims1]") {
Presentation<word_type> p;
p.contains_empty_word(true);
p.alphabet({0, 1});
presentation::add_rule(p, {0, 0, 0}, {0});
presentation::add_rule(p, {1, 1}, {1});
presentation::add_rule(p, {0, 1, 0, 1}, {0});
Sims1 s(congruence_kind::twosided, p);

// REQUIRE(s.number_of_congruences(4) == 6); // Verified with GAP
auto it = s.cbegin(5);
REQUIRE(*(it++) == to_word_graph<node_type>(5, {{0, 0}}));
REQUIRE(*(it++) == to_word_graph<node_type>(5, {{1, 0}, {1, 1}}));
REQUIRE(*(it++) == to_word_graph<node_type>(5, {{1, 1}, {1, 1}}));
REQUIRE(*(it++) == to_word_graph<node_type>(5, {{1, 2}, {1, 1}, {1, 2}}));
REQUIRE(*(it++) == to_word_graph<node_type>(5, {{1, 2}, {1, 1}, {2, 2}}));
REQUIRE(*(it++)
== to_word_graph<node_type>(5, {{1, 2}, {1, 1}, {3, 2}, {3, 3}}));
}
} // namespace libsemigroups

// [[[0, 0, 0]], #1#
Expand Down

0 comments on commit ded81ac

Please sign in to comment.