// here the embeddings used in our experiments are implemented // Copyright (C) 2011-2022 Tehora and Zeno Rogue, see 'hyper.cpp' for details #include "kohonen.h" namespace rogueviz { namespace embeddings { embedding_type etype = eNatural; /** landscape embedding */ map landscape_at; map delta_at; map delta_id; int qdelta; void init_landscape(int dimensions) { etype = eLandscape; landscape_at.clear(); delta_at.clear(); delta_id.clear(); qdelta = 0; landscape_at[currentmap->gamestart()].resize(dimensions, 0); println(hlog, "initialized for ", currentmap->gamestart()); } kohvec& get_landscape_at(cell *h); void init_landscape_det(const vector& ac) { etype = eLandscape; landscape_at.clear(); delta_at.clear(); delta_id.clear(); qdelta = 0; landscape_at[currentmap->gamestart()].resize(0, 0); for(cell *c: ac) get_landscape_at(c); int dimensions = isize(delta_at); landscape_at.clear(); landscape_at[currentmap->gamestart()].resize(dimensions, 0); println(hlog, "qdelta = ", qdelta, " size of delta_at = ", isize(delta_at)); for(auto& d: delta_at) { d.second.resize(dimensions, 0); // d.second[id++] = 1; d.second[delta_id[d.first]] = 1; } println(hlog, "initialized for ", currentmap->gamestart(), ", dimensions = ", dimensions); } void normalize(cellwalker& cw) { int d = celldist(cw.at); back: if(GDIM == 3) { auto& da = currentmap->dirdist(cw.at); for(int j=0; jstrafe(cw, j); int d1 = celldist(str.at); if(d1 == d+1) continue; else if(d1 == d-1) { d = d1; cw = str; goto back; } else println(hlog, tie(d, d1)); } } else if(S3 == OINF) return; else if(S3 == 4) for(int s: {1, -1}) { cellwalker str = (cw + s) + wstep + s; int d1 = celldist(str.at); if(d1 < d) { d = d1; cw = str; goto back; } } else { while(true) { cellwalker str = (cw + 1) + wstep + 2; int d1 = celldist(str.at); if(d1 > d) break; d = d1; cw = str; } while(true) { cellwalker str = (cw - 2) + wstep - 1; int d1 = celldist(str.at); if(d1 > d) break; d = d1; cw = str; } } } ld hrandd() { return ((hrngen() & HRANDMAX) + .5) / HRANDMAX; } ld gaussian_random() { ld u1 = hrandd(); ld u2 = hrandd(); return sqrt(-2*log(u1)) * cos(TAU*u2); } void apply_delta(cellwalker cw, kohvec& v) { normalize(cw); auto& da = delta_at[cw]; if(!delta_id.count(cw)) { delta_id[cw] = qdelta++; da.resize(isize(v)); for(int i=0; i 2) exit(1); for(int i=0; itype; i++) { cell *h1 = h->cmove(i); auto hd1 = celldist(h1); if(hd1 < hd) { cellwalker cw(h, i); auto& res = landscape_at[h]; res = get_landscape_at(h1); if(S3 == 3) { apply_delta(cw, res); apply_delta(cw+1, res); } else apply_delta(cw, res); break; } } return landscape_at[h]; } /** signposts embedding */ vector signposts; void mark_signposts(bool full, const vector& ac) { etype = eSignpost; println(hlog, "marking signposts"); signposts.clear(); int maxd = 0; if(!closed_manifold) for(cell *c: ac) maxd = max(celldist(c), maxd); for(cell *c: ac) if(full || c->type != 6) if(closed_manifold || celldist(c) == maxd) signposts.push_back(c); } /** special signposts */ void mark_signposts_subg(int a, int b, const vector& ac) { etype = eSignpost; println(hlog, "marking bitrunc signposts"); signposts.clear(); int maxd = 0; if(!closed_manifold) for(cell *c: ac) maxd = max(celldist(c), maxd); for(cell *c: ac) { auto li = gp::get_local_info(c); auto rel = li.relative * gp::loc(a, b); auto rel2 = rel * gp::param.conj(); rel2 = rel2 / (gp::param * gp::param.conj()).first; if(rel2 * gp::param == rel) signposts.push_back(c); } } /** rug embedding */ map rug_coordinates; void generate_rug(int i, bool close) { etype = eHypersian; rug::init(); while(rug::precision_increases < i) rug::physics(); if(close) rug::close(); for(auto p: rug::rug_map) rug_coordinates[p.first] = p.second->native; } /** main function */ void get_coordinates(kohvec& v, cell *c, cell *c0) { switch(etype) { case eLandscape: { v = get_landscape_at(c); columns = isize(v); break; } case eSignpost: columns = isize(signposts); alloc(v); for(int i=0; i ", kz(alpha)); v[2*i] = cos(alpha); v[2*i+1] = sin(alpha); } // println(hlog, kz(h), " -> ", v); } else if(euclid && closed_manifold && WDIM == 2) { columns = 4; alloc(v); rug::clifford_torus ct; h = ct.torus_to_s4(ct.actual_to_torus(h)); for(int i=0; i<4; i++) v[i] = h[i]; } else if(euclid && closed_manifold && WDIM == 3) { columns = 6; alloc(v); using namespace euc; auto& T0 = eu_input.user_axes; for(int i=0; i<3; i++) { int s = T0[i][i]; ld alpha = TAU * h[i] / s; v[2*i] = cos(alpha) * s; v[2*i+1] = sin(alpha) * s; } } else if(euclid && !quotient) { columns = WDIM; alloc(v); for(int i=0; i