Dr. Robert van de Geijn: OK, we're ready to start using Python Notebooks.
What I have done is I've created an icon on my desktop so that all I have
to do is click that icon to get the Notebook server going,
which just popped up.
Notice that there are a number of different notebooks that show up in
what's called the iPython Dashboard.
And the one that we're going to look at in this video is the implementing a
copy routine Notebook, which is the second one.
The first one actually provides a completed notebook for this exercise.
You may want to look at that when we're done.
So let's open this one up.
And the first thing you'll want to do is copy this so that you don't
overwrite the original contents.
So go to File, make a copy, and now we're working with a
copy of that file.
So notice that here, name has changed to implementing a copy
routine copy zero.
All right, what do we have here?
Well, I'm going to let you read the text.
What's important here is that we have boxes that are text.
And then we have boxes in which you can place code that you
can actually execute.
So this is the first box in which we can place executable Python code.
The first thing I'm going to do is use a package called numpy, which makes
defining and operating with matrices particularly convenient.
So I'm going to say import numpy as np, and what that means we'll find out
in a second.
So, that brings in a package that has a bunch of routines that make it easy
to manipulate matrices and perform operations with matrices.
The operation we're going to perform right now is the creation of a matrix.
And for that, numpy has a routine called matrix, where you give it the
entries of the matrix that you would like to create.
Now, what's going on here?
Numpy has a routine called matrix.
There may be other packages that also have routines called matrix.
So to indicate that it's the matrix routine from the package numpy that
you want to use, you prepend the name matrix with np, because up here you
said import numpy as np.
So the np here is going to indicate that it's the routine from numpy that
you want to use.
That's to avoid something that's called name space conflict.
And we also want a vector y.
So we'll put y here, and we'll set the values of y to this.
Now, to execute this box, what you do is you either go up here to cell and
say run, or instead, what I'm going to do is press down the Shift key and hit
the Return button, or the Enter button.
And bingo, what we get are vectors x and y.
Now, what's happened here?
We defined x to actually be a matrix, because when we program with numpy,
we're going to view vectors as special cases of matrices, namely matrices
with only one column.
The fact that we set that matrix to this right here meant that the first
row only has one entry in it, and that entry is 1.
The second row only has one entry in it, and that entry is 2, et cetera.
And bingo, we have ourselves two vectors, x and y.
Now, in Python, you could simply copy by saying y is equal to x, and that
should copy x into y.
And indeed, if we execute this box, we see that the contents of x have been
assigned to the contents of y.
The problem with using the assignment in that way is that if you now change
a value of x, OK, what do we have here?
x is a vector, it's a column vector, but we actually created it as a
matrix, which means that to index in it, we have to give two values, the
row index and the column index.
The column index is always 0, because the vector only has one column.
So this here is the component of x index by 1, and we're setting it equal
to minus 999.
If I execute this box, what we notice is that not only the value in x
changes, but the corresponding value in y changes as well.
And that's rather annoying.
This is known as a shallow copy.
What happened is that when we did this assignment of x to y, what it really
did was it pointed y to the same values as that were stored in x, and
therefore if you change the value in x, it changes it in y.
So let's start over, let's reset x and y to the original vectors.
And one way to change the values of y but not have this shallow copy happen
is to say for i in the range from 0 to 3, set y, i comma 0, that's the i-th
component of the vector y to x of y comma 0.
And if you execute that, you see that the values of x one by one have been
assigned to the corresponding values of y.
Let's look at this a little bit more carefully.
What it really says here is for all indices i in the range from--
so range of three is really the set from 0 to 3, not including 3, but
including 0.
For all i in that range, set the i-th component of y to the i-th
component of x.
And now what we see is if we change one of the values in x, that value
does not change in y.
So the components of x were actually literally copied into y, and now you
can change values of x without being afraid of also changing the same
values in y.
Now, we may want to copy vectors of arbitrary length, and it would be kind
of annoying to have to write this kind of for loop every time you
wanted to do that.
So the way you get around that is to create a little routine that does the
copy for you.
So let's define a routine called copy, input our vectors x and y.
What it does is it copies the contents of x into y.
Now, you need to know how long the vectors v and y are, so we're going to
extract the row and column size of the matrix x.
Remember, x is a vector, but we were creating x, actually, as a special
matrix with only one column.
So we're going to extract the row and column size of that matrix with the
numpy routine shape.
And once we have that shape, then we're going to write a for loop that
says for i in the range from 0 to m, not including m, set y of i comma 0
equal to x of i comma 0.
Now, to make it so that your Notebook knows about this routine, what you
have to do is execute this.
Whoops, I made a mistake.
There should have been a colon here.
So I'll fix that, and then I execute that box again.
And now if we, say, copy from x to y, what we see is the contents of x
copied into the contents of y.
If we now change some other component of x, what we notice is that component
is not changed in y.
Later in the course, it will be convenient to have a much more general
copy routine.
What does this routine look like?
It's considered good practice to only import those routines from a package
that you actually need.
So here I'm only importing the routine matrix and shape from numpy, because
those are the only routines that I actually need.
I then say let's define the routine copy, and I give some comments that
indicate what this routine is supposed to do.
That's good programming habit.
Now, this routine should only work if matrices are passed in, so the first
thing I check is whether x is a matrix, and whether y is a matrix, and
if it isn't, then I'll print out an error message.
I then extract the row and column size of x and y, and I check whether one of
those two sizes is equal to 1.
This particular routine will work whether x is a row
vector or a column vector.
In other words, it will work whether x consists of one row in a matrix or one
column in a matrix.
For that to be true, it has to be the case that one of the two sizes is
equal to 1, and that's what's checked here.
And then finally, this routine can copy a row into a column, a column
into a row, et cetera.
So what it does here is it checks whether one of the sizes is equal to
1, and which size is equal to 1, the term is whether it's a row or a
column, and then it checks whether the size of the vectors is the same, and
then proceeds to actually copy the one vector into the other vector.
The remainder of this notebook then demonstrates how that routine works,
so you may want to just look through that on your own.
Finally, I draw your attention to the very last part of this notebook, where
we discuss how this copy routine we just discussed is part of a package
that we built for this course, called laff.
So if you want to copy one vector to another vector, all you need to do is
import laff as laff.
Remember, that imports the package, and then if you prepend the name of a
routine in that package with laff, it will pick out that
routine from that package.
And now if you're given two different vectors, all you need to do to copy
one into the other is to say laff.copy x to y.