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

รัน dynamic circuits

เวอร์ชันแพ็กเกจ

โค้ดในหน้านี้พัฒนาโดยใช้ requirements ต่อไปนี้ แนะนำให้ใช้เวอร์ชันเหล่านี้หรือใหม่กว่า

qiskit[all]~=2.4.0
qiskit-ibm-runtime~=0.46.1

Dynamic circuits เป็นเครื่องมือที่ทรงพลังที่คุณสามารถวัด qubits ระหว่างการรัน quantum circuit และดำเนินการ logic แบบ classical ภายใน circuit ตามผลของการวัดระหว่าง circuit เหล่านั้น กระบวนการนี้เรียกอีกอย่างว่า classical feedforward แม้ว่านี่จะเป็นช่วงแรกของการทำความเข้าใจวิธีใช้ประโยชน์จาก dynamic circuits ชุมชนวิจัย quantum ได้ระบุกรณีการใช้งานหลายอย่าง เช่น:

อย่างไรก็ตาม การปรับปรุงเหล่านี้ที่ dynamic circuits นำมาพร้อมกับการแลกเปลี่ยน การวัดระหว่าง circuit และ classical operations โดยทั่วไปมีเวลาดำเนินการนานกว่า two-qubit gates และการเพิ่มขึ้นของเวลานี้อาจทำให้ประโยชน์ของ circuit depth ที่ลดลงหายไป ดังนั้น การลดความยาวของการวัดระหว่าง circuit จึงเป็นพื้นที่เน้นของการปรับปรุงเมื่อ IBM Quantum® เผยแพร่ เวอร์ชันใหม่ ของ dynamic circuits สำหรับข้อจำกัดอื่นๆ เมื่อใช้ dynamic circuits ดู Feature compatibility table ของ Estimator หรือ Sampler

OpenQASM 3 specification กำหนดโครงสร้าง control-flow หลายอย่าง แต่ Qiskit Runtime รองรับเฉพาะคำสั่ง conditional if เท่านั้น ใน Qiskit SDK สิ่งนี้สอดคล้องกับเมธอด if_test บน QuantumCircuit เมธอดนี้ส่งคืน context manager และโดยทั่วไปใช้ใน with statement คู่มือนี้อธิบายวิธีใช้ conditional statement นี้

หมายเหตุ

ตัวอย่างโค้ดในคู่มือนี้ใช้คำสั่ง measure มาตรฐานสำหรับการวัดระหว่าง circuit อย่างไรก็ตาม แนะนำให้ใช้คำสั่ง MidCircuitMeasure แทน ถ้า backend รองรับ ดูรายละเอียดในส่วน Mid-circuit measurements

หา backends ที่รองรับ dynamic circuits

เพื่อหา backends ทั้งหมดที่บัญชีของคุณสามารถเข้าถึงและรองรับ dynamic circuits ให้รันโค้ดเช่นต่อไปนี้ ตัวอย่างนี้สมมติว่าคุณได้ บันทึก credentials แล้ว คุณยังสามารถ ระบุ credentials อย่างชัดเจน เมื่อ initialize Qiskit Runtime service account ของคุณ ซึ่งจะให้คุณดู backends ที่มีบน instance หรือประเภท plan เฉพาะได้

หมายเหตุ
  • Backends ที่มีสำหรับบัญชีขึ้นอยู่กับ instance ที่ระบุใน credentials
  • เวอร์ชันใหม่ของ dynamic circuits ตอนนี้มีให้สำหรับผู้ใช้ทั้งหมดบน backends ทั้งหมด ดู ประกาศ สำหรับรายละเอียดเพิ่มเติม
# Added by doQumentation — required packages for this notebook
!pip install -q qiskit qiskit-ibm-runtime
# This cell is hidden from users. It hides all those "...instance was not set..." warnings.
import warnings

warnings.filterwarnings("ignore", message=".*Instance was not set*")
from qiskit_ibm_runtime import QiskitRuntimeService

service = QiskitRuntimeService()
dc_backends = service.backends(dynamic_circuits=True)
print(dc_backends)
[<IBMBackend('ibm_pittsburgh')>, <IBMBackend('ibm_kingston')>, <IBMBackend('ibm_marrakesh')>, <IBMBackend('ibm_fez')>, <IBMBackend('ibm_boston')>]

Mid-circuit measurements

ก่อน qiskit-ibm-runtime v0.43.0 measure เป็นคำสั่งการวัดเดียวใน Qiskit อย่างไรก็ตาม mid-circuit measurements มีข้อกำหนดการปรับแต่งที่แตกต่างจากการวัด terminal (การวัดที่เกิดขึ้นตอนท้ายของ circuit) ตัวอย่างเช่น คุณต้องพิจารณา instruction duration เมื่อปรับแต่ง mid-circuit measurement เพราะ instructions ที่ยาวกว่าทำให้ circuits มี noise มากขึ้น คุณไม่จำเป็นต้องพิจารณา instruction duration สำหรับ terminal measurements เนื่องจากไม่มี instructions หลัง terminal measurements

หมายเหตุ

คำสั่ง MidCircuitMeasure map ไปยังคำสั่ง measure_2 ที่รายงานใน supported_instructions ของ backend อย่างไรก็ตาม measure_2 ไม่รองรับบน backends ทั้งหมด ใช้ service.backends(filters=lambda b: "measure_2" in b.supported_instructions) เพื่อหา backends ที่รองรับ การวัดใหม่อาจเพิ่มในอนาคต แต่ไม่รับประกัน

เมธอด MidCircuitMeasure

ใน qiskit-ibm-runtime v0.43.0 มีการนำคำสั่ง MidCircuitMeasure มาใช้ ตามชื่อที่บ่งบอก เป็นคำสั่งการวัดใหม่ที่ optimize สำหรับ mid-circuit บน IBM® QPUs แม้ว่าคุณสามารถใช้ QuantumCircuit.measure สำหรับ mid-circuit measurement แต่ด้วยการออกแบบ MidCircuitMeasure โดยทั่วไปเป็นตัวเลือกที่ดีกว่า ตัวอย่างเช่น มี overhead น้อยกว่าใน circuit ของคุณกว่าเมื่อใช้ QuantumCircuit.measure

from qiskit import QuantumCircuit
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_runtime.circuit import MidCircuitMeasure

service = QiskitRuntimeService()
backend = service.least_busy(
operational=True, simulator=False, dynamic_circuits=True
)

circ = QuantumCircuit(2, 2)
circ.x(0)
circ.append(MidCircuitMeasure(), [0], [0])
# circ.measure([0], [0])
# circ.measure_all()
print(circ.draw(cregbundle=False))
┌───┐┌────────────┐
q_0: ┤ X ├┤0 ├
└───┘│ │
q_1: ─────┤ Measure_2 ├
│ │
c_0: ═════╡0 ╞
└────────────┘
c_1: ═══════════════════
หมายเหตุสำคัญ
  • ต้องมี classical register อย่างน้อยหนึ่งรายการเพื่อใช้การวัด
  • Sampler primitive ต้องการการวัด circuit คุณสามารถเพิ่มการวัด circuit ด้วย Estimator primitive แต่จะถูก ignore

Store

ด้วย qiskit-ibm-runtime เวอร์ชัน 0.47.0 หรือใหม่กว่า คุณสามารถใช้คำสั่ง store เพื่อบันทึกผลของ classical expression ถ้า expression นั้นจะถูกใช้ซ้ำหลายครั้ง operations จะถูก parallelize โดยอัตโนมัติ ทำให้โค้ดของคุณมีประสิทธิภาพมากขึ้นอย่างมีนัยสำคัญในช่วง runtime

สำหรับข้อมูลเพิ่มเติม ดูคู่มือ Classical feedforward and control flow

หมายเหตุ

เมื่อคุณใช้ store เพื่อบันทึกค่าไปยัง classical register บน backend จริง ค่านั้นจะถูกบันทึกในหน่วยความจำระหว่างการรันเท่านั้นและไม่ได้ถูก copy หรือส่งคืนในผลลัพธ์ job

ตัวอย่างเช่น ในโค้ดต่อไปนี้ temp มีค่าเดียวกับ creg ระหว่างการรัน และ if_test ทำงานตามที่คาดหวัง แต่หลัง job เสร็จสิ้น temp BitArray ที่ส่งคืนในผลลัพธ์ job ไม่ ประกอบด้วยค่าของ creg นั่นคือ job.result()[0].data.temp เป็น 0

creg = ClassicalRegister(3, "c")
temp = ClassicalRegister(3, "temp")
...
qc.store(temp, creg)
with circuit.if_test((temp, 0b001)):
...

ตัวอย่างแบบสมบูรณ์

โค้ดต่อไปนี้สร้างและรัน dynamic circuit บน IBM® hardware

from qiskit_ibm_runtime import SamplerV2, QiskitRuntimeService
from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit.transpiler import generate_preset_pass_manager

service = QiskitRuntimeService()
backend = service.least_busy(
operational=True, simulator=False, dynamic_circuits=True
)

# Create a dynamic circuit

qubits = QuantumRegister(1)
clbits = ClassicalRegister(1)
qc = QuantumCircuit(qubits, clbits)
(q0,) = qubits
(c0,) = clbits

qc.h(q0)
qc.measure(q0, c0)
with qc.if_test((c0, 1)):
qc.x(q0)
qc.measure(q0, c0)

# Convert to an ISA circuit for the given backend

pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit = pm.run(qc)

# Generate samplers for backend targets
sampler = SamplerV2(backend)

# Submit jobs
sampler_job = sampler.run([isa_circuit])
result = sampler_job.result()

print(
f">>> {' Job ID:':<10} {sampler_job.job_id()} ({sampler_job.status()})"
)
>>> Job ID: d88cakp789is7391vq0g (DONE)

ข้อจำกัดของ Qiskit Runtime

รับทราบข้อจำกัดต่อไปนี้เมื่อรัน dynamic circuits ใน Qiskit Runtime

  • เนื่องจากหน่วยความจำทางกายภาพที่จำกัดบน control electronics ยังมีขีดจำกัดสำหรับจำนวนคำสั่ง if และขนาดของ operands ขีดจำกัดนี้เป็นฟังก์ชันของจำนวน broadcasts และจำนวน broadcasted bits ใน job (ไม่ใช่ circuit)

    เมื่อประมวลผลเงื่อนไข if ข้อมูลการวัดต้องถูกถ่ายโอนไปยัง control logic เพื่อทำการประเมิน broadcast คือการถ่ายโอนข้อมูล classical ที่ไม่ซ้ำกัน และ broadcasted bits คือจำนวน classical bits ที่ถูกถ่ายโอน พิจารณาสิ่งต่อไปนี้:

    c0 = ClassicalRegister(3)
    c1 = ClassicalRegister(5)
    ...
    with circuit.if_test((c0, 1)) ...
    with circuit.if_test((c0, 3)) ...
    with circuit.if_test((c1[2], 1)) ...

    ในตัวอย่างโค้ดก่อนหน้า if_test สองตัวแรกบน c0 ถือว่าเป็น broadcast เดียวเพราะเนื้อหาของ c0 ไม่ได้เปลี่ยน ดังนั้นไม่จำเป็นต้อง re-broadcast if_test บน c1 คือ broadcast ที่สอง อันแรก broadcasts ทั้งสาม bits ใน c0 และอันที่สอง broadcasts เพียงหนึ่ง bit ทำให้รวมเป็นสี่ broadcasted bits

    ปัจจุบัน ถ้าคุณ broadcast 60 bits แต่ละครั้ง job สามารถมีประมาณ 300 broadcasts ถ้าคุณ broadcast เพียงหนึ่ง bit แต่ละครั้ง job สามารถมี 2400 broadcasts

  • Operand ที่ใช้ใน if_test statement ต้องมี 32 bits หรือน้อยกว่า ดังนั้น ถ้าคุณกำลังเปรียบเทียบ ClassicalRegister ทั้งหมด ขนาดของ ClassicalRegister นั้นต้องมี 32 bits หรือน้อยกว่า อย่างไรก็ตาม ถ้าคุณกำลังเปรียบเทียบเพียง bit เดียวจาก ClassicalRegister ClassicalRegister นั้นสามารถมีขนาดใดก็ได้ (เนื่องจาก operand เป็นเพียงหนึ่ง bit)

    ตัวอย่างเช่น code block "Not valid" ไม่ทำงานเพราะ cr มีมากกว่า 32 bits อย่างไรก็ตาม คุณสามารถใช้ classical register ที่กว้างกว่า 32 bits ถ้าคุณกำลังทดสอบเพียงหนึ่ง bit ตามที่แสดงใน code block "Valid"

    cr = ClassicalRegister(50)
    qr = QuantumRegister(50)
    circuit = QuantumCircuit(qr, cr)
    ...
    circ.measure(qr, cr)
    with circ.if_test((cr, 15)):
    ...
  • Nested conditionals ไม่อนุญาต ตัวอย่างเช่น code block ต่อไปนี้จะไม่ทำงานเพราะมี if_test อยู่ภายใน if_test อื่น:

    c1 = ClassicalRegister(1, "c1")
    c2 = ClassicalRegister(2, "c2")
    ...
    with circ.if_test((c1, 1)):
    with circ.if_test(c2, 1)):
    ...
  • การมี reset หรือการวัดภายใน conditionals ไม่รองรับ

  • Arithmetic operations ไม่รองรับ

  • ดู OpenQASM 3 feature table เพื่อกำหนดว่า OpenQASM 3 features ใดรองรับบน Qiskit และ Qiskit Runtime

  • เมื่อใช้ OpenQASM 3 (แทน QuantumCircuit) เป็นรูปแบบ input เพื่อส่ง circuits ไปยัง Qiskit Runtime primitives รองรับเฉพาะคำสั่งที่สามารถ load ลงใน Qiskit ตัวอย่างเช่น classical operations ไม่รองรับเพราะไม่สามารถ load ลงใน Qiskit ดู Import an OpenQASM 3 program into Qiskit สำหรับข้อมูลเพิ่มเติม

  • คำสั่ง for, while และ switch ไม่รองรับ

ใช้ dynamic circuits กับ Estimator

เนื่องจาก Estimator ไม่รองรับ dynamic circuits คุณสามารถใช้ Sampler และสร้าง measurement circuits ของคุณเองแทน

เพื่อจำลองพฤติกรรมของ Estimator ทำตามกระบวนการนี้:

  1. จัดกลุ่ม terms ของ observables ทั้งหมดเป็น partition สามารถทำได้โดยใช้ PauliList API เช่น
    หมายเหตุ

    คุณสามารถใช้ attribute primitive BitArray เพื่อคำนวณ expectation values ของ observables ที่ให้

  2. รัน basis change circuit หนึ่งอันต่อ partition (ไม่ว่าจะต้องทำ basis change ใดสำหรับแต่ละ partition) ดู Measurement bases addon utility measurement_bases module สำหรับข้อมูลเพิ่มเติม สำหรับข้อมูลเพิ่มเติม ดู เอกสาร สำหรับแพ็กเกจ Qiskit addon utilities
  3. รวมผลลัพธ์สำหรับแต่ละ partition กลับเข้าด้วยกัน

ข้อจำกัด

ทบทวน Feature compatibility table ใดๆ เพื่อทำความเข้าใจข้อจำกัดเมื่อใช้ dynamic circuits โปรดทราบว่าความเข้ากันได้ของ feature ไม่ขึ้นอยู่กับ primitive

ขั้นตอนถัดไป

คำแนะนำ
  • เรียนรู้วิธีใช้ dynamic decoupling ที่แม่นยำโดยใช้ stretch
  • ทบทวนคู่มือ classical feedforward and control flow
  • ใช้ circuit schedule visualization เพื่อ debug และ optimize dynamic circuits ของคุณ
  • ฟังก์ชันบางอย่างไม่รองรับ dynamic circuits ดูส่วน feature compatibility สำหรับ Sampler หรือ Executor เพื่อดูรายละเอียด