Bellman-Ford, Floyd-Warshall, and Dynamic Programming!
Bellman-Ford, Floyd-Warshall, and Dynamic Programming!
12
Bellman-Ford, Floyd-Warshall, and Dynamic
Programming!
Announcements
• HW5 due Friday
• Midterms have been graded!
• Pick up your exam after class.
• Average: 84, Median: 87
• Max: 100 (x4)
• I am very happy with how well y’all did!
• Regrade policy:
• Write out a regrade request as you would on
Gradescope.
• Hand your exam and your request to me after class on
Wednesday or in my office hours Tuesday (or by
appointment).
Last time
• Dijkstra’s algorithm!
• Solves single-source shortest path in weighted graphs.
u
s 3 32
1 5
1
b v
13
a 2 2
1
16 t
Today
• Bellman-Ford algorithm
• Another single-source shortest path algorithm
• This is an example of dynamic programming
• We’ll see what that means
• Floyd-Warshall algorithm
• An “all-pairs” shortest path algorithm
• Another example of dynamic programming
• Weights on edges
Recall represent costs.
u
s 3 32
-1 5
-1
b v
13
Why would we ever
a 21 -2 have negative weights?
• Negative costs might
mean benefits.
16 • eg, it costs me -$2
t when I get $2.
Bellman-Ford Algorithm
• Slower (but arguably simpler) than Dijkstra’s algorithm.
• Works with negative edge weights.
*We won’t actually store all these, but let’s pretend we do for now.
Bellman-Ford Algorithm
• We keep* an array d(k) of length n for each k = 0, 1, …, n-1.
Formally, we will maintain
the loop invariant: d(k)[b] is the cost of the shortest path
s u v t from s to b with at most k edges in it,
• For example, this is the shortest for all b in V.
d(0) path from s to t with at most
two edges in it.
s 2
s u v t
d(1) • But it’s not the shortest path
from s to t (with any number of u
1
edges).
s u v t
• That’s this one. 5
d(2) 2
s u v t t
-2 v
d(3)
*We won’t actually store all these, but let’s pretend we do for now.
Bellman-Ford Algorithm
• We keep* an array d(k) of length n for each k = 0, 1, …, n-1.
Formally, we will maintain
the loop invariant: d(k)[b] is the cost of the shortest path
s u v t from s to b with at most k edges in it,
for all b in V.
d(0) 0 ∞ ∞ ∞
0
s u v t s 2
∞
d(1) u
1
s u v t
5
d(2) 2
s u v t t
-2 v
d(3) ∞ ∞
While maintaining:
d(k)[b] is the cost of the shortest path
Now update! from s to b with at most k edges in it.
s 10 b
2 u
say k=3
Bellman-Ford Algorithm*
• Bellman-Ford*(G,s):
• Initialize d(k) for k = 0, …, n-1
• d(0)[v] = ∞ for all v other than s This minimum is over
• d(0)[s] = 0. all a so that (a,b) is in E
• For k = 1, …, n-1:
• For b in V:
• d(k)[b] ← min{ d(k-1)[b], mina {d(k-1)[a] + weight(a,b)} }
• Return d(n-1)
s u v t
d(0) 0 ∞ ∞ ∞
0
s u v t s 2
∞
d(1) u
1
s u v t
5
d(2) 2
s u v t t
-2 v
d(3) ∞ ∞
Bellman-Ford Algorithm* Example
d(k)[b] is the cost of the shortest path
from s to b with at most k edges in it.
• For k = 1,…,n-1:
• For b in V:
• d(k)[b] ← min{ d(k-1)[b], mina {d(k-1)[a] + weight(a,b)} }
s u v t
d(0) 0 ∞ ∞ ∞
0
s u v t s 2
2
d(1) 0 2 5 ∞
u
1
s u v t
5
d(2) 2
s u v t t
-2 v
d(3) ∞ 5
Bellman-Ford Algorithm* Example
d(k)[b] is the cost of the shortest path
from s to b with at most k edges in it.
• For k = 1,…,n-1:
• For b in V:
• d(k)[b] ← min{ d(k-1)[b], mina {d(k-1)[a] + weight(a,b)} }
s u v t
d(0) 0 ∞ ∞ ∞
0
s u v t s 2
2
d(1) 0 2 5 ∞
u
1
s u v t
5
d(2) 0 2 4 3 2
s u v t t
-2 v
d(3) 3 4
Bellman-Ford Algorithm* Example
d(k)[b] is the cost of the shortest path
from s to b with at most k edges in it.
• For k = 1,…,n-1:
• For b in V:
• d(k)[b] ← min{ d(k-1)[b], mina {d(k-1)[a] + weight(a,b)} }
s u v t
d(0) 0 ∞ ∞ ∞
0
s u v t s 2
2
d(1) 0 2 5 ∞
u
1
s u v t
5
d(2) 0 2 4 3 2
s u v t t
-2 v
d(3) 0 2 4 2 2 4
Bellman-Ford Algorithm* Example
d(k)[b] is the cost of the shortest path
from s to b with at most k edges in it.
SANITY CHECK:
• The shortest path with 1 edge from s to t has cost ∞. (there is no such path).
• The shortest path with 2 edges from s to t has cost 3. (s-v-t)
• The shortest path with 3 edges from s to t has cost 2. (s-u-v-t)
And this one is the shortest path!!!
s u v t
d(0) 0 ∞ ∞ ∞
0
s u v t s 2
2
d(1) 0 2 5 ∞
u
1
s u v t
5
d(2) 0 2 4 3 2
s u v t t
-2 v
d(3) 0 2 4 2 2 4
How do we actually implement this?
(This is what the * on all the previous slides was for).
• Bellman-Ford*(G,s):
• Initialize d(k) for k = 0, …, n-1
• d(0)[v] = ∞ for all v other than s
• d(0)[s] = 0.
• For k = 1, …, n-1:
• For b in V:
• d(k)[b] ← min{ d(k-1)[b], mina {d(k-1)[a] + weight(a,b)} }
• Return d(n-1)
Why does it work?
• First, we’ve been asserting that:
• Enough to show:
A negative cycle is a
• If the graph has a negative directed cycle with
negative total cost
cycle, this might not be true.
• If there is a negative cycle,
there may not be a shortest
path between two vertices!
s 2
1 u
-5
2
t
-2 v
But if there is no negative cycle
• Then not only are there shortest paths, but actually
there’s always a simple shortest path.
-2 10
s v
2 t
-5
This cycle isn’t helping.
x y Just get rid of it.
3
• Top down
• Bottom up
• BF*_helper(G, s, b, k):
• For each a so that (a,b) in E, and also for a=b:
• If d(k-1)[a] is not already in the table:
• d(k-1)[a] = BF*_helper( G, s, a, k-1 )
• return min{ d(k-1)[b], mina {d(k-1)[a] + weight(a,b)} }
*Not the actual Bellman-Ford algorithm; we don’t want to keep all these tables around
**Probably not the best way to think about Bellman-Ford: this is for DP pedagogy only!
Visualization
top-down approach
d(n-1)[u] d(n-1)[v]
d(n-1)[u] d(n-1)[v]
s 0 2 4 2
1 u
u 1 0 2 0
5
v ∞ ∞ 0 -2 2
t ∞ ∞ ∞ 0 t
-2 v
Another example
• Floyd-Warshall Algorithm
• This is an algorithm for All-Pairs Shortest Paths (APSP)
• That is, I want to know the shortest path from u to v for ALL
pairs u,v of vertices in the graph.
• Not just from a special single source s.
• Naïve solution (if we want to handle negative edge weights):
• For all s in G:
• Run Bellman-Ford on G starting at s.
• Time O(n⋅nm) = O(n2m),
• may be as bad as n4 if m=n2
Label the vertices 1,2,…,n
Optimal substructure (We omit edges in the
picture below).
Sub-problem: For all pairs, u,v, find the cost of
the shortest path from u to v, so that all the
internal vertices on that path are in {1,…,k-1}.
u 1 2
v
3
This is the shortest
… k-1 path from u to v
n through the blue
set. It has length
D(k-1)[u,v]
Label the vertices 1,2,…,n
Optimal substructure (We omit edges in the
picture below).
Sub-problem: For all pairs, u,v, find the cost of
the shortest path from u to v, so that all the
internal vertices on that path are in {1,…,k-1}.
k
k+1
u 1 2
v
3
… k-1
n
How can we find D(k)[u,v] using D(k-1)?
D(k)[u,v] is the cost of the shortest path from u to v so
that all internal vertices on that path are in {1, …, k}.
Case 1: we don’t
k
need vertex k. k+1
u 1 2
v
3
… k-1
n
D(k)[u,v] = D(k-1)[u,v]
How can we find D(k)[u,v] using D(k-1)?
D(k)[u,v] is the cost of the shortest path from u to v so
that all internal vertices on that path are in {1, …, k}.
Case 2: we need
k
vertex k. k+1
u 1 2
v
3
… k-1
n
Case 2 continued
Case 2: we need
• Suppose there are no negative
vertex k.
cycles.
• Then WLOG the shortest path from
u to v through {1,…,k} is simple.
k
• Optimal substructure:
• We can solve the big problem using smaller problems.
• Overlapping sub-problems:
• D(k-1)[k,v] can be used to help compute D(k)[u,v] for lots
of different u’s.
How can we find D(k)[u,v] using D(k-1)?
s a
t b
s a
NOPE!
t b
This doesn’t work
What went wrong?
• The subproblems we came up with aren’t independent:
• Once we’ve chosen the longest path from a to t
• which uses b,
• our longest path from s to a shouldn’t be allowed to use b
• since b was already used.