From cddb3b56dccee2ba02d50bc514f31b48033e9ad8 Mon Sep 17 00:00:00 2001 From: allem Date: Mon, 16 Sep 2019 00:34:56 -0400 Subject: [PATCH] split coxeter.hpp into header and source --- cosets/CMakeLists.txt | 16 +- cosets/include/coxeter.hpp | 82 +++++++++ cosets/src/coxeter.cpp | 27 --- cosets/src/main.cpp | 4 +- cosets/src/mesh.cpp | 14 -- cosets/src/mirrors.cpp | 14 -- cosets/src/util/coxeter.cpp | 271 ++++++++++++++++++++++++++++ cosets/src/util/coxeter.hpp | 349 ------------------------------------ cosets/src/util/mesh.hpp | 10 +- 9 files changed, 367 insertions(+), 420 deletions(-) create mode 100644 cosets/include/coxeter.hpp delete mode 100644 cosets/src/coxeter.cpp delete mode 100644 cosets/src/mesh.cpp delete mode 100644 cosets/src/mirrors.cpp create mode 100644 cosets/src/util/coxeter.cpp delete mode 100644 cosets/src/util/coxeter.hpp diff --git a/cosets/CMakeLists.txt b/cosets/CMakeLists.txt index 0df1610..bfb586b 100644 --- a/cosets/CMakeLists.txt +++ b/cosets/CMakeLists.txt @@ -8,16 +8,14 @@ add_custom_command( ) add_executable(${PROJECT_NAME} - src/main.cpp) + src/main.cpp + src/util/coxeter.cpp) + +target_include_directories(${PROJECT_NAME} PRIVATE include) + add_dependencies(cosets shaders) + target_link_libraries(${PROJECT_NAME} PRIVATE glad glm glfw) + target_compile_options(${PROJECT_NAME} PRIVATE -O3) - -add_executable(coxeter src/coxeter.cpp) - -add_executable(mirror src/mirrors.cpp) -target_link_libraries(mirror PRIVATE glm) - -add_executable(mesh src/mesh.cpp) -target_link_libraries(mesh PRIVATE glm) diff --git a/cosets/include/coxeter.hpp b/cosets/include/coxeter.hpp new file mode 100644 index 0000000..29c07e6 --- /dev/null +++ b/cosets/include/coxeter.hpp @@ -0,0 +1,82 @@ +#pragma once + +#include +#include +#include + +struct Mults; +struct Table; +struct IRow; + +struct Mults { + std::map, int> mults; + + void set(int a, int b, int mult); + + [[nodiscard]] int get(int a, int b) const; + + [[nodiscard]] std::vector relation(int a, int b) const; + + [[nodiscard]] std::vector> relations(std::vector gens) const; + + [[nodiscard]] std::vector> irelations(Table *table, std::vector gens) const; +}; + +struct Table { + const std::vector gens; + std::vector gen_inds; + std::vector> fwd; + std::vector> rev; + + explicit Table(std::vector gens); + + [[nodiscard]] int gen_index(int gen) const; + + [[nodiscard]] std::vector gen_index_each(std::vector rel) const; + + void add_row(); + + int add_coset(); + + [[nodiscard]] unsigned size() const; + + void set(int from, int gen, int to); + + [[nodiscard]] int get(int from, int gen) const; + + [[nodiscard]] int rget(int gen, int to) const; + + void iset(int from, int igen, int to); + + [[nodiscard]] int iget(int from, int igen) const; + + [[nodiscard]] int irget(int igen, int to) const; + + [[nodiscard]] std::vector> words() const; + + [[nodiscard]] int apply(int e, const std::vector &word) const; + + [[nodiscard]] int apply(const std::vector &word) const; + + [[nodiscard]] std::vector apply_each(int e, const std::vector> &words) const; + + [[nodiscard]] std::vector apply_each(const std::vector> &words) const; +}; + +struct IRow { + std::vector::const_iterator l; + std::vector::const_iterator r; + + int from; + int to; + + IRow(const std::vector &rel, int cos); + + [[nodiscard]] bool learn(Table *table); +}; + +Table *solve(const std::vector &gens, const std::vector &subgens, const Mults &mults); + +Mults schlafli(const std::vector &symbol); + +std::vector all_gens(int N); diff --git a/cosets/src/coxeter.cpp b/cosets/src/coxeter.cpp deleted file mode 100644 index a4e3e9b..0000000 --- a/cosets/src/coxeter.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "util/coxeter.hpp" - -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; -} diff --git a/cosets/src/main.cpp b/cosets/src/main.cpp index 56ac4b4..c8d592a 100644 --- a/cosets/src/main.cpp +++ b/cosets/src/main.cpp @@ -46,12 +46,12 @@ public: u_color = glGetUniformLocation(program, "color"); const int N = 4; - const Mults &mults = schlafli({3, 4, 3}); + const Mults &mults = schlafli({3, 4, 3}); std::cout << "Generation times: " << std::endl; auto gen_start = std::chrono::high_resolution_clock::now(); - vert_data = vertices(mults, {5, .1, .1, .1}); + vert_data = vertices(mults, {5, .1, .1}); auto gen_vert = std::chrono::high_resolution_clock::now(); std::chrono::duration vert_time = gen_vert - gen_start; std::cout << "Vertices: " << vert_time.count() << std::endl; diff --git a/cosets/src/mesh.cpp b/cosets/src/mesh.cpp deleted file mode 100644 index 2ef34ed..0000000 --- a/cosets/src/mesh.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "util/mesh.hpp" - -int main(int argc, char *argv[]) { - const int N = 3; - const Mults &mults = schlafli({4, 3}); - const std::vector &vs = vertices(mults, {10, 1, 1}); - - std::cout << "# verts: " << vs.size() << std::endl; - - const auto es = edges(mults); - - - return 0; -} diff --git a/cosets/src/mirrors.cpp b/cosets/src/mirrors.cpp deleted file mode 100644 index d6281bf..0000000 --- a/cosets/src/mirrors.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "util/mirrors.hpp" - -int main(int argc, char *argv[]) { - auto normals = mirror<3>(Multiplicities<3>({ - {0, 1, 4}, - {1, 2, 3} - })); - - for (const auto &normal : normals) { - std::cout << glm::to_string(normal) << std::endl; - } - - return 0; -} \ No newline at end of file diff --git a/cosets/src/util/coxeter.cpp b/cosets/src/util/coxeter.cpp new file mode 100644 index 0000000..f03fb15 --- /dev/null +++ b/cosets/src/util/coxeter.cpp @@ -0,0 +1,271 @@ +#include "coxeter.hpp" + +void Mults::set(int a, int b, int mult) { + if (a > b) std::swap(a, b); + mults[std::make_tuple(a, b)] = mult; +} + +int Mults::get(int a, int b) const { + if (a == b) return 1; + if (a > b) std::swap(a, b); + + const auto &tup = std::make_tuple(a, b); + const auto &res = mults.find(tup); + + if (res == mults.end()) return 2; + return res->second; +} + +std::vector Mults::relation(int a, int b) const { + std::vector res{}; + int mult = get(a, b); + + for (int i = 0; i < mult; ++i) { + res.push_back(a); + res.push_back(b); + } + + return res; +} + +std::vector> Mults::relations(std::vector gens) const { + std::vector> res{}; + for (int a = 0; a < gens.size(); ++a) { + for (int b = a; b < gens.size(); ++b) { + res.push_back(relation(gens[a], gens[b])); + } + } + return res; +} + +std::vector> Mults::irelations(Table *table, std::vector gens) const { + std::vector> rels = relations(gens); + std::vector> irels(rels.size()); + for (int i = 0; i < rels.size(); ++i) { + irels[i] = table->gen_index_each(rels[i]); + } + return irels; +} + +Table::Table(const std::vector gens) : gens(gens) { + add_row(); + + gen_inds = std::vector(gens[gens.size() - 1] + 1, -1); + for (int i = 0; i < gens.size(); i++) { + gen_inds[gens[i]] = i; + } +} + +int Table::gen_index(int gen) const { + if (gen >= gen_inds.size()) + throw std::logic_error("Referencing nonexistant generator (too large)"); + int i = gen_inds[gen]; + if (i < 0) + throw std::logic_error("Referencing nonexistant generator (not present)"); + return i; +} + +std::vector Table::gen_index_each(std::vector rel) const { + std::vector res(rel.size(), 0); + for (int i = 0; i < rel.size(); ++i) { + res[i] = gen_index(rel[i]); + } + return res; +} + +void Table::add_row() { + int N = gens.size(); + fwd.emplace_back(N, -1); + rev.emplace_back(N, -1); +} + +int Table::add_coset() { + for (int from = 0; from < (int) size(); ++from) { + for (int gen : gens) { + if (get(from, gen) < 0) { + int to = (int) size(); + add_row(); + set(from, gen, to); + return to; + } + } + } + return 0; +} + +unsigned Table::size() const { + return fwd.size(); +} + +void Table::set(int from, int gen, int to) { + int i = gen_index(gen); + fwd[from][i] = to; + rev[to][i] = from; +} + +int Table::get(int from, int gen) const { + int i = gen_index(gen); + return fwd[from][i]; +} + +int Table::rget(int gen, int to) const { + int i = gen_index(gen); + return rev[to][i]; +} + +void Table::iset(int from, int igen, int to) { + fwd[from][igen] = to; + rev[to][igen] = from; +} + +int Table::iget(int from, int igen) const { + return fwd[from][igen]; +} + +int Table::irget(int igen, int to) const { + return rev[to][igen]; +} + +std::vector> Table::words() const { + 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 igen = 0; igen < gens.size(); igen++) { + int to = iget(from, igen); + if (vecs[to] != nullptr) { + continue; + } + + vecs[to] = new std::vector(*word); + vecs[to]->push_back(gens[igen]); + } + } + } + + std::vector> res(size()); + for (int i = 0; i < (int) size(); ++i) { + res[i] = *vecs[i]; + delete vecs[i]; + } + + return res; +} + +int Table::apply(int e, const std::vector &word) const { + for (const auto &gen : word) { + e = get(e, gen); + } + return e; +} + +int Table::apply(const std::vector &word) const { + return apply(0, word); +} + +std::vector Table::apply_each(int e, const std::vector> &words) const { + std::vector res{}; + + for (const auto &word:words) { + res.push_back(apply(e, word)); + } + + return res; +} + +std::vector Table::apply_each(const std::vector> &words) const { + return apply_each(0, words); +} + +IRow::IRow(const std::vector &rel, int cos) { + this->l = rel.begin(); + this->r = rel.end() - 1; + this->from = cos; + this->to = cos; +} + +bool IRow::learn(Table *table) { + if (r - l == 0) { + return false; + } + + while (r - l > 0) { + int next = table->iget(from, *l); + if (next < 0) break; + l++; + from = next; + } + + while (r - l > 0) { + int next = table->irget(*r, to); + if (next < 0) break; + r--; + to = next; + } + + if (r - l == 0) { + table->iset(from, *l, to); + return true; + } + + return false; +} + +Table *solve(const std::vector &gens, const std::vector &subgens, const Mults &mults) { + auto *table = new Table(gens); + const auto irels = mults.irelations(table, gens); + + for (int gen : subgens) + table->set(0, gen, 0); + + std::vector irows; + irows.reserve(irels.size()); + for (const auto &irel : irels) + irows.emplace_back(irel, 0); + + while (!irows.empty()) { + while (true) { + bool learned = false; + for (int i = (int) irows.size() - 1; i >= 0; i--) { + if (irows[i].learn(table)) { + learned = true; + irows.erase(irows.begin() + i); + } + } + if (!learned) + break; + } + + int i = (int) table->size(); + if (table->add_coset() > 0) { + for (const auto &irel : irels) + irows.emplace_back(irel, i); + } else { + break; + } + } + + return table; +} + +Mults schlafli(const std::vector &symbol) { + Mults mults{}; + for (int i = 0; i < symbol.size(); ++i) { + mults.set(i, i + 1, symbol[i]); + } + return mults; +} + +std::vector all_gens(int N) { + std::vector gens(N); + for (int i = 0; i < N; ++i) { + gens[i] = i; + } + return gens; +} diff --git a/cosets/src/util/coxeter.hpp b/cosets/src/util/coxeter.hpp deleted file mode 100644 index 998c423..0000000 --- a/cosets/src/util/coxeter.hpp +++ /dev/null @@ -1,349 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include - -struct Table; - -struct Mults { - std::map, int> mults{}; - - void set(int a, int b, int mult) { - if (a > b) std::swap(a, b); - mults[std::make_tuple(a, b)] = mult; - } - - [[nodiscard]] int get(int a, int b) const { - if (a == b) return 1; - if (a > b) std::swap(a, b); - - const auto &tup = std::make_tuple(a, b); - const auto &res = mults.find(tup); - - if (res == mults.end()) return 2; - return res->second; - } - - [[nodiscard]] std::vector relation(int a, int b) const { - std::vector res{}; - int mult = get(a, b); - - for (int i = 0; i < mult; ++i) { - res.push_back(a); - res.push_back(b); - } - - return res; - } - - [[nodiscard]] std::vector> relations(std::vector gens) const { - std::vector> res{}; - for (int a = 0; a < gens.size(); ++a) { - for (int b = a; b < gens.size(); ++b) { - res.push_back(relation(gens[a], gens[b])); - } - } - return res; - } - - [[nodiscard]] std::vector> irelations(Table *table, std::vector gens) const; -}; - -template -Mults schlafli(const int (&symbol)[N - 1]) { - Mults mults{}; - for (int i = 0; i < N; ++i) { - mults.set(i, i + 1, symbol[i]); - } - return mults; -} - -struct Table { - const std::vector gens; - std::vector gen_inds; - std::vector> fwd{}; - std::vector> rev{}; - - explicit Table(const std::vector gens) : gens(gens) { - add_row(); - - gen_inds = std::vector(gens[gens.size() - 1] + 1, -1); - for (int i = 0; i < gens.size(); i++) { - gen_inds[gens[i]] = i; - } - } - - [[nodiscard]] int gen_index(int gen) const { - if (gen >= gen_inds.size()) - throw std::logic_error("Referencing nonexistant generator (too large)"); - int i = gen_inds[gen]; - if (i < 0) - throw std::logic_error("Referencing nonexistant generator (not present)"); - return i; - } - - [[nodiscard]] std::vector gen_index_each(std::vector rel) const { - std::vector res(rel.size(), 0); - for (int i = 0; i < rel.size(); ++i) { - res[i] = gen_index(rel[i]); - } - return res; - } - - void add_row() { - int N = gens.size(); - fwd.emplace_back(N, -1); - rev.emplace_back(N, -1); - } - - int add_coset() { - for (int from = 0; from < (int) size(); ++from) { - for (int gen : gens) { - 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) { - int i = gen_index(gen); - fwd[from][i] = to; - rev[to][i] = from; - } - - [[nodiscard]] int get(int from, int gen) const { - int i = gen_index(gen); - return fwd[from][i]; - } - - [[nodiscard]] int rget(int gen, int to) const { - int i = gen_index(gen); - return rev[to][i]; - } - - void iset(int from, int igen, int to) { - fwd[from][igen] = to; - rev[to][igen] = from; - } - - [[nodiscard]] int iget(int from, int igen) const { - return fwd[from][igen]; - } - - [[nodiscard]] int irget(int igen, int to) const { - return rev[to][igen]; - } - - // todo iwords for index-based words? - - 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 igen = 0; igen < gens.size(); igen++) { - int to = iget(from, igen); - if (vecs[to] != nullptr) { - continue; - } - - vecs[to] = new std::vector(*word); - vecs[to]->push_back(gens[igen]); - } - } - } - - std::vector> res(size()); - for (int i = 0; i < (int) size(); ++i) { - res[i] = *vecs[i]; - delete vecs[i]; - } - - return res; - } - - // todo iapply(e) - - [[nodiscard]] int apply(int e, const std::vector &word) const { - for (const auto &gen : word) { - e = get(e, gen); - } - return e; - } - - // todo iapply - - [[nodiscard]] int apply(const std::vector &word) const { - return apply(0, word); - } - - // todo iapply_each(e) - - [[nodiscard]] std::vector apply_each(int e, const std::vector> &words) const { - std::vector res{}; - - for (const auto &word:words) { - res.push_back(apply(e, word)); - } - - return res; - } - - // todo iapply_each - - [[nodiscard]] std::vector apply_each(const std::vector> &words) const { - return apply_each(0, words); - } -}; - -[[nodiscard]] std::vector> Mults::irelations(Table *table, std::vector gens) const { - std::vector> rels = relations(gens); - std::vector> irels(rels.size()); - for (int i = 0; i < rels.size(); ++i) { - irels[i] = table->gen_index_each(rels[i]); - } - return irels; -} - -struct IRow { - std::vector::const_iterator l; - std::vector::const_iterator r; - - int from; - int to; - - IRow(const std::vector &vec, int cos) { - this->l = vec.begin(); - this->r = vec.end() - 1; - this->from = cos; - this->to = cos; - } - - [[nodiscard]] bool learn(Table *table) { - if (r - l == 0) { - return false; - } - - while (r - l > 0) { - int next = table->iget(from, *l); - if (next < 0) break; - l++; - from = next; - } - - while (r - l > 0) { - int next = table->irget(*r, to); - if (next < 0) break; - r--; - to = next; - } - - if (r - l == 0) { - table->iset(from, *l, to); - return true; - } - - return false; - } -}; - -Table *solve(const std::vector &gens, const std::vector &subgens, const Mults &mults) { - auto *table = new Table(gens); - const auto irels = mults.irelations(table, gens); - - for (int gen : subgens) - table->set(0, gen, 0); - - std::vector irows; - irows.reserve(irels.size()); - for (const auto &irel : irels) - irows.emplace_back(irel, 0); - - while (!irows.empty()) { - while (true) { - bool learned = false; - for (int i = (int) irows.size() - 1; i >= 0; i--) { - if (irows[i].learn(table)) { - learned = true; - irows.erase(irows.begin() + i); - } - } - if (!learned) - break; - } - - int i = (int) table->size(); - if (table->add_coset() > 0) { - for (const auto &irel : irels) - irows.emplace_back(irel, i); - } else { - break; - } - } - - return table; -} - -template -Table *solve(const std::vector &subgens, const Mults &mults) { - std::vector gens{}; - for (int i = 0; i < N; ++i) { - gens.push_back(i); - } - return solve(gens, subgens, mults); -} - -std::ostream &operator<<(std::ostream &out, const IRow &row) { - out << "[ " << row.from << " | "; - auto it = row.l; - while (row.r - it > 0) { - out << *it << " "; - it++; - } - out << "| " << row.to << " ]"; - return out; -} - -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 < (int) table.gens.size(); ++i) { - out << arr[i]; - - if (i < table.gens.size() - 1) - out << " "; - } - - out << "]"; - if (j < table.fwd.size() - 1) - out << "\n "; - } - out << "]\n"; - - return out; -} diff --git a/cosets/src/util/mesh.hpp b/cosets/src/util/mesh.hpp index f534ce9..5f5c3b5 100644 --- a/cosets/src/util/mesh.hpp +++ b/cosets/src/util/mesh.hpp @@ -24,7 +24,7 @@ glm::vec4 identity(const std::vector &normals, const float(&coords)[N template std::vector vertices(const Mults &mults, const float (&coords)[N]) { - Table *table = solve({}, mults); + Table *table = solve(all_gens(N), {}, mults); const std::vector normals = mirror(mults); glm::vec4 ident = identity(normals, coords); @@ -45,14 +45,14 @@ template std::vector edges(const Mults &mults) { std::vector res{}; - Table *t_vert = solve({}, mults); + Table *t_vert = solve(all_gens(N), {}, mults); for (const auto &subgens : combinations(N, 1)) { Table *t_edge = solve(subgens, {}, mults); std::vector edge = t_vert->apply_each(t_edge->words()); - Table *c_edge = solve(subgens, mults); + Table *c_edge = solve(all_gens(N), subgens, mults); for (const auto &coset : c_edge->words()) { for (const auto &e : edge) { @@ -68,11 +68,11 @@ template std::vector faces(const Mults &mults) { std::vector res{}; - Table *t_vert = solve({}, mults); + Table *t_vert = solve(all_gens(N), {}, mults); // for each *kind* of face for (const auto &sg_face : combinations(N, 2)) { - Table *cs_face = solve(sg_face, mults); + Table *cs_face = solve(all_gens(N), sg_face, mults); // for each *kind* of edge for (const auto &sg_edge : combinations(sg_face, 1)) {