// 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]; void tallyedgesof(int i, int delta, mycell *mc) { using namespace rogueviz; for(auto p: vdata[i].edges) { int j = p.second->i ^ p.second->j ^ i; if(j==i) printf("LOOP!\n"); edgetally[quickdist(mc, vertices[j], 0)] += delta; } } // --- count all edge tallies void counttallies() { using namespace rogueviz; { progressbar pb(N, "Tallying pairs"); for(int i=0; ii ^ p.second->j ^ i; if(j < i) { edgetally[quickdist(vertices[i], vertices[j], 0)]++; pb++; } } } } void destroytallies() { 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, 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, format("%s = %20.10" PLDF " (R=%10.5" PLDF " T=%10.5" PLDF ")", name, cur, l.R, l.T)); fflush(stdout); } } 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"); int tab[N]; for(int i=0; ii ^ p.second->j ^ i; if(j -1e-10) break; } return llh; } // --- placement loglikelihood ld loglik_placement() { mycell *root = mroot; ld placement_loglik = 0; auto seg = getsegment(root,root,0); for(int j=0; jqty[j]; if(!qj) continue; placement_loglik += qj * (log(qj*1./N) - cgi.expansion->get_descendants(j).log_approx()); } return placement_loglik; } // --- logistic loglikelihood ld loglik_logistic(logistic& l = current_logistic) { ld result = 0; for(int u=0; u > pairs; ld result = 0; for(int u=0; u (edgetally[u], tally[u]); if(p.second == 0) continue; while(isize(pairs)) { auto pb = pairs.back(); if(p.first / p.second > pb.first / pb.second) p.first += pb.first, p.second += pb.second, pairs.pop_back(); else break; } pairs.push_back(p); } for(auto p: pairs) result += bestll2(p.first, p.second); return result; } // --- compute loglikelihood according to current method char lc_type = 'R'; ld loglik_chosen() { switch(lc_type) { case 'O': return loglikopt(); case 'R': return loglik_logistic(); case 'M': return loglikopt_mono(); case 'C': return loglikopt() + loglik_placement(); case 'D': return loglikopt_mono() + loglik_placement(); default: return loglikopt(); } } // 1e-3 (cont), 1e-6 (normal) // statistics void writestats() { indenter_finish im("writestats"); memoryInfo(); println(hlog, "Vertices by distance (N = ", N, "):"); mycell *root = mroot; for(int j=0; jqty[j]; if(!qj) continue; print(hlog, " ", j, ":", qj); } println(hlog); ld placement_loglik = loglik_placement(); for(int u=0; u auto parallelize(long long N, T action) -> decltype(action(0,0)) { #ifndef USE_THREADS return action(0,N); #else if(threads == 1) return action(0,N); std::vector v; typedef decltype(action(0,0)) Res; std::vector results(threads); for(int k=0; k> disttable_approx; ld precise_hdist(hyperpoint vi, hyperpoint vj) { ld da = acosh(vi[2]); ld db = acosh(vj[2]); ld phia = atan2(vi[0], vi[1]); ld phib = atan2(vj[0], vj[1]); ld co = sinh(da) * sinh(db) * (1 - cos(phia-phib)); // - (vi[0]*vj[0] + vi[1]*vj[1]); ld v = cosh(da - db) + co; if(v < 1) return 0; 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; ki ^ p.second->j ^ i; if(j; 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, 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 > 1000) break; cur = t; changed = true; } l.R -= step; while(true) { steps++; l.R -= step; ld t = ff(); if(t <= cur || steps > 1000) break; cur = t; changed = true; } l.R += step; while(true) { steps++; l.T += step; ld t = ff(); if(t <= cur || steps > 1000) 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 > 1000) break; cur = t; changed = true; } l.T += step; if(changed) goto loop; if(name) println(hlog, format("%s = %20.10" PLDF " (R=%10.5" PLDF " T=%10.5" PLDF ")", name, cur, l.R, l.T)); fflush(stdout); } } }