diff --git a/.idea/cosets.iml b/.idea/cosets.iml deleted file mode 100644 index f08604b..0000000 --- a/.idea/cosets.iml +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 9bb8048..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 44442b6..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/cosets/CMakeLists.txt b/cosets/CMakeLists.txt index dfa29e2..c8cf75b 100644 --- a/cosets/CMakeLists.txt +++ b/cosets/CMakeLists.txt @@ -15,3 +15,5 @@ add_custom_command( ${CMAKE_CURRENT_SOURCE_DIR}/src/shaders ${CMAKE_CURRENT_BINARY_DIR}/shaders ) + +add_executable(coxeter src/tc.cpp) diff --git a/cosets/src/main.cpp b/cosets/src/main.cpp index 8531459..de0e007 100644 --- a/cosets/src/main.cpp +++ b/cosets/src/main.cpp @@ -29,16 +29,16 @@ public: program = build_program("main", vs, fs); - float verts_data[4 * VERTS_N]{ - +.5f, +.5f, 0.f, 0.f, - +.5f, -.5f, 0.f, 0.f, - -.5f, -.5f, 0.f, -.1f, - -.5f, +.5f, 0.f, -.1f, + glm::vec4 verts_data[VERTS_N]{ + {+0.5, +0.5, +0.5, +0.0}, + {+0.5, -0.5, +0.5, +0.0}, + {-0.5, -0.5, +0.5, +0.0}, + {-0.5, +0.5, +0.5, +0.0}, - +.5f, +.5f, 0.f, .1f, - +.5f, -.5f, 0.f, .1f, - -.5f, -.5f, 0.2f, .0f, - -.5f, +.5f, 0.2f, .0f, + {+0.5, +0.5, +0.5, -0.5}, + {+0.5, -0.5, +0.5, -0.5}, + {-0.5, -0.5, +0.5, +0.5}, + {-0.5, +0.5, +0.5, +0.5}, }; glGenBuffers(1, &verts); diff --git a/cosets/src/tc.cpp b/cosets/src/tc.cpp new file mode 100644 index 0000000..12ca511 --- /dev/null +++ b/cosets/src/tc.cpp @@ -0,0 +1,222 @@ +#include +#include +#include +#include +#include + + +struct Table { + int N; + std::vector> fwd; + std::vector> rev; + + explicit Table(int N) { + add_row(); + this->N = N; + } + + void add_row() { + fwd.emplace_back(N, -1); + rev.emplace_back(N, -1); + } + + int add_coset() { + for (int from = 0; from < (int) size(); ++from) { + for (int gen = 0; gen < N; ++gen) { + if (get(from, gen) < 0) { + int to = (int) size(); + add_row(); + set(from, gen, to); + return to; + } + } + } + return 0; + } + + [[nodiscard]] unsigned size() const { + return fwd.size(); + } + + void set(int from, int gen, int to) { + fwd[from][gen] = to; + rev[to][gen] = from; + } + + [[nodiscard]] int get(int from, int gen) const { + return fwd[from][gen]; + } + + [[nodiscard]] int rget(int gen, int to) const { + return rev[to][gen]; + } + + std::vector> words() { + std::vector *> vecs(size()); + vecs[0] = new std::vector(); + + while (std::find(vecs.begin(), vecs.end(), nullptr) != vecs.end()) { + for (int from = 0; from < (int) vecs.size(); ++from) { + std::vector *word = vecs[from]; + if (word == nullptr) { + continue; + } + + for (int gen = 0; gen < (int) N; ++gen) { + int to = get(from, gen); + if (vecs[to] != nullptr) { + continue; + } + + vecs[to] = new std::vector(*word); + vecs[to]->push_back(gen); + } + } + } + + std::vector> res(size()); + for (int i = 0; i < (int) size(); ++i) { + res[i] = *vecs[i]; + } + + return res; + } +}; + +struct Row { + std::vector::const_iterator l; + std::vector::const_iterator r; + + int from; + int to; + + Row(const std::vector &vec, int cos) { + this->l = vec.begin(); + this->r = vec.end() - 1; + this->from = cos; + this->to = cos; + } + + bool learn(Table *table) { + if (r - l == 0) { + return false; + } + + while (r - l > 0) { + int next = table->get(from, *l); + if (next < 0) break; + l++; + from = next; + } + + while (r - l > 0) { + int next = table->rget(*r, to); + if (next < 0) break; + r--; + to = next; + } + + if (r - l == 0) { + table->set(from, *l, to); + return true; + } + + return false; + } +}; + +std::ostream &operator<<(std::ostream &out, const Row &row) { + out << "[ " << row.from << " | "; + auto it = row.l; + while (row.r - it > 0) { + out << *it << " "; + it++; + } + out << "| " << row.to << " ]"; + return out; +} + +Table *solve(int gens, const std::vector &subgens, const std::vector> &rels) { + auto *table = new Table(gens); + + for (int gen : subgens) + table->set(0, gen, 0); + + std::vector rows; + rows.reserve(rels.size()); + for (const auto &rel : rels) + rows.emplace_back(rel, 0); + + while (!rows.empty()) { + while (true) { + bool learned = false; + for (int i = (int) rows.size() - 1; i >= 0; i--) { + if (rows[i].learn(table)) { + learned = true; + rows.erase(rows.begin() + i); + } + } + if (!learned) + break; + } + + int i = (int) table->size(); + if (table->add_coset() > 0) { + for (const auto &rel : rels) + rows.emplace_back(rel, i); + } else { + break; + } + } + + return table; +} + +std::ostream &operator<<(std::ostream &out, const Table &table) { + int k = ceil(log10(table.size())); + + out << "["; + for (unsigned j = 0; j < table.size(); ++j) { + auto arr = table.fwd[j]; + out << " " << std::setw(k) << j << " ["; + for (int i = 0; i < table.N; ++i) { + out << arr[i]; + + if (i < table.N - 1) + out << " "; + } + + out << "]"; + if (j < table.fwd.size() - 1) + out << "\n "; + } + out << "]\n"; + + return out; +} + +int main(int argc, char *argv[]) { + std::vector> ids{ + {0, 0}, + {1, 1}, + {2, 2}, + {0, 1, 0, 1, 0, 1, 0, 1}, + {1, 2, 1, 2, 1, 2}, + {0, 2, 0, 2} + }; + + Table *table = solve(3, {0, 1}, ids); + + std::cout << table->size() << std::endl; + std::cout << *table << std::endl; + + for (const auto &v : table->words()) { + std::cout << "[ "; + for (auto e : v) { + std::cout << e << " "; + } + std::cout << "]\n"; + } + + return 0; +}