### Computing for Mathematics - 2020/2021 individual coursework

**Important** Do not delete the cells containing: 

```
### BEGIN SOLUTION

### END SOLUTION
```

write your solution attempts in those cells.

To submit this notebook:

- Change the name of the notebook from `main` to: `<student_number>`. For example, if your student number is `c1234567` then change the name of the notebook to `c1234567`.
- **Write all your solution attempts in the correct locations**;
- **Do not delete** any code that is already in the cells;
- Save the notebook (`File>Save As`);
- Follow the instructions given in class/email to submit.

#### Question 1

(__Hint__: This question is similar to the [first exercise of the Probability chapter of Python for mathematics](https://vknight.org/pfm/tools-for-mathematics/06-probability/exercises/main.html#exercises).)

For each of the following, write a function `sample_experiment`, and repeatedly use it to simulate the probability of an event occurring with the following chances.

For each chance **output** the simulated probability.

a. $0$ 

_Available marks: 2_


```python
import random

def sample_experiment():
    ### BEGIN SOLUTION
    """
    Returns true if a random number is less than 0
    """
    return random.random() < 0


number_of_experiments = 1000
sum(
    sample_experiment() for repetition in range(number_of_experiments)
) / number_of_experiments
### END SOLUTION
```




    0.0




```python
q1_a_answer = _
q1_a_expected_answer = 0
feedback_text = """Your output is not the expected answer
"""
assert q1_a_answer == q1_a_expected_answer, feedback_text
```


```python
feedback_text = """You did not include a docstring. This is important to help document your code.


It is done  using triple quotation marks. For example:

def get_remainder(m, n):
    \"\"\"
    This function returns the remainder of m when dividing by n
    \"\"\"
    …

Using that it's possible to access the docstring,
one way to do this is to type: `get_remainder?`
(which only works in Jupyter) or help(get_remainder).

We can also comment code using `#` but this is completely
ignored by Python so cannot be accessed in the same way.

"""
try:
    assert  sample_experiment.__doc__ is not None, feedback_text
except NameError:
    assert False, "You did not create a function called `sample_experiment`"
```

b. $1/2$

_Available marks: 2_


```python
def sample_experiment():
    ### BEGIN SOLUTION
    """
    Returns true if a random number is less than 1 / 2
    """
    return random.random() < 1 / 2


number_of_experiments = 1000
sum(
    sample_experiment() for repetition in range(number_of_experiments)
) / number_of_experiments
### END SOLUTION
```




    0.527




```python
import numpy as np

q1_b_answer = _
q1_b_expected_answer = 1 / 2
feedback_text = """Your output is not within an acceptable range of the expected answer
"""
assert q1_b_expected_answer * .75 <= q1_b_answer <= q1_b_expected_answer * 1.25, feedback_text
```


```python
feedback_text = """You did not include a docstring. This is important to help document your code.


It is done  using triple quotation marks. For example:

def get_remainder(m, n):
    \"\"\"
    This function returns the remainder of m when dividing by n
    \"\"\"
    …

Using that it's possible to access the docstring,
one way to do this is to type: `get_remainder?`
(which only works in Jupyter) or help(get_remainder).

We can also comment code using `#` but this is completely
ignored by Python so cannot be accessed in the same way.

"""
try:
    assert  sample_experiment.__doc__ is not None, feedback_text
except NameError:
    assert False, "You did not create a function called `sample_experiment`"
```

c. $3/4$

_Available marks: 2_


```python
def sample_experiment():
    ### BEGIN SOLUTION
    """
    Returns true if a random number is less than 3 / 4
    """
    return random.random() < 3 / 4


number_of_experiments = 1000
sum(
    sample_experiment() for repetition in range(number_of_experiments)
) / number_of_experiments
### END SOLUTION
```




    0.763




```python
q1_c_answer = _
q1_c_expected_answer = 3 / 4
feedback_text = """Your output is not within an acceptable range of the expected answer
"""
assert q1_c_expected_answer * .75 <= q1_c_answer <= q1_c_expected_answer * 1.25, feedback_text
```


```python
feedback_text = """You did not include a docstring. This is important to help document your code.


It is done  using triple quotation marks. For example:

def get_remainder(m, n):
    \"\"\"
    This function returns the remainder of m when dividing by n
    \"\"\"
    …

Using that it's possible to access the docstring,
one way to do this is to type: `get_remainder?`
(which only works in Jupyter) or help(get_remainder).

We can also comment code using `#` but this is completely
ignored by Python so cannot be accessed in the same way.

"""
try:
    assert  sample_experiment.__doc__ is not None, feedback_text
except NameError:
    assert False, "You did not create a function called `sample_experiment`"
```

d. $1$

_Available marks: 2_


```python
def sample_experiment():
    ### BEGIN SOLUTION
    """
    Returns true if a random number is less than 1
    """
    return random.random() < 1

number_of_experiments = 1000
sum(
    sample_experiment() for repetition in range(number_of_experiments)
) / number_of_experiments
### END SOLUTION
```




    1.0




```python
q1_d_answer = _
q1_d_expected_answer = 1
feedback_text = """Your output is not the expected answer
"""
assert q1_d_answer == q1_d_expected_answer, feedback_text
```


```python
feedback_text = """You did not include a docstring. This is important to help document your code.


It is done  using triple quotation marks. For example:

def get_remainder(m, n):
    \"\"\"
    This function returns the remainder of m when dividing by n
    \"\"\"
    …

Using that it's possible to access the docstring,
one way to do this is to type: `get_remainder?`
(which only works in Jupyter) or help(get_remainder).

We can also comment code using `#` but this is completely
ignored by Python so cannot be accessed in the same way.

"""
try:
    assert  sample_experiment.__doc__ is not None, feedback_text
except NameError:
    assert False, "You did not create a function called `sample_experiment`"
```

### Question 2


(__Hint__: This question is similar to the [second exercise of the Combinatorics chapter of Python for mathematics](https://vknight.org/pfm/tools-for-mathematics/05-combinations-permutations/exercises/main.html).)

a. Create a variable `number_of_permutations` that gives the number of permutations of `pets = ("cat", "dog", "fish", "lizard", "hamster)` of size 4. Do this by generating and counting them.

_Available marks: 2_


```python
import itertools

pets = ("cat", "dog", "fish", "lizard", "hamster")

### BEGIN SOLUTION
permutations = tuple(itertools.permutations(pets, 4))
number_of_permutations = len(permutations)
### END SOLUTION
```


```python
expected_number_of_permutations = 120
feedback = "The expected answer is 120"

try:
    assert expected_number_of_permutations == number_of_permutations, feedback
except NameError:
    assert False, "You did not create a variable called `number_of_permutations`"
```

b. Create a variable `direct_number_of_permutations` that gives the number of permutations of `pets` of size 4 by direct computation.

_Available marks: 1_


```python
import scipy.special

### BEGIN SOLUTION
direct_number_of_permutations = scipy.special.perm(5, 4)
### END SOLUTION
```


```python
expected_number_of_permutations = 120
feedback = "The expected answer is 120"

try:
    assert expected_number_of_permutations == direct_number_of_permutations, feedback
except NameError:
    assert False, "You did not create a variable called `direct_number_of_permutations`"
```

### Question 3

(__Hint__: This question uses concepts from the [Algebra](https://vknight.org/pfm/tools-for-mathematics/02-algebra/how/main.html) and [Calculus](https://vknight.org/pfm/tools-for-mathematics/03-calculus/how/main.html) chapters of Python for mathematics.)

Consider the second derivative $f''(x)=4 x + \cos(x)$.

a. Create a variable `derivative` which has value $f'(x)$ (use the variables `x` and `c1` if necessary):

_Available marks: 3_


```python
import sympy as sym


x = sym.Symbol("x")
c1 = sym.Symbol("c1")
### BEGIN SOLUTION
second_derivative = 4 * x + sym.cos(x)
derivative = sym.integrate(second_derivative, x) + c1
### END SOLUTION
```


```python
feedback_text = """`derivative` is not a symbolic expression.

You are expected to use sympy for this question.
"""
try:
    assert derivative.expand(), feedback_text
except NameError:
    assert False, "You did not create a variable called `derivative`"
```


```python
import sympy as sym
x = sym.Symbol("x")
c1 = sym.Symbol("c1")

expected_answer = c1 + 2 * x ** 2 + sym.sin(x)
feedback_text = f"""Your answer is not correct.

The expected answer is {expected_answer}."""
assert sym.expand(derivative - expected_answer) == 0, feedback_text
```

b. Create a variable `equation` that has value the equation $f'(0)=0$.

_Available marks: 4_


```python
### BEGIN SOLUTION
equation = sym.Eq(derivative.subs({x:0}), 0)
### END SOLUTION
```


```python
expected_lhs = c1
feedback = f"The expected left hand side is {expected_lhs}"
try:
    assert sym.expand(equation.lhs - expected_lhs) == 0, feedback
except AttributeError:
    assert False, "You did not create a symbolic equation"
```


```python
expected_rhs = 0
feedback = f"The expected right hand side is {expected_rhs}. Note that the exact value of pi can be used from the sympy library."
try:
    assert sym.expand(equation.rhs - expected_rhs) == 0, feedback
except AttributeError:
    assert "You did not create a symbolic equation", False
```

c. Using the solution to that equation, output the value of $\int_{0}^{5\pi}f(x)dx$.

_Available marks: 4_


```python
### BEGIN SOLUTION
particular_derivative = derivative.subs({c1: 0})
function = sym.integrate(particular_derivative) + c1
sym.integrate(function, (x, 0, 5 * sym.pi))
### END SOLUTION
```




$\displaystyle 5 \pi c_{1} + \frac{625 \pi^{4}}{6}$




```python
q3_c_answer = _
feedback_text = """your output is not a symbolic expression.

You are expected to use sympy for this question.
"""
assert q3_c_answer.expand(), feedback_text
```


```python
expected_answer = 625 * sym.pi ** 4 / 6
delta = sym.expand((q3_c_answer - expected_answer) / (5 * sym.pi))
feedback_text = f"""The expected answer is: {expected_answer} (up to a constant of integration). 
This is done by substituting the value of c1=pi+1 and then integrating.)

If your we let your answer be Y, so that Y={q3_c_answer}

Then

(Y - {expected_answer}) / (5 pi) should be a constant (with respect to x) but you have:

(Y - {expected_answer}) / (5 pi) = {delta}
"""
assert sym.diff(delta, x) == 0, feedback_text
```

### Question 4

(__Hint__: This question uses concepts from the [Calculus](https://vknight.org/pfm/tools-for-mathematics/03-calculus/how/main.html) and [Sequences](https://vknight.org/pfm/tools-for-mathematics/07-sequences/how/main.html) chapters of Python for mathematics.)

Consider this recursive definition for the sequence $a_n$:

$$
a_n = \begin{cases}
        c & \text{ if n = 1}\\
        3a_{n - 1} + \frac{c}{n}
      \end{cases}
$$


a. Output the sum of the 15 terms.

_Available marks: 5_


```python
c = sym.Symbol("c")
### BEGIN SOLUTION
def get_sequence_a(n):
    """
    Return the sequence a.
    """
    if n == 1:
        return c
    return 3 * get_sequence_a(n - 1) + c / n


sum(get_sequence_a(n) for n in range(1, 16))
### END SOLUTION
```




$\displaystyle \frac{2748995546 c}{315}$




```python
q4_a_answer = _
feedback_text = """your output is not a symbolic expression.

You are expected to use sympy for this question.
"""

assert q4_a_answer.expand(), feedback_text
```


```python
expected_answer = 2748995546 * c / 315
feedback_text = f"The expected answer is: {expected_answer}."
assert sym.expand(q4_a_answer - expected_answer) == 0, feedback_text
```

b. Given that $c=2$ output $\frac{df}{dx}$ where:

$$
f(x) = a_1 + a_2 x + a_3 x ^ 2 + a_4 x ^ 3
$$

_Available marks: 4_


```python
### BEGIN SOLUTION
f = (get_sequence_a(n=1) + get_sequence_a(n=2) * x + get_sequence_a(n=3) * x ** 2 + + get_sequence_a(n=4) * x ** 3).subs({c: 2})
sym.diff(f, x)
### END SOLUTION
```




$\displaystyle \frac{393 x^{2}}{2} + \frac{130 x}{3} + 7$




```python
q4_b_answer = _
feedback_text = """your output is not a symbolic expression.

You are expected to use sympy for this question.
"""

assert q4_b_answer.expand(), feedback_text
```


```python
import sympy as sym
expected_answer = sym.S(393) * x ** 2 / 2 + sym.S(130) * x / 3 + sym.S(7)
feedback_text = f"The expected answer is: {expected_answer}."
assert sym.expand(q4_b_answer - expected_answer) == 0, feedback_text
```

c. Given that $c=2$ output $\int f(x)dx$

_Available marks: 4_


```python
### BEGIN SOLUTION
sym.integrate(f, x)
### END SOLUTION
```




$\displaystyle \frac{131 x^{4}}{8} + \frac{65 x^{3}}{9} + \frac{7 x^{2}}{2} + 2 x$




```python
q4_c_answer = _
feedback_text = """your output is not a symbolic expression.

You are expected to use sympy for this question.
"""

assert q4_c_answer.expand(), feedback_text
```


```python
import sympy as sym

def _get_sequence_a(n):
    """
    Return the sequence a.
    """
    if n == 1:
        return c
    return 3 * _get_sequence_a(n - 1) + c / n

expected_derivative = (_get_sequence_a(n=1) + _get_sequence_a(n=2) * x + _get_sequence_a(n=3) * x ** 2 + _get_sequence_a(n=4) * x ** 3).subs({c: 2})
feedback_text = f"The expected answer is: {sym.integrate(expected_derivative, x)}."
assert sym.expand(sym.diff(q4_c_answer, x) - expected_derivative) == 0, feedback_text
```

6b942749654bebeb60c6887d224b175e4b122120
ipynb
Jupyter Notebook
assets/assessment/2020-2021/ind/main.ipynb
drvinceknight/cfm
06977f5c1ba37590b17a8d2a22f57e3575875b3b
MIT
2016-08-25T01:05:20.000Z
2021-07-04T16:17:06.000Z
assets/assessment/2020-2021/ind/main.ipynb
drvinceknight/cfm
06977f5c1ba37590b17a8d2a22f57e3575875b3b
MIT
2016-08-24T20:08:15.000Z
2021-12-19T23:26:14.000Z
assets/assessment/2020-2021/ind/main.ipynb
drvinceknight/cfm
06977f5c1ba37590b17a8d2a22f57e3575875b3b
MIT
2016-09-22T12:36:03.000Z
2019-03-13T13:21:30.000Z
Qwen/Qwen-72B
1. YES
2. YES