我正在尝试创建一个特定样式的艾德矩阵(参见Wikipedia)。下面的代码可以工作,但是对于大的M
(~300左右),由于for循环的原因,它变得相当慢。有没有办法将它矢量化/更好地使用NumPy和/或SciPy?我在计算它对应的数学运算时遇到了麻烦,因此到目前为止我还没有成功。
我的代码如下
def banded_matrix(M):
phis = np.linspace(0, 2*np.pi, M)
i = 0
ham = np.zeros((int(2*M), int(2*M)))
for phi in phis:
ham_phi = np.array([[1, 1],
[1, -1]])*(1+np.cos(phi))
array_phi = np.zeros(M)
array_phi[i] = 1
mat_phi = np.diag(array_phi)
ham += np.kron(mat_phi, ham_phi)
i += 1
return ham
有了%timeit banded_matrix(M=300)
,在我的电脑上大约需要4秒钟。
由于代码有点不透明,我想做的是构造一个2 M × 2 M的大矩阵。在某种意义上,它在“宽度2”的对角线上有M个元素,其中的元素是依赖于phi的2x2矩阵ham_phi。矩阵随后将被对角化,所以也许人们甚至可以利用它的结构/它相当稀疏的事实来加快速度,但我不确定。
如果有人有一个想法去与此,我很乐意跟进!
3条答案
按热度按时间kqqjbcuj1#
您的矩阵是按块对角排列的,因此可以使用
scipy.linalg.block_diag
:让我们检查一下它是否工作正常,速度是否更快:
第一个
8fsztsew2#
强制性
np.einsum
基准输出量
性能指标评测结果
scipy.linalg.block_diag
与np.einsum
的详细信息hsgswve43#
作为另一种方法,您可以使用numba加速器通过jitting来加速它。我提出了一个基于paime answer的等价的
scipy.linalg.block_diag
numba方法:这种方法比以前的方法快至少4-5倍,m=400(us规模)。这种方法可以调整为其他数组形状,并通过进一步优化代码(不使用 paime 答案)和将所有代码行转换为numba函数或并行化来改进。我没有进一步研究,因为 paime 答案的性能似乎可以满足OP的接受;为了说明我们可以使用numba编写更快的
scipy.linalg.block_diag
等效代码: