M.Hiroi's Home Page

Memorandum

数学編

M.Hiroi の数学に関する覚え書です
[ Home | Math ]

ベクトルと行列

●ベクトル

「ベクトル (vector)」の本来の意味は、方向を持った量のことでした。高校の数学や物理では、二次元ベクトルや三次元ベクトルを使いましたが、広い意味でのベクトルはそれだけではなく、数をいくつも並べることで、5 次元や 10 次元など高次元のベクトルを表すことができます。本ページでは、n 個の数 \(v_1, v_2, \ldots, v_n\) を並べたものを n 次元空間のベクトル \(\vec v\) として扱うことにします。

\( \vec v = (v_1, \ v_2, \ \ldots, \ v_n) \)

\(v_i\) をベクトル \(\vec v\) の第 \(i\) 成分といいます。ベクトルは文字の上に矢印を付けるだけではなく、\(\overrightarrow{AB}\) のように 2 文字の上に矢印を付けたり、\(\boldsymbol A\) のように太い文字で表すこともあります。

ベクトルの大きさを「ノルム (norm)」といいます。ノルムにはいくつかの定義ありますが、よく用いられるのがユークリッドノルムで \(|\vec v|\) と表します。以下にノルムの定義を示します。

\( |\vec v| = \sqrt{{v_1}^2 + {v_2}^2 + \cdots + {v_n}^2} = \sqrt{\displaystyle \sum_{i=1}^n {v_i}^2} \)

ノルムは成分の二乗和の平方根になります。特に、大きさが 0 のベクトルをゼロ・ベクトルといい、\(\vec O\) と表記します。大きさが 1 のベクトルを単位ベクトル、一つの成分が 1 でそれ以外の成分が 0 のベクトルを基本ベクトルといいます。単位ベクトルや基本ベクトルは \(\vec e\) と表記することが多いです。

大きさが同じで方向が反対のベクトルを「逆ベクトル」といいます。\(\overrightarrow{AB}\) の逆ベクトルは \(\overrightarrow{BA}\) と表記し、\(\vec v\) の逆ベクトルは \(-\vec v\) と表記することが多いです。

プログラミング言語の場合、ベクトルは一次元配列で表すことができます。たとえば、Python であれば [1, 2, 3, 4, 5] のようにリスト (一次元配列) を使うと簡単です。ただし、リストをそのまま使うと不便なことが多いので、ベクトルや行列をサポートしている言語、Python であれば NumPy や SymPy を使ったほうが簡単だと思います。

NumPy での使用例を示します。NumPy については、拙作のページ お気楽 NumPy プログラミング超入門 をお読みくださいませ。

>>> import numpy as np
>>> a = np.array([1.0,2.0,3.0,4.0,5.0])
>>> a
array([1., 2., 3., 4., 5.])
>>> b = np.array([-1.0,-2.0,-3.0,-4.0,-5.0])
>>> b
array([-1., -2., -3., -4., -5.])
>>> z = np.zeros(5)
>>> z
array([0., 0., 0., 0., 0.])
>>> np.linalg.norm(a)
7.416198487095663
>>> np.linalg.norm(b)
7.416198487095663
>>> np.linalg.norm(z)
0.0

●ベクトルの和と差

ベクトルの和は成分同士の足し算、差は成分同士の引き算になります。

\( \vec v \pm \vec w = (v_1 \pm w_1, \ v_2 \pm w_2, \ \ldots, \ v_n \pm w_n) \)

ベクトルの和は以下の法則が成り立ちます。

ベクトルの和は数と同様に交換法則や結合法則が成立します。また、単位元はゼロ・ベクトルになり、逆元は逆ベクトルになります。

NumPy を使うと、ベクトルの和と差は演算子 +, - で求めることができます。簡単な実行例を示します。

>>> u = np.array([1.,1.,1.,1.,1.])
>>> v = np.array([1.,2.,3.,4.,5.])
>>> w = np.array([5.,4.,3.,2.,1.])
>>> z = np.zeros(5)
>>> v + w
array([6., 6., 6., 6., 6.])
>>> w + v
array([6., 6., 6., 6., 6.])
>>> (u + v) + w
array([7., 7., 7., 7., 7.])
>>> u + (v + w)
array([7., 7., 7., 7., 7.])
>>> v + z
array([1., 2., 3., 4., 5.])
>>> v + (- v)
array([0., 0., 0., 0., 0.])
>>> v - v
array([0., 0., 0., 0., 0.])
>>> v - w
array([-4., -2.,  0.,  2.,  4.])
>>> v + (- w)
array([-4., -2.,  0.,  2.,  4.])

●ベクトルの実数倍

k を実数とすると、\(k\vec v\) は各成分 \(v_i\) を \(k\) 倍したものになります。

\( k\vec v\ = (k v_1, \ k v_2, \ \ldots, \ k v_n) \)

\(m, n\) を実数とすると、ベクトルの実数倍は以下の法則が成り立ちます。

第 i 成分が 1 で残りの成分が 0 の基本ベクトルを \(\vec {e_i}\) とします。ベクトル \(\vec v\) は成分 \(v_i\) と基本ベクトル \(\vec {e_i}\) を使って、次のように表すことができます。

\(\begin{array}{l} \vec e_i = (0, \ldots, 0, \stackrel{i}{1}, 0, \ldots, 0) \\ \vec v = v_1 \vec e_1 + v_2 \vec e_2 + \cdots + v_i \vec e_i + \cdots + v_n \vec e_n \end{array}\)

NumPy を使うと、ベクトルの和と差は演算子 * で求めることができます。簡単な実行例を示します。

>>> v = np.array([1.0,2.0,3.0,4.0,5.0])
>>> v
array([1., 2., 3., 4., 5.])
>>> 3 * v
array([ 3.,  6.,  9., 12., 15.])
>>> v * 3
array([ 3.,  6.,  9., 12., 15.])
>>> 3 * (5 * v)
array([15., 30., 45., 60., 75.])
>>> 5 * (3 * v)
array([15., 30., 45., 60., 75.])
>>> 3 * 5 * v
array([15., 30., 45., 60., 75.])
>>> (3 + 5) * v
array([ 8., 16., 24., 32., 40.])
>>> 3 * v + 5 * v
array([ 8., 16., 24., 32., 40.])
>>> w = np.array([5.0,4.0,3.0,2.0,1.0])
>>> w
array([5., 4., 3., 2., 1.])
>>> 3 * (v + w)
array([18., 18., 18., 18., 18.])
>>> 3 * v + 3 * w
array([18., 18., 18., 18., 18.])

>>> e1 = np.array([1.0,0.0,0.0,0.0,0.0])
>>> e2 = np.array([0.0,1.0,0.0,0.0,0.0])
>>> e3 = np.array([0.0,0.0,1.0,0.0,0.0])
>>> e4 = np.array([0.0,0.0,0.0,1.0,0.0])
>>> e5 = np.array([0.0,0.0,0.0,0.0,1.0])
>>> v
array([1., 2., 3., 4., 5.])
>>> 1*e1 + 2*e2 + 3*e3 + 4*e4 + 5*e5
array([1., 2., 3., 4., 5.])

●ベクトルの内積

ベクトル同士の掛け算は 2 つの考え方があり、ひとつが「内積 (nner product)」で、もう一つが「外積 (outer product)」です。

ベクトルとベクトルを掛け算した結果がスカラー (量) なる演算を内積といい、結果がベクトルになる演算を外積といいます。内積のことをドット積、外積のことをクロス積と呼ぶこともあります。本ページでは内積について説明し、外積の説明は割愛させていただきます。あしからずご了承くださいませ。

内積の定義を示します。

\( \vec v \cdot \vec w = v_1 w_1 + v_2 w_2 + \cdots + v_i w_i + \cdots + v_n w_n = \displaystyle \sum_{i=1}^n v_i w_i \)

内積は対応する成分同士の掛け算を足したものになります。上の定義により、\(\vec v\) 自身の内積 \(\vec v \cdot \vec v\) は、\(\vec v\) のノルムの 2 乗 \(|\vec v|^2\) になることがわかります。

ベクトルの内積にはもう一つ定義があります。

\( \vec v \cdot \vec w = |\vec v||\vec w| \cos \theta \)

\(\theta\) は \(\vec v\) と \(\vec w\) のなす角を表します。高校の数学では、これを内積の定義としています。この定義は平面上で考えるとわかりやすいと思います。両方の定義が同じものであることを示します。

\(\vec v = (v_x, v_y), \vec w = (w_x, w_y)\) とし、
\(\vec v\) と x 軸のなす角を \(\alpha\), \(\vec w\) と x 軸のなす角を \(\beta\) とすると、三角比により次の式が成り立つ

\(\begin{array}{l} \sin \alpha = \dfrac{v_y}{\sqrt {{v_x}^2 + {v_y}^2}} = \dfrac{v_y}{|\vec v|} \\ \cos \alpha = \dfrac{v_x}{\sqrt {{v_x}^2 + {v_y}^2}} = \dfrac{v_x}{|\vec v|} \\ \sin \beta = \dfrac{w_y}{\sqrt {{w_x}^2 + {w_y}^2}} = \dfrac{w_y}{|\vec w|} \\ \cos \beta = \dfrac{w_x}{\sqrt {{w_x}^2 + {w_y}^2}} = \dfrac{w_x}{|\vec w|} \\ \end{array}\)

\(\theta = \alpha - \beta\) とすると、三角関数の加法定理により \(\cos \theta\) は次のように書き直すことができる

\(\begin{array}{l} \cos \theta = \cos(\alpha - \beta) \\ = \cos \alpha \cos \beta + \sin \alpha \sin \beta \\ = \dfrac{v_x}{|\vec v|} \dfrac{w_x}{|\vec w|} + \dfrac{v_y}{|\vec v|} \dfrac{w_y}{|\vec w|} \\ = \dfrac{v_x w_x + v_y w_y}{|\vec v||\vec w|} \end{array}\)

よって、\(\vec v \cdot \vec w = |\vec v||\vec w| \cos \theta = |\vec v||\vec w| \dfrac{v_x w_x + v_y w_y}{|\vec v||\vec w|} = v_x w_x + v_y w_y\) となる

ベクトルの内積には以下の法則が成り立ちます。

NumPy の場合、ベクトルの内積は演算子 @ や関数 dot(), vdot() を使います。演算子 * は成分同士の掛け算になります。@ や dot() は行列の積も求めることができますが、vdot() はベクトル専用の関数です。

簡単な実行例を示します。

>>> v = np.array([1.0,2.0,3.0,4.0])
>>> w = np.array([5.0,6.0,7.0,8.0])
>>> v @ w
70.0
>>> np.dot(v, w)
70.0
>>> np.vdot(v, w)
70.0
>>> v @ v
30.0
>>> np.linalg.norm(v)
5.477225575051661
>>> math.sqrt(v @ v)
5.477225575051661

>>> v @ w
70.0
>>> w @ v
70.0
>>> u = np.array([2.0,4.0,6.0,8.0])
>>> u @ (v + w)
200.0
>>> u @ v + u @ w
200.0
>>> (5 * v) @ w
350.0
>>> v @ (5 * w)
350.0
>>> 5 * (v @ w)
350.0

>>> v * w
array([ 5., 12., 21., 32.])

●行列

「行列 (matrix)」は要素 (element) を長方形または正方形に並べた「表 (table)」みたいなものです。

\(\begin{array}{llll} \begin{pmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \end{pmatrix} & \begin{pmatrix} 1 & 2 \\ 3 & 4 \\ 5 & 6 \end{pmatrix} & \begin{pmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \end{pmatrix} & \begin{pmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{pmatrix} \end{array}\)

行列は丸カッコや角カッコで囲んで表すことが多いです。要素のことを成分と呼ぶこともあります。行列の横方向の並びを「行 (row)」といい、縦方向の並びを「列 (column)」といいます。一番左の例は 2 行 3 列の行列で、二番目の例は 3 行 2 列の行列になります。

行の数と列の数が等しい行列 (n 行 n 列の行列) を「正方行列」といいます。3, 4 番目の例は 3 行 3 列の正方行列になります。正方行列 \(A\) の左上から右下の対角成分が 1 で、それ以外の成分が 0 の行列を「単位行列」といいます。最後の例は単位行列です。単位行列は \(I\) または \(E\) で表すのがふつうです。また、すべての成分が 0 の行列を「零行列」といいます。零行列は \(O\) と表記します。。

行列 \(A\) と \(B\) において、行の数 m と列の数 n が等しいとき、\(A\) と \(B\) を同じ型であるといいます。同じ型の行列 \(A\) と \(B\) において、対応する成分がすべて等しいとき、\(A\) と \(B\) は等しいといい、\(A = B\) と表記します。それから、1 行だけの行列を「行ベクトル」、1 列だけの行列を「列ベクトル」といいます。

●行列の計算

行列の和と差は同じ型の行列で成立し、結果は成分同士の足し算または引き算になります。2 行 2 列の正方行列を例を示します。

\( \begin{pmatrix} a_{11} & a_{12} \\ a_{21} & a_{22} \end{pmatrix} \pm \begin{pmatrix} b_{11} & b_{12} \\ b_{21} & b_{22} \end{pmatrix} = \begin{pmatrix} a_{11} \pm b_{11} & a_{12} \pm b_{12}\\ a_{21} \pm b_{21} & a_{22} \pm b_{22} \end{pmatrix} \)

行列の加法は零行列が単位元になります。

\( A + O = O + A = A \)

行列の実数 (k) 倍は各成分に k を掛け算するだけです。

\( k \begin{pmatrix} a_{11} & a_{12} \\ a_{21} & a_{22} \end{pmatrix} = \begin{pmatrix} ka_{11} & ka_{12} \\ ka_{21} & ka_{22} \end{pmatrix} \)

行列 \(A\) と \(B\) の積は \(A\) の列数と \(B\) の行数が等しいときに成立します。

\( \begin{pmatrix} a_{11} & a_{12} \\ a_{21} & a_{22} \end{pmatrix} \begin{pmatrix} b_{11} & b_{12} \\ b_{21} & b_{22} \end{pmatrix} = \begin{pmatrix} a_{11} b_{11} + a_{12} b_{21} & a_{11} b_{12} + a_{12} b_{22} \\ a_{21} b_{11} + a_{22} b_{21} & a_{21} b_{12} + a_{22} b_{22} \end{pmatrix} \)

n 行 l 列の行列 \(A\) と l 行 m 列の行列 \(B\) を掛け算すると、結果は n 行 m 列の行列 \(C\) になります。その成分 \(c_{ij}\) は次式のようになります。

\( c_{ij} = a_{i1} b_{1j} + a_{i2} b_{2j} + \cdots + a_{il} b_{lj} \)

行列 \(A\) に \(O\) を掛けると \(O\) になります。また、行列の積の単位元は単位行列になります。

行列の計算には以下の法則が成り立ちます。

行列の積の場合、乗法の交換法則は成立しません。一般に、\(AB \ne BA\) になるので注意してください。

NumPy の場合、行列の和と積は演算子 +, - で、行列の実数倍は演算子 * で、行列の積は演算子 @ や関数 dot() で行うことができます。簡単な実行例を示します。

>>> a = np.array([[1,2],[3,4]])
>>> a
array([[1, 2],
       [3, 4]])
>>> b = np.array([[5,6],[7,8]])
>>> b
array([[5, 6],
       [7, 8]])
>>> a + b
array([[ 6,  8],
       [10, 12]])
>>> b + a
array([[ 6,  8],
       [10, 12]])
>>> a - b
array([[-4, -4],
       [-4, -4]])
>>> c = 10 * a
>>> c
array([[10, 20],
       [30, 40]])
>>> (a + b) + c
array([[16, 28],
       [40, 52]])
>>> a + (b + c)
array([[16, 28],
       [40, 52]])
>>> a @ b
array([[19, 22],
       [43, 50]])
>>> b @ a
array([[23, 34],
       [31, 46]])
>>> (a @ b) @ c
array([[ 850, 1260],
       [1930, 2860]])
>>> a @ (b @ c)
array([[ 850, 1260],
       [1930, 2860]])
>>> a @ (b + c)
array([[ 89, 122],
       [193, 270]])
>>> a @ b + a @ c
array([[ 89, 122],
       [193, 270]])
>>> (b + c) @ a
array([[ 93, 134],
       [181, 266]])
>>> b @ a + c @ a
array([[ 93, 134],
       [181, 266]])

>>> e = np.array([[1,0],[0,1]])
>>> e
array([[1, 0],
       [0, 1]])
>>> e @ e
array([[1, 0],
       [0, 1]])
>>> a @ e
array([[1, 2],
       [3, 4]])
>>> e @ a
array([[1, 2],
       [3, 4]])

なお、NumPy では行列 \(A\) の n 乗 (\(A^n\)) を演算子 ** で求めることはできません。モジュール numpy.linalg の関数 matrix_power(M, n) か、行列専用のクラス matrix を使ってください。コンストラクタは matrix() です。matrix の場合、行列の積は演算子 * を使います。演算子 ** を使って行列の累乗を計算することもできます。

>>> f = np.array([[1,1],[1,0]])
>>> f
array([[1, 1],
       [1, 0]])
>>> np.linalg.matrix_power(f, 10)
array([[89, 55],
       [55, 34]])
>>> np.linalg.matrix_power(f, 20)
array([[10946,  6765],
       [ 6765,  4181]])
>>> np.linalg.matrix_power(f, 40)
array([[165580141, 102334155],
       [102334155,  63245986]])

●逆行列

正方行列 \(A\) について、\(AX = XA = E\) となるような行列 \(X\) を \(A\) の逆行列といい、\(A^{-1}\) と表記します。つまり、\(AA^{-1} = A^{-1}A = E\) となります。2 行 2 列の逆行列を示します。

\( A = \begin{pmatrix} a & b \\ c & d \end{pmatrix} \) の場合、\(ad - bc \ne 0\) のときのみ逆行列が存在する

\( A^{-1} = \dfrac{1}{ad - bc} \begin{pmatrix} d & -b \\ -c & a \end{pmatrix} \)

逆行列の性質を示します。

連立 1 次方程式の解は逆行列を使って求めることができます。

\( \left\{ \begin{array}{l} ax + by = p \\ cx + dy = q \end{array} \right. \quad \) の解は

\( \begin{pmatrix} x \\ y \end{pmatrix} = \dfrac{1}{ad - bc} \begin{pmatrix} d & -b \\ -c & a \end{pmatrix} \begin{pmatrix} p \\ q \end{pmatrix} \)

正方行列 \(A\) に逆行列 \(A^{-1}\) が存在するとき、\(A\) は「正則行列 (regular matrix)」であるといいます。\(A\) が正則行列であれば、連立方程式 \(Ax = b\) の解 \(x\) は一意に定まります。

NumPy の場合、逆行列はモジュール linalg の関数 inv() で求めることができます。また、linalg には連立方程式を解く関数 solve() も用意されています。簡単な使用例を示します。

>>> a = np.array([[2, 3], [1, 2]])
>>> a
array([[2, 3],
       [1, 2]])
>>> b = np.linalg.inv(a)
>>> b
array([[ 2., -3.],
       [-1.,  2.]])
>>> a @ b
array([[1., 0.],
       [0., 1.]])
>>> b @ a
array([[1., 0.],
       [0., 1.]])
>>> np.linalg.inv(np.linalg.inv(a))
array([[2., 3.],
       [1., 2.]])

>>> c = np.array([[2,3],[1,2]])
>>> c
array([[2, 3],
       [1, 2]])
>>> np.linalg.inv(c)
array([[ 2., -3.],
       [-1.,  2.]])
>>> np.linalg.inv(a @ c)
array([[  7., -12.],
       [ -4.,   7.]])
>>> np.linalg.inv(c) @ np.linalg.inv(a)
array([[  7., -12.],
       [ -4.,   7.]])

●行列式

「行列式 (determinant)」は正方行列に対して決まる重要な量 (スカラー) です。行列 \(A\) の行列式は \(\det A\) とか \(|A|\) と表します。2 行 2 列と 3 行 3 列の行列の行列式を示します。

\( A = \begin{pmatrix} a & b \\ c & d \end{pmatrix} \) の行列式は

\( \det A = \begin{vmatrix} a & b \\ c & d \end{vmatrix} = ad - bc \)
\( A = \begin{pmatrix} a & b & c \\ d & e & f \\ g & h & i \end{pmatrix} \) の行列式は

\( \det A = \begin{vmatrix} a & b & c \\ d & e & f \\ g & h & i \end{vmatrix} = aei + bfg + chd - ceg - bdi - ahf \)

行列式が 0 の場合、その行列に逆行列は存在しません。これは 2 行 2 列, 3 行 3 列だけではなく、n 行 n 列の正方行列でも同じです。

NumPy の場合、モジュール linalg に行列式を求める関数 det() が用意されています。簡単な使用例を示します。

>>> a1 = np.array([[2,3],[1,2]])
>>> a1
array([[2, 3],
       [1, 2]])
>>> np.linalg.det(a1)
1.0
>>> a2 = np.array([[1, 1, 1], [2, 4, 6], [2, 0, 4]])
>>> a2
array([[1, 1, 1],
       [2, 4, 6],
       [2, 0, 4]])
>>> np.linalg.det(a2)
11.999999999999995
>>> a3 = np.array([[2, 4, 2, 2], [4, 10, 3, 3], [2, 6, 1, 1], [3, 7, 1, 4]])
>>> a3
array([[ 2,  4,  2,  2],
       [ 4, 10,  3,  3],
       [ 2,  6,  1,  1],
       [ 3,  7,  1,  4]])
>>> np.linalg.det(a3)
0.0

Copyright (C) 2024 Makoto Hiroi
All rights reserved.

[ Home | Math ]