量子テレポーテーション
理学系研究科、情報理工研究科共通の「量子計算論」という授業で提出したレポートをもとに書いています。量子テレポーテーションの説明やQiskitを用いた実装についてはQiskit Textbookに書かれているのでそちらを参考にしてください。日本語(自動翻訳)はこちら。
EPR Pairの変更
$$
\def\bra#1{\mathinner{\left\langle{#1}\right|}}
\def\ket#1{\mathinner{\left|{#1}\right\rangle}}
\def\braket#1#2{\mathinner{\left\langle{#1}\middle|#2\right\rangle}}
$$Qiskit Textbookにもある通りEPR Pairとしては
$$
\frac{\ket{00}+\ket{11}}{\sqrt{2}}
$$が用いられますが、
$$
\frac{\ket{10}+\ket{01}}{\sqrt{2}}
$$を用いた場合にどうすれば量子テレポーテーションを行うことができるのか考えます。アリスは未知の状態$\ket{\psi}$を持ち、$\Psi^+$をボブと共有するとします。
$$
\begin{eqnarray}
\ket{\psi} &=& \alpha\ket{0} + \beta\ket{1} \
\Psi^+ &=& \frac{\ket{10}+\ket{01}}{\sqrt{2}}
\end{eqnarray}
$$量子テレポーテーション・プロトコルに従って、アリスは先ずCNOTゲートを用いて$\ket{\psi}$と$\Psi^+$をエンタングルします。$\ket{\psi_1}$がエンタングルする前、$\ket{\psi_2}$がエンタングルした後です。
$$
\begin{eqnarray}
\ket{\psi_1} &=& (\alpha\ket{0} + \beta\ket{1})\otimes
\frac{1}{\sqrt{2}}(\ket{10}+\ket{01}) \
\ket{\psi_2} &=& \frac{1}{\sqrt{2}}(\alpha\ket{010} +
\alpha\ket{001} + \beta\ket{100} + \beta\ket{111} ) \
&=& \frac{1}{\sqrt{2}}\left[
\alpha\ket{0}(\ket{10} + \ket{01})
+ \beta\ket{1}(\ket{00}+ \ket{11})
\right]
\end{eqnarray}
$$そしてアリスは$\psi$に$H$ゲートを適用します。$\ket{\psi_3}$は$H$ゲート適用後の状態です。
$$
\begin{eqnarray}
\ket{\psi_3} &=& \frac{1}{\sqrt{2}}\left[
\alpha H \ket{0}(\ket{10} + \ket{01})
+ \beta H \ket{1}(\ket{00}+ \ket{11})
\right] \
&=& \frac{1}{2}[
\ket{00}(\alpha\ket{1}+\beta\ket{0})
+\ket{01}(\alpha\ket{0}+\beta\ket{1})
+\ket{10}(\alpha\ket{1}-\beta\ket{0})
+\ket{11}(\alpha\ket{0}-\beta\ket{1})
]
\end{eqnarray}
$$ボブが$\ket{\psi}$を得るためには、アリスから受け取る観測結果が
- $\ket{00}$の時、$X$ゲート
- $\ket{01}$の時、何もしない
- $\ket{10}$の時、$Z$ゲートと$X$ゲート
- $\ket{11}$の時、$Z$ゲート
$$
\begin{eqnarray}
&&I\otimes X \otimes I \ket{\psi_3} \
&=&
\frac{1}{2}[
\ket{00}(\alpha\ket{0}+\beta\ket{1})
+\ket{01}(\alpha\ket{1}+\beta\ket{0})
+\ket{10}(\alpha\ket{0}-\beta\ket{1})
+\ket{11}(\alpha\ket{1}-\beta\ket{0})
]
\end{eqnarray}
$$するとアリスから測定結果を受け取ったボブが適用すべきゲートはEPR pairが$\frac{\ket{00}+\ket{11}}{\sqrt{2}}$の時と全く同じになります。以下にQiskitでシミュレーターを使った時の結果と実際の量子コンピュータを使った時の結果を置いておきます。
import numpy as np
import matplotlib.pyplot as plt
from qiskit import QuantumCircuit, execute, Aer, IBMQ
from qiskit.quantum_info import random_statevector
from qiskit.visualization import plot_histogram
from qiskit.extensions import Initialize
from qiskit.providers.ibmq import least_busy
from qiskit.tools.monitor import job_monitor
IBMQ.load_account()
provider = IBMQ.get_provider(hub="ibm-q")
real_backend = least_busy(provider.backends(filters= lambda x: x.configuration().n_qubits > 3
and not x.configuration().simulator))
sim_backend = Aer.get_backend("qasm_simulator")
print("The backend as a real device is " + real_backend.name())
print("The backend as a simulator is " + sim_backend.name())
The backend as a real device is ibmq_athens
The backend as a simulator is qasm_simulator
psi = random_statevector(2, 1)
init_gate = Initialize(psi)
init_gate.label = "init"
inverse_init_gate = init_gate.gates_to_uncompute()
$$
\Psi^+ = \frac{\ket{10}+\ket{01}}{\sqrt{2}} = X\otimes I\frac{\ket{00}+\ket{11}}{\sqrt{2}}
$$なので、$\frac{\ket{00}+\ket{11}}{\sqrt{2}}$の状態を構成してから、片方のqubitに$X$ゲートを適用すれば$\Psi^+$を構成できます。Qiskitの場合qubitは$\ket{0}$で初期化されています。したがって片方のqubitに$H$ゲートを適用してからCNOTゲートを適用することで$\frac{\ket{00}+\ket{11}}{\sqrt{2}}$を構成することができます。
$$
\ket{0}\otimes\ket{0} \xrightarrow[H\otimes I]{} \frac{\ket{0}+\ket{1}}{\sqrt{2}}\otimes\ket{0}\xrightarrow[CNOT]{}\frac{\ket{00}+\ket{11}}{\sqrt{2}}
$$
def create_psiplus(qc, a, b):
qc.h(a)
qc.cx(a, b)
qc.x(a)
def alice_gates(qc, psi, a):
qc.cx(psi, a)
qc.h(psi)
qc.x(a)
def bob_gates(qc, a, b, c):
qc.cz(a, c)
qc.cx(b, c)
qc = QuantumCircuit(3, 1)
qc.append(init_gate, [0])
qc.barrier()
create_psiplus(qc, 1, 2)
qc.barrier()
alice_gates(qc, 0, 1)
qc.barrier()
bob_gates(qc, 0, 1, 2)
qc.barrier()
qc.append(inverse_init_gate, [2])
qc.measure(2, 0)
qc.draw(output="mpl")
# results using simulator
counts = execute(qc, sim_backend, shots=1000).result().get_counts()
plot_histogram(counts)
# results using real device
job = execute(qc, real_backend)
job_monitor(job)
real_result = job.result()
plot_histogram(real_result.get_counts(qc))
Job Status: job has successfully run
error_rate_percent = sum([
real_result.get_counts(qc)[result] for result in real_result.get_counts(qc).keys() if result[0]=="1"
]) * 100 / sum(list(real_result.get_counts(qc).values()))
print("The experimental error rate: ", error_rate_percent, "%")
The experimental error rate: 10.05859375 %


