traveling-salesman-bangkok/src/solvers/heuristic-construction/nearestInsertion.worker.js

73 lines
1.8 KiB
JavaScript
Raw Normal View History

2025-02-22 21:18:41 +07:00
/* eslint-disable no-restricted-globals */
import makeSolver from "../makeSolver";
import { pathCost, distance } from "../cost";
const nearestInsertion = async points => {
// from the starting point
const path = [points.shift()];
//
// INITIALIZATION - go to the nearest point first
//
points.sort((a, b) => distance(path[0], b) - distance(path[0], a));
path.push(points.pop());
self.setEvaluatingPaths(() => ({
paths: [{ path }],
cost: pathCost(path)
}));
await self.sleep();
while (points.length > 0) {
//
// SELECTION - nearest point to the path
//
let [selectedDistance, selectedIdx] = [Infinity, null];
for (const [freePointIdx, freePoint] of points.entries()) {
for (const pathPoint of path) {
const dist = distance(freePoint, pathPoint);
if (dist < selectedDistance) {
[selectedDistance, selectedIdx] = [dist, freePointIdx];
}
}
}
// get the next point to add
const [nextPoint] = points.splice(selectedIdx, 1);
//
// INSERTION - find the insertion spot that minimizes distance
//
let [bestCost, bestIdx] = [Infinity, null];
for (let i = 1; i < path.length; i++) {
const insertionCost = pathCost([path[i - 1], nextPoint, path[i]]);
if (insertionCost < bestCost) {
[bestCost, bestIdx] = [insertionCost, i];
}
}
path.splice(bestIdx, 0, nextPoint);
self.setEvaluatingPaths(() => ({
paths: [{ path }],
cost: pathCost(path)
}));
await self.sleep();
}
// return to start after visiting all other points
path.push(path[0]);
const cost = pathCost(path);
self.setEvaluatingPaths(() => ({
paths: [{ path }],
cost
}));
await self.sleep();
self.setBestPath(path, cost);
};
makeSolver(nearestInsertion);