対角化の理論と応用 — 対角化可能条件からジョルダン標準形まで

行列 $\bm{A}$ を「最も簡単な形」に変換できれば、理論的な分析も数値計算も圧倒的に楽になります。最も簡単な行列は対角行列 — 対角成分以外が全てゼロの行列です。対角行列は掛け算も、べき乗も、指数関数も、対角成分に対して独立に計算するだけです。

では、どんな行列でも対角行列に変換できるのでしょうか。残念ながら答えは「いいえ」です。対角化できない行列が存在します。しかし、どの行列が対角化でき、どの行列ができないのかを正確に判定する理論があります。

対角化の理論を理解すると、以下のような場面で活用できます。

  • 連立微分方程式: $\dot{\bm{x}} = \bm{Ax}$ の一般解が、対角化により各成分に分離した形で得られる
  • 行列のべき乗: フィボナッチ数列やマルコフ連鎖の長期的振る舞いの分析
  • 量子力学: 観測量(エルミート行列)の対角化で測定の固有値を求める
  • 振動解析: 固有振動モードの分離と解析

本記事の内容

  • 対角化の定義と意味
  • 対角化可能条件の厳密な議論(代数的重複度と幾何学的重複度)
  • 対角化の具体的な計算手順
  • 対角化不可能な行列とジョルダン標準形の概要
  • 行列のべき乗と行列指数関数への応用
  • Pythonでの実装と可視化

前提知識

この記事を読む前に、以下の記事を読んでおくと理解が深まります。

対角化とは何か

直感的な理解

座標軸を適切に回転(基底変換)すると、複雑に見える線形変換が「各軸方向に引き伸ばすだけ」の単純な変換に分解できることがあります。これが対角化の本質です。

2次元で具体的にイメージしましょう。行列 $\bm{A} = \begin{pmatrix} 3 & 1 \\ 0 & 2 \end{pmatrix}$ は、標準基底 $\bm{e}_1, \bm{e}_2$ では $x$ 方向と $y$ 方向が混ざった変換です。しかし、$\bm{A}$ の固有ベクトル $\bm{v}_1 = (1, 0)^T$, $\bm{v}_2 = (1, -1)^T$ を新しい基底として使えば、$\bm{A}$ は各軸方向に固有値 3, 2 倍にスケーリングする対角行列になります。

この「適切な基底変換で対角行列に変換する」操作が対角化です。

数学的定義

$n \times n$ 正方行列 $\bm{A}$ が対角化可能(diagonalizable)であるとは、正則行列 $\bm{P}$ が存在して

$$ \begin{equation} \bm{P}^{-1}\bm{A}\bm{P} = \bm{D} = \begin{pmatrix} \lambda_1 & & \\ & \ddots & \\ & & \lambda_n \end{pmatrix} \end{equation} $$

と書けることをいいます。同値な表現として

$$ \bm{A} = \bm{P}\bm{D}\bm{P}^{-1} $$

があり、これは固有値分解そのものです。$\bm{P}$ の列ベクトルは $\bm{A}$ の固有ベクトル、$\bm{D}$ の対角成分は対応する固有値です。

$\bm{P}^{-1}\bm{A}\bm{P} = \bm{D}$ は「$\bm{P}$ の列ベクトルで定義される基底に座標変換すると、$\bm{A}$ の作用が対角行列 $\bm{D}$ で表される」ことを意味しています。

対角化の定義を踏まえて、次に「いつ対角化が可能なのか」を厳密に論じましょう。

対角化可能条件

代数的重複度と幾何学的重複度

対角化可能性を正確に判定するには、固有値の代数的重複度幾何学的重複度の概念が必要です。

代数的重複度(algebraic multiplicity)$m_a(\lambda)$: 特性多項式 $\det(\bm{A} – \lambda\bm{I})$ における $\lambda$ の重複度(根の重複度)。

幾何学的重複度(geometric multiplicity)$m_g(\lambda)$: 固有空間 $\ker(\bm{A} – \lambda\bm{I})$ の次元。つまり、固有値 $\lambda$ に対応する線形独立な固有ベクトルの最大本数。

これらの間には常に以下の関係が成り立ちます。

$$ \begin{equation} 1 \leq m_g(\lambda) \leq m_a(\lambda) \end{equation} $$

幾何学的重複度は少なくとも1(固有値には少なくとも1つの固有ベクトルが存在する)で、代数的重複度を超えることはありません。

対角化可能の必要十分条件

$n \times n$ 行列 $\bm{A}$ が対角化可能であるための必要十分条件

$$ \boxed{\text{全ての固有値 } \lambda_i \text{ について } m_g(\lambda_i) = m_a(\lambda_i)} $$

つまり、全ての固有値について幾何学的重複度と代数的重複度が一致することです。

この条件は同値な言い換えがいくつかあります。

  • $\bm{A}$ が $n$ 個の線形独立な固有ベクトルを持つ
  • 異なる固有値に対応する固有空間の直和が $\mathbb{R}^n$(または $\mathbb{C}^n$)に等しい

十分条件(実用的な判定基準)

対角化可能であるための十分条件(必要条件ではない)として、以下が実用的です。

条件1: $n$ 個の異なる固有値を持つ(全ての $m_a = 1$)

異なる固有値に対応する固有ベクトルは線形独立なので、$n$ 個の異なる固有値があれば $n$ 個の線形独立な固有ベクトルが保証されます。

条件2: 実対称行列($\bm{A} = \bm{A}^T$)

スペクトル定理により、実対称行列は常に直交行列で対角化できます。固有値の重複があっても幾何学的重複度が代数的重複度に一致します。

条件3: 正規行列($\bm{A}^T\bm{A} = \bm{A}\bm{A}^T$)

より一般に、正規行列(直交行列、対称行列、反対称行列を含むクラス)はユニタリ行列で対角化可能です。

具体例による判定

例1: 対角化可能な場合

$$ \bm{A} = \begin{pmatrix} 5 & 4 \\ 1 & 2 \end{pmatrix} $$

特性方程式: $\lambda^2 – 7\lambda + 6 = (\lambda – 6)(\lambda – 1) = 0$

固有値 $\lambda_1 = 6$, $\lambda_2 = 1$(異なる2つ)→ 対角化可能。

$\lambda_1 = 6$ の固有ベクトル: $(\bm{A} – 6\bm{I})\bm{x} = \bm{0}$ → $\bm{v}_1 = (4, 1)^T$

$\lambda_2 = 1$ の固有ベクトル: $(\bm{A} – \bm{I})\bm{x} = \bm{0}$ → $\bm{v}_2 = (-1, 1)^T$

$$ \bm{P} = \begin{pmatrix} 4 & -1 \\ 1 & 1 \end{pmatrix}, \quad \bm{D} = \begin{pmatrix} 6 & 0 \\ 0 & 1 \end{pmatrix} $$

例2: 対角化不可能な場合

$$ \bm{B} = \begin{pmatrix} 2 & 1 \\ 0 & 2 \end{pmatrix} $$

特性方程式: $(\lambda – 2)^2 = 0$

固有値 $\lambda = 2$($m_a = 2$)。

固有空間: $(\bm{B} – 2\bm{I})\bm{x} = \begin{pmatrix} 0 & 1 \\ 0 & 0 \end{pmatrix}\bm{x} = \bm{0}$ → $\bm{x} = c(1, 0)^T$

幾何学的重複度 $m_g = 1 < m_a = 2$ → 対角化不可能

この行列は「固有値2の方向に伸ばしつつ、少しせん断する」変換であり、純粋なスケーリングに分解できません。

対角化不可能な行列をどう扱うかは後で議論するとして、まず対角化可能な場合の計算手順を整理しましょう。

対角化の計算手順

行列 $\bm{A}$ を対角化する手順は以下の通りです。

ステップ1: 特性方程式 $\det(\bm{A} – \lambda\bm{I}) = 0$ を解いて固有値 $\lambda_1, \ldots, \lambda_k$(重複含む)を求める。

ステップ2: 各固有値 $\lambda_i$ について、固有空間 $\ker(\bm{A} – \lambda_i\bm{I})$ の基底を求める($(\bm{A} – \lambda_i\bm{I})\bm{x} = \bm{0}$ を解く)。

ステップ3: 全ての固有空間の基底ベクトルを合わせて $n$ 個の線形独立なベクトルが得られれば対角化可能。得られなければ対角化不可能。

ステップ4: $\bm{P} = [\bm{v}_1 | \bm{v}_2 | \cdots | \bm{v}_n]$(固有ベクトルを列に並べた行列)を構成する。

ステップ5: $\bm{D} = \text{diag}(\lambda_1, \lambda_2, \ldots, \lambda_n)$(対応する固有値を並べた対角行列)を構成する。

このとき $\bm{A} = \bm{PDP}^{-1}$ が成り立ちます。

3次の計算例

$$ \bm{A} = \begin{pmatrix} 1 & 2 & 0 \\ 0 & 3 & 0 \\ 2 & -4 & 2 \end{pmatrix} $$

ステップ1: 特性方程式を求めます。

余因子展開で行列式を計算すると

$$ \det(\bm{A} – \lambda\bm{I}) = (1-\lambda)(3-\lambda)(2-\lambda) + 0 + 0 – 0 – 0 – 0 $$

第3列で余因子展開すると、$(3,3)$ 要素のみが非零なので

$$ \det(\bm{A} – \lambda\bm{I}) = (2-\lambda)\det\begin{pmatrix} 1-\lambda & 2 \\ 0 & 3-\lambda \end{pmatrix} = (2-\lambda)(1-\lambda)(3-\lambda) $$

固有値は $\lambda_1 = 1$, $\lambda_2 = 2$, $\lambda_3 = 3$(全て異なる)→ 対角化可能。

ステップ2: 各固有値の固有ベクトルを求めます。

$\lambda_1 = 1$: $(\bm{A} – \bm{I})\bm{x} = \begin{pmatrix} 0 & 2 & 0 \\ 0 & 2 & 0 \\ 2 & -4 & 1 \end{pmatrix}\bm{x} = \bm{0}$

第2式から $x_2 = 0$、第3式から $2x_1 + x_3 = 0$。$\bm{v}_1 = (1, 0, -2)^T$ が得られます。

$\lambda_2 = 2$: $(\bm{A} – 2\bm{I})\bm{x} = \begin{pmatrix} -1 & 2 & 0 \\ 0 & 1 & 0 \\ 2 & -4 & 0 \end{pmatrix}\bm{x} = \bm{0}$

第2式から $x_2 = 0$、第1式から $x_1 = 0$、$x_3$ は自由。$\bm{v}_2 = (0, 0, 1)^T$ が得られます。

$\lambda_3 = 3$: $(\bm{A} – 3\bm{I})\bm{x} = \begin{pmatrix} -2 & 2 & 0 \\ 0 & 0 & 0 \\ 2 & -4 & -1 \end{pmatrix}\bm{x} = \bm{0}$

第1式から $x_1 = x_2$、第3式から $2x_2 – 4x_2 – x_3 = 0$ つまり $x_3 = -2x_2$。$\bm{v}_3 = (1, 1, -2)^T$ が得られます。

ステップ3-5:

$$ \bm{P} = \begin{pmatrix} 1 & 0 & 1 \\ 0 & 0 & 1 \\ -2 & 1 & -2 \end{pmatrix}, \quad \bm{D} = \begin{pmatrix} 1 & 0 & 0 \\ 0 & 2 & 0 \\ 0 & 0 & 3 \end{pmatrix} $$

対角化の計算ができるようになったところで、対角化の最も重要な応用を見ていきましょう。

対角化の応用

行列のべき乗

対角化の最も基本的な応用は行列のべき乗です。$\bm{A} = \bm{PDP}^{-1}$ のとき

$$ \bm{A}^k = (\bm{PDP}^{-1})^k = \bm{PD}^k\bm{P}^{-1} $$

$\bm{D}^k$ は対角成分をそれぞれ $k$ 乗するだけです。

$$ \bm{D}^k = \begin{pmatrix} \lambda_1^k & & \\ & \ddots & \\ & & \lambda_n^k \end{pmatrix} $$

直接 $\bm{A}$ を $k$ 回掛けると $O(kn^3)$ ですが、対角化を使えば $O(n^3)$(1回の対角化と行列積)で済みます。

フィボナッチ数列への応用

フィボナッチ数列 $F_{n+1} = F_n + F_{n-1}$ は行列形式で

$$ \begin{pmatrix} F_{n+1} \\ F_n \end{pmatrix} = \begin{pmatrix} 1 & 1 \\ 1 & 0 \end{pmatrix}^n \begin{pmatrix} 1 \\ 0 \end{pmatrix} $$

と書けます。行列 $\bm{M} = \begin{pmatrix} 1 & 1 \\ 1 & 0 \end{pmatrix}$ の固有値は黄金比 $\phi = \frac{1+\sqrt{5}}{2}$ とその共役 $\hat{\phi} = \frac{1-\sqrt{5}}{2}$ です。

対角化 $\bm{M} = \bm{PDP}^{-1}$ を使って $\bm{M}^n$ を計算すると、ビネの公式が得られます。

$$ F_n = \frac{\phi^n – \hat{\phi}^n}{\sqrt{5}} $$

連立線形微分方程式

定係数の連立線形微分方程式

$$ \dot{\bm{x}} = \bm{Ax}, \quad \bm{x}(0) = \bm{x}_0 $$

に対して、$\bm{A} = \bm{PDP}^{-1}$ のとき $\bm{y} = \bm{P}^{-1}\bm{x}$ と変数変換すると

$$ \dot{\bm{y}} = \bm{Dy} $$

これは各成分が分離した $\dot{y}_i = \lambda_i y_i$ であり、解は $y_i(t) = y_i(0) e^{\lambda_i t}$ です。

元の変数に戻すと

$$ \bm{x}(t) = \bm{P} \begin{pmatrix} e^{\lambda_1 t} & & \\ & \ddots & \\ & & e^{\lambda_n t} \end{pmatrix} \bm{P}^{-1} \bm{x}_0 = e^{\bm{A}t} \bm{x}_0 $$

ここで $e^{\bm{A}t} = \bm{P} e^{\bm{D}t} \bm{P}^{-1}$ は行列指数関数です。対角化によって行列指数関数が簡単に計算できます。

マルコフ連鎖の定常分布

確率遷移行列 $\bm{T}$ で定義されるマルコフ連鎖の $n$ ステップ後の状態分布は $\bm{T}^n \bm{p}_0$ で計算されます。$\bm{T}$ を対角化すれば $\bm{T}^n$ を効率的に計算でき、$n \to \infty$ での定常分布は固有値1に対応する固有ベクトルから得られます。

対角化の応用を見てきましたが、全ての行列が対角化できるわけではありません。対角化不可能な行列をどう扱うかを見ていきましょう。

対角化不可能な行列とジョルダン標準形

ジョルダン標準形の動機

対角化不可能な行列 $\bm{B} = \begin{pmatrix} 2 & 1 \\ 0 & 2 \end{pmatrix}$ を考えます。この行列は「対角行列に最も近い形」にはできますが、完全な対角行列にはなりません。

ジョルダン標準形は、対角化不可能な行列に対する「次善の標準形」です。対角成分に固有値を並べ、対角の一つ上に0または1を置く形です。

ジョルダンブロック

ジョルダンブロック(Jordan block)$\bm{J}_k(\lambda)$ は $k \times k$ の行列で

$$ \bm{J}_k(\lambda) = \begin{pmatrix} \lambda & 1 & & \\ & \lambda & \ddots & \\ & & \ddots & 1 \\ & & & \lambda \end{pmatrix} $$

対角成分が固有値 $\lambda$、超対角(対角の一つ上)が1、それ以外が0の行列です。サイズ1のジョルダンブロックはスカラー $\lambda$ そのものです。

ジョルダン標準形の定義

任意の $n \times n$ 行列 $\bm{A}$ に対して、正則行列 $\bm{P}$ が存在して

$$ \bm{P}^{-1}\bm{A}\bm{P} = \bm{J} = \begin{pmatrix} \bm{J}_{k_1}(\lambda_1) & & \\ & \ddots & \\ & & \bm{J}_{k_r}(\lambda_r) \end{pmatrix} $$

と変換できます。これがジョルダン標準形です。$k_1 + k_2 + \cdots + k_r = n$ であり、ジョルダンブロックの配置は(順序を除いて)一意です。

行列が対角化可能な場合、全てのジョルダンブロックがサイズ1であり、ジョルダン標準形は対角行列に一致します。つまり、対角化はジョルダン標準形の特別な場合です。

ジョルダン標準形の具体例

$$ \bm{A} = \begin{pmatrix} 5 & 4 & 2 & 1 \\ 0 & 1 & -1 & -1 \\ -1 & -1 & 3 & 0 \\ 1 & 1 & -1 & 2 \end{pmatrix} $$

この行列の固有値が $\lambda_1 = 4$($m_a = 2$, $m_g = 1$)と $\lambda_2 = 2$($m_a = 2$, $m_g = 2$)の場合、ジョルダン標準形は

$$ \bm{J} = \begin{pmatrix} 4 & 1 & 0 & 0 \\ 0 & 4 & 0 & 0 \\ 0 & 0 & 2 & 0 \\ 0 & 0 & 0 & 2 \end{pmatrix} $$

$\lambda_1 = 4$ は $m_g < m_a$ なのでサイズ2のジョルダンブロック、$\lambda_2 = 2$ は $m_g = m_a$ なので2つのサイズ1のブロック(対角化可能)になっています。

ジョルダン標準形でのべき乗

ジョルダンブロックのべき乗は

$$ \bm{J}_k(\lambda)^n = \begin{pmatrix} \lambda^n & \binom{n}{1}\lambda^{n-1} & \binom{n}{2}\lambda^{n-2} & \cdots \\ & \lambda^n & \binom{n}{1}\lambda^{n-1} & \cdots \\ & & \ddots & \ddots \\ & & & \lambda^n \end{pmatrix} $$

二項係数 $\binom{n}{k}$ が現れるのが特徴で、$|\lambda| < 1$ のとき $\bm{J}_k(\lambda)^n \to \bm{0}$ ですが、収束の速度は対角行列のべき乗($\lambda^n$ のみ)より遅くなります。

理論の整理が一通り済んだので、Pythonで実装・可視化して理解を深めましょう。

Pythonでの実装と可視化

対角化の実装と検証

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import FancyArrowPatch

def diagonalize(A):
    """行列を対角化する(可能な場合)"""
    eigenvalues, P = np.linalg.eig(A)
    D = np.diag(eigenvalues)

    # 検証: A = P D P^{-1}
    A_reconstructed = P @ D @ np.linalg.inv(P)
    error = np.max(np.abs(A - A_reconstructed))

    return P, D, error

# 例1: 対角化可能な行列
A1 = np.array([[5, 4], [1, 2]], dtype=float)
P1, D1, err1 = diagonalize(A1)

print("=== 例1: 対角化可能 ===")
print(f"A =\n{A1}")
print(f"固有値: {np.diag(D1)}")
print(f"P =\n{P1}")
print(f"再構成誤差: {err1:.2e}\n")

# 例2: 対角化不可能な行列
A2 = np.array([[2, 1], [0, 2]], dtype=float)
eigenvalues2, eigenvectors2 = np.linalg.eig(A2)
print("=== 例2: 対角化不可能(ジョルダンブロック) ===")
print(f"A =\n{A2}")
print(f"固有値: {eigenvalues2}")
print(f"固有ベクトル:\n{eigenvectors2}")
print("注: 固有ベクトルが1つしかない(線形独立な固有ベクトルが不足)")

例1では対角化が成功し、再構成誤差が機械精度であることを確認できます。例2では数値的に固有ベクトルが得られますが、実際には線形独立な固有ベクトルが1つしかないため対角化不可能です。

対角化の幾何学的意味の可視化

fig, axes = plt.subplots(1, 3, figsize=(16, 5))

# (a) 対角化可能な行列の変換
ax = axes[0]
A = np.array([[2, 1], [1, 2]], dtype=float)
eigenvalues, P = np.linalg.eig(A)

theta = np.linspace(0, 2 * np.pi, 200)
circle = np.array([np.cos(theta), np.sin(theta)])

# 元の基底での変換
transformed = A @ circle
ax.plot(circle[0], circle[1], 'b-', linewidth=1, alpha=0.5, label='Unit circle')
ax.plot(transformed[0], transformed[1], 'r-', linewidth=2, label='$Ax$')

# 固有ベクトル方向
for i in range(2):
    v = P[:, i]
    lam = eigenvalues[i]
    ax.annotate('', xy=v*lam, xytext=[0,0],
                arrowprops=dict(arrowstyle='->', color='green', lw=2))
    ax.annotate('', xy=v, xytext=[0,0],
                arrowprops=dict(arrowstyle='->', color='green', lw=1, linestyle='--'))

ax.set_xlim(-4, 4)
ax.set_ylim(-4, 4)
ax.set_aspect('equal')
ax.set_title('Diagonalizable: $A = PDP^{-1}$', fontsize=13)
ax.legend(fontsize=9)
ax.grid(True, alpha=0.3)

# (b) 対角化不可能な行列の変換
ax = axes[1]
B = np.array([[2, 1], [0, 2]], dtype=float)

transformed_B = B @ circle
ax.plot(circle[0], circle[1], 'b-', linewidth=1, alpha=0.5, label='Unit circle')
ax.plot(transformed_B[0], transformed_B[1], 'r-', linewidth=2, label='$Bx$')

# 唯一の固有ベクトル方向
v_only = np.array([1, 0])
ax.annotate('', xy=v_only*2, xytext=[0,0],
            arrowprops=dict(arrowstyle='->', color='green', lw=2))
ax.text(2.2, 0.1, '$\\lambda=2$', fontsize=12, color='green')
ax.text(0.5, 1.5, 'Shear!', fontsize=14, color='red', fontweight='bold')

ax.set_xlim(-4, 4)
ax.set_ylim(-4, 4)
ax.set_aspect('equal')
ax.set_title('Non-diagonalizable: Jordan block', fontsize=13)
ax.legend(fontsize=9)
ax.grid(True, alpha=0.3)

# (c) 行列のべき乗の比較
ax = axes[2]
k_values = np.arange(0, 15)

# 対角化可能: 固有値 0.9, 0.5
A_stable = np.array([[0.7, 0.2], [0.0, 0.5]])
# ジョルダンブロック: 固有値 0.9 (重複度2)
J_block = np.array([[0.9, 1.0], [0.0, 0.9]])

norms_diag = [np.linalg.norm(np.linalg.matrix_power(A_stable, k), ord=2) for k in k_values]
norms_jordan = [np.linalg.norm(np.linalg.matrix_power(J_block, k), ord=2) for k in k_values]
norms_diag_ref = [0.7**k for k in k_values]

ax.semilogy(k_values, norms_diag, 'bo-', markersize=6, linewidth=2,
            label='Diag: $\\lambda=0.7, 0.5$')
ax.semilogy(k_values, norms_jordan, 'rs-', markersize=6, linewidth=2,
            label='Jordan: $\\lambda=0.9$ (2x2 block)')
ax.semilogy(k_values, norms_diag_ref, 'b--', alpha=0.5,
            label='$0.7^k$ reference')

ax.set_xlabel('$k$', fontsize=12)
ax.set_ylabel('$\\|A^k\\|_2$', fontsize=12)
ax.set_title('Matrix Power Decay', fontsize=13)
ax.legend(fontsize=9)
ax.grid(True, alpha=0.3, which='both')

plt.tight_layout()
plt.savefig('matrix_diagonalization.png', dpi=150, bbox_inches='tight')
plt.show()

このグラフから、対角化の幾何学的意味と影響が読み取れます。

  1. 左図(対角化可能な行列): 単位円が楕円に変換され、固有ベクトル方向(緑の矢印)が楕円の主軸に一致しています。固有ベクトルの方向では純粋にスケーリング(伸縮)のみが起き、せん断は起きません。対角化とは、この「純粋なスケーリング軸」を見つけることです

  2. 中央図(対角化不可能な行列): 単位円が平行四辺形のように歪んだ楕円に変換されています。固有ベクトルは1つしかなく($x$ 軸方向)、$y$ 方向にせん断が入っています。「Shear」と書かれた部分が対角化不可能性の幾何学的な現れです

  3. 右図(べき乗の減衰比較): 対角化可能な行列のべき乗は固有値の指数的減衰 $\lambda_{\max}^k$ に従いますが、ジョルダンブロックの場合は $k\lambda^{k-1}$ の項が加わるため、初期の減衰が遅くなります。最終的にはどちらも0に収束しますが、過渡的な振る舞いが異なります

連立微分方程式のシミュレーション

fig, axes = plt.subplots(1, 2, figsize=(14, 6))

# 対角化可能な場合: 安定な渦(複素固有値)
A_ode = np.array([[-0.5, 2], [-2, -0.5]])
eigenvalues_ode = np.linalg.eigvals(A_ode)
print(f"微分方程式の固有値: {eigenvalues_ode}")

# 相平面のプロット
ax = axes[0]
t = np.linspace(0, 10, 500)
x0_list = [[1, 0], [0, 1], [-1, 0], [0, -1],
           [1.5, 0.5], [-0.5, 1.5]]

from scipy.linalg import expm

for x0 in x0_list:
    x0 = np.array(x0)
    trajectory = np.array([expm(A_ode * ti) @ x0 for ti in t])
    ax.plot(trajectory[:, 0], trajectory[:, 1], linewidth=1.5)
    ax.plot(x0[0], x0[1], 'ko', markersize=4)

# ベクトル場
xx, yy = np.meshgrid(np.linspace(-2, 2, 12), np.linspace(-2, 2, 12))
dx = A_ode[0, 0] * xx + A_ode[0, 1] * yy
dy = A_ode[1, 0] * xx + A_ode[1, 1] * yy
ax.quiver(xx, yy, dx, dy, alpha=0.3, color='gray')

ax.set_xlabel('$x_1$', fontsize=12)
ax.set_ylabel('$x_2$', fontsize=12)
ax.set_title(f'Stable spiral ($\\lambda = {eigenvalues_ode[0]:.2f}$)', fontsize=13)
ax.set_xlim(-2, 2)
ax.set_ylim(-2, 2)
ax.set_aspect('equal')
ax.grid(True, alpha=0.3)

# 時間発展
ax = axes[1]
x0 = np.array([1.5, 0.5])
trajectory = np.array([expm(A_ode * ti) @ x0 for ti in t])

ax.plot(t, trajectory[:, 0], 'b-', linewidth=2, label='$x_1(t)$')
ax.plot(t, trajectory[:, 1], 'r-', linewidth=2, label='$x_2(t)$')

# 包絡線(減衰)
decay = np.abs(x0[0]) * np.exp(eigenvalues_ode[0].real * t)
ax.plot(t, decay, 'k--', alpha=0.5, label=f'$e^{{{eigenvalues_ode[0].real:.1f}t}}$')
ax.plot(t, -decay, 'k--', alpha=0.5)

ax.set_xlabel('$t$', fontsize=12)
ax.set_ylabel('$x(t)$', fontsize=12)
ax.set_title('Time Evolution', fontsize=13)
ax.legend(fontsize=10)
ax.grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig('diagonalization_ode.png', dpi=150, bbox_inches='tight')
plt.show()

このグラフから、対角化と微分方程式の関係が確認できます。

  1. 左図(相平面): 固有値の実部が負($-0.5$)なので全ての軌道は原点に向かって螺旋状に収束しています。虚部($\pm 2i$)が振動を、実部が減衰を生み出しています。ベクトル場(灰色矢印)が軌道の接線方向と一致していることも確認できます

  2. 右図(時間発展): 各成分 $x_1(t), x_2(t)$ が振動しながら減衰しています。減衰の包絡線が $e^{-0.5t}$(黒破線)に一致しており、固有値の実部が減衰率を決めていることが数値的にも確認できます

対角化と他の行列分解の関係

対角化は行列分解の体系の中で重要な位置を占めています。

分解 条件 特徴
対角化 $n$ 個の線形独立な固有ベクトル $\bm{A} = \bm{PDP}^{-1}$ 最も簡単な形
スペクトル分解 実対称行列 $\bm{A} = \bm{QDQ}^T$ $\bm{Q}$ が直交行列
ジョルダン標準形 任意の正方行列 $\bm{A} = \bm{PJP}^{-1}$ 常に存在
特異値分解 任意の行列 $\bm{A} = \bm{U\Sigma V}^T$ 長方行列にも適用可能

対角化は対称行列ではスペクトル分解に特殊化され、一般の正方行列ではジョルダン標準形に一般化されます。SVDはさらに長方行列にも拡張された分解です。

まとめ

本記事では、行列の対角化について理論と応用を解説しました。

  • 対角化 $\bm{A} = \bm{PDP}^{-1}$ は、適切な基底変換で行列を対角行列に変換する操作であり、固有値分解と同じ
  • 対角化可能条件は「全ての固有値について幾何学的重複度 = 代数的重複度」が必要十分条件
  • 実用的な十分条件として「$n$ 個の異なる固有値」「対称行列」「正規行列」がある
  • 対角化不可能な行列にはジョルダン標準形が次善の標準形として存在する
  • 対角化の応用として行列のべき乗($\bm{A}^k = \bm{PD}^k\bm{P}^{-1}$)、連立微分方程式($e^{\bm{A}t}$)、マルコフ連鎖の解析が重要

次のステップとして、以下の記事も参考にしてください。