Shortest path now uses a heap

Use a heap in dijkstra's algoritm to keep track of the shortest path. Change time from O(v^2) to O(u + v log(v)).

@companje tijdens een college kwam een algoritme aan bod wat ik gebruikt heb in de slicer. Ik kwam er achter dat ik een fout had gemaakt waardoor het algoritme een stuk trager was als zou moeten. Door een binary heap te gebruiken is het algoritme een stuk sneller. Dit algoritme rekent een kortste pad uit en wordt gebruikt in de `comb` functie.
This commit is contained in:
Casper Lamboo 2019-04-04 23:02:01 +02:00
parent 3b440b346a
commit 13ffea4115
3 changed files with 2266 additions and 3729 deletions

5961
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -24,6 +24,7 @@
"@doodle3d/doodle3d-core": "github:doodle3d/doodle3d-core", "@doodle3d/doodle3d-core": "github:doodle3d/doodle3d-core",
"babel-plugin-transform-class-properties": "^6.24.1", "babel-plugin-transform-class-properties": "^6.24.1",
"file-saver": "^1.3.3", "file-saver": "^1.3.3",
"heap": "^0.2.6",
"lodash": "^4.17.4", "lodash": "^4.17.4",
"material-ui": "^0.19.4", "material-ui": "^0.19.4",
"material-ui-icons": "^1.0.0-beta.17", "material-ui-icons": "^1.0.0-beta.17",

View File

@ -1,3 +1,4 @@
import Heap from 'heap';
import { angle, subtract, distanceTo } from './vector2.js'; import { angle, subtract, distanceTo } from './vector2.js';
const graphs = new WeakMap(); const graphs = new WeakMap();
@ -147,40 +148,36 @@ function betweenAngles(n, a, b) {
// dijkstra's algorithm // dijkstra's algorithm
function shortestPath(graph, start, end) { function shortestPath(graph, start, end) {
const traverse = graph.map(() => -1);
traverse[start] = start;
const visited = graph.map(() => false);
const distances = graph.map(() => Infinity); const distances = graph.map(() => Infinity);
distances[start] = 0; distances[start] = 0;
const traverse = [];
const queue = [];
for (let i = 0; i < distances.length; i ++) {
queue.push(i);
}
while (queue.length > 0) { const heap = new Heap((a, b) => a.distance - b.distance);
let queueIndex; heap.push({ nodeIndex: start, distance: 0 });
let minDistance = Infinity;
for (let index = 0; index < queue.length; index ++) { for (let i = 0; i < graph.length; i ++) {
const nodeIndex = queue[index]; let nodeIndex;
const distance = distances[nodeIndex]; do { nodeIndex = heap.pop().nodeIndex } while (visited[nodeIndex]);
if (distances[nodeIndex] < minDistance) {
queueIndex = index; if (nodeIndex === end) break;
minDistance = distance;
}
}
const [nodeIndex] = queue.splice(queueIndex, 1);
const node = graph[nodeIndex]; const node = graph[nodeIndex];
visited[nodeIndex] = true;
for (let i = 0; i < node.length; i ++) { for (let i = 0; i < node.length; i ++) {
const child = node[i]; const child = node[i];
const distance = distances[nodeIndex] + child.distance; const distance = distances[nodeIndex] + child.distance;
if (distance < distances[child.to]) { if (distance < distances[child.to]) {
heap.push({ nodeIndex: child.to, distance });
distances[child.to] = distance; distances[child.to] = distance;
traverse[child.to] = nodeIndex; traverse[child.to] = nodeIndex;
} }
} }
} }
if (!traverse.hasOwnProperty(end)) return null; if (traverse[end] === -1) return null;
const path = [end]; const path = [end];
let nodeIndex = end; let nodeIndex = end;