Python科学计算(第2版)
上QQ阅读APP看书,第一时间看更新

3.3.1 解线性方程组

numpy.linalg.solve(A, b)和scipy.linalg.solve(A, b)可以用来解线性方程组A x=b,也就是计算x=A-1 b。这里,A是m×n的方形矩阵,x和b是长为m的向量。有时候A是固定的,需要对多组b进行求解,因此第二个参数也可以是m×n的矩阵B。这样计算出来的X也是m×n的矩阵,相当于计算A-1 B

在一些矩阵公式中经常会出现类似于A-1 B的运算,它们都可以用solve(A,B)计算,这要比直接计算逆矩阵然后做矩阵乘法更快捷一些,下面的程序比较solve( )和逆矩阵的运算速度:

    import numpy as np
    from scipy import linalg
    
    m, n = 500, 50
    A = np.random.rand(m, m)
    B = np.random.rand(m, n)
    X1 = linalg.solve(A, B)
    X2 = np.dot(linalg.inv(A), B)
    print np.allclose(X1, X2)
    %timeit linalg.solve(A, B)
    %timeit np.dot(linalg.inv(A), B)
    True
    100 loops, best of 3: 10.1 ms per loop
    10 loops, best of 3: 20 ms per loop

若需要对多组B进行求解,但是又不好将它们合并成一个矩阵,例如某些矩阵公式中可能会有A-1 BA-1 CA-1 D等乘法,而BCD是通过某种方式逐次计算的。这时可以采用lu_factor( )和lu_solve( )。先调用lu_factor(A)对矩阵A进行LU分解,得到一个元组:(LU矩阵,排序数组)。将这个元组传递给lu_solve( ),即可对不同的B进行求解。由于已经对A进行了LU分解,lu_solve( )能够很快得出结果。

    luf = linalg.lu_factor(A)
    X3 = linalg.lu_solve(luf, B)
    np.allclose(X1, X3)
    True

除了使用lu_factor( )和lu_solve( )之外,可以先通过inv( )计算逆矩阵,然后通过dot( )计算矩阵乘积。下面比较二者的速度,可以看出lu_factor( )比inv( )要快很多,而lu_solve( )和dot( )的运算速度几乎相同:

    M, N = 1000, 100
    np.random.seed(0)
    A = np.random.rand(M, M)
    B = np.random.rand(M, N)
    Ai = linalg.inv(A)
    luf = linalg.lu_factor(A)   
    %timeit linalg.inv(A)
    %timeit np.dot(Ai, B)
    %timeit linalg.lu_factor(A)
    %timeit linalg.lu_solve(luf, B)
    10 loops, best of 3: 131 ms per loop
    100 loops, best of 3: 9.65 ms per loop
    10 loops, best of 3: 52.6 ms per loop
    100 loops, best of 3: 13.8 ms per loop