Example of efficiently computing Fibonacci numbers using a cache to implement a dynamic programming technique:
@lru_cache(maxsize=None)
def fib(n):
if n < 2:
return n
return fib(n-1) + fib(n-2)
>>> [fib(n) for n in range(16)]
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]
>>> fib.cache_info()
CacheInfo(hits=28, misses=16, maxsize=None, currsize=16)
New in version 3.2.
Changed in version 3.3: Added the typed option.
https://en.wikipedia.org/wiki/Dynamic_programming
https://zh.wikipedia.org/wiki/动态规划
动态规划(英语:Dynamic programming,简称DP)是一种在数学、管理科学、计算机科学、经济学和生物信息学中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。
动态规划常常适用于有重叠子问题[1]和最优子结构性质的问题,动态规划方法所耗时间往往远少于朴素解法。
动态规划背后的基本思想非常简单。大致上,若要解一个给定问题,我们需要解其不同部分(即子问题),再根据子问题的解以得出原问题的解。
通常许多子问题非常相似,为此动态规划法试图仅仅解决每个子问题一次,从而减少计算量:一旦某个给定子问题的解已经算出,则将其记忆化存储,以便下次需要同一个子问题解之时直接查表。这种做法在重复子问题的数目关于输入的规模呈指数增长时特别有用。
动态规划在查找有很多重叠子问题的情况的最优解时有效。它将问题重新组合成子问题。为了避免多次解决这些子问题,它们的结果都逐渐被计算并被保存,从简单的问题直到整个问题都被解决。因此,动态规划保存递归时的结果,因而不会在解决同样的问题时花费时间。
动态规划只能应用于有最优子结构的问题。最优子结构的意思是局部最优解能决定全局最优解(对有些问题这个要求并不能完全满足,故有时需要引入一定的近似)。简单地说,问题能够分解成子问题来解决。
- 最优子结构性质。如果问题的最优解所包含的子问题的解也是最优的,我们就称该问题具有最优子结构性质(即满足最优化原理)。最优子结构性质为动态规划算法解决问题提供了重要线索。
- 无后效性。即子问题的解一旦确定,就不再改变,不受在这之后、包含它的更大的问题的求解决策影响。
- 子问题重叠性质。子问题重叠性质是指在用递归算法自顶向下对问题进行求解时,每次产生的子问题并不总是新问题,有些子问题会被重复计算多次。动态规划算法正是利用了这种子问题的重叠性质,对每一个子问题只计算一次,然后将其计算结果保存在一个表格中,当再次需要计算已经计算过的子问题时,只是在表格中简单地查看一下结果,从而获得较高的效率。
背包问题
- 最长公共子序列
- Floyd-Warshall算法
- Viterbi算法
实验代码
import time
def fib(**kwargs):
n = kwargs['n']
if n < 2:
return n
return fib(n=(n - 1)) + fib(n=(n - 2))
def now():
return time.time()
def runtime(f, **kwargs):
s = now()
f(**kwargs)
e = now()
return e - s
import functools
@functools.lru_cache(maxsize=None)
def fib_cache(**kwargs):
n = kwargs['n']
if n < 2:
return n
return fib_cache(n=(n - 1)) + fib_cache(n=(n - 2))
if __name__ == '__main__':
N = [2, 4, 8, 16, 32, 64]
for i in N:
print(i, ':', fib(n=i), ',', fib_cache(n=i), runtime(fib, n=i), ',', runtime(fib_cache, n=i))
2 : 1 , 1 0.0 , 0.0
4 : 3 , 3 0.0 , 0.0
8 : 21 , 21 0.0 , 0.0 1
6 : 987 , 987 0.0009951591491699219 , 0.0
32 : 2178309 , 2178309 1.3061189651489258 , 0.0