NumPyで対称行列を生成・判定

Posted: | Tags: Python, NumPy

対称行列を表すNumPy配列ndarrayを生成したり、あるndarrayが対称行列であるかを判定する方法について、以下の内容を説明する。

  • NumPy配列ndarrayを元に対称行列を生成
  • NumPy配列ndarrayが対称行列であるか判定
  • 歪対称行列(交代行列)の場合

なお、対称行列の定義は以下の通り。

線型代数学における対称行列(たいしょうぎょうれつ、英: symmetric matrix)は、自身の転置行列と一致するような正方行列を言う。 対称行列 - Wikipedia

NumPyの行列演算についての詳細は以下の記事を参照。

NumPy配列ndarrayを元に対称行列を生成

正方行列を表す任意のNumPy配列ndarrayを元に対称行列を生成する方法について説明する。

以下のndarrayを例とする。

import numpy as np

a = np.arange(16).reshape(4, 4)
print(a)
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]
#  [12 13 14 15]]

関数np.tril(), np.triu()ndarrayから下三角成分・上三角成分を抽出できる。

print(np.tril(a))
# [[ 0  0  0  0]
#  [ 4  5  0  0]
#  [ 8  9 10  0]
#  [12 13 14 15]]

print(np.triu(a))
# [[ 0  1  2  3]
#  [ 0  5  6  7]
#  [ 0  0 10 11]
#  [ 0  0  0 15]]

以降はnp.tril()によって生成した下三角行列を使って例を示すが、考え方はnp.triu()による上三角行列でも同じ。

Tで転置行列を取得できる。

三角行列とその転置行列を足し合わせると対角成分以外は所望の対称行列となるが、対角成分は重複するため2倍の値になってしまう。

print(np.tril(a).T)
# [[ 0  4  8 12]
#  [ 0  5  9 13]
#  [ 0  0 10 14]
#  [ 0  0  0 15]]

print(np.tril(a) + np.tril(a).T)
# [[ 0  4  8 12]
#  [ 4 10  9 13]
#  [ 8  9 20 14]
#  [12 13 14 30]]

diagonal()メソッドとnp.diag()関数を利用すると対角行列を生成できる。

print(a.diagonal())
# [ 0  5 10 15]

print(np.diag(a.diagonal()))
# [[ 0  0  0  0]
#  [ 0  5  0  0]
#  [ 0  0 10  0]
#  [ 0  0  0 15]]

三角行列とその転置行列を足し合わせたものから対角行列を引くと所望の対称行列が得られる。

print(np.tril(a) + np.tril(a).T - np.diag(a.diagonal()))
# [[ 0  4  8 12]
#  [ 4  5  9 13]
#  [ 8  9 10 14]
#  [12 13 14 15]]

これを関数にすると以下のようになる。対象のndarrayが正方行列ではない場合の例外処理は省略しているので注意。

def get_symmetric(a, use_tril=True):
    if use_tril:
        a = np.tril(a)
    else:
        a = np.triu(a)
    return a + a.T - np.diag(a.diagonal())

第二引数use_trilで元のndarrayの下三角成分を使うか上三角成分を使うかを選択できるようにしている。使用例は以下の通り。

print(get_symmetric(a))
# [[ 0  4  8 12]
#  [ 4  5  9 13]
#  [ 8  9 10 14]
#  [12 13 14 15]]

print(get_symmetric(a, False))
# [[ 0  1  2  3]
#  [ 1  5  6  7]
#  [ 2  6 10 11]
#  [ 3  7 11 15]]

NumPy配列ndarrayが対称行列であるか判定

ndarrayが対称行列であるかどうかは、元のndarrayとその転置が一致するかで判定できる。

np.array_equal()を使うと簡単。

def is_symmetric(a):
    return np.array_equal(a, a.T)

a_sym = get_symmetric(a)
print(a_sym)
# [[ 0  4  8 12]
#  [ 4  5  9 13]
#  [ 8  9 10 14]
#  [12 13 14 15]]

print(is_symmetric(a_sym))
# True

print(is_symmetric(a))
# False

歪対称行列(交代行列)の場合

対称行列と同様の考え方で、歪対称行列(交代行列)を生成したり判定したりすることもできる。

歪対称行列(交代行列)の定義は以下の通り。

線型代数学において、交代行列(こうたいぎょうれつ、英: alternating matrix)、歪対称行列(わいたいしょうぎょうれつ、英: skew-symmetric matrix)または反対称行列(はんたいしょうぎょうれつ、英: antisymmetric matrix, antimetric matrix; 反称行列)は、正方行列 A であってその転置 A⊤ が自身の −1 倍となるものをいう。 交代行列 - Wikipedia

対称行列の場合と同様に、元のndarrayの下三角成分または上三角成分から生成できる。

def get_skew_symmetric(a, use_tril=True):
    if use_tril:
        a = np.tril(a)
    else:
        a = np.triu(a)
    return a - a.T

print(get_skew_symmetric(a))
# [[  0  -4  -8 -12]
#  [  4   0  -9 -13]
#  [  8   9   0 -14]
#  [ 12  13  14   0]]

print(get_skew_symmetric(a, False))
# [[  0   1   2   3]
#  [ -1   0   6   7]
#  [ -2  -6   0  11]
#  [ -3  -7 -11   0]]

判定も対称行列の場合と同様。

def is_skew_symmetric(a):
    return np.array_equal(a, -a.T)

a_sk_sym = get_skew_symmetric(a)
print(a_sk_sym)
# [[  0  -4  -8 -12]
#  [  4   0  -9 -13]
#  [  8   9   0 -14]
#  [ 12  13  14   0]]

print(is_skew_symmetric(a_sk_sym))
# True

print(is_skew_symmetric(a))
# False

関連カテゴリー

関連記事