260 likes | 281 Views
Learn about dynamic programming techniques for optimization problems, including greedy algorithms and matrix-chain multiplication. Discover how to find optimal solutions and improve on backtracking. Study the structure of optimal solutions and subproblems in detail.
E N D
Algorithms (2IL15) – Lecture 3 DYNAMIC PROGRAMMING 0 0 0 0 0 0 0 0 0 0
Optimization problems • for each instance there are (possibly) multiple valid solutions • goal is to find an optimal solution • minimization problem: • associate cost to every solution, find min-cost solution • maximization problem: • associate profit to every solution, find max-profit solution
Techniques for optimization optimization problems typically involve making choices backtracking: just try all solutions • can be applied to almost all problems, but gives very slow algorithms • try all options for first choice, for each option, recursively make other choices greedy algorithms: construct solution iteratively, always make choice that seems best • can be applied to few problems, but gives fast algorithms • only try option that seems best for first choice (greedy choice), recursively make other choices dynamic programming • in between: not as fast as greedy, but works for more problems
Algorithms for optimization: how to improve on backtracking for greedy algorithms • try to discover structure of optimal solutions: what properties do optimal solutions have ? • what are the choices that need to be made ? • do we have optimal substructure ? optimal solution = first choice + optimal solution for subproblem • do we have greedy-choice property for the first choice ? what if we do not have a good greedy choice? then we can often use dynamic programming
Dynamic programming: examples • maximum weight independent set (non-adjacent vertices) in path graph • optimal matrix-chain multiplication: today • more examples in book and next week 1 4 5 4
Matrix-chain multiplication Input:n matrices A1, A2, …, An Required output:A1• A2 • … • An multiplying two matrices b c c = a a b a x b matrix a x c matrix b x c matrix cost = a∙b∙c scalar multiplications = Θ(a∙b∙c ) time
Matrix-chain mutiplication Multiplying three matrices: A • B • C 2 x 10 10 x 50 50 x 20 • Does it matter in which order we multiply? • Note for answer: (A•B)•C = A•(B•C) matrix multiplication is associative: • What about the cost? • (A•B)•C costs (2∙10∙50) + (2∙50∙20) = 3,000 scalar multiplications • A•(B•C) costs (10∙50∙20) + (2∙10∙20) = 10,400 scalar multiplications
Matrix-chain multiplication: the optimization problem Input:n matrices A1, A2, …, An, where Ai is pi-1 x pimatrix In fact: we only need p0, … ,pn as input Required output: an order to multiply the matrices minimizing the cost in other words: the best way to place brackets So we have valid solution = complete parenthesization: ((A1 • A2) • (A3 •(A4 •(A5 • A6)))) cost = total number of scalar multiplications needed to multiply according to the given parenthesization
Let’s study the structure of an optimal solution • what are the choices that need to be made? • what are the subproblems that remain? do we have optimal substructure? optimal solution (A1•(A2 • A3 ) ) • ((A4• A5) •(A6 • A7) ) choice: final multiplication optimal way to multiply A1,…, A3 optimal way to multiply A4,…, A7 optimal substructure: optimal solution is composed of optimal solutions to subproblems of same type as original problem necessary for dynamic programming (and for greedy)
Let’s study the structure of an optimal solution • what are the choices that need to be made? • what are the subproblems that remain? do we have optimal substructure? optimal solution (A1•(A2 • A3 ) ) • ((A4• A5) •(A6 • A7) ) choice: final multiplication Do we have a good greedy choice ? no … then what to do? try all possible options for position of final multiplication
Approach: • try all possible options for final multiplication • for each option recursively solve subproblems Need to specify exactly what the subproblems are initial problem: compute A1•… • An in cheapest way (A1•… • Ak ) • (Ak+1 • … •An ) subproblem: compute A1•… • Ak in cheapest way (A1•… • Ai) • (Ai+1 • … •Ak ) subproblem: compute Ai+1•… • Ak in cheapest way general form: given i,j with 1≤i<j ≤n, compute Ai•… • Aj in cheapest way
Now let’s prove that we indeed have optimal substructure Subproblem:given i,j with 1≤i<j ≤n, compute Ai•… • Aj in cheapest way Define m [ i, j ] = value of optimal solution to subproblem = minimum cost to compute Ai•… • Aj Lemma:m [i,j ] = 0 if i = j min{ m [i,k ] + m [k+1,j ] + pi-1 pk pj }if i < j i≤k<j optimal solution composed of optimal solutions to subproblems but we don’t know the best way to decompose into subproblems
Lemma:m [i,j ] = 0 if i = j min{ m [i,k ] + m [k+1,j ] + pi-1 pk pj }if i < j Proof: i=j:trivial i<j : Consider optimal solution OPT for computing Ai• .. • Ajand let k* be the index suchthat OPT has the form (Ai• .. • Ak* ) • (Ak*+1• ..• Aj ). Then m [ i,j ] = (cost in OPT for Ai• .. • Ak* ) + (cost in OPT for Ak*+1• .. • An) + pi-1 pk* pj ≥ m [i,k* ] + m [k*+1,j ] + pi-1 pk* pj ≥ min{ m [i,k ] + m [k+1,j ] + pi-1 pk pj } On the other hand, for any i ≤ k <j, there is a solution of costm [i,k ] + m [k+1,j ] + pi-1 pk pj som [ i,j ] ≤ min{ m [i,k ] + m [k+1,j ] + pi-1 pk pj }. i≤k<j i≤k<j i≤k<j “cut-and-paste” argument: replace solution that OPT uses for subproblem by optimal solution to subproblem, without making overall solution worse.
Lemma:m [i,j ] = 0 if i = j min{ m [i,k ] + m [k+1,j ] + pi-1 pk pj }if i < j i≤k<j initial call:RMC(p[0..n],1,n) RMC (p,i, j ) \\ RMC (RecursiveMatrixChain) determines min cost for computing Ai• … • Aj \\ p [0..n] is array such that Ai = p[i-1] x p[i ] matrix • if i = j • then • cost←0 • else • cost ← ∞ • for k ← i to j-1 • do cost ← min(cost, RMC(p,i,k) + RMC(p,k+1,j) + pi-1 pk pj ) • return cost
Correctness: by induction and lemma on optimal substructure Analysis of running time: Define T(m) = worst-case running time of RMC(i,j), where m =j - i +1. Then: T(m) = Θ(1) if m = 1 Θ(1) + ∑1≤s<m{T(s) + T(m-s) + Θ(1) }if m >1 Claim: T(m) = Ω (2m) Proof: by induction (exercise) Algorithm is faster than completely brute-force, but still very slow …
Why is the algorithm so slow? (1,n) (1,1) (2,n) (1,2) (3,n) (1,3) (4,n) … (1,n-1) (n,n) (2,2) (3,n) (2,3) (4,n) … (2,n-1) (n,n) (3,3) (4,n) … recursive calls overlapping subproblems, so same subproblem is solved many times optimal substructure + overlapping subproblems: then you can often use dynamic programming
How many different subproblems are there? (1,n) (1,1) (2,n) (1,2) (3,n) (1,3) (4,n) … (1,n-1) (n,n) (2,2) (3,n) (2,3) (4,n) … (2,n-1) (n,n) (3,3) (4,n) … recursive calls subproblem: given i,j with 1≤i<j ≤n, compute Ai•… • Aj in cheapest way number of subproblems = Θ (n2)
0 0 0 0 0 0 0 0 j 1 n 1 Fill in the table in an order so that the entries needed to compute a new entry are already available. i or or … n Lemma:m [i,j ] = 0 if i = j min{ m [i,k ] + m [k+1,j ] + pi-1 pk pj }if i < j i≤k<j Idea: fill in the values m [i,j ] in a table (that is, an array) m [1..n,1..n] value of optimal solution to original problem 0 0
Lemma:m [i,j ] = 0 if i = j min{ m [i,k ] + m [k+1,j ] + pi-1 pk pj }if i < j i≤k<j MatrixChainDP( p [0..n] ) \\ algorithm uses two-dimensional table (array) m[1..n,1..n] to store values of solutions to subproblems • for i ← 1 ton • do m[i,i] ← 0 • for i ← n-1 downto1 • do for j ← i +1 ton • do m[i,j] ← min { m[i,k] + m[k+1,j] + pi-1 pk pj } • return m[1,n] i≤k<j
Θ(n) Analysis of running time MatrixChainDP( p [0..n] ) • for i ← 1 ton • do m[i,i] ← 0 • for i ← n-1 downto1 • do for j ← i +1 ton • do m[i,j] ← min { m[i,k] + m[k+1,j] + pi-1 pk pj } • return m[1,n] i≤k<j Θ(1) ∑ 1≤i≤n-1∑ i+1≤j≤nΘ(j-i) = ∑ 1≤i≤n-1∑ 1≤j≤n-iΘ(j) = ∑ 1≤i≤n-1Θ((n-i)2) = ∑ 1≤i≤n-1Θ(i2) = Θ(n3) for each of the O(n2) cells we spend O(n) time
m [i,j ] = 0 if i = j min{ m [i,k ] + m [k+1,j ] + pi-1 pk pj }if i< j i≤k<j Designing dynamic-programming algorithms • Investigate structure of optimal solution: do we have optimal substructure, no greedy choice, and overlapping subproblems? • Give recursive formula for the value of an optimal solution • define subproblem in terms of a few parameters • define variable m[..] = value of optimal solution for subproblem • give recursive formula for m[..] • Algorithm: fill in table for m[..] in suitable order • Extend algorithm so that it computes an actual solution that is optimal, and not just the value of an optimal solution given i,j with 1≤i<j ≤n, compute Ai•… • Aj in cheapest way m [i,j ] =minimum cost to compute Ai•… • Aj
Extend algorithm so that it computes an actual solution that is optimal, and not just the value of an optimal solution • introduce extra table that remembers choices leading to optimal solution m [i,j ] = minimum cost to compute Ai•…• Aj s [i,j ] = index k such that there is an optimal solution of the form (Ai•…• Ak) • (Ak+1•…•Aj ) • modify algorithm such that it also fills in the new table • write another algorithm that computes an optimal solution by walking “backwards” through the new table value of opt choice leading to opt
MatrixChainDP( p [0..n] ) • for i ← 1 ton • do m[i,i] ← 0 • for i ← n-1 downto1 • do for j ← i +1 ton • do m[i,j] ← min { m[i,k] + m[k+1,j] + pi-1 pk pj } • return m[1,n] i≤k<j m[i,j] ← ∞ for k ← i to j-1 do begin cost ← m[i,k] + m[k+1,j] + pi-1 pk pj if cost < m[i,j] then m[i,j] ← cost end s[i,j] ← k
s[i,j ] = index k such that there is an optimal solution of the form (Ai•…• Ak ) • (Ak+1•…•Aj ) to compute Ai•…• Aj PrintParentheses ( i, j ) • if i = j • then print “Ai” • else begin • print “(“ • PrintParentheses ( i, s[i,j ] ) • PrintParentheses ( s[i,j ]+1, j ) • print “)” • end
if m[i,j] < ∞ then return m[i,j] elselines 4 – 7 Alternative to filling in table in suitable order: memoization recursive algorithm, but remember which subproblems have been solved already initialize array m[i,j] (global variable): m[i,j] = ∞ for all 1 ≤ i,j ≤ n RMC(i,j) if i = j • then • return 0 • else • cost ← ∞ • for k ← i to j-1 • do cost ← min(m, RMC(i,k) + RMC(k+1,j) + pi-1 pk pj ) • return cost m[i,j] ← cost
Summary dynamic programming • Investigate structure of optimal solution: do we have optimal substructure, no greedy choice, and overlapping subproblems? • Give recursive formula for the value of an optimal solution • define subproblem in terms of a few parameters • define variable m[..] = value of optimal solution for subproblem • give recursive formula for m[..] • Algorithm: fill in table for m[..] in suitable order • Extend algorithm so that it computes an actual solution that is optimal, and not just the value of an optimal solution next week more examples of dynamic programming