ข้ามไปยังเนื้อหาหลัก
โครงการนี้อยู่ในช่วงเบต้า พบข้อผิดพลาด? สร้าง GitHub Issue มีคำถามหรือไอเดีย? ถามใน Discussions — ยินดีรับฟังความคิดเห็น!
คุณภาพการแปลในหน้านี้เป็นอย่างไร?

การเทเลพอร์ตเทชันควอนตัมและการเข้ารหัสแบบซูเปอร์เดนส์

หมายเหตุ

Kifumi Numata (26 Apr 2024)

ดาวน์โหลด PDF ของการบรรยายต้นฉบับ โปรดทราบว่าโค้ดบางส่วนอาจล้าสมัยแล้ว เนื่องจากเป็นภาพนิ่ง

เวลา QPU โดยประมาณในการรันการทดลองนี้คือ 10 วินาที

1. บทนำ​

ในการแก้ปัญหาควอนตัมระดับ utility-scale ใด ๆ เราจำเป็นต้องย้ายข้อมูลภายในคอมพิวเตอร์ควอนตัมจาก Qubit หนึ่งไปยังอีก Qubit หนึ่ง มีโปรโตคอลที่เป็นที่รู้จักดีสำหรับเรื่องนี้ แต่บางโปรโตคอลพื้นฐานที่สุดถูกพัฒนาขึ้นในบริบทของการส่งข้อมูลระหว่างผู้ส่งและผู้รับที่อยู่ห่างไกลกัน ตลอดบทเรียนนี้ บางครั้งเราจะใช้ภาษาที่สอดคล้องกับบริบทนี้ เช่น "เพื่อนที่อยู่ห่างไกลส่งข้อมูลถึงกัน" แต่โปรดจำไว้ว่าโปรโตคอลเหล่านี้มีความสำคัญกว้างกว่านั้นในการคำนวณควอนตัม ในบทเรียนนี้เราพิจารณาโปรโตคอลการสื่อสารควอนตัมต่อไปนี้:

  • การเทเลพอร์ตเทชันควอนตัม การใช้สถานะ entangled ที่แบ่งปันกัน (บางครั้งเรียกว่า e-bit) เพื่อส่งสถานะควอนตัมที่ไม่ทราบค่าไปยังเพื่อนที่อยู่ห่างไกล โดยต้องใช้การสื่อสารแบบคลาสสิกเพิ่มเติม
  • การเข้ารหัสแบบซูเปอร์เดนส์ควอนตัม วิธีการส่งข้อมูลสองบิตโดยการส่ง Qubit เดียวไปยังเพื่อนที่อยู่ห่างไกล (โดยใช้ Qubit ที่ entangle กันไว้ล่วงหน้าเช่นกัน)

สำหรับพื้นฐานเพิ่มเติมที่เกี่ยวข้องกับหัวข้อเหล่านี้ แนะนำให้ดูบทเรียนที่ 4 ใน Basics of Quantum Information เรื่อง Entanglement in action

ในคำอธิบายข้างต้น "สถานะควอนตัมที่ไม่ทราบค่า" หมายถึงสถานะในรูปแบบที่อธิบายไว้ในบทเรียนก่อนหน้า:

∣ψ⟩=α∣0⟩+β∣1⟩|\psi\rangle =\alpha|0\rangle+\beta|1\rangle

โดยที่ α\alpha และ β\beta เป็นจำนวนเชิงซ้อนที่ ∣α∣2+∣β∣2=1|\alpha|^2+|\beta|^2 = 1 ทำให้เราเขียนสถานะควอนตัมได้ว่า

∣ψ⟩=cos⁡θ2∣0⟩+eiφsin⁡θ2∣1⟩=(cos⁡θ2eiφsin⁡θ2)|\psi\rangle =\cos\frac{\theta}{2}|0\rangle+e^{i\varphi}\sin\frac{\theta}{2}|1\rangle= \left( \begin{matrix} \cos\frac{\theta}{2}\\ e^{i\varphi}\sin\frac{\theta}{2} \end{matrix} \right)

เนื่องจากเราต้องการสามารถถ่ายโอนข้อมูลในสถานะควอนตัมสุ่มใด ๆ ได้ การสร้างสถานะดังกล่าวจึงเป็นจุดเริ่มต้นของบทเรียนนี้

2. เมทริกซ์ความหนาแน่น​

เราสามารถเขียนสถานะควอนตัม ∣ψ⟩|\psi \rangle ในรูปของเมทริกซ์ความหนาแน่นได้เช่นกัน รูปแบบนี้มีประโยชน์สำหรับการแทนส่วนผสมเชิงความน่าจะเป็นของสถานะควอนตัมบริสุทธิ์ สำหรับ Qubit เดียว เราเขียนได้ว่า

∣ψ⟩⟨ψ∣≡ρ=((cos⁡θ2eiφsin⁡θ2))((cos⁡θ2e−iφsin⁡θ2))=12((1+cos⁡θe−iφsin⁡θe−iφsin⁡θ1−cos⁡θ))|\psi \rangle \langle \psi| \equiv \rho = \left( \begin{pmatrix} \cos\frac{\theta}{2}\\ e^{i\varphi}\sin\frac{\theta}{2} \end{pmatrix} \right) \left( \begin{pmatrix} \cos\frac{\theta}{2} & e^{-i\varphi}\sin\frac{\theta}{2} \end{pmatrix} \right) =\frac{1}{2}\left(\begin{pmatrix} 1+\cos\theta & e^{-i\varphi}\sin\theta\\ e^{-i\varphi}\sin\theta & 1-\cos\theta \end{pmatrix}\right)

สังเกตว่าเมทริกซ์ความหนาแน่น ρ\rho เป็นผลรวมเชิงเส้นของเมทริกซ์ Pauli ดังนี้

ρ=12(I+(sin⁡θcos⁡φ)X+(sin⁡θsin⁡φ)Y+(cos⁡θ)Z)\rho = \frac{1}{2}\bigl( \textbf{I} + (\sin{\theta}\cos{\varphi})\textbf{X}+ (\sin{\theta}\sin{\varphi})\textbf{Y} + (\cos{\theta})\textbf{Z} \bigr)

หรือในรูปทั่วไป

ρ=12(I+rxX+ryY+rzZ)\rho = \frac{1}{2}(\textbf{I} + r_{x}\textbf{X}+ r_{y}\textbf{Y} + r_{z}\textbf{Z})

โดยที่ rx2+ry2+rz2=1r_{x}^2+r_{y}^2+r_{z}^2=1

และ Bloch vector คือ r=(rx,ry,rz)\textbf{r} = (r_{x}, r_{y}, r_{z})

ตอนนี้ มาสร้างสถานะควอนตัมสุ่มโดยใช้ตัวเลขสุ่ม

# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util

_needed = {"numpy": "numpy", "qiskit": "qiskit", "qiskit_aer": "qiskit-aer", "qiskit_ibm_runtime": "qiskit-ibm-runtime"}
_missing = [pip for module, pip in _needed.items()
if importlib.util.find_spec(module) is None]
# One at a time, so a package that fails to install does not block the others
for _pip in _missing:
%pip install -q {_pip}
if not _missing:
print("\u2713 All required packages are installed")
import numpy as np

# create a random 1-qubit state from a random (theta, varphi) to define r vector
np.random.seed(1) # fixing seed for repeatibility

theta = np.random.uniform(0.0, 1.0) * np.pi # from 0 to pi
varphi = np.random.uniform(0.0, 2.0) * np.pi # from 0 to 2*pi

def get_r_vec(theta, varphi):
rx = np.sin(theta) * np.cos(varphi)
ry = np.sin(theta) * np.sin(varphi)
rz = np.cos(theta)
return (rx, ry, rz)

# get r vector
rx, ry, rz = get_r_vec(theta, varphi)

print("theta=" + str(theta), ",varphi=" + str(varphi))
print("(rx, ry, rz) = (" + str(rx) + ", " + str(ry) + ", " + str(rz) + ")")
theta=1.3101132663588946 ,varphi=4.525932273597346
(rx, ry, rz) = (-0.1791150283307452, -0.9494670044331133, 0.2577405946274022)

เราสามารถแสดง Bloch vector นี้บน Bloch sphere ได้

from qiskit.visualization import plot_bloch_vector

r = [rx, ry, rz]
plot_bloch_vector(r)

Output of the previous code cell

3. การทำ quantum state tomography​

ถ้าวัดสถานะควอนตัมในฐาน computational (∣0⟩|0 \rangle และ ∣1⟩|1 \rangle) เท่านั้น ข้อมูลเฟส (ข้อมูลจำนวนเชิงซ้อน) จะสูญหาย แต่ถ้าเรามีสำเนาของ ∣ψ⟩|\psi \rangle หลายชุดโดยการทำซ้ำกระบวนการเตรียม (เราไม่สามารถ clone สถานะได้ แต่สามารถทำซ้ำกระบวนการเตรียมได้) เราสามารถประมาณค่า rx,ry,rzr_{x}, r_{y}, r_{z} ได้โดยการทำ quantum state tomography สำหรับเมทริกซ์ความหนาแน่น ρ\rho เมื่อให้รูปแบบ:

ρ=12(I+rxX+ryY+rzZ)\rho = \frac{1}{2}(\textbf{I} + r_{x}\textbf{X}+ r_{y}\textbf{Y} + r_{z}\textbf{Z})

จะได้ว่า

Tr(Xρ)=rx,Tr(Yρ)=ry,Tr(Zρ)=rzTr(\textbf{X} \rho) = r_{x}, \quad Tr(\textbf{Y} \rho) = r_{y}, \quad Tr(\textbf{Z} \rho) = r_{z}

ในกรณีของ rzr_{z},

Tr(Zρ)=⟨0∣Zρ∣0⟩+⟨1∣Zρ∣1⟩Tr(\textbf{Z} \rho) = \langle 0|\textbf{Z} \rho|0 \rangle + \langle 1|\textbf{Z} \rho|1 \rangle =⟨0∣(∣0⟩⟨0∣−∣1⟩⟨1∣)ρ∣0⟩+⟨1∣(∣0⟩⟨0∣−∣1⟩⟨1∣)ρ∣1⟩= \langle 0|(|0 \rangle\langle 0|-|1 \rangle\langle 1|) \rho|0 \rangle +\langle 1|(|0 \rangle\langle 0|-|1 \rangle\langle 1|) \rho|1 \rangle =⟨0∣ρ∣0⟩−⟨1∣ρ∣1⟩=\langle 0|\rho|0 \rangle- \langle 1| \rho|1 \rangle =⟨0∣ψ⟩⟨ψ∣0⟩−⟨1∣ψ⟩⟨ψ∣1⟩=\langle 0|\psi\rangle\langle \psi|0 \rangle - \langle 1| \psi\rangle\langle \psi|1 \rangle =∣α∣2−∣β∣2=|\alpha|^2-|\beta|^2

การแปลงสมการขั้นสุดท้ายเป็นสำหรับ ∣ψ⟩=α∣0⟩+β∣1⟩|\psi \rangle =\alpha|0\rangle+\beta|1\rangle ดังนั้น เราสามารถหา rzr_{z} ได้จาก ความน่าจะเป็นของ ∣0⟩|0 \rangle ลบ ความน่าจะเป็นของ ∣1⟩|1 \rangle

ประมาณค่า rzr_z​

ในการประมาณค่า rzr_z เราสร้างสถานะควอนตัมแล้ววัดผล จากนั้นทำซ้ำกระบวนการเตรียมและวัดผลหลายครั้ง สุดท้ายใช้สถิติการวัดเพื่อประมาณความน่าจะเป็นข้างต้นและประมาณค่า rzr_z

สำหรับการสร้างสถานะควอนตัมสุ่ม เราจะใช้ Gate unitary ทั่วไป UU ที่มีพารามิเตอร์ θ,φ\theta, \varphi (ดูข้อมูลเพิ่มเติมได้ที่ U-gate)

from qiskit import QuantumCircuit

# create a 1-qubit quantum state psi from theta, varphi parameters
qc = QuantumCircuit(1, 1)
qc.u(theta, varphi, 0.0, 0)

# measure in computational basis
qc.measure(0, 0)

qc.draw(output="mpl")

Output of the previous code cell

การใช้ AerSimulator เราจะวัดใน computational basis เพื่อประมาณค่า rzr_z

# see if the expected value of measuring in the computational basis
# approaches the limit of rz
from qiskit_aer import AerSimulator
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import Sampler
from qiskit.visualization import plot_histogram

# Define backend
backend = AerSimulator()
nshots = 1000 # or 10000
# nshots = 10000

# Transpile to backend
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_qc = pm.run(qc)

# Run the job
sampler = Sampler(mode=backend)
job = sampler.run([isa_qc], shots=nshots)
result = job.result()

# Extract counts data
counts = result[0].data.c.get_counts()
print(counts)

# Plot the counts in a histogram

plot_histogram(counts)
{'1': 375, '0': 625}

Output of the previous code cell

rz_approx = (counts["0"] - counts["1"]) / nshots

print("rz = ", rz, " and approx of rz = ", rz_approx)
rz = 0.2577405946274022 and approx of rz = 0.25

ด้วยวิธี quantum state tomography เราประมาณค่า rzr_z ได้แล้ว ในกรณีนี้ เนื่องจากเราเลือกพารามิเตอร์สำหรับสถานะ "สุ่ม" เอง เราจึงรู้ค่าของ rzr_z และสามารถตรวจสอบผลลัพธ์ได้ แต่โดยธรรมชาติแล้ว งานระดับ utility-scale ไม่ได้ตรวจสอบง่ายขนาดนั้นเสมอไป เราจะพูดถึงการตรวจสอบผลลัพธ์ควอนตัมเพิ่มเติมในภายหลังในหลักสูตรนี้ ตอนนี้ขอให้สังเกตว่าการประมาณของเราค่อนข้างแม่นยำ

แบบฝึกหัดที่ 1: ประมาณค่า rxr_x​

ระลึกว่าคอมพิวเตอร์ควอนตัม IBM® วัดตามแกน zz (บางครั้งเรียกว่า "ใน zz basis" หรือ "ใน computational basis") อย่างไรก็ตาม โดยการใช้การหมุนก่อนการวัด เราสามารถวัดการฉายของสถานะควอนตัมบนแกน x ได้ด้วย พูดให้ชัดเจนขึ้น ถ้าเราหมุนระบบเพื่อให้สิ่งที่เคยชี้ไปตามแนว xx มาชี้ตามแนว zz แทน เราก็สามารถคงฮาร์ดแวร์วัดแบบเดิมตามแนว zz ไว้ได้ แต่เรียนรู้เกี่ยวกับสถานะที่เพิ่งชี้ตามแนว xx เมื่อครู่นี้ นี่คือวิธีที่คอมพิวเตอร์ควอนตัมส่วนใหญ่ (และคอมพิวเตอร์ควอนตัม IBM ทั้งหมด) วัดตามหลายแกน

ด้วยความเข้าใจนี้ ลองเขียนโค้ดเพื่อประมาณค่า rxr_x โดยใช้ quantum state tomography

วิธีแก้:

# create a 1-qubit quantum state psi from theta, varphi parameters
qc = QuantumCircuit(1, 1)
qc.u(theta, varphi, 0.0, 0)

qc.h(0)
qc.measure(0, 0)

qc.draw(output="mpl")

Output of the previous code cell

# Define backend
backend = AerSimulator()
nshots = 10000

# Transpile to backend
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_qc = pm.run(qc)

# Run the job
sampler = Sampler(mode=backend)
job = sampler.run([isa_qc], shots=nshots)
result = job.result()

# Extract counts data
counts = result[0].data.c.get_counts()
print(counts)

# Plot the counts in a histogram
plot_histogram(counts)
{'1': 5925, '0': 4075}

Output of the previous code cell

rx_approx = (counts["0"] - counts["1"]) / nshots

print("rx = ", rx, " and approx of rx = ", rx_approx)
rx = -0.1791150283307452 and approx of rx = -0.185

แบบฝึกหัดที่ 2: ประมาณค่า ryr_y​

ด้วยหลักการทางตรรกะเดียวกัน เราสามารถหมุนระบบก่อนการวัดเพื่อเรียนรู้เกี่ยวกับ ryr_y ลองเขียนโค้ดด้วยตัวเองเพื่อประมาณค่า ryr_y โดยใช้ quantum state tomography คุณอาจเริ่มจากตัวอย่างก่อนหน้า แต่ทำการหมุนที่แตกต่างกัน (สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ Gate ต่าง ๆ รวมถึง sdg ดู API reference)

วิธีแก้:

# create a 1-qubit quantum state psi from theta, varphi parameters
qc = QuantumCircuit(1, 1)
qc.u(theta, varphi, 0.0, 0)

qc.sdg(0)
qc.h(0)
qc.measure(0, 0)

qc.draw(output="mpl")

Output of the previous code cell

# Define backend
backend = AerSimulator()
nshots = 10000

# Transpile to backend
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_qc = pm.run(qc)

# Run the job
sampler = Sampler(mode=backend)
job = sampler.run([isa_qc], shots=nshots)
result = job.result()

# Extract counts data
counts = result[0].data.c.get_counts()
print(counts)

# Plot the counts in a histogram
plot_histogram(counts)
{'1': 9759, '0': 241}

Output of the previous code cell

ry_approx = (counts["0"] - counts["1"]) / nshots

print("ry = ", ry, " and approx of ry = ", ry_approx)
ry = -0.9494670044331133 and approx of ry = -0.9518

ตอนนี้เราประมาณองค์ประกอบทั้งหมดของ r⃗\vec{r} ได้แล้ว และสามารถเขียนเวกเตอร์เต็มได้

print("Estimated vector is (", rx_approx, ",", ry_approx, ",", rz_approx, ").")
print("Original random vector was (" + str(rx) + ", " + str(ry) + ", " + str(rz) + ").")
Estimated vector is ( -0.185 , -0.9518 , 0.25 ).
Original random vector was (-0.1791150283307452, -0.9494670044331133, 0.2577405946274022).

ด้วยวิธี quantum state tomography นี้ คุณประมาณค่าเวกเตอร์สุ่มต้นฉบับได้ค่อนข้างแม่นยำ

4. การเทเลพอร์ตเทชันควอนตัม​

ลองพิจารณาสถานการณ์ที่ Alice ต้องการส่งสถานะควอนตัมที่ไม่ทราบค่า ∣ψ⟩|\psi \rangle ไปยัง Bob เพื่อนของเธอที่อยู่ห่างไกล สมมติว่าพวกเขาสื่อสารได้เฉพาะทางคลาสสิกเท่านั้น (เช่น อีเมลหรือโทรศัพท์) Alice ไม่สามารถคัดลอกสถานะควอนตัมได้ (เพราะทฤษฎีบท no-cloning) ถ้าเธอทำซ้ำกระบวนการเตรียมหลาย ๆ ครั้ง เธอสามารถสร้างสถิติเหมือนที่เราเพิ่งทำได้ แต่ถ้ามีสถานะที่ไม่ทราบค่าเพียงชุดเดียว? สถานะนี้อาจเกิดขึ้นจากกระบวนการทางฟิสิกส์ที่คุณต้องการศึกษา หรืออาจเป็นส่วนหนึ่งของการคำนวณควอนตัมขนาดใหญ่ ในกรณีนั้น Alice จะส่งสถานะไปยัง Bob ได้อย่างไร? เธอทำได้ ถ้าเธอและ Bob แบ่งปันทรัพยากรควอนตัมอันมีค่า: สถานะ entangled ที่แบ่งปันกัน เช่น Bell state ที่แนะนำในบทเรียนก่อนหน้า: ∣00⟩+∣11⟩2\frac {|00\rangle + |11\rangle}{\sqrt 2} บางครั้งคุณอาจเห็นสิ่งนี้เรียกว่า "EPR pair" หรือ "e-bit" (หน่วยพื้นฐานของ entanglement) ถ้า Alice แบ่งปันสถานะ entangled ดังกล่าวกับ Bob เธอสามารถ teleport สถานะควอนตัมที่ไม่ทราบค่าไปยัง Bob ได้ โดยการทำการดำเนินการควอนตัมหลายชุดและส่งข้อมูลคลาสสิกสองบิตให้เขา

4.1 โปรโตคอลของการเทเลพอร์ตเทชันควอนตัม​

สมมติฐาน: Alice มีสถานะควอนตัมที่ไม่ทราบค่า ∣ψ⟩|\psi \rangle ที่จะส่งไปยัง Bob Alice และ Bob แบ่งปันสถานะ entangled 2 Qubit หรือ e-bit โดยแต่ละคนมี Qubit หนึ่งอยู่ที่ตำแหน่งของตนเอง

ต่อไปนี้คือโครงร่างขั้นตอนโดยไม่มีคำอธิบาย ซึ่งจะมีการนำไปใช้อย่างละเอียดด้านล่าง

  1. Alice ทำ entangle ∣ψ⟩|\psi \rangle กับส่วนของ e-bit ที่เธอถือด้วย CNOT Gate
  2. Alice ใช้ Hadamard Gate กับ ∣ψ⟩|\psi \rangle แล้ววัด Qubit ทั้งสองของเธอใน computational basis
  3. Alice ส่งผลการวัดให้ Bob (ไม่ว่าจะเป็น "00", "01", "10" หรือ "11")
  4. Bob ทำการดำเนินการ correction ตามข้อมูลสองบิตของ Alice บนส่วน e-bit ของเขา
    • ถ้า "00", Bob ไม่ทำอะไร
    • ถ้า "01", Bob ใช้ X Gate
    • ถ้า "10", Bob ใช้ Z Gate
    • ถ้า "11", Bob ใช้ iY = ZX Gate
  5. ส่วน e-bit ของ Bob กลายเป็น ∣ψ⟩|\psi \rangle

เรื่องนี้ยังมีรายละเอียดเพิ่มเติมใน Basics of Quantum Information แต่สถานการณ์จะชัดเจนขึ้นเมื่อเราสร้างมันใน Qiskit

4.2 Circuit ควอนตัมที่จำลองการเทเลพอร์ตเทชันควอนตัม​

เช่นเคย เราจะใช้กรอบงาน Qiskit patterns ส่วนนี้จะมุ่งเน้นเฉพาะการ mapping เท่านั้น

ขั้นตอนที่ 1: จับคู่ปัญหากับ Circuit ควอนตัมและ Operator​

เพื่ออธิบายสถานการณ์ข้างต้น เราต้องการ Circuit ที่มีสาม Qubit: สองอันสำหรับคู่ entangled ที่ Alice และ Bob แบ่งปันกัน และหนึ่งอันสำหรับสถานะควอนตัมที่ไม่ทราบค่า ∣ψ⟩|\psi\rangle

from qiskit import QuantumCircuit
import numpy as np
# create 3-qubits circuit
qc = QuantumCircuit(3, 3)

qc.draw(output="mpl")

Output of the previous code cell

ในตอนเริ่มต้น Alice มีสถานะควอนตัมที่ไม่ทราบค่า ∣ψ⟩|\psi \rangle เราจะสร้างสิ่งนี้โดยใช้ Gate UU

# Create the unknown quantum state using the u-gate. Alice has this.
qc.u(theta, varphi, 0.0, 0)
qc.barrier() # for visual separation

qc.draw(output="mpl")

Output of the previous code cell

เราสามารถแสดงภาพสถานะที่สร้างขึ้นได้ แต่เฉพาะเพราะเราทราบพารามิเตอร์ที่ใช้ใน Gate UU ถ้าสถานะนี้เกิดขึ้นจากกระบวนการควอนตัมที่ซับซ้อน สถานะนั้นจะไม่สามารถทราบได้หากไม่รันกระบวนการเพื่อสร้างสถานะหลาย ๆ ครั้งและรวบรวมสถิติเหมือนใน tomography

# show the quantum state on bloch sphere
from qiskit.quantum_info import Statevector
from qiskit.visualization import plot_bloch_multivector

out_vector = Statevector(qc)

plot_bloch_multivector(out_vector)

Output of the previous code cell

ก่อนที่โปรโตคอลนี้จะเริ่มต้น เราสมมติว่า Alice และ Bob มีคู่ entangled ที่แบ่งปันกันอยู่แล้ว ถ้า Alice และ Bob อยู่คนละที่จริง ๆ พวกเขาอาจตั้งค่าสถานะที่แบ่งปันกัน ก่อน ที่สถานะที่ไม่ทราบค่า ∣ψ⟩|\psi\rangle จะถูกสร้างขึ้น เนื่องจากสิ่งเหล่านั้นเกิดขึ้นบน Qubit ต่างกัน ลำดับที่นี่จึงไม่สำคัญ และลำดับนี้สะดวกสำหรับการแสดงภาพ

# Alice and Bob are together in the same place and set up an entangled pair.
qc.h(1)
qc.cx(1, 2)
qc.barrier() # for visual separation.
# We can consider that Alice and Bob might move their qubits to different physical locations, now.

qc.draw(output="mpl")

Output of the previous code cell

ต่อมา Alice ทำ entangle ∣ψ⟩|\psi \rangle กับส่วน e-bit ของเธอโดยใช้ Gate CXCX และ Gate HH แล้ววัดพวกมันใน computational basis

# Alice entangles the unknown state with her part of the e-bit, using the CNOT gate and H gate.
qc.cx(0, 1)
qc.h(0)
qc.barrier()

# Alice measures the two qubits.
qc.measure(0, 0)
qc.measure(1, 1)

qc.draw(output="mpl")

Output of the previous code cell

Alice ส่งผลการวัดให้ Bob (ไม่ว่าจะเป็น "00", "01", "10" หรือ "11") แล้ว Bob ทำการดำเนินการ correction ตามข้อมูลสองบิตของ Alice บนส่วน e-bit ที่แบ่งปันกัน จากนั้น ส่วนของ Bob กลายเป็น ∣ψ⟩|\psi \rangle

# Alice sent the results to Bob. Bob applies correction
with qc.if_test((0, 1)):
qc.z(2)
with qc.if_test((1, 1)):
qc.x(2)
qc.barrier()

qc.draw(output="mpl")

Output of the previous code cell

คุณสร้าง Circuit การเทเลพอร์ตเทชันควอนตัมสำเร็จแล้ว! มาดูสถานะผลลัพธ์ของ Circuit นี้โดยใช้ statevector simulator

from qiskit_aer import StatevectorSimulator

backend = StatevectorSimulator()
out_vector = backend.run(qc, shots=1).result().get_statevector() # set shots = 1

plot_bloch_multivector(out_vector)

Output of the previous code cell

คุณจะเห็นว่าสถานะควอนตัมที่สร้างโดย Gate UU ของ Qubit 0 (Qubit ที่ถือ secret state เดิม) ได้ถูกถ่ายโอนไปยัง Qubit 2 (Qubit ของ Bob) แล้ว

คุณสามารถรันเซลล์ข้างต้นหลาย ๆ ครั้งเพื่อตรวจสอบ คุณอาจสังเกตว่า Qubit 0 และ 1 เปลี่ยนสถานะ แต่ Qubit 2 อยู่ในสถานะ ∣ψ⟩|\psi\rangle เสมอ

4.3 รันและยืนยันผลลัพธ์โดยการใช้ U inverse​

ข้างต้น เราตรวจสอบด้วยสายตาว่าสถานะที่ teleport ดูถูกต้อง อีกวิธีหนึ่งในการตรวจสอบว่าสถานะควอนตัมถูก teleport อย่างถูกต้องหรือไม่ คือการใช้ inverse ของ Gate UU กับ Qubit ของ Bob เพื่อให้เราวัดได้ '0' นั่นคือ เนื่องจาก U−1UU^{-1}U เป็น identity ถ้า Qubit ของ Bob อยู่ในสถานะที่สร้างจาก U∣0⟩U|0\rangle การใช้ inverse ควรให้ U−1U∣0⟩=∣0⟩U^{-1}U|0\rangle=|0\rangle

# Apply the inverse of u-gate to measure |0>
qc.u(theta, varphi, 0.0, 2).inverse() # inverse of u(theta,varphi,0.0)
qc.measure(2, 2) # add measurement gate

qc.draw(output="mpl")

Output of the previous code cell

เราจะรัน Circuit ด้วย AerSimulator ก่อน ก่อนจะไปทดสอบกับคอมพิวเตอร์ควอนตัมจริง

from qiskit_aer import AerSimulator
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import Sampler
from qiskit.visualization import plot_histogram

# Define backend
backend = AerSimulator()

# Transpile to backend
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_qc = pm.run(qc)

# Run the job
sampler = Sampler(mode=backend)
job = sampler.run([isa_qc], shots=nshots)
result = job.result()

# Extract counts data
counts = result[0].data.c.get_counts()
print(counts)

# Plot the counts in a histogram
plot_histogram(counts)
{'011': 2510, '010': 2417, '000': 2635, '001': 2438}

Output of the previous code cell

ระลึกว่าในสัญกรณ์ little endian Qubit 2 คือ Qubit ซ้ายสุด (หรือล่างสุด ในป้ายกำกับคอลัมน์) สังเกตว่า Qubit ซ้ายและล่างสุดในป้ายกำกับคอลัมน์เป็น 0 สำหรับทุกผลลัพธ์ที่เป็นไปได้ ซึ่งแสดงว่าเรามีโอกาส 100% ที่จะวัด q2q_2 ในสถานะ ∣0⟩|0\rangle นี่คือผลลัพธ์ที่คาดหวัง และบ่งชี้ว่าโปรโตคอลการเทเลพอร์ตเทชันทำงานได้อย่างถูกต้อง

4.4 การเทเลพอร์ตเทชันบนคอมพิวเตอร์ควอนตัมจริง​

ต่อไป เราจะทำการเทเลพอร์ตเทชันบนคอมพิวเตอร์ควอนตัมจริง โดยใช้ฟังก์ชัน dynamic circuit เราสามารถดำเนินการกลางวงจรโดยใช้ผลการวัด ซึ่งนำการดำเนินการแบบมีเงื่อนไขใน Circuit การเทเลพอร์ตเทชันมาใช้แบบ real-time สำหรับการแก้ปัญหากับคอมพิวเตอร์ควอนตัมจริง เราจะทำตามสี่ขั้นตอนของ Qiskit patterns

  1. จับคู่ปัญหากับ Circuit ควอนตัมและ Operator

  2. ปรับแต่งสำหรับฮาร์ดแวร์เป้าหมาย

  3. รันบนฮาร์ดแวร์เป้าหมาย

  4. ประมวลผลผลลัพธ์

แบบฝึกหัดที่ 3: สร้าง Circuit การเทเลพอร์ตเทชัน​

ลองสร้าง Circuit การเทเลพอร์ตเทชันทั้งหมดตั้งแต่ต้นเพื่อทดสอบความเข้าใจของคุณ เลื่อนกลับขึ้นถ้าต้องการทบทวน

วิธีแก้:

# Step 1: Map problem to quantum circuits and operators
# Create the circuit with 3-qubits and 1-bit
qc = QuantumCircuit(3, 3)

# Alice creates an unknown quantum state using the u-gate.
qc.u(theta, varphi, 0.0, 0)
qc.barrier() # for visual separation

# Eve creates EPR pair and sends q1 to Alice and q2 to Bob
##your code goes here##
qc.h(1)
qc.cx(1, 2)
qc.barrier()

# Alice entangles the unknown state with her EPR part, using the CNOT gate and H gate.
##your code goes here##
qc.cx(0, 1)
qc.h(0)
qc.barrier()

# Alice measures the two qubits.
##your code goes here##
qc.measure(0, 0)
qc.measure(1, 1)

# Alice sent the results to Bob. Now, Bob applies correction
##your code goes here##
with qc.if_test((0, 1)):
qc.z(2)
with qc.if_test((1, 1)):
qc.x(2)
qc.barrier()

# Apply the inverse of u-gate to measure |0>
qc.u(theta, varphi, 0.0, 2).inverse()
qc.measure(2, 2)

qc.draw(output="mpl")

Output of the previous code cell

เป็นการเตือนความจำ การใช้ inverse ของ Gate UU เป็นเพียงเพื่อให้เราสามารถยืนยันพฤติกรรมที่คาดหวัง มันไม่ใช่ส่วนหนึ่งของการส่งสถานะไปยัง Bob และเราจะไม่ใช้ Gate UU inverse นั้นถ้าเป้าหมายเดียวคือถ่ายโอนข้อมูลควอนตัม

ขั้นตอนที่ 2: ปรับแต่งสำหรับฮาร์ดแวร์เป้าหมาย​

ในการรันบนฮาร์ดแวร์ ให้ import QiskitRuntimeService และโหลด credentials ที่บันทึกไว้ เลือก Backend ที่มีงานรอน้อยที่สุดในคิว

from qiskit_ibm_runtime import QiskitRuntimeService

service = QiskitRuntimeService()
service.backends()
[<IBMBackend('ibm_brisbane')>,
<IBMBackend('ibm_torino')>]
# You can also identify the least busy device
backend = service.least_busy(operational=True)
print("The least busy device is ", backend)
The least busy device is <IBMBackend('ibm_brisbane')>
# You can specify the device
# backend = service.backend('ibm_brisbane')

มาดู coupling map ของอุปกรณ์ที่คุณเลือก

from qiskit.visualization import plot_gate_map

plot_gate_map(backend)

Output of the previous code cell

อุปกรณ์ต่าง ๆ อาจมี coupling map ที่แตกต่างกัน และแต่ละอุปกรณ์มี Qubit และ coupler บางตัวที่มีประสิทธิภาพดีกว่า ท้ายที่สุด คอมพิวเตอร์ควอนตัมต่าง ๆ อาจมี native gates ที่แตกต่างกัน (Gate ที่ฮาร์ดแวร์สามารถรันได้) การ Transpile Circuit จะเขียน Circuit ควอนตัมนามธรรมใหม่โดยใช้ Gate ที่คอมพิวเตอร์ควอนตัมเป้าหมายสามารถรันได้ และเลือก mapping ที่เหมาะสมที่สุดไปยัง physical Qubit (รวมถึงสิ่งอื่น ๆ) การ Transpilation เป็นหัวข้อที่ซับซ้อนมาก ดูข้อมูลเพิ่มเติมเกี่ยวกับการ Transpilation ได้ที่ API reference

# Step 2: Optimize for target hardware
# Transpile the circuit into basis gates executable on the hardware
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager

pm = generate_preset_pass_manager(backend=backend, optimization_level=2)
qc_compiled = pm.run(qc)

qc_compiled.draw("mpl", idle_wires=False, fold=-1)

Output of the previous code cell

ขั้นตอนที่ 3: รัน Circuit​

โดยใช้ Runtime primitive Sampler เราจะรัน Circuit เป้าหมาย

# Step 3: Execute the target circuit
sampler = Sampler(backend)
job = sampler.run([qc_compiled])
job_id = job.job_id()
print("job id:", job_id)
job id: d13nkhpn2txg008jt0d0
# Check the job status
job.status()
'DONE'

คุณยังสามารถตรวจสอบสถานะงานได้จาก IBM Quantum® dashboard

# If the Notebook session got disconnected you can also check your job status
# by running the following code

from qiskit_ibm_runtime import QiskitRuntimeService

service = QiskitRuntimeService()
job_real = service.job(job.job_id()) # Input your job-id between the quotations
job_real.status()
'DONE'

ถ้าเห็น 'DONE' แสดงขึ้นมา คุณสามารถรับผลลัพธ์ได้โดยรันเซลล์ด้านล่าง

# Execute after 'DONE' is displayed
result_real = job_real.result()
print(result_real[0].data.c.get_counts())
{'001': 992, '110': 430, '011': 579, '010': 605, '111': 402, '000': 925, '100': 57, '101': 106}

ขั้นตอนที่ 4: ประมวลผลผลลัพธ์​

# Step 4: Post-process the results
from qiskit.visualization import plot_histogram

plot_histogram(result_real[0].data.c.get_counts())

Output of the previous code cell

คุณสามารถตีความผลลัพธ์ข้างต้นได้โดยตรง หรือใช้ marginal_count เพื่อ marginalize (trace out) เอาเฉพาะผลลัพธ์ของ Bob บน Qubit 2 ออกมา

# trace out Bob's results on qubit 2
from qiskit.result import marginal_counts

bobs_qubit = 2
real_counts = result_real[0].data.c.get_counts()
bobs_counts = marginal_counts(real_counts, [bobs_qubit])
plot_histogram(bobs_counts)

Output of the previous code cell

จากที่เห็น มีผลลัพธ์บางส่วนที่เราวัดได้ ∣1⟩|1 \rangle ซึ่งเกิดจาก noise และ errors โดยเฉพาะอย่างยิ่ง dynamic circuit มักจะมีอัตราข้อผิดพลาดสูงกว่า เนื่องจากการวัดกลางวงจรที่ใช้เวลานาน

4.5 บทสรุปสำคัญเกี่ยวกับการเทเลพอร์ตเทชันควอนตัม​

เราสามารถส่งสถานะควอนตัมไปยังเพื่อนที่อยู่ห่างไกลได้โดยการแบ่งปันคู่ Qubit ที่ entangle กัน (e-bit)

  1. การเทเลพอร์ตเทชันควอนตัมสามารถส่งสถานะควอนตัมได้เร็วกว่าแสงได้หรือไม่? ไม่ได้ เพราะ Alice ต้องบอก Bob เกี่ยวกับผลการวัดในแบบคลาสสิก

  2. การเทเลพอร์ตเทชันควอนตัมจะละเมิด "ทฤษฎีบท no-cloning" ที่ห้ามการคัดลอกสถานะควอนตัมหรือไม่? ไม่ เพราะสถานะควอนตัมดั้งเดิมที่ให้กับ Alice บน Qubit หนึ่งของเธอสูญหายไปในการวัด มันยุบตัวเป็น ∣0⟩|0\rangle หรือ ∣1⟩|1\rangle

5. การเข้ารหัสแบบซูเปอร์เดนส์ (Superdense coding)​

การตั้งค่าที่แทบจะเหมือนเดิมนี้สามารถนำไปใช้เพื่อจุดประสงค์อื่นได้ สมมติว่า Alice ต้องการส่งข้อมูลคลาสสิกสองบิตให้ Bob แต่เธอไม่มีช่องทางสื่อสารคลาสสิกกับ Bob อย่างไรก็ตาม เธอแบ่งปันคู่ entangled กับ Bob และได้รับอนุญาตให้ส่ง Qubit ของเธอไปยังตำแหน่งของ Bob สังเกตความแตกต่างกับโปรโตคอลการเทเลพอร์ตเทชันควอนตัม ในการเทเลพอร์ตเทชัน เพื่อนทั้งสอง สามารถ สื่อสารแบบคลาสสิกได้ และเป้าหมายคือการส่งสถานะควอนตัม ในกรณีนี้ ไม่มีช่องทางสื่อสารแบบคลาสสิกให้ใช้ พวกเขาจึงอาศัยการส่ง Qubit เพื่อส่งข้อมูลคลาสสิกสองบิตแทน

5.1 โปรโตคอลของ superdense coding​

สมมติฐาน: Alice มีข้อมูลสองบิต เช่น a1a2∈{00,01,10,11}a_1a_2 \in \{00, 01, 10, 11\} Alice และ Bob แบ่งปันคู่ entangled (e-bit) แต่พวกเขาไม่สามารถสื่อสารแบบคลาสสิกได้

  1. Alice ทำการดำเนินการหนึ่งในต่อไปนี้กับส่วน e-bit ของเธอ

    • ถ้า a1a2=00a_1a_2 = 00, เธอไม่ทำอะไร

    • ถ้า a1a2=01a_1a_2 = 01, เธอใช้ Z Gate

    • ถ้า a1a2=10a_1a_2 = 10, เธอใช้ X Gate

    • ถ้า a1a2=11a_1a_2 = 11, เธอใช้ Z Gate และ X Gate

  2. Alice ส่งส่วน e-bit ของเธอไปยังตำแหน่งของ Bob

  3. Bob ใช้ CNOT Gate โดยให้ Qubit จาก Alice เป็น control และ Qubit ของเขาเป็น target จากนั้นใช้ H Gate กับ Qubit จาก Alice แล้ววัด Qubit ทั้งสอง สถานะเริ่มต้นที่เป็นไปได้และผลลัพธ์จากการดำเนินการของ Bob คือ:

∣00⟩+∣11⟩2→CX01⊗H0→∣00⟩\frac {|00\rangle + |11\rangle}{\sqrt 2} \rightarrow CX_{01}\otimes H_0 \rightarrow |00\rangle ∣00⟩−∣11⟩2→CX01⊗H0→∣01⟩\frac {|00\rangle - |11\rangle}{\sqrt 2} \rightarrow CX_{01}\otimes H_0 \rightarrow |01\rangle ∣10⟩+∣01⟩2→CX01⊗H0→∣10⟩\frac {|10\rangle + |01\rangle}{\sqrt 2} \rightarrow CX_{01}\otimes H_0 \rightarrow |10\rangle ∣10⟩−∣01⟩2→CX01⊗H0→−∣11⟩\frac {|10\rangle - |01\rangle}{\sqrt 2} \rightarrow CX_{01}\otimes H_0 \rightarrow -|11\rangle

สังเกตว่าเครื่องหมายลบของ −∣11⟩-|11\rangle เป็น global phase ดังนั้นจึงวัดไม่ได้

5.2 Circuit ควอนตัมที่จำลอง superdense coding​

ตามโปรโตคอลของ superdense coding คุณสามารถสร้าง Circuit superdense coding ได้ดังนี้ ลองเปลี่ยน msg ซึ่งเป็นข้อความที่ Alice ต้องการส่งไปยัง Bob

from qiskit import QuantumCircuit

ขั้นตอน Qiskit patterns ถูกระบุไว้ใน comments ของโค้ด

# Step 1: Map problem to quantum circuits and operators
# Create 2-qubits circuit
qc = QuantumCircuit(2, 2)

# Eve creates EPR pair and send q0 to Alice and q1 to Bob
qc.h(0)
qc.cx(0, 1)
qc.barrier()

# set message which Alice wants to transform to Bob
msg = "11" # You can change the message

if msg == "00":
pass
elif msg == "10":
qc.x(0)
elif msg == "01":
qc.z(0)
elif msg == "11":
qc.z(0)
qc.x(0)

qc.barrier()
# Bob receives EPR qubit from Alice and performs unitary operations
qc.cx(0, 1)
qc.h(0)
qc.barrier()

# Bob measures q0 and q1
qc.measure(0, 0)
qc.measure(1, 1)

qc.draw(output="mpl")

Output of the previous code cell

# We will execute on a simulator first
from qiskit_aer import AerSimulator
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import Sampler

# Define backend
backend = AerSimulator()
shots = 1000

# Transpile to backend
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_qc = pm.run(qc)

# Run the job
sampler = Sampler(mode=backend)
job_sim = sampler.run([isa_qc], shots=shots)
result_sim = job_sim.result()

# Extract counts data
counts = result_sim[0].data.c.get_counts()
print(counts)
{'11': 1000}
# Visualize the results
from qiskit.visualization import plot_histogram

plot_histogram(counts)

Output of the previous code cell

คุณจะเห็นว่า Bob ได้รับข้อความที่ Alice ต้องการส่งให้เขา

ต่อไป มาทดลองกับคอมพิวเตอร์ควอนตัมจริง

from qiskit_ibm_runtime import QiskitRuntimeService

service = QiskitRuntimeService()
backend = service.least_busy(operational=True)
print("The least busy device is ", backend)
The least busy device is <IBMBackend('ibm_brisbane')>
# Step 1 was already completed before the simulator job above.
# Step 2: Optimize for target hardware
# Transpile the circuit into basis gates executable on the hardware
pm = generate_preset_pass_manager(backend=backend, optimization_level=2)
qc_compiled = pm.run(qc)

qc_compiled.draw("mpl", idle_wires=False)

Output of the previous code cell

# Step 3:Execute the target circuit
sampler = Sampler(backend)
job = sampler.run([qc_compiled])
job_id = job.job_id()
print("job id:", job_id)
job id: d13nnyq3grvg008j0zag
# Check the job status
job.status()
'DONE'
# If the Notebook session got disconnected you can also check your job status
# by running the following code

# from qiskit_ibm_runtime import QiskitRuntimeService
# service = QiskitRuntimeService()
job = service.job(job_id) # Input your job-id between the quotations
job.status()
'DONE'
# Execute after job has successfully run
real_result = job.result()
print(real_result[0].data.c.get_counts())
{'11': 3942, '01': 107, '10': 41, '00': 6}
# Step 4: post-process the results
from qiskit.visualization import plot_histogram

plot_histogram(real_result[0].data.c.get_counts())

Output of the previous code cell

ผลลัพธ์เป็นไปตามที่คาดหวัง สังเกตว่า superdense coding บนคอมพิวเตอร์ควอนตัมจริงแสดงข้อผิดพลาดน้อยกว่าในกรณีการเทเลพอร์ตเทชันควอนตัมบนคอมพิวเตอร์ควอนตัมจริง เหตุผลหนึ่งอาจเป็นเพราะการเทเลพอร์ตเทชันควอนตัมใช้ dynamic circuit และ superdense coding ไม่ใช้ เราจะเรียนรู้เพิ่มเติมเกี่ยวกับข้อผิดพลาดใน Circuit ควอนตัมในบทเรียนต่อ ๆ ไป

6. สรุป​

ในบทเรียนนี้ เราได้นำโปรโตคอลควอนตัมสองอย่างไปใช้ แม้ว่าสถานการณ์สำหรับทั้งสองที่เกี่ยวข้องกับเพื่อนที่อยู่ห่างไกลจะค่อนข้างห่างจากการคำนวณควอนตัมบน QPU เครื่องเดียว แต่มีการประยุกต์ใช้ในการคำนวณควอนตัม และช่วยให้เราเข้าใจการถ่ายโอนข้อมูลควอนตัมได้ดีขึ้น

  • การเทเลพอร์ตเทชันควอนตัม: แม้เราไม่สามารถคัดลอกสถานะควอนตัมได้ เราสามารถ teleport สถานะควอนตัมที่ไม่ทราบค่าได้โดยมี entanglement ที่แบ่งปันกัน

  • การเข้ารหัสแบบซูเปอร์เดนส์ควอนตัม: คู่ entangled ที่แบ่งปันกันและการถ่ายโอน Qubit หนึ่งอัน ทำให้สามารถสื่อสารข้อมูลคลาสสิกสองบิตได้

# See the version of Qiskit
import qiskit

qiskit.__version__
'2.0.2'