INSERT YOUR NAME HERE

**Directions:** Add work to this notebook to solve the problems below.

Be careful to name the objects you create as described in the problem. Some problems may include some tests you can run to test your code.

Before you submit your work, make sure it runs correctly without errors. Click “Kernel > Restart & Run All” to restart and run everything.

Some problems are derived from problems in these books:

**LL**:*Programming for Computations - Python*by Svein Linge and Hans Petter Langtangen, 2nd edition.**L**:*A Primer on Scientific Programming with Python*by Hans Petter Langtangen, 2nd edition.**TAK**:*Applied Scientific Computing With Python*by Peter R. Turner, Thomas Arildsen, and Kathleen Kavanagh.

In [ ]:

```
import math as m
```

The function $cosh(x) = \frac{e^x + e^{-x}}{2}$ is analytic with Taylor series
$$\cosh x = 1 + \frac{x^2}{2!} + \frac{x^4}{4!} + \ldots = \sum_{k=0}^\infty \frac{x^{2k}}{(2k)!}$$
What degree Taylor polynomial is needed to estimate $\cosh(1/2)$ with a truncation error less than $\epsilon>0$? Use Taylor's Theorem to figure this out how to decide this. Write a function `cosh_half_degree(epsilon)`

that returns this degree. Write a second function `cosh_half(epsilon)`

that returns the value of the degree $d$ Taylor polynomial evaluated at $\frac{1}{2}$, where $d$ is the value returned by `cosh_half_degree(epsilon)`

.

Check that your answer achieves the desired accuracy with $\epsilon=10^{-8}$ by comparing your answer to the value of $cosh(\frac{1}{2})$ returned by the `cosh`

function in the math library (i.e., `m.cosh(0.5)`

).

(This is similar to Problem 5 from Chapter 2 of TAK.)

In [ ]:

```
```

**Tests for your code:**

In [ ]:

```
assert type(cosh_half_degree(0.1)) == int, "cosh_half_degree should return an integer."
assert type(cosh_half(0.5)) == float, "cosh_half should return a float."
```

Write a function `exp_poly`

which takes as input a degree $d$ and returns a function that evaluates the Taylor polynomial of degree $d$ for the exponential function centered at zero. (You should use closures as described in the *Plotting Graphs* notebook.)

Check your answers against the first few Taylor polnomials by hand.

(*Hint:* You are asked to do something similar to the `sin_polynomial`

function in the Taylor Series notebook.)

In [ ]:

```
```

**Tests for your code:**

In [ ]:

```
# Define $p$ to be the Taylor polynomial of degree 1:
p = exp_poly(1)
# Note that the Taylor polynomial should be p(x)=x+1
assert p(5.5)==6.5, "Unexpected result!"
```

Let $f:{\mathbb R} \to {\mathbb R}$ be a infinitely differentiable function with the property that the derivative of any order $n \geq 1$ satisfies $-1 \leq f^{(n)}(x) \leq 1$ for each $x \in {\mathbb R}$. We will consider the Taylor series of $f$ centered at zero. Let $P_d(x)$ be the degree $d$ Taylor polynomial centered at zero.

By Taylor's theorem, the remainder, $R_d(x) = f(x) - P_d(x),$ always has the form $$R_d(x)=\frac{f^{(d+1)}(y)}{(d+1)!} x^{d+1},$$ for some $y$ between $0$ and $x$.

Using the information above, write a function `minimal_degree(x, epsilon)`

which takes as input a float $x$ and a float $\epsilon>0$ and returns the smallest $d$ for which it can be guaranteed that
$$|R_d(x)|<\epsilon.$$

In [ ]:

```
```

**Tests for your code:**

In [ ]:

```
# We test some cases with x=2:
assert minimal_degree(2, 3) == 0, \
"Wrong answer when x=2 and epsilon=3"
assert minimal_degree(2, 1.5) == 2, \
"Wrong answer when x=2 and epsilon=1.5"
assert minimal_degree(2, 1) == 3, \
"Wrong answer when x=2 and epsilon=1"
assert minimal_degree(2, 0.5) == 4, \
"Wrong answer when x=2 and epsilon=0.5"
```

Consider the approximation
$$f'(x_0)\approx \frac{f(x_0+h) - f(x_0)}{h}$$
for the case of $f(x)=\ln x$ at the point $x_0=1$. Compute the approximation with $h=10^{-k}$ for $k \in \{1,\ldots, 10\}$.
Store the results in a list `approx1`

. (So, `approx1[3]`

should be the computation with $h=10^{-4}$.)

Do the same for the approximation
$$f'(x_0)\approx \frac{f(x_0+h) - f(x_0-h)}{2h},$$
storing the result in `approx2`

.

The absolute error is the difference of an approximation from the actual value. Store the list of errors in the first case in `error1`

and the list of errors in the second case in `error2`

.

Discuss based on your computations what the best approximation is, and what the best choice of $h$ seems to be.

(This problem was based on Problems 1 and 4 from TAK § 3.2)

In [ ]:

```
```

**Tests for your code:**

In [ ]:

```
assert type(approx1)==list, "Error: approx1 should be a list."
assert len(approx1)==10, "Error: approx1 should have 10 elements."
assert type(approx2)==list, "Error: approx2 should be a list."
assert len(approx2)==10, "Error: approx2 should have 10 elements."
assert type(error1)==list, "Error: error1 should be a list."
assert len(error1)==10, "Error: error1 should have 10 elements."
assert type(error2)==list, "Error: error2 should be a list."
assert len(error2)==10, "Error: error2 should have 10 elements."
assert abs(approx1[0] - m.log(1.1)/0.1) < 10**-8, "approx1[0] is incorrect."
```

Repeat the previous exercise (*Comparing approximations for the derivative*), this time comparing approximations for the second derivative. For `approx3`

use
$$f''(x_0) \approx \frac{f(x_0+h) - 2 f(x_0) + f(x_0-h)}{h^2}.$$
for `approx4`

use
$$f''(x_0) \approx \frac{-f(x_0+2h) + 16 f(x_0+h) - 30 f(x_0) + 16 f(x_0-h) - f(x_0-2h)}{12 h^2}.$$

Use the same function $f(x)=\ln x$ at the point $x_0=1$ and same values of $h$ as before. Also compute the corresponding lists of errors `error3`

and `error4`

.

Explain which approximation is better and what the best choice of $h$ is.

In [ ]:

```
```

**Tests for your code:**

In [ ]:

```
# Tests:
assert type(approx3)==list, "Error: approx1 should be a list."
assert len(approx3)==10, "Error: approx1 should have 10 elements."
assert type(approx4)==list, "Error: approx2 should be a list."
assert len(approx4)==10, "Error: approx2 should have 10 elements."
assert type(error3)==list, "Error: error1 should be a list."
assert len(error3)==10, "Error: error1 should have 10 elements."
assert type(error4)==list, "Error: error2 should be a list."
assert len(error4)==10, "Error: error2 should have 10 elements."
assert abs(approx3[0] - -1.0050335853501344) < 10**-8, "approx1[0] is incorrect."
```

The `time_position`

list below contains pairs $(t, p)$ consisting of the the time $t$ (in seconds) and position $p$ (in meters) of a drone. (The drone is moving within a line.) Estimate its signed velocity and acceleration for times $t \in \{2,4,6,8,10\}$. Place the pairs $(t,v)$ where $v$ is the estimated velocity in order in a list `velocity`

. Similarly, place the pairs $(t,a)$ where $a$ is the estimated acceleration in a list `acceleration`

.

(This is Problem 8 from TAK § 3.2.)

In [1]:

```
time_position = [(0,0.7),(2,1.9),(4,3.7),(6,5.3),(8,6.3), \
(10,7.4),(12,8.0)]
for t,pos in time_position:
print("At {} seconds, the drone is at position {} meters." \
.format(t,pos))
```

In [ ]:

```
```

**Tests for your code:**

In [ ]:

```
# For printing out your answers:
for t,v in velocity:
print("At {} seconds, the drone's velocity is approximately {:.3f} m/s." \
.format(t,v))
for t,a in acceleration:
print("At {} seconds, the drone's acceleration is approximately {:.3f} m/s^2." \
.format(t,a))
```

In [ ]:

```
# Tests
assert type(velocity)==list, "Error: velocity should be a list."
assert len(velocity)==5, "Error: velocity should have 5 elements."
assert len(velocity[0])==2, "Error: each member of velocity should be a pair."
assert type(acceleration)==list, "Error: acceleration should be a list."
assert len(acceleration)==5, "Error: acceleration should have 5 elements."
assert len(acceleration[0])==2, "Error: each member of acceleration should be a pair."
```