ユニタリ行列

ユニタリ行列

 

ユニタリ行列

 実空間 $\mathbb{R}^n$ の 直交行列 $Q$ は、複素空間 $\mathbb{C}^n$ において ユニタリ行列 $U$ として拡張定義されます。ユニタリ行列は
 
\[U^{\dagger}U=UU^{\dagger}=I\tag{1}\]
を満たす正方行列です。$U$ が実行列であれば $U^{\dagger}=U^T$ なので、(1) は直交行列 $Q$ の定義を包含します。たとえば、前回記事で扱ったエルミート行列
 
\[H=\begin{bmatrix}2&1-i\\1+i&3\end{bmatrix}\tag{2}\]
を対角化する行列
 
\[\left[\begin{matrix}- \cfrac{\sqrt{6}}{3} & \cfrac{\sqrt{3}}{3}\\
\cfrac{\sqrt{6} \left(1 + i\right)}{6} & \cfrac{\sqrt{3} \left(1 + i\right)}{3}\end{matrix}\right]\tag{3}\]
はノルム $1$ の列ベクトル同士が直交するので ユニタリ行列 です。

 列ベクトル同士が直交する任意の行列は、正規化して各々のベクトルのノルムを $1$ に揃えることで、ユニタリ行列にすることができます。たとえば、
 
\[A=\begin{bmatrix}-2&1\\1+i&1+i\end{bmatrix}\tag{4}\]
は列ベクトル同士が直交する行列です。これを正規化して、ユニタリ行列にしてみましょう。

# python_unitary

# In[1]

import numpy as np
from scipy import linalg
np.set_printoptions(precision=3)

# 共役転置関数
def hermitian(arr):
    return np.conjugate(arr.T)

# 正規化関数
def normalize(arr, axis=0):
    norm = linalg.norm(arr, axis=axis)
    return arr / norm

A = np.array([[-2, 1],
              [1+1j, 1+1j]])

# Aを正規化してユニタリ行列にする
U = normalize(A)

# ユニタリ行列が満たすべき性質を確認
X1 = hermitian(U) @ U
X2 = U @ hermitian(U)

print("U:\n{}\n".format(U))
print("(U^†)U:\n{}\n".format(X1))
print("U(U^†):\n{}".format(X2))
U:
[[-0.816+0.j     0.577+0.j   ]
 [ 0.408+0.408j  0.577+0.577j]]

(U^†)U:
[[1.+0.j 0.+0.j]
 [0.+0.j 1.+0.j]]

U(U^†):
[[ 1.000e+00+0.000e+00j -2.946e-18+2.946e-18j]
 [-2.946e-18-2.946e-18j  1.000e+00+0.000e+00j]]

 $U^{\dagger}U=UU^{\dagger}=I$ を満たすので、ユニタリ行列 $U$ の随伴行列 $U^{\dagger}$ は $U$ の逆行列です。
 
\[U^{\dagger}=U^{-1}\tag{5}\]
 (4) を正規化して作ったユニタリ行列の随伴行列と逆行列を計算して、両者が一致することを確認してみましょう。

# In[2]

U_H = hermitian(U)
U_inv = linalg.inv(U)

print("Uの随伴行列:\n{}\n".format(U_H))
print("Uの逆行列:\n{}".format(U_inv))
Uの随伴行列:
[[-0.816-0.j     0.408-0.408j]
 [ 0.577-0.j     0.577-0.577j]]

Uの逆行列:
[[-0.816+0.j     0.408-0.408j]
 [ 0.577+0.j     0.577-0.577j]]

 任意のベクトル $\boldsymbol{x}$ にユニタリ行列 $U$ をかけたとき、$U\boldsymbol{x}$ のノルムは
 
\[(U\boldsymbol{x}, U\boldsymbol{x})=(U\boldsymbol{x})^{\dagger}U\boldsymbol{x}
=\boldsymbol{x}^{\dagger}U^{\dagger}U\boldsymbol{x}=\boldsymbol{x}^{\dagger}\boldsymbol{x}
=(\boldsymbol{x},\boldsymbol{x})\tag{6}\]
となって、ユニタリ行列による線型変換 (ユニタリ変換) がベクトルのノルムを保持する等長変換であることがわかります (実数空間の直交行列 $Q$ と同じです)。すなわち、
 
\[\parallel U\boldsymbol{x} \parallel=\parallel \boldsymbol{x} \parallel\tag{7}\]
が成り立ちます。一例として、複素ベクトル
 
\[\boldsymbol{z}=\begin{bmatrix}3+5i\\2-i\end{bmatrix}\tag{8}\]
について、自身のノルムと $Uz$ のノルムが一致することを確認してみます。

# In[3]

# 複素ベクトルを定義
z = np.array([3 + 5j, 2-1j])

# zのノルムを計算
z_norm = linalg.norm(z)

# zにユニタリ行列Uを作用させる
Uz = U @ z

# Uzのノルムを計算
Uz_norm = linalg.norm(Uz)

print(z_norm)
print(Uz_norm)
6.244997998398398
6.244997998398399

 ユニタリ行列 $U$ の固有値が $\lambda$、すなわち $U\boldsymbol{x}=\lambda\boldsymbol{x}$ であるとき、$\parallel\lambda\boldsymbol{x}\parallel=\boldsymbol{x}$ より、$\parallel\lambda\parallel=1$ となります。

# In[4]

# ユニタリ行列Uの固有値
eigvals = linalg.eig(U)[0]

# 固有値の絶対値
norm = np.abs(eigvals)

print("Uの固有値:\n{}\n".format(eigvals))
print("固有値の絶対値:\n{}".format(norm))
Uの固有値:
[-0.997-0.075j  0.758+0.652j]

固有値の絶対値:
[1. 1.]

[参考文献]・ Wikipedia ・『ストラング:線形代数イントロダクション』

【プログラミング日記】OneDrive に保存したテキストを iPhone で開いてみると文字化けしました。ファイルを ANSI で保存していたのが原因でした。UTF-8 で保存し直すと無事に問題解決。まあ、それだけのことなんですけど、Windows 10 ではデフォルトで UTF-8 になっているようです。今や UTF-8 が世界標準の文字コードなのんでしょうかね。いまだに Windows 7 なんて使ってる私はこうやって時代に取り残されていくのかもしれないですね (← ていうか、セキュリティを心配しろよ)。