1.0 - Shortest Path
-
A path
from to is a sequence of vertices: -
The total weight of the path,
is the sum of the edges along the path’ -
The distance from
to is the minimum weight of all paths from -
The shortest path frp,
to is a path from to of minimum weight
1.1 - Types of Shortest Paths
Single-PairGiven a pair, find a shortest path between them Single-SourceGiven a vertex, find a shortest path to every other vertex Single-DestinationGiven a vertex, find a shortest path from every other vertex All-PairsGiven a graph, find a shortest path between every pair of vertices
1.1.1 - Single-Source Shortest Path
Given a graph
Distance from source vertex The predecessor to on a shortest path from to
The steps to this algorithm are:
- Initialise
and for all vertices - We have the invariant that
- We have the invariant that
- Initialise
for all vertices - Invariant
is v’s predecessor on the shortest path found so far
- Invariant
- Improve upper bound estimates until they reach a solution
Can we improve our estimate
- Our estimate
and - The existence of edge
with weight
We know that:
And thus, we know that
1.1.2 - Edge Relaxation Algorithm
relax(u, v, w):
improves estimate distance(s,v) ≤ v.d if possible, based on:
our estimate distance(s, u) ≤ u.d and
the existence of edge (u,v) with weight w(u,v)
relax(u, v, w)
if v.d > u.d + w(u,v)
v.d = u.d + w(u,v)
v.π = u
- This preserves the distance and predecessor invariants:
- Invariant
- Invariant
is ’s predecessor on the shortest path sound so far
- Invariant
- Does not change
and if the shortest path to has already been found - The relax(u,v,w) algorithm will find a shortest path from s to v if:
- A shortest path from
to has already been found - Vertex
is predecessor on a shortest path from , and - Another shortest path from
to has not already been found
- A shortest path from
1.1.3 - Edge Relaxation
Let
be a shortest path from
If edge
We can relax edges in a wa y that guarantees that we find shortest paths from our source vertex
1.2 - Dijkstra’s Algorithm
🌱 Dijkstra’s algorithm is a generalisation of Breadth First Search, but for weighted graphs.
- Solves the single-source shortest paths problem for weighted graphs without negative weight edges.
- AI in computer games use a sophisticated variant called A*
- Solves graphs in order from start vertex
1.2.1 - Shortest Path Algorithm - Steps
- For each vertex
, we calculate v.dDistance of vertex from the source vertex sv.$\pi$The predecessor to v on the shortest path from s to v
- Steps:
Initialise=0 and = for all vertices (all vertices but starting vertex) =0 (set the distance of the source vertex to 0) = (set distance of all other vertices to source vertex to initially) - Invariant that distance(s,v)
v.d
Initialise= NIL for all - Invariant that
is a predecessor on the shortest path found so far.
- Invariant that
ImproveVisit each vertex once (after we have found a shortest path to it) in order of its distance from the source vertex - when we visit a vertex, we can relax its outgoing edges
1.2.2 - Efficient Implementation of Dijkstra
🌱 How do we (efficiently) find the next vertex to visit?
- Let S be the set of visited vertices
- We main a priority queue, Q, containing vertices
, with key - At each step of the algorithm, we visit the vertex
vertex on Q, with minimum key. - That is, we remove the element from the PQ
- We then relax all of its edges.
1.2.3 - Why does Dijkstra’s Algorithm Work?
- When we visit a vertex u, we are guaranteed to have already found a shortest path to u, assuming that the graph has no negative weight edges.
- Suppose v is a predecessor of u on a shortest path from
- Since our graph doesn’t have negative-weight edges, we know that
and so either: - We have already visited v and have relaxed its edges, or
- We have already found another shortest-path to u of length distance(s, u) = distance(s, v)
1.2.4 - Dijkstra’s Algorithm
Dijkstra(G, w, s)
// (G) Graph, (w) weight function, (s) source vertex
init_single_source(G, s)
S = ∅ // S is the set of visited vertices
Q = G.V // Q is a priority queue, maintaining G.V - S
while Q != ∅
u = extract_min(Q)
S = S ∪ {u}
for each vertex in G.adj[u]
relax(u, v, w)
init_single_source(G, s)
for each vertex v in G.V
v.d = ∞
v.pi = NIL
s.d = 0
relax(u, v, w)
if v.d > u.d + w(u,v)
v.d = u.d + w(u,v)
v.pi = u
1.2.5 - Analysis of Dijkstra’s Algorithm
-
The initialisation (init_single_source) and addition to the priority queue are both completed
time, where number of vertices -
We complete the body of the main while loop
times, as a vertex is removed each iteration, and each vertex can only be added to the priority queue once. -
The removal from the priority queue incurs some cost - this depends on the PQ implementation
-
We complete the inner for-loop
times. - Since each edge is removed at least once, we know that the relaxation algorithm is performed exactly
times.
- Since each edge is removed at least once, we know that the relaxation algorithm is performed exactly
-
Thus, the time complexity of the algorithm is
-
Using this, we can analyse the performance of Dijkstra’s algorithm, based on the data structures used.
Q Data Structure Total array binary heap Fibonacci heap amortised amortized amortised -
Fibonacci heap is an implementation with very large constant factors.