2020-03-29 11:41:56 +00:00
|
|
|
#include "rogueviz.h"
|
|
|
|
|
|
|
|
// SAG visualizer (e.g. Reddit roguelikes, GitHub languages)
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
|
|
|
|
// see: https://www.youtube.com/watch?v=mDG3_f8R2Ns (SAG boardgames)
|
|
|
|
// see: https://www.youtube.com/watch?v=WSyygk_3j9o (SAG roguelikes)
|
|
|
|
// see: https://www.youtube.com/watch?v=HWQkDkeEUeM (SAG programming languages)
|
|
|
|
|
|
|
|
namespace rogueviz {
|
|
|
|
|
|
|
|
namespace sag {
|
|
|
|
|
2021-03-30 22:23:01 +00:00
|
|
|
bool turn(int delta);
|
|
|
|
|
2020-03-29 11:41:56 +00:00
|
|
|
int sagpar = 0;
|
|
|
|
|
|
|
|
enum eSagmode { sagOff, sagHC, sagSA };
|
|
|
|
|
|
|
|
eSagmode sagmode; // 0 - off, 1 - hillclimbing, 2 - SA
|
|
|
|
|
|
|
|
const char *sagmodes[3] = {"off", "HC", "SA"};
|
|
|
|
|
|
|
|
ld temperature = -4;
|
|
|
|
const char *loadfname;
|
|
|
|
|
2022-08-20 14:43:26 +00:00
|
|
|
int vizsa_start;
|
|
|
|
int vizsa_len;
|
2020-03-29 11:41:56 +00:00
|
|
|
|
2022-08-20 14:43:26 +00:00
|
|
|
/** all the SAG cells */
|
|
|
|
vector<cell*> sagcells;
|
2020-03-29 11:41:56 +00:00
|
|
|
|
2022-08-20 14:43:26 +00:00
|
|
|
/** table of distances between SAG cells */
|
|
|
|
vector<vector<int>> sagdist;
|
|
|
|
|
|
|
|
/** what node is on sagcells[i] */
|
|
|
|
vector<int> sagnode;
|
|
|
|
|
|
|
|
/** node i is on sagcells[sagid[i]] */
|
|
|
|
vector<int> sagid;
|
|
|
|
|
|
|
|
/** sagcells[ids[c]]] == c */
|
|
|
|
map<cell*, int> ids;
|
|
|
|
|
|
|
|
/** if i in neighbors[j], sagcells[i] is a neighbor of sagcells[j] */
|
|
|
|
vector<vector<int>> neighbors;
|
2020-03-29 11:41:56 +00:00
|
|
|
|
2022-08-20 14:43:26 +00:00
|
|
|
void compute_dists() {
|
|
|
|
int N = isize(sagcells);
|
|
|
|
|
|
|
|
neighbors.clear();
|
|
|
|
neighbors.resize(N);
|
|
|
|
|
|
|
|
for(int i=0; i<N; i++)
|
|
|
|
for(cell *c1: adj_minefield_cells(sagcells[i]))
|
|
|
|
if(ids.count(c1)) neighbors[i].push_back(ids[c1]);
|
|
|
|
|
|
|
|
sagdist.clear();
|
|
|
|
sagdist.resize(N);
|
|
|
|
for(int i=0; i<N; i++) {
|
|
|
|
auto &sdi = sagdist[i];
|
|
|
|
sdi.resize(N, N);
|
|
|
|
vector<int> q;
|
|
|
|
auto visit = [&] (int j, int dist) { if(sdi[j] < N) return; sdi[j] = dist; q.push_back(j); };
|
|
|
|
visit(i, 0);
|
|
|
|
for(int j=0; j<isize(q); j++) for(int k: neighbors[q[j]]) visit(k, sdi[q[j]]+1);
|
2020-03-29 11:41:56 +00:00
|
|
|
}
|
|
|
|
}
|
2022-08-20 14:43:26 +00:00
|
|
|
|
|
|
|
bool legacy;
|
|
|
|
|
|
|
|
/* legacy method */
|
|
|
|
void init_snake(int n) {
|
|
|
|
sagcells.clear();
|
|
|
|
ids.clear();
|
|
|
|
|
|
|
|
auto enlist = [&] (cellwalker cw) {
|
|
|
|
ids[cw.at] = isize(sagcells);
|
|
|
|
sagcells.push_back(cw.at);
|
|
|
|
};
|
|
|
|
|
|
|
|
cellwalker cw = cwt;
|
|
|
|
enlist(cw);
|
|
|
|
cw += wstep;
|
|
|
|
enlist(cw);
|
|
|
|
for(int i=2; i<n; i++) {
|
2020-03-29 11:41:56 +00:00
|
|
|
cw += wstep;
|
2022-08-20 14:43:26 +00:00
|
|
|
while(ids.count(cw.at)) {
|
|
|
|
cw = cw + wstep + 1 + wstep;
|
2020-03-29 11:41:56 +00:00
|
|
|
}
|
2022-08-20 14:43:26 +00:00
|
|
|
enlist(cw); cw += 1;
|
2020-03-29 11:41:56 +00:00
|
|
|
}
|
|
|
|
}
|
2022-08-20 14:43:26 +00:00
|
|
|
|
|
|
|
void init_sag_cells() {
|
|
|
|
sagcells = currentmap->allcells();
|
|
|
|
int N = isize(sagcells);
|
|
|
|
|
|
|
|
ids.clear();
|
|
|
|
for(int i=0; i<N; i++) ids[sagcells[i]] = i;
|
|
|
|
}
|
|
|
|
|
2021-06-25 11:49:55 +00:00
|
|
|
ld hub_penalty;
|
|
|
|
string hub_filename;
|
|
|
|
vector<int> hubval;
|
|
|
|
|
2020-03-29 11:41:56 +00:00
|
|
|
double costat(int vid, int sid) {
|
|
|
|
if(vid < 0) return 0;
|
|
|
|
double cost = 0;
|
|
|
|
vertexdata& vd = vdata[vid];
|
|
|
|
for(int j=0; j<isize(vd.edges); j++) {
|
|
|
|
edgeinfo *ei = vd.edges[j].second;
|
|
|
|
int t2 = vd.edges[j].first;
|
2022-08-20 14:43:26 +00:00
|
|
|
if(sagid[t2] != -1) cost += sagdist[sid][sagid[t2]] * ei->weight2;
|
2020-03-29 11:41:56 +00:00
|
|
|
}
|
2021-06-25 11:49:55 +00:00
|
|
|
|
|
|
|
if(!hubval.empty()) {
|
2022-08-20 14:43:26 +00:00
|
|
|
for(auto sid2: neighbors[sid]) {
|
|
|
|
int vid2 = sagnode[sid2];
|
|
|
|
if(vid2 >= 0 && (hubval[vid] & hubval[vid]) == 0)
|
|
|
|
cost += hub_penalty;
|
2021-06-25 11:49:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-29 11:41:56 +00:00
|
|
|
return cost;
|
|
|
|
}
|
|
|
|
|
|
|
|
// std::mt19937 los;
|
|
|
|
|
|
|
|
bool infullsa;
|
|
|
|
|
|
|
|
double cost;
|
|
|
|
|
|
|
|
vector<double> chgs;
|
|
|
|
|
|
|
|
edgetype *sag_edge;
|
|
|
|
|
|
|
|
void forgetedges(int id) {
|
|
|
|
for(int i=0; i<isize(vdata[id].edges); i++)
|
|
|
|
vdata[id].edges[i].second->orig = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool chance(double p) {
|
|
|
|
p *= double(hrngen.max()) + 1;
|
|
|
|
auto l = hrngen();
|
|
|
|
auto pv = (decltype(l)) p;
|
|
|
|
if(l < pv) return true;
|
|
|
|
if(l == pv) return chance(p-pv);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void saiter() {
|
2022-08-20 14:43:26 +00:00
|
|
|
int DN = isize(sagid);
|
|
|
|
int t1 = hrand(DN);
|
|
|
|
int sid1 = sagid[t1];
|
2020-03-29 11:41:56 +00:00
|
|
|
|
|
|
|
int sid2;
|
|
|
|
|
2022-08-20 14:43:26 +00:00
|
|
|
int s = hrand(4)+1;
|
2020-03-29 11:41:56 +00:00
|
|
|
|
2022-08-20 14:43:26 +00:00
|
|
|
if(s == 4) sid2 = hrand(isize(sagcells));
|
2020-03-29 11:41:56 +00:00
|
|
|
else {
|
2022-08-20 14:43:26 +00:00
|
|
|
sid2 = sid1;
|
|
|
|
for(int ii=0; ii<s; ii++) sid2 = hrand_elt(neighbors[sid2]);
|
2020-03-29 11:41:56 +00:00
|
|
|
}
|
2022-08-20 14:43:26 +00:00
|
|
|
int t2 = sagnode[sid2];
|
2020-03-29 11:41:56 +00:00
|
|
|
|
2022-08-20 14:43:26 +00:00
|
|
|
sagnode[sid1] = -1; sagid[t1] = -1;
|
|
|
|
sagnode[sid2] = -1; if(t2 >= 0) sagid[t2] = -1;
|
2020-03-29 11:41:56 +00:00
|
|
|
|
|
|
|
double change =
|
|
|
|
costat(t1,sid2) + costat(t2,sid1) - costat(t1,sid1) - costat(t2,sid2);
|
|
|
|
|
2022-08-20 14:43:26 +00:00
|
|
|
sagnode[sid1] = t1; sagid[t1] = sid1;
|
|
|
|
sagnode[sid2] = t2; if(t2 >= 0) sagid[t2] = sid2;
|
|
|
|
|
2020-03-29 11:41:56 +00:00
|
|
|
if(change > 0 && (sagmode == sagHC || !chance(exp(-change * exp(-temperature))))) return;
|
|
|
|
|
2022-08-20 14:43:26 +00:00
|
|
|
sagnode[sid1] = t2; sagnode[sid2] = t1;
|
|
|
|
sagid[t1] = sid2; if(t2 >= 0) sagid[t2] = sid1;
|
2020-03-29 11:41:56 +00:00
|
|
|
cost += 2*change;
|
|
|
|
}
|
|
|
|
|
2022-08-20 14:43:26 +00:00
|
|
|
void create_sagnode() {
|
|
|
|
sagnode.clear();
|
|
|
|
sagnode.resize(isize(sagcells), -1);
|
|
|
|
int DN = isize(sagid);
|
|
|
|
for(int i=0; i<DN; i++)
|
|
|
|
sagnode[sagid[i]] = i;
|
|
|
|
cost = 0;
|
|
|
|
for(int i=0; i<DN; i++)
|
|
|
|
cost += costat(i, sagid[i]);
|
2020-03-29 11:41:56 +00:00
|
|
|
}
|
|
|
|
|
2022-08-20 14:43:26 +00:00
|
|
|
void reassign() {
|
|
|
|
int DN = isize(sagid);
|
|
|
|
for(int i=0; i<DN; i++) {
|
|
|
|
vdata[i].m->base = sagcells[sag::sagid[i]];
|
|
|
|
forgetedges(i);
|
|
|
|
}
|
|
|
|
shmup::fixStorage();
|
|
|
|
}
|
|
|
|
|
|
|
|
void load_sag_solution(const string& fname) {
|
2020-03-29 11:41:56 +00:00
|
|
|
printf("Loading the sag from: %s\n", fname.c_str());
|
|
|
|
FILE *sf = fopen(fname.c_str(), "rt");
|
|
|
|
if(!sf) { printf("Failed to open file.\n"); exit(1); }
|
2022-08-20 14:43:26 +00:00
|
|
|
int SN = isize(sagcells);
|
2020-03-29 11:41:56 +00:00
|
|
|
if(sf) while(true) {
|
|
|
|
string lab;
|
|
|
|
while(true) {
|
|
|
|
int c = fgetc(sf);
|
|
|
|
if(c == EOF) goto afterload;
|
|
|
|
else if(c == ',' || c == ';') break;
|
2021-06-25 12:00:01 +00:00
|
|
|
else if(rv_ignore(c)) ;
|
2020-03-29 11:41:56 +00:00
|
|
|
else lab += c;
|
|
|
|
}
|
|
|
|
int sid = -1;
|
|
|
|
int err = fscanf(sf, "%d", &sid);
|
2022-08-20 14:43:26 +00:00
|
|
|
if(sid < 0 || sid >= SN || err < 1) sid = -1;
|
2020-03-29 11:41:56 +00:00
|
|
|
if(!labeler.count(lab)) {
|
|
|
|
printf("unknown vertex: %s\n", lab.c_str());
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
int id = getid(lab);
|
2022-08-20 14:43:26 +00:00
|
|
|
sagid[id] = sid;
|
2020-03-29 11:41:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
afterload:
|
|
|
|
if(sf) fclose(sf);
|
|
|
|
|
2022-08-20 14:43:26 +00:00
|
|
|
create_sagnode();
|
|
|
|
reassign();
|
2020-03-29 11:41:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
vector<edgeinfo> sagedges;
|
|
|
|
|
|
|
|
int ipturn = 100;
|
|
|
|
int numiter = 0;
|
|
|
|
|
|
|
|
int hightemp = 10;
|
|
|
|
int lowtemp = -15;
|
|
|
|
|
|
|
|
void dofullsa(int satime) {
|
|
|
|
sagmode = sagSA;
|
|
|
|
int t1 = SDL_GetTicks();
|
|
|
|
|
|
|
|
while(true) {
|
|
|
|
int t2 = SDL_GetTicks();
|
|
|
|
double d = (t2-t1) / (1000. * satime);
|
|
|
|
if(d > 1) break;
|
|
|
|
temperature = hightemp - (d*(hightemp-lowtemp));
|
|
|
|
chgs.clear();
|
|
|
|
for(int i=0; i<50000; i++) {
|
|
|
|
numiter++;
|
|
|
|
sag::saiter();
|
|
|
|
}
|
2022-08-20 14:43:26 +00:00
|
|
|
|
|
|
|
print(hlog, format("it %8d temp %6.4f [1/e at %13.6f] cost = %f ",
|
2020-03-29 11:41:56 +00:00
|
|
|
numiter, double(sag::temperature), (double) exp(sag::temperature),
|
2022-08-20 14:43:26 +00:00
|
|
|
double(sag::cost)));
|
2020-03-29 11:41:56 +00:00
|
|
|
|
|
|
|
sort(chgs.begin(), chgs.end());
|
|
|
|
int cc = chgs.size() - 1;
|
2022-08-20 14:43:26 +00:00
|
|
|
println(hlog, format("%9.4f .. %9.4f .. %9.4f .. %9.4f .. %9.4f",
|
|
|
|
double(chgs[0]), double(chgs[cc/4]), double(chgs[cc/2]), double(chgs[cc*3/4]), double(chgs[cc])));
|
2020-03-29 11:41:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
temperature = -5;
|
|
|
|
sagmode = sagOff;
|
2022-08-20 14:43:26 +00:00
|
|
|
reassign();
|
2020-03-29 11:41:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void iterate() {
|
|
|
|
if(!sagmode) return;
|
|
|
|
int t1 = SDL_GetTicks();
|
|
|
|
for(int i=0; i<ipturn; i++) {
|
|
|
|
numiter++;
|
|
|
|
sag::saiter();
|
|
|
|
}
|
|
|
|
int t2 = SDL_GetTicks();
|
|
|
|
int t = t2 - t1;
|
|
|
|
if(t < 50) ipturn *= 2;
|
|
|
|
else if(t > 200) ipturn /= 2;
|
|
|
|
else ipturn = ipturn * 100 / t;
|
2022-08-20 14:43:26 +00:00
|
|
|
print(hlog, format("it %8d temp %6.4f [2:%8.6f,10:%8.6f,50:%8.6f] cost = %f\n",
|
2020-03-29 11:41:56 +00:00
|
|
|
numiter, double(sag::temperature),
|
|
|
|
(double) exp(-2 * exp(-sag::temperature)),
|
|
|
|
(double) exp(-10 * exp(-sag::temperature)),
|
|
|
|
(double) exp(-50 * exp(-sag::temperature)),
|
|
|
|
(double) sag::cost));
|
2022-08-20 14:43:26 +00:00
|
|
|
|
|
|
|
reassign();
|
2020-03-29 11:41:56 +00:00
|
|
|
}
|
|
|
|
|
2022-08-20 14:43:26 +00:00
|
|
|
void save_sag_solution(const string& fname) {
|
2020-03-29 11:41:56 +00:00
|
|
|
FILE *f = fopen(fname.c_str(), "wt");
|
2022-08-20 14:43:26 +00:00
|
|
|
for(int i=0; i<isize(sagid); i++)
|
|
|
|
fprintf(f, "%s;%d\n", vdata[i].name.c_str(), sagid[i]);
|
2020-03-29 11:41:56 +00:00
|
|
|
fclose(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
void loglik() {
|
|
|
|
int indist[30], pedge[30];
|
|
|
|
for(int d=0; d<30; d++) indist[d] = 0, pedge[d] = 0;
|
|
|
|
|
2022-08-20 14:43:26 +00:00
|
|
|
int N = isize(sagid);
|
2020-03-29 11:41:56 +00:00
|
|
|
for(int i=0; i<N; i++)
|
|
|
|
for(int j=0; j<i; j++)
|
2022-08-20 14:43:26 +00:00
|
|
|
indist[sagdist[sagid[i]][sagid[j]]]++;
|
2020-03-29 11:41:56 +00:00
|
|
|
|
|
|
|
for(int i=0; i<isize(sagedges); i++) {
|
|
|
|
edgeinfo& ei = sagedges[i];
|
2022-08-20 14:43:26 +00:00
|
|
|
if(ei.i != ei.j)
|
2020-03-29 11:41:56 +00:00
|
|
|
if(ei.weight >= sag_edge->visible_from)
|
2022-08-20 14:43:26 +00:00
|
|
|
pedge[sagdist[sagid[ei.i]][sagid[ei.j]]]++;
|
2020-03-29 11:41:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for(int d=0; d<30; d++)
|
|
|
|
if(indist[d])
|
|
|
|
printf("%2d: %7d/%7d %7.3lf\n",
|
|
|
|
d, pedge[d], indist[d], double(pedge[d] * 100. / indist[d]));
|
|
|
|
|
|
|
|
ld loglik = 0;
|
|
|
|
for(int d=0; d<30; d++) {
|
|
|
|
int p = pedge[d], pq = indist[d];
|
|
|
|
int q = pq - p;
|
|
|
|
if(p && q)
|
|
|
|
loglik += p * log(p) + q * log(q) - pq * log(pq);
|
|
|
|
}
|
|
|
|
|
|
|
|
println(hlog, "loglikelihood = ", fts(loglik));
|
|
|
|
}
|
2021-06-25 11:49:55 +00:00
|
|
|
|
|
|
|
void read_hubs(const string& fname) {
|
|
|
|
hubval.resize(isize(vdata), -1);
|
|
|
|
fhstream f(fname, "rt");
|
|
|
|
if(!f.f) { printf("Failed to open hub file: %s\n", fname.c_str()); exit(1); }
|
|
|
|
println(hlog, "loading hubs: ", fname);
|
|
|
|
while(!feof(f.f)) {
|
|
|
|
string l1, l2;
|
|
|
|
while(true) {
|
|
|
|
int c = fgetc(f.f);
|
2021-06-25 13:14:22 +00:00
|
|
|
if(c == EOF) return;
|
2021-06-25 11:49:55 +00:00
|
|
|
else if(c == ';') break;
|
2021-06-25 12:00:01 +00:00
|
|
|
else if(rv_ignore(c)) ;
|
2021-06-25 11:49:55 +00:00
|
|
|
else l1 += c;
|
|
|
|
}
|
|
|
|
while(true) {
|
|
|
|
int c = fgetc(f.f);
|
2021-06-25 13:14:22 +00:00
|
|
|
if(c == EOF) return;
|
|
|
|
else if(c == ';') return;
|
2021-06-25 12:00:01 +00:00
|
|
|
else if(rv_ignore(c)) break;
|
2021-06-25 11:49:55 +00:00
|
|
|
else l2 += c;
|
|
|
|
}
|
|
|
|
if(!id_known(l1)) {
|
|
|
|
printf("label unknown: %s\n", l1.c_str());
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
hubval[getid(l1)] = atoi(l2.c_str());
|
|
|
|
}
|
|
|
|
}
|
2020-03-29 11:41:56 +00:00
|
|
|
|
|
|
|
void readsag(const char *fname) {
|
|
|
|
maxweight = 0;
|
|
|
|
sag_edge = add_edgetype("SAG edge");
|
|
|
|
fhstream f(fname, "rt");
|
2022-08-20 14:43:26 +00:00
|
|
|
if(!f.f) {
|
|
|
|
printf("Failed to open SAG file: %s\n", fname);
|
|
|
|
throw "failed to open SAG file";
|
|
|
|
}
|
2020-03-29 11:41:56 +00:00
|
|
|
while(!feof(f.f)) {
|
|
|
|
string l1, l2;
|
|
|
|
while(true) {
|
|
|
|
int c = fgetc(f.f);
|
|
|
|
if(c == EOF) return;
|
|
|
|
else if(c == ';') break;
|
2021-06-25 12:00:01 +00:00
|
|
|
else if(rv_ignore(c)) ;
|
2020-03-29 11:41:56 +00:00
|
|
|
else l1 += c;
|
|
|
|
}
|
|
|
|
while(true) {
|
|
|
|
int c = fgetc(f.f);
|
|
|
|
if(c == EOF) return;
|
|
|
|
else if(c == ';') break;
|
2021-06-25 12:00:01 +00:00
|
|
|
else if(rv_ignore(c)) ;
|
2020-03-29 11:41:56 +00:00
|
|
|
else l2 += c;
|
|
|
|
}
|
|
|
|
ld wei;
|
|
|
|
if(!scan(f, wei)) continue;
|
|
|
|
edgeinfo ei(sag_edge);
|
|
|
|
ei.i = getid(l1);
|
|
|
|
ei.j = getid(l2);
|
|
|
|
ei.weight = wei;
|
|
|
|
sagedges.push_back(ei);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ld edgepower=1, edgemul=1;
|
|
|
|
|
|
|
|
void read(string fn) {
|
|
|
|
fname = fn;
|
2021-03-30 23:10:45 +00:00
|
|
|
init(RV_GRAPH | RV_WHICHWEIGHT | RV_AUTO_MAXWEIGHT | RV_HAVE_WEIGHT);
|
2021-03-30 22:23:01 +00:00
|
|
|
|
|
|
|
rv_hook(rogueviz::hooks_close, 100, [] { sag::sagedges.clear(); });
|
|
|
|
rv_hook(shmup::hooks_turn, 100, turn);
|
|
|
|
rv_hook(rogueviz::hooks_rvmenu, 100, [] {
|
|
|
|
dialog::addSelItem(XLAT("temperature"), fts(sag::temperature), 't');
|
|
|
|
dialog::add_action([] {
|
|
|
|
dialog::editNumber(sag::temperature, sag::lowtemp, sag::hightemp, 1, 0, XLAT("temperature"), "");
|
|
|
|
});
|
|
|
|
dialog::addSelItem(XLAT("SAG mode"), sag::sagmodes[sag::sagmode], 'm');
|
|
|
|
dialog::add_action([] { sag::sagmode = sag::eSagmode( (1+sag::sagmode) % 3 ); });
|
|
|
|
});
|
|
|
|
|
2020-03-29 13:14:23 +00:00
|
|
|
weight_label = "min weight";
|
2020-03-29 11:41:56 +00:00
|
|
|
temperature = 0; sagmode = sagOff;
|
|
|
|
readsag(fname.c_str());
|
2021-06-25 11:49:55 +00:00
|
|
|
if(hub_filename != "")
|
|
|
|
read_hubs(hub_filename);
|
2020-03-29 11:41:56 +00:00
|
|
|
|
2022-08-20 14:43:26 +00:00
|
|
|
int DN = isize(vdata);
|
2020-03-29 11:41:56 +00:00
|
|
|
|
2022-08-20 14:43:26 +00:00
|
|
|
for(int i=0; i<DN; i++) vdata[i].data = 0;
|
2020-03-29 11:41:56 +00:00
|
|
|
for(int i=0; i<isize(sagedges); i++) {
|
|
|
|
edgeinfo& ei = sagedges[i];
|
|
|
|
|
|
|
|
ei.weight2 = pow((double) ei.weight, (double) edgepower) * edgemul;
|
|
|
|
|
|
|
|
addedge0(ei.i, ei.j, &ei);
|
|
|
|
}
|
|
|
|
|
2022-08-20 14:43:26 +00:00
|
|
|
if(legacy)
|
|
|
|
init_snake(2 * DN);
|
|
|
|
else
|
|
|
|
init_sag_cells();
|
|
|
|
|
|
|
|
compute_dists();
|
|
|
|
|
|
|
|
int SN = isize(sagcells);
|
|
|
|
if(SN < DN) {
|
|
|
|
println(hlog, "SN = ", SN, " DN = ", DN);
|
|
|
|
throw hr_exception("not enough cells for SAG");
|
2020-03-29 11:41:56 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
2022-08-20 14:43:26 +00:00
|
|
|
sagid.resize(DN);
|
|
|
|
for(int i=0; i<DN; i++) sagid[i] = i;
|
|
|
|
create_sagnode();
|
2020-03-29 11:41:56 +00:00
|
|
|
|
2022-08-20 14:43:26 +00:00
|
|
|
for(int i=0; i<DN; i++) {
|
2020-03-29 11:41:56 +00:00
|
|
|
int ii = i;
|
|
|
|
vertexdata& vd = vdata[ii];
|
|
|
|
vd.cp = colorpair(dftcolor);
|
2022-08-20 14:43:26 +00:00
|
|
|
createViz(ii, sagcells[sagid[i]], Id);
|
2020-03-29 11:41:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
storeall();
|
|
|
|
}
|
|
|
|
|
|
|
|
int readArgs() {
|
|
|
|
#if CAP_COMMANDLINE
|
|
|
|
using namespace arg;
|
|
|
|
|
|
|
|
if(0) ;
|
|
|
|
|
|
|
|
else if(argis("-sagmin")) {
|
|
|
|
shift_arg_formula(default_edgetype.visible_from);
|
|
|
|
default_edgetype.visible_from_hi = default_edgetype.visible_from;
|
|
|
|
default_edgetype.visible_from_help = default_edgetype.visible_from;
|
|
|
|
}
|
|
|
|
else if(argis("-sagminhi")) {
|
|
|
|
shift_arg_formula(default_edgetype.visible_from_hi);
|
|
|
|
}
|
|
|
|
else if(argis("-sagminhelp")) {
|
|
|
|
shift_arg_formula(default_edgetype.visible_from_help);
|
|
|
|
}
|
|
|
|
|
|
|
|
// (1) configure edge weights
|
2022-08-20 14:43:26 +00:00
|
|
|
else if(argis("-sag-edgepower")) {
|
2020-03-29 11:41:56 +00:00
|
|
|
shift_arg_formula(sag::edgepower);
|
|
|
|
shift_arg_formula(sag::edgemul);
|
|
|
|
}
|
|
|
|
// (1) configure temperature (high, low)
|
|
|
|
else if(argis("-sagtemp")) {
|
|
|
|
shift(); sag::hightemp = argi();
|
|
|
|
shift(); sag::lowtemp = argi();
|
|
|
|
}
|
|
|
|
// (2) read the edge data
|
|
|
|
else if(argis("-sagpar")) {
|
|
|
|
PHASE(3);
|
|
|
|
shift();
|
|
|
|
sag::sagpar = argi();
|
|
|
|
}
|
|
|
|
else if(argis("-sag")) {
|
|
|
|
PHASE(3);
|
|
|
|
shift(); sag::read(args());
|
|
|
|
}
|
2021-06-25 11:49:55 +00:00
|
|
|
else if(argis("-saghubs")) {
|
|
|
|
println(hlog, "HUBS");
|
|
|
|
PHASE(3);
|
|
|
|
shift_arg_formula(sag::hub_penalty);
|
|
|
|
shift(); hub_filename = args();
|
|
|
|
}
|
2020-03-29 11:41:56 +00:00
|
|
|
// (3) load the initial positioning
|
2022-08-20 14:43:26 +00:00
|
|
|
else if(argis("-sagload")) {
|
|
|
|
PHASE(3); shift(); sag::load_sag_solution(args());
|
2020-03-29 11:41:56 +00:00
|
|
|
}
|
|
|
|
// (4) perform simulated annealing: -fullsa <time in seconds>
|
2022-08-20 14:43:26 +00:00
|
|
|
else if(argis("-sagfull")) {
|
2020-03-29 11:41:56 +00:00
|
|
|
shift(); sag::dofullsa(argi());
|
|
|
|
}
|
2022-08-20 14:43:26 +00:00
|
|
|
else if(argis("-sagviz")) {
|
|
|
|
sag::vizsa_start = SDL_GetTicks();
|
|
|
|
shift(); sag::vizsa_len = argi();
|
|
|
|
}
|
2020-03-29 11:41:56 +00:00
|
|
|
// (5) save the positioning
|
2022-08-20 14:43:26 +00:00
|
|
|
else if(argis("-sagsave")) {
|
|
|
|
PHASE(3); shift(); sag::save_sag_solution(args());
|
2020-03-29 11:41:56 +00:00
|
|
|
}
|
|
|
|
// (6) output loglikelihood
|
2022-08-20 14:43:26 +00:00
|
|
|
else if(argis("-sagloglik")) {
|
2020-03-29 11:41:56 +00:00
|
|
|
sag::loglik();
|
|
|
|
}
|
2022-08-20 14:43:26 +00:00
|
|
|
else if(argis("-sagmode")) {
|
|
|
|
shift();
|
|
|
|
sagmode = (eSagmode) argi();
|
|
|
|
if(sagmode == sagSA) {
|
|
|
|
shift(); temperature = argf();
|
|
|
|
}
|
|
|
|
}
|
2020-03-29 11:41:56 +00:00
|
|
|
else return 1;
|
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool turn(int delta) {
|
2022-08-20 14:43:26 +00:00
|
|
|
if(vizsa_start) {
|
|
|
|
auto t = ticks;
|
|
|
|
double d = (t-vizsa_start) / (1000. * vizsa_len);
|
|
|
|
if(d > 1) sagmode = sagOff;
|
|
|
|
else {
|
|
|
|
temperature = hightemp - (d*(hightemp-lowtemp));
|
|
|
|
sagmode = sagSA;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
iterate();
|
2020-03-29 11:41:56 +00:00
|
|
|
return false;
|
|
|
|
// shmup::pc[0]->rebase();
|
|
|
|
}
|
|
|
|
|
2020-03-29 13:37:56 +00:00
|
|
|
string cname() {
|
|
|
|
if(euclid) return "coord-6.txt";
|
|
|
|
if(PURE) return "coord-7.txt";
|
|
|
|
return "coord-67.txt";
|
|
|
|
}
|
|
|
|
|
2020-03-29 11:41:56 +00:00
|
|
|
int ah = addHook(hooks_args, 100, readArgs)
|
2021-06-25 11:53:23 +00:00
|
|
|
+ addHook_rvslides(120, [] (string s, vector<tour::slide>& v) {
|
2021-03-30 19:48:04 +00:00
|
|
|
if(s != "data") return;
|
2020-09-13 04:32:18 +00:00
|
|
|
using namespace pres;
|
2021-03-30 19:48:04 +00:00
|
|
|
string sagf = "SAG/";
|
2020-03-29 11:41:56 +00:00
|
|
|
v.push_back(
|
2020-04-07 12:07:41 +00:00
|
|
|
slide{sagf+"Roguelikes", 63, LEGAL::UNLIMITED | QUICKGEO,
|
2020-03-29 11:41:56 +00:00
|
|
|
"A visualization of roguelikes, based on discussion on /r/reddit. "
|
|
|
|
"See: http://www.roguetemple.com/z/hyper/reddit.php",
|
|
|
|
roguevizslide('0', [] () {
|
|
|
|
rogueviz::dftcolor = 0x282828FF;
|
|
|
|
|
|
|
|
rogueviz::showlabels = true;
|
|
|
|
part(rogueviz::default_edgetype.color, 0) = 181;
|
|
|
|
rogueviz::sag::edgepower = 1;
|
|
|
|
rogueviz::sag::edgemul = 1;
|
|
|
|
|
|
|
|
gmatrix.clear();
|
|
|
|
drawthemap();
|
|
|
|
gmatrix0 = gmatrix;
|
|
|
|
|
2022-08-20 14:43:26 +00:00
|
|
|
slide_backup(rogueviz::sag::legacy, true);
|
2020-03-29 11:41:56 +00:00
|
|
|
rogueviz::sag::read(RVPATH "roguelikes/edges.csv");
|
|
|
|
rogueviz::readcolor(RVPATH "roguelikes/color.csv");
|
2022-08-20 14:43:26 +00:00
|
|
|
rogueviz::sag::load_sag_solution(RVPATH "roguelikes/" + cname());
|
2020-03-29 11:41:56 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
);
|
2020-04-07 12:07:41 +00:00
|
|
|
v.push_back(slide {sagf+"Programming languages of GitHub", 64, LEGAL::UNLIMITED | QUICKGEO,
|
2020-03-29 11:41:56 +00:00
|
|
|
"A visualization of programming languages.",
|
|
|
|
roguevizslide('0', [] () {
|
|
|
|
rogueviz::dftcolor = 0x282828FF;
|
|
|
|
|
|
|
|
rogueviz::showlabels = true;
|
|
|
|
part(rogueviz::default_edgetype.color, 0) = 128;
|
|
|
|
rogueviz::sag::edgepower = .4;
|
|
|
|
rogueviz::sag::edgemul = .02;
|
|
|
|
|
|
|
|
gmatrix.clear();
|
|
|
|
drawthemap();
|
|
|
|
gmatrix0 = gmatrix;
|
|
|
|
|
2022-08-20 14:43:26 +00:00
|
|
|
slide_backup(rogueviz::sag::legacy, true);
|
2020-03-29 11:41:56 +00:00
|
|
|
rogueviz::sag::read(RVPATH "lang/edges.csv");
|
|
|
|
rogueviz::readcolor(RVPATH "lang/color.csv");
|
2022-08-20 14:43:26 +00:00
|
|
|
rogueviz::sag::load_sag_solution(RVPATH "lang/" + cname());
|
2020-03-29 11:41:56 +00:00
|
|
|
if(euclid) rogueviz::legend.clear();
|
|
|
|
})
|
|
|
|
});
|
|
|
|
|
2020-04-07 12:07:41 +00:00
|
|
|
v.push_back(slide {sagf+"Boardgames", 62, LEGAL::UNLIMITED | QUICKGEO,
|
2020-03-29 11:41:56 +00:00
|
|
|
"A visualization of board games, based on discussions on Reddit.",
|
|
|
|
roguevizslide('0', [] () {
|
|
|
|
rogueviz::dftcolor = 0x282828FF;
|
|
|
|
|
|
|
|
rogueviz::showlabels = true;
|
|
|
|
part(rogueviz::default_edgetype.color, 0) = 157;
|
|
|
|
rogueviz::sag::edgepower = 1;
|
|
|
|
rogueviz::sag::edgemul = 1;
|
|
|
|
|
|
|
|
gmatrix.clear();
|
|
|
|
drawthemap();
|
|
|
|
gmatrix0 = gmatrix;
|
|
|
|
|
2022-08-20 14:43:26 +00:00
|
|
|
slide_backup(rogueviz::sag::legacy, true);
|
2020-03-29 11:41:56 +00:00
|
|
|
rogueviz::sag::read(RVPATH "boardgames/edges.csv");
|
|
|
|
rogueviz::readcolor(RVPATH "boardgames/color.csv");
|
2022-08-20 14:43:26 +00:00
|
|
|
rogueviz::sag::load_sag_solution(RVPATH "boardgames/" + cname());
|
2020-03-29 11:41:56 +00:00
|
|
|
})
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
EX }
|
|
|
|
|
|
|
|
}
|