はじめに
量子プログラムを書いてみようと思います。
京都大学・QunaSys社のオープンソースライブラリのQulacsを使って、練習と勉強がてらToffoliゲートをPythonで実装してみました。
Qulacsについては
PythonフレームワークのQulacsで量子コンピュータに触れてみる
にも記事があるので、参考にしてください。
Toffoliゲート
量子回路上で$|x,y,z\rangle\mapsto |x,y,x\wedge y \oplus z\rangle~(x,y,z=0,1)$を実現します。
したがって$z=0$とすれば、3番目の量子ビットの状態を観測することにより、1,2番目の量子状態のANDが得られるので、それを見てみます。
実装ですが、適当にググって出てきた
Realization of the quantum Toffoli gate
のp.5にToffoliを実現する回路図がありますが、面倒くさいので今回はToffoliゲートを表すユニタリー変換を実装します。
表現行列は以下になります:
\begin{pmatrix}
1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\
0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\
0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\
0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 \\
0 & 0 & 0 & 0 & 0 & 0 & 1 & 0
\end{pmatrix}
コード
Qulacs公式リファレンス見ながら書いてみます。
まず、必要なモジュールをインポートします。
from qulacs import QuantumState
from qulacs import QuantumCircuit
from qulacs import Observable
from qulacs.gate import DenseMatrix
Toffoliゲートは3量子ビットの回路なので、その設定と入力状態を設定します。
この例では$|110\rangle$を入力します。
したがって、出力は量子ビット3を観測するので、$|1\rangle$となるはずです。
# 量子ビット数3(0,1,2の3つ)
n = 3
state = QuantumState(n)
# 入力状態は|110>
state.set_computational_basis(0b110)
回路にToffoliゲートを追加。
toffoli = [
[1, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 1],
[0, 0, 0, 0, 0, 0, 1, 0]
]
gate = DenseMatrix([0, 1, 2], toffoli)
circuit.add_gate(gate)
量子状態を更新します。
circuit.update_quantum_state(state)
観測のため、オブザーバブルを設定します。
$Z$方向の上下を観測するので、Pauli $Z$で観測します。
ここちょっと謎なんですが、リファレンス読む限り、下記'Z 0'と書いている部分は'Z 2'だと思うのですが、ゲートなし3量子回路で書いてみて確認したら'Z 0'じゃないと想定した動作をしませんでした。これだけ数える順番逆なのかな?
# オブザーバブルの設定
# 量子ビット数3
# n = 3
observable = Observable(n)
# 量子ビット2の上下を観測
# 何故か'Z 2'ではなく'Z 0'
observable.add_operator(1.0, 'Z 0')
最後に結果を表示します。
# 量子ビット2の上下を観測
value = observable.get_expectation_value(state)
# 結果表示
value = (1.0 - value) / 2.0
# 状態ベクトル表記で出力するように細工
print('|' + str(int(value)) + '>')
結果
ちゃんと$|1\rangle$が返ってきました。
他の入力$|x,y,0\rangle$でも$|x\wedge y\rangle$が返ってきました。
まとめ
今回はToffoliゲートをPython Qulacsを使って量子プログラムを実装してみて、ちゃんとANDを返す量子回路を書くことができました。
最後に全体コードです。
# インポート
from qulacs import QuantumState
from qulacs import QuantumCircuit
from qulacs import Observable
from qulacs.gate import DenseMatrix
# 量子状態の設定
# 量子ビット数3(0,1,2の3つ)
n = 3
state = QuantumState(n)
state.set_computational_basis(0b110)
# 入力状態を表示
print('initial state: ' + str(state.get_vector()))
# 回路にToffoliゲート追加
circuit = QuantumCircuit(n)
toffoli = [
[1, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 1],
[0, 0, 0, 0, 0, 0, 1, 0]
]
gate = DenseMatrix([0, 1, 2], toffoli)
circuit.add_gate(gate)
circuit.update_quantum_state(state)
# オブザーバブルの設定
# 量子ビット数3
observable = Observable(n)
# 量子ビット2の上下を観測
# 何故か'Z 2'ではなく'Z 0'
observable.add_operator(1.0, 'Z 0')
# 量子ビット2の上下を観測
value = observable.get_expectation_value(state)
# 結果表示
value = (1.0 - value) / 2.0
print('|' + str(int(value)) + '>')