diagonalize2d.py テクニカルドキュメント
プログラムの動作
diagonalize2d.py は、ユーザーが指定した2x2の実数行列 \(S\) による2次元空間における線形変換を視覚化し、その行列が実数上で対角化可能であるかどうかの解析を行うPythonスクリプトです。
主な機能:
入力行列の表示: コマンドライン引数として与えられた2x2行列 \(S\) の内容を標準出力に表示します。
標準基底の変換と表示: 標準基底ベクトル \(\mathbf{a}_1 = (1, 0)^T\) と \(\mathbf{a}_2 = (0, 1)^T\)、およびそれらが \(S\) によって変換された画像 \(\mathbf{Sa}_1\), \(\mathbf{Sa}_2\) を計算し、それぞれの角度や平行性を標準出力に表示します。
対角化可能性の判定: 行列 \(S\) の固有値と固有ベクトルを計算し、実数上で対角化可能であるかを判定します。
固有値に虚数成分が含まれる場合、実数上で対角化不可能と判断します。
実数固有値が得られても、対応する固有ベクトルが線形独立でない場合(例:ジョルダンブロックを持つ行列)、実数上で対角化不可能と判断します。
実固有ベクトルによる対角化の表示: \(S\) が実数上で対角化可能である場合、計算された実固有ベクトル \(\mathbf{v}_1, \mathbf{v}_2\) を新しい基底として表示します。これらの固有ベクトルとその \(S\) による変換後の画像 \(\mathbf{Sv}_1, \mathbf{Sv}_2\) を出力します。
基底間の角度比較: 標準基底と、実数で対角化可能な場合は固有ベクトルからなる対角化基底とのなす角度を比較し、その性質(対称行列の場合は直交性など)についてコメントを出力します。
変換の視覚化:
matplotlibを用いて、標準基底とその変換後のベクトル、および対角化可能な場合は固有ベクトルとその変換後のベクトルを2次元平面上に描画し、画像ファイルとして保存します。また、GUIウィンドウでも表示します。
解決する課題:
線形代数における抽象的な概念である「行列の線形変換」「固有値と固有ベクトル」「行列の対角化」を、具体的な2次元ベクトルの動きとして視覚的に表現することで、これらの概念への理解を深めることを目的としています。特に、実数上で対角化可能であるか、そしてその際の基底が直交するかどうかといった性質を直感的に把握するのに役立ちます。
原理
このプログラムは、線形代数の以下の基本的な原理に基づいています。
1. 線形変換
2x2行列 \(S = \begin{pmatrix} S_{11} & S_{12} \\ S_{21} & S_{22} \end{pmatrix}\) は、2次元のベクトル \(\mathbf{x} = \begin{pmatrix} x \\ y \end{pmatrix}\) を別のベクトル \(\mathbf{Sx}\) に変換する線形変換を表します。
2. 固有値と固有ベクトル
ベクトル \(\mathbf{v}\) が行列 \(S\) の固有ベクトルであるとは、 \(S\) による変換後もその方向が変わらず、定数倍されるだけである場合に言います。この定数を固有値 \(\lambda\) と呼びます。数式で表すと以下のようになります。
これは、\((\mathbf{S} - \lambda\mathbf{I})\mathbf{v} = \mathbf{0}\) と書き換えられ、非自明な解 \(\mathbf{v}\) が存在するためには、行列 \((\mathbf{S} - \lambda\mathbf{I})\) が正則でない、すなわちその行列式がゼロである必要があります。
この方程式は特性方程式と呼ばれ、\(\lambda\) についての多項式方程式となり、その根が固有値です。
3. 対角化
行列 \(S\) が対角化可能であるとは、ある正則行列 \(P\) が存在して、\(P^{-1}SP\) が対角行列 \(D\) になることを言います。
ここで、対角行列 \(D\) の対角成分は \(S\) の固有値であり、行列 \(P\) の列ベクトルは対応する \(S\) の線形独立な固有ベクトルです。
実数上での対角化: プログラムは、固有値がすべて実数であり、かつ対応する固有ベクトルが線形独立である場合に「実数上で対角化可能」と判断します。
複素固有値を持つ行列(例:回転行列)は実数上で対角化できません。
同じ固有値に対して線形独立な固有ベクトルが十分な数だけ存在しない場合(例:ジョルダン標準形が必要な場合)も、実数上で対角化できません。
4. 角度計算
ベクトルの角度 (
angle_deg): 2次元ベクトル \(\mathbf{v} = (v_x, v_y)^T\) の正のx軸からの角度は、math.atan2(vy, vx)関数を使って計算されます。この関数は、符号を考慮して \((-180^\circ, 180^\circ]\) の範囲で正確な角度を返します。2ベクトル間の角度 (
angle_between_deg): 2つの非ゼロベクトル \(\mathbf{v}_1\) と \(\mathbf{v}_2\) のなす角度 \(\theta\) は、内積の定義から導かれます。\[ \mathbf{v}_1 \cdot \mathbf{v}_2 = \|\mathbf{v}_1\| \|\mathbf{v}_2\| \cos \theta \]これにより、\(\cos \theta\) を計算し、
math.acosを用いて \(\theta\) を得ます。\[ \cos \theta = \frac{\mathbf{v}_1 \cdot \mathbf{v}_2}{\|\mathbf{v}_1\| \|\mathbf{v}_2\|} \]プログラムでは、まず各ベクトルを単位ベクトルに正規化し、その内積を計算することで \(\cos \theta\) を得ています。
5. 平行性判定
2つの2次元ベクトル \(\mathbf{v}_1 = (v_{1x}, v_{1y})^T\) と \(\mathbf{v}_2 = (v_{2x}, v_{2y})^T\) が平行であるかどうかは、それらの外積のZ成分がゼロであるかどうかで判定できます。
プログラムでは、浮動小数点数の誤差を考慮して、この値が許容誤差 tol (デフォルト 1e-9) よりも小さい場合に平行と判断しています。
必要な非標準ライブラリとインストール方法
このプログラムは、数値計算とグラフ描画のために以下の非標準ライブラリを使用します。
numpy: Pythonで数値計算を効率的に行うためのライブラリです。特に、多次元配列(行列)の操作や線形代数演算(固有値分解など)に利用されます。matplotlib: Pythonでグラフや図を作成するためのライブラリです。このプログラムでは、ベクトルの視覚化に使用されます。
これらのライブラリは、Pythonのパッケージマネージャである pip を使用してインストールできます。
pip install numpy matplotlib
必要な入力ファイル
このプログラムは、コマンドライン引数として直接行列の要素を受け取るため、特別な入力ファイルは必要ありません。
生成される出力ファイル
プログラムの実行により、以下の画像ファイルが生成されます。
ファイル名:
diagonalize2d.png(デフォルト)。--saveオプションで任意のファイル名を指定できます。
内容:
左側のサブプロット: 2x2行列 \(S\) による標準基底ベクトル \(\mathbf{a}_1 = (1, 0)^T\), \(\mathbf{a}_2 = (0, 1)^T\) の変換を視覚化します。黒い矢印で元の基底ベクトル、赤い矢印で変換後の画像 \(\mathbf{Sa}_1\), \(\mathbf{Sa}_2\) が描かれます。
右側のサブプロット:
行列 \(S\) が実数上で対角化可能な場合、実固有ベクトル \(\mathbf{v}_1, \mathbf{v}_2\) が新しい基底として描かれます(黒い矢印)。そして、それらの \(S\) による変換後の画像 \(\mathbf{Sv}_1, \mathbf{Sv}_2\) (赤い矢印)も描かれます。固有ベクトルの場合、変換後のベクトルは元のベクトルのスカラー倍(固有値倍)になるため、赤い矢印は黒い矢印と同じ方向を向いているはずです。
行列 \(S\) が実数上で対角化不可能な場合、右側のサブプロットは生成されず、左側のサブプロットのみを含む画像となります。
コマンドラインでの使用例 (Usage)
基本的な実行コマンドと引数の説明は以下の通りです。
python diagonalize2d.py S11 S12 S21 S22 [--save FILENAME]
S11,S12,S21,S22: 必須引数。2x2行列の各要素を表す浮動小数点数です。行列は次のように構成されます。 $\( S = \begin{pmatrix} S_{11} & S_{12} \\ S_{21} & S_{22} \end{pmatrix} \)$--save FILENAME: オプション引数。生成される画像ファイルのファイル名を指定します。指定しない場合、デフォルトでdiagonalize2d.pngが使用されます。
コマンドラインでの具体的な使用例
例1: 対称行列 (直交対角化)
対称行列は常に実数上で対角化可能であり、その固有ベクトルは直交します。
行列: \(S = \begin{pmatrix} 2 & 1 \\ 1 & 2 \end{pmatrix}\)
コマンド:
python diagonalize2d.py 2 1 1 2 --save symmetric_example.png
実行結果の説明:
コンソールには、行列 \(S\) の値、標準基底とその変換、対角化の診断結果、固有値と固有ベクトル、そして標準基底と固有ベクトル基底のなす角度が表示されます。
この場合、
Symmetric matrix? Trueと表示され、対角化基底のなす角度はangle(diagonalizing basis) = 90.000000 degとなります。P^{-1} S Pは対角行列 \(\begin{pmatrix} 1 & 0 \\ 0 & 3 \end{pmatrix}\) と表示されます(固有値の順序によって異なる場合があります)。symmetric_example.pngという画像ファイルが生成され、左側には標準基底とその変換、右側には直交する固有ベクトルとその変換(方向は変わらず長さのみ変化)が描画されます。
例2: 非対称行列 (実数で対角化可能、非直交対角化)
非対称行列でも実数上で対角化可能な場合がありますが、その固有ベクトルは一般に直交しません。
行列: \(S = \begin{pmatrix} 1 & 1 \\ 0 & 2 \end{pmatrix}\)
コマンド:
python diagonalize2d.py 1 1 0 2 --save nonsymmetric_diag_example.png
実行結果の説明:
コンソールには、行列 \(S\) の値、標準基底とその変換、対角化の診断結果、固有値と固有ベクトル、そして標準基底と固有ベクトル基底のなす角度が表示されます。
この場合、
Symmetric matrix? Falseと表示され、対角化基底のなす角度はangle(diagonalizing basis)が90度ではない値(例:45.000000 deg)となることが示されます。P^{-1} S Pは対角行列 \(\begin{pmatrix} 1 & 0 \\ 0 & 2 \end{pmatrix}\) と表示されます。nonsymmetric_diag_example.pngという画像ファイルが生成され、左側には標準基底とその変換、右側には直交しない固有ベクトルとその変換が描画されます。
例3: 実数で対角化不可能 (複素固有値)
回転行列のような特定の行列は、実数の範囲で固有ベクトルを持ちません(複素固有値を持つ)。
行列: \(S = \begin{pmatrix} 0 & -1 \\ 1 & 0 \end{pmatrix}\) (90度回転行列)
コマンド:
python diagonalize2d.py 0 -1 1 0 --save complex_eigenvalues_example.png
実行結果の説明:
コンソールには、行列 \(S\) の値、標準基底とその変換、対角化の診断結果が表示されます。
この場合、
Complex eigenvalues: no real principal axes.というメッセージが出力され、実数で対角化できないことが明示されます。固有値は複素数(例:
0.+1.j,0.-1.jに対応する値)として表示されます。complex_eigenvalues_example.pngという画像ファイルが生成され、標準基底とその変換のみが描画されます。実固有ベクトルが存在しないため、対角化基底のサブプロットは生成されません。