【发布时间】:2015-07-16 15:52:06
【问题描述】:
我正在编写一个 Python 3.4 脚本,它为我做了大量计算。此计算涉及计算 many many binomial coefficients,并在求和和与其他数字相乘中多次使用它们中的每一个。每次在计算中需要 bc(二项式系数)时,它都会检查 bc 是否已经计算过。如果是这样,它返回这个已经计算的值。否则,它会计算并存储它以供以后查找。目前,我的计算 bc“n 选择 k”的函数 bc(n,k) 如下所示:
bcvalues = {}
def bc(n,k):
k = min(k,n-k) # take advantage of symmetry
if (n,k) in bcvalues: # check whether value has already been calculated
return bcvalues[(n,k)] # if so, return that already calculated value
if k == 0 or n <= 1: # base case
return 1
result = bc(n-1,k) + bc(n-1,k-1) # Use formula for Pascal's triangle
bcvalues[(n,k)] = result # store the value for later look-up
return result
我的查找表是一个字典,其中 (n,k) 元组作为键,bc(n,k) 作为值。它满足所有的
严格要求
- 可以在运行时填充/扩展为任意大小(在计算运行之前,我不知道需要计算多少 bc,但这是一个 很多公元前)
- 值可以任意大(
int(Python 3 之一)或gmpy2 类型mpz,我还不确定)。这很重要,因为值可能会变得非常非常大 - 可以用两个自然数n和k来索引
- 可以跳过某些元组 (n,k) 的 bc(例如,可能有 (100,50) 的条目,但没有 (100,49) 的条目)
但是,我不确定它是否是“最佳”解决方案(如果有的话)
性能要求(按重要性排序)
- 快速查找/读出
- 内存使用率低(在测试中,我的字典已经占用了几个 GB;我最终可能会在大内存机器上租用计算能力)
- 快速写入查找表
在我刚刚运行的非常小的输入大小测试中,函数 bc 被调用了 1600 万次,对于我真正感兴趣的输入大小,这个数字可能会增长很多。因此,性能很重要。
我当前的解决方案(字典)的优点是在计算运行结束时,我可以序列化查找表(使用 pickle),这样当我执行具有更高输入值的新运行时,我可以取消pickle它并拥有之前运行中计算的所有 bc。这是一个strong加分:
奖励积分
- 查找表可以轻松序列化
我的问题
除了字典,还有什么可以匹配这些条件?
我想编写一个函数,将三角形的元组 (n,k) 双射映射到自然数,然后使用一个列表作为查找表。这是多么有前途?其他想法?
【问题讨论】:
标签: python performance python-3.x lookup memory-efficient