Встановлення рівня оптимізації транспілятора
Версії пакетів
Код на цій сторінці розроблено з використанням наведених нижче залежностей. Рекомендуємо використовувати ці або новіші версії.
qiskit[all]~=2.4.0
qiskit-ibm-runtime~=0.46.1
Реальні квантові пристрої схильні до шумів і помилок вентилів, тому оптимізація схем для зменшення їхньої глибини та кількості вентилів може суттєво покращити результати виконання цих схем.
Функція generate_preset_pass_manager має один обов'язковий позиційний аргумент — optimization_level, який визначає, скільки зусиль транспілятор витрачає на оптимізацію схем. Цей аргумент може бути цілим числом з множини: 0, 1, 2 або 3.
Вищі рівні оптимізації генерують більш оптимізовані схеми ціною збільшення часу компіляції.
У наведеній нижче таблиці пояснюються оптимізації, що виконуються при кожному налаштуванні.
| Рівень оптимізації | Опис |
|---|---|
| 0 | Без оптимізації: зазвичай використовується для характеризації апаратного забезпечення
|
| 1 | Легка оптимізація:
|
| 2 | Середня оптимізація:
|
| 3 | Висока оптимізація:
|
Рівень оптимізації в дії
Оскільки двокубітні вентилі зазвичай є найзначнішим джерелом помилок, ми можемо приблизно оцінити «апаратну ефективність» транспіляції, підрахувавши кількість двокубітних вентилів у результуючій схемі. Тут ми спробуємо різні рівні оптимізації на вхідній схемі, що складається з випадкового унітарного оператора, за яким слідує SWAP-вентиль.
# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit qiskit-ibm-runtime
from qiskit import QuantumCircuit
from qiskit.circuit.library import UnitaryGate
from qiskit.quantum_info import Operator, random_unitary
UU = random_unitary(4, seed=12345)
rand_U = UnitaryGate(UU)
qc = QuantumCircuit(2)
qc.append(rand_U, range(2))
qc.swap(0, 1)
qc.draw("mpl", style="iqp")
Симульований бекенд FakeSherbrooke з qiskit_ibm_runtime використовується у цих прикладах, але ти можеш спробувати будь-який реальний або симульований бекенд, сумісний з Qiskit. Твої результати можуть відрізнятися.
Спочатку виконаємо транспіляцію з рівнем оптимізації 0.
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_ibm_runtime.fake_provider import FakeSherbrooke
backend = FakeSherbrooke()
pass_manager = generate_preset_pass_manager(
optimization_level=0, backend=backend, seed_transpiler=12345
)
qc_t1_exact = pass_manager.run(qc)
qc_t1_exact.draw("mpl", idle_wires=False)
Транспільована схема містить шість двокубітних вентилів ECR.
Повторимо для рівня оптимізації 1:
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_ibm_runtime.fake_provider import FakeSherbrooke
backend = FakeSherbrooke()
pass_manager = generate_preset_pass_manager(
optimization_level=1, backend=backend, seed_transpiler=12345
)
qc_t1_exact = pass_manager.run(qc)
qc_t1_exact.draw("mpl", idle_wires=False)
Транспільована схема все ще містить шість вентилів ECR, але кількість однокубітних вентилів зменшилася.
Повторимо для рівня оптимізації 2:
pass_manager = generate_preset_pass_manager(
optimization_level=2, backend=backend, seed_transpiler=12345
)
qc_t2_exact = pass_manager.run(qc)
qc_t2_exact.draw("mpl", idle_wires=False)
Це дає ті самі результати, що й рівень оптимізації 1. Зверни увагу, що підвищення рівня оптимізації не завжди має ефект.
Повторимо ще раз, з рівнем оптимізації 3:
pass_manager = generate_preset_pass_manager(
optimization_level=3, backend=backend, seed_transpiler=12345
)
qc_t3_exact = pass_manager.run(qc)
qc_t3_exact.draw("mpl", idle_wires=False)
Тепер є лише три вентилі ECR. Ми отримуємо цей результат тому, що на рівні оптимізації 3 Qiskit намагається повторно синтезувати двокубітні блоки вентилів, і будь-який двокубітний вентиль можна реалізувати не більш ніж трьома вентилями ECR. Ми можемо отримати ще менше вентилів ECR, якщо встановимо approximation_degree менше 1, дозволяючи транспілятору робити наближення, що можуть вносити певну похибку в розкладання вентилів (дивись Поширено використовувані параметри транспіляції):
pass_manager = generate_preset_pass_manager(
optimization_level=3,
approximation_degree=0.99,
backend=backend,
seed_transpiler=12345,
)
qc_t3_approx = pass_manager.run(qc)
qc_t3_approx.draw("mpl", idle_wires=False)
Ця схема містить лише два вентилі ECR, але є наближеною. Щоб зрозуміти, наскільки її дія відрізняється від точної схеми, ми можемо обчислити точність між унітарним оператором, який реалізує ця схема, та точним унітарним. Перед обчисленням ми спочатку зводимо транспільовану схему, яка містить 127 кубітів, до схеми лише з активними кубітами — їх двоє.
import numpy as np
def trace_to_fidelity_2q(trace: float) -> float:
return (4.0 + trace * trace.conjugate()) / 20.0
# Reduce circuits down to 2 qubits so they are easy to simulate
qc_t3_exact_small = QuantumCircuit.from_instructions(qc_t3_exact)
qc_t3_approx_small = QuantumCircuit.from_instructions(qc_t3_approx)
# Compute the fidelity
exact_fid = trace_to_fidelity_2q(
np.trace(np.dot(Operator(qc_t3_exact_small).adjoint().data, UU))
)
approx_fid = trace_to_fidelity_2q(
np.trace(np.dot(Operator(qc_t3_approx_small).adjoint().data, UU))
)
print(
f"Synthesis fidelity\nExact: {exact_fid:.3f}\nApproximate: {approx_fid:.3f}"
)
Synthesis fidelity
Exact: 1.000+0.000j
Approximate: 0.992+0.000j
Зміна рівня оптимізації може вплинути й на інші аспекти схеми, не лише на кількість вентилів ECR. Приклади того, як налаштування рівня оптимізації змінює розміщення, дивись у розділі Представлення квантових комп'ютерів.
Наступні кроки
- Щоб дізнатися більше про функцію
generate_preset_passmanager, почни з теми Параметри транспіляції за замовчуванням та варіанти конфігурації. - Продовж вивчення транспіляції з темою Етапи транспілятора.
- Спробуй посібник Порівняння налаштувань транспілятора.
- Спробуй навчальний матеріал Побудова кодів повторення.
- Переглянь документацію Transpile API.