Rで 線形代数:逆行列 を確認します。
1. 逆行列(Inverse Matrix)とは
定義
ある正方行列 A
に対して、掛けると単位行列 I
になるような行列 B
が存在するとき、B
を A
の逆行列と呼び、A⁻¹
と書きます。
数式で書くと以下のようになります。
A A⁻¹ = A⁻¹ A = I
ここで I
は単位行列(対角成分がすべて1で、それ以外が0の行列)です。
つまり、逆行列は「ある行列の操作を打ち消して、元に戻す」働きをします。
存在条件:正則行列
すべての行列に逆行列が存在するわけではありません。
逆行列が存在する行列を正則行列 (Nonsingular Matrix) または可逆行列 (Invertible Matrix) と呼びます。逆行列が存在しない行列は特異行列 (Singular Matrix) と呼びます。
ある行列 A
が正則である(逆行列を持つ)ための条件は以下の通りです。(すべて同値です)
- 正方行列であること。(行数と列数が同じ)
- 行列式(determinant)が 0 ではないこと。(
det(A) ≠ 0
) - 行列のランクが、行列のサイズ(次元)と等しいこと。(フルランクであること)
幾何学的な意味:逆変換
行列がベクトルに対する「変換(移動、回転、拡大・縮小など)」を表すと考えると、逆行列はその「逆変換」を表します。
- 回転の例: あるベクトルを時計回りに30度回転させる行列
A
があったとします。このとき、逆行列A⁻¹
は、そのベクトルを反時計回りに30度回転させる(元の位置に戻す)行列になります。 - 拡大・縮小の例: あるベクトルを2倍に拡大する行列
B
があったとします。このとき、逆行列B⁻¹
は、そのベクトルを1/2倍に縮小する(元の大きさに戻す)行列になります。
応用
逆行列は、連立一次方程式を解く際に利用されます。
例えば、以下のような連立一次方程式があるとします。
2x + y = 8
x + 3y = 9
これは行列を使って次のように表現できます。
[[2, 1], [1, 3]] [[x], [y]] = [[8], [9]]
この式を Ax = b
と書くと、両辺に左から逆行列 A⁻¹
を掛けることで、
A⁻¹Ax = A⁻¹b
Ix = A⁻¹b
x = A⁻¹b
となり、逆行列を計算することで解 x
(この場合は x
と y
の値)を直接求めることができます。
2. Rによるシミュレーション
Rでは solve()
関数を使って逆行列を計算できます。
Rコード
# --------------------------------------------------
# 逆行列のシミュレーション
# --------------------------------------------------
# --- シナリオ1: 基本的な逆行列の計算 ---
cat("--- シナリオ1: 基本的な逆行列の計算 ---\n")
# 逆行列が存在する行列 A を作成
# det(A) = 2*4 - 3*1 = 8 - 3 = 5 ≠ 0 なので逆行列は存在する
<- matrix(c(2, 1, 3, 4), nrow = 2, ncol = 2)
A cat("元の行列 A:\n")
print(A)
# Aの逆行列を計算
<- solve(A)
A_inv cat("\nAの逆行列 A_inv:\n")
print(A_inv)
# 確認: A %*% A_inv が単位行列 I になるか?
<- A %*% A_inv
I cat("\n確認 (A %*% A_inv):\n")
# 計算誤差を考慮して丸めて表示
print(round(I, 10))
cat("→ 単位行列になりました。\n\n")
# --- シナリオ2: 逆行列が存在しない場合(特異行列) ---
cat("--- シナリオ2: 逆行列が存在しない場合 ---\n")
# 逆行列が存在しない行列 B を作成
# 2行目が1行目の2倍になっており、線形独立ではない
# det(B) = 1*4 - 2*2 = 4 - 4 = 0
<- matrix(c(1, 2, 2, 4), nrow = 2, ncol = 2)
B cat("特異行列 B:\n")
print(B)
# solve(B) を実行するとエラーになることを確認
# tryCatch でエラーを捕捉して、エラーメッセージを表示
<- tryCatch(
result
{solve(B)
},error = function(e) {
return(e) # エラーオブジェクトを返す
}
)
cat("\n特異行列 B の逆行列を計算しようとすると...\n")
if (inherits(result, "error")) {
cat("エラーが発生しました:\n")
print(result$message)
cat("→ 行列式が0のため、逆行列を計算できませんでした。\n\n")
}
# --- シナリオ3: 応用例(連立一次方程式の解法) ---
cat("--- シナリオ3: 応用例(連立一次方程式の解法) ---\n")
# 方程式:
# 2x + y = 8
# x + 3y = 9
# 行列形式 Ax = b に変換
<- matrix(c(2, 1, 1, 3), nrow = 2, byrow = TRUE)
A_eq <- matrix(c(8, 9), nrow = 2)
b_eq
cat("係数行列 A:\n")
print(A_eq)
cat("\n定数ベクトル b:\n")
print(b_eq)
# 解 x = A⁻¹b を計算
# 方法1: 逆行列を明示的に計算してから掛ける
<- solve(A_eq)
A_eq_inv <- A_eq_inv %*% b_eq
x_sol1
# 方法2: solve(A, b) を使う
<- solve(A_eq, b_eq)
x_sol2
cat("\n解 x (x_sol1):\n")
print(x_sol1)
cat("\n解 x (x_sol2):\n")
print(x_sol2)
# 検算: A %*% x が b に戻るか確認
<- A_eq %*% x_sol2
check cat("\n検算 (A %*% x):\n")
print(check)
cat("→ 元のベクトル b と一致しました。\n")
cat(paste0("\nよって、方程式の解は x = ", x_sol2[1], ", y = ", x_sol2[2], " です。\n"))
--- シナリオ1: 基本的な逆行列の計算 ---
元の行列 A:
[,1] [,2]
[1,] 2 3
[2,] 1 4
Aの逆行列 A_inv:
[,1] [,2]
[1,] 0.8 -0.6
[2,] -0.2 0.4
確認 (A %*% A_inv):
[,1] [,2]
[1,] 1 0
[2,] 0 1
→ 単位行列になりました。
--- シナリオ2: 逆行列が存在しない場合 ---
特異行列 B:
[,1] [,2]
[1,] 1 2
[2,] 2 4
特異行列 B の逆行列を計算しようとすると...
エラーが発生しました:
[1] "Lapack routine dgesv: system is exactly singular: U[2,2] = 0"
→ 行列式が0のため、逆行列を計算できませんでした。
--- シナリオ3: 応用例(連立一次方程式の解法) ---
係数行列 A:
[,1] [,2]
[1,] 2 1
[2,] 1 3
定数ベクトル b:
[,1]
[1,] 8
[2,] 9
解 x (x_sol1):
[,1]
[1,] 3
[2,] 2
解 x (x_sol2):
[,1]
[1,] 3
[2,] 2
検算 (A %*% x):
[,1]
[1,] 8
[2,] 9
→ 元のベクトル b と一致しました。
よって、方程式の解は x = 3, y = 2 です。
以上です。