Lewati ke konten utama
Proyek ini masih dalam tahap beta. Menemukan bug? Buat isu GitHub. Punya pertanyaan atau ide? Tanya di Discussions — kami sangat menghargai masukan kamu!
Bagaimana kualitas terjemahan di halaman ini?

Panduan cepat

Panduan ini menunjukkan contoh kerja minimal dari paket qiskit-addon-obp. Kita memakai operator backpropagation (OBP) untuk mengurangi depth circuit kuantum dengan menyerap gate di bagian akhir ke dalam observable.

Nilai ekspektasi ⟨O⟩=⟨ψ∣U†OU∣ψ⟩\langle O \rangle = \langle \psi | U^\dagger O U | \psi \rangle tidak berubah kalau kita melepas blok gate di bagian akhir circuit UU dan mengonjugasikan observable dengannya secara klasik. OBP menerapkan ini berulang kali, mengevaluasi sebagian circuit secara klasik sehingga hanya circuit yang lebih dangkal yang dijalankan di hardware. Harganya, setiap gate yang diserap bisa memperluas observable menjadi lebih banyak suku Pauli, jadi depth yang dihemat harus ditimbang dengan pertumbuhan observable.

Untuk melihat contoh cara membangun workflow yang realistis dengan tool ini dan menjalankannya di hardware kuantum, lihat tutorial di IBM Quantum Platform (OBP Tutorial).

Siapkan input untuk OBP​

OBP menerima daftar slice circuit dan sebuah observable sebagai input. OBP melakukan backpropagation slice satu per satu dari ujung circuit ke dalam observable, mengurangi depth circuit dengan konsekuensi tambahan suku Pauli di observable. Di sini kita membuat circuit evolusi waktu untuk model Heisenberg 10 qubit dan mengirisnya berdasarkan jenis gate.

Di bawah ini kita gambar circuit aslinya, lalu circuit yang sama yang digabung ulang dengan barrier sebagai penanda batas slice — setiap slice adalah satu unit yang bisa diserap ke dalam observable dalam satu langkah 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

Kurangi depth circuit dengan OBP​

Kita memanggil backpropagate untuk menyerap slice ke dalam observable. Fungsi ini mengembalikan observable yang sudah diperluas, slice circuit yang tidak di-propagate, dan metadata tentang prosedurnya.

Kalau dibiarkan, observable bisa tumbuh hingga 2n2^n suku Pauli. operator_budget membatasi pertumbuhan ini — di sini kita mengizinkan paling banyak 8 grup yang commute secara qubit-wise, yang kira-kira menentukan jumlah shot yang dibutuhkan untuk mengevaluasi observable di QPU. Backpropagation berhenti begitu penyerapan slice berikutnya akan melebihi budget, dan itulah yang terjadi di bawah: hanya 7 dari 18 slice yang diserap sebelum observable memenuhi semua 8 grup commuting dan prosedur berhenti.

Untuk masuk lebih dalam ke circuit, argumen kata kunci truncation_error_budget pada backpropagate bisa dipakai untuk membuang suku Pauli berkoefisien kecil dari observable saat observable itu tumbuh. Ini meredam pertumbuhan observable dengan imbalan error yang sebanding dengan besar suku Pauli yang dipangkas. Kedua budget ini saling melengkapi dan bisa dipakai bersamaan: operator_budget mengatur ukuran observable, sedangkan truncation_error_budget mengatur error yang muncul akibat membuang suku.

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