前置き
行列もベクトル空間の定義を満たすので、ベクトルと見なすことが出来ます。Fortranに慣れていれば、多次元配列はメモリーに1次元に並んでいるだけなので、行列を一本のベクトルと見なすこと有りかなと納得できると思います。
そうなると、行列に内積を考えて、ただのベクトル空間から計量ベクトル空間に進みたい気持ちも湧いてくるというものです。ヒルベルト=シュミット型の内積は、そういう二つの行列の間の内積です。定義は、
<A|B>={\rm Tr}(A^*B)
のようになっています。ここで$A^*$は行列$A$のエルミート共役です。
これは、見かけは面倒ですが、実際は行列$A$の複素共役と行列$B$の対応する各成分の積の和になります。つまり、行列を一次元ベクトルにしたとき、普通のベクトルの内積と一致します。
{\rm Tr}(A^*B)=\sum_{i, j}(\bar{A}_{i,j})({B}_{i,j})
成分で書いてある方が単純ですが、Trace を使って書いてあると結果が基底に依らないことが明白になって、好ましいと思われます。
計算での確認
プログラム
module m_subs
implicit none
contains
complex function Hilbert_Schmidt(c, d)
complex, intent(in) :: c(:, :), d(:, :)
Hilbert_Schmidt = trace(matmul(Hermitian_Conjugate(c), d))
end function Hilbert_Schmidt
function Hermitian_Conjugate(c)
complex, intent(in) :: c(:, :)
complex, allocatable :: Hermitian_Conjugate(:, :)
Hermitian_Conjugate = transpose(conjg(c))
end function Hermitian_Conjugate
complex function trace(c)
complex, intent(in) :: c(:, :)
integer :: i
trace = sum( [(c(i, i), i = 1, size(c, 1))] )
end function trace
end module m_subs
program HS
use m_subs
implicit none
integer, parameter :: n = 10
complex :: a(n, n), b(n, n), c, d, e
complex, allocatable :: s(:), t(:)
real :: x(n, n), y(n, n)
call random_seed()
call random_number(x)
call random_number(y)
a = cmplx(x, y)
call random_number(x)
call random_number(y)
b = cmplx(x, y)
s = reshape(a, [size(a)]) ! 1-dimensional array of size n^2
t = reshape(b, [size(b)]) ! 1-dimensional array of size n^2
c = Hilbert_Schmidt(a, b) ! Trace(A* B)
d = sum(conjg(a) * b) ! sum (A_ij)* (B_ij)
e = dot_product(s, t) ! inner-product(A, B)
print *, c, d, abs(c - d) / abs(c)
print *, d, e, abs(d - e) / abs(d)
end program HS
実行結果
乱数で行列を生成しているので複数回実行してみます。単精度の範囲で結果が一致しているのが分かります。
(51.86407,-2.380983) (51.86405,-2.380983) 2.9404126E-07
(51.86405,-2.380983) (51.86405,-2.380983) 0.000000
続行するには何かキーを押してください . . .
(54.13935,4.021431) (54.13936,4.021432) 2.8161699E-07
(54.13936,4.021432) (54.13936,4.021432) 0.000000
続行するには何かキーを押してください . . .
(48.62010,5.180973) (48.62009,5.180972) 7.8624716E-08
(48.62009,5.180972) (48.62009,5.180972) 0.000000
続行するには何かキーを押してください . . .