Rで線形代数:コーシー・シュワルツの不等式

Rで 線形代数:コーシー・シュワルツの不等式 を確認します。

1. コーシー・シュワルツの不等式 (Cauchy-Schwarz Inequality) とは

定義

コーシー・シュワルツの不等式は、

2つのベクトル uv があるとき、その内積の絶対値は、それぞれのベクトルの長さ(ノルム)の積以下である、

という関係を表します。

数式で書くと以下のようになります。

|u ⋅ v| ≤ ||u|| ||v||

  • u ⋅ v: ベクトル uv内積(ドット積)。
  • | |: 絶対値。
  • ||u||: ベクトル uノルム(ユークリッドノルム、つまり長さ)。√(u₁² + u₂² + ...)
  • ||v||: ベクトル vノルム√(v₁² + v₂² + ...)

両辺を2乗した以下の形で表されることもありますが、同値です。

(u ⋅ v)² ≤ ||u||² ||v||²

幾何学的な意味:射影と直角三角形

この不等式は、内積の幾何学的な定義から直感的に理解できます。 ベクトル uv のなす角を θ とすると、内積は以下のように定義されます。

u ⋅ v = ||u|| ||v|| cos(θ)

この式の両辺に絶対値をとると、

|u ⋅ v| = | ||u|| ||v|| cos(θ) | = ||u|| ||v|| |cos(θ)|

ここで、cos(θ) は必ず -1 ≤ cos(θ) ≤ 1 の範囲にあるので、その絶対値 |cos(θ)|0 ≤ |cos(θ)| ≤ 1 となります。 したがって、

|u ⋅ v| = ||u|| ||v|| × (|cos(θ)|) (ここで |cos(θ)| は1以下の数)

となり、|u ⋅ v|||u|| ||v|| と等しいか、それより小さくなることがわかります。

等号が成立する条件

この不等式で等号(=)が成立するのは、|cos(θ)| = 1 のときです。

|cos(θ)| = 1 となるのは、θ = 0 または θ = π (180度) のとき、つまり 2つのベクトルが互いに平行な関係にあるときです。

  • ベクトル uv が同じ向きを向いている(v = c u, c > 0
  • ベクトル uv が正反対の向きを向いている(v = c u, c < 0

つまり、2つのベクトルが線形従属(一方が他方の定数倍で表せる)である場合に限り、等号が成立します。

ベクトルが少しでも違う方向を向いていると、必ず < の関係になります。


2. Rによるシミュレーション

Rを使って、ランダムに生成したベクトルに対してコーシー・シュワルツの不等式が常に成り立つことを確認します。また、等号が成立する特別なケースもシミュレーションします。

Rコード

# --------------------------------------------------
# コーシー・シュワルツの不等式のシミュレーション
# --------------------------------------------------

# ベクトルの内積を計算する関数
dot_product <- function(u, v) {
  sum(u * v)
}

# ベクトルのノルム(長さ)を計算する関数
norm_vec <- function(v) {
  sqrt(sum(v^2))
}

# --- シナリオ1: ランダムなベクトルで不等式が成り立つことの確認 ---
cat("--- シナリオ1: ランダムなベクトル ---\n")

# 3次元のランダムなベクトルを2つ生成
seed <- 20250625
set.seed(seed)
u <- rnorm(3)
v <- rnorm(3)

cat("ベクトルu:", u, "\n")
cat("ベクトルv:", v, "\n")

# 不等式の左辺を計算: |u・v|
lhs <- abs(dot_product(u, v))

# 不等式の右辺を計算: ||u|| * ||v||
rhs <- norm_vec(u) * norm_vec(v)

cat("\n左辺 |u・v|:", lhs, "\n")
cat("右辺 ||u||*||v||:", rhs, "\n")

cat("\n不等式の検証:", lhs, "<=", rhs, "->", lhs <= rhs, "\n")
cat("→ 不等式は成り立っています。\n\n")


# --- シナリオ2: 等号が成立するケース(ベクトルが平行な場合) ---
cat("--- シナリオ2: 等号が成立するケース(平行なベクトル) ---\n")

# ベクトルu'を定義
u_prime <- c(1, 2, 3)

# u'と平行なベクトルv'を作成 (v' = 2 * u')
v_prime <- 2 * u_prime

cat("ベクトルu':", u_prime, "\n")
cat("ベクトルv':", v_prime, "\n")

# 不等式の左辺と右辺を計算
lhs_parallel <- abs(dot_product(u_prime, v_prime))
rhs_parallel <- norm_vec(u_prime) * norm_vec(v_prime)

cat("\n左辺 |u'・v'|:", lhs_parallel, "\n")
cat("右辺 ||u'||*||v'||:", rhs_parallel, "\n")

cat("\n不等式の検証:", lhs_parallel, "<=", rhs_parallel, "->", lhs_parallel <= rhs_parallel, "\n")

# Rの数値計算上の微小な誤差を考慮して、等しいかを確認
are_equal <- all.equal(lhs_parallel, rhs_parallel)
cat("左辺と右辺は等しいか? ->", isTRUE(are_equal), "\n")
cat("→ ベクトルが平行な場合、等号が成立することが確認できました。\n\n")


# --- シナリオ3: 多数のベクトルでシミュレーション ---
cat("--- シナリオ3: 1000回のシミュレーション ---\n")
n_sim <- 1000
results <- logical(n_sim) # 結果を格納するベクトル

for (i in 1:n_sim) {
  # 2次元から10次元までのランダムな次元数のベクトルを生成
  dim <- sample(2:10, 1)
  vec1 <- rnorm(dim)
  vec2 <- rnorm(dim)

  # 不等式を検証
  lhs_sim <- abs(dot_product(vec1, vec2))
  rhs_sim <- norm_vec(vec1) * norm_vec(vec2)

  results[i] <- (lhs_sim <= rhs_sim)
}

# すべてのシミュレーションで不等式が成り立ったか確認
if (all(results)) {
  cat(n_sim, "回のシミュレーションすべてで、コーシー・シュワルツの不等式が成り立ちました。\n")
} else {
  cat("不等式が成り立たないケースが見つかりました。\n")
}
--- シナリオ1: ランダムなベクトル ---
ベクトルu: 1.52588 0.4194963 -1.078101 
ベクトルv: -1.269916 -0.6472587 -0.3926426 

左辺 |u・v|: 1.785954 
右辺 ||u||*||v||: 2.830977 

不等式の検証: 1.785954 <= 2.830977 -> TRUE 
→ 不等式は成り立っています。

--- シナリオ2: 等号が成立するケース(平行なベクトル) ---
ベクトルu': 1 2 3 
ベクトルv': 2 4 6 

左辺 |u'・v'|: 28 
右辺 ||u'||*||v'||: 28 

不等式の検証: 28 <= 28 -> TRUE 
左辺と右辺は等しいか? -> TRUE 
→ ベクトルが平行な場合、等号が成立することが確認できました。

--- シナリオ3: 1000回のシミュレーション ---
1000 回のシミュレーションすべてで、コーシー・シュワルツの不等式が成り立ちました。

実行結果と解説

  • シナリオ1では、ランダムに生成した2つのベクトルに対して、不等式の左辺(内積の絶対値)と右辺(ノルムの積)を計算します。結果として、左辺 < 右辺 となり、不等式が成り立っていることがわかります。

  • シナリオ2では、意図的に平行なベクトル(v' = 2 * u')を作成します。この場合、左辺と右辺の値が一致し、不等式の等号が成立する条件をシミュレーションで確認できます。

  • シナリオ3では、さまざまな次元数のランダムなベクトルを多数生成し、繰り返し不等式を検証します。結果として、1000回すべての試行で不等式が成立していることを確認できます。

以上です。