Skip to content

Commit 4610bed

Browse files
authored
Merge pull request #71 from krm35/fix/shortestPaths
Fix/shortest paths
2 parents 8b5bcad + e3cc716 commit 4610bed

2 files changed

Lines changed: 34 additions & 24 deletions

File tree

src/index.ts

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ export function Graph(serialized?: Serialized) {
178178
function depthFirstSearch(
179179
sourceNodes?: NodeId[],
180180
includeSourceNodes: boolean = true,
181-
errorOnCycle: boolean = false
181+
errorOnCycle: boolean = false,
182182
) {
183183
if (!sourceNodes) {
184184
sourceNodes = nodes();
@@ -284,7 +284,7 @@ export function Graph(serialized?: Serialized) {
284284
// Cormen et al. "Introduction to Algorithms" 3rd Ed. p. 613
285285
function topologicalSort(
286286
sourceNodes?: NodeId[],
287-
includeSourceNodes: boolean = true
287+
includeSourceNodes: boolean = true,
288288
) {
289289
return depthFirstSearch(sourceNodes, includeSourceNodes, true).reverse();
290290
}
@@ -394,12 +394,22 @@ export function Graph(serialized?: Serialized) {
394394
function shortestPaths(source: NodeId, destination: NodeId) {
395395
let path = shortestPath(source, destination);
396396
const paths = [path],
397-
removedEdges = [],
397+
removedEdges: { u: NodeId; v: NodeId; weight: EdgeWeight }[] = [],
398398
weight = path.weight;
399399
while (weight) {
400-
removeEdge(path[0], path[1]);
401-
removeEdge(path[1], path[0]);
402-
removedEdges.push([path[0], path[1]]);
400+
const u = path[0];
401+
const v = path[1];
402+
403+
if (hasEdge(u, v)) {
404+
removedEdges.push({ u, v, weight: getEdgeWeight(u, v) });
405+
removeEdge(u, v);
406+
}
407+
408+
if (hasEdge(v, u)) {
409+
removedEdges.push({ u: v, v: u, weight: getEdgeWeight(v, u) });
410+
removeEdge(v, u);
411+
}
412+
403413
try {
404414
path = shortestPath(source, destination);
405415
if (!path.weight || weight < path.weight) break;
@@ -408,10 +418,7 @@ export function Graph(serialized?: Serialized) {
408418
break;
409419
}
410420
}
411-
for (const [u, v] of removedEdges) {
412-
addEdge(u, v);
413-
addEdge(v, u);
414-
}
421+
for (const { u, v, weight } of removedEdges) addEdge(u, v, weight);
415422
return paths;
416423
}
417424

test.js

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ describe("Graph", function () {
378378
var graph = Graph().addEdge("a", "b").addEdge("b", "c");
379379
assert.deepEqual(
380380
graph.shortestPath("a", "c"),
381-
withWeight(["a", "b", "c"], 2)
381+
withWeight(["a", "b", "c"], 2),
382382
);
383383
});
384384

@@ -396,11 +396,11 @@ describe("Graph", function () {
396396

397397
assert.deepEqual(
398398
graph.shortestPath("s", "z"),
399-
withWeight(["s", "y", "z"], 5 + 2)
399+
withWeight(["s", "y", "z"], 5 + 2),
400400
);
401401
assert.deepEqual(
402402
graph.shortestPath("s", "x"),
403-
withWeight(["s", "y", "t", "x"], 5 + 3 + 1)
403+
withWeight(["s", "y", "t", "x"], 5 + 3 + 1),
404404
);
405405
});
406406

@@ -423,11 +423,11 @@ describe("Graph", function () {
423423
var graph = Graph().addEdge("a", "b").addEdge("b", "c").addEdge("d", "e");
424424
assert.deepEqual(
425425
graph.shortestPath("a", "c"),
426-
withWeight(["a", "b", "c"], 2)
426+
withWeight(["a", "b", "c"], 2),
427427
);
428428
});
429429

430-
it("Should compute shortest paths on six edges.", function () {
430+
it("Should compute shortest paths.", function () {
431431
var graph = Graph()
432432
.addEdge("a", "b")
433433
.addEdge("b", "c")
@@ -436,14 +436,21 @@ describe("Graph", function () {
436436
.addEdge("a", "e")
437437
.addEdge("e", "f")
438438
.addEdge("f", "c");
439+
const serializedGraph = graph.serialize();
439440
assert.deepEqual(graph.shortestPaths("a", "c"), [
440441
withWeight(["a", "b", "c"], 2),
441442
withWeight(["a", "d", "c"], 2),
442443
]);
443-
// need to check nodes are still present because we remove them to get all shortest paths
444-
const nodes = ["a", "b", "c", "d", "e", "f"];
445-
assert.equal(graph.nodes().length, nodes.length);
446-
nodes.forEach((node) => assert(contains(graph.nodes(), node)));
444+
// check graph has not changed
445+
const postSerializedGraph = graph.serialize();
446+
assert.equal(
447+
postSerializedGraph.links.length,
448+
serializedGraph.links.length,
449+
);
450+
assert.equal(
451+
postSerializedGraph.nodes.length,
452+
serializedGraph.nodes.length,
453+
);
447454
});
448455
});
449456

@@ -458,11 +465,7 @@ describe("Graph", function () {
458465
});
459466

460467
function contains(arr, item) {
461-
return (
462-
arr.filter(function (d) {
463-
return d === item;
464-
}).length > 0
465-
);
468+
return arr.includes(item);
466469
}
467470

468471
function comesBefore(arr, a, b) {

0 commit comments

Comments
 (0)