====== Chapter 6 – Dynamic Programming ====== My notes on the assigned sections of Chapter 6 of Algorithm Design by Jon Kleinberg and Éva Tardos. This chapter details dynamic programming. Dynamic programming involves "operating dangerously close to the edge of a brute-force search: although it's systematically working through the exponentially large set of possible solutions to the problem, it does this without ever examining them all explicitly." This is usually achieved with memoization. ===== 6.1 – Weighted Interval Scheduling: A Recursive Procedure ===== The weighted interval scheduling problem can be designed with a simple recursive approach. opt(j) = max(vj + opt(p(j)), opt(j-1)). We know that request j bleongs to an optimal solution on the set {1,2,...,j} if an only if vj + opt(p(j)) >= opt(j-1). Also, Compute-Opt(j) correctly computes OPT(j) for each j = 1,2,...,n. Adding in memoization can reduce the redundancy in all the Compute-Opt calls, storing the calls at certain values. This memoization marks the dynamic programming solution to weighted interval scheduling. Input: n jobs (associated start time sj, finish time fj, and value vj) Sort jobs by finish times so that f1 ≤ f2 ≤ ... ≤ fn Compute p(1), p(2), …, p(n) for j = 1 to n M[j] = empty M[0] = 0 M-Compute-Opt(j): if M[j] is empty: M[j] = max(vj + M-Compute-Opt(p(j)), M-Compute-Opt(j-1)) return M[j] M-Compute-Opt(n) Overall, I'd give this section a 7/10 on readability and interestingness. ===== 6.2 – Principles of Dynamic Programming: Memoization or Iteration over Subproblems ===== Basic Outline of Dynamic Programming: - There's a polynomial number of subproblems. - The original problem's solution can easily be computed from the subproblems' solutions. - There's an ordering of the subproblems from smallest to largest with a simply computable recurrence. There is a sort-of chicken and egg relationship between subproblems and recurrences in dynamic programming. It isn't clear that a collection of subproblems will be useful until you find the linking recurrence. However, it can also be difficult thinking about recurrences without their subproblems. Overall I'd give this section a 10/10 on readability and a 8/10 on interestingness. ===== 6.3 – Segmented Least Squares: Multi-way Choices ===== This problem arises from the need to fit a line to some data points to achieve a "best fit." What needs to be optimized is the fewest number of best fit lines possible to achieve the best fit. There are a lot of repeated checks of each point's error in a naive, brute-force solution. These checks can be memoized. The following implementation in the below two methods incorporate memoization to achieve a dynamic programming solution. INPUT: n, p1,…,pn , c Segmented-Least-Squares() M[0] = 0 e[0][0] = 0 for j = 1 to n for i = 1 to j e[i][j] = least square error for the segment pi,…, pj for j = 1 to n M[j] = min 1 ≤ i ≤ j (e[i][j] + c + M[i-1]) return M[n] FindSegments(j): if j = 0: output nothing else: Find an i that minimizes ei,j + c + M[i-1] Output the segment {pi,...pj} FindSegments(i-1) Overall, I'd give this section a 9/10 on readability and interestingness.