fieldpattern:: now can work with triplets
This commit is contained in:
parent
dd0e9ddae7
commit
6e942e98f5
106
fieldpattern.cpp
106
fieldpattern.cpp
|
@ -75,6 +75,10 @@ EX int btspin(int id, int d) {
|
||||||
|
|
||||||
static const int ERR = -99;
|
static const int ERR = -99;
|
||||||
|
|
||||||
|
struct triplet_info {
|
||||||
|
int i, j, size;
|
||||||
|
};
|
||||||
|
|
||||||
struct fpattern {
|
struct fpattern {
|
||||||
|
|
||||||
unsigned force_hash;
|
unsigned force_hash;
|
||||||
|
@ -224,6 +228,13 @@ struct fpattern {
|
||||||
|
|
||||||
int gmul(int a, int b) { return matcode[mmul(matrices[a], matrices[b])]; }
|
int gmul(int a, int b) { return matcode[mmul(matrices[a], matrices[b])]; }
|
||||||
int gpow(int a, int N) { return matcode[mpow(matrices[a], N)]; }
|
int gpow(int a, int N) { return matcode[mpow(matrices[a], N)]; }
|
||||||
|
|
||||||
|
int gorder(int a) {
|
||||||
|
int b = a;
|
||||||
|
int q = 1;
|
||||||
|
while(b) b = gmul(b, a), q++;
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
|
||||||
pair<int,bool> gmul(pair<int, bool> a, int b) {
|
pair<int,bool> gmul(pair<int, bool> a, int b) {
|
||||||
return make_pair(gmul(a.first,b), a.second);
|
return make_pair(gmul(a.first,b), a.second);
|
||||||
|
@ -310,6 +321,8 @@ struct fpattern {
|
||||||
vector<matrix> generate_isometries3();
|
vector<matrix> generate_isometries3();
|
||||||
int solve3();
|
int solve3();
|
||||||
bool generate_all3();
|
bool generate_all3();
|
||||||
|
|
||||||
|
vector<triplet_info> find_triplets();
|
||||||
|
|
||||||
#if CAP_THREAD
|
#if CAP_THREAD
|
||||||
struct discovery *dis;
|
struct discovery *dis;
|
||||||
|
@ -671,6 +684,84 @@ int fpattern::order(const matrix& M) {
|
||||||
return cnt;
|
return cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EX int triplet_id = 0;
|
||||||
|
|
||||||
|
vector<triplet_info> fpattern::find_triplets() {
|
||||||
|
int N = isize(matrices);
|
||||||
|
auto compute_transcript = [&] (int i, int j) {
|
||||||
|
|
||||||
|
vector<int> indices(N, -1);
|
||||||
|
vector<int> transcript;
|
||||||
|
vector<int> q;
|
||||||
|
|
||||||
|
int qty = 0;
|
||||||
|
|
||||||
|
auto visit = [&] (int id) {
|
||||||
|
transcript.push_back(indices[id]);
|
||||||
|
if(indices[id] == -1) {
|
||||||
|
indices[id] = isize(q);
|
||||||
|
q.push_back(id);
|
||||||
|
qty++;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
visit(0);
|
||||||
|
for(int x=0; x<isize(q); x++) {
|
||||||
|
int at = q[x];
|
||||||
|
visit(gmul(at, i));
|
||||||
|
visit(gmul(at, j));
|
||||||
|
}
|
||||||
|
|
||||||
|
transcript.push_back(qty);
|
||||||
|
|
||||||
|
return transcript;
|
||||||
|
};
|
||||||
|
|
||||||
|
DEBB(DF_FIELD, ("looking for alternate solutions"));
|
||||||
|
auto orig_transcript = compute_transcript(1, S7);
|
||||||
|
|
||||||
|
set<vector<int>> transcripts_seen;
|
||||||
|
transcripts_seen.insert(orig_transcript);
|
||||||
|
|
||||||
|
set<int> conjugacy_classes;
|
||||||
|
vector<int> cc;
|
||||||
|
|
||||||
|
for(int i=0; i<N; i++) conjugacy_classes.insert(i);
|
||||||
|
for(int i=0; i<N; i++) {
|
||||||
|
if(!conjugacy_classes.count(i)) continue;
|
||||||
|
vector<int> removals;
|
||||||
|
for(int j=0; j<N; j++) {
|
||||||
|
int c = gmul(inverses[j], gmul(i, j));
|
||||||
|
if(c > i) removals.push_back(c);
|
||||||
|
}
|
||||||
|
for(auto r: removals) conjugacy_classes.erase(r);
|
||||||
|
cc.push_back(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBB(DF_FIELD, ("conjugacy_classes = ", cc));
|
||||||
|
|
||||||
|
vector<triplet_info> tinf;
|
||||||
|
triplet_info ti;
|
||||||
|
ti.i = 1; ti.j = S7; ti.size = orig_transcript.back();
|
||||||
|
tinf.push_back(ti);
|
||||||
|
|
||||||
|
for(int i: conjugacy_classes) if(gorder(i) == S7) {
|
||||||
|
DEBB(DF_FIELD, ("checking i=", i));
|
||||||
|
for(int j=1; j<N; j++) if(gorder(j) == 2 && gorder(gmul(i, j)) == S3) {
|
||||||
|
auto t = compute_transcript(i, j);
|
||||||
|
if(!transcripts_seen.count(t)) {
|
||||||
|
transcripts_seen.insert(t);
|
||||||
|
triplet_info ti;
|
||||||
|
ti.i = i; ti.j = j; ti.size = t.back();
|
||||||
|
tinf.push_back(ti);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBB(DF_FIELD, ("solutions found = ", isize(transcripts_seen)));
|
||||||
|
return tinf;
|
||||||
|
}
|
||||||
|
|
||||||
void fpattern::build() {
|
void fpattern::build() {
|
||||||
|
|
||||||
if(WDIM == 3) return;
|
if(WDIM == 3) return;
|
||||||
|
@ -734,6 +825,20 @@ void fpattern::build() {
|
||||||
if(i%S7 == S7-1) printf("\n");
|
if(i%S7 == S7-1) printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEBB(DF_FIELD, ("triplet_id = ", triplet_id, " N = ", N));
|
||||||
|
if(triplet_id) {
|
||||||
|
auto triplets = find_triplets();
|
||||||
|
if(triplet_id >= 0 && triplet_id < isize(triplets)) {
|
||||||
|
auto ti = triplets[triplet_id];
|
||||||
|
R = matrices[ti.i];
|
||||||
|
P = matrices[ti.j];
|
||||||
|
dynamicval<int> t(triplet_id, 0);
|
||||||
|
build();
|
||||||
|
DEBB(DF_FIELD, ("triplet built successfully"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DEBB(DF_FIELD, ("Built.\n"));
|
DEBB(DF_FIELD, ("Built.\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1229,6 +1334,7 @@ EX int current_extra = 0;
|
||||||
|
|
||||||
EX void nextPrime(fgeomextra& ex) {
|
EX void nextPrime(fgeomextra& ex) {
|
||||||
dynamicval<eGeometry> g(geometry, ex.base);
|
dynamicval<eGeometry> g(geometry, ex.base);
|
||||||
|
dynamicval<int> t(triplet_id, 0);
|
||||||
int nextprime;
|
int nextprime;
|
||||||
if(isize(ex.primes))
|
if(isize(ex.primes))
|
||||||
nextprime = ex.primes.back().p + 1;
|
nextprime = ex.primes.back().p + 1;
|
||||||
|
|
80
geom-exp.cpp
80
geom-exp.cpp
|
@ -46,6 +46,7 @@ void showQuotientConfig() {
|
||||||
for(int i=0; i<isize(fgeomextras); i++) {
|
for(int i=0; i<isize(fgeomextras); i++) {
|
||||||
auto& g = fgeomextras[i];
|
auto& g = fgeomextras[i];
|
||||||
dialog::addBoolItem(ginf[g.base].tiling_name, g.base == gxcur.base, 'a'+i);
|
dialog::addBoolItem(ginf[g.base].tiling_name, g.base == gxcur.base, 'a'+i);
|
||||||
|
dialog::add_action([i] { current_extra = i; });
|
||||||
}
|
}
|
||||||
|
|
||||||
dialog::addBreak(100);
|
dialog::addBreak(100);
|
||||||
|
@ -64,6 +65,7 @@ void showQuotientConfig() {
|
||||||
s += stars[gxcur.dualval[i]];
|
s += stars[gxcur.dualval[i]];
|
||||||
|
|
||||||
dialog::addBoolItem(s, i == gxcur.current_prime_id, 'A'+i);
|
dialog::addBoolItem(s, i == gxcur.current_prime_id, 'A'+i);
|
||||||
|
dialog::add_action([&gxcur, i] { gxcur.current_prime_id = i; });
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isize(gxcur.primes) <= 6) {
|
if(isize(gxcur.primes) <= 6) {
|
||||||
|
@ -79,34 +81,57 @@ void showQuotientConfig() {
|
||||||
}
|
}
|
||||||
|
|
||||||
dialog::addItem("find the next prime", 'p');
|
dialog::addItem("find the next prime", 'p');
|
||||||
|
dialog::add_action([&gxcur] { nextPrime(gxcur); });
|
||||||
|
|
||||||
dialog::addItem("activate", 'x');
|
dialog::addItem("activate", 'x');
|
||||||
dialog::addItem("default", 'c');
|
dialog::add_action_confirmed([&gxcur] {
|
||||||
|
set_geometry(gxcur.base);
|
||||||
|
enableFieldChange();
|
||||||
|
set_geometry(gFieldQuotient);
|
||||||
|
start_game();
|
||||||
|
});
|
||||||
|
|
||||||
|
dialog::addItem("find alternate manifolds", 'y');
|
||||||
|
dialog::add_action_confirmed([&gxcur] {
|
||||||
|
set_geometry(gxcur.base);
|
||||||
|
triplet_id = 0;
|
||||||
|
enableFieldChange();
|
||||||
|
set_geometry(gFieldQuotient);
|
||||||
|
start_game();
|
||||||
|
|
||||||
|
auto& cfp = currfp;
|
||||||
|
auto triplets = cfp.find_triplets();
|
||||||
|
pushScreen([triplets] {
|
||||||
|
gamescreen(2);
|
||||||
|
dialog::init(XLAT("alternate manifolds"));
|
||||||
|
int id = 0;
|
||||||
|
for(auto t: triplets) {
|
||||||
|
dialog::addItem(XLAT("generators (%1,%2), size %3", its(t.i), its(t.j), its(t.size/S7)), 'a'+id);
|
||||||
|
dialog::add_action([id] {
|
||||||
|
stop_game();
|
||||||
|
triplet_id = id;
|
||||||
|
fieldpattern::enableFieldChange();
|
||||||
|
start_game();
|
||||||
|
});
|
||||||
|
id++;
|
||||||
|
}
|
||||||
|
dialog::addBreak(100);
|
||||||
|
dialog::addHelp(XLAT(
|
||||||
|
"This option finds alternate solutions. For example, there are three {7,3} manifolds with 156 heptagons each (\"first Hurwitz triplet\").")
|
||||||
|
);
|
||||||
|
dialog::display();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
dialog::addItem("default", 'z');
|
||||||
|
dialog::add_action_confirmed([] {
|
||||||
|
set_geometry(gEuclid);
|
||||||
|
fieldpattern::quotient_field_changed = false;
|
||||||
|
set_geometry(gFieldQuotient);
|
||||||
|
start_game();
|
||||||
|
});
|
||||||
|
|
||||||
dialog::addBack();
|
dialog::addBack();
|
||||||
|
|
||||||
keyhandler = [&gxcur] (int sym, int uni) {
|
|
||||||
if(uni >= 'a' && uni < 'a' + isize(fgeomextras))
|
|
||||||
current_extra = uni - 'a';
|
|
||||||
else if(uni >= 'A' && uni < 'A' + isize(gxcur.primes))
|
|
||||||
gxcur.current_prime_id = uni - 'A';
|
|
||||||
else if(uni == 'p')
|
|
||||||
nextPrime(gxcur);
|
|
||||||
else if(uni == 'x' || uni == '\n') dialog::do_if_confirmed([&gxcur] {
|
|
||||||
set_geometry(gxcur.base);
|
|
||||||
enableFieldChange();
|
|
||||||
set_geometry(gFieldQuotient);
|
|
||||||
start_game();
|
|
||||||
});
|
|
||||||
else if(uni == 'c') dialog::do_if_confirmed([] {
|
|
||||||
set_geometry(gEuclid);
|
|
||||||
fieldpattern::quotient_field_changed = false;
|
|
||||||
set_geometry(gFieldQuotient);
|
|
||||||
start_game();
|
|
||||||
});
|
|
||||||
else if(doexiton(sym, uni))
|
|
||||||
popScreen();
|
|
||||||
};
|
|
||||||
|
|
||||||
dialog::display();
|
dialog::display();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1111,6 +1136,11 @@ int read_geom_args() {
|
||||||
enableFieldChange();
|
enableFieldChange();
|
||||||
set_geometry(gFieldQuotient);
|
set_geometry(gFieldQuotient);
|
||||||
}
|
}
|
||||||
|
else if(argis("-triplet")) {
|
||||||
|
stop_game();
|
||||||
|
shift(); fieldpattern::triplet_id = argi();
|
||||||
|
fieldpattern::enableFieldChange();
|
||||||
|
}
|
||||||
else if(argis("-to-fq")) {
|
else if(argis("-to-fq")) {
|
||||||
cgi.require_basics();
|
cgi.require_basics();
|
||||||
int p = 2;
|
int p = 2;
|
||||||
|
|
Loading…
Reference in New Issue