Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Ben Glocker
algo202
Commits
f3f53c84
Commit
f3f53c84
authored
Jan 30, 2018
by
Ben Glocker
Browse files
added fibonacci challenge
parent
8f48c8b2
Changes
1
Hide whitespace changes
Inline
Side-by-side
03-Fibonacci-Challenge.ipynb
0 → 100644
View file @
f3f53c84
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# CO202 - Software Engineering - Algorithms"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Fibonacci Challenge: Dynamic Programming vs. Divide-and-Conquer"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### DP Fibonacci - Bottom-up (space efficient)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def fib_dp_bottom_up(n):\n",
" if n == 0:\n",
" return 0\n",
" f = [0]*(n+1)\n",
" f[0] = 0\n",
" f[1] = 1\n",
" for i in range(2,n+1):\n",
" f[i] = f[i-1] + f[i-2]\n",
" return f[n]\n",
"\n",
"print(fib_dp_bottom_up(10))\n",
"%timeit fib_dp_bottom_up(10)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def fib_dp_bottom_up(n):\n",
" i,j = 1,0\n",
" for k in range(1,n + 1):\n",
" i,j = j, i + j\n",
" return j\n",
"\n",
"print(fib_dp_bottom_up(10))\n",
"%timeit fib_dp_bottom_up(10)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### DP Fibonacci - Top-down with Memoization"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"m = {0: 0, 1: 1}\n",
"def fib_dp_top_down(n):\n",
" m.clear()\n",
" m[0] = 0\n",
" m[1] = 1\n",
" return fib_dp_top_down_aux(n)\n",
"\n",
"def fib_dp_top_down_aux(n):\n",
" if n not in m: \n",
" m[n] = fib_dp_top_down_aux(n-1) + fib_dp_top_down_aux(n-2)\n",
" return m[n]\n",
"\n",
"print(fib_dp_top_down_aux(10))\n",
"%timeit fib_dp_top_down(10)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### D&C Fibonacci"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import math\n",
"\n",
"def fib_dc(n):\n",
" if n == 0:\n",
" return 0\n",
" elif n == 1:\n",
" return 1\n",
" else:\n",
" a = fib_dc(math.ceil(n / 2))\n",
" b = fib_dc(math.ceil(n / 2) - 1)\n",
" if n % 2 == 0:\n",
" return a * (a + 2 * b)\n",
" else:\n",
" return a * a + b * b \n",
" \n",
"print(fib_dc(10))\n",
"%timeit fib_dc(10)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### D&C Fast Fibonacci (v1) - provided by Jacek Burys"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"\n",
"dt = np.int64\n",
"\n",
"def fib_dc_fast(n):\n",
" init = np.matrix([[1], [0]], dtype=dt )\n",
" transform = matrix_pow(np.matrix([[1,1],[1,0]], dtype=dt), n)\n",
" return (transform * init).item(1)\n",
"\n",
"def matrix_pow(m, n):\n",
" if n == 0:\n",
" return np.matrix([[1,0],[0,1]], dtype=dt)\n",
" if n == 1:\n",
" return m\n",
" temp = matrix_pow(m, n // 2)\n",
" if n % 2 == 0:\n",
" return temp * temp\n",
" else:\n",
" return temp * temp * m\n",
" \n",
"print(fib_dc_fast(10))\n",
"%timeit fib_dc_fast(10)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### D&C Fast Fibonacci (v2)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def fib_dc_fast2(n):\n",
" init = [1,0]\n",
" transform = matrix_pow2([1,1,1,0], n)\n",
" return matrix_vec_mul(transform,init)[1]\n",
"\n",
"def matrix_pow2(m, n):\n",
" if n == 0:\n",
" return [1,0,0,1]\n",
" if n == 1:\n",
" return m\n",
" temp = matrix_pow2(m, n // 2)\n",
" if n % 2 == 0:\n",
" return matrix_mul(temp,temp)\n",
" else:\n",
" return matrix_mul(matrix_mul(temp,temp),m)\n",
" \n",
"def matrix_vec_mul(m,v):\n",
" r = [0]*2\n",
" r[0] = m[0]*v[0] + m[2] * v[1]\n",
" r[1] = m[1]*v[0] + m[3] * v[1]\n",
" return r\n",
"\n",
"def matrix_mul(m1,m2):\n",
" r = [0]*4\n",
" r[0] = m1[0]*m2[0] + m1[2] * m2[1]\n",
" r[1] = m1[1]*m2[0] + m1[3] * m2[1]\n",
" r[2] = m1[0]*m2[2] + m1[2] * m2[3]\n",
" r[3] = m1[1]*m2[2] + m1[3] * m2[3]\n",
" return r\n",
"\n",
"print(fib_dc_fast2(10))\n",
"%timeit fib_dc_fast2(10)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Closed form expression - Binet's formula"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import math\n",
"\n",
"def fib_binet(n):\n",
" f = (1 + math.sqrt(5))/2\n",
" return (f**n - (-f)**-n)/math.sqrt(5)\n",
"\n",
"print(fib_binet(10))\n",
"%timeit fib_binet(10)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Sanity check"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"n = 500\n",
"print(\"DP Bottom-up\\t\" + str(fib_dp_bottom_up(n)))\n",
"print(\"DP Top-down\\t\" + str(fib_dp_top_down(n)))\n",
"print(\"D&C\\t\\t\" + str(fib_dc(n)))\n",
"print(\"D&C Fast\\t\" + str(fib_dc_fast(n)))\n",
"print(\"D&C Fast v2\\t\" + str(fib_dc_fast2(n)))\n",
"print(\"Binet\\t\\t\" + str(int(fib_binet(n))))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Comparison"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import time\n",
"\n",
"def time_f(f):\n",
" before = time.clock()\n",
" f()\n",
" after = time.clock()\n",
" return after - before\n",
"\n",
"n_max = 10000\n",
"samples = 50\n",
"step = int(n_max/samples)\n",
"data = range(1,n_max,step)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"t1 = []\n",
"for i in data:\n",
" t1.append(time_f(lambda: fib_dp_bottom_up(i)))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"t2 = []\n",
"\n",
"for i in data:\n",
" t2.append(time_f(lambda: fib_dc(i)))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib inline\n",
"from matplotlib import pyplot as plt\n",
"\n",
"plt.scatter(data, t1, c='green')\n",
"plt.scatter(data, t2, c='red')\n",
"plt.xlabel('n')\n",
"plt.ylabel('time (/s)')\n",
"plt.legend(['dp bottom-up','d&c'],loc='upper left')\n",
"plt.xlim(0)\n",
"plt.ylim(0)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"t3 = []\n",
"\n",
"for i in data:\n",
" t3.append(time_f(lambda: fib_dc_fast2(i)))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib inline\n",
"from matplotlib import pyplot as plt\n",
"\n",
"plt.scatter(data, t1, c='green')\n",
"plt.scatter(data, t2, c='red')\n",
"plt.scatter(data, t3, c='blue')\n",
"plt.xlabel('n')\n",
"plt.ylabel('time (/s)')\n",
"plt.legend(['dp bottom-up','d&c','d&c fast'],loc='upper left')\n",
"plt.xlim(0)\n",
"plt.ylim(0)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"n_max = 1000000\n",
"samples = 50\n",
"step = int(n_max/samples)\n",
"data = range(1,n_max,step)\n",
"\n",
"t3 = []\n",
"for i in data:\n",
" t3.append(time_f(lambda: fib_dc_fast2(i)))\n",
" \n",
"%matplotlib inline\n",
"from matplotlib import pyplot as plt\n",
"\n",
"plt.scatter(data, t3, c='blue')\n",
"plt.xlabel('n')\n",
"plt.ylabel('time (/s)')\n",
"plt.legend(['d&c fast'],loc='upper left')\n",
"plt.xlim(0)\n",
"plt.ylim(0)"
]
},
{
"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 - Software Engineering - Algorithms
%% Cell type:markdown id: tags:
## Fibonacci Challenge: Dynamic Programming vs. Divide-and-Conquer
%% Cell type:markdown id: tags:
### DP Fibonacci - Bottom-up (space efficient)
%% Cell type:code id: tags:
```
python
def
fib_dp_bottom_up
(
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
(
fib_dp_bottom_up
(
10
))
%
timeit
fib_dp_bottom_up
(
10
)
```
%% Cell type:code id: tags:
```
python
def
fib_dp_bottom_up
(
n
):
i
,
j
=
1
,
0
for
k
in
range
(
1
,
n
+
1
):
i
,
j
=
j
,
i
+
j
return
j
print
(
fib_dp_bottom_up
(
10
))
%
timeit
fib_dp_bottom_up
(
10
)
```
%% Cell type:markdown id: tags:
### DP Fibonacci - Top-down with Memoization
%% Cell type:code id: tags:
```
python
m
=
{
0
:
0
,
1
:
1
}
def
fib_dp_top_down
(
n
):
m
.
clear
()
m
[
0
]
=
0
m
[
1
]
=
1
return
fib_dp_top_down_aux
(
n
)
def
fib_dp_top_down_aux
(
n
):
if
n
not
in
m
:
m
[
n
]
=
fib_dp_top_down_aux
(
n
-
1
)
+
fib_dp_top_down_aux
(
n
-
2
)
return
m
[
n
]
print
(
fib_dp_top_down_aux
(
10
))
%
timeit
fib_dp_top_down
(
10
)
```
%% Cell type:markdown id: tags:
### D&C Fibonacci
%% Cell type:code id: tags:
```
python
import
math
def
fib_dc
(
n
):
if
n
==
0
:
return
0
elif
n
==
1
:
return
1
else
:
a
=
fib_dc
(
math
.
ceil
(
n
/
2
))
b
=
fib_dc
(
math
.
ceil
(
n
/
2
)
-
1
)
if
n
%
2
==
0
:
return
a
*
(
a
+
2
*
b
)
else
:
return
a
*
a
+
b
*
b
print
(
fib_dc
(
10
))
%
timeit
fib_dc
(
10
)
```
%% Cell type:markdown id: tags:
### D&C Fast Fibonacci (v1) - provided by Jacek Burys
%% Cell type:code id: tags:
```
python
import
numpy
as
np
dt
=
np
.
int64
def
fib_dc_fast
(
n
):
init
=
np
.
matrix
([[
1
],
[
0
]],
dtype
=
dt
)
transform
=
matrix_pow
(
np
.
matrix
([[
1
,
1
],[
1
,
0
]],
dtype
=
dt
),
n
)
return
(
transform
*
init
).
item
(
1
)
def
matrix_pow
(
m
,
n
):
if
n
==
0
:
return
np
.
matrix
([[
1
,
0
],[
0
,
1
]],
dtype
=
dt
)
if
n
==
1
:
return
m
temp
=
matrix_pow
(
m
,
n
//
2
)
if
n
%
2
==
0
:
return
temp
*
temp
else
:
return
temp
*
temp
*
m
print
(
fib_dc_fast
(
10
))
%
timeit
fib_dc_fast
(
10
)
```
%% Cell type:markdown id: tags:
### D&C Fast Fibonacci (v2)
%% Cell type:code id: tags:
```
python
def
fib_dc_fast2
(
n
):
init
=
[
1
,
0
]
transform
=
matrix_pow2
([
1
,
1
,
1
,
0
],
n
)
return
matrix_vec_mul
(
transform
,
init
)[
1
]
def
matrix_pow2
(
m
,
n
):
if
n
==
0
:
return
[
1
,
0
,
0
,
1
]
if
n
==
1
:
return
m
temp
=
matrix_pow2
(
m
,
n
//
2
)
if
n
%
2
==
0
:
return
matrix_mul
(
temp
,
temp
)
else
:
return
matrix_mul
(
matrix_mul
(
temp
,
temp
),
m
)
def
matrix_vec_mul
(
m
,
v
):
r
=
[
0
]
*
2
r
[
0
]
=
m
[
0
]
*
v
[
0
]
+
m
[
2
]
*
v
[
1
]
r
[
1
]
=
m
[
1
]
*
v
[
0
]
+
m
[
3
]
*
v
[
1
]
return
r
def
matrix_mul
(
m1
,
m2
):
r
=
[
0
]
*
4
r
[
0
]
=
m1
[
0
]
*
m2
[
0
]
+
m1
[
2
]
*
m2
[
1
]
r
[
1
]
=
m1
[
1
]
*
m2
[
0
]
+
m1
[
3
]
*
m2
[
1
]
r
[
2
]
=
m1
[
0
]
*
m2
[
2
]
+
m1
[
2
]
*
m2
[
3
]
r
[
3
]
=
m1
[
1
]
*
m2
[
2
]
+
m1
[
3
]
*
m2
[
3
]
return
r
print
(
fib_dc_fast2
(
10
))
%
timeit
fib_dc_fast2
(
10
)
```
%% Cell type:markdown id: tags:
### Closed form expression - Binet's formula
%% Cell type:code id: tags:
```
python
import
math
def
fib_binet
(
n
):
f
=
(
1
+
math
.
sqrt
(
5
))
/
2
return
(
f
**
n
-
(
-
f
)
**-
n
)
/
math
.
sqrt
(
5
)
print
(
fib_binet
(
10
))
%
timeit
fib_binet
(
10
)
```
%% Cell type:markdown id: tags:
### Sanity check
%% Cell type:code id: tags:
```
python
n
=
500
print
(
"DP Bottom-up
\t
"
+
str
(
fib_dp_bottom_up
(
n
)))
print
(
"DP Top-down
\t
"
+
str
(
fib_dp_top_down
(
n
)))
print
(
"D&C
\t\t
"
+
str
(
fib_dc
(
n
)))
print
(
"D&C Fast
\t
"
+
str
(
fib_dc_fast
(
n
)))
print
(
"D&C Fast v2
\t
"
+
str
(
fib_dc_fast2
(
n
)))
print
(
"Binet
\t\t
"
+
str
(
int
(
fib_binet
(
n
))))
```
%% Cell type:markdown id: tags:
### Comparison
%% Cell type:code id: tags:
```
python
import
time
def
time_f
(
f
):
before
=
time
.
clock
()
f
()
after
=
time
.
clock
()
return
after
-
before
n_max
=
10000
samples
=
50
step
=
int
(
n_max
/
samples
)
data
=
range
(
1
,
n_max
,
step
)
```
%% Cell type:code id: tags:
```
python
t1
=
[]
for
i
in
data
:
t1
.
append
(
time_f
(
lambda
:
fib_dp_bottom_up
(
i
)))
```
%% Cell type:code id: tags:
```
python
t2
=
[]
for
i
in
data
:
t2
.
append
(
time_f
(
lambda
:
fib_dc
(
i
)))
```
%% Cell type:code id: tags:
```
python
%
matplotlib
inline
from
matplotlib
import
pyplot
as
plt
plt
.
scatter
(
data
,
t1
,
c
=
'green'
)
plt
.
scatter
(
data
,
t2
,
c
=
'red'
)
plt
.
xlabel
(
'n'
)
plt
.
ylabel
(
'time (/s)'
)
plt
.
legend
([
'dp bottom-up'
,
'd&c'
],
loc
=
'upper left'
)
plt
.
xlim
(
0
)
plt
.
ylim
(
0
)
```
%% Cell type:code id: tags:
```
python
t3
=
[]
for
i
in
data
:
t3
.
append
(
time_f
(
lambda
:
fib_dc_fast2
(
i
)))
```
%% Cell type:code id: tags:
```
python
%
matplotlib
inline
from
matplotlib
import
pyplot
as
plt
plt
.
scatter
(
data
,
t1
,
c
=
'green'
)
plt
.
scatter
(
data
,
t2
,
c
=
'red'
)
plt
.
scatter
(
data
,
t3
,
c
=
'blue'
)
plt
.
xlabel
(
'n'
)
plt
.
ylabel
(
'time (/s)'
)
plt
.
legend
([
'dp bottom-up'
,
'd&c'
,
'd&c fast'
],
loc
=
'upper left'
)
plt
.
xlim
(
0
)
plt
.
ylim
(
0
)
```
%% Cell type:code id: tags:
```
python
n_max
=
1000000
samples
=
50
step
=
int
(
n_max
/
samples
)
data
=
range
(
1
,
n_max
,
step
)