Imagine for a minute you are Google Maps (because they actually do use something very similar to what we’ll describe). Your job then is to get someone from A to B as quickly as possible. How do you find the best path?
Suppose we have a road network, seen here:
The numbers represent some resource (time, fuel, distance), which
is precious, and which we want to use the least amount of, to get from one
place to another.
Suppose we live at A and work at F.
We can use Dijkstra’s algorithm to figure out the shortest path.
1.
Assume that everything is infinitely far away,
because we haven’t calculated ant distances
2.
Look at the graph, and see that from A, we can
get to B in 4 and C in 5. Everything else is infinitely far away.
3.
Now, from B, we can get to D in an additional 9,
or E in an additional 7. From C, we can get to B in an additional 11, or E in an
additional 3. (We ignore going back to A for 5 as useless).
4.
We already know that the shortest path will not
be ABE…, because there’s a faster way to get to E, via C, as in ACE…: ABE has a
total cost of 4+7 = 11, and ACE has a total cost of 5+3 = 8; 8 < 11, so the
8-cost path is better.
5.
From E, we can go backwards to C (which we again
ignore), or to B for 7, or to D to 13 or to F for 6. We choose the best (which
happens to be the leg that gets us to our solution) and go to F for 6.
6.
Now, we have the whole path which minimizes the
use of our precious resource: start at A, and go through C and E en route to F.
The following paths (without loops) are possible:
|
Path |
Cost |
|
ABEF |
17 |
|
ABDF |
15 |
|
ACBDF |
27 |
|
ACEBDF |
26 |
|
ACBEF |
29 |
|
ACBDEF |
46 |
|
ACEF |
14 |
Of all the paths, the one we came up with with our strategy
is the shortest between A and F.
Heuristically, the approach is twofold:
- Choose the next location as the one that can be reached at the smallest total cost
- Update the shortest known distance to every node, if a new shortest path has been found
This approach is Dijkstra's algorithm. If I'm not mistaken, it was invented in about half an hour while its inventor (a professor and pioneer of computer science) was on or waiting for an intercity train, sometime in the 1950s or 1960s-- and still today it remains a cornerstone algorithm at the heart of so many different applications.
There is one important consideration when using Dijkstra's algorithm. Most of the time, edge weights are positive: it costs you some money, or it requires some amount of gas, or you need to spend time. But that does not always need to be the case in every graph; edge weights can be negative. However, if a graph has any negative edge weights, Dijkstra's algorithm will not necessarily work, so it should not be used.
Here is the pseudocode for the algorithm:
function Dijkstra(Graph, source):
// Initialize distances and previous node trackers
for each vertex v in Graph:
dist[v] := infinity
prev[v] := undefined
dist[source] := 0
// Create a set of all unvisited nodes
Q := set of all vertices in Graph
while Q is not empty:
// Select the unvisited node with the smallest distance
u := vertex in Q with smallest dist[u]
remove u from Q
// For each neighbor v of u still in Q:
for each neighbor v of u:
alt := dist[u] + weight(u, v)
if alt < dist[v]:
dist[v] := alt
prev[v] := u
return dist, prev
And here it is in Java: