mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2026-03-16 18:19:43 +00:00
rogueviz:: moved some parts from dhrg to embeddings
This commit is contained in:
@@ -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<int> 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<embedding> 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; goal<dhrg::N; goal++) {
|
||||
dhrg::prepare_goal(goal);
|
||||
auto p = dhrg::path(me2);
|
||||
for(int goal=0; goal<isize(rogueviz::vdata); goal++) {
|
||||
prepare_goal(goal);
|
||||
auto p = path(me2);
|
||||
if(p.back() == goal) {
|
||||
println(hlog, "actual = ", dhrg::get_actual(me), " p = ", p, " ~ ", rogueviz::vdata[p.back()].name);
|
||||
}
|
||||
@@ -69,7 +58,10 @@ void greedy_test() {
|
||||
void launch_sea() {
|
||||
enable_canvas_backup(&ccolor::plain);
|
||||
start_game();
|
||||
dhrg::graphv("rogueviz/dhrg-data/sea-ppl");
|
||||
read_edgelist("rogueviz/dhrg-data/sea-ppl-links.txt");
|
||||
read_polar("rogueviz/dhrg-data/sea-ppl-coordinates.txt");
|
||||
dhrg_embedding = current;
|
||||
dhrg::graph_from_rv();
|
||||
resetview();
|
||||
}
|
||||
|
||||
@@ -192,7 +184,7 @@ void graph_visuals(presmode mode) {
|
||||
void swap_snap() {
|
||||
snapped = !snapped;
|
||||
if(snapped) { for(auto& v: rogueviz::vdata) v.be(v.m->base, Id); }
|
||||
if(!snapped) dhrg::unsnap();
|
||||
if(!snapped) enable_embedding(dhrg_embedding);
|
||||
}
|
||||
|
||||
void dhrg_hooks() {
|
||||
|
||||
@@ -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<N; i++) {
|
||||
@@ -383,7 +384,6 @@ void build(mycell *c, int lev, string s) {
|
||||
|
||||
void build_all(int d) {
|
||||
build(mroot, d, "");
|
||||
N = isize(vertices);
|
||||
counttallies();
|
||||
}
|
||||
|
||||
@@ -398,7 +398,6 @@ void load_test() {
|
||||
rogueviz::vdata.back().name = "PATH:" + s;
|
||||
}
|
||||
// build(mroot, 5, "");
|
||||
N = isize(vertices);
|
||||
counttallies();
|
||||
// add_to_set(vertices[0], -1, 0);
|
||||
}
|
||||
|
||||
@@ -16,13 +16,11 @@ namespace rogueviz { extern string fname; }
|
||||
#include "tests.cpp"
|
||||
#include "betweenness.cpp"
|
||||
#include "groundtruth.cpp"
|
||||
#include "routing.cpp"
|
||||
|
||||
namespace dhrg {
|
||||
|
||||
int M;
|
||||
vector<struct mycell*> vertices;
|
||||
vector<ld> 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; i<N; i++) vdata[i].be(vertices[i]->ascell(), Id);
|
||||
}
|
||||
|
||||
int destroy;
|
||||
|
||||
void clear() {
|
||||
coords.clear();
|
||||
// destroytallies();
|
||||
// todo: correct cleanup!
|
||||
for(int i=0; i<MAXDIST; i++) tally[i] = 0;
|
||||
@@ -90,35 +80,16 @@ int ts_coords;
|
||||
int ts_vertices;
|
||||
bool stored;
|
||||
|
||||
void graphv(string s) {
|
||||
dhrg_init(); read_graph(s);
|
||||
next_timestamp++;
|
||||
ts_rogueviz = next_timestamp;
|
||||
ts_rbase = next_timestamp;
|
||||
stored = true;
|
||||
}
|
||||
|
||||
int dhrgArgs() {
|
||||
using namespace arg;
|
||||
|
||||
if(argis("-dhrg")) {
|
||||
PHASE(3); shift(); dhrg_init(); read_graph_full(args());
|
||||
PHASE(3); dhrg_init(); graph_from_rv();
|
||||
next_timestamp++;
|
||||
ts_rogueviz = next_timestamp;
|
||||
ts_vertices = next_timestamp;
|
||||
}
|
||||
|
||||
else if(argis("-graph")) {
|
||||
PHASE(3); shift(); dhrg_init(); read_graph(args());
|
||||
next_timestamp++;
|
||||
ts_rogueviz = next_timestamp;
|
||||
// stored = true;
|
||||
}
|
||||
|
||||
else if(argis("-graphv")) {
|
||||
PHASE(3); shift(); graphv(args());
|
||||
}
|
||||
|
||||
else if(argis("-analyze_grid")) {
|
||||
PHASE(3); shift(); dhrg_init(); do_analyze_grid(argi());
|
||||
}
|
||||
@@ -131,36 +102,6 @@ int dhrgArgs() {
|
||||
PHASE(3); dhrg_init(); shift(); test_paths(argi());
|
||||
}
|
||||
|
||||
else if(argis("-contll")) {
|
||||
if(ts_rogueviz >= 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
|
||||
|
||||
@@ -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<ld> 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<array<ll, 2>> disttable_approx;
|
||||
|
||||
using logisticfun = std::function<ld(logistic&)>;
|
||||
|
||||
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<vector<int> (int)>;
|
||||
using distfun = std::function<ld(int a, int b)>;
|
||||
|
||||
void prepare_pairs(int N, const neighborhoodfun& nei);
|
||||
void greedy_routing(iddata& d, const distfun& distance_function);
|
||||
void clear();
|
||||
|
||||
void graph_from_rv();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -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; i<N; i++) {
|
||||
@@ -165,6 +168,7 @@ void preparegraph() {
|
||||
indenter_finish im("preparegraph");
|
||||
using namespace rogueviz;
|
||||
M = 0;
|
||||
int N = isize(rogueviz::vdata);
|
||||
vertices.resize(N);
|
||||
|
||||
if(1) {
|
||||
@@ -178,8 +182,6 @@ void preparegraph() {
|
||||
|
||||
memoryInfo();
|
||||
|
||||
cont_logistic.setRT(graph_R, graph_T);
|
||||
|
||||
counttallies();
|
||||
|
||||
memoryInfo();
|
||||
@@ -189,7 +191,7 @@ void preparegraph() {
|
||||
if(1) {
|
||||
indenter_finish im("optimizing parameters");
|
||||
ld factor = 1/log(cgi.expansion->get_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; u<MAXDIST; u++) iprintf("%d/%lld\n", edgetally[u], tally[u]);
|
||||
@@ -209,17 +211,28 @@ void preparegraph() {
|
||||
println(hlog, "Using distlimit = ", distlimit);
|
||||
}
|
||||
|
||||
void read_graph_full(const string& fname) {
|
||||
struct dhrg_embedding : public rogueviz::embeddings::tiled_embedding {
|
||||
|
||||
pair<cell*, hyperpoint> as_location(int id) override {
|
||||
return { vertices[id]->ascell(), C0 };
|
||||
}
|
||||
|
||||
ld distance(int i, int j) override {
|
||||
return quickdist(vertices[i], vertices[j]);
|
||||
}
|
||||
|
||||
ld zero_distance(int i) override {
|
||||
return vertices[i]->lev;
|
||||
}
|
||||
};
|
||||
|
||||
void graph_from_rv() {
|
||||
using namespace rogueviz;
|
||||
|
||||
memoryInfo();
|
||||
|
||||
if(true) {
|
||||
indenter_finish im("Read graph");
|
||||
|
||||
// N = isize(vdata);
|
||||
|
||||
read_graph(fname);
|
||||
int N = isize(rogueviz::vdata);
|
||||
vertices.resize(N);
|
||||
progressbar pb(N, "Translating to cells");
|
||||
|
||||
@@ -239,29 +252,9 @@ void read_graph_full(const string& fname) {
|
||||
}
|
||||
|
||||
recycle_compute_map();
|
||||
preparegraph();
|
||||
}
|
||||
|
||||
void graph_from_rv() {
|
||||
using namespace rogueviz;
|
||||
|
||||
memoryInfo();
|
||||
|
||||
vertices.resize(N);
|
||||
progressbar pb(N, "converting RogueViz to DHRG");
|
||||
|
||||
for(int i=0; i<N; i++) {
|
||||
#if BUILD_ON_HR
|
||||
vertices[i] = find_mycell(vdata[i].m->base);
|
||||
#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<dhrg_embedding>());
|
||||
}
|
||||
|
||||
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<N; i++) {
|
||||
string p = get_path(vertices[i]);
|
||||
if(p == "") p = "X";
|
||||
@@ -301,22 +295,17 @@ void save_embedding(const string s) {
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void load_embedded(const string s) {
|
||||
if(true) {
|
||||
read_graph(s);
|
||||
indenter_finish im("Read graph");
|
||||
}
|
||||
|
||||
string t = rogueviz::fname + "-dhrg.txt";
|
||||
void load_embedded(const string& s) {
|
||||
|
||||
if(true) {
|
||||
int N = isize(rogueviz::vdata);
|
||||
progressbar pb(N, "reading embedding");
|
||||
vertices.resize(N, NULL);
|
||||
|
||||
map<string, int> ids;
|
||||
for(int i=0; i<N; i++) ids[rogueviz::vdata[i].name] = i;
|
||||
|
||||
FILE *f = fopen(t.c_str(), "rt");
|
||||
FILE *f = fopen(s.c_str(), "rt");
|
||||
while(true) {
|
||||
char who[500], where[500];
|
||||
who[0] = 0;
|
||||
@@ -336,6 +325,7 @@ void load_embedded(const string s) {
|
||||
}
|
||||
}
|
||||
preparegraph();
|
||||
rogueviz::embeddings::enable_embedding(std::make_shared<dhrg_embedding>());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,14 +1,7 @@
|
||||
// log-likelihood computation
|
||||
|
||||
#include <thread>
|
||||
#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<N; i++) add_to_set(vertices[i], -1, 0), pb++;
|
||||
for(int i=0; i<MAXDIST; i++)
|
||||
tally[i] = edgetally[i] = 0;
|
||||
}
|
||||
|
||||
// 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); }
|
||||
|
||||
// various methods of loglikelihood computation
|
||||
|
||||
template<class T> 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<hyperpoint> vertexcoords;
|
||||
|
||||
// compute vertexcoords from the original embedding data
|
||||
void origcoords() {
|
||||
indenter_finish im("origcoords");
|
||||
using namespace rogueviz;
|
||||
vertexcoords.resize(N);
|
||||
for(int i=0; i<N; i++)
|
||||
vertexcoords[i] = spin(coords[i].second * degree) * xpush(coords[i].first) * C0;
|
||||
}
|
||||
|
||||
// compute vertexcoords from the RogueViz representation
|
||||
void rvcoords() {
|
||||
indenter_finish im("rvcoords");
|
||||
using namespace rogueviz;
|
||||
vertexcoords.resize(N);
|
||||
for(int i=0; i<N; i++)
|
||||
vertexcoords[i] = calc_relative_matrix(rogueviz::vdata[i].m->base, 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; i<N; i++) {
|
||||
vertexcoords[i] = celltopoint(vertices[i]->ascell()); // 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<int> tab(N, N);
|
||||
disttable0.clear();
|
||||
disttable1.clear();
|
||||
|
||||
using namespace rogueviz;
|
||||
|
||||
for(int i=0; i<N; i++) {
|
||||
for(auto p: vdata[i].edges) {
|
||||
int j = p.second->i ^ p.second->j ^ i;
|
||||
if(j<i) tab[j] = i;
|
||||
}
|
||||
for(int j=0; j<i; j++) {
|
||||
ld dist = hdist(vertexcoords[i], vertexcoords[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;
|
||||
}
|
||||
|
||||
// --- 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; j<BOXSIZE; j++) {
|
||||
int qj = seg->qty[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<MAXDIST; u++) result += bestll2(edgetally[u], tally[u]);
|
||||
for(int u=0; u<MAXDIST; u++) result += rogueviz::embeddings::bestll2(edgetally[u], tally[u]);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -225,7 +112,7 @@ ld loglikopt_mono() {
|
||||
pairs.push_back(p);
|
||||
}
|
||||
for(auto p: pairs)
|
||||
result += bestll2(p.first, p.second);
|
||||
result += rogueviz::embeddings::bestll2(p.first, p.second);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -257,6 +144,7 @@ ld loglik_chosen() {
|
||||
void writestats() {
|
||||
indenter_finish im("writestats");
|
||||
memoryInfo();
|
||||
int N = isize(rogueviz::vdata);
|
||||
println(hlog, "Vertices by distance (N = ", N, "):");
|
||||
mycell *root = mroot;
|
||||
for(int j=0; j<BOXSIZE; j++) {
|
||||
@@ -274,7 +162,7 @@ void writestats() {
|
||||
}
|
||||
|
||||
println(hlog, "log likelihood\n");
|
||||
ld loglik_chaos = bestll2(M, N*(N-1)/2);
|
||||
ld loglik_chaos = rogueviz::embeddings::bestll2(M, N*(N-1)/2);
|
||||
ld loglik_opt = loglikopt();
|
||||
ld loglik_mono = loglikopt_mono();
|
||||
ld loglik_rt = loglik_logistic();
|
||||
@@ -307,8 +195,6 @@ template<class T> auto parallelize(long long N, T action) -> decltype(action(0,0
|
||||
#endif
|
||||
}
|
||||
|
||||
vector<array<ll, 2>> 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<ll, 2> zero = {0, 0};
|
||||
|
||||
using namespace rogueviz;
|
||||
|
||||
std::vector<vector<array<ll, 2>>> results(threads);
|
||||
std::vector<std::thread> v;
|
||||
for(int k=0; k<threads; k++)
|
||||
v.emplace_back([&,k] () {
|
||||
auto& dt = results[k];
|
||||
vector<int> tab(N, N);
|
||||
auto p = k ? nullptr : new progressbar(N/threads, "build_disttable_approx");
|
||||
for(int i=k; i<N; i+=threads) {
|
||||
if(p) (*p)++;
|
||||
for(auto p: vdata[i].edges) {
|
||||
int j = p.second->i ^ p.second->j ^ i;
|
||||
if(j<i) tab[j] = i;
|
||||
}
|
||||
for(int j=0; j<i; j++) {
|
||||
ld dist = precise_hdist(vertexcoords[i], vertexcoords[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; i<isize(r); i++)
|
||||
for(int j=0; j<2; j++)
|
||||
disttable_approx[i][j] += r[i][j];
|
||||
}
|
||||
|
||||
ld loglik_cont_approx(logistic& l) {
|
||||
|
||||
ld llh = 0;
|
||||
int N = isize(disttable_approx);
|
||||
for(int i=0; i<N; i++) {
|
||||
if(disttable_approx[i][0])
|
||||
llh += l.lno((i+.5)/llcont_approx_prec) * disttable_approx[i][0];
|
||||
if(disttable_approx[i][1])
|
||||
llh += l.lyes((i+.5)/llcont_approx_prec) * disttable_approx[i][1];
|
||||
}
|
||||
return llh;
|
||||
}
|
||||
|
||||
using logisticfun = std::function<ld(logistic&)>;
|
||||
|
||||
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<pair<double, double>, 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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; i<N; i++) if(rogueviz::vdata[i].m->base == 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);
|
||||
|
||||
|
||||
@@ -1,28 +1,29 @@
|
||||
#include "../rogueviz.h"
|
||||
#include "embeddings.h"
|
||||
|
||||
namespace rogueviz {
|
||||
|
||||
unique_ptr<embedding> current_embedding;
|
||||
|
||||
namespace embeddings {
|
||||
|
||||
std::shared_ptr<embedding> current;
|
||||
|
||||
vector<vector<int> > 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<cell*, hyperpoint> 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<rv_embedding> ();
|
||||
current = std::make_shared<rv_embedding> ();
|
||||
}
|
||||
}
|
||||
|
||||
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<embedding> 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"
|
||||
|
||||
|
||||
222
rogueviz/embeddings/loglik.cpp
Normal file
222
rogueviz/embeddings/loglik.cpp
Normal file
@@ -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<ld> disttable0, disttable1;
|
||||
|
||||
using logisticfun = std::function<ld(logistic&)>;
|
||||
|
||||
// needs cellcoords/rvcoords/origcoords
|
||||
void build_disttable() {
|
||||
indenter_finish im("build_disttable");
|
||||
int N = isize(rogueviz::vdata);
|
||||
vector<int> tab(N, N);
|
||||
disttable0.clear();
|
||||
disttable1.clear();
|
||||
|
||||
using namespace rogueviz;
|
||||
|
||||
for(int i=0; i<N; i++) {
|
||||
for(auto p: vdata[i].edges) {
|
||||
int j = p.second->i ^ p.second->j ^ i;
|
||||
if(j<i) tab[j] = i;
|
||||
}
|
||||
for(int j=0; j<i; j++) {
|
||||
ld dist = current->distance(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<array<ll, 2>> disttable_approx;
|
||||
|
||||
ld llcont_approx_prec = 10000;
|
||||
|
||||
int threads = 32;
|
||||
|
||||
void build_disttable_approx() {
|
||||
indenter_finish im("build_disttable_approx");
|
||||
|
||||
array<ll, 2> zero = {0, 0};
|
||||
|
||||
using namespace rogueviz;
|
||||
|
||||
std::vector<vector<array<ll, 2>>> results(threads);
|
||||
std::vector<std::thread> v;
|
||||
int N = isize(rogueviz::vdata);
|
||||
for(int k=0; k<threads; k++)
|
||||
v.emplace_back([&,k] () {
|
||||
auto& dt = results[k];
|
||||
vector<int> tab(N, N);
|
||||
auto p = k ? nullptr : new progressbar(N/threads, "build_disttable_approx");
|
||||
for(int i=k; i<N; i+=threads) {
|
||||
if(p) (*p)++;
|
||||
for(auto p: vdata[i].edges) {
|
||||
int j = p.second->i ^ p.second->j ^ i;
|
||||
if(j<i) tab[j] = i;
|
||||
}
|
||||
for(int j=0; j<i; j++) {
|
||||
ld dist = current->distance(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; i<isize(r); i++)
|
||||
for(int j=0; j<2; j++)
|
||||
disttable_approx[i][j] += r[i][j];
|
||||
}
|
||||
|
||||
ld loglik_cont_approx(logistic& l) {
|
||||
|
||||
ld llh = 0;
|
||||
int N = isize(disttable_approx);
|
||||
for(int i=0; i<N; i++) {
|
||||
if(disttable_approx[i][0])
|
||||
llh += l.lno((i+.5)/llcont_approx_prec) * disttable_approx[i][0];
|
||||
if(disttable_approx[i][1])
|
||||
llh += l.lyes((i+.5)/llcont_approx_prec) * disttable_approx[i][1];
|
||||
}
|
||||
return llh;
|
||||
}
|
||||
|
||||
int max_steps = 100000;
|
||||
|
||||
void fix_logistic_parameters(logistic& l, const logisticfun& 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);
|
||||
}
|
||||
}
|
||||
|
||||
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<pair<double, double>, 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);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,66 +1,78 @@
|
||||
namespace dhrg {
|
||||
|
||||
namespace rogueviz {
|
||||
|
||||
namespace embeddings {
|
||||
|
||||
double graph_R, graph_alpha, graph_T;
|
||||
vector<pair<double, double> > 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<polar_point> 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<string>(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<polar_embedding> ();
|
||||
pe->coords.resize(N);
|
||||
|
||||
for(int i=0; i<N; i++) {
|
||||
string s = scan<string>(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; i<N; i++) {
|
||||
using rogueviz::vdata;
|
||||
transmatrix h = spin(coords[i].second * degree) * xpush(coords[i].first);
|
||||
vdata[i].be(currentmap->gamestart(), h);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<pairdata> pairs;
|
||||
vector<int> last_goal;
|
||||
vector<int> next_stop;
|
||||
|
||||
int gr_N;
|
||||
|
||||
using neighborhoodfun = std::function<vector<int> (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<N; i++) actual[i].resize(N, NOYET);
|
||||
@@ -35,8 +33,8 @@ void prepare_pairs(int N, const neighborhoodfun& nei) {
|
||||
visit(i, 0);
|
||||
for(int k=0; k<isize(bfsqueue); k++) {
|
||||
int a = bfsqueue[k];
|
||||
for(auto b: nei(a))
|
||||
visit(b, p[a] + 1);
|
||||
for(auto ed: rogueviz::vdata[a].edges)
|
||||
visit(ed.first, p[a] + 1);
|
||||
}
|
||||
}
|
||||
last_goal.clear();
|
||||
@@ -45,17 +43,6 @@ void prepare_pairs(int N, const neighborhoodfun& nei) {
|
||||
next_stop.resize(N, -1);
|
||||
}
|
||||
|
||||
void prepare_pairs() {
|
||||
prepare_pairs(N, [] (int a) {
|
||||
vector<int> 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<ld>& 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<ld>& distances_from_goal) {
|
||||
indent += 2; */
|
||||
|
||||
vector<int> 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<ld>& distances_from_goal) {
|
||||
last_goal[src] = goal;
|
||||
}
|
||||
|
||||
void greedy_routing_to(iddata& d, int goal, const distfun& distance_function) {
|
||||
vector<ld> distances_from_goal(gr_N);
|
||||
for(int src=0; src<gr_N; src++)
|
||||
distances_from_goal[src] = distance_function(goal, src);
|
||||
for(int src=0; src<gr_N; src++)
|
||||
void greedy_routing_to(iddata& d, int goal) {
|
||||
int N = isize(rogueviz::vdata);
|
||||
vector<ld> distances_from_goal(N);
|
||||
for(int src=0; src<N; src++)
|
||||
distances_from_goal[src] = current->distance(goal, src);
|
||||
for(int src=0; src<N; src++)
|
||||
route_from(src, goal, distances_from_goal);
|
||||
|
||||
for(int j=0; j<gr_N; j++) if(j != goal){
|
||||
for(int j=0; j<N; j++) if(j != goal){
|
||||
d.tot++;
|
||||
ld p = pairs[j].success;
|
||||
d.suc += p;
|
||||
@@ -108,10 +96,12 @@ void greedy_routing_to(iddata& d, int goal, const distfun& distance_function) {
|
||||
}
|
||||
}
|
||||
|
||||
void greedy_routing(iddata& d, const distfun& distance_function) {
|
||||
for(int goal=0; goal<gr_N; goal++) greedy_routing_to(d, goal, distance_function);
|
||||
void greedy_routing(iddata& d) {
|
||||
int N = isize(rogueviz::vdata);
|
||||
for(int goal=0; goal<N; goal++) greedy_routing_to(d, goal);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void routing_test(string s) {
|
||||
|
||||
iddata datas[6];
|
||||
@@ -163,11 +153,12 @@ void routing_test(string s) {
|
||||
println(hlog, "HDR;", separated(";", reps), ";N;GROWTH\n");
|
||||
println(hlog, "RES;", separated(";", values), ";", N, ";", cgi.expansion->get_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<int> 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);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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<embedding> current_embedding;
|
||||
|
||||
#if CAP_TEXTURE
|
||||
struct rvimage {
|
||||
basic_textureinfo tinf;
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace sag {
|
||||
|
||||
int recover_from;
|
||||
|
||||
vector<pair<dhrg::logistic, ld>> results;
|
||||
vector<pair<embeddings::logistic, ld>> 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);
|
||||
|
||||
@@ -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<ld> 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<max_sag_dist; d++) {
|
||||
int p = pedge[d], pq = indist[d];
|
||||
@@ -165,7 +167,7 @@ void optimize_sag_loglik_logistic() {
|
||||
if(debug_opt) println(hlog, "cost = ", cost, " logisticf = ", logisticf(lgsag), " R= ", lgsag.R, " T= ", lgsag.T);
|
||||
if(should_good && abs(cost + logisticf(lgsag)) > 0.1) throw hr_exception("computation error");
|
||||
|
||||
dhrg::fast_loglik_cont(lgsag, logisticf, nullptr, 1, 1e-5);
|
||||
embeddings::fast_loglik_cont(lgsag, logisticf, nullptr, 1, 1e-5);
|
||||
if(debug_opt) println(hlog, "loglikelihood logistic = ", logisticf(lgsag), " R= ", lgsag.R, " T= ", lgsag.T);
|
||||
|
||||
if(method == smLogistic) {
|
||||
|
||||
Reference in New Issue
Block a user