I have been searching for weeks for a way to compute shortest paths in JavaScript. I have been playing with the book Data Structures and Algorithms by Groner (aptly named) at https://github.com/loiane/javascript-datastructures-algorithms/tree/master/chapter09.
The trouble I keep on finding is that the code is so customized that it is almost impossible to rewrite to produce the desired results. I would like to be able to get the shortest path from any given vertex to any other, rather than, as Groner codes it, just the list of everything from A. I would like to be able to get, for example, the path from F to B, or from C to A.
The full code is here: http://jsfiddle.net/8cn7e2x8/
Can anyone help?
var graph = new Graph();
var myVertices = ['A','B','C','D','E','F'];
for (var i=0; i<myVertices.length; i++) {
graph.addVertex(myVertices[i]);
}
graph.addEdge('A', 'B');
graph.addEdge('B', 'C');
graph.addEdge('B', 'E');
graph.addEdge('C', 'D');
graph.addEdge('C', 'E');
graph.addEdge('C', 'G');
graph.addEdge('D', 'E');
graph.addEdge('E', 'F');
graph.dfs();
console.log('********* sortest path - BFS ***********');
var shortestPathA = graph.BFS(myVertices[0]);
//from A to all other vertices
var fromVertex = myVertices[0];
for (i = 1; i < myVertices.length; i++) {
var toVertex = myVertices[i],
path = new Stack();
for (var v = toVertex; v !== fromVertex; v = shortestPathA.predecessors[v]) {
path.push(v);
}
path.push(fromVertex);
var s = path.pop();
while (!path.isEmpty()) {
s += ' - ' + path.pop();
}
console.log(s);
}
Let us begin by remarking that breadth-first search (BFS) computes the shortest paths from a given source vertex if the graph is unweighted. In other words, we consider the length of a path to be the number of edges in the path.
Here is an easy way to construct an unweighted graph:
Note that we have implemented an undirected graph. As mentioned in the inline comments, you can modify the code to construct a directed graph by deleting four lines from the
addEdge
function.This implementation of BFS would work equally well on a directed graph:
To find the shortest path between two given vertices and display the vertices along the path, we have to remember the predecessor of each vertex as we explore the graph:
The following snippet demonstrates these operations on the graph that you gave in your question. First we find the shortest paths to all vertices reachable from
A
. Then we find the shortest path fromB
toG
and fromG
toA
.Reading your question, I can read it one of two ways... Either you're trying to reduce the amount of things it checks, or you're trying to allow yourself to pass in variables to change end points. I'm going to assume the former and let someone else handle the latter case.
Giving a cursory glance over the problem, it looks like you've come across what is known in Comp Sci as "The traveling salesman problem." It's a classical problem in computer programming that's considered a logical impossibility, and is a good example of "perfect being the enemy of the good."
The classical travelling salesman problem is this, "Program a way for a salesman to reach all of his destination cities on a map in the shortest time. Do so without having to check every single possible path." The thing is, logical way to do this has (yet) to ever be discovered (it's yet to be proved if it's impossible or possible). That said, if it doesn't have to be THE shortest, but just a shorter path, there's a number of shortcuts that can be taken. One example is just calculating a line from start to finish, and then push in the deviations to match up with closest vertices. Another is to break the paths into triangles that connect each vertices only to the next closest two vertices and then connect clumps the same way until all vertices are connected and then only calculate your starting potential paths from those subsets.
Neither of those two answers are guaranteed to give you the best answer, but they will provide a good answer with a lot less computational time required so you don't have to calculate every path coming from A and B and C etc. etc.