ข้ามไปยังเนื้อหาหลัก

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

หมายเหตุ

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θ20+eiφsinθ21=(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θ2eiφsinθ2))=12((1+cosθeiφsinθeiφsinθ1cosθ))|\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 — required packages for this notebook
!pip install -q numpy qiskit qiskit-aer qiskit-ibm-runtime
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ρ)=0Zρ0+1Zρ1Tr(\textbf{Z} \rho) = \langle 0|\textbf{Z} \rho|0 \rangle + \langle 1|\textbf{Z} \rho|1 \rangle =0(0011)ρ0+1(0011)ρ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ρ01ρ1=\langle 0|\rho|0 \rangle- \langle 1| \rho|1 \rangle =0ψψ01ψψ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+112\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' นั่นคือ เนื่องจาก U1UU^{-1}U เป็น identity ถ้า Qubit ของ Bob อยู่ในสถานะที่สร้างจาก U0U|0\rangle การใช้ inverse ควรให้ U1U0=0U^{-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 เพื่อตรวจสอบผลลัพธ์ของ 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+112CX01H000\frac {|00\rangle + |11\rangle}{\sqrt 2} \rightarrow CX_{01}\otimes H_0 \rightarrow |00\rangle 00112CX01H001\frac {|00\rangle - |11\rangle}{\sqrt 2} \rightarrow CX_{01}\otimes H_0 \rightarrow |01\rangle 10+012CX01H010\frac {|10\rangle + |01\rangle}{\sqrt 2} \rightarrow CX_{01}\otimes H_0 \rightarrow |10\rangle 10012CX01H011\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 ที่แบ่งปันกัน
  • Quantum superdense coding: คู่ entangled ที่แบ่งปันกันและการถ่ายโอน Qubit หนึ่งอัน ทำให้สามารถสื่อสารข้อมูลคลาสสิกสองบิตได้
# See the version of Qiskit
import qiskit

qiskit.__version__
'2.0.2'
Source: IBM Quantum docs — updated 15 ม.ค. 2569
English version on doQumentation — updated 7 พ.ค. 2569
This translation based on the English version of approx. 26 มี.ค. 2569