Швидкий старт
Цей посібник демонструє мінімальний робочий приклад пакета qiskit-addon-obp. Ми використовуємо зворотне поширення операторів (OBP), щоб зменшити глибину квантової схеми, поглинаючи кінцеві вентилі в спостережувану.
Очікуване значення не змінюється, якщо відокремити кінцевий блок вентилів від схеми і класично спряжити з ним спостережувану. OBP застосовує це багаторазово, обчислюючи частину схеми класично, так що на апаратному забезпеченні виконується лише менш глибока схема. Ціна цього полягає в тому, що кожен поглинений вентиль може розширити спостережувану до більшої кількості доданків Паулі, тому виграну глибину слід зважувати проти зростання спостережуваної.
Щоб побачити приклади побудови реалістичних робочих процесів за допомогою цього інструмента та виконання на квантовому апаратному забезпеченні, ознайомся з посібниками на IBM Quantum Platform (OBP Tutorial).
Підготовка вхідних даних для OBP
OBP приймає на вхід список зрізів схеми та спостережувану. Вона по одному зворотно поширює зрізи від кінця схеми в спостережувану, зменшуючи глибину схеми ціною додаткових доданків Паулі в спостережуваній. Тут ми генеруємо схему часової еволюції для 10-кубітної моделі Гейзенберга та розрізаємо її за типом вентиля.
Нижче ми малюємо початкову схему, а потім ту саму схему, перекомбіновану з бар'єрами, що позначають межі зрізів — кожен зріз є одиницею, яку можна поглинути в спостережувану за один крок зворотного поширення.
# 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)

Зменшення глибини схеми за допомогою OBP
Ми викликаємо backpropagate, щоб поглинути зрізи в спостережувану. Функція повертає розширену спостережувану, зрізи схеми, через які поширення не виконувалося, та метадані про процедуру.
Без обмежень спостережувана може зрости до доданків Паулі. Параметр operator_budget обмежує це зростання — тут ми дозволяємо не більше 8 груп, що комутують за кубітами, що приблизно задає кількість вимірювань (shots), потрібних для оцінки спостережуваної на QPU. Зворотне поширення зупиняється, щойно поглинання наступного зрізу перевищило б бюджет, що саме й відбувається нижче: поглинається лише 7 із 18 зрізів, перш ніж спостережувана заповнить усі 8 груп, що комутують, і процедура зупиняється.
Щоб просунутися глибше в схему, можна використати іменований аргумент truncation_error_budget функції backpropagate, щоб відкидати доданки Паулі з малими коефіцієнтами зі спостережуваної в міру її зростання. Це стримує зростання спостережуваної в обмін на певну похибку, пропорційну величині усічених доданків Паулі. Ці два бюджети взаємодоповнюють один одного й можуть використовуватися разом: operator_budget керує розміром спостережуваної, тоді як 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)