Pythonで行列の和を計算する

行列の定義と和の計算

リストによる定義と計算

Pythonで行列の計算をするときは、NumPyやSymPyモジュールを使うことが一般的で実用的ではありませんが、計算の流れを知るためリストによる表現からはじめます。ここでは、2つの行列をリストm_a、m_bとして定義して、2つの行列の和を求めます。それでは、行列を定義します。

行列の定義
  1. m_a = [[3, 2, 4],
  2. [5, 1 ,2],
  3. [3, 4 ,5]]
  4. m_b = [[1, 3, 2],
  5. [6, 2, 4],
  6. [2, 8, 3]]

行列の和は、要素同士の合計なので、はじめに合計を計算するための配列m_s1を空のリストとして定義し、for文で各要素の合計を計算した結果をappendメソッドでリストに追加します。

リストによる行列の和 ~ 最も単純な方法
  1. m_s1 = []
  2. for i in range(len(m_a)):
  3. m_t = []
  4. for j in range (len(m_a[0])):
  5. m_t.append(m_a[i][j]+m_b[i][j])
  6. m_s1.append(m_t)

結果は次の通り、うまく計算することができました。

[[4, 5, 6], [11, 3, 6], [5, 12, 8]]

しかし何ともさえない方法なので、zip関数を使って2つのリストから同時に要素を取り出す方法を試してみます。

行列の和 ~ PythonらしくZipを使う方法
  1. m_s2 = []
  2. for x, y in zip(m_a, m_b):
  3. m_t = []
  4. for xx,yy in zip(x,y):
  5. m_t.append(xx+yy)
  6. m_s2.append(m_t)
  7. m_s2

結果は、同じです。少しPythonらしくなりましたが、さらにリスト内包表記を使って計算します。

リスト内包表記による行列の和
  1. [[xx + yy for xx,yy in zip(x,y)] for x,y in zip(m_a,m_b)]

1行で計算できるのでとても便利ですが、リスト内包表記は2つのリストを扱うとわかりにくくなるのが難点です。

リストを使った計算はPythonのプログラミングの練習にはなりますが手間がかかるので、行列の計算にはNumPyモジュールを使うのが一般的です。

NumPyによる定義と計算

NumPyモジュールの配列にはndarrayとmatrixの2つの形式があり、表記の仕方が異なります。まず、一般的なndarrayからです。ndarrayにはベクトル演算という機能があり、同じサイズの配列の算術演算では、同位要素(同じ場所の要素)ごとに計算されます。

NumPyのインポートと、ndarrayによる行列の定義
  1. import numpy as np
  2. # 行列の定義
  3. n_a = np.array([[3, 2, 4],
  4. [5, 1 ,2],
  5. [3, 4 ,5]])
  6. n_b = np.array([[1, 3, 2],
  7. [6, 2, 4],
  8. [2, 8, 3]])
  9. n_a + n_b

結果は、次の通り計算結果はndarray形式になります。

sympyによる行列の数値計算
sympyによる行列の数値計算

array([5, 7, 9])となります。次に、matrixによる方法です。

NumPyのmatrixによる行列の定義
  1. nm_a = np.matrix([[3, 2, 4],
  2. [5, 1 ,2],
  3. [3, 4 ,5]])
  4. nm_b = np.matrix([[1, 3, 2],
  5. [6, 2, 4],
  6. [2, 8, 3]])
  7. nm_a + nm_b

結果は次の通り計算結果はmatrix形式になります。

sympyによる行列の数値計算
sympyによる行列の数値計算

SymPyによる定義と計算

SymPyはPython library for symbolic mathematicsといわれるように、代数を扱うことができます。sympy.matrixによりベクトルを定義し、合計します。Pythonは変数を明示的に定義しなくてもよい仕様になっていますが、SymPyでは、s_a、s_bのようにsympy.symbolsとして定義する必要があります。

SymPy Matrixによる行列の定義と和の計算
  1. import sympy
  2. \ sympy.init_printing()
  3. s_a, s_b = sympy.symbols('s_a s_b')
  4. s_a = sympy.Matrix([[3, 2, 4],
  5. [5, 1 ,2],
  6. [3, 4 ,5]])
  7. s_b = sympy.Matrix([[1, 3, 2],
  8. [6, 2, 4],
  9. [2, 8, 3]])
  10. s_a + s_b

結果は次の通り。

sympyによる行列の数値計算
sympyによる行列の数値計算

これだけだと、わざわざ変数を定義するだけ手間がかかるだけですが、SymPyのすごさは、次のような代数計算ができることです。

Sympy Matrixによる行列の和の代数計算
  1. a_x1,a_x2,a_x3,a_y1,a_y2,a_y3,a_z1,a_z2,a_z3 = sympy.symbols('a_x1,a_x2,a_x3,a_y1,a_y2,a_y3,a_z1,a_z2,a_z3')
  2. b_x1,b_x2,b_x3,b_y1,b_y2,b_y3,b_z1,b_z2,b_z3 = sympy.symbols('b_x1,b_x2,b_x3,b_y1,b_y2,b_y3,b_z1,b_z2,b_z3')
  3. sv_a = sympy.Matrix([[a_x1,a_x2,a_x3],
  4. [a_y1,a_y2,a_y3],
  5. [a_z1,a_z2,a_z3]])
  6. sv_b = sympy.Matrix([[b_x1,b_x2,b_x3],
  7. [b_y1,b_y2,b_y3],
  8. [b_z1,b_z2,b_z3]])
  9. sv_s= sv_a+sv_b
  10. sv_s

ここでは、sv_sで2つのベクトルの和を計算しており、その中身は変数で格納されています。

sympyによる行列の代数計算
sympyによる行列の代数計算

次に、変数が格納されているベクトルにsubsメソッドで数値をしてすると、前例のように計算することができます。

Sympy Matrixの代数計算に数値を代入
  1. sv_s.subs([(a_x1, 3), (a_x2, 2),(a_x3, 4),(a_y1, 5), (a_y2, 1), (a_y3, 2), (a_z1, 3),(a_z2, 4), (a_z3, 5),
  2. (b_x1, 1), (b_x2, 3),(b_x3, 2),(b_y1, 6), (b_y2, 2), (b_y3, 4), (b_z1, 2),(b_z2, 8), (b_z3, 3)])

結果は同じように縦のベクトルで戻ります。