Commit 8c6adbca authored by Ben Glocker's avatar Ben Glocker
Browse files

tutorials 5-7

parent ecec7a38
......@@ -615,7 +615,7 @@
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": 2,
"metadata": {
"collapsed": true
},
......@@ -651,7 +651,7 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 3,
"metadata": {
"collapsed": true
},
......@@ -685,7 +685,7 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 4,
"metadata": {},
"outputs": [
{
......@@ -707,14 +707,14 @@
},
{
"cell_type": "code",
"execution_count": 33,
"execution_count": 40,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[973886, 409460, 337342, 398719, 273231, 700388, 243130, 347759, 604817, 319332, 721668, 8793, 485780, 541846, 42575, 77128, 47963, 528511, 342950, 552766]\n"
"[658042, 242361, 863569, 787057, 225873, 237945, 236740, 938816, 355375, 141558, 892528, 211345, 581149, 33164, 158996, 838642, 498178, 151876, 1675, 23323]\n"
]
}
],
......
%% Cell type:markdown id: tags:
# Introduction to Python (for Algorithms 2)
%% Cell type:markdown id: tags:
by *James Booth* and *Ghislain Antony Vaillant*
%% Cell type:markdown id: tags:
### Disclaimer
%% Cell type:markdown id: tags:
This notebook is by no means a comprehensive introduction to the Python programming language. It covers the essential language features required to implement, test and validate the Algorithms 202 courseworks. It is strongly advised to complement this tutorial with additional reading such as the [official Python documentation](https://docs.python.org/3/), [Python 101](https://leanpub.com/python_101) or the excellent [Hitchhiker's guide to Python](http://docs.python-guide.org/en/latest/).
%% Cell type:markdown id: tags:
## Language basics
%% Cell type:markdown id: tags:
### Syntax and features
%% Cell type:markdown id: tags:
#### Hello world
%% Cell type:code id: tags:
``` python
print("Hello, world!")
```
%% Cell type:markdown id: tags:
#### Built-in [functions](https://docs.python.org/3/library/functions.html)
%% Cell type:code id: tags:
``` python
print("Hello, world!")
print("Hello,", "world!")
print("{}, {}!".format("Hello", "world"))
```
%% Cell type:code id: tags:
``` python
help(print)
```
%% Cell type:code id: tags:
``` python
type(1.0)
```
%% Cell type:code id: tags:
``` python
assert(2 % 2 == 0)
#assert(2 / 2 == 0)
```
%% Cell type:markdown id: tags:
#### Built-in [types](https://docs.python.org/3/library/stdtypes.html)
%% Cell type:code id: tags:
``` python
# Booleans
B = True
print(type(B))
# Numeric types
N = 1
print(type(N))
N = 1.0
print(type(N))
N = 1j
print(type(N))
# Strings
N = "Hello, word"
print(type(N))
# Lists
L = [False, 1.0, "Hello"]
print(type(L))
# Ranges
R = range(10)
print(type(R))
# None
print(type(None))
```
%% Cell type:markdown id: tags:
#### Dynamic typing
%% Cell type:code id: tags:
``` python
x = 3 # Defines a binding a variable named "x",
# to an object of type integer with value 3.
print('x is of type {} with value {}'.format(type(x), x))
x = 2.0 # Redefine the binding between "x" and an
# object of type float with value 2.0.
print('x is of type {} with value {}'.format(type(x), x))
```
%% Cell type:markdown id: tags:
#### Strong typing
%% Cell type:code id: tags:
``` python
print(1 + '2') # What is the intent here?
# "Explicit is better than implicit."
```
%% Cell type:code id: tags:
``` python
print(str(1) + '2') # String concatenation.
print(1 + int('2')) # Integer summation.
```
%% Cell type:markdown id: tags:
#### Variables and scopes
%% Cell type:code id: tags:
``` python
a = 0
if False:
b = 1
def my_function(c):
d = 3
print(a) # a is global
print(b) # b is global
print(c) # c is local
print(d) # d is local
my_function(2)
```
%% Cell type:markdown id: tags:
### Control flow
%% Cell type:markdown id: tags:
#### `if` statements
%% Cell type:code id: tags:
``` python
# simple branching
if condition:
do_something()
# 2-way branching
if condition:
do_something()
else:
do_other_thing()
# switch-case style
if condition:
do_something()
elif other_condition:
do_other_thing()
else:
do_default_thing()
```
%% Cell type:markdown id: tags:
#### `while` statements
%% Cell type:code id: tags:
``` python
# loop until
while condition:
do_something()
# loop until with break clause
while condition:
do_something()
if specific_condition:
break # exit while loop regardless
do_other_thing()
# loop until with break clause
while condition:
do_something()
if specific_condition:
continue # loop-back regardless
do_other_thing()
```
%% Cell type:markdown id: tags:
#### `for` statements
%% Cell type:code id: tags:
``` python
for n in range(10):
print(n)
```
%% Cell type:code id: tags:
``` python
numbers = [1, 2, 3]
for number in numbers:
print(number)
```
%% Cell type:code id: tags:
``` python
ingredients = ['carrots', 'leeks', 'potatoes']
for index, ingredient in enumerate(ingredients):
print(index, ingredient)
```
%% Cell type:markdown id: tags:
### Data structures
%% Cell type:markdown id: tags:
#### Common concepts
%% Cell type:code id: tags:
``` python
# literals
vowels = ['a', 'e', 'i', 'o', 'u', 'y']
print('vowels: {}'.format(vowels))
```
%% Cell type:code id: tags:
``` python
# indexing
print('the first vowel is: ' + vowels[0])
print('the last vowel is: ' + vowels[-1])
print('the second-to-last vowel is: ' + vowels[-2])
```
%% Cell type:code id: tags:
``` python
# slicing
print('first three: {}'.format(vowels[:3]))
print('last two: {}'.format(vowels[-2:]))
print('middle ones: {}'.format(vowels[1:-1]))
print('one each two: {}'.format(vowels[::2]))
```
%% Cell type:code id: tags:
``` python
# iteration
for vowel in vowels:
print(vowel.upper())
```
%% Cell type:code id: tags:
``` python
# enumeration
for index, vowel in enumerate(vowels):
print("vowel {} is {}".format(1+index, vowel))
```
%% Cell type:markdown id: tags:
#### Immutable sequences
%% Cell type:code id: tags:
``` python
vowels = ('a', 'e', 'i', 'o', 'u', 'y')
print(type(vowels))
```
%% Cell type:code id: tags:
``` python
vowels[1] = 'b'
```
%% Cell type:markdown id: tags:
#### Mutable sequences
%% Cell type:code id: tags:
``` python
vowels = ['a', 'e', 'i', 'o', 'u', 'y']
print(type(vowels))
```
%% Cell type:code id: tags:
``` python
vowels[1] = 'b'
print(vowels)
```
%% Cell type:markdown id: tags:
#### Dictionaries
%% Cell type:code id: tags:
``` python
# build using literal construct: {k1: v1, k2:v2}
D = {"one": 1,
"two": 2,
"three": 3}
print('D: {}'.format(D))
```
%% Cell type:code id: tags:
``` python
# indexing
print(D["one"])
print(D["two"])
print(D["three"])
```
%% Cell type:code id: tags:
``` python
# iterating
for item in D.items():
print(item)
for key in D.keys():
print(key)
for value in D.values():
print(value)
```
%% Cell type:markdown id: tags:
### Functions
%% Cell type:code id: tags:
``` python
# Standard definiton
def my_function(arg1, arg2):
# Do something with arg1, arg2
# ...
return result
```
%% Cell type:code id: tags:
``` python
# Lambda definition
x_power_x = lambda x: x**x
print(x_power_x(2))
```
%% Cell type:markdown id: tags:
## Application: Complexity analysis of bubble sort
%% Cell type:markdown id: tags:
### Implementation
%% Cell type:code id: tags:
``` python
def bubble_sort(L):
"""
Sorts the input list inplace using a deterministic version of the bubble sort algorithm [1].
[1] https://en.wikipedia.org/wiki/Bubble_sort
"""
max_pass = len(L) - 1
for pass_num in range(max_pass):
for i in range(max_pass-pass_num):
if L[i+1] < L[i]:
L[i], L[i+1] = L[i+1], L[i]
return L
def my_sorted(iterable):
"""
Returns the sorted elements of the iterable as a list.
"""
return bubble_sort(list(iterable))
```
%% Cell type:markdown id: tags:
### Unit testing
%% Cell type:code id: tags:
``` python
test_cases = [
[3, 2, 1, 6, 5, 4],
[6, 5, 4, 3, 2, 1], # Worst case
[1, 3, 2, 4, 6, 5], # One pass required
]
for case in test_cases:
# Validate against built-in sorted
#print(my_sorted(case), sorted(case))
assert(my_sorted(case) == sorted(case))
```
%% Cell type:markdown id: tags:
### Complexity analysis
%% Cell type:markdown id: tags:
#### Data generation
%% Cell type:code id: tags:
``` python
from random import randint
help(randint)
```
%%%% Output: stream
Help on method randint in module random:
randint(a, b) method of random.Random instance
Return random integer in range [a, b], including both end points.
%% Cell type:code id: tags:
``` python
randlist = lambda n: [randint(1e1, 1e6) for i in range(n)]
print(randlist(20))
```
%%%% Output: stream
[973886, 409460, 337342, 398719, 273231, 700388, 243130, 347759, 604817, 319332, 721668, 8793, 485780, 541846, 42575, 77128, 47963, 528511, 342950, 552766]
[658042, 242361, 863569, 787057, 225873, 237945, 236740, 938816, 355375, 141558, 892528, 211345, 581149, 33164, 158996, 838642, 498178, 151876, 1675, 23323]
%% Cell type:markdown id: tags:
#### Timing method
%% Cell type:code id: tags:
``` python
def timed(f, *args, **kwargs):
from time import clock
before = clock()
result = f(*args, **kwargs)
after = clock()
return after-before
# Collect enough time samples
timings = [timed(my_sorted, case) for case in [randlist(6) for n in range(1000)]]
from statistics import mean
print("min = {}, max = {}, mean = {}".format(
min(timings), max(timings), mean(timings)))
```
%%%% Output: stream
min = 3.8399983616006945e-06, max = 0.0001740799257258993, mean = 9.804795816620452e-06
%% Cell type:markdown id: tags:
#### Experiment
%% Cell type:code id: tags:
``` python
sizes = list(range(1, 1000, 100)) + list(range(1000, 10000, 1000))
timings = [timed(my_sorted, case) for case in [randlist(size) for size in sizes]]
```
%% Cell type:markdown id: tags:
#### Plotting
%% Cell type:code id: tags:
``` python
%matplotlib inline
import matplotlib.pyplot as plt
# Uncomment for details about the plot function
#help(plt.plot)
```
%% Cell type:code id: tags:
``` python
plt.plot(sizes, timings, linewidth=4)
plt.xlabel('size')
plt.ylabel('time (s)')
plt.xlim(0)
plt.ylim(0)
```
%%%% Output: execute_result
(0, 16.67753193491971)
%%%% Output: display_data
%% Cell type:markdown id: tags:
#### Fitting
%% Cell type:code id: tags:
``` python
from numpy import polyfit
# Uncomment for details about polyfit
#help(polyfit)
poly = polyfit(sizes, timings, deg=2)
```
%% Cell type:code id: tags:
``` python
from numpy import polyval
# Uncomment for details about polyval
#help(polyval)
fitted = polyval(poly, sizes)
```
%% Cell type:code id: tags:
``` python
plt.plot(sizes, timings, '-', linewidth=4)
plt.plot(sizes, fitted, '--', linewidth=4)
plt.xlabel('size')
plt.ylabel('time (s)')
plt.xlim(0)
plt.ylim(0)
```
%%%% Output: execute_result
(0, 17.591113768918017)
%%%% Output: display_data
%% Cell type:markdown id: tags:
### Going further
%% Cell type:markdown id: tags:
- Provide an alternative implementation of bubble sort with the optimization tricks explained in the Wikipedia article.
- Modify the `my_sorted` function to allow users to choose between the deterministic and the optimized implementations. By default, `my_sorted` should still be using the determinisitic version.
- Run the experiment above with the optimized bubble sort implementation.
- Compare the deterministic and optimized implementations with a plot.
- Draw some conclusions from this analysis.
......
......@@ -4,7 +4,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"# CO202 - Software Engineering - Algorithms"
"# CO202 - Algorithms 2"
]
},
{
......@@ -23,9 +23,18 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 4,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"55\n",
"54.9 µs ± 10.4 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)\n"
]
}
],
"source": [
"def naive_fib(n):\n",
" if n == 0:\n",
......@@ -48,9 +57,18 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 5,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"55\n",
"4.13 µs ± 285 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)\n"
]
}
],
"source": [
"def dp_fib(n):\n",
" if n == 0:\n",
......@@ -82,8 +100,10 @@
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"execution_count": 6,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import time\n",
......@@ -104,12 +124,14 @@
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"execution_count": 11,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"data = range(1,20)\n",
"#data = range(1,30)\n",
"#data = range(1,20)\n",
"data = range(1,30)\n",
"#data = range(1,1000,10)\n",
"#data = range(1,10000,100)\n",
"#data = range(1,100000,1000)"
......@@ -124,8 +146,10 @@
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"execution_count": 12,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"tdc = []\n",
......@@ -143,8 +167,10 @@
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"execution_count": 13,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"tdp = []\n",
......@@ -162,9 +188,30 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 14,
"metadata": {},
"outputs": [],
"outputs": [
{
"data": {
"text/plain": [
"(0, 0.6281491025812429)"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\ngg==\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x1e64afc2eb8>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%matplotlib inline\n",
"from matplotlib import pyplot as plt\n",
......
%% Cell type:markdown id: tags:
# CO202 - Software Engineering - Algorithms
# CO202 - Algorithms 2
%% Cell type:markdown id: tags:
## Tutorial on Dynamic Programming: Fibonacci
%% Cell type:markdown id: tags:
### Naive Divide-and-Conquer Approach
%% Cell type:code id: tags:
``` python
def naive_fib(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return naive_fib(n-1) + naive_fib(n-2)
print(naive_fib(10))
%timeit naive_fib(10)
```
%%%% Output: stream
55
54.9 µs ± 10.4 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%% Cell type:markdown id: tags:
### Bottom-up Dynamic Programming Approach
%% Cell type:code id: tags:
``` python
def dp_fib(n):
if n == 0:
return 0
f = [0]*(n+1)
f[0] = 0
f[1] = 1
for i in range(2,n+1):
f[i] = f[i-1] + f[i-2]
return f[n]
print(dp_fib(10))
%timeit dp_fib(10)
```
%%%% Output: stream
55
4.13 µs ± 285 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%% Cell type:markdown id: tags:
### Comparison
%% Cell type:markdown id: tags:
#### Timer
%% Cell type:code id: tags:
``` python
import time
def time_f(f):
before = time.clock()
f()
after = time.clock()
return after - before
```
%% Cell type:markdown id: tags:
#### Test data
%% Cell type:code id: tags:
``` python
data = range(1,20)
#data = range(1,30)
#data = range(1,20)
data = range(1,30)
#data = range(1,1000,10)
#data = range(1,10000,100)
#data = range(1,100000,1000)
```
%% Cell type:markdown id: tags:
#### Running Divide-and-Conquer
%% Cell type:code id: tags:
``` python
tdc = []
for i in data:
tdc.append(time_f(lambda: naive_fib(i)))
```
%% Cell type:markdown id: tags:
#### Running Dynamic Programming
%% Cell type:code id: tags:
``` python
tdp = []
for i in data:
tdp.append(time_f(lambda: dp_fib(i)))
```
%% Cell type:markdown id: tags:
#### Plot DC vs DP
%% Cell type:code id: tags:
``` python
%matplotlib inline
from matplotlib import pyplot as plt
plt.scatter(data, tdc, c='red')
plt.scatter(data, tdp, c='blue')
plt.xlabel('n')
plt.ylabel('time (/s)')
plt.xlim(0)
plt.ylim(0)
```
%%%% Output: execute_result
(0, 0.6281491025812429)
%%%% Output: display_data
%% Cell type:code id: tags:
``` python
```
......
This diff is collapsed.
This diff is collapsed.
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# CO202 - Algorithms 2"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Tutorial on Randomised Algorithms: Approximating Pi"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import numpy as np\n",
"\n",
"def approximate_pi(samples):\n",
" n = len(samples)\n",
" m = np.sum(np.sqrt(np.sum(np.multiply(samples,samples),axis=1)) <= 1)\n",
" return 4*m/n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def monte_carlo_pi(num_samples, num_runs): \n",
" a_pi = 0 \n",
" for _ in range(num_runs):\n",
" samples = np.random.rand(num_samples, 2) * 2 - 1\n",
" a_pi = a_pi + approximate_pi(samples)\n",
" return a_pi / num_runs\n",
"\n",
"print(monte_carlo_pi(100,1000))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Visualisation"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib inline\n",
"from matplotlib import pyplot as plt\n",
"\n",
"\n",
"samples_100 = np.random.rand(100, 2) * 2 - 1\n",
"samples_1000 = np.random.rand(1000, 2) * 2 - 1\n",
"samples_10000 = np.random.rand(10000, 2) * 2 - 1\n",
"\n",
"flag_100 = np.sqrt(np.sum(np.multiply(samples_100,samples_100),axis=1)) <= 1;\n",
"samples_in_circle_100 = samples_100[flag_100, :]\n",
"\n",
"flag_1000 = np.sqrt(np.sum(np.multiply(samples_1000,samples_1000),axis=1)) <= 1;\n",
"samples_in_circle_1000 = samples_1000[flag_1000, :]\n",
"\n",
"flag_10000 = np.sqrt(np.sum(np.multiply(samples_10000,samples_10000),axis=1)) <= 1;\n",
"samples_in_circle_10000 = samples_10000[flag_10000, :]\n",
"\n",
"\n",
"pi_100 = approximate_pi(samples_100)\n",
"pi_1000 = approximate_pi(samples_1000)\n",
"pi_10000 = approximate_pi(samples_10000)\n",
"\n",
"fig, axs = plt.subplots(1, 3, figsize=(18,5))\n",
"axs[0].scatter(samples_100[:,0], samples_100[:,1], marker='o')\n",
"axs[0].scatter(samples_in_circle_100[:,0], samples_in_circle_100[:,1], color='red')\n",
"axs[0].set_title('100 samples. ~pi: {}'.format(pi_100))\n",
"axs[1].scatter(samples_1000[:,0], samples_1000[:,1], marker='o')\n",
"axs[1].scatter(samples_in_circle_1000[:,0], samples_in_circle_1000[:,1], color='red')\n",
"axs[1].set_title('1000 samples. ~pi: {}'.format(pi_1000))\n",
"axs[2].scatter(samples_10000[:,0], samples_10000[:,1], marker='o')\n",
"axs[2].scatter(samples_in_circle_10000[:,0], samples_in_circle_10000[:,1], color='red')\n",
"axs[2].set_title('10000 samples. ~pi: {}'.format(pi_10000))\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Comparison"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib inline\n",
"from matplotlib import pyplot as plt\n",
"from time import clock\n",
"\n",
"# a timer - runs the provided function and reports the\n",
"# run time in ms\n",
"def time_f(f):\n",
" before = clock()\n",
" f()\n",
" after = clock()\n",
" return after - before\n",
"\n",
"t1, t2, t3, t4, t5 = [], [], [], [], []\n",
"n = 20\n",
"for _ in range(n):\n",
" t1.append(time_f(lambda: monte_carlo_pi(100,10000)))\n",
" t2.append(time_f(lambda: monte_carlo_pi(1000,1000)))\n",
" t3.append(time_f(lambda: monte_carlo_pi(10000,100)))\n",
" t4.append(time_f(lambda: monte_carlo_pi(100000,10)))\n",
" t5.append(time_f(lambda: monte_carlo_pi(1000000,1)))\n",
"\n",
"# Plot both merge and insertion against each other\n",
"plt.scatter(range(n), t1, marker='x', c='r', label='100/10000')\n",
"plt.scatter(range(n), t2, marker='x', c='b', label='1000/1000')\n",
"plt.scatter(range(n), t3, marker='x', c='y', label='10000/100')\n",
"plt.scatter(range(n), t4, marker='x', c='g', label='100000/10')\n",
"plt.scatter(range(n), t5, marker='x', c='k', label='1000000/1')\n",
"plt.legend(loc='upper left')\n",
"plt.xlim((0, n))\n",
"plt.ylim((0, max(max(t1), max(t2), max(t3), max(t4), max(t5))))\n",
"plt.xlabel('n')\n",
"plt.ylabel('time /s')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib inline\n",
"from matplotlib import pyplot as plt\n",
"\n",
"e1, e2, e3, e4, e5 = [], [], [], [], []\n",
"n = 20\n",
"for _ in range(n):\n",
" e1.append(np.abs(np.pi - monte_carlo_pi(100,10000)))\n",
" e2.append(np.abs(np.pi - monte_carlo_pi(1000,1000)))\n",
" e3.append(np.abs(np.pi - monte_carlo_pi(10000,100)))\n",
" e4.append(np.abs(np.pi - monte_carlo_pi(100000,10)))\n",
" e5.append(np.abs(np.pi - monte_carlo_pi(1000000,1)))\n",
"\n",
"# Plot both merge and insertion against each other\n",
"plt.scatter(range(n), e1, marker='x', c='r', label='100/10000')\n",
"plt.scatter(range(n), e2, marker='x', c='b', label='1000/1000')\n",
"plt.scatter(range(n), e3, marker='x', c='y', label='10000/100')\n",
"plt.scatter(range(n), e4, marker='x', c='g', label='100000/10')\n",
"plt.scatter(range(n), e5, marker='x', c='k', label='1000000/1')\n",
"plt.legend(loc='upper left')\n",
"plt.xlim((0, n))\n",
"plt.ylim((0, max(max(e1), max(e2), max(e3), max(e4), max(e5))))\n",
"plt.xlabel('n')\n",
"plt.ylabel('error')\n",
"\n",
"print(np.mean(e1))\n",
"print(np.mean(e2))\n",
"print(np.mean(e3))\n",
"print(np.mean(e4))\n",
"print(np.mean(e5))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.2"
}
},
"nbformat": 4,
"nbformat_minor": 1
}
%% Cell type:markdown id: tags:
# CO202 - Algorithms 2
%% Cell type:markdown id: tags:
## Tutorial on Randomised Algorithms: Approximating Pi
%% Cell type:code id: tags:
``` python