Student's Name: PLEASE INSERT YOUR NAME HERE (DOUBLE CLICK THIS BOX TO EDIT.)

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

Check your work. I give some tests that should be passed if you get it correct.

**Your notebook should run without printing errors and without user input. If this is not the case, points will be deducted from your grade.**

Problem Sources:

**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 numpy as np
import matplotlib.pyplot as plt
import math as m
```

A geometric series is a series with a constant ratio $r$ between successive terms. Let $c$ be the first term in the series. Then the *geometric series* with ratio $r$ and first term $c$ is
$$c + cr + cr^2 + cr^3+\ldots=\sum_{k=0}^\infty c r^k.$$

Write a function `geometric_partial_sum(c, r, N)`

that returns the sum of the first $N$ terms of this series. That is, you should return
$$\sum_{k=0}^{N-1} c r^k.$$
You should work with floats. The test included is insufficient. Test your code!

In [ ]:

```
# Tests
x = geometric_partial_sum(1, 0.5, 2)
assert abs(x - (1+ 1/2))<2**-50, "This series sum (1, 0.5, 2) is incorrect."
# Tests
x = geometric_partial_sum(5, 2, 3)
assert abs(x - (5+10+20))<2**-50, "This series sum (5, 2, 3) is incorrect."
```

It is well known that if $|r|<1$, then the geometric series converges and satisfies $$\frac{c}{1-r} = \sum_{k=0}^\infty c r^k.$$ You probably learned this in calculus.

Write a function `geometric_terms_needed(c, r, epsilon)`

that takes as input a constant $c$, an $r$ satisfying $|r|<1$, and an $\epsilon>0$. The function should returns the smallest number of terms $N$ such that the remainder is less than $\epsilon$ in absolute value.

In [ ]:

```
# Tests
c = 1
r = 0.5
epsilon = 0.0001
N = geometric_terms_needed(c,r,epsilon)
remainder = 2 - geometric_partial_sum(c, r, N)
assert abs(remainder) < epsilon, "Remainder is not small enough."
remainder = 2 - geometric_partial_sum(c, r, N-1)
assert abs(remainder) >= epsilon, "Previous remainder is not big enough."
```

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$? 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}$.

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 [ ]:

```
# Some tests you should pass.
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.

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 [ ]:

```
# 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!"
```

For $n \geq 1$, let $a_n = \frac{2}{n(n+1)(n+2)}$. And consider the series $$\sum_{n=1}^\infty a_n = \sum_{n=1}^\infty \frac{2}{n(n+1)(n+2)}.$$

Write a function `partial_sum_3`

which takes as input an integer $N \geq 1$ and computes the partial sum consisting of the sum of the first $N$ terms in the series. Use Python floats for computing the series.

In [ ]:

```
# Some basic tests
assert abs(partial_sum_3(1) - 2/6) < 2**-50, \
"The first partial sum is wrong."
assert abs(partial_sum_3(2) - (2/6+2/24)) < 2**-50, \
"The second partial sum is wrong."
```

Print out the first 10 partial sums in the following format:

`Partial sum 1 is 0.3333333333333333`

`Partial sum 2 is 0.41666666666666663`

`...`

Conjecture the limit $L$ and store the value in the variable `limit_prob_4`

. Recall that the *$N$-th remainder* is the difference $L-S_N$ where $S_N$ is the $N$-th partial sum $S_N$. Print out the first 10 values of the conjectured remainder in the following format:

`Remainder 1 is ?.??????????????????`

`...`

Conjecture a formula for the remainder. (*Hint:* You may also want to print the reciprocals of the remainders.) Give a rigorous inductive proof of this formula in a Markdown cell in the notebook. (Including a picture of your hand-written proof is okay.)

Explain why the proof of your remainder formula implies that your conjecture for the limit is correct.

For $s > 1$, the Reimann zeta function is given by the convergent series
$$\zeta(s)=\sum_{n=1}^\infty \frac{1}{n^s}=\frac{1}{1^s}+\frac{1}{2^s}+\frac{1}{3^s}\ldots.$$
In the `Series`

notebook, we calculated that $\zeta(2)=\frac{\pi^2}{6}$. Now we will approximate $\zeta(3)$.

Let $b_n=\frac{1}{n^3}$. Then $\zeta(3)=\sum_{n=1}^\infty b_n$. Define the partial sum and remainder $$S'_N=\sum_{n=1}^N b_n \quad \text{and} \quad R'_N=\sum_{n=N+1}^\infty b_n.$$

For $n$ large enough, find indices $l(n)$ and $u(n)$ such that $$a_{l(n)} \leq 2 b_n \leq a_{u(n)},$$ where $a_k = \frac{2}{k(k+1)(k+2)}$ as in the problems above. Use these inequalities to find lower and upper bounds for $R'_N$ in terms of the sequence of remainders $R_N$ from the series $\sum a_k$. Include a Markdown cell explaining what you have found.

Use your results to write a function `zeta_3(epsilon)`

which takes as input a positive real number $\epsilon>0$ and returns a pair consisting of a lower bound $L$ and an upper bound $U$ for $\zeta(3)$ such that $U-L \leq \epsilon$. You may use floats and ignore the effects of round off error.

(*Remark.* To return a pair $(L,U)$ you can use the statement `return (L,U)`

at the end of your function.)

In [ ]:

```
# Some simple tests
L,U = zeta_3(0.001)
assert type(L)==float, "The lower bound should be a float."
assert type(U)==float, "The upper bound should be a float."
assert L<=U, "The lower bound should be smaller than the upper bound."
assert U-L<=0.001, "The gap should be smaller than 0.001."
```