diff --git a/example/bench.cpp b/example/bench.cpp index 250d34b..5b83d36 100644 --- a/example/bench.cpp +++ b/example/bench.cpp @@ -15,7 +15,7 @@ void test(const G &group) { int order = cosets.order(); std::cout - << std::setw(7) << group.name() << ", " + << std::setw(7) << group.name << ", " << std::setw(7) << order << ", " << std::fixed << std::setprecision(6) << diff << "s" << std::endl; diff --git a/include/tc/core/group.hpp b/include/tc/core/group.hpp index 4e56033..7f6f296 100644 --- a/include/tc/core/group.hpp +++ b/include/tc/core/group.hpp @@ -10,81 +10,59 @@ #include #include +namespace { + template + std::string stringify(const T &vec) { + std::stringstream ss; + ss << "[" << vec << "]"; + return ss.str(); + } +} + namespace tc { + /// A Schlafli Matrix template - struct Group; - - template - struct SubGroup; - - template - class Group { + class Group : public Eigen::Matrix { public: - using Matrix = Eigen::Matrix; + using Base = Eigen::Matrix; - private: - public: - std::string _name; - Matrix _data; - Eigen::SelfAdjointView _mults; + std::string name; - public: - Group(const Group &g) : - _name(g._name), - _data(g._data), - _mults(_data) { - } - - Group(Group &&g) noexcept: - _name(std::move(g._name)), - _data(std::move(g._data)), - _mults(_data) { - } - - explicit Group(std::string name = "G") : - _name(std::move(name)), - _data(), - _mults(_data) { - _data.fill(2); - } - - unsigned int rank() const { - return _data.rows(); - } - - std::string name() const { - return _name; - } - - typename Matrix::Scalar &operator()(int a, int b) { - return _mults(a, b); - } - - typename Matrix::Scalar operator()(int a, int b) const { - return _mults(a, b); - } + using Base::Base; }; + template + using Symbol = Eigen::Vector; + + template + Group schlafli(const Symbol &mults, const std::string &name) { + Group res; + res.name = name; + + res.fill(2); + res.topRightCorner(Rank - 1, Rank - 1).diagonal() << mults; + res.bottomLeftCorner(Rank - 1, Rank - 1).diagonal() << mults; + + return res; + } + + template + Group schlafli(const Symbol &mults) { + return schlafli(mults, stringify(mults)); + } + template Group product(const Group &g, const Group
&h) { - std::stringstream ss; - ss << g.name << "*" << h.name; + Group res; + res.name = g.name + "*" + h.name; - Group res(ss.str()); + res.fill(2); int off = 0; - for (int i = 0; i < GR; ++i) { - for (int j = i; j < GR; ++j) { - res(i + off, j + off) = g(i, j); - } - } + res.block(off, off, GR, GR) << g.array() + off; off += GR; - for (int i = 0; i < HR; ++i) { - for (int j = i; j < HR; ++j) { - res(i + off, j + off) = h(i, j); - } - } + res.block(off, off, HR, HR) << h.array() + off; off += HR; return res; @@ -92,19 +70,14 @@ namespace tc { template Group power(const Group &g) { - std::stringstream ss; - ss << g.name << "^" << P; + Group res; + res.name = g.name + "^" + P; - Group res(ss.str()); + res.fill(2); for (int k = 0; k < P; ++k) { int off = k * GR; - - for (int i = 0; i < GR; ++i) { - for (int j = i; j < GR; ++j) { - res(i + off, j + off) = g(i, j); - } - } + res.block(off, off, GR, GR) << g.array() + off; } return res; diff --git a/include/tc/core/solver.hpp b/include/tc/core/solver.hpp index e9ff640..e80f138 100644 --- a/include/tc/core/solver.hpp +++ b/include/tc/core/solver.hpp @@ -242,8 +242,11 @@ namespace { } namespace tc { + /** + * Assumes that g is a coxeter group - that is, self-adjoint and the diagonal is 2. + */ template - tc::Cosets solve(const Group &g, const std::vector &sub_gens = {}) { + tc::Cosets solve(const Group &group, const std::vector &sub_gens = {}) { tc::Cosets cosets; cosets.add_row(); @@ -256,7 +259,7 @@ namespace tc { cosets.put(0, gen, 0); } - Tables tables(g); + Tables tables(group); tables.add_row(); tables.initialize(0, cosets); diff --git a/include/tc/groups.hpp b/include/tc/groups.hpp index 2ab3625..e01a091 100644 --- a/include/tc/groups.hpp +++ b/include/tc/groups.hpp @@ -2,167 +2,150 @@ #include "core.hpp" -namespace tc { +namespace tc::group { /** - * Construct a group from a (simplified) Schlafli Symbol of the form [a, b, ..., c] - * @param mults: The sequence of multiplicites between adjacent generators. + * Universal Coxeter Group */ template - Group schlafli(const std::array &mults, const std::string &name) { - Group g(name); + Group U() { + std::stringstream ss; + ss << "U(" << Rank << ")"; - for (int i = 0; i < Rank - 1; i++) { - g(i, i + 1) = mults[i]; + Group res; + res.name = ss.str(); + res.fill(2); + return res; + } + + /** + * Simplex + */ + template + Group A() { + std::stringstream ss; + ss << "A(" << Rank << ")"; + + if (Rank == 0) { + Group res; + res.name = ss.str(); + return res; } + std::array mults; + mults.fill(3); + + return schlafli(mults, ss.str()); + } + + /** + * Cube, Orthoplex + */ + template + Group B() { + std::stringstream ss; + ss << "B(" << Rank << ")"; + + tc::Symbol mults; + mults.fill(3); + mults(0) = 4; + + return schlafli(mults, ss.str()); + } + + /** + * Demicube, Orthoplex + */ + template + Group D() { + std::stringstream ss; + ss << "D(" << Rank << ")"; + + tc::Symbol mults; + mults.fill(3); + mults(Rank - 2) = 2; + + Group g = schlafli(mults, ss.str()); + g(1, Rank - 1) = 3; + g(Rank - 1, 1) = 3; + return g; } /** - * Construct a group from a (simplified) Schlafli Symbol of the form [a, b, ..., c] - * @param mults: The sequence of multiplicites between adjacent generators. + * E groups */ template - Group schlafli(const std::array &mults) { + Group E() { std::stringstream ss; - ss << "["; - if (Rank) { - for (size_t i = 0; i < Rank - 2; ++i) { - ss << mults[i] << ","; - } - ss << mults[Rank - 1]; - } - ss << "]"; + ss << "E(" << Rank << ")"; + + tc::Symbol mults; + mults.fill(3); + mults(Rank - 2) = 2; + + Group g = schlafli(mults, ss.str()); + g(2, Rank - 1) = 3; + g(Rank - 1, 2) = 3; + + return g; + } + + /** + * 24 Cell + */ + Group<4> F4() { + return schlafli<4>({3, 4, 3}, "F4"); + } + + /** + * Hexagon + */ + Group<2> G2() { + return schlafli<2>(tc::Symbol<1>(6), "G2"); + } + + /** + * Icosahedron + */ + template + Group H() { + std::stringstream ss; + ss << "H(" << Rank << ")"; + + tc::Symbol mults; + mults.fill(3); + mults(0) = 5; return schlafli(mults, ss.str()); } - namespace group { - /** - * Simplex - */ - template - Group A() { - std::stringstream ss; - ss << "A(" << Rank << ")"; + /** + * Polygonal + */ + Group<2> I2(unsigned int n) { + std::stringstream ss; + ss << "I2(" << n << ")"; - if (Rank == 0) - return Group(ss.str()); + return schlafli<2>(tc::Symbol<1>(n), ss.str()); + } - std::array mults; - mults.fill(3); + /** + * Toroidal. I2(n) * I2(m) + */ + Group<4> T(unsigned int n, unsigned int m) { + std::stringstream ss; + ss << "T(" << n << "," << m << ")"; - return schlafli(mults, ss.str()); - } + return schlafli<4>({n, 2, m}, ss.str()); + } - /** - * Cube, Orthoplex - */ - template - Group B() { - std::stringstream ss; - ss << "B(" << Rank << ")"; + /** + * Toroidal. T(n, n) + */ + Group<4> T(unsigned int n) { + std::stringstream ss; + ss << "T(" << n << ")"; - std::array mults; - mults.fill(3); - mults[0] = 4; - - return schlafli(mults, ss.str()); - } - - /** - * Demicube, Orthoplex - */ - template - Group D() { - std::stringstream ss; - ss << "D(" << Rank << ")"; - - std::array mults; - mults.fill(3); - mults[Rank - 2] = 2; - - Group g = schlafli(mults, ss.str()); - g(1, Rank - 1) = 3; - - return g; - } - - /** - * E groups - */ - template - Group E() { - std::stringstream ss; - ss << "E(" << Rank << ")"; - - std::array mults; - mults.fill(3); - mults[Rank - 2] = 2; - - Group g = schlafli(mults, ss.str()); - g(2, Rank - 1) = 3; - - return g; - } - - /** - * 24 Cell - */ - Group<4> F4() { - return schlafli<4>({3, 4, 3}, "F4"); - } - - /** - * Hexagon - */ - Group<2> G2() { - return schlafli<2>({6}, "G2"); - } - - /** - * Icosahedron - */ - template - Group H() { - std::stringstream ss; - ss << "H(" << Rank << ")"; - - std::array mults; - mults.fill(3); - mults[0] = 5; - - return schlafli(mults, ss.str()); - } - - /** - * Polygonal - */ - Group<2> I2(unsigned int n) { - std::stringstream ss; - ss << "I2(" << n << ")"; - - return schlafli<2>({n}, ss.str()); - } - - /** - * Toroidal. I2(n) * I2(m) - */ - Group<4> T(unsigned int n, unsigned int m) { - std::stringstream ss; - ss << "T(" << n << "," << m << ")"; - - return schlafli<4>({n, 2, m}, ss.str()); - } - - /** - * Toroidal. T(n, n) - */ - Group<4> T(unsigned int n) { - std::stringstream ss; - ss << "T(" << n << ")"; - - return schlafli<4>({n, 2, n}, ss.str()); - } + return schlafli<4>({n, 2, n}, ss.str()); } }