再帰のLU分解

資源の無駄使い

lu_decompの返り値が(転置されたL, U)なのであとから転置する。

# coding: utf8
# 正方行列のLU分解
# 再帰で書いたLU分解

def lu_decomp(A):
    if len(A)==1:
        return [ [1] ], [ [A[0][0]] ]
    else:
        li = [row[0] / A[0][0] for row in A]
        ui = A[0][:] # copy
        for i in xrange(len(li)):
            for j in range(len(ui)):
                A[i][j] -= li[i] * ui[j]
        nextA = [row[1:] for row in A[1:]]
        nextL, nextU = lu_decomp(nextA)
        L = [li] + [[0]+row for row in nextL]
        U = [ui] + [[0]+row for row in nextU]
        return L, U

def transpose(m):
    for i in xrange(len(m)):
        for j in xrange(i, len(m[0])):
            m[i][j], m[j][i] = m[j][i], m[i][j]
    return m

def main():
    import copy
    A = [[3.0, 1.0, -2.0],
        [8.0, 4.0, 6.0],
        [5.0, 1.0, 1.0],
        ]
    L,U = lu_decomp(copy.deepcopy(A))
    L = transpose(L)
    
    # print
    ms = [A,L,U]
    rep = ["A", "L", "U"]
    for k in range(3):
        m = ms[k]
        print rep[k],":"
        for i in xrange(len(m)):
            for j in xrange(len(m[0])):
                print "%3.1lf" % m[i][j],
            print ""
        print ""
    
    print "LU:"
    for i in xrange(3):
        for j in range(3):
            x = 0.0
            for k in range(3):
                x += L[i][k] * U[k][j]
            A[i][j] = x
    for i in range(3):
        for j in range(3):
            print A[i][j],
        print ""
    print ""
                

if __name__ == '__main__':
    main()

実行結果:

A :
3.0 1.0 -2.0 
8.0 4.0 6.0 
5.0 1.0 1.0 

L :
1.0 0.0 0.0 
2.7 1.0 0.0 
1.7 -0.5 1.0 

U :
3.0 1.0 -2.0 
0.0 1.3 11.3 
0.0 0.0 10.0 

LU:
3.0 1.0 -2.0 
8.0 4.0 6.0 
5.0 1.0 1.0