Mabilisang simula
Ipinapakita ng gabay na ito ang isang minimal na gumaganang halimbawa ng package na qiskit-addon-obp. Gumagamit tayo ng operator backpropagation (OBP) para bawasan ang depth ng isang quantum circuit sa pamamagitan ng pagsipsip ng mga huling gate papunta sa observable.
Ang isang expectation value na ay hindi nagbabago kung aalisin natin ang huling bloke ng mga gate mula sa circuit na at i-conjugate nang classical ang observable gamit ito. Paulit-ulit itong ina-apply ng OBP, na kinakalkula nang classical ang bahagi ng circuit para mas mababaw na circuit na lang ang tumakbo sa hardware. Ang kapalit nito ay maaaring palawakin ng bawat sinipsip na gate ang observable sa mas maraming Pauli term, kaya dapat timbangin ang natipid na depth laban sa paglaki ng observable.
Para makita ang mga halimbawa kung paano bumuo ng makatotohanang workflow gamit ang tool na ito at magpatakbo sa quantum hardware, tingnan ang mga tutorial sa IBM Quantum Platform (OBP Tutorial).
Ihanda ang mga input para sa OBP
Ang input ng OBP ay isang listahan ng mga circuit slice at isang observable. Bina-backpropagate nito ang mga slice isa-isa mula sa dulo ng circuit papunta sa observable, na binabawasan ang circuit depth kapalit ng mas maraming Pauli term sa observable. Dito, gumagawa tayo ng time-evolution circuit para sa isang 10-qubit na Heisenberg model at hinihiwa ito ayon sa uri ng gate.
Sa ibaba, iginuguhit natin ang orihinal na circuit, tapos ang parehong circuit na muling pinagsama na may mga barrier na nagmamarka ng hangganan ng mga slice — ang bawat slice ay isang unit na maaaring sipsipin sa observable sa isang hakbang ng 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:

Sliced circuit (recombined with barriers for visualization)

Bawasan ang circuit depth gamit ang OBP
Tinatawag natin ang backpropagate para sipsipin ang mga slice sa observable. Ibinabalik ng function ang pinalawak na observable, ang mga circuit slice na hindi napagdaanan ng propagation, at metadata tungkol sa proseso.
Kung hindi lilimitahan, maaaring lumaki ang observable hanggang na Pauli term. Nililimitahan ng operator_budget ang paglaking ito — dito, pinapayagan natin ang hanggang 8 qubit-wise commuting group, na halos nagtatakda ng bilang ng mga shot na kailangan para i-evaluate ang observable sa QPU. Humihinto ang backpropagation sa sandaling lalampas sa budget ang pagsipsip ng susunod na slice, na eksaktong nangyayari sa ibaba: 7 lang sa 18 slice ang nasipsip bago mapuno ng observable ang lahat ng 8 commuting group at huminto ang proseso.
Para mas makapasok pa sa circuit, magagamit ang keyword argument na truncation_error_budget sa backpropagate para alisin ang mga Pauli term na maliit ang coefficient mula sa observable habang lumalaki ito. Pinipigilan nito ang paglaki ng observable kapalit ng kaunting error na proporsyonal sa laki ng mga Pauli term na tina-truncate. Magkaagapay ang dalawang budget at maaaring gamitin nang magkasama: kinokontrol ng operator_budget ang laki ng observable, habang kinokontrol ng truncation_error_budget ang error na dulot ng pagtanggal ng mga term.
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)