Matrix exponentiation in Python

前端 未结 1 1534
失恋的感觉
失恋的感觉 2021-02-06 04:37

I\'m trying to exponentiate a complex matrix in Python and am running into some trouble. I\'m using the scipy.linalg.expm function, and am having a rather strange e

1条回答
  •  误落风尘
    2021-02-06 05:06

    That is interesting. One thing I can say is that the problem is specific to the np.matrix subclass. For example, the following works fine:

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

    Digging a little deeper into the traceback, the exception is being raised in _fragment_2_1 in scipy.sparse.linalg.matfuncs.py, specifically these lines:

    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]
    

    The error message

        X[k, k] = exp_diag[k]
    TypeError: only length-1 arrays can be converted to Python scalars
    

    suggests to me that exp_diag[k] ought to be a scalar, but is instead returning a vector (and you can't assign a vector to X[k, k], which is a scalar).

    Setting a breakpoint and examining the shapes of these variables confirms this:

    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
    ()
    

    The underlying problem is that exp_diag is assumed to be either 1D or a column vector, but the diagonal of an np.matrix object is a row vector. This highlights a more general point that np.matrix is generally less well-supported than np.ndarray, so in most cases it's better to use the latter.

    One possible solution would be to use np.ravel() to flatten diag_T into a 1D np.ndarray:

    diag_T = np.ravel(T.diagonal().copy())
    

    This seems to fix the problem you're encountering, although there may be other issues relating to np.matrix that I haven't spotted yet.


    I've opened a pull request here.

    0 讨论(0)
提交回复
热议问题