KEMBAR78
Algorithm chapter 8 | PDF
Dynamic Programming
Dynamic Programming
  Dynamic Programming is a general algorithm design technique.
“Programming” here means “planning”.
  Invented by American mathematician Richard Bellman in the 1950s to
solve optimization problems
  Main idea:
      solve several smaller (overlapping) subproblems
      record solutions in a table so that each subproblem is only solved
    once
      final state of the table will be (or contain) solution
  Dynamic programming vs. divide-and-conquer
      partition a problem into overlapping subproblems and
    independent ones
      store and not store solutions to subproblems
Example: Fibonacci numbers
• Recall definition of Fibonacci numbers:
    f(0) = 0
    f(1) = 1
    f(n) = f(n-1) + f(n-2)
• Computing the nth Fibonacci number recursively (top-down):

                           f(n)

         f(n-1)            +               f(n-2)

f(n-2)    +       f(n-3)          f(n-3)     +      f(n-4)
                    ...
Example: Fibonacci numbers
    Computing the nth fibonacci number
    using bottom-up iteration:
• f(0) = 0
• f(1) = 1
• f(2) = 0+1 = 1
• f(3) = 1+1 = 2
• f(4) = 1+2 = 3           ALGORITHM Fib(n)
• f(5) = 2+3 = 5           F[0]    0, F[1]    1
•                          for i 2 to n do
•                                  F[i]    F[i-1] + F[i-2]
•                          return F[n]
• f(n-2) =
• f(n-1) =                 extra space
• f(n) = f(n-1) + f(n-2)
Examples of Dynamic Programming
             Algorithms

  Computing binomial coefficients

  Warshall’s algorithm for transitive closure

  Floyd’s algorithms for all-pairs shortest paths

  Constructing an optimal binary search tree

  Some instances of difficult discrete optimization
problems:
     knapsack
Computing Binomial Coefficients

  A binomial coefficient, denoted C(n, k), is the number of
  combinations of k elements from an n-element set (0 ≤ k ≤ n).
  Recurrence relation (a problem 2 overlapping problems)
     C(n, k) = C(n-1, k-1) + C(n-1, k), for n > k > 0, and
     C(n, 0) = C(n, n) = 1
  Dynamic programming solution:
     Record the values of the binomial coefficients in a table of n+1
     rows and k+1 columns, numbered from 0 to n and 0 to k
      respectively.
  1
  1    1
  1    2     1
  1    3     3        1
  1    4     6    4       1
  1    5    10    10      5   1
  …
Transitive Closure
The transitive closure of a directed graph with n vertices can be
   defined as the nxn matrix T = {tij}, in which the element in the
   ith row (1 ≤ i ≤ n) and the jth column (1 ≤ j ≤ n) is 1 if there
   exists a nontrivial directed path (i.e., a directed path of a positive
   length) from the ith vertex to the jth vertex; otherwise, tij is 0.

Graph traversal-based algorithm and Warshall’s algorithm

               3                                      3
   1                                      1



                     4                                      4          0   0   1   0
       2                  0   0   1   0       2
                          1   0   0   1                                1   1   1   1
                          0   0   0   0                                0   0   0   0
       Adjacency matrix                                                1   1   1   1
                          0   1   0   0           Transitive closure
Warshall’s Algorithm
• Main idea: Use a bottom-up method to construct the transitive closure of a given
digraph with n vertices through a series of nxn boolean matrices:
                     R(0),…, R(k-1), R(k) , …, R(n)
The question is: how to obtain R(k) from R(k-1) ?

                                                  R(k) : rij(k) = 1 in R(k) , iff
                                                         there   is an edge from i to j; or
                                                         there   is a path from i to j going through vertex 1; or
                                                         there   is a path from i to j going through vertex 1 and/or 2; or
                                                        ...
                                                         there   is a path from i to j going through 1, 2, … and/or k

                 3                            3                           3                           3                              3
 1                            1                            1                           1                              1


                         4                         4                            4                             4           2                  4
     2                            2                            2                           2
          R(0)                     R(1)                        R(2)                            R(3)                           R(4)
 0       0 1     0                 0 0    1   0                0 0    1   0                    0 0    1   0                   0 0    1   0
 1       0 0     1                 1 0    1   1                1 0    1   1                    1 0    1   1                   1 1    1   1
 0       0 0     0                 0 0    0   0                0 0    0   0                    0 0    0   0                   0 0    0   0
 0       1 0     0                 0 1    0   0                1 1    1   1                    1 1    1   1                   1 1    1   1
Does not allow an              Allow 1 to be an  Allow 1,2 to be an                 Allow 1,2,3 to be an          Allow 1,2,3,4 to be an
intermediate node              intermediate node intermediate node                  intermediate node             intermediate node
Warshall’s Algorithm
In the kth stage: to determine R(k) is to determine if a path exists
between two vertices i, j using just vertices among 1,…,k



          {
rij(k) = 1:
                rij(k-1) = 1
                   or
                                             (path using just 1 ,…,k-1)


              (rik(k-1) = 1 and rkj(k-1)) = 1 (path from i to k
                                                       and from k to i
                                                       using just 1 ,…,k-1)
                     k
                          kth stage
i
                          Rule to determine whether rij (k) should be 1 in R(k) :

                          • If an element rij is 1 in R(k-1) , it remains 1 in R(k) .

                j         • If an element rij is 0 in R(k-1) ,it has to be changed
                          to 1 in R(k) iff the element in its row i and column k
                          and the element in its column j and row k are both
                          1’s in R(k-1).
Floyd’s Algorithm: All pairs shortest paths

 All pairs shortest paths problem: In a weighted graph,
                                                                  dij(k) = length of the
find shortest paths between every pair of vertices.               shortest path from i to
                                                                  j with each vertex
Applicable to: undirected and directed weighted graphs;           numbered no higher
no negative weight.                                               than k.
Same idea as the Warshall’s algorithm : construct
solution through series of matrices D(0) , D(1), …, D(n)

Example:
           4       3             0 ∞   4   ∞                0 ∞   4   ∞
   1                             1 0   6   3                1 0   5   3
                       1         ∞ ∞   0   ∞
           6                                                ∞ ∞   0   ∞
  1            5                 ∞ 5   1   0                6 5   1   0

                           4
       2       3               weight matrix               distance matrix
Floyd’s Algorithm
D(k) : allow 1, 2, …, k to be intermediate vertices.
In the kth stage, determine whether the introduction of k as a new eligible
intermediate vertex will bring about a shorter path from i to j.

dij(k) = min{dij(k-1) , dik(k-1) + dkj(k-1} for k ≥ 1, dij(0) = wij

                         dik(k-1)
                                               k
                  i
                                    dkj(k-1)       kth stage

                      dij(k-1)
                                        j
General Comments
The crucial step in designing a dynamic
programming algorithm:
  Deriving a recurrence relating a solution to
  the problem’s current instance with
  solutions of its smaller ( and overlapping)
  subinstances.
The Knapsack Problem and Memory
             Functions (1)
The problem
  Find the most valuable subset of the given n
  items that fit into a knapsack of capacity W.
Consider the following subproblem P(i, j)
  Find the most valuable subset of the first i items
  that fit into a knapsack of capacity j, where 1 ≤ i ≤
  n, and 1≤ j ≤ W
  Let V[i, j] be the value of an optimal solution to
  the above subproblem P(i, j). Goal: V[n, W]
  The question: What is the recurrence relation that
  expresses a solution to this instance in terms of
  solutions to smaller subinstances?
The Knapsack Problem and Memory
                 Functions (2)
The Recurrence
  Two possibilities for the most valuable subset
  for the subproblem P(i, j)
     It does not include the ith item: V[i, j] = V[i-1, j]
     It includes the ith item: V[i, j] = vi+ V[i-1, j – wi]

V[i, j] =   max{V[i-1, j], vi+ V[i-1, j – wi] }, if j – wi ≥ 0
            {            V[i-1, j]              if j – wi < 0

V[0, j] = 0 for j ≥ 0 and V[i, 0] = 0 for i ≥ 0
Memory Functions
   Memory functions: a combination of the top-down and bottom-
   up method. The idea is to solve the subproblems that are
   necessary and do it only once.
       Top-down: solve common subproblems more than once.
       Bottom-up: Solve subproblems whose solution are not necessary
       for the solving the original problem.

ALGORITHM MFKnapsack(i, j)
if V[i, j] < 0 //if subproblem P(i, j) hasn’t been solved yet.
    if j < Weights[i]
            value     MFKnapsack(i – 1, j)
    else
            value max(MFKnapsack(i – 1, j),
                              values[I] + MFKnapsck( i – 1, j – Weights[i]))
    V[i, j]     value
return V[i, j]

Algorithm chapter 8

  • 1.
  • 2.
    Dynamic Programming Dynamic Programming is a general algorithm design technique. “Programming” here means “planning”. Invented by American mathematician Richard Bellman in the 1950s to solve optimization problems Main idea: solve several smaller (overlapping) subproblems record solutions in a table so that each subproblem is only solved once final state of the table will be (or contain) solution Dynamic programming vs. divide-and-conquer partition a problem into overlapping subproblems and independent ones store and not store solutions to subproblems
  • 3.
    Example: Fibonacci numbers •Recall definition of Fibonacci numbers: f(0) = 0 f(1) = 1 f(n) = f(n-1) + f(n-2) • Computing the nth Fibonacci number recursively (top-down): f(n) f(n-1) + f(n-2) f(n-2) + f(n-3) f(n-3) + f(n-4) ...
  • 4.
    Example: Fibonacci numbers Computing the nth fibonacci number using bottom-up iteration: • f(0) = 0 • f(1) = 1 • f(2) = 0+1 = 1 • f(3) = 1+1 = 2 • f(4) = 1+2 = 3 ALGORITHM Fib(n) • f(5) = 2+3 = 5 F[0] 0, F[1] 1 • for i 2 to n do • F[i] F[i-1] + F[i-2] • return F[n] • f(n-2) = • f(n-1) = extra space • f(n) = f(n-1) + f(n-2)
  • 5.
    Examples of DynamicProgramming Algorithms Computing binomial coefficients Warshall’s algorithm for transitive closure Floyd’s algorithms for all-pairs shortest paths Constructing an optimal binary search tree Some instances of difficult discrete optimization problems: knapsack
  • 6.
    Computing Binomial Coefficients A binomial coefficient, denoted C(n, k), is the number of combinations of k elements from an n-element set (0 ≤ k ≤ n). Recurrence relation (a problem 2 overlapping problems) C(n, k) = C(n-1, k-1) + C(n-1, k), for n > k > 0, and C(n, 0) = C(n, n) = 1 Dynamic programming solution: Record the values of the binomial coefficients in a table of n+1 rows and k+1 columns, numbered from 0 to n and 0 to k respectively. 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1 …
  • 7.
    Transitive Closure The transitiveclosure of a directed graph with n vertices can be defined as the nxn matrix T = {tij}, in which the element in the ith row (1 ≤ i ≤ n) and the jth column (1 ≤ j ≤ n) is 1 if there exists a nontrivial directed path (i.e., a directed path of a positive length) from the ith vertex to the jth vertex; otherwise, tij is 0. Graph traversal-based algorithm and Warshall’s algorithm 3 3 1 1 4 4 0 0 1 0 2 0 0 1 0 2 1 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 Adjacency matrix 1 1 1 1 0 1 0 0 Transitive closure
  • 8.
    Warshall’s Algorithm • Mainidea: Use a bottom-up method to construct the transitive closure of a given digraph with n vertices through a series of nxn boolean matrices: R(0),…, R(k-1), R(k) , …, R(n) The question is: how to obtain R(k) from R(k-1) ? R(k) : rij(k) = 1 in R(k) , iff there is an edge from i to j; or there is a path from i to j going through vertex 1; or there is a path from i to j going through vertex 1 and/or 2; or ... there is a path from i to j going through 1, 2, … and/or k 3 3 3 3 3 1 1 1 1 1 4 4 4 4 2 4 2 2 2 2 R(0) R(1) R(2) R(3) R(4) 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 1 0 0 1 1 0 1 1 1 0 1 1 1 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1 Does not allow an Allow 1 to be an Allow 1,2 to be an Allow 1,2,3 to be an Allow 1,2,3,4 to be an intermediate node intermediate node intermediate node intermediate node intermediate node
  • 9.
    Warshall’s Algorithm In thekth stage: to determine R(k) is to determine if a path exists between two vertices i, j using just vertices among 1,…,k { rij(k) = 1: rij(k-1) = 1 or (path using just 1 ,…,k-1) (rik(k-1) = 1 and rkj(k-1)) = 1 (path from i to k and from k to i using just 1 ,…,k-1) k kth stage i Rule to determine whether rij (k) should be 1 in R(k) : • If an element rij is 1 in R(k-1) , it remains 1 in R(k) . j • If an element rij is 0 in R(k-1) ,it has to be changed to 1 in R(k) iff the element in its row i and column k and the element in its column j and row k are both 1’s in R(k-1).
  • 10.
    Floyd’s Algorithm: Allpairs shortest paths All pairs shortest paths problem: In a weighted graph, dij(k) = length of the find shortest paths between every pair of vertices. shortest path from i to j with each vertex Applicable to: undirected and directed weighted graphs; numbered no higher no negative weight. than k. Same idea as the Warshall’s algorithm : construct solution through series of matrices D(0) , D(1), …, D(n) Example: 4 3 0 ∞ 4 ∞ 0 ∞ 4 ∞ 1 1 0 6 3 1 0 5 3 1 ∞ ∞ 0 ∞ 6 ∞ ∞ 0 ∞ 1 5 ∞ 5 1 0 6 5 1 0 4 2 3 weight matrix distance matrix
  • 11.
    Floyd’s Algorithm D(k) :allow 1, 2, …, k to be intermediate vertices. In the kth stage, determine whether the introduction of k as a new eligible intermediate vertex will bring about a shorter path from i to j. dij(k) = min{dij(k-1) , dik(k-1) + dkj(k-1} for k ≥ 1, dij(0) = wij dik(k-1) k i dkj(k-1) kth stage dij(k-1) j
  • 12.
    General Comments The crucialstep in designing a dynamic programming algorithm: Deriving a recurrence relating a solution to the problem’s current instance with solutions of its smaller ( and overlapping) subinstances.
  • 13.
    The Knapsack Problemand Memory Functions (1) The problem Find the most valuable subset of the given n items that fit into a knapsack of capacity W. Consider the following subproblem P(i, j) Find the most valuable subset of the first i items that fit into a knapsack of capacity j, where 1 ≤ i ≤ n, and 1≤ j ≤ W Let V[i, j] be the value of an optimal solution to the above subproblem P(i, j). Goal: V[n, W] The question: What is the recurrence relation that expresses a solution to this instance in terms of solutions to smaller subinstances?
  • 14.
    The Knapsack Problemand Memory Functions (2) The Recurrence Two possibilities for the most valuable subset for the subproblem P(i, j) It does not include the ith item: V[i, j] = V[i-1, j] It includes the ith item: V[i, j] = vi+ V[i-1, j – wi] V[i, j] = max{V[i-1, j], vi+ V[i-1, j – wi] }, if j – wi ≥ 0 { V[i-1, j] if j – wi < 0 V[0, j] = 0 for j ≥ 0 and V[i, 0] = 0 for i ≥ 0
  • 15.
    Memory Functions Memory functions: a combination of the top-down and bottom- up method. The idea is to solve the subproblems that are necessary and do it only once. Top-down: solve common subproblems more than once. Bottom-up: Solve subproblems whose solution are not necessary for the solving the original problem. ALGORITHM MFKnapsack(i, j) if V[i, j] < 0 //if subproblem P(i, j) hasn’t been solved yet. if j < Weights[i] value MFKnapsack(i – 1, j) else value max(MFKnapsack(i – 1, j), values[I] + MFKnapsck( i – 1, j – Weights[i])) V[i, j] value return V[i, j]