Download presentation
Presentation is loading. Please wait.
1
CS6045: Advanced Algorithms
Dynamic Programming
2
Fibonacci Numbers Computing the nth Fibonacci number recursively: F(n)
F(n) = F(n-1) + F(n-2) F(0) = 0 F(1) = 1 Top-down approach Time complexity? int Fib(int n) { if (n <= 1) return 1; else return Fib(n - 1) + Fib(n - 2); } F(n) F(n-1) F(n-2) F(n-2) F(n-3) F(n-3) F(n-4) n levels
3
Fibonacci Numbers Computing the nth Fibonacci number using a bottom-up approach: F(0) = 0 F(1) = 1 F(2) = 1+0 = 1 … F(n-2) = F(n-1) = F(n) = F(n-1) + F(n-2) Complexity: Time – O(n) Space – O(n)
4
Fibonacci Numbers The bottom-up approach is only O(n).
Why is the top-down so inefficient? Re-computes many sub-problems. How many times is F(n-5) computed? F(n) F(n-1) F(n-2) F(n-2) F(n-3) F(n-3) F(n-4) n levels
5
Fibonacci Numbers Fib(5) + Fib(3) + Fib(4) + Fib(3) + Fib(2) + Fib(1)
6
Dynamic Programming Dynamic Programming is an algorithm design technique for optimization problems: often minimizing or maximizing. Like divide and conquer, DP solves problems by combining solutions to sub-problems. Unlike divide and conquer, sub-problems are not independent. Sub-problems overlap (share sub-sub-problems) Dynamic Programming = meta-technique (not a particular algorithm) Programming = “tableau method’’, not writing a code
7
Dynamic Programming In dynamic programming we usually reduce time by increasing the amount of space We solve the problem by solving sub-problems of increasing size and saving each optimal solution in a table (usually). The table is then used for finding the optimal solution to larger problems. Time is saved since each sub-problem is solved only once.
8
Dynamic Programming The best way to get a feel for this is through some more examples. Longest Common Subsequence 0-1 Knapsack Problem Matrix Chaining optimization
9
Longest Common Subsequence
Longest common subsequence (LCS) problem: Given two sequences X = <x1 x2 … xm> and Y = <y1 y2 … yn>, find the longest subsequence which occurs in both Ex: X = {A B C B D A B }, Y = {B D C A B A} What’s the LCS? X = A B C B D A B Y = B D C A B A Brute-force algorithm: For every subsequence of X, check if it’s a subsequence of Y How many subsequences of X are there? What will be the running time of the brute-force algorithm?
10
LCS Algorithm Brute-force algorithm: 2m subsequences of X to check against n elements of Y: O(n 2m) We can do better: for now, let’s only worry about the problem of finding the length of LCS When finished we will see how to backtrack from this solution back to the actual LCS Notice LCS problem has optimal substructure Subproblems: LCS of pairs of prefixes of X and Y
11
LCS Algorithm First we’ll find the length of LCS. Later we’ll modify the algorithm to find LCS itself. Define Xi, Yj to be the prefixes of X and Y of length i and j respectively (i ≤ m; j ≤ n) Xi = <x1 x2 … xi>; Yj = <y1 y2 … yj> Define c[i,j] to be the length of LCS of Xi and Yj Then the length of LCS of X and Y will be c[m,n] X = A B C B D A B Y = B D C A B A
12
LCS recursive solution
We start with i = j = 0 (empty substrings of X and Y) Since X0 and Y0 are empty strings, their LCS is always empty (i.e., c[0,0] = 0) LCS of empty string and any other string is empty, so for every i and j: c[0, j] = c[i,0] = 0
13
LCS recursive solution
When we calculate c[i,j], we consider two cases: First case: x[i]=y[j]: one more symbol in strings X and Y matches, so the length of LCS Xi and Yj equals to the length of LCS of smaller strings Xi-1 and Yi-1 , plus 1
14
LCS recursive solution
Second case: x[i] != y[j] As symbols don’t match, our solution is not improved, and the length of LCS(Xi , Yj) is the same as before (i.e., maximum of LCS(Xi, Yj-1) and LCS(Xi-1,Yj) For example: AB | C; BC | A Why not just take the length of LCS(Xi-1, Yj-1) ?
15
LCS Length Algorithm LCS-Length(X, Y)
1. m = length(X) // get the # of symbols in X 2. n = length(Y) // get the # of symbols in Y 3. for i = 1 to m c[i,0] = 0 // special case: Y0 4. for j = 1 to n c[0,j] = 0 // special case: X0 5. for i = 1 to m // for all Xi 6. for j = 1 to n // for all Yj 7. if ( Xi == Yj ) 8. c[i,j] = c[i-1,j-1] + 1 9. else c[i,j] = max( c[i-1,j], c[i,j-1] ) 10. return c
16
LCS Example What is the Longest Common Subsequence of X and Y?
We’ll see how LCS algorithm works on the following example: X = ABCB Y = BDCAB What is the Longest Common Subsequence of X and Y? LCS(X, Y) = BCB X = A B C B Y = B D C A B
17
LCS Example (0) ABCB BDCAB X = ABCB; m = |X| = 4
j i Yj B D C A B Xi A 1 B 2 3 C 4 B X = ABCB; m = |X| = 4 Y = BDCAB; n = |Y| = 5 Allocate array c[4,5]
18
LCS Example (1) ABCB BDCAB for i = 1 to m c[i,0] = 0
j i Yj B D C A B Xi A 1 B 2 3 C 4 B for i = 1 to m c[i,0] = 0 for j = 1 to n c[0,j] = 0
19
LCS Example (2) ABCB BDCAB j 0 1 2 3 4 5 i Yj B D C A B Xi A 1 B 2 3 C
A 1 B 2 3 C 4 B if ( Xi == Yj ) c[i,j] = c[i-1,j-1] + 1 else c[i,j] = max( c[i-1,j], c[i,j-1] )
20
LCS Example (3) ABCB BDCAB j 0 1 2 3 4 5 i Yj B D C A B Xi A 1 B 2 3 C
A 1 B 2 3 C 4 B if ( Xi == Yj ) c[i,j] = c[i-1,j-1] + 1 else c[i,j] = max( c[i-1,j], c[i,j-1] )
21
LCS Example (4) ABCB BDCAB j 0 1 2 3 4 5 i Yj B D C A B Xi A 1 1 B 2 3
A 1 1 B 2 3 C 4 B if ( Xi == Yj ) c[i,j] = c[i-1,j-1] + 1 else c[i,j] = max( c[i-1,j], c[i,j-1] )
22
LCS Example (5) ABCB BDCAB j 0 1 2 3 4 5 i Yj B D C A B Xi A 1 1 1 B 2
A 1 1 1 B 2 3 C 4 B if ( Xi == Yj ) c[i,j] = c[i-1,j-1] + 1 else c[i,j] = max( c[i-1,j], c[i,j-1] )
23
LCS Example (6) ABCB BDCAB j 0 1 2 3 4 5 i Yj B D C A B Xi A 1 1 1 B 2
A 1 1 1 B 2 1 3 C 4 B if ( Xi == Yj ) c[i,j] = c[i-1,j-1] + 1 else c[i,j] = max( c[i-1,j], c[i,j-1] )
24
LCS Example (7) ABCB BDCAB j 0 1 2 3 4 5 i Yj B D C A B Xi A 1 1 1 B 2
A 1 1 1 B 2 1 1 1 1 3 C 4 B if ( Xi == Yj ) c[i,j] = c[i-1,j-1] + 1 else c[i,j] = max( c[i-1,j], c[i,j-1] )
25
LCS Example (8) ABCB BDCAB j 0 1 2 3 4 5 i Yj B D C A B Xi A 1 1 1 B 2
A 1 1 1 B 2 1 1 1 1 2 3 C 4 B if ( Xi == Yj ) c[i,j] = c[i-1,j-1] + 1 else c[i,j] = max( c[i-1,j], c[i,j-1] )
26
LCS Example (10) ABCB BDCAB j 0 1 2 3 4 5 i Yj B D C A B Xi A 1 1 1 B
A 1 1 1 B 2 1 1 1 1 2 3 C 1 1 4 B if ( Xi == Yj ) c[i,j] = c[i-1,j-1] + 1 else c[i,j] = max( c[i-1,j], c[i,j-1] )
27
LCS Example (11) ABCB BDCAB j 0 1 2 3 4 5 i Yj B D C A B Xi A 1 1 1 B
A 1 1 1 B 2 1 1 1 1 2 3 C 1 1 2 4 B if ( Xi == Yj ) c[i,j] = c[i-1,j-1] + 1 else c[i,j] = max( c[i-1,j], c[i,j-1] )
28
LCS Example (12) ABCB BDCAB j 0 1 2 3 4 5 i Yj B D C A B Xi A 1 1 1 B
A 1 1 1 B 2 1 1 1 1 2 3 C 1 1 2 2 2 4 B if ( Xi == Yj ) c[i,j] = c[i-1,j-1] + 1 else c[i,j] = max( c[i-1,j], c[i,j-1] )
29
LCS Example (13) ABCB BDCAB j 0 1 2 3 4 5 i Yj B D C A B Xi A 1 1 1 B
A 1 1 1 B 2 1 1 1 1 2 3 C 1 1 2 2 2 4 B 1 if ( Xi == Yj ) c[i,j] = c[i-1,j-1] + 1 else c[i,j] = max( c[i-1,j], c[i,j-1] )
30
LCS Example (14) ABCB BDCAB j 0 1 2 3 4 5 i Yj B D C A B Xi A 1 1 1 B
A 1 1 1 B 2 1 1 1 1 2 3 C 1 1 2 2 2 4 B 1 1 2 2 if ( Xi == Yj ) c[i,j] = c[i-1,j-1] + 1 else c[i,j] = max( c[i-1,j], c[i,j-1] )
31
LCS Example (15) 3 ABCB BDCAB j 0 1 2 3 4 5 i Yj B D C A B Xi A 1 1 1
A 1 1 1 B 2 1 1 1 1 2 3 C 1 1 2 2 2 3 4 B 1 1 2 2 if ( Xi == Yj ) c[i,j] = c[i-1,j-1] + 1 else c[i,j] = max( c[i-1,j], c[i,j-1] )
32
LCS Algorithm Running Time
LCS algorithm calculates the values of each entry of the array c[m,n] So what is the running time? O(mn) since each c[i,j] is calculated in constant time, and there are mn elements in the array
33
How to find actual LCS For example, here
So far, we have just found the length of LCS, but not LCS itself. We want to modify this algorithm to make it output Longest Common Subsequence of X and Y Each c[i,j] depends on c[i-1,j] and c[i,j-1] or c[i-1, j-1] For each c[i,j] we can say how it was acquired: For example, here c[i,j] = c[i-1,j-1] +1 = 2+1=3 2 2 2 3
34
Finding LCS 3 ABCB BDCAB j 0 1 2 3 4 5 i Yj B D C A B Xi A 1 1 1 B 2 1
A 1 1 1 B 2 1 1 1 1 2 3 C 1 1 2 2 2 3 4 B 1 1 2 2
35
How to find actual LCS - continued
Remember that So we can start from c[m,n] and go backwards Whenever c[i,j] = c[i-1, j-1]+1, remember x[i] (because x[i] is a part of LCS) When i=0 or j=0 (i.e., we reached the beginning), output remembered letters in reverse order
36
Finding LCS (2) 3 B C B LCS (reversed order): B C B
j i Yj B D C A B Xi A 1 1 1 B 2 1 1 1 1 2 3 C 1 1 2 2 2 3 4 B 1 1 2 2 B C B LCS (reversed order): B C B (this string turned out to be a palindrome) LCS (straight order):
37
Properties of a problem that can be solved with dynamic programming
Simple Sub-problems We should be able to break the original problem to smaller sub-problems that have the same structure Optimal Substructure of the problems The solution to the problem must be a composition of sub-problem solutions Sub-problem Overlap Optimal sub-problems to unrelated problems can contain sub-problems in common
38
0-1 Knapsack problem Given a knapsack with maximum capacity W, and a set S consisting of n items Each item i has some weight wi and benefit value bi (all wi , bi and W are integer values) Problem: How to pack the knapsack to achieve maximum total value of packed items?
39
0-1 Knapsack problem: a picture
Weight Benefit value wi bi Items 2 3 This is a knapsack Max weight: W = 20 4 5 5 8 W = 20 3 4 9 10
40
0-1 Knapsack problem Problem, in other words, is to find The problem is called a “0-1” problem, because each item must be entirely accepted or rejected. Just another version of this problem is the “Fractional Knapsack Problem”, where we can take fractions of items.
41
0-1 Knapsack problem: brute-force approach
Let’s first solve this problem with a straightforward algorithm Since there are n items, there are 2n possible combinations of items. We go through all combinations and find the one with the most total value and with total weight less or equal to W Running time will be O(2n)
42
0-1 Knapsack problem: brute-force approach
Can we do better? Yes, with an algorithm based on dynamic programming We need to carefully identify the sub-problems Let’s try this: If items are labeled 1..n, then a sub-problem would be to find an optimal solution for Sk = {items labeled 1, 2, .. k}, where k ≤ n
43
Defining a Subproblem If items are labeled 1..n, then a sub-problem would be to find an optimal solution for Sk = {items labeled 1, 2, .. k} This is a valid sub-problem definition. The question is: can we describe the final solution (Sn ) in terms of sub-problems (Sk)? Unfortunately, we can’t do that. Explanation follows….
44
? Defining a Subproblem wi bi
Weight Benefit wi bi Item # 1 2 3 Max weight: W = 20 For S4: Total weight: 14; total benefit: 20 S4 2 4 5 Optimal Solution ? 3 5 8 4 3 4 5 9 10 w1 =2 b1 =3 w2=4 b2 =5 w3 =5 b3 =8 w5 =9 b5 =10 Solution for S4 is not part of the solution for the problem!!! Optimal Solution: Total weight: 20 total benefit: 26
45
Defining a Subproblem (continued)
As we have seen, the solution for S4 is not part of the solution for the problem So our definition of a sub-problem is flawed and we need another one! Let’s add another parameter: w, which will represent the remaining weight of the knapsack The sub-problem then will be to compute B[k,w]: maximum value in a knapsack with k item and remaining weight w
46
Recursive Formula for subproblems
It means, that the best subset of Sk that has total weight w is one of the two: 1) the best subset of Sk-1 that has total weight w, or 2) the best subset of Sk-1 that has total weight w-wk plus the value of item k
47
Recursive Formula The best subset of Sk that has the total weight w, either contains item k or not. First case: wk>w. Item k can’t be part of the solution, since if it was, the total weight would be > w, which is unacceptable Second case: wk <=w. Then the item k can be in the solution, and we choose the case with greater value
48
0-1 Knapsack Algorithm for w = 0 to W B[0,w] = 0 for i = 0 to n
B[i,0] = 0 if wi <= w // item i can be part of the solution if bi + B[i-1,w-wi] > B[i-1,w] B[i,w] = bi + B[i-1,w- wi] else B[i,w] = B[i-1,w] else B[i,w] = B[i-1,w] // wi > w
49
Remember that the brute-force algorithm takes O(2n)
Running time What is the running time of this algorithm? O(n*W) Remember that the brute-force algorithm takes O(2n)
50
Example (1) Let’s run our algorithm on the following data: n = 4 (# of elements) W = 5 (max weight) Elements (weight, benefit): (2,3), (3,4), (4,5), (5,6)
51
Example (2) i 1 2 3 4 W 1 2 3 4 5 for w = 0 to W B[0,w] = 0
52
Example (3) i 1 2 3 4 W 1 2 3 4 5 for i = 0 to n B[i,0] = 0
53
Example (4) Items: 1: (2,3) 2: (3,4) 3: (4,5) 4: (5,6) i=1 bi=3 wi=2
1 2 3 4 W i=1 bi=3 wi=2 w=1 w-wi =-1 1 2 3 4 5 if wi <= w // item i can be part of the solution if bi + B[i-1,w-wi] > B[i-1,w] B[i,w] = bi + B[i-1,w- wi] else B[i,w] = B[i-1,w] else B[i,w] = B[i-1,w] // wi > w
54
Example (5) Items: 1: (2,3) 2: (3,4) 3: (4,5) 4: (5,6) i=1 bi=3 wi=2
1 2 3 4 W i=1 bi=3 wi=2 w=2 w-wi =0 1 2 3 3 4 5 if wi <= w // item i can be part of the solution if bi + B[i-1,w-wi] > B[i-1,w] B[i,w] = bi + B[i-1,w- wi] else B[i,w] = B[i-1,w] else B[i,w] = B[i-1,w] // wi > w
55
Example (6) Items: 1: (2,3) 2: (3,4) 3: (4,5) 4: (5,6) i=1 bi=3 wi=2
1 2 3 4 W i=1 bi=3 wi=2 w=3 w-wi=1 1 2 3 3 3 4 5 if wi <= w // item i can be part of the solution if bi + B[i-1,w-wi] > B[i-1,w] B[i,w] = bi + B[i-1,w- wi] else B[i,w] = B[i-1,w] else B[i,w] = B[i-1,w] // wi > w
56
Example (7) Items: 1: (2,3) 2: (3,4) 3: (4,5) 4: (5,6) i=1 bi=3 wi=2
1 2 3 4 W i=1 bi=3 wi=2 w=4 w-wi=2 1 2 3 3 3 4 3 5 if wi <= w // item i can be part of the solution if bi + B[i-1,w-wi] > B[i-1,w] B[i,w] = bi + B[i-1,w- wi] else B[i,w] = B[i-1,w] else B[i,w] = B[i-1,w] // wi > w
57
Example (8) Items: 1: (2,3) 2: (3,4) 3: (4,5) 4: (5,6) i=1 bi=3 wi=2
1 2 3 4 W i=1 bi=3 wi=2 w=5 w-wi=2 1 2 3 3 3 4 3 5 3 if wi <= w // item i can be part of the solution if bi + B[i-1,w-wi] > B[i-1,w] B[i,w] = bi + B[i-1,w- wi] else B[i,w] = B[i-1,w] else B[i,w] = B[i-1,w] // wi > w
58
Example (9) Items: 1: (2,3) 2: (3,4) 3: (4,5) 4: (5,6) i=2 bi=4 wi=3
1 2 3 4 W i=2 bi=4 wi=3 w=1 w-wi=-2 1 2 3 3 3 4 3 5 3 if wi <= w // item i can be part of the solution if bi + B[i-1,w-wi] > B[i-1,w] B[i,w] = bi + B[i-1,w- wi] else B[i,w] = B[i-1,w] else B[i,w] = B[i-1,w] // wi > w
59
Example (10) Items: 1: (2,3) 2: (3,4) 3: (4,5) 4: (5,6) i=2 bi=4 wi=3
1 2 3 4 W i=2 bi=4 wi=3 w=2 w-wi=-1 1 2 3 3 3 3 4 3 5 3 if wi <= w // item i can be part of the solution if bi + B[i-1,w-wi] > B[i-1,w] B[i,w] = bi + B[i-1,w- wi] else B[i,w] = B[i-1,w] else B[i,w] = B[i-1,w] // wi > w
60
Example (11) Items: 1: (2,3) 2: (3,4) 3: (4,5) 4: (5,6) i=2 bi=4 wi=3
1 2 3 4 W i=2 bi=4 wi=3 w=3 w-wi=0 1 2 3 3 3 3 4 4 3 5 3 if wi <= w // item i can be part of the solution if bi + B[i-1,w-wi] > B[i-1,w] B[i,w] = bi + B[i-1,w- wi] else B[i,w] = B[i-1,w] else B[i,w] = B[i-1,w] // wi > w
61
Example (12) Items: 1: (2,3) 2: (3,4) 3: (4,5) 4: (5,6) i=2 bi=4 wi=3
1 2 3 4 W i=2 bi=4 wi=3 w=4 w-wi=1 1 2 3 3 3 3 4 4 3 4 5 3 if wi <= w // item i can be part of the solution if bi + B[i-1,w-wi] > B[i-1,w] B[i,w] = bi + B[i-1,w- wi] else B[i,w] = B[i-1,w] else B[i,w] = B[i-1,w] // wi > w
62
Example (13) Items: 1: (2,3) 2: (3,4) 3: (4,5) 4: (5,6) i=2 bi=4 wi=3
1 2 3 4 W i=2 bi=4 wi=3 w=5 w-wi=2 1 2 3 3 3 3 4 4 3 4 5 3 7 if wi <= w // item i can be part of the solution if bi + B[i-1,w-wi] > B[i-1,w] B[i,w] = bi + B[i-1,w- wi] else B[i,w] = B[i-1,w] else B[i,w] = B[i-1,w] // wi > w
63
Example (14) Items: 1: (2,3) 2: (3,4) 3: (4,5) 4: (5,6) i=3 bi=5 wi=4
1 2 3 4 W i=3 bi=5 wi=4 w=1..3 1 2 3 3 3 3 3 4 4 4 3 4 5 3 7 if wi <= w // item i can be part of the solution if bi + B[i-1,w-wi] > B[i-1,w] B[i,w] = bi + B[i-1,w- wi] else B[i,w] = B[i-1,w] else B[i,w] = B[i-1,w] // wi > w
64
Example (15) Items: 1: (2,3) 2: (3,4) 3: (4,5) 4: (5,6) i=3 bi=5 wi=4
1 2 3 4 W i=3 bi=5 wi=4 w=4 w- wi=0 1 2 3 3 3 3 3 4 4 4 3 4 5 5 3 7 if wi <= w // item i can be part of the solution if bi + B[i-1,w-wi] > B[i-1,w] B[i,w] = bi + B[i-1,w- wi] else B[i,w] = B[i-1,w] else B[i,w] = B[i-1,w] // wi > w
65
Example (15) Items: 1: (2,3) 2: (3,4) 3: (4,5) 4: (5,6) i=3 bi=5 wi=4
1 2 3 4 W i=3 bi=5 wi=4 w=5 w- wi=1 1 2 3 3 3 3 3 4 4 4 3 4 5 5 3 7 7 if wi <= w // item i can be part of the solution if bi + B[i-1,w-wi] > B[i-1,w] B[i,w] = bi + B[i-1,w- wi] else B[i,w] = B[i-1,w] else B[i,w] = B[i-1,w] // wi > w
66
Example (16) Items: 1: (2,3) 2: (3,4) 3: (4,5) 4: (5,6) i=3 bi=5 wi=4
1 2 3 4 W i=3 bi=5 wi=4 w=1..4 1 2 3 3 3 3 3 3 4 4 4 4 3 4 5 5 5 3 7 7 if wi <= w // item i can be part of the solution if bi + B[i-1,w-wi] > B[i-1,w] B[i,w] = bi + B[i-1,w- wi] else B[i,w] = B[i-1,w] else B[i,w] = B[i-1,w] // wi > w
67
Example (17) Items: 1: (2,3) 2: (3,4) 3: (4,5) 4: (5,6) i=3 bi=5 wi=4
1 2 3 4 W i=3 bi=5 wi=4 w=5 1 2 3 3 3 3 The greedy approach is not giving us the optimal value. 3 3 4 4 4 4 3 4 5 5 5 3 7 7 7 if wi <= w // item i can be part of the solution if bi + B[i-1,w-wi] > B[i-1,w] B[i,w] = bi + B[i-1,w- wi] else B[i,w] = B[i-1,w] else B[i,w] = B[i-1,w] // wi > w
68
Comments This algorithm only finds the max possible value that can be carried in the knapsack To know the items that make this maximum value, an addition to this algorithm is necessary Please see LCS algorithm from the previous lecture for the example how to extract this data from the table we built
69
Find Items Item (reversed order): i = 2, i = 1
1 2 3 4 W 1 2 3 3 3 3 3 3 4 4 4 4 3 4 5 5 5 3 7 7 7 Item (reversed order): i = 2, i = 1 Item (straight order): i=1, i = 2
70
Matrix Chain-Products
Review: Matrix Multiplication. C = A*B A is d × e and B is e × f O(def ) time A C B d f e i j i,j
71
Matrix Chain-Products
Compute A=A0*A1*…*An-1 Ai is di × di+1 Problem: How to parenthesize to minimize the number of operations? Example B is 3 × 100 C is 100 × 5 D is 5 × 5 (B*C)*D takes = 1575 ops B*(C*D) takes = 4000 ops
72
Enumeration Approach Brute-force Algorithm: Running time:
Try all possible ways to parenthesize A=A0*A1*…*An-1 Calculate number of ops for each one Pick the one that is best Running time: The number of parenthesizes is equal to the number of binary trees with n nodes This is exponential! It is called the Catalan number, and it is almost 4n. This is a terrible algorithm!
73
Greedy Approach Idea #1: repeatedly select the product that uses the fewest operations. Counter-example: A is 101 × 11 B is 11 × 9 C is 9 × 100 D is 100 × 99 Greedy idea #1 gives A*((B*C)*D)), which takes = ops (A*B)*(C*D) takes = ops The greedy approach is not giving us the optimal value.
74
Dynamic Programming Approach
The optimal solution can be defined in terms of optimal sub-problems There has to be a final multiplication (root of the expression tree) for the optimal solution. Say, the final multiplication is at index k: (A0*…*Ak)*(Ak+1*…*An-1). Let us consider all possible places for that final multiplication: There are n-1 possible splits. Assume we know the minimum cost of computing the matrix product of each combination A0…Ai and Ai…An. Let’s denote these as N0,i and Ni,n. Recall that Ai is a di × di+1 dimensional matrix, and the final product will be a d0 × dn.
75
Dynamic Programming Approach
Minimum cost of multiplying A0*…*An-1: Then the optimal solution N0,n-1 is the sum of two optimal sub-problems, N0,k and Nk+1,n-1 plus the time for the last multiplication.
76
Dynamic Programming Approach
Define sub-problems: Find the best parenthesization of an arbitrary set of consecutive products: Ai*Ai+1*…*Aj. Let Ni,j denote the minimum number of operations done by this sub-problem. Define Nk,k = 0 for all k. The optimal solution for the whole problem is then N0,n-1.
77
Dynamic Programming Approach
The characterizing equation for Ni,j is: Note that sub-problems are not independent. Also note that, for example N2,6 and N3,7, both need solutions to N3,6, N4,6, N5,6, and N6,6. Solutions from the set of no matrix multiplies to four matrix multiplies. This is an example of high sub-problem overlap, and clearly pre-computing these will significantly speed up the algorithm. A = A0 (3 * 100) * A1 (100 * 5) * A2 (5 * 5) N03 = min{(N00 + N12 + d0*d1*d3), (N01 + N22 + d0*d2*d3)} = min{( *5*5 + 3*100*5), (3*100* *5*5)} = min{4000, 1575} = 1575
78
Subproblem Overlap 1..4 1..1 2..4 1..2 3..4 1..3 4..4 2..2 1..1 2..2 3..3 4..4 ... 3..4 2..3 4..4 3..3 4..4 2..2 3..3
79
Recursive Approach We could implement the calculation of these Ni,j’s using a straight-forward recursive implementation of the equation Algorithm RecursiveMatrixChain(S, i, j): Input: sequence S of n matrices to be multiplied Output: number of operations in an optimal parenthesization of S if i=j then return 0 for k i to j do Ni, j min{Ni,j, RecursiveMatrixChain(S, i ,k) RecursiveMatrixChain(S, k+1,j) + di dk+1 dj+1} return Ni,j
80
Dynamic Programming Algorithm
High sub-problem overlap, with independent sub-problems indicate that a dynamic programming approach may work. Construct optimal sub-problems “bottom-up.” and remember them. Ni,i’s are easy, so start with them Then do problems of length 2,3,… sub-problems, and so on. Running time: O(n3) Algorithm matrixChain(S): Input: sequence S of n matrices to be multiplied Output: number of operations in an optimal parenthesization of S for i 1 to n - 1 do Ni,i 0 for b 1 to n - 1 do { b = j - i is the length of the problem } for i 0 to n - b - 1 do j i + b Ni,j + for k i to j - 1 do Ni,j min{Ni,j, Ni,k + Nk+1,j + di dk+1 dj+1} Mi,j ←k return N,M
81
Algorithm Visualization
The bottom-up construction fills in the N array by diagonals Ni,j gets values from previous entries in i-th row and j-th column Filling in each entry in the N table takes O(n) time. Total run time: O(n3) Getting actual parenthesization can be done by remembering “k” for each N entry answer N 1 2 i j … n-1 1 … i j n-1
82
Algorithm Visualization
A0: 30 * 35; A1: 35 * 15; A2: 15 * 5; A3: 5 * 10; A4: 10 * 20; A5: 20 * 25 d0 = 30; d1 = 35; d2 = 15; d3 = 5; d4 = 10; d5 = 20; d6 = 25;
83
Algorithm Visualization
(A0*(A1*A2))*((A3*A4)*A5) N M
84
Matrix Chain-Products
Some final thoughts We replaced a O(2n) algorithm with a O(n3) algorithm. While the generic top-down recursive algorithm would have solved O(2n) sub-problems, there are O(n2) sub-problems. Implies a high overlap of sub-problems. The sub-problems are independent: Solution to A0A1…Ak is independent of the solution to Ak+1…An.
85
Matrix Chain-Products Summary
Determine the cost of each pair-wise multiplication, then the minimum cost of multiplying three consecutive matrices (2 possible choices), using the pre-computed costs for two matrices. Repeat until we compute the minimum cost of all n matrices using the costs of the minimum n-1 matrix product costs. n-1 possible choices.
86
Dynamic Programming Steps
A Dynamic Programming approach consists of a sequence of 4 steps: Characterize the structure of an optimal solution Recursively define the value of an optimal solution Computer the value of an optimal solution in a bottom-up fashion Construct an optimal solution from computer information
87
Dynamic Programming Summary
Summary of the basic idea: Optimal substructure: optimal solution to problem consists of optimal solutions to sub-problems Overlapping sub-problems: few sub-problems in total, many recurring instances of each Solve bottom-up, building a table of solved sub-problems that are used to solve larger ones Variations: “Table” could be 3-dimensional, triangular, a tree, etc.
88
Conclusion Dynamic programming is a useful technique of solving certain kind of problems When the solution can be recursively described in terms of partial solutions, we can store these partial solutions and re-use them as necessary Running time (Dynamic Programming algorithm vs. naïve algorithm): LCS: O(mn) vs. O(n2m) 0-1 Knapsack problem: O(Wn) vs. O(2n) Matrix Chain-Products: O(n3) vs. O(2n)
Similar presentations
© 2024 SlidePlayer.com Inc.
All rights reserved.