mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2024-11-23 21:07:17 +00:00
arb::relative_matrix
This commit is contained in:
parent
6956808dea
commit
59a9605b13
@ -443,6 +443,35 @@ struct hrmap_arbi : hrmap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
transmatrix relative_matrix(heptagon *h2, heptagon *h1, const hyperpoint& hint) override {
|
||||||
|
if(gmatrix0.count(h2->c7) && gmatrix0.count(h1->c7))
|
||||||
|
return inverse(gmatrix0[h1->c7]) * gmatrix0[h2->c7];
|
||||||
|
transmatrix gm = Id, where = Id;
|
||||||
|
while(h1 != h2) {
|
||||||
|
for(int i=0; i<h1->type; i++) {
|
||||||
|
if(h1->move(i) == h2) {
|
||||||
|
return gm * adj(h1, i) * where;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(h1->distance > h2->distance) {
|
||||||
|
for(int i=0; i<h1->type; i++) if(h1->move(i) && h1->move(i)->distance < h1->distance) {
|
||||||
|
gm = gm * adj(h1, i);
|
||||||
|
h1 = h1->move(i);
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for(int i=0; i<h2->type; i++) if(h2->move(i) && h2->move(i)->distance < h2->distance) {
|
||||||
|
where = iadj(h2, 0) * where;
|
||||||
|
h2 = h2->move(i);
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
again: ;
|
||||||
|
}
|
||||||
|
return gm * where;
|
||||||
|
}
|
||||||
|
|
||||||
transmatrix adj(cell *c, int dir) override { return adj(c->master, dir); }
|
transmatrix adj(cell *c, int dir) override { return adj(c->master, dir); }
|
||||||
|
|
||||||
ld spin_angle(cell *c, int d) override { return SPIN_NOT_AVAILABLE; }
|
ld spin_angle(cell *c, int d) override { return SPIN_NOT_AVAILABLE; }
|
||||||
|
2
cell.cpp
2
cell.cpp
@ -983,7 +983,7 @@ EX int celldistance(cell *c1, cell *c2) {
|
|||||||
if(hybri) return hybrid::celldistance(c1, c2);
|
if(hybri) return hybrid::celldistance(c1, c2);
|
||||||
|
|
||||||
#if CAP_FIELD
|
#if CAP_FIELD
|
||||||
if(geometry == gFieldQuotient && !GOLDBERG)
|
if(geometry == gFieldQuotient && !GOLDBERG && WDIM == 2)
|
||||||
return currfp.getdist(fieldpattern::fieldval(c1), fieldpattern::fieldval(c2));
|
return currfp.getdist(fieldpattern::fieldval(c1), fieldpattern::fieldval(c2));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
254
fieldpattern.cpp
254
fieldpattern.cpp
@ -29,7 +29,7 @@ struct fgeomextra {
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool isprime(int n) {
|
EX bool isprime(int n) {
|
||||||
for(int k=2; k<n; k++) if(n%k == 0) return false;
|
for(int k=2; k<n; k++) if(n%k == 0) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -70,6 +70,8 @@ EX int btspin(int id, int d) {
|
|||||||
#if HDR
|
#if HDR
|
||||||
struct fpattern {
|
struct fpattern {
|
||||||
|
|
||||||
|
unsigned force_hash;
|
||||||
|
|
||||||
int Prime, wsquare, Field, dual;
|
int Prime, wsquare, Field, dual;
|
||||||
// we perform our computations in the field Z_Prime[w] where w^2 equals wsquare
|
// we perform our computations in the field Z_Prime[w] where w^2 equals wsquare
|
||||||
// (or simply Z_Prime for wsquare == 0)
|
// (or simply Z_Prime for wsquare == 0)
|
||||||
@ -273,6 +275,7 @@ struct fpattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fpattern(int p) {
|
fpattern(int p) {
|
||||||
|
force_hash = 0;
|
||||||
if(!p) return;
|
if(!p) return;
|
||||||
init(p);
|
init(p);
|
||||||
}
|
}
|
||||||
@ -282,6 +285,17 @@ struct fpattern {
|
|||||||
vector<matrix> generate_isometries();
|
vector<matrix> generate_isometries();
|
||||||
|
|
||||||
bool check_order(matrix M, int req);
|
bool check_order(matrix M, int req);
|
||||||
|
|
||||||
|
unsigned compute_hash();
|
||||||
|
|
||||||
|
// general 4D
|
||||||
|
vector<transmatrix> fullv;
|
||||||
|
|
||||||
|
void add1(const matrix& M);
|
||||||
|
void add1(const matrix& M, const transmatrix& Full);
|
||||||
|
vector<matrix> generate_isometries3();
|
||||||
|
int solve3();
|
||||||
|
void generate_all3();
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -323,6 +337,166 @@ vector<matrix> fpattern::generate_isometries() {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vector<matrix> fpattern::generate_isometries3() {
|
||||||
|
|
||||||
|
matrix T = Id;
|
||||||
|
int low = wsquare ? 1-Prime : 0;
|
||||||
|
vector<matrix> res;
|
||||||
|
|
||||||
|
auto colprod = [&] (int a, int b) {
|
||||||
|
return add(add(mul(T[0][a], T[0][b]), mul(T[1][a], T[1][b])), sub(mul(T[2][a], T[2][b]), mul(T[3][a], T[3][b])));
|
||||||
|
};
|
||||||
|
|
||||||
|
auto rowcol = [&] (int a, int b) {
|
||||||
|
return add(add(mul(T[a][0], T[0][b]), mul(T[a][1], T[1][b])), add(mul(T[a][2], T[2][b]), mul(T[a][3], T[3][b])));
|
||||||
|
};
|
||||||
|
|
||||||
|
for(T[0][0]=low; T[0][0]<Prime; T[0][0]++)
|
||||||
|
for(T[1][0]=low; T[1][0]<Prime; T[1][0]++)
|
||||||
|
for(T[2][0]=low; T[2][0]<Prime; T[2][0]++)
|
||||||
|
for(T[3][0]=low; T[3][0]<Prime; T[3][0]++)
|
||||||
|
if(colprod(0, 0) == 1)
|
||||||
|
for(T[0][1]=low; T[0][1]<Prime; T[0][1]++)
|
||||||
|
for(T[1][1]=low; T[1][1]<Prime; T[1][1]++)
|
||||||
|
for(T[2][1]=low; T[2][1]<Prime; T[2][1]++)
|
||||||
|
for(T[3][1]=low; T[3][1]<Prime; T[3][1]++)
|
||||||
|
if(colprod(1, 1) == 1)
|
||||||
|
if(colprod(1, 0) == 0)
|
||||||
|
for(T[0][2]=low; T[0][2]<Prime; T[0][2]++)
|
||||||
|
for(T[0][3]=low; T[0][3]<Prime; T[0][3]++)
|
||||||
|
if(rowcol(0, 0) == 1)
|
||||||
|
if(rowcol(0, 1) == 0)
|
||||||
|
for(T[1][2]=low; T[1][2]<Prime; T[1][2]++)
|
||||||
|
for(T[1][3]=low; T[1][3]<Prime; T[1][3]++)
|
||||||
|
if(rowcol(1, 0) == 0)
|
||||||
|
if(rowcol(1, 1) == 1)
|
||||||
|
for(T[2][2]=low; T[2][2]<Prime; T[2][2]++)
|
||||||
|
for(T[3][2]=low; T[3][2]<Prime; T[3][2]++)
|
||||||
|
if(colprod(2, 2) == 1)
|
||||||
|
if(colprod(2, 0) == 0)
|
||||||
|
if(colprod(2, 1) == 0)
|
||||||
|
for(T[2][3]=low; T[2][3]<Prime; T[2][3]++)
|
||||||
|
for(T[3][3]=low; T[3][3]<Prime; T[3][3]++)
|
||||||
|
if(rowcol(2, 0) == 0)
|
||||||
|
if(rowcol(2, 1) == 0)
|
||||||
|
if(rowcol(2, 2) == 1)
|
||||||
|
// if(colprod(3, 3) == 1)
|
||||||
|
if(add(colprod(3, 3), 1) == 0)
|
||||||
|
if(colprod(3, 0) == 0)
|
||||||
|
if(colprod(3, 1) == 0)
|
||||||
|
if(colprod(3, 2) == 0)
|
||||||
|
if(rowcol(3, 3) == 1)
|
||||||
|
if(rowcol(3, 0) == 0)
|
||||||
|
if(rowcol(3, 1) == 0)
|
||||||
|
if(rowcol(3, 2) == 0)
|
||||||
|
res.push_back(T);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fpattern::add1(const matrix& M) {
|
||||||
|
if(!matcode.count(M)) {
|
||||||
|
int i = matrices.size();
|
||||||
|
matcode[M] = i, matrices.push_back(M);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fpattern::add1(const matrix& M, const transmatrix& Full) {
|
||||||
|
if(!matcode.count(M)) {
|
||||||
|
int i = matrices.size();
|
||||||
|
matcode[M] = i, matrices.push_back(M), fullv.push_back(Full);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
map<unsigned,int> hash_found;
|
||||||
|
|
||||||
|
unsigned fpattern::compute_hash() {
|
||||||
|
unsigned hashv = 0;
|
||||||
|
int iR = matcode[R];
|
||||||
|
int iP = matcode[P];
|
||||||
|
int iX = matcode[X];
|
||||||
|
for(int i=0; i<isize(matrices); i++) {
|
||||||
|
hashv = 3 * hashv + gmul(i, iP) + 7 * gmul(i, iR);
|
||||||
|
if(MWDIM == 4) hashv += 11 * gmul(i, iX);
|
||||||
|
}
|
||||||
|
return hashv;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fpattern::generate_all3() {
|
||||||
|
matrices.clear();
|
||||||
|
matcode.clear();
|
||||||
|
add1(Id);
|
||||||
|
fullv = {hr::Id};
|
||||||
|
for(int i=0; i<isize(matrices); i++) {
|
||||||
|
add1(mmul(matrices[i], R), fullv[i] * reg3::full_R);
|
||||||
|
add1(mmul(matrices[i], X), fullv[i] * reg3::full_X);
|
||||||
|
}
|
||||||
|
local_group = isize(matrices);
|
||||||
|
for(int i=0; i<(int)matrices.size(); i++) {
|
||||||
|
matrix E = mmul(matrices[i], P);
|
||||||
|
if(!matcode.count(E))
|
||||||
|
for(int j=0; j<local_group; j++) add1(mmul(E, matrices[j]));
|
||||||
|
}
|
||||||
|
unsigned hashv = compute_hash();
|
||||||
|
DEBB(DF_FIELD, ("all = ", isize(matrices), "/", local_group, " = ", isize(matrices) / local_group, " hash = ", hashv, " count = ", ++hash_found[hashv]));
|
||||||
|
}
|
||||||
|
|
||||||
|
int fpattern::solve3() {
|
||||||
|
if(!wsquare) return 0;
|
||||||
|
reg3::construct_relations();
|
||||||
|
|
||||||
|
DEBB(DF_FIELD, ("generating isometries for ", Field));
|
||||||
|
|
||||||
|
auto iso3 = generate_isometries();
|
||||||
|
auto iso4 = generate_isometries3();
|
||||||
|
|
||||||
|
int cmb = 0;
|
||||||
|
|
||||||
|
int N = isize(reg3::rels);
|
||||||
|
|
||||||
|
vector<int> fails(N);
|
||||||
|
|
||||||
|
vector<matrix> possible_P, possible_X, possible_R;
|
||||||
|
|
||||||
|
for(auto& M: iso3) {
|
||||||
|
if(check_order(M, 2))
|
||||||
|
possible_X.push_back(M);
|
||||||
|
if(check_order(M, reg3::r_order))
|
||||||
|
possible_R.push_back(M);
|
||||||
|
}
|
||||||
|
for(auto& M: iso4)
|
||||||
|
if(check_order(M, 2))
|
||||||
|
possible_P.push_back(M);
|
||||||
|
|
||||||
|
DEBB(DF_FIELD, ("field = ", Field, " #P = ", isize(possible_P), " #X = ", isize(possible_X), " #R = ", isize(possible_R), " r_order = ", reg3::r_order, " xp_order = ", reg3::xp_order));
|
||||||
|
|
||||||
|
for(auto& xX: possible_X)
|
||||||
|
for(auto& xP: possible_P) if(check_order(mmul(xP, xX), reg3::xp_order))
|
||||||
|
for(auto& xR: possible_R) if(check_order(mmul(xR, xX), reg3::rx_order)) { // if(xR[0][0] == 1 && xR[0][1] == 0) {
|
||||||
|
auto by = [&] (char ch) -> matrix& { return ch == 'X' ? xX : ch == 'R' ? xR : xP; };
|
||||||
|
for(int i=0; i<N; i++) {
|
||||||
|
matrix ml = Id;
|
||||||
|
for(char c: reg3::rels[i].first) { ml = mmul(ml, by(c)); if(ml == Id) { fails[i]++; goto bad; }}
|
||||||
|
matrix mr = Id;
|
||||||
|
for(char c: reg3::rels[i].second) { mr = mmul(mr, by(c)); if(mr == Id) { fails[i]++; goto bad; }}
|
||||||
|
if(ml != mr) { fails[i]++; goto bad;}
|
||||||
|
}
|
||||||
|
P = xP; R = xR; X = xX;
|
||||||
|
generate_all3();
|
||||||
|
if(force_hash && compute_hash() != force_hash) continue;
|
||||||
|
cmb++;
|
||||||
|
goto ok;
|
||||||
|
bad: ;
|
||||||
|
}
|
||||||
|
|
||||||
|
ok:
|
||||||
|
|
||||||
|
DEBB(DF_FIELD, ("cmb = ", cmb, " for field = ", Field));
|
||||||
|
for(int i=0; i<N; i++) if(fails[i]) DEBB(DF_FIELD, (reg3::rels[i], " fails = ", fails[i]));
|
||||||
|
|
||||||
|
return cmb;
|
||||||
|
}
|
||||||
|
|
||||||
int fpattern::solve() {
|
int fpattern::solve() {
|
||||||
|
|
||||||
for(int a=0; a<MWDIM; a++) for(int b=0; b<MWDIM; b++) Id[a][b] = a==b?1:0;
|
for(int a=0; a<MWDIM; a++) for(int b=0; b<MWDIM; b++) Id[a][b] = a==b?1:0;
|
||||||
@ -347,6 +521,14 @@ int fpattern::solve() {
|
|||||||
}
|
}
|
||||||
} else wsquare = 0;
|
} else wsquare = 0;
|
||||||
|
|
||||||
|
if(WDIM == 3) {
|
||||||
|
if(dual == 0) {
|
||||||
|
int s = solve3();
|
||||||
|
if(s) return 0;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if(dual == 2) {
|
if(dual == 2) {
|
||||||
if(Field <= 10) {
|
if(Field <= 10) {
|
||||||
vector<matrix> all_isometries = generate_isometries();
|
vector<matrix> all_isometries = generate_isometries();
|
||||||
@ -419,6 +601,8 @@ int fpattern::order(const matrix& M) {
|
|||||||
|
|
||||||
void fpattern::build() {
|
void fpattern::build() {
|
||||||
|
|
||||||
|
if(WDIM == 3) return;
|
||||||
|
|
||||||
for(int i=0; i<isize(qpaths); i++) {
|
for(int i=0; i<isize(qpaths); i++) {
|
||||||
matrix M = strtomatrix(qpaths[i]);
|
matrix M = strtomatrix(qpaths[i]);
|
||||||
qcoords.push_back(M);
|
qcoords.push_back(M);
|
||||||
@ -789,6 +973,7 @@ EX void info() {
|
|||||||
#ifndef EASY
|
#ifndef EASY
|
||||||
neasy = 0;
|
neasy = 0;
|
||||||
#endif
|
#endif
|
||||||
|
if(WDIM == 3) continue;
|
||||||
fp.build();
|
fp.build();
|
||||||
#ifndef EASY
|
#ifndef EASY
|
||||||
printf("Not easy: %d\n", neasy);
|
printf("Not easy: %d\n", neasy);
|
||||||
@ -813,11 +998,60 @@ EX bool quotient_field_changed;
|
|||||||
EX struct fpattern& getcurrfp() {
|
EX struct fpattern& getcurrfp() {
|
||||||
if(geometry == gFieldQuotient && quotient_field_changed)
|
if(geometry == gFieldQuotient && quotient_field_changed)
|
||||||
return current_quotient_field;
|
return current_quotient_field;
|
||||||
if(WDIM == 3) {
|
if(geometry == gSpace535) {
|
||||||
dynamicval<eGeometry> g(geometry, gSpace435);
|
// 120 cells, hash = 9EF7A9C4
|
||||||
static fpattern fp(5);
|
static fpattern fp(5);
|
||||||
return fp;
|
return fp;
|
||||||
}
|
}
|
||||||
|
if(geometry == gSpace534) {
|
||||||
|
// 260 cells, hash = 72414D0C (not 0C62E214)
|
||||||
|
static fpattern fp(0);
|
||||||
|
if(fp.Prime) return fp;
|
||||||
|
fp.Prime = 5; fp.force_hash = 0x72414D0C; fp.solve();
|
||||||
|
return fp;
|
||||||
|
}
|
||||||
|
if(geometry == gSpace435) {
|
||||||
|
// 650 cells, hash = EB201050
|
||||||
|
static fpattern fp(0);
|
||||||
|
if(fp.Prime) return fp;
|
||||||
|
fp.Prime = 5; fp.force_hash = 0x72414D0C; fp.solve();
|
||||||
|
return fp;
|
||||||
|
}
|
||||||
|
if(geometry == gSpace336) {
|
||||||
|
// 672 cells in E3F6B7BC
|
||||||
|
// 672 cells in 885F1184
|
||||||
|
// 9408 cells in C4089F34
|
||||||
|
static fpattern fp(0);
|
||||||
|
if(fp.Prime) return fp;
|
||||||
|
fp.Prime = 7; fp.force_hash = 0xE3F6B7BCu; fp.solve();
|
||||||
|
return fp;
|
||||||
|
}
|
||||||
|
if(geometry == gSpace344) {
|
||||||
|
// 600 cells in 558C8ED0
|
||||||
|
// 2400 cells in AF042EA8
|
||||||
|
// 2600 cells in D26948E0
|
||||||
|
// 2600 cells in EC29DCEC
|
||||||
|
static fpattern fp(0);
|
||||||
|
if(fp.Prime) return fp;
|
||||||
|
fp.Prime = 5; fp.force_hash = 0x558C8ED0u; fp.solve();
|
||||||
|
return fp;
|
||||||
|
// 4900 cells in CDCC7860 (7)
|
||||||
|
}
|
||||||
|
if(geometry == gSpace536) {
|
||||||
|
static fpattern fp(0);
|
||||||
|
if(fp.Prime) return fp;
|
||||||
|
// 130 cells in 3BA5C5A4
|
||||||
|
// 260 cells in 9FDE7B38
|
||||||
|
fp.Prime = 7; fp.force_hash = 0x9FDE7B38u; fp.solve();
|
||||||
|
return fp;
|
||||||
|
}
|
||||||
|
if(WDIM == 3) {
|
||||||
|
static fpattern fp(0);
|
||||||
|
if(fp.Prime) return fp;
|
||||||
|
for(int p=2; p<8; p++) { fp.Prime = p; if(!fp.solve()) break; }
|
||||||
|
DEBB(DF_FIELD, ("set prime = ", fp.Prime));
|
||||||
|
return fp;
|
||||||
|
}
|
||||||
if(S7 == 8 && S3 == 3) {
|
if(S7 == 8 && S3 == 3) {
|
||||||
static fpattern fp(17);
|
static fpattern fp(17);
|
||||||
return fp;
|
return fp;
|
||||||
@ -900,6 +1134,20 @@ EX void enableFieldChange() {
|
|||||||
fieldpattern::current_quotient_field.init(gxcur.primes[gxcur.current_prime_id].p);
|
fieldpattern::current_quotient_field.init(gxcur.primes[gxcur.current_prime_id].p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EX void field_from_current() {
|
||||||
|
auto& go = ginf[geometry];
|
||||||
|
dynamicval<eGeometry> g(geometry, gFieldQuotient);
|
||||||
|
auto& gg = ginf[geometry];
|
||||||
|
gg.sides = go.sides;
|
||||||
|
gg.vertex = go.vertex;
|
||||||
|
gg.distlimit = go.distlimit;
|
||||||
|
gg.tiling_name = go.tiling_name;
|
||||||
|
gg.flags = go.flags | qANYQ | qFIELD | qBOUNDED;
|
||||||
|
gg.g = go.g;
|
||||||
|
gg.default_variation = go.default_variation;
|
||||||
|
fieldpattern::quotient_field_changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
EX }
|
EX }
|
||||||
|
|
||||||
#define currfp fieldpattern::getcurrfp()
|
#define currfp fieldpattern::getcurrfp()
|
||||||
|
24
geom-exp.cpp
24
geom-exp.cpp
@ -316,6 +316,8 @@ void set_or_configure_geometry(eGeometry g) {
|
|||||||
bool same_tiling(eGeometry g2) {
|
bool same_tiling(eGeometry g2) {
|
||||||
if(g2 == gCrystal)
|
if(g2 == gCrystal)
|
||||||
return S3 == 4;
|
return S3 == 4;
|
||||||
|
if(g2 == gFieldQuotient && hyperbolic && standard_tiling())
|
||||||
|
return true;
|
||||||
if(g2 == gFieldQuotient && geometry != gFieldQuotient) {
|
if(g2 == gFieldQuotient && geometry != gFieldQuotient) {
|
||||||
int ce = 0;
|
int ce = 0;
|
||||||
for(auto& ge: fieldpattern::fgeomextras) {
|
for(auto& ge: fieldpattern::fgeomextras) {
|
||||||
@ -456,7 +458,15 @@ EX void select_quotient_screen() {
|
|||||||
"no quotient",
|
"no quotient",
|
||||||
g == geometry, key++);
|
g == geometry, key++);
|
||||||
dialog::add_action([g] {
|
dialog::add_action([g] {
|
||||||
if(g == gFieldQuotient)
|
if(g == gFieldQuotient && WDIM == 3) {
|
||||||
|
stop_game();
|
||||||
|
fieldpattern::field_from_current();
|
||||||
|
set_geometry(gFieldQuotient);
|
||||||
|
for(int p=2;; p++) { currfp.Prime = p; currfp.force_hash = 0; if(!currfp.solve()) break; }
|
||||||
|
println(hlog, "set prime = ", currfp.Prime);
|
||||||
|
start_game();
|
||||||
|
}
|
||||||
|
else if(g == gFieldQuotient)
|
||||||
pushScreen(showQuotientConfig);
|
pushScreen(showQuotientConfig);
|
||||||
else if(g == gCrystal)
|
else if(g == gCrystal)
|
||||||
pushScreen(crystal::show);
|
pushScreen(crystal::show);
|
||||||
@ -900,6 +910,14 @@ int read_geom_args() {
|
|||||||
enableFieldChange();
|
enableFieldChange();
|
||||||
set_geometry(gFieldQuotient);
|
set_geometry(gFieldQuotient);
|
||||||
}
|
}
|
||||||
|
else if(argis("-to-fq")) {
|
||||||
|
shift(); unsigned hash = arghex();
|
||||||
|
stop_game_and_switch_mode(rg::nothing);
|
||||||
|
fieldpattern::field_from_current();
|
||||||
|
set_geometry(gFieldQuotient);
|
||||||
|
for(int p=2;; p++) { currfp.Prime = p; currfp.force_hash = hash; if(!currfp.solve()) break; }
|
||||||
|
println(hlog, "set prime = ", currfp.Prime);
|
||||||
|
}
|
||||||
else if(argis("-cs")) {
|
else if(argis("-cs")) {
|
||||||
shift(); cheat();
|
shift(); cheat();
|
||||||
fieldpattern::matrix M = currfp.strtomatrix(args());
|
fieldpattern::matrix M = currfp.strtomatrix(args());
|
||||||
@ -940,6 +958,10 @@ int read_geom_args() {
|
|||||||
fieldpattern::info();
|
fieldpattern::info();
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
else if(argis("-fi-geo")) {
|
||||||
|
fieldpattern::info();
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
else if(argis("-qs")) {
|
else if(argis("-qs")) {
|
||||||
cheat();
|
cheat();
|
||||||
shift(); currfp.qpaths.push_back(args());
|
shift(); currfp.qpaths.push_back(args());
|
||||||
|
310
reg3.cpp
310
reg3.cpp
@ -32,7 +32,7 @@ EX namespace reg3 {
|
|||||||
EX int face;
|
EX int face;
|
||||||
|
|
||||||
EX vector<hyperpoint> cellshape;
|
EX vector<hyperpoint> cellshape;
|
||||||
vector<hyperpoint> vertices_only;
|
EX vector<hyperpoint> vertices_only;
|
||||||
|
|
||||||
EX transmatrix spins[12], adjmoves[12];
|
EX transmatrix spins[12], adjmoves[12];
|
||||||
|
|
||||||
@ -237,6 +237,8 @@ EX namespace reg3 {
|
|||||||
|
|
||||||
void initialize(int cell_count);
|
void initialize(int cell_count);
|
||||||
vector<cell*>& allcells() override { return acells; }
|
vector<cell*>& allcells() override { return acells; }
|
||||||
|
|
||||||
|
vector<hyperpoint> get_vertices(cell* c) override { return vertices_only; }
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -325,195 +327,36 @@ EX namespace reg3 {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hrmap_field3 : hrmap_quotient3 {
|
struct hrmap_field3 : reg3::hrmap_quotient3 {
|
||||||
|
|
||||||
int mgmul(std::initializer_list<int> v) {
|
|
||||||
int a = 0;
|
|
||||||
for(int b: v) a = a ? currfp_gmul(a, b) : b;
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
vector<transmatrix> fullmatrices;
|
|
||||||
|
|
||||||
int P, R, X;
|
|
||||||
transmatrix full_P, full_R, full_X;
|
|
||||||
|
|
||||||
vector<int> field_adjmoves;
|
|
||||||
vector<int> cyclers;
|
|
||||||
int perm_group;
|
|
||||||
|
|
||||||
vector<int> cell_to_code;
|
|
||||||
vector<int> code_to_cell;
|
|
||||||
|
|
||||||
void seek(set<int>& seen_matrices, set<int>& seen_codes, const transmatrix& at, int ccode, const hyperpoint checker) {
|
|
||||||
if(hdist0(tC0(at)) > 4) return;
|
|
||||||
int b = bucketer(tC0(at));
|
|
||||||
if(seen_matrices.count(b)) return;
|
|
||||||
seen_matrices.insert(b);
|
|
||||||
for(int a=0; a<perm_group; a++) {
|
|
||||||
transmatrix T = at * fullmatrices[a];
|
|
||||||
if(hdist(T * checker, checker) < 1e-2) {
|
|
||||||
int co = mgmul({ccode, a});
|
|
||||||
seen_codes.insert(co);
|
|
||||||
fullmatrices[co] = T;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(int a=0; a<perm_group; a++) seek(seen_matrices, seen_codes, at * fullmatrices[a] * full_P, mgmul({ccode, a, P}), checker);
|
|
||||||
}
|
|
||||||
|
|
||||||
hrmap_field3() {
|
hrmap_field3() {
|
||||||
eGeometry g = geometry;
|
|
||||||
geometry = gSpace435;
|
|
||||||
reg3::generate();
|
|
||||||
R = currfp_get_R();
|
|
||||||
P = currfp_get_P();
|
|
||||||
X = currfp_get_X();
|
|
||||||
full_P = reg3::adjmoves[0] * cspin(0, 2, M_PI) * cspin(0, 1, M_PI);
|
|
||||||
full_R = spin(-2 * M_PI / 4);
|
|
||||||
full_X = cspin(1, 2, M_PI / 2);
|
|
||||||
|
|
||||||
DEBB(DF_FIELD, ("full_P = ", full_P, " / ", R));
|
auto& f = currfp;
|
||||||
DEBB(DF_FIELD, ("full_R = ", full_R, " / ", P));
|
auto lgr = f.local_group;
|
||||||
DEBB(DF_FIELD, ("full_X = ", full_X, " / ", X));
|
|
||||||
|
|
||||||
int N = currfp_n();
|
int N = isize(f.matrices) / lgr;
|
||||||
|
initialize(N);
|
||||||
|
|
||||||
perm_group = 24;
|
vector<int> moveid(S7), movedir(lgr);
|
||||||
fullmatrices.resize(N);
|
for(int s=0; s<lgr; s++)
|
||||||
fullmatrices[0] = Id;
|
for(int i=0; i<S7; i++) if(eqmatrix(f.fullv[s] * reg3::adjmoves[0], reg3::adjmoves[i]))
|
||||||
vector<bool> known(perm_group, false);
|
moveid[i] = s;
|
||||||
known[0] = true;
|
|
||||||
for(int a=0; a<perm_group; a++)
|
|
||||||
for(int i=0; i<perm_group; i++) if(known[i]) {
|
|
||||||
int iR = currfp_gmul(i, R);
|
|
||||||
fullmatrices[iR] = fullmatrices[i] * full_R;
|
|
||||||
known[iR] = true;
|
|
||||||
int iX = currfp_gmul(i, X);
|
|
||||||
fullmatrices[iX] = fullmatrices[i] * full_X;
|
|
||||||
known[iX] = true;
|
|
||||||
}
|
|
||||||
for(int i=0; i<perm_group; i++) if(known[i]) {
|
|
||||||
DEBB(DF_FIELD, (i, ". ", fullmatrices[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
// find cav such that:
|
for(int s=0; s<lgr; s++)
|
||||||
// cav * Id * C0 = corner0
|
for(int i=0; i<S7; i++) if(hdist(tC0(inverse(f.fullv[s]) * reg3::adjmoves[0]), tC0(reg3::adjmoves[i])) < 1e-4)
|
||||||
// cav * adjmoves[0] * C0 = corner1
|
movedir[s] = i;
|
||||||
// cav * adjmoves[1] * C0 = corner3
|
|
||||||
// cav * adjmoves[2] * C0 = cornerx
|
|
||||||
|
|
||||||
hyperpoint corner0 = reg3::cellshape[0];
|
for(int a=0; a<N; a++) {
|
||||||
hyperpoint corner1 = reg3::cellshape[1];
|
tmatrices[a].resize(S7);
|
||||||
hyperpoint corner3 = reg3::cellshape[3];
|
for(int b=0; b<S7; b++) {
|
||||||
hyperpoint cornerx;
|
int k = lgr*a;
|
||||||
|
k = f.gmul(f.gmul(k, moveid[b]), lgr);
|
||||||
for(hyperpoint h: reg3::cellshape) DEBB(DF_FIELD, ("some corner ", h));
|
for(int l=0; l<lgr; l++) if(f.gmul(k, l) % lgr == 0) {
|
||||||
|
tmatrices[a][b] = reg3::adjmoves[b] * f.fullv[l];
|
||||||
for(hyperpoint h: reg3::cellshape)
|
allh[a]->c.connect(b, allh[k/lgr], movedir[l], false);
|
||||||
if(hdist(h, corner1) > .1 && hdist(h, corner3) > .1 && abs(hdist(h, corner0)-hdist(corner0, corner1)) < .1)
|
|
||||||
cornerx = h;
|
|
||||||
DEBB(DF_FIELD, ("corner0 = ", corner0));
|
|
||||||
DEBB(DF_FIELD, ("corner1 = ", corner1));
|
|
||||||
DEBB(DF_FIELD, ("corner3 = ", corner3));
|
|
||||||
DEBB(DF_FIELD, ("cornerx = ", cornerx));
|
|
||||||
|
|
||||||
transmatrix adj = Id, iadj = Id;
|
|
||||||
|
|
||||||
geometry = g;
|
|
||||||
reg3::generate();
|
|
||||||
|
|
||||||
cyclers.clear();
|
|
||||||
DEBB(DF_FIELD, ("S7 = ", S7));
|
|
||||||
if(S7 == 12) {
|
|
||||||
|
|
||||||
transmatrix resmatrix;
|
|
||||||
set_column(resmatrix, 0, corner0);
|
|
||||||
set_column(resmatrix, 1, corner1);
|
|
||||||
set_column(resmatrix, 2, corner3);
|
|
||||||
set_column(resmatrix, 3, cornerx);
|
|
||||||
|
|
||||||
transmatrix transformer;
|
|
||||||
set_column(transformer, 0, C0);
|
|
||||||
set_column(transformer, 1, tC0(reg3::adjmoves[0]));
|
|
||||||
set_column(transformer, 2, tC0(reg3::adjmoves[1]));
|
|
||||||
set_column(transformer, 3, tC0(reg3::adjmoves[2]));
|
|
||||||
|
|
||||||
transmatrix cav = resmatrix * inverse(transformer);
|
|
||||||
DEBB(DF_FIELD, ("cav = ", cav));
|
|
||||||
DEBB(DF_FIELD, ("cav * C0 = ", cav * C0));
|
|
||||||
|
|
||||||
set<int> seen_matrices;
|
|
||||||
set<int> seen_codes;
|
|
||||||
seek(seen_matrices, seen_codes, Id, 0, corner0);
|
|
||||||
|
|
||||||
for(int x: seen_codes) cyclers.push_back(x);
|
|
||||||
perm_group = isize(cyclers);
|
|
||||||
adj = cav;
|
|
||||||
iadj = inverse(cav);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for(int i=0; i<perm_group; i++) cyclers.push_back(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
field_adjmoves.resize(S7);
|
|
||||||
for(int i=0; i<S7; i++) field_adjmoves[i] = -1;
|
|
||||||
|
|
||||||
for(int i=0; i<S7; i++)
|
|
||||||
for(int a: cyclers)
|
|
||||||
for(int b: cyclers) {
|
|
||||||
transmatrix T = iadj * fullmatrices[a] * full_P * fullmatrices[b] * adj;
|
|
||||||
if(eqmatrix(T, reg3::adjmoves[i])) {
|
|
||||||
int code = mgmul({a,P,b});
|
|
||||||
field_adjmoves[i] = code;
|
|
||||||
DEBB(DF_FIELD, (i, " = ", make_tuple(a,P,b), " = ", code, " T = ", T));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBB(DF_FIELD, ("field_adjmoves = ", field_adjmoves));
|
|
||||||
|
|
||||||
DEBB(DF_FIELD, ("finding code_to_cell/cell_to_code..."));
|
|
||||||
|
|
||||||
cell_to_code.clear();
|
|
||||||
code_to_cell.resize(N);
|
|
||||||
for(int i=0; i<N; i++) code_to_cell[i] = -1;
|
|
||||||
for(int i=0; i<N; i++) if(code_to_cell[i] == -1) {
|
|
||||||
for(int j: cyclers) code_to_cell[currfp_gmul(i, j)] = isize(cell_to_code);
|
|
||||||
cell_to_code.push_back(i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBB(DF_FIELD, ("building allh..."));
|
|
||||||
int cells = N / perm_group;
|
|
||||||
initialize(cells);
|
|
||||||
|
|
||||||
DEBB(DF_FIELD, ("finding tmatrices..."));
|
|
||||||
for(int i=0; i<cells; i++) {
|
|
||||||
for(int d=0; d<S7; d++) {
|
|
||||||
int found = 0;
|
|
||||||
int tmul = currfp_gmul(cell_to_code[i], field_adjmoves[d]);
|
|
||||||
for(int s: cyclers) {
|
|
||||||
int tmul2 = currfp_gmul(tmul, s);
|
|
||||||
if(cell_to_code[code_to_cell[tmul2]] == tmul2) {
|
|
||||||
allh[i]->move(d) = allh[code_to_cell[tmul2]];
|
|
||||||
allh[i]->c7->move(d) = allh[i]->move(d)->c7;
|
|
||||||
tmatrices[i].push_back(reg3::adjmoves[d] * iadj * fullmatrices[s] * adj);
|
|
||||||
found++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(found != 1) DEBB(DF_FIELD, ("bad found: ", i, "/", d, "/", found));
|
|
||||||
// println(hlog, "tmatrix(",i,",",d,") = ", tmatrices[i][d]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBB(DF_FIELD, ("setting spin..."));
|
|
||||||
for(int i=0; i<cells; i++)
|
|
||||||
for(int d=0; d<S7; d++)
|
|
||||||
for(int e=0; e<S7; e++)
|
|
||||||
if(allh[i]->move(d)->move(e) == allh[i]) {
|
|
||||||
allh[i]->c.setspin(d, e, false);
|
|
||||||
allh[i]->c7->c.setspin(d, e, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBB(DF_FIELD, ("creating patterns..."));
|
|
||||||
create_patterns();
|
create_patterns();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -529,8 +372,9 @@ EX namespace reg3 {
|
|||||||
|
|
||||||
|
|
||||||
void create_patterns() {
|
void create_patterns() {
|
||||||
|
auto& f = currfp;
|
||||||
// change the geometry to make sure that the correct celldistance is used
|
// change the geometry to make sure that the correct celldistance is used
|
||||||
dynamicval<eGeometry> g(geometry, S7 == 12 ? gField534 : gField435);
|
dynamicval<eGeometry> g(geometry, gFieldQuotient);
|
||||||
// also, strafe needs currentmap
|
// also, strafe needs currentmap
|
||||||
dynamicval<hrmap*> c(currentmap, this);
|
dynamicval<hrmap*> c(currentmap, this);
|
||||||
|
|
||||||
@ -572,7 +416,7 @@ EX namespace reg3 {
|
|||||||
for(int i=0; i<currfp_n(); i++) {
|
for(int i=0; i<currfp_n(); i++) {
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
for(auto o: plane_indices) {
|
for(auto o: plane_indices) {
|
||||||
int j = code_to_cell[currfp_gmul(i, cell_to_code[o])];
|
int j = currfp_gmul(i, o * f.local_group) / f.local_group;
|
||||||
if(plane_indices.count(j)) ok = false;
|
if(plane_indices.count(j)) ok = false;
|
||||||
forCellEx(c1, allcells()[j]) if(plane_indices.count(c1->master->fieldval)) ok = false;
|
forCellEx(c1, allcells()[j]) if(plane_indices.count(c1->master->fieldval)) ok = false;
|
||||||
}
|
}
|
||||||
@ -595,17 +439,13 @@ EX namespace reg3 {
|
|||||||
int u = 0;
|
int u = 0;
|
||||||
for(int a=0; a<5; a++) {
|
for(int a=0; a<5; a++) {
|
||||||
for(int o: plane_indices) {
|
for(int o: plane_indices) {
|
||||||
int j = code_to_cell[currfp_gmul(u, cell_to_code[o])];
|
int j = currfp_gmul(u, o * f.local_group) / f.local_group;
|
||||||
allcells()[j]->master->zebraval |= 2;
|
allcells()[j]->master->zebraval |= 2;
|
||||||
}
|
}
|
||||||
u = currfp_gmul(u, gpow);
|
u = currfp_gmul(u, gpow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<hyperpoint> get_vertices(cell* c) override {
|
|
||||||
return vertices_only;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** homology cover of the Seifert-Weber space */
|
/** homology cover of the Seifert-Weber space */
|
||||||
@ -770,7 +610,7 @@ EX namespace reg3 {
|
|||||||
quotient_map = new seifert_weber::hrmap_seifert_cover;
|
quotient_map = new seifert_weber::hrmap_seifert_cover;
|
||||||
h.zebraval = quotient_map->allh[0]->zebraval;
|
h.zebraval = quotient_map->allh[0]->zebraval;
|
||||||
}
|
}
|
||||||
else if(hyperbolic && !(cgflags & qIDEAL)) {
|
else if(hyperbolic) {
|
||||||
quotient_map = new hrmap_field3;
|
quotient_map = new hrmap_field3;
|
||||||
h.zebraval = quotient_map->allh[0]->zebraval;
|
h.zebraval = quotient_map->allh[0]->zebraval;
|
||||||
}
|
}
|
||||||
@ -1085,6 +925,7 @@ EX bool pseudohept(cell *c) {
|
|||||||
return hr::celldistance(c, currentmap->gamestart()) & 1;
|
return hr::celldistance(c, currentmap->gamestart()) & 1;
|
||||||
if(geometry == gCrystal344 || geometry == gCrystal534 || geometry == gSeifertCover)
|
if(geometry == gCrystal344 || geometry == gCrystal534 || geometry == gSeifertCover)
|
||||||
return false;
|
return false;
|
||||||
|
if(quotient) return false; /* added */
|
||||||
if(hyperbolic) {
|
if(hyperbolic) {
|
||||||
heptagon *h = m->reg_gmatrix[c->master].first;
|
heptagon *h = m->reg_gmatrix[c->master].first;
|
||||||
return (h->zebraval == 1) && (h->distance & 1);
|
return (h->zebraval == 1) && (h->distance & 1);
|
||||||
@ -1225,6 +1066,99 @@ EX cellwalker strafe(cellwalker cw, int j) {
|
|||||||
println(hlog, "incorrect strafe");
|
println(hlog, "incorrect strafe");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EX vector<pair<string, string> > rels;
|
||||||
|
EX int xp_order, r_order, rx_order;
|
||||||
|
|
||||||
|
EX transmatrix full_X, full_R, full_P;
|
||||||
|
geometry_information *for_cgi;
|
||||||
|
|
||||||
|
EX int matrix_order(const transmatrix A) {
|
||||||
|
transmatrix T = A;
|
||||||
|
int res = 1;
|
||||||
|
while(!eqmatrix(T, Id)) {
|
||||||
|
res++; T = T * A;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
EX void construct_relations() {
|
||||||
|
if(for_cgi == &cgi) return;
|
||||||
|
for_cgi = &cgi;
|
||||||
|
rels.clear();
|
||||||
|
|
||||||
|
reg3::generate();
|
||||||
|
reg3::generate_cellrotations();
|
||||||
|
vector<transmatrix> all;
|
||||||
|
|
||||||
|
vector<string> formulas;
|
||||||
|
|
||||||
|
formulas.push_back("");
|
||||||
|
|
||||||
|
all.push_back(Id);
|
||||||
|
hyperpoint v = reg3::cellshape[0];
|
||||||
|
auto add = [&] (transmatrix T) {
|
||||||
|
for(int i=0; i<isize(all); i++) if(eqmatrix(all[i], T)) return i;
|
||||||
|
int S = isize(all);
|
||||||
|
all.push_back(T);
|
||||||
|
return S;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto cons = [&] (int i0, int i1, int i2) {
|
||||||
|
using reg3::adjmoves;
|
||||||
|
transmatrix T = build_matrix(adjmoves[ 0]*C0, adjmoves[ 1]*C0, adjmoves[ 2]*C0, C0);
|
||||||
|
transmatrix U = build_matrix(adjmoves[i0]*C0, adjmoves[i1]*C0, adjmoves[i2]*C0, C0);
|
||||||
|
return U * inverse(T);
|
||||||
|
};
|
||||||
|
|
||||||
|
full_P = reg3::adjmoves[0];
|
||||||
|
full_R = S7 == 8 ? cons(1, 7, 0) : cons(1, 2, 0);
|
||||||
|
full_X = S7 == 8 ? cons(1, 0, 6) : S7 == 6 ? cons(1, 0, 5) : cons(1, 0, reg3::face);
|
||||||
|
|
||||||
|
println(hlog, reg3::cellshape);
|
||||||
|
|
||||||
|
println(hlog, "cellshape = ", isize(reg3::cellshape));
|
||||||
|
bool ok = true;
|
||||||
|
int last_i = -1;
|
||||||
|
for(hyperpoint h: reg3::cellshape) {
|
||||||
|
int i = 0, j = 0;
|
||||||
|
for(hyperpoint u: reg3::cellshape) if(hdist(h, full_X*u) < 1e-4) i++;
|
||||||
|
for(hyperpoint u: reg3::cellshape) if(hdist(h, full_R*u) < 1e-4) j++;
|
||||||
|
if(last_i == -1) last_i = i;
|
||||||
|
if(i != j || i != last_i) ok = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!ok) { println(hlog, "something wrong"); exit(1); }
|
||||||
|
|
||||||
|
add(Id);
|
||||||
|
|
||||||
|
auto work = [&] (transmatrix T, int p, char c) {
|
||||||
|
if(hdist0(tC0(T)) > 5) return;
|
||||||
|
for(hyperpoint h: reg3::cellshape) if(hdist(T * h, v) < 1e-4) goto ok;
|
||||||
|
return;
|
||||||
|
ok:
|
||||||
|
int id = add(T);
|
||||||
|
// println(hlog, p, " x ", (s0+c), " = ", id);
|
||||||
|
|
||||||
|
if(id >= isize(formulas)) formulas.push_back(formulas[p] + c);
|
||||||
|
else if(id == 0) println(hlog, "reached identity: ", formulas[p]+c);
|
||||||
|
else if(formulas[p][0] != formulas[id][0])
|
||||||
|
rels.emplace_back(formulas[p] + c, formulas[id]);
|
||||||
|
};
|
||||||
|
|
||||||
|
for(int i=0; i<isize(all); i++) {
|
||||||
|
transmatrix T = all[i];
|
||||||
|
work(T * full_R, i, 'R');
|
||||||
|
work(T * full_X, i, 'X');
|
||||||
|
work(T * full_P, i, 'P');
|
||||||
|
}
|
||||||
|
|
||||||
|
xp_order = matrix_order(full_X * full_P);
|
||||||
|
r_order = matrix_order(full_R);
|
||||||
|
rx_order = matrix_order(full_R * full_X);
|
||||||
|
println(hlog, "orders = ", tie(rx_order, r_order, xp_order));
|
||||||
|
}
|
||||||
|
|
||||||
EX }
|
EX }
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user