Python中的对角矩阵指数

时间:2013-04-18 11:32:33

标签: python matrix numpy scipy exponential

我正在编写一个考虑速度的数值算法。我在scipy / numpy(scipy.linalg.expm2,scipy.linalg.expm)中遇到了两个矩阵指数函数。但是我有一个矩阵,我知道它是预先对角的。这些scipy函数是否在运行之前检查矩阵是否是对角线?显然,对于对角矩阵,取幂算法可以快得多,我只想确保它们正在做一些聪明的事情 - 如果它们不是,那么有一种简单的方法吗?

3 个答案:

答案 0 :(得分:4)

如果矩阵是对角线,则可以通过对主对角线上的每个条目取幂来获得其指数,因此您可以通过以下方式计算:

np.diag(np.exp(np.diag(a)))

答案 1 :(得分:3)

如果你知道A是对角线而你想要k次幂:

def dpow(a, k):
    return np.diag(np.diag(a) ** k)

检查矩阵是否是对角线:

def isdiag(a):
    return np.all(a == np.diag(np.diag(a)))

所以:

def pow(a, k):
    if isdiag(a):
        return dpow(a, k)
    else:
        return np.asmatrix(a) ** k

同样对于指数(你可以通过扩展一套战略来数学获得),你可以这样做:

def dexp(a, k):
    return np.diag(np.exp(np.diag(a)))

def exp(a, k):
    if isdiag(a):
        return dexp(a, k)
    else:
        #use scipy.linalg.expm2 or whatever

答案 2 :(得分:1)

我开发了一种工具,可以帮助更快地像HYRY一样做,但是通过就地

def diagonal(array):
    """ Return a **view** of the diagonal elements of 'array' """
    from numpy.lib.stride_tricks import as_strided
    return as_strided(array,shape=(min(array.shape),),strides=(sum(array.strides),))

# generate a random diagonal array
d  = np.diag(np.random.random(4000))

# in-place exponent of the diagonal elements
ddiag = diagonal(d)
ddiag[:] = np.exp(ddiag)

# timeit comparison with HYRY's method
%timeit -n10 np.diag(np.exp(np.diag(d)))   
    # out> 10 loops, best of 3: 52.1 ms per loop
%timeit -n10 ddiag = diagonal(d); ddiag[:] = np.exp(ddiag)
    # out> 10 loops, best of 3: 108 µs per loop

现在,

  • HYRY的方法是对角线长度的二次方(可能是因为新的数组内存分配),所以如果你的矩阵维度很小,差异可能不会那么大。

  • 您需要使用就地计算

  • 最后,非对角线元素为0,所以它们的指数应该是1,不是吗?在我们的方法中,非对角线都是0。

对于最后一部分,如果你想让所有非对角线元素为1,那么你可以这样做:

d2 = np.ones_like(d); 
diagonal(d2)[:] = np.exp(np.diag(d))

print (d2==np.exp(d)).all()  # True

但是这与数组大小呈线性关系,因此对角线长度是二次方的w.r.t。对于4000x4000阵列,timeit给出~90ms,对于2000x2000阵列,给出22.3ms。

最后,你也可以就地加快速度:

diag = np.diag(d)
d[:]=1
diagonal(d)[:] = np.exp(diag)

Timeit为4000 ^ 2阵列提供66.1ms,为2000 ^ 2

提供16.8ms