Lec 19 | MIT 6.00 Introduction to Computer Science and Programming, Fall 2008


OPERATOR: The following content
is provided under a Creative Commons license. Your support will help MIT
OpenCourseWare continue to offer high quality educational
resources for free. To make a donation, or view
additional materials from hundreds of MIT courses, visit
MIT OpenCourseWare at ocw.mit.edu. PROFESSOR: So you may recall
that, in the last lecture, we more or less solved the drunken
student problem, looking at a random walk. I now want to move on and
discuss some variants of the random walk problem that are
collectively known as biased random walks. So the notion here is, the walk
is still stochastic but there is some bias in the
direction, so the movements are not uniformly distributed or
equally distributed in all directions. As I go through this, I want
you to sort of, think in advance about what the take-home
message should be. One, and this is probably the
most important part for today, is I want to illustrate how by
designing our programs in a nice way around classes, we
can change them to do something else writing a
minimal amount of code. And the idea here is that
classes are not there just to provide some syntax that makes
life complicated, but to actually provide a mechanism
that lets us structure our programs in a way that we
can modify them later. I also want to give you a bit
more experience looking at data, and understanding how,
when you get the results of a simulation or anything else that
provides you with data, you can plot, them study the
plots, and try and use those to develop an understanding
about what’s going on. And finally, I want to just get
you thinking more about random behavior. Because we’re going to talk a
lot more this semester and in general throughout your careers,
you’ll see a lot of uses of stochastic things. All right, so let’s think about
these biased walks. So for example, assume that
the drunk grew up in South Florida, and really hates
the New England winter. Well there might be a bias that
even though the drunk is not in total control, she’s kind
of wandering southward. So there’s a bias when taking a
step to more likely go south than certainly north. Or imagine that the drunk is
photosensitive and moves either towards the sun
or away from the sun, or some such thing. So we’re going to look at
different things of that nature and think about, I’ll
come back to Chutes and Ladders later in the lecture,
you can speculate on why this is here. And we’ll look at that. So, this is on the front page
of your handout here. I’ve taken the random walk
program we looked at last time and changed it a bit. And in particular,
I’ve changed the way the drunk works. So let’s look at the code. Wow, haven’t even done
anything it’s — see how this works. So now, drunk itself is a very
small class, one I don’t actually intend to
ever instantiate. I’ve pared it down, it has
only two methods in it. It has an init, which is the
same as before, and a move which is the same as before,
almost the same. Now I’m going to have the
class usual drunk. That’s the drunk we looked
at the last time. And this usual drunk will behave
just like the drunk we looked at last time. In here, I’m going to override
the move method of the inherited superclass, and what
this is going to do is, it’s going to make the same random
choice it made before and then it’s going to call drunk
dot move with the new compass point. So all I’ve done is, I’ve taken
a couple of lines of code out of the previous
implementation and moved it to the subclass. So it’s now, excuse me, in the
subclass I’m making the decision about which
direction to move. Once I’ve made that decision,
then I can call the drunk in the superclass. Notice here, when I’ve made
the call, drunk dot move. So usually you’re expecting
me to write something like d dot move. The object. Here, instead I’m specifying
which class to get the move from, So this is saying, don’t
call my local move, call the move from the superclass. There are a number of other
syntaxes I could’ve used to accomplish the same thing. I used this because it seemed
the most straightforward. Now let’s compare the usual
drunk to the cold drunk. So the cold drunk, again, I’ve
overridden the move, and now it does something different. It gets the random compass point
as before, but if it happens to be south, it
calls drunk dot move with twice the distance. So whenever I get the notion
I’m moving south, because I love the warmth, I actually move
twice as fast. So instead of taking one step, which I do
to the other compass points, if I happen to be going south
I’ll take two steps. So I’m biased towards
moving southward. And then I call drunk
dot move. Otherwise, I call drunk
dot move with the distances before. So I’ve isolated into the
subclass this notion of being heat-seeking. We’ve got a third sub class,
ew drunk, known for east west drunk. And here, what I’ve done is, I
choose to compass point and then while it’s not either east
or west, I choose again. So this drunk can only move
eastward or westward. Can’t move north or south. So again you’ll see I’m able to
have three kinds of drunks. Who as we will see, exhibit
rather different behavior from each other with a minimal amount
of change to the code. If we look down at the bottom,
we’ll see that the code is pretty much exactly what
it was last time. By the way, this doesn’t
quite match the code in your handout. I decided to make the plots
a little bit prettier with better titles and things, but
when I tried to put these in your handouts it wouldn’t fit. So I have a little more compact
things, but this is, I think, a better way
to write it. But essentially, perform trial,
perform sim, answer quest, are all identical to
what they were before. So because I structured my
program in such a way that the drunk’s behavior was independent
of all the code for the generating the trials
and plotting the results, I didn’t have to change
any of that. And this is the key
to good design. Is to isolate decisions in small
parts of your program, so when as inevitable happens,
you want to enhance the program, or you discover you’ve
done something wrong, the number changes you
make is not large. OK, one thing we do need to look
at down here is, it’s not quite the same as before,
because we’ll see that there’s an extra parameter to these
things called drunk type. So if we start with answer
question, it takes as before, the time, the number of trials,
a title, and this one extra thing called
the drunk type. And then when it goes on and
it calls perform sim, it passes the drunk type. And this is the key line here. Before, you may recall
we just said d equals drunk with the arguments. Here, I say d equals
drunk type. So what is drunk type? Drunk type is itself a type. We can use types, you know
variables can have as their values types, parameters can
have as their values types. So I’m just passing the type
around so that here, when it comes time to get a drunk,
I get a drunk of the appropriate type. So I can now answer the question
about a usual drunk, or a cold drunk,
or a ew drunk. This is very common kind of
programming paradigm. We’ve talked about it before,
but this is yet another example of how we use
polymorphism. Polymorphism. We write our code in such a way
that it works with many types of objects. Here we’re writing code
that will work with any subtype of drunk. Now I’d better not
pass it a float. You know, if I answer quest, and
instead of something like usual drunk or cold drunk or e
w drunk, I pass it float or int, the world will come
crashing down around my head. But I haven’t, so you’ll see
down here, I pass it num steps, number trials,
and usual drunk. Which is the name of? A class. Any questions about this? Yes? STUDENT: [INAUDIBLE] PROFESSOR: Louder, please? STUDENT: [INAUDIBLE] PROFESSOR: Good,
good question. The question is, does a drunk
type make a new drunk? Now, I have so much candy to
choose from, I don’t know what to throw you. Do you like Tootsie Rolls,
Snickers, Tootsie Roll Pops, Dots, what’s your choice? Snickers. OK, so what is it? Down here nothing is created
when that call was made. It was if I had typed the
word float or int. I’m merely saying, here is a
type, and the parameter should now be bound to that type. Now any time you use the
parameter, it’s just as if you had written the string, in
this case, usual drunk. So when I get up to here, think
about, it will take, the variable drunk type, evaluate
it, it will evaluate to a type usual drunk, say, in
the first call. And then it will, just as if
I had written usual drunk, invoke the init method of drunk,
and create a new drunk, but this drunk will be
of type usual drunk rather than a drunk. Does that make sense? All right, so this avoids my
having to write a whole bunch of tests, I could have passed
a string, and said if the string said usual drunk, then
d equals something. But here instead of
that, I’m actually passing the type itself. OK? So other than the fact that I
have to pass the type around, this is exactly the
same as before. Now just for fun, we saw that
last time when I asked you what did usual drunk do, there
was some confusion. Not confusion, just a bad guess
about how the drunk would wander. So, let’s try it again. What do you think about
the cold drunk? Will the cold drunk get further
from the origin than the usual drunk? Not further from the origin? Who thinks the cold drunk
will be further away the end of 500 steps? Who thinks the cold drunk will
not be further away? And I’ll bet we can all agr —
got that right, I think — and I’ll bet you’ll all agree that,
with higher probability, the cold drunk will be south
of the origin than north of the origin. More interesting, how
about the ew drunk? So this is a drunk that only
goes east or west, east or west. Will this drunk, well,
first of all, what’s the expected distance? Do you think it should
be close to zero or not close to zero? Who thinks it should
be close to 0? Who thinks it won’t
be close to 0? Well you guys have all fallen
for the same trick you fell for last time. Fooled you twice. Be careful, one more
and you’re out. As we’ll see. But it’s interesting. So let’s run this program
and see what happens. I can take a just a second
or two and we should get a bunch of plots. All right, so here’s
the usual drunk. 100 trials and just as before,
wandered away. Moderately smooth, but of course
little ups and downs, maybe suggesting averaging
over 100 trials is not quite enough. I felt a little better if it
were smoother, but the trend is pretty clear here, I think
we probably don’t doubt it. Well, look at cold drunk. Like a shot heading south. So here we see, there’s bias,
that if you get south you go twice as far makes a
huge difference. Instead of being roughly 20
steps away, it’s roughly 120 steps away. So we see, and this is something
to think about, a small bias can end up making a
huge difference over time. This is why casinos
do so well. They don’t have to have a very
much of a bias in their favor on each roll of the dice in
order to accumulate a lot of money over time. It’s why if you just weigh your
dice a little bit, so that they’re not fair, you’ll
do very very well. I’m not recommending that. Kind of interesting. The e w drunk is pretty much the
same distance away as the usual drunk. This is why we run these
simulations, is because we learn things. Now, I have to confess,
it fooled me, too. The first time I ran this, I
looked at this and said, wait a minute, that’s not
what I expected. So I scratched my head, and
thought about, all right, why is it behaving this way? This happens me a lot in my own
research, that I crunch some data, do some plots, look
at it, get surprised, and on the basis of that I learned
something about the underlying system I’m modeling. Because it provokes me to
think in ways I had not thought before I saw the data. This is an important lesson. You don’t ignore the data, you
try and explain the data. So when I thought about what
happened, I realize that while I might have started at the
origin, and after the first step I’m equally likely
to be here or here. Once I’ve taken the first step,
now my expected location is not zero, right? The first step, my expected
location was zero. Because equally likely to
be plus 1 or minus 1. But once I’ve taken a step and
I happen to be here, my expected location, if I’m here,
is plus 1, it’s not 0. Because half the time I’ll get
back to 0, but half the time I’ll get to 2. So once I have moved away from
where I’ve started, the expectation of where I’ll
end up has changed. This is kind of a profound thing
to think about, because when we look at it, this kind of
behavior explains a lot of surprising results in life. Where, if you get a small run of
random events that take you far from where you started,
it’s hard to get back. So if you think about the stock
market, for example, if you happen to get unlucky and
have a few days or weeks or months, as the case may be,
where you get a run of bad days, it’s really hard to get
back if all the movements after that are random. Because you’ve established
a new baseline. And as we’ll see later, when
you start doing things at random, it’s likely you’ll get a
few runs in one direction or another, and then you’ve got
a new baseline, and it’s unlikely to get back to where
you were originally. We’ll see a lot of
examples of this. But that’s what’s happening
here, and that’s why it looks the way it does. That makes sense to people? Well, so I had this theory,
as I often do when I have theories, I don’t believe them,
so I decided I better write some more code
to check it out. So, what I did is, I took the
previous simulation and now instead of looking at different
kinds of drunks, I got more aggressive in
thinking about my analysis of the data. So again, there’s
a lesson here. I decided I wanted to analyze
my data in new ways. And the beauty of it was, I
could do that without changing either any of the code about the
drunk, or any they of the code about performing the
simulation, really. All I had to do was do a
different kind of analysis to a first approximation. So, let’s look at what
I’ve done here. What I’ve decided to do here is
not only plot, and again, I think you’ll see this code, not
only plot how far from the origin the drunk is over time,
but I’m going to actually plot two other things. I’m going to use a scatter plot,
I think I use scatter in this one, I do, to show
where the drunk is at each period of time. Actually, just all the
places the drunk ends up in each trial. This will give me a visualized
way just see, OK, in my, say, 100 trials, how many the drunk
ended up near the origin, how many of them ended up
really far away? And just, allow me to visualize
what’s going on. And then I’m going to also use
a histogram to sort of summarize some things. To get a look at the
distribution of the data. We’ve been just looking at
average results, but it’s often the case that the average
does not really tell the whole story. You want to ask, well, how many
of the drunks ended up really far away? How many of the drunks ended
up where they started? You can’t tell that
from the averages. So you use a distribution, which
tells you information about how many people
ended up where. So we again saw that, in a less
pleasant context, maybe, in looking at the quizzes,
remember I sent you some plots about the quizzes, and
I didn’t just say, here was the average. I showed you the distribution
of grades. That allowed you to see, not
only where you were relative to the average, but whether
you were an outlier. Was your grade much better
than the average? Or were there a whole bunch of
people around where you are? So there’s a lot of information
there, that will help us understand what’s
really going on. So we’ll run this now. Again, there’s nothing very
interesting here about how I did it, I just used some of
these Pylab dot hist, which gives me a histogram, Pylab dot
scatter, which gives me a scatter plot. I’ll take 500 steps,
400 trials. I’ve done some more trials here,
so we get some smoother lines, better distributions. And then I’m going to look at
the usual drunk and ew drunk only, just to save some time. At least I think I am. My computer runs faster
when it’s plugged in. All right, but we have
our figures here, let’s look at them. So here’s figure one,
the usual drunk. Well, all right, as we’ve
seen this 1000 times, or at least six. So doing what it usually
does, not quite 20. This is kind of interesting. This is the final locations
of the 400 trials of the usual drunk. So we see some information here,
that we really couldn’t get from the averages. That there are more of these
points near the middle, but there are certainly plenty
scattered around. And we get to see that, they’re
pretty much symmetric around where we started. This is what we would
have hoped, right? If we had looked at it, and we
had seen all the points up here, or most of them up here,
we would have said, wait a minute, there’s something
wrong with my code. This was supposed to not
be a biased walk, but an unbiased walk. And if I’d seen a bias in this
population, I should have gotten nervous that I had
some problems with my implementation. My simulation. So in addition to helping me
understand results, this gives me some confidence that I really
am doing an unbiased walk, right? Some over here, some
over here. Not exactly the same, but
close enough that I feel pretty comfortable. And if I look at the
distribution, which probably I could’ve if I worked really
hard, gotten from the scatter plot, but I really didn’t want
to, we’ll see that most of the drunks actually do end up pretty
close to the origin. But that there are a few that
are pretty far away. And again, it’s close to
symmetric around zero. Which gives me a good feeling
that things are working the way they should. This, by the way, is what’s
called a normal distribution. Because once upon a time, people
believed this was the way things usually happened. This is called either
normal or Gaussian. The mathematician Gauss was
one of the first people to write about this distribution. We’ll come back to this later,
and among other things, we’ll try and see whether normal
is really normal. But you see it a lot of times. And basically what it says is
that most of the values hang out around the average,
the middle. And there are a few outliers,
and as we get further and further out, fewer and
fewer points occur. So you’ll see these kind of
curves, of distributions, occurring a lot. Again, we’ll come back to
distributions in a week, or actually in a lecture or two. See a little bit more today,
and then more later on. All right, here’s our east west
drunk, again as before, drifting off to around 18. Well, look at these dots. Well, this makes me feel, that
at least I know that the drunk is only moving east and west.
And again you’ll see, pretty dense in the middle and
a few outliers. Managed to get a little further
east than west, but that happens. East is always more
attractive. What we might have guessed. And if we look at the
distribution, again we can look at it, and I’m just giving
you the east west values here, and again
it’s about the same. So, what do I want you to take
away from these graphs? Different plots show you
different things. So I’m not going to try and
claim that of these three different plots we did, one
is the right one to do. What I’m going to assert
is that you want to do all of them. Try and visualize the data
in multiple ways. And sometimes it’s much easier
to, even if different plots contain exactly the same
information, and in some sense of the scatter plot and the
histogram do contain exactly the same information. In fact, there’s more
information in the scatter plot, in some sense, because I
see each one individually. But it’s, for me, a
lot harder to see. If I’d ask you from the
scatter plot, are they normally distributed? You might have had a hard
time answering it. Particularly for the usual
drunk, where you just saw a lot of points. So the idea of some summarizing
it in the histogram makes it much easier
to make sense of the data, and see what you’re doing, and to
try and learn the lesson you’re trying to learn. OK, this makes sense
to people? All right, let’s move on. Now we’ll go back to this lovely
picture we had before. Any of you ever play the game
Chutes and Ladders? Raise your hand? OK, some things never
go out of style. Well, imagine your poor drunk
wandering through this board, and every once in a while,
because I’m kind of a, not a nice person, I’ve eliminated all
the ladders, and have only some chutes. And every once in a while
the drunk hits a chute and goes whoosh. And in fact, let’s, for the
sake of simplicity here, assume that the chutes are
going to, every once in a while, the drunk will hit a bad
spot, and go right back to the origin. So this poor, say, heat-seeking
drunk who’s trying to head south, does it
for a while and maybe gets zipped right back to where
he or she started. All right, I’ve now told
you I want to put some, make this happen. What part of the code do you
think I should change? Somebody? STUDENT: The field. PROFESSOR: The field,
absolutely. Those are good to throw
short distances. The field, right, because what
we’re talking about here is not a property of the drunk,
or a property of the simulation, but a property of
the space in which the drunk is wandering. So again, we see that by
structuring the initial program around the natural
abstractions that occur in the problem, natural kinds of
changes can be localized. So let’s go and change
the field. So I’m going to have the field
I had before plus this thing called an odd field. Odd field will be a
subclass of field. This is not odd as in
odd or even, this is odd as in strange. So I’m going to first define
where my chutes are. So is chute will take, will
get the coordinates, and assign it to x and y, so it
gets the coordinates of a place, and then will return
abs x minus abs y is equal to zero. So, where are my chutes
going to occur? Somebody? Yeah, kind of radiating
out from the origin. Any place, so I’ll have
my origin, here. Got my graph. And all along here, any place
x and y are equal, there’ll be a chute. Now, I have to be a little bit
careful that it doesn’t happen here, or we won’t
get anywhere. So, and then move, in odd field,
will call field dot move, which is unchanged from
what it was before. And then it will say, if self
dot is chute, set the location back to 0,0. So the poor drunk will move as
before, and if he or she hits this wormhole, get instantly
teleported back to the origin. Very small change, but it will
give us rather different behaviors, at least
I think it will. And then if we look at how we
use it, not much changes. Except, what do you think is
going to have to change? Where will I have to make
the change, somebody? You can actually see
the code here. I’ll have to get a different
field, right? So, at the place where I
instantiate a field, instead of instantiating a field, I’ll
instantiate an odd field. Now if I’d had 16 different
kinds of odd fields, or even two, I might well have done
what I did with drunk. But in order to sort of minimize
things, I’ve done something much smaller. So let’s see, where did
we get the field? I don’t even remember. So, here’s what I do when I’m
looking at my program and I want to see where
something is. I use the text editor, and I’m
going to search for it. Let’s see. Well, it’s not there. There it is. So here when I get my field, I
get my drunk, and then I get a field which is an odd field. All right, anyone want to
speculate what will happen when I run this one? Think the drunk will be closer
or further from the origin when we’re done? Who thinks closer? Who thinks further? Who thinks no difference? Well, you’re right, I mean it’s
sort of logical if we think about it, that if every
once in a while you get to zipped, back it’s going to be
harder to get further away. We’ll see different behaviors,
by the way, it depends on the drunk, right? That’s true for the usual drunk,
but maybe not for the east west drunk. We can see what happens. So let’s try some. We’ll do it for the usual
drunk, which is the more interesting case
to start with. So you’ll see whereas before we
were up just shy of 20 most of the time, here we don’t get
very much much, further. We do get steadily further,
but at a lot slower pace. What do you think it means that,
before you remember, we saw a pretty smooth line. Here we see what may look you
like a fat line, but is in fact a line with a lot
of wiggles in it. What does that imply, about
what’s going on in the simulation, the fact that line
is jagged rather than smooth as it was before? Pardon? Can’t hear you? STUDENT: That it jumps. PROFESSOR: Well, certainly it
happens because of the jumps, but what else is going on? But what is it, sort of, imply
more, whoa, sorry about that, more generally? Right, what it’s saying, is
that because of the jumps, there’s a lot more variation
from trial to trial. Not surprising, right, because
you sometimes you hit these wormholes and sometimes
you don’t. So let’s look at this
other figure. This is kind of interesting. So here’s the scatter plot. And if we zoom in on it, what
we see here is, there are essentially holes, you
know, these alleys where no points lie. Just as we might have
guessed from here. The only way you would get a
point lying on these alleys, if it happened to be the very
last step of the simulation, not even then, because the last
thing we do is go back to the origin. So we can look at this, and say,
well, sure enough, this is keeping people off of a
certain part of the field. All right, some of you will be
happy to know we are, for the moment, actually maybe for the
whole rest of the term, leaving the notion of drunks. Though not of random walks. All right, any questions about
what’s going on here? And again, I would urge you to
sort of study the code and the way it’s been factored to
accomplish these things. And play with it, and look
at what you get from the different plots. I now want to pull back from
this specific example, and spend a few minutes talking
about simulation in general. Computer simulation really grew
hand in hand with the development of the computers,
from the very beginning. The first large-scale deployment
of computer simulation was as part of
the Manhattan Project. This was done during the war
to model the process of nuclear detonation. And, in fact, what they did was
a simulation of 12 hard spheres, and what would
happen when they would bump into each other. It was a huge step forward to
do it with simulation, since the whole project had been
stalled by their attempt to do this analytically. They were unable to actually
solve the problem analytically. And it was only when they hit
upon the notion of using a computer, a relatively new
tool in those days, to simulate it, that they
were able to get the answers they needed. And they did it using something
called a Monte Carlo simulation. Now in fact, that’s just what
we’ve been doing with the random walk, the Monte Carlo
simulation, and I’ll come back to that in a minute. In general, the thing to think
about, is we use simulation when we really can’t get a
closed form analytic solution. If you can put down a system of
equations and easily solve it to get an answer, that’s
usually the right thing to do. But when we can’t easily do
that, the right thing to do is typically to fall back
on simulation. Sometimes even when we can do
it analytically, simulation has some advantages, as we’ll
be seeing as we go forward. What we’re typically doing
when we’re simulating anything, is we’re attempting
to generate a sample of representative scenarios. Because an exhaustive
enumeration of all possible states would be impossible. So again, if sometimes you can’t
solve it analytically, you can exhaustively enumerate
the space and then see what’s going on. But again, usually you can’t. And so we look for a sample, and
the key is, it’s gotta be representative. Of what we would
get in reality. We’ll see an example
of that shortly. So simulation attempts to build
an experimental device that will act like the real
system in important aspects. So I always think of
a simulation as an experimental device. And every time I run it, I’m
running an experiment designed to give me some information
about the real world. These things are enormously
popular, so if you were to get on Google and look
at simulation. So for, example, we could Google
simulation finance. You know, we see we get
about 3,000,000 hits. We can do biology. We get twice as many hits,
showing the relative importance in the world of
biology and finance. For all you Course 7 majors,
we should make sure that should compare biology
to physics. Oh dear, we’ll see that physics
is even more important than biology. And I know we have a lot of
Course 2 students in here, so let’s try mechanical. Oh, lot of those, too. And if I did baseball, or
football, we’d get more than any of them. Showing the real importance
of things in the world. As we look at simulations, I
want you to keep in mind that they are typically descriptive
not prescriptive. So by that I mean, they describe
a situation, they don’t tell you what
the answer is. So another way to think about
this is, a simulation is not an optimization procedure. When we looked at optimization,
that was prescriptive. We ran an optimization
algorithm, and it gave us the best possible solution. A simulation typically doesn’t
give you this best possible solution, but if you give it
the starting point, it will tell you the consequences
of that. Now, can we use simulation
to do optimization? Absolutely. For example, we can use it
to do guess and check. Where we guess a, probably not
to get a truly optimal solution, but to get a good
solution, we can guess various possibilities, simulate
them, and see. People do that all the time. If they want to see what’s the
right number of checkout counters at the supermarket,
or what’s the right airline schedule to use? They’ll make a guess, they’ll
simulate it, and they’ll say all right, this was better than
this, so we’ll choose it. All right, I’m going
to stop here. Next time we’re going to get
more deeply into the actual stochastics, the probability
distributions, and start understanding what’s going
on under the covers.

12 Comments

Add a Comment

Your email address will not be published. Required fields are marked *