// define all our manifolds, and perform tests on them // Copyright (C) 2011-2022 Tehora and Zeno Rogue, see 'hyper.cpp' for details #include "kohonen.h" #include <unordered_map> namespace rogueviz { transmatrix& memo_relative_matrix(cell *c1, cell *c2); namespace kohonen_test { using namespace kohonen; void equal_weights() { alloc(weights); for(auto& w: weights) w = 1; } void show_all() { samples_to_show.clear(); for(int i=0; i<samples; i++) samples_to_show.push_back(i); } bool check(bool deb); vector<pair<int, int> > voronoi_edges; bool nmap; vector<cell*> where; int max_distance = 999; bool using_subdata; vector<sample> orig_data; vector<int> sub_indices; vector<int> inv_sub_indices; void ideal() { for(int i=0; i<isize(net); i++) for(auto& v: net[i].net) v = 1000; for(int i=0; i<isize(net); i++) for(int j=0; j<isize(where); j++) if(where[j] == net[i].where) net[i].net = (using_subdata ? orig_data : data)[j].val; println(hlog, make_pair(isize(net), isize(where))); } bool sphere_data = false; bool edge_data; vector<bool> is_special; vector<int> ctrdist; int ctrdist_max; voronoi::manifold data_manifold; using measures::manidata; manidata test_emb, test_orig; void create_manidata(manidata& mdata) { auto ac = gen_neuron_cells(); auto& edges = mdata.edges; edges.clear(); mdata.size = isize(ac); mdata.distances.clear(); for(int i=0; i<mdata.size; i++) { for(int j=0; j<i; j++) if(isNeighbor(ac[i], ac[j])) edges.emplace_back(i, j); } } void create_data() { if(sphere_data) return; sphere_data = true; initialize_rv(); cell *c0 = currentmap->gamestart(); where.clear(); is_special.clear(); ctrdist.clear(); ctrdist_max = 0; edge_data = false; drawthemap(); data.clear(); samples_to_show.clear(); auto ac = gen_neuron_cells(); for(auto c: ac) { if(celldistance(c, c0) > max_distance) continue; where.push_back(c); sample s; embeddings::get_coordinates(s.val, c, c0); data.push_back(std::move(s)); } samples = isize(data); test_orig.size = samples; colnames.resize(columns); for(int i=0; i<columns; i++) colnames[i] = "Coordinate " + its(i); equal_weights(); show_all(); data_manifold = voronoi::build_manifold(ac); for(int i=0; i<samples; i++) { bool sign = false; using embeddings::signposts; for(cell *c: signposts) if(c == where[i]) sign = true; if(signposts.empty()) sign = where[i]->type != (S3 == 3 ? 6 : 4); is_special.push_back(sign); ctrdist.push_back(celldist(where[i])); ctrdist_max = max(ctrdist_max, ctrdist.back()); } create_manidata(test_orig); } void create_subdata(int qty) { if(!using_subdata) orig_data = data; using_subdata = true; int N = isize(orig_data); sub_indices.resize(N); for(int i=0; i<N; i++) sub_indices[i] = i; hrandom_shuffle(sub_indices); sub_indices.resize(qty); data.clear(); for(int i=0; i<isize(vdata); i++) if(vdata[i].m) vdata[i].m->dead = true; vdata.clear(); sample_vdata_id.clear(); state &= ~KS_SAMPLES; for(int idx: sub_indices) data.push_back(orig_data[idx]); samples = isize(data); inv_sub_indices.clear(); inv_sub_indices.resize(N, -1); for(int i=0; i<samples; i++) inv_sub_indices[sub_indices[i]] = i; show_all(); edge_data = false; } bool colorless = false; void create_edgedata() { if(edge_data) return; edge_data = true; create_data(); if(!colorless) for(int i=0; i<samples; i++) { if(is_special[i]) vdata[i].cp.color1 = gradient(0xC0C000FF, 0xC00000FF, 0, ctrdist[i], ctrdist_max); else vdata[i].cp.color1 = gradient(0x0000FFFF, 0x101010FF, 0, ctrdist[i], ctrdist_max); } auto& edges = test_orig.edges; for(int i=0; i<samples; i++) { vector<int> ids; for(auto e: edges) { if(e.first == i) ids.push_back(e.second); if(e.second == i) ids.push_back(e.first); } vdata[i].name = lalign(0, "#", i, " ", ids); } auto any = add_edgetype("adjacent"); if(!using_subdata) { for(auto e: edges) addedge(e.first, e.second, 1, false, any); } else { vector<int> nearest(isize(orig_data), -1); set<pair<int, int>> subedges; for(int i=0; i<samples; i++) nearest[sub_indices[i]] = i; while(true) { vector<pair<int, int> > changes; for(auto e: edges) { if(nearest[e.first] == -1 && nearest[e.second] >= 0) changes.emplace_back(e.first, nearest[e.second]); if(nearest[e.second] == -1 && nearest[e.first] >= 0) changes.emplace_back(e.second, nearest[e.first]); } if(changes.empty()) break; // hrandom_shuffle(changes); for(auto ch: changes) nearest[ch.first] = ch.second; } for(auto e: edges) if(nearest[e.first] != nearest[e.second]) subedges.emplace(nearest[e.first], nearest[e.second]); // for(auto se: subedges) println(hlog, "subedges = ", se); for(auto sube: subedges) addedge(sube.first, sube.second, 1, false, any); } println(hlog, "edgedata created, ", using_subdata); } void sphere_test() { create_data(); initialize_dispersion(); initialize_neurons_initial(); analyze(); create_edgedata(); ideal(); analyze(); } void sphere_test_no_disp() { create_data(); initialize_neurons_initial(); analyze(); create_edgedata(); ideal(); analyze(); } void check_energy() { vector<int> dlist; vector<cell*> win_cells(samples); for(int i=0; i<samples; i++) win_cells[i] = winner(i).where; vector<int> distlist; for(int i=0; i<samples; i++) for(int j=0; j<i; j++) distlist.push_back(celldistance(where[i], where[j])); for(int i=0; i<samples; i++) { shiftmatrix M = ggmatrix(where[i]); println(hlog, i, ": ", M * C0); } // println(hlog, distlist); for(auto e: test_orig.edges) { cell *w1 = win_cells[e.first]; cell *w2 = win_cells[e.second]; int d = celldistance(w1, w2); dlist.push_back(d); } println(hlog, dlist); } void evaluate() { create_manidata(test_emb); test_orig.distances = measures::build_distance_matrix(test_orig.size, test_orig.edges); test_emb.distances = measures::build_distance_matrix(test_emb.size, test_emb.edges); vector<int> mapp(test_orig.size, 0); map<cell*, int> id; for(int i=0; i<isize(net); i++) id[net[i].where] = i; for(int i=0; i<samples; i++) mapp[i] = id[winner(i).where]; vector<pair<int, int>> edo_recreated = measures::recreate_topology(mapp, test_orig.edges); for(int k=0; k<measures::MCOUNT; k++) { print(hlog, measures::catnames[k], " = ", measures::evaluate_measure(test_emb, test_orig, mapp, voronoi_edges, edo_recreated, k), " "); } println(hlog); } bool kst_key(int sym, int uni) { if((cmode & sm::NORMAL) && uni == 'l') { set_neuron_initial(); t = tmax; analyze(); return true; } else if((cmode & sm::NORMAL) && uni == 'd') { for(int i=0; i<samples; i++) println(hlog, i, ": ", data[i].val); return true; } else if((cmode & sm::NORMAL) && uni == 'v') { voronoi_edges = voronoi::compute_voronoi_edges(data_manifold); println(hlog, "voronoi edges computed"); evaluate(); return true; } else if((cmode & sm::NORMAL) && uni == 'r') { set_neuron_initial(); t = tmax; dynamicval ks(qpct, 0); while(!finished()) kohonen::step(); println(hlog, "check result = ", check(true)); check_energy(); return true; } if((cmode & sm::NORMAL) && uni == 't') { tmax /= 2; println(hlog, "tmax = ", tmax); return true; } if((cmode & sm::NORMAL) && uni == 'x') { int t = clock(); println(hlog, "weights = ", weights, " w0 = ", weights[0]); check(true); println(hlog, "time = ", int(clock() - t), " power = ", kohonen::ttpower, " dea = ", kohonen::dispersion_end_at, " dm = ", kohonen::distmul); return true; } return false; } int ks_empty, ks_nonadj, ks_distant; int qenergy = 0; double tot_energy = 0; bool check(bool deb) { dynamicval dd(debugflags, 0); set_neuron_initial(); t = tmax; dynamicval dp(qpct, 0); while(!finished()) kohonen::step(); analyze(); int empty = 0, nonadj = 0, distant = 0; for(int i=0; i<cells; i++) if(net[i].csample == 0) empty++; vector<cell*> win_cells(samples); for(int i=0; i<samples; i++) win_cells[i] = winner(i).where; int energy = 0; for(auto e: test_orig.edges) { cell *w1 = win_cells[e.first]; cell *w2 = win_cells[e.second]; int rho = celldistance(w1, w2); energy += rho * rho; if(!isNeighbor(w1, w2)) { nonadj++; bool dist2 = false; forCellEx(w3, w1) if(isNeighbor(w3, w2)) dist2 = true; if(!dist2) distant++; } } tot_energy += energy; qenergy++; if(deb) println(hlog, "empty = ", empty, " nonadj = ", nonadj, " distant = ", distant, " energy = ", energy, " avg ", tot_energy / qenergy); bool res = empty <= ks_empty && distant <= ks_distant && nonadj <= ks_nonadj; return res; } vector<ld> get_parameters() { return vector<ld> { ttpower, learning_factor, gaussian ? distmul : dispersion_end_at-1 }; } void set_parameters(const vector<ld>& v) { ttpower = v[0]; learning_factor = v[1]; if(gaussian) distmul = v[2]; else dispersion_end_at = v[2] + 1; } void som_table() { sphere_test(); map<array<int, 3>, pair<int, int> > tries; map<array<int, 3>, string> sucorder; auto bttpower = ttpower; auto blearning = learning_factor; auto bdist = distmul; auto bdispe = dispersion_end_at - 1; ld last_distmul = -1; auto set_parameters = [&] (array<int, 3>& u) { distmul = bdist * exp(u[0] / 5.); dispersion_end_at = 1 + bdispe * exp(u[0] / 5.); ttpower = bttpower * exp(u[2] / 5.); learning_factor = blearning * exp(u[1] / 5.); if(last_distmul != distmul) { last_distmul = distmul, state &=~ KS_DISPERSION; } }; array<int, 3> best = {0, 0, 0}; int maxtry = 20; while(true) { array<int, 3> best_at; ld bestval = -1; vector<ld> vals; for(int k=0; k<27; k++) { array<int, 3> cnt; int k1 = k; for(int i=0; i<3; i++) cnt[2-i] = best[2-i] + (k1%3-1), k1 /= 3; set_parameters(cnt); do { tries[cnt].second++; dynamicval dd(debugflags, 0); bool chk = check(false); if(chk) tries[cnt].first++; sucorder[cnt] += (chk ? 'y' : 'n'); } while(tries[cnt].second < maxtry); ld val_here = tries[cnt].first * 1. / tries[cnt].second; if(val_here > bestval) bestval = val_here, best_at = cnt; vals.push_back(val_here); } sort(vals.begin(), vals.end()); best = best_at; set_parameters(best); println(hlog, "score ", bestval, " at ", best_at, " : ", tie(distmul, dispersion_end_at, learning_factor, ttpower), " x", tries[best].second, " s=", vals[vals.size()-2]); if(tries[best].second > maxtry) maxtry = tries[best].second; if(tries[best].second >= 1000) { println(hlog, "suc ", best, " :\n", sucorder[best]); for(int vv=10; vv>=0; vv--) { dynamicval ks(qpct, 0); t = vv ? tmax * vv / 10 : 1; step(); println(hlog, "t=", t); println(hlog, "dispersion_count = ", dispersion_count); } return; } } } vector<string> shapelist; map<string, reaction_t> shapes; map<string, reaction_t> embeddings; int data_scale = 1; int embed_scale = 1; int current_scale = 1; void set_gp(int a, int b) { a *= current_scale; b *= current_scale; if(a == 1 && b == 1) set_variation(eVariation::bitruncated); else if(a == 1 && b == 0) set_variation(eVariation::pure); else { set_variation(eVariation::goldberg); gp::param = gp::loc(a, b); } } void set_restrict() { kohonen::kqty = 5000; kohonen::kohrestrict = 520 * current_scale * current_scale; } void set_torus2(int a, int b, int c, int d, int e) { using namespace euc; auto& T0 = eu_input.user_axes; T0[0][0] = a; T0[0][1] = b; T0[1][0] = c; T0[1][1] = d; eu_input.twisted = e; build_torus3(); } int dim = 10; string emb; void add(string name, reaction_t embed, reaction_t set) { shapelist.push_back(name); shapes[name] = set; embeddings[name] = embed; } void set_euclid3(int x, int y, int z, int twist) { using namespace euc; auto& T0 = eu_input.user_axes; for(int i=0; i<3; i++) for(int j=0; j<3; j++) T0[i][j] = 0; T0[0][0] = x; T0[1][1] = y; T0[2][2] = z; eu_input.twisted = twist; build_torus3(); } void klein_signposts() { embeddings::etype = embeddings::eSignpost; println(hlog, "marking klein signposts"); embeddings::signposts.clear(); for(cell *c: currentmap->allcells()) setdist(c, 7, nullptr); for(int x=0; x<4; x++) for(int y=0; y<13; y++) { cellwalker cw = cellwalker(currentmap->gamestart(), 0); for(int i=0; i<x*5*current_scale; i++) { cw += wstep; cw += 3; } cw+=2; for(int j=0; j<y*current_scale; j++) { cw += wstep; cw += 2; cw += wstep; cw -= 2; } embeddings::signposts.push_back(cw.at); } println(hlog, embeddings::signposts); } flagtype flags; const static flagtype m_symmetric = Flag(0); int landscape_dim = 60; void init_shapes() { auto signpost = [] { emb = "signpost"; embeddings::mark_signposts(false, gen_neuron_cells()); }; auto signpost_subg = [] (int a, int b) { return [a,b] { emb = "signpost" + its(a) + its(b); embeddings::mark_signposts_subg(a, b, gen_neuron_cells()); }; }; // auto signpost_full = [] { emb = "signpost-full"; embeddings::mark_signposts(true, gen_neuron_cells()); }; auto signpost_klein = [] { emb = "signpost-klein"; klein_signposts(); }; auto landscape = [] { emb = "landscape"; if(landscape_dim) embeddings::init_landscape(landscape_dim); else embeddings::init_landscape_det(gen_neuron_cells()); }; auto natural = [] { emb = "natural"; embeddings::etype = embeddings::eNatural; }; /* disks */ add("disk10", landscape, [] { set_geometry(gNormal); set_gp(1,0); set_restrict(); flags = 0; }); add("disk11", landscape, [] { set_geometry(gNormal); set_gp(1,1); set_restrict(); flags = 0; }); add("disk20", landscape, [] { set_geometry(gNormal); set_gp(2,0); set_restrict(); flags = 0; }); add("disk21", landscape, [] { set_geometry(gNormal); set_gp(2,1); set_restrict(); flags = 0; }); add("disk40", landscape, [] { set_geometry(gNormal); set_gp(4,0); set_restrict(); flags = 0; }); add("disk43", landscape, [] { set_geometry(gNormal); set_gp(4,3); set_restrict(); flags = 0; }); add("disk-euclid", landscape, [] { set_geometry(gEuclid); set_gp(1,0); set_restrict(); set_torus2(0,0,0,0,0); flags = 0; }); /* spheres */ add("elliptic", signpost, [] { set_geometry(gElliptic); set_gp(6,6); flags = m_symmetric; }); add("sphere", natural, [] { set_geometry(gSphere); set_gp(6,2); flags = m_symmetric; }); add("sphere4", natural, [] { set_geometry(gSmallSphere); set_gp(7,6); flags = m_symmetric; }); /* tori */ add("torus-hex", natural, [] { set_geometry(gEuclid); set_gp(1,0); dim = 23; set_torus2(dim, 0, 0, dim, 0); flags = m_symmetric; }); add("torus-sq", natural, [] { set_geometry(gEuclid); set_gp(1,0); dim = 13; set_torus2(dim*1.6,0,-dim,dim*2,0); }); add("torus-rec", natural, [] { set_geometry(gEuclid); set_gp(1,0); dim = 9; set_torus2(dim*3+2,0,-dim,dim*2,0); flags = 0; }); if(0) add("torus-sq-sq", natural, [] { set_geometry(gEuclidSquare); set_gp(1,0); set_torus2(23,0,0,23,0); flags = m_symmetric; }); add("klein-sq", signpost_klein, [] { set_geometry(gEuclid); set_gp(1,0); dim = 13; set_torus2(dim*1.6,0,-dim,dim*2,8); flags = 0; }); /* hyperbolic 8 */ add("Bolza", signpost_subg(1, 1), [] { set_geometry(gBolza); set_gp(6,3); flags = m_symmetric; }); add("Bolza2", signpost, [] { set_geometry(gBolza2); set_gp(5,1); flags = m_symmetric; }); /* hyperbolic 7 */ add("minimal", signpost, [] { set_geometry(gMinimal); set_gp(5,5); flags = 0; }); add("Zebra", signpost, [] { set_geometry(gZebraQuotient); set_gp(4,3); flags = 0; }); add("KQ", signpost, [] { set_geometry(gKleinQuartic); set_gp(3,2); flags = m_symmetric; }); add("Macbeath", signpost, [] { set_geometry(gMacbeath); set_gp(2,1); flags = m_symmetric; }); add("triplet1", signpost, [] { field_quotient_2d(0, 1, 0); set_gp(1, 1); flags = m_symmetric; }); add("triplet2", signpost, [] { field_quotient_2d(0, 1, 1); set_gp(1, 1); flags = m_symmetric; }); add("triplet3", signpost, [] { field_quotient_2d(0, 1, 2); set_gp(1, 1); flags = m_symmetric; }); } void shot_settings() { View = Id; brm_limit = GDIM == 2 ? 1000 : 0; if(GDIM == 3) View = cspin(0, 2, 30 * degree) * cspin(1, 2, 30._deg) * View; shift_view(ctangent(2, -0.5)); vid.creature_scale = GDIM == 2 ? 4.5 : 1; if(geometry == gCell600) vid.creature_scale = 0.5; pconf.alpha = 1; pmodel = mdDisk; if(GDIM == 3 && hyperbolic) { sightranges[geometry] = 8; vid.creature_scale = 2; } shot::shotformat = -1; shot::shotx = 1000; shot::shoty = 1000; shot::transparent = GDIM == 2; pconf.scale = 0.9; modelcolor = 0xFF; drawthemap(); if(sphere) pconf.scale = 0.6; if(euclid) { ld maxs = 0; auto& cd = current_display; for(auto n: net) { auto w = n.where; shiftmatrix g = ggmatrix(w); for(int i=0; i<w->type; i++) { shiftpoint h = tC0(g * currentmap->adj(w, i)); hyperpoint onscreen; applymodel(h, onscreen); maxs = max(maxs, onscreen[0] / cd->xsize); maxs = max(maxs, onscreen[1] / cd->ysize); } } pconf.alpha = 1; pconf.scale = pconf.scale / 2 / maxs / cd->radius; pconf.scale /= 1.2; if(closed_manifold) pconf.scale = WDIM == 3 ? 0.2 : 0.07; } if(GDIM == 3) pmodel = mdPerspective; if(nil || sol) pmodel = mdGeodesic; vid.use_smart_range = 2; vid.smart_range_detail = 7; vid.cells_generated_limit = 999999; vid.cells_drawn_limit = 200000; } void shot_settings_png() { vid.use_smart_range = 2; vid.smart_range_detail = 0.5; shot::shotx = 500; shot::shoty = 500; } bool more = true; void create_index() { hr::ignore(system(("mkdir " + som_test_dir).c_str())); fhstream f(som_test_dir + "index-" + its(current_scale) + ".html", "wt"); fhstream csv(som_test_dir + "manifold-data-" + its(current_scale) + ".csv", "wt"); fhstream tex(som_test_dir + "manifold-data-" + its(current_scale) + ".tex", "wt"); println(f, "<html><body>"); // fhstream distf(som_test_dir + "distlists-" + its(current_scale) + ".txt", "wt"); bool add_header = true; for(auto s: shapelist) { sphere_data = false; println(hlog, "building ", s); kohonen::kqty = kohonen::krad = 0; kohonen::kohrestrict = 999999999; stop_game(); shapes[s](); // if(!euclid) continue; start_game(); initialize_rv(); embeddings[s](); println(hlog, "create_data"); create_data(); println(hlog, "sphere_test"); sphere_test_no_disp(); println(hlog, "building disttable"); vector<int> disttable(100, 0); int pairs = 0; test_orig.distances = measures::build_distance_matrix(test_orig.size, test_orig.edges); int N = test_orig.size; for(int i=0; i<N; i++) for(int j=0; j<i; j++) { disttable[test_orig.distances[i][j]]++; pairs++; } println(hlog, "render"); shot_settings(); shot_settings_png(); shot::take(som_test_dir + s + "-" + its(current_scale) + ".png"); println(f, "<img src=\"" + s + "-" + its(current_scale) + ".png\"/><br/>"); println(f, "shape ", s, " : ", samples, " items, ", isize(test_orig.edges), " edges, dim ", columns, " (", emb, "), ", full_geometry_name()); println(f, "<hr/>"); fflush(f.f); again: if(add_header) print(csv, "name"); else print(csv, s); if(add_header) print(tex, "name"); else print(tex, s); #define Out(title,value) if(add_header) { print(csv, ";", title); print(tex, "&", title); } else { print(csv, ";", value); print(tex, "&", value); } double avgdist = 0, avgdist2 = 0, sqsum = 0; int maxdist = 0; for(int i=0; i<100; i++) { if(disttable[i] > 0) maxdist = i; avgdist += i * disttable[i]; avgdist2 += i * i * disttable[i]; sqsum += disttable[i] * (disttable[i]-1.); } disttable.resize(maxdist + 1); if(more) println(hlog, disttable, " pairs = ", pairs); avgdist /= pairs; avgdist2 /= pairs; double kmax = 1 - sqsum / (pairs * (pairs-1.)); Out("samples", samples); Out("edges", isize(test_orig.edges)); Out("columns", columns); Out("embtype", emb); Out("gpx", gp::univ_param().first); Out("gpy", gp::univ_param().second); Out("orientable", nonorientable ? 0 : 1); Out("symmetric", (flags & m_symmetric) ? 1 : 0); Out("closed", closed_manifold ? 1 : 0); Out("quotient", quotient ? 1 : 0); Out("dim", WDIM); Out("valence", S3); Out("tile", S7); println(hlog, "gen neuron cells"); auto ac = gen_neuron_cells(); int sum = 0; for(cell *c: ac) sum += c->type; ld curvature = (S3 == 3 ? 6 : S3 >= OINF ? 2 : 4) - sum * 1. / isize(ac); if(GDIM == 3) curvature = hyperbolic ? -1 : sphere ? 1 : 0; Out("curvature", curvature); println(hlog, "compute geometry data"); auto gd = compute_geometry_data(); Out("euler", gd.euler); Out("area", gd.area); Out("geometry", hyperbolic ? "hyperbolic" : euclid ? "euclidean" : sphere ? "spherical" : "other"); if(more) { Out("maxdist", maxdist); Out("avgdist", avgdist); Out("avgdist2", avgdist2); Out("kmax", kmax); } println(csv); println(tex, "\\\\"); fflush(csv.f); fflush(f.f); fflush(tex.f); if(add_header) { add_header = false; goto again; } println(hlog, "geom = ", s, " delta = ", isize(embeddings::delta_at)); } println(f, "</body></html>"); } unsigned hash(string s) { unsigned res = 0; for(char c: s) res = res * 37 + c; return res; } int subdata_value; bool only_landscape; string cg() { string s = ""; if(kohonen::gaussian == 1) s += "-cg"; if(kohonen::gaussian == 2) s += "-gg"; if(kohonen::dispersion_long) s += "-dl"; if(ttpower != 1) s += "-tt" + lalign(0, ttpower); if(subdata_value) s += "-s" + its(subdata_value); if(landscape_dim) s += "-l" + its(landscape_dim); if(data_scale) s += "-d" + its(data_scale); if(embed_scale) s += "-e" + its(embed_scale); return s; } vector<vector<sample> > saved_data; void all_pairs(bool one) { string dir = som_test_dir + "pairs" + cg(); hr::ignore(system(("mkdir -p " + dir + "/img").c_str())); int sid = 0; for(auto s1: shapelist) { for(auto s2: shapelist) { sid++; if(kohonen::gaussian == 2 && s2.substr(0, 4) != "disk" && s2.substr(0, 6) != "sphere") continue; if(only_landscape && s1.substr(0, 4) != "disk") continue; string fname_vor = dir + "/" + s1 + "-" + s2 + ".vor"; string fname = dir + "/" + s1 + "-" + s2 + ".txt"; if(file_exists(fname)) continue; fhstream f(fname, "wt"); fhstream fvor(fname_vor, "wt"); println(hlog, "mapping ", s1, " to " ,s2); shrand(hash(s1) ^ hash(s2)); sphere_data = false; using_subdata = false; kohonen::kqty = kohonen::krad = 0; kohonen::kohrestrict = 999999999; current_scale = data_scale; stop_game(); shapes[s1](); start_game(); initialize_rv(); if(landscape_dim) { saved_data.clear(); for(int i=0; i<100; i++) { sphere_data = false; data.clear(); embeddings[s1](); create_data(); saved_data.push_back(data); if(i < 5) for(int j=0; j<20; j++) println(hlog, "saved data ", i, ":", j, ": ", saved_data[i][j].val); } } else { embeddings[s1](); create_data(); } stop_game(); kohonen::kqty = kohonen::krad = 0; kohonen::kohrestrict = 999999999; current_scale = embed_scale; shapes[s2](); initialize_dispersion(); initialize_neurons_initial(); analyze(); create_edgedata(); int orig_samples = samples; for(int i=0; i<100; i++) { println(hlog, "iteration ", lalign(3, i), " of ", fname); if(landscape_dim) { data = orig_data = saved_data[i]; } if(subdata_value) create_subdata(subdata_value); set_neuron_initial(); if(0) { println(hlog, "initial neuron values:"); indenter ind(2); for(auto& n: net) println(hlog, n.net); } t = tmax; dynamicval ks(qpct, 0); while(!finished()) kohonen::step(); for(int i=0; i<orig_samples; i++) { if(i) print(f, " "); int j = i; if(using_subdata) { j = inv_sub_indices[i]; if(j == -1) { print(f, "-1"); continue; } } auto& w = winner(j); print(f, int((&w) - &net[0])); } print(f, "\n"); fflush(f.f); voronoi::debug_str = lalign(0, fname_vor, " iteration ", i); auto ve = voronoi::compute_voronoi_edges(data_manifold); println(fvor, isize(ve)); for(auto e: ve) print(fvor, e.first, " ", e.second, " "); println(fvor); fflush(fvor.f); if(i < 10) { analyze(); if(i == 0) { shot_settings(); shot_settings_png(); shot::shotx = 200; shot::shoty = 200; } if(using_subdata) { create_edgedata(); } shot::take(dir + "/img/" + s1 + "-" + s2 + "-" + its(i) + ".png"); } if(i == 10) brm_structure.clear(); fflush(stdout); } if(1) { fhstream rndcheck(som_test_dir + "rndcheck" + cg(), "at"); vector<int> rnd; for(int i=0; i<10; i++) rnd.push_back(hrand(1000)); println(hlog, "finished ", s1, "-", s2, " rnd = ", rnd); println(rndcheck, "finished ", s1, "-", s2, " rnd = ", rnd); } if(one) exit(0); } } hr::ignore(system("touch done")); } bool verify_distlists = false; void create_edgelists() { fhstream f("results/edgelists-" + its(current_scale) + ".txt", "wt"); for(auto s: shapelist) { sphere_data = false; kohonen::kqty = kohonen::krad = 0; kohonen::kohrestrict = 999999999; stop_game(); shapes[s](); // if(!euclid) continue; start_game(); initialize_rv(); embeddings[s](); println(hlog, "create_data"); create_data(); println(hlog, "sphere_test"); sphere_test_no_disp(); auto ac = gen_neuron_cells(); int N = isize(ac); int M = isize(test_orig.edges); print(f, s, "\n", N, " ", M); for(auto e: test_orig.edges) print(f, " ", e.first, " ", e.second); if(verify_distlists) { test_orig.distances = measures::build_distance_matrix(test_orig.size, test_orig.edges); for(int i=0; i<N; i++) for(int j=0; j<i; j++) if(celldistance(ac[i], ac[j]) != test_orig.distances[i][j]) println(hlog, "failure on ", tie(i, j)); } println(f); fflush(f.f); } } #if CAP_COMMANDLINE int readArgs() { using namespace arg; if(0) ; /* choose the embedding */ else if(argis("-som-landscape")) { PHASE(3); start_game(); initialize_rv(); shift(); embeddings::init_landscape(argi()); println(hlog, "landscape init, ", argi()); } else if(argis("-som-landscape-det")) { PHASE(3); start_game(); initialize_rv(); embeddings::init_landscape_det(gen_neuron_cells()); println(hlog, "landscape init, ", argi()); } else if(argis("-som-signposts")) { PHASE(3); start_game(); initialize_rv(); embeddings::mark_signposts(false, gen_neuron_cells()); } else if(argis("-som-signposts-full")) { PHASE(3); start_game(); initialize_rv(); embeddings::mark_signposts(true, gen_neuron_cells()); } else if(argis("-som-signposts-klein")) { PHASE(3); start_game(); klein_signposts(); } else if(argis("-som-signposts-subg")) { PHASE(3); shift(); int a = argi(); shift(); int b = argi(); start_game(); initialize_rv(); embeddings::mark_signposts_subg(a, b, gen_neuron_cells()); } else if(argis("-som-signposts-draw")) { for(cell *c: embeddings::signposts) c->wall = waPlatform; } else if(argis("-som-rug")) { PHASE(3); start_game(); initialize_rv(); shift(); embeddings::generate_rug(argi(), true); } else if(argis("-som-rug-show")) { PHASE(3); start_game(); initialize_rv(); shift(); embeddings::generate_rug(argi(), false); } else if(argis("-som-proj")) { PHASE(3); embeddings::etype = embeddings::eProjection; } else if(argis("-som-emb")) { PHASE(3); embeddings::etype = embeddings::eNatural; } /* other stuff */ else if(argis("-som-test")) { PHASE(3); start_game(); sphere_test(); println(hlog, "data = ", isize(data), " neurons = ", isize(net)); } else if(argis("-som-cdata")) { PHASE(3); start_game(); create_data(); } else if(argis("-subdata")) { shift(); create_subdata(argi()); } else if(argis("-subdata-val")) { shift(); subdata_value = argi(); } else if(argis("-landscape-dim")) { shift(); landscape_dim = argi(); } else if(argis("-som-optimize")) { PHASE(3); start_game(); // som_optimize(); } else if(argis("-som-table")) { PHASE(3); start_game(); som_table(); } else if(argis("-som-scale-data")) { PHASE(3); shift(); current_scale = data_scale = argi(); } else if(argis("-som-scale-embed")) { PHASE(3); shift(); current_scale = embed_scale = argi(); } else if(argis("-by-name")) { PHASE(3); init_shapes(); land_structure = lsSingle; shift(); string s = args(); if(shapes.count(s)) { kohonen::kqty = kohonen::krad = 0; kohonen::kohrestrict = 999999999; stop_game(); shapes[s](); start_game(); initialize_rv(); embeddings[s](); println(hlog, "embedding used: ", emb, " for: ", s); } else { println(hlog, "shape unknown: ", s); } } else if(argis("-only-landscape")) { only_landscape = true; } else if(argis("-som-experiment")) { PHASE(3); init_shapes(); land_structure = lsSingle; all_pairs(false); } else if(argis("-som-experiment1")) { PHASE(3); init_shapes(); land_structure = lsSingle; all_pairs(true); } else if(argis("-som-experiment-index")) { PHASE(3); init_shapes(); land_structure = lsSingle; create_index(); } else if(argis("-edgecheck")) { PHASE(3); unsigned x = 1; for(auto e: test_orig.edges) { x*= 7; x += e.first; x += 123 * e.second; } println(hlog, "x = ", x, " edges = ", isize(test_orig.edges)); } else if(argis("-som-experiment-tables")) { PHASE(3); init_shapes(); land_structure = lsSingle; create_edgelists(); } else if(argis("-ex")) exit(0); else return 1; return 0; } auto hooks3 = addHook(hooks_args, 100, readArgs); #endif auto khook = arg::add3("-kst-keys", [] { rv_hook(hooks_handleKey, 150, kst_key); }) + addHook(hooks_configfile, 100, [] { param_i(ks_empty, "ks_empty", 0); param_i(ks_distant, "ks_distant", 0); param_i(ks_nonadj, "ks_nonadj", 0); param_i(max_distance, "ks_max"); }) + arg::add3("-kst-colorless", [] { colorless = true; }) + addHook(hooks_markers, 100, [] () { int N = isize(net); bool multidraw = quotient; bool use_brm = closed_manifold && isize(currentmap->allcells()) <= brm_limit; vid.linewidth *= 3; for(auto e: voronoi_edges) if(e.first < N && e.second < N) for(const shiftmatrix& V1 : hr::span_at(current_display->all_drawn_copies, net[e.first].where)) { if(use_brm) { auto V2 = brm_get(net[e.first].where, C0, net[e.second].where, C0); queueline(V1*C0, V1*V2*C0, 0xC010C0FF, vid.linequality + 3); } else if(multidraw || elliptic) { auto V2 = memo_relative_matrix(net[e.second].where, net[e.first].where); queueline(V1*C0, V1*V2*C0, 0xC010C0FF, vid.linequality + 3); } else for(const shiftmatrix& V2 : hr::span_at(current_display->all_drawn_copies, net[e.second].where)) queueline(V1*C0, V2*C0, 0xC010C0FF, vid.linequality + 3); } vid.linewidth /= 3; }) + arg::add3("-kst-animate", [] { rv_hook(anims::hooks_record_anim, 100, [] (int i, int noframes) { bool steps = false; ld nf = noframes; while(t * nf > (nf - i) * tmax) step(), steps = true; if(steps) analyze(); }); }); }}