From aed65e5bc096d0854a6a2d55c0e4846c774b7c9f Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Thu, 4 Dec 2025 23:21:46 +0100 Subject: [PATCH] rogueviz:: moved some parts from dhrg to embeddings --- rogueviz/dhrg-pres.cpp | 38 ++--- rogueviz/dhrg/betweenness.cpp | 3 +- rogueviz/dhrg/dhrg.cpp | 66 +------- rogueviz/dhrg/dhrg.h | 47 +----- rogueviz/dhrg/embedder.cpp | 68 ++++----- rogueviz/dhrg/groundtruth.cpp | 10 +- rogueviz/dhrg/loglik.cpp | 232 +---------------------------- rogueviz/dhrg/visualize.cpp | 5 +- rogueviz/embeddings/embeddings.cpp | 41 +++-- rogueviz/embeddings/loglik.cpp | 222 +++++++++++++++++++++++++++ rogueviz/embeddings/polar.cpp | 114 +++++++------- rogueviz/embeddings/routing.cpp | 67 +++++---- rogueviz/rogueviz.h | 8 - rogueviz/sag/experiments.cpp | 8 +- rogueviz/sag/functions.cpp | 12 +- 15 files changed, 428 insertions(+), 513 deletions(-) create mode 100644 rogueviz/embeddings/loglik.cpp diff --git a/rogueviz/dhrg-pres.cpp b/rogueviz/dhrg-pres.cpp index 02556164..a18aef9f 100644 --- a/rogueviz/dhrg-pres.cpp +++ b/rogueviz/dhrg-pres.cpp @@ -1,27 +1,16 @@ // -noscr -slides DHRG rv_latex=1 -slide-textoff -title c000 #include "rogueviz.h" +#include "embeddings/embeddings.h" +#include "dhrg/dhrg.h" #if CAP_RVSLIDES -namespace dhrg { - void graphv(std::string s); - extern double graph_R; - extern int N; - extern int iterations; - void unsnap(); - bool dhrg_animate(int sym, int uni); - void rvcoords(); - void clear(); - - void prepare_pairs(); - std::vector path(int src); - int get_actual(int src); - void prepare_goal(int goal); - } - namespace hr { using namespace rogueviz::pres; +using namespace rogueviz::embeddings; + +shared_ptr dhrg_embedding; int find_vertex(string name) { int id = 0; @@ -50,12 +39,12 @@ int me, them; void greedy_test() { me = find_vertex("Eryk_Kopczynski"); auto me2 = find_vertex("Erich_Grädel"); - dhrg::prepare_pairs(); - dhrg::rvcoords(); + prepare_pairs(); + reenable_embedding(); them = find_vertex(dhrg::iterations ? "Florian_Willich" : "Stéphane_Chrétien"); - for(int goal=0; goalbase, Id); } - if(!snapped) dhrg::unsnap(); + if(!snapped) enable_embedding(dhrg_embedding); } void dhrg_hooks() { diff --git a/rogueviz/dhrg/betweenness.cpp b/rogueviz/dhrg/betweenness.cpp index 87ad519f..9bb2e6bd 100644 --- a/rogueviz/dhrg/betweenness.cpp +++ b/rogueviz/dhrg/betweenness.cpp @@ -323,6 +323,7 @@ bool neq(betweenness_type a, betweenness_type b) { } void compute_betweenness(bool verify) { + auto N = isize(rogueviz::vdata); progressbar pb(N, "compute_betweenness"); int errorcount = 0, errorcount2 = 0; for(int i=0; i vertices; -vector disttable0, disttable1; void memoryInfo() { string s = ""; @@ -48,17 +46,9 @@ void debugtally() { println(hlog, " .. %", loglikopt()); } -void place_rogueviz_vertices() { - progressbar pb(N, "place_rogueviz_vertices"); - // transmatrix In = inverse(ggmatrix(currentmap->gamestart())); - using namespace rogueviz; - for(int i=0; iascell(), Id); - } - int destroy; void clear() { - coords.clear(); // destroytallies(); // todo: correct cleanup! for(int i=0; i= ts_rbase && ts_rogueviz >= ts_vertices && ts_rogueviz > ts_coords) { - origcoords(); - build_disttable_approx(); - ts_coords = ts_rogueviz; - } - else if(ts_rbase >= ts_vertices && ts_rbase > ts_coords) { - ts_coords = ts_rbase; - rvcoords(); - build_disttable_approx(); - } - else if(ts_vertices > ts_coords) { - ts_coords = ts_vertices; - cellcoords(); - build_disttable_approx(); - } - logistic cont; - cont.setRT(graph_R, graph_T); - fast_loglik_cont(cont, loglik_cont_approx, "lcont", 1, 1e-6); - // return loglik_cont(); - } - - else if(argis("-dhrgview")) { - if(ts_vertices > ts_rbase) { - place_rogueviz_vertices(); - ts_rbase = ts_vertices; - } - mainloop(); quitmainloop = false; - } - else if(argis("-iterate")) { if(ts_rbase > ts_vertices) { @@ -209,10 +150,6 @@ int dhrgArgs() { shift(); ground_truth_test(args()); } - else if(argis("-routing")) { - shift(); routing_test(args()); - } - else if(argis("-esaveas")) { shift(); save_embedding(args()); } @@ -237,7 +174,6 @@ void store_gamedata(struct hr::gamedata* gd) { if(true) { for(auto& t: tally) gd->store(t); for(auto& t: edgetally) gd->store(t); - gd->store(coords); #ifdef BUILD_ON_HR gd->store(mymap); #else diff --git a/rogueviz/dhrg/dhrg.h b/rogueviz/dhrg/dhrg.h index 4d72d143..f6824e48 100644 --- a/rogueviz/dhrg/dhrg.h +++ b/rogueviz/dhrg/dhrg.h @@ -2,6 +2,7 @@ #define _DHRG_H_ #define DHRGVER "7.1" #include "../rogueviz.h" +#include "../embeddings/embeddings.h" #define LONG_BRACKETS @@ -28,53 +29,13 @@ extern vector disttable0, disttable1; void memoryInfo(); -void cellcoords(); -void origcoords(); -void build_disttable(); - void dhrg_init(); bool dhrg_animate(int sym, int uni); -/* implemented in loglik.cpp: */ +extern int iterations; -/* for logistic regression */ -struct logistic { - ld R, T; - ld yes1(ld d) { return 1/(1 + exp(d)); } - ld no1(ld d) { return 1/(1 + exp(-d)); } - ld nor(ld d) { return (d-R) / 2 / T; } - ld yes(ld d) { return yes1(nor(d)); } - ld no(ld d) { return no1(nor(d)); } - ld lyes(ld d) { d = nor(d); return d > 200 ? -d : log(yes1(d)); } - ld lno(ld d) { d = nor(d); return d < -200 ? d : log(no1(d)); } - logistic() {} - logistic(ld _R, ld _T) : R(_R), T(_T) {} - void setRT(ld _R, ld _T) { R = _R; T = _T; } - }; - -extern ld llcont_approx_prec; -extern vector> disttable_approx; - -using logisticfun = std::function; - -extern logistic current_logistic; - -ld loglik_cont_approx(logistic& l = current_logistic); - -void fast_loglik_cont(logistic& l, const logisticfun& f, const char *name, ld start, ld eps); - -/* greedy routing */ - -struct iddata { - ld tot, suc, routedist, bestdist; - iddata() { tot = suc = routedist = bestdist = 0; } - }; - -using neighborhoodfun = std::function (int)>; -using distfun = std::function; - -void prepare_pairs(int N, const neighborhoodfun& nei); -void greedy_routing(iddata& d, const distfun& distance_function); +void clear(); +void graph_from_rv(); } #endif diff --git a/rogueviz/dhrg/embedder.cpp b/rogueviz/dhrg/embedder.cpp index bc0d5093..3e61bc3e 100644 --- a/rogueviz/dhrg/embedder.cpp +++ b/rogueviz/dhrg/embedder.cpp @@ -22,6 +22,7 @@ int lastmoves; int movearound() { indenter_finish im("movearound"); + int N = isize(rogueviz::vdata); int total = 0; if(smartmove) for(bool b: tomove) if(b) total++; if(total == 0) { @@ -90,6 +91,8 @@ int move_restart() { for(int a=0; a<2; a++) for(int b=0; b<128; b++) distances_map[a][b] = 0; int moves = 0; // int im = 0; + + int N = isize(rogueviz::vdata); {progressbar pb(N, "move_restart"); for(int i=0; iget_growth()); - current_logistic.setRT(factor * graph_R, factor * graph_T); + current_logistic.setRT(factor * rogueviz::embeddings::cont_logistic.R, factor * rogueviz::embeddings::cont_logistic.T); saved_logistic = current_logistic; // for(int u=0; ubase); -#else - auto path1 = computePath(vdata[i].m->base); - vertices[i] = find_mycell_by_path(path1); -#endif - vdata[i].m->at = Id; - pb++; - } - preparegraph(); + + rogueviz::embeddings::enable_embedding(std::make_shared()); } bool iteration() { @@ -293,6 +286,7 @@ void embedder_loop(int max) { void save_embedding(const string s) { FILE *f = fopen(s.c_str(), "wt"); + int N = isize(rogueviz::vdata); for(int i=0; i ids; for(int i=0; i()); } } diff --git a/rogueviz/dhrg/groundtruth.cpp b/rogueviz/dhrg/groundtruth.cpp index 01a7e40e..2b982464 100644 --- a/rogueviz/dhrg/groundtruth.cpp +++ b/rogueviz/dhrg/groundtruth.cpp @@ -9,6 +9,8 @@ bool is(char *where, const char *what) { } void ground_truth_test(string s) { + throw hr_exception("this test is currently not implemented to work after the structural changes"); +#if 0 logistic cont; @@ -38,8 +40,6 @@ if(1) { origcoords(); build_disttable(); - cont.setRT(graph_R, graph_T); - report("gz", loglik_cont(cont)); fix_logistic_parameters(cont, loglik_cont, "lcont", 1e-3); report("grc", loglik_cont(cont)); @@ -51,7 +51,6 @@ if(1) { report("gcm", loglikopt_mono()); report("gcrt", loglik_logistic()); - cont.setRT(graph_R, graph_T); report("gcz", loglik_cont(cont)); fix_logistic_parameters(cont, loglik_cont, "lcont", 1e-3); report("gcrc", loglik_cont(cont)); @@ -65,7 +64,6 @@ if(1) { cellcoords(); build_disttable(); - cont.setRT(graph_R, graph_T); fix_logistic_parameters(cont, loglik_cont, "lcont", 1e-3); report("gerc", loglik_cont(cont)); @@ -81,7 +79,6 @@ if(1) { dhrg_init(); read_graph_full("data/sime-" + s); origcoords(); build_disttable(); - cont.setRT(graph_R, graph_T); report("ez", loglik_cont(cont)); fix_logistic_parameters(cont, loglik_cont, "lcont", 1e-3); report("erc", loglik_cont(cont)); @@ -93,7 +90,6 @@ if(1) { cellcoords(); build_disttable(); - cont.setRT(graph_R, graph_T); report("ecz", loglik_cont(cont)); fix_logistic_parameters(cont, loglik_cont, "lcont", 1e-3); report("ecrc", loglik_cont(cont)); @@ -110,12 +106,12 @@ if(1) { cellcoords(); build_disttable(); - cont.setRT(graph_R, graph_T); fix_logistic_parameters(cont, loglik_cont, "lcont", 1e-3); report("eerc", loglik_cont(cont)); print(hlog, "HDR;", separated(";", reps), ";TIME;N;GROWTH\n"); print(hlog, "RES'", separated(";", logliks), ";", int(tim), ";", N, ";", cgi.expansion->get_growth()); +#endif } } diff --git a/rogueviz/dhrg/loglik.cpp b/rogueviz/dhrg/loglik.cpp index b37ff34c..f7a8ea64 100644 --- a/rogueviz/dhrg/loglik.cpp +++ b/rogueviz/dhrg/loglik.cpp @@ -1,14 +1,7 @@ // log-likelihood computation -#include -#define USE_THREADS - namespace dhrg { -int threads = 32; - -ld llcont_approx_prec = 10000; - // tally edges of the given vertex at the given index int edgetally[MAXDIST]; @@ -26,6 +19,7 @@ void tallyedgesof(int i, int delta, mycell *mc) { void counttallies() { using namespace rogueviz; + int N = isize(rogueviz::vdata); { progressbar pb(N, "Tallying pairs"); @@ -53,127 +47,19 @@ void counttallies() { } void destroytallies() { + int N = isize(rogueviz::vdata); progressbar pb(N, "Destroying tallies"); for(int i=0; i void fix_logistic_parameters(logistic& l, const T& f, const char *name, ld eps) { - indenter_finish im("fix_logistic_parameters"); - ld cur = f(l); - println(hlog, hr::format("%s = %20.10" PLDF " (R=%10.5" PLDF " T=%" PLDF ")", name, cur, l.R, l.T)); - - for(ld step=1; step>eps; step /= 2) { - - while(true) { l.R += step; ld t = f(l); if(t <= cur) break; cur = t; } - l.R -= step; - - while(true) { l.R -= step; ld t = f(l); if(t <= cur) break; cur = t; } - l.R += step; - - while(true) { l.T += step; ld t = f(l); if(t <= cur) break; cur = t; } - l.T -= step; - - while(true) { l.T -= step; ld t = f(l); if(t <= cur) break; cur = t; } - l.T += step; - - println(hlog, hr::format("%s = %20.10" PLDF " (R=%10.5" PLDF " T=%10.5" PLDF ")", name, cur, l.R, l.T)); - fflush(stdout); - } - } +using rogueviz::embeddings::logistic; logistic current_logistic; logistic saved_logistic; -logistic cont_logistic; - -// --- continuous logistic loglikelihood -// -------------------------------------- - -vector vertexcoords; - -// compute vertexcoords from the original embedding data -void origcoords() { - indenter_finish im("origcoords"); - using namespace rogueviz; - vertexcoords.resize(N); - for(int i=0; ibase, currentmap->gamestart(), C0) * rogueviz::vdata[i].m->at * C0; - } - -// compute vertexcoords from vertices -void cellcoords() { - indenter_finish im("cellcoords"); - vertexcoords.resize(N); - for(int i=0; iascell()); // calc_relative_matrix(vertices[i]->ascell(), currentmap->gamestart(), C0) * C0; - if(isnan(vertexcoords[i][0])) println(hlog, "got NAN for i=", i, " in lev= ", vertices[i]->lev); - } - } - -// needs cellcoords/rvcoords/origcoords -void build_disttable() { - indenter_finish im("build_disttable"); - vector tab(N, N); - disttable0.clear(); - disttable1.clear(); - - using namespace rogueviz; - - for(int i=0; ii ^ p.second->j ^ i; - if(j -1e-10) break; - } - - return llh; - } // --- placement loglikelihood @@ -181,6 +67,7 @@ ld loglik_placement() { mycell *root = mroot; ld placement_loglik = 0; auto seg = getsegment(root,root,0); + int N = isize(rogueviz::vdata); for(int j=0; jqty[j]; if(!qj) continue; @@ -204,7 +91,7 @@ ld loglik_logistic(logistic& l = current_logistic) { ld loglikopt() { ld result = 0; - for(int u=0; u auto parallelize(long long N, T action) -> decltype(action(0,0 #endif } -vector> disttable_approx; - ld precise_hdist(hyperpoint vi, hyperpoint vj) { ld da = acosh(vi[2]); ld db = acosh(vj[2]); @@ -325,106 +211,4 @@ ld precise_hdist(hyperpoint vi, hyperpoint vj) { return acosh(v); } -void build_disttable_approx() { - indenter_finish im("build_disttable_approx"); - - array zero = {0, 0}; - - using namespace rogueviz; - - std::vector>> results(threads); - std::vector v; - for(int k=0; k tab(N, N); - auto p = k ? nullptr : new progressbar(N/threads, "build_disttable_approx"); - for(int i=k; ii ^ p.second->j ^ i; - if(j; - -int max_steps = 100000; - -void fast_loglik_cont(logistic& l, const logisticfun& f, const char *name, ld start, ld eps) { - - if(name) println(hlog, "fix_logistic_parameters"); - indenter_finish im(name); - ld cur = f(l); - if(name) println(hlog, hr::format("%s = %20.10" PLDF " (R=%10.5" PLDF " T=%" PLDF ")", name, cur, l.R, l.T)); - - map, double> memo; - auto ff = [&] () { - if(l.T < -5) exit(1); - if(memo.count(make_pair(l.R, l.T))) - return memo[make_pair(l.R, l.T)]; - return memo[make_pair(l.R, l.T)] = f(l); - }; - - int steps = 0; - - for(ld step=start; step>eps; step /= 2) { - - loop: - bool changed = false; - - while(true) { steps++; l.R += step; ld t = ff(); if(t <= cur || steps > max_steps) break; cur = t; changed = true; } - l.R -= step; - - while(true) { steps++; l.R -= step; ld t = ff(); if(t <= cur || steps > max_steps) break; cur = t; changed = true; } - l.R += step; - - while(true) { steps++; l.T += step; ld t = ff(); if(t <= cur || steps > max_steps) break; cur = t; changed = true; } - l.T -= step; - - while(true) { steps++; l.T -= step; ld t = ff(); if(t <= cur || l.T < 1e-3 || steps > max_steps) break; cur = t; changed = true; } - l.T += step; - - if(changed) goto loop; - - if(name) println(hlog, hr::format("%s = %20.10" PLDF " (R=%10.5" PLDF " T=%10.5" PLDF ")", name, cur, l.R, l.T)); - fflush(stdout); - } - } - } diff --git a/rogueviz/dhrg/visualize.cpp b/rogueviz/dhrg/visualize.cpp index 1a96f6df..b5739ac3 100644 --- a/rogueviz/dhrg/visualize.cpp +++ b/rogueviz/dhrg/visualize.cpp @@ -54,7 +54,7 @@ void show_likelihood() { dialog::add_action([] () { embedder_loop(1); ts_vertices = ts_rbase; - place_rogueviz_vertices(); + rogueviz::embeddings::reenable_embedding(); }); dialog::addBack(); @@ -83,6 +83,7 @@ void show_likelihood() { handlePanning(sym, uni); if(uni == '-' && held_id == -1) { + int N = isize(rogueviz::vdata); for(int i=0; ibase == mouseover) held_id = i; return; @@ -100,7 +101,7 @@ bool dhrg_animate(int sym, int uni) { if(ts_rbase > ts_vertices) { dhrg_init(); graph_from_rv(); ts_vertices = ts_rbase; - place_rogueviz_vertices(); + rogueviz::embeddings::reenable_embedding(); } pushScreen(show_likelihood); diff --git a/rogueviz/embeddings/embeddings.cpp b/rogueviz/embeddings/embeddings.cpp index d351b43e..ef425b92 100644 --- a/rogueviz/embeddings/embeddings.cpp +++ b/rogueviz/embeddings/embeddings.cpp @@ -1,28 +1,29 @@ #include "../rogueviz.h" +#include "embeddings.h" namespace rogueviz { -unique_ptr current_embedding; - namespace embeddings { +std::shared_ptr current; + vector > directed_edges; rogueviz::edgetype *any; -struct rv_embedding : public embedding { - hyperpoint as_hyperpoint(int id) override { - return currentmap->relative_matrix(vdata[id].m->base, currentmap->gamestart(), C0) * (vdata[id].m->at * C0); +struct rv_embedding : public tiled_embedding { + pair as_location(int id) override { + return { vdata[id].m->base, vdata[id].m->at * C0 }; } }; -void read_edgelist(string fname) { +void read_edgelist(const string& fname) { rogueviz::init(RV_GRAPH); rv_hook(hooks_clearmemory, 100, [] { directed_edges.clear(); - current_embedding = nullptr; + current = nullptr; }); any = rogueviz::add_edgetype("embedded edges"); @@ -54,12 +55,34 @@ void read_edgelist(string fname) { if(rogueviz::rv_quality >= 0) { for(auto& v: vdata) v.be(all[gmod(id++, isize(all))], Id); - current_embedding = std::make_unique (); + current = std::make_shared (); } } -int a = arg::add3("-edgelist", [] { arg::shift(); read_edgelist(arg::args()); }); +void reenable_embedding() { + if(rogueviz::rv_quality >= 0) + for(auto& v: vdata) { + auto p = current->as_location(v.id); + v.be(p.first, rgpushxto0(p.second)); + } + } + +void enable_embedding(std::shared_ptr pe) { + current = std::move(pe); + reenable_embedding(); + } + +void store_gamedata(struct hr::gamedata* gd) { gd->store(current); } + +int a = arg::add3("-edgelist", [] { arg::shift(); read_edgelist(arg::args()); }) + + addHook(hooks_gamedata, 230, store_gamedata); + } } + +#include "polar.cpp" +#include "loglik.cpp" +#include "routing.cpp" + diff --git a/rogueviz/embeddings/loglik.cpp b/rogueviz/embeddings/loglik.cpp new file mode 100644 index 00000000..e8f38e56 --- /dev/null +++ b/rogueviz/embeddings/loglik.cpp @@ -0,0 +1,222 @@ +namespace rogueviz { + +namespace embeddings { + +// log likelihood utilities +//-------------------------- + +// MLE of the binomial distribution (a successes, b failures) + +ld bestll(ld a, ld b) { + if(a == 0 || b == 0) return 0; + return a * log(a/(a+b)) + b * log(b/(a+b)); + } + +// a successes, ab total + +ld bestll2(ld a, ld ab) { return bestll(a, ab-a); } + +// --- continuous logistic loglikelihood +// -------------------------------------- + +vector disttable0, disttable1; + +using logisticfun = std::function; + +// needs cellcoords/rvcoords/origcoords +void build_disttable() { + indenter_finish im("build_disttable"); + int N = isize(rogueviz::vdata); + vector tab(N, N); + disttable0.clear(); + disttable1.clear(); + + using namespace rogueviz; + + for(int i=0; ii ^ p.second->j ^ i; + if(jdistance(i, j); + if(dist < 0) continue; + (tab[j] == i ? disttable1:disttable0).push_back(dist); + } + } + + sort(disttable0.begin(), disttable0.end()); + sort(disttable1.begin(), disttable1.end()); + } + +// needs build_disttable +ld loglik_cont(logistic& l = current_logistic) { + + ld llh = 1; + for(auto p: disttable1) llh += l.lyes(p); + for(auto p: disttable0) { + ld lp = l.lno(p); + llh += lp; + if(lp > -1e-10) break; + } + + return llh; + } + +using ll = long long; +vector> disttable_approx; + +ld llcont_approx_prec = 10000; + +int threads = 32; + +void build_disttable_approx() { + indenter_finish im("build_disttable_approx"); + + array zero = {0, 0}; + + using namespace rogueviz; + + std::vector>> results(threads); + std::vector v; + int N = isize(rogueviz::vdata); + for(int k=0; k tab(N, N); + auto p = k ? nullptr : new progressbar(N/threads, "build_disttable_approx"); + for(int i=k; ii ^ p.second->j ^ i; + if(jdistance(i, j); + if(dist < 0) continue; + int dista = dist * llcont_approx_prec; + if(isize(dt) < dista+1) + dt.resize(dista+1, zero); + dt[dista][(tab[j] == i) ? 1 : 0]++; + } + } + if(p) delete p; + }); + for(std::thread& t:v) t.join(); + + int mx = 0; + for(auto& r: results) mx = max(mx, isize(r)); + disttable_approx.clear(); + disttable_approx.resize(mx, zero); + + for(auto& r: results) + for(int i=0; ieps; step /= 2) { + + while(true) { l.R += step; ld t = f(l); if(t <= cur) break; cur = t; } + l.R -= step; + + while(true) { l.R -= step; ld t = f(l); if(t <= cur) break; cur = t; } + l.R += step; + + while(true) { l.T += step; ld t = f(l); if(t <= cur) break; cur = t; } + l.T -= step; + + while(true) { l.T -= step; ld t = f(l); if(t <= cur) break; cur = t; } + l.T += step; + + println(hlog, hr::format("%s = %20.10" PLDF " (R=%10.5" PLDF " T=%10.5" PLDF ")", name, cur, l.R, l.T)); + fflush(stdout); + } + } + +void fast_loglik_cont(logistic& l, const logisticfun& f, const char *name, ld start, ld eps) { + + if(name) println(hlog, "fix_logistic_parameters"); + indenter_finish im(name); + ld cur = f(l); + if(name) println(hlog, hr::format("%s = %20.10" PLDF " (R=%10.5" PLDF " T=%" PLDF ")", name, cur, l.R, l.T)); + + map, double> memo; + auto ff = [&] () { + if(l.T < -5) exit(1); + if(memo.count(make_pair(l.R, l.T))) + return memo[make_pair(l.R, l.T)]; + return memo[make_pair(l.R, l.T)] = f(l); + }; + + int steps = 0; + + for(ld step=start; step>eps; step /= 2) { + + loop: + bool changed = false; + + while(true) { steps++; l.R += step; ld t = ff(); if(t <= cur || steps > max_steps) break; cur = t; changed = true; } + l.R -= step; + + while(true) { steps++; l.R -= step; ld t = ff(); if(t <= cur || steps > max_steps) break; cur = t; changed = true; } + l.R += step; + + while(true) { steps++; l.T += step; ld t = ff(); if(t <= cur || steps > max_steps) break; cur = t; changed = true; } + l.T -= step; + + while(true) { steps++; l.T -= step; ld t = ff(); if(t <= cur || l.T < 1e-3 || steps > max_steps) break; cur = t; changed = true; } + l.T += step; + + if(changed) goto loop; + + if(name) println(hlog, hr::format("%s = %20.10" PLDF " (R=%10.5" PLDF " T=%10.5" PLDF ")", name, cur, l.R, l.T)); + fflush(stdout); + } + } + +logistic cont_logistic; + +int loglik_args() { + using namespace arg; + + if(argis("-loglik-approx")) { + build_disttable_approx(); + fast_loglik_cont(cont_logistic, loglik_cont_approx, "lcont", 1, 1e-6); + // return loglik_cont(); + } + else if(argis("-loglik-precise")) { + build_disttable(); + fast_loglik_cont(cont_logistic, loglik_cont, "lcont", 1, 1e-6); + // return loglik_cont(); + } + else return 1; + + return 0; + } + +auto alol = addHook(hooks_args, 50, loglik_args); + +} +} + diff --git a/rogueviz/embeddings/polar.cpp b/rogueviz/embeddings/polar.cpp index d69606cb..71d83f1b 100644 --- a/rogueviz/embeddings/polar.cpp +++ b/rogueviz/embeddings/polar.cpp @@ -1,66 +1,78 @@ -namespace dhrg { + +namespace rogueviz { + +namespace embeddings { + double graph_R, graph_alpha, graph_T; - vector > coords; - - rogueviz::edgetype *any; - - int N; - - void tst() {} - void read_graph(string fn) { + struct polar_point { + ld r, theta; + }; - any = rogueviz::add_edgetype("embedded edges"); - rogueviz::fname = fn; - fhstream f(fn + "-coordinates.txt", "rt"); - if(!f.f) { - printf("Missing file: %s-coordinates.txt\n", rogueviz::fname.c_str()); - exit(1); + struct polar_embedding : public untiled_embedding { + vector coords; + + hyperpoint as_hyperpoint(int id) override { + return spin(coords[id].theta) * xpush0(coords[id].r); } + + ld zero_distance(int id) { return coords[id].r; } + + ld distance(int i, int j) { + ld da = coords[i].r; + ld db = coords[j].r; + + ld phi = coords[i].theta - coords[j].theta; + + ld co = sinh(da) * sinh(db) * (1 - cos(phi)); + + ld v = cosh(da - db) + co; + if(v < 1) return 0; + + return acosh(v); + } + + }; + + /** read polar coordinates, in the format returned by the BFKL embdder. */ + + void read_polar(const string& fn) { + + fhstream f(fn, "rt"); + if(!f.f) return file_error(fn); + + int N; + printf("Reading coordinates...\n"); string ignore; if(!scan(f, ignore, ignore, ignore, ignore, N, graph_R, graph_alpha, graph_T)) { printf("Error: incorrect format of the first line\n"); exit(1); } - rogueviz::vdata.reserve(N); - while(true) { - string s = scan(f); - if(s == "D11.11") tst(); - if(s == "" || s == "#ROGUEVIZ_ENDOFDATA") break; - int id = rogueviz::getid(s); - rogueviz::vertexdata& vd(rogueviz::vdata[id]); - vd.name = s; - vd.cp = rogueviz::colorpair(rogueviz::dftcolor); - - double r, alpha; - if(!scan(f, r, alpha)) { printf("Error: incorrect format of r/alpha\n"); exit(1); } - coords.push_back(make_pair(r, alpha)); - - transmatrix h = spin(alpha * degree) * xpush(r); - vd.be(currentmap->gamestart(), h); + if(graph_R && graph_T) cont_logistic.setRT(graph_R, graph_T); + + if(N == 0) N = isize(vdata); + if(N != isize(vdata)) throw hr_exception("incorrect N"); + + auto pe = std::make_shared (); + pe->coords.resize(N); + + for(int i=0; i(f); + if(s == "" || s == "#ROGUEVIZ_ENDOFDATA") throw hr_exception("data failure"); + int id = rogueviz::labeler.at(s); + + double r, theta; + if(!scan(f, r, theta)) { printf("Error: incorrect format of r/alpha\n"); exit(1); } + pe->coords[id] = polar_point{.r = r, .theta = theta * degree}; } - fhstream g(fn + "-links.txt", "rt"); - if(!g.f) { - println(hlog, "Missing file: ", rogueviz::fname, "-links.txt"); - exit(1); - } - println(hlog, "Reading links..."); - int qlink = 0; - while(true) { - int i = rogueviz::readLabel(g), j = rogueviz::readLabel(g); - if(i == -1 || j == -1) break; - addedge(i, j, 1, any); - qlink++; - } + enable_embedding(std::move(pe)); } + + int a_polar = + arg::add3("-el-polar", [] { arg::shift(); read_polar(arg::args()); }) + + arg::add3("-el-bfkl", [] { arg::shift(); read_edgelist(arg::args() + "-links.txt"); read_polar(arg::args() + "-coordinates.txt"); }); - void unsnap() { - for(int i=0; igamestart(), h); - } - } } +} \ No newline at end of file diff --git a/rogueviz/embeddings/routing.cpp b/rogueviz/embeddings/routing.cpp index 7b745f22..a324540e 100644 --- a/rogueviz/embeddings/routing.cpp +++ b/rogueviz/embeddings/routing.cpp @@ -1,7 +1,9 @@ // $(VARIANT) -nogui -dhrg embedded-graphs/facebook_combined_result -contll -iterate 99 -contll -esave > $@ -namespace dhrg { +namespace rogueviz { + +namespace embeddings { struct pairdata { ld success, route_length; }; @@ -14,12 +16,8 @@ vector pairs; vector last_goal; vector next_stop; -int gr_N; - -using neighborhoodfun = std::function (int)>; - -void prepare_pairs(int N, const neighborhoodfun& nei) { - gr_N = N; +void prepare_pairs() { + int N = isize(rogueviz::vdata); pairs.resize(N); actual.resize(N); for(int i=0; i res; - for(auto ed: rogueviz::vdata[a].edges) { - int b = ed.second->i ^ ed.second->j ^ a; - res.push_back(b); - } - return res; - }); - } - void route_from(int src, int goal, const vector& distances_from_goal) { if(last_goal[src] == goal) return; if(src == goal) { @@ -70,8 +57,8 @@ void route_from(int src, int goal, const vector& distances_from_goal) { indent += 2; */ vector candidates; - for(auto ed: rogueviz::vdata[src].edges) { - int e = ed.second->i ^ ed.second->j ^ src; + for(auto& ed: rogueviz::vdata[src].edges) { + int e = ed.first; ld d = e == goal ? -1 : distances_from_goal[e]; if(d < bestd) bestd = d, candidates.clear(); if(d == bestd) candidates.push_back(e); @@ -92,14 +79,15 @@ void route_from(int src, int goal, const vector& distances_from_goal) { last_goal[src] = goal; } -void greedy_routing_to(iddata& d, int goal, const distfun& distance_function) { - vector distances_from_goal(gr_N); - for(int src=0; src distances_from_goal(N); + for(int src=0; srcdistance(goal, src); + for(int src=0; srcget_growth()); } +#endif int current_goal; iddata prepared; void prepare_goal(int goal) { - greedy_routing_to(prepared, current_goal = goal, [] (int i, int j) { return hdist(vertexcoords[i], vertexcoords[j]); }); + greedy_routing_to(prepared, current_goal = goal); } vector path(int src) { @@ -183,4 +174,18 @@ int get_actual(int src) { return actual[src][current_goal]; } +int routing_args() { + using namespace arg; + + if(argis("-routing")) { + // shift(); routing_test(args()); + } + else return 1; + + return 0; + } + +auto arou = addHook(hooks_args, 50, routing_args); + } +} \ No newline at end of file diff --git a/rogueviz/rogueviz.h b/rogueviz/rogueviz.h index 85e2101a..81a09284 100644 --- a/rogueviz/rogueviz.h +++ b/rogueviz/rogueviz.h @@ -84,14 +84,6 @@ namespace rogueviz { int readLabel(fhstream& f); - struct embedding { - virtual hyperpoint as_hyperpoint(int id) = 0; - virtual ld distance(int i, int j) { return hdist(as_hyperpoint(i), as_hyperpoint(j)); } - virtual ld zero_distance(int id) { return hdist0(as_hyperpoint(id)); } - }; - - extern unique_ptr current_embedding; - #if CAP_TEXTURE struct rvimage { basic_textureinfo tinf; diff --git a/rogueviz/sag/experiments.cpp b/rogueviz/sag/experiments.cpp index 069aefc2..e48115cb 100644 --- a/rogueviz/sag/experiments.cpp +++ b/rogueviz/sag/experiments.cpp @@ -8,7 +8,7 @@ namespace sag { int recover_from; -vector> results; +vector> results; ld bestcost; @@ -228,9 +228,9 @@ void output_stats() { println(hlog, "solution: ", sagid); int DN = isize(sagid); auto [mAP, MeanRank] = compute_mAP(); - dhrg::iddata routing_result; - if(!known_pairs) { known_pairs = true; dhrg::prepare_pairs(DN, [] (int i) { return edges_yes[i]; }); } - dhrg::greedy_routing(routing_result, [] (int i, int j) { return sagdist[sagid[i]][sagid[j]]; }); + embeddings::iddata routing_result; + if(!known_pairs) { known_pairs = true; embeddings::prepare_pairs(); } + embeddings::greedy_routing(routing_result); print(hlog, "CSV;", logid++, ";", isize(sagnode), ";", DN, ";", isize(edgeinfos), ";", lgsag_pre.R, ";", lgsag_pre.T, ";", lgsag.R, ";", lgsag.T, ";", cost, ";", mAP, ";", MeanRank, ";", routing_result.suc / routing_result.tot, ";", routing_result.routedist / routing_result.bestdist); if(lastmethod) print(hlog, ";", lastmethod); if(mul_used) print(hlog, ";", mul_used); diff --git a/rogueviz/sag/functions.cpp b/rogueviz/sag/functions.cpp index 48980c24..234ad611 100644 --- a/rogueviz/sag/functions.cpp +++ b/rogueviz/sag/functions.cpp @@ -3,7 +3,7 @@ #include "../rogueviz.h" -#include "../dhrg/dhrg.h" +#include "../embeddings/embeddings.h" #include "../statistics.cpp" namespace rogueviz { @@ -20,11 +20,13 @@ int method_count = 3; ld match_a = 1, match_b = 0; /* parameters for smLogistic */ -dhrg::logistic lgsag(1, 1), lgsag_pre(1, 1); +embeddings::logistic lgsag(1, 1), lgsag_pre(1, 1); + +ld yes_for(ld d) { return lgsag.yes(d); } vector loglik_tab_y, loglik_tab_n; -dhrg::logistic best; +embeddings::logistic best; debugflag debug_opt("sag_opt"); @@ -152,7 +154,7 @@ void optimize_sag_loglik_logistic() { if(debug_opt) println(hlog, "loglikelihood best = ", fts(loglik)); - auto logisticf = [&] (dhrg::logistic& l) { + auto logisticf = [&] (embeddings::logistic& l) { ld loglik = 0; for(int d=0; d