上三角行列、下三角行列の性質を確認する。

参考:http://mathtrain.jp/triangularmatrix

三角行列の性質

定義

$n \times n$ の正方行列$A=(a_{ij})$について、
「$i > j$ならば$a_{ij}=0$を満たす行列を上三角行列
「$i < j$ならば$a_{ij}=0$を満たす行列を下三角行列
という。

固有値

三角行列の固有値は対角成分に等しい。

三角行列の積

上三角行列同士の積は上三角行列になり、 下三角行列同士の積は下三角行列になる。

三角行列の逆行列

正則な上三角行列の逆行列は、上三角行列である。 正則な下三角行列の逆行列は、下三角行列である。

問題設定

ある正方行列Aを与えた時に、それが三角行列であるかどうかを判定する関数を作れ。

そして三角行列を用い、三角行列の固有値・積・逆行列に関する性質に対し実例をひとつ挙げて確認せよ。

実装

定義

In [2]:
import matplotlib.pyplot as plt
%matplotlib inline
import numpy as np
import theano
import theano.tensor as T
In [6]:
def check_triangular(mat, upper=True):
    for row in range(len(mat)):
        for col in range(len(mat[row])):
            if upper:
                if row > col and (not mat[row][col] == 0):
                    return False
            else:
                if row < col and (not mat[row][col] == 0):
                    return False
    return True
In [4]:
A = np.array([[1, 2, 3],
              [0, 1, 2],
              [0, 0, 1]])
B = np.array([[1, 1, 1],
              [0, 1, 1],
              [0, 0, 1]])
C = np.array([[3, 0, 0],
              [3, 2, 0],
              [3, 2, 1]])
D = np.array([[1, 0, 0],
              [1, 1, 0],
              [1, 1, 1]])
E = np.array([[1, 1, 1],
              [1, 1, 1],
              [0, 0, 1]])
In [7]:
for m in [A, B, C, D, E]:
    if check_triangular(m):
        print("Upper triangular matrix.")
    elif check_triangular(m, upper=False):
        print("Lower triangular matrix.")
    else:
        print("Not triangular matrix.")
Upper triangular matrix.
Upper triangular matrix.
Lower triangular matrix.
Lower triangular matrix.
Not triangular matrix.

三角行列の判定ができた。

固有値

次に、固有値が対角成分と一致するかどうかを確認する。

固有値の確認にはnumpy.linalg.eigh()関数を使う。

In [20]:
w, v = np.linalg.eigh(A, UPLO="L")
w
Out[20]:
array([ 1.,  1.,  1.])
In [21]:
w, v = np.linalg.eigh(B, UPLO="L")
w
Out[21]:
array([ 1.,  1.,  1.])
In [22]:
w, v = np.linalg.eigh(C, UPLO="U")
w
Out[22]:
array([ 1.,  2.,  3.])
In [23]:
w, v = np.linalg.eigh(D, UPLO="U")
w
Out[23]:
array([ 1.,  1.,  1.])

上三角行列では、UPLOにLを、下三角行列では、UPLOにOを入れるようだ。

対角成分が固有値であると確認できた。

行列の積の計算にはnumpy.dot関数を使う。

In [25]:
np.dot(A, B)
Out[25]:
array([[1, 3, 6],
       [0, 1, 3],
       [0, 0, 1]])
In [26]:
np.dot(C, D)
Out[26]:
array([[3, 0, 0],
       [5, 2, 0],
       [6, 3, 1]])

上三角行列同士の積は上三角行列になり、 下三角行列同士の積は下三角行列になることがわかった。

逆行列

逆行列を求めるには、まず行列式が0でないことを確認する。

行列式はnumpy.linalg.det()で、逆行列はnumpy.linalg.inv()で求める。

In [29]:
label = ["A","B","C","D"]
label_iter = iter(label)
for m in [A, B, C, D]:
    print(label_iter.__next__() + "-"*30)
    det = np.linalg.det(m)
    print(det)
    if det:
        print(np.linalg.inv(m))
A------------------------------
1.0
[[ 1. -2.  1.]
 [ 0.  1. -2.]
 [ 0.  0.  1.]]
B------------------------------
1.0
[[ 1. -1.  0.]
 [ 0.  1. -1.]
 [ 0.  0.  1.]]
C------------------------------
6.0
[[ 0.33333333  0.          0.        ]
 [-0.5         0.5         0.        ]
 [ 0.         -1.          1.        ]]
D------------------------------
1.0
[[ 1.  0.  0.]
 [-1.  1.  0.]
 [ 0. -1.  1.]]

正則な上三角行列の逆行列は、上三角行列であり、正則な下三角行列の逆行列は、下三角行列であることが確認できた。