Dynamic Programming

By Prof. Seungchul Lee
http://iai.postech.ac.kr/
Industrial AI Lab at POSTECH

Source

• By Prof. David J. Malan from Harvard University
• By Prof. Erik Demaine from MIT online lecture

1. Recursive Algorithm¶

• one of the central ideas of computer science
• depends on solutions to smaller instances of the same problem ( = subproblem)
• function to call itself (it is impossible in the real world)
• factorial example
• $n! = n\cdot(n-1) \cdots 2\cdot 1$

In [1]:
%%html
frameborder="0" allowfullscreen></iframe></center>


1.1. foo example¶

In [2]:
print ('{c}\n'.format(c="Hello class"))

Hello class


In [3]:
def foo(str):
print(str)

In [4]:
foo('Hello class')

Hello class

In [5]:
def foo_recursion(str):
print('{s}\n'.format(s=str))
foo_recursion(str)

In [6]:
# Do not run. It falls into infinite loop.

#foo_recursion('Hello Class')

In [7]:
# base line

def foo_recursion_correct(n):
if n <= 0:
return
else:
print('Hi! \n')
foo_recursion_correct(n-1)

In [8]:
foo_recursion_correct(4)

Hi!

Hi!

Hi!

Hi!



1.2. Factorial example¶

• factorial example
• $n! = n\cdot(n-1) \cdots 2\cdot 1$
In [9]:
n = 5

m = 1
for i in range(n):
m = m*(i+1)

print (m)

120

In [10]:
def fac(n):
if n == 1:
return 1
else:
return n*fac(n-1)

In [11]:
# recursive
fac(5)

Out[11]:
120

2. Dynamic Programming¶

• Dynamic Programming: general, powerful algorithm design technique
• Fibonacci numbers:
\begin{align*} F_1 &= F_2 = 1 \\ F_n &= F_{n-1} + F_{n-2} \end{align*}

2.1. Naive Recursive algorithm¶

\begin{align*} \text{fib}(n):&\\ &\text{if } n \leq 2:\; f = 1\\ &\text{else}:\; f = \text{fib}(n-1) + \text{fib}(n-2)\\ &\text{return } f \end{align*}

it works, Is it good?

2.2. Memorized DP algorithm¶

\begin{align*} \text{memo }= [\;]&\\ \text{fib}(n):&\\ & \text{if n in memo : return memo}[n]\\ \\ & \text{if } n\leq 2 :\; f = 1\\ & \text{else}: \;f = \text{fib}(n-1) + \text{fib}(n-2)\\ \\ &\text{memo}[n] = f\\ &\text{return } f \end{align*}

Benefit?

• fib$(n)$ only recurses the first time it's called

• memorize (remember) & re-use solutions to subproblems that helps solve the problem.

$\quad \implies$ DP $\simeq$ recursion + memorization

In [12]:
%%html
frameborder="0" allowfullscreen></iframe></center>


2.3. Examples¶

2.3.1. Fibonacci¶

In [13]:
# naive Fibonacci

def fib(n):
if n <= 2:
return 1
else:
return fib(n-1) + fib(n-2)

In [14]:
fib(10)

Out[14]:
55
In [15]:
# Memorized DP Fibonacci

def mfib(n):
global memo

if memo[n-1] != 0:
return memo[n-1]

elif n <= 2:
return 1
else:
memo[n-1] = mfib(n-1) + mfib(n-2)
return memo[n-1]

In [16]:
import numpy as np

n = 10
memo = np.zeros(n)
mfib(n)

Out[16]:
55.0
In [17]:
memo

Out[17]:
array([ 0.,  0.,  2.,  3.,  5.,  8., 13., 21., 34., 55.])
In [18]:
n = 30
%timeit fib(30)

891 ms ± 188 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [19]:
memo = np.zeros(n)
%timeit mfib(30)

2.15 µs ± 595 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)


2.3.2. Climbing a stair¶

You are climbing a stair case. Each time you can either make 1 step, 2 steps, or 3 steps. How many distinct ways can you climb if the stairs has $n = 30$ steps?

In [20]:
import numpy as np

def stair(n):
global memo

if memo[n] != 0:
m = memo[n]
elif n == 1:
m = 1
elif n == 2:
m = 2
elif n == 3:
m = 4
else:
m = stair(n-1) + stair(n-2) + stair(n-3)

memo[n] = m
return m

In [21]:
n = 5
global memo
memo = np.zeros(n+1)

stair(n)
print(memo)

[ 0.  1.  2.  4.  7. 13.]


3. Video Lectures¶

In [22]:
%%html

%%html

%%javascript