当每个循环读取最后一个循环的结果时优化Python循环

时间:2015-06-11 06:50:59

标签: python loops numpy optimization

应该优化由两个循环(外部和内部)组成的函数 - 理想情况下,用Numpy函数替换Python循环。内循环可以很容易地优化(变量inner_loop),但外循环也可以改变吗?

问题是inner_loop读取向量U,其中一个元素在每个外部循环中被更改。如果我使用匹配的Numpy函数优化外部循环,则“递归”元素(更新U[i])将丢失。

for i in (y for y in xrange(0, n)):
    inner_loop = -np.sum(self.Y[i, :] * U) + self.Y[i, i] * U[i] + np.conjugate(self.shares[i] / U[i])
    U[i] = U_last[i] + accelerator * (1/self.Y[i,i] * inner_loop - U_last[i])

U是一个向量(n维),U_lastself.sharesY是一个nxn矩阵,U。 对于那些想知道的人来说,它是Gauss-Seidel潮流算法的一部分。

1 个答案:

答案 0 :(得分:1)

因为你以递归方式构建数组,所以没有。您必须找出另一种不递归的算法,或者将递归部分算出来。

尽管如此,让我们尽力而为。

for i in (y for y in xrange(0, n)):相当于for i in xrange(n)y没有任何目的,因为它没有作为名称公开。

使用U更改值的唯一位置是np.sum的传递,因此我们可以通过进行一些预先计算来进行一些简化。

  • self.Y[i, i] * U[i]可以是Ydiag_times_U[i],其中Ydiag_times_U = np.diag(Y) * U
  • np.conjugate(self.shares[i] / U[i])可以是conjugate_shares_over_U[i],其中conjugate_shares_over_U = np.conjugate(self.shares/U)
  • U_last[i] + accelerator * (1/self.Y[i,i] * inner_loop - U_last[i])可以同样重新排列并制作成U_last_minus_accelerator_times_U_last[i] + accelerator_over_Ydiag[i] * inner_loop,其中愚蠢是

    U_last_minus_accelerator_times_U_last[i] = U_last - accelerator * U_last accelerator_over_Ydiag = accelerator/np.diag(self.Y)

进行更改:

Ydiag_times_U = np.diag(Y) * U
conjugate_shares_over_U = np.conjugate(self.shares / U)
inner_silliness = Ydiag_times_U + conjugate_shares_over_U
U_last_minus_accelerator_times_U_last[i] = U_last - accelerator * U_last
accelerator_over_Ydiag = accelerator/np.diag(self.Y)

for i in xrange(n):
    inner_loop = inner_silliness[i] - np.sum(self.Y[i, :] * U)
    U[i] = U_last_minus_accelerator_times_U_last[i] + accelerator_over_Ydiag[i] * inner_loop

这些是较低级别的变化。除此之外,你可以尝试做一些代数来提取递归性。如果您担心效率,请尝试在C中进行循环。