Solutions
Contents
Solutions#
Question 1#
1
. Use the class created in Tutorial to find the roots of the following quadratics:
1
. \(f(x) = -4x ^ 2 + x + 6\)
First we define the class:
import math
class QuadraticExpression:
"""A class for a quadratic expression"""
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
self.discriminant = self.b ** 2 - 4 * self.a * self.c
def get_roots(self):
"""
Return the real valued roots of the quadratic expression
Returns
-------
array
The roots of the quadratic
"""
if self.discriminant >= 0:
x1 = -(self.b + math.sqrt(self.discriminant)) / (2 * self.a)
x2 = -(self.b - math.sqrt(self.discriminant)) / (2 * self.a)
return x1, x2
return ()
def __add__(self, other):
"""A magic method: let's us have addition between expressions"""
return QuadraticExpression(self.a + other.a, self.b + other.b, self.c + other.c)
def __repr__(self):
"""A magic method: changes the default way an instance is displayed"""
return f"Quadratic expression: {self.a} x ^ 2 + {self.b} x + {self.c}"
class QuadraticExpressionWithAllRoots(QuadraticExpression):
"""
A class for a quadratic expression that can return imaginary roots
The `get_roots` function returns two tuples of the form (re, im) where re is
the real part and im is the imaginary part.
"""
def get_roots(self):
"""
Return the real valued roots of the quadratic expression
Returns
-------
array
The roots of the quadratic: each root is represented as an array
of the form (Re, Im).
"""
if self.discriminant >= 0:
x1 = -(self.b + math.sqrt(self.discriminant)) / (2 * self.a)
x2 = -(self.b - math.sqrt(self.discriminant)) / (2 * self.a)
return (x1, 0), (x2, 0)
real_part = self.b / (2 * self.a)
im1 = math.sqrt(-self.discriminant) / (2 * self.a)
im2 = -math.sqrt(-self.discriminant) / (2 * self.a)
return ((real_part, im1), (real_part, im2))
def __add__(self, other):
"""A special method: let's us have addition between expressions"""
return QuadraticExpressionWithAllRoots(
self.a + other.a, self.b + other.b, self.c + other.c
)
Now we use it:
f = QuadraticExpressionWithAllRoots(a=-4, b=1, c=6)
f.get_roots()
((1.356107225224513, 0), (-1.106107225224513, 0))
2
. \(g(x) = 3x^2 - 6\)
g = QuadraticExpressionWithAllRoots(a=3, b=0, c=-6)
g.get_roots()
((-1.414213562373095, 0), (1.414213562373095, 0))
3
. \(h(x) = f(x) + g(x)\)
h = f + g
h.get_roots()
((1.0, 0), (0.0, 0))
## Question 2
2
. Write a class for a Linear expression and use it to find the roots of the following expressions:
1
. \(f(x) = 2x + 6\)
First we define the class:
import math
class LinearExpression:
"""A class for a linear expression a x + b"""
def __init__(self, a, b):
self.a = a
self.b = b
def get_roots(self):
"""
Return the real valued roots of the linear expression
Returns
-------
float
The root of the linear expression.
"""
if self.a != 0:
return -self.b / self.a
return None
def __add__(self, other):
"""A magic method: let's us have addition between expressions"""
return LinearExpression(self.a + other.a, self.b + other.b)
def __repr__(self):
"""A magic method: changes the default way an instance is displayed"""
return f"Linear expression: {self.a} x + {self.b}"
Now we use it:
f = LinearExpression(a=2, b=6)
f.get_roots()
-3.0
2
. \(g(x) = 3x - 6\)
g = LinearExpression(a=3, b=-6)
g.get_roots()
2.0
3
. \(h(x) = f(x) + g(x)\)
h = f + g
h.get_roots()
0.0
Question 3#
3
. If rain drops were to fall randomly on a square of side length \(2r\) the probability of the drops landing in an inscribed circle of radius \(r\) would be given by:
$$
P = \frac{\text{Area of circle}}{\text{Area of square}}=\frac{\pi r ^2}{4r^2}=\frac{\pi}{4}
\[ \begin{align}\begin{aligned}> Thus, if we can approximate $P$ then we can approximate $\pi$ as $4P$. In this
> question we will write code to approximate $P$ using the random library.\\> First create the following class:\\> ```
> class Drop:
> """
> A class used to represent a random rain drop falling on a square of
> length r.
> """
>
> def __init__(self, r=1):
> self.x = (0.5 - random.random()) * 2 * r
> self.y = (0.5 - random.random()) * 2 * r
> self.in_circle = (self.y) ** 2 + (self.x) ** 2 <= r ** 2
> ```\\```{code-cell} ipython3
import random\\
class Drop:
"""
A class used to represent a random rain drop falling on a square of
length r.
"""\\ def __init__(self, r=1):
self.x = (0.5 - random.random()) * 2 * r
self.y = (0.5 - random.random()) * 2 * r
self.in_circle = (self.y) ** 2 + (self.x) ** 2 <= r ** 2
```\\> To approximate $P$ create $N=1000$ instances of Drops and count the
> number of those that are in the circle. Use this to approximate $\pi$.\\We start by creating the required number of drops:\\```{code-cell} ipython3
number_of_instances = 10000
random.seed(0)
drops = [Drop() for number in range(number_of_instances)]
```\\Now we count the number in the circle:\\```{code-cell} ipython3
number_in_circle = len([drop for drop in drops if drop.in_circle])
number_in_circle
```\\The number in the circle leads to the probability $P$:\\```{code-cell} ipython3
P = number_in_circle / number_of_instances
```\\And $\pi$ can be approximated:\\```{code-cell} ipython3
4 * P
```\\## Question 4\\> `4`. In a similar fashion to question 3, approximate the integral
> $\int_{0}^11-x^2\;dx$. Recall that the integral corresponds to the area
> under a curve.\\We create a different drop class changing the `in_circle` attribute to
`under_curve` and simplifying where the `x` and `y` are sampled from.\\```{code-cell} ipython3
class Drop:
"""
A class used to represent a random rain drop falling on a square of
length 1.
"""\\ def __init__(self):
self.x = random.random()
self.y = random.random()
self.under_curve = self.y <= 1 - self.x ** 2
```\\Now we repeat the steps of question 3:\\```{code-cell} ipython3
number_of_instances = 10000
random.seed(0)
drops = [Drop() for number in range(number_of_instances)]
```\\Now we count the number in the circle:\\```{code-cell} ipython3
number_under_curve = len([drop for drop in drops if drop.under_curve])
number_under_curve
```\\In this particular problem the area of the square is 1 so the probability of
being under the curve is equal to the 1: $P=\frac{\int_{0}^11-x^2\;dx}{1}$.\\```{code-cell} ipython3
number_under_curve / number_of_instances
```\\We can confirm this:\\```{code-cell} ipython3
import sympy as sym\\x = sym.Symbol("x")
sym.integrate(1 - x ** 2, (x, 0, 1))
```
\end{aligned}\end{align} \]