Python中的矩阵求幂

Python中的矩阵求幂,python,numpy,scipy,linear-algebra,Python,Numpy,Scipy,Linear Algebra,我试图用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(

我试图用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]
运行第二个实验时的错误为:

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
这行得通!
回溯(最近一次呼叫最后一次):
文件“matrix_exp.py”,第11行,在
酉t=[linalg.expm(-1*t*(1j)*t_列表中t的哈密顿量]
expm中的文件“/usr/lib/python2.7/dist packages/scipy/linalg/matfuncs.py”,第105行
返回scipy.sparse.linalg.expm(A)
expm中的文件“/usr/lib/python2.7/dist-packages/scipy/sparse/linalg/matfuncs.py”,第344行
X=_片段_2_1(X,A,s)
文件“/usr/lib/python2.7/dist-packages/scipy/sparse/linalg/matfuncs.py”,第462行,在_fragment_2_1中
X[k,k]=exp_diag[k]
TypeError:只有长度为1的数组才能转换为Python标量

这看起来真的很奇怪,因为我只改变了我使用的
t
的范围。是因为哈密顿量是对角的吗?一般来说,哈密顿量不会是,但我也希望它对对角量起作用。我真的不知道
expm
的机制,因此非常感谢您的帮助

这很有趣。我可以说的一件事是,这个问题是特定于
np.matrix
子类的。例如,以下方法可以很好地工作:

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

再深入一点追溯,在
scipy.sparse.linalg.matfuncs.py
中的
\u fragment\u 2\u 1
中提出了异常,具体来说:

错误消息

    X[k, k] = exp_diag[k]
TypeError: only length-1 arrays can be converted to Python scalars
向我建议,
exp\u 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
()
潜在的问题是
exp_diag
被假定为1D或列向量,但
np.matrix
对象的对角线是行向量。这突出了一个更普遍的观点,即
np.matrix
通常没有
np.ndarray
得到很好的支持,因此在大多数情况下,最好使用后者

一种可能的解决方案是使用
np.ravel()
diag\u T
展平为1D
np.ndarray

diag_T = np.ravel(T.diagonal().copy())
这似乎解决了您遇到的问题,尽管可能还有其他与
np.matrix
相关的问题,我还没有发现



我打开了一个拉取请求。

您可以尝试将计算移动到for循环,而不是列表。然后,您至少可以找出它失败的t值。程序失败的第一个数字是
t=2.1212121
。这似乎完全是武断的。。。程序不适用于
t=2.ax
其中
a>0
。而且它根本不适用于
t=3.x
,非常感谢!我想我可以只使用
ndarray
而不是
mat
,如果需要的话,可以在最后将内容转换回矩阵。我想我对这两个类的内部工作原理了解得不够。不相关,但如何在Python中设置断点?您是在使用特定的IDE,还是可以在
emacs
等中执行此操作?您不需要IDE来设置断点。我正在使用,但您也可以使用标准的Python调试器,
pdb
。我使用SublimiteText3作为一个编辑器,它有一个扩展,可以方便地设置断点,但肯定会有一个与Emacs等效的编辑器。。。
diag_T = np.ravel(T.diagonal().copy())