Rで線形代数:行列のランク

Rで 線形代数:行列のランク を試みます。

行列のランクを求めるコード

行列のランクとは、その行列の線形独立な列(または行)ベクトルの最大数です。これは、ガウスの消去法を使って行列を階段行列 (Row Echelon Form) に変形し、その結果の非ゼロ行(要素がすべてゼロではない行)の数を数えることで求められます。

以下に、ガウスの消去法を実装して行列のランクを計算する関数 fun_rank を示します。

# ガウスの消去法により行列のランクを計算する関数
# A: 入力行列
# tol: 浮動小数点数の計算誤差を考慮するための許容誤差
fun_rank <- function(A, tol = 1e-10) {
  # 行列をコピーして、元の行列を変更しないようにする
  M <- A

  # 行数と列数を取得
  m <- nrow(M)
  n <- ncol(M)

  # ランク(非ゼロ行の数)を初期化
  rank <- 0
  # 現在注目しているピボット行
  pivot_row <- 1

  # 各列について処理を進める
  for (j in 1:n) {
    # 全ての行がピボットとして確定したら終了
    if (pivot_row > m) {
      break
    }

    # --- 部分ピボット選択 (Partial Pivoting) ---
    # 数値的安定性のために、pivot_row以降で絶対値が最大の要素をピボットとして探す
    i <- pivot_row
    max_row <- i
    max_val <- abs(M[i, j])

    # pivot_rowより下の行を探索
    if (i < m) {
      for (k in (i + 1):m) {
        if (abs(M[k, j]) > max_val) {
          max_val <- abs(M[k, j])
          max_row <- k
        }
      }
    }

    # ピボット(列の最大値)が許容誤差より小さい場合、
    # この列は線形従属とみなし、次の列に移る
    if (max_val < tol) {
      next
    }

    # --- 行の交換 ---
    # 見つけた最大値を持つ行を現在のpivot_rowと交換する
    if (max_row != pivot_row) {
      temp_row <- M[pivot_row, ]
      M[pivot_row, ] <- M[max_row, ]
      M[max_row, ] <- temp_row
    }

    # --- 前進消去 (Forward Elimination) ---
    # pivot_rowより下のすべての行について、j列目の要素を0にする
    # (ただし、pivot_rowが最終行でない場合)
    if (pivot_row < m) {
      for (i in (pivot_row + 1):m) {
        # 消去するための係数を計算
        factor <- M[i, j] / M[pivot_row, j]
        # 行の基本変形(下の行から、ピボット行の倍数を引く)
        M[i, ] <- M[i, ] - factor * M[pivot_row, ]
      }
    }

    # ピボットが見つかったので、ランクを1増やし、次のピボット行に進む
    rank <- rank + 1
    pivot_row <- pivot_row + 1
  }

  return(rank)
}

コードのテスト

ランクが3の行列

A_full_rank <- matrix(c(1, 2, 3, 0, 1, 4, 5, 6, 0), nrow = 3, byrow = TRUE)
cat("--- ランク計算のテスト ---\n")
cat("行列 A_full_rank:\n")
print(A_full_rank)
cat("実装によるランク:", fun_rank(A_full_rank), "\n") # 期待値: 3
cat("組み込み関数によるランク:", qr(A_full_rank)$rank, "\n\n")
--- ランク計算のテスト ---
行列 A_full_rank:
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    0    1    4
[3,]    5    6    0
実装によるランク: 3 
組み込み関数によるランク: 3 

ランクが2の行列(3列目が1列目+2列目)

B_rank_deficient <- matrix(c(1, 2, 3, 4, 5, 9, 6, 7, 13), nrow = 3, byrow = TRUE)
cat("行列 B_rank_deficient:\n")
print(B_rank_deficient)
cat("実装によるランク:", fun_rank(B_rank_deficient), "\n") # 期待値: 2
cat("組み込み関数によるランク:", qr(B_rank_deficient)$rank, "\n")
行列 B_rank_deficient:
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    9
[3,]    6    7   13
実装によるランク: 2 
組み込み関数によるランク: 2 

以上です。