bitterharvest’s diary

A Bitter Harvestは小説の題名。作者は豪州のPeter Yeldham。苦闘の末に勝ちえた偏見からの解放は命との引換になったという悲しい物語

量子力学の初歩をHaskellで学ぶ(1):ブラとケット

前回の記事までで、量子力学Haskellで表す方法について説明してきた。まだ、初歩の初歩という段階だが、ここまでのプログラムを利用して量子力学の世界に少しだけ触れてみよう。

プログラムはすべてBitHubに登録してあるので、そこからダウンロードして利用してほしい。テストプログラムとして、ケットとブラを利用するTest0と重ね合わせを利用するTest1があるので、これを利用してほしい。

なお、量子力学での演算子Haskellでの関数との対応は以下の表のとおりである(量子力学演算子については、西野友年著『場の理論』に準拠している)。

量子力学ケットブラ
真空状態(ケット)\(|...00\dot000...>\)KetZero
真空状態(ブラ)\(<...00\dot000...|\)BraZero
区間1,2に1粒子(有)\(|...00\dot01100...>\)2 :+: 1 :+: KetZero
区間1,2に1粒子(待)\(<...00\dot01100...|\)BraZero :-: 1 :-: 2
生成演算子\(\hat{a}^\dagger_i\)i +^^+ i
消滅演算子\(\hat{a}_i\)i -^^- i
生成演算子使用例\(\hat{a}^\dagger_1|...00\dot000...>\)i +^ KetZero
生成演算子使用例\(<...00\dot000...|\hat{a}^\dagger_1\)BraZero ^+ i
消滅演算子使用例\(\hat{a}_1|...00\dot000...>\)1 -^ KetZero
消滅演算子使用例\(<...00\dot000...|\hat{a}_1\)BraZero ^- 1
内積 ^*^
内積使用例\(<...00\dot000...|...00\dot000...>\)BraZero ^*^ KetZero
状態でない\(0\)ZeroZero'
f:id:bitterharvest:20160502092414j:plain

0.復習

前の記事を読まなくても良いようにするために、簡単に復習しておこう。

量子力学では、量子の状態をケットとブラで表現する。ケットとブラは、本来は、3次元で連続な状態を表す。しかし、ここでは、量子力学の考え方を理解するために、ケットとブラは、1次元で離散的である。即ち、1次元の直線が、等間隔の格子で区切られている。

ケットは、どの格子点に粒子が存在するかで、量子の状態を表す。ケットは、左側に\(|\)の記号、右側に\(>\)の記号を有し、それらの間で、状態を表す。ここでは、0番目の格子点を表しているところの上にドットをつけ、左側に行くにしたがって番号が一つずつ下がり、右に行くにしたがって番号が一つずつ上がるようにする。

例えば、1と2番目のそれぞれに1粒子が存在する場合には、\(|...00\dot{0}1100...>\)となる。また、どこにも粒子が存在しない状態\(|...00\dot{0}00...>\)は真空状態と呼ばれる。

ケットとブラに作用するものとして、演算子が存在する。これらの演算子はケットの場合には左から、ブラの場合には右から作用する。

\(\hat{a}^\dagger_i\)は生成演算子と呼ばれる。これはケットに左から作用させると、\(i\)番目の格子点での粒子を1増やす。\(\hat{a}_i\)は消滅演算子と呼ばれ、生成演算子とは逆の働きをする。即ち、ケットに左から作用させると、\(i\)番目の格子点での粒子を1減ずる。しかし、減ずることができないとき、即ち、\(i\)番目のそれが作用させる前に0のときは、状態ではなくなる。例を挙げると、
\begin{align*}
\hat{a}^\dagger_{-2}|...00\dot{0}1100...>=&|...0010\dot{0}1100...> \\
\hat{a}_2 |...00\dot{0}1100...>=&|...00\dot{0}100...>
\end{align*}
さてもう一方のブラであるが、ケットとは共役になっていて、これも量子の状態を表す。ケットは、左側に\(<\)の記号、右側に\(|\)の記号を有し、それらの間で、状態を表す。ここでは、0番目の格子点を表しているところの上にドットをつけ、左側に行くにしたがって番号が一つずつ下がり、右に行くにしたがって番号が一つずつ上がるようにする。真空の状態は、ケットと同じように、\(<...00\dot{0}00...|\)である。

しかし、演算子は逆に働く。消滅演算子\(\hat{a}_i\)を右から作用させると、\(i\)番目の格子点での値が1増える。例えば、真空状態に\(\hat{a}_1\)を作用させると\(<...00\dot{0}00...|\hat{a}_1=<...00\dot{0}100...|\)となる。生成演算子はこれとは逆の作用をする。

なお、共役であることから次の関係が成り立つ。
\begin{align*}
(\hat{a}_{i})^\dagger=&\hat{a}^\dagger_{i} \\
(\hat{a}^\dagger_{i})^\dagger=&\hat{a}_{i} \\
(\hat{a}_{i}\hat{a}^\dagger_{k})^\dagger=&\hat{a}_{k}\hat{a}^\dagger_{i} \\
(\hat{a}^\dagger_{i}|...00\dot{0}00...>)^\dagger=&<...00\dot{0}00...|\hat{a}_{i} \\
(<...00\dot{0}00...|\hat{a}_{i})^\dagger=&\hat{a}^\dagger_{i}|...00\dot{0}00...> \\
\end{align*}

1.ケット

Teat0のプログラムをロードしてみよう。次のようになると思う。

GHCi, version 7.8.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> :cd C:\Users\xxxxxx
Prelude> :load "Test0.hs"
[1 of 4] Compiling Qtm.KetBra.Ket   ( Qtm\KetBra\Ket.hs, interpreted )
[2 of 4] Compiling Qtm.KetBra.Bra   ( Qtm\KetBra\Bra.hs, interpreted )
[3 of 4] Compiling Qtm.KetBra       ( Qtm\KetBra.hs, interpreted )
[4 of 4] Compiling Test0             ( Test0.hs, interpreted )
Ok, modules loaded: Test0, Qtm.KetBra, Qtm.KetBra.Ket, Qtm.KetBra.Bra.
*Test0> 

まずケットについてだが、test0では次の状態を用意している。
\begin{align*}
a =& |...00\dot{0}00..> \\
b =& |...00\dot{0}0100..> \\
c =& |...00\dot{0}01100..> \\
d =& |...00\dot{1}01100..> \\
e =& \hat{a}_4 \hat{a}_3 \hat{a}^\dagger_2 \hat{a}^\dagger_4 \hat{a}^\dagger_0 \hat{a}^\dagger_3|...00\dot{0}00..>
\end{align*}

それでは、それぞれのHaskellでの内部表現を見てみよう。

*Test0> a
| ...00(0)00... >
*Test0> b
,a2+| ...00(0)00... >
*Test0> c
,a3+,a2+| ...00(0)00... >
*Test0> d
,a0+,a3+,a2+| ...00(0)00... >
*Test0> e
,a2+,a0+| ...00(0)00... >

上手くいっているようである。でも、分かりにくいので、プリティー・プリントで見てみよう。

*Test0> prKet a
"|...000(0)000...>"
*Test0> prKet b
"|...00000(0)01000...>"
*Test0> prKet c
"|...000000(0)011000...>"
*Test0> prKet d
"|...000000(1)011000...>"
*Test0> prKet e
"|...00000(1)01000...>"

それでは、これらの状態を使って、少し、遊んでみよう。dの状態から始めて、生成演算子\(\hat{a}^\dagger_{-1}\),\(\hat{a}^\dagger_{-3}\),\(\hat{a}^\dagger_0\)を次々に作用させてみよう。

*Test0> prKet $ (-1) +^ d
"|...000001(1)011000...>"
*Test0> prKet $ (-3) +^ (-1) +^ d
"|...000101(1)011000...>"
*Test0> prKet $ 0 +^ (-3) +^ (-1) +^ d
"|...000101(2)011000...>"

引き続き消滅演算子\(\hat{a}_3\),\(\hat{a}_0\),\(\hat{a}_{-3}\),\(\hat{a}_4\)を次々に作用させてみよう。次のようになるが、最後は状態がなくなってしまう(これは、粒子がないところから消滅しようとしたため、である)。

*Test0> prKet $ 3 -^ 0 +^ (-3) +^ (-1) +^ d
"|...000101(2)01000...>"
*Test0> prKet $ 0 -^ 3 -^ 0 +^ (-3) +^ (-1) +^ d
"|...000101(1)01000...>"
*Test0> prKet $ (-3) -^ 0 -^ 3 -^ 0 +^ (-3) +^ (-1) +^ d
"|...00001(1)01000...>"
*Test0> prKet $ 4 -^ (-3) -^ 0 -^ 3 -^ 0 +^ (-3) +^ (-1) +^ d
"0"

2.ブラ

まずケットについてだが、test0では次の状態を用意している。
\begin{eqnarray}
a' &=& <...00\dot{0}00..| \\
b' &=& <...00\dot{0}0100..| \\
c' &=& <...00\dot{0}01100..| \\
d' &=& <...00\dot{1}01100..| \\
e' &=& <...00\dot{0}00..|\hat{a}_4 \hat{a}_3 \hat{a}_2 \hat{a}^\dagger_4 \hat{a}_0 \hat{a}^\dagger_3
\end{eqnarray}

それでは、それぞれのHaskellでの内部表現を見てみよう。

*Test0> a'
< ...00(0)00... |
*Test0> b'
< ...00(0)00... |-a2,
*Test0> c'
< ...00(0)00... |-a2,-a3,
*Test0> d'
< ...00(0)00... |-a2,-a3,-a0,
*Test0> e'
< ...00(0)00... |-a2,-a0,

上手くいっているようである。でも、分かりにくいので、プリティー・プリントで見てみよう。

*Test0> prBra a'
"<...000(0)000...|"
*Test0> prBra b'
"<...00000(0)01000...|"
*Test0> prBra c'
"<...000000(0)011000...|"
*Test0> prBra d'
"<...000000(1)011000...|"
*Test0> prBra e'
"<...00000(1)01000...|"

それでは、これらの状態を使って、少し、遊んでみよう。dの状態から始めて、消滅演算子\(\hat{a}_{-1}\),\(\hat{a}_{-3}\),\(\hat{a}_0\)を次々に作用させてみよう。

*Test0> prBra $ d' ^- (-1)
"<...000001(1)011000...|"
*Test0> prBra $ d' ^- (-1) ^- (-3)
"<...000101(1)011000...|"
*Test0> prBra $ d' ^- (-1) ^- (-3) ^- 0
"<...000101(2)011000...|"

引き続き生成演算子\(\hat{a}^\dagger_3\),\(\hat{a}^\dagger_0\),\(\hat{a}^\dagger_{-3}\),\(\hat{a}^\dagger_4\)を次々に作用させてみよう。次のようになるが、最後は状態がなくなってしまう。

*Test0> prBra $ d' ^- (-1) ^- (-3) ^- 0 ^+ 3
"<...000101(2)01000...|"
*Test0> prBra $ d' ^- (-1) ^- (-3) ^- 0 ^+ 3 ^+ 0
"<...000101(1)01000...|"
*Test0> prBra $ d' ^- (-1) ^- (-3) ^- 0 ^+ 3 ^+ 0 ^+ (-3)
"<...00001(1)01000...|"
*Test0> prBra $ d' ^- (-1) ^- (-3) ^- 0 ^+ 3 ^+ 0 ^+ (-3) ^+ 4
"0"

3.ケットとブラの内積

test0には、内積の例もある。最初は\( e = |...00000(1)01000...> \)と\( e' = <...00000(1)01000...| \)の内積\(f\)である。最後は\( e = |...000(0)000...> \)と\( e' = <...00000(1)01000...| \)との内積\(g\)である。それぞれの値を求めよう。次に示すように正しい結果が得られている。

*Test0> f
1
*Test0> g
0

最後に共役の関係を見ておこう。

*Test0> e
,a2+,a0+| ...00(0)00... >
*Test0> invK e
< ...00(0)00... |-a0,-a2,
*Test0> prBra $ invK e
"<...00000(1)01000...|"
*Test0> e'
< ...00(0)00... |-a2,-a0,
*Test0> invB e'
,a0+,a2+| ...00(0)00... >
*Test0> prKet $ invB e'
"|...00000(1)01000...>"