CS 460, Lab 6 solutions Chapter 6 2. (a) The given algorithm fails for the following schedule: week 1 Low 5 High 0 2 5 11 3 5 20 4 5 0 5 5 12 The algorithm picks high in week 2, low in week 3, and high in week 5, total = 28 Optimal is low in week 1, high in week 3, high in week 5, total = 37 (b) This is a straightforward dynamic program. The recurrence is as follows: opt(j) = max( Hj + opt(j-2), Lj + opt(j-1)). opt(1) = max(H1, L1), opt(0) = 0 So the algorithm is to build the array opt, with opt(0) and opt(1) initialized and starting from j=2. We can also keep an array, Job, indicating whether we choose Lj or Hj for each step to facilitate rebuilding the sequence of choices. for(j = 2 to n) if(Hj + opt(j-2) > Lj + opt(j-1)) opt(j) = Hj + opt(j-2); Job(j) = H else opt(j) = Lj + opt(j-1); Job(j) = L When done, opt(n) is the optimum value and the sequence can be traced back using the Job array. For the above example, the results of the algorithm would be as follows: Week: 0 Opt: 0 Job: - 1 5 L 2 11 H 3 25 H 4 30 L 5 37 H The proof that the algorithm yields the optimum is the obvious induction argument. It is true for opt(0) and opt(1). Assume that it is true for all k < j, then the recurrence simply defines the optimum for j. By induction, opt(j) yields the optimum for all j >= 1. Time is O(n), since the loop runs over n periods and has constant time for each loop. The back trace also takes n or fewer steps. 3. (a) The given greedy algorithm fails for the following example. v1 v2 v3 v4 v5 v6 v7 v8 The greedy algorithm finds the path v1-v2-v6-v7-v8, with length 4, while the optimum is the path v1-v4-v5-v6-v7-v8 with length 5. (b) The algorithm is based on the recurrence, for a digraph G = (V, E): opt(j) = 1 + max(opt(k)), where the max is over k such that (vk, vj) in E. opt(1) = 0 We build the vector of opt from 1 to n and also keep an array, prev, that holds the previous vertex that gave the optimum. Initialize opt(1) = 0. for(j = 2 to n) set opt(j) = -n for each k < j, (vk, vj) in E if(opt(k) + 1 > opt(j)) opt(j) = opt(k) + 1; prev(j) = k The proof that the algorithm yields the optimum is the obvious induction argument. First, from the definition of a path in a digraph, any path from v1 to vj must consist of a path v1 to vk and the edge (vk, vj) in E. opt(1) = 0. For any j > 1 such that vj has no incoming edges, the algorithm will set opt(j) = -n, so that no path beginning at vj will be selected as the optimum when there is another path beginning at v1. Assume that opt(k) is correct for all k < j, then the recurrence simply defines the optimum for j. By induction, opt(j) yields the optimum for all j>= 1. The time for this algorithm is the total time for the inner loop, which is O(m), since each edge will be considered once in the inner loop. The outer loop is executed n times, so the total running time is O(n+m). The array prev can be used to construct the optimal path in O(n) time, making the whole algorithm O(n+m). 17. (a) The given greedy algorithm fails for the following example: Day 1 Price 1 2 10 3 2 4 3 5 4 The greedy algorithm returns 2 for the sequence of days 1-2, whereas the optimal solution is 4 for the sequence of days 1-3-4-5. (b) Our algorithm maps this problem to the problem given in exercise 3 by defining a digraph as follows: For each day, j, define a node vj. Add an additional node v(n+1), V = {v1, v2, …, v(n+1)}. The set of edges E = {(vj, vk) such that j < k and pj < pk } U {(vj, v(n+1)) for all j < n+1} (add an edge from every node in the original graph to the new node v(n+1)). Then the length of longest rising trend will be the length of the longest path from v1 to v(n+1) in the digraph G = (V, E), with the days given by the sequence of vertices except the last. Because if we remove the last edge in any path from v1 to v(n+1), every edge in the path (vj, vk) has j < k and pj < pk. So the whole sequence along the path forms a rising trend as defined for the problem, with the number of days in the sequence equal to the number of edges in the path. Conversely, any rising trend will result in such a path in G. So apply the solution for exercise 3. The time complexity for this problem will be O(n+m), where m = the number of edges in G = n + the number of pairs j < k with pj < pk. m <= n2, so we can characterize the algorithm as O(n2) as well. We could easily construct the algorithm directly but this reduction saves the extra work. I have attached the book solution which does such a direct solution. 23. Gerrymandering. This is a tricky problem that I did not complete. The solution from the book resources is attached. Note that there are typos in this file (it is a pdf that I cannot change): a dash often is found where it should be “=”. 26. Ordering and Inventory. I have also attached the books solution, which is a bit different. In the book solution, they assign inventory cost to the period that it goes into, whereas I assign it to the period were it comes from. Consequently, their opt is in terms of the inventory left at the end of the period (to be paid in the next) and mine is in terms of the inventory coming into the period (already paid in the previous period). This difference in view makes their recurrence run forward: opt(j, s) is in terms of opts for j-1, whereas mine runs backwards, opt(j, s) is in terms of opts for j+1. Both work and reflect different views of the problem. For each period, k, we define the following values: dk, the demand for that period, given as part of the problem. Ok, the order amount for that period – this is what we need to determine Ik, the incoming inventory for that period (the sum of all orders for previous periods less the demands for those periods) Recall that there is a cost Cx for x trucks left in inventory for a given month and a cost K for each order made, regardless of the number of trucks ordered. For each period we have the constraint that Ik + Ok – dk <= S, the maximum inventory that can be stored. Note, as described in the problem, we assume that an order for a period arrives at the beginning of the period and the demand for the period is consumed at the beginning of the period using the incoming inventory and the incoming order. The remaining inventory, x, costs Cx. For simplicity, we will also assume that there is a penalty, P, for any inventory left at the end of the n months. We make P large so that the optimum solution will be forced to have zero inventory left (I(n+1) = 0). Notice that we can optimize a given month in terms of the costs for that month and the optimum for the next month, given the amount of inventory we carry over. We can easily optimize the final month, given the incoming inventory, In <= S: K if In < dn (1) Opt(n, In) = 0 if In = dn P if In > dn (we make P large, so this will not be used in the optimal solution, thus avoiding an additional constraint) For all other months, Ij <= S if(Ij < dj) --- we must order Min( C(Ij + Oj – dj) + K + opt(j+1, Ij + Oj – dj) (inventory cost + order cost + (min over Oj with dj – Ij <= Oj <= S + dj – Ij) next period cost) (2) Opt(j, Ij) = else (Ij >= dj) C(Ij – dj) + opt(j+1, Ij – dj) (no order, inventory cost + next period) min min( C(Ij + Oj – dj) + K + opt(j+1, Ij + Oj – dj) (inventory cost + order (min over Oj with 0 < Oj <= S + dj – Ij) cost + next period) Example. Suppose K = 6, C = 1, S = 5 and make P = 100 and demands are as follows: Month 1 Dem 3 2 2 3 2 4 1 5 4 6 3 7 2 We need to initialize our table for opt(j, Ij) for j = n. Ij \ j 1 2 3 4 5 6 7 0 1 2 3 4 5 8 4 9 1 10 1 11 3 12 4 8 9 10 11 12 6 6 6 6 0 100 Now we optimize for period 11. With I11 = 0, 1 or 2, we order what we need for this period and enough for the next period, since the carrying cost is less then the order cost for the next period. If I11 = 3, 4, 5, then we fill our demand and carry over the rest (0, 1, or 2) and order again in the last period. (First number is the opt, second the order) Dem 3 2 2 1 4 3 2 4 1 1 3 4 Ij \ j 1 2 3 4 5 6 7 8 9 10 11 12 0 10-7 6-4 1 10-6 6-3 2 10-5 6-2 3 6 -0 6-1 4 7 -0 0-0 5 8 -0 100 Optimize for period 10: With I10 = 0, we must order. If we order 4, we can hold 3 over to the next period. With I10 = 1, we can fill our demand and hold zero inventory. Otherwise an order and inventory cost would outweigh the saving in the next period. Similarly, if we have I10 = 2, 3, 4, 5, we are best not ordering. We fill in the rest of the table in a similar fashion. Dem Ij \ j 0 1 2 3 4 5 3 1 47-5 - 2 2 42-5 42-4 39-0 40-0 39-0 36-0 2 3 39-3 39-2 37-0 33-0 35-0 37-0 1 4 37-5 32-0 33-0 34-0 35-0 31-0 4 5 32-9 32-8 32-7 32-6 27-0 28-0 3 6 27-5 27-4 27-3 25-0 26-0 21-0 2 7 25-2 25-1 19-0 20-0 21-0 22-0 4 8 19- 6 19- 5 19- 4 19- 3 17- 0 16- 0 1 9 17- 2 15- 0 11- 0 13- 0 15- 0 13- 0 1 10 15- 4 10- 0 11- 0 12- 0 9 -0 11- 0 3 11 10-7 10-6 10-5 6 -0 7 -0 8 -0 4 12 6-4 6-3 6 -2 6 -1 0-0 0 - 100 Note: the first period is also optimal for 47-8, which then carries over to 36-0 in the second. Because the order cost is high relative to the inventory carrying cost, the tendency is to order ahead for as many periods as possible. If you do an example with order cost lower, say K = 3, then you would order more frequently and carry less inventory. The algorithm is optimal by the usual induction argument on k, taking periods n-k. The base case is k = 0 (month n) and the optimum is given by (1). Assume true for all i < k, then the next optimums for k are given by the recurrence (2). Therefore true for all k, in particular, k = n-1. The time for this algorithm is clearly O(n*S^2) since the time to fill one element in the n by S array is S (checking for the opt over the S possibilities for the next period).