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

การแนะนำเกณฑ์ DiVincenzo แบบลงมือปฏิบัติด้วย Qiskit 2

บทนำ

นักฟิสิกส์ David DiVincenzo ได้ระบุข้อกำหนดสำคัญห้าประการสำหรับการนำคอมพิวเตอร์ควอนตัมไปใช้งานจริงในเชิงฟิสิกส์ บวกกับเกณฑ์เพิ่มเติมอีกสองประการสำหรับการสื่อสารควอนตัม ใน notebook นี้ เราจะสัมผัสกับเกณฑ์ DiVincenzo แต่ละข้อผ่านการสาธิตด้วย Qiskit แบบลงมือปฏิบัติ แทนที่จะเจาะลึกเรื่องทฤษฎี แต่ละส่วนจะอธิบายเกณฑ์หนึ่งข้ออย่างย่อ แล้วให้แบบฝึกหัดโค้ดด้วย Qiskit 2 คุณจะได้รัน Circuit บนซิมูเลเตอร์และอุปกรณ์ IBM Quantum จริง เพื่อสำรวจแต่ละหลักการด้วยตัวเอง

เกณฑ์ห้าประการของ DiVincenzo สำหรับการคำนวณเชิงควอนตัม:

  1. ระบบฟิสิกส์ที่ขยายขนาดได้พร้อม Qubit ที่มีลักษณะเฉพาะที่ชัดเจน
  2. ความสามารถในการกำหนดค่าเริ่มต้น Qubit ให้อยู่ในสถานะอ้างอิงที่เรียบง่าย (เช่น |00…0〉)
  3. เวลา decoherence ที่ยาวนาน (ความสอดคล้องของ Qubit ต้องยาวนานกว่าเวลาการทำงานของ Gate มาก)
  4. ชุด Gate ควอนตัมแบบ universal (สามารถทำ unitary operation ใดก็ได้ตามต้องการ)
  5. ความสามารถในการวัดแบบเจาะจง Qubit (อ่านค่าสถานะของแต่ละ Qubit)

(DiVincenzo ยังได้อธิบายเกณฑ์สองประการสำหรับการสื่อสารควอนตัมด้วย ได้แก่ ความสามารถในการแปลงระหว่าง Qubit แบบนิ่งและ "flying" Qubit และการส่ง flying Qubit ระหว่างตำแหน่งต่าง ๆ อย่างถูกต้อง เราจะรวมเรื่องนี้ไว้ในกิจกรรมแนะนำตอนท้ายของ notebook นี้)

แต่ละส่วนต่อไปนี้สอดคล้องกับเกณฑ์หนึ่งข้อ เราจะใช้ Qiskit เพื่ออธิบายแนวคิดด้วยโค้ดและการทดลองแบบโต้ตอบที่คุณสามารถลองทำได้ ตัวอย่างเช่น เราจะเห็นว่าการเพิ่มจำนวน Qubit และความลึกของ Circuit ส่งผลต่อผลลัพธ์อย่างไร (เกณฑ์ 1) วิธีรีเซ็ตและเตรียมสถานะ Qubit (เกณฑ์ 2) วิธีวัด Qubit บนซิมูเลเตอร์เทียบกับอุปกรณ์จริง (เกณฑ์ 4) วิธีที่ Qiskit สร้าง Gate แบบ universal (เกณฑ์ 3) และผลกระทบของ coherence ที่จำกัด (T₁, T₂) ต่อการคำนวณ (เกณฑ์ 5) เมื่อจบแล้ว คุณจะมีความเข้าใจที่ลึกซึ้งขึ้นว่าแต่ละเกณฑ์ DiVincenzo หมายความว่าอะไรในทางปฏิบัติ และ Qiskit ช่วยให้ทดลองกับเกณฑ์เหล่านั้นได้อย่างไร

# Added by doQumentation — required packages for this notebook
!pip install -q numpy
# Install necessary packages
!pip install qiskit[visualization] qiskit-ibm-runtime qiskit-aer qiskit_ibm_runtime

1. เกณฑ์ 1 – Qubit ที่ขยายขนาดได้และมีลักษณะเฉพาะที่ชัดเจน

เกณฑ์ 1: "ระบบฟิสิกส์ที่ขยายขนาดได้พร้อม Qubit ที่มีลักษณะเฉพาะที่ชัดเจน" หมายความว่าเราต้องการแพลตฟอร์มฮาร์ดแวร์ควอนตัมที่สามารถเพิ่มจำนวน Qubitได้ในขณะที่ยังควบคุมได้อย่างน่าเชื่อถือ คุณสมบัติของ Qubit แต่ละตัว (ระดับพลังงาน, อัตราความผิดพลาด, การเชื่อมต่อ ฯลฯ) ควรเป็นที่เข้าใจดี โดยพื้นฐานแล้ว เราต้องการสร้าง Circuit ขนาดใหญ่ขึ้นโดยไม่ให้ระบบพัง ในทางปฏิบัติ เมื่อเราขยายจำนวน Qubit หรือความลึกของ Circuit ความผิดพลาดและ decoherence จะสะสมขึ้น ดังนั้นการแสดงให้เห็น scalability ยังหมายถึงการทำความเข้าใจว่าการเพิ่มขนาดส่งผลต่อประสิทธิภาพอย่างไร

เป้าหมายของการสาธิต: ใช้ Qiskit เพื่อแสดงผลกระทบของการขยายขนาด Circuit (ในจำนวน Qubit หรือความลึกของ Gate) ต่อ fidelity ของผลลัพธ์ เราจะจำลองสถานการณ์ในอุดมคติเทียบกับแบบมีสัญญาณรบกวน เพื่อดูว่าระบบขนาดใหญ่ขึ้นหรือ Circuit ที่ลึกขึ้นพ่ายแพ้ต่อ decoherence และความผิดพลาดได้อย่างไร

ก่อนอื่น มาสร้างสถานะ entanglement ขนาดเล็ก (สถานะ GHZ) บน 3 Qubit จากนั้นขนาดใหญ่ขึ้นบน 5 Qubit เพื่อทดสอบการขยายขนาดอย่างง่าย สถานะ GHZ ของ Qubit จำนวน n ตัวคือ 12(0...0+1...1)\frac{1}{\sqrt{2}}(|0...0\rangle + |1...1\rangle) ในการจำลองแบบอุดมคติ การวัด GHZ ขนาด n Qubit จะได้เพียงสองผลลัพธ์ (ทั้งหมดเป็น 0 หรือทั้งหมดเป็น 1) ด้วยความน่าจะเป็นเท่ากัน เราจะเปรียบเทียบผลลัพธ์อุดมคติกับผลลัพธ์ที่มีสัญญาณรบกวนเมื่อเราเพิ่ม n หรือความลึกของ Circuit

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

# 3-qubit GHZ circuit
qc3 = QuantumCircuit(3, 3)
qc3.h(0)
qc3.cx(0, 1)
qc3.cx(1, 2)
qc3.measure([0, 1, 2], [0, 1, 2])

# 5-qubit GHZ circuit (scaling up the number of qubits)
qc5 = QuantumCircuit(5, 5)
qc5.h(0)
qc5.cx(0, range(1, 5)) # entangle qubit 0 with all others
qc5.measure(range(5), range(5))

# Transpile for a simulator backend
sim_backend = AerSimulator()
pm = generate_preset_pass_manager(backend=sim_backend, optimization_level=1)
isa_qc3 = pm.run(qc3)
isa_qc5 = pm.run(qc5)

# Run ideal simulations (no noise)
sampler = Sampler(mode=sim_backend)

job3 = sampler.run([isa_qc3], shots=1024)
result3 = job3.result()
counts3 = result3[0].data.c.get_counts()

job5 = sampler.run([isa_qc5], shots=1024)
result5 = job5.result()
counts5 = result5[0].data.c.get_counts()

print("3-qubit GHZ counts (ideal):", counts3)
plot_histogram(counts3, legend=['3-qubit ideal'], figsize=(6,4))
3-qubit GHZ counts (ideal): {'000': 531, '111': 493}

Quantum circuit diagram

print("5-qubit GHZ counts (ideal):", counts5)
plot_histogram(counts5, legend=['5-qubit ideal'], figsize=(6,4))
5-qubit GHZ counts (ideal): {'11111': 535, '00000': 489}

Code output

ผลลัพธ์ที่คาดหวัง (กรณีอุดมคติ): GHZ 3 Qubit ในอุดมคติจะได้ประมาณ 50% 000 และ 50% 111 ใน counts GHZ 5 Qubit จะได้ ~50% 00000 และ 50% 11111 ไม่มี bit-string อื่นปรากฏขึ้น เพราะสถานะอยู่ใน coherent และ entanglement อย่างสมบูรณ์ในอุดมคติ คุณควรเห็นแท่งสูงสองแท่งบน histogram สำหรับแต่ละ Circuit ที่สอดคล้องกับผลลัพธ์ทั้งหมดเป็นศูนย์และทั้งหมดเป็นหนึ่ง

ต่อไป มาดูว่าเกิดอะไรขึ้นในสภาพแวดล้อมที่มีสัญญาณรบกวน เราจะใช้ความสามารถของ noise model ใน Qiskit Aer เพื่อจำลองความผิดพลาดของอุปกรณ์จริง ตัวอย่างเช่น เราสามารถนำคุณสมบัติของ IBM backend มาสร้าง noise model ที่รวมถึงความผิดพลาดของ Gate, เวลา Gate ที่จำกัด, การคลายตัวของ Qubit (T₁), dephasing (T₂) และความผิดพลาดในการอ่านค่า ที่นี่ เราจะใช้ fake backend ที่แสดงถึงอุปกรณ์ IBM Quantum Brisbane เพื่อสร้าง noise model แล้วรัน Circuit GHZ อีกครั้งผ่านโมเดลนั้น

แบบฝึกหัด 1a: จำลองด้วย Noise

เติมโค้ดด้านล่างให้สมบูรณ์เพื่อจำลอง Circuit GHZ บนซิมูเลเตอร์ที่มีสัญญาณรบกวนจาก backend FakeBrisbane ซึ่งจะแสดงให้เห็นว่าประสิทธิภาพลดลงอย่างไรเมื่อระบบขยายขนาดในสภาพแวดล้อม noise จริง

from qiskit_ibm_runtime.fake_provider import FakeBrisbane

# We will reuse the ideal circuits qc3 and qc5 and their results from the previous cell.

# --- YOUR CODE HERE ---

# 1. Create a fake backend for IBM Quantum Brisbane
###brisbane_backend = ...

# 2. Create a noisy AerSimulator from the fake backend's properties
###noisy_sim = ...

# 3. Transpile the circuits for the noisy simulator (this adapts them to the device's specific gates and connectivity)
###pm = ...

###isa_qc3_noisy = ...

###isa_qc5_noisy = ...

# 4. Run the noisy simulations using the Sampler and get the counts
###sampler = ...

###job3 = ...

###result3_noisy = ...

###counts3_noisy = ...

###job5 = ...

###result5_noisy = ...

###counts5_noisy = ...

# --- END YOUR CODE ---

# This part is done for you to print and plot the results:
print("3-qubit GHZ counts (noisy):", counts3_noisy)
plot_histogram(counts3_noisy, legend=['3-qubit noisy'], figsize=(6,4))
print("5-qubit GHZ counts (noisy):", counts5_noisy)
plot_histogram(counts5_noisy, legend=['5-qubit noisy'], figsize=(6,4))

แบบฝึกหัด 1b: รันบนคอมพิวเตอร์ควอนตัม IBM จริง

โค้ดด้านล่างนี้รัน Circuit GHZ บนคอมพิวเตอร์ควอนตัม IBM จริง ซึ่งจะแสดงให้เห็นว่าประสิทธิภาพลดลงอย่างไรบนอุปกรณ์จริง

# your_api_key = "deleteThisAndPasteYourAPIKeyHere"
# your_crn = "deleteThisAndPasteYourCRNHere"

# QiskitRuntimeService.save_account(
# channel="ibm_quantum_platform",
# token=your_api_key,
# instance=your_crn,
# name="fallfest-2025",
# )

# Check that the account has been saved properly
# service = QiskitRuntimeService(name="fallfest-2025")
# print(service.saved_accounts())

# We will reuse the ideal circuits qc3 and qc5 and their results from the previous cell.

from qiskit_ibm_runtime import QiskitRuntimeService

service = QiskitRuntimeService(name="fallfest-2025")
real_backend = service.least_busy(operational=True, simulator=False)
print("Running on " + real_backend.name)

pm = generate_preset_pass_manager(backend=real_backend, optimization_level=1)
isa_qc3r = pm.run(qc3)
isa_qc5r = pm.run(qc5)

sampler = Sampler(mode=real_backend)

job3r = sampler.run([isa_qc3r], shots=1024)
result3r = job3r.result()
counts3r = result3r[0].data.c.get_counts()

job5r = sampler.run([isa_qc5r], shots=1024)
result5r = job5r.result()
counts5r = result5r[0].data.c.get_counts()

print("3-qubit GHZ counts (real):", counts3r)
plot_histogram(counts3r, legend=['3-qubit real'], figsize=(6,4))
print("5-qubit GHZ counts (real):", counts5r)
plot_histogram(counts5r, legend=['5-qubit real'], figsize=(6,4))

ผลลัพธ์ที่คาดหวัง (noisy เทียบกับ ideal): เมื่อมีสัญญาณรบกวน ไม่ว่าจะจำลองหรือบนอุปกรณ์จริง สถานะ GHZ จะไม่สมบูรณ์แบบ คุณจะเห็นผลลัพธ์เพิ่มเติมนอกเหนือจากทั้งหมดเป็น 0 และทั้งหมดเป็น 1 สำหรับ 3 Qubit แทนที่จะได้ 100% ใน 000/111 ความน่าจะเป็นบางส่วนจะรั่วไหลไปยัง bit-string อื่น (เช่น 001, 010 ฯลฯ) เนื่องจากความผิดพลาดของ Gate หรือ decoherence ที่พลิก Qubit บางตัว สำหรับ 5 Qubit ผลกระทบจะเด่นชัดยิ่งขึ้น Circuit ขนาดใหญ่ (มี Qubit และ CNOT Gate มากขึ้น) จะสะสมความผิดพลาดมากขึ้น ดังนั้นยอด all-0 และ all-1 จึงต่ำลง และผลลัพธ์อื่น ๆ อีกมากมายปรากฏขึ้น แนวโน้มนี้แสดงให้เห็นถึงความท้าทายของ scalability: เมื่อเราขยายขนาด การรักษา fidelity สูงทำได้ยากขึ้นหากไม่มีการแก้ไขความผิดพลาด

ข้อสังเกต: คอมพิวเตอร์ควอนตัมที่ขยายขนาดได้ต้องรักษาความสัมพันธ์เชิงควอนตัมเมื่อระบบเติบโตขึ้น ตัวอย่างของเราแสดงให้เห็นว่าการเพิ่มจำนวน Qubit/ความลึกของ Gate ทำให้ fidelity ของผลลัพธ์ลดลงเมื่อมีสัญญาณรบกวน เกณฑ์ที่เหลือจะจัดการกับการรักษา Qubit เหล่านั้นให้ทำงานได้ดี (ความผิดพลาดต่ำ, กำหนดค่าเริ่มต้นได้ ฯลฯ) เมื่อเราขยายขนาด

2. เกณฑ์ 2 – การกำหนดค่าเริ่มต้น Qubit

เกณฑ์ 2: "ความสามารถในการกำหนดค่าเริ่มต้นของสถานะ Qubit ให้เป็นสถานะอ้างอิงที่เรียบง่าย เช่น |000…〉" Qubit ทุกตัวควรเริ่มต้นในสถานะอ้างอิงที่รู้จักอย่างน่าเชื่อถือ (โดยปกติคือสถานะพื้น |0〉 สำหรับแต่ละ Qubit) การกำหนดค่าเริ่มต้นเป็นสิ่งจำเป็นเพื่อให้อัลกอริทึมเริ่มต้นจากจุดเริ่มต้นที่สะอาด ในทางปฏิบัติ บนอุปกรณ์ IBM quantum แต่ละ Qubit จะถูกรีเซ็ตเป็น |0〉 โดยอัตโนมัติเมื่อเริ่มต้นการรัน Circuit แต่ละครั้ง Qiskit ยังมีคำสั่งสำหรับรีเซ็ต Qubit หรือเตรียมสถานะที่กำหนดเองระหว่างการคำนวณด้วย

เป้าหมายของการสาธิต: แสดงวิธีกำหนดค่าเริ่มต้น Qubit ใน Qiskit ทั้งตอนเริ่มต้นและกลาง Circuit เราจะสาธิตการใช้คำสั่ง reset และวิธีการเตรียมสถานะ

แบบฝึกหัด 2: เตรียมสถานะที่กำหนด

ในบล็อกโค้ดด้านล่าง เติม QuantumCircuit ให้สมบูรณ์เพื่อเตรียมสถานะ 10|10\rangle หมายความว่า Qubit 0 ควรอยู่ในสถานะ 0|0\rangle และ Qubit 1 ควรอยู่ในสถานะ 1|1\rangle ใช้ Gate และคำสั่งที่เหมาะสมเพื่อบรรลุเป้าหมายนี้

from qiskit import QuantumCircuit
from qiskit_aer import AerSimulator

# Create a circuit to initialize qubits to |10> and verify by measurement
qc_init = QuantumCircuit(2, 2)

# --- YOUR CODE HERE ---

# 1. Set qubit 1 to the |1> state

# 2. Explicitly reset qubit 0 to the |0> state

# --- END YOUR CODE ---

qc_init.measure([0, 1], [0, 1])
qc_init.draw('mpl')
# Run the circuit and check the outcome
sim_backend = AerSimulator()
pm = generate_preset_pass_manager(backend=sim_backend, optimization_level=1)
isa_qc_init = pm.run(qc_init)

sampler = Sampler(mode=sim_backend)

job = sampler.run([isa_qc_init], shots=1024)
result = job.result()
counts = result[0].data.c.get_counts()

print("Outcome of |10> state measured in Z-basis:", counts)
plot_histogram(counts)

คุณควรเห็น 10 (เลขฐานสองสำหรับ qubit1=1, qubit0=0) ด้วยความน่าจะเป็น 100% จากการจำลอง หมายความว่า Qubit 1 ถูกเตรียมไว้ใน |1〉 และ Qubit 0 อยู่ใน |0〉 สำเร็จ

ตอนนี้ สำหรับการเตรียมสถานะทั่วไปมากขึ้น Qiskit อนุญาตให้กำหนดค่าเริ่มต้นเป็นสถานะใดก็ได้โดยใช้เมธอด initialize ตัวอย่างเช่น มาเตรียม Qubit ในสถานะ +=(0+1)/2|+\rangle = (|0\rangle+|1\rangle)/\sqrt{2} ซึ่งเป็นสถานะ superposition และ Qubit คู่หนึ่งในสถานะ Bell (00+11)/2(|00\rangle+|11\rangle)/\sqrt{2}:

import numpy as np

# Initialize a single qubit in |+> state and measure in Z-basis
qc_plus = QuantumCircuit(1, 1)
state_plus = [1/np.sqrt(2), 1/np.sqrt(2)] # amplitude for |0> and |1>
qc_plus.initialize(state_plus, 0)
qc_plus.measure(0, 0)

# Initialize two qubits in a Bell state manually
qc_bell = QuantumCircuit(2, 2)
bell_state = [1/np.sqrt(2), 0, 0, 1/np.sqrt(2)] # amplitudes for |00>,|01>,|10>,|11>
qc_bell.initialize(bell_state, [0, 1])
qc_bell.measure([0, 1], [0, 1])

# Transpile and run the initialization circuits
isa_qc_plus = pm.run(qc_plus)
job_plus = sampler.run([isa_qc_plus], shots=1024)
result_plus = job_plus.result()
counts_plus = result_plus[0].data.c.get_counts()

print("Outcome of |+> state measured in Z-basis:", counts_plus)

isa_qc_bell = pm.run(qc_bell)
job_bell = sampler.run([isa_qc_bell], shots=1024)
result_bell = job_bell.result()
counts_bell = result_bell[0].data.c.get_counts()

print("Outcome of Bell state measured in Z-basis:", counts_bell)
Outcome of |+> state measured in Z-basis: {'1': 499, '0': 525}
Outcome of Bell state measured in Z-basis: {'00': 508, '11': 516}

ผลลัพธ์ที่คาดหวัง: สถานะ Qubit เดี่ยว |+〉 เมื่อวัดแล้วจะได้ 0 และ 1 ด้วยความน่าจะเป็นประมาณ 50% แต่ละค่า การวัดสถานะ Bell ควรได้ประมาณ 50% 00 และ 50% 11 หากเห็นผลลัพธ์เหล่านี้ แสดงว่าการกำหนดค่าเริ่มต้นเป็นสถานะเหล่านั้นสำเร็จแล้ว

การกำหนดค่าเริ่มต้นกลาง Circuit: reset ของ Qiskit สามารถใช้กลาง Circuit เพื่อกำหนดค่าเริ่มต้น Qubit ใหม่เป็น |0〉 แบบ on-the-fly ตัวอย่างเช่น ในโค้ด error correction หรืออัลกอริทึมแบบ iterative มักจะวัด Qubit แล้วรีเซ็ตเพื่อนำกลับมาใช้ใหม่ การดำเนินการ reset เป็นแบบ deterministic คือจะทิ้งสถานะที่มีอยู่และทำให้ Qubit กลับสู่สถานะพื้น

Device example: บนฮาร์ดแวร์อย่าง ibmq_brisbane (127 Qubit) หรืออุปกรณ์ IBM ใด ๆ Qubit ทุกตัวจะเริ่มต้นใน |0〉 โดยค่าเริ่มต้นเมื่อรัน job หากต้องการสถานะเริ่มต้นที่แตกต่าง คุณจะต้องใช้ Gate ตอนต้น (เช่นที่เราทำด้วย X เพื่อให้ได้ |1〉) การกำหนดค่าเริ่มต้นใหม่อย่างต่อเนื่อง (สำหรับ quantum error correction) เป็นหัวข้อวิจัยที่ยังดำเนินอยู่ เพราะการทำอย่างรวดเร็วเป็นเรื่องท้าทาย โชคดีที่สำหรับการใช้งานพื้นฐาน ความสามารถในการเริ่มต้นใหม่ใน |0…0〉 พร้อมใช้งาน และเราได้สาธิตวิธีบรรลุสถานะเริ่มต้นที่ต้องการอื่น ๆ ด้วย

3. เกณฑ์ข้อที่ 3 – เวลาความสอดคล้องที่ยาวนาน (Decoherence vs เวลา Gate)

เกณฑ์ข้อที่ 3: "เวลา decoherence ที่เกี่ยวข้องต้องยาวนานกว่าเวลาการทำงานของ Gate มาก" เกณฑ์นี้พูดถึงความจำเป็นที่ Qubit ต้องรักษาสถานะควอนตัมของมันไว้ได้นานพอที่จะทำการคำนวณที่ต้องการได้ Qubit แต่ละตัวมี เวลา T₁ (เวลา relaxation ของพลังงาน หรือความเร็วที่ |1〉 สลายตัวกลับไปเป็น |0〉) และ เวลา T₂ (เวลา dephasing หรือความเร็วที่ความสอดคล้องของเฟสสัมพัทธ์หายไป) เพื่อให้คอมพิวเตอร์ควอนตัมทำงานได้ ช่วงเวลาเหล่านี้ต้องยาวนานกว่าระยะเวลาการทำงานของ Gate อย่างมาก

เป้าหมายของการสาธิต: ตรวจสอบ coherence ของ Qubit ใน Qiskit โดยแสดงให้เห็นว่า decoherence ส่งผลต่อผลลัพธ์ Circuit อย่างไรเมื่อความยาวของการรันเพิ่มขึ้น เราจะใช้ fake backend ที่มีค่า T1/T2 ที่ทราบแน่นอนเพื่อจำลองผลกระทบนี้

เพื่อ สาธิตผลกระทบของ coherence ที่จำกัด เราจะจำลองการทดลอง T1 decay โดยเตรียม Qubit ในสถานะ |1〉 รอสักพักโดยใช้คำสั่ง delay แล้วจึงวัด เราคาดว่าความน่าจะเป็นของการวัดได้ |1〉 จะลดลงเมื่อเวลาหน่วงเพิ่มขึ้น

# This part is done for you. We are creating a list of circuits,
# each with a different delay time.

time_delays_ns = [0, 50000, 100000, 150000, 200000, 250000, 300000] # delay durations in ns

decay_expts = []
for delay in time_delays_ns:
qc = QuantumCircuit(1, 1)
qc.x(0) # initialize qubit to |1>
if delay > 0:
qc.delay(delay, 0, unit='ns') # wait 'delay' nanoseconds
qc.measure(0, 0)
decay_expts.append(qc)

decay_expts[1].draw('mpl') # Visualize one of the circuits

Quantum circuit diagram

แบบฝึกหัด 3: จำลองการทดลอง T1 Decay

ตอนนี้ให้ใช้ noisy simulator ที่อิงจาก FakeVigo (ซึ่งมีเวลา T1 ประมาณ 50-100 µs) เพื่อรัน Circuit เหล่านี้ simulator จะใส่ error จาก T1/T2 โดยอัตโนมัติระหว่างคำสั่ง delay ให้ transpile Circuit สำหรับ backend นี้แล้วรันการทดลอง

from qiskit_ibm_runtime.fake_provider import FakeVigoV2 as FakeVigo
from qiskit_aer import AerSimulator

# --- YOUR CODE HERE ---

# 1. Create a noisy simulator from the FakeVigo backend
###sim_vigo = ...

# 2. Transpile the list of circuits for this simulator
###pm = ...

###isa_decay_expts = ...

# 3. Use the Sampler to run all the transpiled circuits in a single job
###sampler = ...

###job = ...

###result = ...

# --- END YOUR CODE ---

# This part is done for you to analyze and print the results.
for idx, (delay, qc) in enumerate(zip(time_delays_ns, isa_decay_expts)):
counts = result[idx].data.c.get_counts()
p1 = counts.get('1', 0) / 1000 # Assuming 1000 shots
print(f"Delay {delay} ns: P(qubit=1) = {p1:.3f}")

4. เกณฑ์ข้อที่ 4 – ชุด Quantum Gate แบบ Universal

เกณฑ์ข้อที่ 4: "ชุด Quantum Gate ที่เป็น 'universal'" หมายความว่าฮาร์ดแวร์ของเราต้องสามารถทำการคำนวณควอนตัมใดๆ ได้โดยการรวม Gate พื้นฐานจำนวนจำกัด ในการคำนวณแบบคลาสสิก NAND เป็น universal ในเชิงควอนตัมก็มีทางเลือกมากมายสำหรับชุด Gate แบบ universal (เช่น {H, T, CNOT} หรือ Gate ดั้งเดิมของเครื่องที่ใช้) อุปกรณ์ IBM เช่น มีชุดการดำเนินการดั้งเดิม เช่น การหมุน single-qubit แบบอิสระและ CNOT ระหว่าง Qubit บางตัว ซึ่งรวมกันแล้วเป็น universal หน้าที่ของ Qiskit มักเป็นการ compile Gate ระดับสูงให้เป็น basis gates เหล่านี้

เป้าหมายของการสาธิต: แสดงให้เห็น universality ของ Gate โดยแสดงวิธีที่ Qiskit แตก Gate ออก เราจะนำ Gate ที่ไม่ใช่ native (เช่น Toffoli Gate 3-qubit หรือ CCX) แล้วดูว่ามันแตกตัวออกเป็น basis gates ดั้งเดิมของอุปกรณ์อย่างไร ซึ่งแสดงให้เห็นว่าชุด Gate ที่มีให้นั้นเป็น universal จริงๆ คือสามารถสร้างการดำเนินการที่ซับซ้อนกว่าได้

ก่อนอื่น มาดูกันว่า basis gates ของ IBM backend ทั่วไปคืออะไร เราจะ query configuration ของอุปกรณ์ (หรือ fake version ของมัน) เช่น basis gates ของ ibmq_brisbane: คุณควรสังเกตว่าความน่าจะเป็น P(qubit=1) ลดลงเมื่อเวลาหน่วงเพิ่มขึ้น โดยเป็นไปตามเส้นโค้ง exponential decay ที่เป็นลักษณะเฉพาะของ T1 relaxation ซึ่งแสดงให้เห็นโดยตรงว่าเวลา coherence ที่จำกัดนำไปสู่ error ในการคำนวณหากรัน Circuit นานเกินไป

ผลกระทบต่ออัลกอริทึม: หากลองรันอัลกอริทึมที่ยาวขึ้น (ที่มี Gate หลายตัวต่อกัน) เวลาทำงานรวมอาจใกล้เคียงหรือเกิน T2 ทำให้สถานะสูญเสีย coherence ก่อนสิ้นสุด นี่คือสาเหตุที่การปรับปรุงเวลา coherence และทำให้ Gate เร็วขึ้นเป็นสองเป้าหมายที่สำคัญที่สุดในการวิจัยฮาร์ดแวร์ควอนตัม

from qiskit_ibm_runtime.fake_provider import FakeBrisbane
fake_brisbane = FakeBrisbane()
print("Basis gates for ibmq_brisbane:", fake_brisbane.configuration().basis_gates)
Basis gates for ibmq_brisbane: ['ecr', 'id', 'rz', 'sx', 'x']

ผลลัพธ์อาจออกมาประมาณ ['id', 'rz', 'sx', 'x', 'ecr'] เหล่านี้คือการดำเนินการพื้นฐานที่ฮาร์ดแวร์รองรับโดยตรง (Identity/no-op, RZ rotation, sqrt(X) gate, X gate, และ controlled-X) Gate อื่นๆ ทั้งหมดต้องประกอบจากสิ่งเหล่านี้ ชุดนี้เป็นที่รู้กันว่า universal สำหรับการคำนวณควอนตัม (โดยพื้นฐานแล้วการหมุน single-qubit บวกกับ entangling two-qubit gate ก็เป็นชุด universal)

ตอนนี้ ลองใช้ Toffoli (CCX) Gate เป็นกรณีทดสอบ CCX จะ flip target qubit ก็ต่อเมื่อ control qubit ทั้งสองตัวเป็น 1 มันไม่ใช่ native gate บนฮาร์ดแวร์ IBM Qiskit มีคำสั่ง ccx แต่เบื้องหลังมันจะแตกตัวออก

แบบฝึกหัด 4: แตก Toffoli Gate ออก

เติมโค้ดด้านล่างให้สมบูรณ์เพื่อสร้าง Circuit ที่มี Toffoli (CCX) Gate แล้วใช้ Qiskit เพื่อแตกมันออกเป็น basis gates ดั้งเดิมของ Backend FakeBrisbane

from qiskit import QuantumCircuit
from qiskit_ibm_runtime.fake_provider import FakeBrisbane

# The fake_brisbane backend from the previous cell is reused here.

# --- YOUR CODE HERE ---

# 1. Create a circuit that can accommodate a Toffoli gate
###qc_toffoli = ...

# Apply a CCX gate with controls on qubits 0, 1 and target on qubit 2

# 2. Transpile the circuit to the fake Brisbane backend
###pm = ...

###isa_qc_toffoli = ...

# --- END YOUR CODE ---

print("Toffoli circuit before decomposition:")
print(qc_toffoli)

print("\nToffoli circuit after transpiling to Brisbane basis:")
# The .draw() method will now show the decomposed circuit
print(isa_qc_toffoli.draw(fold=120))

ในผลลัพธ์ที่ transpile แล้ว คุณจะเห็น CCX ถูกแทนที่ด้วยลำดับของ Gate พื้นฐานมากขึ้น เช่น rz, sx, และ ecr ซึ่งพิสูจน์ว่า native gates เพียงพอที่จะแสดง Toffoli ได้

Universality ในทางปฏิบัติ: แบบฝึกหัดข้างต้นแสดงให้เห็นว่า Gate 3-qubit ที่ซับซ้อนถูกสร้างจาก Gate ที่ง่ายกว่า โดยทั่วไปแล้ว ทุก unitary หลาย qubit สามารถประกอบจาก 1- และ 2-qubit Gate ได้ Transpiler เป็นองค์ประกอบสำคัญของ quantum software stack ใดๆ เนื่องจากเชื่อมช่องว่างระหว่างอัลกอริทึมเชิงนามธรรมที่เราต้องการรันกับการดำเนินการจริงที่อุปกรณ์ควอนตัมเฉพาะสามารถทำได้จริงๆ

Device example: อุปกรณ์ ibmq_brisbane ใช้สถาปัตยกรรม Eagle พร้อม basis gates ที่แสดงไว้ข้างต้น หมายความว่าอัลกอริทึมใดๆ ที่ส่งไปยังเครื่องเหล่านั้นจะถูกแปลงเป็นลำดับของการดำเนินการเหล่านั้น เกณฑ์นี้โดยพื้นฐานแล้วเกี่ยวกับ controllability เรามี control knob เพียงพอที่จะทำการดำเนินการที่จำเป็นบน Qubit ของเรา

5. เกณฑ์ข้อที่ 5 – การวัด Qubit

เกณฑ์ข้อที่ 5: "ความสามารถในการวัดเฉพาะ Qubit" สถานะของ Qubit ทุกตัวต้องสามารถวัดได้ (โดยปกติใน computational basis คือ |0〉 หรือ |1〉) กล่าวคือ หลังจากรัน quantum Circuit แล้ว เราต้องอ่านค่า Qubit แต่ละตัวเป็น 0/1 แบบ classical bit เกณฑ์นี้เกี่ยวกับการมี detector ที่เชื่อถือได้สำหรับ Qubit แต่ละตัวและสามารถเลือกว่า Qubit ตัวไหนจะวัด

เป้าหมายของการสาธิต: แสดงวิธีการวัดใน Qiskit บน simulator และอุปกรณ์จริง และเน้นความแตกต่าง (เช่น measurement noise) เราจะวัด Qubit บางตัวในสถานะต่างๆ และตรวจสอบผลลัพธ์ นอกจากนี้เราจะสาธิตว่า readout error อาจปรากฏขึ้นอย่างไรโดยเปรียบเทียบผล simulator กับฮาร์ดแวร์

ก่อนอื่น ตัวอย่างการวัดง่ายๆ:

qc_measure = QuantumCircuit(2, 2)
qc_measure.x(0) # qubit 0 -> |1>, qubit 1 stays |0>
qc_measure.measure([0, 1], [0, 1])
qc_measure.draw('mpl')

Quantum circuit diagram

sim_backend = AerSimulator()
pm = generate_preset_pass_manager(backend=sim_backend, optimization_level=1)
isa_qc_measure = pm.run(qc_measure)
job = sampler.run([isa_qc_measure], shots=1000)
result = job.result()
counts = result[0].data.c.get_counts()

print("Simulator measurement counts:", counts)
Simulator measurement counts: {'01': 1000}

เราคาดว่าจะได้ 1000 counts ของ 01 บน simulator ตอนนี้มาดู measurement error ในทางปฏิบัติโดยการจำลองมัน เราสามารถเพิ่ม readout error ให้กับ Aer simulator ของเราได้ Qiskit Aer ช่วยให้เราสามารถกำหนด ReadoutError และแนบมันกับ Qubit ใน noise model

แบบฝึกหัด 5: จำลอง Readout Error

เติมโค้ดให้สมบูรณ์เพื่อกำหนด readout error model ง่ายๆ ที่ Qubit แต่ละตัวมีโอกาส 2% ที่จะถูกวัดผิด (0 ถูกอ่านเป็น 1 หรือ 1 ถูกอ่านเป็น 0) แล้วรัน measurement Circuit พร้อม noise model นี้

from qiskit_aer.noise import NoiseModel, ReadoutError

# --- YOUR CODE HERE ---

# 1. Define a 2% readout error for each single qubit.
# The format is a list of lists of probabilities: [[P(0|0), P(1|0)], [P(0|1), P(1|1)]]
# P(A|B) is the probability of measuring A given the state was |B>.
###ro_error = ...

# 2. Create a new noise model
###noise_model_ro = ...

# 3. Add the readout error to all qubits in the noise model
... # Hint: Use the add_all_qubit_readout_error method

# --- END YOUR CODE ---

sim_backend.set_options(noise_model=noise_model_ro)
pm = generate_preset_pass_manager(backend=sim_backend, optimization_level=1)
isa_qc_measure = pm.run(qc_measure)

# Run the measurement circuit with readout noise
sampler = Sampler(mode=sim_backend)

job = sampler.run([isa_qc_measure], shots=1024)
result = job.result()
counts = result[0].data.c.get_counts()

print("Simulation with 2% readout error:", counts)

ผลลัพธ์จำลองนี้จะแสดง counts ที่ผิดพลาดบางส่วน (เช่น 11, 00, 10) คล้ายกับที่ฮาร์ดแวร์จริงอาจสร้างขึ้น ซึ่งแสดงให้เห็นผลกระทบของการวัดที่ไม่สมบูรณ์

Device example: บนอุปกรณ์จริงอย่าง ibmq_brisbane คุณสามารถรัน Circuit เดียวกันได้และอาจเห็น counts ที่ไม่ใช่ศูนย์สำหรับผลลัพธ์ที่ไม่ถูกต้องในลักษณะเดียวกัน ข้อมูล calibration ของอุปกรณ์จะแสดง readout error สำหรับ Qubit แต่ละตัว ความสามารถในการเลือกและอ่านค่า Qubit เฉพาะนั้นเป็นสิ่งสำคัญ และการเข้าใจลักษณะ error ของมันเป็นกุญแจสำคัญในการได้ผลลัพธ์ที่มีความหมาย การรันบนอุปกรณ์จริงได้สาธิตไว้ใน แบบฝึกหัด 1b: รันบนคอมพิวเตอร์ควอนตัม IBM จริง

เกณฑ์การสื่อสารควอนตัม (Flying Qubits)

DiVincenzo ยังได้ระบุเกณฑ์อีกสองข้อที่เฉพาะเจาะจงสำหรับการสื่อสารควอนตัม ซึ่งสำคัญสำหรับการสร้างคอมพิวเตอร์ควอนตัมแบบเครือข่าย:

  1. ความสามารถในการแปลงระหว่าง stationary qubit และ flying qubit (เช่น แมป Qubit ในโปรเซสเซอร์เป็นโฟตอนที่เดินทางได้)
  2. ความสามารถในการส่ง flying qubit ระหว่างตำแหน่งได้อย่างน่าเชื่อถือ (เช่น ส่งโฟตอน Qubit ผ่านใยแก้วโดยไม่สูญเสียข้อมูลควอนตัม)

สิ่งเหล่านี้อยู่เกินขอบเขตการใช้งาน Qiskit ปกติ เพราะ Qiskit ส่วนใหญ่จัดการกับ stationary qubit บนชิป อย่างไรก็ตาม เราสามารถอธิบาย แนวคิด ของเกณฑ์เหล่านี้ด้วยตัวอย่างง่ายๆ: quantum teleportation Teleportation แสดงให้เห็นการแปลงสถานะของ stationary qubit เป็นข้อมูลที่นำพาโดยคู่ entangled (ส่วน "flying") และการสื่อสารแบบ classical ซึ่งจากนั้นนำมาใช้เพื่อสร้างสถานะขึ้นมาใหม่บน stationary qubit อีกตัวในที่อื่น

Module Quantum Teleportation ของ Qiskit in Classrooms โดย Dr. Katie McCormick จะพาคุณผ่านหนึ่งใน protocols ที่น่าตื่นเต้นที่สุดในข้อมูลควอนตัม: quantum teleportation ที่สถานะควอนตัม (Qubit) ถูกส่งจาก Alice ไปยัง Bob โดยใช้ entanglement และ classical bit เพียงสองบิต คุณจะได้เรียนรู้ขั้นตอน teleportation ทั้งหมดทีละขั้นตอน ทั้งวิธีเตรียม entangled Bell pair การวัดในฐาน Bell ของ Alice การส่งผลลัพธ์แบบ classical และการใช้ quantum gate ที่ถูกต้องบน Qubit ของ Bob เพื่อกู้คืนสถานะดั้งเดิมได้อย่างสมบูรณ์ ระหว่างทาง คุณจะสำรวจว่าทำไมการ teleport ข้อมูลของ Qubit ถึงไม่ละเมิด no-cloning theorem หรือเกินความเร็วแสง ผ่านแบบฝึกหัดแบบ hands-on โดยใช้ฮาร์ดแวร์ IBM Quantum หรือ simulator คุณจะได้รับความเข้าใจในทางปฏิบัติเกี่ยวกับการวัด entanglement และ feed-forward control ในทางปฏิบัติ

การเชี่ยวชาญ quantum teleportation จะทำให้คุณเข้าใจวิธีการเข้ารหัส ส่ง และกู้คืนข้อมูลควอนตัมระหว่าง nodes ที่แตกต่างกัน ซึ่งเป็นรากฐานสำหรับเครือข่ายควอนตัม ระบบ repeater โครงการสื่อสารที่ปลอดภัย และการคำนวณควอนตัมแบบ modular ที่ขยายได้

ความเชื่อมโยงกับเกณฑ์ข้อ 6 & 7: ในเครือข่ายควอนตัมจริง คู่ entangled ที่ใช้ร่วมกันจะถูกสร้างโดยการกระจาย "flying" qubit (เช่น โฟตอน) ระหว่างตำแหน่งของ Alice และ Bob (เกณฑ์ข้อที่ 7: การส่งสัญญาณที่น่าเชื่อถือ) จากนั้น teleportation protocol เองทำหน้าที่เป็นวิธีแมปสถานะ stationary qubit ของ Alice เข้าไปในครึ่งหนึ่งของคู่ entangled ซึ่งทำให้ 'ส่ง' ไปยัง Bob ได้อย่างมีประสิทธิภาพ (เกณฑ์ข้อที่ 6: interconversion) Qiskit ช่วยให้เราจำลอง logic ของ protocol ได้อย่างสมบูรณ์แบบ โดยให้โมเดลเชิงแนวคิดว่าเกณฑ์เหล่านี้ถูกบรรลุในสถาปัตยกรรมการสื่อสารอย่างไร

บทสรุป

เราได้ออกแบบแบบฝึกหัดที่เน้นโค้ดหลายชุดเพื่ออธิบายเกณฑ์ DiVincenzo โดยใช้ Qiskit ผ่านตัวอย่าง hands-on เหล่านี้ คุณได้สำรวจว่าแพลตฟอร์มการคำนวณควอนตัมจริงบรรลุแต่ละข้อกำหนดอย่างไร:

  • Scalability: การสร้าง Circuit บน Qubit จำนวนมากขึ้นและทำความเข้าใจกับ noise scaling
  • Initialization: การใช้ reset และการเตรียมสถานะเพื่อเริ่มต้นการคำนวณในสถานะที่รู้จักอย่างน่าเชื่อถือ
  • Universal Gates: การ transpile การดำเนินการที่ซับซ้อนเป็น basis gates ของเครื่อง ซึ่งพิสูจน์ว่าเราสามารถทำการคำนวณใดๆ ได้
  • Measurement: การอ่านค่า Qubit และการจัดการกับ readout error ที่สมจริง
  • Coherence: การเห็นผลกระทบของ T₁, T₂ ที่จำกัดต่อ fidelity ของอัลกอริทึม และความจำเป็นที่การดำเนินการต้องเร็วเมื่อเทียบกับ decoherence

เพื่อความสมบูรณ์ เรายังได้กล่าวถึงแง่มุมการสื่อสารควอนตัมผ่าน Module Quantum Teleportation ของ Qiskit in Classrooms ซึ่งเชื่อมโยงเกณฑ์สองข้อสุดท้าย (flying qubits)

ท้ายที่สุด ควรสังเกตว่าเกณฑ์เหล่านี้มารวมกันอย่างไรในคอมพิวเตอร์ควอนตัมจริงอย่าง IBM อุปกรณ์อย่าง ibmq_brisbane มี superconducting qubit 127 ตัว (เกณฑ์ข้อที่ 1) แต่ละตัวเริ่มต้นที่ |0〉 (เกณฑ์ข้อที่ 2) พร้อม calibrated gate set และ compiler สำหรับ universality (เกณฑ์ข้อที่ 4) microwave readout resonator สำหรับ Qubit แต่ละตัว (เกณฑ์ข้อที่ 5) และ coherence time ในระดับหลายร้อย microsecond เทียบกับการดำเนินการในระดับ nanosecond (เกณฑ์ข้อที่ 3) สำหรับการทดลองเครือข่ายควอนตัม IBM และบริษัทอื่นๆ กำลังสำรวจ microwave-to-optical transduction สำหรับ flying qubit และการ entangle Qubit ที่อยู่ห่างกัน (เกณฑ์ข้อที่ 6 & 7) ซึ่งเป็นพื้นที่วิจัยที่ยังเปิดอยู่

โดยการทำแบบฝึกหัดใน notebook นี้ให้เสร็จสมบูรณ์ คุณไม่ได้แค่เห็นนิยามของเกณฑ์ DiVincenzo แต่ได้ สัมผัส มันผ่านโค้ด สร้างความเข้าใจในเชิงสัญชาตญาณว่าแต่ละข้อกำหนดหมายความว่าอะไรสำหรับฮาร์ดแวร์ควอนตัมจริงและอัลกอริทึม อย่าลังเลที่จะขยายการทดลองเหล่านี้ แล้วขอให้สนุกกับการคำนวณควอนตัม!