1 00:00:00 --> 00:00:00 2 00:00:00 --> 00:00:02 The following content is provided under a Creative 3 00:00:02 --> 00:00:03 Commons license. 4 00:00:03 --> 00:00:06 Your support will help MIT OpenCourseWare continue to 5 00:00:06 --> 00:00:10 offer high quality educational resources for free. 6 00:00:10 --> 00:00:13 To make a donation or view additional materials from 7 00:00:13 --> 00:00:16 hundreds of MIT courses, visit MIT OpenCourseWare 8 00:00:16 --> 00:00:21 at ocw.mit.edu. 9 00:00:21 --> 00:00:22 PROFESSOR: OK. 10 00:00:22 --> 00:00:24 I want to start where we left off. 11 00:00:24 --> 00:00:30 You remember last time we were looking at Fibonacci. 12 00:00:30 --> 00:00:32 And so we've got it up here, a nice little recursive 13 00:00:32 --> 00:00:34 implementation of it. 14 00:00:34 --> 00:00:40 And the thing I wanted to point out is, we've got this global 15 00:00:40 --> 00:00:43 variable number of calls. 16 00:00:43 --> 00:00:47 Which is there not because Fibonacci needs it but just for 17 00:00:47 --> 00:00:50 pedagogical reasons, so that we can keep track of how much 18 00:00:50 --> 00:00:53 work this thing is doing. 19 00:00:53 --> 00:00:55 And I've turned on a print statement which 20 00:00:55 --> 00:00:57 was off last time. 21 00:00:57 --> 00:01:01 So we can see what it's doing is it runs. 22 00:01:01 --> 00:01:18 So let's try it here with Fib of 6. 23 00:01:18 --> 00:01:25 So, as we would hope, Fib of 6 happens to be 8. 24 00:01:25 --> 00:01:28 That right? 25 00:01:28 --> 00:01:30 That right, everybody? 26 00:01:30 --> 00:01:34 Should Fib of 6 be 8? 27 00:01:34 --> 00:01:38 I don't think so. 28 00:01:38 --> 00:01:41 So first thing we should do is scratch our heads and 29 00:01:41 --> 00:01:48 see what's going on here. 30 00:01:48 --> 00:01:52 Alright, let's look at it. 31 00:01:52 --> 00:01:57 What's happening here? 32 00:01:57 --> 00:02:04 This is your morning wake-up call. 33 00:02:04 --> 00:02:13 What is happening? 34 00:02:13 --> 00:02:13 Yes. 35 00:02:13 --> 00:02:22 STUDENT: [INAUDIBLE] 36 00:02:22 --> 00:02:25 PROFESSOR: See if I can get it all the way to the back. 37 00:02:25 --> 00:02:26 No I can't. 38 00:02:26 --> 00:02:28 That's embarrassing. 39 00:02:28 --> 00:02:29 Alright. 40 00:02:29 --> 00:02:34 So if n is less than or equal to 1, return n. 41 00:02:34 --> 00:02:39 Well that's not right, right? 42 00:02:39 --> 00:02:44 What should I be doing there? 43 00:02:44 --> 00:02:48 Because Fib of 0 is? 44 00:02:48 --> 00:02:49 What? 45 00:02:49 --> 00:02:50 1. 46 00:02:50 --> 00:03:12 So let's fix it. 47 00:03:12 --> 00:03:14 How about that, right? 48 00:03:14 --> 00:03:20 Or maybe, what would be even simpler than that? 49 00:03:20 --> 00:03:23 Maybe I should just do that. 50 00:03:23 --> 00:03:31 Now let's try it. 51 00:03:31 --> 00:03:36 We feel better about this? 52 00:03:36 --> 00:03:39 We like that answer? 53 00:03:39 --> 00:03:46 Yes, no? 54 00:03:46 --> 00:03:47 What's the answer, guys? 55 00:03:47 --> 00:03:51 What should Fibonacci of 6 be? 56 00:03:51 --> 00:03:55 I think that's the right answer, right? 57 00:03:55 --> 00:03:58 OK. 58 00:03:58 --> 00:04:03 So what do I want you to notice about this? 59 00:04:03 --> 00:04:07 I've computed a value which is 13. 60 00:04:07 --> 00:04:10 And it's taken me 25 calls. 61 00:04:10 --> 00:04:14 25 recursive calls to get there. 62 00:04:14 --> 00:04:17 Why is it taking so many? 63 00:04:17 --> 00:04:22 Well, what we can see here is that I'm computing the same 64 00:04:22 --> 00:04:26 value over and over again. 65 00:04:26 --> 00:04:28 Because if we look at the recursive structure of the 66 00:04:28 --> 00:04:41 program, what we'll see that's going on here is, I call Fib of 67 00:04:41 --> 00:04:49 5 and 4, but then Fib of 5 is also going to call Fib of 4. 68 00:04:49 --> 00:04:54 So I'm going to be computing it on those branches. 69 00:04:54 --> 00:04:59 And then it gets worse and worse as I go down. 70 00:04:59 --> 00:05:02 So if I think about computing Fib of 0 I'm going to be 71 00:05:02 --> 00:05:04 computing that a lot of times. 72 00:05:04 --> 00:05:07 Now, fortunately, Fib of 0 is short. 73 00:05:07 --> 00:05:10 But the other ones are not so short. 74 00:05:10 --> 00:05:15 And so what I see is that as I run this, I'm doing a lot 75 00:05:15 --> 00:05:18 of redundant computation. 76 00:05:18 --> 00:05:28 Computing values whose answer I should already know. 77 00:05:28 --> 00:05:32 That's, you'll remember last time, I talked about the notion 78 00:05:32 --> 00:05:36 of overlapping sub-problems. 79 00:05:36 --> 00:05:40 And that's what we have here. 80 00:05:40 --> 00:05:45 As with many recursive algorithms, I solve a bigger 81 00:05:45 --> 00:05:48 problem by solving a smaller instance of 82 00:05:48 --> 00:05:50 the original problem. 83 00:05:50 --> 00:05:52 But here there's overlap. 84 00:05:52 --> 00:05:56 The instant unlike binary search, where each instance 85 00:05:56 --> 00:06:01 was separate, here the instances overlap. 86 00:06:01 --> 00:06:03 They share something in common. 87 00:06:03 --> 00:06:07 In fact, they share quite a lot in common. 88 00:06:07 --> 00:06:12 That's not unusual. 89 00:06:12 --> 00:06:16 That will lead me to use a technique I mentioned again 90 00:06:16 --> 00:06:24 last time, called memoization. 91 00:06:24 --> 00:06:36 Effectively, what that says is, we record a value the first 92 00:06:36 --> 00:06:50 time it's computed, then look it up the subsequent 93 00:06:50 --> 00:06:56 times we need it. 94 00:06:56 --> 00:06:57 So it makes sense. 95 00:06:57 --> 00:06:59 If I know I'm going to need something over and over again, 96 00:06:59 --> 00:07:03 I squirrel it away somewhere and then get it back 97 00:07:03 --> 00:07:06 when I need it. 98 00:07:06 --> 00:07:25 So let's look at an example of that. 99 00:07:25 --> 00:07:34 So I'm going to have something called fast Fib. 100 00:07:34 --> 00:07:38 But first I'm going to have, let's look at what fast Fib 101 00:07:38 --> 00:07:41 does and then we'll come back to the next question. 102 00:07:41 --> 00:07:50 It takes the number whose Fibonacci I want plus a memo. 103 00:07:50 --> 00:07:56 And the memo will be a dictionary that maps me from a 104 00:07:56 --> 00:08:05 number to Fib of that number. 105 00:08:05 --> 00:08:09 So what I'm going to do, well, let's get rid of this 106 00:08:09 --> 00:08:13 print statement for now. 107 00:08:13 --> 00:08:19 I'm going to say, if n is not in memo. 108 00:08:19 --> 00:08:22 Remember the way dictionary works, this is the key. 109 00:08:22 --> 00:08:25 Is the key of a value. 110 00:08:25 --> 00:08:31 Then I'll call fast Fib recursively, with n minus 1 in 111 00:08:31 --> 00:08:38 memo, and n minus 2 in memo. 112 00:08:38 --> 00:08:42 Otherwise I'll return the memo. 113 00:08:42 --> 00:08:44 Well, let's look at it for a second. 114 00:08:44 --> 00:08:47 This is the basic idea. 115 00:08:47 --> 00:08:51 But do we actually believe this is going to work? 116 00:08:51 --> 00:08:53 And, again, I want you to look at this and think about 117 00:08:53 --> 00:08:56 what's going to happen here. 118 00:08:56 --> 00:09:02 Before we do that, or as you do that, let's look at Fib 1. 119 00:09:02 --> 00:09:07 The key thing to notice about Fib 1 is that it has the 120 00:09:07 --> 00:09:12 same specification as Fib. 121 00:09:12 --> 00:09:16 Because when somebody calls Fibonacci, they shouldn't 122 00:09:16 --> 00:09:19 worry about memos. 123 00:09:19 --> 00:09:21 And how I'd implemented it. 124 00:09:21 --> 00:09:23 That has to be under the covers. 125 00:09:23 --> 00:09:25 So I don't want them to have to call something 126 00:09:25 --> 00:09:27 with two arguments. 127 00:09:27 --> 00:09:30 The integer and the memo. 128 00:09:30 --> 00:09:37 So I'll create Fib 1, which has the same arguments as Fib. 129 00:09:37 --> 00:09:43 The first thing it does is it initializes the memo. 130 00:09:43 --> 00:09:47 And initializes it by saying, if I get 0 I -- whoops. 131 00:09:47 --> 00:09:50 Aha. 132 00:09:50 --> 00:09:56 Let's be careful here. 133 00:09:56 --> 00:09:58 If I get 0 I return 1. 134 00:09:58 --> 00:10:00 I get 1, I return 1. 135 00:10:00 --> 00:10:06 So I put two things in the memo already. 136 00:10:06 --> 00:10:15 And then I'll call fast Fib and it returns the result it has. 137 00:10:15 --> 00:10:18 So you see the basic idea. 138 00:10:18 --> 00:10:22 I take something with the same parameters as the original. 139 00:10:22 --> 00:10:23 Add this memo. 140 00:10:23 --> 00:10:26 Give it some initial values. 141 00:10:26 --> 00:10:30 And then call. 142 00:10:30 --> 00:10:32 So now what do we think? 143 00:10:32 --> 00:10:38 Is this going to work? 144 00:10:38 --> 00:10:42 Or is there an issue here? 145 00:10:42 --> 00:10:43 What do you think? 146 00:10:43 --> 00:10:45 Think it through. 147 00:10:45 --> 00:10:50 If it's not in the memo, I'll compute its value 148 00:10:50 --> 00:10:53 and put it in the memo. 149 00:10:53 --> 00:10:55 And then I'll return it. 150 00:10:55 --> 00:10:56 OK? 151 00:10:56 --> 00:11:01 If it was already there, I just look it up. 152 00:11:01 --> 00:11:04 That make sense to everybody? 153 00:11:04 --> 00:11:20 Let's see what happens if we run it. 154 00:11:20 --> 00:11:23 Well, actually, let's turn the print statement on, since 155 00:11:23 --> 00:11:32 we're doing it with a small value here. 156 00:11:32 --> 00:11:38 So what we've seen is I've run it twice here. 157 00:11:38 --> 00:11:43 When I ran it up here, with the old Fib, and we printed 158 00:11:43 --> 00:11:47 the result, and I ran it with Fib 1 down here. 159 00:11:47 --> 00:11:52 The good news is we got 13 both times. 160 00:11:52 --> 00:11:58 The even better news is that instead of 25 calls, 161 00:11:58 --> 00:12:05 it was only 11 calls. 162 00:12:05 --> 00:12:10 So it's a big improvement. 163 00:12:10 --> 00:12:13 Let's see what happens, just to get an idea of how 164 00:12:13 --> 00:12:15 big the improvement is. 165 00:12:15 --> 00:12:23 I'm going to take out the two print statements. 166 00:12:23 --> 00:12:39 And let's try it with a bigger number. 167 00:12:39 --> 00:12:42 It's going to take a little bit. 168 00:12:42 --> 00:12:46 Well, look at this difference. 169 00:12:46 --> 00:12:54 It's 2,692,537 versus 59. 170 00:12:54 --> 00:13:00 That's a pretty darn big difference. 171 00:13:00 --> 00:13:03 And I won't ask you to check whether it got 172 00:13:03 --> 00:13:05 the right answer. 173 00:13:05 --> 00:13:07 At least, not in your heads. 174 00:13:07 --> 00:13:11 So you can see, and this is an important thing we look at, is 175 00:13:11 --> 00:13:14 that as we look at growth, it didn't look like it 176 00:13:14 --> 00:13:15 mattered a lot with 6. 177 00:13:15 --> 00:13:19 Because it was one small number to one slightly smaller number. 178 00:13:19 --> 00:13:24 But this thing grows exponentially. 179 00:13:24 --> 00:13:26 It's a little bit complicated exactly how. 180 00:13:26 --> 00:13:31 But you can see as I go up to 30 I get a pretty big number. 181 00:13:31 --> 00:13:35 And 59 is a pretty small number. 182 00:13:35 --> 00:13:39 So we see that the memoization here is buying me a 183 00:13:39 --> 00:13:43 tremendous advantage. 184 00:13:43 --> 00:13:46 And this is what lies at the heart of this very 185 00:13:46 --> 00:13:50 general technique called dynamic programming. 186 00:13:50 --> 00:13:54 And in fact, it lies at the heart of a lot of useful 187 00:13:54 --> 00:14:00 computational techniques where we save results. 188 00:14:00 --> 00:14:03 So if you think about the way something like, say, Mapquest 189 00:14:03 --> 00:14:07 works, and last week in recitation you looked at 190 00:14:07 --> 00:14:11 the fact that shortest path is exponential. 191 00:14:11 --> 00:14:16 Well, what it does is it saves a lot of paths. 192 00:14:16 --> 00:14:18 It kind of knows people are going to ask how do you get 193 00:14:18 --> 00:14:21 from Boston to New York City. 194 00:14:21 --> 00:14:24 And it may have saved that. 195 00:14:24 --> 00:14:27 And if you're going from Boston to someplace else where New 196 00:14:27 --> 00:14:30 York just happens to be on the way, it doesn't have to 197 00:14:30 --> 00:14:32 recompute that part of it. 198 00:14:32 --> 00:14:36 So it's saved a lot of things and squirreled them away. 199 00:14:36 --> 00:14:38 And that's essentially what we're doing here. 200 00:14:38 --> 00:14:41 Here we're doing it as part of one algorithm. 201 00:14:41 --> 00:14:44 There, they're just storing a database of previously 202 00:14:44 --> 00:14:46 solved problems. 203 00:14:46 --> 00:14:51 And relying on something called table lookup, Of which 204 00:14:51 --> 00:14:57 memoization is a special case. 205 00:14:57 --> 00:14:59 But table lookup is very common. 206 00:14:59 --> 00:15:01 When you do something complicated you save the 207 00:15:01 --> 00:15:06 answers and then you go get it later. 208 00:15:06 --> 00:15:13 I should add that in some sense this is a phony 209 00:15:13 --> 00:15:15 straw-man Fibonacci. 210 00:15:15 --> 00:15:18 Nobody in their right mind actually implements a 211 00:15:18 --> 00:15:22 recursive Fibonacci the way I did it originally. 212 00:15:22 --> 00:15:24 Because the right way to do it is iteratively. 213 00:15:24 --> 00:15:27 And the right way to do it is not starting at the top, it's 214 00:15:27 --> 00:15:29 starting at the bottom. 215 00:15:29 --> 00:15:31 And so you can piece it together that way. 216 00:15:31 --> 00:15:34 But don't worry about it, it's not, I'm just using it because 217 00:15:34 --> 00:15:38 it's a simpler example than the one I really want to get 218 00:15:38 --> 00:15:41 to, which is knapsack. 219 00:15:41 --> 00:15:44 OK, people get this? 220 00:15:44 --> 00:15:50 And see the basic idea and why it's wonderful? 221 00:15:50 --> 00:15:52 Alright. 222 00:15:52 --> 00:15:55 Now, when we talked about optimization problems in 223 00:15:55 --> 00:15:59 dynamic programming, I said there were two 224 00:15:59 --> 00:16:02 things to look for. 225 00:16:02 --> 00:16:06 One was overlapping sub-problems. 226 00:16:06 --> 00:16:17 And the other one was optimal substructure. 227 00:16:17 --> 00:16:22 The notion here is that you can get a globally optimal 228 00:16:22 --> 00:16:56 solution from locally optimal solutions to sub-problems. 229 00:16:56 --> 00:17:03 This is not true of all problems. 230 00:17:03 --> 00:17:07 But as we'll see, it's true of a lot of problems. 231 00:17:07 --> 00:17:12 And when you have an optimal substructure and the local 232 00:17:12 --> 00:17:16 solutions overlap, that's when you can bring dynamic 233 00:17:16 --> 00:17:19 programming to bear. 234 00:17:19 --> 00:17:21 So when you're trying to think about is this a problem that I 235 00:17:21 --> 00:17:24 can solve with dynamic programming, these are the 236 00:17:24 --> 00:17:29 two questions you ask. 237 00:17:29 --> 00:17:33 Let's now go back and instantiate these ideas for 238 00:17:33 --> 00:17:35 the knapsack problem we looked at last time. 239 00:17:35 --> 00:17:42 In particular, for the 0-1 knapsack problem. 240 00:17:42 --> 00:17:47 So, we have a collection of objects. 241 00:17:47 --> 00:17:50 We'll call it a. 242 00:17:50 --> 00:17:54 And for each object in 0, we have a value. 243 00:17:54 --> 00:17:57 In a, we have a value. 244 00:17:57 --> 00:18:02 And now we want to find the subset of a that has the 245 00:18:02 --> 00:18:06 maximum value, subject to the weight constraint. 246 00:18:06 --> 00:18:09 I'm just repeating the problem. 247 00:18:09 --> 00:18:15 Now, what we saw last time is there's a brute force solution. 248 00:18:15 --> 00:18:18 As you have discovered in recent problem set, it is 249 00:18:18 --> 00:18:23 possible to construct all subsets of a set. 250 00:18:23 --> 00:18:28 And so you could construct all subsets, check that the weight 251 00:18:28 --> 00:18:31 is less than the weight of the knapsack, and then choose the 252 00:18:31 --> 00:18:33 subset with the maximum value. 253 00:18:33 --> 00:18:36 Or a subset with the maximum value, there may be more 254 00:18:36 --> 00:18:40 than one, and you're done. 255 00:18:40 --> 00:18:49 On the other hand, we've seen that if the size of a is n, 256 00:18:49 --> 00:18:54 that's to say, we have n elements to choose from, then 257 00:18:54 --> 00:18:58 the number of possible subsets is 2 to the n. 258 00:18:58 --> 00:19:03 Remember, we saw that last time looking at the binary numbers. 259 00:19:03 --> 00:19:07 2 to the n is a big number. 260 00:19:07 --> 00:19:09 And maybe we don't have to consider them all, because 261 00:19:09 --> 00:19:12 we can say, oh this one is going to be way too big. 262 00:19:12 --> 00:19:15 It's going to weigh too much, we don't need to look at it. 263 00:19:15 --> 00:19:19 But it'll still be order 2 to the n. 264 00:19:19 --> 00:19:24 If n is something like 50, not a big number, 2 to 265 00:19:24 --> 00:19:31 the 50 is a huge number. 266 00:19:31 --> 00:19:35 So let's ask, is there an optimal substructure 267 00:19:35 --> 00:19:36 to this problem. 268 00:19:36 --> 00:19:43 That would let us tackle it with dynamic programming. 269 00:19:43 --> 00:19:47 And we're going to do this initially by looking at a 270 00:19:47 --> 00:19:52 straightforward implementation based upon what's called 271 00:19:52 --> 00:20:01 the decision tree. 272 00:20:01 --> 00:20:05 This is a very important concept, and we'll see a lot 273 00:20:05 --> 00:20:10 of algorithms essentially implement decision trees. 274 00:20:10 --> 00:20:12 Let's look at an example. 275 00:20:12 --> 00:20:16 Let's assume that the weights, and I'll try a really small 276 00:20:16 --> 00:20:24 example to start with, are 5, 3 and 2, and the values, 277 00:20:24 --> 00:20:31 corresponding values, are 9, 7 and 8. 278 00:20:31 --> 00:20:39 And the maximum, we'll say, is 5. 279 00:20:39 --> 00:20:45 So what we do is, we start by considering for each item 280 00:20:45 --> 00:20:47 whether to take it or not. 281 00:20:47 --> 00:20:50 For reasons that will become apparent when we implement it 282 00:20:50 --> 00:20:55 in code, I'm going to start at the back. 283 00:20:55 --> 00:20:59 The last element in the list. 284 00:20:59 --> 00:21:03 And what I'm going to use is the index of that element to 285 00:21:03 --> 00:21:05 keep track of where I am. 286 00:21:05 --> 00:21:08 So I'm not going to worry whether this item is a vase 287 00:21:08 --> 00:21:10 or a watch or painting. 288 00:21:10 --> 00:21:13 I'm just going to say it's the n'th element. 289 00:21:13 --> 00:21:19 Where n'th is somewhere between 0 and 2 in this case. 290 00:21:19 --> 00:21:26 And then we'll construct our tree as follows: each node, 291 00:21:26 --> 00:21:28 well, let me put an example here. 292 00:21:28 --> 00:21:40 The first node will be the to-pull 2, 5 and 0. 293 00:21:40 --> 00:21:46 Standing for, let me make sure I get this in the right order, 294 00:21:46 --> 00:21:59 well, the index which is 2, the last element in this case, 295 00:21:59 --> 00:22:03 so that's the index. 296 00:22:03 --> 00:22:09 This is the weight still available. 297 00:22:09 --> 00:22:11 If you see that in the shadow. 298 00:22:11 --> 00:22:17 And this is the value currently obtained. 299 00:22:17 --> 00:22:21 So I haven't included anything. 300 00:22:21 --> 00:22:23 Means I have all 5 pounds left. 301 00:22:23 --> 00:22:27 But I don't have anything of value. 302 00:22:27 --> 00:22:32 Now, the decision tree, if I branch left, 303 00:22:32 --> 00:22:34 it's a binary tree. 304 00:22:34 --> 00:22:42 This is going to be don't take. 305 00:22:42 --> 00:22:48 So I'm not going to take the item with an index of 2. 306 00:22:48 --> 00:22:58 So that means this node will have an index of 1. 307 00:22:58 --> 00:23:05 Next item to be considered, I still have 5 pounds available. 308 00:23:05 --> 00:23:14 And I have 0 value. 309 00:23:14 --> 00:23:21 To be systematic, I'm going to build this tree 310 00:23:21 --> 00:23:32 depth-first left-first. 311 00:23:32 --> 00:23:36 At each node, I'm going to go left until I 312 00:23:36 --> 00:23:41 can't go any further. 313 00:23:41 --> 00:23:46 So we'll take another don't-take branch here. 314 00:23:46 --> 00:23:50 And what is this node going to look like? 315 00:23:50 --> 00:23:50 Pardon? 316 00:23:50 --> 00:23:53 STUDENT: [INAUDIBLE] 317 00:23:53 --> 00:23:57 PROFESSOR: 0, 5, 0. 318 00:23:57 --> 00:23:59 And then we'll go one more. 319 00:23:59 --> 00:24:03 And I'll just put a minus indicating I'm done. 320 00:24:03 --> 00:24:07 I can't look below that. 321 00:24:07 --> 00:24:13 I still have five pounds left, and I still have zero value. 322 00:24:13 --> 00:24:34 The next thing I'm going to do is backtrack. 323 00:24:34 --> 00:24:36 That is to say, I'm going to go back to a node 324 00:24:36 --> 00:24:38 I've already visited. 325 00:24:38 --> 00:24:43 Go up the tree 1. 326 00:24:43 --> 00:24:48 And now, of course, the only place to go is right. 327 00:24:48 --> 00:24:50 And now I get to include something. 328 00:24:50 --> 00:24:54 Yeah. 329 00:24:54 --> 00:24:57 And what does this node look like? 330 00:24:57 --> 00:25:04 Well, I'll give you a hint, it starts with a minus. 331 00:25:04 --> 00:25:05 What next? 332 00:25:05 --> 00:25:08 STUDENT: [INAUDIBLE] 333 00:25:08 --> 00:25:09 PROFESSOR: Pardon. 334 00:25:09 --> 00:25:10 0. 335 00:25:10 --> 00:25:11 And? 336 00:25:11 --> 00:25:12 STUDENT: [INAUDIBLE] 337 00:25:12 --> 00:25:14 PROFESSOR: Pardon? 338 00:25:14 --> 00:25:17 5. 339 00:25:17 --> 00:25:18 Alright. 340 00:25:18 --> 00:25:24 So far, this looks like the winner. 341 00:25:24 --> 00:25:26 But, we'd better keep going. 342 00:25:26 --> 00:25:28 We backtrack to here again. 343 00:25:28 --> 00:25:32 There's nothing useful to do. 344 00:25:32 --> 00:25:35 We backtrack to here. 345 00:25:35 --> 00:25:42 And we ask, what do we get with this node? 346 00:25:42 --> 00:25:47 0, 3. 347 00:25:47 --> 00:25:47 Somebody? 348 00:25:47 --> 00:25:49 STUDENT: [INAUDIBLE] 349 00:25:49 --> 00:25:52 PROFESSOR: Louder. 350 00:25:52 --> 00:25:54 2. 351 00:25:54 --> 00:25:55 And then? 352 00:25:55 --> 00:26:01 STUDENT: [INAUDIBLE] 353 00:26:01 --> 00:26:04 PROFESSOR: There's a value here, what's this value? 354 00:26:04 --> 00:26:09 I've included item number 1, which has a value of 7. 355 00:26:09 --> 00:26:17 Right? 356 00:26:17 --> 00:26:23 So now this looks like the winner. 357 00:26:23 --> 00:26:23 Pardon? 358 00:26:23 --> 00:26:27 STUDENT: [INAUDIBLE] 359 00:26:27 --> 00:26:28 PROFESSOR: This one? 360 00:26:28 --> 00:26:31 STUDENT: Yeah. 361 00:26:31 --> 00:26:31 [INAUDIBLE] 362 00:26:31 --> 00:26:36 PROFESSOR: Remember, I'm working from the back. 363 00:26:36 --> 00:26:38 So it shouldn't be 9. 364 00:26:38 --> 00:26:40 Should be what? 365 00:26:40 --> 00:26:42 Item 0, oh, you're right, items 0 is 9. 366 00:26:42 --> 00:26:45 Thank you. 367 00:26:45 --> 00:26:48 Right you are. 368 00:26:48 --> 00:26:52 Still looks like the winner. 369 00:26:52 --> 00:26:53 I can't hear you. 370 00:26:53 --> 00:27:03 STUDENT: [INAUDIBLE] 371 00:27:03 --> 00:27:06 PROFESSOR: Let's be careful about this. 372 00:27:06 --> 00:27:10 I'm glad people are watching. 373 00:27:10 --> 00:27:11 So we're here. 374 00:27:11 --> 00:27:17 And now we've got 5 pounds available. 375 00:27:17 --> 00:27:18 That's good. 376 00:27:18 --> 00:27:22 And we're considering item number 0. 377 00:27:22 --> 00:27:26 Which happens to weigh 5 pounds. 378 00:27:26 --> 00:27:29 So that's a good thing. 379 00:27:29 --> 00:27:35 So, it's the last item to consider. 380 00:27:35 --> 00:27:40 If we include it, we'll have nothing left. 381 00:27:40 --> 00:27:43 Because we had 5 and we're using all 5. 382 00:27:43 --> 00:27:46 So that will be 0. 383 00:27:46 --> 00:27:53 And its value is 9. 384 00:27:53 --> 00:27:55 So we put one item in the backpack and we've 385 00:27:55 --> 00:27:58 got a value of 9. 386 00:27:58 --> 00:28:01 Anyone have a problem with that? 387 00:28:01 --> 00:28:07 So far, so good? 388 00:28:07 --> 00:28:09 Now we've backed up to here. 389 00:28:09 --> 00:28:12 We're considering item 1 and we're trying to ask 390 00:28:12 --> 00:28:14 whether we can put it in. 391 00:28:14 --> 00:28:17 Item 1 has a weight of 3. 392 00:28:17 --> 00:28:22 So it would fit. 393 00:28:22 --> 00:28:26 And if we use it, we have 2 pounds left. 394 00:28:26 --> 00:28:29 And item 1 has a value of 7. 395 00:28:29 --> 00:28:33 So if we did this, we'd have a value of 7. 396 00:28:33 --> 00:28:36 But we're not done yet, right? 397 00:28:36 --> 00:28:40 We still have some things to consider. 398 00:28:40 --> 00:28:46 Well, we could consider not putting in item 0. 399 00:28:46 --> 00:28:48 That makes perfect sense. 400 00:28:48 --> 00:28:56 And we're back to where we're there, minus 2 and 7. 401 00:28:56 --> 00:29:02 And now let's ask the question how, about putting in item 0. 402 00:29:02 --> 00:29:05 Well, we can't. 403 00:29:05 --> 00:29:09 Because it would weigh 5 pounds, I only have 2 left. 404 00:29:09 --> 00:29:17 So there is no right branch to this one. 405 00:29:17 --> 00:29:20 So I'm making whatever decisions I can 406 00:29:20 --> 00:29:24 make along the way. 407 00:29:24 --> 00:29:26 Let's back up to here. 408 00:29:26 --> 00:29:31 And now we're going to ask about taking item 2. 409 00:29:31 --> 00:29:37 If we take item 2, then, well, the index after 410 00:29:37 --> 00:29:39 that will of course be 1. 411 00:29:39 --> 00:29:45 And the available weight will be 3. 412 00:29:45 --> 00:29:53 And the value will be 8, right? 413 00:29:53 --> 00:29:59 Alright, now we say, can I take item 1. 414 00:29:59 --> 00:29:59 Yeah. 415 00:29:59 --> 00:30:01 I can. 416 00:30:01 --> 00:30:03 It only weighs 3 and I happen to have 3 left. 417 00:30:03 --> 00:30:07 So that's good. 418 00:30:07 --> 00:30:08 Don't take it, right. 419 00:30:08 --> 00:30:08 Sorry. 420 00:30:08 --> 00:30:10 This is the don't take branch. 421 00:30:10 --> 00:30:17 So I go to 0, 3, 8. 422 00:30:17 --> 00:30:20 And then I can do another don't take branch. 423 00:30:20 --> 00:30:28 And this gets me to what, minus 3, 8. 424 00:30:28 --> 00:30:33 I'll now back up. 425 00:30:33 --> 00:30:37 And I'll say, alright, suppose I do take item 0, well I 426 00:30:37 --> 00:30:39 can't take item 0, right? 427 00:30:39 --> 00:30:41 Weighs too much. 428 00:30:41 --> 00:30:46 So, don't have that branch. 429 00:30:46 --> 00:30:49 Back up to here. 430 00:30:49 --> 00:30:51 Alright, can I take item 1? 431 00:30:51 --> 00:30:55 Yes, I can. 432 00:30:55 --> 00:30:57 And that gives me what? 433 00:30:57 --> 00:31:03 STUDENT: [INAUDIBLE] 434 00:31:03 --> 00:31:07 PROFESSOR: We have a winner. 435 00:31:07 --> 00:31:10 So it's kind of tedious, but it's important to 436 00:31:10 --> 00:31:13 see that it works. 437 00:31:13 --> 00:31:15 It's systematic. 438 00:31:15 --> 00:31:21 I have a way of exploring the possible solutions. 439 00:31:21 --> 00:31:29 And at the end I choose the winner. 440 00:31:29 --> 00:31:34 What's the complexity of this decision tree solution? 441 00:31:34 --> 00:31:38 Well, in the worst case, we're enumerating every 442 00:31:38 --> 00:31:41 possibility of in and out. 443 00:31:41 --> 00:31:44 Now I've shortened it a little bit by saying, ah, we've run 444 00:31:44 --> 00:31:46 out of weight, we're OK. 445 00:31:46 --> 00:31:51 But effectively it is, as we saw before, exponential. 446 00:31:51 --> 00:31:54 2 to the n, every value in the bit vector we looked at 447 00:31:54 --> 00:31:57 last time is either 0 or 1. 448 00:31:57 --> 00:32:04 So it's a binary number of n bits, 2 to the n. 449 00:32:04 --> 00:32:11 Let's look at a straightforward implementation of this. 450 00:32:11 --> 00:32:15 I'll get rid of Fibonacci here, we don't want to bother 451 00:32:15 --> 00:32:19 looking at that again. 452 00:32:19 --> 00:32:22 Hold on a second until I comment this out, yes. 453 00:32:22 --> 00:32:28 STUDENT: [INAUDIBLE] 454 00:32:28 --> 00:32:29 PROFESSOR: Yeah. 455 00:32:29 --> 00:32:31 There's a branch we could finish here, but since we're 456 00:32:31 --> 00:32:35 out of weight we sort of know we're going to be done. 457 00:32:35 --> 00:32:38 So we could complete it. 458 00:32:38 --> 00:32:44 But it's not very interesting. 459 00:32:44 --> 00:32:54 But yes, we probably should have done that. 460 00:32:54 --> 00:33:05 So let's look at an implementation here. 461 00:33:05 --> 00:33:06 Whoops. 462 00:33:06 --> 00:33:16 You had these in the handout, by the way. 463 00:33:16 --> 00:33:20 So here's max val. 464 00:33:20 --> 00:33:24 It takes four arguments. 465 00:33:24 --> 00:33:27 The weight, w, and v, these are the two 466 00:33:27 --> 00:33:30 vectors we've seen here. 467 00:33:30 --> 00:33:33 Of the weights and the values. 468 00:33:33 --> 00:33:39 It takes i, which is in some sense the length of those 469 00:33:39 --> 00:33:45 vectors, minus 1, because of the way Python works. 470 00:33:45 --> 00:33:47 So that gives me my index. 471 00:33:47 --> 00:33:51 And the amount of weight available, a w, for 472 00:33:51 --> 00:33:57 available weight. 473 00:33:57 --> 00:34:03 So again, I put in this num calls, which you can ignore. 474 00:34:03 --> 00:34:09 First line says, if i is 0, that means I'm looking at 475 00:34:09 --> 00:34:13 the very last element. 476 00:34:13 --> 00:34:19 Then if the weight of i is less than the available weight, I 477 00:34:19 --> 00:34:24 can return the value of i. 478 00:34:24 --> 00:34:27 Otherwise it's 0. 479 00:34:27 --> 00:34:29 I've got one element to look at. 480 00:34:29 --> 00:34:31 I either put it in if I can. 481 00:34:31 --> 00:34:34 If I can't, I don't. 482 00:34:34 --> 00:34:42 Alright, so if I'm at the end of the chain, that's my value. 483 00:34:42 --> 00:34:47 In either event, if I'm looking at the last element, I return. 484 00:34:47 --> 00:34:52 The next line says alright, suppose I don't, I'm not 485 00:34:52 --> 00:34:54 at the last element. 486 00:34:54 --> 00:34:58 Suppose I don't include it. 487 00:34:58 --> 00:35:02 Then the maximum value I can get is the maximum 488 00:35:02 --> 00:35:05 value of what I had. 489 00:35:05 --> 00:35:09 But with index i minus 1. 490 00:35:09 --> 00:35:16 So that's the don't-take branch. 491 00:35:16 --> 00:35:20 As we've seen systematically in the don't-takes, the only thing 492 00:35:20 --> 00:35:28 that gets changed is the index. 493 00:35:28 --> 00:35:34 The next line says if the weight of i is greater than 494 00:35:34 --> 00:35:39 a w, well then I know I can't put it in. 495 00:35:39 --> 00:35:42 So I might as well return the without i value 496 00:35:42 --> 00:35:46 I just computed. 497 00:35:46 --> 00:35:51 Otherwise, let's see what I get with i. 498 00:35:51 --> 00:35:58 And so the value of with i will be the value of i plus whatever 499 00:35:58 --> 00:36:05 I can get using the remaining items and decrementing the 500 00:36:05 --> 00:36:08 weight by the weight of i. 501 00:36:08 --> 00:36:10 So that's exactly what we see as we go down 502 00:36:10 --> 00:36:13 the right branches. 503 00:36:13 --> 00:36:19 I look at the rest of the list, but I've changed the value. 504 00:36:19 --> 00:36:25 And I've changed the available weight. 505 00:36:25 --> 00:36:29 And then when I get to the very end, I'm going to return the 506 00:36:29 --> 00:36:35 bigger of with i and without i. 507 00:36:35 --> 00:36:37 I've computed the value if I include i. 508 00:36:37 --> 00:36:40 I computed the value if I don't include i. 509 00:36:40 --> 00:36:47 And then I'm going to just return the bigger of the two. 510 00:36:47 --> 00:36:50 Little bit complicated, but it's basically 511 00:36:50 --> 00:36:58 just implementing this decision tree. 512 00:36:58 --> 00:37:02 Let's see what happens if we run it. 513 00:37:02 --> 00:37:05 Well, what I always do in anything like this is, the 514 00:37:05 --> 00:37:08 first thing I do is, I run it on something where I can 515 00:37:08 --> 00:37:13 actually compute the answer in my head. 516 00:37:13 --> 00:37:18 So I get a sense of whether or not I'm doing the right thing. 517 00:37:18 --> 00:37:26 So here's a little example. 518 00:37:26 --> 00:37:30 And I'm going to pause for a minute, before I run it, and 519 00:37:30 --> 00:37:33 ask each of you to compute in your head what you think 520 00:37:33 --> 00:37:38 the answer should be. 521 00:37:38 --> 00:37:40 In line with what I said about debugging. 522 00:37:40 --> 00:37:42 Always guess before you run your program what you 523 00:37:42 --> 00:37:43 think it's going to do. 524 00:37:43 --> 00:37:49 And I'm going to wait until somebody raises their hand 525 00:37:49 --> 00:37:59 and gives me an answer. 526 00:37:59 --> 00:37:59 Yes. 527 00:37:59 --> 00:38:01 STUDENT: 29? 528 00:38:01 --> 00:38:04 PROFESSOR: So we have a hypothesis that the 529 00:38:04 --> 00:38:10 answer should be 29. 530 00:38:10 --> 00:38:11 Ooh. 531 00:38:11 --> 00:38:14 That's bad. 532 00:38:14 --> 00:38:16 So as people in the back are answering these questions 533 00:38:16 --> 00:38:23 because they want to test my arm. 534 00:38:23 --> 00:38:25 The camera probably didn't catch that, but it 535 00:38:25 --> 00:38:29 was a perfect throw. 536 00:38:29 --> 00:38:32 Anyone else think it's 29? 537 00:38:32 --> 00:38:35 Anyone think it's not 29? 538 00:38:35 --> 00:38:37 What do you think it is? 539 00:38:37 --> 00:38:38 Pardon 540 00:38:38 --> 00:38:39 STUDENT: 62? 541 00:38:39 --> 00:38:40 PROFESSOR: 62. 542 00:38:40 --> 00:38:42 That would be impressive. 543 00:38:42 --> 00:38:44 62. 544 00:38:44 --> 00:38:46 Alright, well, we have a guess of 62. 545 00:38:46 --> 00:38:54 Well, let's run it and see. 546 00:38:54 --> 00:38:58 29 it is. 547 00:38:58 --> 00:39:02 And it made a total of 13 calls. 548 00:39:02 --> 00:39:08 It didn't do this little optimization I did over here. 549 00:39:08 --> 00:39:11 But it gives us our answer. 550 00:39:11 --> 00:39:16 So that's pretty good. 551 00:39:16 --> 00:39:23 Let's try a slightly larger example. 552 00:39:23 --> 00:39:25 So here I'm going to use the example we had 553 00:39:25 --> 00:39:28 in class last time. 554 00:39:28 --> 00:39:30 This was the burglar example where they had 555 00:39:30 --> 00:39:39 two copies of everything. 556 00:39:39 --> 00:39:47 Here, it gets a maximum value of 48 and 85 calls. 557 00:39:47 --> 00:39:51 So we see that I've doubled the size of the vector but I've 558 00:39:51 --> 00:39:56 much more than doubled the number of calls. 559 00:39:56 --> 00:39:58 This is one of these properties of this kind 560 00:39:58 --> 00:40:01 of exponential growth. 561 00:40:01 --> 00:40:05 Well, let's be really brave here. 562 00:40:05 --> 00:40:09 And let's try a really big vector. 563 00:40:09 --> 00:40:17 So this particular vector, you probably can't even see the 564 00:40:17 --> 00:40:20 whole thing on your screen. 565 00:40:20 --> 00:40:32 Well, it's got 40 items in it. 566 00:40:32 --> 00:40:40 Let's see what happens here. 567 00:40:40 --> 00:40:42 Alright, who wants to tell me what the answer is 568 00:40:42 --> 00:40:45 while this computes away? 569 00:40:45 --> 00:40:47 Nobody in their right mind. 570 00:40:47 --> 00:40:50 I can tell you the answer, but that's because I've cheated, 571 00:40:50 --> 00:40:52 run the program before. 572 00:40:52 --> 00:40:56 Alright, this is going to take a while. 573 00:40:56 --> 00:41:01 And why is it going to take a while? 574 00:41:01 --> 00:41:04 Actually it's not 40, I think these are, alright. 575 00:41:04 --> 00:41:14 So the answer is 75 and the number of calls is 1.7 million. 576 00:41:14 --> 00:41:15 Pardon? 577 00:41:15 --> 00:41:17 17 million. 578 00:41:17 --> 00:41:20 Computers are fast, fortunately. 579 00:41:20 --> 00:41:29 Well, that's a lot of calls. 580 00:41:29 --> 00:41:32 Let's try and figure out what's going on. 581 00:41:32 --> 00:41:35 But let's not try and figure out what's going on with this 582 00:41:35 --> 00:41:51 big, big example because we'll get really tired. 583 00:41:51 --> 00:41:52 Oh. 584 00:41:52 --> 00:41:56 Actually, before we do that, just for fun, what I want to do 585 00:41:56 --> 00:42:02 is write down for future reference, as we look at a fast 586 00:42:02 --> 00:42:09 one, that the answer is 75 and Eric, how many calls? 587 00:42:09 --> 00:42:15 240,000. 588 00:42:15 --> 00:42:16 Alright. 589 00:42:16 --> 00:42:22 We'll come back to those numbers. 590 00:42:22 --> 00:42:25 Let's look at it with a smaller example. 591 00:42:25 --> 00:42:32 We'll look at our example of 8. 592 00:42:32 --> 00:42:34 That we looked at before. 593 00:42:34 --> 00:42:37 And we'll turn on this print statement. 594 00:42:37 --> 00:42:51 Ooh, what was that? 595 00:42:51 --> 00:42:54 Notice that I'm only printing i and a w. 596 00:42:54 --> 00:42:56 Why is that? 597 00:42:56 --> 00:42:59 Because w and v are constant. 598 00:42:59 --> 00:43:10 I don't want you to print them over and over again. 599 00:43:10 --> 00:43:12 No, I'd better call it. 600 00:43:12 --> 00:43:17 That would be a good thing to do, right? 601 00:43:17 --> 00:43:22 So let's see. 602 00:43:22 --> 00:43:41 We'll call it with this one. 603 00:43:41 --> 00:43:42 So it's printing a lot. 604 00:43:42 --> 00:43:46 It'll print, I think, 85 calls. 605 00:43:46 --> 00:43:49 And the thing you should notice here is that it's doing a 606 00:43:49 --> 00:43:52 lot of the same things over and over again. 607 00:43:52 --> 00:43:56 So, for example, we'll see 2, 1 here. 608 00:43:56 --> 00:43:58 And 2, 1 here. 609 00:43:58 --> 00:44:03 And 2, 1 here. 610 00:44:03 --> 00:44:06 Just like Fibonacci, it's doing the same work 611 00:44:06 --> 00:44:11 over and over again. 612 00:44:11 --> 00:44:15 So what's the solution? 613 00:44:15 --> 00:44:20 Well, you won't be surprised to hear it's the same solution. 614 00:44:20 --> 00:44:26 So let's look at that code. 615 00:44:26 --> 00:44:45 So I'm going to do exactly the same trick we did before. 616 00:44:45 --> 00:44:56 I don't want b to the Fibonacci. 617 00:44:56 --> 00:45:01 I'm going to introduce a max val 0, which has exactly the 618 00:45:01 --> 00:45:03 same arguments as max val. 619 00:45:03 --> 00:45:08 Here I'll initiate the memo to be 0, or to be empty, 620 00:45:08 --> 00:45:10 rather, the dictionary. 621 00:45:10 --> 00:45:14 And then I'll call fast max val passing at this extra 622 00:45:14 --> 00:45:20 argument of the memo. 623 00:45:20 --> 00:45:24 So the first thing I'm going to do is, I'm going to try and 624 00:45:24 --> 00:45:28 return the value in the memo. 625 00:45:28 --> 00:45:30 This is a good thing to do, right? 626 00:45:30 --> 00:45:34 If it's not already there, what will happen? 627 00:45:34 --> 00:45:36 It will raise an exception. 628 00:45:36 --> 00:45:39 And I'll go to the except clause. 629 00:45:39 --> 00:45:44 So I'm using the Python try except to check whether or 630 00:45:44 --> 00:45:47 not the thing is in the memo or not. 631 00:45:47 --> 00:45:50 I try and return the value. 632 00:45:50 --> 00:45:52 If it's there, I return it. 633 00:45:52 --> 00:45:57 If not I'll get a key error. 634 00:45:57 --> 00:46:00 And what do I do if I get a key error? 635 00:46:00 --> 00:46:05 Well, now I go through code very much like what I did for 636 00:46:05 --> 00:46:09 max val in the first place. 637 00:46:09 --> 00:46:12 I check whether it's 0, et cetera, et cetera. 638 00:46:12 --> 00:46:18 It's exactly, really, the same, except before I return the 639 00:46:18 --> 00:46:22 value I would have returned I squirrel it away in my 640 00:46:22 --> 00:46:28 memo for future use. 641 00:46:28 --> 00:46:32 So it's the same structure as before. 642 00:46:32 --> 00:46:36 Except, before I return the value, I save it. 643 00:46:36 --> 00:46:47 So the next time I need it, I can look it up. 644 00:46:47 --> 00:46:54 Let's see if it works. 645 00:46:54 --> 00:47:27 Well, let's do a small example first. 646 00:47:27 --> 00:47:29 It's calling the old max val. 647 00:47:29 --> 00:47:30 With all those print statements. 648 00:47:30 --> 00:47:31 Sorry about that. 649 00:47:31 --> 00:47:35 But we'll let it run. 650 00:47:35 --> 00:47:39 Well, it's a little bit better. 651 00:47:39 --> 00:47:43 It got 85. 652 00:47:43 --> 00:47:46 Same answer, but 50 calls instead of 85. 653 00:47:46 --> 00:47:50 But let's try the big one. 654 00:47:50 --> 00:47:56 Because we're really brave. 655 00:47:56 --> 00:47:59 So here's where we have 30 elements, and a 656 00:47:59 --> 00:48:06 maximum weight of 40. 657 00:48:06 --> 00:48:09 I'm not going to call the other max val here, because we know 658 00:48:09 --> 00:48:11 what happens when I do that. 659 00:48:11 --> 00:48:15 I've created my own little memo over there. 660 00:48:15 --> 00:48:18 And let's let it rip. 661 00:48:18 --> 00:48:20 Wow. 662 00:48:20 --> 00:48:23 Well, I got the same answer. 663 00:48:23 --> 00:48:24 That's a good thing. 664 00:48:24 --> 00:48:31 And instead of 17 million calls, I have 1800 calls. 665 00:48:31 --> 00:48:34 That's a huge improvement. 666 00:48:34 --> 00:48:38 And that's sort of the magic of dynamic programming. 667 00:48:38 --> 00:48:43 On Thursday we'll do a more careful analysis and try and 668 00:48:43 --> 00:48:47 understand how I could have accomplished this seemingly 669 00:48:47 --> 00:48:52 magical task of solving an exponential problem 670 00:48:52 --> 00:48:54 so really quickly. 671 00:48:54 --> 00:48:55