refactor + start optimization
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
cmake_minimum_required(VERSION 2.8)
|
cmake_minimum_required(VERSION 2.8)
|
||||||
project(hpc)
|
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)
|
||||||
|
|||||||
2
common/CMakeLists.txt
Normal file
2
common/CMakeLists.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
add_library(common INTERFACE)
|
||||||
|
target_include_directories(common INTERFACE include)
|
||||||
110
common/include/groups.hpp
Normal file
110
common/include/groups.hpp
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <types.hpp>
|
||||||
|
|
||||||
|
struct Mult {
|
||||||
|
int from, to, multiplicity;
|
||||||
|
};
|
||||||
|
|
||||||
|
Table mults(const std::vector<Mult>& 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<Mult> ezmults(int ngens, const std::vector<Mult> &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<Mult> 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<Table, int> torus(int res) {
|
||||||
|
|
||||||
|
return std::make_pair(mults(ezmults(4, {
|
||||||
|
{0, 1, res},
|
||||||
|
{2, 3, res},
|
||||||
|
})), 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Order 14,400
|
||||||
|
*/
|
||||||
|
std::pair<Table, int> H4() {
|
||||||
|
return std::make_pair(mults(ezmults(4, {
|
||||||
|
{0, 1, 5},
|
||||||
|
{1, 2, 3},
|
||||||
|
{2, 3, 3},
|
||||||
|
})), 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Order 51,840
|
||||||
|
*/
|
||||||
|
std::pair<Table, int> 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<Table, int> 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<Table, int> 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);
|
||||||
|
}
|
||||||
4
common/include/types.hpp
Normal file
4
common/include/types.hpp
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
using Gens=std::vector<int>;
|
||||||
|
using Table=std::vector<Gens>;
|
||||||
3
cpu-opt/CMakeLists.txt
Normal file
3
cpu-opt/CMakeLists.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
set(CMAKE_CXX_FLAGS "-std=gnu++11 -fopenmp -O3")
|
||||||
|
|
||||||
|
add_executable(cpu-opt main.cpp solver.hpp)
|
||||||
15
cpu-opt/main.cpp
Normal file
15
cpu-opt/main.cpp
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
using Gen=int;
|
||||||
|
using Cos=int;
|
||||||
|
|
||||||
|
struct Rels {
|
||||||
|
Gen *gen[2];
|
||||||
|
int *size; // multiplicity * 2
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
195
cpu-opt/solver.hpp
Normal file
195
cpu-opt/solver.hpp
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
struct Mults;
|
||||||
|
struct Table;
|
||||||
|
struct IRow;
|
||||||
|
|
||||||
|
struct Mults {
|
||||||
|
const int dim;
|
||||||
|
std::map<std::tuple<int, int>, int> mults;
|
||||||
|
|
||||||
|
explicit Mults(const int dim) : dim(dim) {
|
||||||
|
mults = std::map<std::tuple<int, int>, 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<int> irelation(int a, int b) const {
|
||||||
|
std::vector<int> 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<int> &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<int> &isubgens) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Table {
|
||||||
|
const Mults mults;
|
||||||
|
std::vector<std::vector<int>> 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<int>::const_iterator l;
|
||||||
|
std::vector<int>::const_iterator r;
|
||||||
|
|
||||||
|
int from;
|
||||||
|
int to;
|
||||||
|
|
||||||
|
IRow(const std::vector<int> &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<int> &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<int> &isubgens) const {
|
||||||
|
auto *table = new Table(*this);
|
||||||
|
for (int igen : isubgens)
|
||||||
|
table->iset(0, igen, 0);
|
||||||
|
|
||||||
|
std::vector<std::vector<int>> irels{};
|
||||||
|
for (unsigned a = 0; a < dim; ++a) {
|
||||||
|
for (unsigned b = a + 1; b < dim; ++b) {
|
||||||
|
irels.push_back(irelation(a, b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<IRow> 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
4
cpu-slo/CMakeLists.txt
Normal file
4
cpu-slo/CMakeLists.txt
Normal file
@@ -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)
|
||||||
@@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
#include <omp.h>
|
#include <omp.h>
|
||||||
|
|
||||||
using Gens=std::vector<int>;
|
#include <types.hpp>
|
||||||
using Table=std::vector<Gens>;
|
#include <groups.hpp>
|
||||||
|
|
||||||
void pp(const Gens &g, int w) {
|
void pp(const Gens &g, int w) {
|
||||||
for (const auto &e : g) {
|
for (const auto &e : g) {
|
||||||
@@ -149,144 +149,39 @@ Table solve_tc(int ngens, const Gens &subgens, const std::vector<Gens> &rels) {
|
|||||||
return cosets;
|
return cosets;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Mult {
|
int main(int argc, const char *argv[]) {
|
||||||
int from, to, multiplicity;
|
|
||||||
};
|
|
||||||
|
|
||||||
Table mults(std::vector<Mult> 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<Mult> 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
Table res = mults(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,i,j});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Order 4*res*res
|
|
||||||
*/
|
|
||||||
std::pair<Table,int> torus(int res) {
|
|
||||||
return std::make_pair(ezmults(4,{
|
|
||||||
{0,1,res},
|
|
||||||
{2,3,res},
|
|
||||||
}),4);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Order 14,400
|
|
||||||
*/
|
|
||||||
std::pair<Table,int> H4() {
|
|
||||||
return std::make_pair(ezmults(4,{
|
|
||||||
{0,1,5},
|
|
||||||
{1,2,3},
|
|
||||||
{2,3,3},
|
|
||||||
}),4);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Order 51,840
|
|
||||||
*/
|
|
||||||
std::pair<Table,int> 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<Table,int> 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<Table,int> 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[]) {
|
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
std::cerr << "REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE" << std::endl;
|
std::cerr << "missing type argument." << std::endl;
|
||||||
std::cerr << "gimme more ~~tendies~~ arguments" << std::endl;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int type = std::strtol(argv[1], nullptr, 10);
|
int type = std::strtol(argv[1], nullptr, 10);
|
||||||
int arg = 0;
|
int arg = 0;
|
||||||
std::pair<Table,int> res;
|
std::pair<Table, int> res;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 0:
|
case 0:
|
||||||
if (argc < 3) {
|
if (argc < 3) {
|
||||||
std::cerr << "Must provide a size for torus!" << std::endl;
|
std::cerr << "Must provide a size for torus!" << std::endl;
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
arg = std::strtol(argv[2], nullptr, 10);
|
arg = std::strtol(argv[2], nullptr, 10);
|
||||||
res = torus(arg);
|
res = torus(arg);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
res = H4();
|
res = H4();
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
res = E6();
|
res = E6();
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
res = E7();
|
res = E7();
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
res = E8();
|
res = E8();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
std::cerr << "Not a valid type!" << std::endl;
|
std::cerr << "Not a valid type!" << std::endl;
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Table &rels = res.first;
|
const Table &rels = res.first;
|
||||||
@@ -300,7 +195,7 @@ int main(int argc, char *argv[]) {
|
|||||||
size_t order = cosets.size();
|
size_t order = cosets.size();
|
||||||
|
|
||||||
// ngens,type,arg,time,order
|
// 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;
|
return 0;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user