矢量化或优化循环,其中每次迭代取决于前一次迭代的状态

时间:2017-06-06 17:49:45

标签: python performance numpy optimization

我有一个算法,我在python中实现。该算法可能会执行1.000.000次,所以我想尽可能地优化它。算法的基础是三个列表(energypointvalList)以及两个计数器pe

两个列表energypoint包含0到1之间的数字,我根据这些数字作出决定。 p是点计数器,e是能量计数器。我可以换取能量积分,每种能量的成本在valList中定义(取决于时间)。我也可以换取其他交易。但我必须立即进行交易。

算法大纲:

  1. 获取一个布尔列表,其中energy中的元素高于阈值,point中的元素低于另一个阈值。这是决定以积分换取能量。得到一个相应的点列表,它决定了能源交易点
  2. 在每个布尔列表中。删除在另一个真值之后的所有真值(如果我交换了能量的所有点数,我不允许再次点数之后)
  3. 对于两个布尔列表中的每个项目对(pB,点bool和eB,能量bool):如果pB为真且我有积分,我想交换我的所有积分,录入。如果eB是真的并且我有能量,我想把所有精力都交换到积分。
  4. 这是我提出的实施方案:

    start = time.time()
    import numpy as np
    
    np.random.seed(2) #Seed for deterministic result, just for debugging
    
    topLimit = 0.55
    bottomLimit = 0.45
    
    #Generate three random arrays, will not be random in the real world
    res = np.random.rand(500,3) #Will probably not be much longer than 500
    energy = res[:,0]        
    point = res[:,1]
    valList = res[:,2]
    
    #Step 1:
    #Generate two bools that (for ex. energy) is true when energy is above a threashold
    #and point below another threshold). The opposite applies to point
    energyListBool = ((energy > topLimit) & (point < bottomLimit))
    pointListBool = ((point > topLimit) & (energy < bottomLimit))
    
    #Step 2:
    #Remove all 'true' that comes after another true since this is not valid
    energyListBool[1:] &= energyListBool[1:] ^ energyListBool[:-1]
    pointListBool[1:] &= pointListBool[1:] ^ pointListBool[:-1]
    
    p = 100
    e = 0
    
    #Step 3:
    #Loop through the lists, if point is true, I loose all p but gain p/valList[i] for e
    #If energy is true I loose all e but gain valList[i]*e for p
    for i in range(len(energyListBool)):
        if pointListBool[i] and e == 0:
            e = p/valList[i] #Trade all points to energy
            p = 0
        elif energyListBool[i] and p == 0:
            p = valList[i]*e #Trade all enery to points
            e = 0
    
    print('p = {0} (correct for seed 2: 3.1108006690739174)'.format(p))
    print('e = {0} (correct for seed 2: 0)'.format(e))
    
    end = time.time()
    print(end - start)
    

    我正在讨论的是如何(如果可以的话)对for循环进行矢量化,所以我可以使用它而不是for-loop,在我看来这可能会更快。

1 个答案:

答案 0 :(得分:1)

在当前的问题设置中,这是不可能的,因为矢量化基本上要求您的n计算步骤不应该依赖于先前的n-1步骤。但是,有时可以找到重复f(n) = F(f(n-1), f(n-2), ... f(n-k))的所谓“封闭形式”,即查找不依赖于f(n)的{​​{1}}的明确表达,但它是一个单独的研究问题。

此外,从算法的角度来看,这样的矢量化不会给出太多,因为算法的复杂性仍然是n。但是,由于“复杂性常数”C*n = O(n)在实践中很重要,因此有不同的方法可以减少它。例如,在C / C ++中重写关键循环应该不是一个大问题。