In this notebook, we will cover variables in Python, Numpy arrays, and plotting with Matplotlib.

We will mostly be following Chapter 1 of *Programming for Computations - Python* by Svein Linge and Hans Petter Langtangen.

Variables can be assigned values with the `=`

operator.

In [1]:

```
x = 3
```

The variable keeps the same value until it is changed by the program.

In [2]:

```
print(x)
```

In math the statement `x=x+1`

is always False (assuming `x`

is a real number). In Python, it means that the program should first compute the value of `x+1`

and then store it in the variable `x`

. This results in `4`

being stored in `x`

.

In [3]:

```
x = x+1
print(x)
```

Note that variables can store more than just numbers. Here, we store and add two strings (which concatenates).

In [4]:

```
s1 = "We are using "
s2 = "Python to compute."
print(s1+s2)
```

Here we store a 4-tuple in v.

In [5]:

```
v = (1,2,3,4)
print(v)
```

Tuples are not quite vectors, for example, `3*v`

is three copies of `v`

concatenated.

In [6]:

```
3*v
```

Out[6]:

Addition concatenates:

In [7]:

```
v + (5,6)
```

Out[7]:

You can access the individual entries using the form `v[i]`

where `i`

runs from zero up through one less than the number of entries in `v`

. For example the 4th entry can be obtained by:

In [8]:

```
v[3]
```

Out[8]:

We'll come back to discussing tuples later in the course.

Numpy is the main numerical math package. It has support for vectors and matrices that Python lacks.

You load Numpy with the command:

In [9]:

```
import numpy as np # standard way of importing numpy
```

Now commands in the Numpy package can be called with the syntax `np.command`

.

(The text after `#`

above is a comment and is ignored by Python.)

In lieu of tuples, we can use numpy arrays for vectors. For example:

In [10]:

```
v = np.array([1,2,3,4])
v
```

Out[10]:

In [11]:

```
3*v
```

Out[11]:

In [12]:

```
v+v
```

Out[12]:

Computing `cos(v)`

with `cos`

from the math package will fail, but numpy has its own cosine function which evaluates termwise. So, `np.cos(v)`

will compute
$$(\cos 1, \cos 2, \cos 3, \cos 4).$$

In [13]:

```
np.cos(v)
```

Out[13]:

You can type `np.`

and press the Tab key to see what commands are available. Then you can type `np.abs?`

and Shift-Enter (for example) to see the documentation of a command.

You can import Mathplotlib's pyplot using:

In [14]:

```
import matplotlib.pyplot as plt
```

In [15]:

```
x = np.array([-2, -1, 0, 1, 2])
```

We'll plot the points $(x_i,y_i)$ where $x_i$ is in the list above and $y_i=x_i^2-1$. Arithmetic in arrays is done component wise. So the following list gives the y-values:

In [16]:

```
y = x*x-1
y
```

Out[16]:

The following gives a plot of the points $(x_i, y_i)$:

In [17]:

```
plt.plot(x, y, 'ro')
plt.show()
```

The string 'ro' above indicates that this is a list plot: The `o`

indicates to plot points, and the `r`

indicates to plot in red. Other options for plotting can be found by typing `plt.plot?`

and Shift+Enter. You need to scroll down to the bottom of the Notes section to see a complete description of the `fmt`

string. Alternately take a look at the api posted to the matplotlib website.

In [18]:

```
plt.show(plt.plot(x, y))
```

To get a nicer curve, we should use more points. The following gives 101 points equally spaced between -2 and 2:

In [19]:

```
x = np.linspace(-2, 2, 101) # 1001 might be better than 101...
x
```

Out[19]:

In [20]:

```
y = x*x-1
```

In [21]:

```
plt.plot(x, y)
plt.show()
```

Here is a nicer plot:

In [22]:

```
x = np.linspace(-2, 2, 101)
y = x*x-1
plot3 = plt.plot(x, y,'g')
plt.xlabel('$x$') # The dollar signs denote LaTeX.
plt.ylabel('$y$')
plt.title('The graph of $y=x^2-1$')
plt.grid(True)
plt.show()
```

The plot command can also plot several functions at once. You just repeat the notation inside of `plt.plot()`

twice. For example:

In [23]:

```
plt.plot(x, 2*x, 'r', x, 4-2*x**2, 'g')
plt.grid(True)
plt.show()
```

There is also no reason that the x-values have to be equally spaced. Here is an example.

In [24]:

```
theta_values = np.linspace(0, 2*np.pi, 100)
plt.plot(np.cos(theta_values), np.sin(theta_values))
plt.show()
```

Because of the aspect ratio, the circle looks like an ellipse. The following corrects this.

In [25]:

```
theta_values = np.linspace(0, 2*np.pi, 100)
plt.axes().set_aspect(1)
plt.plot(np.cos(theta_values), np.sin(theta_values))
plt.show()
```

I think it is good to introduce the idea of simple python functions for mathematics. (In programming, there is another related notion of function.)

The following represents the function $f(x)=x^3-x$.

In [26]:

```
def f(x):
return x**3 - x
```

The function can act on numbers:

In [27]:

```
f(1)
```

Out[27]:

In [28]:

```
f(2)
```

Out[28]:

It also can be used for plotting.

In [29]:

```
x_values = np.linspace(-1.5, 1.5, 100)
```

In [30]:

```
plt.plot(x_values, f(x_values))
plt.show()
```

Functions don't need to simply return numbers, they can return any Python object. In particular, a function can return a function. Here is an example of *currying*, when a function returns a function.

The Gaussian with expected value $m$ and variation $s$ is given by the formula $$f(x)=\frac{1}{s \sqrt{2 \pi}} \exp \left(-\frac{1}{2} \left(\frac{x-m}{s}\right)^2\right).$$

In [31]:

```
from numpy import sqrt, exp, pi
def gaussian(m, s):
def f(x):
return exp(-0.5 * ((x-m)/s)**2)/(sqrt(2*pi)*s)
return f
```

Note that `gaussian`

returns the function `f`

, and the function `f`

can make use of the variables `m`

and `s`

that were passed to Gaussian.

The following gives the gaussian with $m=0$ and $s=2$.

In [32]:

```
g = gaussian(0, 2)
```

Then we can evaluate $g$ like a normal function.

In [33]:

```
g(1)
```

Out[33]:

The following plots the Gaussian.

In [34]:

```
x_values = np.linspace(-10, 10, 100)
plt.plot(x_values, g(x_values))
plt.show()
```