首页 > 解决方案 > 使用 List Comprehension 和/或 map 避免嵌套 for 循环

问题描述

几天来,我一直在努力优化(不仅让它看起来更好)3个嵌套循环,其中包含一个条件调用和一个函数调用。我现在拥有的是以下内容:

def build_prolongation_operator(p,qs):
    '''
    p: dimension of the coarse basis
    q: dimension of the fine basis

    The prolongation operator describes the relationship between
    the coarse and fine bases:    
    V_coarse = np.dot(V_fine, I)
    '''

    q = sum(qs)

    I = np.zeros([q, p])

    for i in range(0, q):
        for j in range(0, p):
            for k in range(0, qs[j]):
                # if BV i is a child of j, we set I[i, j] = 1
                if i == f_map(j, k, qs):
                    I[i, j] = 1
                    break

    return I

哪里f_map是:

def f_map(i, j, q):
    '''
    Mapping which returns the index k of the fine basis vector which
    corresponds to the jth child of the ith coarse basis vector.    
    '''

    if j < 0 or j > q[i]:
        print('ERROR in f_map')
        return None

    result = j

    for k in range(0, i):
        result += q[k]

    return result

在分析我的整个代码时,我得到了build_prolongation_operator45 次和f_map大约850 万次的调用!

这是图片:

图片

我试图对列表理解和地图做同样的事情,但没有任何运气。

以下是build_prolongation_operator预期的输入示例:

p = 10
qs = randint(3, size=p)

标签: pythonpython-3.xlistnumpyoptimization

解决方案


我不知道基数和延长运算符,但你应该关注算法本身。在优化方面,这几乎总是合理的建议。

这可能是症结所在——如果不是,它可以帮助您入门:f_map计算不依赖于i,但您正在为 的每个值重新计算它i。由于i范围从零到 中的值之和qs,因此您将通过缓存结果来节省大量的重新计算;谷歌“python memoize”,它实际上会自己写。解决这个问题,你可能已经完成了,没有任何微优化。

您需要足够的空间来存储max(p) * max(qs[j])值,但从您报告的调用次数来看,这应该不是太大的障碍。


推荐阅读