Pythonによるベクトルの内積と外積の計算

ベクトルの定義と内積の計算

リストによる定義と計算

Pythonでベクトルの内積や外積の計算をします。ベクトルの計算はNumPyやSymPyモジュールを使うが一般的ですが、まずは、計算の流れを知るためリストによる計算からはじめます。ここでは、2つのベクトルv_a=(2, -1, 2)、v_b=(3, -2, 1)を定義して、2つのベクトルの内積を求めます。

なお、内積の本来の定義は別にありますが、ここでは2つのベクトルの内積は、ベクトルの中で同じサイズの配列の算術演算で、同位要素(同じ場所の要素)ごとの積を合計することで計算します。式は次の通りです。

$2×3+(-1)×(-2)+2×1=10$
ベクトルの内積の計算
  1. v_a = [2, -1, 2]
  2. v_b = [3, -2, 1]
  3. v_dot = 0
  4. for x, y in zip(v_a,v_b):
  5. v_dot += x * y
  6. v_dot

10

はじめに合計を計算するための変数v_dotを0として定義し、for文の中で対応する要素の積をzip関数で1つずつ取り出して積を求め、変数v_dotに加算していきます。

NumPyによる内積の計算

Numpyのndarrayの積を求めることで計算

NumPyにより内積を計算します。

Numpyのインポートと、ndarrayによるベクトルの定義
  1. import numpy as np
  2. n_a = np.array([2, -1, 2])
  3. n_b = np.array([3, -2, 1])
  4. n_dot = n_a * n_b
  5. print('arrayの積:', n_dot)
  6. print('内積:', sum(n_dot))

arrayの積: [6 2 2]
内積: 10

NumPyでは、配列n_aとn_bの積を計算すると同じ位置の要素の積の配列になります。内積はその合計なので、sum関数で計算します。

関数などにより内積を計算

さらに、内積を計算する演算子、関数やメソッドを使うと、もっと簡単に内積を計算することができます。

Numpyの関数などによる内積の計算
  1. print('@演算子による内積:',n_a @ n_b)
  2. print('dot関数による内積:',np.dot(n_a, n_b))
  3. print('dot関数はリストでも可:',np.dot(v_a, v_b))
  4. print('inner関数による内積:',np.inner(n_a, n_b))
  5. print('inner関数はリストでも可:',np.inner(v_a, v_b))
  6. print('dotメソッドによる内積:',n_a.dot(n_b))

@演算子による内積: 10
dot関数による内積: 10
dot関数はリストでも可: 10
inner関数による内積: 10
inner関数はリストでも可: 10
dotメソッドによる内積: 10

1. ”@”という記号(演算子)は内積を意味します。
2. dot関数によりndarrayで表現したベクトルの内積を計算することができます。ちなみに、内積を別の言い方ではdot積(dot product)といいます。
3. dot関数は、通常のPythonのリストでも内積を計算することができます。
4. innner関数でも内積(innner product)を計算することができます。innner関数も、5.のようにリストでも内積を計算することができます。
6. 1つのベクトルに対し、もう一つのベクトルを引数としてdotメソッドを適用することで内積を計算することができます。

SymPyによる内積の計算

SympyのMatricesの内積の計算

SymPyでは1列のMatricesとしてベクトルを定義し、dotメソッドで計算します。NumPyのnp.dot(n_a, n_b)のような関数を使うことはできません。

SymPyでの数値による内積の計算
  1. import sympy
  2. sn_a = sympy.Matrix([2, -1, 2])
  3. sn_b = sympy.Matrix([3, -2, 1])
  4. sn_dot = sn_a.dot(sn_b)
  5. sn_dot

結果は同様に10となります。

SymPyの代数を使った内積の計算

SymPyでは、ベクトルの代数計算できます。ここでは、ベクトルの内積を代数で求めます。スカラーとして変数を定義した変数を使い1列のMatrixとしてベクトルを定義します。これに対し、dotメソッドにより代数として内積を計算することができます。

sympyでの代数による内積の計算
  1. sympy.var('a_x:z,b_x:z,c_x:z,d_x:z')
  2. sa_a = sympy.Matrix([a_x, a_y, a_z])
  3. sa_b = sympy.Matrix([b_x, b_y, b_z])
  4. sa_dot = sa_a.dot(sa_b)
  5. sa_dot

結果はsa_dotに格納され、その中身は次の通りです。

SymPyによる内積の代数計算

代数で計算した内積sa_dotにsubsメソッドで数値を代入します。数値の代入は、辞書形式によるのが一般的です。

代数による内積の計算結果に数値を代入
  1. sa_c.subs({a_x: 2, a_y: -1, a_z: 2, b_x: 3, b_y: -2, b_z: 1})

また、タプルによる代入も可能です。

代数による内積の計算結果に数値を代入
  1. sa_c.subs([(a_x, 2), (a_y, -1), (a_z, 2), (b_x, 3), (b_y, -2), (b_z, 1)])

結果は10になります。

Pythonによる外積の計算

Pythonを使って外積を計算します。

リストによる外積の計算

定義に従って、リストから計算することを考えます。外積は3次元のベクトルで計算します。

計算方法は次の通りです。

$外積=[{(-1)\times 1-2\times(-2)}, {(2)\times 3-2\times(1)}, {2\times(-2)-\times(-1)\times 3}]=[3,4,-1]$

リストによる外積の計算
  1. v_a = [2, -1, 2]
  2. v_b = [3, -2, 1]
  3. v_aa = v_a + v_a[0:2]
  4. v_bb = v_b + v_b[0:2]
  5. v_cross = []
  6. for i in range(len(v_a)):
  7. v_cross.append(v_aa[i+1]*v_bb[i+2]-v_aa[i+2]*v_bb[i+1])
  8. v_cross

[3, 4, -1]

  1. 第2要素の計算には第3要素と第1要素を、第3要素の計算には第1要素と第2要素を使いfor文で計算するため、4行目、5行目でリストに第1要素と第2要素を追加します。
  2. 7行目のfor文でリストの要素数(通常は3)までループさせます。
  3. 2のループの中で、1つ下の要素と2つ下の要素をたすき掛けにして積を求めたのち、その差をと取ることでリストの各要素の値としてリストに挿入します。

結果は[3, 4, -1]となり、正しく計算することができました。

NumPyの関数による外積の計算

同じ位置の要素同士の計算であればNumPyのベクトル計算が有効ですが、外積については他の位置の要素を使うので、その方法は思いつきません。その代わりにNumPyには外積を計算する関数が用意されています。

ここでは、NumPyのndarrayによりベクトルを定義し、cross関数により外積を計算します。外積はクロス積(cross product)ともいいます。

NumPyのcross関数による外積の計算
  1. import numpy as np
  2. n_a = np.array([2, -1, 2])
  3. n_b = np.array([3, -2, 1])
  4. n_cross = np.cross(n_a,n_b)
  5. vn_cross = np.cross(v_a,v_b)
  6. print(n_cross,vn_cross)

前に定義した通常のリストを使っても同じ結果が返ります。

SymPyによる外積の計算

SymPyの1列のMatrixとしてベクトルを定義して外積を計算します。NumPyと異なり、1つのベクトルに対してもう1つのベクトルをメソッドとして適用すると、縦ベクトルとして表示されます。

Sympyのcross methodによる外積の数値による計算
  1. import sympy
  2. sn_a = sympy.Matrix([2, -1, 2])
  3. sn_b = sympy.Matrix([3, -2, 1])
  4. sn_cross= sn_a.cross(sn_b)
  5. sn_cross
Sympyによる外積の数値計算

次に、SymPyで代数としてベクトルを定義して外積を計算します。同じようにcrossメソッドを提供すると次のようになります。

Sympyのcross methodによる外積の代数による計算
  1. sympy.var('a_x:z,b_x:z,c_x:z,d_x:z')
  2. sa_a =sympy.Matrix([a_x,a_y,a_z])
  3. sa_b =sympy.Matrix([b_x,b_y,b_z])
  4. sa_cross =sa_a.cross(sa_b)
  5. sa_cross

いったんsv_crossに結果を格納し、表示すると次の通りになります。

SymPyによる外積の代数計算

これに対して、subsメソッドで数値を代入します。

SymPyのcross methodによる外積の計算
  1. sa_cross.subs({a_x:2,a_y:-1,a_z:2,b_x:3, b_y:-2, b_z:1})

前と同じ結果になります。

SymPyのcross methodによる外積の計算
  1. sa_cross.subs([(a_x, 2), (a_y, -1), (a_z, 2), (b_x, 3), (b_y, -2), (b_z, 1)])

外積の次元に関する補足

外積は通常3次元のベクトルを想定していますが、NumPyでは2次元のベクトルにcross関数を使うことができます。

2次元のベクトルに対する外積の計算
  1. n2_a = np.array([1, 2])
  2. n2_b = np.array([4, 5])

np.cross(n2_a,n2_b)結果はarray(-3)と、第1要素と第2要素をたすき掛けした積の差が計算されます。これに対して、4次元のベクトルで計算すると次のようなエラーとなります。

4次元のベクトルに対する外積の計算
  1. n4_a = np.array([1, 2, 3, 4])
  2. n4_b = np.array([5, 6, 7, 8])
  3. np.cross(n4_a,n4_b)
NymPyによる外積は2次元か3次元

エラー表示からも、NumPyでは2次元か3次元を想定していることがわかります。

同じように、SymPyは3次元のみで、2次元以下や4次元以上のベクトルではエラーになります。