{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#0. Basically a calculator"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"###0.0 The very basics"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######What is this thing called \"Python\"?\n",
"\n",
"Python is a programming language - a formal language for giving instructions to a computer. Python is a very high-level language, meaning that instructions you write in Python have to be translated into lower-level (more finicky and harder for humans to deal with) languages before your computer can carry them out. This makes Python code fast and easy to write and read, but detracts from the control that you as a programmer have over exactly how the computer carries out your instructions (leading to less efficient programs). For us, this is a good tradeoff.\n",
"\n",
"Python is an interpreted language, meaning that the instructions are translated on the fly (into C code) when you run a program. Some other languages (like C, FORTRAN, and Java) are compliled languages - meaning that the translation is done once before running the program. This makes Python a bit slower than those languages, since the interpreter has to go through line-by-line translating your code. The advantage is that you can run your code immediately after you write it - no need to wait for compilation or debug compiler errors (they are a pain)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######What is this tutorial?\n",
"\n",
"This section of the tutorial introduces programming in general and some tools of scientific programming in particular. It is not a comprehensive introduction to Python or to scientific programming, but instead offers some tools that you can use to get started programming right away.\n",
"\n",
"This document is called an Ipython notebook. It is a specialized environment for scientific Python that allows for internal code, text, and figures. Ipython notebooks are divided into cells, which can contain text (like this one), or code. To wit:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If you click on a code cell and hit shift-enter on your keyboard (or the \"play\" button at the top of this window), the notebook will execute the instructions in that cell and that cell only. You can make more cells by hitting the \"plus\" button at the top and move them around with the arrow buttons. This notebook has instructions in text cells and lots (lots!) of code cells. The purpose of having lots of code cells is *so that you can enter code in them. *In order to learn how to program, you must spend time actually writing and editing your own code. Whenever the text mentions a command that you can give to Python, you should try it out yourself.\n",
"\n",
"I mentioned earlier that this is not a comprehensive guide to Python. You can find one of those [Here](https://docs.python.org/2/reference/). We will also be using some third party tools, numpy and matplotlib. You can find references for them online as well([numpy](http://docs.scipy.org/doc/numpy/reference/),[matplotlib](http://matplotlib.org/devdocs/index.html))."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"###0.1 Values and operations"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In order to do math we will need some values and some operations to do to those values."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######Excercise: Echo some values\n",
"If you write a code snippet that ends with a value, python will echo that value in its output. Try this out with some positive, negative (put a - in front of the number), integer, or rational numbers of your choice."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######Excercise: Basic operations\n",
"Python has built in operators to do basic arithmatic. These are pretty straightforward: a+b will sum a and b while a-b will subtract. To multiply a and b, type a\\*b and to exponentiate $a^b$ type a\\*\\*b. You can divide $\\frac{a}{b}$ by typing a/b. Order of operations is:\n",
"1. parentheses\n",
"2. exponentiation\n",
"3. multiplication & division\n",
"4. addition and subtraction (What about minus signs? try 2\\*\\*-2 and -2\\*\\*0.5)\n",
"\n",
"Give some expressions a shot. What happens if you divide $\\frac{3}{5}$? What about $\\frac{3.0}{5}$?"
]
},
{
"cell_type": "code",
"execution_count": 50,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######Excercise: Types & Precision\n",
"As you may have noticed, division does not always work as expected. What's the deal with this? The answer is that Python values are not all interchangeable - each one is formatted as one of many data types. So far you have encountered two of these data types:\n",
"1. The 'int' data type is used to store integer values. When you type 8 or -5, you get an int.\n",
"2. The 'float' data type is used to store numbers with fractional components. When you type 8.0, -5.0, or 12.37, you get a float.\n",
"\n",
"You can find the type of a value by running: type(value)\n",
"\n",
"Try it out. What is the type of the value that you get back from using type()?"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"int"
]
},
"execution_count": 33,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"type(5)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Both of these data types are stored with a predifined amount of memory. For int values this results in a maximum (or minimum negative) value. For float variables this results in limited precision. The maximum/minimum integer is not a problem in Python - the interpreter handles too-large/too-small values automatically, but the precision limitation is a potentially serious issue. A python float can only hold 15-17 decimal digits. Anything further than that will be rounded off, which can result in error.\n",
"\n",
"The following code snippet illustrates this problem:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"1234567890123456.8"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"(0.1234567890123456789)*10000000000000000"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######Excercise: print statements and strings\n",
"Typically, we will write code that is more than one line long, so we cannot rely on the automatic echo of the last line's value to tell get output. Fortunately we can easily display a value by running:\n",
"\n",
"print value\n",
"\n",
"Try printing multiple values using multiple lines with print statements."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We will sometimes also want human-readable text. We might even want to generate this text automatically. To do this, we will use a data type called a string. A string is just a sequence of letters, numbers, and special characters (though some special characters do odd things). To make a string in Python, just put quotes around some text.\n",
"\n",
"Try it. What happens if you print vs. echo a string? What happens if you enter \"string1\" + \"string2\"?"
]
},
{
"cell_type": "code",
"execution_count": 51,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######Excercise: Comments\n",
"We do not always want all of our code to run. Maybe we would like to leave a note for a future programmer (often that future programmer is \"us in a week\") or maybe we want to temporarily disable a line of code to test an idea. We can prevent code from running using a comment. In Python, all text on any line that follows a # is ignored by the interpreter (unless the # is in quotes as part of a string). This lets us write whatever note we want after a #."
]
},
{
"cell_type": "code",
"execution_count": 60,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"8"
]
},
"execution_count": 60,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"5+3 # I am a comment! Try disabling this whole line with a #"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"###0.2 Variables and functions"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######Excercise: Name tags for values\n",
"Python would be pretty lame if all we could do was one-line arithmetic. Luckily for us, Python (and just about every other programming language) allows us link values with names and then remembers the names and values so we can use them later. A name-value link is called a variable. This usage of the word \"variable\" differs slightly from the algebra class usage. In particular, a variable in programming is not a symbolic representation of a quantity - the idea of solving for a variable in a program is nonsensical.\n",
"\n",
"In order to use variables, we need a way to link names and values (this is called \"assignment\"). To assign the value 5.0 to the variable named x we type:\n",
"\n",
" x = 5.0\n",
"\n",
"Note that this just means the name x is now linked to the float value 5.0. It is not a statement about x. If we wanted to, we could make the very next line of our program:\n",
"\n",
" x = \"banana\"\n",
"\n",
"...and then the name x would be linked to the string \"banana\". This does not imply that 5.0 is the same as \"banana\" - we have just taken the name tag x and slapped it on the string \"banana\".\n",
"\n",
"Try out some variable assignment. What happens if you assign a variable in one line and then do mathematical operations on it on the next lines? What happens if you run type(variable) or print variable? What happens if you try to do mathematical operations on a variable that you have not assigned? Do variables care about the case of letters in the name?\n",
"\n",
"Note that not all variable names work. A variable name can contain numbers, but not start with one. Special characters are not allowed in the name and the whole name cannot be one of several reserved words (like 'print')."
]
},
{
"cell_type": "code",
"execution_count": 77,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######Excercise: Clearing the namespace\n",
"This ipython notebook is like a collection of many programs (or will be). Since the variables that we assign in one cell stay assigned as long as the notebook is open (even if we delete the lines on which we assigned them!) it is possible for us to write subprograms that unwittingly depend on or are influenced by other subprograms. It would be really nice if we could just clear away all of the names that we have assigned and start fresh. The following code snippet will do tht inside of ipython:"
]
},
{
"cell_type": "code",
"execution_count": 55,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Once deleted, variables cannot be recovered. Proceed (y/[n])? y\n"
]
}
],
"source": [
"%reset"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######Excercise: A function is like a black-box machine\n",
"A function is a subprogram that can be called on by other programs to do a particular task. The internal workings of a function are hidden from the program that calls it, making errors both less likely and easier to catch. Python has several (76) functions built-in that we can call from any program as if they were black-box machines - concerning ourselves only with their inputs and outputs. To call a function in python, type:\n",
"\n",
" functionName(input)\n",
"\n",
"If that looks familiar, it is because that is the syntax you used to call the type function earlier. You can also assign variables to the output of functions:\n",
" \n",
" output = functionName(input)\n",
"\n",
"Some functions take multiple inputs (properly, the inputs to a function are called \"arguments\") and/or return multiple outputs:\n",
"\n",
" output1,output2 = functionName(input1,input2)\n",
"\n",
"Aside from type, you might find these built-in functions useful:\n",
"1. len() takes one argument and returns the length of the argued value. Try it on strings.\n",
"2. float() takes a single numerical argument and returns an equivalent float. What happens if you argue a float value to the similar function int().\n",
"3. round() rounds a float\n",
"4. abs() takes a numerical arguement and returns the absolute value"
]
},
{
"cell_type": "code",
"execution_count": 59,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######Excercise: The math module\n",
"Python has 76 built-in functions, last I checked. That sounds like a lot, but there are actually considerably more than 76 things you might want a function to do. For these things we must either write our own functions or rely on those that others have written. As it happens, others have written a whole heck of a lot of Python functions. Often a team of programmers will write many functions that share a related theme and then package these together in a bundle known as a module. We can then download these modules and call their functions in our code. Even better, the most basic modules are part of the Python standard library, meaning that they are included with most Python distributions and we don't even have to download them.\n",
"\n",
"What is the difference between module functions in the standard library and built-in functions? The answer is that built-in functions are automatically callable from every Python program while module functions must be imported into each program that wishes to use them. Since each function takes up a name, this serves to keep clutter and confusion to a minimum - you can import only the functions you need for your specific program.\n",
"\n",
"How does one import module functions? There are multiple ways, but some are bad. The best way is to just type:\n",
"\n",
" import moduleName\n",
"\n",
"This gets all of the functions from the module (oh no, confusion!) but requires us to prepend our function calls with the module name, like such:\n",
"\n",
" moduleName.functionName()\n",
"\n",
"This makes it clear where functions come from, reducing the probability of confusion. It is a bit wordy, though. We can cut down on the verbosity by typing:\n",
"\n",
" import moduleName as mn\n",
"\n",
"Now we can call functions from that module by typing:\n",
"\n",
" mn.functionName()\n",
"\n",
"We will try this out with the very useful math module. Import math however you like and then try some of the following functions:\n",
"1. math.log() gives the natural logarithm of a value argued to it. If you argue two values: log(a,b) you will get the base b logarithm of a. This function has optional arguments!\n",
"2. math.sqrt() does about what you would expect\n",
"3. math.sin(),math.cos(),math.tan() give trig functions\n",
"4. math.pi is not a function. Modules can store variables!\n",
"\n",
"Try in particular taking sine of pi. How far off is the result? What accounts for this?"
]
},
{
"cell_type": "code",
"execution_count": 77,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######Excercise: Writing your own functions\n",
"\n",
"Let's suppose you had written a piece of code that computes the length of the hypoteneuse of a right triangle with side lengths a and b. Better yet, write that code:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"a = 5 # for instance\n",
"b = 3 # for instance\n",
"\n",
"# your code here"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now suppose that you had some project that required you to do that computation many times. Should you just copy-paste? No, that would be time-consuming and result in ugly, confusing code. Better to define a function once an then call that function as needed. To define a function in Python, use the following syntax:\n",
"\n",
"def functionName(argument1,argument2):
\n",
" calculate output
\n",
" return output\n",
"\n",
"Not every function needs to return output to the program that called it - some might print output directly, save data to files, or make plots. The rest of that example definition needs to be *followed strictly *though, right down to the block of indented lines after the def statement (python uses indentation to tell what parts of your program are in the function)."
]
},
{
"cell_type": "code",
"execution_count": 78,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# now make a hypoteneuse-caulculating function\n",
"\n",
"def hypotenator(a,b):\n",
" \n",
" #your code here\n",
" \n",
" return c"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######Problem: Fibonacci recursion\n",
"Write a function that takes an integer argument $n$ and returns the $n^{th}$ term of the Fibonacci sequence.\n",
"\n",
"Hint: The $n^{th}$ term of the Fibonacci sequence, which we will call $F_n$, is $F_n = F_{n-1}+F_{n-2}$. $F_0 = 0$, $F_1 = 1$\n",
"\n",
"Hint: What if your function called itself?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"###0.3 Lists\n",
"A list is just what it sounds like - a data type that contains an ordered list of values. These values can be whatever you want, incluiding variables or even other lists (a single list can contain many types of values). The len() function will tell you how long a list is."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######Excercise: Making lists\n",
"One way to make a list is to just type out a bunch of values, seperated by commas and surrounded by square brackets:\n",
"\n",
" listName = ['banana', 3, 5.0]\n",
"\n",
"This will make a list that contains exactly what you put in it, but might be a pain to type out. Fortunately, there are shortcuts:\n",
"\n",
" listName = range(4,25,2)\n",
"\n",
"That will make a list whose elements are [4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24]. The syntax is range(start,stop+1,step) where start defaults to 0 and step to 1 if you don't include them, so:\n",
"\n",
" listName = range(10)\n",
"\n",
"...is [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]. Some operators work on lists. Try using + and \\* on pairs of lists. How would you go about making a list of length n whose elements are all 0?"
]
},
{
"cell_type": "code",
"execution_count": 83,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######Excercise: Slicing to read\n",
"Lists are indexed, meaning that each element of a list has a corresponding integer. The first element in a list has index 0, the second has index 1, and so on. You can access the $n^{th}$ element of a list (remember, the indices start at 0) by typing:\n",
"\n",
" nthElement = listName[n]\n",
"\n",
"Maybe you want the $n^{th}$ through ${k}^{th}$? Try:\n",
"\n",
" nThroughk = listName[n:k-1]\n",
"\n",
"You can change the step by typing:\n",
"\n",
" nThroughkbyp = listName[n:k-1:p]\n",
"\n",
"so if $p=2$ you will get every other element from the $n^{th}$ through ${k}^{th}$. There are also some shortcuts:\n",
"\n",
" everypth = listName[::p]\n",
"\n",
"will get every $p^{th}$ element from the whole list. To get the last element, use:\n",
"\n",
" final = listName[-1]\n",
"\n",
"Make some lists and try slicing. How do you get the $n^{th}$ to last? What does listName[::-1] do?"
]
},
{
"cell_type": "code",
"execution_count": 89,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######Excercise: Slicing to write\n",
"\n",
"You can also using slicing to alter a list. The syntax is the same as slicing to read from a list except the assignment is reversed:\n",
"\n",
" listName[n] = newnthElement\n",
"\n",
"Try altering a some lists. What happens if you assign an element of a list to be another list. What happens if you assign multiple elements of a list to be another list. How does the length of the slice (and the second list) affect this result? What happens if the slice is discontiguous (like every second element)?"
]
},
{
"cell_type": "code",
"execution_count": 92,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######Problem: Write a function that takes a list of numbers and returns their mean and standard deviation.\n",
"Hint: sum() is a useful built-in function\n",
"\n",
"Hint: the inputs might be integers"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#1. Not just a calculator"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"###1.0 If and conditions"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######Excercise: if a, then b\n",
"An if statement executes code only when specified conditions are met. In python, they look like this:\n",
"\n",
" if (condition):\n",
" do this stuff only if condition is met\n",
"\n",
"The stuff that is controlled by an if statement is denoted by an indented block, like for functions. What sort of conditions can we set? A basic one is equality:\n",
"\n",
" if (a==b):\n",
" print \"a and b are equal!\"\n",
" \n",
"This will (try it out!) print \"a and b are equal!\" only if a and b in fact contain equal values."
]
},
{
"cell_type": "code",
"execution_count": 116,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######Excercise: The Boolean data type\n",
"\n",
"We are not limited to testing for equality:\n",
"1. a<=b tests whether a is less than or equal to b\n",
"2. a>=b tests whether a is greater than or equal to b\n",
"3. ab tests whether a is greater than b\n",
"5. a!=b tests whether a is not equal to b\n",
"\n",
"You can try these out by just substituting values for a and b (or using variables) and looking at the results of these expressions. For each test you should get either True or False as output. Give a few expressions a shot. What happens if you compare lists, or strings. What if one string/list is shorter than the other. What if you compare a string and an integer?\n",
"\n",
"...\n",
"\n",
"Done? You might be wondering what data type these True and False values are. Maybe you tried using type (maybe you should try that now!) and found that the data type is 'bool'. What does that mean?\n",
"\n",
"Boolean algebra is a logical system in which statements take on one of two truth values - True and False. Statements can be combined into new statements using logical operators:\n",
"1. (a and b) is true if both a and b are true, otherwise it is false\n",
"2. (a or b) is true if one or both of a and b are true, false if both are false\n",
"3. (not a) is true if a is false, otherwise false\n",
"\n",
"These three operators work as-is in Python. For example, when does:\n",
"\n",
" (a==b) or ((not (c>=d))\n",
"\n",
"return True and when does it return False? Work the answer out on paper (write it down!) then check some values in Python."
]
},
{
"cell_type": "code",
"execution_count": 119,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######Excercise: elif else\n",
"\n",
"An If statement can be used to control whether or not a block of code is executed. What if we want to switch between two possibilities? For this, we need else statements. They look like this:\n",
"\n",
" if (condition):\n",
" do this stuff only if condition is met\n",
" else:\n",
" do this stuff only if condition is not met\n",
"\n",
"If we want to check multiple conditions, we can use elif (else if):\n",
"\n",
" if (first condition):\n",
" do this stuff only if first condition is met\n",
" elif (second condition):\n",
" do this stuff only if second condition but not first condition is met\n",
" elif (third condition):\n",
" do this stuff only if third condition but not first or second condition is met\n",
"\n",
"Write a code snippet that tests whether a numerical value is in one of several intervals (you chose how many, but should be >=3). Note that if-elif-else tests conditions in order. Might this ever matter?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######Problem: xor\n",
"\n",
"The xor (exclusive or) operator takes two arguments and returns True if one and only one argument is True, returning False otherwise. Complete the below function so that it implements xor for boolean arguments a,b"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def xor(a,b):\n",
" \n",
" return result"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######Problem: nand\n",
"\n",
"The nand (not and) operator takes two arguments and returns True if and only if at least one is False. Complete the below function so that it implements nand for boolean arguments a,b"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def nand(a,b):\n",
" \n",
" return result"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######Problem: Divisible by?\n",
"Write a function that takes two integer arguments $a$ and $b$. If $a$ is evenly divisible by $b$ return $True$ and the quotient of $\\frac{a}{b}$. If not, return $False$ and the quotient and remainder of $\\frac{a}{b}$."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"###1.1 For\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######Excercise: Counting to n (safely)\n",
"\n",
"In programming, a loop is a tool that causes code to be repeatedly executed. The Python for loop needs a variable, an iterable value (like a list) and an indented block of code:\n",
"\n",
" for variableName in iterableName:\n",
" do this stuff on each iteration\n",
"\n",
"The code in the indented block is executed once for each element in iterableName. On the first iteration, variableName is assigned the value of the first element in iterableName. At the beginning of each new iteration, variableName takes on the vlue of the next element in iterableName. This might be made clearer by the following code snippet, which counts to n:\n",
"\n",
" for ct in range(n):\n",
" print ct\n",
"\n",
"Run this code for an n of your choice. Then modify it so that its output is stored in the elements of a new list. Can you make a simple change so that the elements of this new list are strings rather than integers (hint: the function str converts a numerical value to a string)?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######Problem: Fibonacci list\n",
"Write a function that takes an integer argument $n$ and returns a list containing the $1^{st}$ through $n^{th}$ terms of the Fibonacci sequence.\n",
"\n",
"Hint: The $n^{th}$ term of the Fibonacci sequence, which we will call $F_n$, is $F_n = F_{n-1}+F_{n-2}$. $F_0 = 0$, $F_1 = 1$\n",
"\n",
"Hint: Your function need not call itself"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#2. Numpy"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"###2.0 The numpy ndarray\n",
"The generality of python lists makes them useful, but it also makes them slow and sometimes painful to use for numerical computations. Fortunately we have access to a data type that is specific to numerical computation.\n",
"\n",
"Numpy is a module - not part of the standard library, but frequently distributed - that focuses on a specific data type called the numpy ndarray. Before we use this data type we must import numpy. I assume that you will use the following code:\n",
"\n",
" import numpy as np"
]
},
{
"cell_type": "code",
"execution_count": 120,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######Excercise: Making ndarrays\n",
"\"ndarray\" means n-dimensional array. An array is just an ordered collection of numbers, where each number is specified by n indices. We will start with $n=1$. In such cases, we call the array a vector. We can make a numpy vector easily out of a numerical list by typing:\n",
"\n",
" numpyVector = np.array(aList)\n",
"\n",
"We can also use:\n",
"\n",
" numpyVector = np.arange(start,stop,step)\n",
"\n",
"just like we used range to make a list. But this is old hat. What about two-dimensional arrays? We call arrays with dimension 2 or greater \"matrices\" and we can make them out of lists of lists:\n",
"\n",
" twoByTwo = np.array([[1,2],[3,4]])\n",
"\n",
"This creates a two-by-two (rows-by-columns) matrix. Verify this! Try altering the placement of the values. Can you make a larger or smaller array? Does the number of rows have to equal the number of columns?\n",
"\n",
"...\n",
"\n",
"We may sometimes want to make special arrays. To make an array of all zeros, use:\n",
"\n",
" twoBytwo = np.zeros((2,2))\n",
" fourByTwobySix = np.zeros((4,2,6))\n",
" \n",
"and so on (The inner parentheses are not a mistake). What if you want a square matrix (equal number of rows and columns) with ones on the diagonal, and zeros elsewhere? Use:\n",
"\n",
" twoBytwo = np.eye(2)\n",
"\n",
"Try these with dimensions of your choice."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######Excercise: Slicing ndarrays\n",
"We can slice numpy ndarrays just like lists - though we have to pay attention to matrix slicing. If we have a two-dimensional matrix and we want to get the value at the $m^{th}$ row and $n^{th}$ column (counting from the top left), we type:\n",
"\n",
" twoDArray[m,n]\n",
"\n",
"If we wanted to get the $m^{th}$ row and all columns, we would type:\n",
"\n",
" twoDArray[m,:]\n",
"\n",
"We could also get the $m^{th}$ row and the $0^{th}$ through ${n-1}^{th}$ columns:\n",
"\n",
" twoDArray[m,:n]\n",
"\n",
"or the $m^{th}$ row and the $n^{th}$ and all following columns:\n",
"\n",
" twoDArray[m,n:]\n",
"\n",
"Try these out."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######Excercise: Some useful methods\n",
"A method is a function that requires a specific kind of data. Numpy comes with a bunch of useful methods for ndarrays. To use a method, we type:\n",
"\n",
" variableName.methodName(arguments)\n",
"\n",
"For example, to sum a numpy array, type:\n",
"\n",
" arrayName.sum(axis=0) # 0 is the \"row\" axis in a 2d matrix, 1 is the \"column axis\"\n",
" \n",
"You can take the average of a numpy array much like you take the sum:\n",
"\n",
" arrayName.mean(axis=0) # 0 is the \"row\" axis in a 2d matrix, 1 is the \"column axis\"\n",
"\n",
"len will work on vectors, but for matrices we need a new function:\n",
"\n",
" arrayName.shape()\n",
"\n",
"This will return the dimensions of arrayName. We can also flip the last two dimensions of an array (mostly useful for 2d arrays, where it switches rows and columns):\n",
"\n",
" arrayName.transpose() # This is better seen than explained. Try it out\n",
"\n",
"Say we have a 1x6 array, but would prefer a 3x2 array. We can use reshape as long as the total number of elements does not change:\n",
"\n",
" threeByTwo = twoByThree.reshape((3,2))\n",
"\n",
"If we have two arrays and we just want to stick them together, we can use concatenate:\n",
"\n",
" stuckTogether = np.concatenate((a,b),axis=1)\n",
"\n",
"This will join a and b along axis 1 (columns). The dimensions of a and b must agree in all axes but the one in which they are joined.\n",
"\n",
"All of these functions really need to be tried to be understood. Make matrices and take some time trying to figure out how using these functions alters those matrices."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You might find it useful to take the maximum or minimum values of an ndarray. To do so, use:\n",
"\n",
" maxVal = np.amax(anArray)\n",
" minVal = np.amin(anArray)\n",
" \n",
"amax and amin will flatten multidimensional arrays - meaning that they will find the maximum or minimum value in the whole array. To find maximum or minimum values along a specific axis of an ndarray, use the axis argument:\n",
"\n",
" maxValRow = np.amax(a2dArray,axis=0) # this is the row-wise maximum\n",
" maxValCol = np.amax(a2dArray,axis=1) # this is the column-wise maximum\n",
" \n",
"If you want the indices of the maximum or minimum values, use:\n",
"\n",
" maxInd = np.argmax(anArray)\n",
" minInd = np.argmin(anArray)\n",
" \n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"###2.1 Fast linear algebra"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######Excercise: Elementwise operations\n",
"So, what can we *do *with ndarrays? The most basic kind of operation is to add or multiply (or subtract or divide) a single number (called a \"scalar\") to/by each element in the array. you can do this with the + and \\* operators:\n",
"\n",
" a = 5\n",
" b = np.zeros((5))\n",
" a+b\n",
"\n",
"If two vectors or matrices have the same shape, you can use these operators to add or multiply the elements to/by those in the other. This is done in the most straghtforward way: If we type:\n",
"\n",
" C = A*B\n",
"\n",
"The element at C[m,n] = A[m,n]\\*B[m,n]\n",
"\n",
"Write down two matrices on paper and give this a shot. Then check your work with numpy."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######Excercise: Matrix-vector multiplication\n",
"\n",
"Matrix-vector multiplication is a useful and important operation. It works like this:\n",
"$$\n",
"\\begin{bmatrix}\n",
"a_{11} & a_{12}& \\dots & a_{1n} \\\\\n",
"a_{21} & a_{22}& \\dots & a_{2n} \\\\\n",
"\\vdots & \\vdots & \\ddots & \\vdots \\\\\n",
"a_{m1} & a_{m2} & \\dots & a_{mn}\n",
"\\end{bmatrix}\n",
"\\times\n",
"\\begin{bmatrix}\n",
"b_{1}\\\\\n",
"b_{2}\\\\\n",
"\\vdots\\\\\n",
"b_m\n",
"\\end{bmatrix}\n",
"=\n",
"\\begin{bmatrix}\n",
"b_{1}*a_{11}+b_2+a_{12}...+b_n*a_{1n}\\\\\n",
"b_{1}*a_{21}+b_2+a_{22}...+b_n*a_{2n}\\\\\n",
"\\vdots\\\\\n",
"b_{1}*a_{m1}+b_2+a_{m2}...+b_n*a_{mn}\n",
"\\end{bmatrix}\n",
"$$\n",
"That's the general case, but an example might be clearer:\n",
"$$\n",
"\\begin{bmatrix}\n",
"1 & 2 \\\\\n",
"3 & 4\n",
"\\end{bmatrix}\n",
"\\times\n",
"\\begin{bmatrix}\n",
"5\\\\\n",
"6\\\\\n",
"\\end{bmatrix}\n",
"=\n",
"\\begin{bmatrix}\n",
"1*5+2*6\\\\\n",
"3*5+4*6\n",
"\\end{bmatrix}\n",
"$$\n",
"One way to picture this is to imagine rotating the vector, laying it over all the rows of the matrix, taking the elementwise product on each row, then summing across rows.\n",
"\n",
"It is important to remember a couple of things about matrix multiplication:\n",
"1. If you are want to multiply an $m\\times $ matrix by a $p\\times $ vector, $n$ must equal $p$. Likewise, to multiply a $1\\times p$ vector by an $m\\times n$ matrix, $p$ must equal $m$. This leads to the second point, that...\n",
"2. Matrix-vector multiplication is not commutative! When multiplying scalars, $a\\times =b\\times a$. This is not true of matrix-vector multiplication.\n",
"\n",
"Now would be a good time to break out a pen and some paper and try multiplying some matrices and vectors by hand. In particular, what happens if the matrix has ones on the central diagonal and zeros elsewhere?\n",
"\n",
"...\n",
"\n",
"So why bother with this? You are familiar with the $(x,y)$ notation for describing points in Cartesian space. If we can describe a point in $n$-dimensional space using $n$ numbers, then we can treat a length $n$ vector as specifying a point $n$-dimensional space. This lets us treat matrices as transformations of points in space - mapping points onto other points according to some rule. For instance, imagine we want to define a transformation that will rotate 2d points by an angle $\\theta$ counterclockwise about the origin? This:\n",
"$$\n",
"\\begin{bmatrix}\n",
"\\cos \\theta & -\\sin \\theta \\\\\n",
"\\sin \\theta & \\cos \\theta\n",
"\\end{bmatrix}\n",
"\\times\n",
"\\begin{bmatrix}\n",
"x\\\\\n",
"y\\\\\n",
"\\end{bmatrix}\n",
"$$\n",
"...will rotate the point $(x,y)$ by an angle $\\theta$ about the origin. If you have ever rotated an image in photoshop, that was how it was done. There are many possible transformations, but hopefully you are convinced that at least one is useful.\n",
"\n",
"How can we do this in python? If we are dealing with a 2d numpy array ($m\\times n$) and a length $n$ column vector, just do:\n",
"\n",
" a = np.array([[1,2],[3,4]])\n",
" b = np.array([5,6])\n",
" np.dot(a,b)\n",
" \n",
"Use this to verify the calculations that you did ny hand earlier in this excercise."
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######Problem: The hard way\n",
"Write a function that carries out matrix-vector multiplication using loops. Time your code as it multiplies some large matrices. Compare the elapsed time to that required by numpy.\n",
"\n",
"hint: The standard library module time contains a function (also confusingly called \"time()\") that returns o=your cpu clock time as a float. You can use this to time a section of code."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"###2.2 Random numbers"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######Excercise: Generating random numbers\n",
"Computers do not really generate random numbers. Instead, they produce highly unpredictable (\"psuedorandom\") numbers by taking an arbitrary value (like the number of cpu clock cycles your computer has completed) called the \"seed\" and running it through a hard-to-predict function. Psuedorandom numbers are enough for most purposes. If you want a random number drawn from the interval $[0,1)$, type:\n",
"\n",
" np.random.rand()\n",
" \n",
"The number you get from this is drawn from the uniform distribution, meaning that each value in the interval $[0,1)$ is equally likely (and values outside this interval impossible). Can you think of a way to draw a uniform random number from the interval $[0,10)$? What about $[5,10)$? Try multiplying or adding to the results of np.random.rand().\n",
"\n",
"We are not limited to drawing just one random number at a time. To populate an ndarray with uniform random numbers, enter the dimensions of the ndarray as arguments to the rand function. For instance, you can make a $3\\times2$ random matrix by typing:\n",
"\n",
" np.random.rand(3,2)\n",
" \n",
"Debugging your code may be easier if you first derandomize it so that it always produces the same outputs. To do that, you will need to set the seed value manually\n",
"\n",
" np.random.seed(4) # or whatever seed value you want\n",
" \n",
"Now the values you get from np.random.rand() will be fixed. What are the first three values you get after calling np.random.seed(4)?\n",
"\n",
"Once you have fixed the seed, it will stay that way until you change it or quit python. To get an arbitrary seed again, use:\n",
"\n",
" np.random.seed() # with no arguments\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"###2.3 Looking at numpy arrays"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######Excercise: plot\n",
"\n",
"We will use a module called pyplot in order to look at numpy arrays. We import it like this:\n",
"\n",
" import matplotlib.pyplot as plt\n",
" \n",
"The simplest thing we can do with this is make a line plot of an ndarray. Suppose we have a (1-dimensional) ndarray of x values and another ndarray of y values. Then we can make an y(x) plot by typing:\n",
"\n",
" plt.plot(x,y) # of course, x and y must be the same length\n",
" \n",
"This will produce a plot object, but not display it. To show your plots, put\n",
"\n",
" plt.show()\n",
" \n",
"after you are done with plotting. If you want to have your plots show up in this notebook (recommended) rather than in seperate windows, enter\n",
"\n",
" %matplotlib inline\n",
"\n",
"This is an ipython command - it holds for the entire notebook after you enter it once.\n",
"\n",
"If you want to gussy up your plots, you can use:\n",
"\n",
" plt.title(\"I am a title!\")\n",
" plt.xlabel(\"I am a label on the x-axis!\")\n",
" plt.ylabel(\"I am a label on the y-axis!\")\n",
" \n",
"It is a good habit to label all of your plots, even the ones that you don't think you will ever show to anyone.\n",
"\n",
"Before you go on, try:\n",
"1. making a basic plot\n",
"2. using the plot function with just the y argument\n",
"3. using the plot function twice in a row\n",
"\n",
"The behavior seen in 3 is surely useful for comparisons, but you might want to avoid it sometimes. To do that, type\n",
"\n",
" figureName,axisName = plt.subplots()\n",
" # some plotting stuff here\n",
" \n",
"This lets you make multiple figures (change figureName for each one). Try it out. If you check the documentation, you will see a ton of additional options for controlling color, line width, and other parameters of the plot. Those are optional, but if you want to give them a shot, feel free."
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######Excercise: bar\n",
"\n",
"Line graphs are nice and all, but sometimes they don't really make sense. If you have categorical data, for instance, you will want a bar chart. You can make one by typing:\n",
"\n",
" plt.bar(indices, values)\n",
" \n",
"try this."
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######Excercise: pcolor\n",
"\n",
"Sometimes it is helpful to look at a 2d matrix as an image. To do this, type\n",
"\n",
" plt.pcolor(a2dMatrix)\n",
" \n",
"try this out with some matrices - in particular make one with np.eye and another with np.random.rand. \n",
"\n",
"One advantage of this method vs printing is that you can use it to get a look at really big matrices. A disadvantage is that you can't see the individual values as easily. One way to mitigate that issue is by making a colorbar\n",
"\n",
" plt.colorbar()\n",
" \n",
"This is like a legend that maps colors to values."
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"######Problem: Dice\n",
"Part 1: Write a function that takes two integer arguments $n$ and $k$. Your function should virtually \"roll\" a k-sided die n times, then return a numpy array whose elements are the result of each roll in order.\n",
"\n",
"Part 2: Imagine that we want to know the probability of rolling a particular sum on two six-sided dice. Write a program that repreatedly rolls dice and then make a bar chart of the fraction of times each sum comes up."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"###2.4 (sort of) Saving things\n",
"It is helpful to be able to store your data in a file, so that it does not go away when you quit python. To do that, you will want the cPickle module\n",
"\n",
" import cPickle as pickle\n",
" \n",
"Then you can save a variable to a file by typing:\n",
"\n",
" pickle.dump( variableName, open( \"fileName.p\", \"wb\" ) )\n",
" \n",
"To load this later, use:\n",
"\n",
" newVariableName = pickle.load( open( \"fileName.p\", \"rb\" ) )\n",
" \n",
"Try it out. The file you save to will appear in the current directory (where this notebook is)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": []
}
],
"metadata": {},
"nbformat": 4,
"nbformat_minor": 0
}