forked from mirror/toddcox-faster
Make tc::Group an Eigen::Matrix (Schafli Matrix)
Makes tc::Group a direct subclass of Eigen::Matrix. Group should represent a Schlafli matrix. Added a note that tc::solve assumes the matrix to be for a coxeter group. In theory we could also implement the "normal" todd-coxeter and allow any Schlafli matrix as input.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -10,81 +10,59 @@
|
||||
#include <Eigen/Eigen>
|
||||
#include <iostream>
|
||||
|
||||
namespace {
|
||||
template<class T>
|
||||
std::string stringify(const T &vec) {
|
||||
std::stringstream ss;
|
||||
ss << "[" << vec << "]";
|
||||
return ss.str();
|
||||
}
|
||||
}
|
||||
|
||||
namespace tc {
|
||||
/// A Schlafli Matrix
|
||||
template<unsigned int Rank>
|
||||
struct Group;
|
||||
|
||||
template<unsigned int Rank, unsigned int PRank>
|
||||
struct SubGroup;
|
||||
|
||||
template<unsigned int Rank>
|
||||
class Group {
|
||||
class Group : public Eigen::Matrix<unsigned int, Rank, Rank> {
|
||||
public:
|
||||
using Matrix = Eigen::Matrix<unsigned int, Rank, Rank>;
|
||||
using Base = Eigen::Matrix<unsigned int, Rank, Rank>;
|
||||
|
||||
private:
|
||||
public:
|
||||
std::string _name;
|
||||
Matrix _data;
|
||||
Eigen::SelfAdjointView<Matrix, Eigen::Upper> _mults;
|
||||
std::string name;
|
||||
|
||||
public:
|
||||
Group(const Group<Rank> &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<unsigned int Rank>
|
||||
using Symbol = Eigen::Vector<unsigned int, Rank>;
|
||||
|
||||
template<unsigned int Rank>
|
||||
Group<Rank> schlafli(const Symbol<Rank - 1> &mults, const std::string &name) {
|
||||
Group<Rank> 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<unsigned int Rank>
|
||||
Group<Rank> schlafli(const Symbol<Rank - 1> &mults) {
|
||||
return schlafli<Rank>(mults, stringify(mults));
|
||||
}
|
||||
|
||||
template<unsigned int GR, unsigned int HR>
|
||||
Group<GR + HR> product(const Group<GR> &g, const Group<HR> &h) {
|
||||
std::stringstream ss;
|
||||
ss << g.name << "*" << h.name;
|
||||
Group<GR + HR> res;
|
||||
res.name = g.name + "*" + h.name;
|
||||
|
||||
Group<GR + HR> 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<unsigned int GR, unsigned int P>
|
||||
Group<GR * P> power(const Group<GR> &g) {
|
||||
std::stringstream ss;
|
||||
ss << g.name << "^" << P;
|
||||
Group<GR * P> res;
|
||||
res.name = g.name + "^" + P;
|
||||
|
||||
Group<GR * P> 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;
|
||||
|
||||
@@ -242,8 +242,11 @@ namespace {
|
||||
}
|
||||
|
||||
namespace tc {
|
||||
/**
|
||||
* Assumes that g is a coxeter group - that is, self-adjoint and the diagonal is 2.
|
||||
*/
|
||||
template<unsigned int Rank>
|
||||
tc::Cosets<Rank> solve(const Group <Rank> &g, const std::vector<int> &sub_gens = {}) {
|
||||
tc::Cosets<Rank> solve(const Group <Rank> &group, const std::vector<int> &sub_gens = {}) {
|
||||
tc::Cosets<Rank> cosets;
|
||||
cosets.add_row();
|
||||
|
||||
@@ -256,7 +259,7 @@ namespace tc {
|
||||
cosets.put(0, gen, 0);
|
||||
}
|
||||
|
||||
Tables<Rank> tables(g);
|
||||
Tables<Rank> tables(group);
|
||||
tables.add_row();
|
||||
tables.initialize(0, cosets);
|
||||
|
||||
|
||||
@@ -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<unsigned int Rank>
|
||||
Group <Rank> schlafli(const std::array<unsigned int, Rank - 1> &mults, const std::string &name) {
|
||||
Group<Rank> g(name);
|
||||
Group <Rank> U() {
|
||||
std::stringstream ss;
|
||||
ss << "U(" << Rank << ")";
|
||||
|
||||
for (int i = 0; i < Rank - 1; i++) {
|
||||
g(i, i + 1) = mults[i];
|
||||
Group<Rank> res;
|
||||
res.name = ss.str();
|
||||
res.fill(2);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplex
|
||||
*/
|
||||
template<unsigned int Rank>
|
||||
Group <Rank> A() {
|
||||
std::stringstream ss;
|
||||
ss << "A(" << Rank << ")";
|
||||
|
||||
if (Rank == 0) {
|
||||
Group<Rank> res;
|
||||
res.name = ss.str();
|
||||
return res;
|
||||
}
|
||||
|
||||
std::array<unsigned int, Rank - 1> mults;
|
||||
mults.fill(3);
|
||||
|
||||
return schlafli<Rank>(mults, ss.str());
|
||||
}
|
||||
|
||||
/**
|
||||
* Cube, Orthoplex
|
||||
*/
|
||||
template<unsigned int Rank>
|
||||
Group <Rank> B() {
|
||||
std::stringstream ss;
|
||||
ss << "B(" << Rank << ")";
|
||||
|
||||
tc::Symbol<Rank - 1> mults;
|
||||
mults.fill(3);
|
||||
mults(0) = 4;
|
||||
|
||||
return schlafli<Rank>(mults, ss.str());
|
||||
}
|
||||
|
||||
/**
|
||||
* Demicube, Orthoplex
|
||||
*/
|
||||
template<unsigned int Rank>
|
||||
Group <Rank> D() {
|
||||
std::stringstream ss;
|
||||
ss << "D(" << Rank << ")";
|
||||
|
||||
tc::Symbol<Rank - 1> mults;
|
||||
mults.fill(3);
|
||||
mults(Rank - 2) = 2;
|
||||
|
||||
Group<Rank> g = schlafli<Rank>(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<unsigned int Rank>
|
||||
Group <Rank> schlafli(const std::array<unsigned int, Rank - 1> &mults) {
|
||||
Group <Rank> 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<Rank - 1> mults;
|
||||
mults.fill(3);
|
||||
mults(Rank - 2) = 2;
|
||||
|
||||
Group<Rank> g = schlafli<Rank>(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<unsigned int Rank>
|
||||
Group <Rank> H() {
|
||||
std::stringstream ss;
|
||||
ss << "H(" << Rank << ")";
|
||||
|
||||
tc::Symbol<Rank - 1> mults;
|
||||
mults.fill(3);
|
||||
mults(0) = 5;
|
||||
|
||||
return schlafli<Rank>(mults, ss.str());
|
||||
}
|
||||
|
||||
namespace group {
|
||||
/**
|
||||
* Simplex
|
||||
*/
|
||||
template<unsigned int Rank>
|
||||
Group <Rank> 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<Rank>(ss.str());
|
||||
return schlafli<2>(tc::Symbol<1>(n), ss.str());
|
||||
}
|
||||
|
||||
std::array<unsigned int, Rank - 1> 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<Rank>(mults, ss.str());
|
||||
}
|
||||
return schlafli<4>({n, 2, m}, ss.str());
|
||||
}
|
||||
|
||||
/**
|
||||
* Cube, Orthoplex
|
||||
*/
|
||||
template<unsigned int Rank>
|
||||
Group <Rank> 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<unsigned int, Rank - 1> mults;
|
||||
mults.fill(3);
|
||||
mults[0] = 4;
|
||||
|
||||
return schlafli<Rank>(mults, ss.str());
|
||||
}
|
||||
|
||||
/**
|
||||
* Demicube, Orthoplex
|
||||
*/
|
||||
template<unsigned int Rank>
|
||||
Group <Rank> D() {
|
||||
std::stringstream ss;
|
||||
ss << "D(" << Rank << ")";
|
||||
|
||||
std::array<unsigned int, Rank - 1> mults;
|
||||
mults.fill(3);
|
||||
mults[Rank - 2] = 2;
|
||||
|
||||
Group<Rank> g = schlafli<Rank>(mults, ss.str());
|
||||
g(1, Rank - 1) = 3;
|
||||
|
||||
return g;
|
||||
}
|
||||
|
||||
/**
|
||||
* E groups
|
||||
*/
|
||||
template<unsigned int Rank>
|
||||
Group <Rank> E() {
|
||||
std::stringstream ss;
|
||||
ss << "E(" << Rank << ")";
|
||||
|
||||
std::array<unsigned int, Rank - 1> mults;
|
||||
mults.fill(3);
|
||||
mults[Rank - 2] = 2;
|
||||
|
||||
Group<Rank> g = schlafli<Rank>(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<unsigned int Rank>
|
||||
Group <Rank> H() {
|
||||
std::stringstream ss;
|
||||
ss << "H(" << Rank << ")";
|
||||
|
||||
std::array<unsigned int, Rank - 1> mults;
|
||||
mults.fill(3);
|
||||
mults[0] = 5;
|
||||
|
||||
return schlafli<Rank>(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());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user