Commit e8fbb0e5 authored by Ben Glocker's avatar Ben Glocker
Browse files

updated fibonacci challenge

parent f3f53c84
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
# CO202 - Software Engineering - Algorithms # CO202 - Software Engineering - Algorithms
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
## Fibonacci Challenge: Dynamic Programming vs. Divide-and-Conquer ## Fibonacci Challenge: Dynamic Programming vs. Divide-and-Conquer
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### DP Fibonacci - Bottom-up (space efficient) ### DP Fibonacci - Bottom-up (space efficient)
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
def fib_dp_bottom_up(n): def fib_dp_bottom_up(n):
if n == 0: if n == 0:
return 0 return 0
f = [0]*(n+1) f = [0]*(n+1)
f[0] = 0 f[0] = 0
f[1] = 1 f[1] = 1
for i in range(2,n+1): for i in range(2,n+1):
f[i] = f[i-1] + f[i-2] f[i] = f[i-1] + f[i-2]
return f[n] return f[n]
print(fib_dp_bottom_up(10)) print(fib_dp_bottom_up(10))
%timeit fib_dp_bottom_up(10) %timeit fib_dp_bottom_up(10)
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
def fib_dp_bottom_up(n): def fib_dp_bottom_up(n):
i,j = 1,0 i,j = 1,0
for k in range(1,n + 1): for k in range(1,n + 1):
i,j = j, i + j i,j = j, i + j
return j return j
print(fib_dp_bottom_up(10)) print(fib_dp_bottom_up(10))
%timeit fib_dp_bottom_up(10) %timeit fib_dp_bottom_up(10)
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### DP Fibonacci - Top-down with Memoization ### DP Fibonacci - Top-down with Memoization
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
m = {0: 0, 1: 1} m = {0: 0, 1: 1}
def fib_dp_top_down(n): def fib_dp_top_down(n):
m.clear() m.clear()
m[0] = 0 m[0] = 0
m[1] = 1 m[1] = 1
return fib_dp_top_down_aux(n) return fib_dp_top_down_aux(n)
def fib_dp_top_down_aux(n): def fib_dp_top_down_aux(n):
if n not in m: if n not in m:
m[n] = fib_dp_top_down_aux(n-1) + fib_dp_top_down_aux(n-2) m[n] = fib_dp_top_down_aux(n-1) + fib_dp_top_down_aux(n-2)
return m[n] return m[n]
print(fib_dp_top_down_aux(10)) print(fib_dp_top_down_aux(10))
%timeit fib_dp_top_down(10) %timeit fib_dp_top_down(10)
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### D&C Fibonacci ### D&C Fibonacci
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
import math import math
def fib_dc(n): def fib_dc(n):
if n == 0: if n == 0:
return 0 return 0
elif n == 1: elif n == 1:
return 1 return 1
else: else:
a = fib_dc(math.ceil(n / 2)) a = fib_dc(math.ceil(n / 2))
b = fib_dc(math.ceil(n / 2) - 1) b = fib_dc(math.ceil(n / 2) - 1)
if n % 2 == 0: if n % 2 == 0:
return a * (a + 2 * b) return a * (a + 2 * b)
else: else:
return a * a + b * b return a * a + b * b
print(fib_dc(10)) print(fib_dc(10))
%timeit fib_dc(10) %timeit fib_dc(10)
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### D&C Fast Fibonacci (v1) - provided by Jacek Burys ### D&C Fast Fibonacci (v1) - provided by Jacek Burys
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
import numpy as np import numpy as np
dt = np.int64 dt = np.int64
def fib_dc_fast(n): def fib_dc_fast(n):
init = np.matrix([[1], [0]], dtype=dt )
transform = matrix_pow(np.matrix([[1,1],[1,0]], dtype=dt), n) transform = matrix_pow(np.matrix([[1,1],[1,0]], dtype=dt), n)
return (transform * init).item(1) return transform[0,1]
def matrix_pow(m, n): def matrix_pow(m, n):
if n == 0: if n == 0:
return np.matrix([[1,0],[0,1]], dtype=dt) return np.matrix([[1,0],[0,1]], dtype=dt)
if n == 1: if n == 1:
return m return m
temp = matrix_pow(m, n // 2) temp = matrix_pow(m, n // 2)
if n % 2 == 0: if n % 2 == 0:
return temp * temp return temp * temp
else: else:
return temp * temp * m return temp * temp * m
print(fib_dc_fast(10)) print(fib_dc_fast(10))
%timeit fib_dc_fast(10) %timeit fib_dc_fast(10)
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### D&C Fast Fibonacci (v2) ### D&C Fast Fibonacci (v2)
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
def fib_dc_fast2(n): def fib_dc_fast2(n):
init = [1,0]
transform = matrix_pow2([1,1,1,0], n) transform = matrix_pow2([1,1,1,0], n)
return matrix_vec_mul(transform,init)[1] return transform[1]
def matrix_pow2(m, n): def matrix_pow2(m, n):
if n == 0: if n == 0:
return [1,0,0,1] return [1,0,0,1]
if n == 1: if n == 1:
return m return m
temp = matrix_pow2(m, n // 2) temp = matrix_pow2(m, n // 2)
if n % 2 == 0: if n % 2 == 0:
return matrix_mul(temp,temp) return matrix_mul(temp,temp)
else: else:
return matrix_mul(matrix_mul(temp,temp),m) return matrix_mul(matrix_mul(temp,temp),m)
def matrix_vec_mul(m,v): def matrix_vec_mul(m,v):
r = [0]*2 r = [0]*2
r[0] = m[0]*v[0] + m[2] * v[1] r[0] = m[0]*v[0] + m[2] * v[1]
r[1] = m[1]*v[0] + m[3] * v[1] r[1] = m[1]*v[0] + m[3] * v[1]
return r return r
def matrix_mul(m1,m2): def matrix_mul(m1,m2):
r = [0]*4 r = [0]*4
r[0] = m1[0]*m2[0] + m1[2] * m2[1] r[0] = m1[0]*m2[0] + m1[2] * m2[1]
r[1] = m1[1]*m2[0] + m1[3] * m2[1] r[1] = m1[1]*m2[0] + m1[3] * m2[1]
r[2] = m1[0]*m2[2] + m1[2] * m2[3] r[2] = m1[0]*m2[2] + m1[2] * m2[3]
r[3] = m1[1]*m2[2] + m1[3] * m2[3] r[3] = m1[1]*m2[2] + m1[3] * m2[3]
return r return r
print(fib_dc_fast2(10)) print(fib_dc_fast2(10))
%timeit fib_dc_fast2(10) %timeit fib_dc_fast2(10)
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### Closed form expression - Binet's formula ### Closed form expression - Binet's formula
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
import math import math
def fib_binet(n): def fib_binet(n):
f = (1 + math.sqrt(5))/2 f = (1 + math.sqrt(5))/2
return (f**n - (-f)**-n)/math.sqrt(5) return (f**n - (-f)**-n)/math.sqrt(5)
print(fib_binet(10)) print(fib_binet(10))
%timeit fib_binet(10) %timeit fib_binet(10)
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### Sanity check ### Sanity check
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
n = 500 n = 500
print("DP Bottom-up\t" + str(fib_dp_bottom_up(n))) print("DP Bottom-up\t" + str(fib_dp_bottom_up(n)))
print("DP Top-down\t" + str(fib_dp_top_down(n))) print("DP Top-down\t" + str(fib_dp_top_down(n)))
print("D&C\t\t" + str(fib_dc(n))) print("D&C\t\t" + str(fib_dc(n)))
print("D&C Fast\t" + str(fib_dc_fast(n))) print("D&C Fast\t" + str(fib_dc_fast(n)))
print("D&C Fast v2\t" + str(fib_dc_fast2(n))) print("D&C Fast v2\t" + str(fib_dc_fast2(n)))
print("Binet\t\t" + str(int(fib_binet(n)))) print("Binet\t\t" + str(int(fib_binet(n))))
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### Comparison ### Comparison
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
import time import time
def time_f(f): def time_f(f):
before = time.clock() before = time.clock()
f() f()
after = time.clock() after = time.clock()
return after - before return after - before
n_max = 10000 n_max = 10000
samples = 50 samples = 50
step = int(n_max/samples) step = int(n_max/samples)
data = range(1,n_max,step) data = range(1,n_max,step)
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
t1 = [] t1 = []
for i in data: for i in data:
t1.append(time_f(lambda: fib_dp_bottom_up(i))) t1.append(time_f(lambda: fib_dp_bottom_up(i)))
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
t2 = [] t2 = []
for i in data: for i in data:
t2.append(time_f(lambda: fib_dc(i))) t2.append(time_f(lambda: fib_dc(i)))
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
%matplotlib inline %matplotlib inline
from matplotlib import pyplot as plt from matplotlib import pyplot as plt
plt.scatter(data, t1, c='green') plt.scatter(data, t1, c='green')
plt.scatter(data, t2, c='red') plt.scatter(data, t2, c='red')
plt.xlabel('n') plt.xlabel('n')
plt.ylabel('time (/s)') plt.ylabel('time (/s)')
plt.legend(['dp bottom-up','d&c'],loc='upper left') plt.legend(['dp bottom-up','d&c'],loc='upper left')
plt.xlim(0) plt.xlim(0)
plt.ylim(0) plt.ylim(0)
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
t3 = [] t3 = []
for i in data: for i in data:
t3.append(time_f(lambda: fib_dc_fast2(i))) t3.append(time_f(lambda: fib_dc_fast2(i)))
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
%matplotlib inline %matplotlib inline
from matplotlib import pyplot as plt from matplotlib import pyplot as plt
plt.scatter(data, t1, c='green') plt.scatter(data, t1, c='green')
plt.scatter(data, t2, c='red') plt.scatter(data, t2, c='red')
plt.scatter(data, t3, c='blue') plt.scatter(data, t3, c='blue')
plt.xlabel('n') plt.xlabel('n')
plt.ylabel('time (/s)') plt.ylabel('time (/s)')
plt.legend(['dp bottom-up','d&c','d&c fast'],loc='upper left') plt.legend(['dp bottom-up','d&c','d&c fast'],loc='upper left')
plt.xlim(0) plt.xlim(0)
plt.ylim(0) plt.ylim(0)
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
n_max = 1000000 n_max = 1000000
samples = 50 samples = 50
step = int(n_max/samples) step = int(n_max/samples)
data = range(1,n_max,step) data = range(1,n_max,step)
t3 = [] t3 = []
for i in data: for i in data:
t3.append(time_f(lambda: fib_dc_fast2(i))) t3.append(time_f(lambda: fib_dc_fast2(i)))
%matplotlib inline %matplotlib inline
from matplotlib import pyplot as plt from matplotlib import pyplot as plt
plt.scatter(data, t3, c='blue') plt.scatter(data, t3, c='blue')
plt.xlabel('n') plt.xlabel('n')
plt.ylabel('time (/s)') plt.ylabel('time (/s)')
plt.legend(['d&c fast'],loc='upper left') plt.legend(['d&c fast'],loc='upper left')
plt.xlim(0) plt.xlim(0)
plt.ylim(0) plt.ylim(0)
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
``` ```
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment