diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f7d6f5..de9740b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,7 @@ cmake_minimum_required(VERSION 2.8) project(hpc) -set(CMAKE_CXX_FLAGS "-std=gnu++11 -fopenmp -O3") +add_subdirectory(common) -add_executable(hpc main.cpp) +add_subdirectory(cpu-slo) +add_subdirectory(cpu-opt) diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt new file mode 100644 index 0000000..7cdff4e --- /dev/null +++ b/common/CMakeLists.txt @@ -0,0 +1,2 @@ +add_library(common INTERFACE) +target_include_directories(common INTERFACE include) diff --git a/common/include/groups.hpp b/common/include/groups.hpp new file mode 100644 index 0000000..e8cb22f --- /dev/null +++ b/common/include/groups.hpp @@ -0,0 +1,110 @@ +#pragma once + +#include + +struct Mult { + int from, to, multiplicity; +}; + +Table mults(const std::vector& ms) { + Table res; + for (const auto &m : ms) { + int N = res.size(); + res.emplace_back(m.multiplicity * 2, m.to); + for (int i = 0; i < m.multiplicity * 2; i += 2) { + res[N][i] = m.from; + } + } + return res; +} + +std::vector ezmults(int ngens, const std::vector &ms) { + bool table[ngens][ngens]; + + for (int i = 0; i < ngens; i++) { + for (int j = 0; j < ngens; j++) { + table[i][j] = false; + } + } + + for (const auto &m : ms) { + table[m.from][m.to] = true; + table[m.to][m.from] = true; + } + + std::vector res(ms); + + for (int i = 0; i < ngens; i++) { + for (int j = i + 1; j < ngens; j++) { + if (!table[i][j]) { + res.push_back({i, j, 2}); + } + } + } + + return res; +} + +/* + * Order 4*res*res + */ +std::pair torus(int res) { + + return std::make_pair(mults(ezmults(4, { + {0, 1, res}, + {2, 3, res}, + })), 4); +} + +/* + * Order 14,400 + */ +std::pair H4() { + return std::make_pair(mults(ezmults(4, { + {0, 1, 5}, + {1, 2, 3}, + {2, 3, 3}, + })), 4); +} + +/* + * Order 51,840 + */ +std::pair E6() { + return std::make_pair(mults(ezmults(6, { + {0, 1, 3}, + {1, 2, 3}, + {2, 3, 3}, + {2, 4, 3}, + {4, 5, 3}, + })), 6); +} + +/* + * Order 2,903,040 + */ +std::pair E7() { + return std::make_pair(mults(ezmults(7, { + {0, 1, 3}, + {1, 2, 3}, + {2, 3, 3}, + {2, 4, 3}, + {4, 5, 3}, + {5, 6, 3}, + })), 7); +} + +/* + * Order 696,729,600 + */ +std::pair E8() { + return std::make_pair(mults(ezmults(8, { + {0, 1, 3}, + {1, 2, 3}, + {2, 3, 3}, + {2, 4, 3}, + {4, 5, 3}, + {5, 6, 3}, + {6, 7, 3}, + })), 8); +} diff --git a/common/include/types.hpp b/common/include/types.hpp new file mode 100644 index 0000000..18b23be --- /dev/null +++ b/common/include/types.hpp @@ -0,0 +1,4 @@ +#pragma once + +using Gens=std::vector; +using Table=std::vector; diff --git a/cpu-opt/CMakeLists.txt b/cpu-opt/CMakeLists.txt new file mode 100644 index 0000000..4d7e286 --- /dev/null +++ b/cpu-opt/CMakeLists.txt @@ -0,0 +1,3 @@ +set(CMAKE_CXX_FLAGS "-std=gnu++11 -fopenmp -O3") + +add_executable(cpu-opt main.cpp solver.hpp) diff --git a/cpu-opt/main.cpp b/cpu-opt/main.cpp new file mode 100644 index 0000000..79be89d --- /dev/null +++ b/cpu-opt/main.cpp @@ -0,0 +1,15 @@ +#include + +using Gen=int; +using Cos=int; + +struct Rels { + Gen *gen[2]; + int *size; // multiplicity * 2 +}; + +int main(int argc, char *argv[]) { + + + return EXIT_SUCCESS; +} diff --git a/cpu-opt/solver.hpp b/cpu-opt/solver.hpp new file mode 100644 index 0000000..79469d3 --- /dev/null +++ b/cpu-opt/solver.hpp @@ -0,0 +1,195 @@ +#pragma once + +#include +#include +#include + +struct Mults; +struct Table; +struct IRow; + +struct Mults { + const int dim; + std::map, int> mults; + + explicit Mults(const int dim) : dim(dim) { + mults = std::map, int>(); + } + + 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 irelation(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]] Mults sub(const std::vector &igens) const { + Mults res(igens.size()); + for (int a = 0; a < (int) igens.size(); ++a) { + for (int b = a + 1; b < (int) igens.size(); ++b) { + res.set(a, b, get(igens[a], igens[b])); + } + } + return res; + } + + [[nodiscard]] Table *isolve(const std::vector &isubgens) const; +}; + +struct Table { + const Mults mults; + std::vector> fwd; + + explicit Table(Mults mults) : mults(mults) { + add_row(); + } + + void add_row() { + fwd.emplace_back(mults.dim, -1); + } + + int add_coset() { + for (int from = 0; from < (int) size(); ++from) { + for (int igen = 0; igen < (int) mults.dim; igen++) { + if (iget(from, igen) < 0) { + int to = (int) size(); + add_row(); + iset(from, igen, to); + return to; + } + } + } + return 0; + } + + [[nodiscard]] unsigned size() const { + return fwd.size(); + } + + void iset(int from, int igen, int to) { + fwd[from][igen] = to; + fwd[to][igen] = from; + } + + [[nodiscard]] int iget(int from, int igen) const { + return fwd[from][igen]; + } + + [[nodiscard]] int irget(int igen, int to) const { + return fwd[to][igen]; + } + +}; + +struct IRow { + std::vector::const_iterator l; + std::vector::const_iterator r; + + int from; + int to; + + IRow(const std::vector &rel, int cos) + : l(rel.begin()), r(rel.end() - 1), from(cos), 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; + } +}; + +Mults schlafli(const std::vector &symbol) { + unsigned int dim = symbol.size(); + Mults mults(dim + 1); + for (int i = 0; i < dim; ++i) { + mults.set(i, i + 1, symbol[i]); + } + return mults; +} + +Table *Mults::isolve(const std::vector &isubgens) const { + auto *table = new Table(*this); + for (int igen : isubgens) + table->iset(0, igen, 0); + + std::vector> irels{}; + for (unsigned a = 0; a < dim; ++a) { + for (unsigned b = a + 1; b < dim; ++b) { + irels.push_back(irelation(a, b)); + } + } + + 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; +} + + diff --git a/cpu-slo/CMakeLists.txt b/cpu-slo/CMakeLists.txt new file mode 100644 index 0000000..2b63699 --- /dev/null +++ b/cpu-slo/CMakeLists.txt @@ -0,0 +1,4 @@ +set(CMAKE_CXX_FLAGS "-std=gnu++11 -fopenmp -O3") + +add_executable(cpu-slo main.cpp) +target_link_libraries(cpu-slo PRIVATE common) diff --git a/Makefile b/cpu-slo/Makefile similarity index 100% rename from Makefile rename to cpu-slo/Makefile diff --git a/main.cpp b/cpu-slo/main.cpp similarity index 62% rename from main.cpp rename to cpu-slo/main.cpp index 52ada27..2ce9117 100644 --- a/main.cpp +++ b/cpu-slo/main.cpp @@ -5,8 +5,8 @@ #include -using Gens=std::vector; -using Table=std::vector; +#include +#include void pp(const Gens &g, int w) { for (const auto &e : g) { @@ -149,144 +149,39 @@ Table solve_tc(int ngens, const Gens &subgens, const std::vector &rels) { return cosets; } -struct Mult { - int from, to, multiplicity; -}; - -Table mults(std::vector ms) { - Table res; - for (const auto &m : ms) { - int N = res.size(); - res.emplace_back(m.multiplicity * 2, m.to); - for (int i = 0; i < m.multiplicity * 2; i += 2) { - res[N][i] = m.from; - } - } - return res; -} - -Table ezmults(int ngens, std::vector ms) { - bool table[ngens][ngens]; - - for (int i=0; i torus(int res) { - return std::make_pair(ezmults(4,{ - {0,1,res}, - {2,3,res}, - }),4); -} - -/* - * Order 14,400 - */ -std::pair H4() { - return std::make_pair(ezmults(4,{ - {0,1,5}, - {1,2,3}, - {2,3,3}, - }),4); -} - -/* - * Order 51,840 - */ -std::pair E6() { - return std::make_pair(ezmults(6,{ - {0,1,3}, - {1,2,3}, - {2,3,3}, - {2,4,3}, - {4,5,3}, - }),6); -} - -/* - * Order 2,903,040 - */ -std::pair E7() { - return std::make_pair(ezmults(7,{ - {0,1,3}, - {1,2,3}, - {2,3,3}, - {2,4,3}, - {4,5,3}, - {5,6,3}, - }),7); -} - -/* - * Order 696,729,600 - */ -std::pair E8() { - return std::make_pair(ezmults(8,{ - {0,1,3}, - {1,2,3}, - {2,3,3}, - {2,4,3}, - {4,5,3}, - {5,6,3}, - {6,7,3}, - }),8); -} - -int main(int argc, char *argv[]) { +int main(int argc, const char *argv[]) { if (argc < 2) { - std::cerr << "REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE" << std::endl; - std::cerr << "gimme more ~~tendies~~ arguments" << std::endl; + std::cerr << "missing type argument." << std::endl; return 1; } int type = std::strtol(argv[1], nullptr, 10); int arg = 0; - std::pair res; + std::pair res; switch (type) { - case 0: - if (argc < 3) { + case 0: + if (argc < 3) { std::cerr << "Must provide a size for torus!" << std::endl; return 2; - } - arg = std::strtol(argv[2], nullptr, 10); - res = torus(arg); - break; - case 1: - res = H4(); - break; - case 2: - res = E6(); - break; - case 3: - res = E7(); - break; - case 4: - res = E8(); - break; - default: - std::cerr << "Not a valid type!" << std::endl; - return 3; + } + arg = std::strtol(argv[2], nullptr, 10); + res = torus(arg); + break; + case 1: + res = H4(); + break; + case 2: + res = E6(); + break; + case 3: + res = E7(); + break; + case 4: + res = E8(); + break; + default: + std::cerr << "Not a valid type!" << std::endl; + return 3; } const Table &rels = res.first; @@ -300,7 +195,7 @@ int main(int argc, char *argv[]) { size_t order = cosets.size(); // ngens,type,arg,time,order - std::cout << ngens << ',' << type << ',' << arg << ',' << diff.count() << ',' << order << std::endl; + std::cout << ngens << ',' << type << ',' << arg << ',' << diff.count() << ',' << order << std::endl; return 0; }