Algorithm Design Algorithm Design 1 Introduction The design of good algorithms is more an art than science Basic algorithm-design methods: Greedy method Divide and Conquer Dynamic Programming Backtracking Branch and Bound Advanced methods: Linear Programming Integer Programming Neural Networks Genetic Algorithms Simulated annealing Algorithm Design 2 The Greedy Method Algorithm Design 3 Outline The Greedy Method Technique (§5.1) Fractional Knapsack Problem (§5.1.1) Task Scheduling (§5.1.2) Minimum Spanning Trees (§7.3) Text Compression Algorithm Design 4 The Greedy Method Technique The greedy method is a general algorithm design paradigm, built on the following elements: configurations: different choices, collections, or values to find objective function: a score assigned to configurations, which we want to either maximize or minimize It works best when applied to problems with the greedy-choice property: a globally-optimal solution can always be found by a series of local improvements from a starting configuration. Algorithm Design 5 Making Change Problem: A dollar amount to reach and a collection of coin amounts to use to get there. Configuration: A dollar amount yet to return to a customer plus the coins already returned Objective function: Minimize number of coins returned. Greedy solution: Always return the largest coin you can Example 1: Coins are valued $.32, $.08, $.01 Has the greedy-choice property, since no amount over $.32 can be made with a minimum number of coins by omitting a $.32 coin (similarly for amounts over $.08, but under $.32). Example 2: Coins are valued $.30, $.20, $.05, $.01 Does not have greedy-choice property, since $.40 is best made with two $.20’s, but the greedy solution will pick three coins (which ones?) Algorithm Design 6 The Fractional Knapsack Problem Given: A set S of n items, with each item i having bi - a positive benefit wi - a positive weight Goal: Choose items with maximum total benefit but with weight at most W. If we are allowed to take fractional amounts, then this is the fractional knapsack problem. In this case, we let xi denote the amount we take of item i Objective: maximize b ( x / w ) iS Constraint: x iS i i i i W Algorithm Design 7 Example Given: A set S of n items, with each item i having bi - a positive benefit wi - a positive weight Goal: Choose items with maximum total benefit but with weight at most W. “knapsack” Solution: Items: Weight: Benefit: Value: ($ per ml) 1 2 3 4 5 4 ml 8 ml 2 ml 6 ml 1 ml $12 $32 $40 $30 $50 3 4 20 5 50 Algorithm Design • • • • 1 2 6 1 ml ml ml ml of of of of 10 ml 8 5 3 4 2 The Fractional Knapsack Algorithm Greedy choice: Keep taking item with highest value (benefit to weight ratio) Since bi ( xi / wi ) (bi / wi ) xi iS iS Run time: O(n log n). Why? Correctness: Suppose there is a better solution there is an item i with higher value than a chosen item j (i.e., vi<vj) but xi<wi and xj>0 If we substitute some i with j, we get a better solution How much of i: min{wi-xi, xj} Thus, there is no better solution than the greedy one Algorithm fractionalKnapsack(S, W) Input: set S of items w/ benefit bi and weight wi; max. weight W Output: amount xi of each item i to maximize benefit with weight at most W for each item i in S xi 0 vi bi / wi {value} w0 {total weight} while w < W remove item i with highest vi xi min{wi , W - w} w w + min{wi , W - w} Algorithm Design 9 Task Scheduling Given: a set T of n tasks, each having: A start time, si A finish time, fi (where si < fi) Goal: Perform all the tasks using a minimum number of “machines.” Machine 3 Machine 2 Machine 1 1 2 3 4 5 Algorithm Design 6 7 8 9 10 Task Scheduling Algorithm Greedy choice: consider tasks by their start time and use as few machines as possible with Algorithm taskSchedule(T) this order. Input: set T of tasks w/ start time si Run time: O(n log n). Why? and finish time fi Correctness: Suppose there is a Output: non-conflicting schedule with minimum number of machines better schedule. m0 {no. of machines} We can use k-1 machines while T is not empty The algorithm uses k remove task i w/ smallest si Let i be first task scheduled if there’s a machine j for i then on machine k schedule i on machine j Machine i must conflict with else k-1 other tasks mm+1 But that means there is no schedule i on machine m non-conflicting schedule using k-1 machines Algorithm Design 11 Example Given: a set T of n tasks, each having: A start time, si A finish time, fi (where si < fi) [1,4], [1,3], [2,5], [3,7], [4,7], [6,9], [7,8] (ordered by start) Goal: Perform all tasks on min. number of machines Machine 3 Machine 2 Machine 1 1 2 3 4 5 Algorithm Design 6 7 8 9 12 Text Compression (§ 11.4) Given a string X, efficiently encode X into a smaller string Y Saves memory and/or bandwidth A good approach: Huffman encoding Compute frequency f(c) for each character c. Encode high-frequency characters with short code words No code word is a prefix for another code Use an optimal encoding tree to determine the code words Algorithm Design 13 Encoding Tree Example A code is a mapping of each character of an alphabet to a binary code-word A prefix code is a binary code such that no code-word is the prefix of another code-word An encoding tree represents a prefix code Each external node stores a character The code word of a character is given by the path from the root to the external node storing the character (0 for a left child and 1 for a right child) 00 010 011 10 11 a b c d e a Algorithm Design d b c e 14 Encoding Tree Optimization Given a text string X, we want to find a prefix code for the characters of X that yields a small encoding for X Frequent characters should have long code-words Rare characters should have short code-words Example X = abracadabra T1 encodes X into 29 bits T2 encodes X into 24 bits T1 T2 c d a b r a b c Algorithm Design r d 15 Huffman’s Algorithm Given a string X, Huffman’s algorithm construct a prefix code the minimizes the size of the encoding of X It runs in time O(n + d log d), where n is the size of X and d is the number of distinct characters of X A heap-based priority queue is used as an auxiliary structure Algorithm HuffmanEncoding(X) Input string X of size n Output optimal encoding trie for X C distinctCharacters(X) computeFrequencies(C, X) Q new empty heap for all c C T new single-node tree storing c Q.insert(getFrequency(c), T) while Q.size() > 1 f1 Q.minKey() T1 Q.removeMin() f2 Q.minKey() T2 Q.removeMin() T join(T1, T2) Q.insert(f1 + f2, T) return Q.removeMin() Algorithm Design 16 Example 11 a 5 2 a b c d r 5 2 1 1 2 b 2 c 1 d 1 6 a X = abracadabra Frequencies c b 2 c d b 2 r 2 a 5 c 2 d r 2 r 6 2 a 5 4 a 5 c Algorithm Design 4 d b r 4 d b r 17 Extended Huffman Tree Example Algorithm Design 18 Divide-and-Conquer 7 29 4 2 4 7 9 72 2 7 77 22 Algorithm Design 94 4 9 99 44 19 Outline and Reading Divide-and-conquer paradigm (§5.2) Review Merge-sort (§4.1.1) Recurrence Equations (§5.2.1) Iterative substitution Recursion trees Guess-and-test The master method Integer Multiplication (§5.2.2) Algorithm Design 20 Divide-and-Conquer Divide-and conquer is a general algorithm design paradigm: Divide: divide the input data S in two or more disjoint subsets S1, S2 , … Recur: solve the subproblems recursively Conquer: combine the solutions for S1, S2, …, into a solution for S The base case for the recursion are subproblems of constant size Analysis can be done using recurrence equations Algorithm Design 21 Merge-Sort Review Merge-sort on an input sequence S with n elements consists of three steps: Divide: partition S into two sequences S1 and S2 of about n/2 elements each Recur: recursively sort S1 and S2 Conquer: merge S1 and S2 into a unique sorted sequence Algorithm mergeSort(S, C) Input sequence S with n elements, comparator C Output sequence S sorted according to C if S.size() > 1 (S1, S2) partition(S, n/2) mergeSort(S1, C) mergeSort(S2, C) S merge(S1, S2) Algorithm Design 22 Recurrence Equation Analysis The conquer step of merge-sort consists of merging two sorted sequences, each with n/2 elements and implemented by means of a doubly linked list, takes at most bn steps, for some constant b. Likewise, the basis case (n < 2) will take at b most steps. Therefore, if we let T(n) denote the running time of merge-sort: b if n 2 T (n) 2T (n / 2) + bn if n 2 We can therefore analyze the running time of merge-sort by finding a closed form solution to the above equation. That is, a solution that has T(n) only on the left-hand side. Algorithm Design 23 Iterative Substitution In the iterative substitution, or “plug-and-chug,” technique, we iteratively apply the recurrence equation to itself and see if we can find a pattern: T ( n ) 2T ( n / 2) + bn 2( 2T ( n / 22 )) + b(n / 2)) + bn 22 T (n / 22 ) + 2bn 23 T (n / 23 ) + 3bn 24 T (n / 24 ) + 4bn ... 2i T ( n / 2i ) + ibn Note that base, T(n)=b, case occurs when 2i=n. That is, i = log n. So, T (n) bn + bn logn Thus, T(n) is O(n log n). Algorithm Design 24 The Recursion Tree Draw the recursion tree for the recurrence relation and look for a pattern: b if n 2 T (n) 2T (n / 2) + bn if n 2 time depth T’s size 0 1 n bn 1 2 n/2 bn i 2i n/2i bn … … … … Total time = bn + bn log n (last level plus all previous levels) Algorithm Design 25 Guess-and-Test Method In the guess-and-test method, we guess a closed form solution and then try to prove it is true by induction: b if n 2 T (n) 2T (n / 2) + bn logn if n 2 Guess: T(n) < cn log n. T (n) 2T (n / 2) + bn log n 2(c(n / 2) log(n / 2)) + bn log n cn(logn - log 2) + bn log n cn log n - cn + bn log n Wrong: we cannot make this last line be less than cn log n Algorithm Design 26 Guess-and-Test Method, Part 2 Recall the recurrence equation: b if n 2 T (n) 2T (n / 2) + bn logn if n 2 Guess #2: T(n) < cn log2 n. T (n) 2T (n / 2) + bn log n 2(c(n / 2) log2 (n / 2)) + bn log n cn(logn - log 2) 2 + bn log n cn log2 n - 2cn log n + cn + bn log n if c > b. cn log2 n So, T(n) is O(n log2 n). In general, to use this method, you need to have a good guess and you need to be good at induction proofs. Algorithm Design 27 Master Method Many divide-and-conquer recurrence equations have the form: c T (n) aT (n / b) + f (n) if n d if n d The Master Theorem: 1. if f (n) is O(n logb a - ), thenT (n) is (n logb a ) 2. if f (n) is (n logb a logk n), thenT (n) is (n logb a logk +1 n) 3. if f (n) is (n logb a + ), thenT (n) is ( f (n)), provided af (n / b) f (n) for some 1. Algorithm Design 28 Master Method, Example 1 c if n d aT (n / b) + f (n) if n d The form: T (n) The Master Theorem: 1. if f (n) is O(n logb a - ), thenT (n) is (n logb a ) 2. if f (n) is (n logb a logk n), thenT (n) is (n logb a logk +1 n) 3. if f (n) is (n logb a + ), thenT (n) is ( f (n)), provided af (n / b) f (n) for some 1. Example: T (n) 4T (n / 2) + n Solution: logba=2, so case 1 says T(n) is O(n2). Algorithm Design 29 Master Method, Example 2 c if n d aT (n / b) + f (n) if n d The form: T (n) The Master Theorem: 1. if f (n) is O(n logb a - ), thenT (n) is (n logb a ) 2. if f (n) is (n logb a logk n), thenT (n) is (n logb a logk +1 n) 3. if f (n) is (n logb a + ), thenT (n) is ( f (n)), provided af (n / b) f (n) for some 1. Example: T (n) 2T (n / 2) + n log n Solution: logba=1, so case 2 says T(n) is O(n log2 n). Algorithm Design 30 Master Method, Example 3 c if n d aT (n / b) + f (n) if n d The form: T (n) The Master Theorem: 1. if f (n) is O(n logb a - ), thenT (n) is (n logb a ) 2. if f (n) is (n logb a logk n), thenT (n) is (n logb a logk +1 n) 3. if f (n) is (n logb a + ), thenT (n) is ( f (n)), provided af (n / b) f (n) for some 1. Example: T (n) T (n / 3) + n log n Solution: logba=0, so case 3 says T(n) is O(n log n). Algorithm Design 31 Master Method, Example 4 c if n d aT (n / b) + f (n) if n d The form: T (n) The Master Theorem: 1. if f (n) is O(n logb a - ), thenT (n) is (n logb a ) 2. if f (n) is (n logb a logk n), thenT (n) is (n logb a logk +1 n) 3. if f (n) is (n logb a + ), thenT (n) is ( f (n)), provided af (n / b) f (n) for some 1. Example: T (n) 8T (n / 2) + n 2 Solution: logba=3, so case 1 says T(n) is O(n3). Algorithm Design 32 Master Method, Example 5 c if n d aT (n / b) + f (n) if n d The form: T (n) The Master Theorem: 1. if f (n) is O(n logb a - ), thenT (n) is (n logb a ) 2. if f (n) is (n logb a logk n), thenT (n) is (n logb a logk +1 n) 3. if f (n) is (n logb a + ), thenT (n) is ( f (n)), provided af (n / b) f (n) for some 1. Example: T (n) 9T (n / 3) + n 3 Solution: logba=2, so case 3 says T(n) is O(n3). Algorithm Design 33 Master Method, Example 6 c if n d aT (n / b) + f (n) if n d The form: T (n) The Master Theorem: 1. if f (n) is O(n logb a - ), thenT (n) is (n logb a ) 2. if f (n) is (n logb a logk n), thenT (n) is (n logb a logk +1 n) 3. if f (n) is (n logb a + ), thenT (n) is ( f (n)), provided af (n / b) f (n) for some 1. Example: T (n) T (n / 2) + 1 (binary search) Solution: logba=0, so case 2 says T(n) is O(log n). Algorithm Design 34 Master Method, Example 7 c if n d aT (n / b) + f (n) if n d The form: T (n) The Master Theorem: 1. if f (n) is O(n logb a - ), thenT (n) is (n logb a ) 2. if f (n) is (n logb a logk n), thenT (n) is (n logb a logk +1 n) 3. if f (n) is (n logb a + ), thenT (n) is ( f (n)), provided af (n / b) f (n) for some 1. Example: T (n) 2T (n / 2) + log n (heap construction) Solution: logba=1, so case 1 says T(n) is O(n). Algorithm Design 35 Iterative “Proof” of the Master Theorem Using iterative substitution, let us see if we can find a pattern: T (n) aT (n / b) + f (n) a (aT (n / b 2 )) + f (n / b)) + bn a 2T (n / b 2 ) + af (n / b) + f (n) a 3T (n / b 3 ) + a 2 f (n / b 2 ) + af (n / b) + f (n) ... a T (1) + logb n (logb n ) -1 i a f (n / b i ) i 0 n logb a T (1) + (logb n ) -1 i i a f ( n / b ) i 0 We then distinguish the three cases as The first term is dominant Each part of the summation is equally dominant The summation is a geometric series Algorithm Design 36 Integer Multiplication Algorithm: Multiply two n-bit integers I and J. Divide step: Split I and J into high-order and low-order bits I I h 2n / 2 + I l J J h 2n / 2 + J l We can then define I*J by multiplying the parts and adding: I * J ( I h 2n / 2 + I l ) * ( J h 2n / 2 + J l ) I h J h 2n + I h J l 2n / 2 + I l J h 2n / 2 + I l J l So, T(n) = 4T(n/2) + n, which implies T(n) is O(n2). But that is no better than the algorithm we learned in grade school. Algorithm Design 37 An Improved Integer Multiplication Algorithm Algorithm: Multiply two n-bit integers I and J. Divide step: Split I and J into high-order and low-order bits I I h 2n / 2 + I l J J h 2n / 2 + J l Observe that there is a different way to multiply parts: I * J I h J h 2 n + [(I h - I l )(J l - J h ) + I h J h + I l J l ]2 n / 2 + I l J l I h J h 2 n + [(I h J l - I l J l - I h J h + I l J h ) + I h J h + I l J l ]2 n / 2 + I l J l I h J h 2 n + ( I h J l + I l J h )2 n / 2 + I l J l So, T(n) = 3T(n/2) + n, which implies T(n) is O(nlog23), by the Master Theorem. Thus, T(n) is O(n1.585). Algorithm Design 38 Dynamic Programming Algorithm Design 39 Outline and Reading Matrix Chain-Product The General Technique 0-1 Knapsack Problem Subsequences Algorithm Design 40 Matrix Chain-Products Dynamic Programming is a general algorithm design paradigm. Rather than give the general structure, let us first give a motivating example: Matrix Chain-Products Review: Matrix Multiplication. C = A*B A is d × e and B is e × f O(def ) time f e -1 C[i, j ] A[i, k ] * B[k , j ] d B j e e A C i i,j d k 0 f Algorithm Design 41 Matrix Chain-Products Matrix Chain-Product: Compute A=A0*A1*…*An-1 Ai is di × di+1 Problem: How to parenthesize? Example B is 3 × 100 C is 100 × 5 D is 5 × 5 (B*C)*D takes 1500 + 75 = 1575 ops B*(C*D) takes 1500 + 2500 = 4000 ops Algorithm Design 42 Enumeration Approach Matrix Chain-Product Alg.: Try all possible ways to parenthesize A=A0*A1*…*An-1 Calculate number of ops for each one Pick the one that is best Running time: The number of parenthesizations is equal to the number of binary trees with n nodes This is exponential! It is called the Catalan number, and it is almost 4n. This is a terrible algorithm! Algorithm Design 43 Greedy Approach Idea #1: repeatedly select the product that uses (up) the most operations. Counter-example: A is 10 × 5 B is 5 × 10 C is 10 × 5 D is 5 × 10 Greedy idea #1 gives (A*B)*(C*D), which takes 500+1000+500 = 2000 ops A*((B*C)*D) takes 500+250+250 = 1000 ops Algorithm Design 44 Another Greedy Approach Idea #2: repeatedly select the product that uses the fewest operations. Counter-example: A is 101 × 11 B is 11 × 9 C is 9 × 100 D is 100 × 99 Greedy idea #2 gives A*((B*C)*D)), which takes 109989+9900+108900=228789 ops (A*B)*(C*D) takes 9999+89991+89100=189090 ops The greedy approach is not giving us the optimal value. Algorithm Design 45 “Recursive” Approach Define subproblems: Find the best parenthesization of Ai*Ai+1*…*Aj. Let Ni,j denote the number of operations done by this subproblem. The optimal solution for the whole problem is N0,n-1. Subproblem optimality: The optimal solution can be defined in terms of optimal subproblems There has to be a final multiplication (root of the expression tree) for the optimal solution. Say, the final multiply is at index i: (A0*…*Ai)*(Ai+1*…*An-1). Then the optimal solution N0,n-1 is the sum of two optimal subproblems, N0,i and Ni+1,n-1 plus the time for the last multiply. If the global optimum did not have these optimal subproblems, we could define an even better “optimal” solution. Algorithm Design 46 Characterizing Equation The global optimal has to be defined in terms of optimal subproblems, depending on where the final multiply is at. Let us consider all possible places for that final multiply: Recall that Ai is a di × di+1 dimensional matrix. So, a characterizing equation for Ni,j is the following: N i , j min{N i ,k + N k +1, j + di d k +1d j +1} i k j Note that subproblems are not independent–the subproblems overlap. Algorithm Design 47 Dynamic Programming Algorithm Visualization The bottom-up N i , j min{N i ,k + N k +1, j + di d k +1d j +1} i k j construction fills in the N array by diagonals j … n-1 N 0 1 2 i Ni,j gets values from 0 previous entries in i-th 1 row and j-th column … answer Filling in each entry in i the N table takes O(n) time. Total run time: O(n3) j Getting actual parenthesization can be n-1 done by remembering “k” for each N entry Algorithm Design 48 Dynamic Programming Algorithm Since Algorithm matrixChain(S): subproblems Input: sequence S of n matrices to be multiplied overlap, we don’t use recursion. Output: number of operations in an optimal Instead, we parenthesization of S construct optimal for i 1 to n - 1 do subproblems Ni,i 0 “bottom-up.” for b 1 to n - 1 do Ni,i’s are easy, so start with them { b j - i is the length of the problem } Then do for i 0 to n - b - 1 do problems of ji+b “length” 2,3,… subproblems, Ni,j + and so on. for k i to j - 1 do Running time: Ni,j min{Ni,j, Ni,k + Nk+1,j + di dk+1 dj+1} O(n3) return N0,n-1 Algorithm Design 49 The General Dynamic Programming Technique Applies to a problem that at first seems to require a lot of time (possibly exponential), provided we have: Simple subproblems: the subproblems can be defined in terms of a few variables, such as j, k, l, m, and so on. Subproblem optimality: the global optimum value can be defined in terms of optimal subproblems Subproblem overlap: the subproblems are not independent, but instead they overlap (hence, should be constructed bottom-up). Algorithm Design 50 The 0/1 Knapsack Problem Given: A set S of n items, with each item i having wi - a positive weight bi - a positive benefit Goal: Choose items with maximum total benefit but with weight at most W. If we are not allowed to take fractional amounts, then this is the 0/1 knapsack problem. In this case, we let T denote the set of items we take Objective: maximize b iT Constraint: i w W iT i Algorithm Design 51 Example Given: A set S of n items, with each item i having bi - a positive “benefit” wi - a positive “weight” Goal: Choose items with maximum total benefit but with weight at most W. “knapsack” Items: Weight: Benefit: 1 2 3 4 5 4 in 2 in 2 in 6 in 2 in $20 $3 $6 $25 $80 Algorithm Design box of width 9 in Solution: • item 5 ($80, 2 in) • item 3 ($6, 2in) • item 1 ($20, 4in) 52 A 0/1 Knapsack Algorithm, First Attempt Sk: Set of items numbered 1 to k. Define B[k] = best selection from Sk. Problem: does not have subproblem optimality: Consider set S={(3,2),(5,4),(8,5),(4,3),(10,9)} of (benefit, weight) pairs and total weight W = 20 Best for S4: Best for S5: Algorithm Design 53 A 0/1 Knapsack Algorithm, Second Attempt Sk: Set of items numbered 1 to k. Define B[k,w] to be the best selection from Sk with weight at most w Good news: this does have subproblem optimality. B[k - 1, w] if wk w B[k , w] else max{B[k - 1, w], B[k - 1, w - wk ] + bk } I.e., the best subset of Sk with weight at most w is either the best subset of Sk-1 with weight at most w or the best subset of Sk-1 with weight at most w-wk plus item k Algorithm Design 54 0/1 Knapsack Algorithm B[k - 1, w] if wk w B[k , w] else max{B[k - 1, w], B[k - 1, w - wk ] + bk } Algorithm 01Knapsack(S, W): Recall the definition of Input: set S of n items with benefit bi B[k,w] and weight wi; maximum weight W Output: benefit of best subset of S with Since B[k,w] is defined in weight at most W terms of B[k-1,*], we can let A and B be arrays of length W + 1 use two arrays of instead of a matrix for w 0 to W do B[w] 0 Running time: O(nW). for k 1 to n do Not a polynomial-time copy array B into array A algorithm since W may be for w wk to W do large if A[w-wk] + bk > A[w] then This is a pseudo-polynomial B[w] A[w-wk] + bk time algorithm return B[W] Algorithm Design 55 Subsequences (§ 11.5.1) A subsequence of a character string x0x1x2…xn-1 is a string of the form xi xi …xi , where ij < ij+1. Not the same as substring! Example String: ABCDEFGHIJK 1 2 k Subsequence: ACEGJIK Subsequence: DFGHK Not subsequence: DAGH Algorithm Design 56 The Longest Common Subsequence (LCS) Problem Given two strings X and Y, the longest common subsequence (LCS) problem is to find a longest subsequence common to both X and Y Has applications to DNA similarity testing (alphabet is {A,C,G,T}) Example: ABCDEFG and XZACKDFWGH have ACDFG as a longest common subsequence Algorithm Design 57 A Poor Approach to the LCS Problem A Brute-force solution: Enumerate all subsequences of X Test which ones are also subsequences of Y Pick the longest one. Analysis: If X is of length n, then it has 2n subsequences This is an exponential-time algorithm! Algorithm Design 58 A Dynamic-Programming Approach to the LCS Problem Define L[i,j] to be the length of the longest common subsequence of X[0..i] and Y[0..j]. Allow for -1 as an index, so L[-1,k] = 0 and L[k,-1]=0, to indicate that the null part of X or Y has no match with the other. Then we can define L[i,j] in the general case as follows: 1. If xi=yj, then L[i,j] = L[i-1,j-1] + 1 (we can add this match) 2. If xi≠yj, then L[i,j] = max{L[i-1,j], L[i,j-1]} (we have no match here) Case 1: Case 2: Algorithm Design 59 An LCS Algorithm Algorithm LCS(X,Y ): Input: Strings X and Y with n and m elements, respectively Output: For i = 0,…,n-1, j = 0,...,m-1, the length L[i, j] of a longest string that is a subsequence of both the string X[0..i] = x0x1x2…xi and the string Y [0.. j] = y0y1y2…yj for i =1 to n-1 do L[i,-1] = 0 for j =0 to m-1 do L[-1,j] = 0 for i =0 to n-1 do for j =0 to m-1 do if xi = yj then L[i, j] = L[i-1, j-1] + 1 else L[i, j] = max{L[i-1, j] , L[i, j-1]} return array L Algorithm Design 60 Visualizing the LCS Algorithm Algorithm Design 61 Analysis of LCS Algorithm We have two nested loops The outer one iterates n times The inner one iterates m times A constant amount of work is done inside each iteration of the inner loop Thus, the total running time is O(nm) Answer is contained in L[n,m] (and the subsequence can be recovered from the L table). Algorithm Design 62 Analysis of LCS Algorithm We have two nested loops The outer one iterates n times The inner one iterates m times A constant amount of work is done inside each iteration of the inner loop Thus, the total running time is O(nm) Answer is contained in L[n,m] (and the subsequence can be recovered from the L table). Algorithm Design 63 Backtracking and Branch and Bound Algorithm Design 64 n-Queens Problem A queen that is placed on an n x n chessboard, may attack any piece placed in the same column, row, or diagonal. 8x8 Chessboard n-Queens Problem Can n queens be placed on an n x n chessboard so that no queen may attack another queen? 4x4 n-Queens Problem 8x8 Difficult Problems Many require you to find either a subset or permutation that satisfies some constraints and (possibly also) optimizes some objective function. May be solved by organizing the solution space into a tree and systematically searching this tree for the answer. Algorithm Design 68 Subset Problems Solution requires you to find a of n elements. The subset must satisfy some constraints and possibly optimize some objective function. Examples. Partition. Subset sum. 0/1 Knapsack. Satisfiability (find subset of variables to be set to true so that formula evaluates to true). Scheduling 2 machines. Packing 2 bins. Permutation Problems Solution requires you to find a of n elements. The must satisfy some constraints and possibly optimize some objective function. Examples. TSP. n-queens. Each queen must be placed in a different row and different column. Let queen i be the queen that is going to be placed in row i. Let ci be the column in which queen i is placed. c1, c2, c3, …, cn is a permutation of [1,2,3, …, n] such that no two queens attack. Solution Space Set that includes at least one solution to the problem. Subset problem. n = 2, {00, 01, 10, 11} n = 3, {000, 001, 010, 100, 011, 101, 110, 111} Solution space for subset problem has 2n members. Nonsystematic search of the space for the answer takes O(p2n) time, where p is the time needed to evaluate each member of the solution space. Solution Space Permutation problem. n = 2, {12, 21} n = 3, {123, 132, 213, 231, 312, 321} Solution space for a permutation problem has n! members. Nonsystematic search of the space for the answer takes O(pn!) time, where p is the time needed to evaluate a member of the solution space. Subset & Permutation Problems Subset problem of size n. Nonsystematic search of the space for the answer takes O(p2n) time, where p is the time needed to evaluate each member of the solution space. Permutation problem of size n. Nonsystematic search of the space for the answer takes O(pn!) time, where p is the time needed to evaluate each member of the solution space. Backtracking and branch and bound perform a systematic search; often taking much less time than taken by a nonsystematic search. Tree Organization of Solution Space Set up a tree structure such that the leaves represent members of the solution space. For a size n subset problem, this tree structure has 2n leaves. For a size n permutation problem, this tree structure has n! leaves. The tree structure is too big to store in memory; it also takes too much time to create the tree structure. Portions of the tree structure are created by the backtracking and branch and bound algorithms as needed. Subset Tree For n = 4 x1= 0 x1=1 x2=1 x3=1 x2=1 x2= 0 x2= 0 x3= 0 x4=1 1110 x4=0 1011 0111 0001 Permutation Tree For n = 3 x1=1 x2= 2 x3=3 123 x2= 3 x3=2 132 x1= 3 x1=2 x2= 1 x3=3 213 x 2= 3 x3=1 231 x2= 1 x3=2 312 x2= 2 x3=1 321 Backtracking Search the solution space tree in a depth-first manner. May be done recursively or use a stack to retain the path from the root to the current node in the tree. The solution space tree exists only in your mind, not in the computer. Backtracking Depth-First Search x1=1 x2=1 x2= 0 x1= 0 x2=1 x2= 0 Backtracking Depth-First Search x1=1 x2=1 x2= 0 x1= 0 x2=1 x2= 0 Backtracking Depth-First Search x1=1 x2=1 x2= 0 x1= 0 x2=1 x2= 0 Backtracking Depth-First Search x1=1 x2=1 x2= 0 x1= 0 x2=1 x2= 0 Backtracking Depth-First Search x1=1 x2=1 x2= 0 x1= 0 x2=1 x2= 0 O(2n) Subet Sum & Bounding Functions x1=1 x2=1 x2= 0 x1= 0 x2=1 x2= 0 Each forward and backward move takes O(1) time. Backtracking Space required is O(tree height). With effective bounding functions, large instances can often be solved. For some problems (e.g., 0/1 knapsack), the answer (or a very good solution) may be found quickly but a lot of additional time is needed to complete the search of the tree. Run backtracking for as much time as is feasible and use best solution found up to that time. Branch And Bound Search the tree using a breadth-first search (FIFO branch and bound). Search the tree as in a bfs, but replace the FIFO queue with a stack (LIFO branch and bound). Replace the FIFO queue with a priority queue (least-cost (or max priority) branch and bound). The priority of a node p in the queue is based on an estimate of the likelihood that the answer node is in the subtree whose root is p. Branch And Bound Space required is O(number of leaves). For some problems, solutions are at different levels of the tree (e.g., 16 puzzle). 4 14 1 13 2 3 12 6 11 5 10 9 8 7 15 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Branch And Bound FIFO branch and bound finds solution closest to root. Backtracking may never find a solution because tree depth is infinite (unless repeating configurations are eliminated). Least-cost branch and bound directs the search to parts of the space most likely to contain the answer. So it could perform better than backtracking.