1 00:00:00,530 --> 00:00:02,960 The following content is provided under a Creative 2 00:00:02,960 --> 00:00:04,370 Commons license. 3 00:00:04,370 --> 00:00:07,410 Your support will help MIT OpenCourseWare continue to 4 00:00:07,410 --> 00:00:11,060 offer high-quality educational resources for free. 5 00:00:11,060 --> 00:00:13,960 To make a donation or view additional materials from 6 00:00:13,960 --> 00:00:18,590 hundreds of MIT courses, visit MIT OpenCourseWare at 7 00:00:18,590 --> 00:00:19,840 ocw.mit.edu. 8 00:00:25,400 --> 00:00:25,740 PROFESSOR: Hello. 9 00:00:25,740 --> 00:00:26,990 Welcome. 10 00:00:29,190 --> 00:00:33,440 Today we're going to talk about one last new topic which 11 00:00:33,440 --> 00:00:35,682 has to do with search. 12 00:00:35,682 --> 00:00:38,820 So as you remember, we're working on our last topic. 13 00:00:38,820 --> 00:00:43,490 The last topic was probability and planning. 14 00:00:43,490 --> 00:00:45,130 Last lecture we talked about probability. 15 00:00:49,260 --> 00:00:53,000 Mostly we focused on Bayes' theorem, Bayes' rule. 16 00:00:53,000 --> 00:00:56,400 That was a way of updating our belief about some situation 17 00:00:56,400 --> 00:00:59,350 based on new information. 18 00:00:59,350 --> 00:01:02,580 And this week in Design Lab 12, you'll get a chance to use 19 00:01:02,580 --> 00:01:06,110 that in a robot application. 20 00:01:06,110 --> 00:01:09,300 The idea to Design Lab 12 is going to be that a robot is 21 00:01:09,300 --> 00:01:12,770 pedaling along a corridor with some 22 00:01:12,770 --> 00:01:15,750 obstacles off to its left. 23 00:01:15,750 --> 00:01:20,260 And the idea will be, you don't know where the robot is, 24 00:01:20,260 --> 00:01:24,620 but the robot will be able to estimate where it is by the 25 00:01:24,620 --> 00:01:29,480 signals that it receives from its left-facing sonars. 26 00:01:29,480 --> 00:01:31,450 So this is a very realistic type of 27 00:01:31,450 --> 00:01:33,030 state-estimation problem. 28 00:01:33,030 --> 00:01:37,110 The idea is going to be that at any given time, t, you have 29 00:01:37,110 --> 00:01:41,460 access to your previous belief at time t minus 1. 30 00:01:41,460 --> 00:01:44,940 And you have access to a new observation, which is the 31 00:01:44,940 --> 00:01:46,890 sonar to your left. 32 00:01:46,890 --> 00:01:49,840 And based on those two bits of information, you will update 33 00:01:49,840 --> 00:01:50,430 your belief. 34 00:01:50,430 --> 00:01:53,110 Which means that when you start out you'll have no idea 35 00:01:53,110 --> 00:01:55,200 where you are, but that situation should 36 00:01:55,200 --> 00:01:58,010 improve with time. 37 00:01:58,010 --> 00:01:58,075 Ok. 38 00:01:58,075 --> 00:02:01,900 So that's what we're going to do in Design Lab 12. 39 00:02:01,900 --> 00:02:04,380 Today we're going to blast ahead and think about the 40 00:02:04,380 --> 00:02:08,410 other important topic, which is search. 41 00:02:08,410 --> 00:02:10,370 So we're going to think about planning. 42 00:02:10,370 --> 00:02:11,430 We're going to be planning ahead. 43 00:02:11,430 --> 00:02:13,520 We're not going to just react to the situation 44 00:02:13,520 --> 00:02:14,260 that's given to us. 45 00:02:14,260 --> 00:02:16,840 We're going to try to figure out what's the right thing to 46 00:02:16,840 --> 00:02:17,890 do in the future. 47 00:02:17,890 --> 00:02:20,550 And to do that, we're going to think about all the things we 48 00:02:20,550 --> 00:02:24,540 could possibly do, search through that space, and figure 49 00:02:24,540 --> 00:02:27,790 out the one that's, quote, "best." And we'll have to 50 00:02:27,790 --> 00:02:30,490 define "best" somehow. 51 00:02:30,490 --> 00:02:34,420 Just to get going, I want to show you a very simple kind of 52 00:02:34,420 --> 00:02:37,290 a search problem. 53 00:02:37,290 --> 00:02:40,930 This is called the eight puzzle. 54 00:02:40,930 --> 00:02:45,110 The idea is to make a plan to go from this configuration, 55 00:02:45,110 --> 00:02:48,430 which we'll call the state, to this configuration, which 56 00:02:48,430 --> 00:02:51,790 we'll call the goal state. 57 00:02:51,790 --> 00:02:57,180 And on each move, you get to move one of the tiles into the 58 00:02:57,180 --> 00:02:57,890 free space. 59 00:02:57,890 --> 00:03:00,660 So I could move the 8 to the right or the 6 down. 60 00:03:00,660 --> 00:03:04,070 Those are the only two things I could do in the start state. 61 00:03:04,070 --> 00:03:05,760 So I have to make up my mind which of those I 62 00:03:05,760 --> 00:03:07,340 would like to do. 63 00:03:07,340 --> 00:03:09,750 And I would like to believe that ultimately, after a 64 00:03:09,750 --> 00:03:12,780 series of moves, I'm going to be able to control this state 65 00:03:12,780 --> 00:03:15,680 into that state. 66 00:03:15,680 --> 00:03:18,240 And you can imagine guessing. 67 00:03:18,240 --> 00:03:22,150 And we'll estimate in a moment how big is the guess space. 68 00:03:22,150 --> 00:03:24,360 I mean, if the guess space only had like four elements in 69 00:03:24,360 --> 00:03:27,250 it, guessing's a fine strategy. 70 00:03:27,250 --> 00:03:31,510 If the guess space has a lot more elements than that, 71 00:03:31,510 --> 00:03:34,860 guessing's probably not a good idea. 72 00:03:34,860 --> 00:03:38,720 So I previously ran our search algorithms, the ones that 73 00:03:38,720 --> 00:03:41,320 we'll develop during lecture, on this problem. 74 00:03:41,320 --> 00:03:43,070 And here's the solution that our search 75 00:03:43,070 --> 00:03:44,320 algorithm came up with. 76 00:03:51,300 --> 00:03:55,520 It's not exactly what you might do the first time you 77 00:03:55,520 --> 00:03:56,770 touched it. 78 00:03:59,740 --> 00:04:02,150 OK, I made it. 79 00:04:02,150 --> 00:04:05,430 If you were counting, I made 22 moves. 80 00:04:08,200 --> 00:04:12,180 The question is, how difficult was that problem and how good 81 00:04:12,180 --> 00:04:14,190 was that solution? 82 00:04:14,190 --> 00:04:16,130 Was that a good solution or a bad solution? 83 00:04:16,130 --> 00:04:18,320 Is there a better solution? 84 00:04:18,320 --> 00:04:20,519 How much work did I have to do in order to 85 00:04:20,519 --> 00:04:22,420 calculate that solution? 86 00:04:22,420 --> 00:04:23,850 To get a handle on that, let's start by 87 00:04:23,850 --> 00:04:25,450 asking a simple question. 88 00:04:25,450 --> 00:04:28,610 How many configurations are there? 89 00:04:28,610 --> 00:04:30,190 I got there in 22. 90 00:04:30,190 --> 00:04:33,190 What was the space of things I had to look through? 91 00:04:33,190 --> 00:04:37,470 How many different board configurations exist? 92 00:04:37,470 --> 00:04:38,880 So think about that for 20 seconds. 93 00:04:38,880 --> 00:04:39,720 Talk to your neighbor. 94 00:04:39,720 --> 00:04:43,640 And figure out whether it is 8-squared, 9-squared, 95 00:04:43,640 --> 00:04:46,390 8-factorial, 9-factorial, or none of those. 96 00:05:46,270 --> 00:05:49,530 So how many bar configurations do you see? 97 00:05:49,530 --> 00:05:51,730 Raise your hand, show me a number of fingers, so I can 98 00:05:51,730 --> 00:05:55,410 figure out roughly how people were-- that's excellent. 99 00:05:55,410 --> 00:05:58,560 Very good participation, and nearly 100% correct. 100 00:05:58,560 --> 00:06:00,980 The answer is number (4). 101 00:06:00,980 --> 00:06:01,960 You can think about this. 102 00:06:01,960 --> 00:06:03,880 What if you took all the tiles out and threw them on the 103 00:06:03,880 --> 00:06:07,470 floor, and then put them in one at a time? 104 00:06:07,470 --> 00:06:09,710 Well, you would have 9 possibilities for where you 105 00:06:09,710 --> 00:06:11,390 wanted to put the first one. 106 00:06:11,390 --> 00:06:13,460 Then you would have 8 possibilities for where you 107 00:06:13,460 --> 00:06:15,110 wanted to put the second one. 108 00:06:15,110 --> 00:06:17,300 Then you'd have 7 possibilities for where you 109 00:06:17,300 --> 00:06:19,830 put the third one, et cetera, et cetera. 110 00:06:19,830 --> 00:06:22,450 Even though the space doesn't have a number on it, it still 111 00:06:22,450 --> 00:06:25,390 sort of counts. 112 00:06:25,390 --> 00:06:27,550 And so you end up with 9-factorial. 113 00:06:27,550 --> 00:06:32,130 And the point is, 9-factorial is a big number. 114 00:06:32,130 --> 00:06:37,050 9-factorial is 362880. 115 00:06:37,050 --> 00:06:41,550 So if you thought about simply guessing, that's probably not 116 00:06:41,550 --> 00:06:44,580 going to work all that well, right? 117 00:06:44,580 --> 00:06:48,390 Even if you guessed, you have on each-- 118 00:06:48,390 --> 00:06:53,830 there's a third of a million different configurations that 119 00:06:53,830 --> 00:06:56,260 you have to look at. 120 00:06:56,260 --> 00:06:59,370 And that's if you didn't lose track of things. 121 00:06:59,370 --> 00:07:00,280 If you lost track of-- 122 00:07:00,280 --> 00:07:00,780 Oh, my. 123 00:07:00,780 --> 00:07:02,080 It's coming up-- 124 00:07:02,080 --> 00:07:03,460 almost, anyway. 125 00:07:03,460 --> 00:07:07,040 It looks like it's chopped off at the top. 126 00:07:07,040 --> 00:07:09,130 So ignore that for now. 127 00:07:09,130 --> 00:07:12,100 Look over here. 128 00:07:12,100 --> 00:07:20,270 So even if you didn't confuse yourself, there's a space of a 129 00:07:20,270 --> 00:07:22,760 third of a million things to look at. 130 00:07:22,760 --> 00:07:25,720 And if you confused yourself, there's even more. 131 00:07:25,720 --> 00:07:29,930 So it's not a huge problem by computer science standards. 132 00:07:29,930 --> 00:07:31,690 But it's certainly not a trivial problem. 133 00:07:31,690 --> 00:07:36,190 It's not something that you can just guess and get right. 134 00:07:36,190 --> 00:07:41,790 So what we want to do today is figure out an algorithm for 135 00:07:41,790 --> 00:07:43,920 conducting a search like that. 136 00:07:43,920 --> 00:07:47,520 We'd like to figure out the algorithm, analyze how well it 137 00:07:47,520 --> 00:07:52,530 works, optimize it, and try to find out a way to find the 138 00:07:52,530 --> 00:07:55,900 best solution, where "best" for this particular problem 139 00:07:55,900 --> 00:07:59,090 would mean minimum path length. 140 00:07:59,090 --> 00:08:01,720 So figure out the best solution by considering as few 141 00:08:01,720 --> 00:08:02,810 cases as possible. 142 00:08:02,810 --> 00:08:04,850 Obviously, if you enumerate all the 143 00:08:04,850 --> 00:08:08,120 cases, that should work. 144 00:08:08,120 --> 00:08:10,190 The problem is, it will be interesting to solve problems 145 00:08:10,190 --> 00:08:12,110 where that enumeration is quite large. 146 00:08:12,110 --> 00:08:15,690 Even here, the enumeration is quite large. 147 00:08:15,690 --> 00:08:17,670 So let's think about the algorithm. 148 00:08:17,670 --> 00:08:19,690 And I'll think about the algorithm by way of an even 149 00:08:19,690 --> 00:08:21,790 simpler, more finite problem. 150 00:08:21,790 --> 00:08:25,480 What if I thought about a grid of possible locations 151 00:08:25,480 --> 00:08:27,650 where I could be. 152 00:08:27,650 --> 00:08:28,800 Maybe this is the intersections 153 00:08:28,800 --> 00:08:31,640 of streets in Manhattan. 154 00:08:31,640 --> 00:08:35,130 I want to go from point A to point I. What's the 155 00:08:35,130 --> 00:08:36,260 minimum-distance path? 156 00:08:36,260 --> 00:08:40,100 I hope you probably can all figure that out. 157 00:08:40,100 --> 00:08:41,640 What I want to do is write an algorithm that 158 00:08:41,640 --> 00:08:42,919 can figure that out. 159 00:08:42,919 --> 00:08:45,070 And then if we write the algorithm well, we'll be able 160 00:08:45,070 --> 00:08:47,120 to use it for the tile problem, which is not quite so 161 00:08:47,120 --> 00:08:49,130 easy to do. 162 00:08:49,130 --> 00:08:52,430 The way we're going to think about doing that is to 163 00:08:52,430 --> 00:08:55,270 organize all of our possible paths through 164 00:08:55,270 --> 00:09:00,140 that maze, in a tree. 165 00:09:00,140 --> 00:09:03,640 So if I started at A, I have a decision to make. 166 00:09:03,640 --> 00:09:07,780 I could either go to B or D. 167 00:09:07,780 --> 00:09:16,140 Then if I went to, say, B, I could either then go to A or C 168 00:09:16,140 --> 00:09:18,810 or E. I've organized them alphabetically for no 169 00:09:18,810 --> 00:09:20,310 particularly good reason. 170 00:09:20,310 --> 00:09:20,640 Just-- 171 00:09:20,640 --> 00:09:24,010 I needed some order. 172 00:09:24,010 --> 00:09:34,260 Then if I went from A to B to A, say, then I could either go 173 00:09:34,260 --> 00:09:37,710 from A to B or D. That's illustrated here. 174 00:09:37,710 --> 00:09:40,260 So the idea then-- ah, it works. 175 00:09:40,260 --> 00:09:42,700 So now it looks like they're all three working. 176 00:09:42,700 --> 00:09:46,140 So the idea is, think about the original problem. 177 00:09:46,140 --> 00:09:49,440 The original problem is find the shortest path 178 00:09:49,440 --> 00:09:51,950 through some grid. 179 00:09:51,950 --> 00:09:55,360 I want to go from A to I. And I'll think about all the 180 00:09:55,360 --> 00:09:58,650 possible paths on a tree. 181 00:09:58,650 --> 00:10:03,020 Then the problem is that for the kinds of problems we're 182 00:10:03,020 --> 00:10:08,350 going to look at, that tree could be infinite in length. 183 00:10:08,350 --> 00:10:09,530 Oh, that's a bummer. 184 00:10:09,530 --> 00:10:12,440 That means that the strategy of building the tree and then 185 00:10:12,440 --> 00:10:14,910 searching it is probably not a good strategy. 186 00:10:14,910 --> 00:10:17,890 So what we'll do instead is, we'll try to write the 187 00:10:17,890 --> 00:10:22,650 algorithm in such a way that we construct the tree and 188 00:10:22,650 --> 00:10:26,760 search for the best solution all in one pass. 189 00:10:26,760 --> 00:10:29,650 Then hopefully, if we find a solution in some finite number 190 00:10:29,650 --> 00:10:33,560 of steps, we'll only have built part of the tree. 191 00:10:33,560 --> 00:10:37,650 But we'll have built the part that has the answer. 192 00:10:37,650 --> 00:10:41,200 The idea, then, is going to be, think about what is the 193 00:10:41,200 --> 00:10:44,130 path we want to take, by thinking about the tree of all 194 00:10:44,130 --> 00:10:46,100 possible paths. 195 00:10:46,100 --> 00:10:51,270 But what we want to do is write code that will construct 196 00:10:51,270 --> 00:10:57,150 the tree on the fly, while it's considering how good were 197 00:10:57,150 --> 00:11:00,400 all the different nodes. 198 00:11:00,400 --> 00:11:00,460 Ok. 199 00:11:00,460 --> 00:11:02,820 So how are we going to do that? 200 00:11:02,820 --> 00:11:05,070 We'll be working in Python, not surprisingly. 201 00:11:05,070 --> 00:11:07,510 We'll represent all the possible locations. 202 00:11:07,510 --> 00:11:10,420 We'll call those states. 203 00:11:10,420 --> 00:11:14,160 So the problem will have states A, B, C, D, and we'll 204 00:11:14,160 --> 00:11:17,240 just represent those by strings. 205 00:11:17,240 --> 00:11:19,090 That makes it flexible. 206 00:11:19,090 --> 00:11:21,480 That makes it arbitrary. 207 00:11:21,480 --> 00:11:24,440 Then we'll think about transitions, not by 208 00:11:24,440 --> 00:11:25,570 enumerating them. 209 00:11:25,570 --> 00:11:27,830 Remember, we don't want to enumerate them, because there 210 00:11:27,830 --> 00:11:29,050 could be infinitely many of them. 211 00:11:29,050 --> 00:11:31,050 So how's the other way we could do it? 212 00:11:31,050 --> 00:11:33,730 Well, we'll embody that information in a program. 213 00:11:33,730 --> 00:11:38,780 We'll write a procedure called "successor" that will, given 214 00:11:38,780 --> 00:11:45,730 the current state and action, figure out the next state. 215 00:11:45,730 --> 00:11:48,870 So that's a way that we can incrementally build the tree. 216 00:11:48,870 --> 00:11:58,383 So imagine here, if I started in A and I executed action 0 217 00:11:58,383 --> 00:12:02,420 or 1, I would end up in B or D, respectively. 218 00:12:02,420 --> 00:12:06,630 So I tell you the current state and the current action, 219 00:12:06,630 --> 00:12:09,410 and the successor program then will return 220 00:12:09,410 --> 00:12:12,420 to you the new state. 221 00:12:12,420 --> 00:12:17,730 That's all we need to construct the tree on the fly. 222 00:12:17,730 --> 00:12:20,710 Then, to specify the particular problem with 223 00:12:20,710 --> 00:12:23,400 interest, I have to tell you where you start. 224 00:12:23,400 --> 00:12:27,530 So I have to define initial state. 225 00:12:27,530 --> 00:12:30,250 And I have to tell you where to end. 226 00:12:30,250 --> 00:12:33,000 I could just tell you the final state. 227 00:12:33,000 --> 00:12:35,310 But in some of the problems of the type that we will want to 228 00:12:35,310 --> 00:12:40,250 do, there could be multiple acceptable answers. 229 00:12:40,250 --> 00:12:42,630 So I don't want to just give you the final state. 230 00:12:42,630 --> 00:12:44,750 I'll give you a test. 231 00:12:44,750 --> 00:12:48,550 I'll give you another procedure, called "goalTest." 232 00:12:48,550 --> 00:12:51,070 And that goal test, when passed an input which is a 233 00:12:51,070 --> 00:12:54,410 state, will tell you whether or not you reached the goal. 234 00:12:54,410 --> 00:12:57,400 That way, for example, all the even-numbered squares could 235 00:12:57,400 --> 00:13:00,000 satisfy the goal, if that were the problem of interest. 236 00:13:00,000 --> 00:13:04,560 Or all the states on the right could satisfy the goal. 237 00:13:04,560 --> 00:13:06,520 It's just a little bit more flexible. 238 00:13:06,520 --> 00:13:12,620 The idea, then, is that in order to represent that tree, 239 00:13:12,620 --> 00:13:18,050 we'll do it by specifying a procedure called successor and 240 00:13:18,050 --> 00:13:22,940 specifying the start state and the goal test. 241 00:13:22,940 --> 00:13:27,670 So here's how I might set that up for the simple Manhattan 242 00:13:27,670 --> 00:13:30,720 problem that I showed-- that I started with. 243 00:13:30,720 --> 00:13:34,550 So I want ultimately to have something called successor 244 00:13:34,550 --> 00:13:36,530 that eats a state and an action. 245 00:13:39,560 --> 00:13:46,370 I've built the structure of Manhattan into a dictionary. 246 00:13:46,370 --> 00:13:50,690 The dictionary lists for every state-- 247 00:13:50,690 --> 00:13:55,940 A, B, C, D, E, F, G, H, I-- 248 00:13:55,940 --> 00:14:00,840 for every state, it associates that state with a list of 249 00:14:00,840 --> 00:14:02,490 possible next states. 250 00:14:02,490 --> 00:14:06,780 So if I'm in A, I could next be in B or D. I could next be 251 00:14:06,780 --> 00:14:10,330 in B or D. 252 00:14:10,330 --> 00:14:13,220 I've organized these arbitrarily in alphabetical 253 00:14:13,220 --> 00:14:15,220 order so I can remember what's going on. 254 00:14:15,220 --> 00:14:17,970 So the next states are all in alphabetical order. 255 00:14:17,970 --> 00:14:21,760 The number of next states depends on the state. 256 00:14:21,760 --> 00:14:23,530 I'm not going to worry about that too much. 257 00:14:23,530 --> 00:14:28,170 I'm just going to specify the action as an integer-- 258 00:14:28,170 --> 00:14:29,290 0,1,2,3 -- 259 00:14:29,290 --> 00:14:31,590 however many I need. 260 00:14:31,590 --> 00:14:35,000 So the possible actions are taken from that list. 261 00:14:35,000 --> 00:14:38,290 The possible action might be do action 0, do action 262 00:14:38,290 --> 00:14:39,840 1, do action 2. 263 00:14:39,840 --> 00:14:47,500 So if I did action 2 starting on state E, I would go to-- 264 00:14:47,500 --> 00:14:48,750 so action started at 0 -- 265 00:14:48,750 --> 00:14:50,940 so 0, 1, 2 -- 266 00:14:50,940 --> 00:14:54,330 I would go to state F. OK? 267 00:14:54,330 --> 00:14:56,800 Is that all clear? 268 00:14:56,800 --> 00:15:00,520 The initial state is A, and the goal state is, return S 269 00:15:00,520 --> 00:15:04,130 equal to I. So if S is equal to I, it returns True. 270 00:15:04,130 --> 00:15:06,140 If S is not equal to I, it returns False. 271 00:15:10,010 --> 00:15:11,430 I'm not quite done. 272 00:15:11,430 --> 00:15:13,850 That's enough to completely specify the tree, but now I 273 00:15:13,850 --> 00:15:15,280 have to build the tree in Python. 274 00:15:18,050 --> 00:15:23,020 Not surprisingly, from our object-oriented past, we will 275 00:15:23,020 --> 00:15:29,000 use an object-oriented representation for that tree. 276 00:15:29,000 --> 00:15:33,480 So we'll specify every node in the tree as an instance of the 277 00:15:33,480 --> 00:15:36,230 class SearchNode. 278 00:15:36,230 --> 00:15:37,870 SearchNode is trivial. 279 00:15:37,870 --> 00:15:40,670 SearchNode simply knows, what was the 280 00:15:40,670 --> 00:15:42,140 action that got me here? 281 00:15:42,140 --> 00:15:43,220 Who's my parent? 282 00:15:43,220 --> 00:15:45,420 And what's my current state? 283 00:15:45,420 --> 00:15:49,090 So when you make a new node, you have to tell the 284 00:15:49,090 --> 00:15:52,550 constructor those three things. 285 00:15:52,550 --> 00:15:54,290 What was the action that got me here? 286 00:15:54,290 --> 00:15:55,230 What's my current state? 287 00:15:55,230 --> 00:15:56,480 And who is my parent? 288 00:15:58,930 --> 00:16:03,280 Knowing the node, you're supposed to know the entire 289 00:16:03,280 --> 00:16:05,140 path that got you here. 290 00:16:05,140 --> 00:16:10,420 So we'll also add a method which reports the path. 291 00:16:10,420 --> 00:16:15,750 So if I happen to be in node E, my path ought to be I 292 00:16:15,750 --> 00:16:20,500 started in A, I took action 0 and got to B, and then I took 293 00:16:20,500 --> 00:16:25,360 action 2 and got to E. This subroutine is 294 00:16:25,360 --> 00:16:28,130 intended to do that. 295 00:16:28,130 --> 00:16:31,230 If my parent is "none," which will happen for the initial 296 00:16:31,230 --> 00:16:41,060 state, simply report that the path to me is none, A. 297 00:16:41,060 --> 00:16:47,460 However, if I'm anybody other than the initial node, if I'm 298 00:16:47,460 --> 00:16:52,340 other than the initial node, then figure out the 299 00:16:52,340 --> 00:16:58,280 description of the path to my parent, and add the action 300 00:16:58,280 --> 00:17:01,980 that got me here, and my state. 301 00:17:01,980 --> 00:17:04,790 So that's what this is. 302 00:17:04,790 --> 00:17:06,190 OK, so what are we doing? 303 00:17:06,190 --> 00:17:09,849 We specify a problem by telling you the successor 304 00:17:09,849 --> 00:17:14,180 function, the start state, and the goal test. 305 00:17:14,180 --> 00:17:20,020 Then we provide a class by which you can build nodes to 306 00:17:20,020 --> 00:17:26,010 construct, on the fly, the search tree. 307 00:17:26,010 --> 00:17:27,900 Now we're ready to write the algorithm. 308 00:17:27,900 --> 00:17:30,530 Here's the pseudocode for the algorithm. 309 00:17:30,530 --> 00:17:31,150 What do we do? 310 00:17:31,150 --> 00:17:32,870 We initialize-- 311 00:17:32,870 --> 00:17:34,930 so we're going to be doing a s-- oh, 312 00:17:34,930 --> 00:17:36,270 this is very confusing. 313 00:17:36,270 --> 00:17:37,740 I'm trying to solve a search problem. 314 00:17:40,500 --> 00:17:42,210 To solve the search problem, I'm going to 315 00:17:42,210 --> 00:17:45,610 search through the tree. 316 00:17:45,610 --> 00:17:48,560 So I'm going to think about the state of my search through 317 00:17:48,560 --> 00:17:53,870 the tree by way of something we'll call the agenda. 318 00:17:53,870 --> 00:17:55,330 Very jargon-y word. 319 00:17:55,330 --> 00:17:56,700 I completely apologize for it. 320 00:17:56,700 --> 00:17:58,050 I didn't invent it. 321 00:17:58,050 --> 00:17:59,630 It's what everybody calls it. 322 00:17:59,630 --> 00:18:00,880 Sorry. 323 00:18:05,870 --> 00:18:10,700 The agenda is the set of nodes that I'm 324 00:18:10,700 --> 00:18:12,920 currently thinking about. 325 00:18:12,920 --> 00:18:16,140 So I'll initialize that to contain the starting node. 326 00:18:18,990 --> 00:18:23,640 Then I'll just systematically keep repeating the same thing 327 00:18:23,640 --> 00:18:24,740 over and over again. 328 00:18:24,740 --> 00:18:28,450 Take one of the nodes out of the agenda, think about it, 329 00:18:28,450 --> 00:18:32,960 replace that node by its children. 330 00:18:32,960 --> 00:18:36,740 While I'm doing that, two things are supposed to happen. 331 00:18:36,740 --> 00:18:40,180 I'm supposed to construct the search tree. 332 00:18:40,180 --> 00:18:42,810 But I'm also going to be looking over my shoulder to 333 00:18:42,810 --> 00:18:49,970 see if I just constructed a child who is the answer. 334 00:18:49,970 --> 00:18:51,950 Because if I just constructed the answer, I'm done. 335 00:18:51,950 --> 00:18:54,420 Ok. 336 00:18:54,420 --> 00:18:57,150 So initialize the agenda to contain just 337 00:18:57,150 --> 00:18:58,160 the starting node. 338 00:18:58,160 --> 00:18:59,670 Then repeat the following steps. 339 00:18:59,670 --> 00:19:01,680 Remove one node from the agenda. 340 00:19:01,680 --> 00:19:03,830 Add that node's children to the agenda. 341 00:19:03,830 --> 00:19:07,010 And keep going until one of two things happens. 342 00:19:07,010 --> 00:19:08,510 Either you found it-- 343 00:19:08,510 --> 00:19:13,210 goal test returned True-- 344 00:19:13,210 --> 00:19:16,310 or the agenda got empty, in which case there 345 00:19:16,310 --> 00:19:19,310 must not be a solution. 346 00:19:19,310 --> 00:19:21,480 If I've removed all of my options and still haven't 347 00:19:21,480 --> 00:19:23,170 found anything, then there's no solution. 348 00:19:25,800 --> 00:19:25,900 Ok. 349 00:19:25,900 --> 00:19:27,330 So what's the program look like? 350 00:19:27,330 --> 00:19:30,150 It's actually remarkably simple, especially when you 351 00:19:30,150 --> 00:19:31,780 think about just how hard the problem is. 352 00:19:31,780 --> 00:19:37,450 Imagine if you wanted to do that tiles problem with a very 353 00:19:37,450 --> 00:19:41,290 simple-minded "if this then this, if this then this." 354 00:19:41,290 --> 00:19:44,420 We're talking about a third of a million ifs, right? 355 00:19:44,420 --> 00:19:47,540 That's probably not the right way to do it. 356 00:19:47,540 --> 00:19:49,640 This program is going to end up being about this long. 357 00:19:49,640 --> 00:19:51,460 It'll fit on this page. 358 00:19:51,460 --> 00:19:53,600 And it's going to be able to handle that case, or even 359 00:19:53,600 --> 00:19:56,580 harder cases. 360 00:19:56,580 --> 00:19:57,800 Define the search procedure. 361 00:19:57,800 --> 00:19:59,670 The search procedure is something that's going to take 362 00:19:59,670 --> 00:20:02,870 the initial state, the goal test, the possible actions, 363 00:20:02,870 --> 00:20:06,320 and the successor sub routine, the successor procedure. 364 00:20:06,320 --> 00:20:09,700 That's everything you need to specify the problem. 365 00:20:09,700 --> 00:20:12,818 And it's going to return to me the optimal path. 366 00:20:15,520 --> 00:20:17,310 First, step (1). 367 00:20:17,310 --> 00:20:21,320 Initialize the agenda to contain the start node. 368 00:20:21,320 --> 00:20:22,440 I want to put the start node in. 369 00:20:22,440 --> 00:20:24,420 Well, there's a chance-- 370 00:20:24,420 --> 00:20:26,350 I want this procedure to be general purpose-- 371 00:20:26,350 --> 00:20:30,900 there's a chance that that start node is the answer. 372 00:20:30,900 --> 00:20:32,150 So take care of that first. 373 00:20:34,630 --> 00:20:38,460 If you're already there, return the answer. 374 00:20:38,460 --> 00:20:41,450 The path to the answer is me. 375 00:20:44,080 --> 00:20:46,340 I'm trying to create the agenda. 376 00:20:46,340 --> 00:20:48,330 I'm trying to put the first node into the agenda. 377 00:20:48,330 --> 00:20:51,040 There's a chance that first node is the answer. 378 00:20:51,040 --> 00:20:53,760 If that first node's the answer, return the path to me. 379 00:20:53,760 --> 00:20:55,710 Which is, take no action. 380 00:20:55,710 --> 00:20:56,960 You're here. 381 00:20:59,010 --> 00:21:00,560 But that's not likely to be the case for the kinds of 382 00:21:00,560 --> 00:21:04,430 questions we ask, in which case we will create a list 383 00:21:04,430 --> 00:21:07,560 that contains one node, which is the node that represents 384 00:21:07,560 --> 00:21:08,810 the start node. 385 00:21:12,780 --> 00:21:16,060 Then, repeat 'remove a node' -- which 386 00:21:16,060 --> 00:21:17,890 we'll call the parent-- 387 00:21:17,890 --> 00:21:19,900 from the agenda. 388 00:21:19,900 --> 00:21:21,670 And substitute -- 389 00:21:21,670 --> 00:21:26,590 replace that node that we pulled out of the agenda -- 390 00:21:26,590 --> 00:21:29,920 replace that with the children. 391 00:21:29,920 --> 00:21:32,180 While not empty of agenda-- 392 00:21:32,180 --> 00:21:33,940 empty is some kind of a pseudo-routine that I'm going 393 00:21:33,940 --> 00:21:35,690 to fill in, in a minute-- 394 00:21:35,690 --> 00:21:40,600 while the agenda is not empty, get an element out of the 395 00:21:40,600 --> 00:21:42,110 agenda, which we'll call the parent. 396 00:21:45,320 --> 00:21:48,890 Then I want to think about all the children. 397 00:21:48,890 --> 00:21:51,190 Well, there's a list of possible actions. 398 00:21:51,190 --> 00:21:54,620 So for a in actions, do the following things. 399 00:21:54,620 --> 00:21:57,370 Each parent can have multiple children, one for every 400 00:21:57,370 --> 00:21:58,720 possible action. 401 00:21:58,720 --> 00:22:03,840 So for a in action, figure out what would be the new state. 402 00:22:03,840 --> 00:22:10,370 The new state is just the successor of the parent state. 403 00:22:10,370 --> 00:22:14,240 Remember, the parent is a node, right? 404 00:22:14,240 --> 00:22:15,330 The parent is a node. 405 00:22:15,330 --> 00:22:17,890 We're constructing nodes in the search tree. 406 00:22:17,890 --> 00:22:21,080 But nodes know their state. 407 00:22:21,080 --> 00:22:24,790 So figure out the new state, which is the successor of my 408 00:22:24,790 --> 00:22:27,720 parent, the guy that I pulled out of the agenda. 409 00:22:30,290 --> 00:22:36,300 Make a new node, which corresponds to this child. 410 00:22:36,300 --> 00:22:40,070 Then ask the question, did the new state 411 00:22:40,070 --> 00:22:42,500 satisfy the goal test? 412 00:22:42,500 --> 00:22:45,760 If it did, the answer is the path to the new node. 413 00:22:49,410 --> 00:22:49,585 Ok. 414 00:22:49,585 --> 00:22:53,270 So create a new state, which is the successor of the parent 415 00:22:53,270 --> 00:22:57,070 under the given action A. Create a new node. 416 00:22:57,070 --> 00:22:58,320 See if it's the end. 417 00:22:58,320 --> 00:23:01,410 If it is, just return, I'm done. 418 00:23:01,410 --> 00:23:04,100 Return from search. 419 00:23:04,100 --> 00:23:08,230 Otherwise, add it-- again, one of these pseudo-procedures. 420 00:23:10,890 --> 00:23:12,560 We'll fill that in, in a minute-- 421 00:23:12,560 --> 00:23:14,360 add the new node into the agenda. 422 00:23:17,670 --> 00:23:19,210 There's several things that could happen 423 00:23:19,210 --> 00:23:21,690 when I run this loop. 424 00:23:21,690 --> 00:23:26,800 If the node has no children, I will take out the parent and 425 00:23:26,800 --> 00:23:30,100 not put anything back in. 426 00:23:30,100 --> 00:23:35,700 If the node has multiple children, I could take out one 427 00:23:35,700 --> 00:23:40,010 node and put in more nodes than I took out, so the agenda 428 00:23:40,010 --> 00:23:41,260 could get longer. 429 00:23:46,990 --> 00:23:50,580 So the agenda could either increase in length or decrease 430 00:23:50,580 --> 00:23:53,320 in length as a result of spinning around this loop. 431 00:23:56,020 --> 00:23:59,740 Also, we could either identify a goal or fail 432 00:23:59,740 --> 00:24:01,160 to identify a goal. 433 00:24:01,160 --> 00:24:05,500 So as it's increasing and decreasing, we either will or 434 00:24:05,500 --> 00:24:07,090 won't find an answer. 435 00:24:10,100 --> 00:24:10,195 Ok. 436 00:24:10,195 --> 00:24:11,450 Now the trick-- 437 00:24:11,450 --> 00:24:14,030 the only thing that makes this complicated-- 438 00:24:14,030 --> 00:24:16,346 is that order matters. 439 00:24:19,600 --> 00:24:24,980 So those pseudo-operations, whatever they were-- 440 00:24:24,980 --> 00:24:28,710 get element and add-- 441 00:24:28,710 --> 00:24:32,110 exactly how I get element and exactly how I add it to the 442 00:24:32,110 --> 00:24:36,235 agenda affects the way I conduct the search. 443 00:24:38,820 --> 00:24:40,380 Let's think of something very simple. 444 00:24:40,380 --> 00:24:48,550 Let's always remove the first node from the agenda and 445 00:24:48,550 --> 00:24:52,710 replace it by its children. 446 00:24:52,710 --> 00:24:54,310 So pull out the first node. 447 00:24:54,310 --> 00:24:57,050 And put back into the beginning of the agenda the 448 00:24:57,050 --> 00:24:58,980 children of the first node. 449 00:24:58,980 --> 00:24:59,500 How? 450 00:24:59,500 --> 00:25:01,830 I would start out in step (0). 451 00:25:01,830 --> 00:25:06,070 I would put the start node into the agenda. 452 00:25:06,070 --> 00:25:09,030 So now there's one element in the agenda, the start node. 453 00:25:09,030 --> 00:25:11,840 Then, on the first pass through the loop, I 454 00:25:11,840 --> 00:25:14,350 would pull out that. 455 00:25:14,350 --> 00:25:16,930 That's the first node in the agenda. 456 00:25:16,930 --> 00:25:18,280 There's only one node in the agenda. 457 00:25:18,280 --> 00:25:20,630 That is the first one. 458 00:25:20,630 --> 00:25:23,620 Pull out the first one and replace it by its children. 459 00:25:23,620 --> 00:25:27,900 Its children are AB and AD. 460 00:25:27,900 --> 00:25:33,510 I'm representing the nodes in this notation by the path, 461 00:25:33,510 --> 00:25:37,400 because the same state can appear multiple 462 00:25:37,400 --> 00:25:40,150 times in the tree. 463 00:25:40,150 --> 00:25:44,580 Notice that I could walk ABAB -- 464 00:25:44,580 --> 00:25:46,970 which would correspond to the same state being 465 00:25:46,970 --> 00:25:49,090 repeated in the tree. 466 00:25:49,090 --> 00:25:53,130 So I can't, when I'm writing it down here, represent the 467 00:25:53,130 --> 00:25:55,950 node by a state. 468 00:25:55,950 --> 00:26:00,230 But I can represent a node by a path. 469 00:26:00,230 --> 00:26:04,940 So on the first pass through the loop, pull out the first 470 00:26:04,940 --> 00:26:08,390 item in the agenda, which is A, and push 471 00:26:08,390 --> 00:26:10,900 back that A's children. 472 00:26:10,900 --> 00:26:16,150 Well A's children are AB and AD. 473 00:26:16,150 --> 00:26:16,230 Ok. 474 00:26:16,230 --> 00:26:20,850 So now on the second pass, the rule is pull out the first guy 475 00:26:20,850 --> 00:26:23,420 and replace it by the children. 476 00:26:23,420 --> 00:26:26,450 Now the first guy is AB. 477 00:26:26,450 --> 00:26:28,010 So I'm here. 478 00:26:28,010 --> 00:26:32,310 So pull that guy out and replace him by his children. 479 00:26:32,310 --> 00:26:37,940 His children are ABA, ABC, and ABE. 480 00:26:37,940 --> 00:26:41,030 AD is left over. 481 00:26:41,030 --> 00:26:43,610 The number of elements in the agenda got bigger. 482 00:26:46,430 --> 00:26:51,120 Next step, pull out the first item in the agenda, replace it 483 00:26:51,120 --> 00:26:52,170 by its children. 484 00:26:52,170 --> 00:26:54,020 The first item in the agenda is ABA. 485 00:26:57,340 --> 00:27:02,498 The children of ABA are ABAB and ABAD. 486 00:27:06,320 --> 00:27:06,560 Ok. 487 00:27:06,560 --> 00:27:09,490 Notice the structure of what's going on. 488 00:27:09,490 --> 00:27:11,520 Ignore the stuff on the bottom, and just watch the 489 00:27:11,520 --> 00:27:12,510 picture on the top. 490 00:27:12,510 --> 00:27:16,200 So I start by putting A in the agenda, then its children, 491 00:27:16,200 --> 00:27:19,840 then its children, then its children. 492 00:27:19,840 --> 00:27:21,500 So when I implemented the algorithm-- 493 00:27:21,500 --> 00:27:24,730 take out the first and replace it by its children-- 494 00:27:24,730 --> 00:27:28,080 I'm searching along the depth first. 495 00:27:28,080 --> 00:27:32,820 I'm going deeper and deeper into the tree without fully 496 00:27:32,820 --> 00:27:36,620 exploring all the horizontal spaces. 497 00:27:36,620 --> 00:27:40,970 So I'm tracing a line down that way. 498 00:27:40,970 --> 00:27:42,970 If you imagine this tree-- 499 00:27:42,970 --> 00:27:45,530 I've only represented the first three layers of nodes 500 00:27:45,530 --> 00:27:48,770 here-- this tree goes on forever. 501 00:27:48,770 --> 00:27:52,150 It's an infinite tree, because you can walk around in that 502 00:27:52,150 --> 00:27:54,140 Manhattan grid forever. 503 00:27:54,140 --> 00:27:58,390 There's no limit to how long you can walk around. 504 00:27:58,390 --> 00:28:02,280 So although I'm only listing the first three, the tree, in 505 00:28:02,280 --> 00:28:04,900 principle, goes on forever. 506 00:28:04,900 --> 00:28:08,930 And this algorithm will have the feature that it walks 507 00:28:08,930 --> 00:28:11,740 along the left edge. 508 00:28:11,740 --> 00:28:17,350 We call that depth-first search because we're exploring 509 00:28:17,350 --> 00:28:20,650 depth first, as opposed to breadth. 510 00:28:23,500 --> 00:28:25,630 That results because of our rule. 511 00:28:25,630 --> 00:28:28,040 The rule was, replace the first node by its children. 512 00:28:28,040 --> 00:28:30,260 Let's think about a different rule. 513 00:28:30,260 --> 00:28:32,430 Let's replace the last node by its children. 514 00:28:38,320 --> 00:28:42,440 We start by initializing the agenda to the node that 515 00:28:42,440 --> 00:28:45,320 represents the start state. 516 00:28:45,320 --> 00:28:50,830 So that's the path A. Then pull out the 517 00:28:50,830 --> 00:28:54,040 last node in the agenda-- 518 00:28:54,040 --> 00:28:55,080 that's A-- 519 00:28:55,080 --> 00:28:57,480 and replace it by its children. 520 00:28:57,480 --> 00:28:59,915 Its children are still AB and AD, just like before. 521 00:29:02,460 --> 00:29:04,770 Now the answer differs from the previous answer. 522 00:29:04,770 --> 00:29:08,680 Because when I pull out the last node, I'm pulling out AD 523 00:29:08,680 --> 00:29:09,930 now, instead. 524 00:29:12,710 --> 00:29:16,160 And now I replace AD by its children, which 525 00:29:16,160 --> 00:29:19,350 are ADA, ADE, ADG. 526 00:29:22,900 --> 00:29:28,480 Repeat, and what I've got is a different, but still 527 00:29:28,480 --> 00:29:31,060 depth-first search. 528 00:29:31,060 --> 00:29:33,680 So I've looked at two different orderings-- 529 00:29:33,680 --> 00:29:36,410 pull out the first node from the agenda and replace it by 530 00:29:36,410 --> 00:29:39,190 children, pull out the last node and 531 00:29:39,190 --> 00:29:40,540 replace it by its children. 532 00:29:40,540 --> 00:29:47,320 Both of those algorithms give an exploration of the decision 533 00:29:47,320 --> 00:29:51,580 tree searching out depth first. 534 00:29:51,580 --> 00:29:54,060 So it's going to try to exhaustively go through the 535 00:29:54,060 --> 00:29:57,480 entire depth before it tries to explore the width. 536 00:30:01,510 --> 00:30:04,080 As an alternative, think about a slightly 537 00:30:04,080 --> 00:30:05,770 more complicated rule. 538 00:30:05,770 --> 00:30:08,290 Remove the first element from the agenda and add its 539 00:30:08,290 --> 00:30:09,880 children to the end of the agenda. 540 00:30:13,350 --> 00:30:19,330 So initialize it with the start state, A. Pull out the 541 00:30:19,330 --> 00:30:21,670 first element from the agenda-- that's A-- 542 00:30:21,670 --> 00:30:26,500 and replace it by its children, which is AB, AD. 543 00:30:26,500 --> 00:30:28,360 Now pull out the first guy-- 544 00:30:28,360 --> 00:30:31,470 the first guy is AB-- 545 00:30:31,470 --> 00:30:35,600 and put its children at the end. 546 00:30:35,600 --> 00:30:39,580 It's children are ABA, ABC, ABE-- 547 00:30:39,580 --> 00:30:41,480 ABA, ABC, ABE-- 548 00:30:41,480 --> 00:30:43,380 and they are now put at the end. 549 00:30:43,380 --> 00:30:48,650 So that on the next step, I'll pick up AD-- the guy at the 550 00:30:48,650 --> 00:30:49,900 beginning-- 551 00:30:51,780 --> 00:30:54,940 and put AD's children at the end. 552 00:30:54,940 --> 00:30:57,710 et cetera, et cetera, et cetera, et cetera, 553 00:30:57,710 --> 00:30:59,390 et cetera, et cetera. 554 00:30:59,390 --> 00:31:02,240 The idea being-- and now, pay no attention to the bottom for 555 00:31:02,240 --> 00:31:04,350 a moment and just think about the pattern that 556 00:31:04,350 --> 00:31:06,520 you see at the top. 557 00:31:06,520 --> 00:31:11,640 In this order, where we remove the first node and put its 558 00:31:11,640 --> 00:31:15,770 children at the end of the agenda, has the effect of 559 00:31:15,770 --> 00:31:17,210 exploring breadth first. 560 00:31:22,260 --> 00:31:23,760 So we call that a breadth-first. 561 00:31:23,760 --> 00:31:29,880 so the idea is, we got this generic set of tools that let 562 00:31:29,880 --> 00:31:32,180 us construct search trees. 563 00:31:32,180 --> 00:31:35,630 But the order by which we manipulate the agenda plays a 564 00:31:35,630 --> 00:31:41,210 critical role in how the search is conducted. 565 00:31:41,210 --> 00:31:47,100 And the two that epitomize the two extreme cases are, what 566 00:31:47,100 --> 00:31:50,850 would happen if I replace the last node by its children? 567 00:31:50,850 --> 00:31:54,460 Or what would happen if I remove the first node and put 568 00:31:54,460 --> 00:31:56,000 its children's at the end? 569 00:31:56,000 --> 00:31:58,870 Those two structures have names because 570 00:31:58,870 --> 00:32:00,110 they happen so often. 571 00:32:00,110 --> 00:32:01,780 We'll call the first one a stack and the 572 00:32:01,780 --> 00:32:04,580 second one a queue. 573 00:32:04,580 --> 00:32:07,970 The stack-based is going to give us depth first. 574 00:32:07,970 --> 00:32:11,080 The queue-based is going to give us breadth first. 575 00:32:11,080 --> 00:32:12,720 So, stack. 576 00:32:12,720 --> 00:32:15,270 How do you think about a stack? 577 00:32:15,270 --> 00:32:19,190 You think about a stack by saying, OK, I've got a stack. 578 00:32:19,190 --> 00:32:21,080 A stack is like a stack of dishes. 579 00:32:21,080 --> 00:32:25,620 So here's my table, and I'm going to rack my dishes up. 580 00:32:25,620 --> 00:32:26,870 I'm going to put them on a stack. 581 00:32:29,380 --> 00:32:30,370 So I make a stack. 582 00:32:30,370 --> 00:32:31,660 OK, I made the stack-- 583 00:32:31,660 --> 00:32:33,590 push a 1, push a 9, push a 3. 584 00:32:33,590 --> 00:32:37,720 Push a 1, push a 9, push a 3. 585 00:32:37,720 --> 00:32:39,370 That's how I do a stack. 586 00:32:39,370 --> 00:32:41,530 Then pop. 587 00:32:41,530 --> 00:32:45,920 When I pop, the 3 comes out. 588 00:32:45,920 --> 00:32:50,840 Then pop, then the 9 comes out. 589 00:32:50,840 --> 00:32:53,060 Then push a minus 2. 590 00:32:55,600 --> 00:32:57,290 Then pop. 591 00:32:57,290 --> 00:33:00,850 Now the minus 2 comes out. 592 00:33:00,850 --> 00:33:01,440 OK? 593 00:33:01,440 --> 00:33:03,460 It's stack-based. 594 00:33:03,460 --> 00:33:10,030 So the last in becomes the first out. 595 00:33:10,030 --> 00:33:14,220 That was the rule that we wanted to have for the 596 00:33:14,220 --> 00:33:17,460 depth-first search. 597 00:33:17,460 --> 00:33:18,960 It's very easy to implement this. 598 00:33:18,960 --> 00:33:22,440 We can implement it as a list. 599 00:33:22,440 --> 00:33:26,230 All we need to do is be careful about how we implement 600 00:33:26,230 --> 00:33:29,820 the push and pop operators. 601 00:33:29,820 --> 00:33:34,120 So if we set up the push operator to simply append to 602 00:33:34,120 --> 00:33:39,700 the end, and then pop ordinarily pops from the end, 603 00:33:39,700 --> 00:33:42,320 we'll get the behavior of a stack. 604 00:33:42,320 --> 00:33:45,180 That gives me, then, the rules that I would want to use for 605 00:33:45,180 --> 00:33:50,140 those procedures, the get element an add. 606 00:33:50,140 --> 00:33:55,040 I will use these stack-based operators. 607 00:33:55,040 --> 00:33:58,270 The other alternative is a queue. 608 00:33:58,270 --> 00:33:59,230 A queue is different. 609 00:33:59,230 --> 00:34:01,390 A queue is like when you're waiting in line 610 00:34:01,390 --> 00:34:03,980 at the Stop & Shop. 611 00:34:03,980 --> 00:34:08,500 The queue is, I've got this queue here and I've got the 612 00:34:08,500 --> 00:34:09,750 server over here. 613 00:34:12,880 --> 00:34:14,850 The first person who comes into the queue-- 614 00:34:14,850 --> 00:34:16,620 so say I push one. 615 00:34:16,620 --> 00:34:19,429 So now 1 goes into the queue. 616 00:34:19,429 --> 00:34:22,010 Then another person walks up while he's-- 617 00:34:22,010 --> 00:34:26,889 the second person lines up behind the first person. 618 00:34:26,889 --> 00:34:30,170 Then I push a 3. 619 00:34:30,170 --> 00:34:32,980 But the way the queue works is that when I pop the next 620 00:34:32,980 --> 00:34:38,389 person off the queue, I take the head of the line. 621 00:34:38,389 --> 00:34:39,639 So the 1 comes out. 622 00:34:42,830 --> 00:34:44,880 If I pop again, the 9 comes out. 623 00:34:48,889 --> 00:34:57,410 If I then push a minus 2 and pop, then the next person in 624 00:34:57,410 --> 00:34:58,720 the queue comes out. 625 00:34:58,720 --> 00:35:01,200 And it's like that. 626 00:35:01,200 --> 00:35:04,000 It's queue based versus stack based. 627 00:35:04,000 --> 00:35:06,857 And the queue based is the one that we want to do for a 628 00:35:06,857 --> 00:35:09,873 breadth-first organization. 629 00:35:12,570 --> 00:35:16,300 And the implementation of a queue is very trivially 630 00:35:16,300 --> 00:35:19,170 different from the implementation for a stack. 631 00:35:19,170 --> 00:35:22,690 The only difference is that I'll manipulate the list by 632 00:35:22,690 --> 00:35:26,060 popping off from the head of the queue. 633 00:35:26,060 --> 00:35:29,950 So pop takes an optional argument, which when 634 00:35:29,950 --> 00:35:32,020 0, tells you the-- 635 00:35:32,020 --> 00:35:34,340 the argument tells you which element to pop. 636 00:35:34,340 --> 00:35:36,530 So when you specify the zero-th one, it takes it from 637 00:35:36,530 --> 00:35:39,480 the head of the queue. 638 00:35:39,480 --> 00:35:45,460 That makes it very easy now to replace the pseudo-procedures 639 00:35:45,460 --> 00:35:47,180 with real procedures. 640 00:35:47,180 --> 00:35:52,670 If I wanted to implement a depth-first search, I would 641 00:35:52,670 --> 00:35:57,830 replace the "create a list that contains the agenda" with 642 00:35:57,830 --> 00:36:04,400 "create a stack that will contain the agenda." So create 643 00:36:04,400 --> 00:36:07,850 a new stack, the agenda is a stack. 644 00:36:07,850 --> 00:36:11,900 And then rather than simply sticking the node-- 645 00:36:11,900 --> 00:36:13,340 the start node-- 646 00:36:13,340 --> 00:36:19,020 into a list, I will push it into the stack. 647 00:36:19,020 --> 00:36:21,510 So agenda is a stack. 648 00:36:21,510 --> 00:36:25,560 Agenda.push, the initial node. 649 00:36:25,560 --> 00:36:28,610 And then every time I want to get a new element out, I'll 650 00:36:28,610 --> 00:36:31,080 agenda.pop it. 651 00:36:31,080 --> 00:36:33,500 And every time I want to put something into it, I'll 652 00:36:33,500 --> 00:36:36,050 agenda.push it. 653 00:36:36,050 --> 00:36:40,150 Other than that, it looks just the same as the pseudocode 654 00:36:40,150 --> 00:36:42,800 that I showed earlier. 655 00:36:42,800 --> 00:36:45,982 So there is an implementation, then, for 656 00:36:45,982 --> 00:36:50,400 a depth-first search. 657 00:36:50,400 --> 00:36:53,990 If I wanted instead to do breadth, it's trivial. 658 00:36:53,990 --> 00:36:59,640 Change the word "stack" to the word "queue." Now create an 659 00:36:59,640 --> 00:37:05,060 agenda that is a queue, but queues have the same 660 00:37:05,060 --> 00:37:06,450 operations-- 661 00:37:06,450 --> 00:37:09,660 push and pop and empty-- 662 00:37:09,660 --> 00:37:10,840 that stacks have. 663 00:37:10,840 --> 00:37:12,790 So nothing else in the program changed. 664 00:37:12,790 --> 00:37:16,470 All I needed to do is change the structure of the thing 665 00:37:16,470 --> 00:37:18,580 that's holding the agenda. 666 00:37:18,580 --> 00:37:19,830 Everything else just follows. 667 00:37:27,700 --> 00:37:27,775 Ok. 668 00:37:27,775 --> 00:37:29,770 So that's everything we need, right? 669 00:37:29,770 --> 00:37:31,930 Now what I want to do is think through examples and think 670 00:37:31,930 --> 00:37:33,830 about the advantages and disadvantages of different 671 00:37:33,830 --> 00:37:35,840 kinds of searches. 672 00:37:35,840 --> 00:37:38,680 And I want to go on to the second step that I raised in 673 00:37:38,680 --> 00:37:40,730 the first slide. 674 00:37:40,730 --> 00:37:43,260 I want to think about, how do I optimize the search? 675 00:37:43,260 --> 00:37:46,290 As I said, even that simple little tile problem, even the 676 00:37:46,290 --> 00:37:47,340 eight puzzle-- 677 00:37:47,340 --> 00:37:49,500 eight sounds easy, right? 678 00:37:49,500 --> 00:37:52,990 Even the eight puzzle had a third of a 679 00:37:52,990 --> 00:37:54,540 million different states. 680 00:37:54,540 --> 00:37:56,740 I don't necessarily want to look through all of them. 681 00:37:56,740 --> 00:37:59,100 I want to think now about these different search 682 00:37:59,100 --> 00:38:03,000 strategies, and how optimal are they relative to each 683 00:38:03,000 --> 00:38:05,320 other, and are there ways to improve that? 684 00:38:05,320 --> 00:38:10,910 Now some of you may have noticed that all of these 685 00:38:10,910 --> 00:38:15,070 paths don't seem equally good. 686 00:38:15,070 --> 00:38:16,220 So take a minute. 687 00:38:16,220 --> 00:38:18,500 Think about it. 688 00:38:18,500 --> 00:38:19,590 Remember the problem. 689 00:38:19,590 --> 00:38:22,540 The problem was this walk around Manhattan problem. 690 00:38:22,540 --> 00:38:26,940 I wanted to go from A to I. This was the tree of all 691 00:38:26,940 --> 00:38:30,640 possible paths from A to I. What I'd like you to do is 692 00:38:30,640 --> 00:38:35,780 think about whether all of those paths are important. 693 00:38:35,780 --> 00:38:37,250 Could we get rid of some of them? 694 00:40:52,820 --> 00:40:54,810 So the question is, can I throw away some of the 695 00:40:54,810 --> 00:40:55,700 terminal nodes? 696 00:40:55,700 --> 00:40:57,680 Notice that I'm using the word "terminal" kind of funny here. 697 00:40:57,680 --> 00:41:00,550 The tree keeps going. 698 00:41:00,550 --> 00:41:03,890 The tree is actually infinite in length. 699 00:41:03,890 --> 00:41:06,180 So by "terminal," I just mean this row three. 700 00:41:06,180 --> 00:41:09,840 So could I throw away some of the nodes in row three? 701 00:41:09,840 --> 00:41:12,410 And in particular, how many of them could I throw away? 702 00:41:12,410 --> 00:41:15,190 0, 2, 4, 6, or 8? 703 00:41:15,190 --> 00:41:19,540 or Raise your hand with the funny coding. 704 00:41:19,540 --> 00:41:22,530 And the answer is-- 705 00:41:22,530 --> 00:41:23,080 come on, come on. 706 00:41:23,080 --> 00:41:24,340 Raise your hands, raise your hands. 707 00:41:24,340 --> 00:41:25,690 Blame it on your neighbor. 708 00:41:25,690 --> 00:41:27,840 That's the whole point. 709 00:41:27,840 --> 00:41:35,870 OK, it's 2/3 (5) and 1/3 (4) 710 00:41:35,870 --> 00:41:37,120 How'd you get (5) and (4)? 711 00:41:39,856 --> 00:41:42,286 Yes? 712 00:41:42,286 --> 00:41:45,688 AUDIENCE: When you have that [INAUDIBLE] nodes, you may 713 00:41:45,688 --> 00:41:47,146 know that there's [? a procedure ?] 714 00:41:47,146 --> 00:41:48,130 [INAUDIBLE] before. 715 00:41:48,130 --> 00:41:48,920 PROFESSOR: Good. 716 00:41:48,920 --> 00:41:52,930 If you're walking around Manhattan, and you're trying 717 00:41:52,930 --> 00:41:57,590 to go from A to I, and if you spun around in this loop and 718 00:41:57,590 --> 00:42:03,000 came back to A, that would probably be a bad path, right? 719 00:42:03,000 --> 00:42:09,070 So revisiting a place you've been before is probably a bad 720 00:42:09,070 --> 00:42:13,350 idea, if what your goal was, was to get from A to I in the 721 00:42:13,350 --> 00:42:17,030 shortest possible distance. 722 00:42:17,030 --> 00:42:18,510 So that's exactly right. 723 00:42:18,510 --> 00:42:23,360 So I would like to identify instances where I go back to 724 00:42:23,360 --> 00:42:24,090 where I started. 725 00:42:24,090 --> 00:42:27,730 So for example, that A. That A is bad. 726 00:42:27,730 --> 00:42:30,200 That means I went back to the start place. 727 00:42:30,200 --> 00:42:32,860 I'm just starting over. 728 00:42:32,860 --> 00:42:37,430 So if I think about those, I can identify by red all the 729 00:42:37,430 --> 00:42:38,610 places where I'm repeating. 730 00:42:38,610 --> 00:42:44,380 So ABA, don't really care what happens after that. 731 00:42:44,380 --> 00:42:47,180 ABCB, well, that's B again. 732 00:42:47,180 --> 00:42:49,900 So that's just brain dead, right? 733 00:42:49,900 --> 00:42:55,440 So I can actually remove a fair amount of the tree by 734 00:42:55,440 --> 00:42:59,300 simply getting rid of silliness. 735 00:42:59,300 --> 00:43:05,540 Don't start the path over again, where "over" means if 736 00:43:05,540 --> 00:43:08,200 you come to a place you've been before, 737 00:43:08,200 --> 00:43:09,550 stop looking there. 738 00:43:09,550 --> 00:43:12,320 That's not the right answer. 739 00:43:12,320 --> 00:43:15,850 And so you can see there that I actually 740 00:43:15,850 --> 00:43:18,740 deleted half of the tree. 741 00:43:18,740 --> 00:43:21,370 The number of nodes on the third line was 16. 742 00:43:21,370 --> 00:43:24,870 And 8 of them had the property that they repeated. 743 00:43:24,870 --> 00:43:26,290 Yes? 744 00:43:26,290 --> 00:43:27,778 AUDIENCE: [INAUDIBLE] 745 00:43:27,778 --> 00:43:28,770 [? after D. ?] 746 00:43:28,770 --> 00:43:29,762 Are you [INAUDIBLE]? 747 00:43:29,762 --> 00:43:33,234 PROFESSOR: This B and D. So there's no reason to consider 748 00:43:33,234 --> 00:43:37,698 this D, even though the D didn't repeat. 749 00:43:37,698 --> 00:43:40,674 AUDIENCE: That would be [? AD? ?] 750 00:43:40,674 --> 00:43:42,658 PROFESSOR: ABC, 751 00:43:42,658 --> 00:43:44,146 AUDIENCE: [? That would be E? ?] 752 00:43:44,146 --> 00:43:46,130 PROFESSOR: ABED. 753 00:43:46,130 --> 00:43:48,610 AUDIENCE: [INAUDIBLE] 754 00:43:48,610 --> 00:43:54,066 PROFESSOR: So I didn't, in this path, ever hit D before. 755 00:43:54,066 --> 00:43:58,034 AUDIENCE: When it did lead to the path there, you'll get the 756 00:43:58,034 --> 00:44:01,506 same one, AD [INAUDIBLE] 757 00:44:01,506 --> 00:44:03,490 PROFESSOR: I guess I don't understand. 758 00:44:03,490 --> 00:44:06,466 AUDIENCE: What I'm saying is that without getting the path 759 00:44:06,466 --> 00:44:08,450 AD, I still get (2)? 760 00:44:08,450 --> 00:44:09,442 PROFESSOR: Yes. 761 00:44:09,442 --> 00:44:13,910 So this D seems clearly inferior to that D. Yes, 762 00:44:13,910 --> 00:44:17,530 that's absolutely true. 763 00:44:17,530 --> 00:44:20,960 So this is a very simple rule for removing things. 764 00:44:20,960 --> 00:44:23,380 You're thinking of a more advanced rule. 765 00:44:23,380 --> 00:44:25,100 So if you saw-- 766 00:44:25,100 --> 00:44:27,950 if there's a shorter path to a particular place, don't look 767 00:44:27,950 --> 00:44:28,800 at the longer path. 768 00:44:28,800 --> 00:44:30,100 You're absolutely right. 769 00:44:30,100 --> 00:44:36,500 So in fact, there might be more severe pruning 770 00:44:36,500 --> 00:44:38,290 that you could do. 771 00:44:38,290 --> 00:44:39,670 There might have been an answer that was 772 00:44:39,670 --> 00:44:41,590 bigger than 8 -- 773 00:44:41,590 --> 00:44:41,990 right? 774 00:44:41,990 --> 00:44:43,240 And so you're absolutely right. 775 00:44:47,900 --> 00:44:48,015 Ok. 776 00:44:48,015 --> 00:44:50,100 Let me ignore that for the moment and come back to it in 777 00:44:50,100 --> 00:44:51,580 about four slides. 778 00:44:51,580 --> 00:44:54,490 You're absolutely right. 779 00:44:54,490 --> 00:44:58,850 So what we want to do now is take that idea of throwing 780 00:44:58,850 --> 00:45:03,690 away silly paths and formalize it so that we can put it into 781 00:45:03,690 --> 00:45:05,760 the algorithm. 782 00:45:05,760 --> 00:45:08,870 And we'll think about that as pruning rules. 783 00:45:08,870 --> 00:45:10,730 So the first pruning rule is the easy one. 784 00:45:10,730 --> 00:45:15,460 Don't consider any path that visits the same state twice. 785 00:45:15,460 --> 00:45:19,560 That doesn't pick up your case, but it does pick up 8 786 00:45:19,560 --> 00:45:22,360 cases here. 787 00:45:22,360 --> 00:45:27,630 So that's easy to implement. 788 00:45:27,630 --> 00:45:29,990 All we need to do is-- 789 00:45:29,990 --> 00:45:32,970 down here where we're thinking about whether this is a good 790 00:45:32,970 --> 00:45:35,870 state to add or not-- 791 00:45:35,870 --> 00:45:39,920 we just ask, is it in the path? 792 00:45:39,920 --> 00:45:43,870 So if the state that I'm about to put in the path is already 793 00:45:43,870 --> 00:45:47,750 in the path, don't put it there. 794 00:45:47,750 --> 00:45:49,210 If you don't shove it back into the 795 00:45:49,210 --> 00:45:52,640 agenda, it'll get forgotten. 796 00:45:52,640 --> 00:45:55,570 So before you shove it into the agenda, ask yourself the 797 00:45:55,570 --> 00:45:57,960 question, is it already in the path? 798 00:45:57,960 --> 00:46:00,090 And so I do that here. 799 00:46:00,090 --> 00:46:08,050 Keep in mind, I popped out an element called the parent. 800 00:46:08,050 --> 00:46:10,660 I'm looking at the children. 801 00:46:10,660 --> 00:46:14,640 The children's state is called "new state." So I ask, is new 802 00:46:14,640 --> 00:46:19,400 state in the parent's path? 803 00:46:19,400 --> 00:46:23,000 So parent.inpath of new state. 804 00:46:23,000 --> 00:46:25,280 So that means I have to write inpath. 805 00:46:25,280 --> 00:46:27,630 Inpath is easy. 806 00:46:27,630 --> 00:46:30,960 It's especially easy if we use recursion. 807 00:46:30,960 --> 00:46:40,200 So inpath says, if my state is state, then return True. 808 00:46:40,200 --> 00:46:42,760 I'm in the path. 809 00:46:42,760 --> 00:46:48,530 If that's not true, and I don't have a parent, then that 810 00:46:48,530 --> 00:46:50,850 means I'm the start state. 811 00:46:50,850 --> 00:46:53,590 That means it wasn't in the path. 812 00:46:53,590 --> 00:46:55,990 And if neither of those is true, ask the same 813 00:46:55,990 --> 00:46:59,210 question of my parent. 814 00:46:59,210 --> 00:47:01,830 So that makes it recursive. 815 00:47:01,830 --> 00:47:04,860 So consider two cases that could either 816 00:47:04,860 --> 00:47:06,390 make it true or false. 817 00:47:06,390 --> 00:47:09,680 It would be True if I'm currently sitting on a node 818 00:47:09,680 --> 00:47:11,310 that happens to be the same state. 819 00:47:11,310 --> 00:47:14,980 It would be False if I recursed the whole way back to 820 00:47:14,980 --> 00:47:19,060 the start state and hadn't found it yet. 821 00:47:19,060 --> 00:47:21,680 So there are two termination states-- 822 00:47:21,680 --> 00:47:26,240 I landed on a state in the path that was the same as new 823 00:47:26,240 --> 00:47:29,830 state, or I ran the whole way back to the start state and 824 00:47:29,830 --> 00:47:30,860 didn't find it. 825 00:47:30,860 --> 00:47:34,000 Those two terminate by doing returns -- 826 00:47:34,000 --> 00:47:36,890 return True or return False. 827 00:47:36,890 --> 00:47:39,800 The other option is that I don't know the 828 00:47:39,800 --> 00:47:41,295 answer, ask my parent. 829 00:47:44,040 --> 00:47:48,170 So just recurse on inpath, and ask my parent 830 00:47:48,170 --> 00:47:51,400 to do the same thing. 831 00:47:51,400 --> 00:47:53,380 So that's the way I can figure out-- 832 00:47:53,380 --> 00:47:57,360 I can implement pruning rule (1). 833 00:47:57,360 --> 00:47:59,510 Now pruning rule (2) -- 834 00:47:59,510 --> 00:48:02,200 if multiple actions lead to the same state, only think 835 00:48:02,200 --> 00:48:03,320 about one of them. 836 00:48:03,320 --> 00:48:05,580 That actually doesn't happen on the Manhattan grid problem. 837 00:48:05,580 --> 00:48:09,110 Because you can imagine search cases where there are three 838 00:48:09,110 --> 00:48:10,380 different things that you could do. 839 00:48:10,380 --> 00:48:12,790 In fact, you saw some of those when you were coding 840 00:48:12,790 --> 00:48:15,270 the robot last week. 841 00:48:15,270 --> 00:48:18,160 There were multiple ways you could end up at the state at 842 00:48:18,160 --> 00:48:20,430 the end of the hall. 843 00:48:20,430 --> 00:48:23,840 You could get there by being there and moving left, which 844 00:48:23,840 --> 00:48:24,800 you hit the wall. 845 00:48:24,800 --> 00:48:27,510 Or you could get there by being here and moving left. 846 00:48:27,510 --> 00:48:30,400 Both of them left you in the same place. 847 00:48:30,400 --> 00:48:32,840 So if you're planning a search, you don't need to 848 00:48:32,840 --> 00:48:35,200 distinguish among those, because they take the same 849 00:48:35,200 --> 00:48:37,400 amount of steps. 850 00:48:37,400 --> 00:48:39,810 So since they take the same amount of steps, we don't need 851 00:48:39,810 --> 00:48:40,500 to search further. 852 00:48:40,500 --> 00:48:41,650 So we can collapse them. 853 00:48:41,650 --> 00:48:44,390 That's called pruning rule (2). 854 00:48:44,390 --> 00:48:46,120 That's also easy to implement. 855 00:48:46,120 --> 00:48:49,890 What we do is, we keep track of, for every parent, what are 856 00:48:49,890 --> 00:48:52,830 all of its children. 857 00:48:52,830 --> 00:48:59,250 If the parent already has a child at that place, throw 858 00:48:59,250 --> 00:49:02,210 away the excess children. 859 00:49:02,210 --> 00:49:03,460 That doesn't sound good. 860 00:49:07,220 --> 00:49:10,490 So keep track of how many child states I have. 861 00:49:10,490 --> 00:49:12,480 Make a list. 862 00:49:12,480 --> 00:49:18,180 And if the new state didn't satisfy the goal, ask if it's 863 00:49:18,180 --> 00:49:21,500 already in the list of children. 864 00:49:21,500 --> 00:49:23,360 If it's already there, pass. 865 00:49:23,360 --> 00:49:24,610 Don't do anything. 866 00:49:27,430 --> 00:49:29,360 Otherwise, do pruning rule (1). 867 00:49:29,360 --> 00:49:32,850 And then, before you push it into the agenda, also push it 868 00:49:32,850 --> 00:49:35,150 into the list of new children. 869 00:49:38,010 --> 00:49:41,100 That's a way of making sure that if there's multiple ways 870 00:49:41,100 --> 00:49:43,700 to get the same state, you only keep track of one. 871 00:49:43,700 --> 00:49:47,420 So that's an additional pruning rule. 872 00:49:47,420 --> 00:49:52,050 So now let's think about how we would implement these. 873 00:49:52,050 --> 00:49:55,560 Let's think about the solution to a problem where we want to 874 00:49:55,560 --> 00:50:02,490 apply a depth-first search on this Manhattan problem, to get 875 00:50:02,490 --> 00:50:04,250 from A to I. So let's think about-- 876 00:50:09,800 --> 00:50:11,050 let's go up-- 877 00:50:14,740 --> 00:50:19,780 so I want to think about, how do I apply depth-first search 878 00:50:19,780 --> 00:50:21,260 to that problem? 879 00:50:21,260 --> 00:50:23,040 So think about the agenda. 880 00:50:23,040 --> 00:50:25,870 So the agenda, I initialized it with the node that 881 00:50:25,870 --> 00:50:32,370 corresponds to the start state, so that's A. I'm doing 882 00:50:32,370 --> 00:50:33,050 depth first. 883 00:50:33,050 --> 00:50:35,120 What's the rule for depth first? 884 00:50:35,120 --> 00:50:39,290 Pop the last guy, replace it by his children. 885 00:50:39,290 --> 00:50:41,360 OK, so pop the last guy. 886 00:50:41,360 --> 00:50:42,550 What's the last guy? 887 00:50:42,550 --> 00:50:45,220 The last guy is A. Replace it by his children. 888 00:50:45,220 --> 00:50:47,420 What's his children of A? 889 00:50:47,420 --> 00:50:49,225 Well, there's two of them, AB and AD. 890 00:50:56,050 --> 00:50:56,125 Ok. 891 00:50:56,125 --> 00:51:00,330 So I'm done with the loop for the first level. 892 00:51:00,330 --> 00:51:06,230 So pop the last guy, that's AD. 893 00:51:06,230 --> 00:51:07,420 Replace it by his children. 894 00:51:07,420 --> 00:51:10,780 What are the children of AD? 895 00:51:10,780 --> 00:51:11,830 Well, what could D do? 896 00:51:11,830 --> 00:51:17,040 D could go to A or E or G. A's brain dead, so I 897 00:51:17,040 --> 00:51:18,620 don't want that one. 898 00:51:18,620 --> 00:51:21,970 So I'll think about E and G. 899 00:51:21,970 --> 00:51:26,120 So ADE, ADG. 900 00:51:30,810 --> 00:51:32,900 By the way, stop me if I make a mistake. 901 00:51:32,900 --> 00:51:35,360 It's really embarrassing. 902 00:51:35,360 --> 00:51:39,200 OK, pop the end, ADG. 903 00:51:39,200 --> 00:51:43,740 Who's the possible children of ADG? 904 00:51:43,740 --> 00:51:44,390 ADG? 905 00:51:44,390 --> 00:51:46,130 Well, it could go back to D, but that's stupid. 906 00:51:46,130 --> 00:51:48,940 So ADGH seems to be the only good one. 907 00:51:54,600 --> 00:51:58,260 Pop the last one, ADGH. 908 00:51:58,260 --> 00:52:02,400 And who's his children, ADGH? 909 00:52:02,400 --> 00:52:11,460 ADGH has children E, G, and I. But I don't want G, because 910 00:52:11,460 --> 00:52:12,770 that's brain dead. 911 00:52:12,770 --> 00:52:24,700 So ADGH, E or I. And that one won, right? 912 00:52:24,700 --> 00:52:27,750 Because I got to A. 913 00:52:27,750 --> 00:52:28,960 Everyone see what I did? 914 00:52:28,960 --> 00:52:33,380 I tried to work out the algorithm manually. 915 00:52:33,380 --> 00:52:35,230 So the idea, then, was that-- 916 00:52:38,630 --> 00:52:40,400 so how much work I do? 917 00:52:40,400 --> 00:52:43,570 I visited 1, 2, 3, 4, 5, 6, 7. 918 00:52:43,570 --> 00:52:44,720 And then I found it. 919 00:52:44,720 --> 00:52:45,970 So I did 7 visits. 920 00:52:48,580 --> 00:52:49,830 And I got the right answer. 921 00:52:52,450 --> 00:52:53,740 So both of those are good-- 922 00:52:53,740 --> 00:52:56,220 7 is a small number, and getting the right answer. 923 00:52:56,220 --> 00:52:59,330 Both of those are good things. 924 00:52:59,330 --> 00:53:02,570 And in general, if you think about the way a depth-first 925 00:53:02,570 --> 00:53:03,850 search works-- 926 00:53:03,850 --> 00:53:07,330 here's a transcript of what I just did. 927 00:53:07,330 --> 00:53:09,550 This will be posted on the online version. 928 00:53:09,550 --> 00:53:11,600 So you can see it, even though it's not 929 00:53:11,600 --> 00:53:14,150 handed out to you now. 930 00:53:14,150 --> 00:53:17,410 So you can look this up on the web. 931 00:53:17,410 --> 00:53:21,940 So in general, depth-first search won't 932 00:53:21,940 --> 00:53:23,190 work for every problem. 933 00:53:25,840 --> 00:53:27,790 It happened to work for this problem. 934 00:53:27,790 --> 00:53:29,820 In fact, it happened to be very good for this problem. 935 00:53:29,820 --> 00:53:31,420 But it won't work for every problem because 936 00:53:31,420 --> 00:53:33,570 it could get stuck. 937 00:53:33,570 --> 00:53:36,480 It could run forever in a problem with infinite domain. 938 00:53:36,480 --> 00:53:37,890 This problem has infinite domain. 939 00:53:37,890 --> 00:53:41,030 So if I were to choose my start and end state 940 00:53:41,030 --> 00:53:44,380 judiciously, I could get it stuck in an infinite loop. 941 00:53:44,380 --> 00:53:49,530 That's a property of depth-first search. 942 00:53:49,530 --> 00:53:53,420 Even when it finds a path, it doesn't necessarily find the 943 00:53:53,420 --> 00:53:55,110 shortest path. 944 00:53:55,110 --> 00:53:58,710 Well, that's a bummer. 945 00:53:58,710 --> 00:54:04,040 But it's very efficient in its use of memory. 946 00:54:04,040 --> 00:54:08,580 So it's not a completely brain-dead search strategy, 947 00:54:08,580 --> 00:54:10,720 but it's usually brain dead. 948 00:54:10,720 --> 00:54:16,230 So let's think about breadth-first search as an 949 00:54:16,230 --> 00:54:17,360 alternative. 950 00:54:17,360 --> 00:54:21,060 Again, all we need do is switch the idea of thinking 951 00:54:21,060 --> 00:54:26,020 about stacks versus queues. 952 00:54:26,020 --> 00:54:28,300 Take off the beginning, add to the end. 953 00:54:28,300 --> 00:54:30,180 That's the way queues work. 954 00:54:30,180 --> 00:54:32,650 So now let's do the same problem with a 955 00:54:32,650 --> 00:54:34,640 breadth-first search. 956 00:54:34,640 --> 00:54:36,190 So I start with the agenda. 957 00:54:36,190 --> 00:54:43,260 I put in A. I pop off the head of the queue and stuff the 958 00:54:43,260 --> 00:54:45,320 children at the end. 959 00:54:45,320 --> 00:54:49,280 I pop off the beginning and stuff the children AB, AD. 960 00:54:52,200 --> 00:54:54,520 That looks right. 961 00:54:54,520 --> 00:54:57,940 That's the end of path one. 962 00:54:57,940 --> 00:55:02,020 Now I pop off the beginning and stick in the children. 963 00:55:02,020 --> 00:55:04,160 What are the children of AB? 964 00:55:04,160 --> 00:55:06,840 Well, AB could go to ACE. 965 00:55:06,840 --> 00:55:08,955 A is brain dead, so ABC-- 966 00:55:12,070 --> 00:55:13,320 ABC or ABE. 967 00:55:16,670 --> 00:55:20,340 ABC or ABE, that looks right. 968 00:55:20,340 --> 00:55:26,130 Now pop off this guy, AD, and put his children at the end. 969 00:55:26,130 --> 00:55:27,863 That's ADE and ADG. 970 00:55:35,690 --> 00:55:37,870 I don't think I made a mistake yet. 971 00:55:37,870 --> 00:55:40,430 Pop off the first guy, ABC. 972 00:55:40,430 --> 00:55:44,350 Stick in his children ABC-- 973 00:55:44,350 --> 00:55:49,930 ABC, it could go to B or F. Looks like F is the only one 974 00:55:49,930 --> 00:55:52,630 that makes any sense. 975 00:55:52,630 --> 00:55:54,850 ABC, that looks right. 976 00:55:54,850 --> 00:56:01,750 ABE, put his children ABE-- 977 00:56:01,750 --> 00:56:04,340 E could go to B-- that's brain dead-- 978 00:56:04,340 --> 00:56:11,450 D, F, or H. D, F-- wait. 979 00:56:15,019 --> 00:56:15,920 AUDIENCE: AB. 980 00:56:15,920 --> 00:56:17,170 PROFESSOR: AB, thank you. 981 00:56:21,770 --> 00:56:26,010 I'm supposed to be doing ABE followed by something, ABE 982 00:56:26,010 --> 00:56:27,150 followed by something. 983 00:56:27,150 --> 00:56:32,290 I don't want B. D is fine, F is fine, and H is fine. 984 00:56:32,290 --> 00:56:44,320 D, F, and H. OK so far? 985 00:56:44,320 --> 00:56:45,410 AUDIENCE: [INAUDIBLE] 986 00:56:45,410 --> 00:56:47,000 PROFESSOR: Oh no, it's not right? 987 00:56:47,000 --> 00:56:48,349 OK, what did I do wrong? 988 00:56:48,349 --> 00:56:51,283 AUDIENCE: Just AB. 989 00:56:51,283 --> 00:56:53,239 It's the fourth-- 990 00:56:53,239 --> 00:56:54,217 PROFESSOR: Oh, here. 991 00:56:54,217 --> 00:56:55,195 That's up here. 992 00:56:55,195 --> 00:56:56,662 Is that [INAUDIBLE]. 993 00:56:56,662 --> 00:56:57,640 AUDIENCE: Yeah. 994 00:56:57,640 --> 00:56:58,618 PROFESSOR: Thank you. 995 00:56:58,618 --> 00:57:00,090 That would be embarrassing. 996 00:57:00,090 --> 00:57:03,010 OK, next pop off AD-- 997 00:57:03,010 --> 00:57:04,940 This is why we have computers, right? 998 00:57:04,940 --> 00:57:08,420 We don't normally do this by hand. 999 00:57:08,420 --> 00:57:10,410 OK, so ADE-- 1000 00:57:15,850 --> 00:57:19,880 if I had ADE, I could do B-- 1001 00:57:19,880 --> 00:57:23,370 that seems OK, D seems bad-- 1002 00:57:23,370 --> 00:57:25,790 F, or H. So it would look like 1003 00:57:25,790 --> 00:57:37,490 B, F, H. OK, ADG. 1004 00:57:43,160 --> 00:57:48,013 A, D, G. It looks like H is my only option. 1005 00:57:52,690 --> 00:57:53,940 ABCF. 1006 00:57:56,378 --> 00:58:11,300 A, B, C, F. Looks like I could do E or I. Finally. 1007 00:58:11,300 --> 00:58:12,650 Now the only question is whether I got the 1008 00:58:12,650 --> 00:58:14,380 right number of states. 1009 00:58:14,380 --> 00:58:15,780 Let's assume I did. 1010 00:58:15,780 --> 00:58:17,030 So 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 -- 1011 00:58:26,740 --> 00:58:28,010 which happens to be the right answer. 1012 00:58:28,010 --> 00:58:29,820 At least it happens to be the answer I got this morning when 1013 00:58:29,820 --> 00:58:32,380 I was at breakfast. 1014 00:58:32,380 --> 00:58:34,220 So what did I just do? 1015 00:58:34,220 --> 00:58:37,450 I just did a breadth-first search. 1016 00:58:40,030 --> 00:58:41,660 Here's a transcript. 1017 00:58:41,660 --> 00:58:42,910 16 matches, good. 1018 00:58:45,860 --> 00:58:48,870 Breadth-first search has a different set of properties. 1019 00:58:48,870 --> 00:58:51,680 Notice that it took me longer. 1020 00:58:51,680 --> 00:58:55,490 But because it's breadth first, and because each row 1021 00:58:55,490 --> 00:58:58,020 corresponds to an increasing path length, it's always 1022 00:58:58,020 --> 00:59:00,190 guaranteed to give you the shortest answer. 1023 00:59:00,190 --> 00:59:02,070 That's good. 1024 00:59:02,070 --> 00:59:04,280 So it always gives you the shortest answer. 1025 00:59:07,410 --> 00:59:09,210 It requires more space. 1026 00:59:09,210 --> 00:59:10,930 I mean, you can see that just on the chalkboard. 1027 00:59:13,960 --> 00:59:17,140 And also it still didn't take care of your problem. 1028 00:59:17,140 --> 00:59:20,480 So this still seems like there's too much work. 1029 00:59:24,690 --> 00:59:28,360 I looked at 16 different places. 1030 00:59:28,360 --> 00:59:32,140 I did 16 visits. 1031 00:59:32,140 --> 00:59:34,800 There's just something completely wrong about that, 1032 00:59:34,800 --> 00:59:36,375 because there's only 9 states. 1033 00:59:39,080 --> 00:59:44,750 How could it take more visits than there are states? 1034 00:59:44,750 --> 00:59:46,930 So that just doesn't sound right. 1035 00:59:46,930 --> 00:59:48,830 And it's for exactly your point. 1036 00:59:48,830 --> 00:59:51,570 And so there's another idea that we can use, which is 1037 00:59:51,570 --> 00:59:56,170 called "dynamic programming." The idea in dynamic 1038 00:59:56,170 --> 01:00:00,370 programming, the principal is, if you think about a path that 1039 01:00:00,370 --> 01:00:08,000 goes from x is z through y, the best path from x to z 1040 01:00:08,000 --> 01:00:11,820 through y is the sum of two paths-- 1041 01:00:11,820 --> 01:00:15,608 the best path from x to y and the best path from y to z. 1042 01:00:18,750 --> 01:00:20,520 If you think about that, that has to be the case. 1043 01:00:23,040 --> 01:00:27,690 And if we further assume that we're going to do breadth 1044 01:00:27,690 --> 01:00:33,720 first, then the first time that we see a state is the 1045 01:00:33,720 --> 01:00:35,420 best way to get there. 1046 01:00:38,100 --> 01:00:40,840 So what we can do then, in order to take care of your 1047 01:00:40,840 --> 01:00:45,530 case, is keep track of the states we've already visited. 1048 01:00:45,530 --> 01:00:49,760 If we've already visited a state, it appears earlier in 1049 01:00:49,760 --> 01:00:54,480 the tree, there's no point in thinking about it further. 1050 01:00:54,480 --> 01:00:57,440 That's the idea of dynamic programming. 1051 01:00:57,440 --> 01:00:59,980 And that's also easy to implement. 1052 01:00:59,980 --> 01:01:02,370 All we need to do is keep track of all those places 1053 01:01:02,370 --> 01:01:04,940 we've already visited. 1054 01:01:04,940 --> 01:01:13,440 So we make a dictionary called "visited." So I initialize 1055 01:01:13,440 --> 01:01:15,510 before I start looking at the children. 1056 01:01:15,510 --> 01:01:18,910 I initialize right after I set up the initial 1057 01:01:18,910 --> 01:01:20,900 contents of the agenda. 1058 01:01:20,900 --> 01:01:23,640 I create this dictionary called visited. 1059 01:01:23,640 --> 01:01:30,010 And every time I visit a new state, I put that state in the 1060 01:01:30,010 --> 01:01:32,430 visit list. 1061 01:01:32,430 --> 01:01:41,520 Then before I add the child to the agenda I ask, is the child 1062 01:01:41,520 --> 01:01:45,510 already in the visit list? 1063 01:01:45,510 --> 01:01:47,950 If the child's already there, well forget it. 1064 01:01:47,950 --> 01:01:51,030 I don't need him. 1065 01:01:51,030 --> 01:01:57,560 Otherwise, just before you push the new state, remember 1066 01:01:57,560 --> 01:02:02,180 now that that's an element that's been visited. 1067 01:02:02,180 --> 01:02:05,420 So the idea, then, is that by keeping track of who you've 1068 01:02:05,420 --> 01:02:08,890 already looked at, you can avoid looking-- 1069 01:02:08,890 --> 01:02:15,840 so if there's a depth-3 way to get to D, and a depth-2, then 1070 01:02:15,840 --> 01:02:19,620 I don't need to worry about the previous ones, because 1071 01:02:19,620 --> 01:02:20,560 it's already in the visit list. 1072 01:02:20,560 --> 01:02:21,535 Yes? 1073 01:02:21,535 --> 01:02:25,495 AUDIENCE: Why do we still need the new child states up there? 1074 01:02:25,495 --> 01:02:28,465 PROFESSOR: Why do we still have the new child states? 1075 01:02:28,465 --> 01:02:30,940 AUDIENCE: The placement was based [? on-- ?] the 1076 01:02:30,940 --> 01:02:32,425 [INAUDIBLE] state. 1077 01:02:32,425 --> 01:02:35,395 PROFESSOR: I think you're right. 1078 01:02:35,395 --> 01:02:36,880 I should think about that. 1079 01:02:36,880 --> 01:02:37,870 I think you're right. 1080 01:02:37,870 --> 01:02:41,630 I think when I was modifying the code for the different 1081 01:02:41,630 --> 01:02:43,960 places I slipped and could have removed that line. 1082 01:02:43,960 --> 01:02:45,540 I think you're right. 1083 01:02:45,540 --> 01:02:47,360 I'll have to think about it, but I think you're right. 1084 01:02:47,360 --> 01:02:50,370 So if that line magically disappears from the online 1085 01:02:50,370 --> 01:02:51,620 version, he's right. 1086 01:02:55,020 --> 01:02:58,300 OK, so now one last problem. 1087 01:02:58,300 --> 01:03:04,840 I want to see if I can figure out what would happen with 1088 01:03:04,840 --> 01:03:07,930 dynamic programming. 1089 01:03:07,930 --> 01:03:10,500 So I want to do breadth first. 1090 01:03:10,500 --> 01:03:14,500 And just as a warning, I'm hypoglycemic at this point. 1091 01:03:14,500 --> 01:03:17,440 So there may be more errors than usual. 1092 01:03:17,440 --> 01:03:19,860 So I need to keep track of two things. 1093 01:03:19,860 --> 01:03:22,580 I need to keep track of the visit list. 1094 01:03:22,580 --> 01:03:26,460 And I need to keep track of the agenda. 1095 01:03:26,460 --> 01:03:29,650 So there's two lists I have to keep track of. 1096 01:03:29,650 --> 01:03:30,320 OK. 1097 01:03:30,320 --> 01:03:33,000 Let's start out by saying that the agenda 1098 01:03:33,000 --> 01:03:34,970 contains the start element. 1099 01:03:34,970 --> 01:03:44,100 That's A. That means we visited A. It's breadth first, 1100 01:03:44,100 --> 01:03:47,550 so I want to take the first guy out of the queue and add 1101 01:03:47,550 --> 01:03:49,810 his children to the end of the queue. 1102 01:03:49,810 --> 01:03:51,730 So take the first guy out of the queue. 1103 01:03:51,730 --> 01:03:52,790 Add his children. 1104 01:03:52,790 --> 01:03:59,510 A's children are B and D, which means that I've now 1105 01:03:59,510 --> 01:04:06,620 visited B and D. 1106 01:04:06,620 --> 01:04:10,460 Now I want to take out the first guy from the queue, AB, 1107 01:04:10,460 --> 01:04:14,583 and I want to put his children at the end of the queue. 1108 01:04:14,583 --> 01:04:17,060 AB's children are A-- 1109 01:04:17,060 --> 01:04:19,200 that's been visited, C-- 1110 01:04:19,200 --> 01:04:21,040 not visited, and E-- 1111 01:04:21,040 --> 01:04:22,740 not visited. 1112 01:04:22,740 --> 01:04:24,162 So ABCE. 1113 01:04:28,580 --> 01:04:35,810 But that visits C and E. 1114 01:04:35,810 --> 01:04:42,580 Now I want to take out AD and put its children at the end. 1115 01:04:42,580 --> 01:04:46,060 AD is AEG. 1116 01:04:46,060 --> 01:04:52,245 A is visited, E is visited, which leaves just G, so ADG . 1117 01:04:54,800 --> 01:04:59,700 And that visits G. 1118 01:04:59,700 --> 01:05:04,940 Then I want to take out ABC and put in its children, A, B, 1119 01:05:04,940 --> 01:05:09,180 C. ABC, oh dear. 1120 01:05:09,180 --> 01:05:09,850 AB-- 1121 01:05:09,850 --> 01:05:11,920 I'm looking up there. 1122 01:05:11,920 --> 01:05:14,360 I said I'm hypoglycemic. 1123 01:05:14,360 --> 01:05:15,710 ABC-- 1124 01:05:15,710 --> 01:05:20,030 ABC -- could be B or F. Well, B's no good. 1125 01:05:20,030 --> 01:05:27,290 Which leaves F, but that visits F. 1126 01:05:27,290 --> 01:05:28,540 So now, ABE. 1127 01:05:32,740 --> 01:05:38,570 ABE, so that could be B, D, F, H. B-- 1128 01:05:38,570 --> 01:05:40,270 visited, D-- 1129 01:05:40,270 --> 01:05:41,820 visited, F-- 1130 01:05:41,820 --> 01:05:43,562 visited, H-- 1131 01:05:43,562 --> 01:05:44,812 OK. 1132 01:05:47,530 --> 01:05:50,760 That visits H. 1133 01:05:50,760 --> 01:05:52,010 Now take out ADG. 1134 01:05:55,560 --> 01:05:58,100 Children of ADG-- 1135 01:05:58,100 --> 01:06:03,760 ADG, two children, D and H. D and H, they're both there. 1136 01:06:03,760 --> 01:06:05,380 That didn't work. 1137 01:06:05,380 --> 01:06:09,567 There are no children of ADG. 1138 01:06:09,567 --> 01:06:10,817 ABCF-- 1139 01:06:13,810 --> 01:06:17,210 ABCF, three children-- 1140 01:06:17,210 --> 01:06:20,590 C, E, I. C-- 1141 01:06:20,590 --> 01:06:21,710 visited, E-- 1142 01:06:21,710 --> 01:06:22,970 visited, I-- 1143 01:06:22,970 --> 01:06:25,240 done. 1144 01:06:25,240 --> 01:06:26,070 Found the right answer. 1145 01:06:26,070 --> 01:06:27,320 1, 2, 3, 4, 5, 6, 7, 8 -- 1146 01:06:29,410 --> 01:06:32,050 8 visits. 1147 01:06:32,050 --> 01:06:40,910 So I've got the same answer, and it's optimal, and I did 1148 01:06:40,910 --> 01:06:42,560 fewer than 9 visits. 1149 01:06:42,560 --> 01:06:44,800 9 was the number of states. 1150 01:06:44,800 --> 01:06:48,790 So this algorithm will always have those properties. 1151 01:06:48,790 --> 01:06:52,380 So the dynamic programming-- 1152 01:06:52,380 --> 01:06:53,630 oh, I forgot a slide. 1153 01:06:56,270 --> 01:06:59,360 The dynamic programming with breadth-first search will 1154 01:06:59,360 --> 01:07:01,410 always find the best. 1155 01:07:01,410 --> 01:07:04,600 It will never take longer than the number of states. 1156 01:07:04,600 --> 01:07:07,400 So in this problem that had a finite number of states, even 1157 01:07:07,400 --> 01:07:10,360 though I had an infinite number of paths-- 1158 01:07:10,360 --> 01:07:13,290 because you can go around in circles-- 1159 01:07:13,290 --> 01:07:16,910 it'll still never take more than the number of states. 1160 01:07:16,910 --> 01:07:21,390 And all that it requires to implement is to maintain two 1161 01:07:21,390 --> 01:07:24,040 lists instead of one. 1162 01:07:24,040 --> 01:07:27,670 So the point, then, is that today we looked at a variety-- 1163 01:07:27,670 --> 01:07:29,980 we looked at two real different kinds of search 1164 01:07:29,980 --> 01:07:32,240 algorithms, depth-first search and breadth-first search. 1165 01:07:32,240 --> 01:07:34,600 And we looked at a number of different pruning rules. 1166 01:07:34,600 --> 01:07:36,610 Pruning rule (1) -- don't go to some place that you've 1167 01:07:36,610 --> 01:07:37,880 already visited. 1168 01:07:37,880 --> 01:07:39,570 Pruning rule (2) -- if you have two children that go to 1169 01:07:39,570 --> 01:07:42,200 the same place, only think about one of them. 1170 01:07:42,200 --> 01:07:44,510 You can consider dynamic programming to be a third 1171 01:07:44,510 --> 01:07:49,030 pruning rule, because that's the effect of it. 1172 01:07:49,030 --> 01:07:54,850 And the final announcement, don't forget about Wednesday. 1173 01:07:54,850 --> 01:07:56,100 Have a good week.