diff --git a/rogueviz/embeddings.cpp b/rogueviz/embeddings.cpp new file mode 100644 index 00000000..58039dce --- /dev/null +++ b/rogueviz/embeddings.cpp @@ -0,0 +1,227 @@ +#include "kohonen.h" + +namespace rogueviz { + +namespace embeddings { + +embedding_type etype = eNatural; + +/** landscape embedding */ + +map landscape_at; + +map delta_at; + +void init_landscape(int dimensions) { + etype = eLandscape; + landscape_at.clear(); + delta_at.clear(); + landscape_at[currentmap->gamestart()].resize(dimensions, 0); + println(hlog, "initialized for ", currentmap->gamestart()); + } + +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 gaussian_random() { + return (hrand(1000) + hrand(1000) - hrand(1000) - hrand(1000)) / 1000.; + } + +void apply_delta(cellwalker cw, kohvec& v) { + normalize(cw); + + auto& da = delta_at[cw]; + if(da.empty()) { + da.resize(isize(v)); + for(auto& x: da) x = gaussian_random(); + } + + 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(!bounded) + for(cell *c: ac) maxd = max(celldist(c), maxd); + for(cell *c: ac) + if(full || c->type != 6) + if(bounded || celldist(c) == maxd) + 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 && bounded && 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 && bounded && 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 = 2 * M_PI * 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 kohvec; - -struct sample { - kohvec val; - string name; - }; - vector data; map sample_vdata_id; @@ -33,17 +18,6 @@ int whattodraw[3] = {-2,-2,-2}; int min_group = 10, max_group = 10; -struct neuron { - kohvec net; - cell *where; - double udist; - int lpbak; - color_t col; - int allsamples, drawn_samples, csample, bestsample, max_group_here; - int debug; - neuron() { drawn_samples = allsamples = bestsample = 0; max_group_here = max_group; debug = 0; } - }; - vector colnames; kohvec weights; @@ -52,8 +26,6 @@ vector net; int neuronId(neuron& n) { return &n - &(net[0]); } -void alloc(kohvec& k) { k.resize(columns); } - bool neurons_indexed = false; int samples; @@ -710,12 +682,6 @@ void step() { int initdiv = 1; -flagtype KS_ROGUEVIZ = 1; -flagtype KS_NEURONS = 2; -flagtype KS_DISPERSION = 4; -flagtype KS_SAMPLES = 8; -flagtype KS_NEURONS_INI = 16; - flagtype state = 0; vector bdiffs; diff --git a/rogueviz/kohonen.h b/rogueviz/kohonen.h new file mode 100644 index 00000000..9135f764 --- /dev/null +++ b/rogueviz/kohonen.h @@ -0,0 +1,95 @@ +/* a header file for kohonen and embedding */ +#ifndef _KOHONEN_H_ +#define _KOHONEN_H_ + +#include "rogueviz.h" + +namespace rogueviz { + +namespace kohonen { + +typedef vector kohvec; + +static const flagtype KS_ROGUEVIZ = 1; +static const flagtype KS_NEURONS = 2; +static const flagtype KS_DISPERSION = 4; +static const flagtype KS_SAMPLES = 8; +static const flagtype KS_NEURONS_INI = 16; + +extern flagtype state; + +extern int tmax; +extern int samples; +extern int t, tmax, lpct, cells; +extern int gaussian; + +extern int krad, kqty, kohrestrict; +extern int qpct; +extern int columns; +extern double dispersion_end_at; +extern int dispersion_count; +extern double learning_factor, distmul; +extern double ttpower; +extern int min_group, max_group, columns; + +struct neuron { + kohvec net; + cell *where; + double udist; + int lpbak; + color_t col; + int allsamples, drawn_samples, csample, bestsample, max_group_here; + int debug; + neuron() { drawn_samples = allsamples = bestsample = 0; max_group_here = max_group; debug = 0; } + }; + +struct sample { + kohvec val; + string name; + }; + +inline void alloc(kohvec& k) { k.resize(columns); } + +extern kohvec weights; +extern vector data; +extern vector samples_to_show; +extern vector net; +extern vector colnames; + +void initialize_neurons(); +void initialize_neurons_initial(); +void initialize_dispersion(); +void initialize_samples_to_show(); +void clear(); +void create_neurons(); +void analyze(); +void step(); +void initialize_rv(); +void set_neuron_initial(); +bool finished(); + +vector gen_neuron_cells(); +neuron& winner(int id); +} + +namespace embeddings { + +using kohonen::columns; +using kohonen::kohvec; +using kohonen::alloc; + +enum embedding_type { eProjection, eNatural, eLandscape, eSignpost, eHypersian }; +extern embedding_type etype; +void mark_signposts(bool full, const vector& ac); +void generate_rug(int i, bool close); +void init_landscape(int dimensions); + +extern map rug_coordinates; +extern void get_coordinates(kohvec& v, cell *c, cell *c0); + +} + +} + + +#endif diff --git a/rogueviz/rogueviz-all.cpp b/rogueviz/rogueviz-all.cpp index 35448921..f8d4fb0d 100644 --- a/rogueviz/rogueviz-all.cpp +++ b/rogueviz/rogueviz-all.cpp @@ -6,7 +6,6 @@ #include "objmodels.cpp" #include "smoothcam.cpp" -#include "kohonen.cpp" #include "staircase.cpp" #include "banachtarski.cpp" #include "pentagonal.cpp" @@ -55,5 +54,7 @@ #endif #include "highdim-demo.cpp" +#include "kohonen.cpp" +#include "embeddings.cpp" //#endif