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();
|
int order = cosets.order();
|
||||||
|
|
||||||
std::cout
|
std::cout
|
||||||
<< std::setw(7) << group.name() << ", "
|
<< std::setw(7) << group.name << ", "
|
||||||
<< std::setw(7) << order << ", "
|
<< std::setw(7) << order << ", "
|
||||||
<< std::fixed << std::setprecision(6) << diff << "s"
|
<< std::fixed << std::setprecision(6) << diff << "s"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|||||||
@@ -10,81 +10,59 @@
|
|||||||
#include <Eigen/Eigen>
|
#include <Eigen/Eigen>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
template<class T>
|
||||||
|
std::string stringify(const T &vec) {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "[" << vec << "]";
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace tc {
|
namespace tc {
|
||||||
|
/// A Schlafli Matrix
|
||||||
template<unsigned int Rank>
|
template<unsigned int Rank>
|
||||||
struct Group;
|
class Group : public Eigen::Matrix<unsigned int, Rank, Rank> {
|
||||||
|
|
||||||
template<unsigned int Rank, unsigned int PRank>
|
|
||||||
struct SubGroup;
|
|
||||||
|
|
||||||
template<unsigned int Rank>
|
|
||||||
class Group {
|
|
||||||
public:
|
public:
|
||||||
using Matrix = Eigen::Matrix<unsigned int, Rank, Rank>;
|
using Base = Eigen::Matrix<unsigned int, Rank, Rank>;
|
||||||
|
|
||||||
private:
|
std::string name;
|
||||||
public:
|
|
||||||
std::string _name;
|
|
||||||
Matrix _data;
|
|
||||||
Eigen::SelfAdjointView<Matrix, Eigen::Upper> _mults;
|
|
||||||
|
|
||||||
public:
|
using Base::Base;
|
||||||
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);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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>
|
template<unsigned int GR, unsigned int HR>
|
||||||
Group<GR + HR> product(const Group<GR> &g, const Group<HR> &h) {
|
Group<GR + HR> product(const Group<GR> &g, const Group<HR> &h) {
|
||||||
std::stringstream ss;
|
Group<GR + HR> res;
|
||||||
ss << g.name << "*" << h.name;
|
res.name = g.name + "*" + h.name;
|
||||||
|
|
||||||
Group<GR + HR> res(ss.str());
|
res.fill(2);
|
||||||
|
|
||||||
int off = 0;
|
int off = 0;
|
||||||
for (int i = 0; i < GR; ++i) {
|
res.block(off, off, GR, GR) << g.array() + off;
|
||||||
for (int j = i; j < GR; ++j) {
|
|
||||||
res(i + off, j + off) = g(i, j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
off += GR;
|
off += GR;
|
||||||
|
|
||||||
for (int i = 0; i < HR; ++i) {
|
res.block(off, off, HR, HR) << h.array() + off;
|
||||||
for (int j = i; j < HR; ++j) {
|
|
||||||
res(i + off, j + off) = h(i, j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
off += HR;
|
off += HR;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
@@ -92,19 +70,14 @@ namespace tc {
|
|||||||
|
|
||||||
template<unsigned int GR, unsigned int P>
|
template<unsigned int GR, unsigned int P>
|
||||||
Group<GR * P> power(const Group<GR> &g) {
|
Group<GR * P> power(const Group<GR> &g) {
|
||||||
std::stringstream ss;
|
Group<GR * P> res;
|
||||||
ss << g.name << "^" << P;
|
res.name = g.name + "^" + P;
|
||||||
|
|
||||||
Group<GR * P> res(ss.str());
|
res.fill(2);
|
||||||
|
|
||||||
for (int k = 0; k < P; ++k) {
|
for (int k = 0; k < P; ++k) {
|
||||||
int off = k * GR;
|
int off = k * GR;
|
||||||
|
res.block(off, off, GR, GR) << g.array() + off;
|
||||||
for (int i = 0; i < GR; ++i) {
|
|
||||||
for (int j = i; j < GR; ++j) {
|
|
||||||
res(i + off, j + off) = g(i, j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|||||||
@@ -242,8 +242,11 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace tc {
|
namespace tc {
|
||||||
|
/**
|
||||||
|
* Assumes that g is a coxeter group - that is, self-adjoint and the diagonal is 2.
|
||||||
|
*/
|
||||||
template<unsigned int Rank>
|
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;
|
tc::Cosets<Rank> cosets;
|
||||||
cosets.add_row();
|
cosets.add_row();
|
||||||
|
|
||||||
@@ -256,7 +259,7 @@ namespace tc {
|
|||||||
cosets.put(0, gen, 0);
|
cosets.put(0, gen, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Tables<Rank> tables(g);
|
Tables<Rank> tables(group);
|
||||||
tables.add_row();
|
tables.add_row();
|
||||||
tables.initialize(0, cosets);
|
tables.initialize(0, cosets);
|
||||||
|
|
||||||
|
|||||||
@@ -2,167 +2,150 @@
|
|||||||
|
|
||||||
#include "core.hpp"
|
#include "core.hpp"
|
||||||
|
|
||||||
namespace tc {
|
namespace tc::group {
|
||||||
/**
|
/**
|
||||||
* Construct a group from a (simplified) Schlafli Symbol of the form [a, b, ..., c]
|
* Universal Coxeter Group
|
||||||
* @param mults: The sequence of multiplicites between adjacent generators.
|
|
||||||
*/
|
*/
|
||||||
template<unsigned int Rank>
|
template<unsigned int Rank>
|
||||||
Group <Rank> schlafli(const std::array<unsigned int, Rank - 1> &mults, const std::string &name) {
|
Group <Rank> U() {
|
||||||
Group<Rank> g(name);
|
std::stringstream ss;
|
||||||
|
ss << "U(" << Rank << ")";
|
||||||
|
|
||||||
for (int i = 0; i < Rank - 1; i++) {
|
Group<Rank> res;
|
||||||
g(i, i + 1) = mults[i];
|
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;
|
return g;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a group from a (simplified) Schlafli Symbol of the form [a, b, ..., c]
|
* E groups
|
||||||
* @param mults: The sequence of multiplicites between adjacent generators.
|
|
||||||
*/
|
*/
|
||||||
template<unsigned int Rank>
|
template<unsigned int Rank>
|
||||||
Group <Rank> schlafli(const std::array<unsigned int, Rank - 1> &mults) {
|
Group <Rank> E() {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "[";
|
ss << "E(" << Rank << ")";
|
||||||
if (Rank) {
|
|
||||||
for (size_t i = 0; i < Rank - 2; ++i) {
|
tc::Symbol<Rank - 1> mults;
|
||||||
ss << mults[i] << ",";
|
mults.fill(3);
|
||||||
}
|
mults(Rank - 2) = 2;
|
||||||
ss << mults[Rank - 1];
|
|
||||||
}
|
Group<Rank> g = schlafli<Rank>(mults, ss.str());
|
||||||
ss << "]";
|
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());
|
return schlafli<Rank>(mults, ss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace group {
|
/**
|
||||||
/**
|
* Polygonal
|
||||||
* Simplex
|
*/
|
||||||
*/
|
Group<2> I2(unsigned int n) {
|
||||||
template<unsigned int Rank>
|
std::stringstream ss;
|
||||||
Group <Rank> A() {
|
ss << "I2(" << n << ")";
|
||||||
std::stringstream ss;
|
|
||||||
ss << "A(" << Rank << ")";
|
|
||||||
|
|
||||||
if (Rank == 0)
|
return schlafli<2>(tc::Symbol<1>(n), ss.str());
|
||||||
return Group<Rank>(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
|
* Toroidal. T(n, n)
|
||||||
*/
|
*/
|
||||||
template<unsigned int Rank>
|
Group<4> T(unsigned int n) {
|
||||||
Group <Rank> B() {
|
std::stringstream ss;
|
||||||
std::stringstream ss;
|
ss << "T(" << n << ")";
|
||||||
ss << "B(" << Rank << ")";
|
|
||||||
|
|
||||||
std::array<unsigned int, Rank - 1> mults;
|
return schlafli<4>({n, 2, n}, ss.str());
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user