Snake = (loglike, start, spacing) =>
{
const point2param = point => point.map((p,i) => start[i] + p*spacing[i])
const adjacents = x => {
let points = [];
x.forEach((e,i) => {
let right = [...x]; right[i] += 1; points.push(right);
let left = [...x]; left[i] -= 1; points.push(left);
});
return points;
}
const origin = start.map(() => 0.)
let surface = [{loglike: loglike(point2param(origin)), x: origin}]
let active_points = {};
active_points[origin] = true;
let internals = [];
let bestlike = surface[0].loglike
let iterations = 0;
const iterate = () => {
iterations += 1;
let a = adjacents(surface[0].x);
a = _.default.shuffle(a);
let p;
do p = a.pop(); while (p in active_points);
if(p === undefined) {
internals.push(heapPop(surface));
} else {
const plike = loglike(point2param(p));
heapPush(surface, {loglike: plike, x: p});
active_points[p] = true;
if(plike > bestlike) bestlike = plike;
}
return bestlike - surface[0].loglike
}
const samples = () => [...internals, ...surface]
.map(s => ({loglike: s.loglike, x:point2param(s.x)}));
return {iterate,
internals: () => internals.map(s => ({loglike: s.loglike, x:point2param(s.x)})),
surface: () => surface.map(s => ({loglike: s.loglike, x:point2param(s.x)})),
samples,
run: (threshold) => {while (iterate() < threshold) continue;
return bestlike - surface[0].loglike},
bestlike: () => bestlike,
delta_chi2: () => bestlike - surface[0].loglike,
}
}