量子プログラミングの何たるかについて、MicrosoftのQ#プログラミング言語のチュートリアルを読みながら進めている。 量子プログラミングについて少しわかってみたので、一番最初のサンプルプログラムを読み解いていきたい。
参考にしているのは、これまでと同様にQ#のチュートリアルサイトだ。今回は "Writing a Quantum Program" を読みながら、量子プログラミングの一番最初のプログラムを学んでいく。
ベル状態とは
これは正直まだ理解しきっていない。しかしベルといくらいだし、量子ビットの状態がまだ確定していない状態、つまり0でも1でもない状態であると考えることができるだろう。
Q#では、量子ビットを定義して、最初にそれを初期化する処理が入っている。下記のプログラムでは、量子ビットqubits[0]
を値initial
で初期化し、M()
操作を使って量子ビットの値を測定している。
using (qubits = Qubit[1]) { for (test in 1..count) { Set (initial, qubits[0]); // 量子ビットqubits[0]を、値 initialで初期化する let res = M (qubits[0]); // Mは、量子ビットqubits[0]を測定する。これにより量子ビットqubits[0]の値は0 or 1に確定される。
当然、initial=0
ならば測定される値は0になるはずだし、initial=1
ならば測定される値は1になるはずだ。これは簡単。
Hadamard ゲートを使って量子もつれ状態を作る
次に、量子ビットにHadamardゲートを適用して、量子のもつれ状態を作る。これにより、量子ビットはかかわからない状態になってしまう。 ちなみに、Hadamardゲートというのは、行列の形式で記述すると、
$$ H=\dfrac{1}{\sqrt{2}}\begin{bmatrix}1&&1\\1&&-1\end{bmatrix} $$
量子ビットの0/1の状態から、0/1の等しい重みへの写像となるので、これで量子ビットは 0/1のどちらかわからなくなる。 さて、どっちなんだろう?次に、この量子ビットともう一つの量子ビットをCNOTで制御してみる。
Set (initial, qubits[0]); Set (Zero, qubits[1]); H(qubits[0]); CNOT(qubits[0],qubits[1]); let res = M (qubits[0]);
qubits[0]
は現在もつれ状態。qubits[1]=0
で初期化されている。
CNOTは前回説明したとおりだ。"qubits[0]が1ならば、qubits[1]を反転する、qubits[0]が0ならば、qubits[0]はそのまま"というゲートのため、
- qubits[0]=1 ならば、 qubits[1]=NOT(0)=1
- qubits[0]=0 ならば、 qubits[1]=0
となり、必ずqubits[0]=qubits[1]
となることが確認できる。
これがサンプルプログラムの最後の出力に反映されている。
using (qubits = Qubit[2]) { for (test in 1..count) { Set (initial, qubits[0]); Set (Zero, qubits[1]); H(qubits[0]); CNOT(qubits[0],qubits[1]); let res = M (qubits[0]); if (M (qubits[1]) == res) { set agree = agree + 1; } // Count the number of ones we saw: if (res == One) { set numOnes = numOnes + 1; } }
出力結果は以下だ。注目すべきなのは以下の2点。
- qubits[0]の状態は、Hゲートの作用により確率1/2で0か1のどちらかに転んでいる。
- ただし、qubits[1]の状態は、CNOTの作用により必ずqubits[0]と同じ値に転がっている。つまり、agreeは常に真となっている。
Init:Zero 0s=499 1s=501 agree=1000 Init:One 0s=490 1s=510 agree=1000
なるほど、ここまでは理解できた。次に、Teleportのプログラム解読に取り組みたい。