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]
2番目の実験を実行したときのエラーは次のとおりです。
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
私が変更したのは使用していたt
の範囲だけだったので、これは本当に奇妙に思えます。ハミルトニアンが対角であるからですか?一般的に、ハミルトニアンはそうではありませんが、対角線のハミルトニアンでも機能するようにしたいと思います。 expm
の仕組みはよくわからないので、助けていただければ幸いです。
それは興味深い。私が言えることの1つは、問題は_np.matrix
_サブクラスに固有であるということです。たとえば、次のように正常に機能します。
_h = np.array(hamiltonian)
unitary = [linalg.expm(-(1j)*t*h) for t in t_list]
_
トレースバックをもう少し深く掘り下げると、例外は__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]
_
エラーメッセージ
_ X[k, k] = exp_diag[k]
TypeError: only length-1 arrays can be converted to Python scalars
_
_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
()
_
根本的な問題は、_exp_diag
_が1Dまたは列ベクトルのいずれかであると想定されているが、_np.matrix
_オブジェクトの対角線が行ベクトルであるということです。これは、_np.matrix
_は一般的に_np.ndarray
_よりもサポートが不十分であるというより一般的な点を強調しているため、ほとんどの場合、後者を使用することをお勧めします。
考えられる解決策の1つは、np.ravel()
を使用して_diag_T
_を1D _np.ndarray
_にフラット化することです。
_diag_T = np.ravel(T.diagonal().copy())
_
_np.matrix
_に関連する他の問題がまだ見つかっていない可能性がありますが、これで発生している問題は修正されているようです。
プルリクエストを開きました ここ 。