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

เริ่มต้นอย่างรวดเร็ว

คู่มือนี้สาธิตตัวอย่างการทำงานขั้นต่ำของแพ็กเกจ qiskit-addon-obp เราใช้ operator backpropagation (OBP) เพื่อลดความลึกของวงจรควอนตัมโดยดูดซับ Gate ท้ายวงจรเข้าไปใน observable

ค่าคาดหมาย ⟨O⟩=⟨ψ∣U†OU∣ψ⟩\langle O \rangle = \langle \psi | U^\dagger O U | \psi \rangle จะไม่เปลี่ยนแปลง หากเราแยกบล็อก Gate ท้ายวงจรออกจากวงจร UU แล้วทำ conjugate ให้ observable ด้วยบล็อกนั้นแบบคลาสสิก OBP ใช้วิธีนี้ซ้ำ ๆ โดยประเมินวงจรบางส่วนแบบคลาสสิก เพื่อให้มีเพียงวงจรที่ตื้นกว่าเท่านั้นที่รันบนฮาร์ดแวร์ ราคาที่ต้องจ่ายคือ Gate ที่ถูกดูดซับแต่ละตัวอาจขยาย observable ให้มีเทอม Pauli มากขึ้น ดังนั้นต้องชั่งน้ำหนักระหว่างความลึกที่ลดลงกับการเติบโตของ observable

หากต้องการดูตัวอย่างการสร้าง workflow ที่สมจริงด้วยเครื่องมือนี้และรันบนฮาร์ดแวร์ควอนตัม ดูบทเรียนบน IBM Quantum Platform (บทเรียน OBP)

เตรียมอินพุตสำหรับ OBP​

OBP รับรายการของ circuit slice และ observable เป็นอินพุต โดยจะ backpropagate slice ทีละอันจากท้ายวงจรเข้าไปใน observable ลดความลึกของวงจรโดยแลกกับเทอม Pauli ที่เพิ่มขึ้นใน observable ที่นี่เราสร้างวงจรการวิวัฒนาการตามเวลาสำหรับโมเดล Heisenberg 10 qubit และแบ่งเป็น slice ตามชนิดของ Gate

ด้านล่างเราวาดวงจรต้นฉบับ จากนั้นวาดวงจรเดียวกันที่รวมกลับพร้อม barrier ที่ทำเครื่องหมายขอบเขตของ slice — แต่ละ slice เป็นหน่วยที่สามารถดูดซับเข้าไปใน observable ได้ในขั้นตอน backpropagation เดียว

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

_needed = {"numpy": "numpy", "qiskit": "qiskit", "qiskit_addon_obp": "qiskit-addon-obp", "qiskit_addon_utils": "qiskit-addon-utils"}
_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
from qiskit.quantum_info import SparsePauliOp
from qiskit.synthesis import LieTrotter
from qiskit.transpiler import CouplingMap
from qiskit_addon_utils.problem_generators import (
generate_time_evolution_circuit,
generate_xyz_hamiltonian,
)
from qiskit_addon_utils.slicing import combine_slices, slice_by_gate_types

# Generate a circuit to reduce
coupling_map = CouplingMap.from_heavy_hex(3, bidirectional=False)
reduced_coupling_map = coupling_map.reduce(
[0, 13, 1, 14, 10, 16, 5, 12, 8, 18]
)

hamiltonian = generate_xyz_hamiltonian(
reduced_coupling_map,
coupling_constants=(np.pi / 8, np.pi / 4, np.pi / 2),
ext_magnetic_field=(np.pi / 3, np.pi / 6, np.pi / 9),
)

circuit = generate_time_evolution_circuit(
hamiltonian,
time=0.2,
synthesis=LieTrotter(reps=2),
)

# Slice the circuit and define an observable
slices = slice_by_gate_types(circuit)
observable = SparsePauliOp("IIIIIIIIIZ")

print(f"Original circuit depth: {circuit.depth()}")
print(f"Number of slices: {len(slices)}")
print(f"Observable terms: {len(observable)}")
Original circuit depth: 18
Number of slices: 18
Observable terms: 1
# Recombine the slices with barriers to make the slice boundaries visible
sliced_circuit = combine_slices(slices, include_barriers=True)

print("Original circuit:")
display(circuit.draw("mpl", scale=0.6, fold=-1))
print("Sliced circuit (recombined with barriers for visualization)")
sliced_circuit.draw("mpl", scale=0.6, fold=-1)
Original circuit:

Output of the previous code cell

Sliced circuit (recombined with barriers for visualization)

Output of the previous code cell

ลดความลึกของวงจรด้วย OBP​

เราเรียก backpropagate เพื่อดูดซับ slice เข้าไปใน observable ฟังก์ชันจะคืนค่า observable ที่ขยายแล้ว, circuit slice ที่ไม่ได้ถูก propagate ผ่าน และ metadata เกี่ยวกับขั้นตอนการทำงาน

หากไม่มีการควบคุม observable อาจเติบโตไปสู่เทอม Pauli จำนวน 2n2^n operator_budget จำกัดการเติบโตนี้ — ที่นี่เราอนุญาตกลุ่ม qubit-wise commuting สูงสุด 8 กลุ่ม ซึ่งกำหนดจำนวน shot ที่ต้องใช้ในการประเมิน observable บน QPU โดยประมาณ Backpropagation จะหยุดทันทีที่การดูดซับ slice ถัดไปจะเกินงบประมาณ ซึ่งเป็นสิ่งที่เกิดขึ้นด้านล่างพอดี: มีเพียง 7 จาก 18 slice ที่ถูกดูดซับก่อนที่ observable จะเต็มทั้ง 8 กลุ่ม commuting และขั้นตอนหยุดลง

เพื่อเจาะลึกเข้าไปในวงจรมากขึ้น สามารถใช้ keyword argument truncation_error_budget ของ backpropagate เพื่อทิ้งเทอม Pauli ที่มีสัมประสิทธิ์เล็กออกจาก observable ขณะที่มันเติบโต วิธีนี้ลดการเติบโตของ observable โดยแลกกับความคลาดเคลื่อนที่เป็นสัดส่วนกับขนาดของเทอม Pauli ที่ถูกตัดทอน งบประมาณทั้งสองเสริมกันและใช้ร่วมกันได้: operator_budget ควบคุมขนาดของ observable ส่วน truncation_error_budget ควบคุมความคลาดเคลื่อนที่เกิดจากการทิ้งเทอม

from qiskit_addon_obp import backpropagate
from qiskit_addon_obp.utils.simplify import OperatorBudget

max_qwc_groups = 8
bp_obs, remaining_slices, metadata = backpropagate(
observable,
slices,
operator_budget=OperatorBudget(max_qwc_groups=max_qwc_groups),
)

reduced_circuit = combine_slices(remaining_slices)
num_groups = len(bp_obs.group_commuting(qubit_wise=True))

print(
f"Backpropagated {metadata.num_backpropagated_slices} of {len(slices)} slices."
)
print(
f"Reduced circuit depth: {reduced_circuit.depth()} (was {circuit.depth()})"
)
print(f"Observable grew from {len(observable)} to {len(bp_obs)} Pauli terms.")
print(
f"Filled {num_groups} of {max_qwc_groups} commuting groups, exhausting the budget."
)
Backpropagated 7 of 18 slices.
Reduced circuit depth: 11 (was 18)
Observable grew from 1 to 18 Pauli terms.
Filled 8 of 8 commuting groups, exhausting the budget.
reduced_circuit.draw("mpl", scale=0.6, fold=-1)

Output of the previous code cell