Python中的矩阵求幂

ana*_*nar 8 python numpy linear-algebra scipy

我试图用Python取代复杂矩阵并遇到麻烦.我正在使用该scipy.linalg.expm函数,当我尝试以下代码时,我有一个相当奇怪的错误消息:

import numpy as np
from scipy import linalg

hamiltonian = np.mat('[1,0,0,0;0,-1,0,0;0,0,-1,0;0,0,0,1]')

# This works
t_list = np.linspace(0,1,10)
unitary = [linalg.expm(-(1j)*t*hamiltonian) for t in t_list]

# This doesn't
t_list = np.linspace(0,10,100)
unitary = [linalg.expm(-(1j)*t*hamiltonian) for t in t_list]
Run Code Online (Sandbox Code Playgroud)

第二个实验运行时的错误是:

This works!
Traceback (most recent call last):
  File "matrix_exp.py", line 11, in <module>
    unitary_t = [linalg.expm(-1*t*(1j)*hamiltonian) for t in t_list]
  File "/usr/lib/python2.7/dist-packages/scipy/linalg/matfuncs.py",     line 105, in expm
    return scipy.sparse.linalg.expm(A)
  File "/usr/lib/python2.7/dist- packages/scipy/sparse/linalg/matfuncs.py", line 344, in expm
    X = _fragment_2_1(X, A, s)
  File "/usr/lib/python2.7/dist-  packages/scipy/sparse/linalg/matfuncs.py", line 462, in _fragment_2_1
    X[k, k] = exp_diag[k]
TypeError: only length-1 arrays can be converted to Python scalars
Run Code Online (Sandbox Code Playgroud)

这看起来很奇怪,因为我改变的是t我使用的范围.是因为汉密尔顿主义是对角线吗?一般来说,汉密尔顿主义者不会,但我也希望它能用于对角线.我真的不知道它的机制expm,所以任何帮助都会非常感激.

ali*_*i_m 5

这太有趣了。我可以说的一件事是问题特定于np.matrix子类。例如,以下工作正常:

h = np.array(hamiltonian)
unitary = [linalg.expm(-(1j)*t*h) for t in t_list]
Run Code Online (Sandbox Code Playgroud)

深入研究回溯,在 in_fragment_2_1中引发了异常scipy.sparse.linalg.matfuncs.py,特别是这些行

n = X.shape[0]
diag_T = T.diagonal().copy()

# Replace diag(X) by exp(2^-s diag(T)).
scale = 2 ** -s
exp_diag = np.exp(scale * diag_T)
for k in range(n):
    X[k, k] = exp_diag[k]
Run Code Online (Sandbox Code Playgroud)

错误信息

    X[k, k] = exp_diag[k]
TypeError: only length-1 arrays can be converted to Python scalars
Run Code Online (Sandbox Code Playgroud)

向我建议它exp_diag[k]应该是一个标量,而是返回一个向量(并且您不能将向量分配给X[k, k],这是一个标量)。

设置断点并检查这些变量的形状证实了这一点:

ipdb> l
    751     # Replace diag(X) by exp(2^-s diag(T)).
    752     scale = 2 ** -s
    753     exp_diag = np.exp(scale * diag_T)
    754     for k in range(n):
    755         import ipdb; ipdb.set_trace()  # breakpoint e86ebbd4 //
--> 756         X[k, k] = exp_diag[k]
    757 
    758     for i in range(s-1, -1, -1):
    759         X = X.dot(X)
    760 
    761         # Replace diag(X) by exp(2^-i diag(T)).

ipdb> exp_diag.shape
(1, 4)
ipdb> exp_diag[k].shape
(1, 4)
ipdb> X[k, k].shape
()
Run Code Online (Sandbox Code Playgroud)

潜在的问题是exp_diag假设它是一维或列向量,但np.matrix对象的对角线是行向量。这突出了一个更普遍的观点,该观点np.matrix通常比 支持得少np.ndarray,因此在大多数情况下,最好使用后者。

一种可能的解决方案是np.ravel()用于展平diag_T为 1D np.ndarray

diag_T = np.ravel(T.diagonal().copy())
Run Code Online (Sandbox Code Playgroud)

这似乎解决了您遇到的问题,尽管可能还有其他np.matrix我尚未发现的问题。


我在这里打开了一个拉取请求。

  • 您不需要 IDE 来设置断点。我正在使用 [`ipdb`](https://pypi.python.org/pypi/ipdb),但您也可以使用标准 Python 调试器 `pdb`。我使用 SublimeText3 作为编辑器,它有一个扩展可以方便地设置断点,但肯定会有一个 Emacs 等价物...... (2认同)