{ "metadata": { "name": "" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Implementing a (vector) copy routine" ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Preliminaries" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Copy this notebook so that you don't corrupt the original! Then you can \"play\" with the copy of the notebook all you want!

\n", "\n", "

This particular notebook does everything for you if you follow along with the video and type in code produced there. You will be able to try it yourself in subsequent notebooks that implement other operations.

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's start by importing numpy and creating a vector $ x = \\left( \\begin{array}{r} 1 \\\\ 2 \\\\ 3 \\end{array} \\right) $ and a vector $ y = \\left( \\begin{array}{r} 0 \\\\ -1 \\\\ -2 \\end{array} \\right) $. \n", "\n", "Execute the code in the box by clicking in the box and then on \"Cell -> Run\". Alternative, click on the box and push \"Shift\" and \"Return\" (or \"Enter\") together." ] }, { "cell_type": "code", "collapsed": true, "input": [ "# This imports a package called \"numpy\" that will make working with matrices \n", "# simpler. We choose to call this package by the abbreviation np\n", "\n", "# create two two-dimensional matrices of only one column each. \n", "# In the future we will also think of (column) \n", "# vectors as matrices with only one column.\n", "\n", "print( 'x = ' )\n", "print( x )\n", "\n", "print( 'y = ' )\n", "print( y )" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, let's use assignment to copy x into vector y:\n", "\n", "(Again: \"Shift\" and \"Return\" at the same time!)" ] }, { "cell_type": "code", "collapsed": false, "input": [ "\n", "\n", "print( 'y = ' )\n", "print( y )" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Hmmm, it seems like it all worked. The problem is that, in this situation, Python does a \"shallow copy\". If you change a value in x, then that value also changes in y. In other words, y is just a reference to the same data that x references.\n", "\n", "We illustrate this by setting the second entry in $ x $ to a new value and printing both x and y ." ] }, { "cell_type": "code", "collapsed": false, "input": [ "x[ 1,0 ] = # notice that Python starts indexing at 0. (You count 0, 1, ...)\n", " # Given that a vector of length n is an (n x 1) matrix, x[ 1,0 ] refers to \n", " # the second component [1] of vector x. The [0] idicates that we are working\n", " # with the first column of the matrix, but here the matrix only has one column!\n", "print( 'x = ' )\n", "print( x )\n", "print( 'y = ' )\n", "print( y )" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To fix this, we could write a loop that copies the entries of x into the vector y. Let's start by resetting the values in y:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "x = np.matrix( '1;2;3' )\n", "print( 'x = ' )\n", "print( x )\n", "\n", "y = np.matrix( '0;-1;-2' )\n", "print( 'y = ' )\n", "print( y )" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, we want to copy the three entries in x into the three entries in y using a \"for\" loop:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "\n", "\n", "print( 'y = ' )\n", "print( y )" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If we now change the second value in x, the contents of y do not change:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "x[ 1,0 ] = -999\n", "print( 'x = ' )\n", "print( x )\n", "print( 'y = ' )\n", "print( y )" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Copy as a simple routine" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Clearly, writing the \"for loop\" every time you want to copy a vector would be very cumbersome. For this reason, we are going to write a routine, copy( x, y ), that copies the contents of vector x to vector y. (Note: there are other ways of doing a \"deep copy\" in Python. However, the whole point of writing these routines is to help learn the material in this course. This is not a course in which we teach you Python beyond what you need to better understand linear algebra.) \n", "\n", "Here is what it means to copy a vector of size $ m $:\n", "$$\n", "\\left( \\begin{array}{c}\n", "\\psi_0 \\\\\n", "\\psi_1 \\\\\n", "\\vdots \\\\\n", "\\psi_{m-1}\n", "\\end{array}\n", "\\right)\n", ":=\n", "\\left( \\begin{array}{c}\n", "\\chi_0 \\\\\n", "\\chi_1 \\\\\n", "\\vdots \\\\\n", "\\chi_{m-1}\n", "\\end{array}\n", "\\right)\n", "$$\n", "\n", "As an algorithm this can be written as\n", "

\n", " for $ i = 0, \\ldots , m-1 $
\n", " $ ~~~ \\psi_i := \\chi_i $
\n", " endfor \n", "

\n", "\n", "

\n", "This translates into the following routine:\n", "

" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Be sure the run the above box, or this notebook won't know about the routine!!!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, if you execute" ] }, { "cell_type": "code", "collapsed": false, "input": [ "copy( x, y )\n", "\n", "print( 'x = ' )\n", "print( x )\n", "\n", "print( 'y = ' )\n", "print( y )" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "you notice that vector x has been copied to vector y. And if we change values in x, the values in y don't change:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "x[ 2,0 ] = 111\n", "\n", "print( 'x = ' )\n", "print( x )\n", "\n", "print( 'y = ' )\n", "print( y )" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "A complete copy function" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As we develop our library, we are really going to need a copy routine that can copy rows from a matrix into a column vector, columns of a matrix into a vector, a row of a matrix into a column of a matrix, and all such combinations. As a result, what we really want is a copy routine that works when x and y are column and/or row vectors, in all combinations. It also should notify us if we try to copy between vectors that are not of the same size. We now give a complete copy function.\n", "\n", "From our past experience teaching this course, we've noticed that the details of this routine, and others like it, get confusing to those who have not programmed before and/or have not programmed with Python before. So, don't worry too much if you don't understand it all. We give it more for those who are interested in the details than as a necessary part of the course." ] }, { "cell_type": "code", "collapsed": false, "input": [ "from numpy import matrix\n", "from numpy import shape \n", "\n", "def copy(x, y):\n", " \"\"\"\n", " Compute y = x, overwriting y\n", " \n", " x and y can be row and/or column vectors. If necessary, an\n", " implicit transposition happens.\n", " \"\"\"\n", " \n", " assert type(x) is matrix and len(x.shape) is 2, \\\n", " \"laff.copy: vector x must be a 2D numpy.matrix\"\n", "\n", " assert type(y) is matrix and len(y.shape) is 2, \\\n", " \"laff.copy: vector y must be a 2D numpy.matrix\"\n", "\n", " m_x, n_x = x.shape\n", " m_y, n_y = y.shape\n", " \n", " assert m_x is 1 or n_x is 1, \"laff.copy: x is not a vector\"\n", " assert m_y is 1 or n_y is 1, \"laff.copy: y is not a vector\"\n", "\n", " if m_x is 1 and m_y is 1: # x is a row, y is a row\n", " assert n_x == n_y, \"laff.copy: size mismatch between x and y\"\n", " for i in range(n_x): y[0, i] = x[0, i]\n", " \n", " elif n_x is 1 and n_y is 1: # x is a column, y is a column\n", " assert m_x == m_y, \"laff.copy: size mismatch between x and y\"\n", " for i in range(m_x): y[i, 0] = x[i, 0]\n", " \n", " elif m_x is 1 and n_y is 1: # x is a row, y is a column\n", " assert n_x == m_y, \"laff.copy: size mismatch between x and y\"\n", " for i in range(n_x): y[i, 0] = x[0, i]\n", " \n", " elif n_x is 1 and m_y is 1: # x is a column, y is a row\n", " assert m_x == n_y, \"laff.copy: size mismatch between x and y\"\n", " for i in range(m_x): y[0, i] = x[i, 0]\n" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For a line-by-line explanation, watch the video!" ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Test the code" ] }, { "cell_type": "heading", "level": 4, "metadata": {}, "source": [ "Copy a row to a row" ] }, { "cell_type": "code", "collapsed": false, "input": [ "x = np.matrix( '1 2 3' )\n", "y = np.matrix('0 -2 -3')\n", "\n", "print( \"x = \" )\n", "print( x )\n", "print( \"y = \" )\n", "print( y )\n", "\n", "copy( x, y )\n", "print( \"y = \" )\n", "print( y )\n", "\n", "assert np.array_equal(x,y), \"error!\"" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "import numpy.matlib\n", "\n", "print(\"-----SLAP_copy tests-----\\n\")\n", "\n", "x = np.matrix( '1 2 3' )\n", "y = np.matlib.zeros( (1,3), dtype=int) # create a 1 x 3 matrix of zeros\n", "print(\"From row to row\", \"x = \", x, \"y = \", y, sep=\"\\n\")\n", "copy(x,y)\n", "print(\"\\ny = \", y, \"________________\", sep=\"\\n\")\n", "\n", "x = np.matrix( '1;\\\n", " 2;\\\n", " 3' )\n", "y = np.matlib.zeros( (3,1), dtype=int)\n", "print( \"\\nFrom column to column\", \"x = \", x, \"y = \", y, sep=\"\\n\")\n", "copy(x,y)\n", "print(\"\\ny = \", y, \"________________\", sep=\"\\n\")\n", "\n", "x = np.matrix( '1 2 3' )\n", "y = np.matlib.zeros( (3,1), dtype=int)\n", "print( \"\\nFrom row to column\", \"x = \", x, \"y = \", y, sep=\"\\n\")\n", "copy(x, y)\n", "print(\"\\ny = \", y, \"________________\", sep=\"\\n\")\n", "\n", "x = np.matrix( '1;\\\n", " 2;\\\n", " 3' )\n", "y = np.matlib.zeros(( 1,3), dtype=int)\n", "print( \"\\nFrom column to row\", \"x = \", x, \"y = \", y, sep=\"\\n\")\n", "copy(x, y)\n", "print(\"\\ny = \", y, \"________________\", sep=\"\\n\")" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, let's see what happens if we try to do something like copying a row of the wrong length into a column. Don't worry about the fact that you are getting error messages. The whole point of the next few cells is to illustrate how errors are reported. " ] }, { "cell_type": "code", "collapsed": false, "input": [ "import numpy.matlib\n", "\n", "print(\"-----SLAP_copy tests-----\\n\")\n", "\n", "x = np.matrix( '1 2 3 4' )\n", "y = np.matlib.zeros( (1,3), dtype=int)\n", "print(\"From row to row\", \"x = \", x, \"y = \", y, sep=\"\\n\")\n", "copy(x,y)\n", "print(\"\\ny = \", y, \"________________\", sep=\"\\n\")" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "import numpy.matlib\n", "\n", "print(\"-----SLAP_copy tests-----\\n\")\n", "\n", "x = np.matrix( '1;\\\n", " 2;\\\n", " 3;\\\n", " 4' )\n", "y = np.matlib.zeros( (3,1), dtype=int)\n", "print( \"\\nFrom column to column\", \"x = \", x, \"y = \", y, sep=\"\\n\")\n", "copy(x,y)\n", "print(\"\\ny = \", y, \"________________\", sep=\"\\n\")" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "import numpy.matlib\n", "\n", "print(\"-----SLAP_copy tests-----\\n\")\n", "\n", "x = np.matrix( '1 2 3 4' )\n", "y = np.matlib.zeros( (3,1), dtype=int)\n", "print( \"\\nFrom row to column\", \"x = \", x, \"y = \", y, sep=\"\\n\")\n", "copy(x, y)\n", "print(\"\\ny = \", y, \"________________\", sep=\"\\n\")" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "import numpy.matlib\n", "\n", "print(\"-----SLAP_copy tests-----\\n\")\n", "\n", "x = np.matrix( '1;\\\n", " 2;\\\n", " 3;\\\n", " 4' )\n", "y = np.matlib.zeros(( 1,3), dtype=int)\n", "print( \"\\nFrom column to row\", \"x = \", x, \"y = \", y, sep=\"\\n\")\n", "copy(x, y)\n", "print(\"\\ny = \", y, \"________________\", sep=\"\\n\")" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally, let's see if we can copies rows and/or columns in matrices\n" ] }, { "cell_type": "code", "collapsed": false, "input": [ "import numpy.matlib\n", "\n", "print(\"-----SLAP_copy tests-----\\n\")\n", "\n", "A = np.matrix( '1 2 3 4;\\\n", " 5 6 7 8;\\\n", " 9 10 11 12' )\n", "B = np.matlib.zeros( (3,4), dtype=int)\n", "print(\"From row to row\", \"A = \", A, \"B = \", B, sep=\"\\n\")\n", "copy(A[1,:],B[0,:])\n", "print(\"\\nB = \", B, \"________________\", sep=\"\\n\")" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "import numpy.matlib\n", "\n", "print(\"-----SLAP_copy tests-----\\n\")\n", "\n", "A = np.matrix( '1 2 3 4;\\\n", " 5 6 7 8;\\\n", " 9 10 11 12' )\n", "B = np.matlib.zeros( (3,4), dtype=int)\n", "print(\"From column to column\", \"A = \", A, \"B = \", B, sep=\"\\n\")\n", "copy(A[:,0],B[:,1])\n", "print(\"\\nB = \", B, \"________________\", sep=\"\\n\")" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Copying rows and columns of matrices" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We haven't discussed matrices yet. For now, just think of them as two dimensional arrays of numbers. We illustrate how our general copy routine can copy rows to columns, columns to columns, and so forth." ] }, { "cell_type": "code", "collapsed": false, "input": [ "import numpy.matlib\n", "\n", "print(\"-----SLAP_copy tests-----\\n\")\n", "\n", "A = np.matrix( '1 2 3 4; \\\n", " 5 6 7 8; \\\n", " 9 10 11 12' )\n", "B = np.matlib.zeros( (4,3), dtype=int)\n", "print(\"From row to column\", \"A = \", A, \"B = \", B, sep=\"\\n\")\n", "copy(A[1,:],B[:,0])\n", "print(\"\\nB = \", B, \"________________\", sep=\"\\n\")" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "import numpy.matlib\n", "\n", "print(\"-----SLAP_copy tests-----\\n\")\n", "\n", "A = np.matrix( '1 2 3 4;\\\n", " 5 6 7 8;\\\n", " 9 10 11 12' )\n", "B = np.matlib.zeros( (4,3), dtype=int)\n", "print(\"From column to row\", \"A = \", A, \"B = \", B, sep=\"\\n\")\n", "copy(A[:,1],B[0,:])\n", "print(\"\\nB = \", B, \"________________\", sep=\"\\n\")" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "The laff library copy routine" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The above routine is part of a library routine as part of the laff library. To use it you will have to do
\n", "
\n", " import laff \n", "
\n", "
\n", "after which you can use the routine by calling\n", "
\n", "
\n", " laff.copy( x, y ) " ] }, { "cell_type": "code", "collapsed": false, "input": [ "import laff\n", "\n", "x = np.matrix( '1;\\\n", " 2;\\\n", " 3' )\n", "y = np.matrix( '-1;\\\n", " 0;\\\n", " 2' )\n", "\n", "laff.copy( x, y )\n", "\n", "print( \"x = \" )\n", "print( x )\n", "\n", "print( \"y = \" )\n", "print( y )" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ " That's all! Next, you will get to practice writing some code. But don't panic: we'll get you through it. " ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] } ], "metadata": {} } ] }