Перейти до основного вмісту

Розрізання схем для зменшення глибини

Орієнтовний час виконання: вісім хвилин на процесорі Eagle (ПРИМІТКА: Це лише орієнтовна оцінка. Фактичний час виконання може відрізнятися.)

Передумови

Цей посібник демонструє, як побудувати Qiskit pattern для розрізання вентилів у квантовій схемі з метою зменшення глибини схеми. Для більш детального обговорення розрізання схем відвідайте документацію додатка Qiskit для розрізання схем.

Вимоги

Перед початком роботи з цим посібником переконайся, що у тебе встановлено наступне:

  • Qiskit SDK v2.0 або новішої версії з підтримкою візуалізації
  • Qiskit Runtime v0.22 або новішої версії (pip install qiskit-ibm-runtime)
  • Додаток Qiskit для розрізання схем v0.9.0 або новішої версії (pip install qiskit-addon-cutting)

Налаштування

# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit qiskit-addon-cutting qiskit-ibm-runtime
import numpy as np

from qiskit.circuit.library import EfficientSU2
from qiskit.quantum_info import PauliList, Statevector, SparsePauliOp
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager

from qiskit_addon_cutting import (
cut_gates,
generate_cutting_experiments,
reconstruct_expectation_values,
)

from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2

Крок 1: Відображення класичних вхідних даних на квантову задачу

Ми реалізуємо наш шаблон Qiskit, використовуючи чотири кроки, описані в документації. У цьому випадку ми будемо симулювати очікувані значення на схемі певної глибини шляхом розрізання вентилів, що призводить до swap-вентилів, та виконання підексперименів на схемах меншої глибини. Розрізання вентилів є актуальним для кроків 2 (оптимізація схеми для квантового виконання шляхом декомпозиції віддалених вентилів) та 4 (постобробка для реконструкції очікуваних значень на оригінальній схемі). На першому кроці ми згенеруємо схему з бібліотеки схем Qiskit та визначимо деякі спостережувані величини.

  • Вхідні дані: Класичні параметри для визначення схеми
  • Вихідні дані: Абстрактна схема та спостережувані величини
circuit = EfficientSU2(num_qubits=4, entanglement="circular").decompose()
circuit.assign_parameters([0.4] * len(circuit.parameters), inplace=True)
observables = PauliList(["ZZII", "IZZI", "IIZZ", "XIXI", "ZIZZ", "IXIX"])
circuit.draw("mpl", scale=0.8, style="iqp")

Результат виконання попередньої комірки коду

Крок 2: Оптимізація задачі для виконання на квантовому обладнанні

  • Вхідні дані: Абстрактна схема та спостережувані величини
  • Вихідні дані: Цільова схема та спостережувані величини, отримані шляхом розрізання віддалених вентилів для зменшення глибини транспільованої схеми

Ми обираємо початкову розкладку, яка вимагає двох swap-операцій для виконання вентилів між кубітами 3 та 0, і ще двох swap-операцій для повернення кубітів у їхні початкові позиції. Ми обираємо optimization_level=3, що є найвищим рівнем оптимізації, доступним у попередньо налаштованому менеджері проходів.

service = QiskitRuntimeService()
backend = service.least_busy(
operational=True, min_num_qubits=circuit.num_qubits, simulator=False
)

pm = generate_preset_pass_manager(
optimization_level=3, initial_layout=[0, 1, 2, 3], backend=backend
)
transpiled_qc = pm.run(circuit)

Карта зв'язності, що показує кубіти, які потребуватимуть swap-операцій

print(f"Transpiled circuit depth: {transpiled_qc.depth()}")
transpiled_qc.draw("mpl", scale=0.4, idle_wires=False, style="iqp", fold=-1)
Transpiled circuit depth: 103

Результат виконання попередньої комірки коду

Знаходження та розрізання віддалених вентилів: Ми замінимо віддалені вентилі (вентилі, що з'єднують нелокальні кубіти, 0 та 3) об'єктами TwoQubitQPDGate, вказавши їхні індекси. cut_gates замінить вентилі за вказаними індексами об'єктами TwoQubitQPDGate, а також поверне список екземплярів QPDBasis — по одному для кожної декомпозиції вентиля. Об'єкт QPDBasis містить інформацію про те, як декомпозувати розрізані вентилі на однокубітні операції.

# Find the indices of the distant gates
cut_indices = [
i
for i, instruction in enumerate(circuit.data)
if {circuit.find_bit(q)[0] for q in instruction.qubits} == {0, 3}
]

# Decompose distant CNOTs into TwoQubitQPDGate instances
qpd_circuit, bases = cut_gates(circuit, cut_indices)

qpd_circuit.draw("mpl", scale=0.8)

Результат виконання попередньої комірки коду

Генерація підексперименів для виконання на бекенді: generate_cutting_experiments приймає схему, що містить екземпляри TwoQubitQPDGate, та спостережувані величини у вигляді PauliList.

Для симуляції очікуваного значення повнорозмірної схеми з квазіймовірнісного розподілу декомпозованих вентилів генерується багато підексперименів, які потім виконуються на одному або кількох бекендах. Кількість зразків, взятих з розподілу, контролюється параметром num_samples, і для кожного унікального зразка надається один комбінований коефіцієнт. Для отримання додаткової інформації про обчислення коефіцієнтів зверніться до пояснювальних матеріалів.

# Generate the subexperiments and sampling coefficients
subexperiments, coefficients = generate_cutting_experiments(
circuits=qpd_circuit, observables=observables, num_samples=np.inf
)

Для порівняння: підексперименти QPD будуть мати меншу глибину після розрізання віддалених вентилів: Ось приклад довільно обраного підексперименту, згенерованого зі схеми QPD. Його глибина була зменшена більш ніж удвічі. Необхідно згенерувати та обчислити багато таких імовірнісних підексперименів для реконструкції очікуваного значення більш глибокої схеми.

# Transpile the decomposed circuit to the same layout
transpiled_qpd_circuit = pm.run(subexperiments[100])

print(f"Original circuit depth after transpile: {transpiled_qc.depth()}")
print(
f"QPD subexperiment depth after transpile: {transpiled_qpd_circuit.depth()}"
)
transpiled_qpd_circuit.draw(
"mpl", scale=0.6, style="iqp", idle_wires=False, fold=-1
)
Original circuit depth after transpile: 103
QPD subexperiment depth after transpile: 46

Результат виконання попередньої комірки коду

З іншого боку, розрізання призводить до необхідності додаткового семплювання. У цьому випадку ми розрізали три вентилі CNOT, що призвело до накладних витрат на семплювання у розмірі 939^3. Для отримання додаткової інформації про накладні витрати на семплювання, спричинені розрізанням схем, зверніться до документації Circuit Knitting Toolbox.

print(f"Sampling overhead: {np.prod([basis.overhead for basis in bases])}")
Sampling overhead: 729.0

Крок 3: Виконання за допомогою примітивів Qiskit

Виконайте цільові схеми ("підексперименти") за допомогою примітива Sampler.

  • Вхідні дані: Цільові схеми
  • Вихідні дані: Квазіймовірнісні розподіли
# Transpile the subexperiments to the backend's instruction set architecture (ISA)
isa_subexperiments = pm.run(subexperiments)

# Set up the Qiskit Runtime Sampler primitive. For a fake backend, this will use a local simulator.
sampler = SamplerV2(backend)

# Submit the subexperiments
job = sampler.run(isa_subexperiments)
# Retrieve the results
results = job.result()
print(job.job_id())
czypg1r6rr3g008mgp6g

Крок 4: Постобробка та повернення результату в бажаному класичному форматі

Використайте результати підексперименів, підспостережувані величини та коефіцієнти семплювання для реконструкції очікуваного значення оригінальної схеми.

Вхідні дані: Квазіймовірнісні розподіли Вихідні дані: Реконструйовані очікувані значення

reconstructed_expvals = reconstruct_expectation_values(
results,
coefficients,
observables,
)
# Reconstruct final expectation value
final_expval = np.dot(reconstructed_expvals, [1] * len(observables))
print("Final reconstructed expectation value")
print(final_expval)
Final reconstructed expectation value
1.0751342773437473
ideal_expvals = [
Statevector(circuit).expectation_value(SparsePauliOp(observable))
for observable in observables
]
print("Ideal expectation value")
print(np.dot(ideal_expvals, [1] * len(observables)).real)
Ideal expectation value
1.2283177520039992

Опитування щодо посібника

Будь ласка, пройди це коротке опитування, щоб надати зворотний зв'язок щодо цього посібника. Твої відгуки допоможуть нам покращити наш контент та досвід користувачів.

Посилання на опитування