1
0

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:
David Allemang
2021-11-01 16:58:48 -04:00
parent 6585d79ed9
commit 24d4d1873a
4 changed files with 172 additions and 213 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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());
}
}