EECS 376, Foundations of Computer Science Winter 2019, University of Michigan, Ann Arbor EECS 376 Midterm Exam Instructions: This exam is closed book, closed notebook. You may not provide your own scratch paper, but the last four pages are intentionally left blank for scratch work. No electronic devices are allowed. You may use one 8.5 ⇥ 11-inch study sheet (both sides) as long as you prepared it yourself. Check your seat assignment. Make sure you are taking the exam at the time slot and the classroom you were assigned by the sta↵. Any deviation from these rules will constitute an honor code violation. In addition, the sta↵ reserves the right not to grade an exam taken in a violation of this policy. The exam consists of 10 multiple choice questions, 5 short-answer questions, and 2 questions that require proofs. You only need to answer one of the proof questions. No extra credit will be given if you answer both proof questions. For the multiple choice questions, please mark your answers neatly on the Scantron. For the short-answer and proof sections, please write your answers clearly in the spaces provided. The exam has 12 pages printed on both sides, including this page and the four blank pages at the end. PLEASE DO NOT DETACH PAGES FROM THE EXAM. Failing to comply with this requirement may result in grade deduction! Write out and sign the full honor pledge below. Honor pledge: I have neither given nor received aid on this exam, nor have I concealed any violations of the Honor Code. I will not discuss the exam with anyone before exam grades are released. I attest that I am taking the exam at the time slot and the classroom I was assigned by the sta↵. Signature: Name: Uniqname: I am enrolled in Section: Section Points 1-10 (Multiple Choice) / 30 11-15 (Short Answer) / 50 16 or 17 (Proof) Total / 20 / 100 Multiple choice (3 points each). 1. What algorithmic paradigm is used for implementing MergeSort? A. Greedy B. Divide and Conquer C. Dynamic Programming D. Wolverine E. Naı̈ve Solution: (B) Divide and conquer clearly best describes the MergeSort algorithm. 2. Which of the following languages is decidable? A. LHALT = {(hM i, x) | M is a Turing Machine and M halts on input x} B. L203 := {hM i | M is a Turing Machine and M halts on input ‘203’} C. L376C := {hM i | M is a Turing Machine and M halts on input ‘376’ after exactly 376 steps} D. L376D := {hM i | M is a Turing Machine and M halts on input ‘376’ after a number of steps which is a multiple of 376} E. L376E := {hM i | M is a Turing Machine and M halts on the 376-th cell} Solution: (C) We can make a decider for L376C by on input hM i, simulate M on 376 for 376 steps and see what happens. 3. Which of the following sets is uncountable? A. The set of all languages B. The set of all rational numbers C. {0, 1}⇤ D. The set of all STATS 426 students E. The set of all LATEX files Solution: (A) We have shown this in lecture. Always/Sometimes/Never (3 points each) Always/All = A, Sometimes/Some = B, Never/No = C. O 4. An algorithm that runs in O(n2 ) time (Always / Sometimes / Never) runs faster than an algorithm that runs in O(2n ) time. Solution: Sometimes. Consider the following Python code. Page 2 # lst is a l i s t def a l g o r i t h m A ( l s t ) : f o r i in range ( len ( l s t ) ∗ ∗ 2 ) : f o r j in range ( 3 7 6 3 7 6 3 7 6 3 7 6 ) : print ( ” H e l l o world ! ” + s t r ( j ) ) def a l g o r i t h m B ( l s t ) : f o r i in range ( len ( l s t ) ∗ ∗ 2 ) : print ( ” H e l l o world ! ” + s t r ( j ) ) def a l g o r i t h m C ( l s t ) : f o r i in range ( 2 ∗ ∗ len ( l s t ) ) : print ( ” H e l l o world ! ” + s t r ( i ) ) We can see that algorithm A and algorithm B are O(n2 ) and algorithm C is O(2n ) where n is the length of the list lst. If we run them on input [1], then algorithm A will print 376376376376 lines, algorithm A will print 1 line, and algorithm A will print 2 lines. 5. Suppose a, b, a0 , b0 are natural numbers. If a + b > a0 + b0 , then the Euclidean algorithm (Always / Sometimes / Never) takes more steps on the input (a, b) than on the input (a0 , b0 ). O Solution: Sometimes. Let a = 376, b = 203, a0 = 1, b0 = 0. Then, a + b > a0 + b0 and (a, b) requires more steps than (a0 , b0 ) does. Let a = 376, b = 375, a0 = 37, b0 = 21. Then, a + b > a0 + b0 , but we can check that the next step of (376, 375) will be (375, 1) and the Euclidean algorithm will halt, while (37, 21) will require a bit more steps. 6. Suppose A is recognizable and B T A. Then B is (Always / Sometimes / Never) recognizable. Solution: Sometimes. Suppose A is undecidable but recognizable. Case 1: Let B = A Then, B T A and B is recognizable. Case 2: Let B = A Then, B T A and B is unrecognizable. 7. Suppose A is a decidable language. For (All / Some / No) language(s) B, we have A T B. Solution: All. Suppose MB is a decider for B. Since A is decidable, we know there is a decider MA . We can build a decider M of A using the decider for B in the following way: M on input x: Page 3 (a) Run MB on x for 376 steps. (b) Run MA on x and return same True/False (3 points each). True = A, False = B. 8. (True / False) Suppose G is a graph. If there exists more than one edge with the same weight, then the minimum spanning tree (MST) of G is not unique. Solution: False. If G is a tree, the MST is always unique even if all edges have the same weight. 9. (True / False) There exists an unrecognizable, but decidable language. Solution: False. If a language L is decidable, then L is recognizable and L is also recognizable. 10. (True / False) Consider the Kolmogorov Complexity of a binary string that consists of 376376 1’s concatenated with 281281 0’s, with respect to programming language JAVA. Then ! KJAVA 11 · · · 1} k 00 · · · 0} | {z | {z 376376 times Notes: = 657657. 281281 times (i) There is no need to know JAVA in details to answer this question. (ii) 376 + 281 = 657. Solution: False. public c l a s s p r i n t m a n y o n e s a n d z e r o s { public s t a t i c void main ( S t r i n g [ ] a r g s ) { f o r ( int i = 0 ; i < 3 7 6 3 7 6 ; i ++) { System . out . p r i n t ( 1 ) ; } // Maybe we can make t h i s program a b i t l o n g e r // by a d d i n g random comments f o r ( int i = 0 ; i < 2 8 1 2 8 1 ; i ++) { System . out . p r i n t ( 0 ) ; } } } We do not need 657657 many letters. Page 4 Short Answer (10 points each) 11. Consider the Fractional Knapsack Problem defined as follows. Definition (Fractional Knapsack Problem). Given two n-length arrays containing positive integer weights W = (w1 , w2 , . . . , wn ) and values V = (v1 , v2 , . . . , vn ) of n divisible items (where the ith item has weight wi 2 Z+ and value vi 2 Z+ ), and a knapsack with weight capacity C 2 Z 0 , find n real values c1 , . . . , cn , where each ci 2 [0, 1] denotes the fractionPof item i you choose, such that the total n weight of the chosen items is at mostP the weight capacity: i=1 ci wi C and the total value you can n obtain from items in your knapsack, i=1 ci vi , is maximized. The fractional knapsack problem is di↵erent from the 1-0 Knapsack problem you have seen, in that it allows you to select a fraction of an item. Notice that changing ci 2 [0, 1] to ci 2 {0, 1} in the definition above makes the problem 1-0 Knapsack Problem (now ci = 1 if item i is picked, and ci = 0 otherwise). (a) Give an algorithm that solves the Fractional Knapsack Problem optimally with time complexity O(n log n). Note: You do not need to prove the correctness or analyze the time complexity of your algorithm. Solution: In order to solve the fractional knapsack problem we will take a greedy approach. Our algorithm will first calculate a ratio ri of value vi divided by weight wi for each element. We will then sort the elements in descending order by their ratios. We will then add whole elements into the knapsack from the sorted array until we cannot fit a whole item. We then add however much we can of the next item. At this point we will have an optimal solution to the fractional knapsack problem. Input: Integers n, C, arrays W, V . Output: A list of n real values c1 , . . . , cn , where each ci 2 [0, 1] denotes the fraction of item i taken in the backpack. 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: function FractionalKnapsack(n, C, W, V ) ratio[n] = 0 for i = 1 : n do ratio[i] = (V[i]/W[i], i) sort(ratio) in decreasing order cw = 0 cv = 0 c[n] = 0 for j = 1 : n do itemindex = ratio[j][2] remaining = C current weight frac = remaining / W[itemindex] if frac > 1 then takefrac = 1 else takefrac = frac cw += W[itemindex] ⇤ takefrac cv += V[itemindex] ⇤ takefrac c[itemindex] = takefrac return c Page 5 (b) Provide a counterexample showing why your algorithm fails to output optimal solution for the 1-0 Knapsack Problem. Solution: Suppose C = 2, w0 = 1, v0 = 2, w1 = 2 and v1 = 3. The output of greedy approach will be choosing the item 0, resulting in total value 2. However, the optimal solution is clearly choosing the item 1 since that yields the total value 3. Page 6 12. Let (“crane”) be an operation between two sets defined as follows: A B := {x | x 2 Ā or x 2 B}. Prove or disprove: the class of decidable languages is closed under . (You may use the notation “crane”, if you do not wish to draw the symbol in your solution.) Solution: Proof. We will construct a machine M that decides A B, where A and B are arbitrary decidable languages. Suppose MA decides A and MB decides B. M = “On input x: 1. Run MA on x. 2. Run MB on x. 3. If MA rejects or MB accepts, accept. 4. Otherwise, reject.” Analysis: Since MA and MB are deciders for A and B respectively, they halt on all inputs. Therefore, MA and MB can never loop on x. Thus, M halts on all inputs. x 2 Ā or x 2 B =) x 62 A or x 2 B =) MA rejects and/or MB accepts =) M accepts x 62 Ā and x 62 B =) x 2 A and x 62 B =) MA accepts and MB rejects =) M rejects We have constructed a machine that decides A B given deciders for A and B, where A and B are arbitrary decidable languages. Thus, the class of decidable languages is closed under . Page 7 13. In Karatsuba’s Algorithm, each of the two n-bit integers is split into two parts of lengths approximately n/2, and the number of multiplications in each recursion is reduced from 4 to 3. In this question, we will multiply two n-bit integers by splitting each of them into three parts. We will assume for this question that n is an integer power of 3. ⇢ 2n n x = a · 2 3 + b · 23 + c Let x, y be two n-bit integers, and write . Then we have: 2n n y = d · 2 3 + e · 23 + f xy = ad · 2 4n 3 + (ae + bd)2n + (af + be + cd)2 2n 3 n + (bf + ce)2 3 + cf = A2 4n 3 + B2n + C2 2n 3 n + D2 3 + E, where A = ad B = ae + bd C = af + be + cd D = bf + ce E = cf Consider the following two Divide-and-Conquer based algorithms. In Algorithm A, we first compute the values of ad, ae, af, bd, be, bf, cd, ce, cf , recursively. Then, we compute xy by computing A, B, C, D, E based on the equations above. In Algorithm B, we compute A, B, C, D, E by computing Z0 , Z1 , Z2 , Z3 , Z4 below, where the multiplication in each of them is computed recursively: 8 8 1 A = 24 (6Z0 4Z1 + Z2 4Z3 + Z4 ) Z0 = cf > > > > > > 1 > > ( 2Z1 + Z2 + 2Z3 Z4 ) < Z1 = (a + b + c)(d + e + f ) < B = 12 1 Z2 = (4a + 2b + c)(4d + 2e + f ) =) C = 24 ( 30Z0 + 16Z1 Z2 + 16Z3 Z4 ) . > > 1 > > Z3 = (a b + c)(d e + f ) D = 12 (8Z1 Z2 8Z3 + Z4 ) > > > > : : Z4 = (4a 2b + c)(4d 2e + f ) E = Z0 For each algorithm A and B, write down the recurrence relation T (n) for the time complexity, and then compute T (n) explicitly. Which of the algorithms A and B runs asymptotically faster? How do they compare (asymptotically) to Karatsuba’s Algorithm? Notes: (i) Dividing an n-bit integer by 3 can be done in O(n) time, if the dividend is known to be a multiple of 3, and you can assume this for this question. (ii) ln 2 ⇥ ln 5 < (ln 3)2 < ln 2 ⇥ ln 6 (iii) There is no need to check and/or prove the correctness of the algorithm. Solution: • Algorithm A We can see that there are 9 multiplications of numbers that are about n/3 bits long. We can do addition in linear time and multiplication by power of 2 can be done in constant time by bit shifting. T (n) = 9T (n/3) + O(n) By the Master Theorem, since 9 > 3, T (n) = O(nlog3 9 ) = O(n2 ) • Algorithm B Page 8 We can see that there are 5 multiplications of numbers that are about n/3 bits long. We can do addition and subtraction in linear time and multiplication by constants in also linear time. Also, multiplication by power of 2 can be done in constant time by bit shifting. T (n) = 5T (n/3) + O(n) By the Master Theorem, since 5 > 3, T (n) = O(nlog3 5 ) ⇡ O(n1.46 ) The algorithm B runs asymptotically faster. Karatsuba’s algorithm runs in O(nlog2 3 ) ⇡ O(n1.58 ) so the algorithm B runs faster than Karatsuba’s algorithm but the algorithm A runs slower than 3 ln 5 Karatsuba’s algorithm. Or, we can also use the fact that log2 3 = ln ln 2 and log3 5 = ln 3 , and since ln 5 ln 3 ln 2 ⇥ ln 5 < ln 3 ⇥ ln 3, we have log3 5 = ln 3 < ln 2 = log2 3. Page 9 14. Let A [1 . . . 376] be a global array of integers in strictly increasing order. Consider the following algorithm: Input: integers x and y function Mystery(x, y) if x 0 OR y 0 then return 1 i AskUser(1, 100) . prompt the user to input an integer in the range [1, 100] j AskUser(1, 100) . same as above x x + A [i] y y A [i + j] 8: return Mystery(y, x) 1: 2: 3: 4: 5: 6: 7: Are there any integers x, y and sequences of user inputs that can make Mystery(x, y) run indefinitely (i.e. never terminate)? If yes, describe them. If not, provide a short justification. Note that when prompted for an input, the user is not allowed to input numbers outside of the [1, 100] range. Solution: No, because we can define a valid potential function for Mystery(x, y): si = xi +yi , where xi and yi are the values of x and y at iteration i. Claim: si is a valid potential function, i.e. si is bounded below and strictly decreasing. si is bounded below. The base case of Mystery(x, y) is (x 0) _ (y 0), so the algorithm halts in the worst case when si = xi + yi 0. In other words, 8i : si = xi + yi 0. Note that we include 0 here so that the potential function is still defined when we enter the base case. si is strictly decreasing. Observe: • yi+1 = xi + A[i] and xi+1 = yi A[i + j] because we recursively call Mystery(y, x) • A is strictly increasing, so 8i, j 2 [1, 376] : i < j =) A[i] < A[j] • The user inputs i, j must be in [1, 100], so j > 0. Add i to both sides to get j + i > i. • j + i > i =) A[j + i] > A[i] =) A[j + i] A[i] > 0 • Add the equations yi+1 = xi + A[i] and xi+1 = yi A[i + j] to get xi+1 + yi+1 = xi + A[i] + yi A[i + j] si+1 = si + A[i] = si So we have si+1 < si Page 10 A[i + j] (A[i + j] A[i]) < si 15. Consider the language L = {hM i | M accepts some input}. We know L is recognizable. However, the following Turing machine R somehow fails to recognize L. R = “On input hM i: 1. For all binary strings x 2 {0, 1}⇤ : 1.1 Run M on x. 1.2 If M accepts x, accept. ” (a) Explain why R fails to recognize L. Solution: Assume for the purpose of this explanation that step 1 of the machine R will pick x in the order ", 0, 1, 00, 01, . . . . Consider the machine M376 that accepts the string “101111000” and loops on every other input (note that we could have chosen any “special” string here as long as it isn’t "). Then hM i 2 L, since M accepts an input. However, R will loop on input hM376 i, specifically, when running step 1.1. In particular, R will not accept hM i. Therefore, R does not recognize L. (b) Describe a Turing machine that recognizes L. e to do the following: Solution: Recall that {0, 1}⇤ is countable. So, we can define R e 1: procedure R(hM i): 2: Let sj denote the jth element of {0, 1}⇤ . 3: for i from 1 to 1 do: 4: for j from 1 to i do: 5: Run i steps of M on sj 6: If M accepted, then accept e accepts. If L(M ) 6= ?, then, for some i and j, M accepts sj after i steps. In this case, R e does not loop on machines like M376 defined above since line 5 never loops. Note that R e doesn’t accept (in fact, it loops forever). It follows that R e is a recognizer If L(M ) = ?, then R for L. Page 11 Proofs (20 pts) Answer one of the following two questions (16 or 17). If you answer both we will grade an arbitrary one. 16. In order to improve the view from the top floors of the buildings in downtown Ann Arbor, the city has decided to change the number of floors so no building will conceal the building behind it. Yet, since adding/removing floors is expensive, you need to design an algorithm that will minimize the number of changes. Formally, given a sequence h1 , h2 , . . . , hn of non-negative integers, indicating the number of floors of each building on the street, the goal is to come up withPa non-decreasing sequence h01 , h02 , . . . , h0n of n non-negative integers such that the “absolute change” i=1 |hi h0i | is minimized. (a) Give an example of a sequence where the “greedy” strategy does not provide an optimal solution. Solution: The greedy algorithm would, for each i 2 {1, · · · , n}, choose h0i to minimize i X |hj h0j |, assuming that h01 , · · · , h0i 1 have been chosen. In particular, for i = 1, the j=1 greedy algorithm would choose h01 = h1 . Now, one example where the greedy algorithm fails to be optimal is that n = 3, h1 = 3, h2 = 2, h3 = 1. The optimal solution is h01 = 2, h02 = 2, h03 = 2, with total cost of 2. However, the greedy approach would generate h01 = 3, h02 = 3, h03 = 3, leaving total cost to be 3. (b) For i = 1 . . . n, let W [i][k] be the optimal absolute change you can get, if we are only considering the first i buildings and with the restriction that h01 , . . . , h0i are in the range [0, k]. Write the base case(s) and a recurrence for the entries of W. Solution: Let W [i][h] be the optimal absolute change if we are only minimizing h0j |, with the restriction that h01 , . . . , h0i 2 [0, h]. For the base case, we have ⇢ 0 if h1 h W [1][h] = . |h h1 | otherwise Pi j=1 |hj For the recurrence relation, we have W [i][h] = min h0i =0,1,...,h {W [i 1][h0i ] + |h0i hi |} . (c) State, with brief justification, the runtime of the dynamic programming algorithm based on the previous part. Give your answer using O notation in terms of n and other relevant parameters, if any. Solution: For each i and each h, to compute W [i][h], we need O(h) computations in total. Therefore, the total time complexity is O(n · k 2 ). Page 12 17. Consider the following language: LThe Party Never Halts = {hM i | M loops on all inputs} . Is LThe Party Never Halts decidable? If so, clearly describe a Turing machine that decides it; otherwise, prove that it is undecidable. If needed, you may use any undecidable language covered in class, discussion and/or homework assignment. Solution: LThe Party Never Halts is undecidable. To prove this, we can reduce it from LHALT : LHALT T LThe Party Never Halts . Suppose there is a black-box E that decides LThe Party Never Halts . We will show that the following Turing machine T decides LHALT . T = “on input (hM i, x) 1. Construct the following TM M 0 : M 0 = “On input w. Ignore input w, and run M on x.” 2. Run E on input hM 0 i. 3. If E accepts, reject. 4. If E rejects, accept.” We need to show that T accepts (hM i, x) if and only if (hM i, x) 2 LHALT . This can be shown as follows. (hM i, x) 2 LHALT ) M halts on x ) M 0 halts on all inputs ) E rejects ) T accepts (hM i, x) 2 / LHALT ) M loops on x ) M 0 loops on all inputs ) E accepts ) T rejects Page 13 This page is intentionally left blank for scratch work. Page 14 This page is intentionally left blank for scratch work. Page 15 This page is intentionally left blank for scratch work. Page 16 This page is intentionally left blank for scratch work. Page 17