Python:如何避免构建这个矩阵时的循环,并更快地计算它的行列式?

Python:如何避免构建这个矩阵时的循环,并更快地计算它的行列式?,python,loops,matrix,time,coding-efficiency,Python,Loops,Matrix,Time,Coding Efficiency,我在用Python构建矩阵时遇到了一些问题。 每一个元素都有一个循环,它是在图片中的形式,这里X是Q元素的数组(在下面的代码中用席表示)。 我已经尝试了下面的代码,但是它花费了太多的时间。我认为这是因为循环的数量,所以我想把它看作两个矩阵的乘积,但它不起作用,因为lambda有两个维度 由于这些代码将作为一个函数出现并将被多次使用,有没有办法使其运行得更快?非常感谢你 def lambdak(i,j,alpha,rho): return math.pi * alpha**2 * rho

我在用Python构建矩阵时遇到了一些问题。 每一个元素都有一个循环,它是在图片中的形式,这里X是Q元素的数组(在下面的代码中用席表示)。 我已经尝试了下面的代码,但是它花费了太多的时间。我认为这是因为循环的数量,所以我想把它看作两个矩阵的乘积,但它不起作用,因为lambda有两个维度

由于这些代码将作为一个函数出现并将被多次使用,有没有办法使其运行得更快?非常感谢你

def lambdak(i,j,alpha,rho):
    return math.pi * alpha**2 * rho * math.exp(-math.pi**2 * alpha**2 *(i**2 + j**2))
def phik(i,j,x,alpha,rho):
    return cmath.exp(2 * math.pi * 1j * (i*x[0] + j*x[1]))
alpha = 0.5
rho = 50
num = 30
x = np.random.uniform(-0.5,0.5,num)
y = np.random.uniform(-0.5,0.5,num)
xi = np.zeros((num,3))
for i in range(num):
    xi[i] = np.array([x[i], y[i], 0])
q = len(xi)
A = [[np.sum(list(map(lambda j:
                     np.sum(list(map(lambda i:
                                    lambdak(i,j,alpha,rho)/(1-lambdak(i,j,alpha,rho))* phik(i,j,xi[x]-xi[y],alpha,rho),
                                    range(-N,N+1)))),
                     range(-N,N+1)))) for x in range(q)] for y in range(q)]
a = np.linalg.inv(A)

正如您所怀疑的,性能差的原因是您的循环。我假设您正在使用
numpy
,因为您在循环中调用了
np.sum
。诀窍是将循环从内到外,而是将较大的结构(即矩阵)传递给
numpy
函数

这样做可以显著提高性能。上述代码可修改为:

import numpy as np

def lambdak(i,j,alpha,rho):
    return np.pi * alpha**2 * rho * np.exp(-math.pi**2 * alpha**2 *(i**2 + j**2))

def phik(i,j,x,alpha,rho):
    return np.exp(2 * np.pi * 1j * (i*x[:, :, 0] + j*x[:, :, 1]))

alpha = 0.5
rho = 50
num = 30
x = np.random.uniform(-0.5,0.5,num)
y = np.random.uniform(-0.5,0.5,num)
xi = np.zeros((num,3))
for i in range(num):
    xi[i] = np.array([x[i], y[i], 0])

X = np.arange(num).reshape(1,num)
Y = np.arange(num).reshape(num,1)

xi_diff = xi[X] - xi[Y]

N = 30

A = np.sum(map(lambda j:
                np.sum(map(lambda i:
                        lambdak(i,j,alpha,rho)/(1-lambdak(i,j,alpha,rho))* phik(i,j,xi_diff,alpha,rho),
                        range(-N,N+1)), 0),
                     range(-N,N+1)), 0)

a = np.linalg.inv(A)
在这里,外部循环被转换为矩阵,矩阵作为一个整体传递给
numpy
函数。此外,我还预先计算xi_diff,因为在每次调用中都会传递整个结构(即使只有一部分被
phik()
使用)


这将大大加快速度。然而,计算中的数值稳定性可能会受到影响,当我比较两种方法的输出时,它们的差异约为.1%。不过,希望这是可以的。

只要看看您的代码,我就可以给您一些建议。1) 您可以将计算lambdak(i,j,alpha,rho)移动到单独的函数中,并将其存储在二维数组中。你不必为每个q重新计算它。2) 此外,这段代码可以像中一样并行化,您可以独立计算每个值,但python有GIL限制。基本上,这意味着,即使你用python实现多线程,你也不会看到显著的加速。但是有一些微妙的优化,比如缓存,可以让你的代码更快。@skippy thx,谢谢你的回答!我会尝试第一点@skippy但是关于你的第二点,你能进一步解释一下吗?我研究过“缓存”,但由于我对它不太熟悉,我完全不知道XONo的问题。因此,我试图从(2)中得到的是,python可能不是并行化代码的正确工具,它基本上具有嵌套在它下面的for循环,但每个迭代并不依赖于上一个或下一个迭代。你可能想看看Goang-Langor或C++,它提供了更好的并发模型,不像Python那样有吉尔()。此外,您可以将上述代码推送到GPU以获得一定的加速比。Torch是一个基于Lua的脚本,可以在GPU()上运行,但GPU可能就是答案。